[
  {
    "path": ".gitignore",
    "content": ".vscode\nbuild\ndebug\nrun*/\nscripts/__pycache__\ntags\n\n"
  },
  {
    "path": "LICENSE",
    "content": "READ THIS LICENSE AGREEMENT CAREFULLY BEFORE USING THIS PRODUCT. BY USING THIS PRODUCT YOU INDICATE YOUR ACCEPTANCE OF THE TERMS OF THE FOLLOWING AGREEMENT. THESE TERMS APPLY TO YOU AND ANY SUBSEQUENT LICENSEE OF THIS PRODUCT.\n\n\n\nLicense Agreement for CUGR\n\n\n\nCopyright (c) 2020 by The Chinese University of Hong Kong\n\n\n\nAll rights reserved\n\n\n\nCU-SD LICENSE (adapted from the original BSD license) Redistribution of the any code, with or without modification, are permitted provided that the conditions below are met. \n\n\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n\n\nRedistributions 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.\n\n\n\nNeither the name nor trademark of the copyright holder or the author may be used to endorse or promote products derived from this software without specific prior written permission.\n\n\n\nUsers are entirely responsible, to the exclusion of the author, for compliance with (a) regulations set by owners or administrators of employed equipment, (b) licensing terms of any other software, and (c) local, national, and international regulations regarding use, including those regarding import, export, and use of encryption software.\n\n\n\nTHIS FREE SOFTWARE IS PROVIDED BY THE AUTHOR \"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 AUTHOR OR ANY CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, EFFECTS OF UNAUTHORIZED OR MALICIOUS NETWORK ACCESS; 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.\n"
  },
  {
    "path": "README.md",
    "content": "CUGR\n======================================\nCUGR is a VLSI global routing tool developed by the research team supervised by Prof. Evangeline F. Y. Young at The Chinese University of Hong Kong (CUHK).\nDifferent from previous global routers whose quality is usually measured by wirelength and resource overflow,\nCUGR is a detailed routability-driven global router and its solution quality is solely determined by the final detailed routing results.\nIn particular, our global router adopts several efficient and effective methods to generate a set of connected rectangles to guide the detailed router:\n* A sophisticated probability-based cost scheme\n* An optimal 3D pattern routing technique that combines 2D pattern routing and layer assignment\n* A multi-level maze routing utilizes two levels of routing\n* A patching technique that adds useful route guides to further improve the detailed routability.\n* ...\n\nMore details are in the following paper:\n\n* Jinwei Liu, Chak-Wa Pui, Fangzhou Wang, Evangeline F. Y. Young,\n[\"CUGR: Detailed-Routability-Driven 3D Global Routing with Probabilistic Resource Model\"](https://ieeexplore.ieee.org/document/9218646),\nACM/IEEE Design Automation Conference (DAC), San Francisco, CA, USA, July 19-23, 2020.\n\n(CUGR supports ICCAD'19 benchmarks ([v2](http://iccad-contest.org/2019/Problem_C/iccad19_benchmarks_v2.tar.gz), [hidden](http://iccad-contest.org/2019/Problem_C/iccad19_hidden_benchmarks.tar.gz)).\nThis version of code is consistent with the DAC paper.)\n\n## 1. How to Build\n\n**Step 1:** Download the source code. For example,\n```bash\n$ git clone https://github.com/cuhk-eda/cu-gr\n```\n\n**Step 2:** Go to the project root and build by\n```bash\n$ cd cu-gr\n$ scripts/build.py -o release\n```\n\nNote that this will generate two folders under the root, `build` and `run` (`build` contains intermediate files for build/compilation, while `run` contains binaries and auxiliary files).\nMore details are in [`scripts/build.py`](scripts/build.py).\n\n### 1.1. Dependencies\n\n* [GCC](https://gcc.gnu.org/) (version >= 5.5.0) or other working c++ compliers\n* [CMake](https://cmake.org/) (version >= 2.8)\n* [Boost](https://www.boost.org/) (version >= 1.58)\n* [Python](https://www.python.org/) (version 3, optional, for utility scripts)\n* [Innovus®](https://www.cadence.com/content/cadence-www/global/en_US/home/tools/digital-design-and-signoff/soc-implementation-and-floorplanning/innovus-implementation-system.html) (version 18.1, optional, for design rule checking and evaluation)\n* [Rsyn](https://github.com/RsynTeam/rsyn-x) (a trimmed version is used, already added under folder `rsyn`)\n* [Dr. CU](https://github.com/cuhk-eda/dr-cu) (v4.1.1, optional, official detailed router for ICCAD'19 Contest, [binary](http://iccad-contest.org/2019/Problem_C/drcu_june19.zip) is already included under the root)\n\n## 2. How to Run\n\n### 2.1. Toy Test\n\n#### Run Binary Directly\n\nGo to the `run` directory and run the binary `iccad19gr` with a toy case `ispd18_sample`:\n```bash\n$ cd run\n$ ./iccad19gr -lef ../toys/iccad2019c/ispd18_sample/ispd18_sample.input.lef -def ../toys/iccad2019c/ispd18_sample/ispd18_sample.input.def -output ispd18_sample.solution.guide -threads 8\n```\n\n#### Run with a Wrapping Script\n\nInstead of running the binary directly, you may also use a wrapping script `run.py` to save typing and do more:\n```bash\n$ cd run\n$ ./run.py 8s -p ../toys/\n```\n\nIf Innovus® has been properly installed in your OS, an evaluation can be launched by\n```bash\n$ ./run.py 8s -s eval -p ../toys/\n```\nIn the end, a result table will be printed in the terminal.\n\nFurthermore, the solution can be visualized by\n```bash\n$ ./run.py 8s -s view -p ../toys/\n```\nwhich gives:\n\n![ispd18_sample.solution.png](/toys/iccad2019c/ispd18_sample/ispd18_sample.solution.png)\n\nThe three steps, `route`, `eval` and `view` of `run.py` can also be invoked in a single line:\n```bash\n$ ./run.py 8s -s route eval view -p ../toys/\n```\nMore usage about `run.py` can be known by the option `-h`.\n\n### 2.2. Batch Test\n\nThe benchmarks can be downloaded from [the hompage of ISPD'18 Contest ](http://www.ispd.cc/contests/18/#benchmarks).\nYou may let `run.py` know the benchmark path by setting OS environmental variable `BENCHMARK_PATH` or specifying it under option `-p`.\nThen,\n```bash\n$ cd run\n$ ./run.py <benchmark_name...|all> -s route eval [option...]\n```\n\n## 3. Modules\n\n* `ispd18eval`: scripts and other files for evaluation, provided by [ICCAD'19 Contest](http://iccad-contest.org/2019/Problem_C/eval.zip)\n* `ispd19eval`: scripts and other files for evaluation, provided by [ICCAD'19 Contest](http://iccad-contest.org/2019/Problem_C/eval.zip)\n* `rsyn`: code from [Rsyn](https://github.com/RsynTeam/rsyn-x) for file IO\n* `scripts`: utility python scripts\n* `src`: C++ source code\n    * `db`: database, including the global grid graph and the net information\n    * `single_net`: routing a single net, including querying the global grid graph, building the local grid graph, running maze routing, and some post processing\n    * `multi_net`: routing all nets with \"rip-up and rereoute\" and multithreading\n    * `utils`: some utility code\n* `toys`: toy test cases\n* `drcu`: default detailed router for evaluation\n\n\n## 4. Results\n\nExperiments are performed on a 64-bit Linux workstation with Intel Xeon Silver 4114 CPU (2.20GHz, 40 cores) and 256GB memory.\nConsistent with the contest, eight threads are used.\n\n|   Design  | Wire Length  & Via | Non-Preferred  Usage |   Short  | Min-Area  & Spacing | DR Score | GR  Runtime (sec) |\n|:---------:|:------------------:|:--------------------:|:--------:|:-------------------:|:--------:|:---------------:|\n|  `ispd2018_test5`  |      15613663      |        166994        |  330425  |        288500       | 16089196 |        68       |\n|  `ispd2018_test5_metal5` |      15807997      |        135293        |  261150  |        224000       | 16210303 |        85       |\n|  `ispd2018_test8`  |      37441058      |        269993        |  209470  |        144000       | 37908815 |       236       |\n|  `ispd2018_test8_metal5` |      36746610      |        336768        |  194510  |        129500       | 37293962 |       300       |\n|  `ispd2018_test10` |      39061258      |        882371        |  669965  |        471000       | 40600501 |       334       |\n| `ispd2018_test10_metal5` |      40246090      |        1413120       |  4021620 |        685500       | 46300610 |       373       |\n|  `ispd2019_test7`  |      77286072      |        1428396       |  9680620 |       6883000       | 88577731 |       506       |\n|  `ispd2019_test7_metal5` |      70848996      |        1535876       |  9943260 |       6686000       | 82169293 |       377       |\n|  `ispd2019_test8`  |      119199593      |        1338449       |  7780220 |       6103000       | 128412302 |       365       |\n|  `ispd2019_test8_metal5` |      116062781      |        1493314       |  8561400 |       6089000       | 126429212 |       588       |\n|  `ispd2019_test9`  |      184246497      |        2181774       | 14765850 |       10847000      | 201270655 |       528       |\n|  `ispd2019_test9_metal5` |      179242111      |        2323850       | 16020280 |       10948000      | 197937335 |       658       |\n\n## 5. License\n\nREAD THIS LICENSE AGREEMENT CAREFULLY BEFORE USING THIS PRODUCT. BY USING THIS PRODUCT YOU INDICATE YOUR ACCEPTANCE OF THE TERMS OF THE FOLLOWING AGREEMENT. THESE TERMS APPLY TO YOU AND ANY SUBSEQUENT LICENSEE OF THIS PRODUCT.\n\n\n\nLicense Agreement for CUGR\n\n\n\nCopyright (c) 2020 by The Chinese University of Hong Kong\n\n\n\nAll rights reserved\n\n\n\nCU-SD LICENSE (adapted from the original BSD license) Redistribution of the any code, with or without modification, are permitted provided that the conditions below are met.\n\n\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n\n\nRedistributions 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.\n\n\n\nNeither the name nor trademark of the copyright holder or the author may be used to endorse or promote products derived from this software without specific prior written permission.\n\n\n\nUsers are entirely responsible, to the exclusion of the author, for compliance with (a) regulations set by owners or administrators of employed equipment, (b) licensing terms of any other software, and (c) local, national, and international regulations regarding use, including those regarding import, export, and use of encryption software.\n\n\n\nTHIS FREE SOFTWARE IS PROVIDED BY THE AUTHOR \"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 AUTHOR OR ANY CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, EFFECTS OF UNAUTHORIZED OR MALICIOUS NETWORK ACCESS; 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.\n"
  },
  {
    "path": "ispd18eval/README",
    "content": "Prerequisite\n------------\nPlease make sure you have Innovus installed and the path to Innovus is added to your $PATH environment variable. To add a path to $PATH variable, add the following statement to your shell config file:\n\nAssuming the path to Innovus is /path/to/innovus/bin\n\nFor bash/ksh, add the following line to .bashrc/.kshrc\nexport PATH=/path/to/innovus/bin:$PATH\n\nFor csh/tcsh, add the following line to .cshrc\nsetenv PATH /path/to/innovus/bin:$PATH\n\nUsage\n-----\n./ispd18eval.sh -lef <path/to/input/LEF> -guide <path/to/input/guide> -def <path/to/solution/DEF>\n\nExample\n-------\n./ispd18eval.sh -lef sample/ispd18_sample.input.lef -guide sample/ispd18_sample.input.guide -def sample/ispd18_sample.output.def\n\nRequired files\n--------------\nin benchmark directory (use benchmark \"sample\" as example):\nispd18_sample.input.lef - input LEF file\nispd18_sample.input.guide - input route guide file\nispd18_sample.output.def - output DEF file with routing solution\n\nin evaluation directory:\nispd18eval.sh - evaluation script\nispd18eval - evaluation binary for score calculation\nispd18eval.w - weights for score calculation\nispd18eval.tcl - script for Innovus\n\nOutput files\n------------\nin the current directory (use benchmark \"sample\" as example):\nscore.rpt\n\nNotes\n-----\nPlease make sure:\n1. You have write permission to the current directory.\n2. You are able to start Innovus by just using \"innovus\" command on your terminal. Otherwise, you have to add the Innovus bin directory to your PATH variable.\n\nContacts\n--------\nispd2018contest@gmail.com\n\n"
  },
  {
    "path": "ispd18eval/ispd18eval.sh",
    "content": "#!/bin/sh\n\nif [ $# -eq 0 ] ; then\n    echo \"$0 -lef <input LEF> -guide <guide file> -def <routed DEF>\"\n    echo \"example:\"\n    echo \"$0 -lef sample/ispd18_sample.input.lef -guide sample/ispd18_sample.input.guide -def sample/ispd18_sample.output.def\"\n    exit\nfi\n\nINVS=\"innovus\"\nEVAL=\"./ispd18eval_bin\"\n\ncommand -v $INVS || {\n    echo \"$INVS is not available.\"\n    exit 1\n}\n\nkeepLogs=0\n\n#read arguments\nwhile [ $# -gt 0 ] ; do\n    case $1 in\n        -lef)   shift ; inputLef=$1 ;;\n        -guide) shift ; inputRg=$1 ;;\n        -def)   shift ; outputDef=$1 ;;\n        -keep)  shift ; keepLogs=1 ;;\n        *) echo \"unknown : $1\" ;;\n    esac\n    shift\ndone\n\nevalGeoRpt='eval.geo.rpt'\nevalConRpt='eval.con.rpt'\nevalScoreRpt='eval.score.rpt'\nevalTcl='eval.tcl'\n\nif [ ! -f $inputLef ] ; then\n    echo \"ERROR: $inputLef not found\"\n    exit\nelif [ ! -f $inputRg ] ; then\n    echo \"ERROR: $inputRg not found\"\n    exit\nelif [ ! -f $outputDef ] ; then\n    echo \"ERROR: $outputDef not found\"\n    exit\nfi\n\nif [ -f $evalTcl ] ; then\n    echo \"WARNING: tcl file exists, overwriting...\"\nfi\n\necho \"#evaluation script for ISPD 2018 contest\" > $evalTcl\necho 'source ispd18eval.tcl' >> $evalTcl\necho \"evaluate $inputLef $outputDef $evalGeoRpt $evalConRpt\" >> $evalTcl\necho 'exit' >>$evalTcl\n\nif [ \"$keepLogs\" = 0 ] ; then\n    rm -f $evalGeoRpt\n    rm -f $evalConRpt\nfi\n\ncmd=\"$INVS -init $evalTcl -log eval.log -overwrite -nowin\"\necho $cmd\n$cmd\n\nif [ \"$keepLogs\" = 0 ] ; then\n    rm $evalTcl\n    rm 'eval.log'\n    rm 'eval.logv'\n    rm 'eval.cmd'\n    rm `basename \"$outputDef.v\"`\nfi\n\ncmd=\"$EVAL -lef $inputLef -def $outputDef -guide $inputRg -georpt $evalGeoRpt -conrpt $evalConRpt\"\necho $cmd\n$cmd | tee $evalScoreRpt\n\n"
  },
  {
    "path": "ispd18eval/ispd18eval.tcl",
    "content": "\nproc evaluate { inputLef outputDef evalGeoRpt evalConRpt } {\n    setMultiCpuUsage -localCpu 8\n    loadDesign $inputLef $outputDef\n\n    setVerifyGeometryMode -area { 0 0 0 0 }\n    setVerifyGeometryMode -minWidth false\n    setVerifyGeometryMode -minSpacing true\n    setVerifyGeometryMode -minArea true\n    setVerifyGeometryMode -sameNet true\n    setVerifyGeometryMode -short true\n    setVerifyGeometryMode -overlap false\n    setVerifyGeometryMode -offRGrid false\n    setVerifyGeometryMode -offMGrid false\n    setVerifyGeometryMode -mergedMGridCheck false\n    setVerifyGeometryMode -minHole false\n    setVerifyGeometryMode -implantCheck false\n    setVerifyGeometryMode -minimumCut false\n    setVerifyGeometryMode -minStep false\n    setVerifyGeometryMode -viaEnclosure false\n    setVerifyGeometryMode -antenna false\n    setVerifyGeometryMode -insuffMetalOverlap false\n    setVerifyGeometryMode -pinInBlkg false\n    setVerifyGeometryMode -diffCellViol false\n    setVerifyGeometryMode -sameCellViol false\n    setVerifyGeometryMode -padFillerCellsOverlap false\n    setVerifyGeometryMode -routingBlkgPinOverlap false\n    setVerifyGeometryMode -routingCellBlkgOverlap false\n    setVerifyGeometryMode -regRoutingOnly false\n    setVerifyGeometryMode -stackedViasOnRegNet false\n    setVerifyGeometryMode -wireExt false\n    setVerifyGeometryMode -useNonDefaultSpacing false\n    setVerifyGeometryMode -maxWidth false\n    setVerifyGeometryMode -maxNonPrefLength -1\n    setVerifyGeometryMode -error 10000000\n    catch { verifyGeometry -report $evalGeoRpt }\n\n    catch { verifyConnectivity -noFloatingMetal -error 10000000 -report $evalConRpt }\n    #catch { verifyConnectivity -type all -noAntenna -noUnConnPin -geomConnect -noSoftPGConnect -noFloatingMetal -error 10000000 -report $evalConRpt }\n\n    exit\n}\n\nproc loadDesign { lef def } {\n    catch { loadLefFile $lef }\n    catch { loadDefFile $def }\n}\n\n"
  },
  {
    "path": "ispd18eval/ispd18eval.w",
    "content": "Wire            0.5\nVia             2.0\nOutOfGuideWire  1.0\nOutOfGuideVia   1.0\nOffTrackWire    0.5\nOffTrackVia     1.0\nWrongWayWire    1.0\nShort           500.0\nArea            500.0\nSpacing         500.0\nOpen            0.0\n"
  },
  {
    "path": "ispd19eval/README",
    "content": "Prerequisite\n------------\nPlease make sure you have Innovus installed and the path to Innovus is added to your $PATH environment variable. To add a path to $PATH variable, add the following statement to your shell config file:\n\nAssuming the path to Innovus is /path/to/innovus/bin\n\nFor bash/ksh, add the following line to .bashrc/.kshrc\nexport PATH=/path/to/innovus/bin:$PATH\n\nFor csh/tcsh, add the following line to .cshrc\nsetenv PATH /path/to/innovus/bin:$PATH\n\nUsage\n-----\n./ispd19eval.sh -lef <path/to/input/LEF> -guide <path/to/input/guide> -idef <path/to/input/DEF> -odef <path/to/solution/DEF>\n\nExample\n-------\n./ispd19eval.sh -lef sample/ispd19_sample.input.lef -guide sample/ispd19_sample.input.guide -idef sample/ispd19_sample.input.def -odef sample/ispd19_sample.output.def\n\nRequired files\n--------------\nin benchmark directory (use benchmark \"sample\" as example):\nispd19_sample.input.lef - input LEF file\nispd19_sample.input.def - input DEF file\nispd19_sample.input.guide - input route guide file\nispd19_sample.output.def - output DEF file with routing solution\n\nin evaluation directory:\nispd19eval.sh - evaluation script\nispd19eval - evaluation binary for score calculation\nispd19eval.w - weights for score calculation\nispd19eval.tcl - script for Innovus\n\nOutput files\n------------\nin the current directory (use benchmark \"sample\" as example):\nscore.rpt\n\nNotes\n-----\nPlease make sure:\n1. You have write permission to the current directory.\n2. You are able to start Innovus by just using \"innovus\" command on your terminal. Otherwise, you have to add the Innovus bin directory to your PATH variable.\n\nContacts\n--------\nispd2019contest@gmail.com\n\n"
  },
  {
    "path": "ispd19eval/ispd19eval.sh",
    "content": "#!/bin/sh\n\nif [ $# -eq 0 ] ; then\n    echo \"$0 -lef <input LEF> -guide <guide file> -idef <input DEF> -odef <routed DEF>\"\n    echo \"example:\"\n    echo \"$0 -lef sample/ispd19_sample.input.lef -guide sample/ispd19_sample.input.guide -idef sample/ispd19_sample.input.def -odef sample/ispd19_sample.output.def\"\n    exit\nfi\n\nINVS=\"innovus\"\nEVAL=\"./ispd19eval_bin\"\n\ncommand -v $INVS || {\n    echo \"$INVS is not available.\"\n    exit 1\n}\n\nmethod='a'\nkeepLogs=0\nprefix=\ntrimmedDef='eval.def'\ncombinedDef='comb.def'\n\n#read arguments\nwhile [ $# -gt 0 ] ; do\n    case $1 in\n        -lef)   shift ; inputLef=$1 ;;\n        -guide) shift ; inputRg=$1 ;;\n        -idef)  shift ; inputDef=$1 ;;\n        -odef)  shift ; outputDef=$1 ;;\n        -tdef)  shift ; trimmedDef=$1 ;;\n        -cdef)  shift ; combinedDef=$1 ;;\n        -prefix) shift ; prefix=$1 ;;\n        -method) shift ; method=$1 ;;\n        -keep) keepLogs=1 ;;\n        *) echo \"unknown : $1\" ;;\n    esac\n    shift\ndone\n\nevalGeoRpt=\"${prefix}eval.geo.rpt\"\nevalConRpt=\"${prefix}eval.con.rpt\"\nevalScoreRpt=\"${prefix}eval.score.rpt\"\nevalTcl=\"${prefix}eval.tcl\"\ninvsLog=\"${prefix}eval\"\n\nif [ ! -f $inputLef ] ; then\n    echo \"ERROR: $inputLef not found\"\n    exit\nelif [ ! -f $inputRg ] ; then\n    echo \"ERROR: $inputRg not found\"\n    exit\nelif [ ! -f $inputDef ] ; then\n    echo \"ERROR: $inputDef not found\"\n    exit\nelif [ ! -f $outputDef ] ; then\n    echo \"ERROR: $outputDef not found\"\n    exit\nfi\n\nif [ -f $evalTcl ] ; then\n    echo \"WARNING: tcl file exists, overwriting...\"\nfi\n\nif [ \"$method\" = 'a' ] ; then\n    dbuMicron=`grep \"UNITS DISTANCE MICRONS\" $inputDef | cut -d' ' -f 4`\n    echo 'VERSION 5.8 ;' > $trimmedDef\n    echo 'DIVIDERCHAR \"/\" ;' >> $trimmedDef\n    echo 'BUSBITCHARS \"[]\" ;' >> $trimmedDef\n    echo \"UNITS DISTANCE MICRONS $dbuMicron ;\" >> $trimmedDef\n    sed -n '/^[[:blank:]]*NETS[[:blank:]]*[1-9][0-9]*[[:blank:]]*;[[:blank:]]*$/,/^[[:blank:]]*END NETS[[:blank:]]*$/p' $outputDef >> $trimmedDef\nelif [ \"$method\" = 'b' ] ; then\n    sed -n '/^[[:blank:]]*VERSION[[:blank:]]*[0-9]\\.[0-9][[:blank:]]*;[[:blank:]]*$/,/^END SPECIALNETS[[:blank:]]*$/p' $inputDef > $combinedDef\n    sed -n '/^[[:blank:]]*NETS[[:blank:]]*[1-9][0-9]*[[:blank:]]*;[[:blank:]]*$/,/^[[:blank:]]*END NETS[[:blank:]]*$/p' $outputDef >> $combinedDef\n    echo \"END DESIGN\" >> $combinedDef\n\nelse\n    echo \"ERROR: unknown evaluation method $method\"\n    exit\nfi\n\necho \"#evaluation script for ISPD 2019 contest\" > $evalTcl\necho 'source ispd19eval.tcl' >> $evalTcl\nif [ \"$method\" = 'a' ] ; then\n    echo \"evaluate $inputLef $inputDef $trimmedDef $evalGeoRpt $evalConRpt\" >> $evalTcl\nelse\n    echo \"evaluate $inputLef $combinedDef {} $evalGeoRpt $evalConRpt\" >> $evalTcl\nfi\n\necho 'exit' >>$evalTcl\n\nif [ \"$keepLogs\" = 0 ] ; then\n    rm -f $evalGeoRpt\n    rm -f $evalConRpt\nfi\n\ncmd=\"$INVS -init $evalTcl -log $invsLog.log -overwrite -nowin\"\necho $cmd\n$cmd\n\nif [ \"$keepLogs\" = 0 ] ; then\n    rm -f $evalTcl\n    rm -f \"$invsLog.log\"\n    rm -f \"$invsLog.logv\"\n    rm -f \"$invsLog.cmd\"\n    rm -f `basename \"$outputDef.v\"`\nfi\n\ncmd=\"$EVAL -lef $inputLef -def $outputDef -guide $inputRg -georpt $evalGeoRpt -conrpt $evalConRpt\"\necho $cmd\n$cmd | tee $evalScoreRpt\n\n"
  },
  {
    "path": "ispd19eval/ispd19eval.tcl",
    "content": "setMultiCpuUsage -localCpu 8\nproc evaluate { inputLef inputDef outputDef evalGeoRpt evalConRpt } {\n\n    loadDesign $inputLef $inputDef $outputDef\n    \n    set_verify_drc_mode -disable_rules {}\n    set_verify_drc_mode -check_implant true\n    set_verify_drc_mode -check_implant_across_rows false\n    set_verify_drc_mode -check_ndr_spacing false\n    set_verify_drc_mode -check_only default\n    set_verify_drc_mode -check_same_via_cell false\n    set_verify_drc_mode -exclude_pg_net false\n    set_verify_drc_mode -ignore_trial_route false\n    set_verify_drc_mode -report $evalGeoRpt\n    set_verify_drc_mode -limit 10000000\n    catch { verify_drc }\n\n#   catch { verifyConnectivity -noFloatingMetal -error 10000000 -report $evalConRpt }\n    catch { verifyConnectivity -type all -noAntenna -noUnConnPin -geomConnect -noSoftPGConnect -noFloatingMetal -error 10000000 -report $evalConRpt }\n\n    exit\n}\n\nproc loadDesign { lef idef odef } {\n    catch { loadLefFile $lef }\n    catch { loadDefFile $idef }\n    if { $odef != \"\" } {\n        catch { defIn $odef }\n    }\n}\n\n"
  },
  {
    "path": "ispd19eval/ispd19eval.w",
    "content": "Wire            0.5\nSingleCutVia    4.0\nMultiCutVia     2.0\nOutOfGuideWire  1.0\nOutOfGuideVia   1.0\nOffTrackWire    0.5\nOffTrackVia     1.0\nWrongWayWire    1.0\nShort           500.0\nShortArea       500.0\nParallelRun     500.0\nEndOfLine       500.0\nCutSpacing      500.0\nAdjCutSpacing   500.0\nCornerSpacing   500.0\nMinArea         500.0\nOpen            0.0\n\n"
  },
  {
    "path": "rsyn/.gitrepo",
    "content": "; DO NOT EDIT (unless you know what you are doing)\n;\n; This subdirectory is a git \"subrepo\", and this file is maintained by the\n; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme\n;\n[subrepo]\n\tremote = https://github.com/rsyn/rsyn.git\n\tbranch = master\n\tcommit = 99dc1241ef523c416be2617c7c7bdd3eec15413f\n\tparent = 09d1bb30dc611121087a3ce33968e806944d33bb\n\tcmdver = 0.3.1\n"
  },
  {
    "path": "rsyn/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "rsyn/README.md",
    "content": "\n#### This is a subrepository. Please go to the [rsyn-x](https://github.com/rsyn/rsyn-x) for the main repository.\n"
  },
  {
    "path": "rsyn/include/def5.8/defiAlias.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013 - 2014, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiALIAS_h\n#define defiALIAS_h\n\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defAliasIterator;\nclass defrData;\n\nclass defiAlias_itr {\npublic:\n  defiAlias_itr(defrData *defData = 0);\n  void Init();\n\n  void Destroy();\n  ~defiAlias_itr();\n\n  int Next();\n  const char* Key();\n  const char* Data();\n  int Marked();\n\nprotected:\n  defAliasIterator   *iterator;\n  int first;\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiAssertion.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiAssertion_h\n#define defiAssertion_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Struct holds the data for one assertion/constraint.\n// An assertion or constraint is either a net/path rule or a\n// wired logic rule.\n//\n//  A net/path rule is an item or list of items plus specifications.\n//    The specifications are: rise/fall min/max.\n//    The items are a list of (one or more) net names or paths or a\n//    combination of both.\n//\n//  A wired logic rule is a netname and a distance.\n//\n//  We will NOT allow the mixing of wired logic rules and net/path delays\n//  in the same assertion/constraint.\n//\n//  We will allow the rule to be a sum of sums (which will be interpreted\n//  as just one list).\n//\nclass defrData;\n\nclass defiAssertion {\npublic:\n  defiAssertion(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiAssertion();\n\n  void setConstraintMode();\n  void setAssertionMode();\n  void setSum();\n  void setDiff();\n  void setNetName(const char* name);\n  void setRiseMin(double num);\n  void setRiseMax(double num);\n  void setFallMin(double num);\n  void setFallMax(double num);\n  void setDelay();\n  void setWiredlogicMode();\n  void setWiredlogic(const char* net, double dist);\n  void addNet(const char* name);\n  void addPath(const char* fromInst, const char* fromPin,\n               const char* toInst, const char* toPin);\n  void bumpItems();\n  void unsetSum();\n\n  int isAssertion() const;  // Either isAssertion or isConstraint is true\n  int isConstraint() const;\n  int isWiredlogic() const; // Either isWiredlogic or isDelay is true\n  int isDelay() const;\n  int isSum() const;\n  int isDiff() const;\n  int hasRiseMin() const;\n  int hasRiseMax() const;\n  int hasFallMin() const;\n  int hasFallMax() const;\n  double riseMin() const;\n  double riseMax() const;\n  double fallMin() const;\n  double fallMax() const;\n  const char* netName() const; // Wired logic net name\n  double distance() const; // Wired logic distance\n  int numItems() const;  // number of paths or nets \n  int isPath(int index) const;   // is item #index a path?\n  int isNet(int index) const;    // is item #index a net?\n  void path(int index, char** fromInst, char** fromPin,\n\t   char** toInst, char** toPin) const; // Get path data for item #index\n  void net(int index, char** netName) const;   // Get net data for item #index\n\n  void clear();\n  void print(FILE* f) const;\n\n\nprotected:\n  char isAssertion_;\n  char isSum_;\n  char isDiff_;\n  char hasRiseMin_;\n  char hasRiseMax_;\n  char hasFallMin_;\n  char hasFallMax_;\n  char isWiredlogic_;\n  char isDelay_;\n  char* netName_;     // wired logic net name\n  int netNameLength_;\n  double riseMin_;\n  double riseMax_;\n  double fallMin_;\n  double fallMax_;    // also used to store the wired logic dist\n  int numItems_;\n  int numItemsAllocated_;\n  char* itemTypes_;\n  int** items_;       // not really integers.\n\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiBlockage.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiBLOCKAGES_h\n#define defiBLOCKAGES_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n#include \"defiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\nclass defrData;\n\nclass defiBlockage {\npublic:\n  defiBlockage(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiBlockage();\n\n  void clear();\n  void clearPoly();\n\n  void setLayer(const char* name);\n  void setPlacement();\n  void setComponent(const char* name);\n  void setSlots();\n  void setFills();\n  void setPushdown();\n  void setExceptpgnet();                            // 5.7\n  void setSoft();                                   // 5.7\n  void setPartial(double maxDensity);               // 5.7\n  void setSpacing(int minSpacing);\n  void setDesignRuleWidth(int width);\n  void setMask(int maskColor);                      // 5.8\n  void addRect(int xl, int yl, int xh, int yh);\n  void addPolygon(defiGeometries* geom);\n\n  int hasLayer() const;\n  int hasPlacement() const;\n  int hasComponent() const;\n  int hasSlots() const;\n  int hasFills() const;\n  int hasPushdown() const;\n  int hasExceptpgnet() const;                       // 5.7\n  int hasSoft() const;                              // 5.7\n  int hasPartial() const;                           // 5.7\n  int hasSpacing() const;                           // 5.6\n  int hasDesignRuleWidth() const;                   // 5.6\n  int hasMask() const;                              // 5.8\n  int mask() const;                            // 5.8\n  int minSpacing() const;                           // 5.6\n  int designRuleWidth() const;                      // 5.6\n  double placementMaxDensity() const;               // 5.7\n  const char* layerName() const;\n  const char* layerComponentName() const;\n  const char* placementComponentName() const;\n\n  int numRectangles() const;\n  int xl(int index) const;\n  int yl(int index) const;\n  int xh(int index) const;\n  int yh(int index) const;\n\n  int numPolygons() const;                          // 5.6\n  struct defiPoints getPolygon(int index) const;    // 5.6\n\n  void print(FILE* f) const;\n\nprotected:\n  int    hasLayer_;\n  char*  layerName_;\n  int    layerNameLength_;\n  int    hasPlacement_;\n  int    hasComponent_;\n  char*  componentName_;\n  int    componentNameLength_;\n  int    hasSlots_;\n  int    hasFills_;\n  int    hasPushdown_;                   // 5.7\n  int    hasExceptpgnet_ ;               // 5.7\n  int    hasSoft_;                       // 5.7\n  double maxDensity_;                    // 5.7\n  int    minSpacing_;\n  int    width_;\n  int    numRectangles_;\n  int    rectsAllocated_;\n  int    mask_;                          // 5.8\n  int*   xl_;\n  int*   yl_;\n  int*   xh_;\n  int*   yh_;\n  int    numPolys_;                      // 5.6\n  int    polysAllocated_;                // 5.6\n  struct defiPoints** polygons_;         // 5.6\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiComponent.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiComponent_h\n#define defiComponent_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n// Placement status for the component.\n// Default is 0\n#define DEFI_COMPONENT_UNPLACED 1\n#define DEFI_COMPONENT_PLACED 2\n#define DEFI_COMPONENT_FIXED 3\n#define DEFI_COMPONENT_COVER 4\n\n\n// Struct holds the data for componentMaskShiftLayers.\nclass defiComponentMaskShiftLayer {\npublic:\n                defiComponentMaskShiftLayer(defrData *data);\n                ~defiComponentMaskShiftLayer();\n\n    void         Init();\n    void         Destroy();\n    void         addMaskShiftLayer(const char* layer);\n    int          numMaskShiftLayers() const;\n    void         bumpLayers(int size);\n    void         clear();\n    const  char* maskShiftLayer(int index) const;\n\nprotected:\n    int          layersAllocated_;  // allocated size of layers_\n    int          numLayers_;        // number of places used in layers_\n    char**       layers_;\n\n    defrData    *defData;\n};\n\n\n// Struct holds the data for one component.\nclass defiComponent {\npublic:\n  defiComponent(defrData *defData);\n  void Init();\n\n  void Destroy();\n  ~defiComponent();\n\n  void IdAndName(const char* id, const char* name);\n  void setGenerate(const char* genName, const char* macroName);\n  void setPlacementStatus(int n);\n  void setPlacementLocation(int x, int y, int orient);\n  void setRegionName(const char* name);\n  void setRegionBounds(int xl, int yl, int xh, int yh);\n  void setEEQ(const char* name);\n  void addNet(const char* netName);\n  void addProperty(const char* name, const char* value, const char type);\n  void addNumProperty(const char* name, const double d,\n                      const char* value, const char type);\n  void reverseNetOrder();\n  void setWeight(int w);\n  void setMaskShift(const char* color);\n  void setSource(const char* name);\n  void setForeignName(const char* name);\n  void setFori(const char* name);\n  void setForeignLocation(int x, int y, int orient);\n  void setHalo(int left, int bottom, int right, int top);   // 5.6\n  void setHaloSoft();                                       // 5.7\n  void setRouteHalo(int haloDist, const char* minLayer, const char* maxLayer);\n                                                            // 5.7\n  void clear();\n\n  // For OA to modify the Id & Name\n  void changeIdAndName(const char* id, const char* name);\n\n  const char* id() const;\n  const char* name() const;\n  int placementStatus() const;\n  int isUnplaced() const;\n  int isPlaced() const;\n  int isFixed() const;\n  int isCover() const;\n  int placementX() const;\n  int placementY() const;\n  int placementOrient() const;\n  const char* placementOrientStr() const;\n  int hasRegionName() const;\n  int hasRegionBounds() const;\n  int hasEEQ() const;\n  int hasGenerate() const;\n  int hasSource() const;\n  int hasWeight() const;\n  int weight() const;\n  int maskShiftSize() const;\n  int maskShift(int index) const;\n  int hasNets() const;\n  int numNets() const;\n  const char* net(int index) const;\n  const char* regionName() const;\n  const char* source() const;\n  const char* EEQ() const;\n  const char* generateName() const;\n  const char* macroName() const;\n  int hasHalo() const;                     // 5.6\n  int hasHaloSoft() const;                 // 5.7\n  void haloEdges(int* left, int* bottom, int* right, int* top);  // 5.6 \n  int hasRouteHalo() const;                // 5.7\n  int haloDist() const;                    // 5.7\n  const char* minLayer() const;            // 5.7\n  const char* maxLayer() const;            // 5.7\n\n  // Returns arrays for the ll and ur of the rectangles in the region.\n  // The number of items in the arrays is given in size.\n  void regionBounds(int*size, int** xl, int** yl, int** xh, int** yh) const;\n\n  int hasForeignName() const;\n  const char* foreignName() const;\n  int foreignX() const;\n  int foreignY() const;\n  const char* foreignOri() const; // return the string value of the orient\n  int foreignOrient() const;      // return the enum value of the orient\n  int hasFori() const;\n\n  int    numProps() const;\n  char*  propName(int index) const;\n  char*  propValue(int index) const;\n  double propNumber(int index) const;\n  char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n\n\n  // Debug printing\n  void print(FILE* fout) const;\n\n  void bumpId(int size);\n  void bumpName(int size);\n  void bumpRegionName(int size);\n  void bumpEEQ(int size);\n  void bumpNets(int size);\n  void bumpForeignName(int size);\n  void bumpMinLayer(int size);\n  void bumpMaxLayer(int size);\n  void bumpFori(int size);\n\nprotected:\n  char* id_;            // instance id\n  char* name_;          // name.\n  int nameSize_;        // allocated size of name.\n  int idSize_;          // allocated size of id.\n  int ForiSize_;        // allocate size of foreign ori\n  int status_;          // placement status\n  char hasRegionName_;  // the file supplied a region name for this comp\n  char hasEEQ_;         // the file supplied an eeq\n  char hasGenerate_;    // the file supplied an generate name and macro name\n  char hasWeight_;      // the file supplied a weight\n  char hasFori_;        // the file supplied a foreign orig name\n  int orient_;          // orientation\n  int x_, y_;           // placement loc\n\n  int numRects_;\n  int rectsAllocated_;\n  int* rectXl_;       // region points\n  int* rectYl_;\n  int* rectXh_;\n  int* rectYh_;\n\n  char* regionName_;    // name.\n  int regionNameSize_;  // allocated size of region name\n\n  char* EEQ_;\n  int EEQSize_;         // allocated size of eeq\n\n  int numNets_;         // number of net connections\n  int netsAllocated_;   // allocated size of nets array\n  char** nets_;         // net connections\n\n  int weight_;\n  int* maskShift_; \n  int maskShiftSize_;\n  char* source_;\n  char hasForeignName_; // the file supplied a foreign name\n  char* foreignName_;   // name\n  int foreignNameSize_; // allocate size of foreign name\n  int Fx_, Fy_;         // foreign loc\n  int Fori_;            // foreign ori\n  int generateNameSize_;\n  char* generateName_;\n  int macroNameSize_;\n  char* macroName_;\n\n  int hasHalo_;\n  int hasHaloSoft_;           // 5.7\n  int leftHalo_;\n  int bottomHalo_;\n  int rightHalo_;\n  int topHalo_;\n  int haloDist_;              // 5.7\n  int minLayerSize_;          // 5.7\n  char* minLayer_;            // 5.7\n  int maxLayerSize_;          // 5.7\n  char* maxLayer_;            // 5.7\n\n  int numProps_;\n  int propsAllocated_;\n  char**  names_;\n  char**  values_;\n  double* dvalues_;\n  char*   types_;\n\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiDebug.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiDebug_h\n#define defiDebug_h \n\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n/* Set flag */\nextern void defiSetDebug (int num, int value) ;\n\n/* Read flag */\nextern int defiDebug (int num) ;\n\n/* Error loggin function */\nextern void defiError(int check, int msgNum, const char* message, defrData *defData = NULL);\n\n/* for auto upshifting names in case insensitive files */\nextern const char* upperCase(const char* c, defrData *defData = NULL);\nextern const char* DEFCASE(const char* ch, defrData *defData = NULL);\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiDefs.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n/* Definitions header file for the DEF Interface */\n\n#ifndef DEFI_DEFS_H\n#define DEFI_DEFS_H\n\n#include <stdio.h>\n#include <limits.h>\n\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n/*=================== General Types and Definitions =================*/\n\n#ifndef TRUE\n#define TRUE (1)\n#endif\n\n#ifndef FALSE\n#define FALSE (0)\n#endif\n\n#ifndef NULL\n#define NULL (0)\n#endif\n\ntypedef struct defpoint defPOINT;\n\nstruct defpoint {\n    int x;\n    int y;\n    };\n\ntypedef struct defrect defRECT;\n\nstruct defrect {\n    defPOINT ll,ur;\n    };\n\ntypedef struct deftoken defTOKEN;\n\nstruct deftoken {\n    defTOKEN *next;\n    int what;\n    int data;\n    defPOINT pt;\n    };\n\n#define START_LIST 10001\n#define POINT_SPEC 10002\n#define VIA_SPEC   10003\n#define WIDTH_SPEC 10004\n#define LAYER_SPEC 10005\n#define SHAPE_SPEC 10006\n\n#ifndef\tMIN\n#define MIN(x,y) ((x) < (y)? (x) : (y))\n#endif\n\n#ifndef\tMIN\n#define MAX(x,y) ((x) > (y)? (x) : (y))\n#endif\n\n#define ROUND(x) ((x) >= 0 ? (int)((x)+0.5) : (int)((x)-0.5))\n\n//defTOKEN *TokenFromRect();\n\n/*=================== Enumerated Types ============================*/\ntypedef int defiBoolean;\n\n/* Every type of object has a unique identifier, and each object\n * which is created knows its type, by storing the defiObjectType_e\n * as the first member in the structure.\n *\n */\ntypedef enum\n{\n  /* decrease likelihood of accidentally correct values by starting\n     at an unusual number */\n  defiInvalidObject = 41713, \n  defiUnknownObject /* void * */\n} defiObjectType_e;\n\n\n/* The memory policy controls how an object which refers to or is composed of\n * other objects manages those sub-objects, particularly when the parent\n * object is copied or deleted.  The policy is specified as an argument to the\n * constructor or initializer, and it is stored with the parent object.\n *\n * The memory policy is a generalization of the common distinction between\n * deep and shallow copies.  When a shallow copy of a parent object is made,\n * the copy maintains pointers to the original sub-objects, and the original\n * parent remains responsible for deleting those sub-objects.  When a deep\n * copy of a parent object is made, the copy maintains pointers to new copies\n * of each of the sub-objects, and the copy is responsible for deleting the\n * new sub-objects.\n *\n * The defiPrivateSubObjects policy corresponds to a deep copy, while the the\n * defiReferencedSubObjects policy corresponds to a shallow copy.  Usually an\n * initial parent object will be created using defiPrivateSubObjects.  When a\n * copy is made of that parent object, the copy may either maintain its own\n * private versions of each sub-object, or it may refer to the original\n * sub-objects.\n *\n * In certain cases, it is useful to create a deep copy of a parent object,\n * even though the new parent object shouldn't be responsible for the new\n * sub-objects.  In this case, the defiOrphanSubObjects and\n * defiAdoptedSubObjects policies may be used.  defiOrphanSubObjects is\n * specified while creating the deep copy, and then defiAdoptedSubObjects is\n * specified while creating another parent which will take on the\n * responsibility for the orphans.\n *\n * An object's memory policy affects only the sub-objects which it directly\n * controls.  Those sub-objects themselves may have the same memory policy as\n * their parents, or they may have a different memory policy.  When a copy is\n * made of a child sub-object, the memory policy of the child controls\n * whether deep or shallow copies are made of the grandchildren.\n */\ntypedef enum\n{\n  /* decrease likelihood of accidentally correct values by starting\n     at an unusual number */\n  defiInvalidMemoryPolicy = 23950,\n  defiPrivateSubObjects,      // deep copy + delete\n  defiReferencedSubObjects,   // shallow copy, no delete\n  defiOrphanSubObjects,       // deep copy, no delete\n  defiAdoptedSubObjects       // shallow copy + delete\n} defiMemoryPolicy_e;\n\n/* An opaque pointer for passing user data through from one API\n * function to another.\n * A handle which a user can set to point to their own data\n * on a per-callback basis.  (See the comment in defwWriter.h)\n */\n#define defiUserData void *\n#define defiUserDataHandle void **\n\n/* On SunOs 4.1.3 with acc, this is in libansi.a, but isn't properly\n * declared anywhere in the header files supplied with the compiler.\n */\n#ifdef __SunOS_4_1_3\nextern int strcasecmp(const char*, const char*);\n#endif\n\n#ifdef WIN32\n#define strdup _strdup\n#endif \n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiFPC.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiFPC_h\n#define defiFPC_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiFPC {\npublic:\n  defiFPC(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiFPC();\n\n  void clear();\n\n  void setName(const char* name, const char* direction);\n  void setAlign();\n  void setMax(double num);\n  void setMin(double num);\n  void setEqual(double num);\n  void setDoingBottomLeft();\n  void setDoingTopRight();\n  void addRow(const char* name);\n  void addComps(const char* name);\n  void addItem(char typ, const char* name);\n\n  const char* name() const;\n  int isVertical() const;\n  int isHorizontal() const;\n  int hasAlign() const;\n  int hasMax() const;\n  int hasMin() const;\n  int hasEqual() const;\n  double alignMax() const;\n  double alignMin() const;\n  double equal() const;\n\n  int numParts() const;\n\n  // Return the constraint number \"index\" where index is\n  //    from 0 to numParts()\n  // The returned corner is 'B' for bottom left  'T' for topright\n  // The returned typ is 'R' for rows   'C' for comps\n  // The returned char* points to name of the item.\n  void getPart(int index, int* corner, int* typ, char** name) const;\n\n  // debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameLength_;\n  char direction_; // H or V\n  char hasAlign_;\n  char hasMin_;\n  char hasMax_;\n  char hasEqual_;\n  char corner_;   // Bottomleft or Topright\n  double minMaxEqual_;\n  int namesAllocated_;  // allocated size of names_ and rowOrComp_\n  int namesUsed_;       // number of entries used in the arrays\n  char* rowOrComp_;\n  char** names_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiFill.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiFILL_h\n#define defiFILL_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n#include \"defiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiFill {\npublic:\n  defiFill(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiFill();\n\n  void clear();\n  void clearPoly();\n  void clearPts();\n\n  void setLayer(const char* name);\n  void setLayerOpc();                             // 5.7\n  void addRect(int xl, int yl, int xh, int yh);\n  void addPolygon(defiGeometries* geom);\n  void setVia(const char* name);                  // 5.7\n  void setViaOpc();                               // 5.7\n  void addPts(defiGeometries* geom);              // 5.7\n\n  int hasLayer() const;\n  const char* layerName() const;\n  int hasLayerOpc() const;                        // 5.7\n\n  void setMask(int colorMask);\t\t\t  // 5.8\n  int layerMask() const;                          // 5.8\n  int viaTopMask() const;\t\t\t  // 5.8\n  int viaCutMask() const;\t\t\t  // 5.8\n  int viaBottomMask() const;                      // 5.8\n\n  int numRectangles() const;\n  int xl(int index) const;\n  int yl(int index) const;\n  int xh(int index) const;\n  int yh(int index) const;\n\n  int numPolygons() const;                        // 5.6\n  struct defiPoints getPolygon(int index) const;  // 5.6\n\n  int hasVia() const;                             // 5.7\n  const char* viaName() const;                    // 5.7\n  int hasViaOpc() const;                          // 5.7\n\n  int numViaPts() const;                          // 5.7\n  struct defiPoints getViaPts(int index) const;   // 5.7\n\n  void print(FILE* f) const;\n\nprotected:\n  int   hasLayer_;\n  char* layerName_;\n  int   layerNameLength_;\n  int   layerOpc_;                  // 5.7\n  int   numRectangles_;\n  int   rectsAllocated_;\n  int*  xl_;\n  int*  yl_;\n  int*  xh_;\n  int*  yh_;\n  int   numPolys_;                  // 5.6\n  int   polysAllocated_;            // 5.6\n  struct defiPoints** polygons_;    // 5.6\n  int   hasVia_;                    // 5.7\n  char* viaName_;                   // 5.7\n  int   viaNameLength_;             // 5.7\n  int   viaOpc_;                    // 5.7\n  int   numPts_;                    // 5.7\n  int   ptsAllocated_;              // 5.7\n  int   mask_;                      // 5.8\n  struct defiPoints** viaPts_;      // 5.7\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiGroup.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiGroup_h\n#define defiGroup_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n// Struct holds the data for one property.\n\nclass defiGroup {\npublic:\n  defiGroup(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiGroup();\n\n  void clear();\n\n  void setup(const char* name);\n  void addProperty(const char* name, const char* value, const char type);\n  void addNumProperty(const char* name, const double d,\n                      const char* value, const char type);\n  void addRegionRect(int xl, int yl, int xh, int yh);\n  void setRegionName(const char* name);\n  void setMaxX(int x);\n  void setMaxY(int y);\n  void setPerim(int p);\n\n  const char* name() const;\n  const char* regionName() const;\n  int hasRegionBox() const;\n  int hasRegionName() const;\n  int hasMaxX() const;\n  int hasMaxY() const;\n  int hasPerim() const;\n  void regionRects(int* size, int** xl, int**yl, int** xh, int** yh) const;\n  int maxX() const;\n  int maxY() const;\n  int perim() const;\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n\n  // debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameLength_;\n  char* region_;\n  int regionLength_;\n\n  int rectsAllocated_;\n  int numRects_;\n  int* xl_;\n  int* yl_;\n  int* xh_;\n  int* yh_;\n\n  int maxX_;\n  int maxY_;\n  int perim_;\n  char hasRegionBox_;\n  char hasRegionName_;\n  char hasPerim_;\n  char hasMaxX_;\n  char hasMaxY_;\n\n  int numProps_;\n  int propsAllocated_;\n  char**  propNames_;\n  char**  propValues_;\n  double* propDValues_;\n  char*   propTypes_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiIOTiming.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiIOTiming_h\n#define defiIOTiming_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiIOTiming {\npublic:\n  defiIOTiming(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiIOTiming();\n\n  void clear();\n\n  void setName(const char* inst, const char* pin);\n  void setVariable(const char* riseFall, double min, double max);\n  void setSlewRate(const char* riseFall, double min, double max);\n  void setCapacitance(double num);\n  void setDriveCell(const char* name);\n  void setFrom(const char* name);\n  void setTo(const char* name);\n  void setParallel(double num);\n\n\n  int hasVariableRise() const;\n  int hasVariableFall() const;\n  int hasSlewRise() const;\n  int hasSlewFall() const;\n  int hasCapacitance() const;\n  int hasDriveCell() const;\n  int hasFrom() const;\n  int hasTo() const;\n  int hasParallel() const;\n\n  const char* inst() const;\n  const char* pin() const;\n  double variableFallMin() const;\n  double variableRiseMin() const;\n  double variableFallMax() const;\n  double variableRiseMax() const;\n  double slewFallMin() const;\n  double slewRiseMin() const;\n  double slewFallMax() const;\n  double slewRiseMax() const;\n  double capacitance() const;\n  const char* driveCell() const;\n  const char* from() const;\n  const char* to() const;\n  double parallel() const;\n\n  // debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* inst_;\n  int instLength_;\n  char* pin_;\n  int pinLength_;\n  char* from_;\n  int fromLength_;\n  char* to_;\n  int toLength_;\n  char* driveCell_;\n  char driveCellLength_;\n  char hasVariableRise_;\n  char hasVariableFall_;\n  char hasSlewRise_;\n  char hasSlewFall_;\n  char hasCapacitance_;\n  char hasDriveCell_;\n  char hasFrom_;\n  char hasTo_;\n  char hasParallel_;\n  double variableFallMin_;\n  double variableRiseMin_;\n  double variableFallMax_;\n  double variableRiseMax_;\n  double slewFallMin_;\n  double slewRiseMin_;\n  double slewFallMax_;\n  double slewRiseMax_;\n  double capacitance_;\n  double parallel_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiKRDefs.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiKRDEFS_h\n#define defiKRDEFS_h\n\n#define BEGIN_LEFDEF_PARSER_NAMESPACE namespace LefDefParser {\n#define END_LEFDEF_PARSER_NAMESPACE }\n#define USE_LEFDEF_PARSER_NAMESPACE using namespace LefDefParser;\n\n#endif /* defiKRDEFS_h */\n"
  },
  {
    "path": "rsyn/include/def5.8/defiMisc.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiMisc_h\n#define defiMisc_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nstruct defiPoints {\n  int numPoints;\n  int* x;\n  int* y;\n};\n\nclass defiGeometries {\npublic:\n  defiGeometries(defrData *data);\n  void Init();\n  void Reset();\n\n  void Destroy();\n  ~defiGeometries();\n\n  void startList(int x, int y);\n  void addToList(int x, int y);\n\n  int  numPoints() const;\n  void points(int index, int* x, int* y) const;\n\nprotected:\n  int numPoints_;\n  int pointsAllocated_;\n  int* x_;\n  int* y_;\n\n  defrData *defData;\n};\n\nclass defiStyles {\npublic:\n  defiStyles();\n  void Init();\n\n  void Destroy();\n  ~defiStyles();\n\n  void clear();\n\n  void setStyle(int styleNum);\n  void setPolygon(defiGeometries* geom);\n\n  int style() const;\n  struct defiPoints getPolygon() const;\n\n  protected:\n    int    styleNum_;\n    struct defiPoints* polygon_;\n    int    numPointAlloc_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiNet.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013 - 2017, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: icftcm $\n//  $Revision: #2 $\n//  $Date: 2017/06/19 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiNet_h\n#define defiNet_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n#include \"defiPath.hpp\"\n#include \"defiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n/* Return codes for defiNet::viaOrient \n    DEF_ORIENT_N  0\n    DEF_ORIENT_W  1\n    DEF_ORIENT_S  2\n    DEF_ORIENT_E  3\n    DEF_ORIENT_FN 4\n    DEF_ORIENT_FW 5\n    DEF_ORIENT_FS 6\n    DEF_ORIENT_FE 7\n*/\n\nclass defiWire {\npublic:\n  defiWire(defrData *data);\n  ~defiWire();\n\n  void Init(const char* type, const char* wireShieldName);\n  void Destroy();\n  void clear();\n  void addPath(defiPath *p, int reset, int netOsnet, int *needCbk);\n\n  const char* wireType() const;\n  const char* wireShieldNetName() const;\n  int         numPaths() const;\n\n  defiPath*   path(int index);\n  const defiPath*   path(int index) const;\n\n  void bumpPaths(long long size);\n\nprotected:\n  char*      type_;\n  char*      wireShieldName_;    // It only set from specialnet SHIELD, 5.4\n  int        numPaths_;\n  long long  pathsAllocated_;\n  defiPath** paths_;\n\n  defrData  *defData;\n};\n\n\n\nclass defiSubnet {\npublic:\n  defiSubnet(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiSubnet();\n\n  void setName(const char* name);\n  void setNonDefault(const char* name);\n  void addPin(const char* instance, const char* pin, int syn);\n  void addMustPin(const char* instance, const char* pin, int syn);\n\n  // WMD -- the following will be removed by the next release\n  void setType(const char* typ);  // Either FIXED COVER ROUTED\n  void addPath(defiPath* p, int reset, int netOsnet, int *needCbk);\n\n  // NEW: a net can have more than 1 wire\n  void addWire(const char *typ); \n  void addWirePath(defiPath *p, int reset, int netOsnet, int *needCbk);\n\n  // Debug printing\n  void print(FILE* f) const;\n\n  const char* name() const;\n  int numConnections() const;\n  const char* instance(int index) const;\n  const char* pin(int index) const;\n  int pinIsSynthesized(int index) const;\n  int pinIsMustJoin(int index) const;\n\n  // WMD -- the following will be removed by the next release\n  int isFixed() const;\n  int isRouted() const;\n  int isCover() const;\n\n  int hasNonDefaultRule() const;\n\n  // WMD -- the following will be removed by the next release\n  int numPaths() const;\n  defiPath* path(int index);\n  const defiPath* path(int index) const;\n\n  const char* nonDefaultRule() const;\n\n  int         numWires() const;\n  defiWire*   wire(int index);\n  const defiWire*   wire(int index) const;\n\n  void bumpName(long long size);\n  void bumpPins(long long  size);\n  void bumpPaths(long long  size);\n  void clear();\n\nprotected:\n  char*         name_;            // name.\n  int           nameSize_;          // allocated size of name.\n  int           numPins_;           // number of pins used in array.\n  long long     pinsAllocated_;     // number of pins allocated in array.\n  char**        instances_;      // instance names for connections\n  char**        pins_;           // pin names for connections\n  char*         synthesized_;     // synthesized flags for pins\n  char*         musts_;           // must-join flags\n\n  // WMD -- the following will be removed by the next release\n  char       isFixed_;        // net type\n  char       isRouted_;\n  char       isCover_;\n  defiPath** paths_;          // paths for this subnet\n  int        numPaths_;       // number of paths used\n  long long  pathsAllocated_; // allocated size of paths array\n\n  int        numWires_;          // number of wires defined in the subnet\n  long long  wiresAllocated_;    // number of wires allocated in the subnet\n  defiWire** wires_;             // this replace the paths\n  char*      nonDefaultRule_;\n\n  defrData *defData;\n};\n\n\n\nclass defiVpin {\npublic:\n  defiVpin(defrData *data);\n  ~defiVpin();\n\n  void Init(const char* name);\n  void Destroy();\n  void setLayer(const char* name);\n  void setBounds(int xl, int yl, int xh, int yh);\n  void setOrient(int orient);\n  void setLoc(int x, int y);\n  void setStatus(char st);\n\n  int xl() const ;\n  int yl() const ;\n  int xh() const ;\n  int yh() const ;\n  char status() const;      /* P-placed, F-fixed, C-cover, ' ' - not set */\n  int orient() const ;\n  const char* orientStr() const ;\n  int xLoc() const;\n  int yLoc() const;\n  const char* name() const;\n  const char* layer() const;\n\nprotected:\n  int xl_;\n  int yl_;\n  int xh_;\n  int yh_;\n  int orient_;  /* 0-7  -1 is no orient */\n  char status_; /* P-placed  F-fixed  C-cover  ' '- none */\n  int xLoc_;\n  int yLoc_;\n  char* name_;\n  char* layer_;\n\n  defrData *defData;\n};\n\n\n\n// Pre 5.4\nclass defiShield {\npublic:\n  defiShield(defrData *data);\n  ~defiShield();\n\n  void Init(const char* name);\n  void Destroy();\n  void clear();\n  void addPath(defiPath *p, int reset, int netOsnet, int *needCbk);\n\n  const char* shieldName() const;\n  int         numPaths() const;\n\n  defiPath*         path(int index);\n  const defiPath*   path(int index) const;\n\n  void bumpPaths(long long size);\n\nprotected:\n  char*      name_;\n  int        numPaths_;\n  long long  pathsAllocated_;\n  defiPath** paths_;\n\n  defrData *defData;\n};\n\n\n\n\n// Struct holds the data for one component.\nclass defiNet {\npublic:\n  defiNet(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiNet();\n\n  // Routines used by YACC to set the fields in the net.\n  void setName(const char* name);\n  void addPin(const char* instance, const char* pin, int syn);\n  void addMustPin(const char* instance, const char* pin, int syn);\n  void setWeight(int w);\n\n  // WMD -- the following will be removed by the next release\n  void setType(const char* typ);  // Either FIXED COVER ROUTED\n\n  void addProp(const char* name, const char* value, const char type);\n  void addNumProp(const char* name, const double d,\n                  const char* value, const char type);\n  void addSubnet(defiSubnet* subnet);\n  // NEW: a net can have more than 1 wire\n  void addWire(const char *typ, const char* wireShieldName);\n  void addWirePath(defiPath* p, int reset, int netOsnet, int *needCbk);\n  void addShape(const char *shapeType);         // 5.8\n  void setSource(const char* typ);\n  void setFixedbump();                          // 5.4.1\n  void setFrequency(double frequency);          // 5.4.1\n  void setOriginal(const char* typ);\n  void setPattern(const char* typ);\n  void setCap(double w);\n  void setUse(const char* typ);\n  void setNonDefaultRule(const char* typ);\n  void setStyle(int style);\n  void addShield(const char* shieldNetName);    // pre 5.4\n  void addNoShield(const char* shieldNetName);  // pre 5.4\n  void addShieldNet(const char* shieldNetName);\n\n  void addShieldPath(defiPath* p, int reset, int netOsnet, int *needCbk);\n  void clear();\n  void setWidth(const char* layer, double dist);\n  void setSpacing(const char* layer, double dist);\n  void setVoltage(double num);\n  void setRange(double left, double right);\n  void setXTalk(int num);\n  void addVpin(const char* name);\n  void addVpinLayer(const char* name);\n  void addVpinLoc(const char* status, int x, int y, int orient);\n  void addVpinBounds(int xl, int yl, int xh, int yh);\n  // 5.6\n  void addPolygon(const char* layerName, defiGeometries* geom, int *needCbk,\n\t          int mask, const char* routeStatus,\n\t\t  const char* shapeType,\n                  const char* shieldNetName);\n  void addRect(const char* layerName, int xl, int yl, int xh, int yh,\n               int *needCbk, int mask, const char* routeStatus,\n\t       const char* shapeType,\n               const char* shieldNetName); // 5.6\n  void addPts(const char* viaName, int o, defiGeometries* geom,\n\t      int *needCbk, int mask, const char* routeStatus,\n\t      const char* shapeType,\n              const char* shieldNetName);  //VIA 5.8\n\n  // For OA to modify the netName, id & pinName\n  void changeNetName(const char* name);\n  void changeInstance(const char* name, int index);\n  void changePin(const char* name, int index);\n\n  // Routines to return the value of net data.\n  const char*  name() const;\n  int          weight() const;\n  int          numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n  int          numConnections() const;\n  const char*  instance(int index) const;\n  const char*  pin(int index) const;\n  int          pinIsMustJoin(int index) const;\n  int          pinIsSynthesized(int index) const;\n  int          numSubnets() const;\n\n  defiSubnet*  subnet(int index);\n  const defiSubnet*  subnet(int index) const;\n\n  // WMD -- the following will be removed by the next release\n  int         isFixed() const;\n  int         isRouted() const;\n  int         isCover() const;\n\n  /* The following routines are for wiring */\n  int         numWires() const;\n\n  defiWire*   wire(int index);\n  const defiWire*   wire(int index) const;\n\n  /* Routines to get the information about Virtual Pins. */\n  int       numVpins() const;\n  \n  defiVpin* vpin(int index);\n  const defiVpin* vpin(int index) const;\n\n  int hasProps() const;\n  int hasWeight() const;\n  int hasSubnets() const;\n  int hasSource() const;\n  int hasFixedbump() const;                          // 5.4.1\n  int hasFrequency() const;                          // 5.4.1\n  int hasPattern() const;\n  int hasOriginal() const;\n  int hasCap() const;\n  int hasUse() const;\n  int hasStyle() const;\n  int hasNonDefaultRule() const;\n  int hasVoltage() const;\n  int hasSpacingRules() const;\n  int hasWidthRules() const;\n  int hasXTalk() const;\n\n  int numSpacingRules() const;\n  void spacingRule(int index, char** layer, double* dist, double* left,\n                   double* right) const;\n  int numWidthRules() const;\n  void widthRule(int index, char** layer, double* dist) const;\n  double voltage() const;\n\n  int            XTalk() const;\n  const char*    source() const;\n  double         frequency() const;\n  const char*    original() const;\n  const char*    pattern() const;\n  double         cap() const;\n  const char*    use() const;\n  int            style() const;\n  const char*    nonDefaultRule() const;\n\n  // WMD -- the following will be removed by the next release\n  int            numPaths() const;\n  \n  defiPath*            path(int index);\n  const defiPath*      path(int index) const;\n\n  int            numShields() const;          // pre 5.4\n\n  defiShield*    shield(int index);           // pre 5.4\n  const defiShield*    shield(int index) const ;           // pre 5.4\n\n  int            numShieldNets() const;\n  const char*    shieldNet(int index) const;\n  int            numNoShields() const;        // pre 5.4\n\n  defiShield*    noShield(int index);         // pre 5.4\n  const defiShield*    noShield(int index) const;         // pre 5.4\n\n  // 5.6\n  int            numPolygons() const;                 // 5.6\n  const  char*   polygonName(int index) const;        // 5.6\n  struct defiPoints getPolygon(int index) const;      // 5.6\n  int            polyMask(int index) const;\n  const char*    polyRouteStatus(int index) const;\n  const char*    polyRouteStatusShieldName(int index) const;\n  const char*    polyShapeType(int index) const;\n\n\n  int  numRectangles() const;                         // 5.6\n  const  char* rectName(int index) const;             // 5.6\n  int  xl(int index)const;                            // 5.6\n  int  yl(int index)const;                            // 5.6\n  int  xh(int index)const;                            // 5.6\n  int  yh(int index)const;                            // 5.6\n  int  rectMask(int index)const;\n  const char* rectRouteStatus(int index) const;\n  const char* rectRouteStatusShieldName(int index) const;\n  const char* rectShapeType(int index) const;\n  \n\n  // 5.8\n  int  numViaSpecs() const;\n  struct defiPoints getViaPts(int index) const;                       \n  const char* viaName(int index) const;\n  const int viaOrient(int index) const;\n  const char* viaOrientStr(int index) const;\n  const int topMaskNum(int index) const;\n  const int cutMaskNum(int index) const;\n  const int bottomMaskNum(int index) const;\n  const char* viaRouteStatus(int index) const;\n  const char* viaRouteStatusShieldName(int index) const;\n  const char* viaShapeType(int index) const;\n\n  // Debug printing\n  void print(FILE* f) const;\n\n\n  void bumpName(long long size);\n  void bumpPins(long long size);\n  void bumpProps(long long size);\n  void bumpSubnets(long long size);\n  void bumpPaths(long long  size);\n  void bumpShieldNets(long long size);\n\n  // The method freeWire() is added is user select to have a callback\n  // per wire within a net This is an internal method and is not public\n  void freeWire();\n  void freeShield();\n\n  // Clear the rectangles & polygons data if partial path callback is set\n  void clearRectPolyNPath();\n  void clearRectPoly();\n  void clearVia();\n\nprotected:\n  char*     name_;          // name.\n  int       nameSize_;      // allocated size of name.\n  int       numPins_;       // number of pins used in array.\n  long long pinsAllocated_; // number of pins allocated in array.\n  char**    instances_;     // instance names for connections\n  char**    pins_;          // pin names for connections\n  char*     musts_;         // must-join flags for pins\n  char*     synthesized_;   // synthesized flags for pins\n  int       weight_;        // net weight\n  char      hasWeight_;     // flag for optional weight\n\n  // WMD -- the following will be removed by the nex release\n  char isFixed_;        // net type\n  char isRouted_;\n  char isCover_;\n\n  char hasCap_;         // file supplied a capacitance value\n  char hasFrequency_;   // file supplied a frequency value\n  char hasVoltage_;\n  int numProps_;        // num of props in array\n  char**  propNames_;   // Prop names\n  char**  propValues_;  // Prop values All in strings!\n  double* propDValues_; // Prop values in numbers!\n  char*   propTypes_;   // Prop types, 'I' - Integer, 'R' - Real, 'S' - String\n\n  long long    propsAllocated_;   // allocated size of props array\n  int          numSubnets_;       // num of subnets in array\n  defiSubnet** subnets_;          // Prop names\n  long long    subnetsAllocated_; // allocated size of props array\n  double       cap_;              // cap value\n  char*        source_;\n  int          fixedbump_;     // 5.4.1\n  double       frequency_;     // 5.4.1\n  char* pattern_;\n  char* original_;\n  char* use_;\n  char* nonDefaultRule_;\n  int   style_;\n\n  // WMD -- the following will be removed by the nex release\n  defiPath** paths_;          // paths for this subnet\n  int        numPaths_;       // number of paths used\n  long long  pathsAllocated_; // allocated size of paths array\n\n  double voltage_;\n\n  int         numWires_;         // number of wires defined in the net\n  long long   wiresAllocated_;   // allocated size of wire paths array\n  defiWire**  wires_;            // this replace the paths\n\n  long long   widthsAllocated_;\n  int         numWidths_;\n  char**      wlayers_;\n  double*     wdist_;\n\n  long long   spacingAllocated_;\n  int         numSpacing_;\n  char**      slayers_;\n  double*     sdist_;\n  double*     sleft_;\n  double*     sright_;\n  int         xTalk_;\n\n  int         numVpins_;\n  long long   vpinsAllocated_;\n  defiVpin**  vpins_;\n\n  int          numShields_;            // number of SHIELD paths used\n  long long    shieldsAllocated_;      // allocated size of SHIELD paths array\n  defiShield** shields_;               // SHIELD data \n  int          numNoShields_;          // number of NOSHIELD paths used\n\n  int          numShieldNet_;          // number of SHIELDNETS used in array.\n  long long    shieldNetsAllocated_;   // number of SHIELDNETS allocated in array.\n  char**       shieldNet_;             // name of the SHIELDNET\n\n  int          numPolys_;              // 5.6\n  char**       polygonNames_;          // 5.6 layerName for POLYGON\n  long long    polysAllocated_;        // 5.6\n  struct defiPoints** polygons_;       // 5.6\n  int*         polyMasks_;\n  char** polyRouteStatus_;\n  char** polyShapeTypes_;\n  char** polyRouteStatusShieldNames_;\n\n  int        numRects_;                    // 5.6\n  long long  rectsAllocated_;              // 5.6\n  char**     rectNames_;                   // 5.6\n  int* xl_;\n  int* yl_;\n  int* xh_;\n  int* yh_;\n  int* rectMasks_;\n  char** rectRouteStatus_;\n  char** rectRouteStatusShieldNames_;\n  char** rectShapeTypes_;\n  \n\n  struct defiPoints** viaPts_;      // 5.8                  \n  char**              viaNames_;                   \n  int                 numPts_;                    \n  long long           ptsAllocated_;\n  int*                viaOrients_;\n  int*                viaMasks_;\n  char**              viaRouteStatus_;\n  char**              viaRouteStatusShieldNames_;\n  char**              viaShapeTypes_;\n\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiNonDefault.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiNonDefault_h\n#define defiNonDefault_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n#include \"defiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defiNonDefault {\npublic:\n  defiNonDefault(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiNonDefault();\n\n  void clear();\n  void setName(const char* name);\n  void setHardspacing();\n  void addLayer(const char* name);\n  void addWidth(double num);\n  void addDiagWidth(double num);\n  void addSpacing(double num);\n  void addWireExt(double num);\n  void addVia(const char* name);\n  void addViaRule(const char* name);\n  void addMinCuts(const char* name, int numCuts);\n  void addProperty(const char* name, const char* value, const char type);\n  void addNumProperty(const char* name, const double d,\n                      const char* value, const char type);\n  void end();\n\n  const char* name() const;\n  int   hasHardspacing() const;\n\n  int         numProps() const;\n  const char* propName(int index) const;\n  const char* propValue(int index) const;\n  double      propNumber(int index) const;\n  const char  propType(int index) const;\n  int         propIsNumber(int index) const;\n  int         propIsString(int index) const;\n  \n  // A non default rule can have one or more layers.\n  // The layer information is kept in an array.\n  int         numLayers() const ;\n  const char* layerName(int index) const ;\n  double      layerWidth(int index) const ;       // Will be obsoleted in 5.7\n  int         layerWidthVal(int index) const ;\n  int         hasLayerDiagWidth(int index) const;\n  double      layerDiagWidth(int index) const;    // Will be obsoleted in 5.7\n  int         layerDiagWidthVal(int index) const;\n  int         hasLayerSpacing(int index) const ;\n  double      layerSpacing(int index) const ;     // Will be obsoleted in 5.7\n  int         layerSpacingVal(int index) const ;\n  int         hasLayerWireExt(int index) const ;\n  double      layerWireExt(int index) const ;     // Will be obsoleted in 5.7\n  int         layerWireExtVal(int index) const ;\n  int         numVias() const ;\n  const char* viaName(int index) const ;\n  int         numViaRules() const ;\n  const char* viaRuleName(int index) const ;\n  int         numMinCuts() const;\n  const char* cutLayerName(int index) const;\n  int         numCuts(int index) const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  char*   name_;\n  char    hardSpacing_;\n\n  // Layer information\n  int     numLayers_;\n  int     layersAllocated_;\n  char**  layerName_;\n  double* width_;\n  char*   hasDiagWidth_;\n  double* diagWidth_;\n  char*   hasSpacing_;\n  double* spacing_;\n  char*   hasWireExt_;\n  double* wireExt_;\n\n  int     numVias_;\n  int     viasAllocated_;\n  char**  viaNames_;\n  int     numViaRules_;\n  int     viaRulesAllocated_;\n  char**  viaRuleNames_;\n  int     numMinCuts_;\n  int     minCutsAllocated_;\n  char**  cutLayerName_;\n  int*    numCuts_;\n\n  int     numProps_;\n  int     propsAllocated_;\n  char**  names_;\n  char**  values_;\n  double* dvalues_;\n  char*   types_;\n\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiPartition.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiPartition_h\n#define defiPartition_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiPartition {\npublic:\n  defiPartition(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiPartition();\n\n  void clear();\n\n  void setName(const char* name);\n  void addTurnOff(const char* setup, const char* hold);\n  void setFromClockPin(const char* inst, const char* pin);\n  void setFromCompPin(const char* inst, const char* pin);\n  void setFromIOPin(const char* inst);\n  void setToClockPin(const char* inst, const char* pin);\n  void setToCompPin(const char* inst, const char* pin);\n  void set(char dir, char typ, const char* inst, const char* pin);\n  void setToIOPin(const char* inst);\n  void setMin(double min, double max);\n  void setMax(double min, double max);\n  void addPin(const char* name);\n  void addRiseMin(double d);\n  void addRiseMax(double d);\n  void addFallMin(double d);\n  void addFallMax(double d);\n  void addRiseMinRange(double l, double h);\n  void addRiseMaxRange(double l, double h);\n  void addFallMinRange(double l, double h);\n  void addFallMaxRange(double l, double h);\n\n  const char* name() const;\n  char direction() const;\n  const char* itemType() const;  // \"CLOCK\" or \"IO\" or \"COMP\"\n  const char* pinName() const;\n  const char* instName() const;\n\n  int numPins() const;\n  const char* pin(int index) const;\n\n  int isSetupRise() const;\n  int isSetupFall() const;\n  int isHoldRise() const;\n  int isHoldFall() const;\n  int hasMin() const;\n  int hasMax() const;\n  int hasRiseMin() const;\n  int hasFallMin() const;\n  int hasRiseMax() const;\n  int hasFallMax() const;\n  int hasRiseMinRange() const;\n  int hasFallMinRange() const;\n  int hasRiseMaxRange() const;\n  int hasFallMaxRange() const;\n\n  double partitionMin() const;\n  double partitionMax() const;\n\n  double riseMin() const;\n  double fallMin() const;\n  double riseMax() const;\n  double fallMax() const;\n\n  double riseMinLeft() const;\n  double fallMinLeft() const;\n  double riseMaxLeft() const;\n  double fallMaxLeft() const;\n  double riseMinRight() const;\n  double fallMinRight() const;\n  double riseMaxRight() const;\n  double fallMaxRight() const;\n\n  // debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameLength_;\n  char setup_;\n  char hold_;\n  char hasMin_;\n  char hasMax_;\n  char direction_;   // 'F' or 'T'\n  char type_;        // 'L'-clock   'I'-IO  'C'-comp\n  char* inst_;\n  int instLength_;\n  char* pin_;\n  int pinLength_;\n  double min_, max_;\n\n  int numPins_;\n  int pinsAllocated_;\n  char** pins_;\n\n  char hasRiseMin_;\n  char hasFallMin_;\n  char hasRiseMax_;\n  char hasFallMax_;\n  char hasRiseMinRange_;\n  char hasFallMinRange_;\n  char hasRiseMaxRange_;\n  char hasFallMaxRange_;\n  double riseMin_;\n  double fallMin_;\n  double riseMax_;\n  double fallMax_;\n  double riseMinLeft_;\n  double fallMinLeft_;\n  double riseMaxLeft_;\n  double fallMaxLeft_;\n  double riseMinRight_;\n  double fallMinRight_;\n  double riseMaxRight_;\n  double fallMaxRight_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiPath.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013-2014, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiPath_h\n#define defiPath_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// TX_DIR:TRANSLATION ON\n\nclass defrData;\n\nstruct defiPnt {\n  int x;\n  int y;\n  int ext;\n};\n\n// 5.4.1 1-D & 2-D Arrays of Vias in SPECIALNET Section\nstruct defiViaData {\n  int numX;\n  int numY;\n  int stepX;\n  int stepY;\n};\n\nstruct defiViaRect {\n  int deltaX1;\n  int deltaY1;\n  int deltaX2;\n  int deltaY2;\n};\n\n// value returned by the next() routine.\nenum defiPath_e {\n  DEFIPATH_DONE = 0,\n  DEFIPATH_LAYER,\n  DEFIPATH_VIA,\n  DEFIPATH_VIAROTATION,\n  DEFIPATH_WIDTH,\n  DEFIPATH_POINT,\n  DEFIPATH_FLUSHPOINT,\n  DEFIPATH_TAPER,\n  DEFIPATH_SHAPE,\n  DEFIPATH_STYLE,\n  DEFIPATH_TAPERRULE,\n  DEFIPATH_VIADATA,\n  DEFIPATH_RECT,\n  DEFIPATH_VIRTUALPOINT,\n  DEFIPATH_MASK,\n  DEFIPATH_VIAMASK\n  } ;\n\n\nclass defiPath {\npublic:\n  defiPath(defrData *data);\n  // This is 'data ownership transfer' constructor.\n  defiPath(defiPath *defiPathRef);\n\n  void Init();\n\n  void Destroy();\n  ~defiPath();\n\n  void clear();\n  void reverseOrder();\n\n  // To traverse the path and get the parts.\n  void initTraverse() const;   // Initialize the traverse.\n  void initTraverseBackwards() const;   // Initialize the traverse in reverse.\n  int next() const;            // Get the next element.\n  int prev() const;            // Get the next element in reverse.\n  const char* getLayer() const;// Get the layer.\n  const char* getTaperRule() const;// Get the rule.\n  const char* getVia() const;  // Get the via.\n  const char* getShape() const;// Get the shape.\n  int  getTaper() const;// Get the taper.\n  int  getStyle() const;// Get the style.\n  int  getViaRotation() const;  // Get the via rotation.\n  void getViaRect(int* deltaX1, int* deltaY1, int* deltaX2, int* deltaY2) const;\n  const char* getViaRotationStr() const;   // Return via rotation in string format\n  void getViaData(int* numX, int* numY, int* stepX, int* stepY) const;  // 5.4.1\n  int  getWidth() const;        // Get the width.\n  void getPoint(int* x, int* y) const;// Get the point.\n  void getFlushPoint(int* x, int* y, int* ext) const;// Get the point.\n  void getVirtualPoint(int* x, int* y) const;\n  int  getMask() const;\n  int  getViaTopMask() const;\n  int  getViaCutMask() const;\n  int  getViaBottomMask() const;\n  int  getRectMask() const;\n\n\n  // These routines are called by the parser to fill the path.\n  void addWidth(int w);\n  void addPoint(int x, int y);\n  void addFlushPoint(int x, int y, int ext);\n  void addVirtualPoint(int x, int y);\n  void addLayer(const char* layer);\n  void addVia(const char* name);\n  void addViaRotation(int orient);\n  void addViaRect(int deltaX1, int deltaY1, int deltaX2, int deltaY2);\n  void addMask(int colorMask);\n  void addViaMask(int colorMask);\n  void addViaData(int numX, int numY, int stepX, int stepY);   // 5.4.1\n  void setTaper();\n  void addTaperRule(const char* rule);\n  void addShape(const char* shape);\n  void addStyle(int style);\n\n  // debug printing\n  void print(FILE* fout) const;\n\n  void bumpSize(int size);\n\nprotected:\n  int currentType() const;\n\n  int* keys_;           // type of item in path\n  void** data_;         // extra data\n  int numUsed_;         // number of items used in array\n  int numAllocated_;    // allocated size of keys and data\n  int* pointer_;        // traversal pointer, allocated because used\n                        // as iterator in const traversal functions.\n  int numX_;      \n  int numY_;\n  int stepX_;\n  int stepY_;\n  int deltaX_;\n  int deltaY_;\n  int mask_;\n\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiPinCap.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiPinCap_h\n#define defiPinCap_h\n\n\n#include \"defiKRDefs.hpp\"\n#include \"defiMisc.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiPinCap {\npublic:\n\n  void setPin(int p);\n  void setCap(double d);\n\n  int pin() const;\n  double cap() const;\n\n  void print(FILE* f) const;\n\nprotected:\n  int pin_;        // pin num\n  double cap_;     // capacitance\n};\n\n\n// 5.5\nclass defiPinAntennaModel {\npublic:\n  defiPinAntennaModel(defrData *data);\n  void Init();\n\n  ~defiPinAntennaModel();\n  void clear();\n  void Destroy();\n\n  void setAntennaModel(int oxide);\n  void addAPinGateArea(int value, const char* layer);\n  void addAPinMaxAreaCar(int value, const char* layer);\n  void addAPinMaxSideAreaCar(int value, const char* layer);\n  void addAPinMaxCutCar(int value, const char* layer);\n\n  char* antennaOxide() const;\n\n  int hasAPinGateArea() const;               // ANTENNAPINGATEAREA\n  int numAPinGateArea() const;\n  int APinGateArea(int index) const;\n  int hasAPinGateAreaLayer(int index) const;\n  const char* APinGateAreaLayer(int index) const;\n\n  int hasAPinMaxAreaCar() const;             // ANTENNAPINMAXAREACAR\n  int numAPinMaxAreaCar() const;\n  int APinMaxAreaCar(int index) const;\n  int hasAPinMaxAreaCarLayer(int index) const;\n  const char* APinMaxAreaCarLayer(int index) const;\n\n  int hasAPinMaxSideAreaCar() const;         // ANTENNAPINMAXSIDEAREACAR\n  int numAPinMaxSideAreaCar() const;\n  int APinMaxSideAreaCar(int index) const;\n  int hasAPinMaxSideAreaCarLayer(int index) const;\n  const char* APinMaxSideAreaCarLayer(int index) const;\n\n  int hasAPinMaxCutCar() const;              // ANTENNAPINMAXCUTCAR\n  int numAPinMaxCutCar() const;\n  int APinMaxCutCar(int index) const;\n  int hasAPinMaxCutCarLayer(int index) const;\n  const char* APinMaxCutCarLayer(int index) const;\n\nprotected:\n  char* oxide_;\n\n  int numAPinGateArea_;                  // 5.4\n  int APinGateAreaAllocated_;\n  int* APinGateArea_;                    // 5.4 AntennaPinGateArea\n  char** APinGateAreaLayer_;             // 5.4 Layer\n\n  int numAPinMaxAreaCar_;                // 5.4\n  int APinMaxAreaCarAllocated_;\n  int* APinMaxAreaCar_;                  // 5.4 AntennaPinMaxAreaCar\n  char** APinMaxAreaCarLayer_;           // 5.4 Layer\n\n  int numAPinMaxSideAreaCar_;            // 5.4\n  int APinMaxSideAreaCarAllocated_;\n  int* APinMaxSideAreaCar_;              // 5.4 AntennaPinMaxSideAreaCar\n  char** APinMaxSideAreaCarLayer_;       // 5.4 Layer\n\n  int numAPinMaxCutCar_;                 // 5.4\n  int APinMaxCutCarAllocated_;\n  int* APinMaxCutCar_;                   // 5.4 AntennaPinMaxCutCar\n  char** APinMaxCutCarLayer_;            // 5.4 Layer\n\n  defrData *defData;\n};\n\nclass defiPinPort {                      // 5.7\npublic:\n  defiPinPort(defrData *data);\n  void Init();\n\n  ~defiPinPort();\n\n  void clear();\n\n  void addLayer(const char* layer);\n  void addLayerSpacing(int minSpacing);\n  void addLayerMask(int mask);\n  void addLayerDesignRuleWidth(int effectiveWidth);\n  void addLayerPts(int xl, int yl, int xh, int yh);\n  void addPolygon(const char* layerName);\n  void addPolySpacing(int minSpacing);\n  void addPolyMask(int mask);\n  void addPolyDesignRuleWidth(int effectiveWidth);\n  void addPolygonPts(defiGeometries* geom);\n  void addVia(const char* via, int viaX, int viaY, int color = 0);\n  void setPlacement(int typ, int x, int y, int orient);\n\n  int   numLayer() const;\n  const char* layer(int index) const;\n  void  bounds(int index, int* xl, int* yl, int* xh, int* yh) const;\n  int   hasLayerSpacing(int index) const;\n  int   hasLayerDesignRuleWidth(int index) const;\n  int   layerSpacing(int index) const;\n  int   layerMask(int index) const;\n  int   layerDesignRuleWidth(int index) const;\n  int   numPolygons() const;\n  const char* polygonName(int index) const;\n  defiPoints getPolygon(int index) const;\n  int   hasPolygonSpacing(int index) const;\n  int   hasPolygonDesignRuleWidth(int index) const;\n  int   polygonSpacing(int index) const;\n  int   polygonDesignRuleWidth(int index) const;\n  int   polygonMask(int index) const;\n  int   numVias() const;\n  const char* viaName(int index) const;\n  int   viaPtX (int index) const;\n  int   viaPtY (int index) const;\n  int   viaTopMask (int index) const;\n  int   viaCutMask (int index) const;\n  int   viaBottomMask (int index) const;\n  int   hasPlacement() const;\n  int   isPlaced() const;\n  int   isCover() const;\n  int   isFixed() const;\n  int   placementX() const;\n  int   placementY() const;\n  int   orient() const;\n  const char* orientStr() const;\n\nprotected:\n  int    layersAllocated_;\n  int    numLayers_;\n  char** layers_;\n  int    *layerMinSpacing_;\n  int    *layerEffectiveWidth_;\n  int    *xl_, *yl_, *xh_, *yh_;\n  int    *layerMask_;\n  int    polysAllocated_;\n  int    numPolys_;\n  char** polygonNames_;\n  int    *polyMinSpacing_;\n  int    *polyMask_;\n  int    *polyEffectiveWidth_;\n  defiPoints** polygons_;\n  int    viasAllocated_;\n  int    numVias_;\n  char** viaNames_;\n  int    *viaX_;\n  int    *viaY_;\n  int    *viaMask_;\n  char   placeType_;\n  int    x_, y_;\n  char   orient_;\n\n  defrData *defData;\n};\n\nclass defiPin {\npublic:\n  defiPin(defrData *data);\n  void Init();\n\n  ~defiPin();\n  void Destroy();\n\n  void Setup(const char* pinName, const char* netName);\n  void setDirection(const char* dir);\n  void setUse(const char* use);\n  // 5.6 setLayer is changed to addLayer due to multiple LAYER are allowed\n  // in 5.6\n  void addLayer(const char* layer);\n  void addLayerMask(int mask);                                    // 5.8\n  void addLayerSpacing(int minSpacing);                           // 5.6\n  void addLayerDesignRuleWidth(int effectiveWidth);               // 5.6\n  void addLayerPts(int xl, int yl, int xh, int yh);\n  void addPolygon(const char* layerName);                         // 5.6\n  void addPolyMask(int mask);                                     // 5.8\n  void addPolySpacing(int minSpacing);                            // 5.6\n  void addPolyDesignRuleWidth(int effectiveWidth);                // 5.6\n  void addPolygonPts(defiGeometries* geom);                       // 5.6\n  void setNetExpr(const char* netExpr);                           // 5.6\n  void setSupplySens(const char* pinName);                        // 5.6\n  void setGroundSens(const char* pinName);                        // 5.6\n  void setPlacement(int typ, int x, int y, int orient);\n  void setSpecial();\n  void addAntennaModel(int oxide);                                // 5.5\n  void addAPinPartialMetalArea(int value, const char* layer);\n  void addAPinPartialMetalSideArea(int value, const char* layer);\n  void addAPinGateArea(int value, const char* layer);\n  void addAPinDiffArea(int value, const char* layer);\n  void addAPinMaxAreaCar(int value, const char* layer);\n  void addAPinMaxSideAreaCar(int value, const char* layer);\n  void addAPinPartialCutArea(int value, const char* layer);\n  void addAPinMaxCutCar(int value, const char* layer);\n  void addVia(const char* via, int viaX, int viaY, int color = 0);               // 5.7\n  // 5.7 port statements, which may have LAYER, POLYGON, &| VIA\n  void addPort();                                                 // 5.7\n  void addPortLayer(const char* layer);                           // 5.7\n  void addPortLayerSpacing(int minSpacing);                       // 5.7\n  void addPortLayerDesignRuleWidth(int effectiveWidth);           // 5.7\n  void addPortLayerPts(int xl, int yl, int xh, int yh);           // 5.7\n  void addPortLayerMask(int color);                               // 5.8\n  void addPortPolygon(const char* layerName);                     // 5.7\n  void addPortPolySpacing(int minSpacing);                        // 5.7\n  void addPortPolyDesignRuleWidth(int effectiveWidth);            // 5.7\n  void addPortPolygonPts(defiGeometries* geom);                   // 5.7\n  void addPortPolyMask(int color);                                // 5.8\n  void addPortVia(const char* via, int viaX, int viaY, int color = 0);           // 5.7\n  void setPortPlacement(int typ, int x, int y, int orient);       // 5.7 - 5.8\n\n  void clear();\n\n  void changePinName(const char* pinName);       // For OA to modify the pinName\n\n  const char* pinName() const;\n  const char* netName() const;\n  // optional parts\n  int hasDirection() const;\n  int hasUse() const;\n  int hasLayer() const;\n  int hasPlacement() const;\n  int isUnplaced() const;\n  int isPlaced() const;\n  int isCover() const;\n  int isFixed() const;\n  int placementX() const;\n  int placementY() const;\n  const char* direction() const;\n  const char* use() const;\n  int numLayer() const;\n  const char* layer(int index) const;\n  void bounds(int index, int* xl, int* yl, int* xh, int* yh) const;\n  int layerMask(int index) const;                     // 5.8\n  int hasLayerSpacing(int index) const;               // 5.6\n  int hasLayerDesignRuleWidth(int index) const;       // 5.6\n  int layerSpacing(int index) const;                  // 5.6\n  int layerDesignRuleWidth(int index) const;          // 5.6\n  int  numPolygons() const;                           // 5.6\n  const  char* polygonName(int index) const;          // 5.6\n  defiPoints getPolygon(int index) const;      // 5.6\n  int polygonMask(int index) const;                      // 5.8\n  int hasPolygonSpacing(int index) const;             // 5.6\n  int hasPolygonDesignRuleWidth(int index) const;     // 5.6\n  int polygonSpacing(int index) const;                // 5.6\n  int polygonDesignRuleWidth(int index) const;        // 5.6\n  int  hasNetExpr() const;                            // 5.6\n  int  hasSupplySensitivity() const;                  // 5.6\n  int  hasGroundSensitivity() const;                  // 5.6\n  const char* netExpr() const;                        // 5.6\n  const char* supplySensitivity() const;              // 5.6\n  const char* groundSensitivity() const;              // 5.6\n  int orient() const;\n  const char* orientStr() const;\n  int hasSpecial() const;\n  int numVias() const;                                // 5.7\n  const char* viaName(int index) const;               // 5.7\n  int viaTopMask(int index) const;                    // 5.8\n  int viaCutMask(int index) const;                    // 5.8\n  int viaBottomMask(int index) const;                 // 5.8\n  int viaPtX (int index) const;                       // 5.7\n  int viaPtY (int index) const;                       // 5.7\n\n  // 5.4\n  int hasAPinPartialMetalArea() const;       // ANTENNAPINPARTIALMETALAREA\n  int numAPinPartialMetalArea() const;\n  int APinPartialMetalArea(int index) const;\n  int hasAPinPartialMetalAreaLayer(int index) const;\n  const char* APinPartialMetalAreaLayer(int index) const;\n\n  int hasAPinPartialMetalSideArea() const;   // ANTENNAPINPARTIALMETALSIDEAREA\n  int numAPinPartialMetalSideArea() const;\n  int APinPartialMetalSideArea(int index) const;\n  int hasAPinPartialMetalSideAreaLayer(int index) const;\n  const char* APinPartialMetalSideAreaLayer(int index) const;\n\n  int hasAPinDiffArea() const;               // ANTENNAPINDIFFAREA\n  int numAPinDiffArea() const;\n  int APinDiffArea(int index) const;\n  int hasAPinDiffAreaLayer(int index) const;\n  const char* APinDiffAreaLayer(int index) const;\n\n  int hasAPinPartialCutArea() const;         // ANTENNAPINPARTIALCUTAREA\n  int numAPinPartialCutArea() const;\n  int APinPartialCutArea(int index) const;\n  int hasAPinPartialCutAreaLayer(int index) const;\n  const char* APinPartialCutAreaLayer(int index) const;\n\n  // 5.5\n  int numAntennaModel() const;\n  defiPinAntennaModel* antennaModel(int index) const;\n\n  // 5.7\n  int  hasPort() const;\n  int  numPorts() const;\n  defiPinPort* pinPort(int index) const;\n  void print(FILE* f) const;\n\nprotected:\n  int pinNameLength_;    // allocated size of pin name\n  char* pinName_;\n  int netNameLength_;    // allocated size of net name\n  char* netName_;\n  char hasDirection_;\n  char hasUse_;\n  char placeType_;\n  char orient_;          // orient 0-7\n  int useLength_;        // allocated size of length\n  char* use_;\n  int directionLength_;  // allocated size of direction\n  char* direction_;\n  char** layers_;                   // 5.6, changed to array\n  int *xl_, *yl_, *xh_, *yh_;       // 5.6, changed to arrays\n  int *layerMinSpacing_;            // 5.6, SPACING in LAYER\n  int *layerEffectiveWidth_;        // 5.6, DESIGNRULEWIDTH in LAYER\n  int layersAllocated_;             // 5.6\n  int numLayers_;                   // 5.6\n  int *layerMask_;                  // 5.8\n  char** polygonNames_;             // 5.6 layerName for POLYGON\n  int *polyMinSpacing_;             // 5.6, SPACING in POLYGON\n  int *polyEffectiveWidth_;         // 5.6, DESIGNRULEWIDTH in POLYGON\n  int *polyMask_;                   // 5.8\n  int numPolys_;                    // 5.6\n  int polysAllocated_;              // 5.6\n  defiPoints** polygons_;    // 5.6 \n  int x_, y_;            // placement\n  int hasSpecial_;\n  int numVias_;                     // 5.7\n  int viasAllocated_;               // 5.7\n  char** viaNames_;                 // 5.7\n  int *viaX_;                       // 5.7\n  int *viaY_;                       // 5.7\n  int *viaMask_;                    // 5.8\n  int numPorts_;                    // 5.7\n  int portsAllocated_;              // 5.7\n  defiPinPort ** pinPort_;          // 5.7\n\n  // 5.5 AntennaModel\n  int numAntennaModel_;\n  int antennaModelAllocated_;\n  defiPinAntennaModel** antennaModel_;\n\n  int numAPinPartialMetalArea_;          // 5.4\n  int APinPartialMetalAreaAllocated_;\n  int* APinPartialMetalArea_;            // 5.4 AntennaPinPartialMetalArea\n  char** APinPartialMetalAreaLayer_;     // 5.4 Layer\n\n  int numAPinPartialMetalSideArea_;      // 5.4\n  int APinPartialMetalSideAreaAllocated_;\n  int* APinPartialMetalSideArea_;        // 5.4 AntennaPinPartialMetalSideArea\n  char** APinPartialMetalSideAreaLayer_; // 5.4 Layer\n\n  int numAPinDiffArea_;                  // 5.4\n  int APinDiffAreaAllocated_;\n  int* APinDiffArea_;                    // 5.4 AntennaPinDiffArea\n  char** APinDiffAreaLayer_;             // 5.4 Layer\n\n  int numAPinPartialCutArea_;            // 5.4\n  int APinPartialCutAreaAllocated_;\n  int* APinPartialCutArea_;              // 5.4 AntennaPinPartialCutArea\n  char** APinPartialCutAreaLayer_;       // 5.4 Layer\n\n  int netExprLength_;                    // 5.6\n  char hasNetExpr_;                      // 5.6\n  char* netExpr_;                        // 5.6\n  int supplySensLength_;                 // 5.6\n  char hasSupplySens_;                   // 5.6\n  char* supplySens_;                     // 5.6\n  int groundSensLength_;                 // 5.6\n  char hasGroundSens_;                   // 5.6\n  char* groundSens_;                     // 5.6\n\n  defrData *defData;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiPinProp.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiPinProp_h\n#define defiPinProp_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiPinProp {\npublic:\n  defiPinProp(defrData *data);\n  void Init();\n\n  ~defiPinProp();\n  void Destroy();\n\n  void clear();\n\n  void setName(const char* inst, const char* pin);\n  void addProperty(const char* name, const char* value, const char type);\n  void addNumProperty(const char* name, const double d,\n                      const char* value, const char type);\n\n  int isPin() const;\n  const char* instName() const;\n  const char* pinName() const;\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n\n  void print(FILE* f) const;\n\nprotected:\n  char isPin_;\n  int instNameSize_;\n  char* instName_;\n  int pinNameSize_;\n  char* pinName_;\n\n  int numProps_;\n  int propsAllocated_;\n  char**  propNames_;\n  char**  propValues_;\n  double* propDValues_;\n  char*   propTypes_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiProp.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiProp_h\n#define defiProp_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n// Struct holds the data for one property.\nclass defiProp {\npublic:\n  defiProp(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiProp();\n\n  void setPropType(const char* typ, const char* string);\n  void setRange(double left, double right);\n  void setNumber(double num);\n  void setPropInteger();\n  void setPropReal();\n  void setPropString();\n  void setPropQString(const char* string);\n  void setPropNameMapString(const char* string);\n  void clear();\n\n  const char* string() const;\n  const char* propType() const;\n  const char* propName() const;\n  char  dataType() const;\n       // either I:integer R:real S:string Q:quotedstring N:nameMapString\n  int hasNumber() const;\n  int hasRange() const;\n  int hasString() const;\n  int hasNameMapString() const;\n  double number() const;\n  double left() const;\n  double right() const;\n\n  void bumpSize(int size);\n  void bumpName(int size);\n\n  void print(FILE* f) const;\n\nprotected:\n  char* propType_;      // \"design\" ...\n  char* propName_;      // name.\n  int nameSize_;        // allocated size of name.\n  char hasRange_;       // either 0:NO or 1:YES.\n  char hasNumber_;      // either 0:NO or 1:YES.\n  char hasNameMapString_;\n  char dataType_;       // either I:integer R:real S:string Q:quotedstring.\n                        //   N:nameMapString\n  char* stringData_;    // if it is a string the data is here.\n  int stringLength_;    // allocated size of stringData.\n  double left_, right_; // if it has a range the numbers are here.\n  double d_;            // if it is a real or int the number is here.\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiPropType.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiPropType_h\n#define defiPropType_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Struct holds the data type for one property, if the property is\n// either REAL or INTEGER.\nclass defiPropType {\npublic:\n  defiPropType();\n  void Init();\n\n  void Destroy();\n  ~defiPropType();\n\n  void setPropType(const char* name, const char type);\n  void Clear();\n\n  const char propType(char* name) const;\n  void bumpProps();\n\nprotected:\n  int    numProperties_;\n  int    propertiesAllocated_;\n  char** propNames_;      // name.\n  char*  propTypes_;      // 'R' == \"REAL\", 'I' == \"INTEGER\"\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiRegion.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiRegion_h\n#define defiRegion_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n// Struct holds the data for one property.\nclass defiRegion {\npublic:\n  defiRegion(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiRegion();\n\n  void clear();\n  void setup(const char* name);\n  void addRect(int xl, int yl, int xh, int yh);\n  void addProperty(const char* name, const char* value, const char type);\n  void addNumProperty(const char* name, const double d,\n                      const char* value, const char type);\n  void setType(const char* type);         // 5.4.1\n\n  const char* name() const;\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int propIsNumber(int index) const;\n  int propIsString(int index) const;\n\n  int hasType() const;                    // 5.4.1\n  const char* type() const;               // 5.4.1\n\n  int numRectangles() const;\n  int xl(int index) const;\n  int yl(int index) const;\n  int xh(int index) const;\n  int yh(int index) const;\n\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameLength_;\n\n  int numRectangles_;\n  int rectanglesAllocated_;\n  int* xl_;\n  int* yl_;\n  int* xh_;\n  int* yh_;\n\n  int numProps_;\n  int propsAllocated_;\n  char**  propNames_;\n  char**  propValues_;\n  double* propDValues_;\n  char*   propTypes_;\n\n  char* type_;\n\n  defrData *defData;\n};\n\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiRowTrack.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiRowTrack_h\n#define defiRowTrack_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiRow{\npublic:\n\n  defiRow(defrData *data);\n  void Init();\n\n  ~defiRow();\n  void Destroy();\n  void clear();\n\n  void setup(const char* name, const char* macro,\n\t     double x, double y, int orient);\n  void setDo(double x_num, double y_num,\n\t     double x_step, double y_step);\n  void setHasDoStep();\n  void addProperty(const char* name, const char* value, const char type);\n  void addNumProperty(const char* name, const double d, \n                      const char* value, const char type);\n\n  const char* name() const;\n  const char* macro() const;\n  double x() const;\n  double y() const;\n  int orient() const;\n  const char* orientStr() const;\n  int hasDo() const;               // 5.6, DO is optional\n  double xNum() const;\n  double yNum() const;\n  int hasDoStep() const;           // 5.6, STEP is optional in DO\n  double xStep() const;\n  double yStep() const;\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int propIsNumber(int index) const;\n  int propIsString(int index) const;\n\n  void print(FILE* f) const;\n\nprotected:\n  int nameLength_;\n  char* name_;\n  int macroLength_;\n  char* macro_;\n  double x_;\n  double y_;\n  double xNum_;\n  double yNum_;\n  int orient_;\n  double xStep_;\n  double yStep_;\n  int    hasDo_;\n  int    hasDoStep_;\n\n  int numProps_;\n  int propsAllocated_;\n  char**  propNames_;\n  char**  propValues_;\n  double* propDValues_;\n  char*   propTypes_;\n\n  defrData *defData;\n};\n\n\n\nclass defiTrack{\npublic:\n\n  defiTrack(defrData *data);\n  void Init();\n\n  ~defiTrack();\n  void Destroy();\n\n  void setup(const char* macro);\n  void setDo(double x, double x_num, double x_step);\n  void addLayer(const char* layer);\n  void addMask(int colorMask, int sameMask);\n\n  const char* macro() const;\n  double x() const;\n  double xNum() const;\n  double xStep() const;\n  int numLayers() const;\n  const char* layer(int index) const;\n  int firstTrackMask() const;\n  int sameMask() const;\n\n  void print(FILE* f) const;\n\nprotected:\n  int macroLength_;  // allocated size of macro_;\n  char* macro_;\n  double x_;\n  double xNum_;\n  double xStep_;\n  int layersLength_;  // allocated size of layers_\n  int numLayers_;  // number of places used in layers_\n  char** layers_;\n  int firstTrackMask_;\n  int samemask_;\n\n  defrData *defData;\n};\n\n\n\nclass defiGcellGrid {\npublic:\n\n  defiGcellGrid(defrData *data);\n  void Init();\n\n  ~defiGcellGrid();\n  void Destroy();\n\n  void setup(const char* macro, int x, int xNum, double xStep);\n\n  const char* macro() const;\n  int x() const;\n  int xNum() const;\n  double xStep() const;\n\n  void print(FILE* f) const;\n\nprotected:\n  int macroLength_;\n  char* macro_;\n  int x_;\n  int xNum_;\n  double xStep_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiScanchain.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiScanchain_h\n#define defiScanchain_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiOrdered {\npublic:\n  defiOrdered(defrData *data);\n  ~defiOrdered();\n\n  void addOrdered(const char* inst);\n  void addIn(const char* pin);\n  void addOut(const char* pin);\n  void setOrderedBits(int bits);        // 5.4.1\n  void bump();\n  void Init();\n  void Destroy();\n  void clear();\n\n  int num() const;\n  char** inst() const;\n  char** in() const;\n  char** out() const;\n  int*   bits() const;                  // 5.4.1\n\nprotected:\n  int num_;\n  int allocated_;\n  char** inst_;\n  char** in_;\n  char** out_;\n  int*   bits_;                       // 5.4.1\n    \n  defrData *defData;\n};\n\n\n// Struct holds the data for one Scan chain.\n//\nclass defiScanchain {\npublic:\n  defiScanchain(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiScanchain();\n\n  void setName(const char* name);\n  void clear();\n\n  void addOrderedList();\n  void addOrderedInst(const char* inst);\n  void addOrderedIn(const char* inPin);\n  void addOrderedOut(const char* outPin);\n  void setOrderedBits(int bits);      // 5.4.1\n\n  void addFloatingInst(const char* inst);\n  void addFloatingIn(const char* inPin);\n  void addFloatingOut(const char* outPin);\n  void setFloatingBits(int bits);     // 5.4.1\n\n  void setStart(const char* inst, const char* pin);\n  void setStop(const char* inst, const char* pin);\n  void setCommonIn(const char* pin);\n  void setCommonOut(const char* pin);\n  void setPartition(const char* partName, int maxBits);    // 5.4.1\n\n  const char* name() const;\n  int hasStart() const;\n  int hasStop() const;\n  int hasFloating() const;\n  int hasOrdered() const;\n  int hasCommonInPin() const;\n  int hasCommonOutPin() const;\n  int hasPartition() const;           // 5.4.1\n  int hasPartitionMaxBits() const;    // 5.4.1\n\n  // If the pin part of these routines were not supplied in the DEF\n  // then a NULL pointer will be returned.\n  void start(char** inst, char** pin) const;\n  void stop(char** inst, char** pin) const;\n\n  // There could be many ORDERED constructs in the DEF.  The data in\n  // each ORDERED construct is stored in its own array.  The numOrderedLists()\n  // routine tells how many lists there are.\n  int numOrderedLists() const;\n\n  // This routine will return an array of instances and\n  // an array of in and out pins.\n  // The number if things in the arrays is returned in size.\n  // The inPin and outPin entry is optional for each instance.\n  // If an entry is not given, then that char* is NULL.\n  // For example if the second instance has\n  // instnam= \"FOO\" and IN=\"A\", but no OUT given, then inst[1] points\n  // to \"FOO\"  inPin[1] points to \"A\" and outPin[1] is a NULL pointer.\n  void ordered(int index, int* size, char*** inst, char*** inPin,\n                                      char*** outPin, int** bits) const;\n\n  // All of the floating constructs in the scan chain are\n  // stored in this one array.\n  // If the IN or OUT of an entry is not supplied then the array will have\n  // a NULL pointer in that place.\n  void floating(int* size, char*** inst, char*** inPin, char*** outPin,\n                                      int** bits) const;\n\n  const char* commonInPin() const;\n  const char* commonOutPin() const;\n\n  const char* partitionName() const;        // 5.4.1\n  int partitionMaxBits() const;             // 5.4.1\n\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  char hasStart_;\n  char hasStop_;\n  int nameLength_;\n\n  int numOrderedAllocated_;\n  int numOrdered_;\n  defiOrdered** ordered_; \n\n  int numFloatingAllocated_;\n  int numFloating_;\n  char** floatInst_;    // Array of floating names\n  char** floatIn_;\n  char** floatOut_;\n  int*   floatBits_;    // 5.4.1\n\n  char* stopInst_;\n  char* stopPin_;\n\n  char* startInst_;\n  char* startPin_;\n\n  char* commonInPin_;\n  char* commonOutPin_;\n\n  char  hasPartition_;  // 5.4.1\n  char* partName_;      // 5.4.1\n  int   maxBits_;       // 5.4.1\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiSite.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiSite_h\n#define defiSite_h\n\n#include \"defiKRDefs.hpp\"\n#include \"defiMisc.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n/*\n * Struct holds the data for one site.\n * It is also used for a canplace and cannotoccupy.\n */\nclass defiSite {\npublic:\n  defiSite(defrData *data);\n  void Init();\n\n  ~defiSite();\n  void Destroy();\n\n  void clear();\n\n  void setName(const char* name);\n  void setLocation(double xorg, double yorg);\n  void setOrient(int orient);\n  void setDo(double x_num, double y_num, double x_step, double y_step);\n\n  double x_num() const;\n  double y_num() const;\n  double x_step() const;\n  double y_step() const;\n  double x_orig() const;\n  double y_orig() const;\n  int orient() const;\n  const char* orientStr() const;\n  const char* name() const;\n\n  void print(FILE* f) const;\n\n  void bumpName(int size);\n\nprotected:\n  char* siteName_;     // Name of this.\n  int nameSize_;       // allocated size of siteName_\n  double x_orig_, y_orig_;  // Origin\n  double x_step_, y_step_;  // Array step size.\n  double x_num_, y_num_; \n  int orient_;         // orientation\n\n  defrData *defData;\n};\n\n\n\n/* Struct holds the data for a Box */\nclass defiBox {\npublic:\n  // Use the default destructor and constructor.\n  // 5.6 changed to use it own constructor & destructor\n\n  defiBox();\n  void Init();\n  void Destroy();\n  ~defiBox();\n\n  // NOTE: 5.6\n  // The following methods are still here for backward compatibility\n  // For new reader they should use numPoints & getPoint to get the\n  // data.\n  int xl() const;\n  int yl() const;\n  int xh() const;\n  int yh() const;\n\n  void addPoint(defiGeometries* geom);\n  defiPoints getPoint() const;\n\n  void print(FILE* f) const;\n\nprotected:\n  int xl_, yl_;\n  int xh_, yh_;\n  defiPoints* points_;    // 5.6\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiSlot.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiSLOT_h\n#define defiSLOT_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n#include \"defiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\nclass defiSlot {\npublic:\n  defiSlot(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiSlot();\n\n  void clear();\n  void clearPoly();\n\n  void setLayer(const char* name);\n  void addRect(int xl, int yl, int xh, int yh);\n  void addPolygon(defiGeometries* geom);\n\n  int hasLayer() const;\n  const char* layerName() const;\n\n  int numRectangles() const;\n  int xl(int index) const;\n  int yl(int index) const;\n  int xh(int index) const;\n  int yh(int index) const;\n\n  int numPolygons() const;                        // 5.6\n  defiPoints getPolygon(int index) const;  // 5.6\n\n  void print(FILE* f) const;\n\nprotected:\n  int   hasLayer_;\n  char* layerName_;\n  int   layerNameLength_;\n  int   numRectangles_;\n  int   rectsAllocated_;\n  int*  xl_;\n  int*  yl_;\n  int*  xh_;\n  int*  yh_;\n  int   numPolys_;                  // 5.6\n  int   polysAllocated_;            // 5.6\n  defiPoints** polygons_;    // 5.6\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiTimingDisable.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiTimingDisable_h\n#define defiTimingDisable_h\n\n#include <stdio.h>\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// A Timing disable can be a from-to  or a thru or a macro.\n//   A macro is either a fromto macro or a thru macro.\nclass defrData;\n\n\nclass defiTimingDisable {\npublic:\n  defiTimingDisable(defrData *data);\n  void Init();\n\n  void Destroy();\n  ~defiTimingDisable();\n\n  void clear();\n\n  void setFromTo(const char* fromInst, const char* fromPin,\n\t\t const char* toInst, const char* toPin);\n  void setThru(const char* fromInst, const char* fromPin);\n  void setMacro(const char* name);\n  void setMacroThru(const char* thru);\n  void setMacroFromTo(const char* fromPin, const char* toPin);\n  void setReentrantPathsFlag();\n\n  int hasMacroThru() const;\n  int hasMacroFromTo() const;\n  int hasThru() const;\n  int hasFromTo() const;\n  int hasReentrantPathsFlag() const;\n\n  const char* fromPin() const;\n  const char* toPin() const;\n  const char* fromInst() const;\n  const char* toInst() const;\n  const char* macroName() const;\n  const char* thruPin() const;    // Also macro thru\n  const char* thruInst() const;\n\n  // debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* fromInst_;  // also macro name and thru inst\n  int fromInstLength_;\n  char* toInst_;\n  int toInstLength_;\n  char* fromPin_;  // also macro thru and thru pin\n  int fromPinLength_;\n  char* toPin_;\n  int toPinLength_;\n\n  int hasFromTo_;\n  int hasThru_;\n  int hasMacro_;\n  int hasReentrantPathsFlag_;\n\n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiUser.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n/*\n * User header file for the DEF Interface.  This includes\n * all of the header files which are relevant to both the\n * reader and the writer.\n *\n * defrReader.h and defwWriter.h include this file, so that\n * an application only needs to include either defwReader.h\n * or defwWriter.h.\n */\n\n#ifndef DEFI_USER_H\n#define DEFI_USER_H\n\n/* General utilities. */\n/* #include \"defiMalloc.hpp\" */\n/* #include \"defiUtils.hpp\" */\n\n/*\n * API objects\n */\n#include \"defiDebug.hpp\"\n#include \"defiProp.hpp\"\n#include \"defiSite.hpp\"\n#include \"defiComponent.hpp\"\n#include \"defiNet.hpp\"\n#include \"defiPath.hpp\"\n#include \"defiPinCap.hpp\"\n#include \"defiRowTrack.hpp\"\n#include \"defiVia.hpp\"\n#include \"defiRegion.hpp\"\n#include \"defiGroup.hpp\"\n#include \"defiAssertion.hpp\"\n#include \"defiScanchain.hpp\"\n#include \"defiIOTiming.hpp\"\n#include \"defiFPC.hpp\"\n#include \"defiTimingDisable.hpp\"\n#include \"defiPartition.hpp\"\n#include \"defiPinProp.hpp\"\n#include \"defiBlockage.hpp\"\n#include \"defiSlot.hpp\"\n#include \"defiFill.hpp\"\n#include \"defiNonDefault.hpp\"\n#include \"defiPropType.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n/* NEW CALLBACK - If you are creating a new .cpp and .hpp file to\n * describe a new class of object in the parser, then add a reference\n * to the .hpp here.\n *\n *  You must also add an entry for the .h and the .hpp in the package_list\n * file of the ../../../release directory. */\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defiUtil.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiUtil_h\n#define defiUtil_h\n\n#include \"defiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n/* Return codes Orient and Rotation */\n#define DEF_ORIENT_N  0\n#define DEF_ORIENT_W  1\n#define DEF_ORIENT_S  2\n#define DEF_ORIENT_E  3\n#define DEF_ORIENT_FN 4\n#define DEF_ORIENT_FW 5\n#define DEF_ORIENT_FS 6\n#define DEF_ORIENT_FE 7\n\nconst char* defiOrientStr(int orient);\n\nEND_LEFDEF_PARSER_NAMESPACE\n\n#endif\n\n"
  },
  {
    "path": "rsyn/include/def5.8/defiVia.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defiVia_h\n#define defiVia_h\n\n#include \"defiKRDefs.hpp\"\n#include <stdio.h>\n#include \"defiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrData;\n\n// Struct holds the data for one property.\nclass defiVia {\npublic:\n  defiVia(defrData *data);\n  void Init();\n\n  void clear();\n  void Destroy();\n  ~defiVia();\n\n  void setup(const char* name);\n  void addPattern(const char* patt);\n  void addLayer(const char* layer, int xl, int yl, int xh, int yh, int colorMask = 0);\n  // 5.6\n  void addPolygon(const char* layer, defiGeometries* geom, int colorMask = 0);\n  void addViaRule(char* viaRuleName, int xSize, int ySize, char* botLayer,\n                  char* cutLayer, char* topLayer, int xSpacing, int ySpacing,\n                  int xBotEnc, int yBotEnc, int xTopEnc, int yTopEnc);\n  void addRowCol(int numCutRows, int numCutCols);\n  void addOrigin(int xOffset, int yOffset);\n  void addOffset(int xBotOs, int yBotOs, int xTopOs, int yTopOs);\n  void addCutPattern(char* cutPattern);\n  \n  const char* name() const;\n  const char* pattern() const;\n  int hasPattern() const;\n  int numLayers() const;\n  void layer(int index, char** layer, int* xl, int* yl, int* xh, int* yh) const;\n  int numPolygons() const;                        // 5.6\n  const char* polygonName(int index) const;       // 5.6\n  defiPoints getPolygon(int index) const;  // 5.6\n  int hasViaRule() const;\n  void viaRule(char** viaRuleName, int* xSize, int* ySize, char** botLayer,\n               char** cutLayer, char** topLayer, int* xCutSpacing,\n               int* yCutSpacing, int* xBotEnc, int* yBotEnc, int* xTopEnc,\n               int* yTopEnc) const;\n  int hasRowCol() const;\n  void rowCol(int* numCutRows, int* numCutCols) const;\n  int hasOrigin() const;\n  void origin(int* xOffset, int* yOffset) const;\n  int hasOffset() const;\n  void offset(int* xBotOffset, int* yBotOffset, int* xTopOffset,\n              int* yTopOffset) const;\n  int hasCutPattern() const;\n  const char* cutPattern() const;\n  int hasRectMask(int index) const;\n  int rectMask(int index) const;\n  int hasPolyMask(int index) const;\n  int polyMask(int index) const;\n\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameLength_;\n  char* pattern_;\n  int patternLength_;\n  char** layers_;\n  int hasPattern_;\n  int* xl_;\n  int* yl_;\n  int* xh_;\n  int* yh_;\n  int layersLength_;\n  int numLayers_;\n  int numPolys_;            // 5.6\n  char** polygonNames_;     // 5.6 layerName for POLYGON\n  int polysAllocated_;      // 5.6\n  defiPoints** polygons_; // 5.6\n  char* viaRule_;           // 5.6\n  int   viaRuleLength_;     // 5.6\n  int   hasViaRule_;        // 5.6\n  int xSize_;               // 5.6\n  int ySize_;               // 5.6\n  char* botLayer_;          // 5.6\n  char* cutLayer_;          // 5.6\n  char* topLayer_;          // 5.6\n  int   botLayerLength_;    // 5.6\n  int   cutLayerLength_;    // 5.6\n  int   topLayerLength_;    // 5.6\n  int   xCutSpacing_;       // 5.6\n  int   yCutSpacing_;       // 5.6\n  int   xBotEnc_;           // 5.6\n  int   yBotEnc_;           // 5.6\n  int   xTopEnc_;           // 5.6\n  int   yTopEnc_;           // 5.6\n  int   rows_;              // 5.6\n  int   cols_;              // 5.6\n  int   xOffset_;           // 5.6\n  int   yOffset_;           // 5.6\n  int   xBotOffset_;        // 5.6\n  int   yBotOffset_;        // 5.6\n  int   xTopOffset_;        // 5.6\n  int   yTopOffset_;        // 5.6\n  char* cutPattern_;        // 5.6\n  int   cutPatternLength_;  // 5.6\n  int   hasCutPattern_;     // 5.6\n  int*  rectMask_;          // 5.8\n  int*  polyMask_;          // 5.8\n  \n  defrData *defData;\n};\n\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defrCallBacks.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef DEFRCALLBACKS_H\n#define DEFRCALLBACKS_H 1\n\n#include \"defiKRDefs.hpp\"\n\n#include \"defrReader.hpp\"\n\n#include \"defrReader.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass defrCallbacks {\npublic:\n    defrCallbacks();\n\n    void SetUnusedCallbacks(defrVoidCbkFnType f);\n\n    defrStringCbkFnType DesignCbk;\n    defrStringCbkFnType TechnologyCbk;\n    defrVoidCbkFnType DesignEndCbk;\n    defrPropCbkFnType PropCbk;\n    defrVoidCbkFnType PropDefEndCbk;\n    defrVoidCbkFnType PropDefStartCbk;\n    defrStringCbkFnType ArrayNameCbk;\n    defrStringCbkFnType FloorPlanNameCbk;\n    defrDoubleCbkFnType UnitsCbk;\n    defrStringCbkFnType DividerCbk;\n    defrStringCbkFnType BusBitCbk;\n    defrSiteCbkFnType SiteCbk;\n    defrSiteCbkFnType CanplaceCbk;\n    defrSiteCbkFnType CannotOccupyCbk;\n    defrIntegerCbkFnType ComponentStartCbk;\n    defrVoidCbkFnType ComponentEndCbk;\n    defrComponentCbkFnType ComponentCbk;\n    defrComponentMaskShiftLayerCbkFnType ComponentMaskShiftLayerCbk;\n    defrIntegerCbkFnType NetStartCbk;\n    defrVoidCbkFnType NetEndCbk;\n    defrNetCbkFnType NetCbk;\n    defrStringCbkFnType NetNameCbk;\n    defrStringCbkFnType NetSubnetNameCbk;\n    defrStringCbkFnType NetNonDefaultRuleCbk;\n    defrNetCbkFnType NetPartialPathCbk;\n    defrPathCbkFnType PathCbk;\n    defrDoubleCbkFnType VersionCbk;\n    defrStringCbkFnType VersionStrCbk;\n    defrStringCbkFnType PinExtCbk;\n    defrStringCbkFnType ComponentExtCbk;\n    defrStringCbkFnType ViaExtCbk;\n    defrStringCbkFnType NetConnectionExtCbk;\n    defrStringCbkFnType NetExtCbk;\n    defrStringCbkFnType GroupExtCbk;\n    defrStringCbkFnType ScanChainExtCbk;\n    defrStringCbkFnType IoTimingsExtCbk;\n    defrStringCbkFnType PartitionsExtCbk;\n    defrStringCbkFnType HistoryCbk;\n    defrBoxCbkFnType DieAreaCbk;\n    defrPinCapCbkFnType PinCapCbk;\n    defrPinCbkFnType PinCbk;\n    defrIntegerCbkFnType StartPinsCbk;\n    defrVoidCbkFnType PinEndCbk;\n    defrIntegerCbkFnType DefaultCapCbk;\n    defrRowCbkFnType RowCbk;\n    defrTrackCbkFnType TrackCbk;\n    defrGcellGridCbkFnType GcellGridCbk;\n    defrIntegerCbkFnType ViaStartCbk;\n    defrVoidCbkFnType ViaEndCbk;\n    defrViaCbkFnType ViaCbk;\n    defrIntegerCbkFnType RegionStartCbk;\n    defrVoidCbkFnType RegionEndCbk;\n    defrRegionCbkFnType RegionCbk;\n    defrIntegerCbkFnType SNetStartCbk;\n    defrVoidCbkFnType SNetEndCbk;\n    defrNetCbkFnType SNetCbk;\n    defrNetCbkFnType SNetPartialPathCbk;\n    defrNetCbkFnType SNetWireCbk;\n    defrIntegerCbkFnType GroupsStartCbk;\n    defrVoidCbkFnType GroupsEndCbk;\n    defrStringCbkFnType GroupNameCbk;\n    defrStringCbkFnType GroupMemberCbk;\n    defrGroupCbkFnType GroupCbk;\n    defrIntegerCbkFnType AssertionsStartCbk;\n    defrVoidCbkFnType AssertionsEndCbk;\n    defrAssertionCbkFnType AssertionCbk;\n    defrIntegerCbkFnType ConstraintsStartCbk;\n    defrVoidCbkFnType ConstraintsEndCbk;\n    defrAssertionCbkFnType ConstraintCbk;\n    defrIntegerCbkFnType ScanchainsStartCbk;\n    defrVoidCbkFnType ScanchainsEndCbk;\n    defrScanchainCbkFnType ScanchainCbk;\n    defrIntegerCbkFnType IOTimingsStartCbk;\n    defrVoidCbkFnType IOTimingsEndCbk;\n    defrIOTimingCbkFnType IOTimingCbk;\n    defrIntegerCbkFnType FPCStartCbk;\n    defrVoidCbkFnType FPCEndCbk;\n    defrFPCCbkFnType FPCCbk;\n    defrIntegerCbkFnType TimingDisablesStartCbk;\n    defrVoidCbkFnType TimingDisablesEndCbk;\n    defrTimingDisableCbkFnType TimingDisableCbk;\n    defrIntegerCbkFnType PartitionsStartCbk;\n    defrVoidCbkFnType PartitionsEndCbk;\n    defrPartitionCbkFnType PartitionCbk;\n    defrIntegerCbkFnType PinPropStartCbk;\n    defrVoidCbkFnType PinPropEndCbk;\n    defrPinPropCbkFnType PinPropCbk;\n    defrIntegerCbkFnType CaseSensitiveCbk;\n    defrIntegerCbkFnType BlockageStartCbk;\n    defrVoidCbkFnType BlockageEndCbk;\n    defrBlockageCbkFnType BlockageCbk;\n    defrIntegerCbkFnType SlotStartCbk;\n    defrVoidCbkFnType SlotEndCbk;\n    defrSlotCbkFnType SlotCbk;\n    defrIntegerCbkFnType FillStartCbk;\n    defrVoidCbkFnType FillEndCbk;\n    defrFillCbkFnType FillCbk;\n    defrIntegerCbkFnType NonDefaultStartCbk;\n    defrVoidCbkFnType NonDefaultEndCbk;\n    defrNonDefaultCbkFnType NonDefaultCbk;\n    defrIntegerCbkFnType StylesStartCbk;\n    defrVoidCbkFnType StylesEndCbk;\n    defrStylesCbkFnType StylesCbk;\n    defrStringCbkFnType ExtensionCbk;\n\n\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defrData.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013 - 2015, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: arakhman $\n//  $Revision: #6 $\n//  $Date: 2013/08/09 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#include <cstring>\n#include <string>\n#include <map>\n#include <vector>\n\n#include \"defrReader.hpp\"\n#include \"defrCallBacks.hpp\"\n#include \"defrSettings.hpp\"\n\n#ifndef defrData_h\n#define defrData_h\n\n#define CURRENT_VERSION 5.8\n#define RING_SIZE 10\n#define IN_BUF_SIZE 16384\n#define TOKEN_SIZE 4096\n#define MSG_SIZE 100\n\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nstruct defCompareStrings \n{\n    bool operator()(const std::string &lhs, const std::string &rhs) const {\n        return std::strcmp(lhs.c_str(), rhs.c_str()) < 0;\n    }\n};\n\ntypedef std::map<std::string, std::string, defCompareStrings> defAliasMap;\ntypedef std::map<std::string, std::string, defCompareStrings> defDefineMap;\n\ntypedef union {\n        double dval ;\n        int    integer ;\n        char * string ;\n        int    keyword ;  // really just a nop \n        struct defpoint pt;\n        defTOKEN *tk;\n} YYSTYPE;\n\n#define YYSTYPE_IS_DECLARED\n\nclass defrData {\n\npublic:\n    defrData(const defrCallbacks *pCallbacks,\n             const defrSettings  *pSettings,\n             defrSession         *pSession);\n    ~defrData();\n\n    inline int          defGetKeyword(const char* name, int *result);\n    inline int          defGetAlias(const std::string &name, std::string &result);\n    inline int          defGetDefine(const std::string &name, std::string &result);\n    void                reload_buffer(); \n    int                 GETC();\n\n    void                UNGETC(char ch);\n    char*               ringCopy(const char* string);\n    int                 DefGetTokenFromStack(char *s);\n    inline void         print_lines(long long lines);\n    const char *        lines2str(long long lines);\n    static inline void  IncCurPos(char **curPos, char **buffer, int *bufferSize);\n    int                 DefGetToken(char **buffer, int *bufferSize);\n    static void         uc_array(char *source, char *dest);\n    void                StoreAlias();\n    int                 defyylex(YYSTYPE *pYylval);\n    int                 sublex(YYSTYPE *pYylval);\n    int                 amper_lookup(YYSTYPE *pYylval, char *tkn);\n    void                defError(int msgNum, const char *s);\n    void                defyyerror(const char *s);\n    void                defInfo(int msgNum, const char *s);\n    void                defWarning(int msgNum, const char *s);\n\n    void                defiError(int check, int msgNum, const char* mess);\n    const char          *DEFCASE(const char* ch);\n    void                pathIsDone(int shield, int reset, int netOsnet, int *needCbk);\n    const char          *upperCase(const char* str);\n\n    inline int          checkErrors();\n    int                 validateMaskInput(int input, int warningIndex, int getWarningsIndex);\n    int                 validateMaskShiftInput(const char* shiftMask, int warningIndex, int getWarningsIndex);\n\n    static double       convert_defname2num(char *versionName);\n\n    static int          numIsInt (char* volt);\n    int                 defValidNum(int values);\n\n    inline static const char   *defkywd(int num);\n\n    FILE*  defrLog; \n    char   defPropDefType; // save the current type of the property\n    char*  ch; \n    char*  defMsg; \n    char*  deftoken; \n    char*  uc_token;\n    char*  last; \n    char*  magic; \n    char*  next; \n    char*  pv_deftoken; \n    char*  rowName; // to hold the rowName for message\n    char*  shieldName; // to hold the shieldNetName\n    char*  shiftBuf; \n    char*  warningMsg; \n    double save_x; \n    double save_y; \n    double lVal;\n    double rVal;\n    int  aOxide; // keep track for oxide\n    int  assertionWarnings; \n    int  bit_is_keyword; \n    int  bitsNum; // Scanchain Bits value\n    int  blockageWarnings; \n    int  by_is_keyword; \n    int  caseSensitiveWarnings; \n    int  componentWarnings; \n    int  constraintWarnings; \n    int  cover_is_keyword; \n    int  defIgnoreVersion; // ignore checking version number\n    int  defInvalidChar; \n    int  defMsgCnt; \n    int  defMsgPrinted; // number of msgs output so far\n    int  defPrintTokens; \n    int  defRetVal; \n    int  def_warnings; \n    int  defaultCapWarnings; \n    int  do_is_keyword; \n    int  dumb_mode; \n    int  errors; \n    int  fillWarnings; \n    int  first_buffer; \n    int  fixed_is_keyword; \n    int  gcellGridWarnings; \n    int  hasBlkLayerComp; // only 1 BLOCKAGE/LAYER/COMP\n    int  hasBlkLayerSpac; // only 1 BLOCKAGE/LAYER/SPACING\n    int  hasBlkLayerTypeComp; // SLOTS or FILLS\n    int  hasBlkPlaceComp; // only 1 BLOCKAGE/PLACEMENT/COMP\n    int  hasBlkPlaceTypeComp; // SOFT or PARTIAL\n    int  hasBusBit; // keep track BUSBITCHARS is in the file\n    int  hasDes; // keep track DESIGN is in the file\n    int  hasDivChar; // keep track DIVIDERCHAR is in the file\n    int  hasDoStep; \n    int  hasNameCase; // keep track NAMESCASESENSITIVE is in the file\n    int  hasOpenedDefLogFile; \n    int  hasPort; // keep track is port defined in a Pin\n    int  hasVer; // keep track VERSION is in the file\n    int  hasFatalError; // don't report errors after the file end.\n    int  iOTimingWarnings; \n    int  input_level; \n    int  mask_is_keyword; \n    int  mustjoin_is_keyword; \n    int  names_case_sensitive; // always true in 5.6\n    int  needNPCbk; // if cbk for net path is needed\n    int  needSNPCbk; // if cbk for snet path is needed\n    int  netOsnet; // net = 1 & snet = 2\n    int  netWarnings; \n    int  new_is_keyword; \n    int  nl_token; \n    int  no_num; \n    int  nonDefaultWarnings; \n    int  nondef_is_keyword; \n    int  ntokens; \n    int  orient_is_keyword; \n    int  pinExtWarnings; \n    int  pinWarnings; \n    int  real_num; \n    int  rect_is_keyword; \n    int  regTypeDef; // keep track that region type is defined \n    int  regionWarnings; \n    int  ringPlace; \n    int  routed_is_keyword; \n    int  rowWarnings; \n    int  sNetWarnings; \n    int  scanchainWarnings; \n    int  shield; // To identify if the path is shield for 5.3\n    int  shiftBufLength; \n    int  specialWire_mask; \n    int  step_is_keyword; \n    int  stylesWarnings; \n    int  trackWarnings; \n    int  unitsWarnings; \n    int  versionWarnings; \n    int  viaRule; // keep track the viarule has called first\n    int  viaWarnings; \n    int  virtual_is_keyword; \n    int  deftokenLength;\n    long long nlines;\n\n    std::vector<char>  History_text; \n    defAliasMap        def_alias_set; \n    defDefineMap       def_defines_set;\n\n    char*  specialWire_routeStatus;\n    char*  specialWire_routeStatusName;\n    char*  specialWire_shapeType;\n    double VersionNum;\n    double xStep;\n    double yStep;\n        \n    //defrParser vars.\n    defiPath PathObj;\n    defiProp Prop;\n    defiSite Site;\n    defiComponent Component;\n    defiComponentMaskShiftLayer ComponentMaskShiftLayer;\n    defiNet Net;\n    defiPinCap PinCap;\n    defiSite CannotOccupy;\n    defiSite Canplace;\n    defiBox DieArea;\n    defiPin Pin;\n    defiRow Row;\n    defiTrack Track;\n    defiGcellGrid GcellGrid;\n    defiVia Via;\n    defiRegion Region;\n    defiGroup Group;\n    defiAssertion Assertion;\n    defiScanchain Scanchain;\n    defiIOTiming IOTiming;\n    defiFPC FPC;\n    defiTimingDisable TimingDisable;\n    defiPartition Partition;\n    defiPinProp PinProp;\n    defiBlockage Blockage;\n    defiSlot Slot;\n    defiFill Fill;\n    defiNonDefault NonDefault;\n    defiStyles Styles;\n    defiGeometries Geometries;\n    int doneDesign;      // keep track if the Design is done parsing\n    \n    // Flags to control what happens\n    int NeedPathData;\n\n    defiSubnet* Subnet;\n    int msgLimit[DEF_MSGS];\n    char buffer[IN_BUF_SIZE];\n    char* ring[RING_SIZE];\n    int ringSizes[RING_SIZE];\n    std::string stack[20];  /* the stack itself */\n\n    YYSTYPE yylval;\n    const defrCallbacks *callbacks;\n    const defrSettings  *settings;\n    defrSession         *session;\n    char                lineBuffer[MSG_SIZE];\n\n    FILE* File;\n};\n\nclass defrContext {\npublic:\n    defrContext(int ownConf = 0);\n\n    defrSettings          *settings;\n    defrCallbacks         *callbacks;\n    defrSession           *session;\n    defrData              *data;\n    int                   ownConfig;\n    const char            *init_call_func;\n};\n\nint \ndefrData::checkErrors()\n{\n    if (errors > 20) {\n        defError(6011, \"Too many syntax errors have been reported.\"); \n        errors = 0; \n        return 1; \n    }\n\n    return 0;\n}\n\nEND_LEFDEF_PARSER_NAMESPACE\n\n#endif\n\n"
  },
  {
    "path": "rsyn/include/def5.8/defrReader.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013-2016, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef DEFRREADER_H\n#define DEFRREADER_H\n\n#include <stdarg.h>\n\n#include \"defiKRDefs.hpp\"\n#include \"defiDefs.hpp\"\n#include \"defiUser.hpp\"\n\n#define DEF_MSGS 4013\n#define CBMAX 150    // Number of callbacks.\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// An enum describing all of the types of reader callbacks.\ntypedef enum {\n  defrUnspecifiedCbkType = 0,\n  defrDesignStartCbkType,\n  defrTechNameCbkType,\n  defrPropCbkType,\n  defrPropDefEndCbkType,\n  defrPropDefStartCbkType,\n  defrFloorPlanNameCbkType,\n  defrArrayNameCbkType,\n  defrUnitsCbkType,\n  defrDividerCbkType,\n  defrBusBitCbkType,\n  defrSiteCbkType,\n  defrComponentStartCbkType,\n  defrComponentCbkType,\n  defrComponentEndCbkType,\n  defrNetStartCbkType,\n  defrNetCbkType,\n  defrNetNameCbkType,\n  defrNetNonDefaultRuleCbkType,\n  defrNetSubnetNameCbkType,\n  defrNetEndCbkType,\n  defrPathCbkType,\n  defrVersionCbkType,\n  defrVersionStrCbkType,\n  defrComponentExtCbkType,\n  defrPinExtCbkType,\n  defrViaExtCbkType,\n  defrNetConnectionExtCbkType,\n  defrNetExtCbkType,\n  defrGroupExtCbkType,\n  defrScanChainExtCbkType,\n  defrIoTimingsExtCbkType,\n  defrPartitionsExtCbkType,\n  defrHistoryCbkType,\n  defrDieAreaCbkType,\n  defrCanplaceCbkType,\n  defrCannotOccupyCbkType,\n  defrPinCapCbkType,\n  defrDefaultCapCbkType,\n  defrStartPinsCbkType,\n  defrPinCbkType,\n  defrPinEndCbkType,\n  defrRowCbkType,\n  defrTrackCbkType,\n  defrGcellGridCbkType,\n  defrViaStartCbkType,\n  defrViaCbkType,\n  defrViaEndCbkType,\n  defrRegionStartCbkType,\n  defrRegionCbkType,\n  defrRegionEndCbkType,\n  defrSNetStartCbkType,\n  defrSNetCbkType,\n  defrSNetPartialPathCbkType,\n  defrSNetWireCbkType,\n  defrSNetEndCbkType,\n  defrGroupsStartCbkType,\n  defrGroupNameCbkType,\n  defrGroupMemberCbkType,\n  defrGroupCbkType,\n  defrGroupsEndCbkType,\n  defrAssertionsStartCbkType,\n  defrAssertionCbkType,\n  defrAssertionsEndCbkType,\n  defrConstraintsStartCbkType,\n  defrConstraintCbkType,\n  defrConstraintsEndCbkType,\n  defrScanchainsStartCbkType,\n  defrScanchainCbkType,\n  defrScanchainsEndCbkType,\n  defrIOTimingsStartCbkType,\n  defrIOTimingCbkType,\n  defrIOTimingsEndCbkType,\n  defrFPCStartCbkType,\n  defrFPCCbkType,\n  defrFPCEndCbkType,\n  defrTimingDisablesStartCbkType,\n  defrTimingDisableCbkType,\n  defrTimingDisablesEndCbkType,\n  defrPartitionsStartCbkType,\n  defrPartitionCbkType,\n  defrPartitionsEndCbkType,\n  defrPinPropStartCbkType,\n  defrPinPropCbkType,\n  defrPinPropEndCbkType,\n  defrBlockageStartCbkType,\n  defrBlockageCbkType,\n  defrBlockageEndCbkType,\n  defrSlotStartCbkType,\n  defrSlotCbkType,\n  defrSlotEndCbkType,\n  defrFillStartCbkType,\n  defrFillCbkType,\n  defrFillEndCbkType,\n  defrCaseSensitiveCbkType,\n  defrNonDefaultStartCbkType,\n  defrNonDefaultCbkType,\n  defrNonDefaultEndCbkType,\n  defrStylesStartCbkType,\n  defrStylesCbkType,\n  defrStylesEndCbkType,\n  defrExtensionCbkType,\n\n  // NEW CALLBACK - If you are creating a new callback, you must add\n  // a unique item to this enum for each callback routine. When the\n  // callback is called in def.y you have to supply this enum item\n  // as an argument in the call.\n\n  defrComponentMaskShiftLayerCbkType,\n  defrDesignEndCbkType\n} defrCallbackType_e;\n \n \n// Declarations of function signatures for each type of callback.\n// These declarations are type-safe when compiling with ANSI C\n// or C++; you will only be able to register a function pointer\n// with the correct signature for a given type of callback.\n//\n// Each callback function is expected to return 0 if successful.\n// A non-zero return code will cause the reader to abort.\n//\n// The defrDesignStart and defrDesignEnd callback is only called once.\n// Other callbacks may be called multiple times, each time with a different\n// set of data.\n//\n// For each callback, the Def API will make the callback to the\n// function supplied by the client, which should either make a copy\n// of the Def object, or store the data in the client's own data structures.\n// The Def API will delete or reuse each object after making the callback,\n// so the client should not keep a pointer to it.\n//\n// All callbacks pass the user data pointer provided in defrRead()\n// or defrSetUserData() back to the client; this can be used by the\n// client to obtain access to the rest of the client's data structures.\n//\n// The user data pointer is obtained using defrGetUserData() immediately\n// prior to making each callback, so the client is free to change the\n// user data on the fly if necessary.\n//\n// Callbacks with the same signature are passed a callback type\n// parameter, which allows an application to write a single callback\n// function, register that function for multiple callbacks, then\n// switch based on the callback type to handle the appropriate type of\n// data.\n \n\n// A declaration of the signature of all callbacks that return nothing.     \ntypedef int (*defrVoidCbkFnType) (defrCallbackType_e, void* v, defiUserData);\n\n// A declaration of the signature of all callbacks that return a string.     \ntypedef int (*defrStringCbkFnType) (defrCallbackType_e, const char *string, defiUserData);\n \n// A declaration of the signature of all callbacks that return a integer.     \ntypedef int (*defrIntegerCbkFnType) (defrCallbackType_e, int number, defiUserData);\n \n// A declaration of the signature of all callbacks that return a double.     \ntypedef int (*defrDoubleCbkFnType) (defrCallbackType_e, double number, defiUserData);\n \n// A declaration of the signature of all callbacks that return a defiProp.     \ntypedef int (*defrPropCbkFnType) (defrCallbackType_e, defiProp *prop, defiUserData);\n \n// A declaration of the signature of all callbacks that return a defiSite.     \ntypedef int (*defrSiteCbkFnType) (defrCallbackType_e, defiSite *site, defiUserData);\n \n// A declaration of the signature of all callbacks that return a defComponent.     \ntypedef int (*defrComponentCbkFnType) (defrCallbackType_e, defiComponent *comp, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defComponentMaskShiftLayer.     \ntypedef int (*defrComponentMaskShiftLayerCbkFnType) (defrCallbackType_e, defiComponentMaskShiftLayer *comp, defiUserData);\n \n// A declaration of the signature of all callbacks that return a defNet.     \ntypedef int (*defrNetCbkFnType) (defrCallbackType_e, defiNet *net, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defPath.     \ntypedef int (*defrPathCbkFnType) (defrCallbackType_e, defiPath *path, defiUserData);\n \n// A declaration of the signature of all callbacks that return a defiBox.     \ntypedef int (*defrBoxCbkFnType) (defrCallbackType_e, defiBox *box, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiPinCap.     \ntypedef int (*defrPinCapCbkFnType) (defrCallbackType_e, defiPinCap *pincap, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiPin.     \ntypedef int (*defrPinCbkFnType) (defrCallbackType_e, defiPin *pin, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiRow.     \ntypedef int (*defrRowCbkFnType) (defrCallbackType_e, defiRow *row, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiTrack.     \ntypedef int (*defrTrackCbkFnType) (defrCallbackType_e, defiTrack *track, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiGcellGrid.     \ntypedef int (*defrGcellGridCbkFnType) (defrCallbackType_e, defiGcellGrid *grid, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiVia.     \ntypedef int (*defrViaCbkFnType) (defrCallbackType_e, defiVia *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiRegion.     \ntypedef int (*defrRegionCbkFnType) (defrCallbackType_e, defiRegion *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiGroup.     \ntypedef int (*defrGroupCbkFnType) (defrCallbackType_e, defiGroup *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiAssertion. \ntypedef int (*defrAssertionCbkFnType) (defrCallbackType_e, defiAssertion *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiScanChain. \ntypedef int (*defrScanchainCbkFnType) (defrCallbackType_e, defiScanchain *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiIOTiming. \ntypedef int (*defrIOTimingCbkFnType) (defrCallbackType_e, defiIOTiming *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiFPC. \ntypedef int (*defrFPCCbkFnType) (defrCallbackType_e, defiFPC *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiTimingDisable. \ntypedef int (*defrTimingDisableCbkFnType) (defrCallbackType_e, defiTimingDisable *, defiUserData);\n \n\n// A declaration of the signature of all callbacks that return a defiPartition. \ntypedef int (*defrPartitionCbkFnType) (defrCallbackType_e, defiPartition *, defiUserData);\n \n// A declaration of the signature of all callbacks that return a defiPinProp. \ntypedef int (*defrPinPropCbkFnType) (defrCallbackType_e, defiPinProp *, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defiBlockage. \ntypedef int (*defrBlockageCbkFnType) (defrCallbackType_e, defiBlockage *, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defiSlot. \ntypedef int (*defrSlotCbkFnType) (defrCallbackType_e, defiSlot *, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defiFill. \ntypedef int (*defrFillCbkFnType) (defrCallbackType_e, defiFill *, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defiNonDefault.\ntypedef int (*defrNonDefaultCbkFnType) (defrCallbackType_e, defiNonDefault *, defiUserData);\n\n// A declaration of the signature of all callbacks that return a defiStyles. \ntypedef int (*defrStylesCbkFnType) (defrCallbackType_e, defiStyles *, defiUserData);\n\n// NEW CALLBACK - Each callback must return user data, enum, and\n//   OUR-DATA item.  We must define a callback function type for\n//   each type of OUR-DATA.  Some routines return a string, some\n//   return an integer, and some return a pointer to a class.\n//   If you create a new class, then you must create a new function\n//   type here to return that class to the user. \n\n// The reader initialization.  Must be called before defrRead().\nextern int defrInit ();\nextern int defrInitSession (int startSession = 1);\n\n// obsoleted now.\nextern int defrReset ();\n\n//Sets all parser memory into init state.\nextern int defrClear();\n\n// Change the comment character in the DEF file.  The default\n// is '#' \nextern void defrSetCommentChar (char c);\n\n// Functions to call to set specific actions in the parser.\nextern void defrSetAddPathToNet ();\nextern void defrSetAllowComponentNets ();\nextern int defrGetAllowComponentNets ();\nextern void defrSetCaseSensitivity (int caseSense);\n\n// Functions to keep track of callbacks that the user did not\n// supply.  Normally all parts of the DEF file that the user\n// does not supply a callback for will be ignored.  These\n// routines tell the parser count the DEF constructs that are\n// present in the input file, but did not trigger a callback.\n// This should help you find any \"important\" DEF constructs that\n// you are ignoring.\nextern void defrSetRegisterUnusedCallbacks ();\nextern void defrPrintUnusedCallbacks (FILE* log);\n// Obsoleted now.\nextern int  defrReleaseNResetMemory ();\n\n// This function clear session data.\nextern void defrClearSession();\n\n// The main reader function.\n// The file should already be opened.  This requirement allows\n// the reader to be used with stdin or a pipe.  The file name\n// is only used for error messages.\nextern int defrRead (FILE *file,\n                    const char *fileName,\n                    defiUserData userData,\n                    int case_sensitive);\n\n// Set/get the client-provided user data.  defi doesn't look at\n// this data at all, it simply passes the opaque defiUserData pointer\n// back to the application with each callback.  The client can\n// change the data at any time, and it will take effect on the\n// next callback.  The defi reader and writer maintain separate\n// user data pointers.\nextern void defrSetUserData (defiUserData);\nextern defiUserData defrGetUserData ();\n\n \n// Functions to call to register a callback function or get the function\n//pointer after it has been registered.\n//\n\n// Register one function for all callbacks with the same signature \nextern void defrSetArrayNameCbk (defrStringCbkFnType);\nextern void defrSetAssertionCbk (defrAssertionCbkFnType);\nextern void defrSetAssertionsStartCbk (defrIntegerCbkFnType);\nextern void defrSetAssertionsEndCbk (defrVoidCbkFnType);\nextern void defrSetBlockageCbk (defrBlockageCbkFnType);\nextern void defrSetBlockageStartCbk (defrIntegerCbkFnType);\nextern void defrSetBlockageEndCbk (defrVoidCbkFnType);\nextern void defrSetBusBitCbk (defrStringCbkFnType);\nextern void defrSetCannotOccupyCbk (defrSiteCbkFnType);\nextern void defrSetCanplaceCbk (defrSiteCbkFnType);\nextern void defrSetCaseSensitiveCbk (defrIntegerCbkFnType);\nextern void defrSetComponentCbk (defrComponentCbkFnType);\nextern void defrSetComponentExtCbk (defrStringCbkFnType);\nextern void defrSetComponentStartCbk (defrIntegerCbkFnType);\nextern void defrSetComponentEndCbk (defrVoidCbkFnType);\nextern void defrSetConstraintCbk (defrAssertionCbkFnType);\nextern void defrSetConstraintsStartCbk (defrIntegerCbkFnType);\nextern void defrSetConstraintsEndCbk (defrVoidCbkFnType);\nextern void defrSetDefaultCapCbk (defrIntegerCbkFnType);\nextern void defrSetDesignCbk (defrStringCbkFnType);\nextern void defrSetDesignEndCbk (defrVoidCbkFnType);\nextern void defrSetDieAreaCbk (defrBoxCbkFnType);\nextern void defrSetDividerCbk (defrStringCbkFnType);\nextern void defrSetExtensionCbk (defrStringCbkFnType);\nextern void defrSetFillCbk (defrFillCbkFnType);\nextern void defrSetFillStartCbk (defrIntegerCbkFnType);\nextern void defrSetFillEndCbk (defrVoidCbkFnType);\nextern void defrSetFPCCbk (defrFPCCbkFnType);\nextern void defrSetFPCStartCbk (defrIntegerCbkFnType);\nextern void defrSetFPCEndCbk (defrVoidCbkFnType);\nextern void defrSetFloorPlanNameCbk (defrStringCbkFnType);\nextern void defrSetGcellGridCbk (defrGcellGridCbkFnType);\nextern void defrSetGroupNameCbk (defrStringCbkFnType);\nextern void defrSetGroupMemberCbk (defrStringCbkFnType);\nextern void defrSetComponentMaskShiftLayerCbk (defrComponentMaskShiftLayerCbkFnType);\nextern void defrSetGroupCbk (defrGroupCbkFnType);\nextern void defrSetGroupExtCbk (defrStringCbkFnType);\nextern void defrSetGroupsStartCbk (defrIntegerCbkFnType);\nextern void defrSetGroupsEndCbk (defrVoidCbkFnType);\nextern void defrSetHistoryCbk (defrStringCbkFnType);\nextern void defrSetIOTimingCbk (defrIOTimingCbkFnType);\nextern void defrSetIOTimingsStartCbk (defrIntegerCbkFnType);\nextern void defrSetIOTimingsEndCbk (defrVoidCbkFnType);\nextern void defrSetIoTimingsExtCbk (defrStringCbkFnType);\nextern void defrSetNetCbk (defrNetCbkFnType);\nextern void defrSetNetNameCbk (defrStringCbkFnType);\nextern void defrSetNetNonDefaultRuleCbk (defrStringCbkFnType);\nextern void defrSetNetConnectionExtCbk (defrStringCbkFnType);\nextern void defrSetNetExtCbk (defrStringCbkFnType);\nextern void defrSetNetPartialPathCbk (defrNetCbkFnType);\nextern void defrSetNetSubnetNameCbk (defrStringCbkFnType);\nextern void defrSetNetStartCbk (defrIntegerCbkFnType);\nextern void defrSetNetEndCbk (defrVoidCbkFnType);\nextern void defrSetNonDefaultCbk (defrNonDefaultCbkFnType);\nextern void defrSetNonDefaultStartCbk (defrIntegerCbkFnType);\nextern void defrSetNonDefaultEndCbk (defrVoidCbkFnType);\nextern void defrSetPartitionCbk (defrPartitionCbkFnType);\nextern void defrSetPartitionsExtCbk (defrStringCbkFnType);\nextern void defrSetPartitionsStartCbk (defrIntegerCbkFnType);\nextern void defrSetPartitionsEndCbk (defrVoidCbkFnType);\nextern void defrSetPathCbk (defrPathCbkFnType);\nextern void defrSetPinCapCbk (defrPinCapCbkFnType);\nextern void defrSetPinCbk (defrPinCbkFnType);\nextern void defrSetPinExtCbk (defrStringCbkFnType);\nextern void defrSetPinPropCbk (defrPinPropCbkFnType);\nextern void defrSetPinPropStartCbk (defrIntegerCbkFnType);\nextern void defrSetPinPropEndCbk (defrVoidCbkFnType);\nextern void defrSetPropCbk (defrPropCbkFnType);\nextern void defrSetPropDefEndCbk (defrVoidCbkFnType);\nextern void defrSetPropDefStartCbk (defrVoidCbkFnType);\nextern void defrSetRegionCbk (defrRegionCbkFnType);\nextern void defrSetRegionStartCbk (defrIntegerCbkFnType);\nextern void defrSetRegionEndCbk (defrVoidCbkFnType);\nextern void defrSetRowCbk (defrRowCbkFnType);\nextern void defrSetSNetCbk (defrNetCbkFnType);\nextern void defrSetSNetStartCbk (defrIntegerCbkFnType);\nextern void defrSetSNetEndCbk (defrVoidCbkFnType);\nextern void defrSetSNetPartialPathCbk (defrNetCbkFnType);\nextern void defrSetSNetWireCbk (defrNetCbkFnType);\nextern void defrSetScanChainExtCbk (defrStringCbkFnType);\nextern void defrSetScanchainCbk (defrScanchainCbkFnType);\nextern void defrSetScanchainsStartCbk (defrIntegerCbkFnType);\nextern void defrSetScanchainsEndCbk (defrVoidCbkFnType);\nextern void defrSetSiteCbk (defrSiteCbkFnType);\nextern void defrSetSlotCbk (defrSlotCbkFnType);\nextern void defrSetSlotStartCbk (defrIntegerCbkFnType);\nextern void defrSetSlotEndCbk (defrVoidCbkFnType);\nextern void defrSetStartPinsCbk (defrIntegerCbkFnType);\nextern void defrSetStylesCbk (defrStylesCbkFnType);\nextern void defrSetStylesStartCbk (defrIntegerCbkFnType);\nextern void defrSetStylesEndCbk (defrVoidCbkFnType);\nextern void defrSetPinEndCbk (defrVoidCbkFnType);\nextern void defrSetTechnologyCbk (defrStringCbkFnType);\nextern void defrSetTimingDisableCbk (defrTimingDisableCbkFnType);\nextern void defrSetTimingDisablesStartCbk (defrIntegerCbkFnType);\nextern void defrSetTimingDisablesEndCbk (defrVoidCbkFnType);\nextern void defrSetTrackCbk (defrTrackCbkFnType);\nextern void defrSetUnitsCbk (defrDoubleCbkFnType);\nextern void defrSetVersionCbk (defrDoubleCbkFnType);\nextern void defrSetVersionStrCbk (defrStringCbkFnType);\nextern void defrSetViaCbk (defrViaCbkFnType);\nextern void defrSetViaExtCbk (defrStringCbkFnType);\nextern void defrSetViaStartCbk (defrIntegerCbkFnType);\nextern void defrSetViaEndCbk (defrVoidCbkFnType);\n\n// NEW CALLBACK - For each new callback you create, you must\n// create a routine that allows the user to set it.  Add the\n// setting routines here. \n\n//Set all of the callbacks that have not yet been set to the following\n//function.  This is especially useful if you want to check to see\n//if you forgot anything.\nextern void defrUnsetCallbacks ();\n\n// Functions to call to unregister a callback function.\nextern void defrUnsetArrayNameCbk ();\nextern void defrUnsetAssertionCbk ();\nextern void defrUnsetAssertionsStartCbk ();\nextern void defrUnsetAssertionsEndCbk ();\nextern void defrUnsetBlockageCbk ();\nextern void defrUnsetBlockageStartCbk ();\nextern void defrUnsetBlockageEndCbk ();\nextern void defrUnsetBusBitCbk ();\nextern void defrUnsetCannotOccupyCbk ();\nextern void defrUnsetCanplaceCbk ();\nextern void defrUnsetCaseSensitiveCbk ();\nextern void defrUnsetComponentCbk ();\nextern void defrUnsetComponentExtCbk ();\nextern void defrUnsetComponentStartCbk ();\nextern void defrUnsetComponentEndCbk ();\nextern void defrUnsetConstraintCbk ();\nextern void defrUnsetConstraintsStartCbk ();\nextern void defrUnsetConstraintsEndCbk ();\nextern void defrUnsetDefaultCapCbk ();\nextern void defrUnsetDesignCbk ();\nextern void defrUnsetDesignEndCbk ();\nextern void defrUnsetDieAreaCbk ();\nextern void defrUnsetDividerCbk ();\nextern void defrUnsetExtensionCbk ();\nextern void defrUnsetFillCbk ();\nextern void defrUnsetFillStartCbk ();\nextern void defrUnsetFillEndCbk ();\nextern void defrUnsetFPCCbk ();\nextern void defrUnsetFPCStartCbk ();\nextern void defrUnsetFPCEndCbk ();\nextern void defrUnsetFloorPlanNameCbk ();\nextern void defrUnsetGcellGridCbk ();\nextern void defrUnsetGroupCbk ();\nextern void defrUnsetGroupExtCbk ();\nextern void defrUnsetGroupMemberCbk ();\nextern void defrUnsetComponentMaskShiftLayerCbk ();\nextern void defrUnsetGroupNameCbk ();\nextern void defrUnsetGroupsStartCbk ();\nextern void defrUnsetGroupsEndCbk ();\nextern void defrUnsetHistoryCbk ();\nextern void defrUnsetIOTimingCbk ();\nextern void defrUnsetIOTimingsStartCbk ();\nextern void defrUnsetIOTimingsEndCbk ();\nextern void defrUnsetIOTimingsExtCbk ();\nextern void defrUnsetNetCbk ();\nextern void defrUnsetNetNameCbk ();\nextern void defrUnsetNetNonDefaultRuleCbk ();\nextern void defrUnsetNetConnectionExtCbk ();\nextern void defrUnsetNetExtCbk ();\nextern void defrUnsetNetPartialPathCbk ();\nextern void defrUnsetNetSubnetNameCbk ();\nextern void defrUnsetNetStartCbk ();\nextern void defrUnsetNetEndCbk ();\nextern void defrUnsetNonDefaultCbk ();\nextern void defrUnsetNonDefaultStartCbk ();\nextern void defrUnsetNonDefaultEndCbk ();\nextern void defrUnsetPartitionCbk ();\nextern void defrUnsetPartitionsExtCbk ();\nextern void defrUnsetPartitionsStartCbk ();\nextern void defrUnsetPartitionsEndCbk ();\nextern void defrUnsetPathCbk ();\nextern void defrUnsetPinCapCbk ();\nextern void defrUnsetPinCbk ();\nextern void defrUnsetPinEndCbk ();\nextern void defrUnsetPinExtCbk ();\nextern void defrUnsetPinPropCbk ();\nextern void defrUnsetPinPropStartCbk ();\nextern void defrUnsetPinPropEndCbk ();\nextern void defrUnsetPropCbk ();\nextern void defrUnsetPropDefEndCbk ();\nextern void defrUnsetPropDefStartCbk ();\nextern void defrUnsetRegionCbk ();\nextern void defrUnsetRegionStartCbk ();\nextern void defrUnsetRegionEndCbk ();\nextern void defrUnsetRowCbk ();\nextern void defrUnsetScanChainExtCbk ();\nextern void defrUnsetScanchainCbk ();\nextern void defrUnsetScanchainsStartCbk ();\nextern void defrUnsetScanchainsEndCbk ();\nextern void defrUnsetSiteCbk ();\nextern void defrUnsetSlotCbk ();\nextern void defrUnsetSlotStartCbk ();\nextern void defrUnsetSlotEndCbk ();\nextern void defrUnsetSNetWireCbk ();\nextern void defrUnsetSNetCbk ();\nextern void defrUnsetSNetStartCbk ();\nextern void defrUnsetSNetEndCbk ();\nextern void defrUnsetSNetPartialPathCbk ();\nextern void defrUnsetStartPinsCbk ();\nextern void defrUnsetStylesCbk ();\nextern void defrUnsetStylesStartCbk ();\nextern void defrUnsetStylesEndCbk ();\nextern void defrUnsetTechnologyCbk ();\nextern void defrUnsetTimingDisableCbk ();\nextern void defrUnsetTimingDisablesStartCbk ();\nextern void defrUnsetTimingDisablesEndCbk ();\nextern void defrUnsetTrackCbk ();\nextern void defrUnsetUnitsCbk ();\nextern void defrUnsetVersionCbk ();\nextern void defrUnsetVersionStrCbk ();\nextern void defrUnsetViaCbk ();\nextern void defrUnsetViaExtCbk ();\nextern void defrUnsetViaStartCbk ();\nextern void defrUnsetViaEndCbk ();\n\n// Routine to set all unused callbacks. This is useful for checking\n//to see if you missed something. \nextern void defrSetUnusedCallbacks (defrVoidCbkFnType func);\n\n// Return the current line number in the input file. \nextern int defrLineNumber ();\nextern long long defrLongLineNumber ();\n\n// Routine to set the message logging routine for errors \n#ifndef DEFI_LOG_FUNCTION\n    typedef void (*DEFI_LOG_FUNCTION) (const char*);\n#endif\nextern void defrSetLogFunction(DEFI_LOG_FUNCTION);\n\n// Routine to set the message logging routine for warnings \n#ifndef DEFI_WARNING_LOG_FUNCTION\n    typedef void (*DEFI_WARNING_LOG_FUNCTION) (const char*);\n#endif\nextern void defrSetWarningLogFunction(DEFI_WARNING_LOG_FUNCTION);\n\n// Routine to set the message logging routine for errors \n// Used in re-enterable environment.\n#ifndef DEFI_LOG_FUNCTION\n    typedef void (*DEFI_CONTEXT_LOG_FUNCTION) (defiUserData userData, const char*);\n#endif\nextern void defrSetContextLogFunction(DEFI_CONTEXT_LOG_FUNCTION);\n\n// Routine to set the message logging routine for warnings \n// Used in re-enterable environment.\n#ifndef DEFI_WARNING_LOG_FUNCTION\n    typedef void (*DEFI_CONTEXT_WARNING_LOG_FUNCTION) (defiUserData userData, const char*);\n#endif\nextern void defrSetContextWarningLogFunction(DEFI_CONTEXT_WARNING_LOG_FUNCTION);\n\n// Routine to set the user defined malloc routine \ntypedef void* (*DEFI_MALLOC_FUNCTION) (size_t);\nextern void defrSetMallocFunction(DEFI_MALLOC_FUNCTION);\n\n// Routine to set the user defined realloc routine \ntypedef void* (*DEFI_REALLOC_FUNCTION) (void*, size_t);\nextern void defrSetReallocFunction(DEFI_REALLOC_FUNCTION);\n\n// Routine to set the user defined free routine \ntypedef void (*DEFI_FREE_FUNCTION) (void *);\nextern void defrSetFreeFunction(DEFI_FREE_FUNCTION);\n\n// Routine to set the line number of the file that is parsing routine (takes int)\ntypedef void (*DEFI_LINE_NUMBER_FUNCTION)  (int);\nextern void defrSetLineNumberFunction(DEFI_LINE_NUMBER_FUNCTION);\n\n// Routine to set the line number of the file that is parsing routine (takes long long)\ntypedef void (*DEFI_LONG_LINE_NUMBER_FUNCTION)  (long long);\nextern void defrSetLongLineNumberFunction(DEFI_LONG_LINE_NUMBER_FUNCTION);\n\n// Routine to set the line number of the file that is parsing routine (takes int)\n// Used in re-enterable environment.\ntypedef void (*DEFI_CONTEXT_LINE_NUMBER_FUNCTION)  (defiUserData userData, int);\nextern void defrSetContextLineNumberFunction(DEFI_CONTEXT_LINE_NUMBER_FUNCTION);\n\n// Routine to set the line number of the file that is parsing routine (takes long long\n// Used in re-enterable environment.\ntypedef void (*DEFI_CONTEXT_LONG_LINE_NUMBER_FUNCTION)  (defiUserData userData, long long);\nextern void defrSetContextLongLineNumberFunction(DEFI_CONTEXT_LONG_LINE_NUMBER_FUNCTION);\n\n// Set the number of lines before calling the line function callback routine \n// Default is 10000 \nextern void defrSetDeltaNumberLines  (int);\n\n// Routine to set the read function \ntypedef size_t (*DEFI_READ_FUNCTION)  (FILE*, char*, size_t);\nextern void defrSetReadFunction(DEFI_READ_FUNCTION);\nextern void defrUnsetReadFunction ();\n\n// Routine to set the defrWarning.log to open as append instead for write \n// New in 5.7 \nextern void defrSetOpenLogFileAppend ();\nextern void defrUnsetOpenLogFileAppend ();\n\n// Routine to set the magic comment found routine \ntypedef void (*DEFI_MAGIC_COMMENT_FOUND_FUNCTION) ();\nextern void defrSetMagicCommentFoundFunction(DEFI_MAGIC_COMMENT_FOUND_FUNCTION);\n\n// Routine to set the magic comment string \nextern void defrSetMagicCommentString(char *);\n\n// Routine to disable string property value process, default it will process \n// the value string \nextern void defrDisablePropStrProcess ();\n\n// Testing purposes only \nextern void defrSetNLines(long long n);\n\n// Routine to set the max number of warnings for a perticular section \n\nextern void defrSetAssertionWarnings(int warn);\nextern void defrSetBlockageWarnings(int warn);\nextern void defrSetCaseSensitiveWarnings(int warn);\nextern void defrSetComponentWarnings(int warn);\nextern void defrSetConstraintWarnings(int warn);\nextern void defrSetDefaultCapWarnings(int warn);\nextern void defrSetGcellGridWarnings(int warn);\nextern void defrSetIOTimingWarnings(int warn);\nextern void defrSetNetWarnings(int warn);\nextern void defrSetNonDefaultWarnings(int warn);\nextern void defrSetPinExtWarnings(int warn);\nextern void defrSetPinWarnings(int warn);\nextern void defrSetRegionWarnings(int warn);\nextern void defrSetRowWarnings(int warn);\nextern void defrSetScanchainWarnings(int warn);\nextern void defrSetSNetWarnings(int warn);\nextern void defrSetStylesWarnings(int warn);\nextern void defrSetTrackWarnings(int warn);\nextern void defrSetUnitsWarnings(int warn);\nextern void defrSetVersionWarnings(int warn);\nextern void defrSetViaWarnings(int warn);\n\n// Handling output messages \nextern void defrDisableParserMsgs(int nMsg, int* msgs);\nextern void defrEnableParserMsgs(int nMsg, int* msgs);\nextern void defrEnableAllMsgs();\nextern void defrSetTotalMsgLimit(int totNumMsgs);\nextern void defrSetLimitPerMsg(int msgId, int numMsg);\n\n// Return codes for the user callbacks.\n//The user should return one of these values. \n#define PARSE_OK 0      // continue parsing \n#define STOP_PARSE 1    // stop parsing with no error message \n#define PARSE_ERROR 2   // stop parsing, print an error message \n\n// Add this alias to the list for the parser     \nextern void defrAddAlias (const char* key, \n                          const char* value,\n                          int marked);\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defrSettings.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013-2014, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: arakhman $\n//  $Revision: #6 $\n//  $Date: 2013/08/09 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef defrSettings_h\n#define defrSettings_h\n\n#include \"defrReader.hpp\"\n\n#include <cstring>\n#include <string>\n#include <map>\n\n#define DEF_DEBUG_IDS 100\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nstruct defCompareCStrings \n{\n    bool operator()(const char* lhs, const char* rhs) const {\n        return std::strcmp(lhs, rhs) < 0;\n    }\n};\n\ntypedef std::map<const char*, int, defCompareCStrings>  defKeywordMap;\n\nclass defrSettings {\npublic:\n    defrSettings();\n\n    void init_symbol_table();\n\n    defKeywordMap Keyword_set; \n\n    int defiDeltaNumberLines;\n\n    ////////////////////////////////////\n    //\n    //       Flags to control number of warnings to print out, max will be 999\n    //\n    ////////////////////////////////////\n\n    int AssertionWarnings;\n    int BlockageWarnings;\n    int CaseSensitiveWarnings;\n    int ComponentWarnings;\n    int ConstraintWarnings;\n    int DefaultCapWarnings;\n    int FillWarnings;\n    int GcellGridWarnings;\n    int IOTimingWarnings;\n    int LogFileAppend; \n    int NetWarnings;\n    int NonDefaultWarnings;\n    int PinExtWarnings;\n    int PinWarnings;\n    int RegionWarnings;\n    int RowWarnings;\n    int TrackWarnings;\n    int ScanchainWarnings;\n    int SNetWarnings;\n    int StylesWarnings;\n    int UnitsWarnings;\n    int VersionWarnings;\n    int ViaWarnings;\n\n    int  nDDMsgs; \n    int* disableDMsgs;\n    int  totalDefMsgLimit; // to save the user set total msg limit to output\n    int AddPathToNet;\n    int AllowComponentNets;\n    char CommentChar;\n    int DisPropStrProcess; \n\n    int reader_case_sensitive_set;\n\n    DEFI_READ_FUNCTION ReadFunction;\n    DEFI_LOG_FUNCTION ErrorLogFunction;\n    DEFI_WARNING_LOG_FUNCTION WarningLogFunction;\n    DEFI_CONTEXT_LOG_FUNCTION ContextErrorLogFunction;\n    DEFI_CONTEXT_WARNING_LOG_FUNCTION ContextWarningLogFunction;\n    DEFI_MAGIC_COMMENT_FOUND_FUNCTION MagicCommentFoundFunction;\n    DEFI_MALLOC_FUNCTION MallocFunction;\n    DEFI_REALLOC_FUNCTION ReallocFunction;\n    DEFI_FREE_FUNCTION FreeFunction;\n    DEFI_LINE_NUMBER_FUNCTION LineNumberFunction;\n    DEFI_LONG_LINE_NUMBER_FUNCTION LongLineNumberFunction;\n    DEFI_CONTEXT_LINE_NUMBER_FUNCTION ContextLineNumberFunction;\n    DEFI_CONTEXT_LONG_LINE_NUMBER_FUNCTION ContextLongLineNumberFunction;\n\n    int UnusedCallbacks[CBMAX];\n    int MsgLimit[DEF_MSGS];\n};\n\n\nclass defrSession {\npublic:\n    defrSession();\n\n    char*           FileName;\n    int             reader_case_sensitive;\n    defiUserData    UserData;\n\n    defiPropType    CompProp;\n    defiPropType    CompPinProp;\n    defiPropType    DesignProp;\n    defiPropType    GroupProp;\n    defiPropType    NDefProp;\n    defiPropType    NetProp;\n    defiPropType    RegionProp;\n    defiPropType    RowProp;\n    defiPropType    SNetProp;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defwWriter.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef DEFW_WRITER_H\n#define DEFW_WRITER_H\n\n#include <stdarg.h>\n#include <stdio.h>\n\n#include \"defiKRDefs.hpp\"\n#include \"defiDefs.hpp\"\n#include \"defiUser.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n/* Return codes for writing functions: */\n#define DEFW_OK                0\n#define DEFW_UNINITIALIZED     1\n#define DEFW_BAD_ORDER         2\n#define DEFW_BAD_DATA          3\n#define DEFW_ALREADY_DEFINED   4\n#define DEFW_WRONG_VERSION     5\n#define DEFW_OBSOLETE          6\n#define DEFW_TOO_MANY_STMS     7  // the number defined at the beginning of the\n                                  // section is smaller than the actual number\n                                  // of statements defined in that section \n\n/* orient\n   0 = N\n   1 = W\n   2 = S\n   3 = E\n   4 = FN\n   5 = FW\n   6 = FS\n   7 = FE\n*/\n\n/* This routine will write a new line */\nextern int defwNewLine();\n\n/* The DEF writer initialization.  Must be called first.\n * Either this routine or defwInitCbk should be call only.\n * Can't call both routines in one program.\n * This routine is for user who does not want to use the callback machanism.\n * Returns 0 if successful. */\nextern int defwInit ( FILE* f, int vers1, int version2,\n\t      const char* caseSensitive,  /* NAMESCASESENSITIVE */\n\t      const char* dividerChar,    /* DIVIDERCHAR */\n\t      const char* busBitChars,    /* BUSBITCHARS */\n\t      const char* designName,     /* DESIGN */\n\t      const char* technology,     /* optional(NULL) - TECHNOLOGY */\n\t      const char* array,          /* optional(NULL) - ARRAYNAME */\n\t      const char* floorplan,      /* optional(NULL) - FLOORPLAN */\n\t      double units );             /* optional  (set to -1 to ignore) */\n\n/* The DEF writer initialization.  Must be called first.\n * Either this routine or defwInit should be call only.\n * Can't call both routines in one program.\n * This routine is for user who choose to use the callback machanism.\n * If user uses the callback for the writer, they need to provide\n * callbacks for Version, NamesCaseSensitive, BusBitChars and DividerChar.\n * These sections are required by the def.  If any of these callbacks\n * are missing, defaults will be used.\n * Returns 0 if successful. */\nextern int defwInitCbk (FILE* f);\n\n/* This routine must be called after the defwInit.\n * This routine is required.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwVersion (int vers1, int vers2);\n\n/* This routine must be called after the defwInit.\n * This routine is required.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwCaseSensitive ( const char* caseSensitive );\n\n/* This routine must be called after the defwInit.\n * This routine is required.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwBusBitChars ( const char* busBitChars );\n\n/* This routine must be called after the defwInit.\n * This routine is required.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwDividerChar ( const char* dividerChar );\n\n/* This routine must be called after the defwInit.\n * This routine is required.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwDesignName ( const char* name );\n\n/* This routine must be called after the defwInit.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwTechnology ( const char* technology );\n\n/* This routine must be called after the defwInit.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwArray ( const char* array );\n\n/* This routine must be called after the defwInit.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwFloorplan ( const char* floorplan );\n\n/* This routine must be called after the defwInit.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwUnits ( int units );\n\n/* This routine must be called after the defwInit.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called 0 to many times. */\nextern int defwHistory ( const char* string );\n\n/* This routine must be called after the history routines (if any).\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwStartPropDef ( void );\n\n/* This routine must be called after defwStartPropDef.\n * This routine can be called multiple times.\n * It adds integer property definition to the statement.\n * Returns 0 if successfull.\n * The objType can be LIBRARY or VIA or MACRO or PIN. */\nextern int defwIntPropDef(\n               const char* objType,   // LIBRARY | LAYER | VIA | VIARULE |\n                                      // NONDEFAULTRULE | MACRO | PIN \n               const char* propName,\n               double leftRange,      /* optional(0) - RANGE */\n               double rightRange,     /* optional(0) */\n               int    propValue);     /* optional(NULL) */\n \n/* This routine must be called after defwStartPropDef.\n * This routine can be called multiple times.\n * It adds real property definition to the statement.\n * Returns 0 if successfull.\n * The objType can be LIBRARY or VIA or MACRO or PIN. */\nextern int defwRealPropDef(\n               const char* objType,   // LIBRARY | LAYER | VIA | VIARULE |\n                                      // NONDEFAULTRULE | MACRO | PIN \n               const char* propName,\n               double leftRange,      /* optional(0) - RANGE */\n               double rightRange,     /* optional(0) */\n               double propValue);     /* optional(NULL) */\n \n/* This routine must be called after defwStartPropDef.\n * This routine can be called multiple times.\n * It adds string property definition to the statement.\n * Returns 0 if successfull.\n * The objType can be LIBRARY or VIA or MACRO or PIN. */\nextern int defwStringPropDef(\n               const char* objType,    // LIBRARY | LAYER | VIA | VIARULE |\n                                       // NONDEFAULTRULE | MACRO | PIN\n               const char* propName,\n               double leftRange,       /* optional(0) - RANGE */\n               double rightRange,      /* optional(0) */\n               const char* propValue); /* optional(NULL) */\n\n/* This routine must be called after all the properties have been\n * added to the file.\n * If you called defwPropertyDefinitions then this routine is NOT optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwEndPropDef ( void );\n\n/* This routine can be called after defwRow, defwRegion, defwComponent,\n * defwPin, defwSpecialNet, defwNet, and defwGroup\n * This routine is optional, it adds string property to the statement.\n * Returns 0 if successful.\n * This routine can be called 0 to many times */\nextern int defwStringProperty(const char* propName, const char* propValue);\n\n/* This routine can be called after defwRow, defwRegion, defwComponent,\n * defwPin, defwSpecialNet, defwNet, and defwGroup\n * This routine is optional, it adds real property to the statement.\n * Returns 0 if successful.\n * This routine can be called 0 to many times */\nextern int defwRealProperty(const char* propName, double propValue);\n\n/* This routine can be called after defwRow, defwRegion, defwComponent,\n * defwPin, defwSpecialNet, defwNet, and defwGroup\n * This routine is optional, it adds int property to the statement.\n * Returns 0 if successful.\n * This routine can be called 0 to many times */\nextern int defwIntProperty(const char* propName, int propValue);\n\n/* This routine must be called after the property definitions (if any).\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwDieArea ( int xl,            /* point1 - x */\n                         int yl,            /* point1 - y */\n                         int xh,            /* point2 - x */\n                         int yh );          /* point2 - y */\n\n/* This routine must be called after the property definitions (if any).\n * This routine is optional.\n * This routine is the same as defwDieArea, but accept more than 2 points\n * This is a 5.6 syntax\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwDieAreaList ( int num_points, /* number of points on list */\n                             int* xl,        /* all the x points */\n                             int* yh);       /* all the y points */\n\n/* This routine must be called after the Die Area (if any).\n * This routine is optional.\n * Returns 0 if successful.\n * The integer \"orient\" and operation of the do is explained in\n * the documentation.\n * In 5.6, the DO syntax is optional and the STEP syntax is optional in DO */\nextern int defwRow ( const char* rowName, const char* rowType,\n\t\t     int x_orig, int y_orig, int orient,\n\t\t     int do_count,            /* optional (0) */\n                     int do_increment,        /* optional (0) */\n                     int xstep,               /* optional (0) */\n                     int ystep);              /* optional (0) */\n\n/* This routine must be called after the Die Area (if any).\n * This routine is optional.\n * Returns 0 if successful.\n * This routine is the same as defwRow, excpet orient is a char* */\nextern int defwRowStr ( const char* rowName, const char* rowType,\n\t\t        int x_orig, int y_orig, const char* orient,\n\t\t        int do_count,         /* optional (0) */\n                        int do_increment,     /* optional (0) */\n                        int xstep,            /* optional (0) */\n                        int ystep);           /* optional (0) */\n\n/* This routine must be called after the defwRow (if any).\n * This routine is optional.\n * Returns 0 if successful.\n * The operation of the do is explained in the documentation. */\nextern int defwTracks ( const char* master,   /* X | Y */\n                        int doStart,          /* start */\n\t                int doCount,          /* numTracks */\n                        int doStep,           /* space */\n                        int numLayers,        /* number of layers */\n                        const char** layers,  /* list of layers */\n\t\t\tint mask = 0,         /* optional */\n\t\t\tint sameMask = 0);    /* optional */\n\n/* This routine must be called after the defwTracks (if any).\n * This routine is optional.\n * Returns 0 if successful.\n * The operation of the do is explained in the documentation. */\nextern int defwGcellGrid ( const char* master, /* X | Y */\n                           int doStart,        /* start */\n\t                   int doCount,        /* numColumns | numRows */\n                           int doStep);        /* space */\n\n/* This routine must be called after the defwTracks (if any).\n * This section of routines is optional.\n * Returns 0 if successful.\n * The routine starts the default capacitance section.   All of the\n * capacitances must follow.\n * The count is the number of defwDefaultCap calls to follow.\n * The routine can be called only once.\n * This api is obsolete in 5.4. */\nextern int defwStartDefaultCap ( int count );\n\n/* This routine is called once for each default cap.  The calls must\n * be preceeded by a call to defwStartDefaultCap and must be\n * terminated by a call to defwEndDefaultCap.\n * Returns 0 if successful.\n * This api is obsolete in 5.4. */\nextern int defwDefaultCap ( int pins,           /* MINPINS */\n                            double cap);        /* WIRECAP */\n\n/* This routine must be called after the defwDefaultCap calls (if any).\n * Returns 0 if successful.\n * If the count in StartDefaultCap is not the same as the number of\n * calls to DefaultCap then DEFW_BAD_DATA will return returned.\n * The routine can be called only once.\n * This api is obsolete in 5.4. */\nextern int defwEndDefaultCap ( void );\n\n/* This routine must be called after the defwDefaultCap calls (if any).\n * The operation of the do is explained in the documentation.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called many times. */\nextern int defwCanPlace(const char* master,     /* sitename */\n                        int xOrig,\n                        int yOrig,\n\t                int orient,             /* 0 to 7 */\n                        int doCnt,              /* numX */\n                        int doInc,              /* numY */\n                        int xStep,              /* spaceX */\n                        int yStep);             /* spaceY */\n\n/* This routine must be called after the defwDefaultCap calls (if any).\n * The operation of the do is explained in the documentation.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called many times.\n * This routine is the same as defwCanPlace, except orient is a char* */\nextern int defwCanPlaceStr(const char* master,     /* sitename */\n                           int xOrig,\n                           int yOrig,\n\t                   const char* orient,     /* 0 to 7 */\n                           int doCnt,              /* numX */\n                           int doInc,              /* numY */\n                           int xStep,              /* spaceX */\n                           int yStep);             /* spaceY */\n\n/* This routine must be called after the defwCanPlace calls (if any).\n * The operation of the do is explained in the documentation.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called many times. */\nextern int defwCannotOccupy(const char* master,  /* sitename */\n                            int xOrig,\n                            int yOrig,\n\t                    int orient,          /* 0 to 7 */\n                            int doCnt,           /* numX */\n                            int doInc,           /* numY */\n                            int xStep,           /* spaceX */\n                            int yStep);          /* spaceY */\n\n/* This routine must be called after the defwCanPlace calls (if any).\n * The operation of the do is explained in the documentation.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called many times.\n * This routine is the same as defwCannotOccupy, except orient is a char* */\nextern int defwCannotOccupyStr(const char* master,  /* sitename */\n                               int xOrig,\n                               int yOrig,\n\t                       const char* orient,  /* 0 to 7 */\n                               int doCnt,           /* numX */\n                               int doInc,           /* numY */\n                               int xStep,           /* spaceX */\n                               int yStep);          /* spaceY */\n\n/* This routine must be called after defwCannotOccupy (if any).\n * This section of routines is optional.\n * Returns 0 if successful.\n * The routine starts the via section.   All of the vias must follow.\n * The count is the number of defwVia calls to follow.\n * The routine can be called only once. */\nextern int defwStartVias( int count );\n\n/* These routines enter each via into the file.\n * These routines must be called after the defwStartVias call.\n * defwViaName should be called first, follow either by defwViaPattern or\n * defwViaLayer.  At the end of each via, defwOneViaEnd should be called\n * These routines are for [- viaName [+ PATTERNNAME patternName + RECT layerName\n * pt pt]...;]...\n * Returns 0 if successful.\n * The routines can be called many times. */\nextern int defwViaName(const char* name);\n\nextern int defwViaPattern(const char* patternName);\n\n/* This routine can be called multiple times. */\n/* mask is 5.8 syntax */\nextern int defwViaRect(const char* layerName,\n                   int xl,         /* xl from the RECT */\n                   int yl,         /* yl from the RECT */\n                   int xh,         /* xh from the RECT */\n                   int yh,         /* yh from the RECT */\n\t\t   int mask = 0);  /* optional */\n\n/* This is a 5.6 syntax\n * This routine can be called multiple times. */\n/* mask is 5.8 syntax */\nextern int defwViaPolygon(const char* layerName,\n                          int num_polys, \n\t\t\t  double* xl, \n\t\t\t  double* yl, \n\t\t\t  int mask = 0);\n\n/* These routine must be called after defwViaName.\n * Either this routine or defwViaPattern can be called after each\n * defwViaName is called.\n * This is a 5.6 syntax\n * Returns 0 if successful\n * The routine can be called only once per defwViaName called. */\nextern int defwViaViarule(const char* viaRuleName,\n                          double xCutSize, double yCutSize,\n                          const char* botMetalLayer, const char* cutLayer,\n                          const char* topMetalLayer,\n                          double xCutSpacing, double yCutSpacing,\n                          double xBotEnc, double yBotEnc,\n                          double xTopEnc, double yTopEnc);\n\n/* This routine can call only after defwViaViarule.\n * It can only be called once.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwViaViaruleRowCol(int numCutRows, int numCutCols);\n\n/* This routine can call only after defwViaViarule.\n * It can only be called once.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwViaViaruleOrigin(int xOffset, int yOffset);\n\n/* This routine can call only after defwViaViarule.\n * It can only be called once.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwViaViaruleOffset(int xBotOffset, int yBotOffset,\n                                int xTopOffset, int yTopOffset);\n\n/* This routine can call only after defwViaViarule.\n * It can only be called once.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwViaViarulePattern(const char* cutPattern);\n\nextern int defwOneViaEnd();\n\n/* This routine must be called after the defwVia calls.\n * Returns 0 if successful.\n * If the count in StartVias is not the same as the number of\n * calls to Via or ViaPattern then DEFW_BAD_DATA will return returned.\n * The routine can be called only once. */\nextern int defwEndVias( void );\n\n/* This routine must be called after via section (if any).\n * This section of routines is optional.\n * Returns 0 if successful.\n * The routine starts the region section.   All of the regions must follow.\n * The count is the number of defwRegion calls to follow.\n * The routine can be called only once. */\nextern int defwStartRegions( int count );\n\n/* This routine enter each region into the file.\n * This routine must be called after the defwStartRegions call.\n * Returns 0 if successful.\n * The routine can be called many times. */\nextern int defwRegionName(const char* name);\n\n/* This routine enter the region point to the region name.\n * This routine must be called after the defwRegionName call.\n * Returns 0 if successful.\n * The routine can be called many times. */\nextern int defwRegionPoints(int xl, int yl, int xh, int yh);\n\n/* This routine enter the region type, FENCE | GUIDE.\n * This routine must be called after the defwRegionName call.\n * This is a 5.4.1 syntax.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwRegionType(const char* type);  /* FENCE | GUIDE */\n\n/* This routine must be called after the defwRegion calls.\n * Returns 0 if successful.\n * If the count in StartRegions is not the same as the number of\n * calls to Region or RegionPattern then DEFW_BAD_DATA will return returned.\n * The routine can be called only once. */\nextern int defwEndRegions( void );\n\n/* This is a 5.8 syntax.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwComponentMaskShiftLayers(const char** layerNames,\n\t                                int          numLayerName);\n\n/* This routine must be called after the regions section (if any).\n * This section of routines is NOT optional.\n * Returns 0 if successful.\n * The routine starts the components section. All of the components\n * must follow.\n * The count is the number of defwComponent calls to follow.\n * The routine can be called only once. */\nextern int defwStartComponents( int count );\n\n/* This routine enter each component into the file.\n * This routine must be called after the defwStartComponents call.\n * The optional fields will be ignored if they are set to zero\n * (except for weight which must be set to -1.0).\n * Returns 0 if successful.\n * The routine can be called many times. */\nextern int defwComponent(const char* instance,  /* compName */\n              const char* master,           /* modelName */\n              int   numNetName,             // optional(0) - # netNames defined\n                                            \n              const char** netNames,        /* optional(NULL) - list */\n              const char* eeq,              /* optional(NULL) - EEQMASTER */\n              const char* genName,          /* optional(NULL) - GENERATE */\n              const char* genParemeters,    /* optional(NULL) - parameters */\n              const char* source,           // optional(NULL) - NETLIST | DIST |\n                                            // USER | TIMING \n              int numForeign,               // optional(0) - # foreigns,\n                                            // foreignx, foreigny & orients\n              const char** foreigns,        /* optional(NULL) - list */\n              int* foreignX, int* foreignY, /* optional(0) - list foreign pts */\n              int* foreignOrients,          /* optional(-1) - 0 to 7 */\n              const char* status,           // optional(NULL) - FIXED | COVER |\n                                            //  PLACED | UNPLACED\n              int statusX, int statusY,     /* optional(0) - status pt */\n              int statusOrient,             /* optional(-1) - 0 to 7 */\n              double weight,                /* optional(0) */\n              const char* region,           // optional(NULL) - either xl, yl,\n                                            // xh, yh or region \n              int xl, int yl,               /* optional(0) - region pt1 */\n              int xh, int yh);              /* optional(0) - region pt2 */\n\n\n/* This routine enter each component into the file.\n * This routine must be called after the defwStartComponents call.\n * The optional fields will be ignored if they are set to zero\n * (except for weight which must be set to -1.0).\n * Returns 0 if successful.\n * The routine can be called many times. \n * This routine is the same as defwComponent, except orient is a char** */\nextern int defwComponentStr(const char* instance,  /* compName */\n              const char* master,           /* modelName */\n              int   numNetName,             // optional(0) - # netNames defined\n                                            //\n              const char** netNames,        /* optional(NULL) - list */\n              const char* eeq,              /* optional(NULL) - EEQMASTER */\n              const char* genName,          /* optional(NULL) - GENERATE */\n              const char* genParemeters,    /* optional(NULL) - parameters */\n              const char* source,           // optional(NULL) - NETLIST | DIST |\n                                            // USER | TIMING \n              int numForeign,               // optional(0) - # foreigns,\n                                            // foreignx, foreigny & orients\n              const char** foreigns,        /* optional(NULL) - list */\n              int* foreignX, int* foreignY, /* optional(0) - list foreign pts */\n              const char** foreignOrients,  /* optional(NULL) */\n              const char* status,           // optional(NULL) - FIXED | COVER |\n                                            // PLACED | UNPLACED \n              int statusX, int statusY,     /* optional(0) - status pt */\n              const char* statusOrient,     /* optional(NULL) */\n              double weight,                /* optional(0) */\n              const char* region,           // optional(NULL) - either xl, yl,\n                                            // xh, yh or region \n              int xl, int yl,               /* optional(0) - region pt1 */\n              int xh, int yh);              /* optional(0) - region pt2 */\n\n/* This is a 5.8 syntax.\n * Returns 0 if successful.\n * The routine can be called only once. */\nextern int defwComponentMaskShift(int shiftLayerMasks);\n\n/* This routine must be called after either the defwComponent or\n * defwComponentStr.\n * This routine can only called once per component.\n * Either this routine or defwComponentHaloSoft can be called, but not both\n * This routine is optional.\n * This is a 5.6 syntax.\n * Returns 0 if successful.  */\nextern int defwComponentHalo(int left, int bottom, int right, int top);\n \n/* This routine must be called after either the defwComponent or\n * defwComponentStr.\n * This routine can only called once per component.\n * This routine is just like defwComponentHalo, except it writes the option SOFT\n * Either this routine or defwComponentHalo can be called, but not both\n * This routine is optional.\n * This is a 5.7 syntax.\n * Returns 0 if successful.  */\nextern int defwComponentHaloSoft(int left, int bottom, int right, int top);\n \n/* This routine must be called after either the defwComponent or\n * defwComponentStr.\n * This routine can only called once per component.\n * This routine is optional.\n * This is a 5.7 syntax.\n * Returns 0 if successful.  */\nextern int defwComponentRouteHalo(int haloDist, const char* minLayer,\n                                  const char* maxLayer);\n \n/* This routine must be called after the defwComponent calls.\n * Returns 0 if successful.\n * If the count in StartComponents is not the same as the number of\n * calls to Component then DEFW_BAD_DATA will return returned.\n * The routine can be called only once. */\nextern int defwEndComponents( void );\n\n/* This routine must be called after the components section (if any).\n * This section of routines is optional.\n * Returns 0 if successful.\n * The routine starts the pins section. All of the pins must follow.\n * The count is the number of defwPin calls to follow.\n * The routine can be called only once. */\nextern int defwStartPins( int count );\n\n/* This routine enter each pin into the file.\n * This routine must be called after the defwStartPins call.\n * The optional fields will be ignored if they are set to zero.\n * Returns 0 if successful.\n * The routine can be called many times.\n * NOTE: Use defwPinLayer to write out layer with SPACING or DESIGNRULEWIDTH */\nextern int defwPin(const char* name,     /* pinName */\n              const char* net,           /* netName */\n              int special,               /* 0 - ignore, 1 - special */\n              const char* direction,     // optional(NULL) - INPUT | OUTPUT |\n                                         // INOUT | FEEDTHRU \n              const char* use,           // optional(NULL) - SIGNAL | POWER |\n                                         // GROUND | CLOCK | TIEOFF | ANALOG \n              const char* status,        // optional(NULL) - FIXED | PLACED |\n                                         // COVER \n              int statusX, int statusY,  /* optional(0) - status point */\n              int orient,                /* optional(-1) - status orient */\n              const char* layer,         /* optional(NULL) - layerName */\n              int xl, int yl,            /* optional(0) - layer point1 */\n              int xh, int yh);           /* optional(0) - layer point2 */\n\n/* This routine enter each pin into the file.\n * This routine must be called after the defwStartPins call.\n * The optional fields will be ignored if they are set to zero.\n * Returns 0 if successful.\n * The routine can be called many times.\n * This routine is the same as defwPin, except orient is a char*\n * NOTE: Use defwPinLayer to write out layer with SPACING or DESIGNRULEWIDTH */\nextern int defwPinStr(const char* name,     /* pinName */\n              const char* net,           /* netName */\n              int special,               /* 0 - ignore, 1 - special */\n              const char* direction,     // optional(NULL) - INPUT | OUTPUT |\n                                         // INOUT | FEEDTHRU \n              const char* use,           // optional(NULL) - SIGNAL | POWER |\n                                         // GROUND | CLOCK | TIEOFF | ANALOG \n              const char* status,        // optional(NULL) - FIXED | PLACED |\n                                         // COVER\n              int statusX, int statusY,  /* optional(0) - status point */\n              const char* orient,        /* optional(NULL) */\n              const char* layer,         /* optional(NULL) - layerName */\n              int xl, int yl,            /* optional(0) - layer point1 */\n              int xh, int yh);           /* optional(0) - layer point2 */\n\n/* This routine should be called if the layer has either SPACING or\n * DESIGNRULEWIDTH.  If this routine is used and the pin has only one\n * layer, the layer in defwPin or defwPinStr has to be null, otherwise\n * the layer will be written out twice.\n * This routine must be called after defwPin or defwPinStr.\n * This is a 5.6 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * This routine can be called multiple times within a pin. */\nextern int defwPinLayer(const char* layerName,\n              int spacing,         /* optional(0) - SPACING & DESIGNRULEWIDTH */\n              int designRuleWidth, /* are mutually exclusive */\n              int xl, int yl,\n              int xh, int yh,\n              int mask = 0);\n\n/* This routine must be called after defwPin or defwPinStr.\n * This routine is to write out layer with polygon.\n * This is a 5.6 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called multiple times within a pin. */\nextern int defwPinPolygon(const char* layerName,\n              int spacing,         /* optional(0) - SPACING & DESIGNRULEWIDTH */\n              int designRuleWidth, /* are mutually exclusive */\n              int num_polys, double* xl, double* yl,\n              int mask = 0);\n\n/* This routine must be called after defwPin or defwPinStr.\n * This routine is to write out layer with via.\n * This is a 5.7 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called multiple times within a pin. */\nextern int defwPinVia(const char* viaName, int xl, int yl, int mask = 0);\n\n/* This routine must be called after defwPin or defwPinStr.\n * This routine is to write out pin with port.\n * This is a 5.7 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called multiple times within a pin. */\nextern int defwPinPort();\n\n/* This routine is called after defwPinPort. \n * This is a 5.7 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * This routine can be called multiple times within a pin. */\nextern int defwPinPortLayer(const char* layerName,\n              int spacing,         /* optional(0) - SPACING & DESIGNRULEWIDTH */\n              int designRuleWidth, /* are mutually exclusive */\n              int xl, int yl,\n              int xh, int yh,\n              int mask = 0);\n\n/* This routine must be called after defwPinPort.\n * This is a 5.7 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called multiple times within a pin. */\nextern int defwPinPortPolygon(const char* layerName,\n              int spacing,         /* optional(0) - SPACING & DESIGNRULEWIDTH */\n              int designRuleWidth, /* are mutually exclusive */\n              int num_polys, double* xl, double* yl,\n              int mask = 0);\n\n/* This routine must be called after defwPinPort.\n * This is a 5.7 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called multiple times within a pin. */\nextern int defwPinPortVia(const char* viaName, int xl, int yl, int mask = 0);\n\n/* This routine must be called after defwPinPort.\n * This is a 5.7 syntax.\n * This routine is optional.\n * Returns 0 if successful.\n * The routine can be called many times.\n * NOTE: Use defwPinLayer to write out layer with SPACING or DESIGNRULEWIDTH */\nextern int defwPinPortLocation(\n              const char* status,        /* FIXED | PLACED | COVER */\n              int statusX, int statusY,  /* status point */\n              const char* orient);\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.6 syntax.\n * The routine can be called only once per pin. */\nextern int defwPinNetExpr(const char* pinExpr);\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.6 syntax.\n * The routine can be called only once per pin. */\nextern int defwPinSupplySensitivity(const char* pinName);\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.6 syntax.\n * The routine can be called only once per pin. */\nextern int defwPinGroundSensitivity(const char* pinName);\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinPartialMetalArea(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinPartialMetalSideArea(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinPartialCutArea(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinDiffArea(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.5 syntax.\n * The oxide can be either OXIDE1, OXIDE2, OXIDE3, or OXIDE4.\n * Each oxide value can be called only once after defwPin. */\nextern int defwPinAntennaModel(const char* oxide);\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinGateArea(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinMaxAreaCar(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinMaxSideAreaCar(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after defwPin.\n * Returns 0 if successful.\n * This is a 5.4 syntax.\n * The routine can be called multiple times. */\nextern int defwPinAntennaPinMaxCutCar(int value,\n              const char* layerName);    /* optional(NULL) */\n\n/* This routine must be called after the defwPin calls.\n * Returns 0 if successful.\n * If the count in StartPins is not the same as the number of\n * calls to Pin then DEFW_BAD_DATA will return returned.\n * The routine can be called only once. */\nextern int defwEndPins( void );\n\n/* This routine must be called after the pin section (if any).\n * This section of routines is optional.\n * Returns 0 if successful.\n * The routine starts the pinproperties section. All of the pinproperties\n * must follow.\n * The count is the number of defwPinProp calls to follow.\n * The routine can be called only once. */\nextern int defwStartPinProperties( int count );\n\n/* This routine enter each pinproperty into the file.\n * This routine must be called after the defwStartPinProperties call.\n * The optional fields will be ignored if they are set to zero.\n * Returns 0 if successful.\n * The routine can be called many times. */\nextern int defwPinProperty(const char* name,     /* compName | PIN */\n              const char* pinName);              /* pinName */\n\n/* This routine must be called after the defwPinProperty calls.\n * Returns 0 if successful.\n * If the count in StartPins is not the same as the number of\n * calls to Pin then DEFW_BAD_DATA will return returned.\n * The routine can be called only once. */\nextern int defwEndPinProperties( void );\n\n/* Routines to enter a special net or nets into the file.\n * You must first call defwStartSpecialNets with the number of\n * nets. This section is required, even if you do not have any nets.\n * For each net you should call defwSpecialNet followed by\n * one or more defwSpecialNetConnection calls.\n * After the connections come the options.  Options are\n * NOT required.\n * Each net is completed by calling defwSpecialNetEndOneNet().\n * The nets section is finished by calling defwEndNets(). */\nextern int defwStartSpecialNets(int count);\n\n/* This routine must be called after the defwStartSpecialNets it is for\n * - netName */\nextern int defwSpecialNet(const char* name);   /* netName */\n\n/* This routine is for compNameRegExpr, pinName, and SYNTHESIZED */\n/* It can be called multiple times */\nextern int defwSpecialNetConnection(const char* inst,    /* compNameRegExpr */\n                   const char* pin,       /* pinName */\n                   int synthesized);     /* 0 - ignore, 1 - SYNTHESIZED  */\n\n/* This routine is for + FIXEDBUMP\n * This is a 5.4.1 syntax */\nextern int defwSpecialNetFixedbump();\n\n/* This routine is for + VOLTAGE volts */\nextern int defwSpecialNetVoltage(double v);\n\n/* This routine is for + SPACING layerName spacing [RANGE minwidth maxwidth */\nextern int defwSpecialNetSpacing(const char* layer,  /* layerName */\n                    int spacing,          /* spacing */\n                    double minwidth,      /* optional(0) - minwidth */\n                    double maxwidth);     /* optional(0) - maxwidth */\n\n/* This routine is for + WIDTH layerName width */\nextern int defwSpecialNetWidth(const char* layer, /* layerName */\n                    int width);                   /* width */\n\n/* This routine is for + SOURCE {NETLIST | DIST | USER | TIMING} */\nextern int defwSpecialNetSource(const char* name);\n\n/* This routine is for + ORIGINAL netName */\nextern int defwSpecialNetOriginal(const char* name);   /* netName */\n\n/* This routine is for + PATTERN {STEINER | BALANCED | WIREDLOGIC | TRUNK} */\nextern int defwSpecialNetPattern(const char* name);\n\n/* This routine is for + USE {SIGNAL | POWER | GROUND | CLOCK | TIEOFF |\n   ANALOG | SCAN | RESET} */\nextern int defwSpecialNetUse(const char* name);\n\n/* This routine is for + WEIGHT weight */\nextern int defwSpecialNetWeight(double value);\n\n/* This routine is for + ESTCAP wireCapacitance */\nextern int defwSpecialNetEstCap(double value);\n\n/* Paths are a special type of option.  A path must begin\n * with a defwSpecialNetPathStart and end with a defwSpecialNetPathEnd().\n * The individual parts of the path can be entered in\n * any order. */\nextern int defwSpecialNetPathStart(const char* typ); // ROUTED | FIXED | COVER |\n                                                     // SHIELD | NEW \nextern int defwSpecialNetShieldNetName(const char* name); /* shieldNetName */\n\nextern int defwSpecialNetPathLayer(const char* name); /* layerName */\n\nextern int defwSpecialNetPathWidth(int width);\n\n/* This routine is optional.\n * This is a 5.6 syntax. */\nextern int defwSpecialNetPathStyle(int styleNum);\n\nextern int defwSpecialNetPathShape(const char* shapeType); // RING | STRIPE |\n        // FOLLOWPIN | IOWIRE | COREWIRE | BLOCKWIRE | FILLWIRE | BLOCKAGEWIRE \n\n\n/* This routine is optional.\n   This is a 5.8 syntax.\n * Returns 0 if successful. */\nextern int defwSpecialNetPathMask(int colorMask);\n\n/* x and y location of the path */\nextern int defwSpecialNetPathPoint(int numPts,  /* number of connected points */\n                   double* pointx,     /* point x list */\n                   double* pointy);    /* point y list */\nextern int defwSpecialNetPathVia(const char* name);   /* viaName */\n\n/* This routine is called after defwSpecialNetPath\n * This is a 5.4.1 syntax */\nextern int defwSpecialNetPathViaData(int numX, int numY, int stepX, int stepY);\n\n/* x and y location of the path */\nextern int defwSpecialNetPathPointWithWireExt(\n                   int numPts,                /* number of connected points */\n                   double* pointx,       /* point x list */\n                   double* pointy,       /* point y list */\n                   double* optValue);       /* optional(NULL) value */\n\nextern int defwSpecialNetPathEnd();\n\n/* This is a 5.6 syntax\n * This routine can be called multiple times. */\nextern int defwSpecialNetPolygon(const char* layerName,\n                                 int num_polys, double* xl, double* yl);\n\n/* This is a 5.6 syntax\n * This routine can be called multiple times. */\nextern int defwSpecialNetRect(const char* layerName,\n                              int xl, int yl, int xh, int yh);\n\nextern int defwSpecialNetVia(const char* layerName);\n\nextern int defwSpecialNetViaWithOrient(const char* layerName, int orient);\n\nextern int defwSpecialNetViaPoints(int num_points, double* xl, double* yl);\n\n/* This routine is called at the end of each net */\nextern int defwSpecialNetEndOneNet();\n\n/* 5.3 for special net */\n/* Shields are a special type of option.  A shield must begin\n * with a defwSpecialNetShieldStart and end with a defwSpecialNetShieldEnd().\n * The individual parts of the shield can be entered in\n * any order. */\nextern int defwSpecialNetShieldStart(const char* name);\n\nextern int defwSpecialNetShieldLayer(const char* name); /* layerName */\nextern int defwSpecialNetShieldWidth(int width);        /* width */\nextern int defwSpecialNetShieldShape(const char* shapeType); // RING | STRIPE |\n        // FOLLOWPIN | IOWIRE | COREWIRE | BLOCKWIRE | FILLWIRE | BLOCKAGEWIRE\n \n/* x and y location of the path */\nextern int defwSpecialNetShieldPoint(int numPts, /* # of connected points */\n                   double* pointx,     /* point x list */\n                   double* pointy);    /* point y list */\nextern int defwSpecialNetShieldVia(const char* name);   /* viaName */\n\n/* A 5.4.1 syntax */\nextern int defwSpecialNetShieldViaData(int numX, int numY, int stepX, int stepY);\nextern int defwSpecialNetShieldEnd();\n/* end 5.3 */\n \n/* This routine is called at the end of the special net section */\nextern int defwEndSpecialNets();\n\n/* Routines to enter a net or nets into the file.\n * You must first call defwNets with the number of nets.\n * This section is required, even if you do not have any nets.\n * For each net you should call defwNet followed by one or\n * more defwNetConnection calls.\n * After the connections come the options.  Options are\n * NOT required.\n * Each net is completed by calling defwNetEndOneNet().\n * The nets section is finished by calling defwEndNets(). */\nextern int defwStartNets(int count);\n\n/* This routine must be called after the defwStartNets, it is for - netName */\nextern int defwNet(const char* name);\n\n/* This routine is for { compName | PIN } pinName [+ SYNTHESIZED] */\n/* It can be called multiple times */\nextern int defwNetConnection(const char* inst,    /* compName */\n                   const char* pin,      /* pinName */\n                   int synthesized);    /* 0 - ignore, 1 - SYNTHESIZED */\n\n/* This routine is for MUSTJOIN, compName, pinName */\nextern int defwNetMustjoinConnection(const char* inst,  /* compName */\n                                     const char* pin);     /* pinName */\n\n/* This routine is for + VPIN vpinName [LAYER layerName pt pt\n * [{ PLACED | FIXED | COVER } pt orient] */\nextern int defwNetVpin(const char* vpinName,\n                 const char* layerName,     /* optional(NULL) */\n                 int layerXl, int layerYl,  /* layer point1 */\n                 int layerXh, int layerYh,  /* layer point2 */\n                 const char* status,        /* optional(NULL) */\n                 int statusX, int statusY,  /* optional(0) - status point */\n                 int orient);               /* optional(-1) */\n\n/* This routine is for + VPIN vpinName [LAYER layerName pt pt\n * [{ PLACED | FIXED | COVER } pt orient]\n * This routine is the same as defwNetVpin, except orient is a char* */\nextern int defwNetVpinStr(const char* vpinName,\n                 const char* layerName,     /* optional(NULL) */\n                 int layerXl, int layerYl,  /* layer point1 */\n                 int layerXh, int layerYh,  /* layer point2 */\n                 const char* status,        /* optional(NULL) */\n                 int statusX, int statusY,  /* optional(0) - status point */\n                 const char* orient);       /* optional(NULL) */\n\n/* This routine can be called either within net or subnet.\n * it is for NONDEFAULTRULE rulename */\nextern int defwNetNondefaultRule(const char* name);\n\n/* This routine is for + XTALK num */\nextern int defwNetXtalk(int xtalk);\n\n/* This routine is for + FIXEDBUMP\n * This is a 5.4.1 syntax */\nextern int defwNetFixedbump();\n\n/* This routine is for + FREQUENCY\n * This is a 5.4.1 syntax */\nextern int defwNetFrequency(double frequency);\n\n/* This routine is for + SOURCE {NETLIST | DIST | USER | TEST | TIMING} */\nextern int defwNetSource(const char* name);\n\n/* This routine is for + ORIGINAL netname */\nextern int defwNetOriginal(const char* name);\n\n/* This routine is for + USE {SIGNAL | POWER | GROUND | CLOCK | TIEOFF | \n * ANALOG} */\nextern int defwNetUse(const char* name);\n\n/* This routine is for + PATTERN {STEINER | BALANCED | WIREDLOGIC} */\nextern int defwNetPattern(const char* name);\n\n/* This routine is for + ESTCAP wireCapacitance */\nextern int defwNetEstCap(double value);\n\n/* This routine is for + WEIGHT weight */\nextern int defwNetWeight(double value);\n\n/* 5.3 for net */\n/* This routine is for + SHIELDNET weight */\nextern int defwNetShieldnet(const char* name);\n\n/* Noshield are a special type of option.  A noshield must begin\n * with a defwNetNoshieldStart and end with a defwNetNoshieldEnd().\n * The individual parts of the noshield can be entered in\n * any order. */\nextern int defwNetNoshieldStart(const char* name);\n\n/* x and y location of the path */\nextern int defwNetNoshieldPoint(int numPts, /* number of connected points */\n                   const char** pointx,     /* point x list */\n                   const char** pointy);    /* point y list */\nextern int defwNetNoshieldVia(const char* name);   /* viaName */\nextern int defwNetNoshieldEnd();\n/* end 5.3 */\n\n/* Subnet are a special type of option. A subnet must begin\n * with a defwNetSubnetStart and end with a defwNetSubnetEnd().\n * Routines to call within the subnet are: defwNetSubnetPin,\n * defwNetNondefaultRule and defwNetPathStart... */\nextern int defwNetSubnetStart(const char* name);\n\n/* This routine is called after the defwNetSubnet, it is for\n * [({compName | PIN} pinName) | (VPIN vpinName)]... */\nextern int defwNetSubnetPin(const char* compName,  /* compName | PIN | VPIN */\n                 const char* pinName);    /* pinName | vpinName */\n\nextern int defwNetSubnetEnd();\n\n/* Paths are a special type of option.  A path must begin\n * with a defwNetPathStart and end with a defwPathEnd().\n * The individual parts of the path can be entered in\n * any order. */\nextern int defwNetPathStart(const char* typ); // ROUTED | FIXED | COVER |\n                                              // NOSHIELD | NEW \nextern int defwNetPathWidth(int w);           /* width */\nextern int defwNetPathLayer(const char* name, /* layerName */\n                 int isTaper,                 /* 0 - ignore, 1 - TAPER */\n                 const char* rulename);       /* only one, isTaper or */\n                                              /*rulename can be assigned */\n/* This routine is optional.\n * This is a 5.6 syntax. */\nextern int defwNetPathStyle(int styleNum);\n\n/* This routine is optional.\n * This is a 5.8 syntax. */\nextern int defwNetPathMask(int maskNum);\n\nextern int defwNetPathRect(int deltaX1, int deltaY1, int deltaX2, int deltaY2);\n\nextern int defwNetPathVirtual(int x, int y);\n\n/* x and y location of the path */\nextern int defwNetPathPoint(int numPts,       /* number of connected points */\n                   double* pointx,       /* point x list */\n                   double* pointy);      /* point y list */\n\nextern int defwNetPathPointWithExt(int numPts,\n\t\t\t\t   double* pointx,\n\t\t\t\t   double* pointy,\n\t\t\t\t   double* optValue);\n\nextern int defwNetPathVia(const char* name);  /* viaName */\n\nextern int defwNetPathViaWithOrient(const char* name,\n                                    int orient);  /* optional(-1) */\n\nextern int defwNetPathViaWithOrientStr(const char* name,\n                                       const char* orient); /* optional(Null) */\nextern int defwNetPathEnd();\n\n/* This routine is called at the end of each net */\nextern int defwNetEndOneNet();\n\n/* This routine is called at the end of the net section */\nextern int defwEndNets();\n\n/* This section of routines is optional.\n * Returns 0 if successful.\n * The routine starts the I/O Timing section. All of the iotimings options\n * must follow.\n * The count is the number of defwIOTiming calls to follow.\n * The routine can be called only once.\n * This api is obsolete in 5.4. */\nextern int defwStartIOTimings(int count);\n\n/* This routine can be called after defwStaratIOTiming\n * It is for - - {(comp pin) | (PIN name)}\n * This api is obsolete in 5.4. */\nextern int defwIOTiming(const char* inst,      /* compName | PIN */\n                   const char* pin);           /* pinName */\n\n/* This routine is for + { RISE | FALL } VARIABLE min max\n * This api is obsolete in 5.4. */\nextern int defwIOTimingVariable(const char* riseFall,  /* RISE | FALL */\n                   int num1,                   /* min */\n                   int num2);                  /* max */\n\n/* This routine is for + { RISE | FALL } SLEWRATE min max\n * This api is obsolete in 5.4. */\nextern int defwIOTimingSlewrate(const char* riseFall,  /* RISE | FALL */\n                   int num1,                   /* min */\n                   int num2);                  /* max */\n\n/* This routine is for + DRIVECELL macroName [[FROMPIN pinName] TOPIN pinName]\n * [PARALLEL numDrivers]\n * This api is obsolete in 5.4. */\nextern int defwIOTimingDrivecell(const char* name,   /* macroName*/\n                   const char* fromPin,        /* optional(NULL) */\n                   const char* toPin,          /* optional(NULL) */\n                   int numDrivers);            /* optional(0) */\n\n/* This routine is for + CAPACITANCE capacitance\n * This api is obsolete in 5.4. */\nextern int defwIOTimingCapacitance(double num);\n\n/* This api is obsolete in 5.4. */\nextern int defwEndIOTimings();\n\n/* Routines to enter scan chains.  This section is optional\n * The section must start with a defwStartScanchains() call and\n * end with a defwEndScanchain() call.\n * Each scan chain begins with a defwScanchain() call.\n * The rest of the calls follow.  */\nextern int defwStartScanchains(int count);\n\n/* This routine can be called after defwStartScanchains\n * It is for - chainName */\nextern int defwScanchain(const char* name);\n\n/* This routine is for + COMMONSCANPINS [IN pin] [OUT pin] */\nextern int defwScanchainCommonscanpins(\n                  const char* inst1,      /* optional(NULL) - IN | OUT*/\n                  const char* pin1,       /* can't be null if inst1 is set */\n\t          const char* inst2,      /* optional(NULL) - IN | OUT */\n                  const char* pin2);      /* can't be null if inst2 is set */\n\n\n/* This routine is for + PARTITION paratitionName [MAXBITS maxBits] */\n/* This is 5.4.1 syntax */\nextern int defwScanchainPartition(const char* name,\n                  int maxBits);           /* optional(-1) */\n\n/* This routine is for + START {fixedInComp | PIN } [outPin] */\nextern int defwScanchainStart(const char* inst,   /* fixedInComp | PIN */\n                  const char* pin);               /* outPin */\n\n/* This routine is for + STOP {fixedOutComp | PIN } [inPin] */\nextern int defwScanchainStop(const char* inst,    /* fixedOutComp | PIN */\n                  const char* pin);               /* inPin */\n\n/* This routine is for + FLOATING {floatingComp [IN pin] [OUT pin]}\n * This is a 5.4.1 syntax */\nextern int defwScanchainFloating(const char* name,   /* floatingComp */\n                  const char* inst1,      /* optional(NULL) - IN | OUT */\n                  const char* pin1,       /* can't be null if inst1 is set */\n\t          const char* inst2,      /* optional(NULL) - IN | OUT */\n                  const char* pin2);      /* can't be null if inst2 is set */\n\n/* This routine is for + FLOATING {floatingComp [IN pin] [OUT pin]}\n * This is a 5.4.1 syntax.\n * This routine is the same as defwScanchainFloating.  But also added\n * the option BITS. */\nextern int defwScanchainFloatingBits(const char* name,   /* floatingComp */\n                  const char* inst1,      /* optional(NULL) - IN | OUT */\n                  const char* pin1,       /* can't be null if inst1 is set */\n\t          const char* inst2,      /* optional(NULL) - IN | OUT */\n                  const char* pin2,       /* can't be null if inst2 is set */\n                  int   bits);            /* optional (-1) */\n\n/* This routine is for + ORDERED {fixedComp [IN pin] [OUT pin]\n * fixedComp [IN pin] [OUT pin].\n * When this routine is called for the 1st time within a scanchain, \n * both name1 and name2 are required.  Only name1 is required is the\n * routine is called more than once. */\nextern int defwScanchainOrdered(const char* name1,\n                  const char* inst1,      /* optional(NULL) - IN | OUT */\n                  const char* pin1,       /* can't be null if inst1 is set */\n\t          const char* inst2,      /* optional(NULL) - IN | OUT */\n                  const char* pin2,       /* can't be null if inst2 is set */\n                  const char* name2,\n                  const char* inst3,      /* optional(NULL) - IN | OUT */\n                  const char* pin3,       /* can't be null if inst3 is set */\n\t          const char* inst4,      /* optional(NULL) - IN | OUT */\n                  const char* pin4);      /* can't be null if inst4 is set */\n\n/* This routine is for + ORDERED {fixedComp [IN pin] [OUT pin]\n * fixedComp [IN pin] [OUT pin].\n * When this routine is called for the 1st time within a scanchain, \n * both name1 and name2 are required.  Only name1 is required is the\n * routine is called more than once.\n * This is a 5.4.1 syntax.\n * This routine is the same as defwScanchainOrdered.  But also added\n * the option BITS */\nextern int defwScanchainOrderedBits(const char* name1,\n                  const char* inst1,      /* optional(NULL) - IN | OUT */\n                  const char* pin1,       /* can't be null if inst1 is set */\n\t          const char* inst2,      /* optional(NULL) - IN | OUT */\n                  const char* pin2,       /* can't be null if inst2 is set */\n                  int   bits1,            /* optional(-1) */\n                  const char* name2,\n                  const char* inst3,      /* optional(NULL) - IN | OUT */\n                  const char* pin3,       /* can't be null if inst3 is set */\n\t          const char* inst4,      /* optional(NULL) - IN | OUT */\n                  const char* pin4,       /* can't be null if inst4 is set */\n                  int   bits2);           /* optional(-1) */\n\nextern int defwEndScanchain();\n\n/* Routines to enter constraints.  This section is optional\n * The section must start with a defwStartConstrains() call and\n * end with a defwEndConstraints() call.\n * Each contraint will call the defwConstraint...().\n * This api is obsolete in 5.4. */\nextern int defwStartConstraints (int count);  /* optional */\n\n/* The following routines are for - {operand [+ RISEMAX time] [+ FALLMAX time]\n * [+ RISEMIN time] [+ FALLMIN time] | WIREDLOGIC netName MAXDIST distance };}\n * operand - NET netName | PATH comp fromPin comp toPin | SUM (operand, ...)\n * The following apis are obsolete in 5.4. */ \nextern int defwConstraintOperand();          /* begin an operand */\nextern int defwConstraintOperandNet(const char* netName);  /* NET */\nextern int defwConstraintOperandPath(const char* comp1,    /* PATH - comp|PIN */\n                  const char* fromPin,\n                  const char* comp2,\n                  const char* toPin);\nextern int defwConstraintOperandSum();        /* SUM */\nextern int defwConstraintOperandSumEnd();     /* mark the end of SUM */\nextern int defwConstraintOperandTime(const char* timeType, //  RISEMAX | FALLMAX | RISEMIN | FALLMIN\n                                     int time);\nextern int defwConstraintOperandEnd();        /* mark the end of operand */\n\n/* This routine is for - WIRELOGIC netName MAXDIST distance */\nextern int defwConstraintWiredlogic(const char* netName,\n                  int distance);\n\nextern int defwEndConstraints ();\n\n/* Routines to enter groups.  This section is optional\n * The section must start with a defwStartGroups() call and\n * end with a defwEndGroups() call.\n * Each group will call the defwGroup...(). */\nextern int defwStartGroups (int count);  /* optional */\n\n/* This routine is for - groupName compNameRegExpr ... */\nextern int defwGroup(const char* groupName,\n                   int numExpr,\n                   const char** groupExpr);\n\n/* This routine is for + SOFT [MAXHALFPERIMETER value] [MAXX value]\n * [MAXY value] */\nextern int defwGroupSoft(const char* type1, /* MAXHALFPERIMETER | MAXX | MAXY */\n                   double value1,\n                   const char* type2,\n                   double value2,\n                   const char* type3,\n                   double value3);\n\n/* This routine is for + REGION {pt pt | regionName} */\nextern int defwGroupRegion(int xl, int yl,   /* either the x & y or    */\n                   int xh, int yh,           /* regionName only, can't */\n                   const char* regionName);  /* be both */\n\nextern int defwEndGroups();\n\n/* Routines to enter Blockages.  This section is optional\n * The section must start with a defwStartBlockages() call and\n * end with a defwEndBlockages() call.\n * Each blockage will call the defwBlockages...().\n * This is a 5.4 syntax. */\nextern int defwStartBlockages(int count);   /* count = numBlockages */\n\n/* This routine is for - layerName\n* This routine is called per entry within a blockage for layer.\n* This is a 5.4 syntax. */\nextern int defwBlockagesLayer(const char* layerName);\n\n/* This routine is for - slots \n* This routine is called per entry within a blockage layer, can't be more then one.\n* This is a 5.4 syntax. */\nextern int defwBlockagesLayerSlots();\n\n/* This routine is for - fills\n* This routine is called per entry within a blockage layer, can't be more then one.\n* This is a 5.4 syntax. */\nextern int defwBlockagesLayerFills();\n\n/* This routine is for - pushdown\n* This routine is called per entry within a blockage layer, can't be more then one.\n* This is a 5.4 syntax. */\nextern int defwBlockagesLayerPushdown();\n\n/* This routine is for - exceptpgnet\n* This routine is called per entry within a blockage layer, can't be more then one.\n* This is a 5.7 syntax. */\nextern int defwBlockagesLayerExceptpgnet();\n\n/* This routine is for - component\n* This routine called per entry within a blockage layer, can't be more than one.\n* This is a 5.6 syntax. */\nextern int defwBlockagesLayerComponent(const char* compName);\n\n/* This routine is for - spacing\n* Either this routine or defwBlockagesDesignRuleWidth is called per entry\n* within a blockage layer, can't be more than one.\n* This is a 5.6 syntax. */\nextern int defwBlockagesLayerSpacing(int minSpacing);\n\n/* This routine is for - designrulewidth\n* Either this routine or defwBlockagesSpacing is called per entry\n* within a blockage layer, can't be more than one.\n* This is a 5.6 syntax. */\nextern int defwBlockagesLayerDesignRuleWidth(int effectiveWidth);\n\n/* This routine is for - mask.\n* This routine called per entry within a blockage layer, can't be more than one.\n* This is a 5.8 syntax. */\nextern int defwBlockagesLayerMask(int maskColor);\n\n/* This routine is for - layerName & compName\n * Either this routine, defBlockageLayerSlots, defBlockageLayerFills,\n * or defwBlockagePlacement is called per entry within\n * a blockage, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwBlockageLayer(const char* layerName,\n                             const char* compName);   /* optional(NULL) */\n\n/* This routine is for - layerName & slots \n * Either this routine, defBlockageLayer, defBlockageLayerFills,\n * defwBlockagePlacement, or defwBlockagePushdown is called per entry within\n * a blockage, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwBlockageLayerSlots(const char* layerName);\n\n/* This routine is for - layerName & fills\n * Either this routine, defBlockageLayer, defBlockageLayerSlots,\n * defwBlockagePlacement, or defwBlockagePushdown is called per entry within\n * a blockage, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwBlockageLayerFills(const char* layerName);\n\n/* This routine is for - layerName & pushdown\n * Either this routine, defBlockageLayer, defBlockageLayerSlots,\n * defwBlockagePlacement, or defwBlockageFills is called per entry within\n * a blockage, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwBlockageLayerPushdown(const char* layerName);\n\n/* This routine is for - exceptpgnet\n * Either this routine, defBlockageLayer, defBlockageLayerSlots,\n * defwBlockagePlacement, or defwBlockageFills is called per entry within\n * a blockage, can't be more then one.\n * This is a 5.7 syntax. */\nextern int defwBlockageLayerExceptpgnet(const char* layerName);\n\n/* This routine is for - spacing\n * Either this routine or defwBlockageDesignRuleWidth is called per entry\n * within a blockage, can't be more than one.\n * This is a 5.6 syntax. */\nextern int defwBlockageSpacing(int minSpacing);\n\n/* This routine is for - designrulewidth\n * Either this routine or defwBlockageSpacing is called per entry\n * within a blockage, can't be more than one.\n * This is a 5.6 syntax. */\nextern int defwBlockageDesignRuleWidth(int effectiveWidth);\n\n/* This routine is for - placement\n * This routine is called per entry within blockage for placement.\n * This is a 5.4 syntax.\n * 11/25/2002 - bug fix: submitted by Craig Files (cfiles@ftc.agilent.com)\n * this routine allows to call blockage without a component. */\nextern int defwBlockagesPlacement();\n\n/* This routine is for - component\n* This routine is called per entry within blockage placement, can't be more then one.\n* This is a 5.4 syntax. */\nextern int defwBlockagesPlacementComponent(const char* compName);\n\n/* This routine is for - Pushdown\n* This routine is called per entry within blockage placement, can't be more then one.\n* This is a 5.4 syntax. */\nextern int defwBlockagesPlacementPushdown();\n\n/* This routine is for - soft\n* Either this routine or defwBlockagesPlacementPartial\n* is called per entry within blockage placement, can't be more then one.\n* This is a 5.7 syntax. */\nextern int defwBlockagesPlacementSoft();\n\n/* This routine is for - Partial\n* Either this routine or defwBlockagesPlacementSoft\n* is called per entry within blockage placement, can't be more then one.\n* This is a 5.7 syntax. */\nextern int defwBlockagesPlacementPartial(double maxDensity);\n\n/* This routine is for rectangle.\n* This routine is optional and can be called multiple time. \n* This is a 5.4 syntax. */\nextern int defwBlockagesRect(int xl, int yl, int xh, int yh);\n\n/* This routine is for polygon.\n* This routine is optional and can be called multiple time. \n* This is a 5.6 syntax. */\nextern int defwBlockagesPolygon(int num_polys, int* xl, int* yl);\n\n/* This routine is for - placement\n* Either this routine or defBlockageLayer\n* is called per entry within blockage, can't be more then one.\n* This is a 5.4 syntax.\n* 11/25/2002 - bug fix: submitted by Craig Files (cfiles@ftc.agilent.com)\n* this routine allows to call blockage without a component. */\nextern int defwBlockagePlacement();\n\n/* This routine is for - placement & component\n * Either this routine or defwBlockagePlacementPushdown\n * is called per entry within blockage, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwBlockagePlacementComponent(const char* compName);\n\n/* This routine is for - placement & Pushdown\n * Either this routine or defwBlockagePlacementComponent\n * is called per entry within blockage, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwBlockagePlacementPushdown();\n\n/* This routine is for - placement & soft\n * Either this routine or defwBlockagePlacementPushdown\n * is called per entry within blockage, can't be more then one.\n * This is a 5.7 syntax. */\nextern int defwBlockagePlacementSoft();\n\n/* This routine is for - placement & Partial\n * Either this routine or defwBlockagePlacementComponent\n * is called per entry within blockage, can't be more then one.\n * This is a 5.7 syntax. */\nextern int defwBlockagePlacementPartial(double maxDensity);\n\n/* This routine is optional.\n * This is a 5.8 syntax. */\nextern int defwBlockageMask(int maskColor);\n\n/* This routine is for rectangle.\n * This is a 5.4 syntax. */\nextern int defwBlockageRect(int xl, int yl, int xh, int yh);\n\n/* This routine is for polygon.\n * This routine is optinal and can be called multiple time. \n * This is a 5.6 syntax. */\nextern int defwBlockagePolygon(int num_polys, int* xl, int* yl);\n\n/* This is a 5.4 syntax. */\nextern int defwEndBlockages();\n\n/* Routines to enter Slots.  This section is optional\n * The section must start with a defwStartSlots() call and\n * end with a defwEndSlots() call.\n * Each slots will call the defwSlots...().\n * This is a 5.4 syntax. */\nextern int defwStartSlots(int count);   /* count = numSlots */\n\n/* This routine is for - layerName & compName\n * Either this routine, defSlots, defSlotsLayerFills,\n * or defwSlotsPlacement is called per entry within\n * a slot, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwSlotLayer(const char* layerName);\n\n/* This routine is for rectangle\n * This is a 5.4 syntax. */\nextern int defwSlotRect(int xl, int yl, int xh, int yh);\n\n/* This routine is for rectangle\n * This is a 5.6 syntax and can be called multiple time. */\nextern int defwSlotPolygon(int num_polys, double* xl, double* yl);\n\n/* This is a 5.4 syntax. */\nextern int defwEndSlots();\n\n/* Routines to enter Fills.  This section is optional\n * The section must start with a defwStartFills() call and\n * end with a defwEndFills() call.\n * Each fills will call the defwFills...().\n * This is a 5.4 syntax. */\nextern int defwStartFills(int count);   /* count = numFills */\n\n/* This routine is for - layerName & compName\n * Either this routine, defFills, defFillsLayerFills,\n * or defwFillsPlacement is called per entry within\n * a fill, can't be more then one.\n * This is a 5.4 syntax. */\nextern int defwFillLayer(const char* layerName);\n\n/* This routine is optional.\n * This is a 5.8 syntax. */\nextern int defwFillLayerMask(int maskColor);\n\n/* This routine has to be called after defwFillLayer\n * This routine is optional.\n * This is a 5.7 syntax. */\nextern int defwFillLayerOPC();\n\n/* This routine is for rectangle.\n * This is a 5.4 syntax. */\nextern int defwFillRect(int xl, int yl, int xh, int yh);\n\n/* This routine is for polygon.\n * This is a 5.6 syntax and can be called multiple time. */\nextern int defwFillPolygon(int num_polys, double* xl, double* yl);\n\n/* This routine is for via.\n * This routine is optional.\n * This is a 5.7 syntax and can be called multiple time. */\nextern int defwFillVia(const char* viaName);\n\n/* This routine is optional.\n * This is a 5.8 syntax. */\nextern int defwFillViaMask(int colorMask);\n\n/* This routine is for via OPC.\n * This routine can only be called after defwFillVia.\n * This routine is optional.\n * This is a 5.7 syntax and can be called multiple time. */\nextern int defwFillViaOPC();\n\n/* This routine is for via OPC.\n * This routine can only be called after defwFillVia.\n * This routine is required following defwFillVia.\n * This is a 5.7 syntax and can be called multiple time. */\nextern int defwFillPoints(int num_points, double* xl, double* yl);\n\n/* This is a 5.4 syntax. */\nextern int defwEndFills();\n\n/* Routines to enter NONDEFAULTRULES.  This section is required\n * The section must start with a defwStartNonDefaultRules() and\n * end with defwEndNonDefaultRules() call.\n * This is a 5.6 syntax. */\nextern int defwStartNonDefaultRules(int count);\n\n/* This routine is for Layer within the NONDEFAULTRULES\n * This routine can be called multiple times.  It is required.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwNonDefaultRule(const char* ruleName,\n                              int hardSpacing);   /* optional(0) */\n\n/* Routines to enter NONDEFAULTRULES.  This section is required\n * This routine must be called after the defwNonDefaultRule. \n * This routine can be called multiple times.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwNonDefaultRuleLayer(const char* layerName,\n                                   int width,\n                                   int diagWidth,    /* optional(0) */\n                                   int spacing,      /* optional(0) */\n                                   int wireExt);     /* optional(0) */\n\n/* Routines to enter NONDEFAULTRULES.  This section is optional.\n * This routine must be called after the defwNonDefaultRule. \n * This routine can be called multiple times.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwNonDefaultRuleVia(const char* viaName);\n\n/* Routines to enter NONDEFAULTRULES.  This section is optional.\n * This routine must be called after the defwNonDefaultRule. \n * This routine can be called multiple times.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwNonDefaultRuleViaRule(const char* viaRuleName);\n\n/* Routines to enter NONDEFAULTRULES.  This section is optional.\n * This routine must be called after the defwNonDefaultRule. \n * This routine can be called multiple times.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwNonDefaultRuleMinCuts(const char* cutLayerName, int numCutS);\n\n/* This is a 5.4 syntax. */\nextern int defwEndNonDefaultRules();\n\n/* Routines to enter STYLES.  This section is required\n * The section must start with a defwStartStyles() and\n * end with defwEndStyles() call.\n * This is a 5.6 syntax. */\nextern int defwStartStyles(int count);\n\n/* This routine is for Layer within the NONDEFAULTRULES\n * This routine can be called multiple times.  It is required.\n * This is a 5.6 syntax.\n * Returns 0 if successful. */\nextern int defwStyles(int styleNums, int num_points, double* xp, double* yp);\n\n/* This is a 5.4 syntax. */\nextern int defwEndStyles();\n\n/* This routine is called after defwInit.\n * This routine is optional and it can be called only once.\n * Returns 0 if successful. */\nextern int defwStartBeginext(const char* name);\n\n/* This routine is called after defwBeginext.\n * This routine is optional, it can be called only once.\n * Returns 0 if successful. */\nextern int defwBeginextCreator (const char* creatorName);\n\n/* This routine is called after defwBeginext.\n * This routine is optional, it can be called only once.\n * It gets the current system time and date.\n * Returns 0 if successful. */\nextern int defwBeginextDate ();\n\n/* This routine is called after defwBeginext.\n * This routine is optional, it can be called only once.\n * Returns 0 if successful. */\nextern int defwBeginextRevision (int vers1, int vers2);   /* vers1.vers2 */\n\n/* This routine is called after defwBeginext.\n * This routine is optional, it can be called many times.\n * It allows user to customize their own syntax.\n * Returns 0 if successful. */\nextern int defwBeginextSyntax (const char* title, const char* string);\n\n/* This routine is called after defwInit.\n * This routine is optional and it can be called only once.\n * Returns 0 if successful. */\nextern int defwEndBeginext();\n\n/* End the DEF file.\n * This routine IS NOT OPTIONAL.\n * The routine must be called LAST. */\nextern int defwEnd ( void );\n\n/* General routines that can be called anytime after the Init is called.\n */\nextern int defwCurrentLineNumber ( void );\n\n/*\n * extern void defwError ( const char *, ... );\n * extern void defwWarning ( const char *, ... );\n * extern void defwVError ( const char *, va_list );\n * extern void defwVWarning ( const char *, va_list );\n * extern int  defwGetCurrentLineNumber (void);\n * extern const char *defwGetCurrentFileName (void);\n */\n \n/* This routine will print the error message. */\nextern void defwPrintError(int status);\n\n/* This routine will allow user to write their own comemnt.  It will\n * automactically add a # infront of the line.\n */\nextern void defwAddComment(const char* comment);\n \n/* This routine will indent 3 blank spaces */\nextern void defwAddIndent();\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defwWriterCalls.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2013-2014, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef DEFI_WRITER_H\n#define DEFI_WRITER_H\n\n#include <stdarg.h>\n#include <stdio.h>\n \n#include \"defiKRDefs.hpp\"\n#include \"defiDefs.hpp\"\n#include \"defiUser.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n/*\n * The main writer function.\n * The file should already be opened.  This requirement allows\n * the writer to be used with stdin or a pipe.  The file name\n * is only used for error messages.  The includeSearchPath is\n * a colon-delimited list of directories in which to find\n * include files.\n */\nextern int defwWrite (  FILE *file,\n                        const char *fileName,\n                        defiUserData userData );\n\n/*\n * Set all of the callbacks that have not yet been set to a function\n * that will add up how many times a given def data type was ignored\n * (ie no callback was done).  The statistics can later be printed out.\n */\nextern void defwSetRegisterUnusedCallbacks (void);\nextern void defwPrintUnusedCallbacks (FILE* log);\n\n/*\n * Set/get the client-provided user data.  defi doesn't look at\n * this data at all, it simply passes the opaque defiUserData pointer\n * back to the application with each callback.  The client can\n * change the data at any time, and it will take effect on the\n * next callback.  The defi writer and writer maintain separate\n * user data pointers.\n */\nextern void defwSetUserData ( defiUserData );\nextern defiUserData defwGetUserData ( void );\n \n/*\n * An enum describing all of the types of writer callbacks.\n */\ntypedef enum {\n  defwUnspecifiedCbkType = 0,\n  defwVersionCbkType,\n  defwCaseSensitiveCbkType,\n  defwBusBitCbkType,\n  defwDividerCbkType,\n  defwDesignCbkType,\n  defwTechCbkType,\n  defwArrayCbkType,\n  defwFloorPlanCbkType,\n  defwUnitsCbkType,\n  defwHistoryCbkType,\n  defwPropDefCbkType,\n  defwDieAreaCbkType,\n  defwRowCbkType,\n  defwTrackCbkType,\n  defwGcellGridCbkType,\n  defwDefaultCapCbkType,\n  defwCanplaceCbkType,\n  defwCannotOccupyCbkType,\n  defwViaCbkType,\n  defwRegionCbkType,\n  defwComponentCbkType,\n  defwPinCbkType,\n  defwPinPropCbkType,\n  defwSNetCbkType,\n  defwNetCbkType,\n  defwIOTimingCbkType,\n  defwScanchainCbkType,\n  defwConstraintCbkType,\n  defwAssertionCbkType,    // pre 5.2\n  defwGroupCbkType,\n  defwBlockageCbkType,     // 5.4\n  defwExtCbkType,\n  defwDesignEndCbkType\n\n  /* NEW CALLBACKS - each callback has its own type.  For each callback\n   * that you add, you must add an item to this enum. */\n\n} defwCallbackType_e;\n \n \n/* Declarations of function signatures for each type of callback.\n * These declarations are type-safe when compiling with ANSI C\n * or C++; you will only be able to register a function pointer\n * with the correct signature for a given type of callback.\n *\n * Each callback function is expected to return 0 if successful.\n * A non-zero return code will cause the writer to abort.\n *\n * The defwDesignStart and defwDesignEnd callback is only called once.\n * Other callbacks may be called multiple times, each time with a different\n * set of data.\n *\n * For each callback, the Def API will make the callback to the\n * function supplied by the client, which should either make a copy\n * of the Def object, or store the data in the client's own data structures.\n * The Def API will delete or reuse each object after making the callback,\n * so the client should not keep a pointer to it.\n *\n * All callbacks pass the user data pointer provided in defwRead()\n * or defwSetUserData() back to the client; this can be used by the\n * client to obtain access to the rest of the client's data structures.\n *\n * The user data pointer is obtained using defwGetUserData() immediately\n * prior to making each callback, so the client is free to change the\n * user data on the fly if necessary.\n *\n * Callbacks with the same signature are passed a callback type\n * parameter, which allows an application to write a single callback\n * function, register that function for multiple callbacks, then\n * switch based on the callback type to handle the appropriate type of\n * data.\n */\n \n\n/* A declaration of the signature of all callbacks that return nothing. */\ntypedef int (*defwVoidCbkFnType) ( defwCallbackType_e, defiUserData );\n\n/* Functions to call to register a callback function.\n */\nextern void defwSetArrayCbk (defwVoidCbkFnType);\nextern void defwSetAssertionCbk (defwVoidCbkFnType);\nextern void defwSetBlockageCbk (defwVoidCbkFnType);\nextern void defwSetBusBitCbk (defwVoidCbkFnType);\nextern void defwSetCannotOccupyCbk (defwVoidCbkFnType);\nextern void defwSetCanplaceCbk (defwVoidCbkFnType);\nextern void defwSetCaseSensitiveCbk (defwVoidCbkFnType);\nextern void defwSetComponentCbk (defwVoidCbkFnType);\nextern void defwSetConstraintCbk (defwVoidCbkFnType);\nextern void defwSetDefaultCapCbk (defwVoidCbkFnType);\nextern void defwSetDesignCbk (defwVoidCbkFnType);\nextern void defwSetDesignEndCbk (defwVoidCbkFnType);\nextern void defwSetDieAreaCbk (defwVoidCbkFnType);\nextern void defwSetDividerCbk (defwVoidCbkFnType);\nextern void defwSetExtCbk (defwVoidCbkFnType);\nextern void defwSetFloorPlanCbk (defwVoidCbkFnType);\nextern void defwSetGcellGridCbk (defwVoidCbkFnType);\nextern void defwSetGroupCbk (defwVoidCbkFnType);\nextern void defwSetHistoryCbk (defwVoidCbkFnType);\nextern void defwSetIOTimingCbk (defwVoidCbkFnType);\nextern void defwSetNetCbk (defwVoidCbkFnType);\nextern void defwSetPinCbk (defwVoidCbkFnType);\nextern void defwSetPinPropCbk (defwVoidCbkFnType);\nextern void defwSetPropDefCbk (defwVoidCbkFnType);\nextern void defwSetRegionCbk (defwVoidCbkFnType);\nextern void defwSetRowCbk (defwVoidCbkFnType);\nextern void defwSetSNetCbk (defwVoidCbkFnType);\nextern void defwSetScanchainCbk (defwVoidCbkFnType);\nextern void defwSetTechnologyCbk (defwVoidCbkFnType);\nextern void defwSetTrackCbk (defwVoidCbkFnType);\nextern void defwSetUnitsCbk (defwVoidCbkFnType);\nextern void defwSetVersionCbk (defwVoidCbkFnType);\nextern void defwSetViaCbk (defwVoidCbkFnType);\n\n/* NEW CALLBACK - each callback must have a function to allow the user\n * to set it.  Add the function here. */\n\n\n/*\n * Set all of the callbacks that have not yet been set to the following\n * function.  This is especially useful if you want to check to see\n * if you forgot anything.\n */\nextern void defwSetUnusedCallbacks (defwVoidCbkFnType func);\n\n/* Routine to set the message logging routine for errors */\n#ifndef DEFI_LOG_FUNCTION\n    typedef void (*DEFI_LOG_FUNCTION) (const char*);\n#endif\n\nextern void defwSetLogFunction ( DEFI_LOG_FUNCTION );\n\n/* Routine to set the message logging routine for warnings */\n#ifndef DEFI_WARNING_LOG_FUNCTION\n    typedef void (*DEFI_WARNING_LOG_FUNCTION)(const char*);\n#endif\n\nextern void defwSetWarningLogFunction( DEFI_WARNING_LOG_FUNCTION );\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/def5.8/defzlib.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2015, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef LEFDEFZIP_H\n#define LEFDEFZIP_H\n\n#include \"defiDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\ntypedef void* defGZFile;\nclass defrContext;\n\n//\n// Name: defrSetReadGZipFunction\n// Description: Sets GZip read function for the parser\n// Returns: 0 if no errors\n//\nextern void defrSetGZipReadFunction();\n\n//\n// Name: defOpenGZip\n// Description: Open a gzip file\n// Returns: A file pointer\n//\nextern defGZFile defrGZipOpen(const char* gzipFile, const char* mode);\n\n// \n// Name: defCloseGZip\n// Description: Close a gzip file\n// Returns: 0 if no errors\n//\nextern int defrGZipClose(defGZFile filePtr);\n\n//\n// Name: defrReadGZip\n// Description: Parse a def gzip file\n// Returns: 0 if no errors\n//\nextern int defrReadGZip(defGZFile file, const char* gzipFile, void* uData);\n\n//\n// FUNCTIONS TO BE OBSOLETED.\n// The API is kept only for compatibility reasons.\n//\n\n//\n// Name: defGZipOpen\n// Description: Open a gzip file\n// Returns: A file pointer\n//\nextern defGZFile defGZipOpen(const char* gzipFile, const char* mode);\n\n// \n// Name: defGZipClose\n// Description: Close a gzip file\n// Returns: 0 if no errors\n//\nextern int defGZipClose(defGZFile filePtr);\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiArray.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiArray_h\n#define lefiArray_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n#include \"lefiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefiArrayFloorPlan {\npublic:\n  void Init(const char* name);\n  void Destroy();\n  void addSitePattern(const char* typ, lefiSitePattern* s);\n\n  int numPatterns() const;\n  lefiSitePattern* pattern(int index) const;\n  char* typ(int index) const;\n  const char* name() const;\n\nprotected:\n  int numPatterns_;\n  int patternsAllocated_;\n  lefiSitePattern** patterns_;\n  char** types_;\n  char* name_;\n};\n\nclass lefiArray {\npublic:\n  lefiArray();\n  void Init();\n\n  void Destroy();\n  ~lefiArray();\n\n  void setName(const char* name);\n  void addSitePattern(lefiSitePattern* s);\n  void setTableSize(int tsize);\n  void addDefaultCap(int minPins, double cap);\n  void addCanPlace(lefiSitePattern* s);\n  void addCannotOccupy(lefiSitePattern* s);\n  void addTrack(lefiTrackPattern* t);\n  void addGcell(lefiGcellPattern* g);\n  void addFloorPlan(const char* name);\n  void addSiteToFloorPlan(const char* typ, lefiSitePattern* p);\n  void clear();\n  void bump(void*** arr, int used, int* allocated);\n\n  int numSitePattern() const;\n  int numCanPlace() const;\n  int numCannotOccupy() const;\n  int numTrack() const;\n  int numGcell() const;\n  int hasDefaultCap() const;\n\n  const char* name() const;\n  lefiSitePattern* sitePattern(int index) const;\n  lefiSitePattern* canPlace(int index) const;\n  lefiSitePattern* cannotOccupy(int index) const;\n  lefiTrackPattern* track(int index) const;\n  lefiGcellPattern* gcell(int index) const;\n\n  int tableSize() const;\n  int numDefaultCaps() const;\n  int defaultCapMinPins(int index) const;\n  double defaultCap(int index) const;\n\n  int numFloorPlans() const;\n  const char* floorPlanName(int index) const;\n  int numSites(int index) const;\n  const char* siteType(int floorIndex, int siteIndex) const;\n  lefiSitePattern* site(int floorIndex, int siteIndex) const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int nameSize_;\n  char* name_;\n\n  int patternsAllocated_;\n  int numPatterns_;\n  lefiSitePattern** pattern_;\n\n  int canAllocated_;\n  int numCan_;\n  lefiSitePattern** canPlace_;\n\n  int cannotAllocated_;\n  int numCannot_;\n  lefiSitePattern** cannotOccupy_;\n\n  int tracksAllocated_;\n  int numTracks_;\n  lefiTrackPattern** track_;\n\n  int gAllocated_;\n  int numG_;\n  lefiGcellPattern** gcell_;\n\n  int hasDefault_;\n  int tableSize_;\n  int numDefault_;\n  int defaultAllocated_;\n  int* minPins_;\n  double* caps_;\n\n  int numFloorPlans_;\n  int floorPlansAllocated_;\n  lefiArrayFloorPlan** floors_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiCrossTalk.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiCrossTalk_h\n#define lefiCrossTalk_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Structure returned for the noise margin callback.\n// This lef construct has two floating point numbers. \nstruct lefiNoiseMargin {\n  double high;\n  double low;\n};\n\nclass lefiNoiseVictim {\npublic:\n  lefiNoiseVictim(double d);\n  void Init(double d);\n\n  void Destroy();\n  ~lefiNoiseVictim();\n\n  void clear();\n\n  void addVictimNoise(double d);\n\n  double length() const;\n  int numNoises() const;\n  double noise(int index) const;\n\nprotected:\n  double length_;\n\n  int numNoises_;\n  int noisesAllocated_;\n  double* noises_;\n};\n\nclass lefiNoiseResistance {\npublic:\n  lefiNoiseResistance();\n  void Init();\n\n  void Destroy();\n  ~lefiNoiseResistance();\n\n  void clear();\n\n  void addResistanceNumber(double d);\n  void addVictimLength(double d);\n  void addVictimNoise(double d);\n\n  int numNums() const;\n  double num(int index) const;\n\n  int numVictims() const;\n  lefiNoiseVictim* victim(int index) const;\n\nprotected:\n  int numNums_;\n  int numsAllocated_;\n  double* nums_;\n\n  int numVictims_;\n  int victimsAllocated_;\n  lefiNoiseVictim** victims_;\n};\n\nclass lefiNoiseEdge {\npublic:\n  lefiNoiseEdge();\n  void Init();\n\n  void Destroy();\n  ~lefiNoiseEdge();\n\n  void clear();\n\n  void addEdge(double d);\n  void addResistance();\n  void addResistanceNumber(double d);\n  void addVictimLength(double d);\n  void addVictimNoise(double d);\n\n  double edge();\n  int numResistances();\n  lefiNoiseResistance* resistance(int index);\n\nprotected:\n  double edge_;\n\n  int numResistances_;\n  int resistancesAllocated_;\n  lefiNoiseResistance** resistances_;\n};\n\nclass lefiNoiseTable {\npublic:\n  lefiNoiseTable();\n  void Init();\n\n  void Destroy();\n  ~lefiNoiseTable();\n\n  void setup(int i);\n  void newEdge();\n  void addEdge(double d);\n  void addResistance();\n  void addResistanceNumber(double d);\n  void addVictimLength(double d);\n  void addVictimNoise(double d);\n\n  void clear();\n\n  int num();\n  int numEdges();\n  lefiNoiseEdge* edge(int index);\n\nprotected:\n  int num_;\n\n  int numEdges_;\n  int edgesAllocated_;\n  lefiNoiseEdge** edges_;\n};\n\nclass lefiCorrectionVictim {\npublic:\n  lefiCorrectionVictim(double d);\n  void Init(double d);\n\n  void Destroy();\n  ~lefiCorrectionVictim();\n\n  void clear();\n\n  void addVictimCorrection(double d);\n\n  double length();\n  int numCorrections();\n  double correction(int index);\n\nprotected:\n  double length_;\n\n  int numCorrections_;\n  int correctionsAllocated_;\n  double* corrections_;\n};\n\nclass lefiCorrectionResistance {\npublic:\n  lefiCorrectionResistance();\n  void Init();\n\n  void Destroy();\n  ~lefiCorrectionResistance();\n\n  void clear();\n\n  void addResistanceNumber(double d);\n  void addVictimLength(double d);\n  void addVictimCorrection(double d);\n\n  int numNums();\n  double num(int index);\n\n  int numVictims();\n  lefiCorrectionVictim* victim(int index);\n\nprotected:\n  int numNums_;\n  int numsAllocated_;\n  double* nums_;\n\n  int numVictims_;\n  int victimsAllocated_;\n  lefiCorrectionVictim** victims_;\n};\n\nclass lefiCorrectionEdge {\npublic:\n  lefiCorrectionEdge();\n  void Init();\n \n  void Destroy();\n  ~lefiCorrectionEdge();\n \n  void clear();\n \n  void addEdge(double d);\n  void addResistance();\n  void addResistanceNumber(double d);\n  void addVictimLength(double d);\n  void addVictimCorrection(double d);\n \n  double edge();\n  int numResistances();\n  lefiCorrectionResistance* resistance(int index);\n \nprotected:\n  double edge_;\n \n  int numResistances_;\n  int resistancesAllocated_;\n  lefiCorrectionResistance** resistances_;\n};\n\nclass lefiCorrectionTable {\npublic:\n  lefiCorrectionTable();\n  void Init();\n\n  void Destroy();\n  ~lefiCorrectionTable();\n\n  void setup(int i);\n  void newEdge();\n  void addEdge(double d);\n  void addResistance();\n  void addResistanceNumber(double d);\n  void addVictimLength(double d);\n  void addVictimCorrection(double d);\n\n  void clear();\n\n  int num();\n  int numEdges();\n  lefiCorrectionEdge* edge(int index);\n\nprotected:\n  int num_;\n\n  int numEdges_;\n  int edgesAllocated_;\n  lefiCorrectionEdge** edges_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiDebug.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiDebug_h\n#define lefiDebug_h 1\n\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Set flag \nextern void lefiSetDebug (int num, int value) ;\n\n// Read flag \nextern int lefiDebug (int num) ;\n\n// Error reporting routine \nextern void lefiError (int check, int msgNum, const char* msg);\n\nextern const char* CASE(const char *x); \n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiDefs.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n// Definitions header file for the DEF Interface \n\n#ifndef LEFI_DEFS_H\n#define LEFI_DEFS_H\n\n#include <stdio.h>\n#include <limits.h>\n\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n//=================== General Types and Definitions =================\n\n#ifndef TRUE\n#define TRUE (1)\n#endif\n\n#ifndef FALSE\n#define FALSE (0)\n#endif\n\n#ifndef NULL\n#define NULL (0)\n#endif\n\ntypedef struct point lefPOINT;\n\nstruct point {\n    double x;\n    double y;\n    };\n\ntypedef struct rect lefRECT;\n\nstruct rect {\n    lefPOINT ll,ur;\n    };\n\ntypedef struct token lefTOKEN;\n\nstruct token {\n    lefTOKEN *next;\n    int what;\n    int data;\n    lefPOINT pt;\n    };\n\n#define START_LIST 10001\n#define POINT_SPEC 10002\n#define VIA_SPEC   10003\n#define WIDTH_SPEC 10004\n#define LAYER_SPEC 10005\n#define SHAPE_SPEC 10006\n\n#ifndef MAXINT\n#define MAXINT 0x7FFFFFFF\n#endif\n#ifndef MININT\n#define MININT 0x80000000\n#endif\n\n#ifndef    MIN\n#define MIN(x,y) ((x) < (y)? (x) : (y))\n#endif\n\n#ifndef    MIN\n#define MAX(x,y) ((x) > (y)? (x) : (y))\n#endif\n\n#define ROUND(x) ((x) >= 0 ? (int)((x)+0.5) : (int)((x)-0.5))\n\n//TOKEN *TokenFromRect();\n\n//=================== Enumerated Types ============================\ntypedef int lefiBoolean;\n\n// Every type of object has a unique identifier, and each object\n//  which is created knows its type, by storing the lefiObjectType_e\n//  as the first member in the structure.\n\ntypedef enum\n{\n  // decrease likelihood of accidentally correct values by starting\n  // at an unusual number \n  lefiInvalidObject = 41713, \n  lefiUnknownObject // void * \n} lefiObjectType_e;\n\n// The memory policy controls how an object which refers to or is composed of\n//  other objects manages those sub-objects, particularly when the parent\n//  object is copied or deleted.  The policy is specified as an argument to the\n//  constructor or initializer, and it is stored with the parent object.\n// \n//  The memory policy is a generalization of the common distinction between\n//  deep and shallow copies.  When a shallow copy of a parent object is made,\n//  the copy maintains pointers to the original sub-objects, and the original\n//  parent remains responsible for deleting those sub-objects.  When a deep\n//  copy of a parent object is made, the copy maintains pointers to new copies\n//  of each of the sub-objects, and the copy is responsible for deleting the\n//  new sub-objects.\n// \n//  The lefiPrivateSubObjects policy corresponds to a deep copy, while the the\n//  lefiReferencedSubObjects policy corresponds to a shallow copy.  Usually an\n//  initial parent object will be created using lefiPrivateSubObjects.  When a\n//  copy is made of that parent object, the copy may either maintain its own\n//  private versions of each sub-object, or it may refer to the original\n//  sub-objects.\n// \n//  In certain cases, it is useful to create a deep copy of a parent object,\n//  even though the new parent object shouldn't be responsible for the new\n//  sub-objects.  In this case, the lefiOrphanSubObjects and\n//  lefiAdoptedSubObjects policies may be used.  lefiOrphanSubObjects is\n//  specified while creating the deep copy, and then lefiAdoptedSubObjects is\n//  specified while creating another parent which will take on the\n//  responsibility for the orphans.\n// \n//  An object's memory policy affects only the sub-objects which it directly\n//  controls.  Those sub-objects themselves may have the same memory policy as\n//  their parents, or they may have a different memory policy.  When a copy is\n//  made of a child sub-object, the memory policy of the child controls\n//  whether deep or shallow copies are made of the grandchildren.\n// \ntypedef enum\n{\n  // decrease likelihood of accidentally correct values by starting\n  // at an unusual number \n  lefiInvalidMemoryPolicy = 23950,\n  lefiPrivateSubObjects,      // deep copy + delete\n  lefiReferencedSubObjects,   // shallow copy, no delete\n  lefiOrphanSubObjects,       // deep copy, no delete\n  lefiAdoptedSubObjects       // shallow copy + delete\n} lefiMemoryPolicy_e;\n\n// An opaque pointer for passing user data through from one API\n//  function to another.\n//  A handle which a user can set to point to their own data\n//  on a per-callback basis.  (See the comment in lefwWriter.h)\n\n#define lefiUserData void *\n#define lefiUserDataHandle void **\n\n#ifdef __SunOS_4_1_3\nextern int strcasecmp(const char*, const char*);\n#endif\n\n#ifdef WIN32\n#define strdup _strdup\n#endif \n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiEncryptInt.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef DEFI_ENCRYPTINT_H\n#define DEFI_ENCRYPTINT_H\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Unable the reader to read encrypted lef file.\n//  This function must be called before lefrRead().\n// /\nextern void lefrEnableReadEncrypted();\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiKRDefs.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiKRDEFS_h\n#define lefiKRDEFS_h\n\n#define BEGIN_LEFDEF_PARSER_NAMESPACE namespace LefDefParser {\n#define END_LEFDEF_PARSER_NAMESPACE }\n#define USE_LEFDEF_PARSER_NAMESPACE using namespace LefDefParser;\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiLayer.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2015, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiLayer_h\n#define lefiLayer_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n#include \"lefiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\ntypedef enum lefiAntennaEnum {\n  lefiAntennaAR,\n  lefiAntennaDAR,\n  lefiAntennaCAR,\n  lefiAntennaCDAR,\n  lefiAntennaAF,\n  lefiAntennaSAR,\n  lefiAntennaDSAR,\n  lefiAntennaCSAR,\n  lefiAntennaCDSAR,\n  lefiAntennaSAF,\n  lefiAntennaO,\n  lefiAntennaADR\n} lefiAntennaEnum;\n\nclass lefiAntennaPWL {\npublic:\n  lefiAntennaPWL();\n  ~lefiAntennaPWL();\n\n  static lefiAntennaPWL* create();\n  void Init();\n  void clear();\n  void Destroy();\n\n  void addAntennaPWL(double d, double r);\n\n  int  numPWL() const;\n  double PWLdiffusion(int index); \n  double PWLratio(int index); \n\nprotected:\n  int numAlloc_;\n  int numPWL_;\n  double* d_;\n  double* r_;\n};\n\nclass lefiLayerDensity {\npublic:\n  lefiLayerDensity();\n  ~lefiLayerDensity();\n\n  void Init(const char* type);\n  void Destroy();\n  void clear();\n\n  void setOneEntry(double entry);\n  void addFrequency(int num, double* frequency);\n  void addWidth(int num, double* width);\n  void addTableEntry(int num, double* entry);\n  void addCutarea(int num, double* cutarea);\n\n  char* type() const;\n  int hasOneEntry() const;\n  double oneEntry() const;\n  int numFrequency() const;\n  double frequency(int index) const;\n  int numWidths() const;\n  double width(int index) const;\n  int numTableEntries() const;\n  double tableEntry(int index) const;\n  int numCutareas() const;\n  double cutArea(int index) const;\n\nprotected:\n  char* type_;\n  double oneEntry_;\n  int numFrequency_;\n  double* frequency_;\n  int numWidths_;\n  double* widths_;\n  int numTableEntries_;\n  double* tableEntries_;\n  int numCutareas_;\n  double* cutareas_;\n};\n\n// 5.5\nclass lefiParallel {\npublic:\n  lefiParallel();\n  ~lefiParallel();\n\n  void Init();\n  void clear();\n  void Destroy();\n\n  void addParallelLength(int numLength, double* lengths);\n  void addParallelWidth(double width);\n  void addParallelWidthSpacing(int numSpacing, double* spacings);\n\n  int  numLength() const;\n  int  numWidth() const;\n  double length(int iLength) const;\n  double width(int iWidth) const;\n  double widthSpacing(int iWidth, int iWidthSpacing) const;\n\nprotected:\n  int numLength_;\n  int numWidth_;\n  int numWidthAllocated_;\n  double* length_;\n  double* width_;\n  double* widthSpacing_;\n};\n\n// 5.5\nclass lefiInfluence {\npublic:\n  lefiInfluence();\n  ~lefiInfluence();\n\n  void Init();\n  void clear();\n  void Destroy();\n\n  void addInfluence(double width, double distance, double spacing);\n\n  int  numInfluenceEntry() const;\n  double width(int index) const;\n  double distance(int index) const;\n  double spacing(int index) const;\n\nprotected:\n  int numAllocated_;\n  int numWidth_;\n  int numDistance_;\n  int numSpacing_;\n  double* width_;\n  double* distance_;\n  double* spacing_;\n};\n\n// 5.7\nclass lefiTwoWidths {\npublic:\n  lefiTwoWidths();\n  ~lefiTwoWidths();\n\n  void Init();\n  void clear();\n  void Destroy();\n\n  void addTwoWidths(double width, double runLength, int numSpacing,\n                    double* spacings, int hasPRL = 0);\n\n  int    numWidth() const;\n  double width(int iWidth) const;\n  int    hasWidthPRL(int iWidth) const;\n  double widthPRL(int iWidth) const;\n  int    numWidthSpacing(int iWidth) const;\n  double widthSpacing(int iWidth, int iWidthSpacing) const;\n\nprotected:\n  int numWidth_;\n  int numWidthAllocated_;\n  double* width_;\n  double* prl_;\n  int*    hasPRL_;\n  int*    numWidthSpacing_;   // each slot contains number of spacing of slot\n  double* widthSpacing_;\n  int*    atNsp_;             // accumulate total number of spacing\n};\n\n// 5.5\nclass lefiSpacingTable {\npublic:\n  lefiSpacingTable();\n  ~lefiSpacingTable();\n\n  void Init();\n  void clear();\n  void Destroy();\n\n  void addParallelLength(int numLength, double* lengths);\n  void addParallelWidth(double width);\n  void addParallelWidthSpacing(int numSpacing, double* spacing);\n  void setInfluence();\n  void addInfluence(double width, double distance, double spacing);\n  void addTwoWidths(double width, double runLength, int numSpacing,\n                    double* spacing, int hasPRL = 0);          // 5.7\n  \n  int isInfluence() const;\n  lefiInfluence* influence() const;\n  int isParallel() const;\n  lefiParallel*  parallel() const;\n  lefiTwoWidths* twoWidths() const;           // 5.7\n\nprotected:\n  int hasInfluence_;\n  lefiInfluence*   influence_;\n  lefiParallel*    parallel_;\n  lefiTwoWidths*   twoWidths_;               // 5.7\n};\n\n// 5.7\nclass lefiOrthogonal {\npublic:\n  lefiOrthogonal();\n  ~lefiOrthogonal();\n\n  void Init();\n  void Destroy();\n\n  void addOrthogonal(double cutWithin, double ortho);\n\n  int  numOrthogonal() const;\n  double cutWithin(int index) const;\n  double orthoSpacing(int index) const;\n\nprotected:\n  int numAllocated_;\n  int numCutOrtho_;\n  double* cutWithin_;\n  double* ortho_;\n};\n\n// 5.5\nclass lefiAntennaModel {\npublic:\n  lefiAntennaModel();\n  ~lefiAntennaModel();\n\n  void Init();\n  void Destroy();\n\n  void setAntennaModel(int oxide);\n  void setAntennaAreaRatio(double value);\n  void setAntennaCumAreaRatio(double value);\n  void setAntennaAreaFactor(double value);\n  void setAntennaSideAreaRatio(double value);\n  void setAntennaCumSideAreaRatio(double value);\n  void setAntennaSideAreaFactor(double value);\n  void setAntennaValue(lefiAntennaEnum antennaType, double value);\n  void setAntennaDUO(lefiAntennaEnum antennaType);\n  void setAntennaPWL(lefiAntennaEnum antennaType, lefiAntennaPWL* pwl);\n  void setAntennaCumRoutingPlusCut();             // 5.7\n  void setAntennaGatePlusDiff(double value);      // 5.7\n  void setAntennaAreaMinusDiff(double value);     // 5.7\n\n  int hasAntennaAreaRatio() const;\n  int hasAntennaDiffAreaRatio() const;\n  int hasAntennaDiffAreaRatioPWL() const;\n  int hasAntennaCumAreaRatio() const;\n  int hasAntennaCumDiffAreaRatio() const;\n  int hasAntennaCumDiffAreaRatioPWL() const;\n  int hasAntennaAreaFactor() const;\n  int hasAntennaAreaFactorDUO() const;\n  int hasAntennaSideAreaRatio() const;\n  int hasAntennaDiffSideAreaRatio() const;\n  int hasAntennaDiffSideAreaRatioPWL() const;\n  int hasAntennaCumSideAreaRatio() const;\n  int hasAntennaCumDiffSideAreaRatio() const;\n  int hasAntennaCumDiffSideAreaRatioPWL() const;\n  int hasAntennaSideAreaFactor() const;\n  int hasAntennaSideAreaFactorDUO() const;\n  int hasAntennaCumRoutingPlusCut() const;        // 5.7\n  int hasAntennaGatePlusDiff() const;             // 5.7\n  int hasAntennaAreaMinusDiff() const;            // 5.7\n  int hasAntennaAreaDiffReducePWL() const;        // 5.7\n\n  char*  antennaOxide() const;\n  double antennaAreaRatio() const;\n  double antennaDiffAreaRatio() const;\n  lefiAntennaPWL* antennaDiffAreaRatioPWL() const;\n  double antennaCumAreaRatio() const;\n  double antennaCumDiffAreaRatio() const;\n  lefiAntennaPWL* antennaCumDiffAreaRatioPWL() const;\n  double antennaAreaFactor() const;\n  double antennaSideAreaRatio() const;\n  double antennaDiffSideAreaRatio() const;\n  lefiAntennaPWL* antennaDiffSideAreaRatioPWL() const;\n  double antennaCumSideAreaRatio() const;\n  double antennaCumDiffSideAreaRatio() const;\n  lefiAntennaPWL* antennaCumDiffSideAreaRatioPWL() const;\n  double antennaSideAreaFactor() const;\n  double antennaGatePlusDiff() const;                  // 5.7\n  double antennaAreaMinusDiff() const;                 // 5.7\n  lefiAntennaPWL* antennaAreaDiffReducePWL() const;    // 5.7\n\nprotected:\n  int hasAntennaAreaRatio_;\n  int hasAntennaDiffAreaRatio_;\n  int hasAntennaDiffAreaRatioPWL_;\n  int hasAntennaCumAreaRatio_;\n  int hasAntennaCumDiffAreaRatio_;\n  int hasAntennaCumDiffAreaRatioPWL_;\n  int hasAntennaAreaFactor_;\n  int hasAntennaAreaFactorDUO_;\n  int hasAntennaSideAreaRatio_;\n  int hasAntennaDiffSideAreaRatio_;\n  int hasAntennaDiffSideAreaRatioPWL_;\n  int hasAntennaCumSideAreaRatio_;\n  int hasAntennaCumDiffSideAreaRatio_;\n  int hasAntennaCumDiffSideAreaRatioPWL_;\n  int hasAntennaSideAreaFactor_;\n  int hasAntennaSideAreaFactorDUO_;\n  int hasAntennaCumRoutingPlusCut_;        // 5.7\n  int hasAntennaGatePlusDiff_;             // 5.7\n  int hasAntennaAreaMinusDiff_;            // 5.7\n\n  char*  oxide_;\n  double antennaAreaRatio_;\n  double antennaDiffAreaRatio_;\n  lefiAntennaPWL* antennaDiffAreaRatioPWL_;\n  double antennaCumAreaRatio_;\n  double antennaCumDiffAreaRatio_;\n  lefiAntennaPWL* antennaCumDiffAreaRatioPWL_;\n  double antennaAreaFactor_;\n  double antennaSideAreaRatio_;\n  double antennaDiffSideAreaRatio_;\n  lefiAntennaPWL* antennaDiffSideAreaRatioPWL_;\n  double antennaCumSideAreaRatio_;\n  double antennaCumDiffSideAreaRatio_;\n  lefiAntennaPWL* antennaCumDiffSideAreaRatioPWL_;\n  double antennaSideAreaFactor_;\n  double antennaGatePlusDiff_;                  // 5.7\n  double antennaAreaMinusDiff_;                 // 5.7\n  lefiAntennaPWL* antennaAreaDiffReducePWL_;    // 5.7\n};\n\nclass lefiLayer {\npublic:\n  lefiLayer();\n  void Init();\n\n  void Destroy();\n  ~lefiLayer();\n\n  void clear();\n  void setName(const char* name); // calls clear to init\n  void setType(const char* typ);\n  void setPitch(double num);\n  void setMask(int num);                           // 5.8\n  void setPitchXY(double xdist, double ydist);     // 5.6\n  void setOffset(double num);\n  void setOffsetXY(double xdist, double ydist);    // 5.6\n  void setWidth(double num);\n  void setArea(double num);\n  void setDiagPitch(double dist);                  // 5.6\n  void setDiagPitchXY(double xdist, double ydist); // 5.6\n  void setDiagWidth(double width);                 // 5.6\n  void setDiagSpacing(double spacing);             // 5.6\n  void setSpacingMin(double dist);\n  void setSpacingName(const char* spacingName);    // for CUT layer\n  void setSpacingLayerStack();                     // 5.7 for CUT layer\n  void setSpacingAdjacent(int numCuts, double distance);  // 5.5for CUT layer\n  void setSpacingRange(double left, double right);\n  void setSpacingRangeUseLength();\n  void setSpacingRangeInfluence(double infLength);\n  void setSpacingRangeInfluenceRange(double min, double max);\n  void setSpacingRangeRange(double min, double max);\n  void setSpacingLength(double num);\n  void setSpacingLengthRange(double min, double max);\n  void setSpacingCenterToCenter();\n  void setSpacingParallelOverlap();                            // 5.7\n  void setSpacingArea(double cutArea);                         // 5.7\n  void setSpacingEol(double width, double within);             // 5.7\n  void setSpacingParSW(double space, double within);           // 5.7\n  void setSpacingParTwoEdges();                                // 5.7\n  void setSpacingAdjacentExcept();                             // 5.7\n  void setSpacingSamenet();                                    // 5.7\n  void setSpacingSamenetPGonly();                              // 5.7\n  void setSpacingTableOrtho();                                 // 5.7\n  void addSpacingTableOrthoWithin(double cutWithin, double ortho);  // 5.7\n  void setMaxFloatingArea(double num);                         // 5.7\n  void setArraySpacingLongArray();                             // 5.7\n  void setArraySpacingWidth(double viaWidth);                  // 5.7\n  void setArraySpacingCut(double cutSpacing);                  // 5.7\n  void addArraySpacingArray(int aCuts, double aSpacing);       // 5.7\n  void setSpacingNotchLength(double minNotchLength);           // 5.7\n  void setSpacingEndOfNotchWidth (double endOfNotchWidth,\n           double minNotchSpacing, double minNotchLength);     // 5.7\n  void setDirection(const char* dir);\n  void setResistance(double num);\n  void setCapacitance(double num);\n  void setHeight(double num);\n  void setWireExtension(double num);\n  void setThickness(double num);\n  void setShrinkage(double num);\n  void setCapMultiplier(double num);\n  void setEdgeCap(double num);\n  void setAntennaArea(double num);\n  void setAntennaLength(double num);\n  void setCurrentDensity(double num);\n  void setCurrentPoint(double width, double current);\n  void setResistancePoint(double width, double res);\n  void setCapacitancePoint(double width, double cap);\n  void addProp(const char* name, const char* value, const char type);\n  void addNumProp(const char* name, const double d,\n                  const char* value, const char type);\n  void addAccurrentDensity(const char* type);\n  void setAcOneEntry(double num);\n  void addAcFrequency();\n  void addAcCutarea();\n  void addAcTableEntry();\n  void addAcWidth();\n  void addDccurrentDensity(const char* type);\n  void setDcOneEntry(double num);\n  void addDcTableEntry();\n  void addDcWidth();\n  void addDcCutarea();\n  void addNumber(double num);\n  void setMaxwidth(double width);                                   // 5.5\n  void setMinwidth(double width);                                   // 5.5\n  void addMinenclosedarea(double area);                             // 5.5\n  void addMinenclosedareaWidth(double width);                       // 5.5\n  void addMinimumcut(int cuts, double width);                       // 5.5\n  void addMinimumcutWithin(double cutDistance);                     // 5.7\n  void addMinimumcutConnect(const char* direction);                 // 5.5\n  void addMinimumcutLengDis(double length, double distance);        // 5.5\n  void addParellelLength(double length);                            // 5.5\n  void addParellelSpacing(double width, double spacing);            // 5.5\n  void addParellelWidth(double width);                              // 5.5\n  void setProtrusion(double width, double length, double width2);   // 5.5\n\n  // 5.6 - minstep switch to multiple and added more options\n  void addMinstep(double distance);                                 // 5.5\n  void addMinstepType(char* type);                                  // 5.6\n  void addMinstepLengthsum(double maxLength);                       // 5.6\n  void addMinstepMaxedges(int maxEdges);                            // 5.7\n  void addMinstepMinAdjLength(double minAdjLength);                 // 5.7\n  void addMinstepMinBetLength(double minBetLength);                 // 5.7\n  void addMinstepXSameCorners();                                    // 5.7\n\n  int  getNumber();     // this is for the parser internal use only\n\n  // 5.5 SPACINGTABLE\n  void addSpacingTable();\n  void addSpParallelLength();\n  void addSpParallelWidth(double width);\n  void addSpParallelWidthSpacing();\n  void setInfluence();\n  void setSpTwoWidthsHasPRL(int hasPRL);\n  void addSpInfluence(double width, double distance, double spacing);\n  void addSpTwoWidths(double width, double runLength);              // 5.7\n  \n\n  // 5.6\n  void addEnclosure(char* enclRule, double overhang1, double overhang2);\n  void addEnclosureWidth(double minWidth); \n  void addEnclosureExceptEC(double cutWithin);       // 5.7\n  void addEnclosureLength(double minLength);         // 5.7\n  void addEnclosureExtraCut();                       // 5.7+\n  void addPreferEnclosure(char* enclRule, double overhang1, double overhang2);\n  void addPreferEnclosureWidth(double minWidth); \n  void setResPerCut(double value);\n  void setDiagMinEdgeLength(double value);\n  void setMinSize(lefiGeometries* geom);\n\n  // 5.8\n  // POLYROUTING, MIMCAP, TSV, PASSIVATION, NWELL\n  void setLayerType(const char* lType) ; \n\n  int hasType() const ;\n  int hasLayerType() const ;         // 5.8 - Some layers can be another types\n                                     //  ROUTING can be POLYROUTING or MIMCAP\n                                     //  CUT can be TSV or PASSIVATION\n                                     //  MASTERSLICE can be NWELL\n  int hasMask() const ;              // 5.8\n  int hasPitch() const ;\n  int hasXYPitch() const ;           // 5.6\n  int hasOffset() const ;\n  int hasXYOffset() const ;          // 5.6\n  int hasWidth() const ;\n  int hasArea() const ;\n  int hasDiagPitch() const;          // 5.6\n  int hasXYDiagPitch() const;        // 5.6\n  int hasDiagWidth() const;          // 5.6\n  int hasDiagSpacing() const;        // 5.6 \n  int hasSpacingNumber() const ;\n  int hasSpacingName(int index) const ;\n  int hasSpacingLayerStack(int index) const ;            // 5.7\n  int hasSpacingAdjacent(int index) const ;\n  int hasSpacingCenterToCenter(int index) const ;\n  int hasSpacingRange(int index) const ;\n  int hasSpacingRangeUseLengthThreshold(int index) const;\n  int hasSpacingRangeInfluence(int index) const;\n  int hasSpacingRangeInfluenceRange(int index) const;\n  int hasSpacingRangeRange(int index) const;\n  int hasSpacingLengthThreshold(int index) const;\n  int hasSpacingLengthThresholdRange(int index) const;\n  int hasSpacingParallelOverlap(int index) const;        // 5.7\n  int hasSpacingArea(int index) const;                   // 5.7\n  int hasSpacingEndOfLine(int index) const;              // 5.7\n  int hasSpacingParellelEdge(int index) const;           // 5.7\n  int hasSpacingTwoEdges(int index) const;               // 5.7\n  int hasSpacingAdjacentExcept(int index) const;         // 5.7\n  int hasSpacingSamenet(int index) const;                // 5.7\n  int hasSpacingSamenetPGonly(int index) const;          // 5.7\n  int hasSpacingNotchLength(int index) const;            // 5.7\n  int hasSpacingEndOfNotchWidth(int index) const;        // 5.7\n  int hasDirection() const ;\n  int hasResistance() const ;\n  int hasResistanceArray() const ;\n  int hasCapacitance() const ;\n  int hasCapacitanceArray() const ;\n  int hasHeight() const ;\n  int hasThickness() const ;\n  int hasWireExtension() const ;\n  int hasShrinkage() const ;\n  int hasCapMultiplier() const ;\n  int hasEdgeCap() const ;\n  int hasAntennaLength() const ;\n  int hasAntennaArea() const ;\n  int hasCurrentDensityPoint() const ;\n  int hasCurrentDensityArray() const ;\n  int hasAccurrentDensity() const;\n  int hasDccurrentDensity() const;\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n\n  int numSpacing() const;\n\n  char* name() const ;\n  const char* type() const ;\n  const char* layerType() const ;           // 5.8\n  double pitch() const ;\n  int    mask() const;                      // 5.8\n  double pitchX() const ;                   // 5.6\n  double pitchY() const ;                   // 5.6\n  double offset() const ;\n  double offsetX() const ;                  // 5.6\n  double offsetY() const ;                  // 5.6\n  double width() const ;\n  double area() const ;\n  double diagPitch() const ;                // 5.6\n  double diagPitchX() const ;               // 5.6\n  double diagPitchY() const ;               // 5.6\n  double diagWidth() const ;                // 5.6 \n  double diagSpacing() const ;              // 5.6 \n  double spacing(int index) const ;\n  char*  spacingName(int index) const ;     // for CUT layer\n  int    spacingAdjacentCuts(int index) const ;   // 5.5 - for CUT layer\n  double spacingAdjacentWithin(int index) const ; // 5.5 - for CUT layer\n  double spacingArea(int index) const;            // 5.7 - for CUT layer\n  double spacingRangeMin(int index) const ;\n  double spacingRangeMax(int index) const ;\n  double spacingRangeInfluence(int index) const ;\n  double spacingRangeInfluenceMin(int index) const ;\n  double spacingRangeInfluenceMax(int index) const ;\n  double spacingRangeRangeMin(int index) const ;\n  double spacingRangeRangeMax(int index) const ;\n  double spacingLengthThreshold(int index) const;\n  double spacingLengthThresholdRangeMin(int index) const;\n  double spacingLengthThresholdRangeMax(int index) const;\n\n  // 5.7 Spacing endofline\n  double spacingEolWidth(int index) const;\n  double spacingEolWithin(int index) const;\n  double spacingParSpace(int index) const;\n  double spacingParWithin(int index) const;\n\n  // 5.7 Spacing Notch\n  double spacingNotchLength(int index) const;\n  double spacingEndOfNotchWidth(int index) const;\n  double spacingEndOfNotchSpacing(int index) const;\n  double spacingEndOfNotchLength(int index) const;\n\n  // 5.5 Minimum cut rules\n  int    numMinimumcut() const;\n  int    minimumcut(int index) const;\n  double minimumcutWidth(int index) const;\n  int    hasMinimumcutWithin(int index) const;          // 5.7\n  double minimumcutWithin(int index) const;             // 5.7\n  int    hasMinimumcutConnection(int index) const;      // FROMABOVE|FROMBELOW\n  const  char* minimumcutConnection(int index) const;   // FROMABOVE|FROMBELOW\n  int    hasMinimumcutNumCuts(int index) const;\n  double minimumcutLength(int index) const;\n  double minimumcutDistance(int index) const;\n\n  const char* direction() const ;\n  double resistance() const ;\n  double capacitance() const ;\n  double height() const ;\n  double wireExtension() const ;\n  double thickness() const ;\n  double shrinkage() const ;\n  double capMultiplier() const ;\n  double edgeCap() const ;\n  double antennaLength() const ;\n  double antennaArea() const ;\n  double currentDensityPoint() const ;\n  void currentDensityArray(int* numPoints,\n       double** widths, double** current) const ;\n  void capacitanceArray(int* numPoints,\n       double** widths, double** resValues) const ;\n  void resistanceArray(int* numPoints,\n       double** widths, double** capValues) const ;\n\n  int numAccurrentDensity() const;\n  lefiLayerDensity* accurrent(int index) const;\n  int numDccurrentDensity() const;\n  lefiLayerDensity* dccurrent(int index) const;\n\n  // 3/23/2000 - Wanda da Rosa.  The following are for 5.4 Antenna.\n  //             Only 5.4 or 5.3 are allowed in a lef file, but not both\n  void setAntennaAreaRatio(double value);\n  void setAntennaCumAreaRatio(double value);\n  void setAntennaAreaFactor(double value);\n  void setAntennaSideAreaRatio(double value);\n  void setAntennaCumSideAreaRatio(double value);\n  void setAntennaSideAreaFactor(double value);\n  void setAntennaValue(lefiAntennaEnum antennaType, double value);\n  void setAntennaDUO(lefiAntennaEnum antennaType);\n  void setAntennaPWL(lefiAntennaEnum antennaType, lefiAntennaPWL* pwl);\n  void setAntennaCumRoutingPlusCut();             // 5.7\n  void setAntennaGatePlusDiff(double value);      // 5.7\n  void setAntennaAreaMinusDiff(double value);     // 5.7\n  void addAntennaModel (int aOxide);  // 5.5\n\n  // 5.5\n  int numAntennaModel() const;\n  lefiAntennaModel* antennaModel(int index) const;\n\n  // The following is 8/21/01 5.4 enhancements \n  void setSlotWireWidth(double num);\n  void setSlotWireLength(double num);\n  void setSlotWidth(double num);\n  void setSlotLength(double num);\n  void setMaxAdjacentSlotSpacing(double num);\n  void setMaxCoaxialSlotSpacing(double num);\n  void setMaxEdgeSlotSpacing(double num);\n  void setSplitWireWidth(double num);\n  void setMinimumDensity(double num);\n  void setMaximumDensity(double num);\n  void setDensityCheckWindow(double length, double width);\n  void setDensityCheckStep(double num);\n  void setFillActiveSpacing(double num);\n\n  int hasSlotWireWidth() const;\n  int hasSlotWireLength() const;\n  int hasSlotWidth() const;\n  int hasSlotLength() const;\n  int hasMaxAdjacentSlotSpacing() const;\n  int hasMaxCoaxialSlotSpacing() const;\n  int hasMaxEdgeSlotSpacing() const;\n  int hasSplitWireWidth() const;\n  int hasMinimumDensity() const;\n  int hasMaximumDensity() const;\n  int hasDensityCheckWindow() const;\n  int hasDensityCheckStep() const;\n  int hasFillActiveSpacing() const;\n  int hasMaxwidth() const;                     // 5.5\n  int hasMinwidth() const;                     // 5.5\n  int hasMinstep() const;                      // 5.5\n  int hasProtrusion() const;                   // 5.5\n\n  double slotWireWidth() const;\n  double slotWireLength() const;\n  double slotWidth() const;\n  double slotLength() const;\n  double maxAdjacentSlotSpacing() const;\n  double maxCoaxialSlotSpacing() const;\n  double maxEdgeSlotSpacing() const;\n  double splitWireWidth() const;\n  double minimumDensity() const;\n  double maximumDensity() const;\n  double densityCheckWindowLength() const;\n  double densityCheckWindowWidth() const;\n  double densityCheckStep() const;\n  double fillActiveSpacing() const;\n  double maxwidth() const;                     // 5.5\n  double minwidth() const;                     // 5.5\n  double protrusionWidth1() const;             // 5.5\n  double protrusionLength() const;             // 5.5\n  double protrusionWidth2() const;             // 5.5\n\n  int    numMinstep() const;                   // 5.6\n  double minstep(int index) const;             // 5.5, 5.6 switch to multiple\n  int    hasMinstepType(int index) const;      // 5.6\n  char*  minstepType(int index) const;         // 5.6\n  int    hasMinstepLengthsum(int index) const; // 5.6\n  double minstepLengthsum(int index) const;    // 5.6\n  int    hasMinstepMaxedges(int index) const;  // 5.7\n  int    minstepMaxedges(int index) const;     // 5.7\n  int    hasMinstepMinAdjLength(int index) const;  // 5.7\n  double minstepMinAdjLength(int index) const;     // 5.7\n  int    hasMinstepMinBetLength(int index) const;  // 5.7\n  double minstepMinBetLength(int index) const;     // 5.7\n  int    hasMinstepXSameCorners(int index) const;  // 5.7\n\n  // 5.5 MINENCLOSEDAREA\n  int    numMinenclosedarea() const;\n  double minenclosedarea(int index) const;\n  int    hasMinenclosedareaWidth(int index) const;\n  double minenclosedareaWidth(int index) const;\n\n  // 5.5 SPACINGTABLE FOR LAYER ROUTING\n  int               numSpacingTable();\n  lefiSpacingTable* spacingTable(int index);\n\n  // 5.6 ENCLOSURE, PREFERENCLOSURE, RESISTANCEPERCUT & DIAGMINEDGELENGTH\n  int    numEnclosure() const;\n  int    hasEnclosureRule(int index) const;\n  char*  enclosureRule(int index) ;\n  double enclosureOverhang1(int index) const;\n  double enclosureOverhang2(int index) const;\n  int    hasEnclosureWidth(int index) const;\n  double enclosureMinWidth(int index) const;\n  int    hasEnclosureExceptExtraCut(int index) const;    // 5.7\n  double enclosureExceptExtraCut(int index) const;       // 5.7\n  int    hasEnclosureMinLength(int index) const;         // 5.7\n  double enclosureMinLength(int index) const;            // 5.7\n  int    numPreferEnclosure() const;\n  int    hasPreferEnclosureRule(int index) const;\n  char*  preferEnclosureRule(int index) ;\n  double preferEnclosureOverhang1(int index) const;\n  double preferEnclosureOverhang2(int index) const;\n  int    hasPreferEnclosureWidth(int index) const;\n  double preferEnclosureMinWidth(int index) const;\n  int    hasResistancePerCut() const;\n  double resistancePerCut() const;\n  int    hasDiagMinEdgeLength() const;\n  double diagMinEdgeLength() const;\n  int    numMinSize() const;\n  double minSizeWidth(int index) const;\n  double minSizeLength(int index) const;\n\n  // 5.7\n  int    hasMaxFloatingArea() const; \n  double maxFloatingArea() const;\n  int    hasArraySpacing() const;\n  int    hasLongArray() const;\n  int    hasViaWidth() const;\n  double viaWidth() const;\n  double cutSpacing() const;\n  int    numArrayCuts() const;\n  int    arrayCuts(int index) const;\n  double arraySpacing(int index) const;\n  int    hasSpacingTableOrtho() const; // SPACINGTABLE ORTHOGONAL FOR LAYER CUT\n  lefiOrthogonal *orthogonal() const;\n\n  void parse65nmRules();                  // 5.7\n  void parseLEF58Layer();                 // 5.8\n  int  need58PropsProcessing() const;     // 5.8\n\n  // Debug print\n  void print(FILE* f) const;\n\nprivate:\n  void parseSpacing(int index);\n  void parseMaxFloating(int index);\n  void parseArraySpacing(int index);\n  void parseMinstep(int index);\n  void parseAntennaCumRouting(int index);\n  void parseAntennaGatePlus(int index);\n  void parseAntennaAreaMinus(int index);\n  void parseAntennaAreaDiff(int index);\n\n  void parseLayerType(int index);         // 5.8\n  void parseLayerEnclosure(int index);    // 5.8\n  void parseLayerWidthTable(int indxe);   // 5.8\n\nprotected:\n  char* name_;\n  int nameSize_;\n  char* type_;\n  int typeSize_;\n  char* layerType_;   // 5.8 - POLYROUTING, MIMCAP, TSV, PASSIVATION, NWELL\n\n  int hasPitch_;\n  int hasMask_;                       // 5.8 native\n  int hasOffset_;\n  int hasWidth_;            \n  int hasArea_;\n  int hasSpacing_;\n  int hasDiagPitch_;                  // 5.6\n  int hasDiagWidth_;                  // 5.6\n  int hasDiagSpacing_;                // 5.6\n  int* hasSpacingName_;               // 5.5\n  int* hasSpacingLayerStack_;         // 5.7\n  int* hasSpacingAdjacent_;           // 5.5\n  int* hasSpacingRange_;              // pcr 409334\n  int* hasSpacingUseLengthThreshold_; // pcr 282799, due to mult. spacing allow\n  int* hasSpacingLengthThreshold_;    // pcr 409334\n  int* hasSpacingCenterToCenter_;     // 5.6\n  int* hasSpacingParallelOverlap_;    // 5.7\n  int* hasSpacingCutArea_;            // 5.7\n  int* hasSpacingEndOfLine_;          // 5.7\n  int* hasSpacingParellelEdge_;       // 5.7\n  int* hasSpacingTwoEdges_;           // 5.7\n  int* hasSpacingAdjacentExcept_;     // 5.7\n  int* hasSpacingSamenet_;            // 5.7\n  int* hasSpacingSamenetPGonly_;      // 5.7\n  int hasArraySpacing_;               // 5.7\n  int hasDirection_;\n  int hasResistance_;\n  int hasCapacitance_;\n  int hasHeight_;\n  int hasWireExtension_;\n  int hasThickness_;\n  int hasShrinkage_;\n  int hasCapMultiplier_;\n  int hasEdgeCap_;\n  int hasAntennaArea_;\n  int hasAntennaLength_;\n  int hasCurrentDensityPoint_;\n\n  double currentDensity_;\n  double pitchX_;                     // 5.6\n  double pitchY_;                     // 5.6\n  double offsetX_;                    // 5.6\n  double offsetY_;                    // 5.6\n  double diagPitchX_;                 // 5.6\n  double diagPitchY_;                 // 5.6\n  double diagWidth_;                  // 5.6\n  double diagSpacing_;                // 5.6\n  double width_;\n  double area_;\n  double wireExtension_;\n  int numSpacings_;\n  int spacingsAllocated_;\n  int maskNumber_;                     // 5.8\n  double* spacing_;          // for Cut & routing Layer, spacing is multiple\n  char**  spacingName_;\n  int*    spacingAdjacentCuts_;    // 5.5\n  double* spacingAdjacentWithin_;  // 5.5\n  double* spacingCutArea_;         // 5.7\n  double* rangeMin_;         // pcr 282799 & 408930, due to mult spacing allow\n  double* rangeMax_;         // pcr 282799 & 408930, due to mult spacing allow\n  double* rangeInfluence_;   // pcr 282799 & 408930, due to mult spacing allow\n  double* rangeInfluenceRangeMin_;          // pcr 388183 & 408930\n  double* rangeInfluenceRangeMax_;          // pcr 388183 & 408930\n  double* rangeRangeMin_;                   // pcr 408930\n  double* rangeRangeMax_;                   // pcr 408930\n  double* lengthThreshold_;                 // pcr 408930\n  double* lengthThresholdRangeMin_;         // pcr 408930\n  double* lengthThresholdRangeMax_;         // pcr 408930\n\n  // 5.5\n  int     numMinimumcut_;\n  int     minimumcutAllocated_;\n  int*    minimumcut_;                       // pcr 409334\n  double* minimumcutWidth_;                  // pcr 409334\n  int*    hasMinimumcutWithin_;              // 5.7\n  double* minimumcutWithin_;                 // 5.7\n  int*    hasMinimumcutConnection_;\n  char**  minimumcutConnection_;\n  int*    hasMinimumcutNumCuts_;\n  double* minimumcutLength_;\n  double* minimumcutDistance_;\n\n  double  maxwidth_;                          // 5.5\n  double  minwidth_;                          // 5.5\n  int     numMinenclosedarea_;                // 5.5\n  int     minenclosedareaAllocated_;          // 5.5\n  double* minenclosedarea_;                   // 5.5\n  double* minenclosedareaWidth_;              // 5.5\n  double  protrusionWidth1_;                  // 5.5\n  double  protrusionLength_;                  // 5.5\n  double  protrusionWidth2_;                  // 5.5\n\n  int     numMinstep_;                        // 5.6\n  int     numMinstepAlloc_;                   // 5.6\n  double* minstep_;                           // 5.6, switch to multiple\n  char**  minstepType_;                       // INSIDECORNER|OUTSIDECORNER|STEP\n  double* minstepLengthsum_; \n  int*    minstepMaxEdges_;                   // 5.7\n  double* minstepMinAdjLength_;               // 5.7\n  double* minstepMinBetLength_;               // 5.7\n  int*    minstepXSameCorners_;               // 5.7\n\n  char*  direction_;\n  double resistance_;\n  double capacitance_;\n  double height_;\n  double thickness_;\n  double shrinkage_;\n  double capMultiplier_;\n  double edgeCap_;\n  double antennaArea_;\n  double antennaLength_;\n\n  int numCurrentPoints_;\n  int currentPointsAllocated_;\n  double* currentWidths_;\n  double* current_;\n\n  int numCapacitancePoints_;\n  int capacitancePointsAllocated_;\n  double* capacitanceWidths_;\n  double* capacitances_;\n\n  int numResistancePoints_;\n  int resistancePointsAllocated_;\n  double* resistanceWidths_;\n  double* resistances_;\n\n  int numProps_;\n  int propsAllocated_;\n  char**  names_;\n  char**  values_;\n  double* dvalues_;\n  char*   types_;                     // I: integer, R: real, S:string\n                                      // Q: quotedstring\n  int numAccurrents_;                 // number of ACCURRENTDENSITY\n  int accurrentAllocated_;\n  lefiLayerDensity** accurrents_;\n  int numDccurrents_;                 // number of DCCURRENTDENSITY\n  int dccurrentAllocated_;\n  lefiLayerDensity** dccurrents_;\n  int numNums_;\n  int numAllocated_;\n  double* nums_;\n\n  // 3/23/2000 - Wanda da Rosa.  The following is for 5.4 ANTENNA.\n  //             Either 5.4 or 5.3 are allowed, not both\n  int hasAntennaAreaRatio_;\n  int hasAntennaDiffAreaRatio_;\n  int hasAntennaDiffAreaRatioPWL_;\n  int hasAntennaCumAreaRatio_;\n  int hasAntennaCumDiffAreaRatio_;\n  int hasAntennaCumDiffAreaRatioPWL_;\n  int hasAntennaAreaFactor_;\n  int hasAntennaAreaFactorDUO_;\n  int hasAntennaSideAreaRatio_;\n  int hasAntennaDiffSideAreaRatio_;\n  int hasAntennaDiffSideAreaRatioPWL_;\n  int hasAntennaCumSideAreaRatio_;\n  int hasAntennaCumDiffSideAreaRatio_;\n  int hasAntennaCumDiffSideAreaRatioPWL_;\n  int hasAntennaSideAreaFactor_;\n  int hasAntennaSideAreaFactorDUO_;\n\n  // 5.5 AntennaModel\n  lefiAntennaModel* currentAntennaModel_;\n  int numAntennaModel_;\n  int antennaModelAllocated_;\n  lefiAntennaModel** antennaModel_;\n\n  // 8/29/2001 - Wanda da Rosa.  The following is for 5.4 enhancements.\n  int hasSlotWireWidth_;\n  int hasSlotWireLength_;\n  int hasSlotWidth_;\n  int hasSlotLength_;\n  int hasMaxAdjacentSlotSpacing_;\n  int hasMaxCoaxialSlotSpacing_;\n  int hasMaxEdgeSlotSpacing_;\n  int hasSplitWireWidth_;\n  int hasMinimumDensity_;\n  int hasMaximumDensity_;\n  int hasDensityCheckWindow_;\n  int hasDensityCheckStep_;\n  int hasFillActiveSpacing_;\n  int hasTwoWidthPRL_;\n\n  double slotWireWidth_; \n  double slotWireLength_; \n  double slotWidth_; \n  double slotLength_; \n  double maxAdjacentSlotSpacing_; \n  double maxCoaxialSlotSpacing_; \n  double maxEdgeSlotSpacing_; \n  double splitWireWidth_; \n  double minimumDensity_; \n  double maximumDensity_; \n  double densityCheckWindowLength_; \n  double densityCheckWindowWidth_; \n  double densityCheckStep_; \n  double fillActiveSpacing_; \n\n  // 5.5 SPACINGTABLE\n  int numSpacingTable_;\n  int spacingTableAllocated_;\n  lefiSpacingTable** spacingTable_;\n\n  // 5.6\n  int numEnclosure_;\n  int enclosureAllocated_;\n  char** enclosureRules_;\n  double* overhang1_;\n  double* overhang2_;\n  double* encminWidth_;\n  double* cutWithin_;\n  double* minLength_;\n  int numPreferEnclosure_;\n  int preferEnclosureAllocated_;\n  char** preferEnclosureRules_;\n  double* preferOverhang1_;\n  double* preferOverhang2_;\n  double* preferMinWidth_;\n  double  resPerCut_;\n  double  diagMinEdgeLength_;\n  int numMinSize_;\n  double* minSizeWidth_;\n  double* minSizeLength_;\n\n  // 5.7\n  double* eolWidth_;\n  double* eolWithin_;\n  double* parSpace_;\n  double* parWithin_;\n  double  maxArea_;\n  int     hasLongArray_;\n  double  viaWidth_;\n  double  cutSpacing_;\n  int     numArrayCuts_;\n  int     arrayCutsAllocated_;\n  int*    arrayCuts_;\n  double* arraySpacings_;\n  int     hasSpacingTableOrtho_;\n  lefiOrthogonal* spacingTableOrtho_;\n  double* notchLength_;\n  double* endOfNotchWidth_;\n  double* minNotchSpacing_;\n  double* eonotchLength_;\n\n  int     lef58WidthTableOrthoValues_;\n  int     lef58WidthTableWrongDirValues_;\n  double* lef58WidthTableOrtho_;\n  double* lef58WidthTableWrongDir_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiMacro.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2017, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiMacro_h\n#define lefiMacro_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n#include \"lefiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefiObstruction {\npublic:\n  lefiObstruction();\n  void Init();\n\n  void Destroy();\n  ~lefiObstruction();\n\n  void clear();\n  void setGeometries(lefiGeometries* g);\n\n  lefiGeometries* geometries() const;\n\n  void print(FILE* f) const;\n\nprotected:\n\n  lefiGeometries* geometries_;\n};\n\n// 5.5\nclass lefiPinAntennaModel {\npublic:\n  lefiPinAntennaModel();\n  ~lefiPinAntennaModel();\n\n  void Init();\n  void clear();\n  void Destroy();\n\n  void setAntennaModel(int oxide);\n  void addAntennaGateArea(double value, const char* layer);\n  void addAntennaMaxAreaCar(double value, const char* layer);\n  void addAntennaMaxSideAreaCar(double value, const char* layer);\n  void addAntennaMaxCutCar(double value, const char* layer);\n  void setAntennaReturnFlag(int flag);\n\n  int hasAntennaGateArea() const;\n  int hasAntennaMaxAreaCar() const;\n  int hasAntennaMaxSideAreaCar() const;\n  int hasAntennaMaxCutCar() const;\n\n  char* antennaOxide() const;\n\n  int numAntennaGateArea() const;\n  double antennaGateArea(int index) const;\n  const char* antennaGateAreaLayer(int index) const;\n\n  int numAntennaMaxAreaCar() const;\n  double antennaMaxAreaCar(int index) const;\n  const char* antennaMaxAreaCarLayer(int index) const;\n\n  int numAntennaMaxSideAreaCar() const;\n  double antennaMaxSideAreaCar(int index) const;\n  const char* antennaMaxSideAreaCarLayer(int index) const;\n\n  int numAntennaMaxCutCar() const;\n  double antennaMaxCutCar(int index) const;\n  const char* antennaMaxCutCarLayer(int index) const;\n\n  int hasReturn() const;\n\nprotected:\n  char* oxide_;\n  int   hasReturn_;\n\n  int numAntennaGateArea_;\n  int antennaGateAreaAllocated_;\n  double* antennaGateArea_;\n  char** antennaGateAreaLayer_;\n\n  int numAntennaMaxAreaCar_;\n  int antennaMaxAreaCarAllocated_;\n  double* antennaMaxAreaCar_;\n  char** antennaMaxAreaCarLayer_;\n\n  int numAntennaMaxSideAreaCar_;\n  int antennaMaxSideAreaCarAllocated_;\n  double* antennaMaxSideAreaCar_;\n  char** antennaMaxSideAreaCarLayer_;\n\n  int numAntennaMaxCutCar_;\n  int antennaMaxCutCarAllocated_;\n  double* antennaMaxCutCar_;\n  char** antennaMaxCutCarLayer_;\n};\n\nclass lefiPin {\npublic:\n  lefiPin();\n  void Init();\n\n  void Destroy();\n  ~lefiPin();\n\n  void clear();\n  void bump(char** array, int len, int* size);\n  void setName(const char* name);\n  void addPort(lefiGeometries* g);\n  void addForeign(const char* name, int hasPnt, double x, double y, int orient);\n  void setLEQ(const char* name);\n  void setDirection(const char* name);\n  void setUse(const char* name);\n  void setShape(const char* name);\n  void setMustjoin(const char* name);\n  void setOutMargin(double high, double low);\n  void setOutResistance(double high, double low);\n  void setInMargin(double high, double low);\n  void setPower(double power);\n  void setLeakage(double current);\n  void setMaxload(double capacitance);\n  void setMaxdelay(double delayTime);\n  void setCapacitance(double capacitance);\n  void setResistance(double resistance);\n  void setPulldownres(double resistance);\n  void setTieoffr(double resistance);\n  void setVHI(double voltage);\n  void setVLO(double voltage);\n  void setRiseVoltage(double voltage);\n  void setFallVoltage(double voltage);\n  void setRiseThresh(double capacitance);\n  void setFallThresh(double capacitance);\n  void setRiseSatcur(double current);\n  void setFallSatcur(double current);\n  void setCurrentSource(const char* name);\n  void setTables(const char* highName, const char* lowName);\n  void setProperty(const char* name, const char* value, const char type);\n  void setNumProperty(const char* name, double d, const char* value,\n                      const char type);\n  void addAntennaModel(int oxide);       // 5.5\n  void addAntennaSize(double value, const char* layer);\n  void addAntennaMetalArea(double value, const char* layer);\n  void addAntennaMetalLength(double value, const char* layer);\n  void addAntennaPartialMetalArea(double value, const char* layer);\n  void addAntennaPartialMetalSideArea(double value, const char* layer);\n  void addAntennaGateArea(double value, const char* layer);\n  void addAntennaDiffArea(double value, const char* layer);\n  void addAntennaMaxAreaCar(double value, const char* layer);\n  void addAntennaMaxSideAreaCar(double value, const char* layer);\n  void addAntennaPartialCutArea(double value, const char* layer);\n  void addAntennaMaxCutCar(double value, const char* layer);\n  void setRiseSlewLimit(double value);\n  void setFallSlewLimit(double value);\n  void setTaperRule(const char* name);\n  void setNetExpr(const char* name);                    // 5.6\n  void setSupplySensitivity(const char* pinName);       // 5.6\n  void setGroundSensitivity(const char* pinName);       // 5.6\n  void bumpProps();\n\n  int hasForeign() const;\n  int hasForeignOrient(int index = 0) const;\n  int hasForeignPoint(int index = 0) const;\n  int hasLEQ() const;\n  int hasDirection() const;\n  int hasUse() const;\n  int hasShape() const;\n  int hasMustjoin() const;\n  int hasOutMargin() const; \n  int hasOutResistance() const;\n  int hasInMargin() const;\n  int hasPower() const;\n  int hasLeakage() const;\n  int hasMaxload() const;\n  int hasMaxdelay() const;\n  int hasCapacitance() const;\n  int hasResistance() const;\n  int hasPulldownres() const;\n  int hasTieoffr() const;\n  int hasVHI() const;\n  int hasVLO() const;\n  int hasRiseVoltage() const;\n  int hasFallVoltage() const;\n  int hasRiseThresh() const;\n  int hasFallThresh() const;\n  int hasRiseSatcur() const;\n  int hasFallSatcur() const;\n  int hasCurrentSource() const;\n  int hasTables() const;\n  int hasAntennaSize() const;\n  int hasAntennaMetalArea() const;\n  int hasAntennaMetalLength() const;\n  int hasAntennaPartialMetalArea() const;\n  int hasAntennaPartialMetalSideArea() const;\n  int hasAntennaPartialCutArea() const;\n  int hasAntennaDiffArea() const;\n  int hasAntennaModel() const;         // 5.5\n  int hasTaperRule() const;\n  int hasRiseSlewLimit() const;\n  int hasFallSlewLimit() const;\n  int hasNetExpr() const;              // 5.6\n  int hasSupplySensitivity() const;    // 5.6\n  int hasGroundSensitivity() const;    // 5.6\n\n  const char* name() const;\n\n  int numPorts() const;\n  lefiGeometries* port(int index) const;\n\n  int numForeigns() const;\n  const char* foreignName(int index = 0) const;\n  const char* taperRule() const;\n  int foreignOrient(int index = 0) const;\n  const char* foreignOrientStr(int index = 0) const;\n  double foreignX(int index = 0) const;\n  double foreignY(int index = 0) const;\n  const char* LEQ() const;\n  const char* direction() const;\n  const char* use() const;\n  const char* shape() const;\n  const char* mustjoin() const;\n  double outMarginHigh() const;\n  double outMarginLow() const;\n  double outResistanceHigh() const;\n  double outResistanceLow() const;\n  double inMarginHigh() const;\n  double inMarginLow() const;\n  double power() const;\n  double leakage() const;\n  double maxload() const;\n  double maxdelay() const;\n  double capacitance() const;\n  double resistance() const;\n  double pulldownres() const;\n  double tieoffr() const;\n  double VHI() const;\n  double VLO() const;\n  double riseVoltage() const;\n  double fallVoltage() const;\n  double riseThresh() const;\n  double fallThresh() const;\n  double riseSatcur() const;\n  double fallSatcur() const;\n  double riseSlewLimit() const;\n  double fallSlewLimit() const;\n  const char* currentSource() const;\n  const char* tableHighName() const;\n  const char* tableLowName() const;\n\n  int numAntennaSize() const;\n  double antennaSize(int index) const;\n  const char* antennaSizeLayer(int index) const;\n\n  int numAntennaMetalArea() const;\n  double antennaMetalArea(int index) const;\n  const char* antennaMetalAreaLayer(int index) const;\n\n  int numAntennaMetalLength() const;\n  double antennaMetalLength(int index) const;\n  const char* antennaMetalLengthLayer(int index) const;\n\n  int numAntennaPartialMetalArea() const;\n  double antennaPartialMetalArea(int index) const;\n  const char* antennaPartialMetalAreaLayer(int index) const;\n\n  int numAntennaPartialMetalSideArea() const;\n  double antennaPartialMetalSideArea(int index) const;\n  const char* antennaPartialMetalSideAreaLayer(int index) const;\n\n  int numAntennaPartialCutArea() const;\n  double antennaPartialCutArea(int index) const;\n  const char* antennaPartialCutAreaLayer(int index) const;\n\n  int numAntennaDiffArea() const;\n  double antennaDiffArea(int index) const;\n  const char* antennaDiffAreaLayer(int index) const;\n\n  // 5.6\n  const char* netExpr() const;\n  const char* supplySensitivity() const;\n  const char* groundSensitivity() const;\n\n  // 5.5\n  int numAntennaModel() const;\n  lefiPinAntennaModel* antennaModel(int index) const;\n\n  int    numProperties() const;\n  const  char* propName(int index) const;\n  const  char* propValue(int index) const;\n  double propNum(int index) const;\n  const  char  propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n\n  void print(FILE* f) const ;\n\nprotected:\n  int   nameSize_;\n  char* name_;\n\n  char hasLEQ_;\n  char hasDirection_;\n  char hasUse_;\n  char hasShape_;\n  char hasMustjoin_;\n  char hasOutMargin_;\n  char hasOutResistance_;\n  char hasInMargin_;\n  char hasPower_;\n  char hasLeakage_;\n  char hasMaxload_;\n  char hasMaxdelay_;\n  char hasCapacitance_;\n  char hasResistance_;\n  char hasPulldownres_;\n  char hasTieoffr_;\n  char hasVHI_; \n  char hasVLO_;\n  char hasRiseVoltage_;\n  char hasFallVoltage_;\n  char hasRiseThresh_;\n  char hasFallThresh_;\n  char hasRiseSatcur_;\n  char hasFallSatcur_;\n  char hasCurrentSource_;\n  char hasTables_;\n  char hasAntennasize_;\n  char hasRiseSlewLimit_;\n  char hasFallSlewLimit_;\n\n  int     numForeigns_;\n  int     foreignAllocated_;\n  int*    hasForeignOrient_;\n  int*    hasForeignPoint_;\n  int*    foreignOrient_;\n  double* foreignX_;\n  double* foreignY_;\n  char**  foreign_;\n\n  int    LEQSize_;\n  char*  LEQ_;\n  int    mustjoinSize_;\n  char*  mustjoin_;\n  double outMarginH_;\n  double outMarginL_;\n  double outResistanceH_;\n  double outResistanceL_;\n  double inMarginH_;\n  double inMarginL_;\n  double power_;\n  double leakage_;\n  double maxload_;\n  double maxdelay_;\n  double capacitance_;\n  double resistance_;\n  double pulldownres_;\n  double tieoffr_;\n  double VHI_;\n  double VLO_;\n  double riseVoltage_;\n  double fallVoltage_;\n  double riseThresh_;\n  double fallThresh_;\n  double riseSatcur_;\n  double fallSatcur_;\n  int lowTableSize_;\n  char* lowTable_;\n  int highTableSize_;\n  char* highTable_;\n  double riseSlewLimit_;\n  double fallSlewLimit_;\n\n  // 5.5 AntennaModel\n  int numAntennaModel_;\n  int antennaModelAllocated_;\n  int curAntennaModelIndex_;     // save the current index of the antenna\n  lefiPinAntennaModel** antennaModel_;\n\n  int numAntennaSize_;\n  int antennaSizeAllocated_;\n  double* antennaSize_;\n  char** antennaSizeLayer_;\n\n  int numAntennaMetalArea_;\n  int antennaMetalAreaAllocated_;\n  double* antennaMetalArea_;\n  char** antennaMetalAreaLayer_;\n\n  int numAntennaMetalLength_;\n  int antennaMetalLengthAllocated_;\n  double* antennaMetalLength_;\n  char** antennaMetalLengthLayer_;\n\n  int numAntennaPartialMetalArea_;\n  int antennaPartialMetalAreaAllocated_;\n  double* antennaPartialMetalArea_;\n  char** antennaPartialMetalAreaLayer_;\n\n  int numAntennaPartialMetalSideArea_;\n  int antennaPartialMetalSideAreaAllocated_;\n  double* antennaPartialMetalSideArea_;\n  char** antennaPartialMetalSideAreaLayer_;\n\n  int numAntennaPartialCutArea_;\n  int antennaPartialCutAreaAllocated_;\n  double* antennaPartialCutArea_;\n  char** antennaPartialCutAreaLayer_;\n\n  int numAntennaDiffArea_;\n  int antennaDiffAreaAllocated_;\n  double* antennaDiffArea_;\n  char** antennaDiffAreaLayer_;\n\n  char* taperRule_;\n\n  char* netEpxr_;\n  char* ssPinName_;\n  char* gsPinName_;\n\n  char direction_[32];\n  char use_[12];\n  char shape_[12];\n  char currentSource_[12];\n\n  int numProperties_;\n  int propertiesAllocated_;\n  char** propNames_;\n  char** propValues_;\n  double* propNums_;\n  char*  propTypes_;\n\n  int numPorts_;\n  int portsAllocated_;\n  lefiGeometries** ports_;\n};\n\n// 5.6\nclass lefiDensity {\npublic:\n  lefiDensity();\n  void Init();\n\n  void Destroy();\n  ~lefiDensity();\n\n  void clear();\n  void addLayer(const char* name);\n  void addRect(double x1, double y1, double x2, double y2, double value);\n\n  int numLayer() const;\n  char* layerName(int index) const;\n  int numRects(int index) const;\n  lefiGeomRect getRect(int index, int rectIndex) const;\n  double densityValue(int index, int rectIndex) const;\n\n  void print(FILE* f) const;\n\nprotected:\n  int    numLayers_;\n  int    layersAllocated_;\n  char** layerName_;\n  int*   numRects_;\n  int*   rectsAllocated_;\n  struct lefiGeomRect** rects_;\n  double**       densityValue_;\n};\n\nclass lefiMacro {\npublic:\n  lefiMacro();\n  void Init();\n\n  void Destroy();\n  ~lefiMacro();\n\n  void clear();\n  void bump(char** array, int len, int* size);\n  void setName(const char* name);\n  void setGenerator(const char* name);\n  void setGenerate(const char* name1, const char* name2);\n  void setPower(double d);\n  void setOrigin(double x, double y);\n  void setClass(const char* name);\n  void setSource(const char* name);\n  void setEEQ(const char* name);\n  void setLEQ(const char* name);\n  void setClockType(const char* name);\n  void setProperty(const char* name, const char* value, const char type);\n  void setNumProperty(const char* name, double d, const char* value,\n                      const char type);\n  void bumpProps();\n\n  // orient=-1 means no orient was specified.\n  void addForeign(const char* name, int hasPnt,\n           double x, double y, int orient);\n\n  void setXSymmetry();\n  void setYSymmetry();\n  void set90Symmetry();\n  void setSiteName(const char* name);\n  void setSitePattern(lefiSitePattern* p);\n  void setSize(double x, double y);\n  void setBuffer();\n  void setInverter();\n  void setFixedMask(int isFixedMask = 0);\n\n  int hasClass() const;\n  int hasGenerator() const;\n  int hasGenerate() const;\n  int hasPower() const;\n  int hasOrigin() const;\n  int hasEEQ() const;\n  int hasLEQ() const;\n  int hasSource() const;\n  int hasXSymmetry() const;\n  int hasYSymmetry() const;\n  int has90Symmetry() const;\n  int hasSiteName() const;\n  int hasSitePattern() const;\n  int hasSize() const;\n  int hasForeign() const;\n  int hasForeignOrigin(int index = 0) const;\n  int hasForeignOrient(int index = 0) const;\n  int hasForeignPoint(int index = 0) const;\n  int hasClockType() const;\n  int isBuffer() const;\n  int isInverter() const;\n  int isFixedMask() const;\n\n  int numSitePattern() const;\n  int numProperties() const;\n  const char* propName(int index) const;\n  const char* propValue(int index) const;\n  double propNum(int index) const;\n  const char propType(int index) const;\n  int  propIsNumber(int index) const;\n  int  propIsString(int index) const;\n\n  const char* name() const;\n  const char* macroClass() const;\n  const char* generator() const;\n  const char* EEQ() const;\n  const char* LEQ() const;\n  const char* source() const;\n  const char* clockType() const;\n  double originX() const;\n  double originY() const;\n  double power() const;\n  void generate(char** name1, char** name2) const;\n  lefiSitePattern* sitePattern(int index) const;\n  const char* siteName() const;\n  double sizeX() const;\n  double sizeY() const;\n  int numForeigns() const;\n  int foreignOrient(int index = 0) const;\n  const char*  foreignOrientStr(int index = 0) const;\n  double foreignX(int index = 0) const;\n  double foreignY(int index = 0) const;\n  const char* foreignName(int index = 0) const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int nameSize_;\n  char* name_;\n  char macroClass_[32];\n  char source_[12];\n\n  int generatorSize_;\n  char* generator_;\n\n  char hasClass_;\n  char hasGenerator_;\n  char hasGenerate_;\n  char hasPower_;\n  char hasOrigin_;\n  char hasSource_;\n  char hasEEQ_;\n  char hasLEQ_;\n  char hasSymmetry_;  // X=1  Y=2  R90=4  (can be combined)\n  char hasSiteName_;\n  char hasSize_;\n  char hasClockType_;\n  char isBuffer_;\n  char isInverter_;\n\n  char* EEQ_;\n  int EEQSize_;\n  char* LEQ_;\n  int LEQSize_;\n  char* gen1_;\n  int gen1Size_;\n  char* gen2_;\n  int gen2Size_;\n  double power_;\n  double originX_;\n  double originY_;\n  double sizeX_;\n  double sizeY_;\n\n  int numSites_;\n  int sitesAllocated_;\n  lefiSitePattern** pattern_;\n\n  int numForeigns_;\n  int foreignAllocated_;\n  int*  hasForeignOrigin_;\n  int*  hasForeignPoint_;\n  int*  foreignOrient_;\n  double* foreignX_;\n  double* foreignY_;\n  char** foreign_;\n\n  int siteNameSize_;\n  char* siteName_;\n\n  char* clockType_;\n  int clockTypeSize_;\n\n  int numProperties_;\n  int propertiesAllocated_;\n  char** propNames_;\n  char** propValues_;\n  double* propNums_;\n  char*  propTypes_;\n\n  int isFixedMask_;\n};\n\nclass lefiTiming {\npublic:\n  lefiTiming();\n  void Init();\n\n  void Destroy();\n  ~lefiTiming();\n\n  void addRiseFall(const char* risefall, double one, double two);\n  void addRiseFallVariable(double one, double two);\n  void addRiseFallSlew(double one, double two, double three, double four);\n  void addRiseFallSlew2(double one, double two, double three);\n  void setRiseRS(double one, double two);\n  void setFallRS(double one, double two);\n  void setRiseCS(double one, double two);\n  void setFallCS(double one, double two);\n  void setRiseAtt1(double one, double two);\n  void setFallAtt1(double one, double two);\n  void setRiseTo(double one, double two);\n  void setFallTo(double one, double two);\n  void addUnateness(const char* typ);\n  void setStable(double one, double two, const char* typ);\n  void addTableEntry(double one, double two, double three);\n  void addTableAxisNumber(double one);\n  void addFromPin(const char* name);\n  void addToPin(const char* name);\n  void addDelay(const char* risefall, const char* unateness, double one,\n         double two, double three);\n  void addTransition(const char* risefall, const char* unateness, double one,\n         double two, double three);\n  // addSDF2Pins & addSDF1Pin are for 5.1\n  void addSDF2Pins(const char* trigType, const char* fromTrig,\n         const char* toTrig, double one, double two, double three);\n  void addSDF1Pin(const char* trigType, double one, double two, double three);\n  void setSDFcondStart(const char* condStart);\n  void setSDFcondEnd(const char* condEnd);\n  void setSDFcond(const char* cond);\n  int hasData();\n  void clear();\n\n  int numFromPins();\n  const char* fromPin(int index);\n  int numToPins();\n  const char* toPin(int index);\n  int hasTransition();\n  int hasDelay();\n  int hasRiseSlew();\n  int hasRiseSlew2();\n  int hasFallSlew();\n  int hasFallSlew2();\n  int hasRiseIntrinsic();\n  int hasFallIntrinsic();\n  int numOfAxisNumbers();\n  double* axisNumbers();\n  int numOfTableEntries();\n  void tableEntry(int num, double* one, double* two, double* three);\n  const char* delayRiseOrFall();\n  const char* delayUnateness();\n  double delayTableOne();\n  double delayTableTwo();\n  double delayTableThree();\n  const char* transitionRiseOrFall();\n  const char* transitionUnateness();\n  double transitionTableOne();\n  double transitionTableTwo();\n  double transitionTableThree();\n  double fallIntrinsicOne();\n  double fallIntrinsicTwo();\n  double fallIntrinsicThree();\n  double fallIntrinsicFour();\n  double riseIntrinsicOne();\n  double riseIntrinsicTwo();\n  double riseIntrinsicThree();\n  double riseIntrinsicFour();\n  double fallSlewOne();\n  double fallSlewTwo();\n  double fallSlewThree();\n  double fallSlewFour();\n  double fallSlewFive();\n  double fallSlewSix();\n  double fallSlewSeven();\n  double riseSlewOne();\n  double riseSlewTwo();\n  double riseSlewThree();\n  double riseSlewFour();\n  double riseSlewFive();\n  double riseSlewSix();\n  double riseSlewSeven();\n  int hasRiseRS();\n  double riseRSOne();\n  double riseRSTwo();\n  int hasRiseCS();\n  double riseCSOne();\n  double riseCSTwo();\n  int hasFallRS();\n  double fallRSOne();\n  double fallRSTwo();\n  int hasFallCS();\n  double fallCSOne();\n  double fallCSTwo();\n  int hasUnateness();\n  const char* unateness();\n  int hasRiseAtt1();\n  double riseAtt1One();\n  double riseAtt1Two();\n  int hasFallAtt1();\n  double fallAtt1One();\n  double fallAtt1Two();\n  int hasFallTo();\n  double fallToOne();\n  double fallToTwo();\n  int hasRiseTo();\n  double riseToOne();\n  double riseToTwo();\n  int hasStableTiming();\n  double stableSetup();\n  double stableHold();\n  const char* stableRiseFall();\n  // The following are for 5.1\n  int hasSDFonePinTrigger();\n  int hasSDFtwoPinTrigger();\n  int hasSDFcondStart();\n  int hasSDFcondEnd();\n  int hasSDFcond();\n  const char* SDFonePinTriggerType();\n  const char* SDFtwoPinTriggerType();\n  const char* SDFfromTrigger();\n  const char* SDFtoTrigger();\n  double SDFtriggerOne();\n  double SDFtriggerTwo();\n  double SDFtriggerThree();\n  const char* SDFcondStart();\n  const char* SDFcondEnd();\n  const char* SDFcond();\n\nprotected:\n  int numFrom_;\n  char** from_;\n  int fromAllocated_;\n  int numTo_;\n  char** to_;\n  int toAllocated_;\n\n  int hasTransition_;\n  int hasDelay_;\n  int hasRiseSlew_;\n  int hasRiseSlew2_;\n  int hasFallSlew_;\n  int hasFallSlew2_;\n  int hasRiseIntrinsic_;\n  int hasFallIntrinsic_;\n  int hasRiseRS_;\n  int hasRiseCS_;\n  int hasFallRS_;\n  int hasFallCS_;\n  int hasUnateness_;\n  int hasFallAtt1_;\n  int hasRiseAtt1_;\n  int hasFallTo_;\n  int hasRiseTo_;\n  int hasStableTiming_;\n  int hasSDFonePinTrigger_;\n  int hasSDFtwoPinTrigger_;\n  int hasSDFcondStart_;\n  int hasSDFcondEnd_;\n  int hasSDFcond_;\n  int nowRise_;\n\n  int numOfAxisNumbers_;\n  double* axisNumbers_;\n  int axisNumbersAllocated_;\n\n  int numOfTableEntries_;\n  int tableEntriesAllocated_;\n  double* table_;  // three numbers per entry \n\n  char* delayRiseOrFall_;\n  char* delayUnateness_;\n  double delayTableOne_;\n  double delayTableTwo_;\n  double delayTableThree_;\n  char* transitionRiseOrFall_;\n  char* transitionUnateness_;\n  double transitionTableOne_;\n  double transitionTableTwo_;\n  double transitionTableThree_;\n  double riseIntrinsicOne_;\n  double riseIntrinsicTwo_;\n  double riseIntrinsicThree_;\n  double riseIntrinsicFour_;\n  double fallIntrinsicOne_;\n  double fallIntrinsicTwo_;\n  double fallIntrinsicThree_;\n  double fallIntrinsicFour_;\n  double riseSlewOne_;\n  double riseSlewTwo_;\n  double riseSlewThree_;\n  double riseSlewFour_;\n  double riseSlewFive_;\n  double riseSlewSix_;\n  double riseSlewSeven_;\n  double fallSlewOne_;\n  double fallSlewTwo_;\n  double fallSlewThree_;\n  double fallSlewFour_;\n  double fallSlewFive_;\n  double fallSlewSix_;\n  double fallSlewSeven_;\n  double riseRSOne_;\n  double riseRSTwo_;\n  double riseCSOne_;\n  double riseCSTwo_;\n  double fallRSOne_;\n  double fallRSTwo_;\n  double fallCSOne_;\n  double fallCSTwo_;\n  char* unateness_;\n  double riseAtt1One_;\n  double riseAtt1Two_;\n  double fallAtt1One_;\n  double fallAtt1Two_;\n  double fallToOne_;\n  double fallToTwo_;\n  double riseToOne_;\n  double riseToTwo_;\n  double stableSetup_;\n  double stableHold_;\n  char* stableRiseFall_;\n  char* SDFtriggerType_;\n  char* SDFfromTrigger_;\n  char* SDFtoTrigger_;\n  double SDFtriggerTableOne_;\n  double SDFtriggerTableTwo_;\n  double SDFtriggerTableThree_;\n  char* SDFcondStart_;\n  char* SDFcondEnd_;\n  char* SDFcond_;\n};\n\n// 5.8 \nclass lefiMacroSite {\npublic:\n                        lefiMacroSite(const char *name, const lefiSitePattern* pattern);\n\n  const char            *siteName() const;\n  const lefiSitePattern *sitePattern() const;\n\nprotected:\n  const char            *siteName_;\n  const lefiSitePattern *sitePattern_;\n};\n\nclass lefiMacroForeign {\npublic:\n             lefiMacroForeign(const char *name,\n                              int        hasPts,\n                              double     x,\n                              double     y,\n                              int        hasOrient,\n                              int        orient);\n\n  const char *cellName() const;\n  int        cellHasPts() const;\n  double     px() const;\n  double     py() const;\n  int        cellHasOrient() const;\n  int        cellOrient() const;\n\nprotected:\n  const char *cellName_;\n  int        cellHasPts_;\n  double     px_;\n  double     py_;\n  int        cellHasOrient_;\n  int        cellOrient_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiMisc.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2014, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiMisc_h\n#define lefiMisc_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// The different types of items in a geometry list.\n\nstruct lefiGeomRect {\n      double xl;\n      double yl;\n      double xh;\n      double yh;\n      int    colorMask;\n};\n\nstruct lefiGeomRectIter {\n  double xl;\n  double yl;\n  double xh;\n  double yh;\n  double xStart;\n  double yStart;\n  double xStep;\n  double yStep;\n  int    colorMask;\n};\n\nstruct lefiGeomPath {\n  int     numPoints;\n  double* x;\n  double* y;\n  int     colorMask;\n};\n\nstruct lefiGeomPathIter {\n  int     numPoints;\n  double* x;\n  double* y;\n  double xStart;\n  double yStart;\n  double xStep;\n  double yStep;\n  int    colorMask;\n};\n\nstruct lefiGeomPolygon {\n  int     numPoints;\n  double* x;\n  double* y;\n  int     colorMask;\n};\n\nstruct lefiGeomPolygonIter {\n  int numPoints;\n  double* x;\n  double* y;\n  double xStart;\n  double yStart;\n  double xStep;\n  double yStep;\n  int    colorMask;\n};\n\nenum lefiGeomEnum {\n  lefiGeomUnknown = 0,\n  lefiGeomLayerE,\n  lefiGeomLayerExceptPgNetE,\n  lefiGeomLayerMinSpacingE,\n  lefiGeomLayerRuleWidthE,\n  lefiGeomWidthE,\n  lefiGeomPathE,\n  lefiGeomPathIterE,\n  lefiGeomRectE,\n  lefiGeomRectIterE,\n  lefiGeomPolygonE,\n  lefiGeomPolygonIterE,\n  lefiGeomViaE,\n  lefiGeomViaIterE,\n  lefiGeomClassE,\n  lefiGeomEnd\n};\n\nstruct lefiGeomVia {\n  char*  name;\n  double x;\n  double y;\n  int    topMaskNum;\n  int    cutMaskNum;\n  int    bottomMaskNum;\n};\n\nstruct lefiGeomViaIter {\n  char*  name;\n  double x;\n  double y;\n  double xStart;\n  double yStart;\n  double xStep;\n  double yStep;\n  int    topMaskNum;\n  int    cutMaskNum;\n  int    bottomMaskNum;\n};\n\nclass lefiGeometries {\npublic:\n  lefiGeometries();\n  void Init();\n\n  void Destroy();\n  ~lefiGeometries();\n\n  void clear();\n  void clearPolyItems();\n  void add(void* v, lefiGeomEnum e);\n  void addLayer(const char* name);\n  void addLayerExceptPgNet();                     // 5.7\n  void addLayerMinSpacing(double spacing);\n  void addLayerRuleWidth(double width);\n  void addClass(const char* name);\n  void addWidth(double w);\n  void addPath(int colorMask);\n  void addPathIter(int colorMask);\n/*  pcr 481783 & 560504\n*/\n  void addRect(int colorMask, double xl, double yl, double xh, double yh);\n  void addRectIter(int colorMask, double xl, double yl, double xh, double yh);\n  void addPolygon(int colorMask = 0);\n  void addPolygonIter(int colorMask);\n  void addVia(int viaMasks,\n              double x, double y, const char* name);\n  void addViaIter(int viaMasks,\n                  double x, double y, const char* name);\n  void addStepPattern(double xStart, double yStart,\n                      double xStep, double yStep);\n  void startList(double x, double y);\n  void addToList(double x, double y);\n\n  int numItems() const;\n  lefiGeomEnum itemType(int index) const;\n  lefiGeomRect* getRect(int index) const;\n  lefiGeomRectIter* getRectIter(int index) const;\n  lefiGeomPath* getPath(int index) const;\n  lefiGeomPathIter* getPathIter(int index) const;\n  int    hasLayerExceptPgNet(int index) const ;     // 5.7\n  char*  getLayer(int index) const;\n  double getLayerMinSpacing(int index) const;\n  double getLayerRuleWidth(int index) const;\n  double getWidth(int index) const;\n  lefiGeomPolygon* getPolygon(int index) const;\n  lefiGeomPolygonIter* getPolygonIter(int index) const;\n  char*  getClass(int index) const;\n  lefiGeomVia* getVia(int index) const;\n  lefiGeomViaIter* getViaIter(int index) const;\n\n  void print(FILE* f) const;\n\nprotected:\n\n  int numItems_;\n  int itemsAllocated_;\n  lefiGeomEnum* itemType_;\n  void** items_;\n\n  int numPoints_;\n  int pointsAllocated_;\n  double* x_;\n  double* y_;\n\n  double xStart_;\n  double yStart_;\n  double xStep_;\n  double yStep_;\n};\n\nclass lefiSpacing {\npublic:\n  lefiSpacing();\n  void Init();\n\n  void Destroy();\n  ~lefiSpacing();\n\n  lefiSpacing* clone();\n\n  void set(const char* name1, const char* name2, double num, int hasStack);\n\n  int hasStack() const;\n\n  const char* name1() const;\n  const char* name2() const;\n  double distance() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int    name1Size_;\n  int    name2Size_;\n  char*  name1_;\n  char*  name2_;\n  double distance_;\n  int    hasStack_;\n};\n\nclass lefiIRDrop {\npublic:\n  lefiIRDrop();\n  void Init();\n\n  void Destroy();\n  ~lefiIRDrop();\n\n  void clear();\n  void setTableName(const char* name);\n  void setValues(double name1, double name2);\n\n  const char* name() const;\n  double value1(int index) const;\n  double value2(int index) const;\n\n  int numValues() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int     nameSize_;\n  int     value1Size_;\n  int     value2Size_;\n  int     numValues_;\n  int     valuesAllocated_;\n  char*   name_;\n  double* value1_;\n  double* value2_;\n};\n\nclass lefiMinFeature {\npublic:\n  lefiMinFeature();\n  void Init();\n\n  void Destroy();\n  ~lefiMinFeature();\n\n  void set(double one, double two);\n\n  double one() const;\n  double two() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  double one_;\n  double two_;\n};\n\nclass lefiSite {\npublic:\n  lefiSite();\n  void Init();\n\n  void Destroy();\n  ~lefiSite();\n\n  void setName(const char* name);\n  void setClass(const char* cls);\n  void setSize(double x, double y);\n  void setXSymmetry();\n  void setYSymmetry();\n  void set90Symmetry();\n  void addRowPattern(const char* name, int orient);\n\n  const char* name() const;\n  int hasClass() const;\n  const char* siteClass() const;\n  double sizeX() const;\n  double sizeY() const;\n  int hasSize() const;\n  int hasXSymmetry() const;\n  int hasYSymmetry() const;\n  int has90Symmetry() const;\n  int hasRowPattern() const;                 // 5.6\n  int numSites() const;                      // 5.6\n  char* siteName(int index) const;           // 5.6\n  int   siteOrient(int index) const;         // 5.6\n  char* siteOrientStr(int index) const;      // 5.6\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int    nameSize_;\n  char*  name_;\n  int    hasClass_;\n  char   siteClass_[8];\n  double sizeX_;\n  double sizeY_;\n  int    hasSize_;\n  int    symmetry_;   // bit 0-x   bit 1-y   bit 2-90\n\n  int    numRowPattern_;         // 5.6 ROWPATTERN\n  int    rowPatternAllocated_;\n  char** siteNames_;\n  int*   siteOrients_;\n};\n\nclass lefiSitePattern {\npublic:\n  lefiSitePattern();\n  void Init();\n\n  void Destroy();\n  ~lefiSitePattern();\n\n  void set(const char* name, double x, double y, int orient,\n       double xStart, double yStart, double xStep, double yStep);\n\n  const  char* name() const;\n  int    orient() const;\n  const  char* orientStr() const;\n  double x() const;\n  double y() const;\n  int    hasStepPattern() const;    // 5.6\n  double xStart() const;\n  double yStart() const;\n  double xStep() const;\n  double yStep() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int    nameSize_;\n  char*  name_;\n  int    orient_;\n  double x_;\n  double y_;\n  double xStart_;\n  double yStart_;\n  double xStep_;\n  double yStep_;\n};\n\nclass lefiTrackPattern {\npublic:\n  lefiTrackPattern();\n  void Init();\n\n  void Destroy();\n  ~lefiTrackPattern();\n\n  void clear();\n  void set(const char* name, double start, int numTracks, double space);\n  void addLayer(const char* name);\n\n  const char* name() const;\n  double start() const;\n  int numTracks() const;\n  double space() const;\n\n  int numLayers() const;\n  const char* layerName(int index) const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int    nameSize_;\n  char*  name_;\n  double start_;\n  int    numTracks_;\n  double space_;\n\n  int    numLayers_;\n  int    layerAllocated_;\n  char** layerNames_;\n};\n\nclass lefiGcellPattern {\npublic:\n  lefiGcellPattern();\n  void Init();\n\n  void Destroy();\n  ~lefiGcellPattern();\n\n  void set(const char* name, double start, int numCRs, double space);\n\n  const char* name() const;\n  double start() const;\n  int numCRs() const;\n  double space() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int    nameSize_;\n  char*  name_;\n  double start_;\n  int    numCRs_;\n  double space_;\n};\n\nclass lefiUseMinSpacing {\npublic:\n  lefiUseMinSpacing();\n  void Init();\n\n  void Destroy();\n  ~lefiUseMinSpacing();\n\n  void set(const char* name, int value);\n\n  const char* name() const;\n  int   value() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int   value_;\n};\n\n// 5.5 for Maximum Stacked-via rule\nclass lefiMaxStackVia {\npublic:\n  lefiMaxStackVia();\n  void Init();\n\n  void Destroy();\n  ~lefiMaxStackVia();\n\n  void clear();\n  void setMaxStackVia(int value);\n  void setMaxStackViaRange(const char* bottomLayer, const char* topLayer);\n\n  int maxStackVia() const;\n  int hasMaxStackViaRange() const;\n  const char* maxStackViaBottomLayer() const;\n  const char* maxStackViaTopLayer() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  int   value_;\n  int   hasRange_;\n  char* bottomLayer_;\n  char* topLayer_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiNonDefault.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiNonDefault_h\n#define lefiNonDefault_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n#include \"lefiVia.hpp\"\n#include \"lefiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefiNonDefault {\npublic:\n  lefiNonDefault();\n  void Init();\n\n  void Destroy();\n  ~lefiNonDefault();\n\n  void setName(const char* name);\n  void addLayer(const char* name);\n  void addWidth(double num);\n  void addWireExtension(double num);\n  void addSpacing(double num);\n  void addSpacingRule(lefiSpacing* s);\n  void addResistance(double num);\n  void addCapacitance(double num);\n  void addEdgeCap(double num);\n  void addViaRule(lefiVia* v);\n  void addDiagWidth(double num);                    // 5.6\n  void end();\n  void clear();\n  void addProp(const char* name, const char* value, const char type);\n  void addNumProp(const char* name, const double d,\n                  const char* value, const char type);\n  void setHardspacing();                            // 5.6\n  void addUseVia(const char* name);                 // 5.6\n  void addUseViaRule(const char* name);             // 5.6\n  void addMinCuts(const char* name, int numCuts);   // 5.6\n\n  const char* name() const;\n  int   hasHardspacing() const;                     // 5.6\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n  \n  // A non default rule can have one or more layers.\n  // The layer information is kept in an array.\n  int numLayers() const ;\n  const char* layerName(int index) const ;\n  int hasLayerWidth(int index) const;\n  double layerWidth(int index) const ;\n  int hasLayerSpacing(int index) const ;\n  double layerSpacing(int index) const ;\n  int hasLayerWireExtension(int index) const ;\n  double layerWireExtension(int index) const ;\n  int hasLayerResistance(int index) const;       // obsolete in 5.6\n  double layerResistance(int index) const;       // obsolete in 5.6\n  int hasLayerCapacitance(int index) const;      // obsolete in 5.6\n  double layerCapacitance(int index) const;      // obsolete in 5.6\n  int hasLayerEdgeCap(int index) const;          // obsolete in 5.6\n  double layerEdgeCap(int index) const;          // obsolete in 5.6\n  int hasLayerDiagWidth(int index) const;        // 5.6\n  double layerDiagWidth(int index) const;        // 5.6\n\n  // A non default rule can have one or more vias.\n  // These routines return the via info.\n  int numVias() const ;\n  lefiVia* viaRule(int index) const ;\n\n  // A non default rule can have one or more spacing rules.\n  // These routines return the that info.\n  int numSpacingRules() const ;\n  lefiSpacing* spacingRule(int index) const ;\n\n  int numUseVia() const;                         // 5.6\n  const char* viaName(int index) const;          // 5.6\n  int numUseViaRule() const;                     // 5.6\n  const char* viaRuleName(int index) const;      // 5.6\n  int numMinCuts() const;                        // 5.6\n  const char* cutLayerName(int index) const;     // 5.6\n  int numCuts(int index) const;                  // 5.6\n\n  // Debug print\n  void print(FILE* f);\n\nprotected:\n  int nameSize_;\n  char* name_;\n\n  // Layer information\n  int numLayers_;\n  int layersAllocated_;\n  char** layerName_;\n  double* width_;\n  double* spacing_;\n  double* wireExtension_;\n  char* hasWidth_;\n  char* hasSpacing_;\n  char* hasWireExtension_;\n\n  // 5.4\n  double* resistance_;\n  double* capacitance_;\n  double* edgeCap_;\n  char*   hasResistance_;\n  char*   hasCapacitance_;\n  char*   hasEdgeCap_;\n\n  double* diagWidth_;              // 5.6\n  char*   hasDiagWidth_;           // 5.6\n\n  int numVias_;\n  int allocatedVias_;\n  lefiVia** viaRules_;\n\n  int numSpacing_;\n  int allocatedSpacing_;\n  lefiSpacing** spacingRules_;\n\n  int    hardSpacing_;             // 5.6\n  int    numUseVias_;              // 5.6\n  int    allocatedUseVias_;        // 5.6\n  char** useViaName_;              // 5.6\n  int    numUseViaRules_;          // 5.6\n  int    allocatedUseViaRules_;    // 5.6\n  char** useViaRuleName_;          // 5.6\n  int    numMinCuts_;              // 5.6\n  int    allocatedMinCuts_;        // 5.6\n  char** cutLayerName_;            // 5.6\n  int*   numCuts_;                 // 5.6\n\n  int numProps_;\n  int propsAllocated_;\n  char**  names_;\n  char**  values_;\n  double* dvalues_;\n  char*   types_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiProp.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiProp_h\n#define lefiProp_h\n\n#include \"lefiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Struct holds the data for one property.\nclass lefiProp {\npublic:\n  lefiProp();\n  void Init();\n\n  void Destroy();\n  ~lefiProp();\n\n  void setPropType(const char* typ, const char* string);\n  void setRange(double left, double right);\n  void setNumber(double num);\n  void setPropInteger();\n  void setPropReal();\n  void setPropString();\n  void setPropQString(const char* string);\n  void setPropNameMapString(const char* string);\n  void clear();\n\n  const char* string() const;\n  const char* propType() const;\n  const char* propName() const;\n  char  dataType() const;\n      // either I:integer R:real S:string Q:quotedstring\n      // N:property name is not defined in the property definition section\n  int hasNumber() const;\n  int hasRange() const;\n  int hasString() const;\n  int hasNameMapString() const;\n  double number() const;\n  double left() const;\n  double right() const;\n\n  void bumpSize(int size);\n  void bumpName(int size);\n\n  void print(FILE* f) const;\n\nprotected:\n  char* propType_;      // \"design\" \"net\" \"macro\" ...\n  char* propName_;      // name.\n  int nameSize_;        // allocated size of name.\n  char hasRange_;       // either 0:NO or 1:YES.\n  char hasNumber_;      // either 0:NO or 1:YES.\n  char hasNameMapString_;\n  char dataType_;       // either I:integer R:real S:string Q:quotedstring.\n            // N:property name is not defined.\n  char* stringData_;    // if it is a string the data is here.\n  int stringLength_;    // allocated size of stringData.\n  double left_;\n  double right_; // if it has a range the numbers are here.\n  double d_;            // if it is a real or int the number is here.\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiPropType.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiPropType_h\n#define lefiPropType_h\n\n#include \"lefiKRDefs.hpp\"\n#include <stdio.h>\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Struct holds the data type for one property, if the property is\n// either REAL or INTEGER.\nclass lefiPropType {\npublic:\n  lefiPropType();\n  void Init();\n\n  void Destroy();\n  ~lefiPropType();\n\n  void setPropType(const char* name, const char type);\n  void Clear();\n\n  const char propType(char* name) const;\n  void bumpProps();\n\nprotected:\n  int    numProperties_;\n  int    propertiesAllocated_;\n  char** propNames_;      // name.\n  char*  propTypes_;      // 'R' == \"REAL\", 'I' == \"INTEGER\"\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiUnits.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiUnits_h\n#define lefiUnits_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefiUnits {\npublic:\n  lefiUnits();\n  void Init();\n\n  void Destroy();\n  ~lefiUnits();\n\n  void setDatabase(const char* name, double num);\n  void clear();\n  void setTime(double num);\n  void setCapacitance(double num);\n  void setResistance(double num);\n  void setPower(double num);\n  void setCurrent(double num);\n  void setVoltage(double num);\n  void setFrequency(double num);\n\n  int hasDatabase() const;\n  int hasCapacitance()const;\n  int hasResistance() const;\n  int hasTime() const;\n  int hasPower() const;\n  int hasCurrent() const;\n  int hasVoltage() const;\n  int hasFrequency() const;\n\n  const char* databaseName() const;\n  double databaseNumber() const;\n  double capacitance() const;\n  double resistance() const;\n  double time() const;\n  double power() const;\n  double current() const;\n  double voltage() const;\n  double frequency() const;\n\n  // Debug print\n  void print(FILE* f) const ;\n\nprotected:\n  int hasDatabase_;\n  int hasCapacitance_;\n  int hasResistance_;\n  int hasTime_;\n  int hasPower_;\n  int hasCurrent_;\n  int hasVoltage_;\n  int hasFrequency_;\n  char* databaseName_;\n  double databaseNumber_;\n  double capacitance_;\n  double resistance_;\n  double power_;\n  double time_;\n  double current_;\n  double voltage_;\n  double frequency_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiUser.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n//  User header file for the LEF Interface.  This includes\n//  all of the header files which are relevant to both the\n//  reader and the writer.\n// \n//  lefrReader.h and lefwWriter.h include this file, so that\n//  an application only needs to include either lefrReader.h(pp)\n//  or lefwWriter.h(pp).\n// \n\n#ifndef LEFI_USER_H\n#define LEFI_USER_H\n\n#include \"lefiDebug.hpp\"\n#include \"lefiUnits.hpp\"\n#include \"lefiLayer.hpp\"\n#include \"lefiVia.hpp\"\n#include \"lefiViaRule.hpp\"\n#include \"lefiMisc.hpp\"\n#include \"lefiNonDefault.hpp\"\n#include \"lefiMacro.hpp\"\n#include \"lefiArray.hpp\"\n#include \"lefiCrossTalk.hpp\"\n#include \"lefiProp.hpp\"\n#include \"lefiPropType.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// NEW CALLBACK add the reference here \n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiUtil.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiUtil_h\n#define lefiUtil_h\n\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Structure to return Macro data to FE\nstruct lefiPoints {\n  double x;\n  double y;\n};\n\ntypedef struct lefiPoints lefiNum;\n\n//int lefiValidTime();\nextern int lefiValidUser();\n\nextern char* lefiUser();\n\nextern char* lefiOrientStr(int orient);\n\nextern double convert_name2num(const char *versionName);\n\nextern bool  validateMaskNumber(int num);\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiVia.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiVia_h\n#define lefiVia_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n#include \"lefiMisc.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefiViaLayer {\npublic:\n  lefiViaLayer();\n  void Init();\n\n  void Destroy();\n  ~lefiViaLayer();\n\n  void setName(const char* name);\n  void addRect(int mask,\n               double xl, double yl, \n               double xh, double yh);\n  void addPoly(int mask,\n               lefiGeometries* geom);\n\n  lefiViaLayer* clone();\n\n  int numRects();\n  char* name();\n  double xl(int index);\n  double yl(int index);\n  double xh(int index);\n  double yh(int index);\n  int rectColorMask(int index);\n  int polyColorMask(int index);\n\n  int numPolygons();                                     // 5.6\n  lefiGeomPolygon* getPolygon(int index) const;   // 5.6\n\nprotected:\n  char* name_;\n  int* rectColorMask_;\n  int* polyColorMask_;\n  int numRects_;\n  int rectsAllocated_;\n  double* xl_;\n  double* yl_;\n  double* xh_;\n  double* yh_;\n\n  int numPolys_;\n  int polysAllocated_;\n  lefiGeomPolygon** polygons_;\n\n};\n\nclass lefiVia {\npublic:\n  lefiVia();\n  void Init();\n\n  void Destroy();\n  ~lefiVia();\n\n  void clear();\n\n  // setName calls clear to init\n  // deflt=0 no default specified\n  // deflt=1 default specified in lef file\n  void setName(const char* name, int viaType);\n\n  void setResistance(double num);\n  void addProp(const char* name, const char* value, const char type);\n  void addNumProp(const char* name, double d, const char* value,\n                  const char type);\n\n  // orient=-1 means no orient was specified.\n  void setForeign(const char* name, int hasPnt,\n     double x, double y, int orient);\n  void setTopOfStack();\n\n  void addLayer(const char* name);\n  void addRectToLayer(int    mask, \n                      double xl, double yl, \n                      double xh, double yh);\n  void addPolyToLayer(int    mask,\n                      lefiGeometries* geom);\n  void bumpProps();\n\n  void setViaRule(const char* viaRuleName, double xSize, double ySize,\n                  const char* botLayer, const char* cutLayer,\n                  const char* topLayer, double xCut, double yCut,\n                  double xBotEnc, double yBotEnc, double xTopEnc,\n                  double yTopEnc);                          // 5.6\n  void setRowCol(int numRows, int numCols);                 // 5.6\n  void setOrigin(double xOffset, double yOffset);           // 5.6\n  void setOffset(double xBot, double yBot, double xTop, double yTop);   // 5.6\n  void setPattern(const char* cutPattern);                  // 5.6\n\n  // make a new one \n  lefiVia* clone();\n\n  int hasDefault() const ;\n  int hasGenerated() const ; // 5.6, this no longer in 5.6, should be removed\n  int hasForeign() const ;\n  int hasForeignPnt() const ;\n  int hasForeignOrient() const ;\n  int hasProperties() const ;\n  int hasResistance() const ;\n  int hasTopOfStack() const ;\n\n  int numLayers() const;\n  char* layerName(int layerNum) const;\n  int numRects(int layerNum) const;\n  double xl(int layerNum, int rectNum) const;\n  double yl(int layerNum, int rectNum) const;\n  double xh(int layerNum, int rectNum) const;\n  double yh(int layerNum, int rectNum) const;\n  int rectColorMask(int layerNum, int rectNum) const;\n  int polyColorMask(int layerNum, int polyNum) const;\n  int numPolygons(int layerNum) const;                                 // 5.6\n  lefiGeomPolygon getPolygon(int layerNum, int polyNum) const;  // 5.6\n\n  char* name() const ;\n  double resistance() const ;\n\n  // Given an index from 0 to numProperties()-1 return\n  // information about that property.\n  int numProperties() const ;\n  char* propName(int index) const;\n  char* propValue(int index) const;\n  double propNumber(int index) const;\n  char  propType(int index) const;\n  int propIsNumber(int index) const;\n  int propIsString(int index) const;\n  char* foreign() const;\n  double foreignX() const;\n  double foreignY() const;\n  int foreignOrient() const;\n  char* foreignOrientStr() const;\n\n  // 5.6 VIARULE inside a VIA\n  int hasViaRule() const;\n  const char* viaRuleName() const;\n  double xCutSize() const;\n  double yCutSize() const;\n  const char* botMetalLayer() const;\n  const char* cutLayer() const;\n  const char* topMetalLayer() const;\n  double xCutSpacing() const;\n  double yCutSpacing() const;\n  double xBotEnc() const;\n  double yBotEnc() const;\n  double xTopEnc() const;\n  double yTopEnc() const;\n  int hasRowCol() const;\n  int numCutRows() const; \n  int numCutCols() const; \n  int hasOrigin() const;\n  double xOffset() const; \n  double yOffset() const; \n  int hasOffset() const;\n  double xBotOffset() const; \n  double yBotOffset() const; \n  double xTopOffset() const; \n  double yTopOffset() const; \n  int hasCutPattern() const;\n  const char* cutPattern() const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameSize_;\n\n  int hasDefault_;\n  int hasGenerated_;\n  int hasResistance_;\n  int hasForeignPnt_;\n  int hasTopOfStack_;\n\n  int numProps_;\n  int propsAllocated_;\n  char** propName_;\n  // The prop value is stored in the propValue_ or the propDValue_.\n  // If it is a string it is in propValue_.  If it is a number,\n  // then propValue_ is NULL and it is stored in propDValue_;\n  char** propValue_;\n  double* propDValue_;\n  char*   propType_;\n\n  int numLayers_;\n  int layersAllocated_;\n  lefiViaLayer** layers_;\n\n  double resistance_;\n\n  char* foreign_;\n  double foreignX_;\n  double foreignY_;\n  int foreignOrient_;\n\n  char* viaRuleName_;          // 5.6\n  double xSize_;               // 5.6\n  double ySize_;               // 5.6\n  char* botLayer_;             // 5.6\n  char* cutLayer_;             // 5.6\n  char* topLayer_;             // 5.6\n  double xSpacing_;            // 5.6\n  double ySpacing_;            // 5.6\n  double xBotEnc_;             // 5.6\n  double yBotEnc_;             // 5.6\n  double xTopEnc_;             // 5.6\n  double yTopEnc_;             // 5.6\n  int numRows_;                // 5.6\n  int numCols_;                // 5.6\n  double xOffset_;             // 5.6\n  double yOffset_;             // 5.6\n  double xBotOs_;              // 5.6\n  double yBotOs_;              // 5.6\n  double xTopOs_;              // 5.6\n  double yTopOs_;              // 5.6\n  char* cutPattern_;           // 5.6\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefiViaRule.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefiViaRule_h\n#define lefiViaRule_h\n\n#include <stdio.h>\n#include \"lefiKRDefs.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefiViaRuleLayer {\npublic:\n  lefiViaRuleLayer();\n  void Init();\n\n  void Destroy();\n  ~lefiViaRuleLayer();\n  void clearLayerOverhang();\n\n  void setName(const char* name);\n  void setHorizontal();\n  void setVertical();\n  void setEnclosure(double overhang1, double overhang2);     // 5.5\n  void setWidth(double minW, double maxW);\n  void setOverhang(double d);\n  void setOverhangToEnclosure(double d);                     // 5.6\n  void setMetalOverhang(double d);\n  void setResistance(double d);\n  void setSpacing(double x, double y);\n  void setRect(double xl, double yl, double xh, double yh);\n\n  int hasDirection() const ;\n  int hasEnclosure() const ;                                 // 5.5\n  int hasWidth() const ;\n  int hasResistance() const ;\n  int hasOverhang() const ;\n  int hasMetalOverhang() const ;\n  int hasSpacing() const ;\n  int hasRect() const ;\n\n  char* name() const ;\n  int isHorizontal() const ;\n  int isVertical() const ;\n  double enclosureOverhang1() const;                        // 5.5\n  double enclosureOverhang2() const;                        // 5.5\n  double widthMin() const ;\n  double widthMax() const ;\n  double overhang() const ;\n  double metalOverhang() const ;\n  double resistance() const ;\n  double spacingStepX() const ;\n  double spacingStepY() const ;\n  double xl() const ;\n  double yl() const ;\n  double xh() const ;\n  double yh() const ;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  char direction_;\n  double overhang1_;                                       // 5.5\n  double overhang2_;                                       // 5.5\n  int hasWidth_;\n  int hasResistance_;\n  int hasOverhang_;\n  int hasMetalOverhang_;\n  int hasSpacing_;\n  int hasRect_;\n  double widthMin_;\n  double widthMax_;\n  double overhang_;\n  double metalOverhang_;\n  double resistance_;\n  double spacingStepX_;\n  double spacingStepY_;\n  double xl_, yl_, xh_, yh_;\n};\n\nclass lefiViaRule {\npublic:\n  lefiViaRule();\n  void Init();\n\n  void clear();\n  void clearLayerOverhang();\n\n  void Destroy();\n  ~lefiViaRule();\n\n  void setGenerate();\n  void setDefault();\n\n  // This should clear out all the old stuff.\n  void setName(const char* name);\n\n  // Add one of possibly many via names\n  void addViaName(const char* name);\n\n  // These routines set a part of the active layer.\n  void setRect(double xl, double yl, double xh, double yh);\n  void setSpacing(double x, double y);\n  void setWidth(double x, double y);\n  void setResistance(double d);\n  void setOverhang(double d);\n  void setOverhangToEnclosure(double d);            // 5.6\n  void setMetalOverhang(double d);\n  void setVertical();\n  void setHorizontal();\n  void setEnclosure(double overhang1, double overhang2);\n  void addProp(const char* name, const char* value, const char type);\n  void addNumProp(const char* name, const double d,\n                  const char* value, const char type);\n\n  // This routine sets and creates the active layer.\n  void setLayer(const char* name);\n\n  int hasGenerate() const ;\n  int hasDefault() const ;\n  char* name() const ;\n\n  // There are 2 or 3 layers in a rule.\n  // numLayers() tells how many.\n  // If a third layer exists then it is the cut layer.\n  int numLayers() const ;\n  lefiViaRuleLayer* layer(int index) const;\n\n  int numVias() const ;\n  char* viaName(int index) const ;\n\n  int numProps() const;\n  const char*  propName(int index) const;\n  const char*  propValue(int index) const;\n  double propNumber(int index) const;\n  const char   propType(int index) const;\n  int    propIsNumber(int index) const;\n  int    propIsString(int index) const;\n\n  // Debug print\n  void print(FILE* f) const;\n\nprotected:\n  char* name_;\n  int nameSize_;\n \n  int hasGenerate_;\n  int hasDefault_;\n\n  int numLayers_;\n  lefiViaRuleLayer layers_[3];\n\n  int numVias_;\n  int viasAllocated_;\n  char** vias_;\n\n  int numProps_;\n  int propsAllocated_;\n  char**  names_;\n  char**  values_;\n  double* dvalues_;\n  char*   types_;\n};\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefrCallBacks.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2017, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefrCallbacks_h\n#define lefrCallbacks_h\n\n#include \"lefiKRDefs.hpp\"\n#include \"lefrReader.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nclass lefrCallbacks {\npublic:\n    lefrCallbacks();\n    static void reset();\n\n    // List of call back routines\n    // These are filled in by the user.  See the\n    // \"set\" routines at the end of the file\n    lefrDoubleCbkFnType AntennaInoutCbk;\n    lefrDoubleCbkFnType AntennaInputCbk;\n    lefrDoubleCbkFnType AntennaOutputCbk;\n    lefrStringCbkFnType ArrayBeginCbk;\n    lefrArrayCbkFnType ArrayCbk;\n    lefrStringCbkFnType ArrayEndCbk;\n    lefrStringCbkFnType BusBitCharsCbk;\n    lefrIntegerCbkFnType CaseSensitiveCbk;\n    lefrStringCbkFnType ClearanceMeasureCbk;\n    lefrCorrectionTableCbkFnType CorrectionTableCbk;\n    lefrDensityCbkFnType DensityCbk;\n    lefrDoubleCbkFnType DielectricCbk;\n    lefrStringCbkFnType DividerCharCbk;\n    lefrDoubleCbkFnType EdgeRateScaleFactorCbk;\n    lefrDoubleCbkFnType EdgeRateThreshold1Cbk;\n    lefrDoubleCbkFnType EdgeRateThreshold2Cbk;\n    lefrStringCbkFnType ExtensionCbk;\n    lefrIntegerCbkFnType FixedMaskCbk;\n    lefrVoidCbkFnType IRDropBeginCbk;\n    lefrIRDropCbkFnType IRDropCbk;\n    lefrVoidCbkFnType IRDropEndCbk;\n    lefrDoubleCbkFnType InoutAntennaCbk;\n    lefrDoubleCbkFnType InputAntennaCbk;\n    lefrLayerCbkFnType LayerCbk;\n    lefrVoidCbkFnType LibraryEndCbk;\n    lefrStringCbkFnType MacroBeginCbk;\n    lefrMacroCbkFnType MacroCbk;\n    lefrStringCbkFnType MacroClassTypeCbk;\n    lefrStringCbkFnType MacroEndCbk;\n    lefrIntegerCbkFnType MacroFixedMaskCbk;\n    lefrMacroNumCbkFnType MacroOriginCbk;\n    lefrMacroSiteCbkFnType MacroSiteCbk;\n    lefrMacroForeignCbkFnType MacroForeignCbk;\n    lefrMacroNumCbkFnType MacroSizeCbk;\n    lefrDoubleCbkFnType ManufacturingCbk;\n    lefrMaxStackViaCbkFnType MaxStackViaCbk;\n    lefrMinFeatureCbkFnType MinFeatureCbk;\n    lefrStringCbkFnType NoWireExtensionCbk;\n    lefrNoiseMarginCbkFnType NoiseMarginCbk;\n    lefrNoiseTableCbkFnType NoiseTableCbk;\n    lefrNonDefaultCbkFnType NonDefaultCbk;\n    lefrObstructionCbkFnType ObstructionCbk;\n    lefrDoubleCbkFnType OutputAntennaCbk;\n    lefrPinCbkFnType PinCbk;\n    lefrVoidCbkFnType PropBeginCbk;\n    lefrPropCbkFnType PropCbk;\n    lefrVoidCbkFnType PropEndCbk;\n    lefrSiteCbkFnType SiteCbk;\n    lefrVoidCbkFnType SpacingBeginCbk;\n    lefrSpacingCbkFnType SpacingCbk;\n    lefrVoidCbkFnType SpacingEndCbk;\n    lefrTimingCbkFnType TimingCbk;\n    lefrUnitsCbkFnType UnitsCbk;\n    lefrUseMinSpacingCbkFnType UseMinSpacingCbk;\n    lefrDoubleCbkFnType VersionCbk;\n    lefrStringCbkFnType VersionStrCbk;\n    lefrViaCbkFnType ViaCbk;\n    lefrViaRuleCbkFnType ViaRuleCbk;\n};\n\nextern lefrCallbacks *lefCallbacks;\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefrData.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2014, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: arakhman $\n//  $Revision: #11 $\n//  $Date: 2013/04/23 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefrData_h\n#define lefrData_h\n\n#include <cstring>\n#include <string>\n#include <vector>\n#include <map>\n\n#include \"lefiDefs.hpp\"\n#include \"lefiUser.hpp\"\n#include \"lefiLayer.hpp\"\n#include \"lefiArray.hpp\"\n#include \"lefiUtil.hpp\"\n#include \"lefiMacro.hpp\"\n#include \"lefiPropType.hpp\"\n#include \"lefiCrossTalk.hpp\"\n#include \"lefiProp.hpp\"\n#include \"lefiNonDefault.hpp\"\n#include \"lefiVia.hpp\"\n#include \"lefiViaRule.hpp\"\n#include \"lefiUnits.hpp\"\n#include \"lefrReader.hpp\"\n\n#define CURRENT_VERSION 5.8\n#define RING_SIZE 10\n#define IN_BUF_SIZE 16384\n#define TOKEN_SIZE 4096\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nstruct lefCompareStrings \n{\n    bool operator()(const std::string &lhs, const std::string &rhs) const {\n        return std::strcmp(lhs.c_str(), rhs.c_str()) < 0;\n    }\n};\n\ntypedef std::map<std::string, std::string, lefCompareStrings> lefAliasMap;\n\ntypedef std::map<std::string, std::string, lefCompareStrings> lefStringMap;\n\ntypedef std::map<std::string, int, lefCompareStrings> lefIntMap;\n\ntypedef std::map<std::string, double, lefCompareStrings> lefDoubleMap;\n\n\nclass lefrData {\npublic:\n    lefrData();\n    ~lefrData();\n\n    static void reset();\n\tvoid\t\tinitRead();\n    void\t\tdoubleBuffer();\n    \n    FILE*  lefrFile; \n    FILE*  lefrLog; \n\n    char   lefPropDefType;  \n    \n    char*  arrayName; \n    char*  last; \n    char*  layerName; \n    char*  lefch; \n    char*  lefrFileName; \n    char*  macroName; \n    char*  ndName; \n    char*  next; \n    char*  nonDefaultRuleName; \n    char*  outMsg; \n    char*  pinName; \n    char*  shiftBuf; \n    char*  siteName; \n    char*  viaName; \n    char*  viaRuleName; \n    \n    double  layerCutSpacing; \n    double  lef_save_x; \n    double  lef_save_y; // for interpreting (*) notation of LEF/DEF\n    double  leflVal; \n    double  lefrVal; \n    double  versionNum; \n    \n    int  antennaInoutWarnings; \n    int  antennaInputWarnings; \n    int  antennaOutputWarnings; \n    int  arrayCutsVal; \n    int  arrayCutsWar; \n    int  arrayWarnings; \n    int  caseSensitiveWarnings; \n    int  correctionTableWarnings; \n    int  dielectricWarnings; \n    int  doneLib; // keep track if the library is done parsing\n    int  edgeRateScaleFactorWarnings; \n    int  edgeRateThreshold1Warnings; \n    int  edgeRateThreshold2Warnings; \n    int  encrypted; \n    int  first; \n    int  first_buffer; \n    int  ge56almostDone; // have reached the EXTENSION SECTION\n    int  ge56done; // a 5.6 and it has END LIBRARY statement\n    int  hasBusBit; \n    int  hasDirection; \n    int  hasDivChar; \n    int  hasFixedMask; \n    int  hasGeoLayer; \n    int  hasInfluence; \n    int  hasLayerMincut; \n    int  hasManufactur; \n    int  hasMask; \n    int  hasMinfeature; \n    int  hasNameCase; \n    int  hasOpenedLogFile; \n    int  hasPRP; \n    int  hasParallel; \n    int  hasPitch; \n    int  hasSamenet; \n    int  hasSite; \n    int  hasSiteClass; \n    int  hasSiteSize; \n    int  hasSpCenter; \n    int  hasSpLayer; \n    int  hasSpParallel; \n    int  hasSpSamenet; \n    int  hasTwoWidths; \n    int  hasType; \n    int  hasVer; \n    int  hasViaRule_layer; \n    int  hasWidth; \n    int  hasFatalError; // don't report errors after the file end.\n    int  iRDropWarnings; \n    int  ignoreVersion; // ignore checking version number\n    int  inDefine; \n    int  inoutAntennaWarnings; \n    int  inputAntennaWarnings; \n    int  input_level; \n    int  isGenerate; \n    int  layerCut; \n    int  layerDir; \n    int  layerMastOver; \n    int  layerRout; \n    int  layerWarnings; \n    int  lefDefIf; \n    int  lefDumbMode; \n    int  lefErrMsgPrinted; \n    int  lefFixedMask; //All the LEF MACRO PIN MASK assignments can be \n    int  lefInfoMsgPrinted; \n    int  lefInvalidChar; \n    int  lefNdRule; \n    int  lefNewIsKeyword; \n    int  lefNlToken; \n    int  lefNoNum; \n    int  lefRetVal; \n    int  lefWRetVal; \n    int  lefWarnMsgPrinted; \n    int  lef_errors; \n    int  lef_nlines; \n    int  lef_ntokens; \n    int  lef_warnings; \n    int  lefrDoGcell; \n    int  lefrDoGeometries; \n    int  lefrDoSite; \n    int  lefrDoTrack;\n    int  lefrHasLayer; // 5.5 this & lefrHasMaxVS is to keep track that\n    int  lefrHasMaxVS; // MAXVIASTACK has to be after all layers\n    int  lefrHasSpacing; // keep track of spacing in a layer\n    int  lefrHasSpacingTbl; // keep track of spacing table in a layer\n\n    int  macroWarnings; \n    int  maxStackViaWarnings; \n    int  minFeatureWarnings; \n    int  msgCnt; \n    int  namesCaseSensitive; // always true in 5.6\n    int  ndLayer; \n    int  ndLayerSpace; \n    int  ndLayerWidth; \n    int  ndRule; \n    int  needGeometry; \n    int  noWireExtensionWarnings; \n    int  noiseMarginWarnings; \n    int  noiseTableWarnings; \n    int  nonDefaultWarnings; \n    int  numVia; \n    int  obsDef; \n    int  origDef; \n    int  outputAntennaWarnings; \n    int  pinDef; \n    int  pinWarnings; \n    int  prtNewLine; // sometimes need to print a new line\n    int  prtSemiColon; // sometimes ; is not printed yet\n    int  ringPlace; \n    int  shiftBufLength; \n    int  siteDef; \n    int  siteWarnings; \n    int  sizeDef; \n    int  spParallelLength; \n    int  spaceMissing; \n    int  spacingWarnings; \n    int  symDef; \n    int  timingWarnings; \n    int  unitsWarnings; \n    int  use5_3; \n    int  use5_4; \n    int  useLenThr; \n    int  useMinSpacingWarnings; \n    int  viaLayer; \n    int  viaRuleHasDir; \n    int  viaRuleHasEnc; \n    int  viaRuleLayer; \n    int  viaRuleWarnings; \n    int  viaWarnings; \n    \n    lefiAntennaEnum  antennaType; \n    lefiAntennaPWL*  lefrAntennaPWLPtr; \n    lefiArray  lefrArray; \n    lefiCorrectionTable  lefrCorrectionTable; \n    lefiDensity  lefrDensity; \n    lefiGcellPattern*  lefrGcellPatternPtr; \n    lefiGeometries*  lefrGeometriesPtr; \n    lefiIRDrop  lefrIRDrop; \n    lefiLayer  lefrLayer; \n    lefiMacro  lefrMacro; \n    lefiMaxStackVia  lefrMaxStackVia; // 5.5\n    lefiMinFeature  lefrMinFeature; \n    lefiNoiseMargin  lefrNoiseMargin; \n    lefiNoiseTable  lefrNoiseTable; \n    lefiNonDefault  lefrNonDefault; \n    lefiNonDefault*  nd; // PCR 909010 - For VIA in the nondefaultrule\n    lefiNum  macroNum; \n    lefiObstruction  lefrObstruction; \n    lefiPin  lefrPin; \n    lefiProp  lefrProp; \n    lefiSite  lefrSite; \n    lefiSitePattern*  lefrSitePatternPtr; \n    lefiSpacing  lefrSpacing; \n    lefiTiming  lefrTiming; \n    lefiTrackPattern*  lefrTrackPatternPtr; \n    lefiUnits  lefrUnits; \n    lefiUseMinSpacing  lefrUseMinSpacing; \n    lefiVia  lefrVia; \n    lefiViaRule  lefrViaRule; \n    \n    lefStringMap        alias_set; \n    lefDoubleMap        define_set; \n    lefIntMap           defineb_set; \n    lefStringMap        defines_set; \n    int                 tokenSize;\n\n    //ARRAYS\n    // Ring buffer storage \n    char       *ring[RING_SIZE];\n    int         ringSizes[RING_SIZE];\n    char        lefDebug[100];\n\n    char       *current_token; \n    char       *pv_token; \n    char       *uc_token; \n\n    char       current_buffer[IN_BUF_SIZE];\n    const char *current_stack[20];  // the stack itself \n\n    char       lefrErrMsg[1024];\n    char       temp_name[258];\n\n    std::vector<char>  Hist_text; \n\n    // to hold the msg limit, 0 - num of limit \n    // 1 - num of message printed, 4701 = 4700 + 1, message starts on 1 \n    // 2 - warning printed \n    int msgLimit[2][MAX_LEF_MSGS];\n};\n\nextern lefrData *lefData;\n\nEND_LEFDEF_PARSER_NAMESPACE\n\n#endif\n\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefrReader.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2017, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef LEFRREADER_H\n#define LEFRREADER_H\n\n#include <stdarg.h>\n#include <stdio.h>\n\n#include \"lefiKRDefs.hpp\"\n#include \"lefiDefs.hpp\"\n#include \"lefiUser.hpp\"\n#include \"lefiUtil.hpp\"\n\n#define MAX_LEF_MSGS 4701\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// The reader initialization.  Must be called before lefrRead(). \nextern int lefrInit ();\nextern int lefrInitSession (int startSession = 1);\n\n// obsolted\nextern int lefrReset ();\n\n// Clears parser configuration and return it in inial state.\nextern int lefrClear ();\n\n// obsoleted\nextern int lefrReleaseNResetMemory ();\n\n// Change the comment character in LEF.  The normal character is\n// '#'.   You can change it to anything you want, but be careful.\nextern void lefrSetCommentChar (char c);\n\n// Allow the parser to upshift all names if the LEF\n// file is case insensitive.  The default is no shift, so the user\n// must do case insensitive matching.\nextern void lefrSetShiftCase ();\n\n// Allow the user to change the casesensitivity anytime during\n// parsing.\n// caseSen = 0, will turn off the casesensitivity\n// caseSen != 0, will turn on the casesensitivity\n \nextern void lefrSetCaseSensitivity (int caseSense);\n\n// The reader request the file name they are parsing\n\nextern const char * lefrFName ();\n\n\n//  The main reader function.\n//  The file should already be opened.  This requirement allows\n//  the reader to be used with stdin or a pipe.  The file name\n//  is only used for error messages.  The includeSearchPath is\n//  a colon-delimited list of directories in which to find\n//  include files.\n\nextern int lefrRead (FILE *file, const char *fileName, lefiUserData userData);\n\n//  Set all of the callbacks that have not yet been set to a function\n//  that will add up how many times a given lef data type was ignored\n//  (ie no callback was done).  The statistics can later be printed out.\nextern void lefrSetRegisterUnusedCallbacks ();\nextern void lefrPrintUnusedCallbacks (FILE* f);\n\n// Set/get the client-provided user data.  lefi doesn't look at\n// this data at all, it simply passes the opaque lefiUserData pointer\n// back to the application with each callback.  The client can\n// change the data at any time, and it will take effect on the\n// next callback.  The lefi reader and writer maintain separate\n// user data pointers.\nextern void lefrSetUserData (lefiUserData);\nextern lefiUserData lefrGetUserData ();\n\n// An enum describing all of the types of reader callbacks.\ntypedef enum {\n  lefrUnspecifiedCbkType = 0,\n  lefrVersionCbkType,\n  lefrVersionStrCbkType,\n  lefrDividerCharCbkType,\n  lefrBusBitCharsCbkType,\n  lefrUnitsCbkType,\n  lefrCaseSensitiveCbkType,\n  lefrNoWireExtensionCbkType,\n  lefrPropBeginCbkType,\n  lefrPropCbkType,\n  lefrPropEndCbkType,\n  lefrLayerCbkType,\n  lefrViaCbkType,\n  lefrViaRuleCbkType,\n  lefrSpacingCbkType,\n  lefrIRDropCbkType,\n  lefrDielectricCbkType,\n  lefrMinFeatureCbkType,\n  lefrNonDefaultCbkType,\n  lefrSiteCbkType,\n  lefrMacroBeginCbkType,\n  lefrPinCbkType,\n  lefrMacroCbkType,\n  lefrObstructionCbkType,\n  lefrArrayCbkType,\n\n  // NEW CALLBACKS - each callback has its own type.  For each callback\n  // that you add, you must add an item to this enum. \n\n  lefrSpacingBeginCbkType,\n  lefrSpacingEndCbkType,\n  lefrArrayBeginCbkType,\n  lefrArrayEndCbkType,\n  lefrIRDropBeginCbkType,\n  lefrIRDropEndCbkType,\n  lefrNoiseMarginCbkType,\n  lefrEdgeRateThreshold1CbkType,\n  lefrEdgeRateThreshold2CbkType,\n  lefrEdgeRateScaleFactorCbkType,\n  lefrNoiseTableCbkType,\n  lefrCorrectionTableCbkType,\n  lefrInputAntennaCbkType,\n  lefrOutputAntennaCbkType,\n  lefrInoutAntennaCbkType,\n  lefrAntennaInputCbkType,\n  lefrAntennaInoutCbkType,\n  lefrAntennaOutputCbkType,\n  lefrManufacturingCbkType,\n  lefrUseMinSpacingCbkType,\n  lefrClearanceMeasureCbkType,\n  lefrTimingCbkType,\n  lefrMacroClassTypeCbkType,\n  lefrMacroOriginCbkType,\n  lefrMacroSizeCbkType,\n  lefrMacroFixedMaskCbkType,\n  lefrMacroEndCbkType,\n  lefrMaxStackViaCbkType,\n  lefrExtensionCbkType,\n  lefrDensityCbkType,\n  lefrFixedMaskCbkType,\n  lefrMacroSiteCbkType,\n  lefrMacroForeignCbkType,\n\n  lefrLibraryEndCbkType\n} lefrCallbackType_e;\n \n// Declarations of function signatures for each type of callback.\n// These declarations are type-safe when compiling with ANSI C\n// or C++; you will only be able to register a function pointer\n// with the correct signature for a given type of callback.\n//\n// Each callback function is expected to return 0 if successful.\n// A non-zero return code will cause the reader to abort.\n//\n// The lefrDesignStart and lefrDesignEnd callback is only called once.\n// Other callbacks may be called multiple times, each time with a different\n// set of data.\n//\n// For each callback, the Def API will make the callback to the\n// function supplied by the client, which should either make a copy\n// of the Def object, or store the data in the client's own data structures.\n// The Def API will delete or reuse each object after making the callback,\n// so the client should not keep a pointer to it.\n//\n// All callbacks pass the user data pointer provided in lefrRead()\n// or lefrSetUserData() back to the client; this can be used by the\n// client to obtain access to the rest of the client's data structures.\n//\n// The user data pointer is obtained using lefrGetUserData() immediately\n// prior to making each callback, so the client is free to change the\n// user data on the fly if necessary.\n//\n// Callbacks with the same signature are passed a callback type\n// parameter, which allows an application to write a single callback\n// function, register that function for multiple callbacks, then\n// switch based on the callback type to handle the appropriate type of\n// data.\n \n\n// A declaration of the signature of all callbacks that return nothing. \ntypedef int (*lefrVoidCbkFnType) (lefrCallbackType_e, \n                                  void* num, \n                                  lefiUserData);\n\n// A declaration of the signature of all callbacks that return a string. \ntypedef int (*lefrStringCbkFnType) (lefrCallbackType_e, \n                                    const char *string, \n                                    lefiUserData);\n \n// A declaration of the signature of all callbacks that return a integer. \ntypedef int (*lefrIntegerCbkFnType) (lefrCallbackType_e, \n                                     int number, \n                                     lefiUserData);\n \n// A declaration of the signature of all callbacks that return a double. \ntypedef int (*lefrDoubleCbkFnType) (lefrCallbackType_e, \n                                    double number, \n                                    lefiUserData);\n\n// A declaration of the signature of all callbacks that return a lefiUnits. \ntypedef int (*lefrUnitsCbkFnType) (lefrCallbackType_e, \n                                   lefiUnits* units, \n                                   lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiLayer. \ntypedef int (*lefrLayerCbkFnType) (lefrCallbackType_e, \n                                   lefiLayer* l, \n                                   lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiVia. \ntypedef int (*lefrViaCbkFnType) (lefrCallbackType_e, \n                                 lefiVia* l, \n                                 lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiViaRule. \ntypedef int (*lefrViaRuleCbkFnType) (lefrCallbackType_e, \n                                     lefiViaRule* l, \n                                     lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiSpacing. \ntypedef int (*lefrSpacingCbkFnType) (lefrCallbackType_e, \n                                     lefiSpacing* l, \n                                     lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiIRDrop. \ntypedef int (*lefrIRDropCbkFnType) (lefrCallbackType_e, \n                                    lefiIRDrop* l, \n                                    lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiMinFeature. \ntypedef int (*lefrMinFeatureCbkFnType) (lefrCallbackType_e, \n                                        lefiMinFeature* l, \n                                        lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiNonDefault. \ntypedef int (*lefrNonDefaultCbkFnType) (lefrCallbackType_e, \n                                        lefiNonDefault* l, \n                                        lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiSite. \ntypedef int (*lefrSiteCbkFnType) (lefrCallbackType_e, \n                                  lefiSite* l, \n                                  lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiMacro. \ntypedef int (*lefrMacroCbkFnType) (lefrCallbackType_e, \n                                   lefiMacro* l, \n                                   lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiPin. \ntypedef int (*lefrPinCbkFnType) (lefrCallbackType_e, \n                                 lefiPin* l, \n                                 lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiObstruction. \ntypedef int (*lefrObstructionCbkFnType) (lefrCallbackType_e, \n                                         lefiObstruction* l, \n                                         lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiArray. \ntypedef int (*lefrArrayCbkFnType) (lefrCallbackType_e, \n                                   lefiArray* l, \n                                   lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiProp. \ntypedef int (*lefrPropCbkFnType) (lefrCallbackType_e, \n                                  lefiProp* p, \n                                  lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiNoiseMargin. \ntypedef int (*lefrNoiseMarginCbkFnType) (lefrCallbackType_e, \n                                         struct lefiNoiseMargin* p, \n                                         lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiNoiseTable. \ntypedef int (*lefrNoiseTableCbkFnType) (lefrCallbackType_e, \n                                        lefiNoiseTable* p, \n                                        lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiCorrectionTable. \ntypedef int (*lefrCorrectionTableCbkFnType) (lefrCallbackType_e, \n                                             lefiCorrectionTable* p, \n                                             lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiTiming. \ntypedef int (*lefrTimingCbkFnType) (lefrCallbackType_e, \n                                    lefiTiming* p, \n                                    lefiUserData);\n \n// A declaration of the signature of all callbacks that return a lefiUseMinSpacing. \ntypedef int (*lefrUseMinSpacingCbkFnType) (lefrCallbackType_e, \n                                           lefiUseMinSpacing* l, \n                                           lefiUserData);\n \n  // NEW CALLBACK - If your callback returns a pointer to a new class then\n  // you must add a type function here.\n\n// A declaration of the signature of all callbacks that return a lefiMaxStackVia. \ntypedef int (*lefrMaxStackViaCbkFnType) (lefrCallbackType_e, \n                                         lefiMaxStackVia* l, \n                                         lefiUserData);\n\ntypedef int (*lefrMacroNumCbkFnType) (lefrCallbackType_e, \n                                      lefiNum l, \n                                      lefiUserData);\n\ntypedef int (*lefrMacroSiteCbkFnType) (lefrCallbackType_e, \n                                      const lefiMacroSite *site,\n                                      lefiUserData);\n\ntypedef int (*lefrMacroForeignCbkFnType) (lefrCallbackType_e, \n                                          const lefiMacroForeign *foreign,\n                                          lefiUserData);\n\n// 5.6 \n// A declaration of the signature of all callbacks that return a lefiDensity. \ntypedef int (*lefrDensityCbkFnType) (lefrCallbackType_e, \n                                     lefiDensity* l, \n                                     lefiUserData);\n \n// Functions to call to register a callback function.\nextern void lefrSetUnitsCbk(lefrUnitsCbkFnType);\nextern void lefrSetVersionCbk(lefrDoubleCbkFnType);\nextern void lefrSetVersionStrCbk(lefrStringCbkFnType);\nextern void lefrSetDividerCharCbk(lefrStringCbkFnType);\nextern void lefrSetBusBitCharsCbk(lefrStringCbkFnType);\nextern void lefrSetNoWireExtensionCbk(lefrStringCbkFnType);\nextern void lefrSetCaseSensitiveCbk(lefrIntegerCbkFnType);\nextern void lefrSetPropBeginCbk(lefrVoidCbkFnType);\nextern void lefrSetPropCbk(lefrPropCbkFnType);\nextern void lefrSetPropEndCbk(lefrVoidCbkFnType);\nextern void lefrSetLayerCbk(lefrLayerCbkFnType);\nextern void lefrSetViaCbk(lefrViaCbkFnType);\nextern void lefrSetViaRuleCbk(lefrViaRuleCbkFnType);\nextern void lefrSetSpacingCbk(lefrSpacingCbkFnType);\nextern void lefrSetIRDropCbk(lefrIRDropCbkFnType);\nextern void lefrSetDielectricCbk(lefrDoubleCbkFnType);\nextern void lefrSetMinFeatureCbk(lefrMinFeatureCbkFnType);\nextern void lefrSetNonDefaultCbk(lefrNonDefaultCbkFnType);\nextern void lefrSetSiteCbk(lefrSiteCbkFnType);\nextern void lefrSetMacroBeginCbk(lefrStringCbkFnType);\nextern void lefrSetPinCbk(lefrPinCbkFnType);\nextern void lefrSetObstructionCbk(lefrObstructionCbkFnType);\nextern void lefrSetArrayCbk(lefrArrayCbkFnType);\nextern void lefrSetMacroCbk(lefrMacroCbkFnType);\nextern void lefrSetLibraryEndCbk(lefrVoidCbkFnType);\n\n// NEW CALLBACK - each callback must have a function to allow the user\n// to set it.  Add the function here.\n\nextern void lefrSetTimingCbk(lefrTimingCbkFnType);\nextern void lefrSetSpacingBeginCbk(lefrVoidCbkFnType);\nextern void lefrSetSpacingEndCbk(lefrVoidCbkFnType);\nextern void lefrSetArrayBeginCbk(lefrStringCbkFnType);\nextern void lefrSetArrayEndCbk(lefrStringCbkFnType);\nextern void lefrSetIRDropBeginCbk(lefrVoidCbkFnType);\nextern void lefrSetIRDropEndCbk(lefrVoidCbkFnType);\nextern void lefrSetNoiseMarginCbk(lefrNoiseMarginCbkFnType);\nextern void lefrSetEdgeRateThreshold1Cbk(lefrDoubleCbkFnType);\nextern void lefrSetEdgeRateThreshold2Cbk(lefrDoubleCbkFnType);\nextern void lefrSetEdgeRateScaleFactorCbk(lefrDoubleCbkFnType);\nextern void lefrSetNoiseTableCbk(lefrNoiseTableCbkFnType);\nextern void lefrSetCorrectionTableCbk(lefrCorrectionTableCbkFnType);\nextern void lefrSetInputAntennaCbk(lefrDoubleCbkFnType);\nextern void lefrSetOutputAntennaCbk(lefrDoubleCbkFnType);\nextern void lefrSetInoutAntennaCbk(lefrDoubleCbkFnType);\nextern void lefrSetAntennaInputCbk(lefrDoubleCbkFnType);\nextern void lefrSetAntennaInoutCbk(lefrDoubleCbkFnType);\nextern void lefrSetAntennaOutputCbk(lefrDoubleCbkFnType);\nextern void lefrSetClearanceMeasureCbk(lefrStringCbkFnType);\nextern void lefrSetManufacturingCbk(lefrDoubleCbkFnType);\nextern void lefrSetUseMinSpacingCbk(lefrUseMinSpacingCbkFnType);\nextern void lefrSetMacroClassTypeCbk(lefrStringCbkFnType);\nextern void lefrSetMacroOriginCbk(lefrMacroNumCbkFnType);\nextern void lefrSetMacroSiteCbk(lefrMacroSiteCbkFnType);\nextern void lefrSetMacroForeignCbk(lefrMacroForeignCbkFnType);\nextern void lefrSetMacroSizeCbk(lefrMacroNumCbkFnType);\nextern void lefrSetMacroFixedMaskCbk(lefrIntegerCbkFnType);\nextern void lefrSetMacroEndCbk(lefrStringCbkFnType);\nextern void lefrSetMaxStackViaCbk(lefrMaxStackViaCbkFnType);\nextern void lefrSetExtensionCbk(lefrStringCbkFnType);\nextern void lefrSetDensityCbk(lefrDensityCbkFnType);\nextern void lefrSetFixedMaskCbk(lefrIntegerCbkFnType);\n\n// Set all of the callbacks that have not yet been set to the following\n// function.  This is especially useful if you want to check to see\n// if you forgot anything.\nextern void lefrSetUnusedCallbacks (lefrVoidCbkFnType func);\n\n// Reset all the callback functions to nil\nextern void lefrUnsetCallbacks();\n\n// Functions to call to unregister a callback function.\nextern void lefrUnsetAntennaInputCbk();\nextern void lefrUnsetAntennaInoutCbk();\nextern void lefrUnsetAntennaOutputCbk();\nextern void lefrUnsetArrayBeginCbk();\nextern void lefrUnsetArrayCbk();\nextern void lefrUnsetArrayEndCbk();\nextern void lefrUnsetBusBitCharsCbk();\nextern void lefrUnsetCaseSensitiveCbk();\nextern void lefrUnsetClearanceMeasureCbk();\nextern void lefrUnsetCorrectionTableCbk();\nextern void lefrUnsetDensityCbk();\nextern void lefrUnsetDielectricCbk();\nextern void lefrUnsetDividerCharCbk();\nextern void lefrUnsetEdgeRateScaleFactorCbk();\nextern void lefrUnsetEdgeRateThreshold1Cbk();\nextern void lefrUnsetEdgeRateThreshold2Cbk();\nextern void lefrUnsetExtensionCbk();\nextern void lefrUnsetInoutAntennaCbk();\nextern void lefrUnsetInputAntennaCbk();\nextern void lefrUnsetIRDropBeginCbk();\nextern void lefrUnsetIRDropCbk();\nextern void lefrUnsetIRDropEndCbk();\nextern void lefrUnsetLayerCbk();\nextern void lefrUnsetLibraryEndCbk();\nextern void lefrUnsetMacroBeginCbk();\nextern void lefrUnsetMacroCbk();\nextern void lefrUnsetMacroClassTypeCbk();\nextern void lefrUnsetMacroEndCbk();\nextern void lefrUnsetMacroOriginCbk();\nextern void lefrUnsetMacroSiteCbk();\nextern void lefrUnsetMacroForeignCbk();\nextern void lefrUnsetMacroSizeCbk();\nextern void lefrUnsetManufacturingCbk();\nextern void lefrUnsetMaxStackViaCbk();\nextern void lefrUnsetMinFeatureCbk();\nextern void lefrUnsetNoiseMarginCbk();\nextern void lefrUnsetNoiseTableCbk();\nextern void lefrUnsetNonDefaultCbk();\nextern void lefrUnsetNoWireExtensionCbk();\nextern void lefrUnsetObstructionCbk();\nextern void lefrUnsetOutputAntennaCbk();\nextern void lefrUnsetPinCbk();\nextern void lefrUnsetPropBeginCbk();\nextern void lefrUnsetPropCbk();\nextern void lefrUnsetPropEndCbk();\nextern void lefrUnsetSiteCbk();\nextern void lefrUnsetSpacingBeginCbk();\nextern void lefrUnsetSpacingCbk();\nextern void lefrUnsetSpacingEndCbk();\nextern void lefrUnsetTimingCbk();\nextern void lefrUnsetUseMinSpacingCbk();\nextern void lefrUnsetUnitsCbk();\nextern void lefrUnsetVersionCbk();\nextern void lefrUnsetVersionStrCbk();\nextern void lefrUnsetViaCbk();\nextern void lefrUnsetViaRuleCbk();\n\n// Return the current line number in the parser.\nextern int lefrLineNumber ();\n\n// Routine to set the message logging routine for errors \ntypedef void (*LEFI_LOG_FUNCTION) (const char*);\nextern void lefrSetLogFunction(LEFI_LOG_FUNCTION);\n\n// Routine to set the message logging routine for warnings \ntypedef void (*LEFI_WARNING_LOG_FUNCTION) (const char*);\nextern void lefrSetWarningLogFunction(LEFI_WARNING_LOG_FUNCTION);\n\n// Routine to set the user defined malloc routine \ntypedef void* (*LEFI_MALLOC_FUNCTION) (int);\nextern void lefrSetMallocFunction(LEFI_MALLOC_FUNCTION);\n\n// Routine to set the user defined realloc routine \ntypedef void* (*LEFI_REALLOC_FUNCTION) (void *, int);\nextern void lefrSetReallocFunction(LEFI_REALLOC_FUNCTION);\n\n// Routine to set the user defined free routine \ntypedef void (*LEFI_FREE_FUNCTION) (void *);\nextern void lefrSetFreeFunction(LEFI_FREE_FUNCTION);\n\n// Routine to set the line number callback routine \ntypedef void (*LEFI_LINE_NUMBER_FUNCTION) (int);\nextern void lefrSetLineNumberFunction( LEFI_LINE_NUMBER_FUNCTION);\n\n// Set the number of lines before calling the line function callback routine \n// Default is 10000 \nextern void lefrSetDeltaNumberLines  (int);\n\n// PCR 551229 - Set the parser to be more relax \n// This api is specific for PKS. \n// When in relax mode, the parser will not require width, pitch, & direction \n// in routing layers. Also vias in nondefault rules \nextern void lefrSetRelaxMode ();\nextern void lefrUnsetRelaxMode ();\n\n// PCR 565274 - LEF/DEF API should have the API call to overwrite default \n//              version \nextern void lefrSetVersionValue(const  char*  version);\n\n// Routine to set the read function \ntypedef size_t (*LEFI_READ_FUNCTION) (FILE*, char*, size_t);\nextern void lefrSetReadFunction(LEFI_READ_FUNCTION);\nextern void lefrUnsetReadFunction();\n\n// Routine to set the lefrWarning.log to open as append instead for write \n// New in 5.7 \nextern void lefrSetOpenLogFileAppend();\nextern void lefrUnsetOpenLogFileAppend();\n\n// Routine to disable string property value process, default it will process \n// the value string \nextern void lefrDisablePropStrProcess();\n\n// Routine to set the max number of warnings for a perticular section \n\nextern void lefrSetAntennaInoutWarnings(int warn);\nextern void lefrSetAntennaInputWarnings(int warn);\nextern void lefrSetAntennaOutputWarnings(int warn);\nextern void lefrSetArrayWarnings(int warn);\nextern void lefrSetCaseSensitiveWarnings(int warn);\nextern void lefrSetCorrectionTableWarnings(int warn);\nextern void lefrSetDielectricWarnings(int warn);\nextern void lefrSetEdgeRateThreshold1Warnings(int warn);\nextern void lefrSetEdgeRateThreshold2Warnings(int warn);\nextern void lefrSetEdgeRateScaleFactorWarnings(int warn);\nextern void lefrSetInoutAntennaWarnings(int warn);\nextern void lefrSetInputAntennaWarnings(int warn);\nextern void lefrSetIRDropWarnings(int warn);\nextern void lefrSetLayerWarnings(int warn);\nextern void lefrSetMacroWarnings(int warn);\nextern void lefrSetMaxStackViaWarnings(int warn);\nextern void lefrSetMinFeatureWarnings(int warn);\nextern void lefrSetNoiseMarginWarnings(int warn);\nextern void lefrSetNoiseTableWarnings(int warn);\nextern void lefrSetNonDefaultWarnings(int warn);\nextern void lefrSetNoWireExtensionWarnings(int warn);\nextern void lefrSetOutputAntennaWarnings(int warn);\nextern void lefrSetPinWarnings(int warn);\nextern void lefrSetSiteWarnings(int warn);\nextern void lefrSetSpacingWarnings(int warn);\nextern void lefrSetTimingWarnings(int warn);\nextern void lefrSetUnitsWarnings(int warn);\nextern void lefrSetUseMinSpacingWarnings(int warn);\nextern void lefrSetViaRuleWarnings(int warn);\nextern void lefrSetViaWarnings(int warn);\n\n// Handling output messages \nextern void lefrDisableParserMsgs(int nMsg, int* msgs);\nextern void lefrEnableParserMsgs(int nMsg, int* msgs);\nextern void lefrEnableAllMsgs();\nextern void lefrDisableAllMsgs();\nextern void lefrSetTotalMsgLimit(int totNumMsgs);\nextern void lefrSetLimitPerMsg(int msgId, int numMsg);\n\n// Register lef58Type-layerType pair. \nextern void lefrRegisterLef58Type(const char *lef58Type, \n                                  const char *layerType);\n\n// Return codes for the user callbacks.\n// The user should return one of these values.\n#define PARSE_OK 0      // continue parsing \n#define STOP_PARSE 1    // stop parsing with no error message \n#define PARSE_ERROR 2   // stop parsing, print an error message\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefrSettings.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2017, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: arakhman $\n//  $Revision: #11 $\n//  $Date: 2013/04/23 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef lefrSettings_h\n#define lefrSettings_h\n\n#include <cstring>\n#include <string>\n#include <map>\n#include <set>\n\n#include \"lefrReader.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\nstruct lefCompareCStrings \n{\n    bool operator()(const char* lhs, const char* rhs) const {\n        return std::strcmp(lhs, rhs) < 0;\n    }\n};\n\ntypedef std::map<const char*, int, lefCompareCStrings>  lefKeywordMap;\ntypedef std::map<int, int>                              MsgsDisableMap;\n\ntypedef std::set<std::string>               StringSet;\n\nclass lefrProps {\npublic:\n    lefiPropType  lefrCompProp; \n    lefiPropType  lefrLayerProp; \n    lefiPropType  lefrLibProp; \n    lefiPropType  lefrMacroProp; \n    lefiPropType  lefrNondefProp; \n    lefiPropType  lefrPinProp; \n    lefiPropType  lefrViaProp; \n    lefiPropType  lefrViaRuleProp; \n};\n\nclass lefrSettings {\npublic:\n                    lefrSettings();\n\n    void            init_symbol_table();\n    static void     reset();\n    void            addLef58Type(const char *lef58Type, \n                                 const char **layerType);\n\n    std::string     getLayerLef58Types(const char *type) const;\n\n    void            disableMsg(int msgId);\n    void            enableMsg(int msgId);\n    void            enableAllMsgs();\n    int             suppresMsg(int msgId);\n\n    static std::string     getToken(const std::string   &input, \n                                    int                 &startIdx);\n\n    lefKeywordMap       Keyword_set; \n\n    char CommentChar;\n    double VersionNum;\n    int DisPropStrProcess;\n    int CaseSensitive;\n    int CaseSensitiveSet;\n    int DeltaNumberLines;\n    int AntennaInoutWarnings;\n    int AntennaInputWarnings;\n    int AntennaOutputWarnings;\n    int ArrayWarnings;\n    int CaseSensitiveWarnings;\n    int CorrectionTableWarnings;\n    int DielectricWarnings;\n    int EdgeRateScaleFactorWarnings;\n    int EdgeRateThreshold1Warnings;\n    int EdgeRateThreshold2Warnings;\n    int IRDropWarnings;\n    int InoutAntennaWarnings;\n    int InputAntennaWarnings;\n    LEFI_LINE_NUMBER_FUNCTION LineNumberFunction;\n    int LayerWarnings;\n    int MacroWarnings;\n    int MaxStackViaWarnings;\n    int MinFeatureWarnings;\n    int NoWireExtensionWarnings;\n    int NoiseMarginWarnings;\n    int NoiseTableWarnings;\n    int NonDefaultWarnings;\n    int OutputAntennaWarnings;\n    int PinWarnings;\n    LEFI_READ_FUNCTION ReadFunction;\n    int ReadEncrypted; \n    int RegisterUnused;\n    int RelaxMode;\n    int ShiftCase;\n    int SiteWarnings;\n    int SpacingWarnings;\n    int TimingWarnings;\n    int UnitsWarnings;\n    int UseMinSpacingWarnings;\n    int ViaRuleWarnings;\n    int ViaWarnings;\n    int LogFileAppend;\n    int TotalMsgLimit;\n    lefiUserData UserData;\n\n    StringSet Lef58TypePairs;\n\n    LEFI_MALLOC_FUNCTION MallocFunction;\n    LEFI_REALLOC_FUNCTION ReallocFunction;\n    LEFI_FREE_FUNCTION FreeFunction;\n    LEFI_LOG_FUNCTION ErrorLogFunction;\n    LEFI_LOG_FUNCTION SetLogFunction;\n    LEFI_WARNING_LOG_FUNCTION WarningLogFunction;\n\n    int MsgLimit[MAX_LEF_MSGS];\n\n    MsgsDisableMap msgsDisableMap;\n    int  dAllMsgs; \n\n    lefrProps lefProps;\n};\n\nextern lefrSettings* lefSettings;\n\nEND_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefwWriter.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef LEFW_WRITERCALLS_H\n#define LEFW_WRITERCALLS_H\n\n#include <stdio.h>\n\n#include \"lefiKRDefs.hpp\"\n#include \"lefiDefs.hpp\"\n#include \"lefiUser.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n// Return codes for writing functions: \n#define LEFW_OK               0\n#define LEFW_UNINITIALIZED    1\n#define LEFW_BAD_ORDER        2\n#define LEFW_BAD_DATA         3\n#define LEFW_ALREADY_DEFINED  4\n#define LEFW_WRONG_VERSION    5\n#define LEFW_MIX_VERSION_DATA 6\n#define LEFW_OBSOLETE         7\n\n// orient \n//   0 = N\n//   1 = W\n//   2 = S\n//   3 = E\n//   4 = FN\n//   5 = FW\n//   6 = FS\n//   7 = FE\n\n// The LEF writer initialization.  Must be called first.\n// Either this routine or lefwInitCbk should be call only,\n// Can't call both routines.\n// This routine must be called only once.\n// Returns 0 if successful. \nextern int lefwInit(FILE* f);\n\n// The LEF writer initialization.  Must be called first.\n// Either this routine or lefwInit should be call only,\n// Can't call both routines.\n// This routine must be called only once.\n// Returns 0 if successful. \nextern int lefwInitCbk(FILE* f);\n\n// This routine will set the writer to write out an encrypted\n// lef file.\n// This routine must be called only once and has to be called after\n// lefwInit or lefwInitCbk \n// Need to call lefwCloseEncrypt to do some cleaning if this routine\n// has called\nextern int lefwEncrypt();\n\n// This routine needs to be called if lefwEncrypt has called.\n// It should be called before the fclose.\n// It does some house cleaning.\nextern int lefwCloseEncrypt();\n\n// This routine will write a blank line\n\nextern int lefwNewLine();\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful. \nextern int lefwVersion (int vers1, int vers2);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful.\n// The caseSensitive can be ON or OFF. \nextern int lefwCaseSensitive (const char* caseSensitive);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful.\n// The noWireExtensionAtPin can be ON or OFF. \nextern int lefwNoWireExtensionAtPin (const char* noWireExt);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful.\n//     already have one\nextern int lefwMinfeature (double minFeatureX, double minFeatureY);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful. \nextern int lefwDielectric (double dielectric);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful. \nextern int lefwBusBitChars (const char* busBitChars);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful. \nextern int lefwDividerChar (const char* dividerChar);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwManufacturingGrid (double grid);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// This is a 5.8 syntax.\n// Returns 0 if successful. \nextern int lefwFixedMask();\n\n// This routine is called after lefwInit.\n// This routine can be called multiple times.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwUseMinSpacing (const char* type, const char* onOff);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwClearanceMeasure (const char* type);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwAntennaInputGateArea (double inputGateArea);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwAntennaInOutDiffArea (double inOutDiffArea);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwAntennaOutputDiffArea (double outputDiffArea);\n\n// This routine is called after lefwInit.\n// This routine can be called only once.\n// Returns 0 if successful.\n// This section of routines is optional.\n// The routine starts the units section. All of the units must follow. \nextern int lefwStartUnits();\n\n// This routine is called once for each unit.  The call must\n// be preceeded by a call to lefwStartUnits and must be\n// terminated by a call to lefwEndUnits.\n// Returns 0 if successful. \nextern int lefwUnits(double time,    // optional(0) - TIME NANOSECONDS \n               double capacitance,   // optional(0) - CAPACITANCE PICOFARADS \n               double resistance,    // optional(0) - RESISTANCE OHMS \n               double power,         // optional(0) - POWER MILLIWATTS \n               double current,       // optional(0) - CURRENT MILLIAMPS \n               double voltage,       // optional(0) - VOLTAGE VOLTS \n               double database);     // optional(0) - DATABASE MICRONS \n\n// This routine is called once for each unit.  It is separated from\n// lefwUnits due to backwards compatible for pre 5.3.\n// Returns 0 if successful. \nextern int lefwUnitsFrequency(double frequency);\n\n// This routine must be called after the lefwUnits call (if any).\n// The routine can be called only once.\n// Returns 0 if successful. \nextern int lefwEndUnits();\n\n// This routine is called after lefwInit.\n// Either this routine or lefwStartLayerRouting must be called.\n// Multiple sections of lefwStartLayer can be called.\n// This routine can be called only once per section.\n// Returns 0 if successful.\n// The routine starts the layer section. All of the layers must follow.\n// The type can be either CUT for Cut Layer, MASTERSLICE or OVERLAP for\n// Masterslice or Overlay Layer. \nextern int lefwStartLayer(const char* layerName,\n                          const char* type);  // CUT | MASTERSLICE | OVERLAP \n\n// This routine must be called after lefwStartLayer.\n// This section of routines is optional.\n// Returns 0 if successful.\n// This is a 5.8 syntax. \nextern int lefwLayerMask(int maskColor);\n\n// This routine must be called after lefwStartLayer.\n// This section of routines is optional.\n// Returns 0 if successful.\n// This is a 5.5 syntax.\n// This routine is called if the layer type is IMPLANT when\n// lefwStartLayer is called. \nextern int lefwLayerWidth(double minWidth);\n\n// The following APIs are for lefwrite 5.7 Layer, Spacing with type CUT\n// Due to adding new constructs, it is impossible to use the previous\n// APIs.\n// The following APIs are obsoleted in 5.7:\n//    lefwLayer\n//    lefwLayerStack\n//    lefwLayerSpacingAdjacent\n//    lefwLayerSpacingCenterToCenter\n\n// This routine must be called after lefwStartLayer.\n// This routine starts the Layer Type Cut Spacing\n// Returns 0 if successful.\n// The routing lefwLayerCutSpacingEnd has to call at the end of each spacing.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacing(double spacing) ;\n\n// This routine must be called after lefwLayerSpacing\n// This routine is optional.\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingCenterToCenter();\n\n// This routine must be called after lefwLayerSpacing\n// This routine is optional.\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingSameNet();\n\n// This routine must be called after lefwLayerSpacing\n// This routine is optional.\n// Either this routine, lefwLayerCutSpacingAdjacent,\n// lefwLayerCutSpacingParallel or lefwLayerCutSpacingArea is called per Spacing.\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingLayer(const char* name2,\n                                   int stack);         // optional(0) \n\n// This routine must be called after lefwLayerSpacing\n// This routine is optional.\n// Either this routine, lefwLayerCutSpacingLayer,\n// lefwLayerCutSpacingParallel or lefwLayerCutSpacingArea is called per Spacing.\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingAdjacent(int viaCuts, // either 2, 3, or 4, opt \n                                      double distance,\n                                      int stack);  // optional(0) \n\n// This routine must be called after lefwLayerSpacing\n// This routine is optional.\n// Either this routine, lefwLayerCutSpacingLayer,\n// lefwLayerCutSpacingAdjacent or lefwLayerCutSpacingArea is called per Spacing.\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingParallel();\n\n// This routine must be called after lefwLayerSpacing\n// This routine is optional.\n// Either this routine, lefwLayerCutSpacingLayer, * lefwLayerCutSpacingAdjacent\n// or lefwLayerCutSpacingParallel is called per Spacing.\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingArea(double cutArea);\n\n// This routine must be called after lefwLayerSpacing\n// This routine marks the end of a Layer Type CUT Spacing\n// Returns 0 if successful.\n// This is a 5.7 syntax. \nextern int lefwLayerCutSpacingEnd();\n\n// This routine must be called after lefwStartLayer.\n// This routine can be called only once.\n// This section of routines is optional.\n// This is a 5.7 syntax\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerCutSpacingTableOrtho(int numSpacing,\n                                         double* cutWithins,\n                                         double* orthoSpacings);\n\n// This routine must be called after lefwStartLayer.\n// This routine can be called only once.\n// This section of routines is optional.\n// This is a 5.7 syntax\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerArraySpacing(int longArray,    // optional (0) \n                                 double viaWidth,  // optional (0) \n                                 double cutSpacing,\n                                 int numArrayCut,\n                                 int* arrayCuts, double* arraySpacings);\n\n// This routine must be called after lefwStartLayer.\n// This routine can be called multiple times.\n// This section of routines is optional.\n// This is a 5.6 syntax.\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerEnclosure(const char* location, //ABOVE|BELOW, optional \"\"\n                              double overhang1,\n                              double overhang2,\n                              double width);    // optional (0) \n\n// This routine must be called after lefwStartLayer.\n// This routine can be called multiple times.\n// This routine is similar as lefwLayerEnclosure, but allow user to add\n// EXCEPTEXTRACUT option\n// This section of routines is optional.\n// This is a 5.7 syntax.\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerEnclosureWidth(\n                              const char* location, //ABOVE|BELOW, optional \"\"\n                              double overhang1,\n                              double overhang2,\n                              double width,         // optional (0) \n                              double cutWithin);    // optional (0) \n\n// This routine must be called after lefwStartLayer.\n// This routine can be called multiple times.\n// This routine is to write out minLength inside ENCLOSURE instead of WIDTH\n// as in the routine lefwLayerEnclosure & lefwLayerEnclosureWidth.\n// This section of routines is optional.\n// This is a 5.7 syntax.\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerEnclosureLength(\n                              const char* location, //ABOVE|BELOW, optional \"\"\n                              double overhang1,\n                              double overhang2,\n                              double minLength);    // optional (0) \n\n// This routine must be called after lefwStartLayer.\n// This routine can be called multiple times.\n// This section of routines is optional.\n// This is a 5.6 syntax.\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerPreferEnclosure(\n                              const char* location, //ABOVE|BELOW, optional \"\"\n                              double overhang1,\n                              double overhang2,\n                              double width);    // optional (0) \n\n// This routine must be called after lefwStartLayer.\n// This routine can be called only once per Layer.\n// This section of routines is optional.\n// This is a 5.6 syntax.\n// Returns 0 if successful.\n// This routine is called if the layer type is CUT when\n// lefwStartLayer is called. \nextern int lefwLayerResistancePerCut(double resistance);\n\n// This routine must be called after the lefwStartLayer call (if any).\n// The routine can be called only once per section.\n// Returns 0 if successful. \nextern int lefwEndLayer(const char* layerName);\n\n// This routine is called after lefwInit.\n// Either this routine or lefwStartLayer must be called.\n// Multiple section of lefwStartLayer can be called.\n// The routine can be called only once per section.\n// Returns 0 if successful.\n// The routine starts the layer routing section.\n// All of the layers must follow. \nextern int lefwStartLayerRouting(const char* layerName);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is required for LayerRouting.\n// Returns 0 if successful. \nextern int lefwLayerRouting(const char* direction, // HORIZONTAL | VERTICAL | \n                                                   // DIAG45 | DIAG135 \n                            double width);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// Either this routine or lefwLayerRoutingPitchXYDistance can be called\n// but not both\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingPitch(double pitch);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// Either this routine or lefwLayerRoutingPitch can be called but not both\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingPitchXYDistance(double xDistance, double yDistance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// Either this routine or lefwLayerRoutingDiagPitchXYDistance can be called\n// but not both\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingDiagPitch(double distance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// Either this routine or lefwLayerRoutingDiagPitch can be called\n// but not both\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingDiagPitchXYDistance(double diag45Distance,\n                                               double diag135Distance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingDiagWidth(double diagWidth);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingDiagSpacing(double diagSpacing);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingDiagMinEdgeLength(double diagLength);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Either this routine or lefwLayerRoutingOffsetXYDistance can be called\n// but not both\n// Returns 0 if successful. \nextern int lefwLayerRoutingOffset(double offset);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Either this routine or lefwLayerRoutingOffset can be called but not both\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingOffsetXYDistance(double xDistance, double yDistance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingArea(double area);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinsize(int numRect, double* minWidth,\n                                   double* minLength);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinimumcut(double numCuts, double minWidth);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is similar as lefwLayerRoutingMinimumcut, but allow user\n// to specify value for WITHIN\n// This is a 5.7 syntax.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinimumcutWithin(double numCuts, double minWidth,\n                                            double cutDistance);\n\n// This routine must be called only once after lefwLayerRoutingMinimumcut.\n// This routine is optional.\n// Direction can be either FROMABOVE or FROMBELOW\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinimumcutConnections(const char* direction);\n\n// This routine must be called only once after lefwLayerRoutingMinimumcut.\n// This routine is optional.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinimumcutLengthWithin(double length,\n               double distance);\n\n// This routine must be called multiple time after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacing(double spacing);\n\n// Either this routine, lefwLayerRoutingSpacingLengthThreshold or\n// lefwLayerRoutingSpacingSameNet can be\n// called only once after lefwLayerRoutingSpacing.\n// This routine is optional.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingRange(double minWidth, double maxWidth);\n\n// Either this routine or lefwLayerRoutingSpacingRangeInfluence or\n// lefwLayerRoutingSpacingRangeRange can\n// be called once after llefwLayerRoutingSpacingRange.\n// This routine is valid only if either or both leftRange and rightRange\n// in lefwLayerRoutingSpacing are non zero\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingRangeUseLengthThreshold();\n\n// Either this routine or lefwLayerRoutingSpacingRangeUseLengthThreshold or\n// lefwLayerRoutingSpacingRangeRange can be called once after\n// lefwLayerRoutingSpacingRange.\n// subMinWidth & subMaxWidth are optional.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingRangeInfluence(double infValue,\n              double subMinWidth, double subMaxWidth);\n\n// Either this routine or lefwLayerRoutingSpacingRangeUseLengthThreshold or\n// lefwLayerRoutingSpacingRangeInfluence can be called once after\n// lefwLayerRoutingSpacingRange.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingRangeRange(double minWidth, double maxWidth);\n\n// Either this routine, lefwLayerRoutingSpacingRange or\n// lefwLayerRoutingSpacingSameNet can be\n// be called once after lefwLayerRoutingSpacing.\n// minWidth & maxWidth are optional.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingLengthThreshold(double lengthValue,\n              double minWidth, double maxWidth);\n\n// Either this routine, lefwLayerRoutingSpacingRange or\n// lefwLayerRoutingSpacingRange can be\n// be called once after lefwLayerRoutingSpacing.\n// This is a 5.7 routine.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingSameNet(int PGOnly) ; // optional (0) \n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// This is a 5.7 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingEndOfLine(double eolWidth, double eolWithin);\n\n// This routine must be called only once after lefwLayerRoutingSpacingEndOfLine\n// This routine is optional\n// This is a 5.7 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingEOLParallel(double parSpace, double parWithin,\n                                              int twoEdges); // optional(0) \n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// This is a 5.7 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingNotchLength(double minNLength);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// This is a 5.7 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingEndOfNotchWidth(double eonWidth,\n                  double minNSpacing, double minNLength);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingWireExtension(double wireExtension);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingResistance(const char* resistance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingCapacitance(const char* capacitance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingHeight(double height);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingThickness(double thickness);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingShrinkage(double shrinkage);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingCapMultiplier(double capMultiplier);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingEdgeCap(double edgeCap);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingAntennaArea(double antennaArea);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional\n// Returns 0 if successful. \nextern int lefwLayerRoutingAntennaLength(double antennaLength);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional and can be called once.\n// This is a 5.5 syntax.\n// width is the maximum width.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMaxwidth(double width);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional and can be called once.\n// This is a 5.5 syntax.\n// width is the maximum width.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinwidth(double width);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional.\n// This is a 5.5 syntax.\n// Area is the minimum area size limit for metal that encloses an empty area.\n// Width is optional, it says the rule only applies when a donut is careted\n// from a wire of width <= width.  The parameter width is required for the\n// routine lefwLayerRoutineMinenclosedarea.  If width is optional, a \"0\"\n// value is assigned for that index slot of the array.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinenclosedarea(int numMinenclosed, double* area,\n                                           double* width);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional and can be called once.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinstep(double distance);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional and can be called once.\n// This routine is equivalent to lefwLayerRoutingMinstep, except it also\n// takes the options for type & Lengthsum.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinstepWithOptions(double distance,\n                       const char* rule, // INSIDECORNER|OUTSIDECORNER|STEP \n                       double maxLength);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional and can be called once.\n// This routine is equivalent to lefwLayerRoutingMinstep, except it also\n// takes the option for MaxEdges.\n// This is a 5.7 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingMinstepMaxEdges(double distance,\n                                           double maxEdges);\n\n// This routine must be called only once after lefwStartLayerRouting.\n// This routine is optional and can be called once.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingProtrusion(double width1, double length,\n                                      double width2);\n\n// This routine must be called only after lefwStartLayerRouting.\n// This routine is optional and can be called multiple times.\n// This is a 5.5 syntax.\n// numLength has the size of the array length.\n// length is an array of length values.\n// Returns 0 if successful. \nextern int lefwLayerRoutingStartSpacingtableParallel(int numLength,\n                                                     double* length);\n\n// This routine must be called only after\n// lefwLayerRoutingStartSpacingtableParallel.\n// This routine is required after lefwLayerRoutingStartSpacingtableParallel.\n// This routine can be called multiple times.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingSpacingtableParallelWidth(double width,\n                                     int numSpacing, double* spacing);\n\n// This routine must be called only after lefwStartLayerRouting.\n// This routine is optional and can be called multiple times.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingStartSpacingtableInfluence();\n\n// This routine must be called only after\n// lefwLayerRoutingStartSpacingtableInfluence.\n// This routine is required after lefwLayerRoutingStartSpacingtableInfluence.\n// This routine can be called multiple times.\n// This is a 5.5 syntax.\n// Returns 0 if successful.  \nextern int lefwLayerRoutingSpacingInfluenceWidth(double width, double distance,\n                                     double spacing);\n\n// This routine must be called only after lefwStartLayerRouting.\n// This routine is optional and can be called multiple times.\n// This is a 5.7 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutingStartSpacingtableTwoWidths();\n\n// This routine must be called only after\n// lefwLayerRoutingStartSpacingtableInfluence.\n// This routine is required after lefwLayerRoutingStartSpacingtableTwoWidths.\n// This routine can be called multiple times.\n// This is a 5.7 syntax.\n// Returns 0 if successful.  \nextern int lefwLayerRoutingSpacingtableTwoWidthsWidth(double width,\n                                     double runLength, // PRL, optional (0) \n                                     int numSpacing,\n                                     double* spacing);\n\n// This routine can be called after lefwLayerRoutingStartSpacingtableParallel\n// or lefwLayerRoutingStartSpacingtableInfluence.\n// It can only be called once.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerRoutineEndSpacingtable();\n\n// This routine must be called after the lefwStartLayer call (if any).\n// The routine can be called only once per section.\n// Returns 0 if successful. \nextern int lefwEndLayerRouting(const char* layerName);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called multiple times.\n// if the value for the variable value is not 0, one of the following\n// routines have to be called: lefwLayerACFrequency,\n// lefwLayerACWidth, lefwLayerACCutarea, or\n// lefwLayerACTableEntries\n// Returns 0 if successful. \nextern int lefwLayerACCurrentDensity(const char* type, double value);\n\n// This routine must be called after lefwLayerACCurrentDensity.\n// This routine is required and can be called only once after each\n// lefwLayerACCurrentDensity.\n// Returns 0 if successful. \nextern int lefwLayerACFrequency(int numFrequency, double* frequency);\n\n// This routine must be called after lefwLayerACCurrentDensity.\n// This routine is optional and can be called only once after each\n// lefwLayerACCurrentDensity.\n// This routine can only be called in Layer Routing\n// Returns 0 if successful. \nextern int lefwLayerACWidth(int numWidths, double* widths);\n\n// This routine must be called after lefwLayerACCurrentDensity.\n// This routine is optional and can be called only once after each\n// lefwLayerACCurrentDensity.\n// This routine can only be called in Layer\n// Returns 0 if successful. \nextern int lefwLayerACCutarea(int numCutareas, double* cutareas);\n\n// This routine must be called after lefwLayerACCurrentDensity.\n// This routine is required and can be called only once after each\n// lefwLayerACCurrentDensity.\n// Returns 0 if successful. \nextern int lefwLayerACTableEntries(int numEntries, double* entries);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called multiple times.\n// if the value for the variable value is not 0, one of the following\n// routines have to be called: lefwLayerDCWidth, lefwLayerDCCutarea, or\n// lefwLayerDCTableEntries\n// Returns 0 if successful. \nextern int lefwLayerDCCurrentDensity(const char* type, double value);\n\n// This routine must be called after lefwLayerDCCurrentDensity.\n// This routine is optional and can be called only once after each\n// lefwLayerDCCurrentDensity.\n// This routine can only be called in Layer Routing\n// Returns 0 if successful. \nextern int lefwLayerDCWidth(int numWidths, double* widths);\n\n// This routine must be called after lefwLayerDCCurrentDensity.\n// This routine is optional and can be called only once after each\n// lefwLayerDCCurrentDensity.\n// This routine can only be called in Layer\n// Returns 0 if successful. \nextern int lefwLayerDCCutarea(int numCutareas, double* cutareas);\n\n// This routine must be called after lefwLayerDCCurrentDensity.\n// This routine is required and can be called only once after each\n// lefwLayerDCCurrentDensity.\n// Returns 0 if successful. \nextern int lefwLayerDCTableEntries(int numEntries, double* entries);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional.  The oxide value, can be either OXIDE1, OXIDE2,\n// OXIDE3, or OXIDE4.  Each can only be called once within a layer.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwLayerAntennaModel(const char* oxide);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer\n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer\n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// Either this routine or lefwLayerAntennaDiffAreaRatioPwl can be called, but\n// not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaDiffAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// Either this routine or lefwLayerAntennaDiffAreaRatio can be called, but\n// not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaDiffAreaRatioPwl(int numPwls,\n               double* diffusions, double* ratios);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// Either this routine or lefwLayerAntennaCumDiffAreaRatioPwl can be called,\n// but not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumDiffAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// Either this routine or lefwLayerAntennaCumDiffAreaRatio can be called, but\n// not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumDiffAreaRatioPwl(int numPwls,\n               double* diffusions, double* ratios);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// The option DIFFUSEONLY is a 5.4 syntax.\n// If DIFFUSEONLY, lefwLayerRoutingAntennaLength is not allowed.\n// This function is similar to lefwLayerRoutingAntennaArea\n// diffUseOnly has to be DIFFUSEONLY.\n// Returns 0 if successful. \nextern int lefwLayerAntennaAreaFactor(double value,\n               const char* diffUseOnly);    // optional(NULL) \n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING.\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaSideAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING.\n// Either this routine or lefwLayerAntennaDiffSideAreaRatioPwl can be\n// called, but not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaDiffSideAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// Either this routine or lefwLayerAntennaDiffSideAreaRatio can be called,\n// but not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaDiffSideAreaRatioPwl(int numPwls,\n               double* diffusions, double* ratios);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING.\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumSideAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING.\n// Either this routine or lefwLayerAntennaCumDiffSideAreaRatioPwl can be\n// called, but not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumDiffSideAreaRatio(double value);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// Either this routine or lefwLayerAntennaCumDiffSideAreaRatio can be called,\n// but not both\n// This is a 5.4 syntax.\n// Either this routine or lefwLayerRoutingAntennaLength is allowed, not both.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumDiffSideAreaRatioPwl(int numPwls,\n               double* diffusions, double* ratios);\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING.\n// The option DIFFUSEONLY is a 5.4 syntax.\n// diffUseOnly has to be DIFFUSEONLY.\n// Returns 0 if successful. \nextern int lefwLayerAntennaSideAreaFactor(double value,\n               const char* diffUseOnly);    // optional(NULL) \n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.7 routine.\n// Returns 0 if successful. \nextern int lefwLayerAntennaCumRoutingPlusCut() ;\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.7 routine.\n// Returns 0 if successful. \nextern int lefwLayerAntennaGatePlusDiff(double plusDiffFactor) ;\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.7 routine.\n// Returns 0 if successful. \nextern int lefwLayerAntennaAreaMinusDiff(double minusDiffFactor) ;\n\n// This routine must be called after lefwStartLayerRouting or lefwStartLayer.\n// This routine is optional and can be called only once within a layer \n// after each lefwLayerAntennaModel function.\n// This routine is valid only if the layer type is either ROUTING or CUT.\n// This is a 5.7 routine.\n// Returns 0 if successful. \nextern int lefwLayerAntennaAreaDiffReducePwl(int numPwls,\n               double* diffAreas, double* metalDiffFactors);\n\n// This routine must be called only once after lefwStartLayer.\n// The option MINIMUMDENSITY is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwMinimumDensity(double minDensity);\n\n// This routine must be called only once after lefwStartLayer.\n// The option MAXIMUMDENSITY is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwMaximumDensity(double maxDensity);\n\n// This routine must be called only once after lefwStartLayer.\n// The option DENSITYCHECKWINDOW is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwDensityCheckWindow(double checkWindowLength,\n                                  double checkWindowWidth);\n\n// This routine must be called only once after lefwStartLayer.\n// The option DENSITYCHECKSTEP is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwDensityCheckStep(double checkStepValue);\n\n// This routine must be called only once after lefwStartLayer.\n// The option FILLACTIVESPACING is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwFillActiveSpacing(double fillToActiveSpacing);\n\n// This routine must be called only once after all the layers.\n// This routine is optional.\n// This is a 5.5 syntax.\n// Returns 0 if succesful. \nextern int lefwMaxviastack(int value,\n                           const char* bottomLayer, // optional (NULL) \n                           const char* topLayer);   // optional (NULL) \n\n// This routine is called after lefwInit.\n// This section of routines is optional.\n// The routine can be called only once.\n// Returns 0 if successful.\n// The routine starts propertydefinitions section. \nextern int lefwStartPropDef();\n\n// This routine must be called after lefwStartPropDef.\n// This routine can be called multiple times.\n// It adds integer property definition to the statement.\n// Returns 0 if successful.\n// The objType can be LIBRARY or VIA or MACRO or PIN. \nextern int lefwIntPropDef(\n               const char* objType,   // LIBRARY | LAYER | VIA | VIARULE |\n                                      // NONDEFAULTRULE | MACRO | PIN \n               const char* propName,\n               double leftRange,      // optional(0) - RANGE \n               double rightRange,     // optional(0) \n               int    propValue);     // optional(NULL) \n\n// This routine must be called after lefwStartPropDef.\n// This routine can be called multiple times.\n// It adds real property definition to the statement.\n// Returns 0 if successful.\n// The objType can be LIBRARY or VIA or MACRO or PIN. \nextern int lefwRealPropDef(\n               const char* objType,   // LIBRARY | LAYER | VIA | VIARULE |\n                                      // NONDEFAULTRULE | MACRO | PIN \n               const char* propName,\n               double leftRange,      // optional(0) - RANGE \n               double rightRange,     // optional(0) \n               double propValue);     // optional(NULL) \n\n// This routine must be called after lefwStartPropDef.\n// This routine can be called multiple times.\n// It adds string property definition to the statement.\n// Returns 0 if successful.\n// The objType can be LIBRARY or VIA or MACRO or PIN. \nextern int lefwStringPropDef(\n               const char* objType,    // LIBRARY | LAYER | VIA | VIARULE |\n                                       //  NONDEFAULTRULE | MACRO | PIN \n               const char* propName,\n               double leftRange,       // optional(0) - RANGE \n               double rightRange,      // optional(0) \n               const char* propValue); // optional(NULL) \n\n// This routine must be called after the lefwStartPropDef call (if any).\n// The routine can be called only once.\n// Returns 0 if successful. \nextern int lefwEndPropDef();\n\n// This routine is called after lefwInit.\n// This routine must be called only once.\n// Returns 0 if successful.\n// The routine starts the via section. All of the vias must follow. \nextern int lefwStartVia(const char* viaName,\n               const char* isDefault);    // optional(NULL) - DEFAULT \n\n// This routine is optional, it call only be called after lefwStartVia.\n// It can only be called once.\n// Returns 0 if successful. \nextern int lefwViaTopofstackonly();       // TOPOFSTACKONLY \n\n// This routine is optional, it call only be called after lefwStartVia.\n// It can only be called once.\n// Returns 0 if successful. \nextern int lefwViaForeign(const char* foreignName,\n               double xl,            // optional(0) - pt(x) \n               double yl,            // optional(0) - pt(y) \n               int orient);          // optional(-1) \n\n// This routine is optional, it call only be called after lefwStartVia.\n// It can only be called once.\n// Returns 0 if successful.\n// This routine is the same as lefwViaForeign, except orient is a char* \nextern int lefwViaForeignStr(const char* foreignName,\n               double xl,            // optional(0) - pt(x) \n               double yl,            // optional(0) - pt(y) \n               const char* orient);  // optional(\"\") \n\n// This routine is optional, it call only be called after lefwStartVia.\n// Either this routine or lefwViaViarule can be called within a via.\n// It can only be called once in a via.\n// Returns 0 if successful. \nextern int lefwViaResistance(double resistance); // RESISTANCE \n\n// This routine must be called after lefwStartVia.\n// It can be called multiple times.\n// Returns 0 if successful. \nextern int lefwViaLayer(const char* layerName);  // LAYER \n\n// This routine can call only after lefwViaLayer.\n// Either this routine or lefwViaLayerPolygon can be called within a layer\n// It can be called multiple times.\n// Returns 0 if successful. \n// mask is 5.8 syntax  \nextern int lefwViaLayerRect(double x1l,   // RECT pt1(x) \n                            double y1l,   // RECT pt1(y) \n                            double x2l,   // RECT pt2(x) \n                            double y2l,   // RECT pt2(y) \n                int mask = 0); \n\n// This routine can call only after lefwViaLayer.\n// Either this routine or lefwViaLayerRect can be called within a layer\n// It can be called multiple times.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \n// mask is 5.8 syntax  \nextern int lefwViaLayerPolygon(int num_polys, double* xl, double* yl,\n                   int mask = 0);\n\n// This routine can call only after lefwStartVia.\n// Either this routine or lefwViaResistance can be called within a via.\n// It can only be called once in a via.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwViaViarule(const char* viaRuleName,\n                          double xCutSize, double yCutSize,\n                          const char* botMetalLayer, const char* cutLayer,\n                          const char* topMetalLayer,\n                          double xCutSpacing, double yCutSpacing,\n                          double xBotEnc, double yBotEnc,\n                          double xTopEnc, double yTopEnc);\n\n// This routine can call only after lefwViaViarule.\n// It can only be called once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwViaViaruleRowCol(int numCutRows, int numCutCols);\n\n// This routine can call only after lefwViaViarule.\n// It can only be called once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwViaViaruleOrigin(double xOffset, double yOffset);\n\n// This routine can call only after lefwViaViarule.\n// It can only be called once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwViaViaruleOffset(double xBotOffset, double yBotOffset,\n                                double xTopOffset, double yTopOffset);\n\n// This routine can call only after lefwViaViarule.\n// It can only be called once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwViaViarulePattern(const char* cutPattern);\n\n// This routine is called after lefwVia.\n// This routine is optional, it adds string property to the statement.\n// It can be called multiple times.\n// Returns 0 if successful. \nextern int lefwStringProperty(const char* propName, const char* propValue);\n\n// This routine is called after lefwVia.\n// This routine is optional, it adds real property to the statement.\n// It can be called multiple times.\n// Returns 0 if successful. \nextern int lefwRealProperty(const char* propName, double propValue);\n\n// This routine is called after lefwVia.\n// This routine is optional, it adds int property to the statement.\n// It can be called multiple times.\n// Returns 0 if successful. \nextern int lefwIntProperty(const char* propName, int propValue);\n\n// This routine must be called after the lefwStartVia call (if any).\n// The routine can be called only once.\n// Returns 0 if successful. \nextern int lefwEndVia(const char* viaName);\n\n// This routine is called after lefwInit.\n// This routine must be called as a set with lefwViaRuleLayer, lefwViaRuleVia\n// and lefwEndViaRule\n// multiple times.\n// Returns 0 if successful.\n// The routine starts the via rule section. The via rule data and its property\n// must follow \nextern int lefwStartViaRule(const char* viaRuleName);\n\n// This routine is called after lefwStartViaRule.\n// This routine has to be called 2 times exact.\n// Returns 0 if successful.\n// The direction1 or direction2 can be HORIZONTAL or VERTICAL. \nextern int lefwViaRuleLayer(\n               const char* layerName,\n               const char* direction,    // HORIZONTAL | VERTICAL \n               double minWidth,          // optional(0) - WIDTH \n               double maxWidth,          // optional(0) - WIDTH \n               double overhang,          // optional(0) - OVERHANG \n               double metalOverhang);    // optional(0) - METALOVERHANG \n\n// This routine is called after lefwViaRuleLayer is called twice.\n// This routine is required in a viarule and can be called more than once.\n// Returns 0 if successful.\n// The direction1 or direction2 can be HORIZONTAL or VERTICAL. \nextern int lefwViaRuleVia(\n               const char* viaName);\n\n// This routine must be called after the lefwStartViaRule call (if any).\n// The routine can be called only once per lefwStartViaRule.\n// Returns 0 if successful. \nextern int lefwEndViaRule(const char* viaRuleName);\n\n// This routine is called after lefwInit.\n// This routine must be called as a set with lefwViaRuleGenLayer,\n// lefwViaRuleGenLayer3, and lefwEndViaRuleGen multiple times.\n// Returns 0 if successful.\n// The routine starts the via rule section. The via rule data and its property\n// must follow \nextern int lefwStartViaRuleGen(const char* viaRuleName);\n \n// This routine is called after lefwSartViaRuleGen.\n// This routine is optional\n// Returns 0 if successful  \nextern int lefwViaRuleGenDefault();\n\n// This routine is called after lefwStartViaRuleGen.\n// This routine has to be called 2 times exact.\n// Returns 0 if successful.\n// Either this routine or lefwViaRuleGenLayerEnclosure, not both.\n// The direction1 or direction2 can be HORIZONTAL or VERTICAL. \nextern int lefwViaRuleGenLayer(\n               const char* layerName,\n               const char* direction,    // HORIZONTAL | VERTICAL \n               double minWidth,          // optional(0) - WIDTH \n               double maxWidth,          // optional(0) - WIDTH \n               double overhang,          // optional(0) - OVERHANG \n               double metalOverhang);    // optional(0) - METALOVERHANG \n\n// This routine is called after lefwStartViaRuleGen.\n// This routine has to be called 2 times exact.\n// This is 5.5 syntax\n// Returns 0 if successful.\n// Either this routine or lefwViaRuleGenLayer, not both. \nextern int lefwViaRuleGenLayerEnclosure(\n               const char* layerName,\n               double overhang1,\n               double overhang2,\n               double minWidth,          // optional(0) - WIDTH \n               double maxWidth);         // optional(0) - WIDTH \n \n// This routine is called after lefwViaRuleLayerGen is called twice.\n// This routine is optional in a viarule generate and can be called once.\n// Returns 0 if successful.\n// The direction1 or direction2 can be HORIZONTAL or VERTICAL. \nextern int lefwViaRuleGenLayer3(\n               const char* layerName,\n               double xl, double yl,      // RECT pt1(x), pt1(y) \n               double xh, double yh,      // RECT pt2(x), pt2(y) \n               double xSpacing, double ySpacing, // SPACING x and y \n               double resistance);        // optional(0) - RESISTANCE \n \n// This routine must be called after the lefwStartViaRuleGen call (if any).\n// The routine can be called only once per lefwStartViaRuleGen.\n// Returns 0 if successful. \nextern int lefwEndViaRuleGen(const char* viaRuleName);\n \n\n// This routine is called after lefwInit.\n// This routine must be called only once.\n// Returns 0 if successful.\n// The routine starts the nonDefaultRule section. The nonDefaultRule layers\n// must follow \nextern int lefwStartNonDefaultRule(const char* ruleName);\n\n// This routine is called after lefwInit.\n// This routine must be called after lefwStartNonDefaultRule\n// This routine can be called multiple times.\n// Returns 0 if successful. \nextern int lefwNonDefaultRuleLayer(const char* routingLayerName,\n               double width,           // WIDTH \n               double minSpacing,      // MINSPACING \n               double wireExtension,   // optinal(0) - WIREEXTENSION \n               double resistance,      // optinal(0) - RESISTANCE RPERQ \n               double capacitance,     // optinal(0) - CAPACITANCE CPERSQDIST\n               double edgeCap);        // optinal(0) - EDGECAPACITANCE \n\n// This routine is called after lefwInit.\n// This routine must be called after lefwStartNonDefaultRule\n// This routine is optional and it can be called only once.\n// Returns 0 if successful. \nextern int lefwNonDefaultRuleHardspacing();\n\n// This routine is called after lefwStartNonDefaultRule.\n// This routine must be called only once for each via section.\n// Returns 0 if successful.\n// The routine starts the nondefaultrule via section.\n// Call the following via functions for the rest of NONDEFAULTRULE VIA:\n//   lefwViaTopofstackonly\n//   lefwViaForeign\n//   lefwViaForeignStr\n//   lefwViaResistance\n//   lefwViaLayer\n//   lefwViaLayerRect\n//   lefwNonDefaultRuleEndVia \nextern int lefwNonDefaultRuleStartVia(const char* viaName,\n               const char* isDefault);    // optional(NULL) - DEFAULT \n\n// This routine must be called after the lefwNonDefaultRuleStartVia call.\n// The routine can be called only once per via section.\n// Returns 0 if successful. \nextern int lefwNonDefaultRuleEndVia(const char* viaName);\n\n// This routine is called after lefwStartNonDefaultRule.\n// This routine can be called multiple times.\n// Returns 0 if successful. \nextern int lefwNonDefaultRuleUseVia(const char* viaName);\n\n// This routine is called after lefwStartNonDefaultRule.\n// This routine can be called multiple times.\n// Returns 0 if successful. \nextern int lefwNonDefaultRuleUseViaRule(const char* viaRuleName);\n\n// This routine is called after lefwStartNonDefaultRule.\n// This routine can be called multiple times.\n// Returns 0 if successful. \nextern int lefwNonDefaultRuleMinCuts(const char* layerName, int numCuts);\n\n// This routine must be called after the lefwStartNonDefaultRule call (if any).\n// The routine can be called only once.\n// Returns 0 if successful. \nextern int lefwEndNonDefaultRule(const char* ruleName);\n\n// This routine is called after lefwInit.\n// This section of routines is optional.\n// This routine can be called only once.\n// Returns 0 if successful.\n// It starts the spacing section. \nextern int lefwStartSpacing();\n\n// This routine must be called after lefwStartSpacing.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The stack has to be STACK. \nextern int lefwSpacing(const char* layerName1,\n               const char* layerName2,\n               double minSpace,\n               const char* stack);        // optional(NULL) \n\n// This routine must be called after the lefwStartSpacing call (if any).\n// The routine can be called only once.\n// Returns 0 if successful. \nextern int lefwEndSpacing();\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwUniversalNoiseMargin (double high, double low);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEdgeRateThreshold1 (double num);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEdgeRateThreshold2 (double num);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEdgeRateScaleFactor (double num);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This routine starts the noisetable section.\n// This api is obsolete in 5.4. \nextern int lefwStartNoiseTable(int num);\n\n// This routine is called after lefwStartNoiseTable or lefwStartCorrectTable.\n// This routine is optional and it can be called multiple times\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEdgeRate(double num) ;\n\n// This routine is called after lefwEdgeRate.\n// This routine is optional and it can be called only once inside lefwEdgeRate.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwOutputResistance(int numResists, double* resistance);\n\n// This routine is called after lefwOutputResistance.\n// This routine is optional and it can be called multiple times inside\n// lefwOutputResistance\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwVictims(int length, int numNoises, double* noises);\n\n// This routine must be called after the lefwStartNoiseTable call (if any).\n// The routine can be called only once per section.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEndNoiseTable();\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This routine starts the correctTable section.\n// This api is obsolete in 5.4. \nextern int lefwStartCorrectTable(int num);\n\n// This routine must be called after the lefwStartCorrectTable call (if any).\n// The routine can be called only once per section.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEndCorrectTable();\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful. \nextern int lefwMinFeature (double x, double y);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \n// extern int lefwDielectric (float dielectric); \n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful.\n// This routine starts the irdrop section.\n// This api is obsolete in 5.4. \nextern int lefwStartIrdrop();\n\n// This routine is must be called after lefwStartIrdrop.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The currentsNvolts is a list of current and volts.\n// This api is obsolete in 5.4. \nextern int lefwIrdropTable(const char* tableName, const char* currentsNvolts);\n\n// This routine must be called after the lefwStartIrdrop call (if any).\n// The routine can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEndIrdrop();\n\n// This routine is must be called after lefwInit.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The classType can be PAD or CORE.\n// The symmetry can be a list of X or Y or R90. \nextern int lefwSite(const char* siteName, const char* classType,\n              const char* symmetry, double width, double height);\n\n// This routine is must be called after lefwSite.\n// It can be called multiple times.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwSiteRowPattern(const char* siteName, int orient);\n\n// This routine is must be called after lefwSite.\n// It can be called multiple times.\n// This is a 5.6 syntax.\n// Returns 0 if successful.\n// This routine is the same as lefwSiteRowPattern, except orient is a char* \nextern int lefwSiteRowPatternStr(const char* siteName, const char *orient);\n\n// This routine must be called after the lefwSite call (if any).\n// The routine can be called only once after lefwSite.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwEndSite(const char* siteName);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called multiple times.\n// Returns 0 if successful.\n// This routine starts the array section. \nextern int lefwStartArray(const char* arrayName);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArrayCanplace, lefwArrayCannotoccupy,\n// lefwArrayTracks, or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful. \nextern int lefwArraySite(const char* name, double origX, double origY,\n               int orient, double numX, double numY, double spaceX,\n               double spaceY);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArrayCanplace, lefwArrayCannotoccupy,\n// lefwArrayTracks, or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful.\n// This routine is the same as lefwArraySite, except orient is a char* \nextern int lefwArraySiteStr(const char* name, double origX, double origY,\n               const char *orient, double numX, double numY, double spaceX,\n               double spaceY);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArraySite, lefwArrayCannotoccupy,\n// lefwArrayTracks, or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful. \nextern int lefwArrayCanplace(const char* name, double origX, double origY,\n               int orient, double numX, double numY, double spaceX,\n               double spaceY);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArraySite, lefwArrayCannotoccupy,\n// lefwArrayTracks, or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful.\n// This routine is the same as lefwArrayCanplace, except orient is a char* \nextern int lefwArrayCanplaceStr(const char* name, double origX, double origY,\n               const char *orient, double numX, double numY, double spaceX,\n               double spaceY);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArraySite, lefwArrayCanplace,\n// lefwArrayTracks, or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful. \nextern int lefwArrayCannotoccupy(const char* name, double origX, double origY,\n               int orient, double numX, double numY, double spaceX,\n               double spaceY);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArraySite, lefwArrayCanplace,\n// lefwArrayTracks, or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful.\n// This routine is the same as lefwArrayTracks, except orient is a char* \nextern int lefwArrayCannotoccupyStr(const char* name, double origX,\n               double origY, const char *orient, double numX, double numY,\n               double spaceX, double spaceY);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArraySite, lefwArrayCanplace, lefwArrayCannotoccupy,\n// or lefwStartArrayFloorplan must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful. \nextern int lefwArrayTracks(const char* xy, double start, int numTracks,\n               double space, const char* layers);\n\n// This routine is called after lefwStartArray. \n// Either this routine, lefwArraySite, lefwArrayCanplace, lefwArrayCannotoccupy,\n// or lefwArrayTracks must be called at least once.\n// It can be call multiple times.\n// Returns 0 if successful.\n// The routine starts the array floorplan section \nextern int lefwStartArrayFloorplan(const char* name);\n\n// This routine must be called after lefwStartArrayFloorplan.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The site can be CANPLACE or CANNOTOCCUPY \nextern int lefwArrayFloorplan(const char* site, const char* name,\n                              double origX, double origY, int orient,\n                              int numX, int numY, double spaceX, double spaceY);\n\n// This routine must be called after lefwStartArrayFloorplan.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The site can be CANPLACE or CANNOTOCCUPY\n// This routine is the same as lefwArrayFloorplan, except orient is a char* \nextern int lefwArrayFloorplanStr(const char* site, const char* name,\n                              double origX, double origY, const char *orient,\n                              int numX, int numY, double spaceX, double spaceY);\n\n// This routine must be called after the lefwStartArrayFloorplan call (if any).\n// The routine can be called only once per section.\n// Returns 0 if successful. \nextern int lefwEndArrayFloorplan(const char* name);\n\n// This routine is called after lefwStartArray.\n// This routine is optional.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The xy can be X or Y. \nextern int lefwArrayGcellgrid(const char* xy, double startXY, int colRows, \n               double spaceXY);\n\n// This routine is called after lefwStartArray.\n// This section of routines is optional and can be call only once.\n// Returns 0 if successful.\n// The routine starts the array defaultcap section \nextern int lefwStartArrayDefaultCap(int size);\n\n// This routine must be called after lefwStartArrayDefaultCap.\n// It can be called multiple times.\n// Returns 0 if successful. \nextern int lefwArrayDefaultCap(double numPins, double cap);\n\n// This routine must be called after the lefwStartArrayDefaultCap call (if any).\n// The routine can be called only once.\n// Returns 0 if successful. \nextern int lefwEndArrayDefaultCap();\n\n// This routine must be called after the lefwStartArray call (if any).\n// The routine can be called only once per section.\n// Returns 0 if successful. \nextern int lefwEndArray(const char* arrayName);\n\n// This routine is must be called after lefwInit.\n// This routine can be called multiple times.\n// Returns 0 if successful.\n// This routine starts the macro section. \nextern int lefwStartMacro(const char* macroName);\n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful.\n// The value1 can be COVER, RING, BLOCK, PAD, CORE, or ENCAP.\n// The value2 can be BUMP if value1 is COVER,\n// or BLACKBOX, or SOFT if value1 is BLOCK,\n// or INPUT, OUTPUT, INOUT, POWER, or SPACER if value1 is PAD,\n// or FEEDTHRU, TIEHIGH, TIELOW, SPACER, ANTENNACELL, or WELLTAP\n// if value1 is CORE,\n// or PRE, POST, TOPLEFT, TOPRIGHT, BOOTOMLEFT, or BOTTOMRIGHT if value1 is\n// ENCAP. \nextern int lefwMacroClass(const char* value1,\n                          const char* value2);     // optional(NULL)\n\n// This routine is must be called after lefwInit.\n// This routine can be called multiple times.\n// Returns 0 if successful.\n// This is a 5.8 syntax. \nextern int lefwMacroFixedMask();\n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful.\n// The value1 can be USER, GENERATE, or BLOCK. \nextern int lefwMacroSource(const char* value1);\n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called multiple times per macro section.\n// Returns 0 if successful. \nextern int lefwMacroForeign(const char* name,\n               double xl,          // optional(0) - pt(x) \n               double yl,          // optional(0) - pt(y) \n               int orient);        // optional(-1) - 0 to 7 \n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called multiple times per macro section.\n// Returns 0 if successful.\n// This routine is the same as lefwMacroForeign, except orient is a char* \nextern int lefwMacroForeignStr(const char* name,\n               double xl,             // optional(0) - pt(x) \n               double yl,             // optional(0) - pt(y) \n               const char *orient);   // optional(\"\") \n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwMacroOrigin(double xl,   // pt(x) \n                           double yl);  // pt(y) \n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwMacroEEQ(const char* macroName);\n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwMacroLEQ(const char* macroName);\n\n// This routine is called after lefwStartMacro.\n// This routine must be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwMacroSize(double width, double height);\n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful.\n// The symmetry can be a list of X, Y, or R90 \nextern int lefwMacroSymmetry(const char* symmetry);\n\n// This routine is called after lefwStartMacro.\n// This routine must be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwMacroSite(const char* siteName);\n\n// This routine is called after lefwStartMacro.\n// This routine must be called at least once per macro section.\n// Returns 0 if successful. \nextern int lefwMacroSitePattern(const char* name,\n                                double origX, double origY,  // optional(0) \n                                int orient,                  // optional(-1) \n                                int numX, int numY,          // optional(0) \n                                double spaceX, double spaceY); // optional(0) \n\n// This routine is called after lefwStartMacro.\n// This routine must be called at least once per macro section.\n// Returns 0 if successful.\n// This routine is the same as lefwMacroSitePattern, except orient is a char* \nextern int lefwMacroSitePatternStr(const char* name,\n                                double origX, double origY,    // optional(0) \n                                const char *orient,          // optional (-1) \n                                int numX, int numY,            // optional(0) \n                                double spaceX, double spaceY); // optional(0) \n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPower(double power);\n\n// This routine must be called after the lefwStartMacro call (if any).\n// The routine can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwEndMacro(const char* macroName);\n\n// This routine is called after lefwStartMacro.\n// This routine is optional and can be called only once per macro section.\n// This is a 5.6 syntax.\n// Returns 0 if successful.\nextern int lefwStartMacroDensity(const char* layerName);\n\n// This routine is called after lefwStartMacroDensity.\n// This routine can be called multiple times.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwMacroDensityLayerRect(double x1, double y1,\n                                     double x2, double y2,\n                                     double densityValue);\n\n// This routine must be called after the lefwStartMacroPin call (if any).\n// The routine can be called only once per macro section.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwEndMacroDensity();\n\n// This routine must be called after the lefwStartMacro call (if any).\n// The routine can be called multiple time.\n// Returns 0 if successful.\n// It starts the macro pin section within macro. \nextern int lefwStartMacroPin(const char* pinName);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful. \nextern int lefwMacroPinTaperRule(const char* ruleName);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful. \nextern int lefwMacroPinForeign(const char* name,\n               double xl,       // optional(0) \n               double yl,       // optional(0) \n               int orient);     // optional(-1) - 0 to 7 \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// Ths routine is the same as lefwMacroPinForeign, except orient is a char* \nextern int lefwMacroPinForeignStr(const char* name,\n               double xl,             // optional(0) \n               double yl,             // optional(0) \n               const char* orient);   // optional(\"\") \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful. \nextern int lefwMacroPinLEQ(const char* pinName);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// The direction can be INPUT, OUTPUT, OUTPUT TRISTATE, INOUT, or FEEDTHRU. \nextern int lefwMacroPinDirection(const char* direction);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// The use can be SIGNAL, ANALOG, POWER, GROUND, or CLOCK. \nextern int lefwMacroPinUse(const char* use);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// The namce can be ABUTMENT, RING, or FEEDTHRU. \nextern int lefwMacroPinShape(const char* name);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful. \nextern int lefwMacroPinMustjoin(const char* name);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwMacroPinNetExpr(const char* name);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwMacroPinSupplySensitivity(const char* pinName);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// This is a 5.6 syntax.\n// Returns 0 if successful. \nextern int lefwMacroPinGroundSensitivity(const char* pinName);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinOutputnoisemargin(int high, int low);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinOutputresistance(int high, int low);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinInputnoisemargin(int high, int low);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinPower(double power);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinLeakage(double leakage);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinCapacitance(double capacitance);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinResistance(double resistance);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinPulldownres(double resistance);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinTieoffr(double resistance);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinVHI(double voltage);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinVLO(double voltage);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinRisevoltagethreshold(double voltage);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinFallvoltagethreshold(double voltage);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinRisethresh(double capacitance);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinFallthresh(double capacitance);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinRisesatcur(double current);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinFallsatcur(double current);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// The name can be ACTIVE or RESISTIVE.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinCurrentsource(const char* name);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroPinIV_Tables(const char* lowName, const char* highName);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// Either this routine or 5.4 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennasize(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// Either this routine or 5.4 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaMetalArea(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// Either this routine or 5.4 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaMetalLength(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaPartialMetalArea(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaPartialMetalSideArea(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaPartialCutArea(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaDiffArea(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// The oxide value, can be either OXIDE1, OXIDE2, OXIDE3, or OXIDE4.\n// This routine is optional. Each oxide value can be called only once\n// after the lefwStartMacroPin.\n// This is a 5.5 syntax.\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaModel(const char* oxide);\n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called multiple times.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaGateArea(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaMaxAreaCar(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaMaxSideAreaCar(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine is called after lefwStartMacroPin.\n// This routine is optional and can be called only once.\n// This is a 5.4 syntax.\n// Either this routine or 5.3 Antenna syntax, cannot be both\n// Returns 0 if successful. \nextern int lefwMacroPinAntennaMaxCutCar(double value,\n               const char* layerName); // optional(NULL) \n\n// This routine must be called after the lefwStartMacroPin call (if any).\n// The routine can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwEndMacroPin(const char* pinName);\n\n// This routine must be called after the lefwStartMacroPin call (if any).\n// The routine can be called multiple time.\n// Returns 0 if successful.\n// It starts the macro pin port section within macro pin.\n// The classType can be NONE or CORE. \nextern int lefwStartMacroPinPort(const char* classType); // optional(NULL) \n\n// This routine is called after lefwStartMacroPinPort.\n// Either this routine or lefwMacroPinPortDesignRuleWidth must be called, \n// but can't be both.\n// Spacing is optional for minimum spacing.\n// Returns 0 if successful. \nextern int lefwMacroPinPortLayer(const char* layerName,\n                                 double spacing);       // optional(0) \n\n// This routine is called after lefwStartMacroPinPort.\n// Either this routine or lefwMacroPinPortLayer must be called, but can't\n// be both.\n// width is optional for DesignRuleWidth\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwMacroPinPortDesignRuleWidth(const char* layerName,\n                                           double width);     // optional(0) \n\n// This routine is called after lefwMacroPinPortLayer.\n// Returns 0 if successful. \nextern int lefwMacroPinPortLayerWidth(double width);\n\n// This routine is called after lefwStartMacroPinPortLayer.\n// Either this routine, lefwStartMacroPinPortLayerRect, or\n// lefwStartMacroPinPortLayerPolygon must be called.\n// Returns 0 if successful. \nextern int lefwMacroPinPortLayerPath(int num_paths, double* xl, double* yl,\n               int numX,               // optional(0) \n               int numY,               // optional(0) \n               double spaceX,          // optional(0) \n               double spaceY,          // optional(0) \n           int    mask = 0);       // optional(0) \n\n// This routine is called after lefwStartMacroPinPortLayer.\n// Either this routine, lefwStartMacroPinPortLayerPath, or\n// lefwStartMacroPinPortLayerPolygon must be called.\n// Returns 0 if successful. \nextern int lefwMacroPinPortLayerRect(double xl1, double yl1,\n               double xl2, double yl2,\n               int numX,               // optional(0) \n               int numY,               // optional(0) \n               double spaceX,          // optional(0) \n               double spaceY,          // optional(0) \n           int mask = 0);          // optional(0) \n\n// This routine is called after lefwStartMacroPinPortLayer.\n// Either this routine, lefwStartMacroPinPortLayerPath, or\n// lefwStartMacroPinPortLayerRect must be called.\n// Returns 0 if successful. \nextern int lefwMacroPinPortLayerPolygon(int num_polys,\n               double* xl, double* yl,\n               int numX,               // optional(0) \n               int numY,               // optional(0) \n               double spaceX,          // optional(0) \n               double spaceY,          // optional(0) \n           int mask = 0);          // optional(0) \n\n// This routine is called after lefwStartMacroPinPort.\n// Either this routine or lefwStartMacroPinPortLayer must be called. \n// Returns 0 if successful. \nextern int lefwMacroPinPortVia(double xl, double yl, const char* viaName,\n               int numX,               // optional(0) \n               int numY,               // optional(0) \n               double spaceX,          // optional(0) \n               double spaceY,          // optional(0) \n           int mask = 0);          // optional(0) \n\n// This routine must be called after the lefwStartMacroPinPort call (if any).\n// The routine can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwEndMacroPinPort();\n\n// This routine is called after the lefwStartMacro call (if any).\n// The routine is optional and can be called multiple times.\n// Returns 0 if successful.\n// It starts the macro obs section within macro. \nextern int lefwStartMacroObs();\n\n// This routine is called after lefwStartMacroObs.\n// Either this routine, lefwMacroObsDesignRuleWidth, lefwMacroObsVia or\n// lefwMacroExceptPGNet must be called.\n// Spacing is optional for minimum spacing.\n// Returns 0 if successful. \nextern int lefwMacroObsLayer(const char* layerName,\n                             double spacing);       // optional(0) \n\n// This routine is called after lefwStartMacroObs.\n// Either this routine, lefwMacroObsLayer, lefwMacroObsVia or\n// lefwMacroExceptPGNet must be called.\n// Spacing is optional for minimum spacing.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwMacroObsDesignRuleWidth(const char* layerName,\n                                       double width);       // optional(0) \n\n// This routine is called after lefwStartMacroObs.\n// Either this routine, lefwMacroObsLayer, lefwMacroObsVia or\n// lefwMacroObsDesignRuleWidth must be called.\n// Spacing is optional for minimum spacing.\n// This is a 5.4 syntax.\n// Returns 0 if successful. \nextern int lefwMacroExceptPGNet(const char* layerName);\n\n// This routine is called after lefwStartMacroObs.\n// Returns 0 if successful. \nextern int lefwMacroObsLayerWidth(double width);\n\n// This routine is called after lefwStartMacroObsLayer.\n// Either this routine, lefwMacroObsLayerRect, or\n// lefwStartMacroObsLayerPolygon must be called.\n// Returns 0 if successful. \nextern int lefwMacroObsLayerPath(int num_paths, double* xl, double* yl,\n               int numX,                  // optional(0) \n               int numY,                  // optional(0) \n               double spaceX,             // optional(0) \n               double spaceY,             // optional(0) \n           int mask = 0);             // optional(0) \n\n// This routine is called after lefwStartMacroObsLayer.\n// Either this routine, lefwMacroObsLayerPath, or\n// lefwStartMacroObsLayerPolygon must be called.\n// Returns 0 if successful. \nextern int lefwMacroObsLayerRect(double xl1, double yl1,\n               double xl2, double yl2,\n               int numX,                  // optional(0) \n               int numY,                  // optional(0) \n               double spaceX,             // optional(0) \n               double spaceY,             // optional(0) \n           int mask = 0);             // optional(0) \n\n// This routine is called after lefwStartMacroObsLayer.\n// Either this routine, lefwMacroObsLayerPath, or\n// lefwStartMacroObsLayerPath must be called.\n// Returns 0 if successful. \nextern int lefwMacroObsLayerPolygon(int num_polys, double* xl, double* yl,\n               int numX,                  // optional(0) \n               int numY,                  // optional(0) \n               double spaceX,             // optional(0) \n               double spaceY,             // optional(0) \n           int mask = 0);             // optional(0) \n\n// This routine is called after lefwStartMacroObs.\n// Either this routine or lefwMacroObsLayer|lefwMacroObsDesignRuleWidth\n// must be called.\n// Returns 0 if successful. \nextern int lefwMacroObsVia(double xl, double yl, const char* viaName,\n               int numX,                  // optional(0) \n               int numY,                  // optional(0) \n               double spaceX,             // optional(0) \n               double spaceY,             // optional(0) \n           int mask = 0);             // optional(0) \n\n// This routine must be called after the lefwStartMacroObs call (if any).\n// The routine can be called only once per macro section.\n// Returns 0 if successful. \nextern int lefwEndMacroObs();\n\n// This routine is called after the lefwStartMacro call (if any).\n// The routine is optional and can be called only once.\n// Returns 0 if successful.\n// It starts the macro timing section within macro.\n// This api is obsolete in 5.4. \nextern int lefwStartMacroTiming();\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This routine is for {FROMPIN pinName...; [TOPIN pinName...;] | FROMPIN\n// pinName...;}\n// This routince can be called multiple times.\n// The num_frPinNames contains the number of object in the array fromPins.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingPin(const char* fromPin, const char* toPin);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The riseFall can be RISE or FALL.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingIntrinsic(const char* riseFall, double min,\n               double max,\n               double slewT1,          // optional(0) \n               double slewT1Min,       // optional(0) \n               double slewT1Max,       // optional(0) \n               double slewT2,          // optional(0) \n               double slewT2Min,       // optional(0) \n               double slewT2Max,       // optional(0) \n               double slewT3,          // optional(0) \n               double varMin, double varMax);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingRisers(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingFallrs(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingRisecs(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingFallcs(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingRisesatt1(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingFallsatt1(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingRiset0(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingFallt0(double min, double max);\n\n// This routine must be called after the lefwStartMacroTiming.\n// It can be called multiple times.\n// Returns 0 if successful.\n// The unateness can be INVERT, NONINVERT or NONUNATE.\n// This api is obsolete in 5.4. \nextern int lefwMacroTimingUnateness(const char* unateness);\n\n// This routine must be called after the lefwStartMacroTiming call (if any).\n// The routine can be called only once.\n// Returns 0 if successful.\n// This api is obsolete in 5.4. \nextern int lefwEndMacroTiming();\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful. \nextern int lefwAntenna(const char* type,   // INPUTPINANTENNASIZE |\n                                           // OUTPUTPINANTENNASIZE |\n                                           // INOUTPINANTENNASIZE\n                       double value);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful. \nextern int lefwStartBeginext(const char* name);\n\n// This routine is called after lefwBeginext.\n// This routine is optional, it can be called only once.\n// Returns 0 if successful. \nextern int lefwBeginextCreator (const char* creatorName);\n\n// This routine is called after lefwBeginext.\n// This routine is optional, it can be called only once.\n// It gets the current system time and date.\n// Returns 0 if successful. \nextern int lefwBeginextDate ();\n\n// This routine is called after lefwBeginext.\n// This routine is optional, it can be called only once.\n// Returns 0 if successful. \nextern int lefwBeginextRevision (int vers1, int vers2);   // vers1.vers2 \n\n// This routine is called after lefwBeginext.\n// This routine is optional, it can be called many times.\n// It allows user to customize their own syntax.\n// Returns 0 if successful. \nextern int lefwBeginextSyntax (const char* title, const char* string);\n\n// This routine is called after lefwInit.\n// This routine is optional and it can be called only once.\n// Returns 0 if successful. \nextern int lefwEndBeginext();\n\n// General routines that can be called anytime after the Init is called.\nextern int lefwCurrentLineNumber();\n\n// This routine must call last, it ends the Lef library.\n// It must be called only once.\n// Returns 0 if successful. \nextern int lefwEnd();\n\n// This routine will print the error message. \nextern void lefwPrintError(int status);\n\n// This routine will allow user to write their own comemnt.  It will\n// automactically add a # infront of the line.\nextern void lefwAddComment(const char* comment);\n\n// This routine will indent 3 blank spaces \nextern void lefwAddIndent();\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefwWriterCalls.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012 - 2013, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef LEFI_WRITER_H\n#define LEFI_WRITER_H\n\n#include <stdarg.h>\n#include <stdio.h>\n \n#include \"lefiKRDefs.hpp\"\n#include \"lefiDefs.hpp\"\n#include \"lefiUser.hpp\"\n\nBEGIN_LEFDEF_PARSER_NAMESPACE\n\n/*\n * The main writer function.\n * The file should already be opened.  This requirement allows\n * the writer to be used with stdin or a pipe.  The file name\n * is only used for error messages.  The includeSearchPath is\n * a colon-delimited list of directories in which to find\n * include files.\n */\nextern int lefwWrite ( FILE *file,\n                 const char *fileName,\n                 lefiUserData userData );\n\n/*\n * Set all of the callbacks that have not yet been set to a function\n * that will add up how many times a given lef data type was ignored\n * (ie no callback was done).  The statistics can later be printed out.\n */\nextern void lefwSetRegisterUnusedCallbacks ( void );\nextern void lefwPrintUnusedCallbacks ( FILE* f );\n\n/*\n * Set/get the client-provided user data.  lefi doesn't look at\n * this data at all, it simply passes the opaque lefiUserData pointer\n * back to the application with each callback.  The client can\n * change the data at any time, and it will take effect on the\n * next callback.  The lefi writer and writer maintain separate\n * user data pointers.\n */\nextern void lefwSetUserData ( lefiUserData );\nextern lefiUserData lefwGetUserData ( void );\n \n/*\n * An enum describing all of the types of writer callbacks.\n */\ntypedef enum {\n  lefwUnspecifiedCbkType = 0,\n  lefwVersionCbkType,\n  lefwCaseSensitiveCbkType,\n  lefwNoWireExtensionCbkType,\n  lefwBusBitCharsCbkType,\n  lefwDividerCharCbkType,\n  lefwManufacturingGridCbkType,\n  lefwUseMinSpacingCbkType,\n  lefwClearanceMeasureCbkType,\n  lefwUnitsCbkType,\n  lefwAntennaInputGateAreaCbkType,\n  lefwAntennaInOutDiffAreaCbkType,\n  lefwAntennaOutputDiffAreaCbkType,\n  lefwPropDefCbkType,\n  lefwLayerCbkType,\n  lefwViaCbkType,\n  lefwViaRuleCbkType,\n  lefwNonDefaultCbkType,\n  lefwCrossTalkCbkType,\n  lefwNoiseTableCbkType,\n  lefwCorrectionTableCbkType,\n  lefwSpacingCbkType,\n  lefwMinFeatureCbkType,\n  lefwDielectricCbkType,\n  lefwIRDropCbkType,\n  lefwSiteCbkType,\n  lefwArrayCbkType,\n  lefwMacroCbkType,\n  lefwAntennaCbkType,\n  lefwExtCbkType,\n  lefwEndLibCbkType\n\n  /* NEW CALLBACKS - each callback has its own type.  For each callback\n   * that you add, you must add an item to this enum. */\n\n} lefwCallbackType_e;\n \n \n/* Declarations of function signatures for each type of callback.\n * These declarations are type-safe when compiling with ANSI C\n * or C++; you will only be able to register a function pointer\n * with the correct signature for a given type of callback.\n *\n * Each callback function is expected to return 0 if successful.\n * A non-zero return code will cause the writer to abort.\n *\n * The lefwDesignStart and lefwDesignEnd callback is only called once.\n * Other callbacks may be called multiple times, each time with a different\n * set of data.\n *\n * For each callback, the Lef API will make the callback to the\n * function supplied by the client, which should either make a copy\n * of the Lef object, or store the data in the client's own data structures.\n * The Lef API will delete or reuse each object after making the callback,\n * so the client should not keep a pointer to it.\n *\n * All callbacks pass the user data pointer provided in lefwRead()\n * or lefwSetUserData() back to the client; this can be used by the\n * client to obtain access to the rest of the client's data structures.\n *\n * The user data pointer is obtained using lefwGetUserData() immediately\n * prior to making each callback, so the client is free to change the\n * user data on the fly if necessary.\n *\n * Callbacks with the same signature are passed a callback type\n * parameter, which allows an application to write a single callback\n * function, register that function for multiple callbacks, then\n * switch based on the callback type to handle the appropriate type of\n * data.\n */\n \n\n// A declaration of the signature of all callbacks that return nothing. \ntypedef int (*lefwVoidCbkFnType) ( lefwCallbackType_e, lefiUserData );\n\n /* NEW CALLBACK - If your callback returns a pointer to a new class then\n  * you must add a type function here. */\n\n/* Functions to call to register a callback function.\n */\nextern void lefwSetVersionCbk(lefwVoidCbkFnType);\nextern void lefwSetCaseSensitiveCbk(lefwVoidCbkFnType);\nextern void lefwSetNoWireExtensionCbk(lefwVoidCbkFnType);\nextern void lefwSetBusBitCharsCbk(lefwVoidCbkFnType);\nextern void lefwSetDividerCharCbk(lefwVoidCbkFnType);\nextern void lefwSetManufacturingGridCbk(lefwVoidCbkFnType);\nextern void lefwSetUseMinSpacingCbk(lefwVoidCbkFnType);\nextern void lefwSetClearanceMeasureCbk(lefwVoidCbkFnType);\nextern void lefwSetUnitsCbk(lefwVoidCbkFnType);\nextern void lefwAntennaInputGateAreaCbk(lefwVoidCbkFnType);\nextern void lefwAntennaInOutDiffAreaCbk(lefwVoidCbkFnType);\nextern void lefwAntennaOutputDiffAreaCbk(lefwVoidCbkFnType);\nextern void lefwSetPropDefCbk(lefwVoidCbkFnType);\nextern void lefwSetLayerCbk(lefwVoidCbkFnType);\nextern void lefwSetViaCbk(lefwVoidCbkFnType);\nextern void lefwSetViaRuleCbk(lefwVoidCbkFnType);\nextern void lefwSetNonDefaultCbk(lefwVoidCbkFnType);\nextern void lefwSetCrossTalkCbk(lefwVoidCbkFnType);\nextern void lefwSetNoiseTableCbk(lefwVoidCbkFnType);\nextern void lefwSetCorrectionTableCbk(lefwVoidCbkFnType);\nextern void lefwSetSpacingCbk(lefwVoidCbkFnType);\nextern void lefwSetMinFeatureCbk(lefwVoidCbkFnType);\nextern void lefwSetDielectricCbk(lefwVoidCbkFnType);\nextern void lefwSetIRDropCbk(lefwVoidCbkFnType);\nextern void lefwSetSiteCbk(lefwVoidCbkFnType);\nextern void lefwSetArrayCbk(lefwVoidCbkFnType);\nextern void lefwSetMacroCbk(lefwVoidCbkFnType);\nextern void lefwSetAntennaCbk(lefwVoidCbkFnType);\nextern void lefwSetExtCbk(lefwVoidCbkFnType);\nextern void lefwSetEndLibCbk(lefwVoidCbkFnType);\n\n/* NEW CALLBACK - each callback must have a function to allow the user\n * to set it.  Add the function here. */\n\n/*\n * Set all of the callbacks that have not yet been set to the following\n * function.  This is especially useful if you want to check to see\n * if you forgot anything.\n */\nextern void lefwSetUnusedCallbacks (lefwVoidCbkFnType func);\n\n// Routine to set the message logging routine for errors \ntypedef void (*LEFI_LOG_FUNCTION)(const char*);\nextern void lefwSetLogFunction( LEFI_LOG_FUNCTION );\n\n// Routine to set the message logging routine for warnings \ntypedef void (*LEFI_WARNING_LOG_FUNCTION)(const char*);\nextern void lefwSetWarningLogFunction( LEFI_WARNING_LOG_FUNCTION );\n\nEND_LEFDEF_PARSER_NAMESPACE\n\nUSE_LEFDEF_PARSER_NAMESPACE\n\n#endif\n"
  },
  {
    "path": "rsyn/include/lef5.8/lefzlib.hpp",
    "content": "// *****************************************************************************\n// *****************************************************************************\n// Copyright 2012, Cadence Design Systems\n// \n// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source\n// Distribution,  Product Version 5.8. \n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n//    you may not use this file except in compliance with the License.\n//    You may obtain a copy of the License at\n// \n//        http://www.apache.org/licenses/LICENSE-2.0\n// \n//    Unless required by applicable law or agreed to in writing, software\n//    distributed under the License is distributed on an \"AS IS\" BASIS,\n//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n//    implied. See the License for the specific language governing\n//    permissions and limitations under the License.\n// \n// For updates, support, or to become part of the LEF/DEF Community,\n// check www.openeda.org for details.\n// \n//  $Author: dell $\n//  $Revision: #1 $\n//  $Date: 2017/06/06 $\n//  $State:  $\n// *****************************************************************************\n// *****************************************************************************\n\n#ifndef LEFZLIB_H\n\ntypedef void* lefGZFile;\n\n/* \n * Name: lefGZipOpen\n * Description: Open a gzip file\n * Returns: A file pointer\n */\nextern lefGZFile lefGZipOpen(const char* gzipFile, const char* mode);\n\n/* \n * Name: lefGZipClose\n * Description: Close a gzip file\n * Returns: 0 if no errors\n */\nextern int lefGZipClose(lefGZFile filePtr);\n\n/*\n * Name: lefrReadGZip\n * Description: Parse a lef gzip file\n * Returns: 0 if no errors\n */\nextern int lefrReadGZip(lefGZFile file, const char* gzipFile, void* uData);\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/3rdparty/json/json.hpp",
    "content": "/*\n    __ _____ _____ _____\n __|  |   __|     |   | |  JSON for Modern C++\n|  |  |__   |  |  | | | |  version 2.0.2\n|_____|_____|_____|_|___|  https://github.com/nlohmann/json\n\nLicensed under the MIT License <http://opensource.org/licenses/MIT>.\nCopyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.\n\nPermission is hereby  granted, free of charge, to any  person obtaining a copy\nof this software and associated  documentation files (the \"Software\"), to deal\nin the Software  without restriction, including without  limitation the rights\nto  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell\ncopies  of  the Software,  and  to  permit persons  to  whom  the Software  is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE  IS PROVIDED \"AS  IS\", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR\nIMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,\nFITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE\nAUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER\nLIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n#ifndef NLOHMANN_JSON_HPP\n#define NLOHMANN_JSON_HPP\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <ciso646>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <functional>\n#include <initializer_list>\n#include <iomanip>\n#include <iostream>\n#include <iterator>\n#include <limits>\n#include <locale>\n#include <map>\n#include <memory>\n#include <numeric>\n#include <sstream>\n#include <stdexcept>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n// exclude unsupported compilers\n#if defined(__clang__)\n    #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)\n    #if CLANG_VERSION < 30400\n        #error \"unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers\"\n    #endif\n#elif defined(__GNUC__)\n    #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)\n    #if GCC_VERSION < 40900\n        #error \"unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers\"\n    #endif\n#endif\n\n// disable float-equal warnings on GCC/clang\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n    #pragma GCC diagnostic push\n    #pragma GCC diagnostic ignored \"-Wfloat-equal\"\n#endif\n\n/*!\n@brief namespace for Niels Lohmann\n@see https://github.com/nlohmann\n@since version 1.0.0\n*/\nnamespace nlohmann\n{\n\n\n/*!\n@brief unnamed namespace with internal helper functions\n@since version 1.0.0\n*/\nnamespace\n{\n/*!\n@brief Helper to determine whether there's a key_type for T.\n\nThus helper is used to tell associative containers apart from other containers\nsuch as sequence containers. For instance, `std::map` passes the test as it\ncontains a `mapped_type`, whereas `std::vector` fails the test.\n\n@sa http://stackoverflow.com/a/7728728/266378\n@since version 1.0.0\n*/\ntemplate<typename T>\nstruct has_mapped_type\n{\n  private:\n    template<typename C> static char test(typename C::mapped_type*);\n    template<typename C> static char (&test(...))[2];\n  public:\n    static constexpr bool value = sizeof(test<T>(0)) == 1;\n};\n\n/*!\n@brief helper class to create locales with decimal point\n\nThis struct is used a default locale during the JSON serialization. JSON\nrequires the decimal point to be `.`, so this function overloads the\n`do_decimal_point()` function to return `.`. This function is called by\nfloat-to-string conversions to retrieve the decimal separator between integer\nand fractional parts.\n\n@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315\n@since version 2.0.0\n*/\nstruct DecimalSeparator : std::numpunct<char>\n{\n    char do_decimal_point() const\n    {\n        return '.';\n    }\n};\n\n}\n\n/*!\n@brief a class to store JSON values\n\n@tparam ObjectType type for JSON objects (`std::map` by default; will be used\nin @ref object_t)\n@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used\nin @ref array_t)\n@tparam StringType type for JSON strings and object keys (`std::string` by\ndefault; will be used in @ref string_t)\n@tparam BooleanType type for JSON booleans (`bool` by default; will be used\nin @ref boolean_t)\n@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by\ndefault; will be used in @ref number_integer_t)\n@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c\n`uint64_t` by default; will be used in @ref number_unsigned_t)\n@tparam NumberFloatType type for JSON floating-point numbers (`double` by\ndefault; will be used in @ref number_float_t)\n@tparam AllocatorType type of the allocator to use (`std::allocator` by\ndefault)\n\n@requirement The class satisfies the following concept requirements:\n- Basic\n - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):\n   JSON values can be default constructed. The result will be a JSON null value.\n - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):\n   A JSON value can be constructed from an rvalue argument.\n - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):\n   A JSON value can be copy-constructed from an lvalue expression.\n - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):\n   A JSON value van be assigned from an rvalue argument.\n - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):\n   A JSON value can be copy-assigned from an lvalue expression.\n - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):\n   JSON values can be destructed.\n- Layout\n - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):\n   JSON values have\n   [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):\n   All non-static data members are private and standard layout types, the class\n   has no virtual functions or (virtual) base classes.\n- Library-wide\n - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):\n   JSON values can be compared with `==`, see @ref\n   operator==(const_reference,const_reference).\n - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):\n   JSON values can be compared with `<`, see @ref\n   operator<(const_reference,const_reference).\n - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):\n   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of\n   other compatible types, using unqualified function call @ref swap().\n - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):\n   JSON values can be compared against `std::nullptr_t` objects which are used\n   to model the `null` value.\n- Container\n - [Container](http://en.cppreference.com/w/cpp/concept/Container):\n   JSON values can be used like STL containers and provide iterator access.\n - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);\n   JSON values can be used like STL containers and provide reverse iterator\n   access.\n\n@invariant The member variables @a m_value and @a m_type have the following\nrelationship:\n- If `m_type == value_t::object`, then `m_value.object != nullptr`.\n- If `m_type == value_t::array`, then `m_value.array != nullptr`.\n- If `m_type == value_t::string`, then `m_value.string != nullptr`.\nThe invariants are checked by member function assert_invariant().\n\n@internal\n@note ObjectType trick from http://stackoverflow.com/a/9860911\n@endinternal\n\n@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange\nFormat](http://rfc7159.net/rfc7159)\n\n@since version 1.0.0\n\n@nosubgrouping\n*/\ntemplate <\n    template<typename U, typename V, typename... Args> class ObjectType = std::map,\n    template<typename U, typename... Args> class ArrayType = std::vector,\n    class StringType = std::string,\n    class BooleanType = bool,\n    class NumberIntegerType = std::int64_t,\n    class NumberUnsignedType = std::uint64_t,\n    class NumberFloatType = double,\n    template<typename U> class AllocatorType = std::allocator\n    >\nclass basic_json\n{\n  private:\n    /// workaround type for MSVC\n    using basic_json_t = basic_json<ObjectType, ArrayType, StringType,\n          BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,\n          AllocatorType>;\n\n  public:\n    // forward declarations\n    template<typename Base> class json_reverse_iterator;\n    class json_pointer;\n\n    /////////////////////\n    // container types //\n    /////////////////////\n\n    /// @name container types\n    /// The canonic container types to use @ref basic_json like any other STL\n    /// container.\n    /// @{\n\n    /// the type of elements in a basic_json container\n    using value_type = basic_json;\n\n    /// the type of an element reference\n    using reference = value_type&;\n    /// the type of an element const reference\n    using const_reference = const value_type&;\n\n    /// a type to represent differences between iterators\n    using difference_type = std::ptrdiff_t;\n    /// a type to represent container sizes\n    using size_type = std::size_t;\n\n    /// the allocator type\n    using allocator_type = AllocatorType<basic_json>;\n\n    /// the type of an element pointer\n    using pointer = typename std::allocator_traits<allocator_type>::pointer;\n    /// the type of an element const pointer\n    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;\n\n    /// an iterator for a basic_json container\n    class iterator;\n    /// a const iterator for a basic_json container\n    class const_iterator;\n    /// a reverse iterator for a basic_json container\n    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;\n    /// a const reverse iterator for a basic_json container\n    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;\n\n    /// @}\n\n\n    /*!\n    @brief returns the allocator associated with the container\n    */\n    static allocator_type get_allocator()\n    {\n        return allocator_type();\n    }\n\n\n    ///////////////////////////\n    // JSON value data types //\n    ///////////////////////////\n\n    /// @name JSON value data types\n    /// The data types to store a JSON value. These types are derived from\n    /// the template arguments passed to class @ref basic_json.\n    /// @{\n\n    /*!\n    @brief a type for an object\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:\n    > An object is an unordered collection of zero or more name/value pairs,\n    > where a name is a string and a value is a string, number, boolean, null,\n    > object, or array.\n\n    To store objects in C++, a type is defined by the template parameters\n    described below.\n\n    @tparam ObjectType  the container to store objects (e.g., `std::map` or\n    `std::unordered_map`)\n    @tparam StringType the type of the keys or names (e.g., `std::string`).\n    The comparison function `std::less<StringType>` is used to order elements\n    inside the container.\n    @tparam AllocatorType the allocator to use for objects (e.g.,\n    `std::allocator`)\n\n    #### Default type\n\n    With the default values for @a ObjectType (`std::map`), @a StringType\n    (`std::string`), and @a AllocatorType (`std::allocator`), the default\n    value for @a object_t is:\n\n    @code {.cpp}\n    std::map<\n      std::string, // key_type\n      basic_json, // value_type\n      std::less<std::string>, // key_compare\n      std::allocator<std::pair<const std::string, basic_json>> // allocator_type\n    >\n    @endcode\n\n    #### Behavior\n\n    The choice of @a object_t influences the behavior of the JSON class. With\n    the default type, objects have the following behavior:\n\n    - When all names are unique, objects will be interoperable in the sense\n      that all software implementations receiving that object will agree on\n      the name-value mappings.\n    - When the names within an object are not unique, later stored name/value\n      pairs overwrite previously stored name/value pairs, leaving the used\n      names unique. For instance, `{\"key\": 1}` and `{\"key\": 2, \"key\": 1}` will\n      be treated as equal and both stored as `{\"key\": 1}`.\n    - Internally, name/value pairs are stored in lexicographical order of the\n      names. Objects will also be serialized (see @ref dump) in this order.\n      For instance, `{\"b\": 1, \"a\": 2}` and `{\"a\": 2, \"b\": 1}` will be stored\n      and serialized as `{\"a\": 2, \"b\": 1}`.\n    - When comparing objects, the order of the name/value pairs is irrelevant.\n      This makes objects interoperable in the sense that they will not be\n      affected by these differences. For instance, `{\"b\": 1, \"a\": 2}` and\n      `{\"a\": 2, \"b\": 1}` will be treated as equal.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the maximum depth of nesting.\n\n    In this class, the object's limit of nesting is not constraint explicitly.\n    However, a maximum depth of nesting may be introduced by the compiler or\n    runtime environment. A theoretical limit can be queried by calling the\n    @ref max_size function of a JSON object.\n\n    #### Storage\n\n    Objects are stored as pointers in a @ref basic_json type. That is, for any\n    access to object values, a pointer of type `object_t*` must be\n    dereferenced.\n\n    @sa @ref array_t -- type for an array value\n\n    @since version 1.0.0\n\n    @note The order name/value pairs are added to the object is *not*\n    preserved by the library. Therefore, iterating an object may return\n    name/value pairs in a different order than they were originally stored. In\n    fact, keys will be traversed in alphabetical order as `std::map` with\n    `std::less` is used by default. Please note this behavior conforms to [RFC\n    7159](http://rfc7159.net/rfc7159), because any order implements the\n    specified \"unordered\" nature of JSON objects.\n    */\n    using object_t = ObjectType<StringType,\n          basic_json,\n          std::less<StringType>,\n          AllocatorType<std::pair<const StringType,\n          basic_json>>>;\n\n    /*!\n    @brief a type for an array\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:\n    > An array is an ordered sequence of zero or more values.\n\n    To store objects in C++, a type is defined by the template parameters\n    explained below.\n\n    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or\n    `std::list`)\n    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)\n\n    #### Default type\n\n    With the default values for @a ArrayType (`std::vector`) and @a\n    AllocatorType (`std::allocator`), the default value for @a array_t is:\n\n    @code {.cpp}\n    std::vector<\n      basic_json, // value_type\n      std::allocator<basic_json> // allocator_type\n    >\n    @endcode\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the maximum depth of nesting.\n\n    In this class, the array's limit of nesting is not constraint explicitly.\n    However, a maximum depth of nesting may be introduced by the compiler or\n    runtime environment. A theoretical limit can be queried by calling the\n    @ref max_size function of a JSON array.\n\n    #### Storage\n\n    Arrays are stored as pointers in a @ref basic_json type. That is, for any\n    access to array values, a pointer of type `array_t*` must be dereferenced.\n\n    @sa @ref object_t -- type for an object value\n\n    @since version 1.0.0\n    */\n    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;\n\n    /*!\n    @brief a type for a string\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:\n    > A string is a sequence of zero or more Unicode characters.\n\n    To store objects in C++, a type is defined by the template parameter\n    described below. Unicode values are split by the JSON class into\n    byte-sized characters during deserialization.\n\n    @tparam StringType  the container to store strings (e.g., `std::string`).\n    Note this container is used for keys/names in objects, see @ref object_t.\n\n    #### Default type\n\n    With the default values for @a StringType (`std::string`), the default\n    value for @a string_t is:\n\n    @code {.cpp}\n    std::string\n    @endcode\n\n    #### String comparison\n\n    [RFC 7159](http://rfc7159.net/rfc7159) states:\n    > Software implementations are typically required to test names of object\n    > members for equality. Implementations that transform the textual\n    > representation into sequences of Unicode code units and then perform the\n    > comparison numerically, code unit by code unit, are interoperable in the\n    > sense that implementations will agree in all cases on equality or\n    > inequality of two strings. For example, implementations that compare\n    > strings with escaped characters unconverted may incorrectly find that\n    > `\"a\\\\b\"` and `\"a\\u005Cb\"` are not equal.\n\n    This implementation is interoperable as it does compare strings code unit\n    by code unit.\n\n    #### Storage\n\n    String values are stored as pointers in a @ref basic_json type. That is,\n    for any access to string values, a pointer of type `string_t*` must be\n    dereferenced.\n\n    @since version 1.0.0\n    */\n    using string_t = StringType;\n\n    /*!\n    @brief a type for a boolean\n\n    [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a\n    type which differentiates the two literals `true` and `false`.\n\n    To store objects in C++, a type is defined by the template parameter @a\n    BooleanType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a BooleanType (`bool`), the default value for\n    @a boolean_t is:\n\n    @code {.cpp}\n    bool\n    @endcode\n\n    #### Storage\n\n    Boolean values are stored directly inside a @ref basic_json type.\n\n    @since version 1.0.0\n    */\n    using boolean_t = BooleanType;\n\n    /*!\n    @brief a type for a number (integer)\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n    > The representation of numbers is similar to that used in most\n    > programming languages. A number is represented in base 10 using decimal\n    > digits. It contains an integer component that may be prefixed with an\n    > optional minus sign, which may be followed by a fraction part and/or an\n    > exponent part. Leading zeros are not allowed. (...) Numeric values that\n    > cannot be represented in the grammar below (such as Infinity and NaN)\n    > are not permitted.\n\n    This description includes both integer and floating-point numbers.\n    However, C++ allows more precise storage if it is known whether the number\n    is a signed integer, an unsigned integer or a floating-point number.\n    Therefore, three different types, @ref number_integer_t, @ref\n    number_unsigned_t and @ref number_float_t are used.\n\n    To store integer numbers in C++, a type is defined by the template\n    parameter @a NumberIntegerType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a NumberIntegerType (`int64_t`), the default\n    value for @a number_integer_t is:\n\n    @code {.cpp}\n    int64_t\n    @endcode\n\n    #### Default behavior\n\n    - The restrictions about leading zeros is not enforced in C++. Instead,\n      leading zeros in integer literals lead to an interpretation as octal\n      number. Internally, the value will be stored as decimal number. For\n      instance, the C++ integer literal `010` will be serialized to `8`.\n      During deserialization, leading zeros yield an error.\n    - Not-a-number (NaN) values will be serialized to `null`.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the range and precision of numbers.\n\n    When the default type is used, the maximal integer number that can be\n    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number\n    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers\n    that are out of range will yield over/underflow when used in a\n    constructor. During deserialization, too large or small integer numbers\n    will be automatically be stored as @ref number_unsigned_t or @ref\n    number_float_t.\n\n    [RFC 7159](http://rfc7159.net/rfc7159) further states:\n    > Note that when such software is used, numbers that are integers and are\n    > in the range \\f$[-2^{53}+1, 2^{53}-1]\\f$ are interoperable in the sense\n    > that implementations will agree exactly on their numeric values.\n\n    As this range is a subrange of the exactly supported range [INT64_MIN,\n    INT64_MAX], this class's integer type is interoperable.\n\n    #### Storage\n\n    Integer number values are stored directly inside a @ref basic_json type.\n\n    @sa @ref number_float_t -- type for number values (floating-point)\n\n    @sa @ref number_unsigned_t -- type for number values (unsigned integer)\n\n    @since version 1.0.0\n    */\n    using number_integer_t = NumberIntegerType;\n\n    /*!\n    @brief a type for a number (unsigned)\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n    > The representation of numbers is similar to that used in most\n    > programming languages. A number is represented in base 10 using decimal\n    > digits. It contains an integer component that may be prefixed with an\n    > optional minus sign, which may be followed by a fraction part and/or an\n    > exponent part. Leading zeros are not allowed. (...) Numeric values that\n    > cannot be represented in the grammar below (such as Infinity and NaN)\n    > are not permitted.\n\n    This description includes both integer and floating-point numbers.\n    However, C++ allows more precise storage if it is known whether the number\n    is a signed integer, an unsigned integer or a floating-point number.\n    Therefore, three different types, @ref number_integer_t, @ref\n    number_unsigned_t and @ref number_float_t are used.\n\n    To store unsigned integer numbers in C++, a type is defined by the\n    template parameter @a NumberUnsignedType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a NumberUnsignedType (`uint64_t`), the\n    default value for @a number_unsigned_t is:\n\n    @code {.cpp}\n    uint64_t\n    @endcode\n\n    #### Default behavior\n\n    - The restrictions about leading zeros is not enforced in C++. Instead,\n      leading zeros in integer literals lead to an interpretation as octal\n      number. Internally, the value will be stored as decimal number. For\n      instance, the C++ integer literal `010` will be serialized to `8`.\n      During deserialization, leading zeros yield an error.\n    - Not-a-number (NaN) values will be serialized to `null`.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the range and precision of numbers.\n\n    When the default type is used, the maximal integer number that can be\n    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer\n    number that can be stored is `0`. Integer numbers that are out of range\n    will yield over/underflow when used in a constructor. During\n    deserialization, too large or small integer numbers will be automatically\n    be stored as @ref number_integer_t or @ref number_float_t.\n\n    [RFC 7159](http://rfc7159.net/rfc7159) further states:\n    > Note that when such software is used, numbers that are integers and are\n    > in the range \\f$[-2^{53}+1, 2^{53}-1]\\f$ are interoperable in the sense\n    > that implementations will agree exactly on their numeric values.\n\n    As this range is a subrange (when considered in conjunction with the\n    number_integer_t type) of the exactly supported range [0, UINT64_MAX],\n    this class's integer type is interoperable.\n\n    #### Storage\n\n    Integer number values are stored directly inside a @ref basic_json type.\n\n    @sa @ref number_float_t -- type for number values (floating-point)\n    @sa @ref number_integer_t -- type for number values (integer)\n\n    @since version 2.0.0\n    */\n    using number_unsigned_t = NumberUnsignedType;\n\n    /*!\n    @brief a type for a number (floating-point)\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n    > The representation of numbers is similar to that used in most\n    > programming languages. A number is represented in base 10 using decimal\n    > digits. It contains an integer component that may be prefixed with an\n    > optional minus sign, which may be followed by a fraction part and/or an\n    > exponent part. Leading zeros are not allowed. (...) Numeric values that\n    > cannot be represented in the grammar below (such as Infinity and NaN)\n    > are not permitted.\n\n    This description includes both integer and floating-point numbers.\n    However, C++ allows more precise storage if it is known whether the number\n    is a signed integer, an unsigned integer or a floating-point number.\n    Therefore, three different types, @ref number_integer_t, @ref\n    number_unsigned_t and @ref number_float_t are used.\n\n    To store floating-point numbers in C++, a type is defined by the template\n    parameter @a NumberFloatType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a NumberFloatType (`double`), the default\n    value for @a number_float_t is:\n\n    @code {.cpp}\n    double\n    @endcode\n\n    #### Default behavior\n\n    - The restrictions about leading zeros is not enforced in C++. Instead,\n      leading zeros in floating-point literals will be ignored. Internally,\n      the value will be stored as decimal number. For instance, the C++\n      floating-point literal `01.2` will be serialized to `1.2`. During\n      deserialization, leading zeros yield an error.\n    - Not-a-number (NaN) values will be serialized to `null`.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) states:\n    > This specification allows implementations to set limits on the range and\n    > precision of numbers accepted. Since software that implements IEEE\n    > 754-2008 binary64 (double precision) numbers is generally available and\n    > widely used, good interoperability can be achieved by implementations\n    > that expect no more precision or range than these provide, in the sense\n    > that implementations will approximate JSON numbers within the expected\n    > precision.\n\n    This implementation does exactly follow this approach, as it uses double\n    precision floating-point numbers. Note values smaller than\n    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`\n    will be stored as NaN internally and be serialized to `null`.\n\n    #### Storage\n\n    Floating-point number values are stored directly inside a @ref basic_json\n    type.\n\n    @sa @ref number_integer_t -- type for number values (integer)\n\n    @sa @ref number_unsigned_t -- type for number values (unsigned integer)\n\n    @since version 1.0.0\n    */\n    using number_float_t = NumberFloatType;\n\n    /// @}\n\n\n    ///////////////////////////\n    // JSON type enumeration //\n    ///////////////////////////\n\n    /*!\n    @brief the JSON type enumeration\n\n    This enumeration collects the different JSON types. It is internally used\n    to distinguish the stored values, and the functions @ref is_null(), @ref\n    is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref\n    is_number() (with @ref is_number_integer(), @ref is_number_unsigned(), and\n    @ref is_number_float()), @ref is_discarded(), @ref is_primitive(), and\n    @ref is_structured() rely on it.\n\n    @note There are three enumeration entries (number_integer,\n    number_unsigned, and number_float), because the library distinguishes\n    these three types for numbers: @ref number_unsigned_t is used for unsigned\n    integers, @ref number_integer_t is used for signed integers, and @ref\n    number_float_t is used for floating-point numbers or to approximate\n    integers which do not fit in the limits of their respective type.\n\n    @sa @ref basic_json(const value_t value_type) -- create a JSON value with\n    the default value for a given type\n\n    @since version 1.0.0\n    */\n    enum class value_t : uint8_t\n    {\n        null,            ///< null value\n        object,          ///< object (unordered set of name/value pairs)\n        array,           ///< array (ordered collection of values)\n        string,          ///< string value\n        boolean,         ///< boolean value\n        number_integer,  ///< number value (signed integer)\n        number_unsigned, ///< number value (unsigned integer)\n        number_float,    ///< number value (floating-point)\n        discarded        ///< discarded by the the parser callback function\n    };\n\n\n  private:\n\n    /// helper for exception-safe object creation\n    template<typename T, typename... Args>\n    static T* create(Args&& ... args)\n    {\n        AllocatorType<T> alloc;\n        auto deleter = [&](T * object)\n        {\n            alloc.deallocate(object, 1);\n        };\n        std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);\n        alloc.construct(object.get(), std::forward<Args>(args)...);\n        assert(object.get() != nullptr);\n        return object.release();\n    }\n\n    ////////////////////////\n    // JSON value storage //\n    ////////////////////////\n\n    /*!\n    @brief a JSON value\n\n    The actual storage for a JSON value of the @ref basic_json class. This\n    union combines the different storage types for the JSON value types\n    defined in @ref value_t.\n\n    JSON type | value_t type    | used type\n    --------- | --------------- | ------------------------\n    object    | object          | pointer to @ref object_t\n    array     | array           | pointer to @ref array_t\n    string    | string          | pointer to @ref string_t\n    boolean   | boolean         | @ref boolean_t\n    number    | number_integer  | @ref number_integer_t\n    number    | number_unsigned | @ref number_unsigned_t\n    number    | number_float    | @ref number_float_t\n    null      | null            | *no value is stored*\n\n    @note Variable-length types (objects, arrays, and strings) are stored as\n    pointers. The size of the union should not exceed 64 bits if the default\n    value types are used.\n\n    @since version 1.0.0\n    */\n    union json_value\n    {\n        /// object (stored with pointer to save storage)\n        object_t* object;\n        /// array (stored with pointer to save storage)\n        array_t* array;\n        /// string (stored with pointer to save storage)\n        string_t* string;\n        /// boolean\n        boolean_t boolean;\n        /// number (integer)\n        number_integer_t number_integer;\n        /// number (unsigned integer)\n        number_unsigned_t number_unsigned;\n        /// number (floating-point)\n        number_float_t number_float;\n\n        /// default constructor (for null values)\n        json_value() = default;\n        /// constructor for booleans\n        json_value(boolean_t v) noexcept : boolean(v) {}\n        /// constructor for numbers (integer)\n        json_value(number_integer_t v) noexcept : number_integer(v) {}\n        /// constructor for numbers (unsigned)\n        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}\n        /// constructor for numbers (floating-point)\n        json_value(number_float_t v) noexcept : number_float(v) {}\n        /// constructor for empty values of a given type\n        json_value(value_t t)\n        {\n            switch (t)\n            {\n                case value_t::object:\n                {\n                    object = create<object_t>();\n                    break;\n                }\n\n                case value_t::array:\n                {\n                    array = create<array_t>();\n                    break;\n                }\n\n                case value_t::string:\n                {\n                    string = create<string_t>(\"\");\n                    break;\n                }\n\n                case value_t::boolean:\n                {\n                    boolean = boolean_t(false);\n                    break;\n                }\n\n                case value_t::number_integer:\n                {\n                    number_integer = number_integer_t(0);\n                    break;\n                }\n\n                case value_t::number_unsigned:\n                {\n                    number_unsigned = number_unsigned_t(0);\n                    break;\n                }\n\n                case value_t::number_float:\n                {\n                    number_float = number_float_t(0.0);\n                    break;\n                }\n\n                default:\n                {\n                    break;\n                }\n            }\n        }\n\n        /// constructor for strings\n        json_value(const string_t& value)\n        {\n            string = create<string_t>(value);\n        }\n\n        /// constructor for objects\n        json_value(const object_t& value)\n        {\n            object = create<object_t>(value);\n        }\n\n        /// constructor for arrays\n        json_value(const array_t& value)\n        {\n            array = create<array_t>(value);\n        }\n    };\n\n    /*!\n    @brief checks the class invariants\n\n    This function asserts the class invariants. It needs to be called at the\n    end of every constructor to make sure that created objects respect the\n    invariant. Furthermore, it has to be called each time the type of a JSON\n    value is changed, because the invariant expresses a relationship between\n    @a m_type and @a m_value.\n    */\n    void assert_invariant() const\n    {\n        assert(m_type != value_t::object or m_value.object != nullptr);\n        assert(m_type != value_t::array or m_value.array != nullptr);\n        assert(m_type != value_t::string or m_value.string != nullptr);\n    }\n\n  public:\n    //////////////////////////\n    // JSON parser callback //\n    //////////////////////////\n\n    /*!\n    @brief JSON callback events\n\n    This enumeration lists the parser events that can trigger calling a\n    callback function of type @ref parser_callback_t during parsing.\n\n    @image html callback_events.png \"Example when certain parse events are triggered\"\n\n    @since version 1.0.0\n    */\n    enum class parse_event_t : uint8_t\n    {\n        /// the parser read `{` and started to process a JSON object\n        object_start,\n        /// the parser read `}` and finished processing a JSON object\n        object_end,\n        /// the parser read `[` and started to process a JSON array\n        array_start,\n        /// the parser read `]` and finished processing a JSON array\n        array_end,\n        /// the parser read a key of a value in an object\n        key,\n        /// the parser finished reading a JSON value\n        value\n    };\n\n    /*!\n    @brief per-element parser callback type\n\n    With a parser callback function, the result of parsing a JSON text can be\n    influenced. When passed to @ref parse(std::istream&, const\n    parser_callback_t) or @ref parse(const string_t&, const parser_callback_t),\n    it is called on certain events (passed as @ref parse_event_t via parameter\n    @a event) with a set recursion depth @a depth and context JSON value\n    @a parsed. The return value of the callback function is a boolean\n    indicating whether the element that emitted the callback shall be kept or\n    not.\n\n    We distinguish six scenarios (determined by the event type) in which the\n    callback function can be called. The following table describes the values\n    of the parameters @a depth, @a event, and @a parsed.\n\n    parameter @a event | description | parameter @a depth | parameter @a parsed\n    ------------------ | ----------- | ------------------ | -------------------\n    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded\n    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key\n    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object\n    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded\n    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array\n    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value\n\n    @image html callback_events.png \"Example when certain parse events are triggered\"\n\n    Discarding a value (i.e., returning `false`) has different effects\n    depending on the context in which function was called:\n\n    - Discarded values in structured types are skipped. That is, the parser\n      will behave as if the discarded value was never read.\n    - In case a value outside a structured type is skipped, it is replaced\n      with `null`. This case happens if the top-level element is skipped.\n\n    @param[in] depth  the depth of the recursion during parsing\n\n    @param[in] event  an event of type parse_event_t indicating the context in\n    the callback function has been called\n\n    @param[in,out] parsed  the current intermediate parse result; note that\n    writing to this value has no effect for parse_event_t::key events\n\n    @return Whether the JSON value which called the function during parsing\n    should be kept (`true`) or not (`false`). In the latter case, it is either\n    skipped completely or replaced by an empty discarded object.\n\n    @sa @ref parse(std::istream&, parser_callback_t) or\n    @ref parse(const string_t&, parser_callback_t) for examples\n\n    @since version 1.0.0\n    */\n    using parser_callback_t = std::function<bool(int depth,\n                              parse_event_t event,\n                              basic_json& parsed)>;\n\n\n    //////////////////\n    // constructors //\n    //////////////////\n\n    /// @name constructors and destructors\n    /// Constructors of class @ref basic_json, copy/move constructor, copy\n    /// assignment, static functions creating objects, and the destructor.\n    /// @{\n\n    /*!\n    @brief create an empty value with a given type\n\n    Create an empty JSON value with a given type. The value will be default\n    initialized with an empty value which depends on the type:\n\n    Value type  | initial value\n    ----------- | -------------\n    null        | `null`\n    boolean     | `false`\n    string      | `\"\"`\n    number      | `0`\n    object      | `{}`\n    array       | `[]`\n\n    @param[in] value_type  the type of the value to create\n\n    @complexity Constant.\n\n    @throw std::bad_alloc if allocation for object, array, or string value\n    fails\n\n    @liveexample{The following code shows the constructor for different @ref\n    value_t values,basic_json__value_t}\n\n    @sa @ref basic_json(std::nullptr_t) -- create a `null` value\n    @sa @ref basic_json(boolean_t value) -- create a boolean value\n    @sa @ref basic_json(const string_t&) -- create a string value\n    @sa @ref basic_json(const object_t&) -- create a object value\n    @sa @ref basic_json(const array_t&) -- create a array value\n    @sa @ref basic_json(const number_float_t) -- create a number\n    (floating-point) value\n    @sa @ref basic_json(const number_integer_t) -- create a number (integer)\n    value\n    @sa @ref basic_json(const number_unsigned_t) -- create a number (unsigned)\n    value\n\n    @since version 1.0.0\n    */\n    basic_json(const value_t value_type)\n        : m_type(value_type), m_value(value_type)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a null object (implicitly)\n\n    Create a `null` JSON value. This is the implicit version of the `null`\n    value constructor as it takes no parameters.\n\n    @note The class invariant is satisfied, because it poses no requirements\n    for null values.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this constructor never throws\n    exceptions.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n    - As postcondition, it holds: `basic_json().empty() == true`.\n\n    @liveexample{The following code shows the constructor for a `null` JSON\n    value.,basic_json}\n\n    @sa @ref basic_json(std::nullptr_t) -- create a `null` value\n\n    @since version 1.0.0\n    */\n    basic_json() = default;\n\n    /*!\n    @brief create a null object (explicitly)\n\n    Create a `null` JSON value. This is the explicitly version of the `null`\n    value constructor as it takes a null pointer as parameter. It allows to\n    create `null` values by explicitly assigning a `nullptr` to a JSON value.\n    The passed null pointer itself is not read -- it is only used to choose\n    the right constructor.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this constructor never throws\n    exceptions.\n\n    @liveexample{The following code shows the constructor with null pointer\n    parameter.,basic_json__nullptr_t}\n\n    @sa @ref basic_json() -- default constructor (implicitly creating a `null`\n    value)\n\n    @since version 1.0.0\n    */\n    basic_json(std::nullptr_t) noexcept\n        : basic_json(value_t::null)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an object (explicit)\n\n    Create an object JSON value with a given content.\n\n    @param[in] val  a value for the object\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for object value fails\n\n    @liveexample{The following code shows the constructor with an @ref\n    object_t parameter.,basic_json__object_t}\n\n    @sa @ref basic_json(const CompatibleObjectType&) -- create an object value\n    from a compatible STL container\n\n    @since version 1.0.0\n    */\n    basic_json(const object_t& val)\n        : m_type(value_t::object), m_value(val)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an object (implicit)\n\n    Create an object JSON value with a given content. This constructor allows\n    any type @a CompatibleObjectType that can be used to construct values of\n    type @ref object_t.\n\n    @tparam CompatibleObjectType An object type whose `key_type` and\n    `value_type` is compatible to @ref object_t. Examples include `std::map`,\n    `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with\n    a `key_type` of `std::string`, and a `value_type` from which a @ref\n    basic_json value can be constructed.\n\n    @param[in] val  a value for the object\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for object value fails\n\n    @liveexample{The following code shows the constructor with several\n    compatible object type parameters.,basic_json__CompatibleObjectType}\n\n    @sa @ref basic_json(const object_t&) -- create an object value\n\n    @since version 1.0.0\n    */\n    template <class CompatibleObjectType, typename\n              std::enable_if<\n                  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and\n                  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type\n              = 0>\n    basic_json(const CompatibleObjectType& val)\n        : m_type(value_t::object)\n    {\n        using std::begin;\n        using std::end;\n        m_value.object = create<object_t>(begin(val), end(val));\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an array (explicit)\n\n    Create an array JSON value with a given content.\n\n    @param[in] val  a value for the array\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for array value fails\n\n    @liveexample{The following code shows the constructor with an @ref array_t\n    parameter.,basic_json__array_t}\n\n    @sa @ref basic_json(const CompatibleArrayType&) -- create an array value\n    from a compatible STL containers\n\n    @since version 1.0.0\n    */\n    basic_json(const array_t& val)\n        : m_type(value_t::array), m_value(val)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an array (implicit)\n\n    Create an array JSON value with a given content. This constructor allows\n    any type @a CompatibleArrayType that can be used to construct values of\n    type @ref array_t.\n\n    @tparam CompatibleArrayType An object type whose `value_type` is\n    compatible to @ref array_t. Examples include `std::vector`, `std::deque`,\n    `std::list`, `std::forward_list`, `std::array`, `std::set`,\n    `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a\n    `value_type` from which a @ref basic_json value can be constructed.\n\n    @param[in] val  a value for the array\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for array value fails\n\n    @liveexample{The following code shows the constructor with several\n    compatible array type parameters.,basic_json__CompatibleArrayType}\n\n    @sa @ref basic_json(const array_t&) -- create an array value\n\n    @since version 1.0.0\n    */\n    template <class CompatibleArrayType, typename\n              std::enable_if<\n                  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and\n                  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and\n                  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and\n                  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and\n                  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and\n                  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and\n                  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type\n              = 0>\n    basic_json(const CompatibleArrayType& val)\n        : m_type(value_t::array)\n    {\n        using std::begin;\n        using std::end;\n        m_value.array = create<array_t>(begin(val), end(val));\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a string (explicit)\n\n    Create an string JSON value with a given content.\n\n    @param[in] val  a value for the string\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for string value fails\n\n    @liveexample{The following code shows the constructor with an @ref\n    string_t parameter.,basic_json__string_t}\n\n    @sa @ref basic_json(const typename string_t::value_type*) -- create a\n    string value from a character pointer\n    @sa @ref basic_json(const CompatibleStringType&) -- create a string value\n    from a compatible string container\n\n    @since version 1.0.0\n    */\n    basic_json(const string_t& val)\n        : m_type(value_t::string), m_value(val)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a string (explicit)\n\n    Create a string JSON value with a given content.\n\n    @param[in] val  a literal value for the string\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for string value fails\n\n    @liveexample{The following code shows the constructor with string literal\n    parameter.,basic_json__string_t_value_type}\n\n    @sa @ref basic_json(const string_t&) -- create a string value\n    @sa @ref basic_json(const CompatibleStringType&) -- create a string value\n    from a compatible string container\n\n    @since version 1.0.0\n    */\n    basic_json(const typename string_t::value_type* val)\n        : basic_json(string_t(val))\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a string (implicit)\n\n    Create a string JSON value with a given content.\n\n    @param[in] val  a value for the string\n\n    @tparam CompatibleStringType an string type which is compatible to @ref\n    string_t, for instance `std::string`.\n\n    @complexity Linear in the size of the passed @a val.\n\n    @throw std::bad_alloc if allocation for string value fails\n\n    @liveexample{The following code shows the construction of a string value\n    from a compatible type.,basic_json__CompatibleStringType}\n\n    @sa @ref basic_json(const string_t&) -- create a string value\n    @sa @ref basic_json(const typename string_t::value_type*) -- create a\n    string value from a character pointer\n\n    @since version 1.0.0\n    */\n    template <class CompatibleStringType, typename\n              std::enable_if<\n                  std::is_constructible<string_t, CompatibleStringType>::value, int>::type\n              = 0>\n    basic_json(const CompatibleStringType& val)\n        : basic_json(string_t(val))\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a boolean (explicit)\n\n    Creates a JSON boolean type from a given value.\n\n    @param[in] val  a boolean value to store\n\n    @complexity Constant.\n\n    @liveexample{The example below demonstrates boolean\n    values.,basic_json__boolean_t}\n\n    @since version 1.0.0\n    */\n    basic_json(boolean_t val) noexcept\n        : m_type(value_t::boolean), m_value(val)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an integer number (explicit)\n\n    Create an integer number JSON value with a given content.\n\n    @tparam T A helper type to remove this function via SFINAE in case @ref\n    number_integer_t is the same as `int`. In this case, this constructor\n    would have the same signature as @ref basic_json(const int value). Note\n    the helper type @a T is not visible in this constructor's interface.\n\n    @param[in] val  an integer to create a JSON number from\n\n    @complexity Constant.\n\n    @liveexample{The example below shows the construction of an integer\n    number value.,basic_json__number_integer_t}\n\n    @sa @ref basic_json(const int) -- create a number value (integer)\n    @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number\n    value (integer) from a compatible number type\n\n    @since version 1.0.0\n    */\n    template<typename T,\n             typename std::enable_if<\n                 not (std::is_same<T, int>::value)\n                 and std::is_same<T, number_integer_t>::value\n                 , int>::type\n             = 0>\n    basic_json(const number_integer_t val) noexcept\n        : m_type(value_t::number_integer), m_value(val)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an integer number from an enum type (explicit)\n\n    Create an integer number JSON value with a given content.\n\n    @param[in] val  an integer to create a JSON number from\n\n    @note This constructor allows to pass enums directly to a constructor. As\n    C++ has no way of specifying the type of an anonymous enum explicitly, we\n    can only rely on the fact that such values implicitly convert to int. As\n    int may already be the same type of number_integer_t, we may need to\n    switch off the constructor @ref basic_json(const number_integer_t).\n\n    @complexity Constant.\n\n    @liveexample{The example below shows the construction of an integer\n    number value from an anonymous enum.,basic_json__const_int}\n\n    @sa @ref basic_json(const number_integer_t) -- create a number value\n    (integer)\n    @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number\n    value (integer) from a compatible number type\n\n    @since version 1.0.0\n    */\n    basic_json(const int val) noexcept\n        : m_type(value_t::number_integer),\n          m_value(static_cast<number_integer_t>(val))\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an integer number (implicit)\n\n    Create an integer number JSON value with a given content. This constructor\n    allows any type @a CompatibleNumberIntegerType that can be used to\n    construct values of type @ref number_integer_t.\n\n    @tparam CompatibleNumberIntegerType An integer type which is compatible to\n    @ref number_integer_t. Examples include the types `int`, `int32_t`,\n    `long`, and `short`.\n\n    @param[in] val  an integer to create a JSON number from\n\n    @complexity Constant.\n\n    @liveexample{The example below shows the construction of several integer\n    number values from compatible\n    types.,basic_json__CompatibleIntegerNumberType}\n\n    @sa @ref basic_json(const number_integer_t) -- create a number value\n    (integer)\n    @sa @ref basic_json(const int) -- create a number value (integer)\n\n    @since version 1.0.0\n    */\n    template<typename CompatibleNumberIntegerType, typename\n             std::enable_if<\n                 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and\n                 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and\n                 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,\n                 CompatibleNumberIntegerType>::type\n             = 0>\n    basic_json(const CompatibleNumberIntegerType val) noexcept\n        : m_type(value_t::number_integer),\n          m_value(static_cast<number_integer_t>(val))\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an unsigned integer number (explicit)\n\n    Create an unsigned integer number JSON value with a given content.\n\n    @tparam T  helper type to compare number_unsigned_t and unsigned int (not\n    visible in) the interface.\n\n    @param[in] val  an integer to create a JSON number from\n\n    @complexity Constant.\n\n    @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number\n    value (unsigned integer) from a compatible number type\n\n    @since version 2.0.0\n    */\n    template<typename T,\n             typename std::enable_if<\n                 not (std::is_same<T, int>::value)\n                 and std::is_same<T, number_unsigned_t>::value\n                 , int>::type\n             = 0>\n    basic_json(const number_unsigned_t val) noexcept\n        : m_type(value_t::number_unsigned), m_value(val)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an unsigned number (implicit)\n\n    Create an unsigned number JSON value with a given content. This\n    constructor allows any type @a CompatibleNumberUnsignedType that can be\n    used to construct values of type @ref number_unsigned_t.\n\n    @tparam CompatibleNumberUnsignedType An integer type which is compatible\n    to @ref number_unsigned_t. Examples may include the types `unsigned int`,\n    `uint32_t`, or `unsigned short`.\n\n    @param[in] val  an unsigned integer to create a JSON number from\n\n    @complexity Constant.\n\n    @sa @ref basic_json(const number_unsigned_t) -- create a number value\n    (unsigned)\n\n    @since version 2.0.0\n    */\n    template <typename CompatibleNumberUnsignedType, typename\n              std::enable_if <\n                  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and\n                  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and\n                  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,\n                  CompatibleNumberUnsignedType>::type\n              = 0>\n    basic_json(const CompatibleNumberUnsignedType val) noexcept\n        : m_type(value_t::number_unsigned),\n          m_value(static_cast<number_unsigned_t>(val))\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a floating-point number (explicit)\n\n    Create a floating-point number JSON value with a given content.\n\n    @param[in] val  a floating-point value to create a JSON number from\n\n    @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6\n    disallows NaN values:\n    > Numeric values that cannot be represented in the grammar below (such as\n    > Infinity and NaN) are not permitted.\n    In case the parameter @a val is not a number, a JSON null value is created\n    instead.\n\n    @complexity Constant.\n\n    @liveexample{The following example creates several floating-point\n    values.,basic_json__number_float_t}\n\n    @sa @ref basic_json(const CompatibleNumberFloatType) -- create a number\n    value (floating-point) from a compatible number type\n\n    @since version 1.0.0\n    */\n    basic_json(const number_float_t val) noexcept\n        : m_type(value_t::number_float), m_value(val)\n    {\n        // replace infinity and NAN by null\n        if (not std::isfinite(val))\n        {\n            m_type = value_t::null;\n            m_value = json_value();\n        }\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief create an floating-point number (implicit)\n\n    Create an floating-point number JSON value with a given content. This\n    constructor allows any type @a CompatibleNumberFloatType that can be used\n    to construct values of type @ref number_float_t.\n\n    @tparam CompatibleNumberFloatType A floating-point type which is\n    compatible to @ref number_float_t. Examples may include the types `float`\n    or `double`.\n\n    @param[in] val  a floating-point to create a JSON number from\n\n    @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6\n    disallows NaN values:\n    > Numeric values that cannot be represented in the grammar below (such as\n    > Infinity and NaN) are not permitted.\n    In case the parameter @a val is not a number, a JSON null value is\n    created instead.\n\n    @complexity Constant.\n\n    @liveexample{The example below shows the construction of several\n    floating-point number values from compatible\n    types.,basic_json__CompatibleNumberFloatType}\n\n    @sa @ref basic_json(const number_float_t) -- create a number value\n    (floating-point)\n\n    @since version 1.0.0\n    */\n    template<typename CompatibleNumberFloatType, typename = typename\n             std::enable_if<\n                 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and\n                 std::is_floating_point<CompatibleNumberFloatType>::value>::type\n             >\n    basic_json(const CompatibleNumberFloatType val) noexcept\n        : basic_json(number_float_t(val))\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a container (array or object) from an initializer list\n\n    Creates a JSON value of type array or object from the passed initializer\n    list @a init. In case @a type_deduction is `true` (default), the type of\n    the JSON value to be created is deducted from the initializer list @a init\n    according to the following rules:\n\n    1. If the list is empty, an empty JSON object value `{}` is created.\n    2. If the list consists of pairs whose first element is a string, a JSON\n       object value is created where the first elements of the pairs are\n       treated as keys and the second elements are as values.\n    3. In all other cases, an array is created.\n\n    The rules aim to create the best fit between a C++ initializer list and\n    JSON values. The rationale is as follows:\n\n    1. The empty initializer list is written as `{}` which is exactly an empty\n       JSON object.\n    2. C++ has now way of describing mapped types other than to list a list of\n       pairs. As JSON requires that keys must be of type string, rule 2 is the\n       weakest constraint one can pose on initializer lists to interpret them\n       as an object.\n    3. In all other cases, the initializer list could not be interpreted as\n       JSON object type, so interpreting it as JSON array type is safe.\n\n    With the rules described above, the following JSON values cannot be\n    expressed by an initializer list:\n\n    - the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)\n      with an empty initializer list in this case\n    - arrays whose elements satisfy rule 2: use @ref\n      array(std::initializer_list<basic_json>) with the same initializer list\n      in this case\n\n    @note When used without parentheses around an empty initializer list, @ref\n    basic_json() is called instead of this function, yielding the JSON null\n    value.\n\n    @param[in] init  initializer list with JSON values\n\n    @param[in] type_deduction internal parameter; when set to `true`, the type\n    of the JSON value is deducted from the initializer list @a init; when set\n    to `false`, the type provided via @a manual_type is forced. This mode is\n    used by the functions @ref array(std::initializer_list<basic_json>) and\n    @ref object(std::initializer_list<basic_json>).\n\n    @param[in] manual_type internal parameter; when @a type_deduction is set\n    to `false`, the created JSON value will use the provided type (only @ref\n    value_t::array and @ref value_t::object are valid); when @a type_deduction\n    is set to `true`, this parameter has no effect\n\n    @throw std::domain_error if @a type_deduction is `false`, @a manual_type\n    is `value_t::object`, but @a init contains an element which is not a pair\n    whose first element is a string; example: `\"cannot create object from\n    initializer list\"`\n\n    @complexity Linear in the size of the initializer list @a init.\n\n    @liveexample{The example below shows how JSON values are created from\n    initializer lists.,basic_json__list_init_t}\n\n    @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array\n    value from an initializer list\n    @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object\n    value from an initializer list\n\n    @since version 1.0.0\n    */\n    basic_json(std::initializer_list<basic_json> init,\n               bool type_deduction = true,\n               value_t manual_type = value_t::array)\n    {\n        // check if each element is an array with two elements whose first\n        // element is a string\n        bool is_an_object = std::all_of(init.begin(), init.end(),\n                                        [](const basic_json & element)\n        {\n            return element.is_array() and element.size() == 2 and element[0].is_string();\n        });\n\n        // adjust type if type deduction is not wanted\n        if (not type_deduction)\n        {\n            // if array is wanted, do not create an object though possible\n            if (manual_type == value_t::array)\n            {\n                is_an_object = false;\n            }\n\n            // if object is wanted but impossible, throw an exception\n            if (manual_type == value_t::object and not is_an_object)\n            {\n                throw std::domain_error(\"cannot create object from initializer list\");\n            }\n        }\n\n        if (is_an_object)\n        {\n            // the initializer list is a list of pairs -> create object\n            m_type = value_t::object;\n            m_value = value_t::object;\n\n            std::for_each(init.begin(), init.end(), [this](const basic_json & element)\n            {\n                m_value.object->emplace(*(element[0].m_value.string), element[1]);\n            });\n        }\n        else\n        {\n            // the initializer list describes an array -> create array\n            m_type = value_t::array;\n            m_value.array = create<array_t>(init);\n        }\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief explicitly create an array from an initializer list\n\n    Creates a JSON array value from a given initializer list. That is, given a\n    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the\n    initializer list is empty, the empty array `[]` is created.\n\n    @note This function is only needed to express two edge cases that cannot\n    be realized with the initializer list constructor (@ref\n    basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases\n    are:\n    1. creating an array whose elements are all pairs whose first element is a\n    string -- in this case, the initializer list constructor would create an\n    object, taking the first elements as keys\n    2. creating an empty array -- passing the empty initializer list to the\n    initializer list constructor yields an empty object\n\n    @param[in] init  initializer list with JSON values to create an array from\n    (optional)\n\n    @return JSON array value\n\n    @complexity Linear in the size of @a init.\n\n    @liveexample{The following code shows an example for the `array`\n    function.,array}\n\n    @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --\n    create a JSON value from an initializer list\n    @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object\n    value from an initializer list\n\n    @since version 1.0.0\n    */\n    static basic_json array(std::initializer_list<basic_json> init =\n                                std::initializer_list<basic_json>())\n    {\n        return basic_json(init, false, value_t::array);\n    }\n\n    /*!\n    @brief explicitly create an object from an initializer list\n\n    Creates a JSON object value from a given initializer list. The initializer\n    lists elements must be pairs, and their first elements must be strings. If\n    the initializer list is empty, the empty object `{}` is created.\n\n    @note This function is only added for symmetry reasons. In contrast to the\n    related function @ref array(std::initializer_list<basic_json>), there are\n    no cases which can only be expressed by this function. That is, any\n    initializer list @a init can also be passed to the initializer list\n    constructor @ref basic_json(std::initializer_list<basic_json>, bool,\n    value_t).\n\n    @param[in] init  initializer list to create an object from (optional)\n\n    @return JSON object value\n\n    @throw std::domain_error if @a init is not a pair whose first elements are\n    strings; thrown by\n    @ref basic_json(std::initializer_list<basic_json>, bool, value_t)\n\n    @complexity Linear in the size of @a init.\n\n    @liveexample{The following code shows an example for the `object`\n    function.,object}\n\n    @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --\n    create a JSON value from an initializer list\n    @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array\n    value from an initializer list\n\n    @since version 1.0.0\n    */\n    static basic_json object(std::initializer_list<basic_json> init =\n                                 std::initializer_list<basic_json>())\n    {\n        return basic_json(init, false, value_t::object);\n    }\n\n    /*!\n    @brief construct an array with count copies of given value\n\n    Constructs a JSON array value by creating @a cnt copies of a passed value.\n    In case @a cnt is `0`, an empty array is created. As postcondition,\n    `std::distance(begin(),end()) == cnt` holds.\n\n    @param[in] cnt  the number of JSON copies of @a val to create\n    @param[in] val  the JSON value to copy\n\n    @complexity Linear in @a cnt.\n\n    @liveexample{The following code shows examples for the @ref\n    basic_json(size_type\\, const basic_json&)\n    constructor.,basic_json__size_type_basic_json}\n\n    @since version 1.0.0\n    */\n    basic_json(size_type cnt, const basic_json& val)\n        : m_type(value_t::array)\n    {\n        m_value.array = create<array_t>(cnt, val);\n        assert_invariant();\n    }\n\n    /*!\n    @brief construct a JSON container given an iterator range\n\n    Constructs the JSON value with the contents of the range `[first, last)`.\n    The semantics depends on the different types a JSON value can have:\n    - In case of primitive types (number, boolean, or string), @a first must\n      be `begin()` and @a last must be `end()`. In this case, the value is\n      copied. Otherwise, std::out_of_range is thrown.\n    - In case of structured types (array, object), the constructor behaves as\n      similar versions for `std::vector`.\n    - In case of a null type, std::domain_error is thrown.\n\n    @tparam InputIT an input iterator type (@ref iterator or @ref\n    const_iterator)\n\n    @param[in] first begin of the range to copy from (included)\n    @param[in] last end of the range to copy from (excluded)\n\n    @pre Iterators @a first and @a last must be initialized. **This\n         precondition is enforced with an assertion.**\n\n    @throw std::domain_error if iterators are not compatible; that is, do not\n    belong to the same JSON value; example: `\"iterators are not compatible\"`\n    @throw std::out_of_range if iterators are for a primitive type (number,\n    boolean, or string) where an out of range error can be detected easily;\n    example: `\"iterators out of range\"`\n    @throw std::bad_alloc if allocation for object, array, or string fails\n    @throw std::domain_error if called with a null value; example: `\"cannot\n    use construct with iterators from null\"`\n\n    @complexity Linear in distance between @a first and @a last.\n\n    @liveexample{The example below shows several ways to create JSON values by\n    specifying a subrange with iterators.,basic_json__InputIt_InputIt}\n\n    @since version 1.0.0\n    */\n    template <class InputIT, typename\n              std::enable_if<\n                  std::is_same<InputIT, typename basic_json_t::iterator>::value or\n                  std::is_same<InputIT, typename basic_json_t::const_iterator>::value\n                  , int>::type\n              = 0>\n    basic_json(InputIT first, InputIT last)\n    {\n        assert(first.m_object != nullptr);\n        assert(last.m_object != nullptr);\n\n        // make sure iterator fits the current value\n        if (first.m_object != last.m_object)\n        {\n            throw std::domain_error(\"iterators are not compatible\");\n        }\n\n        // copy type from first iterator\n        m_type = first.m_object->m_type;\n\n        // check if iterator range is complete for primitive values\n        switch (m_type)\n        {\n            case value_t::boolean:\n            case value_t::number_float:\n            case value_t::number_integer:\n            case value_t::number_unsigned:\n            case value_t::string:\n            {\n                if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())\n                {\n                    throw std::out_of_range(\"iterators out of range\");\n                }\n                break;\n            }\n\n            default:\n            {\n                break;\n            }\n        }\n\n        switch (m_type)\n        {\n            case value_t::number_integer:\n            {\n                m_value.number_integer = first.m_object->m_value.number_integer;\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                m_value.number_unsigned = first.m_object->m_value.number_unsigned;\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                m_value.number_float = first.m_object->m_value.number_float;\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                m_value.boolean = first.m_object->m_value.boolean;\n                break;\n            }\n\n            case value_t::string:\n            {\n                m_value = *first.m_object->m_value.string;\n                break;\n            }\n\n            case value_t::object:\n            {\n                m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);\n                break;\n            }\n\n            default:\n            {\n                throw std::domain_error(\"cannot use construct with iterators from \" + first.m_object->type_name());\n            }\n        }\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief construct a JSON value given an input stream\n\n    @param[in,out] i  stream to read a serialized JSON value from\n    @param[in] cb a parser callback function of type @ref parser_callback_t\n    which is used to control the deserialization by filtering unwanted values\n    (optional)\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser. The complexity can be higher if the parser callback function\n    @a cb has a super-linear complexity.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below demonstrates constructing a JSON value from\n    a `std::stringstream` with and without callback\n    function.,basic_json__istream}\n\n    @since version 2.0.0\n    */\n    explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)\n    {\n        *this = parser(i, cb).parse();\n        assert_invariant();\n    }\n\n    ///////////////////////////////////////\n    // other constructors and destructor //\n    ///////////////////////////////////////\n\n    /*!\n    @brief copy constructor\n\n    Creates a copy of a given JSON value.\n\n    @param[in] other  the JSON value to copy\n\n    @complexity Linear in the size of @a other.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is linear.\n    - As postcondition, it holds: `other == basic_json(other)`.\n\n    @throw std::bad_alloc if allocation for object, array, or string fails.\n\n    @liveexample{The following code shows an example for the copy\n    constructor.,basic_json__basic_json}\n\n    @since version 1.0.0\n    */\n    basic_json(const basic_json& other)\n        : m_type(other.m_type)\n    {\n        // check of passed value is valid\n        other.assert_invariant();\n\n        switch (m_type)\n        {\n            case value_t::object:\n            {\n                m_value = *other.m_value.object;\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_value = *other.m_value.array;\n                break;\n            }\n\n            case value_t::string:\n            {\n                m_value = *other.m_value.string;\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                m_value = other.m_value.boolean;\n                break;\n            }\n\n            case value_t::number_integer:\n            {\n                m_value = other.m_value.number_integer;\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                m_value = other.m_value.number_unsigned;\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                m_value = other.m_value.number_float;\n                break;\n            }\n\n            default:\n            {\n                break;\n            }\n        }\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief move constructor\n\n    Move constructor. Constructs a JSON value with the contents of the given\n    value @a other using move semantics. It \"steals\" the resources from @a\n    other and leaves it as JSON null value.\n\n    @param[in,out] other  value to move to this object\n\n    @post @a other is a JSON null value\n\n    @complexity Constant.\n\n    @liveexample{The code below shows the move constructor explicitly called\n    via std::move.,basic_json__moveconstructor}\n\n    @since version 1.0.0\n    */\n    basic_json(basic_json&& other) noexcept\n        : m_type(std::move(other.m_type)),\n          m_value(std::move(other.m_value))\n    {\n        // check that passed value is valid\n        other.assert_invariant();\n\n        // invalidate payload\n        other.m_type = value_t::null;\n        other.m_value = {};\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief copy assignment\n\n    Copy assignment operator. Copies a JSON value via the \"copy and swap\"\n    strategy: It is expressed in terms of the copy constructor, destructor,\n    and the swap() member function.\n\n    @param[in] other  value to copy from\n\n    @complexity Linear.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is linear.\n\n    @liveexample{The code below shows and example for the copy assignment. It\n    creates a copy of value `a` which is then swapped with `b`. Finally\\, the\n    copy of `a` (which is the null value after the swap) is\n    destroyed.,basic_json__copyassignment}\n\n    @since version 1.0.0\n    */\n    reference& operator=(basic_json other) noexcept (\n        std::is_nothrow_move_constructible<value_t>::value and\n        std::is_nothrow_move_assignable<value_t>::value and\n        std::is_nothrow_move_constructible<json_value>::value and\n        std::is_nothrow_move_assignable<json_value>::value\n    )\n    {\n        // check that passed value is valid\n        other.assert_invariant();\n\n        using std::swap;\n        swap(m_type, other.m_type);\n        swap(m_value, other.m_value);\n\n        assert_invariant();\n        return *this;\n    }\n\n    /*!\n    @brief destructor\n\n    Destroys the JSON value and frees all allocated memory.\n\n    @complexity Linear.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is linear.\n    - All stored elements are destroyed and all memory is freed.\n\n    @since version 1.0.0\n    */\n    ~basic_json()\n    {\n        assert_invariant();\n\n        switch (m_type)\n        {\n            case value_t::object:\n            {\n                AllocatorType<object_t> alloc;\n                alloc.destroy(m_value.object);\n                alloc.deallocate(m_value.object, 1);\n                break;\n            }\n\n            case value_t::array:\n            {\n                AllocatorType<array_t> alloc;\n                alloc.destroy(m_value.array);\n                alloc.deallocate(m_value.array, 1);\n                break;\n            }\n\n            case value_t::string:\n            {\n                AllocatorType<string_t> alloc;\n                alloc.destroy(m_value.string);\n                alloc.deallocate(m_value.string, 1);\n                break;\n            }\n\n            default:\n            {\n                // all other types need no specific destructor\n                break;\n            }\n        }\n    }\n\n    /// @}\n\n  public:\n    ///////////////////////\n    // object inspection //\n    ///////////////////////\n\n    /// @name object inspection\n    /// Functions to inspect the type of a JSON value.\n    /// @{\n\n    /*!\n    @brief serialization\n\n    Serialization function for JSON values. The function tries to mimic\n    Python's `json.dumps()` function, and currently supports its @a indent\n    parameter.\n\n    @param[in] indent If indent is nonnegative, then array elements and object\n    members will be pretty-printed with that indent level. An indent level of\n    `0` will only insert newlines. `-1` (the default) selects the most compact\n    representation.\n\n    @return string containing the serialization of the JSON value\n\n    @complexity Linear.\n\n    @liveexample{The following example shows the effect of different @a indent\n    parameters to the result of the serialization.,dump}\n\n    @see https://docs.python.org/2/library/json.html#json.dump\n\n    @since version 1.0.0\n    */\n    string_t dump(const int indent = -1) const\n    {\n        std::stringstream ss;\n        // fix locale problems\n        ss.imbue(std::locale(std::locale(), new DecimalSeparator));\n\n        // 6, 15 or 16 digits of precision allows round-trip IEEE 754\n        // string->float->string, string->double->string or string->long\n        // double->string; to be safe, we read this value from\n        // std::numeric_limits<number_float_t>::digits10\n        ss.precision(std::numeric_limits<double>::digits10);\n\n        if (indent >= 0)\n        {\n            dump(ss, true, static_cast<unsigned int>(indent));\n        }\n        else\n        {\n            dump(ss, false, 0);\n        }\n\n        return ss.str();\n    }\n\n    /*!\n    @brief return the type of the JSON value (explicit)\n\n    Return the type of the JSON value as a value from the @ref value_t\n    enumeration.\n\n    @return the type of the JSON value\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `type()` for all JSON\n    types.,type}\n\n    @since version 1.0.0\n    */\n    constexpr value_t type() const noexcept\n    {\n        return m_type;\n    }\n\n    /*!\n    @brief return whether type is primitive\n\n    This function returns true iff the JSON type is primitive (string, number,\n    boolean, or null).\n\n    @return `true` if type is primitive (string, number, boolean, or null),\n    `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_primitive()` for all JSON\n    types.,is_primitive}\n\n    @sa @ref is_structured() -- returns whether JSON value is structured\n    @sa @ref is_null() -- returns whether JSON value is `null`\n    @sa @ref is_string() -- returns whether JSON value is a string\n    @sa @ref is_boolean() -- returns whether JSON value is a boolean\n    @sa @ref is_number() -- returns whether JSON value is a number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_primitive() const noexcept\n    {\n        return is_null() or is_string() or is_boolean() or is_number();\n    }\n\n    /*!\n    @brief return whether type is structured\n\n    This function returns true iff the JSON type is structured (array or\n    object).\n\n    @return `true` if type is structured (array or object), `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_structured()` for all JSON\n    types.,is_structured}\n\n    @sa @ref is_primitive() -- returns whether value is primitive\n    @sa @ref is_array() -- returns whether value is an array\n    @sa @ref is_object() -- returns whether value is an object\n\n    @since version 1.0.0\n    */\n    constexpr bool is_structured() const noexcept\n    {\n        return is_array() or is_object();\n    }\n\n    /*!\n    @brief return whether value is null\n\n    This function returns true iff the JSON value is null.\n\n    @return `true` if type is null, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_null()` for all JSON\n    types.,is_null}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_null() const noexcept\n    {\n        return m_type == value_t::null;\n    }\n\n    /*!\n    @brief return whether value is a boolean\n\n    This function returns true iff the JSON value is a boolean.\n\n    @return `true` if type is boolean, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_boolean()` for all JSON\n    types.,is_boolean}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_boolean() const noexcept\n    {\n        return m_type == value_t::boolean;\n    }\n\n    /*!\n    @brief return whether value is a number\n\n    This function returns true iff the JSON value is a number. This includes\n    both integer and floating-point values.\n\n    @return `true` if type is number (regardless whether integer, unsigned\n    integer or floating-type), `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number()` for all JSON\n    types.,is_number}\n\n    @sa @ref is_number_integer() -- check if value is an integer or unsigned\n    integer number\n    @sa @ref is_number_unsigned() -- check if value is an unsigned integer\n    number\n    @sa @ref is_number_float() -- check if value is a floating-point number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_number() const noexcept\n    {\n        return is_number_integer() or is_number_float();\n    }\n\n    /*!\n    @brief return whether value is an integer number\n\n    This function returns true iff the JSON value is an integer or unsigned\n    integer number. This excludes floating-point values.\n\n    @return `true` if type is an integer or unsigned integer number, `false`\n    otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number_integer()` for all\n    JSON types.,is_number_integer}\n\n    @sa @ref is_number() -- check if value is a number\n    @sa @ref is_number_unsigned() -- check if value is an unsigned integer\n    number\n    @sa @ref is_number_float() -- check if value is a floating-point number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_number_integer() const noexcept\n    {\n        return m_type == value_t::number_integer or m_type == value_t::number_unsigned;\n    }\n\n    /*!\n    @brief return whether value is an unsigned integer number\n\n    This function returns true iff the JSON value is an unsigned integer\n    number. This excludes floating-point and (signed) integer values.\n\n    @return `true` if type is an unsigned integer number, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number_unsigned()` for all\n    JSON types.,is_number_unsigned}\n\n    @sa @ref is_number() -- check if value is a number\n    @sa @ref is_number_integer() -- check if value is an integer or unsigned\n    integer number\n    @sa @ref is_number_float() -- check if value is a floating-point number\n\n    @since version 2.0.0\n    */\n    constexpr bool is_number_unsigned() const noexcept\n    {\n        return m_type == value_t::number_unsigned;\n    }\n\n    /*!\n    @brief return whether value is a floating-point number\n\n    This function returns true iff the JSON value is a floating-point number.\n    This excludes integer and unsigned integer values.\n\n    @return `true` if type is a floating-point number, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number_float()` for all\n    JSON types.,is_number_float}\n\n    @sa @ref is_number() -- check if value is number\n    @sa @ref is_number_integer() -- check if value is an integer number\n    @sa @ref is_number_unsigned() -- check if value is an unsigned integer\n    number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_number_float() const noexcept\n    {\n        return m_type == value_t::number_float;\n    }\n\n    /*!\n    @brief return whether value is an object\n\n    This function returns true iff the JSON value is an object.\n\n    @return `true` if type is object, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_object()` for all JSON\n    types.,is_object}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_object() const noexcept\n    {\n        return m_type == value_t::object;\n    }\n\n    /*!\n    @brief return whether value is an array\n\n    This function returns true iff the JSON value is an array.\n\n    @return `true` if type is array, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_array()` for all JSON\n    types.,is_array}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_array() const noexcept\n    {\n        return m_type == value_t::array;\n    }\n\n    /*!\n    @brief return whether value is a string\n\n    This function returns true iff the JSON value is a string.\n\n    @return `true` if type is string, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_string()` for all JSON\n    types.,is_string}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_string() const noexcept\n    {\n        return m_type == value_t::string;\n    }\n\n    /*!\n    @brief return whether value is discarded\n\n    This function returns true iff the JSON value was discarded during parsing\n    with a callback function (see @ref parser_callback_t).\n\n    @note This function will always be `false` for JSON values after parsing.\n    That is, discarded values can only occur during parsing, but will be\n    removed when inside a structured value or replaced by null in other cases.\n\n    @return `true` if type is discarded, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_discarded()` for all JSON\n    types.,is_discarded}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_discarded() const noexcept\n    {\n        return m_type == value_t::discarded;\n    }\n\n    /*!\n    @brief return the type of the JSON value (implicit)\n\n    Implicitly return the type of the JSON value as a value from the @ref\n    value_t enumeration.\n\n    @return the type of the JSON value\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies the @ref value_t operator for\n    all JSON types.,operator__value_t}\n\n    @since version 1.0.0\n    */\n    constexpr operator value_t() const noexcept\n    {\n        return m_type;\n    }\n\n    /// @}\n\n  private:\n    //////////////////\n    // value access //\n    //////////////////\n\n    /// get an object (explicit)\n    template <class T, typename\n              std::enable_if<\n                  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and\n                  std::is_convertible<basic_json_t, typename T::mapped_type>::value\n                  , int>::type = 0>\n    T get_impl(T*) const\n    {\n        if (is_object())\n        {\n            return T(m_value.object->begin(), m_value.object->end());\n        }\n        else\n        {\n            throw std::domain_error(\"type must be object, but is \" + type_name());\n        }\n    }\n\n    /// get an object (explicit)\n    object_t get_impl(object_t*) const\n    {\n        if (is_object())\n        {\n            return *(m_value.object);\n        }\n        else\n        {\n            throw std::domain_error(\"type must be object, but is \" + type_name());\n        }\n    }\n\n    /// get an array (explicit)\n    template <class T, typename\n              std::enable_if<\n                  std::is_convertible<basic_json_t, typename T::value_type>::value and\n                  not std::is_same<basic_json_t, typename T::value_type>::value and\n                  not std::is_arithmetic<T>::value and\n                  not std::is_convertible<std::string, T>::value and\n                  not has_mapped_type<T>::value\n                  , int>::type = 0>\n    T get_impl(T*) const\n    {\n        if (is_array())\n        {\n            T to_vector;\n            std::transform(m_value.array->begin(), m_value.array->end(),\n                           std::inserter(to_vector, to_vector.end()), [](basic_json i)\n            {\n                return i.get<typename T::value_type>();\n            });\n            return to_vector;\n        }\n        else\n        {\n            throw std::domain_error(\"type must be array, but is \" + type_name());\n        }\n    }\n\n    /// get an array (explicit)\n    template <class T, typename\n              std::enable_if<\n                  std::is_convertible<basic_json_t, T>::value and\n                  not std::is_same<basic_json_t, T>::value\n                  , int>::type = 0>\n    std::vector<T> get_impl(std::vector<T>*) const\n    {\n        if (is_array())\n        {\n            std::vector<T> to_vector;\n            to_vector.reserve(m_value.array->size());\n            std::transform(m_value.array->begin(), m_value.array->end(),\n                           std::inserter(to_vector, to_vector.end()), [](basic_json i)\n            {\n                return i.get<T>();\n            });\n            return to_vector;\n        }\n        else\n        {\n            throw std::domain_error(\"type must be array, but is \" + type_name());\n        }\n    }\n\n    /// get an array (explicit)\n    template <class T, typename\n              std::enable_if<\n                  std::is_same<basic_json, typename T::value_type>::value and\n                  not has_mapped_type<T>::value\n                  , int>::type = 0>\n    T get_impl(T*) const\n    {\n        if (is_array())\n        {\n            return T(m_value.array->begin(), m_value.array->end());\n        }\n        else\n        {\n            throw std::domain_error(\"type must be array, but is \" + type_name());\n        }\n    }\n\n    /// get an array (explicit)\n    array_t get_impl(array_t*) const\n    {\n        if (is_array())\n        {\n            return *(m_value.array);\n        }\n        else\n        {\n            throw std::domain_error(\"type must be array, but is \" + type_name());\n        }\n    }\n\n    /// get a string (explicit)\n    template <typename T, typename\n              std::enable_if<\n                  std::is_convertible<string_t, T>::value\n                  , int>::type = 0>\n    T get_impl(T*) const\n    {\n        if (is_string())\n        {\n            return *m_value.string;\n        }\n        else\n        {\n            throw std::domain_error(\"type must be string, but is \" + type_name());\n        }\n    }\n\n    /// get a number (explicit)\n    template<typename T, typename\n             std::enable_if<\n                 std::is_arithmetic<T>::value\n                 , int>::type = 0>\n    T get_impl(T*) const\n    {\n        switch (m_type)\n        {\n            case value_t::number_integer:\n            {\n                return static_cast<T>(m_value.number_integer);\n            }\n\n            case value_t::number_unsigned:\n            {\n                return static_cast<T>(m_value.number_unsigned);\n            }\n\n            case value_t::number_float:\n            {\n                return static_cast<T>(m_value.number_float);\n            }\n\n            default:\n            {\n                throw std::domain_error(\"type must be number, but is \" + type_name());\n            }\n        }\n    }\n\n    /// get a boolean (explicit)\n    constexpr boolean_t get_impl(boolean_t*) const\n    {\n        return is_boolean()\n               ? m_value.boolean\n               : throw std::domain_error(\"type must be boolean, but is \" + type_name());\n    }\n\n    /// get a pointer to the value (object)\n    object_t* get_impl_ptr(object_t*) noexcept\n    {\n        return is_object() ? m_value.object : nullptr;\n    }\n\n    /// get a pointer to the value (object)\n    constexpr const object_t* get_impl_ptr(const object_t*) const noexcept\n    {\n        return is_object() ? m_value.object : nullptr;\n    }\n\n    /// get a pointer to the value (array)\n    array_t* get_impl_ptr(array_t*) noexcept\n    {\n        return is_array() ? m_value.array : nullptr;\n    }\n\n    /// get a pointer to the value (array)\n    constexpr const array_t* get_impl_ptr(const array_t*) const noexcept\n    {\n        return is_array() ? m_value.array : nullptr;\n    }\n\n    /// get a pointer to the value (string)\n    string_t* get_impl_ptr(string_t*) noexcept\n    {\n        return is_string() ? m_value.string : nullptr;\n    }\n\n    /// get a pointer to the value (string)\n    constexpr const string_t* get_impl_ptr(const string_t*) const noexcept\n    {\n        return is_string() ? m_value.string : nullptr;\n    }\n\n    /// get a pointer to the value (boolean)\n    boolean_t* get_impl_ptr(boolean_t*) noexcept\n    {\n        return is_boolean() ? &m_value.boolean : nullptr;\n    }\n\n    /// get a pointer to the value (boolean)\n    constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept\n    {\n        return is_boolean() ? &m_value.boolean : nullptr;\n    }\n\n    /// get a pointer to the value (integer number)\n    number_integer_t* get_impl_ptr(number_integer_t*) noexcept\n    {\n        return is_number_integer() ? &m_value.number_integer : nullptr;\n    }\n\n    /// get a pointer to the value (integer number)\n    constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept\n    {\n        return is_number_integer() ? &m_value.number_integer : nullptr;\n    }\n\n    /// get a pointer to the value (unsigned number)\n    number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept\n    {\n        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;\n    }\n\n    /// get a pointer to the value (unsigned number)\n    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept\n    {\n        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;\n    }\n\n    /// get a pointer to the value (floating-point number)\n    number_float_t* get_impl_ptr(number_float_t*) noexcept\n    {\n        return is_number_float() ? &m_value.number_float : nullptr;\n    }\n\n    /// get a pointer to the value (floating-point number)\n    constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept\n    {\n        return is_number_float() ? &m_value.number_float : nullptr;\n    }\n\n    /*!\n    @brief helper function to implement get_ref()\n\n    This funcion helps to implement get_ref() without code duplication for\n    const and non-const overloads\n\n    @tparam ThisType will be deduced as `basic_json` or `const basic_json`\n\n    @throw std::domain_error if ReferenceType does not match underlying value\n    type of the current JSON\n    */\n    template<typename ReferenceType, typename ThisType>\n    static ReferenceType get_ref_impl(ThisType& obj)\n    {\n        // helper type\n        using PointerType = typename std::add_pointer<ReferenceType>::type;\n\n        // delegate the call to get_ptr<>()\n        auto ptr = obj.template get_ptr<PointerType>();\n\n        if (ptr != nullptr)\n        {\n            return *ptr;\n        }\n        else\n        {\n            throw std::domain_error(\"incompatible ReferenceType for get_ref, actual type is \" +\n                                    obj.type_name());\n        }\n    }\n\n  public:\n\n    /// @name value access\n    /// Direct access to the stored value of a JSON value.\n    /// @{\n\n    /*!\n    @brief get a value (explicit)\n\n    Explicit type conversion between the JSON value and a compatible value.\n\n    @tparam ValueType non-pointer type compatible to the JSON value, for\n    instance `int` for JSON integer numbers, `bool` for JSON booleans, or\n    `std::vector` types for JSON arrays\n\n    @return copy of the JSON value, converted to type @a ValueType\n\n    @throw std::domain_error in case passed type @a ValueType is incompatible\n    to JSON; example: `\"type must be object, but is null\"`\n\n    @complexity Linear in the size of the JSON value.\n\n    @liveexample{The example below shows several conversions from JSON values\n    to other types. There a few things to note: (1) Floating-point numbers can\n    be converted to integers\\, (2) A JSON array can be converted to a standard\n    `std::vector<short>`\\, (3) A JSON object can be converted to C++\n    associative containers such as `std::unordered_map<std::string\\,\n    json>`.,get__ValueType_const}\n\n    @internal\n    The idea of using a casted null pointer to choose the correct\n    implementation is from <http://stackoverflow.com/a/8315197/266378>.\n    @endinternal\n\n    @sa @ref operator ValueType() const for implicit conversion\n    @sa @ref get() for pointer-member access\n\n    @since version 1.0.0\n    */\n    template<typename ValueType, typename\n             std::enable_if<\n                 not std::is_pointer<ValueType>::value\n                 , int>::type = 0>\n    ValueType get() const\n    {\n        return get_impl(static_cast<ValueType*>(nullptr));\n    }\n\n    /*!\n    @brief get a pointer value (explicit)\n\n    Explicit pointer access to the internally stored JSON value. No copies are\n    made.\n\n    @warning The pointer becomes invalid if the underlying JSON object\n    changes.\n\n    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\n    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\n    @ref number_unsigned_t, or @ref number_float_t.\n\n    @return pointer to the internally stored JSON value if the requested\n    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how pointers to internal values of a\n    JSON value can be requested. Note that no type conversions are made and a\n    `nullptr` is returned if the value and the requested pointer type does not\n    match.,get__PointerType}\n\n    @sa @ref get_ptr() for explicit pointer-member access\n\n    @since version 1.0.0\n    */\n    template<typename PointerType, typename\n             std::enable_if<\n                 std::is_pointer<PointerType>::value\n                 , int>::type = 0>\n    PointerType get() noexcept\n    {\n        // delegate the call to get_ptr\n        return get_ptr<PointerType>();\n    }\n\n    /*!\n    @brief get a pointer value (explicit)\n    @copydoc get()\n    */\n    template<typename PointerType, typename\n             std::enable_if<\n                 std::is_pointer<PointerType>::value\n                 , int>::type = 0>\n    constexpr const PointerType get() const noexcept\n    {\n        // delegate the call to get_ptr\n        return get_ptr<PointerType>();\n    }\n\n    /*!\n    @brief get a pointer value (implicit)\n\n    Implicit pointer access to the internally stored JSON value. No copies are\n    made.\n\n    @warning Writing data to the pointee of the result yields an undefined\n    state.\n\n    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\n    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\n    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static\n    assertion.\n\n    @return pointer to the internally stored JSON value if the requested\n    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how pointers to internal values of a\n    JSON value can be requested. Note that no type conversions are made and a\n    `nullptr` is returned if the value and the requested pointer type does not\n    match.,get_ptr}\n\n    @since version 1.0.0\n    */\n    template<typename PointerType, typename\n             std::enable_if<\n                 std::is_pointer<PointerType>::value\n                 , int>::type = 0>\n    PointerType get_ptr() noexcept\n    {\n        // get the type of the PointerType (remove pointer and const)\n        using pointee_t = typename std::remove_const<typename\n                          std::remove_pointer<typename\n                          std::remove_const<PointerType>::type>::type>::type;\n        // make sure the type matches the allowed types\n        static_assert(\n            std::is_same<object_t, pointee_t>::value\n            or std::is_same<array_t, pointee_t>::value\n            or std::is_same<string_t, pointee_t>::value\n            or std::is_same<boolean_t, pointee_t>::value\n            or std::is_same<number_integer_t, pointee_t>::value\n            or std::is_same<number_unsigned_t, pointee_t>::value\n            or std::is_same<number_float_t, pointee_t>::value\n            , \"incompatible pointer type\");\n\n        // delegate the call to get_impl_ptr<>()\n        return get_impl_ptr(static_cast<PointerType>(nullptr));\n    }\n\n    /*!\n    @brief get a pointer value (implicit)\n    @copydoc get_ptr()\n    */\n    template<typename PointerType, typename\n             std::enable_if<\n                 std::is_pointer<PointerType>::value\n                 and std::is_const<typename std::remove_pointer<PointerType>::type>::value\n                 , int>::type = 0>\n    constexpr const PointerType get_ptr() const noexcept\n    {\n        // get the type of the PointerType (remove pointer and const)\n        using pointee_t = typename std::remove_const<typename\n                          std::remove_pointer<typename\n                          std::remove_const<PointerType>::type>::type>::type;\n        // make sure the type matches the allowed types\n        static_assert(\n            std::is_same<object_t, pointee_t>::value\n            or std::is_same<array_t, pointee_t>::value\n            or std::is_same<string_t, pointee_t>::value\n            or std::is_same<boolean_t, pointee_t>::value\n            or std::is_same<number_integer_t, pointee_t>::value\n            or std::is_same<number_unsigned_t, pointee_t>::value\n            or std::is_same<number_float_t, pointee_t>::value\n            , \"incompatible pointer type\");\n\n        // delegate the call to get_impl_ptr<>() const\n        return get_impl_ptr(static_cast<const PointerType>(nullptr));\n    }\n\n    /*!\n    @brief get a reference value (implicit)\n\n    Implict reference access to the internally stored JSON value. No copies\n    are made.\n\n    @warning Writing data to the referee of the result yields an undefined\n    state.\n\n    @tparam ReferenceType reference type; must be a reference to @ref array_t,\n    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or\n    @ref number_float_t. Enforced by static assertion.\n\n    @return reference to the internally stored JSON value if the requested\n    reference type @a ReferenceType fits to the JSON value; throws\n    std::domain_error otherwise\n\n    @throw std::domain_error in case passed type @a ReferenceType is\n    incompatible with the stored JSON value\n\n    @complexity Constant.\n\n    @liveexample{The example shows several calls to `get_ref()`.,get_ref}\n\n    @since version 1.1.0\n    */\n    template<typename ReferenceType, typename\n             std::enable_if<\n                 std::is_reference<ReferenceType>::value\n                 , int>::type = 0>\n    ReferenceType get_ref()\n    {\n        // delegate call to get_ref_impl\n        return get_ref_impl<ReferenceType>(*this);\n    }\n\n    /*!\n    @brief get a reference value (implicit)\n    @copydoc get_ref()\n    */\n    template<typename ReferenceType, typename\n             std::enable_if<\n                 std::is_reference<ReferenceType>::value\n                 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value\n                 , int>::type = 0>\n    ReferenceType get_ref() const\n    {\n        // delegate call to get_ref_impl\n        return get_ref_impl<ReferenceType>(*this);\n    }\n\n    /*!\n    @brief get a value (implicit)\n\n    Implicit type conversion between the JSON value and a compatible value.\n    The call is realized by calling @ref get() const.\n\n    @tparam ValueType non-pointer type compatible to the JSON value, for\n    instance `int` for JSON integer numbers, `bool` for JSON booleans, or\n    `std::vector` types for JSON arrays. The character type of @ref string_t\n    as well as an initializer list of this type is excluded to avoid\n    ambiguities as these types implicitly convert to `std::string`.\n\n    @return copy of the JSON value, converted to type @a ValueType\n\n    @throw std::domain_error in case passed type @a ValueType is incompatible\n    to JSON, thrown by @ref get() const\n\n    @complexity Linear in the size of the JSON value.\n\n    @liveexample{The example below shows several conversions from JSON values\n    to other types. There a few things to note: (1) Floating-point numbers can\n    be converted to integers\\, (2) A JSON array can be converted to a standard\n    `std::vector<short>`\\, (3) A JSON object can be converted to C++\n    associative containers such as `std::unordered_map<std::string\\,\n    json>`.,operator__ValueType}\n\n    @since version 1.0.0\n    */\n    template < typename ValueType, typename\n               std::enable_if <\n                   not std::is_pointer<ValueType>::value\n                   and not std::is_same<ValueType, typename string_t::value_type>::value\n#ifndef _MSC_VER  // Fix for issue #167 operator<< abiguity under VS2015\n                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value\n#endif\n                   , int >::type = 0 >\n    operator ValueType() const\n    {\n        // delegate the call to get<>() const\n        return get<ValueType>();\n    }\n\n    /// @}\n\n\n    ////////////////////\n    // element access //\n    ////////////////////\n\n    /// @name element access\n    /// Access to the JSON value.\n    /// @{\n\n    /*!\n    @brief access specified array element with bounds checking\n\n    Returns a reference to the element at specified location @a idx, with\n    bounds checking.\n\n    @param[in] idx  index of the element to access\n\n    @return reference to the element at index @a idx\n\n    @throw std::domain_error if the JSON value is not an array; example:\n    `\"cannot use at() with string\"`\n    @throw std::out_of_range if the index @a idx is out of range of the array;\n    that is, `idx >= size()`; example: `\"array index 7 is out of range\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how array elements can be read and\n    written using `at()`.,at__size_type}\n\n    @since version 1.0.0\n    */\n    reference at(size_type idx)\n    {\n        // at only works for arrays\n        if (is_array())\n        {\n            try\n            {\n                return m_value.array->at(idx);\n            }\n            catch (std::out_of_range&)\n            {\n                // create better exception explanation\n                throw std::out_of_range(\"array index \" + std::to_string(idx) + \" is out of range\");\n            }\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use at() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified array element with bounds checking\n\n    Returns a const reference to the element at specified location @a idx,\n    with bounds checking.\n\n    @param[in] idx  index of the element to access\n\n    @return const reference to the element at index @a idx\n\n    @throw std::domain_error if the JSON value is not an array; example:\n    `\"cannot use at() with string\"`\n    @throw std::out_of_range if the index @a idx is out of range of the array;\n    that is, `idx >= size()`; example: `\"array index 7 is out of range\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how array elements can be read using\n    `at()`.,at__size_type_const}\n\n    @since version 1.0.0\n    */\n    const_reference at(size_type idx) const\n    {\n        // at only works for arrays\n        if (is_array())\n        {\n            try\n            {\n                return m_value.array->at(idx);\n            }\n            catch (std::out_of_range&)\n            {\n                // create better exception explanation\n                throw std::out_of_range(\"array index \" + std::to_string(idx) + \" is out of range\");\n            }\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use at() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified object element with bounds checking\n\n    Returns a reference to the element at with specified key @a key, with\n    bounds checking.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw std::domain_error if the JSON value is not an object; example:\n    `\"cannot use at() with boolean\"`\n    @throw std::out_of_range if the key @a key is is not stored in the object;\n    that is, `find(key) == end()`; example: `\"key \"the fast\" not found\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read and\n    written using `at()`.,at__object_t_key_type}\n\n    @sa @ref operator[](const typename object_t::key_type&) for unchecked\n    access by reference\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    reference at(const typename object_t::key_type& key)\n    {\n        // at only works for objects\n        if (is_object())\n        {\n            try\n            {\n                return m_value.object->at(key);\n            }\n            catch (std::out_of_range&)\n            {\n                // create better exception explanation\n                throw std::out_of_range(\"key '\" + key + \"' not found\");\n            }\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use at() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified object element with bounds checking\n\n    Returns a const reference to the element at with specified key @a key,\n    with bounds checking.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @throw std::domain_error if the JSON value is not an object; example:\n    `\"cannot use at() with boolean\"`\n    @throw std::out_of_range if the key @a key is is not stored in the object;\n    that is, `find(key) == end()`; example: `\"key \"the fast\" not found\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read using\n    `at()`.,at__object_t_key_type_const}\n\n    @sa @ref operator[](const typename object_t::key_type&) for unchecked\n    access by reference\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    const_reference at(const typename object_t::key_type& key) const\n    {\n        // at only works for objects\n        if (is_object())\n        {\n            try\n            {\n                return m_value.object->at(key);\n            }\n            catch (std::out_of_range&)\n            {\n                // create better exception explanation\n                throw std::out_of_range(\"key '\" + key + \"' not found\");\n            }\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use at() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified array element\n\n    Returns a reference to the element at specified location @a idx.\n\n    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),\n    then the array is silently filled up with `null` values to make `idx` a\n    valid reference to the last stored element.\n\n    @param[in] idx  index of the element to access\n\n    @return reference to the element at index @a idx\n\n    @throw std::domain_error if JSON is not an array or null; example:\n    `\"cannot use operator[] with string\"`\n\n    @complexity Constant if @a idx is in the range of the array. Otherwise\n    linear in `idx - size()`.\n\n    @liveexample{The example below shows how array elements can be read and\n    written using `[]` operator. Note the addition of `null`\n    values.,operatorarray__size_type}\n\n    @since version 1.0.0\n    */\n    reference operator[](size_type idx)\n    {\n        // implicitly convert null value to an empty array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value.array = create<array_t>();\n            assert_invariant();\n        }\n\n        // operator[] only works for arrays\n        if (is_array())\n        {\n            // fill up array with null values if given idx is outside range\n            if (idx >= m_value.array->size())\n            {\n                m_value.array->insert(m_value.array->end(),\n                                      idx - m_value.array->size() + 1,\n                                      basic_json());\n            }\n\n            return m_value.array->operator[](idx);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use operator[] with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified array element\n\n    Returns a const reference to the element at specified location @a idx.\n\n    @param[in] idx  index of the element to access\n\n    @return const reference to the element at index @a idx\n\n    @throw std::domain_error if JSON is not an array; example: `\"cannot use\n    operator[] with null\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how array elements can be read using\n    the `[]` operator.,operatorarray__size_type_const}\n\n    @since version 1.0.0\n    */\n    const_reference operator[](size_type idx) const\n    {\n        // const operator[] only works for arrays\n        if (is_array())\n        {\n            return m_value.array->operator[](idx);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use operator[] with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified object element\n\n    Returns a reference to the element at with specified key @a key.\n\n    @note If @a key is not found in the object, then it is silently added to\n    the object and filled with a `null` value to make `key` a valid reference.\n    In case the value was `null` before, it is converted to an object.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw std::domain_error if JSON is not an object or null; example:\n    `\"cannot use operator[] with string\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read and\n    written using the `[]` operator.,operatorarray__key_type}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    reference operator[](const typename object_t::key_type& key)\n    {\n        // implicitly convert null value to an empty object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value.object = create<object_t>();\n            assert_invariant();\n        }\n\n        // operator[] only works for objects\n        if (is_object())\n        {\n            return m_value.object->operator[](key);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use operator[] with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief read-only access specified object element\n\n    Returns a const reference to the element at with specified key @a key. No\n    bounds checking is performed.\n\n    @warning If the element with key @a key does not exist, the behavior is\n    undefined.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @pre The element with key @a key must exist. **This precondition is\n         enforced with an assertion.**\n\n    @throw std::domain_error if JSON is not an object; example: `\"cannot use\n    operator[] with null\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read using\n    the `[]` operator.,operatorarray__key_type_const}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    const_reference operator[](const typename object_t::key_type& key) const\n    {\n        // const operator[] only works for objects\n        if (is_object())\n        {\n            assert(m_value.object->find(key) != m_value.object->end());\n            return m_value.object->find(key)->second;\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use operator[] with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified object element\n\n    Returns a reference to the element at with specified key @a key.\n\n    @note If @a key is not found in the object, then it is silently added to\n    the object and filled with a `null` value to make `key` a valid reference.\n    In case the value was `null` before, it is converted to an object.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw std::domain_error if JSON is not an object or null; example:\n    `\"cannot use operator[] with string\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read and\n    written using the `[]` operator.,operatorarray__key_type}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    template<typename T, std::size_t n>\n    reference operator[](T * (&key)[n])\n    {\n        return operator[](static_cast<const T>(key));\n    }\n\n    /*!\n    @brief read-only access specified object element\n\n    Returns a const reference to the element at with specified key @a key. No\n    bounds checking is performed.\n\n    @warning If the element with key @a key does not exist, the behavior is\n    undefined.\n\n    @note This function is required for compatibility reasons with Clang.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @throw std::domain_error if JSON is not an object; example: `\"cannot use\n    operator[] with null\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read using\n    the `[]` operator.,operatorarray__key_type_const}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    template<typename T, std::size_t n>\n    const_reference operator[](T * (&key)[n]) const\n    {\n        return operator[](static_cast<const T>(key));\n    }\n\n    /*!\n    @brief access specified object element\n\n    Returns a reference to the element at with specified key @a key.\n\n    @note If @a key is not found in the object, then it is silently added to\n    the object and filled with a `null` value to make `key` a valid reference.\n    In case the value was `null` before, it is converted to an object.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw std::domain_error if JSON is not an object or null; example:\n    `\"cannot use operator[] with string\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read and\n    written using the `[]` operator.,operatorarray__key_type}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.1.0\n    */\n    template<typename T>\n    reference operator[](T* key)\n    {\n        // implicitly convert null to object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value = value_t::object;\n            assert_invariant();\n        }\n\n        // at only works for objects\n        if (is_object())\n        {\n            return m_value.object->operator[](key);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use operator[] with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief read-only access specified object element\n\n    Returns a const reference to the element at with specified key @a key. No\n    bounds checking is performed.\n\n    @warning If the element with key @a key does not exist, the behavior is\n    undefined.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @pre The element with key @a key must exist. **This precondition is\n         enforced with an assertion.**\n\n    @throw std::domain_error if JSON is not an object; example: `\"cannot use\n    operator[] with null\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read using\n    the `[]` operator.,operatorarray__key_type_const}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.1.0\n    */\n    template<typename T>\n    const_reference operator[](T* key) const\n    {\n        // at only works for objects\n        if (is_object())\n        {\n            assert(m_value.object->find(key) != m_value.object->end());\n            return m_value.object->find(key)->second;\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use operator[] with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief access specified object element with default value\n\n    Returns either a copy of an object's element at the specified key @a key\n    or a given default value if no element with key @a key exists.\n\n    The function is basically equivalent to executing\n    @code {.cpp}\n    try {\n        return at(key);\n    } catch(std::out_of_range) {\n        return default_value;\n    }\n    @endcode\n\n    @note Unlike @ref at(const typename object_t::key_type&), this function\n    does not throw if the given key @a key was not found.\n\n    @note Unlike @ref operator[](const typename object_t::key_type& key), this\n    function does not implicitly add an element to the position defined by @a\n    key. This function is furthermore also applicable to const objects.\n\n    @param[in] key  key of the element to access\n    @param[in] default_value  the value to return if @a key is not found\n\n    @tparam ValueType type compatible to JSON values, for instance `int` for\n    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\n    JSON arrays. Note the type of the expected value at @a key and the default\n    value @a default_value must be compatible.\n\n    @return copy of the element at key @a key or @a default_value if @a key\n    is not found\n\n    @throw std::domain_error if JSON is not an object; example: `\"cannot use\n    value() with null\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be queried\n    with a default value.,basic_json__value}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref operator[](const typename object_t::key_type&) for unchecked\n    access by reference\n\n    @since version 1.0.0\n    */\n    template <class ValueType, typename\n              std::enable_if<\n                  std::is_convertible<basic_json_t, ValueType>::value\n                  , int>::type = 0>\n    ValueType value(const typename object_t::key_type& key, ValueType default_value) const\n    {\n        // at only works for objects\n        if (is_object())\n        {\n            // if key is found, return value and given default value otherwise\n            const auto it = find(key);\n            if (it != end())\n            {\n                return *it;\n            }\n            else\n            {\n                return default_value;\n            }\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use value() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief overload for a default value of type const char*\n    @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const\n    */\n    string_t value(const typename object_t::key_type& key, const char* default_value) const\n    {\n        return value(key, string_t(default_value));\n    }\n\n    /*!\n    @brief access specified object element via JSON Pointer with default value\n\n    Returns either a copy of an object's element at the specified key @a key\n    or a given default value if no element with key @a key exists.\n\n    The function is basically equivalent to executing\n    @code {.cpp}\n    try {\n        return at(ptr);\n    } catch(std::out_of_range) {\n        return default_value;\n    }\n    @endcode\n\n    @note Unlike @ref at(const json_pointer&), this function does not throw\n    if the given key @a key was not found.\n\n    @param[in] ptr  a JSON pointer to the element to access\n    @param[in] default_value  the value to return if @a ptr found no value\n\n    @tparam ValueType type compatible to JSON values, for instance `int` for\n    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\n    JSON arrays. Note the type of the expected value at @a key and the default\n    value @a default_value must be compatible.\n\n    @return copy of the element at key @a key or @a default_value if @a key\n    is not found\n\n    @throw std::domain_error if JSON is not an object; example: `\"cannot use\n    value() with null\"`\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be queried\n    with a default value.,basic_json__value_ptr}\n\n    @sa @ref operator[](const json_pointer&) for unchecked access by reference\n\n    @since version 2.0.2\n    */\n    template <class ValueType, typename\n              std::enable_if<\n                  std::is_convertible<basic_json_t, ValueType>::value\n                  , int>::type = 0>\n    ValueType value(const json_pointer& ptr, ValueType default_value) const\n    {\n        // at only works for objects\n        if (is_object())\n        {\n            // if pointer resolves a value, return it or use default value\n            try\n            {\n                return ptr.get_checked(this);\n            }\n            catch (std::out_of_range&)\n            {\n                return default_value;\n            }\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use value() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief overload for a default value of type const char*\n    @copydoc basic_json::value(const json_pointer&, ValueType) const\n    */\n    string_t value(const json_pointer& ptr, const char* default_value) const\n    {\n        return value(ptr, string_t(default_value));\n    }\n\n    /*!\n    @brief access the first element\n\n    Returns a reference to the first element in the container. For a JSON\n    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.\n\n    @return In case of a structured type (array or object), a reference to the\n    first element is returned. In cast of number, string, or boolean values, a\n    reference to the value is returned.\n\n    @complexity Constant.\n\n    @pre The JSON value must not be `null` (would throw `std::out_of_range`)\n    or an empty array or object (undefined behavior, **guarded by\n    assertions**).\n    @post The JSON value remains unchanged.\n\n    @throw std::out_of_range when called on `null` value\n\n    @liveexample{The following code shows an example for `front()`.,front}\n\n    @sa @ref back() -- access the last element\n\n    @since version 1.0.0\n    */\n    reference front()\n    {\n        return *begin();\n    }\n\n    /*!\n    @copydoc basic_json::front()\n    */\n    const_reference front() const\n    {\n        return *cbegin();\n    }\n\n    /*!\n    @brief access the last element\n\n    Returns a reference to the last element in the container. For a JSON\n    container `c`, the expression `c.back()` is equivalent to\n    @code {.cpp}\n    auto tmp = c.end();\n    --tmp;\n    return *tmp;\n    @endcode\n\n    @return In case of a structured type (array or object), a reference to the\n    last element is returned. In cast of number, string, or boolean values, a\n    reference to the value is returned.\n\n    @complexity Constant.\n\n    @pre The JSON value must not be `null` (would throw `std::out_of_range`)\n    or an empty array or object (undefined behavior, **guarded by\n    assertions**).\n    @post The JSON value remains unchanged.\n\n    @throw std::out_of_range when called on `null` value.\n\n    @liveexample{The following code shows an example for `back()`.,back}\n\n    @sa @ref front() -- access the first element\n\n    @since version 1.0.0\n    */\n    reference back()\n    {\n        auto tmp = end();\n        --tmp;\n        return *tmp;\n    }\n\n    /*!\n    @copydoc basic_json::back()\n    */\n    const_reference back() const\n    {\n        auto tmp = cend();\n        --tmp;\n        return *tmp;\n    }\n\n    /*!\n    @brief remove element given an iterator\n\n    Removes the element specified by iterator @a pos. The iterator @a pos must\n    be valid and dereferenceable. Thus the `end()` iterator (which is valid,\n    but is not dereferenceable) cannot be used as a value for @a pos.\n\n    If called on a primitive type other than `null`, the resulting JSON value\n    will be `null`.\n\n    @param[in] pos iterator to the element to remove\n    @return Iterator following the last removed element. If the iterator @a\n    pos refers to the last element, the `end()` iterator is returned.\n\n    @tparam InteratorType an @ref iterator or @ref const_iterator\n\n    @post Invalidates iterators and references at or after the point of the\n    erase, including the `end()` iterator.\n\n    @throw std::domain_error if called on a `null` value; example: `\"cannot\n    use erase() with null\"`\n    @throw std::domain_error if called on an iterator which does not belong to\n    the current JSON value; example: `\"iterator does not fit current value\"`\n    @throw std::out_of_range if called on a primitive type with invalid\n    iterator (i.e., any iterator which is not `begin()`); example: `\"iterator\n    out of range\"`\n\n    @complexity The complexity depends on the type:\n    - objects: amortized constant\n    - arrays: linear in distance between pos and the end of the container\n    - strings: linear in the length of the string\n    - other types: constant\n\n    @liveexample{The example shows the result of `erase()` for different JSON\n    types.,erase__IteratorType}\n\n    @sa @ref erase(InteratorType, InteratorType) -- removes the elements in\n    the given range\n    @sa @ref erase(const typename object_t::key_type&) -- removes the element\n    from an object at the given key\n    @sa @ref erase(const size_type) -- removes the element from an array at\n    the given index\n\n    @since version 1.0.0\n    */\n    template <class InteratorType, typename\n              std::enable_if<\n                  std::is_same<InteratorType, typename basic_json_t::iterator>::value or\n                  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value\n                  , int>::type\n              = 0>\n    InteratorType erase(InteratorType pos)\n    {\n        // make sure iterator fits the current value\n        if (this != pos.m_object)\n        {\n            throw std::domain_error(\"iterator does not fit current value\");\n        }\n\n        InteratorType result = end();\n\n        switch (m_type)\n        {\n            case value_t::boolean:\n            case value_t::number_float:\n            case value_t::number_integer:\n            case value_t::number_unsigned:\n            case value_t::string:\n            {\n                if (not pos.m_it.primitive_iterator.is_begin())\n                {\n                    throw std::out_of_range(\"iterator out of range\");\n                }\n\n                if (is_string())\n                {\n                    AllocatorType<string_t> alloc;\n                    alloc.destroy(m_value.string);\n                    alloc.deallocate(m_value.string, 1);\n                    m_value.string = nullptr;\n                }\n\n                m_type = value_t::null;\n                assert_invariant();\n                break;\n            }\n\n            case value_t::object:\n            {\n                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);\n                break;\n            }\n\n            case value_t::array:\n            {\n                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);\n                break;\n            }\n\n            default:\n            {\n                throw std::domain_error(\"cannot use erase() with \" + type_name());\n            }\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief remove elements given an iterator range\n\n    Removes the element specified by the range `[first; last)`. The iterator\n    @a first does not need to be dereferenceable if `first == last`: erasing\n    an empty range is a no-op.\n\n    If called on a primitive type other than `null`, the resulting JSON value\n    will be `null`.\n\n    @param[in] first iterator to the beginning of the range to remove\n    @param[in] last iterator past the end of the range to remove\n    @return Iterator following the last removed element. If the iterator @a\n    second refers to the last element, the `end()` iterator is returned.\n\n    @tparam InteratorType an @ref iterator or @ref const_iterator\n\n    @post Invalidates iterators and references at or after the point of the\n    erase, including the `end()` iterator.\n\n    @throw std::domain_error if called on a `null` value; example: `\"cannot\n    use erase() with null\"`\n    @throw std::domain_error if called on iterators which does not belong to\n    the current JSON value; example: `\"iterators do not fit current value\"`\n    @throw std::out_of_range if called on a primitive type with invalid\n    iterators (i.e., if `first != begin()` and `last != end()`); example:\n    `\"iterators out of range\"`\n\n    @complexity The complexity depends on the type:\n    - objects: `log(size()) + std::distance(first, last)`\n    - arrays: linear in the distance between @a first and @a last, plus linear\n      in the distance between @a last and end of the container\n    - strings: linear in the length of the string\n    - other types: constant\n\n    @liveexample{The example shows the result of `erase()` for different JSON\n    types.,erase__IteratorType_IteratorType}\n\n    @sa @ref erase(InteratorType) -- removes the element at a given position\n    @sa @ref erase(const typename object_t::key_type&) -- removes the element\n    from an object at the given key\n    @sa @ref erase(const size_type) -- removes the element from an array at\n    the given index\n\n    @since version 1.0.0\n    */\n    template <class InteratorType, typename\n              std::enable_if<\n                  std::is_same<InteratorType, typename basic_json_t::iterator>::value or\n                  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value\n                  , int>::type\n              = 0>\n    InteratorType erase(InteratorType first, InteratorType last)\n    {\n        // make sure iterator fits the current value\n        if (this != first.m_object or this != last.m_object)\n        {\n            throw std::domain_error(\"iterators do not fit current value\");\n        }\n\n        InteratorType result = end();\n\n        switch (m_type)\n        {\n            case value_t::boolean:\n            case value_t::number_float:\n            case value_t::number_integer:\n            case value_t::number_unsigned:\n            case value_t::string:\n            {\n                if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())\n                {\n                    throw std::out_of_range(\"iterators out of range\");\n                }\n\n                if (is_string())\n                {\n                    AllocatorType<string_t> alloc;\n                    alloc.destroy(m_value.string);\n                    alloc.deallocate(m_value.string, 1);\n                    m_value.string = nullptr;\n                }\n\n                m_type = value_t::null;\n                assert_invariant();\n                break;\n            }\n\n            case value_t::object:\n            {\n                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,\n                                              last.m_it.object_iterator);\n                break;\n            }\n\n            case value_t::array:\n            {\n                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,\n                                             last.m_it.array_iterator);\n                break;\n            }\n\n            default:\n            {\n                throw std::domain_error(\"cannot use erase() with \" + type_name());\n            }\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief remove element from a JSON object given a key\n\n    Removes elements from a JSON object with the key value @a key.\n\n    @param[in] key value of the elements to remove\n\n    @return Number of elements removed. If @a ObjectType is the default\n    `std::map` type, the return value will always be `0` (@a key was not\n    found) or `1` (@a key was found).\n\n    @post References and iterators to the erased elements are invalidated.\n    Other references and iterators are not affected.\n\n    @throw std::domain_error when called on a type other than JSON object;\n    example: `\"cannot use erase() with null\"`\n\n    @complexity `log(size()) + count(key)`\n\n    @liveexample{The example shows the effect of `erase()`.,erase__key_type}\n\n    @sa @ref erase(InteratorType) -- removes the element at a given position\n    @sa @ref erase(InteratorType, InteratorType) -- removes the elements in\n    the given range\n    @sa @ref erase(const size_type) -- removes the element from an array at\n    the given index\n\n    @since version 1.0.0\n    */\n    size_type erase(const typename object_t::key_type& key)\n    {\n        // this erase only works for objects\n        if (is_object())\n        {\n            return m_value.object->erase(key);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use erase() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief remove element from a JSON array given an index\n\n    Removes element from a JSON array at the index @a idx.\n\n    @param[in] idx index of the element to remove\n\n    @throw std::domain_error when called on a type other than JSON array;\n    example: `\"cannot use erase() with null\"`\n    @throw std::out_of_range when `idx >= size()`; example: `\"array index 17\n    is out of range\"`\n\n    @complexity Linear in distance between @a idx and the end of the container.\n\n    @liveexample{The example shows the effect of `erase()`.,erase__size_type}\n\n    @sa @ref erase(InteratorType) -- removes the element at a given position\n    @sa @ref erase(InteratorType, InteratorType) -- removes the elements in\n    the given range\n    @sa @ref erase(const typename object_t::key_type&) -- removes the element\n    from an object at the given key\n\n    @since version 1.0.0\n    */\n    void erase(const size_type idx)\n    {\n        // this erase only works for arrays\n        if (is_array())\n        {\n            if (idx >= size())\n            {\n                throw std::out_of_range(\"array index \" + std::to_string(idx) + \" is out of range\");\n            }\n\n            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use erase() with \" + type_name());\n        }\n    }\n\n    /// @}\n\n\n    ////////////\n    // lookup //\n    ////////////\n\n    /// @name lookup\n    /// @{\n\n    /*!\n    @brief find an element in a JSON object\n\n    Finds an element in a JSON object with key equivalent to @a key. If the\n    element is not found or the JSON value is not an object, end() is\n    returned.\n\n    @param[in] key key value of the element to search for\n\n    @return Iterator to an element with key equivalent to @a key. If no such\n    element is found, past-the-end (see end()) iterator is returned.\n\n    @complexity Logarithmic in the size of the JSON object.\n\n    @liveexample{The example shows how `find()` is used.,find__key_type}\n\n    @since version 1.0.0\n    */\n    iterator find(typename object_t::key_type key)\n    {\n        auto result = end();\n\n        if (is_object())\n        {\n            result.m_it.object_iterator = m_value.object->find(key);\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief find an element in a JSON object\n    @copydoc find(typename object_t::key_type)\n    */\n    const_iterator find(typename object_t::key_type key) const\n    {\n        auto result = cend();\n\n        if (is_object())\n        {\n            result.m_it.object_iterator = m_value.object->find(key);\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief returns the number of occurrences of a key in a JSON object\n\n    Returns the number of elements with key @a key. If ObjectType is the\n    default `std::map` type, the return value will always be `0` (@a key was\n    not found) or `1` (@a key was found).\n\n    @param[in] key key value of the element to count\n\n    @return Number of elements with key @a key. If the JSON value is not an\n    object, the return value will be `0`.\n\n    @complexity Logarithmic in the size of the JSON object.\n\n    @liveexample{The example shows how `count()` is used.,count}\n\n    @since version 1.0.0\n    */\n    size_type count(typename object_t::key_type key) const\n    {\n        // return 0 for all nonobject types\n        return is_object() ? m_value.object->count(key) : 0;\n    }\n\n    /// @}\n\n\n    ///////////////\n    // iterators //\n    ///////////////\n\n    /// @name iterators\n    /// @{\n\n    /*!\n    @brief returns an iterator to the first element\n\n    Returns an iterator to the first element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return iterator to the first element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n\n    @liveexample{The following code shows an example for `begin()`.,begin}\n\n    @sa @ref cbegin() -- returns a const iterator to the beginning\n    @sa @ref end() -- returns an iterator to the end\n    @sa @ref cend() -- returns a const iterator to the end\n\n    @since version 1.0.0\n    */\n    iterator begin() noexcept\n    {\n        iterator result(this);\n        result.set_begin();\n        return result;\n    }\n\n    /*!\n    @copydoc basic_json::cbegin()\n    */\n    const_iterator begin() const noexcept\n    {\n        return cbegin();\n    }\n\n    /*!\n    @brief returns a const iterator to the first element\n\n    Returns a const iterator to the first element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return const iterator to the first element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.\n\n    @liveexample{The following code shows an example for `cbegin()`.,cbegin}\n\n    @sa @ref begin() -- returns an iterator to the beginning\n    @sa @ref end() -- returns an iterator to the end\n    @sa @ref cend() -- returns a const iterator to the end\n\n    @since version 1.0.0\n    */\n    const_iterator cbegin() const noexcept\n    {\n        const_iterator result(this);\n        result.set_begin();\n        return result;\n    }\n\n    /*!\n    @brief returns an iterator to one past the last element\n\n    Returns an iterator to one past the last element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return iterator one past the last element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n\n    @liveexample{The following code shows an example for `end()`.,end}\n\n    @sa @ref cend() -- returns a const iterator to the end\n    @sa @ref begin() -- returns an iterator to the beginning\n    @sa @ref cbegin() -- returns a const iterator to the beginning\n\n    @since version 1.0.0\n    */\n    iterator end() noexcept\n    {\n        iterator result(this);\n        result.set_end();\n        return result;\n    }\n\n    /*!\n    @copydoc basic_json::cend()\n    */\n    const_iterator end() const noexcept\n    {\n        return cend();\n    }\n\n    /*!\n    @brief returns a const iterator to one past the last element\n\n    Returns a const iterator to one past the last element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return const iterator one past the last element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.\n\n    @liveexample{The following code shows an example for `cend()`.,cend}\n\n    @sa @ref end() -- returns an iterator to the end\n    @sa @ref begin() -- returns an iterator to the beginning\n    @sa @ref cbegin() -- returns a const iterator to the beginning\n\n    @since version 1.0.0\n    */\n    const_iterator cend() const noexcept\n    {\n        const_iterator result(this);\n        result.set_end();\n        return result;\n    }\n\n    /*!\n    @brief returns an iterator to the reverse-beginning\n\n    Returns an iterator to the reverse-beginning; that is, the last element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `reverse_iterator(end())`.\n\n    @liveexample{The following code shows an example for `rbegin()`.,rbegin}\n\n    @sa @ref crbegin() -- returns a const reverse iterator to the beginning\n    @sa @ref rend() -- returns a reverse iterator to the end\n    @sa @ref crend() -- returns a const reverse iterator to the end\n\n    @since version 1.0.0\n    */\n    reverse_iterator rbegin() noexcept\n    {\n        return reverse_iterator(end());\n    }\n\n    /*!\n    @copydoc basic_json::crbegin()\n    */\n    const_reverse_iterator rbegin() const noexcept\n    {\n        return crbegin();\n    }\n\n    /*!\n    @brief returns an iterator to the reverse-end\n\n    Returns an iterator to the reverse-end; that is, one before the first\n    element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `reverse_iterator(begin())`.\n\n    @liveexample{The following code shows an example for `rend()`.,rend}\n\n    @sa @ref crend() -- returns a const reverse iterator to the end\n    @sa @ref rbegin() -- returns a reverse iterator to the beginning\n    @sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\n    @since version 1.0.0\n    */\n    reverse_iterator rend() noexcept\n    {\n        return reverse_iterator(begin());\n    }\n\n    /*!\n    @copydoc basic_json::crend()\n    */\n    const_reverse_iterator rend() const noexcept\n    {\n        return crend();\n    }\n\n    /*!\n    @brief returns a const reverse iterator to the last element\n\n    Returns a const iterator to the reverse-beginning; that is, the last\n    element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.\n\n    @liveexample{The following code shows an example for `crbegin()`.,crbegin}\n\n    @sa @ref rbegin() -- returns a reverse iterator to the beginning\n    @sa @ref rend() -- returns a reverse iterator to the end\n    @sa @ref crend() -- returns a const reverse iterator to the end\n\n    @since version 1.0.0\n    */\n    const_reverse_iterator crbegin() const noexcept\n    {\n        return const_reverse_iterator(cend());\n    }\n\n    /*!\n    @brief returns a const reverse iterator to one before the first\n\n    Returns a const reverse iterator to the reverse-end; that is, one before\n    the first element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.\n\n    @liveexample{The following code shows an example for `crend()`.,crend}\n\n    @sa @ref rend() -- returns a reverse iterator to the end\n    @sa @ref rbegin() -- returns a reverse iterator to the beginning\n    @sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\n    @since version 1.0.0\n    */\n    const_reverse_iterator crend() const noexcept\n    {\n        return const_reverse_iterator(cbegin());\n    }\n\n  private:\n    // forward declaration\n    template<typename IteratorType> class iteration_proxy;\n\n  public:\n    /*!\n    @brief wrapper to access iterator member functions in range-based for\n\n    This function allows to access @ref iterator::key() and @ref\n    iterator::value() during range-based for loops. In these loops, a\n    reference to the JSON values is returned, so there is no access to the\n    underlying iterator.\n\n    @note The name of this function is not yet final and may change in the\n    future.\n    */\n    static iteration_proxy<iterator> iterator_wrapper(reference cont)\n    {\n        return iteration_proxy<iterator>(cont);\n    }\n\n    /*!\n    @copydoc iterator_wrapper(reference)\n    */\n    static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)\n    {\n        return iteration_proxy<const_iterator>(cont);\n    }\n\n    /// @}\n\n\n    //////////////\n    // capacity //\n    //////////////\n\n    /// @name capacity\n    /// @{\n\n    /*!\n    @brief checks whether the container is empty\n\n    Checks if a JSON value has no elements.\n\n    @return The return value depends on the different types and is\n            defined as follows:\n            Value type  | return value\n            ----------- | -------------\n            null        | `true`\n            boolean     | `false`\n            string      | `false`\n            number      | `false`\n            object      | result of function `object_t::empty()`\n            array       | result of function `array_t::empty()`\n\n    @note This function does not return whether a string stored as JSON value\n    is empty - it returns whether the JSON container itself is empty which is\n    false in the case of a string.\n\n    @complexity Constant, as long as @ref array_t and @ref object_t satisfy\n    the Container concept; that is, their `empty()` functions have constant\n    complexity.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `begin() == end()`.\n\n    @liveexample{The following code uses `empty()` to check if a JSON\n    object contains any elements.,empty}\n\n    @sa @ref size() -- returns the number of elements\n\n    @since version 1.0.0\n    */\n    bool empty() const noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::null:\n            {\n                // null values are empty\n                return true;\n            }\n\n            case value_t::array:\n            {\n                // delegate call to array_t::empty()\n                return m_value.array->empty();\n            }\n\n            case value_t::object:\n            {\n                // delegate call to object_t::empty()\n                return m_value.object->empty();\n            }\n\n            default:\n            {\n                // all other types are nonempty\n                return false;\n            }\n        }\n    }\n\n    /*!\n    @brief returns the number of elements\n\n    Returns the number of elements in a JSON value.\n\n    @return The return value depends on the different types and is\n            defined as follows:\n            Value type  | return value\n            ----------- | -------------\n            null        | `0`\n            boolean     | `1`\n            string      | `1`\n            number      | `1`\n            object      | result of function object_t::size()\n            array       | result of function array_t::size()\n\n    @note This function does not return the length of a string stored as JSON\n    value - it returns the number of elements in the JSON value which is 1 in\n    the case of a string.\n\n    @complexity Constant, as long as @ref array_t and @ref object_t satisfy\n    the Container concept; that is, their size() functions have constant\n    complexity.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `std::distance(begin(), end())`.\n\n    @liveexample{The following code calls `size()` on the different value\n    types.,size}\n\n    @sa @ref empty() -- checks whether the container is empty\n    @sa @ref max_size() -- returns the maximal number of elements\n\n    @since version 1.0.0\n    */\n    size_type size() const noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::null:\n            {\n                // null values are empty\n                return 0;\n            }\n\n            case value_t::array:\n            {\n                // delegate call to array_t::size()\n                return m_value.array->size();\n            }\n\n            case value_t::object:\n            {\n                // delegate call to object_t::size()\n                return m_value.object->size();\n            }\n\n            default:\n            {\n                // all other types have size 1\n                return 1;\n            }\n        }\n    }\n\n    /*!\n    @brief returns the maximum possible number of elements\n\n    Returns the maximum number of elements a JSON value is able to hold due to\n    system or library implementation limitations, i.e. `std::distance(begin(),\n    end())` for the JSON value.\n\n    @return The return value depends on the different types and is\n            defined as follows:\n            Value type  | return value\n            ----------- | -------------\n            null        | `0` (same as `size()`)\n            boolean     | `1` (same as `size()`)\n            string      | `1` (same as `size()`)\n            number      | `1` (same as `size()`)\n            object      | result of function `object_t::max_size()`\n            array       | result of function `array_t::max_size()`\n\n    @complexity Constant, as long as @ref array_t and @ref object_t satisfy\n    the Container concept; that is, their `max_size()` functions have constant\n    complexity.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](http://en.cppreference.com/w/cpp/concept/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of returning `b.size()` where `b` is the largest\n      possible JSON value.\n\n    @liveexample{The following code calls `max_size()` on the different value\n    types. Note the output is implementation specific.,max_size}\n\n    @sa @ref size() -- returns the number of elements\n\n    @since version 1.0.0\n    */\n    size_type max_size() const noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::array:\n            {\n                // delegate call to array_t::max_size()\n                return m_value.array->max_size();\n            }\n\n            case value_t::object:\n            {\n                // delegate call to object_t::max_size()\n                return m_value.object->max_size();\n            }\n\n            default:\n            {\n                // all other types have max_size() == size()\n                return size();\n            }\n        }\n    }\n\n    /// @}\n\n\n    ///////////////\n    // modifiers //\n    ///////////////\n\n    /// @name modifiers\n    /// @{\n\n    /*!\n    @brief clears the contents\n\n    Clears the content of a JSON value and resets it to the default value as\n    if @ref basic_json(value_t) would have been called:\n\n    Value type  | initial value\n    ----------- | -------------\n    null        | `null`\n    boolean     | `false`\n    string      | `\"\"`\n    number      | `0`\n    object      | `{}`\n    array       | `[]`\n\n    @note Floating-point numbers are set to `0.0` which will be serialized to\n    `0`. The vale type remains @ref number_float_t.\n\n    @complexity Linear in the size of the JSON value.\n\n    @liveexample{The example below shows the effect of `clear()` to different\n    JSON types.,clear}\n\n    @since version 1.0.0\n    */\n    void clear() noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::number_integer:\n            {\n                m_value.number_integer = 0;\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                m_value.number_unsigned = 0;\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                m_value.number_float = 0.0;\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                m_value.boolean = false;\n                break;\n            }\n\n            case value_t::string:\n            {\n                m_value.string->clear();\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_value.array->clear();\n                break;\n            }\n\n            case value_t::object:\n            {\n                m_value.object->clear();\n                break;\n            }\n\n            default:\n            {\n                break;\n            }\n        }\n    }\n\n    /*!\n    @brief add an object to an array\n\n    Appends the given element @a val to the end of the JSON value. If the\n    function is called on a JSON null value, an empty array is created before\n    appending @a val.\n\n    @param[in] val the value to add to the JSON array\n\n    @throw std::domain_error when called on a type other than JSON array or\n    null; example: `\"cannot use push_back() with number\"`\n\n    @complexity Amortized constant.\n\n    @liveexample{The example shows how `push_back()` and `+=` can be used to\n    add elements to a JSON array. Note how the `null` value was silently\n    converted to a JSON array.,push_back}\n\n    @since version 1.0.0\n    */\n    void push_back(basic_json&& val)\n    {\n        // push_back only works for null objects or arrays\n        if (not(is_null() or is_array()))\n        {\n            throw std::domain_error(\"cannot use push_back() with \" + type_name());\n        }\n\n        // transform null object into an array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value = value_t::array;\n            assert_invariant();\n        }\n\n        // add element to array (move semantics)\n        m_value.array->push_back(std::move(val));\n        // invalidate object\n        val.m_type = value_t::null;\n    }\n\n    /*!\n    @brief add an object to an array\n    @copydoc push_back(basic_json&&)\n    */\n    reference operator+=(basic_json&& val)\n    {\n        push_back(std::move(val));\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an array\n    @copydoc push_back(basic_json&&)\n    */\n    void push_back(const basic_json& val)\n    {\n        // push_back only works for null objects or arrays\n        if (not(is_null() or is_array()))\n        {\n            throw std::domain_error(\"cannot use push_back() with \" + type_name());\n        }\n\n        // transform null object into an array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value = value_t::array;\n            assert_invariant();\n        }\n\n        // add element to array\n        m_value.array->push_back(val);\n    }\n\n    /*!\n    @brief add an object to an array\n    @copydoc push_back(basic_json&&)\n    */\n    reference operator+=(const basic_json& val)\n    {\n        push_back(val);\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an object\n\n    Inserts the given element @a val to the JSON object. If the function is\n    called on a JSON null value, an empty object is created before inserting\n    @a val.\n\n    @param[in] val the value to add to the JSON object\n\n    @throw std::domain_error when called on a type other than JSON object or\n    null; example: `\"cannot use push_back() with number\"`\n\n    @complexity Logarithmic in the size of the container, O(log(`size()`)).\n\n    @liveexample{The example shows how `push_back()` and `+=` can be used to\n    add elements to a JSON object. Note how the `null` value was silently\n    converted to a JSON object.,push_back__object_t__value}\n\n    @since version 1.0.0\n    */\n    void push_back(const typename object_t::value_type& val)\n    {\n        // push_back only works for null objects or objects\n        if (not(is_null() or is_object()))\n        {\n            throw std::domain_error(\"cannot use push_back() with \" + type_name());\n        }\n\n        // transform null object into an object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value = value_t::object;\n            assert_invariant();\n        }\n\n        // add element to array\n        m_value.object->insert(val);\n    }\n\n    /*!\n    @brief add an object to an object\n    @copydoc push_back(const typename object_t::value_type&)\n    */\n    reference operator+=(const typename object_t::value_type& val)\n    {\n        push_back(val);\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an object\n\n    This function allows to use `push_back` with an initializer list. In case\n\n    1. the current value is an object,\n    2. the initializer list @a init contains only two elements, and\n    3. the first element of @a init is a string,\n\n    @a init is converted into an object element and added using\n    @ref push_back(const typename object_t::value_type&). Otherwise, @a init\n    is converted to a JSON value and added using @ref push_back(basic_json&&).\n\n    @param init  an initializer list\n\n    @complexity Linear in the size of the initializer list @a init.\n\n    @note This function is required to resolve an ambiguous overload error,\n          because pairs like `{\"key\", \"value\"}` can be both interpreted as\n          `object_t::value_type` or `std::initializer_list<basic_json>`, see\n          https://github.com/nlohmann/json/issues/235 for more information.\n\n    @liveexample{The example shows how initializer lists are treated as\n    objects when possible.,push_back__initializer_list}\n    */\n    void push_back(std::initializer_list<basic_json> init)\n    {\n        if (is_object() and init.size() == 2 and init.begin()->is_string())\n        {\n            const string_t key = *init.begin();\n            push_back(typename object_t::value_type(key, *(init.begin() + 1)));\n        }\n        else\n        {\n            push_back(basic_json(init));\n        }\n    }\n\n    /*!\n    @brief add an object to an object\n    @copydoc push_back(std::initializer_list<basic_json>)\n    */\n    reference operator+=(std::initializer_list<basic_json> init)\n    {\n        push_back(init);\n        return *this;\n    }\n\n    /*!\n    @brief inserts element\n\n    Inserts element @a val before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] val element to insert\n    @return iterator pointing to the inserted @a val.\n\n    @throw std::domain_error if called on JSON values other than arrays;\n    example: `\"cannot use insert() with string\"`\n    @throw std::domain_error if @a pos is not an iterator of *this; example:\n    `\"iterator does not fit current value\"`\n\n    @complexity Constant plus linear in the distance between pos and end of the\n    container.\n\n    @liveexample{The example shows how `insert()` is used.,insert}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, const basic_json& val)\n    {\n        // insert only works for arrays\n        if (is_array())\n        {\n            // check if iterator pos fits to this JSON value\n            if (pos.m_object != this)\n            {\n                throw std::domain_error(\"iterator does not fit current value\");\n            }\n\n            // insert to array and return iterator\n            iterator result(this);\n            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);\n            return result;\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use insert() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief inserts element\n    @copydoc insert(const_iterator, const basic_json&)\n    */\n    iterator insert(const_iterator pos, basic_json&& val)\n    {\n        return insert(pos, val);\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts @a cnt copies of @a val before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] cnt number of copies of @a val to insert\n    @param[in] val element to insert\n    @return iterator pointing to the first element inserted, or @a pos if\n    `cnt==0`\n\n    @throw std::domain_error if called on JSON values other than arrays;\n    example: `\"cannot use insert() with string\"`\n    @throw std::domain_error if @a pos is not an iterator of *this; example:\n    `\"iterator does not fit current value\"`\n\n    @complexity Linear in @a cnt plus linear in the distance between @a pos\n    and end of the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert__count}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)\n    {\n        // insert only works for arrays\n        if (is_array())\n        {\n            // check if iterator pos fits to this JSON value\n            if (pos.m_object != this)\n            {\n                throw std::domain_error(\"iterator does not fit current value\");\n            }\n\n            // insert to array and return iterator\n            iterator result(this);\n            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);\n            return result;\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use insert() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts elements from range `[first, last)` before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] first begin of the range of elements to insert\n    @param[in] last end of the range of elements to insert\n\n    @throw std::domain_error if called on JSON values other than arrays;\n    example: `\"cannot use insert() with string\"`\n    @throw std::domain_error if @a pos is not an iterator of *this; example:\n    `\"iterator does not fit current value\"`\n    @throw std::domain_error if @a first and @a last do not belong to the same\n    JSON value; example: `\"iterators do not fit\"`\n    @throw std::domain_error if @a first or @a last are iterators into\n    container for which insert is called; example: `\"passed iterators may not\n    belong to container\"`\n\n    @return iterator pointing to the first element inserted, or @a pos if\n    `first==last`\n\n    @complexity Linear in `std::distance(first, last)` plus linear in the\n    distance between @a pos and end of the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert__range}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, const_iterator first, const_iterator last)\n    {\n        // insert only works for arrays\n        if (not is_array())\n        {\n            throw std::domain_error(\"cannot use insert() with \" + type_name());\n        }\n\n        // check if iterator pos fits to this JSON value\n        if (pos.m_object != this)\n        {\n            throw std::domain_error(\"iterator does not fit current value\");\n        }\n\n        // check if range iterators belong to the same JSON object\n        if (first.m_object != last.m_object)\n        {\n            throw std::domain_error(\"iterators do not fit\");\n        }\n\n        if (first.m_object == this or last.m_object == this)\n        {\n            throw std::domain_error(\"passed iterators may not belong to container\");\n        }\n\n        // insert to array and return iterator\n        iterator result(this);\n        result.m_it.array_iterator = m_value.array->insert(\n                                         pos.m_it.array_iterator,\n                                         first.m_it.array_iterator,\n                                         last.m_it.array_iterator);\n        return result;\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts elements from initializer list @a ilist before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] ilist initializer list to insert the values from\n\n    @throw std::domain_error if called on JSON values other than arrays;\n    example: `\"cannot use insert() with string\"`\n    @throw std::domain_error if @a pos is not an iterator of *this; example:\n    `\"iterator does not fit current value\"`\n\n    @return iterator pointing to the first element inserted, or @a pos if\n    `ilist` is empty\n\n    @complexity Linear in `ilist.size()` plus linear in the distance between\n    @a pos and end of the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert__ilist}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)\n    {\n        // insert only works for arrays\n        if (not is_array())\n        {\n            throw std::domain_error(\"cannot use insert() with \" + type_name());\n        }\n\n        // check if iterator pos fits to this JSON value\n        if (pos.m_object != this)\n        {\n            throw std::domain_error(\"iterator does not fit current value\");\n        }\n\n        // insert to array and return iterator\n        iterator result(this);\n        result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);\n        return result;\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of the JSON value with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other JSON value to exchange the contents with\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how JSON values can be swapped with\n    `swap()`.,swap__reference}\n\n    @since version 1.0.0\n    */\n    void swap(reference other) noexcept (\n        std::is_nothrow_move_constructible<value_t>::value and\n        std::is_nothrow_move_assignable<value_t>::value and\n        std::is_nothrow_move_constructible<json_value>::value and\n        std::is_nothrow_move_assignable<json_value>::value\n    )\n    {\n        std::swap(m_type, other.m_type);\n        std::swap(m_value, other.m_value);\n        assert_invariant();\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of a JSON array with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other array to exchange the contents with\n\n    @throw std::domain_error when JSON value is not an array; example: `\"cannot\n    use swap() with string\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how arrays can be swapped with\n    `swap()`.,swap__array_t}\n\n    @since version 1.0.0\n    */\n    void swap(array_t& other)\n    {\n        // swap only works for arrays\n        if (is_array())\n        {\n            std::swap(*(m_value.array), other);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use swap() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of a JSON object with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other object to exchange the contents with\n\n    @throw std::domain_error when JSON value is not an object; example:\n    `\"cannot use swap() with string\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how objects can be swapped with\n    `swap()`.,swap__object_t}\n\n    @since version 1.0.0\n    */\n    void swap(object_t& other)\n    {\n        // swap only works for objects\n        if (is_object())\n        {\n            std::swap(*(m_value.object), other);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use swap() with \" + type_name());\n        }\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of a JSON string with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other string to exchange the contents with\n\n    @throw std::domain_error when JSON value is not a string; example: `\"cannot\n    use swap() with boolean\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how strings can be swapped with\n    `swap()`.,swap__string_t}\n\n    @since version 1.0.0\n    */\n    void swap(string_t& other)\n    {\n        // swap only works for strings\n        if (is_string())\n        {\n            std::swap(*(m_value.string), other);\n        }\n        else\n        {\n            throw std::domain_error(\"cannot use swap() with \" + type_name());\n        }\n    }\n\n    /// @}\n\n\n    //////////////////////////////////////////\n    // lexicographical comparison operators //\n    //////////////////////////////////////////\n\n    /// @name lexicographical comparison operators\n    /// @{\n\n  private:\n    /*!\n    @brief comparison operator for JSON types\n\n    Returns an ordering that is similar to Python:\n    - order: null < boolean < number < object < array < string\n    - furthermore, each type is not smaller than itself\n\n    @since version 1.0.0\n    */\n    friend bool operator<(const value_t lhs, const value_t rhs) noexcept\n    {\n        static constexpr std::array<uint8_t, 8> order = {{\n                0, // null\n                3, // object\n                4, // array\n                5, // string\n                1, // boolean\n                2, // integer\n                2, // unsigned\n                2, // float\n            }\n        };\n\n        // discarded values are not comparable\n        if (lhs == value_t::discarded or rhs == value_t::discarded)\n        {\n            return false;\n        }\n\n        return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];\n    }\n\n  public:\n    /*!\n    @brief comparison: equal\n\n    Compares two JSON values for equality according to the following rules:\n    - Two JSON values are equal if (1) they are from the same type and (2)\n      their stored values are the same.\n    - Integer and floating-point numbers are automatically converted before\n      comparison. Floating-point numbers are compared indirectly: two\n      floating-point numbers `f1` and `f2` are considered equal if neither\n      `f1 > f2` nor `f2 > f1` holds.\n    - Two JSON null values are equal.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether the values @a lhs and @a rhs are equal\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__equal}\n\n    @since version 1.0.0\n    */\n    friend bool operator==(const_reference lhs, const_reference rhs) noexcept\n    {\n        const auto lhs_type = lhs.type();\n        const auto rhs_type = rhs.type();\n\n        if (lhs_type == rhs_type)\n        {\n            switch (lhs_type)\n            {\n                case value_t::array:\n                {\n                    return *lhs.m_value.array == *rhs.m_value.array;\n                }\n                case value_t::object:\n                {\n                    return *lhs.m_value.object == *rhs.m_value.object;\n                }\n                case value_t::null:\n                {\n                    return true;\n                }\n                case value_t::string:\n                {\n                    return *lhs.m_value.string == *rhs.m_value.string;\n                }\n                case value_t::boolean:\n                {\n                    return lhs.m_value.boolean == rhs.m_value.boolean;\n                }\n                case value_t::number_integer:\n                {\n                    return lhs.m_value.number_integer == rhs.m_value.number_integer;\n                }\n                case value_t::number_unsigned:\n                {\n                    return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;\n                }\n                case value_t::number_float:\n                {\n                    return lhs.m_value.number_float == rhs.m_value.number_float;\n                }\n                default:\n                {\n                    return false;\n                }\n            }\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\n        {\n            return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\n        {\n            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\n        {\n            return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\n        {\n            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\n        {\n            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\n        {\n            return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);\n        }\n\n        return false;\n    }\n\n    /*!\n    @brief comparison: equal\n\n    The functions compares the given JSON value against a null pointer. As the\n    null pointer can be used to initialize a JSON value to null, a comparison\n    of JSON value @a v with a null pointer should be equivalent to call\n    `v.is_null()`.\n\n    @param[in] v  JSON value to consider\n    @return whether @a v is null\n\n    @complexity Constant.\n\n    @liveexample{The example compares several JSON types to the null pointer.\n    ,operator__equal__nullptr_t}\n\n    @since version 1.0.0\n    */\n    friend bool operator==(const_reference v, std::nullptr_t) noexcept\n    {\n        return v.is_null();\n    }\n\n    /*!\n    @brief comparison: equal\n    @copydoc operator==(const_reference, std::nullptr_t)\n    */\n    friend bool operator==(std::nullptr_t, const_reference v) noexcept\n    {\n        return v.is_null();\n    }\n\n    /*!\n    @brief comparison: not equal\n\n    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether the values @a lhs and @a rhs are not equal\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__notequal}\n\n    @since version 1.0.0\n    */\n    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (lhs == rhs);\n    }\n\n    /*!\n    @brief comparison: not equal\n\n    The functions compares the given JSON value against a null pointer. As the\n    null pointer can be used to initialize a JSON value to null, a comparison\n    of JSON value @a v with a null pointer should be equivalent to call\n    `not v.is_null()`.\n\n    @param[in] v  JSON value to consider\n    @return whether @a v is not null\n\n    @complexity Constant.\n\n    @liveexample{The example compares several JSON types to the null pointer.\n    ,operator__notequal__nullptr_t}\n\n    @since version 1.0.0\n    */\n    friend bool operator!=(const_reference v, std::nullptr_t) noexcept\n    {\n        return not v.is_null();\n    }\n\n    /*!\n    @brief comparison: not equal\n    @copydoc operator!=(const_reference, std::nullptr_t)\n    */\n    friend bool operator!=(std::nullptr_t, const_reference v) noexcept\n    {\n        return not v.is_null();\n    }\n\n    /*!\n    @brief comparison: less than\n\n    Compares whether one JSON value @a lhs is less than another JSON value @a\n    rhs according to the following rules:\n    - If @a lhs and @a rhs have the same type, the values are compared using\n      the default `<` operator.\n    - Integer and floating-point numbers are automatically converted before\n      comparison\n    - In case @a lhs and @a rhs have different types, the values are ignored\n      and the order of the types is considered, see\n      @ref operator<(const value_t, const value_t).\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is less than @a rhs\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__less}\n\n    @since version 1.0.0\n    */\n    friend bool operator<(const_reference lhs, const_reference rhs) noexcept\n    {\n        const auto lhs_type = lhs.type();\n        const auto rhs_type = rhs.type();\n\n        if (lhs_type == rhs_type)\n        {\n            switch (lhs_type)\n            {\n                case value_t::array:\n                {\n                    return *lhs.m_value.array < *rhs.m_value.array;\n                }\n                case value_t::object:\n                {\n                    return *lhs.m_value.object < *rhs.m_value.object;\n                }\n                case value_t::null:\n                {\n                    return false;\n                }\n                case value_t::string:\n                {\n                    return *lhs.m_value.string < *rhs.m_value.string;\n                }\n                case value_t::boolean:\n                {\n                    return lhs.m_value.boolean < rhs.m_value.boolean;\n                }\n                case value_t::number_integer:\n                {\n                    return lhs.m_value.number_integer < rhs.m_value.number_integer;\n                }\n                case value_t::number_unsigned:\n                {\n                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;\n                }\n                case value_t::number_float:\n                {\n                    return lhs.m_value.number_float < rhs.m_value.number_float;\n                }\n                default:\n                {\n                    return false;\n                }\n            }\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\n        {\n            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\n        {\n            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\n        {\n            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\n        {\n            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\n        {\n            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\n        {\n            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;\n        }\n\n        // We only reach this line if we cannot compare values. In that case,\n        // we compare types. Note we have to call the operator explicitly,\n        // because MSVC has problems otherwise.\n        return operator<(lhs_type, rhs_type);\n    }\n\n    /*!\n    @brief comparison: less than or equal\n\n    Compares whether one JSON value @a lhs is less than or equal to another\n    JSON value by calculating `not (rhs < lhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is less than or equal to @a rhs\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__greater}\n\n    @since version 1.0.0\n    */\n    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (rhs < lhs);\n    }\n\n    /*!\n    @brief comparison: greater than\n\n    Compares whether one JSON value @a lhs is greater than another\n    JSON value by calculating `not (lhs <= rhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is greater than to @a rhs\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__lessequal}\n\n    @since version 1.0.0\n    */\n    friend bool operator>(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (lhs <= rhs);\n    }\n\n    /*!\n    @brief comparison: greater than or equal\n\n    Compares whether one JSON value @a lhs is greater than or equal to another\n    JSON value by calculating `not (lhs < rhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is greater than or equal to @a rhs\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__greaterequal}\n\n    @since version 1.0.0\n    */\n    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (lhs < rhs);\n    }\n\n    /// @}\n\n\n    ///////////////////\n    // serialization //\n    ///////////////////\n\n    /// @name serialization\n    /// @{\n\n    /*!\n    @brief serialize to stream\n\n    Serialize the given JSON value @a j to the output stream @a o. The JSON\n    value will be serialized using the @ref dump member function. The\n    indentation of the output can be controlled with the member variable\n    `width` of the output stream @a o. For instance, using the manipulator\n    `std::setw(4)` on @a o sets the indentation level to `4` and the\n    serialization result is the same as calling `dump(4)`.\n\n    @note During serializaion, the locale and the precision of the output\n    stream @a o are changed. The original values are restored when the\n    function returns.\n\n    @param[in,out] o  stream to serialize to\n    @param[in] j  JSON value to serialize\n\n    @return the stream @a o\n\n    @complexity Linear.\n\n    @liveexample{The example below shows the serialization with different\n    parameters to `width` to adjust the indentation level.,operator_serialize}\n\n    @since version 1.0.0\n    */\n    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)\n    {\n        // read width member and use it as indentation parameter if nonzero\n        const bool pretty_print = (o.width() > 0);\n        const auto indentation = (pretty_print ? o.width() : 0);\n\n        // reset width to 0 for subsequent calls to this stream\n        o.width(0);\n\n        // fix locale problems\n        const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));\n        // set precision\n\n        // 6, 15 or 16 digits of precision allows round-trip IEEE 754\n        // string->float->string, string->double->string or string->long\n        // double->string; to be safe, we read this value from\n        // std::numeric_limits<number_float_t>::digits10\n        const auto old_precision = o.precision(std::numeric_limits<double>::digits10);\n\n        // do the actual serialization\n        j.dump(o, pretty_print, static_cast<unsigned int>(indentation));\n\n        // reset locale and precision\n        o.imbue(old_locale);\n        o.precision(old_precision);\n        return o;\n    }\n\n    /*!\n    @brief serialize to stream\n    @copydoc operator<<(std::ostream&, const basic_json&)\n    */\n    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)\n    {\n        return o << j;\n    }\n\n    /// @}\n\n\n    /////////////////////\n    // deserialization //\n    /////////////////////\n\n    /// @name deserialization\n    /// @{\n\n    /*!\n    @brief deserialize from string\n\n    @param[in] s  string to read a serialized JSON value from\n    @param[in] cb a parser callback function of type @ref parser_callback_t\n    which is used to control the deserialization by filtering unwanted values\n    (optional)\n\n    @return result of the deserialization\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser. The complexity can be higher if the parser callback function\n    @a cb has a super-linear complexity.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below demonstrates the `parse()` function with\n    and without callback function.,parse__string__parser_callback_t}\n\n    @sa @ref parse(std::istream&, const parser_callback_t) for a version that\n    reads from an input stream\n\n    @since version 1.0.0\n    */\n    static basic_json parse(const string_t& s,\n                            const parser_callback_t cb = nullptr)\n    {\n        return parser(s, cb).parse();\n    }\n\n    /*!\n    @brief deserialize from stream\n\n    @param[in,out] i  stream to read a serialized JSON value from\n    @param[in] cb a parser callback function of type @ref parser_callback_t\n    which is used to control the deserialization by filtering unwanted values\n    (optional)\n\n    @return result of the deserialization\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser. The complexity can be higher if the parser callback function\n    @a cb has a super-linear complexity.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below demonstrates the `parse()` function with\n    and without callback function.,parse__istream__parser_callback_t}\n\n    @sa @ref parse(const string_t&, const parser_callback_t) for a version\n    that reads from a string\n\n    @since version 1.0.0\n    */\n    static basic_json parse(std::istream& i,\n                            const parser_callback_t cb = nullptr)\n    {\n        return parser(i, cb).parse();\n    }\n\n    /*!\n    @copydoc parse(std::istream&, const parser_callback_t)\n    */\n    static basic_json parse(std::istream&& i,\n                            const parser_callback_t cb = nullptr)\n    {\n        return parser(i, cb).parse();\n    }\n\n    /*!\n    @brief deserialize from stream\n\n    Deserializes an input stream to a JSON value.\n\n    @param[in,out] i  input stream to read a serialized JSON value from\n    @param[in,out] j  JSON value to write the deserialized input to\n\n    @throw std::invalid_argument in case of parse errors\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below shows how a JSON value is constructed by\n    reading a serialization from a stream.,operator_deserialize}\n\n    @sa parse(std::istream&, const parser_callback_t) for a variant with a\n    parser callback function to filter values while parsing\n\n    @since version 1.0.0\n    */\n    friend std::istream& operator<<(basic_json& j, std::istream& i)\n    {\n        j = parser(i).parse();\n        return i;\n    }\n\n    /*!\n    @brief deserialize from stream\n    @copydoc operator<<(basic_json&, std::istream&)\n    */\n    friend std::istream& operator>>(std::istream& i, basic_json& j)\n    {\n        j = parser(i).parse();\n        return i;\n    }\n\n    /// @}\n\n\n  private:\n    ///////////////////////////\n    // convenience functions //\n    ///////////////////////////\n\n    /*!\n    @brief return the type as string\n\n    Returns the type name as string to be used in error messages - usually to\n    indicate that a function was called on a wrong JSON type.\n\n    @return basically a string representation of a the @ref m_type member\n\n    @complexity Constant.\n\n    @since version 1.0.0\n    */\n    std::string type_name() const\n    {\n        switch (m_type)\n        {\n            case value_t::null:\n                return \"null\";\n            case value_t::object:\n                return \"object\";\n            case value_t::array:\n                return \"array\";\n            case value_t::string:\n                return \"string\";\n            case value_t::boolean:\n                return \"boolean\";\n            case value_t::discarded:\n                return \"discarded\";\n            default:\n                return \"number\";\n        }\n    }\n\n    /*!\n    @brief calculates the extra space to escape a JSON string\n\n    @param[in] s  the string to escape\n    @return the number of characters required to escape string @a s\n\n    @complexity Linear in the length of string @a s.\n    */\n    static std::size_t extra_space(const string_t& s) noexcept\n    {\n        return std::accumulate(s.begin(), s.end(), size_t{},\n                               [](size_t res, typename string_t::value_type c)\n        {\n            switch (c)\n            {\n                case '\"':\n                case '\\\\':\n                case '\\b':\n                case '\\f':\n                case '\\n':\n                case '\\r':\n                case '\\t':\n                {\n                    // from c (1 byte) to \\x (2 bytes)\n                    return res + 1;\n                }\n\n                default:\n                {\n                    if (c >= 0x00 and c <= 0x1f)\n                    {\n                        // from c (1 byte) to \\uxxxx (6 bytes)\n                        return res + 5;\n                    }\n                    else\n                    {\n                        return res;\n                    }\n                }\n            }\n        });\n    }\n\n    /*!\n    @brief escape a string\n\n    Escape a string by replacing certain special characters by a sequence of\n    an escape character (backslash) and another character and other control\n    characters by a sequence of \"\\u\" followed by a four-digit hex\n    representation.\n\n    @param[in] s  the string to escape\n    @return  the escaped string\n\n    @complexity Linear in the length of string @a s.\n    */\n    static string_t escape_string(const string_t& s)\n    {\n        const auto space = extra_space(s);\n        if (space == 0)\n        {\n            return s;\n        }\n\n        // create a result string of necessary size\n        string_t result(s.size() + space, '\\\\');\n        std::size_t pos = 0;\n\n        for (const auto& c : s)\n        {\n            switch (c)\n            {\n                // quotation mark (0x22)\n                case '\"':\n                {\n                    result[pos + 1] = '\"';\n                    pos += 2;\n                    break;\n                }\n\n                // reverse solidus (0x5c)\n                case '\\\\':\n                {\n                    // nothing to change\n                    pos += 2;\n                    break;\n                }\n\n                // backspace (0x08)\n                case '\\b':\n                {\n                    result[pos + 1] = 'b';\n                    pos += 2;\n                    break;\n                }\n\n                // formfeed (0x0c)\n                case '\\f':\n                {\n                    result[pos + 1] = 'f';\n                    pos += 2;\n                    break;\n                }\n\n                // newline (0x0a)\n                case '\\n':\n                {\n                    result[pos + 1] = 'n';\n                    pos += 2;\n                    break;\n                }\n\n                // carriage return (0x0d)\n                case '\\r':\n                {\n                    result[pos + 1] = 'r';\n                    pos += 2;\n                    break;\n                }\n\n                // horizontal tab (0x09)\n                case '\\t':\n                {\n                    result[pos + 1] = 't';\n                    pos += 2;\n                    break;\n                }\n\n                default:\n                {\n                    if (c >= 0x00 and c <= 0x1f)\n                    {\n                        // convert a number 0..15 to its hex representation\n                        // (0..f)\n                        static const char hexify[16] =\n                        {\n                            '0', '1', '2', '3', '4', '5', '6', '7',\n                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'\n                        };\n\n                        // print character c as \\uxxxx\n                        for (const char m :\n                    { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]\n                        })\n                        {\n                            result[++pos] = m;\n                        }\n\n                        ++pos;\n                    }\n                    else\n                    {\n                        // all other characters are added as-is\n                        result[pos++] = c;\n                    }\n                    break;\n                }\n            }\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief internal implementation of the serialization function\n\n    This function is called by the public member function dump and organizes\n    the serialization internally. The indentation level is propagated as\n    additional parameter. In case of arrays and objects, the function is\n    called recursively. Note that\n\n    - strings and object keys are escaped using `escape_string()`\n    - integer numbers are converted implicitly via `operator<<`\n    - floating-point numbers are converted to a string using `\"%g\"` format\n\n    @param[out] o              stream to write to\n    @param[in] pretty_print    whether the output shall be pretty-printed\n    @param[in] indent_step     the indent level\n    @param[in] current_indent  the current indent level (only used internally)\n    */\n    void dump(std::ostream& o,\n              const bool pretty_print,\n              const unsigned int indent_step,\n              const unsigned int current_indent = 0) const\n    {\n        // variable to hold indentation for recursive calls\n        unsigned int new_indent = current_indent;\n\n        switch (m_type)\n        {\n            case value_t::object:\n            {\n                if (m_value.object->empty())\n                {\n                    o << \"{}\";\n                    return;\n                }\n\n                o << \"{\";\n\n                // increase indentation\n                if (pretty_print)\n                {\n                    new_indent += indent_step;\n                    o << \"\\n\";\n                }\n\n                for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)\n                {\n                    if (i != m_value.object->cbegin())\n                    {\n                        o << (pretty_print ? \",\\n\" : \",\");\n                    }\n                    o << string_t(new_indent, ' ') << \"\\\"\"\n                      << escape_string(i->first) << \"\\\":\"\n                      << (pretty_print ? \" \" : \"\");\n                    i->second.dump(o, pretty_print, indent_step, new_indent);\n                }\n\n                // decrease indentation\n                if (pretty_print)\n                {\n                    new_indent -= indent_step;\n                    o << \"\\n\";\n                }\n\n                o << string_t(new_indent, ' ') + \"}\";\n                return;\n            }\n\n            case value_t::array:\n            {\n                if (m_value.array->empty())\n                {\n                    o << \"[]\";\n                    return;\n                }\n\n                o << \"[\";\n\n                // increase indentation\n                if (pretty_print)\n                {\n                    new_indent += indent_step;\n                    o << \"\\n\";\n                }\n\n                for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)\n                {\n                    if (i != m_value.array->cbegin())\n                    {\n                        o << (pretty_print ? \",\\n\" : \",\");\n                    }\n                    o << string_t(new_indent, ' ');\n                    i->dump(o, pretty_print, indent_step, new_indent);\n                }\n\n                // decrease indentation\n                if (pretty_print)\n                {\n                    new_indent -= indent_step;\n                    o << \"\\n\";\n                }\n\n                o << string_t(new_indent, ' ') << \"]\";\n                return;\n            }\n\n            case value_t::string:\n            {\n                o << string_t(\"\\\"\") << escape_string(*m_value.string) << \"\\\"\";\n                return;\n            }\n\n            case value_t::boolean:\n            {\n                o << (m_value.boolean ? \"true\" : \"false\");\n                return;\n            }\n\n            case value_t::number_integer:\n            {\n                o << m_value.number_integer;\n                return;\n            }\n\n            case value_t::number_unsigned:\n            {\n                o << m_value.number_unsigned;\n                return;\n            }\n\n            case value_t::number_float:\n            {\n                if (m_value.number_float == 0)\n                {\n                    // special case for zero to get \"0.0\"/\"-0.0\"\n                    o << (std::signbit(m_value.number_float) ? \"-0.0\" : \"0.0\");\n                }\n                else\n                {\n                    o << m_value.number_float;\n                }\n                return;\n            }\n\n            case value_t::discarded:\n            {\n                o << \"<discarded>\";\n                return;\n            }\n\n            case value_t::null:\n            {\n                o << \"null\";\n                return;\n            }\n        }\n    }\n\n  private:\n    //////////////////////\n    // member variables //\n    //////////////////////\n\n    /// the type of the current element\n    value_t m_type = value_t::null;\n\n    /// the value of the current element\n    json_value m_value = {};\n\n\n  private:\n    ///////////////\n    // iterators //\n    ///////////////\n\n    /*!\n    @brief an iterator for primitive JSON types\n\n    This class models an iterator for primitive JSON types (boolean, number,\n    string). It's only purpose is to allow the iterator/const_iterator classes\n    to \"iterate\" over primitive values. Internally, the iterator is modeled by\n    a `difference_type` variable. Value begin_value (`0`) models the begin,\n    end_value (`1`) models past the end.\n    */\n    class primitive_iterator_t\n    {\n      public:\n        /// set iterator to a defined beginning\n        void set_begin() noexcept\n        {\n            m_it = begin_value;\n        }\n\n        /// set iterator to a defined past the end\n        void set_end() noexcept\n        {\n            m_it = end_value;\n        }\n\n        /// return whether the iterator can be dereferenced\n        constexpr bool is_begin() const noexcept\n        {\n            return (m_it == begin_value);\n        }\n\n        /// return whether the iterator is at end\n        constexpr bool is_end() const noexcept\n        {\n            return (m_it == end_value);\n        }\n\n        /// return reference to the value to change and compare\n        operator difference_type& () noexcept\n        {\n            return m_it;\n        }\n\n        /// return value to compare\n        constexpr operator difference_type () const noexcept\n        {\n            return m_it;\n        }\n\n      private:\n        static constexpr difference_type begin_value = 0;\n        static constexpr difference_type end_value = begin_value + 1;\n\n        /// iterator as signed integer type\n        difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();\n    };\n\n    /*!\n    @brief an iterator value\n\n    @note This structure could easily be a union, but MSVC currently does not\n    allow unions members with complex constructors, see\n    https://github.com/nlohmann/json/pull/105.\n    */\n    struct internal_iterator\n    {\n        /// iterator for JSON objects\n        typename object_t::iterator object_iterator;\n        /// iterator for JSON arrays\n        typename array_t::iterator array_iterator;\n        /// generic iterator for all other types\n        primitive_iterator_t primitive_iterator;\n\n        /// create an uninitialized internal_iterator\n        internal_iterator() noexcept\n            : object_iterator(), array_iterator(), primitive_iterator()\n        {}\n    };\n\n    /// proxy class for the iterator_wrapper functions\n    template<typename IteratorType>\n    class iteration_proxy\n    {\n      private:\n        /// helper class for iteration\n        class iteration_proxy_internal\n        {\n          private:\n            /// the iterator\n            IteratorType anchor;\n            /// an index for arrays (used to create key names)\n            size_t array_index = 0;\n\n          public:\n            explicit iteration_proxy_internal(IteratorType it) noexcept\n                : anchor(it)\n            {}\n\n            /// dereference operator (needed for range-based for)\n            iteration_proxy_internal& operator*()\n            {\n                return *this;\n            }\n\n            /// increment operator (needed for range-based for)\n            iteration_proxy_internal& operator++()\n            {\n                ++anchor;\n                ++array_index;\n\n                return *this;\n            }\n\n            /// inequality operator (needed for range-based for)\n            bool operator!= (const iteration_proxy_internal& o) const\n            {\n                return anchor != o.anchor;\n            }\n\n            /// return key of the iterator\n            typename basic_json::string_t key() const\n            {\n                assert(anchor.m_object != nullptr);\n\n                switch (anchor.m_object->type())\n                {\n                    // use integer array index as key\n                    case value_t::array:\n                    {\n                        return std::to_string(array_index);\n                    }\n\n                    // use key from the object\n                    case value_t::object:\n                    {\n                        return anchor.key();\n                    }\n\n                    // use an empty key for all primitive types\n                    default:\n                    {\n                        return \"\";\n                    }\n                }\n            }\n\n            /// return value of the iterator\n            typename IteratorType::reference value() const\n            {\n                return anchor.value();\n            }\n        };\n\n        /// the container to iterate\n        typename IteratorType::reference container;\n\n      public:\n        /// construct iteration proxy from a container\n        explicit iteration_proxy(typename IteratorType::reference cont)\n            : container(cont)\n        {}\n\n        /// return iterator begin (needed for range-based for)\n        iteration_proxy_internal begin() noexcept\n        {\n            return iteration_proxy_internal(container.begin());\n        }\n\n        /// return iterator end (needed for range-based for)\n        iteration_proxy_internal end() noexcept\n        {\n            return iteration_proxy_internal(container.end());\n        }\n    };\n\n  public:\n    /*!\n    @brief a const random access iterator for the @ref basic_json class\n\n    This class implements a const iterator for the @ref basic_json class. From\n    this class, the @ref iterator class is derived.\n\n    @note An iterator is called *initialized* when a pointer to a JSON value\n          has been set (e.g., by a constructor or a copy assignment). If the\n          iterator is default-constructed, it is *uninitialized* and most\n          methods are undefined. **The library uses assertions to detect calls\n          on uninitialized iterators.**\n\n    @requirement The class satisfies the following concept requirements:\n    - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):\n      The iterator that can be moved to point (forward and backward) to any\n      element in constant time.\n\n    @since version 1.0.0\n    */\n    class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>\n    {\n        /// allow basic_json to access private members\n        friend class basic_json;\n\n      public:\n        /// the type of the values when the iterator is dereferenced\n        using value_type = typename basic_json::value_type;\n        /// a type to represent differences between iterators\n        using difference_type = typename basic_json::difference_type;\n        /// defines a pointer to the type iterated over (value_type)\n        using pointer = typename basic_json::const_pointer;\n        /// defines a reference to the type iterated over (value_type)\n        using reference = typename basic_json::const_reference;\n        /// the category of the iterator\n        using iterator_category = std::bidirectional_iterator_tag;\n\n        /// default constructor\n        const_iterator() = default;\n\n        /*!\n        @brief constructor for a given JSON instance\n        @param[in] object  pointer to a JSON object for this iterator\n        @pre object != nullptr\n        @post The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        explicit const_iterator(pointer object) noexcept\n            : m_object(object)\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    m_it.object_iterator = typename object_t::iterator();\n                    break;\n                }\n\n                case basic_json::value_t::array:\n                {\n                    m_it.array_iterator = typename array_t::iterator();\n                    break;\n                }\n\n                default:\n                {\n                    m_it.primitive_iterator = primitive_iterator_t();\n                    break;\n                }\n            }\n        }\n\n        /*!\n        @brief copy constructor given a non-const iterator\n        @param[in] other  iterator to copy from\n        @note It is not checked whether @a other is initialized.\n        */\n        explicit const_iterator(const iterator& other) noexcept\n            : m_object(other.m_object)\n        {\n            if (m_object != nullptr)\n            {\n                switch (m_object->m_type)\n                {\n                    case basic_json::value_t::object:\n                    {\n                        m_it.object_iterator = other.m_it.object_iterator;\n                        break;\n                    }\n\n                    case basic_json::value_t::array:\n                    {\n                        m_it.array_iterator = other.m_it.array_iterator;\n                        break;\n                    }\n\n                    default:\n                    {\n                        m_it.primitive_iterator = other.m_it.primitive_iterator;\n                        break;\n                    }\n                }\n            }\n        }\n\n        /*!\n        @brief copy constructor\n        @param[in] other  iterator to copy from\n        @note It is not checked whether @a other is initialized.\n        */\n        const_iterator(const const_iterator& other) noexcept\n            : m_object(other.m_object), m_it(other.m_it)\n        {}\n\n        /*!\n        @brief copy assignment\n        @param[in,out] other  iterator to copy from\n        @note It is not checked whether @a other is initialized.\n        */\n        const_iterator& operator=(const_iterator other) noexcept(\n            std::is_nothrow_move_constructible<pointer>::value and\n            std::is_nothrow_move_assignable<pointer>::value and\n            std::is_nothrow_move_constructible<internal_iterator>::value and\n            std::is_nothrow_move_assignable<internal_iterator>::value\n        )\n        {\n            std::swap(m_object, other.m_object);\n            std::swap(m_it, other.m_it);\n            return *this;\n        }\n\n      private:\n        /*!\n        @brief set the iterator to the first value\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        void set_begin() noexcept\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    m_it.object_iterator = m_object->m_value.object->begin();\n                    break;\n                }\n\n                case basic_json::value_t::array:\n                {\n                    m_it.array_iterator = m_object->m_value.array->begin();\n                    break;\n                }\n\n                case basic_json::value_t::null:\n                {\n                    // set to end so begin()==end() is true: null is empty\n                    m_it.primitive_iterator.set_end();\n                    break;\n                }\n\n                default:\n                {\n                    m_it.primitive_iterator.set_begin();\n                    break;\n                }\n            }\n        }\n\n        /*!\n        @brief set the iterator past the last value\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        void set_end() noexcept\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    m_it.object_iterator = m_object->m_value.object->end();\n                    break;\n                }\n\n                case basic_json::value_t::array:\n                {\n                    m_it.array_iterator = m_object->m_value.array->end();\n                    break;\n                }\n\n                default:\n                {\n                    m_it.primitive_iterator.set_end();\n                    break;\n                }\n            }\n        }\n\n      public:\n        /*!\n        @brief return a reference to the value pointed to by the iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        reference operator*() const\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    assert(m_it.object_iterator != m_object->m_value.object->end());\n                    return m_it.object_iterator->second;\n                }\n\n                case basic_json::value_t::array:\n                {\n                    assert(m_it.array_iterator != m_object->m_value.array->end());\n                    return *m_it.array_iterator;\n                }\n\n                case basic_json::value_t::null:\n                {\n                    throw std::out_of_range(\"cannot get value\");\n                }\n\n                default:\n                {\n                    if (m_it.primitive_iterator.is_begin())\n                    {\n                        return *m_object;\n                    }\n                    else\n                    {\n                        throw std::out_of_range(\"cannot get value\");\n                    }\n                }\n            }\n        }\n\n        /*!\n        @brief dereference the iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        pointer operator->() const\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    assert(m_it.object_iterator != m_object->m_value.object->end());\n                    return &(m_it.object_iterator->second);\n                }\n\n                case basic_json::value_t::array:\n                {\n                    assert(m_it.array_iterator != m_object->m_value.array->end());\n                    return &*m_it.array_iterator;\n                }\n\n                default:\n                {\n                    if (m_it.primitive_iterator.is_begin())\n                    {\n                        return m_object;\n                    }\n                    else\n                    {\n                        throw std::out_of_range(\"cannot get value\");\n                    }\n                }\n            }\n        }\n\n        /*!\n        @brief post-increment (it++)\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator operator++(int)\n        {\n            auto result = *this;\n            ++(*this);\n            return result;\n        }\n\n        /*!\n        @brief pre-increment (++it)\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator& operator++()\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    std::advance(m_it.object_iterator, 1);\n                    break;\n                }\n\n                case basic_json::value_t::array:\n                {\n                    std::advance(m_it.array_iterator, 1);\n                    break;\n                }\n\n                default:\n                {\n                    ++m_it.primitive_iterator;\n                    break;\n                }\n            }\n\n            return *this;\n        }\n\n        /*!\n        @brief post-decrement (it--)\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator operator--(int)\n        {\n            auto result = *this;\n            --(*this);\n            return result;\n        }\n\n        /*!\n        @brief pre-decrement (--it)\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator& operator--()\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    std::advance(m_it.object_iterator, -1);\n                    break;\n                }\n\n                case basic_json::value_t::array:\n                {\n                    std::advance(m_it.array_iterator, -1);\n                    break;\n                }\n\n                default:\n                {\n                    --m_it.primitive_iterator;\n                    break;\n                }\n            }\n\n            return *this;\n        }\n\n        /*!\n        @brief  comparison: equal\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        bool operator==(const const_iterator& other) const\n        {\n            // if objects are not the same, the comparison is undefined\n            if (m_object != other.m_object)\n            {\n                throw std::domain_error(\"cannot compare iterators of different containers\");\n            }\n\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    return (m_it.object_iterator == other.m_it.object_iterator);\n                }\n\n                case basic_json::value_t::array:\n                {\n                    return (m_it.array_iterator == other.m_it.array_iterator);\n                }\n\n                default:\n                {\n                    return (m_it.primitive_iterator == other.m_it.primitive_iterator);\n                }\n            }\n        }\n\n        /*!\n        @brief  comparison: not equal\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        bool operator!=(const const_iterator& other) const\n        {\n            return not operator==(other);\n        }\n\n        /*!\n        @brief  comparison: smaller\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        bool operator<(const const_iterator& other) const\n        {\n            // if objects are not the same, the comparison is undefined\n            if (m_object != other.m_object)\n            {\n                throw std::domain_error(\"cannot compare iterators of different containers\");\n            }\n\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    throw std::domain_error(\"cannot compare order of object iterators\");\n                }\n\n                case basic_json::value_t::array:\n                {\n                    return (m_it.array_iterator < other.m_it.array_iterator);\n                }\n\n                default:\n                {\n                    return (m_it.primitive_iterator < other.m_it.primitive_iterator);\n                }\n            }\n        }\n\n        /*!\n        @brief  comparison: less than or equal\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        bool operator<=(const const_iterator& other) const\n        {\n            return not other.operator < (*this);\n        }\n\n        /*!\n        @brief  comparison: greater than\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        bool operator>(const const_iterator& other) const\n        {\n            return not operator<=(other);\n        }\n\n        /*!\n        @brief  comparison: greater than or equal\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        bool operator>=(const const_iterator& other) const\n        {\n            return not operator<(other);\n        }\n\n        /*!\n        @brief  add to iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator& operator+=(difference_type i)\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    throw std::domain_error(\"cannot use offsets with object iterators\");\n                }\n\n                case basic_json::value_t::array:\n                {\n                    std::advance(m_it.array_iterator, i);\n                    break;\n                }\n\n                default:\n                {\n                    m_it.primitive_iterator += i;\n                    break;\n                }\n            }\n\n            return *this;\n        }\n\n        /*!\n        @brief  subtract from iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator& operator-=(difference_type i)\n        {\n            return operator+=(-i);\n        }\n\n        /*!\n        @brief  add to iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator operator+(difference_type i)\n        {\n            auto result = *this;\n            result += i;\n            return result;\n        }\n\n        /*!\n        @brief  subtract from iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        const_iterator operator-(difference_type i)\n        {\n            auto result = *this;\n            result -= i;\n            return result;\n        }\n\n        /*!\n        @brief  return difference\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        difference_type operator-(const const_iterator& other) const\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    throw std::domain_error(\"cannot use offsets with object iterators\");\n                }\n\n                case basic_json::value_t::array:\n                {\n                    return m_it.array_iterator - other.m_it.array_iterator;\n                }\n\n                default:\n                {\n                    return m_it.primitive_iterator - other.m_it.primitive_iterator;\n                }\n            }\n        }\n\n        /*!\n        @brief  access to successor\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        reference operator[](difference_type n) const\n        {\n            assert(m_object != nullptr);\n\n            switch (m_object->m_type)\n            {\n                case basic_json::value_t::object:\n                {\n                    throw std::domain_error(\"cannot use operator[] for object iterators\");\n                }\n\n                case basic_json::value_t::array:\n                {\n                    return *std::next(m_it.array_iterator, n);\n                }\n\n                case basic_json::value_t::null:\n                {\n                    throw std::out_of_range(\"cannot get value\");\n                }\n\n                default:\n                {\n                    if (m_it.primitive_iterator == -n)\n                    {\n                        return *m_object;\n                    }\n                    else\n                    {\n                        throw std::out_of_range(\"cannot get value\");\n                    }\n                }\n            }\n        }\n\n        /*!\n        @brief  return the key of an object iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        typename object_t::key_type key() const\n        {\n            assert(m_object != nullptr);\n\n            if (m_object->is_object())\n            {\n                return m_it.object_iterator->first;\n            }\n            else\n            {\n                throw std::domain_error(\"cannot use key() for non-object iterators\");\n            }\n        }\n\n        /*!\n        @brief  return the value of an iterator\n        @pre The iterator is initialized; i.e. `m_object != nullptr`.\n        */\n        reference value() const\n        {\n            return operator*();\n        }\n\n      private:\n        /// associated JSON instance\n        pointer m_object = nullptr;\n        /// the actual iterator of the associated instance\n        internal_iterator m_it = internal_iterator();\n    };\n\n    /*!\n    @brief a mutable random access iterator for the @ref basic_json class\n\n    @requirement The class satisfies the following concept requirements:\n    - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):\n      The iterator that can be moved to point (forward and backward) to any\n      element in constant time.\n    - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):\n      It is possible to write to the pointed-to element.\n\n    @since version 1.0.0\n    */\n    class iterator : public const_iterator\n    {\n      public:\n        using base_iterator = const_iterator;\n        using pointer = typename basic_json::pointer;\n        using reference = typename basic_json::reference;\n\n        /// default constructor\n        iterator() = default;\n\n        /// constructor for a given JSON instance\n        explicit iterator(pointer object) noexcept\n            : base_iterator(object)\n        {}\n\n        /// copy constructor\n        iterator(const iterator& other) noexcept\n            : base_iterator(other)\n        {}\n\n        /// copy assignment\n        iterator& operator=(iterator other) noexcept(\n            std::is_nothrow_move_constructible<pointer>::value and\n            std::is_nothrow_move_assignable<pointer>::value and\n            std::is_nothrow_move_constructible<internal_iterator>::value and\n            std::is_nothrow_move_assignable<internal_iterator>::value\n        )\n        {\n            base_iterator::operator=(other);\n            return *this;\n        }\n\n        /// return a reference to the value pointed to by the iterator\n        reference operator*() const\n        {\n            return const_cast<reference>(base_iterator::operator*());\n        }\n\n        /// dereference the iterator\n        pointer operator->() const\n        {\n            return const_cast<pointer>(base_iterator::operator->());\n        }\n\n        /// post-increment (it++)\n        iterator operator++(int)\n        {\n            iterator result = *this;\n            base_iterator::operator++();\n            return result;\n        }\n\n        /// pre-increment (++it)\n        iterator& operator++()\n        {\n            base_iterator::operator++();\n            return *this;\n        }\n\n        /// post-decrement (it--)\n        iterator operator--(int)\n        {\n            iterator result = *this;\n            base_iterator::operator--();\n            return result;\n        }\n\n        /// pre-decrement (--it)\n        iterator& operator--()\n        {\n            base_iterator::operator--();\n            return *this;\n        }\n\n        /// add to iterator\n        iterator& operator+=(difference_type i)\n        {\n            base_iterator::operator+=(i);\n            return *this;\n        }\n\n        /// subtract from iterator\n        iterator& operator-=(difference_type i)\n        {\n            base_iterator::operator-=(i);\n            return *this;\n        }\n\n        /// add to iterator\n        iterator operator+(difference_type i)\n        {\n            auto result = *this;\n            result += i;\n            return result;\n        }\n\n        /// subtract from iterator\n        iterator operator-(difference_type i)\n        {\n            auto result = *this;\n            result -= i;\n            return result;\n        }\n\n        /// return difference\n        difference_type operator-(const iterator& other) const\n        {\n            return base_iterator::operator-(other);\n        }\n\n        /// access to successor\n        reference operator[](difference_type n) const\n        {\n            return const_cast<reference>(base_iterator::operator[](n));\n        }\n\n        /// return the value of an iterator\n        reference value() const\n        {\n            return const_cast<reference>(base_iterator::value());\n        }\n    };\n\n    /*!\n    @brief a template for a reverse iterator class\n\n    @tparam Base the base iterator type to reverse. Valid types are @ref\n    iterator (to create @ref reverse_iterator) and @ref const_iterator (to\n    create @ref const_reverse_iterator).\n\n    @requirement The class satisfies the following concept requirements:\n    - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):\n      The iterator that can be moved to point (forward and backward) to any\n      element in constant time.\n    - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):\n      It is possible to write to the pointed-to element (only if @a Base is\n      @ref iterator).\n\n    @since version 1.0.0\n    */\n    template<typename Base>\n    class json_reverse_iterator : public std::reverse_iterator<Base>\n    {\n      public:\n        /// shortcut to the reverse iterator adaptor\n        using base_iterator = std::reverse_iterator<Base>;\n        /// the reference type for the pointed-to element\n        using reference = typename Base::reference;\n\n        /// create reverse iterator from iterator\n        json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept\n            : base_iterator(it)\n        {}\n\n        /// create reverse iterator from base class\n        json_reverse_iterator(const base_iterator& it) noexcept\n            : base_iterator(it)\n        {}\n\n        /// post-increment (it++)\n        json_reverse_iterator operator++(int)\n        {\n            return base_iterator::operator++(1);\n        }\n\n        /// pre-increment (++it)\n        json_reverse_iterator& operator++()\n        {\n            base_iterator::operator++();\n            return *this;\n        }\n\n        /// post-decrement (it--)\n        json_reverse_iterator operator--(int)\n        {\n            return base_iterator::operator--(1);\n        }\n\n        /// pre-decrement (--it)\n        json_reverse_iterator& operator--()\n        {\n            base_iterator::operator--();\n            return *this;\n        }\n\n        /// add to iterator\n        json_reverse_iterator& operator+=(difference_type i)\n        {\n            base_iterator::operator+=(i);\n            return *this;\n        }\n\n        /// add to iterator\n        json_reverse_iterator operator+(difference_type i) const\n        {\n            auto result = *this;\n            result += i;\n            return result;\n        }\n\n        /// subtract from iterator\n        json_reverse_iterator operator-(difference_type i) const\n        {\n            auto result = *this;\n            result -= i;\n            return result;\n        }\n\n        /// return difference\n        difference_type operator-(const json_reverse_iterator& other) const\n        {\n            return this->base() - other.base();\n        }\n\n        /// access to successor\n        reference operator[](difference_type n) const\n        {\n            return *(this->operator+(n));\n        }\n\n        /// return the key of an object iterator\n        typename object_t::key_type key() const\n        {\n            auto it = --this->base();\n            return it.key();\n        }\n\n        /// return the value of an iterator\n        reference value() const\n        {\n            auto it = --this->base();\n            return it.operator * ();\n        }\n    };\n\n\n  private:\n    //////////////////////\n    // lexer and parser //\n    //////////////////////\n\n    /*!\n    @brief lexical analysis\n\n    This class organizes the lexical analysis during JSON deserialization. The\n    core of it is a scanner generated by [re2c](http://re2c.org) that\n    processes a buffer and recognizes tokens according to RFC 7159.\n    */\n    class lexer\n    {\n      public:\n        /// token types for the parser\n        enum class token_type\n        {\n            uninitialized,   ///< indicating the scanner is uninitialized\n            literal_true,    ///< the `true` literal\n            literal_false,   ///< the `false` literal\n            literal_null,    ///< the `null` literal\n            value_string,    ///< a string -- use get_string() for actual value\n            value_number,    ///< a number -- use get_number() for actual value\n            begin_array,     ///< the character for array begin `[`\n            begin_object,    ///< the character for object begin `{`\n            end_array,       ///< the character for array end `]`\n            end_object,      ///< the character for object end `}`\n            name_separator,  ///< the name separator `:`\n            value_separator, ///< the value separator `,`\n            parse_error,     ///< indicating a parse error\n            end_of_input     ///< indicating the end of the input buffer\n        };\n\n        /// the char type to use in the lexer\n        using lexer_char_t = unsigned char;\n\n        /// constructor with a given buffer\n        explicit lexer(const string_t& s) noexcept\n            : m_stream(nullptr), m_buffer(s)\n        {\n            m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());\n            assert(m_content != nullptr);\n            m_start = m_cursor = m_content;\n            m_limit = m_content + s.size();\n        }\n\n        /// constructor with a given stream\n        explicit lexer(std::istream* s) noexcept\n            : m_stream(s), m_buffer()\n        {\n            assert(m_stream != nullptr);\n            std::getline(*m_stream, m_buffer);\n            m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());\n            assert(m_content != nullptr);\n            m_start = m_cursor = m_content;\n            m_limit = m_content + m_buffer.size();\n        }\n\n        /// default constructor\n        lexer() = default;\n\n        // switch off unwanted functions\n        lexer(const lexer&) = delete;\n        lexer operator=(const lexer&) = delete;\n\n        /*!\n        @brief create a string from one or two Unicode code points\n\n        There are two cases: (1) @a codepoint1 is in the Basic Multilingual\n        Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2)\n        @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to\n        represent a code point above U+FFFF.\n\n        @param[in] codepoint1  the code point (can be high surrogate)\n        @param[in] codepoint2  the code point (can be low surrogate or 0)\n\n        @return string representation of the code point; the length of the\n        result string is between 1 and 4 characters.\n\n        @throw std::out_of_range if code point is > 0x10ffff; example: `\"code\n        points above 0x10FFFF are invalid\"`\n        @throw std::invalid_argument if the low surrogate is invalid; example:\n        `\"\"missing or wrong low surrogate\"\"`\n\n        @complexity Constant.\n\n        @see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>\n        */\n        static string_t to_unicode(const std::size_t codepoint1,\n                                   const std::size_t codepoint2 = 0)\n        {\n            // calculate the code point from the given code points\n            std::size_t codepoint = codepoint1;\n\n            // check if codepoint1 is a high surrogate\n            if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)\n            {\n                // check if codepoint2 is a low surrogate\n                if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)\n                {\n                    codepoint =\n                        // high surrogate occupies the most significant 22 bits\n                        (codepoint1 << 10)\n                        // low surrogate occupies the least significant 15 bits\n                        + codepoint2\n                        // there is still the 0xD800, 0xDC00 and 0x10000 noise\n                        // in the result so we have to subtract with:\n                        // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00\n                        - 0x35FDC00;\n                }\n                else\n                {\n                    throw std::invalid_argument(\"missing or wrong low surrogate\");\n                }\n            }\n\n            string_t result;\n\n            if (codepoint < 0x80)\n            {\n                // 1-byte characters: 0xxxxxxx (ASCII)\n                result.append(1, static_cast<typename string_t::value_type>(codepoint));\n            }\n            else if (codepoint <= 0x7ff)\n            {\n                // 2-byte characters: 110xxxxx 10xxxxxx\n                result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));\n                result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));\n            }\n            else if (codepoint <= 0xffff)\n            {\n                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx\n                result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));\n                result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));\n                result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));\n            }\n            else if (codepoint <= 0x10ffff)\n            {\n                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n                result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));\n                result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));\n                result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));\n                result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));\n            }\n            else\n            {\n                throw std::out_of_range(\"code points above 0x10FFFF are invalid\");\n            }\n\n            return result;\n        }\n\n        /// return name of values of type token_type (only used for errors)\n        static std::string token_type_name(const token_type t)\n        {\n            switch (t)\n            {\n                case token_type::uninitialized:\n                    return \"<uninitialized>\";\n                case token_type::literal_true:\n                    return \"true literal\";\n                case token_type::literal_false:\n                    return \"false literal\";\n                case token_type::literal_null:\n                    return \"null literal\";\n                case token_type::value_string:\n                    return \"string literal\";\n                case token_type::value_number:\n                    return \"number literal\";\n                case token_type::begin_array:\n                    return \"'['\";\n                case token_type::begin_object:\n                    return \"'{'\";\n                case token_type::end_array:\n                    return \"']'\";\n                case token_type::end_object:\n                    return \"'}'\";\n                case token_type::name_separator:\n                    return \"':'\";\n                case token_type::value_separator:\n                    return \"','\";\n                case token_type::parse_error:\n                    return \"<parse error>\";\n                case token_type::end_of_input:\n                    return \"end of input\";\n                default:\n                {\n                    // catch non-enum values\n                    return \"unknown token\"; // LCOV_EXCL_LINE\n                }\n            }\n        }\n\n        /*!\n        This function implements a scanner for JSON. It is specified using\n        regular expressions that try to follow RFC 7159 as close as possible.\n        These regular expressions are then translated into a minimized\n        deterministic finite automaton (DFA) by the tool\n        [re2c](http://re2c.org). As a result, the translated code for this\n        function consists of a large block of code with `goto` jumps.\n\n        @return the class of the next token read from the buffer\n\n        @complexity Linear in the length of the input.\\n\n\n        Proposition: The loop below will always terminate for finite input.\\n\n\n        Proof (by contradiction): Assume a finite input. To loop forever, the\n        loop must never hit code with a `break` statement. The only code\n        snippets without a `break` statement are the continue statements for\n        whitespace and byte-order-marks. To loop forever, the input must be an\n        infinite sequence of whitespace or byte-order-marks. This contradicts\n        the assumption of finite input, q.e.d.\n        */\n        token_type scan() noexcept\n        {\n            while (true)\n            {\n                // pointer for backtracking information\n                m_marker = nullptr;\n\n                // remember the begin of the token\n                m_start = m_cursor;\n                assert(m_start != nullptr);\n\n\n                {\n                    lexer_char_t yych;\n                    unsigned int yyaccept = 0;\n                    static const unsigned char yybm[] =\n                    {\n                        0,   0,   0,   0,   0,   0,   0,   0,\n                        0,  32,  32,   0,   0,  32,   0,   0,\n                        0,   0,   0,   0,   0,   0,   0,   0,\n                        0,   0,   0,   0,   0,   0,   0,   0,\n                        160, 128,   0, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        192, 192, 192, 192, 192, 192, 192, 192,\n                        192, 192, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128,   0, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                        128, 128, 128, 128, 128, 128, 128, 128,\n                    };\n                    if ((m_limit - m_cursor) < 5)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yybm[0 + yych] & 32)\n                    {\n                        goto basic_json_parser_6;\n                    }\n                    if (yych <= '\\\\')\n                    {\n                        if (yych <= '-')\n                        {\n                            if (yych <= '\"')\n                            {\n                                if (yych <= 0x00)\n                                {\n                                    goto basic_json_parser_2;\n                                }\n                                if (yych <= '!')\n                                {\n                                    goto basic_json_parser_4;\n                                }\n                                goto basic_json_parser_9;\n                            }\n                            else\n                            {\n                                if (yych <= '+')\n                                {\n                                    goto basic_json_parser_4;\n                                }\n                                if (yych <= ',')\n                                {\n                                    goto basic_json_parser_10;\n                                }\n                                goto basic_json_parser_12;\n                            }\n                        }\n                        else\n                        {\n                            if (yych <= '9')\n                            {\n                                if (yych <= '/')\n                                {\n                                    goto basic_json_parser_4;\n                                }\n                                if (yych <= '0')\n                                {\n                                    goto basic_json_parser_13;\n                                }\n                                goto basic_json_parser_15;\n                            }\n                            else\n                            {\n                                if (yych <= ':')\n                                {\n                                    goto basic_json_parser_17;\n                                }\n                                if (yych == '[')\n                                {\n                                    goto basic_json_parser_19;\n                                }\n                                goto basic_json_parser_4;\n                            }\n                        }\n                    }\n                    else\n                    {\n                        if (yych <= 't')\n                        {\n                            if (yych <= 'f')\n                            {\n                                if (yych <= ']')\n                                {\n                                    goto basic_json_parser_21;\n                                }\n                                if (yych <= 'e')\n                                {\n                                    goto basic_json_parser_4;\n                                }\n                                goto basic_json_parser_23;\n                            }\n                            else\n                            {\n                                if (yych == 'n')\n                                {\n                                    goto basic_json_parser_24;\n                                }\n                                if (yych <= 's')\n                                {\n                                    goto basic_json_parser_4;\n                                }\n                                goto basic_json_parser_25;\n                            }\n                        }\n                        else\n                        {\n                            if (yych <= '|')\n                            {\n                                if (yych == '{')\n                                {\n                                    goto basic_json_parser_26;\n                                }\n                                goto basic_json_parser_4;\n                            }\n                            else\n                            {\n                                if (yych <= '}')\n                                {\n                                    goto basic_json_parser_28;\n                                }\n                                if (yych == 0xEF)\n                                {\n                                    goto basic_json_parser_30;\n                                }\n                                goto basic_json_parser_4;\n                            }\n                        }\n                    }\nbasic_json_parser_2:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::end_of_input;\n                        break;\n                    }\nbasic_json_parser_4:\n                    ++m_cursor;\nbasic_json_parser_5:\n                    {\n                        last_token_type = token_type::parse_error;\n                        break;\n                    }\nbasic_json_parser_6:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yybm[0 + yych] & 32)\n                    {\n                        goto basic_json_parser_6;\n                    }\n                    {\n                        continue;\n                    }\nbasic_json_parser_9:\n                    yyaccept = 0;\n                    yych = *(m_marker = ++m_cursor);\n                    if (yych <= 0x1F)\n                    {\n                        goto basic_json_parser_5;\n                    }\n                    goto basic_json_parser_32;\nbasic_json_parser_10:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::value_separator;\n                        break;\n                    }\nbasic_json_parser_12:\n                    yych = *++m_cursor;\n                    if (yych <= '/')\n                    {\n                        goto basic_json_parser_5;\n                    }\n                    if (yych <= '0')\n                    {\n                        goto basic_json_parser_13;\n                    }\n                    if (yych <= '9')\n                    {\n                        goto basic_json_parser_15;\n                    }\n                    goto basic_json_parser_5;\nbasic_json_parser_13:\n                    yyaccept = 1;\n                    yych = *(m_marker = ++m_cursor);\n                    if (yych <= 'D')\n                    {\n                        if (yych == '.')\n                        {\n                            goto basic_json_parser_37;\n                        }\n                    }\n                    else\n                    {\n                        if (yych <= 'E')\n                        {\n                            goto basic_json_parser_38;\n                        }\n                        if (yych == 'e')\n                        {\n                            goto basic_json_parser_38;\n                        }\n                    }\nbasic_json_parser_14:\n                    {\n                        last_token_type = token_type::value_number;\n                        break;\n                    }\nbasic_json_parser_15:\n                    yyaccept = 1;\n                    m_marker = ++m_cursor;\n                    if ((m_limit - m_cursor) < 3)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yybm[0 + yych] & 64)\n                    {\n                        goto basic_json_parser_15;\n                    }\n                    if (yych <= 'D')\n                    {\n                        if (yych == '.')\n                        {\n                            goto basic_json_parser_37;\n                        }\n                        goto basic_json_parser_14;\n                    }\n                    else\n                    {\n                        if (yych <= 'E')\n                        {\n                            goto basic_json_parser_38;\n                        }\n                        if (yych == 'e')\n                        {\n                            goto basic_json_parser_38;\n                        }\n                        goto basic_json_parser_14;\n                    }\nbasic_json_parser_17:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::name_separator;\n                        break;\n                    }\nbasic_json_parser_19:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::begin_array;\n                        break;\n                    }\nbasic_json_parser_21:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::end_array;\n                        break;\n                    }\nbasic_json_parser_23:\n                    yyaccept = 0;\n                    yych = *(m_marker = ++m_cursor);\n                    if (yych == 'a')\n                    {\n                        goto basic_json_parser_39;\n                    }\n                    goto basic_json_parser_5;\nbasic_json_parser_24:\n                    yyaccept = 0;\n                    yych = *(m_marker = ++m_cursor);\n                    if (yych == 'u')\n                    {\n                        goto basic_json_parser_40;\n                    }\n                    goto basic_json_parser_5;\nbasic_json_parser_25:\n                    yyaccept = 0;\n                    yych = *(m_marker = ++m_cursor);\n                    if (yych == 'r')\n                    {\n                        goto basic_json_parser_41;\n                    }\n                    goto basic_json_parser_5;\nbasic_json_parser_26:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::begin_object;\n                        break;\n                    }\nbasic_json_parser_28:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::end_object;\n                        break;\n                    }\nbasic_json_parser_30:\n                    yyaccept = 0;\n                    yych = *(m_marker = ++m_cursor);\n                    if (yych == 0xBB)\n                    {\n                        goto basic_json_parser_42;\n                    }\n                    goto basic_json_parser_5;\nbasic_json_parser_31:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\nbasic_json_parser_32:\n                    if (yybm[0 + yych] & 128)\n                    {\n                        goto basic_json_parser_31;\n                    }\n                    if (yych <= 0x1F)\n                    {\n                        goto basic_json_parser_33;\n                    }\n                    if (yych <= '\"')\n                    {\n                        goto basic_json_parser_34;\n                    }\n                    goto basic_json_parser_36;\nbasic_json_parser_33:\n                    m_cursor = m_marker;\n                    if (yyaccept == 0)\n                    {\n                        goto basic_json_parser_5;\n                    }\n                    else\n                    {\n                        goto basic_json_parser_14;\n                    }\nbasic_json_parser_34:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::value_string;\n                        break;\n                    }\nbasic_json_parser_36:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= 'e')\n                    {\n                        if (yych <= '/')\n                        {\n                            if (yych == '\"')\n                            {\n                                goto basic_json_parser_31;\n                            }\n                            if (yych <= '.')\n                            {\n                                goto basic_json_parser_33;\n                            }\n                            goto basic_json_parser_31;\n                        }\n                        else\n                        {\n                            if (yych <= '\\\\')\n                            {\n                                if (yych <= '[')\n                                {\n                                    goto basic_json_parser_33;\n                                }\n                                goto basic_json_parser_31;\n                            }\n                            else\n                            {\n                                if (yych == 'b')\n                                {\n                                    goto basic_json_parser_31;\n                                }\n                                goto basic_json_parser_33;\n                            }\n                        }\n                    }\n                    else\n                    {\n                        if (yych <= 'q')\n                        {\n                            if (yych <= 'f')\n                            {\n                                goto basic_json_parser_31;\n                            }\n                            if (yych == 'n')\n                            {\n                                goto basic_json_parser_31;\n                            }\n                            goto basic_json_parser_33;\n                        }\n                        else\n                        {\n                            if (yych <= 's')\n                            {\n                                if (yych <= 'r')\n                                {\n                                    goto basic_json_parser_31;\n                                }\n                                goto basic_json_parser_33;\n                            }\n                            else\n                            {\n                                if (yych <= 't')\n                                {\n                                    goto basic_json_parser_31;\n                                }\n                                if (yych <= 'u')\n                                {\n                                    goto basic_json_parser_43;\n                                }\n                                goto basic_json_parser_33;\n                            }\n                        }\n                    }\nbasic_json_parser_37:\n                    yych = *++m_cursor;\n                    if (yych <= '/')\n                    {\n                        goto basic_json_parser_33;\n                    }\n                    if (yych <= '9')\n                    {\n                        goto basic_json_parser_44;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_38:\n                    yych = *++m_cursor;\n                    if (yych <= ',')\n                    {\n                        if (yych == '+')\n                        {\n                            goto basic_json_parser_46;\n                        }\n                        goto basic_json_parser_33;\n                    }\n                    else\n                    {\n                        if (yych <= '-')\n                        {\n                            goto basic_json_parser_46;\n                        }\n                        if (yych <= '/')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= '9')\n                        {\n                            goto basic_json_parser_47;\n                        }\n                        goto basic_json_parser_33;\n                    }\nbasic_json_parser_39:\n                    yych = *++m_cursor;\n                    if (yych == 'l')\n                    {\n                        goto basic_json_parser_49;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_40:\n                    yych = *++m_cursor;\n                    if (yych == 'l')\n                    {\n                        goto basic_json_parser_50;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_41:\n                    yych = *++m_cursor;\n                    if (yych == 'u')\n                    {\n                        goto basic_json_parser_51;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_42:\n                    yych = *++m_cursor;\n                    if (yych == 0xBF)\n                    {\n                        goto basic_json_parser_52;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_43:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= '@')\n                    {\n                        if (yych <= '/')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= '9')\n                        {\n                            goto basic_json_parser_54;\n                        }\n                        goto basic_json_parser_33;\n                    }\n                    else\n                    {\n                        if (yych <= 'F')\n                        {\n                            goto basic_json_parser_54;\n                        }\n                        if (yych <= '`')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= 'f')\n                        {\n                            goto basic_json_parser_54;\n                        }\n                        goto basic_json_parser_33;\n                    }\nbasic_json_parser_44:\n                    yyaccept = 1;\n                    m_marker = ++m_cursor;\n                    if ((m_limit - m_cursor) < 3)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= 'D')\n                    {\n                        if (yych <= '/')\n                        {\n                            goto basic_json_parser_14;\n                        }\n                        if (yych <= '9')\n                        {\n                            goto basic_json_parser_44;\n                        }\n                        goto basic_json_parser_14;\n                    }\n                    else\n                    {\n                        if (yych <= 'E')\n                        {\n                            goto basic_json_parser_38;\n                        }\n                        if (yych == 'e')\n                        {\n                            goto basic_json_parser_38;\n                        }\n                        goto basic_json_parser_14;\n                    }\nbasic_json_parser_46:\n                    yych = *++m_cursor;\n                    if (yych <= '/')\n                    {\n                        goto basic_json_parser_33;\n                    }\n                    if (yych >= ':')\n                    {\n                        goto basic_json_parser_33;\n                    }\nbasic_json_parser_47:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= '/')\n                    {\n                        goto basic_json_parser_14;\n                    }\n                    if (yych <= '9')\n                    {\n                        goto basic_json_parser_47;\n                    }\n                    goto basic_json_parser_14;\nbasic_json_parser_49:\n                    yych = *++m_cursor;\n                    if (yych == 's')\n                    {\n                        goto basic_json_parser_55;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_50:\n                    yych = *++m_cursor;\n                    if (yych == 'l')\n                    {\n                        goto basic_json_parser_56;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_51:\n                    yych = *++m_cursor;\n                    if (yych == 'e')\n                    {\n                        goto basic_json_parser_58;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_52:\n                    ++m_cursor;\n                    {\n                        continue;\n                    }\nbasic_json_parser_54:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= '@')\n                    {\n                        if (yych <= '/')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= '9')\n                        {\n                            goto basic_json_parser_60;\n                        }\n                        goto basic_json_parser_33;\n                    }\n                    else\n                    {\n                        if (yych <= 'F')\n                        {\n                            goto basic_json_parser_60;\n                        }\n                        if (yych <= '`')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= 'f')\n                        {\n                            goto basic_json_parser_60;\n                        }\n                        goto basic_json_parser_33;\n                    }\nbasic_json_parser_55:\n                    yych = *++m_cursor;\n                    if (yych == 'e')\n                    {\n                        goto basic_json_parser_61;\n                    }\n                    goto basic_json_parser_33;\nbasic_json_parser_56:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::literal_null;\n                        break;\n                    }\nbasic_json_parser_58:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::literal_true;\n                        break;\n                    }\nbasic_json_parser_60:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= '@')\n                    {\n                        if (yych <= '/')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= '9')\n                        {\n                            goto basic_json_parser_63;\n                        }\n                        goto basic_json_parser_33;\n                    }\n                    else\n                    {\n                        if (yych <= 'F')\n                        {\n                            goto basic_json_parser_63;\n                        }\n                        if (yych <= '`')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= 'f')\n                        {\n                            goto basic_json_parser_63;\n                        }\n                        goto basic_json_parser_33;\n                    }\nbasic_json_parser_61:\n                    ++m_cursor;\n                    {\n                        last_token_type = token_type::literal_false;\n                        break;\n                    }\nbasic_json_parser_63:\n                    ++m_cursor;\n                    if (m_limit <= m_cursor)\n                    {\n                        yyfill();\n                    }\n                    yych = *m_cursor;\n                    if (yych <= '@')\n                    {\n                        if (yych <= '/')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= '9')\n                        {\n                            goto basic_json_parser_31;\n                        }\n                        goto basic_json_parser_33;\n                    }\n                    else\n                    {\n                        if (yych <= 'F')\n                        {\n                            goto basic_json_parser_31;\n                        }\n                        if (yych <= '`')\n                        {\n                            goto basic_json_parser_33;\n                        }\n                        if (yych <= 'f')\n                        {\n                            goto basic_json_parser_31;\n                        }\n                        goto basic_json_parser_33;\n                    }\n                }\n\n            }\n\n            return last_token_type;\n        }\n\n        /// append data from the stream to the internal buffer\n        void yyfill() noexcept\n        {\n            if (m_stream == nullptr or not * m_stream)\n            {\n                return;\n            }\n\n            const auto offset_start = m_start - m_content;\n            const auto offset_marker = m_marker - m_start;\n            const auto offset_cursor = m_cursor - m_start;\n\n            m_buffer.erase(0, static_cast<size_t>(offset_start));\n            std::string line;\n            assert(m_stream != nullptr);\n            std::getline(*m_stream, line);\n            m_buffer += \"\\n\" + line; // add line with newline symbol\n\n            m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());\n            assert(m_content != nullptr);\n            m_start  = m_content;\n            m_marker = m_start + offset_marker;\n            m_cursor = m_start + offset_cursor;\n            m_limit  = m_start + m_buffer.size() - 1;\n        }\n\n        /// return string representation of last read token\n        string_t get_token_string() const\n        {\n            assert(m_start != nullptr);\n            return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),\n                            static_cast<size_t>(m_cursor - m_start));\n        }\n\n        /*!\n        @brief return string value for string tokens\n\n        The function iterates the characters between the opening and closing\n        quotes of the string value. The complete string is the range\n        [m_start,m_cursor). Consequently, we iterate from m_start+1 to\n        m_cursor-1.\n\n        We differentiate two cases:\n\n        1. Escaped characters. In this case, a new character is constructed\n           according to the nature of the escape. Some escapes create new\n           characters (e.g., `\"\\\\n\"` is replaced by `\"\\n\"`), some are copied\n           as is (e.g., `\"\\\\\\\\\"`). Furthermore, Unicode escapes of the shape\n           `\"\\\\uxxxx\"` need special care. In this case, to_unicode takes care\n           of the construction of the values.\n        2. Unescaped characters are copied as is.\n\n        @pre `m_cursor - m_start >= 2`, meaning the length of the last token\n        is at least 2 bytes which is trivially true for any string (which\n        consists of at least two quotes).\n\n            \" c1 c2 c3 ... \"\n            ^                ^\n            m_start          m_cursor\n\n        @complexity Linear in the length of the string.\\n\n\n        Lemma: The loop body will always terminate.\\n\n\n        Proof (by contradiction): Assume the loop body does not terminate. As\n        the loop body does not contain another loop, one of the called\n        functions must never return. The called functions are `std::strtoul`\n        and to_unicode. Neither function can loop forever, so the loop body\n        will never loop forever which contradicts the assumption that the loop\n        body does not terminate, q.e.d.\\n\n\n        Lemma: The loop condition for the for loop is eventually false.\\n\n\n        Proof (by contradiction): Assume the loop does not terminate. Due to\n        the above lemma, this can only be due to a tautological loop\n        condition; that is, the loop condition i < m_cursor - 1 must always be\n        true. Let x be the change of i for any loop iteration. Then\n        m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This\n        can be rephrased to m_cursor - m_start - 2 > x. With the\n        precondition, we x <= 0, meaning that the loop condition holds\n        indefinitly if i is always decreased. However, observe that the value\n        of i is strictly increasing with each iteration, as it is incremented\n        by 1 in the iteration expression and never decremented inside the loop\n        body. Hence, the loop condition will eventually be false which\n        contradicts the assumption that the loop condition is a tautology,\n        q.e.d.\n\n        @return string value of current token without opening and closing\n        quotes\n        @throw std::out_of_range if to_unicode fails\n        */\n        string_t get_string() const\n        {\n            assert(m_cursor - m_start >= 2);\n\n            string_t result;\n            result.reserve(static_cast<size_t>(m_cursor - m_start - 2));\n\n            // iterate the result between the quotes\n            for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)\n            {\n                // process escaped characters\n                if (*i == '\\\\')\n                {\n                    // read next character\n                    ++i;\n\n                    switch (*i)\n                    {\n                        // the default escapes\n                        case 't':\n                        {\n                            result += \"\\t\";\n                            break;\n                        }\n                        case 'b':\n                        {\n                            result += \"\\b\";\n                            break;\n                        }\n                        case 'f':\n                        {\n                            result += \"\\f\";\n                            break;\n                        }\n                        case 'n':\n                        {\n                            result += \"\\n\";\n                            break;\n                        }\n                        case 'r':\n                        {\n                            result += \"\\r\";\n                            break;\n                        }\n                        case '\\\\':\n                        {\n                            result += \"\\\\\";\n                            break;\n                        }\n                        case '/':\n                        {\n                            result += \"/\";\n                            break;\n                        }\n                        case '\"':\n                        {\n                            result += \"\\\"\";\n                            break;\n                        }\n\n                        // unicode\n                        case 'u':\n                        {\n                            // get code xxxx from uxxxx\n                            auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),\n                                                          4).c_str(), nullptr, 16);\n\n                            // check if codepoint is a high surrogate\n                            if (codepoint >= 0xD800 and codepoint <= 0xDBFF)\n                            {\n                                // make sure there is a subsequent unicode\n                                if ((i + 6 >= m_limit) or * (i + 5) != '\\\\' or * (i + 6) != 'u')\n                                {\n                                    throw std::invalid_argument(\"missing low surrogate\");\n                                }\n\n                                // get code yyyy from uxxxx\\uyyyy\n                                auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>\n                                                               (i + 7), 4).c_str(), nullptr, 16);\n                                result += to_unicode(codepoint, codepoint2);\n                                // skip the next 10 characters (xxxx\\uyyyy)\n                                i += 10;\n                            }\n                            else\n                            {\n                                // add unicode character(s)\n                                result += to_unicode(codepoint);\n                                // skip the next four characters (xxxx)\n                                i += 4;\n                            }\n                            break;\n                        }\n                    }\n                }\n                else\n                {\n                    // all other characters are just copied to the end of the\n                    // string\n                    result.append(1, static_cast<typename string_t::value_type>(*i));\n                }\n            }\n\n            return result;\n        }\n\n        /*!\n        @brief parse floating point number\n\n        This function (and its overloads) serves to select the most approprate\n        standard floating point number parsing function based on the type\n        supplied via the first parameter.  Set this to @a\n        static_cast<number_float_t*>(nullptr).\n\n        @param[in] type  the @ref number_float_t in use\n\n        @param[in,out] endptr recieves a pointer to the first character after\n        the number\n\n        @return the floating point number\n        */\n        long double str_to_float_t(long double* /* type */, char** endptr) const\n        {\n            return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);\n        }\n\n        /*!\n        @brief parse floating point number\n\n        This function (and its overloads) serves to select the most approprate\n        standard floating point number parsing function based on the type\n        supplied via the first parameter.  Set this to @a\n        static_cast<number_float_t*>(nullptr).\n\n        @param[in] type  the @ref number_float_t in use\n\n        @param[in,out] endptr  recieves a pointer to the first character after\n        the number\n\n        @return the floating point number\n        */\n        double str_to_float_t(double* /* type */, char** endptr) const\n        {\n            return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);\n        }\n\n        /*!\n        @brief parse floating point number\n\n        This function (and its overloads) serves to select the most approprate\n        standard floating point number parsing function based on the type\n        supplied via the first parameter.  Set this to @a\n        static_cast<number_float_t*>(nullptr).\n\n        @param[in] type  the @ref number_float_t in use\n\n        @param[in,out] endptr  recieves a pointer to the first character after\n        the number\n\n        @return the floating point number\n        */\n        float str_to_float_t(float* /* type */, char** endptr) const\n        {\n            return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);\n        }\n\n        /*!\n        @brief return number value for number tokens\n\n        This function translates the last token into the most appropriate\n        number type (either integer, unsigned integer or floating point),\n        which is passed back to the caller via the result parameter.\n\n        This function parses the integer component up to the radix point or\n        exponent while collecting information about the 'floating point\n        representation', which it stores in the result parameter. If there is\n        no radix point or exponent, and the number can fit into a @ref\n        number_integer_t or @ref number_unsigned_t then it sets the result\n        parameter accordingly.\n\n        If the number is a floating point number the number is then parsed\n        using @a std:strtod (or @a std:strtof or @a std::strtold).\n\n        @param[out] result  @ref basic_json object to receive the number, or\n        NAN if the conversion read past the current token. The latter case\n        needs to be treated by the caller function.\n        */\n        void get_number(basic_json& result) const\n        {\n            assert(m_start != nullptr);\n\n            const lexer::lexer_char_t* curptr = m_start;\n\n            // accumulate the integer conversion result (unsigned for now)\n            number_unsigned_t value = 0;\n\n            // maximum absolute value of the relevant integer type\n            number_unsigned_t max;\n\n            // temporarily store the type to avoid unecessary bitfield access\n            value_t type;\n\n            // look for sign\n            if (*curptr == '-')\n            {\n                type = value_t::number_integer;\n                max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;\n                curptr++;\n            }\n            else\n            {\n                type = value_t::number_unsigned;\n                max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());\n            }\n\n            // count the significant figures\n            for (; curptr < m_cursor; curptr++)\n            {\n                // quickly skip tests if a digit\n                if (*curptr < '0' || *curptr > '9')\n                {\n                    if (*curptr == '.')\n                    {\n                        // don't count '.' but change to float\n                        type = value_t::number_float;\n                        continue;\n                    }\n                    // assume exponent (if not then will fail parse): change to\n                    // float, stop counting and record exponent details\n                    type = value_t::number_float;\n                    break;\n                }\n\n                // skip if definitely not an integer\n                if (type != value_t::number_float)\n                {\n                    // multiply last value by ten and add the new digit\n                    auto temp = value * 10 + *curptr - '0';\n\n                    // test for overflow\n                    if (temp < value || temp > max)\n                    {\n                        // overflow\n                        type = value_t::number_float;\n                    }\n                    else\n                    {\n                        // no overflow - save it\n                        value = temp;\n                    }\n                }\n            }\n\n            // save the value (if not a float)\n            if (type == value_t::number_unsigned)\n            {\n                result.m_value.number_unsigned = value;\n            }\n            else if (type == value_t::number_integer)\n            {\n                result.m_value.number_integer = -static_cast<number_integer_t>(value);\n            }\n            else\n            {\n                // parse with strtod\n                result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);\n            }\n\n            // save the type\n            result.m_type = type;\n        }\n\n      private:\n        /// optional input stream\n        std::istream* m_stream = nullptr;\n        /// the buffer\n        string_t m_buffer;\n        /// the buffer pointer\n        const lexer_char_t* m_content = nullptr;\n        /// pointer to the beginning of the current symbol\n        const lexer_char_t* m_start = nullptr;\n        /// pointer for backtracking information\n        const lexer_char_t* m_marker = nullptr;\n        /// pointer to the current symbol\n        const lexer_char_t* m_cursor = nullptr;\n        /// pointer to the end of the buffer\n        const lexer_char_t* m_limit = nullptr;\n        /// the last token type\n        token_type last_token_type = token_type::end_of_input;\n    };\n\n    /*!\n    @brief syntax analysis\n\n    This class implements a recursive decent parser.\n    */\n    class parser\n    {\n      public:\n        /// constructor for strings\n        parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept\n            : callback(cb), m_lexer(s)\n        {\n            // read first token\n            get_token();\n        }\n\n        /// a parser reading from an input stream\n        parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept\n            : callback(cb), m_lexer(&_is)\n        {\n            // read first token\n            get_token();\n        }\n\n        /// public parser interface\n        basic_json parse()\n        {\n            basic_json result = parse_internal(true);\n            result.assert_invariant();\n\n            expect(lexer::token_type::end_of_input);\n\n            // return parser result and replace it with null in case the\n            // top-level value was discarded by the callback function\n            return result.is_discarded() ? basic_json() : std::move(result);\n        }\n\n      private:\n        /// the actual parser\n        basic_json parse_internal(bool keep)\n        {\n            auto result = basic_json(value_t::discarded);\n\n            switch (last_token)\n            {\n                case lexer::token_type::begin_object:\n                {\n                    if (keep and (not callback\n                                  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))\n                    {\n                        // explicitly set result to object to cope with {}\n                        result.m_type = value_t::object;\n                        result.m_value = value_t::object;\n                    }\n\n                    // read next token\n                    get_token();\n\n                    // closing } -> we are done\n                    if (last_token == lexer::token_type::end_object)\n                    {\n                        get_token();\n                        if (keep and callback and not callback(--depth, parse_event_t::object_end, result))\n                        {\n                            result = basic_json(value_t::discarded);\n                        }\n                        return result;\n                    }\n\n                    // no comma is expected here\n                    unexpect(lexer::token_type::value_separator);\n\n                    // otherwise: parse key-value pairs\n                    do\n                    {\n                        // ugly, but could be fixed with loop reorganization\n                        if (last_token == lexer::token_type::value_separator)\n                        {\n                            get_token();\n                        }\n\n                        // store key\n                        expect(lexer::token_type::value_string);\n                        const auto key = m_lexer.get_string();\n\n                        bool keep_tag = false;\n                        if (keep)\n                        {\n                            if (callback)\n                            {\n                                basic_json k(key);\n                                keep_tag = callback(depth, parse_event_t::key, k);\n                            }\n                            else\n                            {\n                                keep_tag = true;\n                            }\n                        }\n\n                        // parse separator (:)\n                        get_token();\n                        expect(lexer::token_type::name_separator);\n\n                        // parse and add value\n                        get_token();\n                        auto value = parse_internal(keep);\n                        if (keep and keep_tag and not value.is_discarded())\n                        {\n                            result[key] = std::move(value);\n                        }\n                    }\n                    while (last_token == lexer::token_type::value_separator);\n\n                    // closing }\n                    expect(lexer::token_type::end_object);\n                    get_token();\n                    if (keep and callback and not callback(--depth, parse_event_t::object_end, result))\n                    {\n                        result = basic_json(value_t::discarded);\n                    }\n\n                    return result;\n                }\n\n                case lexer::token_type::begin_array:\n                {\n                    if (keep and (not callback\n                                  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))\n                    {\n                        // explicitly set result to object to cope with []\n                        result.m_type = value_t::array;\n                        result.m_value = value_t::array;\n                    }\n\n                    // read next token\n                    get_token();\n\n                    // closing ] -> we are done\n                    if (last_token == lexer::token_type::end_array)\n                    {\n                        get_token();\n                        if (callback and not callback(--depth, parse_event_t::array_end, result))\n                        {\n                            result = basic_json(value_t::discarded);\n                        }\n                        return result;\n                    }\n\n                    // no comma is expected here\n                    unexpect(lexer::token_type::value_separator);\n\n                    // otherwise: parse values\n                    do\n                    {\n                        // ugly, but could be fixed with loop reorganization\n                        if (last_token == lexer::token_type::value_separator)\n                        {\n                            get_token();\n                        }\n\n                        // parse value\n                        auto value = parse_internal(keep);\n                        if (keep and not value.is_discarded())\n                        {\n                            result.push_back(std::move(value));\n                        }\n                    }\n                    while (last_token == lexer::token_type::value_separator);\n\n                    // closing ]\n                    expect(lexer::token_type::end_array);\n                    get_token();\n                    if (keep and callback and not callback(--depth, parse_event_t::array_end, result))\n                    {\n                        result = basic_json(value_t::discarded);\n                    }\n\n                    return result;\n                }\n\n                case lexer::token_type::literal_null:\n                {\n                    get_token();\n                    result.m_type = value_t::null;\n                    break;\n                }\n\n                case lexer::token_type::value_string:\n                {\n                    const auto s = m_lexer.get_string();\n                    get_token();\n                    result = basic_json(s);\n                    break;\n                }\n\n                case lexer::token_type::literal_true:\n                {\n                    get_token();\n                    result.m_type = value_t::boolean;\n                    result.m_value = true;\n                    break;\n                }\n\n                case lexer::token_type::literal_false:\n                {\n                    get_token();\n                    result.m_type = value_t::boolean;\n                    result.m_value = false;\n                    break;\n                }\n\n                case lexer::token_type::value_number:\n                {\n                    m_lexer.get_number(result);\n                    get_token();\n                    break;\n                }\n\n                default:\n                {\n                    // the last token was unexpected\n                    unexpect(last_token);\n                }\n            }\n\n            if (keep and callback and not callback(depth, parse_event_t::value, result))\n            {\n                result = basic_json(value_t::discarded);\n            }\n            return result;\n        }\n\n        /// get next token from lexer\n        typename lexer::token_type get_token() noexcept\n        {\n            last_token = m_lexer.scan();\n            return last_token;\n        }\n\n        void expect(typename lexer::token_type t) const\n        {\n            if (t != last_token)\n            {\n                std::string error_msg = \"parse error - unexpected \";\n                error_msg += (last_token == lexer::token_type::parse_error ? (\"'\" +  m_lexer.get_token_string() +\n                              \"'\") :\n                              lexer::token_type_name(last_token));\n                error_msg += \"; expected \" + lexer::token_type_name(t);\n                throw std::invalid_argument(error_msg);\n            }\n        }\n\n        void unexpect(typename lexer::token_type t) const\n        {\n            if (t == last_token)\n            {\n                std::string error_msg = \"parse error - unexpected \";\n                error_msg += (last_token == lexer::token_type::parse_error ? (\"'\" +  m_lexer.get_token_string() +\n                              \"'\") :\n                              lexer::token_type_name(last_token));\n                throw std::invalid_argument(error_msg);\n            }\n        }\n\n      private:\n        /// current level of recursion\n        int depth = 0;\n        /// callback function\n        const parser_callback_t callback = nullptr;\n        /// the type of the last read token\n        typename lexer::token_type last_token = lexer::token_type::uninitialized;\n        /// the lexer\n        lexer m_lexer;\n    };\n\n  public:\n    /*!\n    @brief JSON Pointer\n\n    A JSON pointer defines a string syntax for identifying a specific value\n    within a JSON document. It can be used with functions `at` and\n    `operator[]`. Furthermore, JSON pointers are the base for JSON patches.\n\n    @sa [RFC 6901](https://tools.ietf.org/html/rfc6901)\n\n    @since version 2.0.0\n    */\n    class json_pointer\n    {\n        /// allow basic_json to access private members\n        friend class basic_json;\n\n      public:\n        /*!\n        @brief create JSON pointer\n\n        Create a JSON pointer according to the syntax described in\n        [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).\n\n        @param[in] s  string representing the JSON pointer; if omitted, the\n                      empty string is assumed which references the whole JSON\n                      value\n\n        @throw std::domain_error if reference token is nonempty and does not\n        begin with a slash (`/`); example: `\"JSON pointer must be empty or\n        begin with /\"`\n        @throw std::domain_error if a tilde (`~`) is not followed by `0`\n        (representing `~`) or `1` (representing `/`); example: `\"escape error:\n        ~ must be followed with 0 or 1\"`\n\n        @liveexample{The example shows the construction several valid JSON\n        pointers as well as the exceptional behavior.,json_pointer}\n\n        @since version 2.0.0\n        */\n        explicit json_pointer(const std::string& s = \"\")\n            : reference_tokens(split(s))\n        {}\n\n        /*!\n        @brief return a string representation of the JSON pointer\n\n        @invariant For each JSON pointer `ptr`, it holds:\n        @code {.cpp}\n        ptr == json_pointer(ptr.to_string());\n        @endcode\n\n        @return a string representation of the JSON pointer\n\n        @liveexample{The example shows the result of `to_string`.,\n        json_pointer__to_string}\n\n        @since version 2.0.0\n        */\n        std::string to_string() const noexcept\n        {\n            return std::accumulate(reference_tokens.begin(),\n                                   reference_tokens.end(), std::string{},\n                                   [](const std::string & a, const std::string & b)\n            {\n                return a + \"/\" + escape(b);\n            });\n        }\n\n        /// @copydoc to_string()\n        operator std::string() const\n        {\n            return to_string();\n        }\n\n      private:\n        /// remove and return last reference pointer\n        std::string pop_back()\n        {\n            if (is_root())\n            {\n                throw std::domain_error(\"JSON pointer has no parent\");\n            }\n\n            auto last = reference_tokens.back();\n            reference_tokens.pop_back();\n            return last;\n        }\n\n        /// return whether pointer points to the root document\n        bool is_root() const\n        {\n            return reference_tokens.empty();\n        }\n\n        json_pointer top() const\n        {\n            if (is_root())\n            {\n                throw std::domain_error(\"JSON pointer has no parent\");\n            }\n\n            json_pointer result = *this;\n            result.reference_tokens = {reference_tokens[0]};\n            return result;\n        }\n\n        /*!\n        @brief create and return a reference to the pointed to value\n\n        @complexity Linear in the number of reference tokens.\n        */\n        reference get_and_create(reference j) const\n        {\n            pointer result = &j;\n\n            // in case no reference tokens exist, return a reference to the\n            // JSON value j which will be overwritten by a primitive value\n            for (const auto& reference_token : reference_tokens)\n            {\n                switch (result->m_type)\n                {\n                    case value_t::null:\n                    {\n                        if (reference_token == \"0\")\n                        {\n                            // start a new array if reference token is 0\n                            result = &result->operator[](0);\n                        }\n                        else\n                        {\n                            // start a new object otherwise\n                            result = &result->operator[](reference_token);\n                        }\n                        break;\n                    }\n\n                    case value_t::object:\n                    {\n                        // create an entry in the object\n                        result = &result->operator[](reference_token);\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        // create an entry in the array\n                        result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));\n                        break;\n                    }\n\n                    /*\n                    The following code is only reached if there exists a\n                    reference token _and_ the current value is primitive. In\n                    this case, we have an error situation, because primitive\n                    values may only occur as single value; that is, with an\n                    empty list of reference tokens.\n                    */\n                    default:\n                    {\n                        throw std::domain_error(\"invalid value to unflatten\");\n                    }\n                }\n            }\n\n            return *result;\n        }\n\n        /*!\n        @brief return a reference to the pointed to value\n\n        @param[in] ptr  a JSON value\n\n        @return reference to the JSON value pointed to by the JSON pointer\n\n        @complexity Linear in the length of the JSON pointer.\n\n        @throw std::out_of_range      if the JSON pointer can not be resolved\n        @throw std::domain_error      if an array index begins with '0'\n        @throw std::invalid_argument  if an array index was not a number\n        */\n        reference get_unchecked(pointer ptr) const\n        {\n            for (const auto& reference_token : reference_tokens)\n            {\n                switch (ptr->m_type)\n                {\n                    case value_t::object:\n                    {\n                        // use unchecked object access\n                        ptr = &ptr->operator[](reference_token);\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        // error condition (cf. RFC 6901, Sect. 4)\n                        if (reference_token.size() > 1 and reference_token[0] == '0')\n                        {\n                            throw std::domain_error(\"array index must not begin with '0'\");\n                        }\n\n                        if (reference_token == \"-\")\n                        {\n                            // explicityly treat \"-\" as index beyond the end\n                            ptr = &ptr->operator[](ptr->m_value.array->size());\n                        }\n                        else\n                        {\n                            // convert array index to number; unchecked access\n                            ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));\n                        }\n                        break;\n                    }\n\n                    default:\n                    {\n                        throw std::out_of_range(\"unresolved reference token '\" + reference_token + \"'\");\n                    }\n                }\n            }\n\n            return *ptr;\n        }\n\n        reference get_checked(pointer ptr) const\n        {\n            for (const auto& reference_token : reference_tokens)\n            {\n                switch (ptr->m_type)\n                {\n                    case value_t::object:\n                    {\n                        // note: at performs range check\n                        ptr = &ptr->at(reference_token);\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        if (reference_token == \"-\")\n                        {\n                            // \"-\" always fails the range check\n                            throw std::out_of_range(\"array index '-' (\" +\n                                                    std::to_string(ptr->m_value.array->size()) +\n                                                    \") is out of range\");\n                        }\n\n                        // error condition (cf. RFC 6901, Sect. 4)\n                        if (reference_token.size() > 1 and reference_token[0] == '0')\n                        {\n                            throw std::domain_error(\"array index must not begin with '0'\");\n                        }\n\n                        // note: at performs range check\n                        ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));\n                        break;\n                    }\n\n                    default:\n                    {\n                        throw std::out_of_range(\"unresolved reference token '\" + reference_token + \"'\");\n                    }\n                }\n            }\n\n            return *ptr;\n        }\n\n        /*!\n        @brief return a const reference to the pointed to value\n\n        @param[in] ptr  a JSON value\n\n        @return const reference to the JSON value pointed to by the JSON\n                pointer\n        */\n        const_reference get_unchecked(const_pointer ptr) const\n        {\n            for (const auto& reference_token : reference_tokens)\n            {\n                switch (ptr->m_type)\n                {\n                    case value_t::object:\n                    {\n                        // use unchecked object access\n                        ptr = &ptr->operator[](reference_token);\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        if (reference_token == \"-\")\n                        {\n                            // \"-\" cannot be used for const access\n                            throw std::out_of_range(\"array index '-' (\" +\n                                                    std::to_string(ptr->m_value.array->size()) +\n                                                    \") is out of range\");\n                        }\n\n                        // error condition (cf. RFC 6901, Sect. 4)\n                        if (reference_token.size() > 1 and reference_token[0] == '0')\n                        {\n                            throw std::domain_error(\"array index must not begin with '0'\");\n                        }\n\n                        // use unchecked array access\n                        ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));\n                        break;\n                    }\n\n                    default:\n                    {\n                        throw std::out_of_range(\"unresolved reference token '\" + reference_token + \"'\");\n                    }\n                }\n            }\n\n            return *ptr;\n        }\n\n        const_reference get_checked(const_pointer ptr) const\n        {\n            for (const auto& reference_token : reference_tokens)\n            {\n                switch (ptr->m_type)\n                {\n                    case value_t::object:\n                    {\n                        // note: at performs range check\n                        ptr = &ptr->at(reference_token);\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        if (reference_token == \"-\")\n                        {\n                            // \"-\" always fails the range check\n                            throw std::out_of_range(\"array index '-' (\" +\n                                                    std::to_string(ptr->m_value.array->size()) +\n                                                    \") is out of range\");\n                        }\n\n                        // error condition (cf. RFC 6901, Sect. 4)\n                        if (reference_token.size() > 1 and reference_token[0] == '0')\n                        {\n                            throw std::domain_error(\"array index must not begin with '0'\");\n                        }\n\n                        // note: at performs range check\n                        ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));\n                        break;\n                    }\n\n                    default:\n                    {\n                        throw std::out_of_range(\"unresolved reference token '\" + reference_token + \"'\");\n                    }\n                }\n            }\n\n            return *ptr;\n        }\n\n        /// split the string input to reference tokens\n        static std::vector<std::string> split(const std::string& reference_string)\n        {\n            std::vector<std::string> result;\n\n            // special case: empty reference string -> no reference tokens\n            if (reference_string.empty())\n            {\n                return result;\n            }\n\n            // check if nonempty reference string begins with slash\n            if (reference_string[0] != '/')\n            {\n                throw std::domain_error(\"JSON pointer must be empty or begin with '/'\");\n            }\n\n            // extract the reference tokens:\n            // - slash: position of the last read slash (or end of string)\n            // - start: position after the previous slash\n            for (\n                // search for the first slash after the first character\n                size_t slash = reference_string.find_first_of(\"/\", 1),\n                // set the beginning of the first reference token\n                start = 1;\n                // we can stop if start == string::npos+1 = 0\n                start != 0;\n                // set the beginning of the next reference token\n                // (will eventually be 0 if slash == std::string::npos)\n                start = slash + 1,\n                // find next slash\n                slash = reference_string.find_first_of(\"/\", start))\n            {\n                // use the text between the beginning of the reference token\n                // (start) and the last slash (slash).\n                auto reference_token = reference_string.substr(start, slash - start);\n\n                // check reference tokens are properly escaped\n                for (size_t pos = reference_token.find_first_of(\"~\");\n                        pos != std::string::npos;\n                        pos = reference_token.find_first_of(\"~\", pos + 1))\n                {\n                    assert(reference_token[pos] == '~');\n\n                    // ~ must be followed by 0 or 1\n                    if (pos == reference_token.size() - 1 or\n                            (reference_token[pos + 1] != '0' and\n                             reference_token[pos + 1] != '1'))\n                    {\n                        throw std::domain_error(\"escape error: '~' must be followed with '0' or '1'\");\n                    }\n                }\n\n                // finally, store the reference token\n                unescape(reference_token);\n                result.push_back(reference_token);\n            }\n\n            return result;\n        }\n\n      private:\n        /*!\n        @brief replace all occurrences of a substring by another string\n\n        @param[in,out] s  the string to manipulate\n        @param[in]     f  the substring to replace with @a t\n        @param[in]     t  the string to replace @a f\n\n        @return The string @a s where all occurrences of @a f are replaced\n                with @a t.\n\n        @pre The search string @a f must not be empty.\n\n        @since version 2.0.0\n        */\n        static void replace_substring(std::string& s,\n                                      const std::string& f,\n                                      const std::string& t)\n        {\n            assert(not f.empty());\n\n            for (\n                size_t pos = s.find(f);         // find first occurrence of f\n                pos != std::string::npos;       // make sure f was found\n                s.replace(pos, f.size(), t),    // replace with t\n                pos = s.find(f, pos + t.size()) // find next occurrence of f\n            );\n        }\n\n        /// escape tilde and slash\n        static std::string escape(std::string s)\n        {\n            // escape \"~\"\" to \"~0\" and \"/\" to \"~1\"\n            replace_substring(s, \"~\", \"~0\");\n            replace_substring(s, \"/\", \"~1\");\n            return s;\n        }\n\n        /// unescape tilde and slash\n        static void unescape(std::string& s)\n        {\n            // first transform any occurrence of the sequence '~1' to '/'\n            replace_substring(s, \"~1\", \"/\");\n            // then transform any occurrence of the sequence '~0' to '~'\n            replace_substring(s, \"~0\", \"~\");\n        }\n\n        /*!\n        @param[in] reference_string  the reference string to the current value\n        @param[in] value             the value to consider\n        @param[in,out] result        the result object to insert values to\n\n        @note Empty objects or arrays are flattened to `null`.\n        */\n        static void flatten(const std::string& reference_string,\n                            const basic_json& value,\n                            basic_json& result)\n        {\n            switch (value.m_type)\n            {\n                case value_t::array:\n                {\n                    if (value.m_value.array->empty())\n                    {\n                        // flatten empty array as null\n                        result[reference_string] = nullptr;\n                    }\n                    else\n                    {\n                        // iterate array and use index as reference string\n                        for (size_t i = 0; i < value.m_value.array->size(); ++i)\n                        {\n                            flatten(reference_string + \"/\" + std::to_string(i),\n                                    value.m_value.array->operator[](i), result);\n                        }\n                    }\n                    break;\n                }\n\n                case value_t::object:\n                {\n                    if (value.m_value.object->empty())\n                    {\n                        // flatten empty object as null\n                        result[reference_string] = nullptr;\n                    }\n                    else\n                    {\n                        // iterate object and use keys as reference string\n                        for (const auto& element : *value.m_value.object)\n                        {\n                            flatten(reference_string + \"/\" + escape(element.first),\n                                    element.second, result);\n                        }\n                    }\n                    break;\n                }\n\n                default:\n                {\n                    // add primitive value with its reference string\n                    result[reference_string] = value;\n                    break;\n                }\n            }\n        }\n\n        /*!\n        @param[in] value  flattened JSON\n\n        @return unflattened JSON\n        */\n        static basic_json unflatten(const basic_json& value)\n        {\n            if (not value.is_object())\n            {\n                throw std::domain_error(\"only objects can be unflattened\");\n            }\n\n            basic_json result;\n\n            // iterate the JSON object values\n            for (const auto& element : *value.m_value.object)\n            {\n                if (not element.second.is_primitive())\n                {\n                    throw std::domain_error(\"values in object must be primitive\");\n                }\n\n                // assign value to reference pointed to by JSON pointer; Note\n                // that if the JSON pointer is \"\" (i.e., points to the whole\n                // value), function get_and_create returns a reference to\n                // result itself. An assignment will then create a primitive\n                // value.\n                json_pointer(element.first).get_and_create(result) = element.second;\n            }\n\n            return result;\n        }\n\n      private:\n        /// the reference tokens\n        std::vector<std::string> reference_tokens {};\n    };\n\n    //////////////////////////\n    // JSON Pointer support //\n    //////////////////////////\n\n    /// @name JSON Pointer functions\n    /// @{\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Uses a JSON pointer to retrieve a reference to the respective JSON value.\n    No bound checking is performed. Similar to @ref operator[](const typename\n    object_t::key_type&), `null` values are created in arrays and objects if\n    necessary.\n\n    In particular:\n    - If the JSON pointer points to an object key that does not exist, it\n      is created an filled with a `null` value before a reference to it\n      is returned.\n    - If the JSON pointer points to an array index that does not exist, it\n      is created an filled with a `null` value before a reference to it\n      is returned. All indices between the current maximum and the given\n      index are also filled with `null`.\n    - The special value `-` is treated as a synonym for the index past the\n      end.\n\n    @param[in] ptr  a JSON pointer\n\n    @return reference to the element pointed to by @a ptr\n\n    @complexity Constant.\n\n    @throw std::out_of_range      if the JSON pointer can not be resolved\n    @throw std::domain_error      if an array index begins with '0'\n    @throw std::invalid_argument  if an array index was not a number\n\n    @liveexample{The behavior is shown in the example.,operatorjson_pointer}\n\n    @since version 2.0.0\n    */\n    reference operator[](const json_pointer& ptr)\n    {\n        return ptr.get_unchecked(this);\n    }\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Uses a JSON pointer to retrieve a reference to the respective JSON value.\n    No bound checking is performed. The function does not change the JSON\n    value; no `null` values are created. In particular, the the special value\n    `-` yields an exception.\n\n    @param[in] ptr  JSON pointer to the desired element\n\n    @return const reference to the element pointed to by @a ptr\n\n    @complexity Constant.\n\n    @throw std::out_of_range      if the JSON pointer can not be resolved\n    @throw std::domain_error      if an array index begins with '0'\n    @throw std::invalid_argument  if an array index was not a number\n\n    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}\n\n    @since version 2.0.0\n    */\n    const_reference operator[](const json_pointer& ptr) const\n    {\n        return ptr.get_unchecked(this);\n    }\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Returns a reference to the element at with specified JSON pointer @a ptr,\n    with bounds checking.\n\n    @param[in] ptr  JSON pointer to the desired element\n\n    @return reference to the element pointed to by @a ptr\n\n    @complexity Constant.\n\n    @throw std::out_of_range      if the JSON pointer can not be resolved\n    @throw std::domain_error      if an array index begins with '0'\n    @throw std::invalid_argument  if an array index was not a number\n\n    @liveexample{The behavior is shown in the example.,at_json_pointer}\n\n    @since version 2.0.0\n    */\n    reference at(const json_pointer& ptr)\n    {\n        return ptr.get_checked(this);\n    }\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Returns a const reference to the element at with specified JSON pointer @a\n    ptr, with bounds checking.\n\n    @param[in] ptr  JSON pointer to the desired element\n\n    @return reference to the element pointed to by @a ptr\n\n    @complexity Constant.\n\n    @throw std::out_of_range      if the JSON pointer can not be resolved\n    @throw std::domain_error      if an array index begins with '0'\n    @throw std::invalid_argument  if an array index was not a number\n\n    @liveexample{The behavior is shown in the example.,at_json_pointer_const}\n\n    @since version 2.0.0\n    */\n    const_reference at(const json_pointer& ptr) const\n    {\n        return ptr.get_checked(this);\n    }\n\n    /*!\n    @brief return flattened JSON value\n\n    The function creates a JSON object whose keys are JSON pointers (see [RFC\n    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all\n    primitive. The original JSON value can be restored using the @ref\n    unflatten() function.\n\n    @return an object that maps JSON pointers to primitve values\n\n    @note Empty objects and arrays are flattened to `null` and will not be\n          reconstructed correctly by the @ref unflatten() function.\n\n    @complexity Linear in the size the JSON value.\n\n    @liveexample{The following code shows how a JSON object is flattened to an\n    object whose keys consist of JSON pointers.,flatten}\n\n    @sa @ref unflatten() for the reverse function\n\n    @since version 2.0.0\n    */\n    basic_json flatten() const\n    {\n        basic_json result(value_t::object);\n        json_pointer::flatten(\"\", *this, result);\n        return result;\n    }\n\n    /*!\n    @brief unflatten a previously flattened JSON value\n\n    The function restores the arbitrary nesting of a JSON value that has been\n    flattened before using the @ref flatten() function. The JSON value must\n    meet certain constraints:\n    1. The value must be an object.\n    2. The keys must be JSON pointers (see\n       [RFC 6901](https://tools.ietf.org/html/rfc6901))\n    3. The mapped values must be primitive JSON types.\n\n    @return the original JSON from a flattened version\n\n    @note Empty objects and arrays are flattened by @ref flatten() to `null`\n          values and can not unflattened to their original type. Apart from\n          this example, for a JSON value `j`, the following is always true:\n          `j == j.flatten().unflatten()`.\n\n    @complexity Linear in the size the JSON value.\n\n    @liveexample{The following code shows how a flattened JSON object is\n    unflattened into the original nested JSON object.,unflatten}\n\n    @sa @ref flatten() for the reverse function\n\n    @since version 2.0.0\n    */\n    basic_json unflatten() const\n    {\n        return json_pointer::unflatten(*this);\n    }\n\n    /// @}\n\n    //////////////////////////\n    // JSON Patch functions //\n    //////////////////////////\n\n    /// @name JSON Patch functions\n    /// @{\n\n    /*!\n    @brief applies a JSON patch\n\n    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for\n    expressing a sequence of operations to apply to a JSON) document. With\n    this funcion, a JSON Patch is applied to the current JSON value by\n    executing all operations from the patch.\n\n    @param[in] json_patch  JSON patch document\n    @return patched document\n\n    @note The application of a patch is atomic: Either all operations succeed\n          and the patched document is returned or an exception is thrown. In\n          any case, the original value is not changed: the patch is applied\n          to a copy of the value.\n\n    @throw std::out_of_range if a JSON pointer inside the patch could not\n    be resolved successfully in the current JSON value; example: `\"key baz\n    not found\"`\n    @throw invalid_argument if the JSON patch is malformed (e.g., mandatory\n    attributes are missing); example: `\"operation add must have member path\"`\n\n    @complexity Linear in the size of the JSON value and the length of the\n    JSON patch. As usually only a fraction of the JSON value is affected by\n    the patch, the complexity can usually be neglected.\n\n    @liveexample{The following code shows how a JSON patch is applied to a\n    value.,patch}\n\n    @sa @ref diff -- create a JSON patch by comparing two JSON values\n\n    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\n    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)\n\n    @since version 2.0.0\n    */\n    basic_json patch(const basic_json& json_patch) const\n    {\n        // make a working copy to apply the patch to\n        basic_json result = *this;\n\n        // the valid JSON Patch operations\n        enum class patch_operations {add, remove, replace, move, copy, test, invalid};\n\n        const auto get_op = [](const std::string op)\n        {\n            if (op == \"add\")\n            {\n                return patch_operations::add;\n            }\n            if (op == \"remove\")\n            {\n                return patch_operations::remove;\n            }\n            if (op == \"replace\")\n            {\n                return patch_operations::replace;\n            }\n            if (op == \"move\")\n            {\n                return patch_operations::move;\n            }\n            if (op == \"copy\")\n            {\n                return patch_operations::copy;\n            }\n            if (op == \"test\")\n            {\n                return patch_operations::test;\n            }\n\n            return patch_operations::invalid;\n        };\n\n        // wrapper for \"add\" operation; add value at ptr\n        const auto operation_add = [&result](json_pointer & ptr, basic_json val)\n        {\n            // adding to the root of the target document means replacing it\n            if (ptr.is_root())\n            {\n                result = val;\n            }\n            else\n            {\n                // make sure the top element of the pointer exists\n                json_pointer top_pointer = ptr.top();\n                if (top_pointer != ptr)\n                {\n                    basic_json& x = result.at(top_pointer);\n                }\n\n                // get reference to parent of JSON pointer ptr\n                const auto last_path = ptr.pop_back();\n                basic_json& parent = result[ptr];\n\n                switch (parent.m_type)\n                {\n                    case value_t::null:\n                    case value_t::object:\n                    {\n                        // use operator[] to add value\n                        parent[last_path] = val;\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        if (last_path == \"-\")\n                        {\n                            // special case: append to back\n                            parent.push_back(val);\n                        }\n                        else\n                        {\n                            const auto idx = std::stoi(last_path);\n                            if (static_cast<size_type>(idx) > parent.size())\n                            {\n                                // avoid undefined behavior\n                                throw std::out_of_range(\"array index \" + std::to_string(idx) + \" is out of range\");\n                            }\n                            else\n                            {\n                                // default case: insert add offset\n                                parent.insert(parent.begin() + static_cast<difference_type>(idx), val);\n                            }\n                        }\n                        break;\n                    }\n\n                    default:\n                    {\n                        // if there exists a parent it cannot be primitive\n                        assert(false);  // LCOV_EXCL_LINE\n                    }\n                }\n            }\n        };\n\n        // wrapper for \"remove\" operation; remove value at ptr\n        const auto operation_remove = [&result](json_pointer & ptr)\n        {\n            // get reference to parent of JSON pointer ptr\n            const auto last_path = ptr.pop_back();\n            basic_json& parent = result.at(ptr);\n\n            // remove child\n            if (parent.is_object())\n            {\n                // perform range check\n                auto it = parent.find(last_path);\n                if (it != parent.end())\n                {\n                    parent.erase(it);\n                }\n                else\n                {\n                    throw std::out_of_range(\"key '\" + last_path + \"' not found\");\n                }\n            }\n            else if (parent.is_array())\n            {\n                // note erase performs range check\n                parent.erase(static_cast<size_type>(std::stoi(last_path)));\n            }\n        };\n\n        // type check\n        if (not json_patch.is_array())\n        {\n            // a JSON patch must be an array of objects\n            throw std::invalid_argument(\"JSON patch must be an array of objects\");\n        }\n\n        // iterate and apply th eoperations\n        for (const auto& val : json_patch)\n        {\n            // wrapper to get a value for an operation\n            const auto get_value = [&val](const std::string & op,\n                                          const std::string & member,\n                                          bool string_type) -> basic_json&\n            {\n                // find value\n                auto it = val.m_value.object->find(member);\n\n                // context-sensitive error message\n                const auto error_msg = (op == \"op\") ? \"operation\" : \"operation '\" + op + \"'\";\n\n                // check if desired value is present\n                if (it == val.m_value.object->end())\n                {\n                    throw std::invalid_argument(error_msg + \" must have member '\" + member + \"'\");\n                }\n\n                // check if result is of type string\n                if (string_type and not it->second.is_string())\n                {\n                    throw std::invalid_argument(error_msg + \" must have string member '\" + member + \"'\");\n                }\n\n                // no error: return value\n                return it->second;\n            };\n\n            // type check\n            if (not val.is_object())\n            {\n                throw std::invalid_argument(\"JSON patch must be an array of objects\");\n            }\n\n            // collect mandatory members\n            const std::string op = get_value(\"op\", \"op\", true);\n            const std::string path = get_value(op, \"path\", true);\n            json_pointer ptr(path);\n\n            switch (get_op(op))\n            {\n                case patch_operations::add:\n                {\n                    operation_add(ptr, get_value(\"add\", \"value\", false));\n                    break;\n                }\n\n                case patch_operations::remove:\n                {\n                    operation_remove(ptr);\n                    break;\n                }\n\n                case patch_operations::replace:\n                {\n                    // the \"path\" location must exist - use at()\n                    result.at(ptr) = get_value(\"replace\", \"value\", false);\n                    break;\n                }\n\n                case patch_operations::move:\n                {\n                    const std::string from_path = get_value(\"move\", \"from\", true);\n                    json_pointer from_ptr(from_path);\n\n                    // the \"from\" location must exist - use at()\n                    basic_json v = result.at(from_ptr);\n\n                    // The move operation is functionally identical to a\n                    // \"remove\" operation on the \"from\" location, followed\n                    // immediately by an \"add\" operation at the target\n                    // location with the value that was just removed.\n                    operation_remove(from_ptr);\n                    operation_add(ptr, v);\n                    break;\n                }\n\n                case patch_operations::copy:\n                {\n                    const std::string from_path = get_value(\"copy\", \"from\", true);;\n                    const json_pointer from_ptr(from_path);\n\n                    // the \"from\" location must exist - use at()\n                    result[ptr] = result.at(from_ptr);\n                    break;\n                }\n\n                case patch_operations::test:\n                {\n                    bool success = false;\n                    try\n                    {\n                        // check if \"value\" matches the one at \"path\"\n                        // the \"path\" location must exist - use at()\n                        success = (result.at(ptr) == get_value(\"test\", \"value\", false));\n                    }\n                    catch (std::out_of_range&)\n                    {\n                        // ignore out of range errors: success remains false\n                    }\n\n                    // throw an exception if test fails\n                    if (not success)\n                    {\n                        throw std::domain_error(\"unsuccessful: \" + val.dump());\n                    }\n\n                    break;\n                }\n\n                case patch_operations::invalid:\n                {\n                    // op must be \"add\", \"remove\", \"replace\", \"move\", \"copy\", or\n                    // \"test\"\n                    throw std::invalid_argument(\"operation value '\" + op + \"' is invalid\");\n                }\n            }\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief creates a diff as a JSON patch\n\n    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can\n    be changed into the value @a target by calling @ref patch function.\n\n    @invariant For two JSON values @a source and @a target, the following code\n    yields always `true`:\n    @code {.cpp}\n    source.patch(diff(source, target)) == target;\n    @endcode\n\n    @note Currently, only `remove`, `add`, and `replace` operations are\n          generated.\n\n    @param[in] source  JSON value to copare from\n    @param[in] target  JSON value to copare against\n    @param[in] path    helper value to create JSON pointers\n\n    @return a JSON patch to convert the @a source to @a target\n\n    @complexity Linear in the lengths of @a source and @a target.\n\n    @liveexample{The following code shows how a JSON patch is created as a\n    diff for two JSON values.,diff}\n\n    @sa @ref patch -- apply a JSON patch\n\n    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\n\n    @since version 2.0.0\n    */\n    static basic_json diff(const basic_json& source,\n                           const basic_json& target,\n                           const std::string& path = \"\")\n    {\n        // the patch\n        basic_json result(value_t::array);\n\n        // if the values are the same, return empty patch\n        if (source == target)\n        {\n            return result;\n        }\n\n        if (source.type() != target.type())\n        {\n            // different types: replace value\n            result.push_back(\n            {\n                {\"op\", \"replace\"},\n                {\"path\", path},\n                {\"value\", target}\n            });\n        }\n        else\n        {\n            switch (source.type())\n            {\n                case value_t::array:\n                {\n                    // first pass: traverse common elements\n                    size_t i = 0;\n                    while (i < source.size() and i < target.size())\n                    {\n                        // recursive call to compare array values at index i\n                        auto temp_diff = diff(source[i], target[i], path + \"/\" + std::to_string(i));\n                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());\n                        ++i;\n                    }\n\n                    // i now reached the end of at least one array\n                    // in a second pass, traverse the remaining elements\n\n                    // remove my remaining elements\n                    const auto end_index = static_cast<difference_type>(result.size());\n                    while (i < source.size())\n                    {\n                        // add operations in reverse order to avoid invalid\n                        // indices\n                        result.insert(result.begin() + end_index, object(\n                        {\n                            {\"op\", \"remove\"},\n                            {\"path\", path + \"/\" + std::to_string(i)}\n                        }));\n                        ++i;\n                    }\n\n                    // add other remaining elements\n                    while (i < target.size())\n                    {\n                        result.push_back(\n                        {\n                            {\"op\", \"add\"},\n                            {\"path\", path + \"/\" + std::to_string(i)},\n                            {\"value\", target[i]}\n                        });\n                        ++i;\n                    }\n\n                    break;\n                }\n\n                case value_t::object:\n                {\n                    // first pass: traverse this object's elements\n                    for (auto it = source.begin(); it != source.end(); ++it)\n                    {\n                        // escape the key name to be used in a JSON patch\n                        const auto key = json_pointer::escape(it.key());\n\n                        if (target.find(it.key()) != target.end())\n                        {\n                            // recursive call to compare object values at key it\n                            auto temp_diff = diff(it.value(), target[it.key()], path + \"/\" + key);\n                            result.insert(result.end(), temp_diff.begin(), temp_diff.end());\n                        }\n                        else\n                        {\n                            // found a key that is not in o -> remove it\n                            result.push_back(object(\n                            {\n                                {\"op\", \"remove\"},\n                                {\"path\", path + \"/\" + key}\n                            }));\n                        }\n                    }\n\n                    // second pass: traverse other object's elements\n                    for (auto it = target.begin(); it != target.end(); ++it)\n                    {\n                        if (source.find(it.key()) == source.end())\n                        {\n                            // found a key that is not in this -> add it\n                            const auto key = json_pointer::escape(it.key());\n                            result.push_back(\n                            {\n                                {\"op\", \"add\"},\n                                {\"path\", path + \"/\" + key},\n                                {\"value\", it.value()}\n                            });\n                        }\n                    }\n\n                    break;\n                }\n\n                default:\n                {\n                    // both primitive type: replace value\n                    result.push_back(\n                    {\n                        {\"op\", \"replace\"},\n                        {\"path\", path},\n                        {\"value\", target}\n                    });\n                    break;\n                }\n            }\n        }\n\n        return result;\n    }\n\n    /// @}\n};\n\n\n/////////////\n// presets //\n/////////////\n\n/*!\n@brief default JSON class\n\nThis type is the default specialization of the @ref basic_json class which\nuses the standard template types.\n\n@since version 1.0.0\n*/\nusing json = basic_json<>;\n}\n\n\n///////////////////////\n// nonmember support //\n///////////////////////\n\n// specialization of std::swap, and std::hash\nnamespace std\n{\n/*!\n@brief exchanges the values of two JSON objects\n\n@since version 1.0.0\n*/\ntemplate <>\ninline void swap(nlohmann::json& j1,\n                 nlohmann::json& j2) noexcept(\n                     is_nothrow_move_constructible<nlohmann::json>::value and\n                     is_nothrow_move_assignable<nlohmann::json>::value\n                 )\n{\n    j1.swap(j2);\n}\n\n/// hash value for JSON objects\ntemplate <>\nstruct hash<nlohmann::json>\n{\n    /*!\n    @brief return a hash value for a JSON object\n\n    @since version 1.0.0\n    */\n    std::size_t operator()(const nlohmann::json& j) const\n    {\n        // a naive hashing via the string representation\n        const auto& h = hash<nlohmann::json::string_t>();\n        return h(j.dump());\n    }\n};\n}\n\n/*!\n@brief user-defined string literal for JSON values\n\nThis operator implements a user-defined string literal for JSON objects. It\ncan be used by adding `\"_json\"` to a string literal and returns a JSON object\nif no parse error occurred.\n\n@param[in] s  a string representation of a JSON object\n@return a JSON object\n\n@since version 1.0.0\n*/\ninline nlohmann::json operator \"\" _json(const char* s, std::size_t)\n{\n    return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));\n}\n\n/*!\n@brief user-defined string literal for JSON pointer\n\nThis operator implements a user-defined string literal for JSON Pointers. It\ncan be used by adding `\"_json\"` to a string literal and returns a JSON pointer\nobject if no parse error occurred.\n\n@param[in] s  a string representation of a JSON Pointer\n@return a JSON pointer object\n\n@since version 2.0.0\n*/\ninline nlohmann::json::json_pointer operator \"\" _json_pointer(const char* s, std::size_t)\n{\n    return nlohmann::json::json_pointer(s);\n}\n\n// restore GCC/clang diagnostic settings\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n    #pragma GCC diagnostic pop\n#endif\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/core/Rsyn.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_H\n#define RSYN_H\n\n#include <cstdint>\n#include <functional>\n#include <array>\n#include <set>\n#include <unordered_set>\n#include <map>\n#include <unordered_map>\n#include <list>\n#include <queue>\n#include <vector>\n#include <bitset>\n#include <memory>\n#include <string>\n#include <sstream>\n#include <limits>\n#include <algorithm>\n#include <type_traits>\n#include <cassert>\n#include <stdexcept>\n\n#include <rsyn/core/RsynTypes.h>\n\n#include <rsyn/core/infra/List.h>\n#include <rsyn/core/infra/RangeBasedLoop.h>\n#include <rsyn/core/infra/Exception.h>\n\n#include <rsyn/util/dbu.h>\n#include <rsyn/util/Bounds.h>\n#include <rsyn/phy/util/PhysicalTransform.h>\n\n#include <rsyn/util/Proxy.h>\n#include <rsyn/util/TristateFlag.h>\n\n#define RSYN_KERNEL\n#define RSYN_LIST_CHUNCK_SIZE 1000\n\n#define RSYN_FRIEND_OF_GENERIC_LIST_COLLECTION \\\ntemplate<class Object, class Reference, unsigned int CHUNK_SIZE> \\\nfriend class GenericListCollection;\n\nnamespace Rsyn {\n\nclass ObjectData;\nclass NetData;\nclass PinData;\nclass ArcData;\nclass InstanceData;\nclass CellData;\nclass PortData;\nclass ModuleData;\nclass LibraryPinData;\nclass LibraryArcData;\nclass LibraryCellData;\nclass LibraryModuleData;\nclass DesignData;\nclass LibraryData;\n\nclass NetTagData;\nclass InstanceTagData;\nclass LibraryCellTagData;\n\nclass Net;\nclass Pin;\nclass Arc;\nclass Instance;\nclass Cell;\nclass Port;\nclass Module;\nclass LibraryPin;\nclass LibraryArc;\nclass LibraryCell;\nclass LibraryModule;\nclass Design;\nclass Library;\n\nclass AttributeInitializer;\ntemplate<typename DefaultValueType> class AttributeInitializerWithDefaultValue;\n\nclass DesignObserver;\n\ntemplate<class Object, class Reference, unsigned int CHUNK_SIZE> class GenericListCollection;\ntemplate<class Reference, unsigned int CHUNK_SIZE> class GenericReferenceListCollection;\n\ntemplate<class Object, class Reference>\nusing ListCollection = GenericListCollection<Object, Reference, RSYN_LIST_CHUNCK_SIZE>;\n\ntemplate<class Reference>\nusing ReferenceListCollection = GenericReferenceListCollection<Reference, RSYN_LIST_CHUNCK_SIZE>;\n\nclass CollectionOfLibraryPinsFilteredByDirection;\nclass CollectionOfLibraryPins;\nclass CollectionOfLibraryArcs;\nclass CollectionOfLibraryArcsToLibraryPin;\nclass CollectionOfLibraryArcsFromLibraryPin;\n\ntemplate<class PinType>\nclass CollectionOfGenericPinsFilteredByDirection;\ntemplate<class PinType>\nclass CollectionOfGenericPins;\ntemplate<class ArcType>\nclass CollectionOfGenericArcs;\ntemplate<class PinType, class NetType, class ArcType>\nclass CollectionOfGenericPredecessorPins;\ntemplate<class PinType, class NetType, class ArcType>\nclass CollectionOfGenericSuccessorPins;\n\ntypedef CollectionOfGenericPinsFilteredByDirection<Pin>\n\t\tCollectionOfPinsFilteredByDirection;\ntypedef CollectionOfGenericPins<Pin>\n\t\tCollectionOfPins;\ntypedef CollectionOfGenericArcs<Arc>\n\t\tCollectionOfArcs;\ntypedef CollectionOfGenericPredecessorPins<Pin, Net, Arc>\n\t\tCollectionOfPredecessorPins;\ntypedef CollectionOfGenericSuccessorPins<Pin, Net, Arc>\n\t\tCollectionOfSuccessorPins;\n\ntypedef std::uint32_t Index;\ntypedef int TopologicalIndex;\n\n// =============================================================================\n// Tags\n// =============================================================================\n\nclass TagNotSpecifiedException : public std::runtime_error {\npublic:\n\tTagNotSpecifiedException(const std::string &tagName) : \n\t\tstd::runtime_error(\"Trying to use the value of the tag '\" + tagName + \"', which was not set.\") {}\n}; // end class\n\nenum LogicTypeTag {\n\tLOGIC_TYPE_TAG_NOT_SPECIFIED,\n\n\tLOGIC_TYPE_TAG_NONE,\n\tLOGIC_TYPE_TAG_COMBINATIONAL,\n\tLOGIC_TYPE_TAG_SEQUENTIAL\n}; // end enum\n\nenum BufferTypeTag {\n\tBUFFER_TYPE_TAG_NOT_SPECIFIED,\n\n\tBUFFER_TYPE_TAG_NONE,\n\tBUFFER_TYPE_TAG_NON_INVERTING,\n\tBUFFER_TYPE_TAG_INVERTING\n}; // end enum\n\nenum TieTypeTag {\n\tTIE_TYPE_TAG_NOT_SPECIFIED,\n\n\tTIE_TYPE_TAG_NONE,\n\tTIE_TYPE_TAG_LOW,\n\tTIE_TYPE_TAG_HIGH\n}; // end enum\n\nenum NetTypeTag {\n\tNET_TYPE_TAG_NOT_SPECIFIED,\n\n\tNET_TYPE_TAG_NONE,\n\tNET_TYPE_TAG_DATA,\n\tNET_TYPE_TAG_CLOCK,\n\tNET_TYPE_TAG_SCAN,\n\tNET_TYPE_TAG_RESET\n}; // end enum\n\n// =============================================================================\n// Events\n// =============================================================================\n\nenum SessionEventType {\n\tEVENT_DESIGN_LOADED,\n\tEVENT_SERVICE_STARTED,\n\n\tNUM_SESSION_EVENTS\n}; // end enum\n\nenum DesignEventType {\n\tEVENT_DESTRUCTION,\n\tEVENT_POST_INSTANCE_CREATE,\n\tEVENT_PRE_INSTANCE_REMOVE,\n\tEVENT_POST_NET_CREATE,\n\tEVENT_PRE_NET_REMOVE,\n\tEVENT_POST_CELL_REMAP,\n\tEVENT_POST_PIN_CONNECT,\n\tEVENT_PRE_PIN_DISCONNECT,\n\tEVENT_POST_INSTANCE_MOVE,\n\n\tNUM_DESIGN_EVENTS\n}; // end enum\n\n// =============================================================================\n// Exception\n// =============================================================================\n\nclass SafeModeException : public Exception {\npublic:\n\tSafeModeException(const std::string &msg) : Exception(msg) {}\n}; // end class\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n// Some constants...\nenum {\n\tTOPOLOGICAL_SORTING_SMALL_GAP = 10,\n\tTOPOLOGICAL_SORTING_LARGE_GAP = 1000\n}; // end enum\n\nstatic const std::string NullName = \"<null>\";\nstatic const TopologicalIndex MIN_TOPOLOGICAL_INDEX =\n\t-std::numeric_limits<TopologicalIndex>::infinity();\n\n} // end namespace\n\n// =============================================================================\n// Descriptors\n// =============================================================================\n\n#include \"rsyn/core/dscp/LibraryCell.h\"\n#include \"rsyn/core/dscp/LibraryModule.h\"\n\n// =============================================================================\n// Global\n// =============================================================================\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\nclass Global {\npublic:\n\t\n\tstatic\n\tconst std::string &\n\tgetDirectionName(const Direction direction) {\n\t\tstatic const std::array<std::string, NUM_SIGNAL_DIRECTIONS> NAMES =\n\t\t\t{ \"UNKNOWN\", \"INPUT\", \"OUTPUT\", \"BIDIRECTIONAL\" };\n\t\treturn NAMES[direction];\n\t} // end method\n\n\tstatic\n\tconst std::string &\n\tgetDirectionShortName(const Direction direction) {\n\t\tstatic const std::array<std::string, NUM_SIGNAL_DIRECTIONS> NAMES =\n\t\t\t{ \"UNKNOWN\", \"IN\", \"OUT\", \"BIDI\" };\n\t\treturn NAMES[direction];\n\t} // end method\n\n\tstatic\n\tconst std::string &\n\tgetDirectionSingleCharName(const Direction direction) {\n\t\tstatic const std::array<std::string, NUM_SIGNAL_DIRECTIONS> NAMES =\n\t\t\t{ \"?\", \"I\", \"O\", \"B\" };\n\t\treturn NAMES[direction];\t\n\t} // end method\n\t\n\tstatic\n\tconst Direction \n\tgetReverseDirection(const Direction direction) {\n\t\tstatic const Direction DIRECTION_REVERSED[NUM_SIGNAL_DIRECTIONS] = {\n\t\t\tUNKNOWN_DIRECTION, OUT, IN, BIDIRECTIONAL };\n\t\treturn DIRECTION_REVERSED[direction];\n\t} // end method\t\n\t\n}; // end class\n\n} // end namespace\n\n// =============================================================================\n// Objects\n// =============================================================================\n\n// Object's Declarations (Proxies)\n#include \"rsyn/core/obj/decl/Object.h\"\n#include \"rsyn/core/obj/decl/Net.h\"\n#include \"rsyn/core/obj/decl/Pin.h\"\n#include \"rsyn/core/obj/decl/Arc.h\"\n#include \"rsyn/core/obj/decl/Instance.h\"\n#include \"rsyn/core/obj/decl/Cell.h\"\n#include \"rsyn/core/obj/decl/Port.h\"\n#include \"rsyn/core/obj/decl/Module.h\"\n#include \"rsyn/core/obj/decl/LibraryPin.h\"\n#include \"rsyn/core/obj/decl/LibraryArc.h\"\n#include \"rsyn/core/obj/decl/LibraryCell.h\"\n#include \"rsyn/core/obj/decl/LibraryModule.h\"\n#include \"rsyn/core/obj/decl/Design.h\"\n#include \"rsyn/core/obj/decl/Library.h\"\n\n// Object's Data\n#include \"rsyn/core/obj/data/Object.h\"\n#include \"rsyn/core/obj/data/Net.h\"\n#include \"rsyn/core/obj/data/Pin.h\"\n#include \"rsyn/core/obj/data/Arc.h\"\n#include \"rsyn/core/obj/data/Instance.h\"\n#include \"rsyn/core/obj/data/Cell.h\"\n#include \"rsyn/core/obj/data/Port.h\"\n#include \"rsyn/core/obj/data/Module.h\"\n#include \"rsyn/core/obj/data/LibraryPin.h\"\n#include \"rsyn/core/obj/data/LibraryArc.h\"\n#include \"rsyn/core/obj/data/LibraryCell.h\"\n#include \"rsyn/core/obj/data/LibraryModule.h\"\n#include \"rsyn/core/obj/data/Design.h\"\n#include \"rsyn/core/obj/data/Library.h\"\n\n// Hashes\nnamespace std {\n\n#define RSYN_CREATE_HASH(OBJ) \\\ntemplate <> \\\nstruct hash<OBJ> { \\\n\tsize_t operator()(const OBJ &obj) const { \\\n\t\treturn hash<Rsyn::Proxy<OBJ##Data>>()(obj); \\\n\t} \\\n};\n\nRSYN_CREATE_HASH(Rsyn::Net);\nRSYN_CREATE_HASH(Rsyn::Pin);\nRSYN_CREATE_HASH(Rsyn::Arc);\nRSYN_CREATE_HASH(Rsyn::Instance);\nRSYN_CREATE_HASH(Rsyn::LibraryPin);\nRSYN_CREATE_HASH(Rsyn::LibraryArc);\nRSYN_CREATE_HASH(Rsyn::LibraryCell);\n\n} // end namespace\n\n// Infra\n#include \"rsyn/core/infra/Attribute.h\"\n#include \"rsyn/core/infra/Observer.h\"\n\n// Object's Implementations\n#include \"rsyn/core/obj/impl/Object.h\"\n#include \"rsyn/core/obj/impl/Net.h\"\n#include \"rsyn/core/obj/impl/Pin.h\"\n#include \"rsyn/core/obj/impl/Arc.h\"\n#include \"rsyn/core/obj/impl/Instance.h\"\n#include \"rsyn/core/obj/impl/Cell.h\"\n#include \"rsyn/core/obj/impl/Port.h\"\n#include \"rsyn/core/obj/impl/Module.h\"\n#include \"rsyn/core/obj/impl/LibraryPin.h\"\n#include \"rsyn/core/obj/impl/LibraryArc.h\"\n#include \"rsyn/core/obj/impl/LibraryCell.h\"\n#include \"rsyn/core/obj/impl/LibraryModule.h\"\n#include \"rsyn/core/obj/impl/Design.h\"\n#include \"rsyn/core/obj/impl/Library.h\"\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/core/RsynTypes.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_TYPES_H\n#define RSYN_TYPES_H\n\n#include <cstdint>\n\nnamespace Rsyn {\n\nenum ObjectType {\n\tOBJECT_TYPE_INVALID = -1,\n\n\tOBJECT_TYPE_NET,\n\tOBJECT_TYPE_PIN,\n\tOBJECT_TYPE_ARC,\n\n\tOBJECT_TYPE_INSTANCE,\n\tOBJECT_TYPE_CELL,\n\tOBJECT_TYPE_PORT,\n\tOBJECT_TYPE_MODULE,\n\n\tOBJECT_TYPE_LIBRARY_PIN,\n\tOBJECT_TYPE_LIBRARY_ARC,\n\tOBJECT_TYPE_LIBRARY_CELL,\n\n\tNUM_OBJECT_TYPES\n}; // end enum\n\nenum InstanceType {\n\tUNKNOWN_INSTANCE_TYPE = 0,  // used in bit fields (needs to start at zero)\n\n\tCELL,\n\tPORT,\n\tMODULE,\n\n\tNUM_INSTANCE_TYPES\n}; // end enum\n\nenum ArcType {\n\tUNKNOWN_ARC_TYPE = 0, // used in bit fields (needs to start at zero)\n\n\tINSTANCE_ARC,\n\tNET_ARC,\n\n\tNUM_ARC_TYPES\n}; // end enum\n\nenum TraverseType {\n\tINVALID_TRAVERSE_TYPE = -1,\n\n\tFORWARD,  // from inputs to outputs (topological order)\n\tBACKWARD, // from outputs to inputs (reverse topological order)\n\n\tNUM_TRAVERSE_TYPES\n}; // end enum\n\nenum Direction { // TODO: Many rename to SignalDirection\n\tUNKNOWN_DIRECTION  = 0, // used in bit fields (needs to start at zero)\n\n\tIN = 1,\n\tSINK = 1,\n\n\tOUT = 2,\n\tDRIVER = 2,\n\n\tBIDIRECTIONAL = 3,\n\n\tNUM_SIGNAL_DIRECTIONS\n}; // end enum\n\n//! @brief Orientation based on compass rose.\n//! @details The default orientation is \"vertically and face up\" - N (North).\n//!        Rotate by 90deg clockwise to get E, S and W, flip to get FN, FE,\n//!        FS and FW. (think of a dial).\n//!        Source: http://vlsicad.ucsd.edu/GSRC/bookshelf/Slots/Placement/plFormats.html\n//! @note  This orientations are compatible with LEF/DEF and OpenAccess.\n\nenum PhysicalOrientation : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tORIENTATION_INVALID = -1,\n\n\t//! @brief North Orientation (R0)\n\tORIENTATION_N = 0,\n\t//! @brief South orientation (R180)\n\tORIENTATION_S = 1,\n\t//! @brief West orientation (R90)\n\tORIENTATION_W = 2,\n\t//! @brief East orientation  (R270)\n\tORIENTATION_E = 3,\n\t//! @brief Flipped-North orientation (MY)\n\tORIENTATION_FN = 4,\n\t//! @brief Flipped-South orientation (MX)\n\tORIENTATION_FS = 5,\n\t//! @brief Flipped-West orientation (MX90)\n\tORIENTATION_FW = 6,\n\t//! @brief Flipped-East orientation (MY90)\n\tORIENTATION_FE = 7,\n\n\t//! @brief Number of orientations\n\tNUM_PHY_ORIENTATION = 8\n}; // end enum\n\nenum BufferType {\n\tNON_INVERTING,\n\tINVERTING,\n\tANY_BUFFER_TYPE\n}; // end enum\n\nenum TieType {\n\tTIE_LOW,\n\tTIE_HIGH,\n\tANY_TIE_TYPE\n}; // end enum\n\n// Mateus @ 20190204: Refatoring Use\n//! @brief Describes the usage of a pin or a net\n//! @note Compatible with LEF/DEF standard 5.8\nenum Use {\n\tUNKNOWN_USE = -1,\n\tSIGNAL,\n\tPOWER,\n\tGROUND,\n\tCLOCK,\n\tTIEOFF,\n\tANALOG,\n\tSCAN,\n\tRESET\n};\n\n} // end namespace\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/core/dscp/LibraryCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_LIBRARY_CELL_DESCRIPTOR_H\n#define RSYN_LIBRARY_CELL_DESCRIPTOR_H\n\n#include <cstdint>\n#include <memory>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <unordered_map>\n\n#include \"lef5.8/lefiMacro.hpp\"\n\nnamespace Rsyn {\n\nclass CellDescriptor {\nfriend class Design; // TODO: destroy this friendship...\nprivate:\n\t// macro\n\tlefiMacro* macro;\n\n\t// Mateus @ 20180917: Adding PinUse\n\t// pin name, pin direction\n\tstd::vector<std::tuple<std::string, Direction, Use>> pins;\n\t\n\t// from -> to\n\tstd::vector<std::tuple<std::string, std::string>> arcs;\n\t\npublic:\n\t\n\tvoid setMacro(lefiMacro* macro) {\n\t\tthis->macro = macro; // TODO: ugly\n\t} // end method\n\t\n\t// Mateus @ 20180917: Adding PinUse\n\tvoid addPin(const std::string &name, const Direction &direction, const Use& pinUse = UNKNOWN_USE) {\n\t\tpins.push_back(std::make_tuple(name, direction, pinUse));\n\t} // end method\n\t\n\tvoid addArc(const std::string &from, const std::string &to) {\n\t\tarcs.push_back(std::make_tuple(from, to));\n\t} // end method\n\t\n\tconst std::string getName() const { \n\t\treturn macro->name(); \n\t} // end method\n\t\n\tRsyn::Direction getPinDirection(const std::string &name) const {\n\t\tconst int numPins = pins.size();\n\t\tfor (int i = 0; i < numPins; i++) {\n\t\t\tif (std::get<0>(pins[i]) == name) {\n\t\t\t\treturn std::get<1>(pins[i]);\n\t\t\t} // end if\n\t\t} // end for\n\t\treturn Rsyn::UNKNOWN_DIRECTION;\n\t} // end if\n\t\n\tvoid checkConsistency() const {\n\t\tconst int numArcs = arcs.size();\n\t\tconst int numPins = pins.size();\n\t\t\n\t\tstd::map<std::string, Rsyn::Direction> mapPinToDirection;\n\t\t\n\t\tfor (int i = 0; i < numPins; i++) {\n\t\t\tif ((std::get<1>(pins[i]) != Rsyn::IN) && (std::get<1>(pins[i]) != Rsyn::OUT)) {\n\t\t\t\tthrow Exception(\"Only in and out direction are supported right now.\");\n\t\t\t} // end if\n\t\t\t\n\t\t\tif (std::get<0>(pins[i]) == \"\") {\n\t\t\t\tthrow Exception(\"Invalid pin name.\");\n\t\t\t} // end if\n\t\t\t\n\t\t\tmapPinToDirection[std::get<0>(pins[i])] = std::get<1>(pins[i]);\n\t\t} // end for\n\t\t\n\t\tfor (int i = 0; i < numArcs; i++) {\n\t\t\tconst std::string &from = std::get<0>(arcs[i]);\n\t\t\tconst std::string &to = std::get<1>(arcs[i]);\n\t\t\t\n\t\t\tif (from == to) {\n\t\t\t\tthrow Exception(\"From and to pins are equal.\");\n\t\t\t} // end if\n\t\t\t\n\t\t\tif (!mapPinToDirection.count(from)) {\n\t\t\t\tthrow Exception(\"From pin not found.\");\n\t\t\t} // end if\n\n\t\t\tif (!mapPinToDirection.count(to)) {\n\t\t\t\tthrow Exception(\"To pin not found.\");\n\t\t\t} // end if\n\n\t\t\tif (mapPinToDirection[from] != Rsyn::IN) {\n\t\t\t\tthrow Exception(\"From pin is not an input pin.\");\n\t\t\t} // end if\n\t\t\t\n\t\t\tif (mapPinToDirection[to] != Rsyn::OUT) {\n\t\t\t\tthrow Exception(\"To pin is not an output pin.\");\n\t\t\t} // end if\n\t\t} // end for\t\t\n\t\t\n\t} // end method\n\t\n}; // end class\n\n} // end namespace\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/core/dscp/LibraryModule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_LIBRARY_MODULE_DESCRIPTOR_H\n#define RSYN_LIBRARY_MODULE_DESCRIPTOR_H\n\n#include <cstdint>\n#include <memory>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <unordered_map>\n\nnamespace Rsyn {\n\nclass ModuleDescriptor {\nprivate:\n\t// port names\n\tstd::vector<std::tuple<std::string, Direction>> ports;\n\t\n\t// instance name, instance type (library cell, module)\n\tstd::vector<std::tuple<std::string, std::string>> instances;\n\t\n\t// instance, pin, net\n\tstd::vector<std::tuple<std::string, std::string, std::string>> connections;\npublic:\n\t\n\tvoid addPort(const std::string &name, const Direction &direction) {\n\t\tports.push_back(std::make_tuple(name, direction));\n\t} // end method\n\t\n\tvoid addInstance(const std::string &name, const std::string &type) {\n\t\tinstances.push_back(std::make_tuple(name, type));\n\t} // end method\n\t\n\tvoid addConnection(const std::string &instance, const std::string &pin, const std::string &net) {\n\t\tconnections.push_back(std::make_tuple(instance, pin, net));\n\t} // end method\n}; // end class\n\n} // end namespace\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/core/infra/Attribute.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_ATTRIBUTE_H\n#define RSYN_ATTRIBUTE_H\n\n#include <deque>\n\nnamespace Rsyn {\n\nclass AttributeInitializer {\nfriend class Design;\t\nprivate:\n\tDesign design;\n\tAttributeInitializer(Design design): design(design) {};\npublic:\n\tDesign getDesign() { return design; }\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename DefaultValueType>\nclass AttributeInitializerWithDefaultValue {\nfriend class Design;\t\nprivate:\n\tDesign design;\n\tDefaultValueType defaultValue;\n\tAttributeInitializerWithDefaultValue(Design design, DefaultValueType defaultValue)\n\t\t\t: design(design), defaultValue(defaultValue) {};\npublic:\n\tDesign getDesign() { return design; }\n\tDefaultValueType &getDefaultValue() { return defaultValue; }\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename _Object, typename _ObjectExtension>\nclass AttributeImplementation;\n\n// -----------------------------------------------------------------------------\n\ntemplate <typename RsynObject, typename RsynObjectExtension>\nclass Attribute : public std::shared_ptr<AttributeImplementation<RsynObject, RsynObjectExtension>> {\npublic:\t\n\tAttribute() {}\n\t\n\tAttribute(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer);\n\t\n\ttemplate<typename DefaultValueType>\n\tAttribute(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer);\n\t\n\tRsynObjectExtension &operator[](RsynObject obj);\n\tconst RsynObjectExtension &operator[](RsynObject obj) const;\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename _Object, typename _ObjectReference, typename _ObjectExtension>\nclass AttributeBase {\nprivate:\n\t// [TODO] Make design and list const.\n\t\n\tDesign clsDesign;\n\tList<_Object> *clsListPtr;\n\t_ObjectExtension clsDefaultValue;\n\t\n\ttypename List<_Object>::CreateElementCallbackHandler clsHandlerOnCreate;\n\ttypename List<_Object>::DestructorCallbackHandler clsListDestructorCallbackHandler;\n\t\n\tstd::deque<_ObjectExtension> clsData;\n\t\n\tvoid accommodate(const Index index) {\n\t\tif (index >= clsData.size()) {\n\t\t\tclsData.resize(index + 1, clsDefaultValue);\n\t\t} // end if\n\t} // end method\n\t\nprotected:\n\t\n\tvoid setupCallbacks() {\n\t\tclsHandlerOnCreate = clsListPtr->addCreateCallback([&](const int index) {\n\t\t\taccommodate(clsListPtr->largestId());\n\t\t}); // end method\n\t\t\n\t\tclsListDestructorCallbackHandler = clsListPtr->addDestructorEventCallback([&]() {\n\t\t\tclsListPtr = nullptr;\n\t\t}); // end method\t\t\n\t\t\n\t} // end method\n\t\n\tvoid load(Design design, List<_Object> &list, _ObjectExtension defaultValue = _ObjectExtension()) {\n\t\tclsDesign = design;\n\t\tclsListPtr = &list;\n\t\tclsDefaultValue = defaultValue;\n\t\taccommodate(clsListPtr->largestId());\n\t\tsetupCallbacks();\n\t} // end method\t\t\n\t\npublic:\n\t\n\tAttributeBase() : clsDesign(nullptr), clsListPtr(nullptr) {\n\t} // end constructor\n\t\n\tAttributeBase(const AttributeBase<_Object, _ObjectReference, _ObjectExtension> &other) {\n\t\toperator=(other);\n\t} // end constructor\n\t\n\tAttributeBase(Design design, List<_Object> &list) {\n\t\tload(design, list);\n\t} // end constructor\n\n\tAttributeBase<_Object, _ObjectReference, _ObjectExtension> &\n\toperator=(const AttributeBase<_Object, _ObjectReference, _ObjectExtension> &other) {\n\t\tunload();\n\t\t\n\t\tclsDesign = other.clsDesign;\n\t\tclsListPtr = other.clsListPtr;\n\t\tclsData = other.clsData;\n\t\t\t\t\t\t\n\t\t// When a layer gets copied, we need to setup new callbacks.\n\t\tsetupCallbacks();\n\t\t\n\t\treturn *this;\n\t} // end method\n\t\n\t~AttributeBase() {\n\t\tunload();\n\t} // end constructor\n\t\n\tvoid unload() {\n\t\tif (clsDesign) {\n\t\t\tclsDesign = nullptr;\n\t\t} // end if\n\t\t\n\t\tif (clsListPtr) {\n\t\t\tclsListPtr->deleteCreateCallback(clsHandlerOnCreate);\n\t\t\tclsListPtr->deleteDestructorCallback(clsListDestructorCallbackHandler);\n\t\t\tclsListPtr = nullptr;\n\t\t} // end if\n\n\t\tclsData.clear();\n\t\tclsData.shrink_to_fit();\n\t} // end method\t\n\n\tinline _ObjectExtension &operator[](_ObjectReference obj) { return clsData[clsDesign.getId(obj)]; }\n\tinline const _ObjectExtension &operator[](_ObjectReference obj) const { return clsData[clsDesign.getId(obj)]; }\n\n}; // end class\t\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: (Generic) - Internal Use Only\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _Object, typename _ObjectExtension>\nclass AttributeImplementation {\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: Net\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::Net, _ObjectExtension> \n\t: public Rsyn::AttributeBase<NetData, Net, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<NetData, Net, _ObjectExtension>::load(design, design.data->nets);\n\t} // end operator\n\t\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<NetData, Net, _ObjectExtension>::load(design, design.data->nets, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: Instance\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::Instance, _ObjectExtension> \n\t: public Rsyn::AttributeBase<InstanceData, Instance, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<InstanceData, Instance, _ObjectExtension>::load(design, design.data->instances);\n\t} // end operator\n\t\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<InstanceData, Instance, _ObjectExtension>::load(design, design.data->instances, initializer.getDefaultValue());\n\t} // end operator\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: Pin\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::Pin, _ObjectExtension> \n\t: public Rsyn::AttributeBase<PinData, Pin, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<PinData, Pin, _ObjectExtension>::load(design, design.data->pins);\n\t} // end operator\n\t\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<PinData, Pin, _ObjectExtension>::load(design, design.data->pins, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: Arc\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::Arc, _ObjectExtension> \n\t: public Rsyn::AttributeBase<ArcData, Arc, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<ArcData, Arc, _ObjectExtension>::load(design, design.data->arcs);\n\t} // end operator\n\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<ArcData, Arc, _ObjectExtension>::load(design, design.data->arcs, initializer.getDefaultValue());\n\t} // end operator\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: LibraryCell\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::LibraryCell, _ObjectExtension> \n\t: public Rsyn::AttributeBase<LibraryCellData, LibraryCell, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<LibraryCellData, LibraryCell, _ObjectExtension>::load(design, design.data->libraryCells);\n\t} // end operator\n\t\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\t\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<LibraryCellData, LibraryCell, _ObjectExtension>::load(design, design.data->libraryCells, initializer.getDefaultValue());\n\t} // end operator\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: LibraryPin\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::LibraryPin, _ObjectExtension> \n\t: public Rsyn::AttributeBase<LibraryPinData, LibraryPin, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<LibraryPinData, LibraryPin, _ObjectExtension>::load(design, design.data->libraryPins);\n\t} // end operator\n\t\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\t\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<LibraryPinData, LibraryPin, _ObjectExtension>::load(design, design.data->libraryPins, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute Layer: LibraryArc\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _ObjectExtension>\nclass AttributeImplementation<Rsyn::LibraryArc, _ObjectExtension> \n\t: public Rsyn::AttributeBase<LibraryArcData, LibraryArc, _ObjectExtension> {\npublic:\n\tAttributeImplementation() {}\n\t\n\tAttributeImplementation(AttributeInitializer initializer) { operator=(initializer); }\n\tvoid operator=(AttributeInitializer initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<LibraryArcData, LibraryArc, _ObjectExtension>::load(design, design.data->libraryArcs);\n\t} // end operator\n\t\n\ttemplate<typename DefaultValueType>\n\tAttributeImplementation(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) { operator=(initializer); }\t\n\ttemplate<typename DefaultValueType>\n\tvoid operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\t\tDesign design = initializer.getDesign();\n\t\tAttributeBase<LibraryArcData, LibraryArc, _ObjectExtension>::load(design, design.data->libraryArcs, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Attribute\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename RsynObject, typename RsynObjectExtension>\ninline\nvoid Attribute<RsynObject, RsynObjectExtension>::operator=(AttributeInitializer initializer) {\n\tthis->reset(new AttributeImplementation<RsynObject, RsynObjectExtension>(initializer));\n} // end method\n\ntemplate<typename RsynObject, typename RsynObjectExtension>\ntemplate<typename DefaultValueType>\ninline\nvoid Attribute<RsynObject, RsynObjectExtension>::operator=(AttributeInitializerWithDefaultValue<DefaultValueType> initializer) {\n\tthis->reset(new AttributeImplementation<RsynObject, RsynObjectExtension>(initializer));\n} // end method\n\ntemplate<typename RsynObject, typename RsynObjectExtension>\ninline\nRsynObjectExtension &Attribute<RsynObject, RsynObjectExtension>::operator[](RsynObject obj) {\n\treturn (*this)->operator[](obj); \n} // end method\n\ntemplate<typename RsynObject, typename RsynObjectExtension>\ninline\nconst RsynObjectExtension &Attribute<RsynObject, RsynObjectExtension>::operator[](RsynObject obj) const {\n\treturn (*this)->operator[](obj); \n} // end method\n\n} // end namespace\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/infra/Exception.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_EXCEPTION_H\n#define RSYN_EXCEPTION_H\n\n#include <string>\n#include <exception>\n\nnamespace Rsyn {\n\nclass Exception : public std::exception {\npublic:\n\tException(const std::string &msg) : std::exception(),  msg(msg) {}\n\tvirtual const char* what() const throw() { return msg.c_str(); };\nprivate:\n\tstd::string msg;\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass CellAlreadyExistsException : public Exception {\npublic:\n\tCellAlreadyExistsException(const std::string &name) :\n\t\t\tException(\"Cell '\" + name + \"' already exists.\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass CellNotFoundException : public Exception {\npublic:\n\tCellNotFoundException(const std::string &name) :\n\t\t\tException(\"Cell '\" + name + \"' not found.\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass LibraryCellAlreadyExistsException : public Exception {\npublic:\n\tLibraryCellAlreadyExistsException(const std::string &name) :\n\t\t\tException(\"Library cell '\" + name + \"' already exists.\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass LibraryCellNotFoundException : public Exception {\npublic:\n\tLibraryCellNotFoundException(const std::string &libCellName) :\n\t\t\tException(\"Library cell '\" + libCellName + \"' not found.\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass LibraryPinNotFoundException : public Exception {\npublic:\n\tLibraryPinNotFoundException(const std::string &libCellName, const std::string &libPinName) :\n\t\t\tException(\"Library pin '\" + libPinName + \"' not found in library cell '\" + libCellName + \"'.\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass NetAlreadyExistsException : public Exception {\npublic:\n\tNetAlreadyExistsException(const std::string &name) :\n\t\t\tException(\"Net '\" + name + \"' already exists.\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass PinNotFoundException : public Exception {\npublic:\n\tPinNotFoundException(const std::string &libCellName, const std::string &cellName, const std::string &pinName) :\n\t\t\tException(\"Pin '\" + pinName + \"' not found in cell '\" + cellName + \"'(\" + libCellName + \").\") {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass IncompatibleLibraryCellForRemapping : public Exception {\npublic:\n\tIncompatibleLibraryCellForRemapping(const std::string &oldLibraryCell, const std::string &newLibraryCell) :\n\t\t\tException(\"Library cell '\" + newLibraryCell + \"' is not compatible to library cell '\" + oldLibraryCell + \"'.\") {}\n}; // end class\n\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/infra/List.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_LIST_H\n#define RSYN_LIST_H\n\n#include <cmath>\n#include <deque>\n#include <list>\n#include <vector>\n#include <functional>\n#include <iostream>\n\nnamespace Rsyn {\n\ntemplate<typename T> \nstruct Element {\n\tT value;\n    bool deleted;\n\n    Element() : deleted(true) {};\n\tElement(T value) : value(value), deleted(false) {};\n}; // end struct \n\n//--------------------------------------------------------------------------\n\ntemplate<typename T> struct ElementPointer {\nprivate:\n\t// For some reason the compiler allows ElementPointer to be silently casted\n\t// to int, which led to hard to find bugs. Now we explicitly tell the \n\t// compiler to not allow such conversion by making the cast operator \n\t// private.\n\toperator int() const { return 0; }\nprotected:\n\tElement<T> *e;\n\npublic:\t\n\tT &getValue() { return e->value; }\t\n\tElement<T> *getPointer() { return e; }\n\n\tElementPointer() : e( nullptr ) {};\t\n\tElementPointer(Element<T> *e) : e(e) {};\n\n\tT * operator->() { return &(e->value); };\n\tconst T * operator->() const { return &(e->value); };\n\t\n\tbool operator!() const { return e == nullptr; };\n\tbool operator==(const ElementPointer<T> &p) const { return e == p.e; };\n\tbool operator!=(const ElementPointer<T> &p) const { return e != p.e; };\n\t\n\toperator bool() const { return e; }\n\t\n\t// Used in map-like data structures.\n\tfriend bool operator<(const ElementPointer<T> &left, const ElementPointer<T> &right) {\n\t\t// [IMPORTANT] We don't use the pointer (e) directly to avoid \n\t\t// non-determinism behavior. Note that the pointer address may change\n\t\t// from execution to execution and hence the mapping function may return\n\t\t// elements in different order leading to different results.\n\t\treturn left.e->value.getId() < right.e->value.getId();\n\t} // end method\n}; // end struct \n\n//--------------------------------------------------------------------------\n\ntemplate<typename T, unsigned int DEFAULT_CHUNK_SIZE> \nstruct Chunk {\t\t\n\tElement<T> elements[DEFAULT_CHUNK_SIZE];\n}; // end struct\n\n//--------------------------------------------------------------------------\n\n//\n// DEFAULT CHUNCK SIZE\n// \n// Date: 2016-03-02\n//\n// superblu18\n//    10 runtime: 126.876 s memory: +2804 MB\n//   100 runtime: 113.372 s memory: +2790 MB\n//  1000 runtime: 112.172 s memory: +2786 MB\n// 10000 runtime: 114.887 s memory: +2790 MB\n//\n// superblue10\n//    10 runtime: 331.377 s memory: +6293 MB\n//   100 runtime: 326.238 s memory: +6258 MB\n//  1000 runtime: 324.864 s memory: +6258 MB\n// 10000 runtime: 324.034 s memory: +6259 MB\n//\n\ntemplate<typename T, unsigned int DEFAULT_CHUNK_SIZE = 1000>\nclass List {\npublic:\t\n\t\n\ttypedef std::function<void(const int index)> CreateElementCallback;\n\ttypedef std::function<void(const int index)> RemoveElementCallback;\n\ttypedef std::function<void()> DestructorCallback;\n\t\n\ttypedef std::list<CreateElementCallback>::iterator CreateElementCallbackHandler;\n\ttypedef std::list<RemoveElementCallback>::iterator RemoveElementCallbackHandler;\n\ttypedef std::list<DestructorCallback>::iterator DestructorCallbackHandler;\n\t\nprivate:\t\n\t// Iterator validity (std::deque)\n\t// ------------------------------\n\t// In case the container shrinks, all iterators, pointers and references to \n\t// elements that have not been removed remain valid after the resize and refer\n\t// to the same elements they were referring to before the call.\n\t// If the container expands, all iterators are invalidated, but existing\n\t// pointers and references remain valid, referring to the same elements they \n\t// were referring to before.\n\t\n\tstd::deque<Chunk<T, DEFAULT_CHUNK_SIZE>> chunks;\n\tstd::list<int> available;\n\tstd::list<CreateElementCallback> callbackOnCreate;\n\tstd::list<RemoveElementCallback> callbackOnRemove;\n\tstd::list<DestructorCallback> callbackOnDestructor;\n\n\tint numElements;\n\tint lastInsertedElementId;\n\tint currentChunk;\n\tint currentChunkFreeSpace;\n\n\tElement<T> *create_internal() {\n\t\tElement<T> *e = nullptr;\n\n\t\tconst int recycle = recycleId();\n\t\t\n\t\tif (recycle != -1) {\n\t\t\t// Recycle a previously removed element...\n\t\t\te = get(recycle);\n\t\t\tavailable.pop_back();\n\t\t\t\n\t\t\t// Clean-up the recycled element.\n\t\t\t*e = T();\n\t\t\tlastInsertedElementId = recycle;\n\t\t} else {\n\t\t\tif (currentChunkFreeSpace == 0) {\n\t\t\t   // Move to the next chunk or creates a new chunk to store the new \n\t\t\t   // element.\n\n\t\t\t   currentChunk++;\n\t\t\t   if (currentChunk >= chunks.size()) {\n\t\t\t\t   chunks.resize(chunks.size()+1);\n\t\t\t   } // end if\n\n\t\t\t   currentChunkFreeSpace = DEFAULT_CHUNK_SIZE;\n\t\t   } // end else\n\t\t\t\n\t\t\tauto &c = chunks[currentChunk];\n\t\t\te = &(c.elements[DEFAULT_CHUNK_SIZE - currentChunkFreeSpace]);\n\t\t\tlastInsertedElementId = (currentChunk+1)*DEFAULT_CHUNK_SIZE - \n\t\t\t\tcurrentChunkFreeSpace;\n\t\t\t\n\t\t\tcurrentChunkFreeSpace--;\n\t\t} // end else\n\n\t\te->deleted = false;\n\t\tnumElements++;\n\n\t\treturn e;\n\t} // end method\t\n\t\npublic:\t\n\t\n\tList() : \n\t\t\tnumElements(0), \n\t\t\tlastInsertedElementId(-1),\n\t\t\tcurrentChunk(-1),\n\t\t\tcurrentChunkFreeSpace(0) {\n\t}; // end constructor\n\n\t~List() {\n\t\tfor (DestructorCallback &callback : callbackOnDestructor) {\n\t\t\tcallback();\n\t\t} // end for\t\t\n\t} // end destructor\n\t\n\tbool isEmpty() const { return !numElements; };\n\n\tint size() const { return numElements; };\n\tint lastId() const { return lastInsertedElementId; }\n\tint largestId() const { return (currentChunk+1)*DEFAULT_CHUNK_SIZE \n\t\t- currentChunkFreeSpace; }\n\n\tint recycleId() const {\n\t\treturn available.empty()? -1 : available.front();\n\t} // end method\n\t\n\tint capacity() const {\n\t\t// It can be optimized, but for now its just for debug purpose.\n\t\tint capacity = 0;\n\n\t\tfor (auto &c : chunks )\n\t\t\tcapacity += DEFAULT_CHUNK_SIZE;\n\n\t\treturn capacity;\n\t} // end method\n\n\tvoid reserve(const int n) {\n\t\tconst int numChunks = (int) std::ceil(n / double(DEFAULT_CHUNK_SIZE));\n\t\tif (numChunks > chunks.size()) {\n\t\t\tchunks.resize(numChunks);\n\t\t} // end if\n\t}; // end method\n\n\tElement<T> *create() {\n\t\tElement<T> *e = create_internal();\n\t\tfor (CreateElementCallback &callback : callbackOnCreate) {\n\t\t\tcallback(lastId());\n\t\t} // end for\n\t\treturn e;\n\t} // end method\n\t\n\tElement<T> *add(const T &value) {\n\t\tElement<T> *e = create_internal();\n\t\te->value = value;\n\t\tfor (CreateElementCallback &callback : callbackOnCreate) {\n\t\t\tcallback(lastId());\n\t\t} // end for\n\t\treturn e;\n\t} // end method\n\n\tElement<T> *get(const int index) {\n\t\treturn &chunks[index/DEFAULT_CHUNK_SIZE].elements[index%DEFAULT_CHUNK_SIZE];\n\t} // end method\n\t\n\tconst Element<T> *get(const int index) const {\n\t\treturn &chunks[index/DEFAULT_CHUNK_SIZE].elements[index%DEFAULT_CHUNK_SIZE];\n\t} // end method\t\n\t\n\tvoid remove(const int index) {\n\t\tElement<T> *e = get(index);\n\t\te->deleted = true;\n                \n\t\tavailable.push_back(index);\n\t\tnumElements--;\n\t\t\n\t\tfor (RemoveElementCallback &callback : callbackOnRemove) {\n\t\t\tcallback(index);\n\t\t} // end for\n\t} // end method\n\t\n\tDestructorCallbackHandler addDestructorEventCallback(DestructorCallback callback) {\n\t\tcallbackOnDestructor.push_back(callback);\n\t\treturn --callbackOnDestructor.end();\n\t} // end method\t\n\t\n\tCreateElementCallbackHandler addCreateCallback(CreateElementCallback callback) {\n\t\tcallbackOnCreate.push_back(callback);\n\t\treturn --callbackOnCreate.end();\n\t} // end method\n\n\tRemoveElementCallbackHandler addRemoveCallback(CreateElementCallback callback) {\n\t\tcallbackOnRemove.push_back(callback);\n\t\treturn --callbackOnRemove.end();\n\t} // end method\n\n\tvoid deleteDestructorCallback(DestructorCallbackHandler handler) {\n\t\tcallbackOnDestructor.erase(handler);\n\t} // end method\t\n\t\n\tvoid deleteCreateCallback(CreateElementCallbackHandler handler) {\n\t\tcallbackOnCreate.erase(handler);\n\t} // end method\t\n\n\tvoid deleteRemoveCallback(RemoveElementCallbackHandler handler) {\n\t\tcallbackOnRemove.erase(handler);\n\t} // end method\t\n\t\n\tclass Iterator {\n\tfriend class List;\n\tprivate:\n\t\tList *l;\n\t\tElement<T> *e;\n\t\tint currChunk;\n\t\tint currElementInChunk;\n\t\tint size;\n\t\tbool stop;\n\t\t\n\t\tElement<T> *nextElement() {\n\t\t\tdo {\t\t\t\t\n\t\t\t\tcurrElementInChunk++;\n\t\t\t\n\t\t\t\tif (currElementInChunk == DEFAULT_CHUNK_SIZE) {\n\t\t\t\t\tcurrElementInChunk = 0;\n\t\t\t\t\tcurrChunk++;\n\t\t\t\t\t\n\t\t\t\t\tif (currChunk == l->chunks.size()) {\n\t\t\t\t\t\tstop = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} // end if\n\t\t\t\t\t\n\t\t\t\t\tauto &chunk = l->chunks[currChunk];\n\t\t\t\t\te = &(chunk.elements[0]);\t\n\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\te++;\n\t\t\t\t} // end else\n\t\t\t} while (e->deleted);\t\n\t\t\t\n\t\t\treturn e;\n\t\t} // end method\n\t\t\n\tpublic:\t\t\n\t\tIterator() : l(NULL), e(NULL), currChunk(0), currElementInChunk(0) {};\n\t\tIterator( List *l ) : l(l), currChunk(0), currElementInChunk(0) {\n\t\t\tif (!l->isEmpty()) {\n\t\t\t\te = l->get(0);\n\t\t\t\tif (e->deleted) {\n\t\t\t\t\t// Skip deleted elements at the beginning of the list.\n\t\t\t\t\te = nextElement();\n\t\t\t\t} // end if\n\t\t\t\tstop = false;\n\t\t\t} else {\n\t\t\t\tstop = true;\n\t\t\t} // end else\n\t\t} // end constructor\n\t\t\n\t\tvoid operator++ () {\n\t\t\te = nextElement();\n\t\t} // end method\n\t\t\n\t\tElementPointer<T> operator*() { return e; }\n\t\t\n\t\tfriend bool operator != ( Iterator it1, Iterator it2 ) {\n\t\t\treturn !it1.stop;\n\t\t} // end operator\n\t\t\n\t\tbool stopFlag() { return stop; }\n\t}; // end structure\n\t\n\tIterator begin() {\n\t\treturn Iterator( this );\n\t}\n\t\n\tIterator end() {\n\t\tIterator end;\n\t\t\n\t\tend.l = this;\n\t\tend.currChunk = chunks.size() - 1;\n\t\tend.currElementInChunk = DEFAULT_CHUNK_SIZE - 1;\n\t\tend.e = &(chunks[ end.currChunk ].elements[ end.currElementInChunk ]);\n\t\t\n\t\treturn end;\n\t}\t\n\t\n\t/* Method for debug purposes */\n\tvoid printState() {\n\t\tstd::cout << \" --- List state---\" << std::endl;\n\t\t\n\t\tstd::cout << \"> Number of elements: \" << numElements << std::endl;\n\t\tstd::cout << \"> Current chunk free elements: \" << currentChunkFreeSpace << std::endl;\n\t\tstd::cout << \"> Number of chunks: \" << chunks.size() << std::endl;\n\t\tfor( auto c: chunks ) \n\t\t\tstd::cout << \">> Chunk size: \" << c.size << std:: endl;\n\t\t\n\t\tstd::cout << \" -----------------\" << std::endl;\n\t} // end method\n\t\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename T, unsigned int DEFAULT_CHUNK_SIZE = 1000>\nclass ConstList {\nprivate:\n\tList<T, DEFAULT_CHUNK_SIZE> *l;\n\tConstList() {}\npublic:\n\t\n\ttypedef typename List<T, DEFAULT_CHUNK_SIZE>::Iterator Iterator;\n\t\n\tConstList(const List<T, DEFAULT_CHUNK_SIZE> &list) {\n\t\tl = const_cast<List<T, DEFAULT_CHUNK_SIZE> *>(&list);\n\t} // end constructor\n\t\n\tElement<T> *get(const int index) { return l->get(index); }\n\tIterator begin() { return l->begin(); }\n\tIterator end() { return l->end(); }\n}; // end class\n\n\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/infra/Observer.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_DESIGN_OBSERVER_H\n#define RSYN_DESIGN_OBSERVER_H\n\nnamespace Rsyn {\n\nclass DesignObserver {\nfriend class Rsyn::Design;\nprivate:\n\n\tDesign observedDesign;\n\npublic:\n\t\n\t// Note: The observer will not be registered to receive notifications for\n\t// methods that it does not overwrite. Therefore, no runtime overhead for\n\t// handling undesired notifications.\n\n\tvirtual void\n\tonDesignDestruction() {}\n\n\tvirtual void\n\tonPostInstanceCreate(Rsyn::Instance instance) {}\n\n\tvirtual void\n\tonPreInstanceRemove(Rsyn::Instance instance) {}\n\n\tvirtual void\n\tonPostNetCreate(Rsyn::Net net) {}\n\n\tvirtual void\n\tonPreNetRemove(Rsyn::Net net) {}\n\n\tvirtual void\n\tonPostCellRemap(Rsyn::Cell cell, Rsyn::LibraryCell oldLibraryCell) {}\n\n\tvirtual void\n\tonPostPinConnect(Rsyn::Pin pin) {}\n\n\tvirtual void\n\tonPrePinDisconnect(Rsyn::Pin pin) {}\n\n\tvirtual void\n\tonPreInstanceMove(Rsyn::Instance) {}\n\n\tvirtual void\n\tonPostInstanceMove(Rsyn::Instance) {}\n\n\tvirtual\n\t~DesignObserver() {\n\t\tif (observedDesign)\n\t\t\tobservedDesign.unregisterObserver(this);\n\t} // end destructor\n\n}; // end class\n\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/infra/RangeBasedLoop.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef UTIL_RANGEBASEDLOOP_H\n#define\tUTIL_RANGEBASEDLOOP_H\n\n////////////////////////////////////////////////////////////////////////////////\n// Author: Guilherme Flach\n// Date: 2015-02-17\n//\n// Description\n// -----------\n// This class makes it easier to create range-based loops.\n//\n// How To Use It\n// -------------\n// Create a class/struct with the following methods:\n//     1) Object current() {...}\n//     2) void next() {...}\n//     3) bool filter() {...}\n//     4) bool stop() {...}\n//\n// which the following meaning\n//\n//     1) returns the current object in the collection;\n//     2) moves to the next object in the collection;\n//     3) indicates if the current object should be filtered (i.e. not\n//        processed), this class will call next() until filter() returns true\n//        or the end of collection is reached;\n//     4) indicates if we reached the end of the collection.\n//\n// Example\n// -------\n// Traverse only non-zero elements of a vector (i.e. filter out zeros):\n//\n//    // This is the class the user (you) needs to provide to create a\n//    // ranged-based loop.\n//    class NonZeroElementsCollection {\n//    private:\n//        const std::vector<int> &v;\n//        std::size_t index;\n//    public:\n//        NonZeroElementsCollection(const std::vector<int> &v) \n//            : v(v), index(0) {}\n//\n//        int current() {return v[index];}\n//        void next() {index++;}\n//        bool filter() {return current() == 0;}\n//        bool stop() {return index >= v.size();}        \n//    }; // end class\n//\n//    // Give it a nice name...\n//    typedef Range<NonZeroElementsCollection> allNonZeroElements;\n//\n//    // Testing...\n//    int main() {\n//        std::vector<int> v = {0, 1, 0, 2, 0, 3, 4, 0, 0, 0, 5};\n//\n//        for (int value : allNonZeroElements(v)) {\n//            std::cout << value << \" \";\n//        } // end for\n//        std::cout << \"\\n\";\n//\n//        return 1;\n//    } // end function\n//\n////////////////////////////////////////////////////////////////////////////////\n\n////////////////////////////////////////////////////////////////////////////////\n// According to the C++11 standard, the following range-loop statement\n// \n//        for ( declaration : expression ) statement\n//\n// is equivalent to the the following statament\n//\n//        {\n//            auto&& __range = expression;\n//            for (auto __begin = begin-expression,\n//                      __end = end-expression;\n//                 __begin != __end;\n//                 ++__begin\n//            ) {\n//                declaration = *__begin;\n//                statement\n//            }\n//        }\n//\n// So that, we can override the operator != of an iterator to make it\n// return false whenever the stop condition was reached in the begin \n// iterator in code above.\n//\n// Source: http://en.cppreference.com/w/cpp/language/range-for\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<class Collection>\nclass Range {\nprivate:\n\tCollection collection;\n\n\tstruct RangeIterator {\n\t\tCollection *collection;\n\n\t\tRangeIterator() : collection(nullptr) {}\n\t\tRangeIterator(Collection &collection_) : collection(&collection_) {\n\t\t\twhile (!collection->stop() && collection->filter()) { // stop must be first\n\t\t\t\tcollection->next();\n\t\t\t} // end while\n\t\t} // end constructor\n\n\t\tvoid operator++() { \n\t\t\tdo {\n\t\t\t\tcollection->next();\n\t\t\t} while (!collection->stop() && collection->filter()); // stop must be first\n\t\t} // end method\n\n\t\tbool operator!=(const RangeIterator &) {\n\t\t\treturn !collection->stop();\n\t\t} // end method\n\n\t\tauto operator*() -> decltype(collection->current()) {\n\t\t\treturn collection->current();\n\t\t} // end method\t\n\n\t}; // end class\n\npublic:\n\n\tRange(Collection &&collection) : collection(collection) {}\n\n\tRangeIterator begin() { return RangeIterator(collection); }\n\tRangeIterator end() { return RangeIterator(); /*dummy, not used */}\n}; // end class\t\n\n////////////////////////////////////////////////////////////////////////////////\n// Traverse a collection backwards.\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate <typename Collection>\nclass BackwardsCollection {\nprivate:\n    const Collection &collection;\npublic:\n    explicit BackwardsCollection(const Collection &t) : collection(t) {}\n    typename Collection::const_reverse_iterator begin() const { return collection.rbegin(); }\n    typename Collection::const_reverse_iterator end()   const { return collection.rend(); }\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Returns an specific element of a tuple collection.\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<std::size_t index, typename... _Elements>\nclass TupleElement : public std::tuple<_Elements...> {\npublic:\n\ttypedef typename std::tuple_element<index, std::tuple<_Elements...>>::type T;\n\t\n\tTupleElement() {}\n\tTupleElement(const std::tuple<_Elements...> &t) : std::tuple<_Elements...>(t) {}\n\tvoid operator=(const std::tuple<_Elements...> &t) { std::tuple<_Elements...>::operator=(t); }\n\toperator T() { return std::get<index>(*this);} \n}; // end class\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/infra/RawPointer.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_RAW_POINTER_H\n#define RSYN_RAW_POINTER_H\n\n#include <exception>\n#include \"rsyn/core/Rsyn.h\"\n\nnamespace Rsyn {\n\n//! @brief Allows Rsyn objects to be casted as raw pointer (i.e. void *).\nclass RawPointer {\nprivate:\n\tvoid * pointer = nullptr;\n\npublic:\n\n\tRawPointer(void * data) : pointer(data) {}\n\n\tRawPointer(Rsyn::Net obj)         : pointer(static_cast<void *>(obj.getData())) {}\n\tRawPointer(Rsyn::Pin obj)         : pointer(static_cast<void *>(obj.getData())) {}\n\tRawPointer(Rsyn::Arc obj)         : pointer(static_cast<void *>(obj.getData())) {}\n\tRawPointer(Rsyn::Instance obj)    : pointer(static_cast<void *>(obj.getData())) {}\n\tRawPointer(Rsyn::LibraryPin obj)  : pointer(static_cast<void *>(obj.getData())) {}\n\tRawPointer(Rsyn::LibraryArc obj)  : pointer(static_cast<void *>(obj.getData())) {}\n\tRawPointer(Rsyn::LibraryCell obj) : pointer(static_cast<void *>(obj.getData())) {}\n\n\tRsyn::Net         asNet        () { return static_cast<NetData *        >(pointer); }\n\tRsyn::Pin         asPin        () { return static_cast<PinData *        >(pointer); }\n\tRsyn::Arc         asArc        () { return static_cast<ArcData *        >(pointer); }\n\tRsyn::Instance    asInstance   () { return static_cast<InstanceData *   >(pointer); }\n\tRsyn::LibraryPin  asLibraryPin () { return static_cast<LibraryPinData * >(pointer); }\n\tRsyn::LibraryArc  asLibraryArc () { return static_cast<LibraryArcData * >(pointer); }\n\tRsyn::LibraryCell asLibraryCell() { return static_cast<LibraryCellData *>(pointer); }\n\n\toperator void *() { return pointer; }\n\toperator const void *() const { return pointer; }\n\n}; // end class\n\n} // end namespace\n\n#endif /* RAWPOINTER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Arc.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\t\t\nstruct ArcData : ObjectData {\n\tArcType type : 3;\n\tPin from;\n\tPin to;\n\t\n\tunion {\n\t\t// Place holder for initialization...\n\t\tvoid * extra;\n\t\t\n\t\t// Meaningful only when this is arc belongs to a cell.\n\t\tLibraryArcData * libraryArcData;\n\t\t\n\t\t// Meaningful only when this is arc belongs to a net.\n\t\tNetData * netData;\n\t}; // end union\n\n\tArcData() : \n\t\ttype(UNKNOWN_ARC_TYPE),\n\t\textra(nullptr),\n\t\tfrom(nullptr), \n\t\tto(nullptr) {\n\t} // end constructor\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Cell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct CellData {\n\t\n}; // end struct\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Design.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct DesignData {  \n\tstd::string name;\n\n\tRsyn::Module topModule;\n\n\tList<InstanceData> instances;\n\tList<PinData> pins;\n\tList<ArcData> arcs;\n\tList<NetData> nets;\n        List<Cell> cells;\n\t\n\tList<LibraryCellData> libraryCells;\n\tList<LibraryPinData> libraryPins;\n\tList<LibraryArcData> libraryArcs;\n\n\tstd::vector<std::string> instanceNames;\n\tstd::vector<std::string> netNames;\n\t\n\tint anonymousInstanceId;\n\tint anonymousNetId;\n\t\n\tstd::unordered_map<std::string, Instance> instanceMapping;\n\tstd::unordered_map<std::string, Net> netMapping;\n\tstd::unordered_map<std::string, LibraryCell> libraryCellMapping;\n\t\n\tstd::array<LibraryCell, NUM_SIGNAL_DIRECTIONS> portLibraryCells;\n\tstd::set<Cell> ports[NUM_SIGNAL_DIRECTIONS];\n\t\n\tstd::array<int, NUM_INSTANCE_TYPES> instanceCount;\n\t\n\tstd::vector<Pin> structuralStartpoints;\n\tstd::vector<Pin> structuralEndpoints;\t\n\tstd::vector<Net> netsInTopologicalOrder;\n\t\n\tbool dirty;\t\n\tbool initialized;\n\t\n\t// Used for some netlist traversing (e.g. update topological ordering)...\n\tint sign;\t\n\t\n\t// Observers\n\tstd::array<std::list<DesignObserver *>, NUM_DESIGN_EVENTS> observers;\n\t\n\t// Constructor\n\tDesignData() :\n\t\tinitialized(false),\n\t\tdirty(false),\n\t\tanonymousInstanceId(0),\n\t\tanonymousNetId(0),\n\t\tinstanceCount({0, 0, 0}),\n\t\tsign(0) {\n\t} // end constructor\n}; // end class\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Instance.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct InstanceTagData {\n\tTristateFlag fixed;\n\tTristateFlag block;\n}; // end struct\n\n// -----------------------------------------------------------------------------\n\nstruct InstanceData : ObjectData {\n\tInstanceType type;\n\t\t\n\tstd::vector<Pin> pins;\n\tstd::vector<Arc> arcs;\n\t\n\t// Design (Cached)\n\t// @todo Remove.\n\tDesign design;\n\t\n\t// The module where this instance is instantiated. If only null for the top\n\t// module.\n\tModule parent;\n\t\n\t// Local index inside it's parent module.\n\tIndex mid;\n\n\t// Extra data for different types of instances.\n\tunion {\n\t\tvoid * extra;\n\t\t\n\t\tModuleData * moduleData;\n\t\tPinData * outerPin;\n\t\tLibraryCellData * lcell;\n\t}; // end union\n\n\t// User tag\n\tInstanceTagData tag;\n\n\t// Physical information.\n\tBounds clsBounds;\n\tPhysicalOrientation clsOrientation;\n\tDBUxy clsPortPos; // only for port to define position. (@todo remove, use bounds instead).\n\n\t// Constructor\n\tInstanceData() : \n\t\tdesign(nullptr),\n\t\ttype(UNKNOWN_INSTANCE_TYPE),\n\t\tparent(nullptr),\n\t\textra(nullptr),\n\t\tmid(-1),\n\t\tclsBounds(0, 0, 0, 0),\n\t\tclsOrientation(ORIENTATION_N), // @todo set to R0 by default\n\t\tclsPortPos(0, 0) {\n\t} // end constructor\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Library.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Rsyn {\n\nstruct LibraryData : ObjectData {\n\tDesignData *designData = nullptr;\n}; // end struct\n\n} // end namespace\n\n"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/LibraryArc.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct LibraryArcData : ObjectData {\n\tDesign design;\n\tint index; // TODO: index may be confusing as objects have a field called id \n\t\n\tLibraryCell lcell;\n\tLibraryPin from;\n\tLibraryPin to;\n\n\tLibraryArcData() : \n\t\tdesign(nullptr),\n\t\tindex(-1), \n\t\tlcell(nullptr),\n\t\tfrom(nullptr), \n\t\tto(nullptr) {\n\t} // end class\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/LibraryCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct LibraryCellTagData {\n\tLogicTypeTag logicType : 2;\n\tBufferTypeTag bufferType : 2;\n\tTieTypeTag tieType : 2;\n\n\tLibraryCellTagData() :\n\t\tlogicType(LOGIC_TYPE_TAG_NOT_SPECIFIED),\n\t\tbufferType(BUFFER_TYPE_TAG_NOT_SPECIFIED),\n\t\ttieType(TIE_TYPE_TAG_NOT_SPECIFIED) {\n\t} // end constructor\n}; // end struct\n\n// -----------------------------------------------------------------------------\n\nstruct LibraryCellData : ObjectData {\n\tDesign design;\n\tstd::string name;\n\tstd::vector<LibraryPin> pins;\n\tstd::vector<LibraryArc> arcs;\n\tDBUxy size;\n\n\t// User flags.\n\tLibraryCellTagData tag;\n\n\t// TODO: use array\n\tint numInputPins;\n\tint numOutputPins;\n\tint numInOutPins;\n\n\tLibraryCellData() : \n\t\tdesign(nullptr),\n\t\tnumInputPins(0),\n\t\tnumOutputPins(0), \n\t\tnumInOutPins(0),\n\t\tsize(0, 0) {\n\t} // constructor\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/LibraryModule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct LibraryModuleData : ObjectData {\n\tDesign design;\n\t\n\tLibraryModuleData() :\n\t\tdesign(nullptr) {\n\t} // end constructor\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/LibraryPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct LibraryPinData : ObjectData {\n\tDesign design;\n\tLibraryCell lcell;\n\tstd::string name;\n\tDirection direction;\n\t// Mateus @ 20180917: Adding PinUse\n\tUse pinUse;\n\tint index;\n\n\tLibraryPinData() : \n\t\tdesign(nullptr),\n\t\tlcell(nullptr),\n\t\tdirection(UNKNOWN_DIRECTION),\n\t\tpinUse(UNKNOWN_USE),\n\t\tindex(-1) {\n\t} // end constructor\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Module.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct ModuleData {\n\tDesign design;\n\t\n\t// Pointers to instances and nets in this hierarchy level (objects above and\n\t// below this hierarchy level are not stored). We don't need to store\n\t// pin and arc pointers as they can be deduced from cell pointers. Nets\n\t// on the other may exist without connecting any cell (pin) so can not be \n\t// completely deduced from cells.\n\t//\n\t// TODO: Find a better way to store module-specific data. It seems we are\n\t// spending too much memory to keep this.\n\tList<Instance> instances;\n\tList<Net> nets;\n\t\n\t// Ports.\n\t// Redundant with instances, but allow faster access to ports.\n\tList<Port> ports;\n\tstd::set<Port> portsByDirection[Rsyn::NUM_SIGNAL_DIRECTIONS]; // TODO: unify these too\n\t\n\t// Used for some netlist traversing...\n\tmutable int sign;\n\t\n\tModuleData() :\n\t\tsign(0) {}\n\t\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Net.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct NetTagData {\n\tTristateFlag ideal;\n\tNetTypeTag type;\n\n\tNetTagData() :\n\t\ttype(NET_TYPE_TAG_NOT_SPECIFIED) {\n\t} // end constructor\n}; // end struct\n\n// -----------------------------------------------------------------------------\n\nstruct NetData : ObjectData {\n\t// Index in parent module.\n\tIndex mid;\n\n\t// User tags.\n\tNetTagData tag;\n\t\n\t// Using a vector for fast traverse, but slow insertion and removal.\n\tstd::vector<Pin> pins;\n\t\n\t// Driver. If multiple-drivers, store one of them without any assumptions.\n\tPin driver;\n\t\n\t// Parent\n\tModule parent;\n\t\n\tstd::array<int, NUM_SIGNAL_DIRECTIONS> numPinsOfType;\n\t\n\t// Helper used for netlist traversals.\n\tint sign;\n\t\n\t// Mateus @ 20190204: Adding net use;\n\tUse netUse;\n\t\n\tNetData() : \n\t\tmid(-1),\n\t\tsign(-1),\n\t\tdriver(nullptr), \n\t\tnumPinsOfType({0, 0, 0, 0}),\n\t\tparent(nullptr),\n\t\tnetUse(UNKNOWN_USE) {\n\t} // end constructor\t\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Object.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\t\t\nstruct ObjectData {\n\tIndex id;\n}; // end struct\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Pin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct PinData : ObjectData {\n\t// #> bit pack\n\tint index : 20;           // index of this pin in the library cell.\n\tDirection direction : 3;  // direction of this pin\n\tInstanceType type : 3;    // the type of instance that this pin belongs to\n\tbool boundary : 1;        // Is this pin a port? Pins belonging to both\n\t                          // Rsyn::PORT and Rsyn::MODULE are marked as boundary\n\t                          // pins.\n\t// <#\n\t\n\tint sign;\n\t\n\tInstance instance;\n\tNet net;\n\tstd::vector<Arc> arcs[NUM_TRAVERSE_TYPES];\n\tTopologicalIndex order; // topological ordering\n\n\tPinData() : \n\t\tindex(-1),\n\t\tdirection(UNKNOWN_DIRECTION),\n\t\ttype(UNKNOWN_INSTANCE_TYPE),\n\t\tboundary(false),\n\t\tsign(0),\n\t\tinstance(nullptr), \n\t\tnet(nullptr), \n\t\t\n\t\torder(std::numeric_limits<TopologicalIndex>::quiet_NaN()) {\n\t} // end constructor\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/data/Port.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\nstruct PortData {\n\t\n}; // end struct\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Arc.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist arc.\nclass Arc : public Proxy<ArcData> {\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nfriend class RawPointer;\nfriend class Design;\nprivate:\n\tArc(ArcData * data) : Proxy(data) {}\n\t\npublic:\n\n\t//! @brief Default constructor.\n\tArc() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tArc(std::nullptr_t) {}\n\n\t//! @brief Returns the name of the arc (e.g. a -> o).\n\tstd::string getName() const;\n\n\t//! @brief Returns the full name of the arc (e.g. u1:a -> u1:o).\n\tstd::string getFullName() const;\n\n\t//! @brief Returns the name of the \"from\" pin.\n\tconst std::string getFromName() const;\n\n\t//! @brief Returns the name of the \"to\" pin.\n\tconst std::string getToName() const;\t\n\n\t//! @brief Returns the design in which this arc is instantiated.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this arc is instantiated.\n\tconst Design getDesign() const;\n\n\t//! @brief Returns the type of this arc (i.e. cell or net arc).\n\tArcType getType() const;\n\n\t//! @brief Returns the instance to which this arc is associated if any. If\n\t//!        this is a net arc, returns null.\n\tInstance getInstance() const;\n\n\t//! @brief Returns the net to which this arc is associated if any. If\n\t//!        this is a cell arc, returns null.\n\tNet getNet() const;\n\n\t//! @brief Returns the library arc related to this arc if any. If this is a\n\t//!        net arc, returns null.\n\tLibraryArc getLibraryArc() const;\n\n\t//! @brief Returns the library cell related to this arc if any. If this is a\n\t//!        net arc or belong to an instance without library cell, returns\n\t//!        null.\n\tLibraryCell getLibraryCell() const;\n\n\t//! @brief Returns the \"from\" pin of this arc.\n\t//! @note  For cell arcs, the \"from\" pin is always an input pin. For net\n\t//!        arcs, the \"from\" pin is always an output (driver) pin.\n\t//!        Bidirectional pins are not handled yet.\n\tPin getFromPin() const;\n\t\n\t//! @brief Returns the \"to\" pin of this arc.\n\t//! @note  For cell arcs, the \"to\" pin is always an output pin. For net\n\t//!        arcs, the \"to\" pin is always an input (sink) pin.\n\t//!        Bidirectional pins are not handled yet.\n\tPin getToPin() const;\n\n\t//! @brief Returns the net to which the \"from\" pin connects to if any.\n\tNet getFromNet() const;\n\n\t//! @brief Returns the net to which the \"to\" pin connects to if any.\n\tNet getToNet() const;\n\n\t//! @brief Returns the index of this arc relative to its instance and\n\t//! library cell. If this arc does not belong to an instance (i.e. net arc),\n\t//! returns -1.\n\tint getIndex() const;\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Cell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist cell.\nclass Cell : public Instance {\nfriend class RawPointer;\nfriend class Design;\nfriend class Instance;\nprivate:\t\n\tCell(InstanceData * data) : Instance(data) {}\npublic:\n\n\t//! @brief Default constructor.\n\tCell() : Instance(nullptr) {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tCell(std::nullptr_t) : Instance(nullptr) {}\n\n\t//! @brief Returns the name of the library cell associated to this cell.\n\tconst std::string &getLibraryCellName() const;\n\n\t//! @brief Returns the library cell associated to this cell.\n\tLibraryCell getLibraryCell() const;\n\n\t//! @brief Returns the respective pin in this cell associated to a library\n\t//!        pin if any.\n\tPin getPinByLibraryPin(LibraryPin lpin) const;\n\n\t//! @brief Changes the library cell of this cell. The new library cell must\n\t//!        have the same interface (i.e. pin names and directions) as the\n\t//!        old one.\n\tvoid remap(LibraryCell libraryCell);\n\n\t//! @brief Changes the library cell of this cell. The new library cell must\n\t//!        have the same interface (i.e. pin names and directions) as the\n\t//!        old one.\n\tvoid remap(const std::string &libraryCellName);\n\t\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Design.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\n//! @brief A proxy class representing the design netlist.\nclass Design : public Proxy<DesignData> {\nfriend class RawPointer;\n\nfriend class Session;\nfriend class Library;\nfriend class Net;\nfriend class Cell;\nfriend class Pin;\nfriend class Instance;\nfriend class Module;\n\nfriend class Sandbox;\nfriend class SandboxNet;\nfriend class SandboxInstance;\n\ntemplate<typename _Object, typename _ObjectReference, typename _ObjectExtension> friend class AttributeBase;\ntemplate<typename _Object, typename _ObjectExtension> friend class AttributeImplementation;\n\nprivate:\n\n\tDesign(DesignData * data) : Proxy(data) {}\n\n\t//! @brief Create a new empty design.\n\tvoid create(const std::string &name);\n\npublic:\n\n\t//! @brief Default constructor.\n\tDesign() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tDesign(std::nullptr_t) {}\n\n\t//! @brief Creates a new designs.\n\tDesign(const std::string &name);\n\n\t//! @brief Copy operator.\n\t//! @note  Not sure if this is actually necessary. I don't remember why it\n\t//!        was created.\n\tDesign &operator=(const Design &other) {\n\t\tdata = other.data;\n\t\treturn *this;\n\t} // end method\t\n\n\t//! @brief Returns the top module of the design.\n\tModule getTopModule();\n\n\t//! @brief Returns the name of the design.\n\tconst std::string &getName() const;\n\n\t//! @brief Changes the name of the design.\n\tvoid updateName(std::string name);\n\t\nprivate:\n\n\t//! @brief A default string to represent the name of null objects.\n\tstatic const std::string NULL_NAME;\n\n\t//! @brief Generates an unique name for a new instance.\n\tstd::string generateUniqueInstanceName(const std::string &prefix);\n\n\t//! @brief Generates an unique name for a new net.\n\tstd::string generateUniqueNetName(const std::string &prefix);\n\n\t//! @brief Generates the next sign to be used in some traversal algorithms\n\t//!        as topological sorting.\n\tint generateNextSign();\n\n\t//! @brief Gets the current sign to be used in some traversal algorithms as\n\t//!        topological sorting.\n\tint getSign() const;\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Unique Identifiers for Rsyn Objects\n\t//--------------------------------------------------------------------------\n\t// Currently Rsyn uses unique identifiers (indexes) internally to manage \n\t// layers.\n\t//\n\t// Indexes should not be exposed to users as they are merely an internal\n\t// way to support layers and this scheme may be changed in the future.\n\t//\n\t// Layers allow users to associate data to the several Rsyn objects.\n\t// Moreover layers are aware to incremental changes in the netlist.\n\t////////////////////////////////////////////////////////////////////////////\t\nprivate:\n\n\t//! @brief Gets the internal id of a net.\n\tIndex getId(Net net) const;\n\n\t//! @brief Gets the internal id of an instance.\n\tIndex getId(Instance instance) const;\n\n\t//! @brief Gets the internal id of a pin.\n\tIndex getId(Pin pin) const;\n\n\t//! @brief Gets the internal id of an arc.\n\tIndex getId(Arc arc) const;\n\n\t//! @brief Gets the internal id of a library cell.\n\tIndex getId(LibraryCell lcell) const;\n\n\t//! @brief Gets the internal id of a library pin.\n\tIndex getId(LibraryPin lpin) const;\n\n\t//! @brief Gets the internal id of a library arc.\n\tIndex getId(LibraryArc larc) const;\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Library\n\t////////////////////////////////////////////////////////////////////////////\t\npublic:\n\n\t//! @brief Creates a new library cell.\n\tLibraryCell createLibraryCell(const CellDescriptor &dscp, const bool ignoreDuplicated = false);\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Netlist\n\t////////////////////////////////////////////////////////////////////////////\nprivate:\n\t\n\t//! @brief Instantiates a new cell inside a module.\n\tCell createCell(const Module parent, const LibraryCell lcell, const std::string &name);\n\n\t//! @brief Instantiates a new port inside a module.\n\tPort createPort(Module parent, const Direction direction, const std::string &name);\n\n\t//! @brief Creates a new module.\n\tModule createModule(const LibraryModule lmoudle, const std::string &name);\n\n\t//! @brief Instantiates a new net inside a module.\n\tNet createNet(Module parent, const std::string &name);\n\n\t//! @brief Connects a pin to a net.\n\tvoid connectPin(Pin pin, Net net);\n\n\t//! @brief Disconnect a pin.\n\tvoid disconnectPin(Pin pin);\n\n\t//! @brief Changes the library cell of a cell. The new library cell must\n\t//!        have the same interface (i.e. pin names and directions) as the\n\t//!        old one.\n\tvoid remap(Cell cell, LibraryCell newLibraryCell);\n\n\t//! @brief Changes the library cell of a cell. The new library cell must\n\t//!        have the same interface (i.e. pin names and directions) as the\n\t//!        old one.\n\tvoid remap(Cell cell, const std::string &newLibraryCellName);\n\npublic:\n\n\t//! @brief Gets the current number of instances in the design.\n\tint getNumInstances() const;\n\n\t//! @brief Gets the current number of instances of a given type in the\n\t//!        design.\n\tint getNumInstances(const InstanceType type) const;\n\n\t//! @brief Gets the current number of nets in the design.\n\tint getNumNets() const;\n\n\t//! @brief Gets the current number of pins in the design.\n\tint getNumPins() const;\n        \n        Range<ReferenceListCollection<Cell>> getAllCells() const;\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Topological Ordering\n\t////////////////////////////////////////////////////////////////////////////\nprivate:\n\n\t//! @brief Updates incrementally the topological ordering given a change in\n\t//!        a pin (e.g. pin gets connected).\n\tvoid updateTopologicalIndex(Pin pin);\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Events\n\t////////////////////////////////////////////////////////////////////////////\t\npublic:\n\n\t//! @brief Registers an observer to be notified about changes in the\n\t//!        netlist.\n\ttemplate<class T>\n\tvoid\n\tregisterObserver(T *observer);\n\n\t//! @brief Unregisters an observer so it will no longer receives\n\t//!        notifications about changes in the netlist.\n\tvoid\n\tunregisterObserver(DesignObserver *observer);\n\n\t//! @brief Notifies about a change in an instance placement. Usually this\n\t//! does not need to be done manually, but notification can be turned off\n\t//! and then observer must be manually notified.\n\t//! @todo Return also the old position.\n\tvoid\n\tnotifyInstancePlaced(Rsyn::Instance instance, Rsyn::DesignObserver *ignoreObserver = nullptr);\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Searching\n\t////////////////////////////////////////////////////////////////////////////\t\npublic:\n\n\t//! @brief Finds an instance by name. If the instance is not found, returns\n\t//!        null.\n\tInstance findInstanceByName(const std::string &name) const;\n\n\t//! @brief Finds a cell by name. If the cell is not found, returns null.\n\tCell findCellByName(const std::string &name) const;\n\n\t//! @brief Finds a port by name. If the port is not found, returns null.\n\tPort findPortByName(const std::string &name) const;\n\n\t//! @brief Finds a module by name. If the module is not found, returns\n\t//!        null.\n\tModule findModuleByName(const std::string &name) const;\n\n\t//! @brief Finds a library cell by name. If the library cell is not found,\n\t//!        returns null.\n\tLibraryCell findLibraryCellByName(const std::string &name) const;\n\n\t//! @brief Finds a net by name. If the net is not found, returns null.\n\tNet findNetByName(const std::string &name) const;\n\n\t//! @brief Finds a pin by name. If the pin is not found, returns null.\n\t//! @note  A pin name is in the form <instance>:<pin name>.\n\tPin findPinByName(const std::string &cellName, const std::string &pinName) const;\n\n\t//! @brief Finds a pin by name. If the pin is not found, returns null.\n\t//! @note  A pin name is in the form <instance>:<pin name>.\n\tPin findPinByName(const std::string &name, const std::string::value_type separator = ':') const;\t\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Attributes\n\t////////////////////////////////////////////////////////////////////////////\npublic:\n\n\t//! @brief Creates an object attribute.\n\tAttributeInitializer \n\tcreateAttribute();\n\n\t//! @brief Creates an object attribute with a default value.\n\ttemplate<typename DefaultValueType>\n\tAttributeInitializerWithDefaultValue<DefaultValueType>\n\tcreateAttribute(const DefaultValueType &defaultValue);\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// User Flags\n\t////////////////////////////////////////////////////////////////////////////\npublic:\n\n\t//! @brief Gets the tag information associate to a net.\n\tNetTag getTag(Rsyn::Net net);\n\n\t//! @brief Gets the tag information associate to an instance.\n\tInstanceTag getTag(Rsyn::Instance instance);\n\n\t//! @brief Gets the tag information associate to a library cell.\n\tLibraryCellTag getTag(Rsyn::LibraryCell libraryCell);\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Range-Based Loops\n\t////////////////////////////////////////////////////////////////////////////\n\n\t//! @brief Returns an iterable collection of all library cells in the\n\t//!        design.\n\t//! @todo  This should be removed once we concentrate everything library\n\t//!        related in Rsyn::Library.\n\tRange<ListCollection<LibraryCellData, LibraryCell>>\n\tallLibraryCells(const bool showDeprecatedMessage = true);\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Range-Based Loop Collections\n////////////////////////////////////////////////////////////////////////////////\n\n//! @brief TODO\ntemplate<class Object, class Reference, unsigned int CHUNK_SIZE>\nclass GenericListCollection {\nprotected:\n\tConstList<Object, CHUNK_SIZE> list;\n\ttypename ConstList<Object, CHUNK_SIZE>::Iterator it;\npublic:\n\tGenericListCollection(const List<Object, CHUNK_SIZE> &pins)\n\t\t\t: list(pins), it(list.begin()) {}\n\n\tbool filter() { return false; }\n\tbool stop() { return it.stopFlag(); }\n\tvoid next() { ++it; }\n\tReference current() { return &((*it).getPointer()->value); } // TODO: awful\n}; // end class\t\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\ntemplate<class Reference, unsigned int CHUNK_SIZE>\nclass GenericReferenceListCollection {\nprotected:\n\tConstList<Reference, CHUNK_SIZE> list;\n\ttypename ConstList<Reference, CHUNK_SIZE>::Iterator it;\npublic:\n\tGenericReferenceListCollection(const List<Reference, CHUNK_SIZE> &pins)\n\t\t\t: list(pins), it(list.begin()) {}\n\n\tbool filter() { return false; }\n\tbool stop() { return it.stopFlag(); }\n\tvoid next() { ++it; }\n\tReference current() { return (*it).getPointer()->value; } // TODO: awful\n}; // end class\t\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\ntemplate<class PinType>\nclass CollectionOfGenericPinsFilteredByDirection {\nprotected:\n\tstd::vector<PinType> &pins;\n\tDirection direction;\n\tint index;\n\tbool filterPG;\npublic:\n\tCollectionOfGenericPinsFilteredByDirection(std::vector<PinType> &pins,\n\t\t\tDirection direction, bool filterPG = true) \n\t\t\t: pins(pins), direction(direction), index(0), filterPG(filterPG) {}\n\n\tbool filter() { return current().getDirection() != direction || \n\t\t\t(filterPG && current().isPowerOrGround()); }\n\tbool stop() { return index >= pins.size(); }\n\tvoid next() { ++index; }\n\tPinType current() {\treturn pins[index];\t}\n}; // end class\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\ntemplate<class PinType>\nclass CollectionOfGenericPins {\nprotected:\n\tstd::vector<PinType> &pins;\n\tint index;\n\tbool filterPG;\npublic:\n\tCollectionOfGenericPins(std::vector<PinType> &pins, bool filterPG = true)\n\t\t\t: pins(pins), index(0), filterPG(filterPG) {}\n\n\tbool filter() { return filterPG && current().isPowerOrGround(); }\n\tbool stop() { return index >= pins.size(); }\n\tvoid next() { ++index; }\n\tPinType current() {\treturn pins[index];\t}\n}; // end class\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\nclass CollectionOfLibraryPinsFilteredByDirection {\nprotected:\n\tstd::vector<LibraryPin> &pins;\n\tDirection direction;\n\tint index;\npublic:\n\tCollectionOfLibraryPinsFilteredByDirection( std::vector<LibraryPin> &pins,\n\t\t\tDirection direction) \n\t\t\t: pins(pins), direction(direction), index(0) {}\n\n\tbool filter() { return current().getDirection() != direction; }\n\tbool stop() { return index >= pins.size(); }\n\tvoid next() { ++index; }\n\tLibraryPin current() {\treturn pins[index];\t}\n}; // end class\t\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\nclass CollectionOfLibraryPins {\nprotected:\n\tstd::vector<LibraryPin> &pins;\n\tint index;\npublic:\n\tCollectionOfLibraryPins(std::vector<LibraryPin> &pins) \n\t\t\t: pins(pins), index(0) {}\n\n\tbool filter() { return false; }\n\tbool stop() { return index >= pins.size(); }\n\tvoid next() { ++index; }\n\tLibraryPin current() {\treturn pins[index];\t}\n}; // end class\t\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\ntemplate<class ArcType>\nclass CollectionOfGenericArcs {\nprotected:\n\tstd::vector<ArcType> &arcs;\n\tint index;\npublic:\n\tCollectionOfGenericArcs(std::vector<ArcType> &arcs)\n\t\t\t: arcs(arcs), index(0) {}\n\n\tbool filter() { return false; }\n\tbool stop() { return index >= arcs.size(); }\n\tvoid next() { ++index; }\n\tArcType current() { return arcs[index]; }\n}; // end class\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\nclass CollectionOfLibraryArcs {\nprotected:\n\tstd::vector<LibraryArc> &arcs;\n\tint index;\npublic:\n\tCollectionOfLibraryArcs(std::vector<LibraryArc> &arcs) \n\t\t\t: arcs(arcs), index(0) {}\n\n\tbool filter() { return false; }\n\tbool stop() { return index >= arcs.size(); }\n\tvoid next() { ++index; }\n\tLibraryArc current() {\treturn arcs[index];\t}\n}; // end class\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\nclass CollectionOfLibraryArcsToLibraryPin {\nprotected:\n\tconst std::vector<LibraryArc> &arcs;\n\tLibraryPin to;\n\tsize_t index;\npublic:\n\tCollectionOfLibraryArcsToLibraryPin(const std::vector<LibraryArc> &arcs, LibraryPin to) \n\t: arcs(arcs), to(to) {\n\t\tindex = 0;\n\t} // end constructor\n\n\tbool filter() { return arcs[index].getToLibraryPin() != to; }\n\tbool stop() { return index >= arcs.size(); }\n\tvoid next() { index++; }\n\tLibraryArc current() { return arcs[index]; }\n}; // end class\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\nclass CollectionOfLibraryArcsFromLibraryPin {\nprotected:\n\tconst std::vector<LibraryArc> &arcs;\n\tLibraryPin from;\n\tsize_t index;\npublic:\n\tCollectionOfLibraryArcsFromLibraryPin(const std::vector<LibraryArc> &arcs, LibraryPin from) \n\t: arcs(arcs), from(from) {\n\t\tindex = 0;\n\t} // end constructor\n\n\tbool filter() { return arcs[index].getFromLibraryPin() != from; }\n\tbool stop() { return index >= arcs.size(); }\n\tvoid next() { index++; }\n\tLibraryArc current() { return arcs[index]; }\n}; // end class\t\t\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\n//! @todo  Update this when net arcs are implemented.\ntemplate<class PinType, class NetType, class ArcType>\nclass CollectionOfGenericPredecessorPins {\nprotected:\n\tstd::vector<PinType> pins;\n\tint index;\npublic:\n\t\n\tCollectionOfGenericPredecessorPins(PinType pin, const bool crossBoundary) {\n\t\tswitch (pin.getDirection()) {\n\t\tcase IN: {\n\t\t\tNetType net = pin.getNet();\n\t\t\tif (net) {\n\t\t\t\tpins.reserve(net.getNumDrivers());\n\t\t\t\tfor (PinType predecessor : net.allPins(DRIVER)) {\n\t\t\t\t\tpins.push_back(predecessor);\n\t\t\t\t} // end for\n\t\t\t} // end if\n\t\t\tbreak;\n\t\t} // end case\n\n\t\tcase OUT: {\n\t\t\tif (pin.isPort()) {\n\t\t\t\t// An output pin means an input port.\n\t\t\t\tif (crossBoundary) {\n\t\t\t\t\tPinType related = pin.getPort().getOtherPin(pin);\n\t\t\t\t\tif (related) {\n\t\t\t\t\t\tpins.push_back(related);\n\t\t\t\t\t} // end if\t\t\t\t\n\t\t\t\t} // end if\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\tfor (ArcType arc : pin.allIncomingArcs()) {\n\t\t\t\t\tpins.push_back(arc.getFromPin());\n\t\t\t\t} // end for\n\t\t\t}\n\t\t\tbreak;\n\t\t} // end case\n\n\t\tdefault:\n\t\t\tstd::cout << \"[ERROR] 1e1673fccd9b42d225b502a273cb3a20\\n\";\n\t\t\tstd::exit(1);\n\t\t} // end switch\n\t\t\n\t\tindex = 0;\n\t} // end constructor\n\n\tbool filter() { return false; }\n\tbool stop() { return index >= pins.size(); }\n\tvoid next() { ++index; }\n\tPinType current() {\treturn pins[index];\t}\n}; // end class\t\n\n// -------------------------------------------------------------------------\n\n//! @brief TODO\n//! @todo  Update this when net arcs are implemented.\ntemplate<class PinType, class NetType, class ArcType>\nclass CollectionOfGenericSuccessorPins {\nprotected:\n\tstd::vector<PinType> pins;\n\tint index;\npublic:\n\tCollectionOfGenericSuccessorPins(PinType pin, const bool crossBoundary) {\n\t\t\n\t\tswitch (pin.getDirection()) {\n\t\tcase IN: {\n\t\t\tif (pin.isPort()) {\n\t\t\t\t// An input pin means an output port.\n\t\t\t\tif (crossBoundary) {\n\t\t\t\t\tPinType related = pin.getPort().getOtherPin(pin);\n\t\t\t\t\tif (related) {\n\t\t\t\t\t\tpins.push_back(related);\n\t\t\t\t\t} // end if\t\t\t\t\n\t\t\t\t} // end if\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\tfor (ArcType arc : pin.allOutgoingArcs()) {\n\t\t\t\t\tpins.push_back(arc.getToPin());\n\t\t\t\t} // end for\n\t\t\t} // end else\n\t\t\tbreak;\n\t\t} // end case\n\n\t\tcase OUT: {\n\t\t\tNetType net = pin.getNet();\n\t\t\tif (net) {\n\t\t\t\tpins.reserve(net.getNumSinks());\n\t\t\t\tfor (PinType successor : net.allPins(SINK)) {\n\t\t\t\t\tpins.push_back(successor);\n\t\t\t\t} // end for\n\t\t\t} // end if\n\t\t\tbreak;\n\t\t} // end case\n\n\t\tdefault:\n\t\t\tstd::cout << \"[ERROR] 44167c065ebd3a23a553fdd96301831e\\n\";\n\t\t\tstd::exit(1);\n\t\t} // end switch\t\t\t\t\n\t\n\t\tindex = 0;\n\t} // end constructor\n\n\tbool filter() { return false; }\n\tbool stop() { return index >= pins.size(); }\n\tvoid next() { ++index; }\n\tPinType current() { return pins[index];\t}\n}; // end class\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Instance.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist instance (i.e. cell, port or\n//!        module).\nclass Instance : public Proxy<InstanceData> {\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Pin;\nfriend class Cell;\nfriend class Port;\nfriend class Module;\n\n// Temporary while we merge some physical data into the netlist (2018/01/17).\nfriend class PhysicalDesign;\nfriend class PhysicalService;\n\nprivate:\n\tInstance(InstanceData * data) : Proxy(data) {}\n\n\tDesignData * _getDesignData() const;\n\tDesign _getDesign() const;\n\tModule _getParent() const;\n\n\t// TODO: remove, use -> instead\n\tDesignData * getDesignData();\n\tconst DesignData * getDesignData() const;\n\t\npublic:\n\n\t//! @brief Default constructor.\n\tInstance() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tInstance(std::nullptr_t) {}\t\n\n\t//! @brief Converts this instance to a cell.\n\tCell asCell() const;\n\n\t//! @brief Converts this instance to a port.\n\tPort asPort() const;\n\n\t//! @brief Converts this instance to a module.\n\tModule asModule() const;\n\n\t//! @brief Returns the design in which this instance is instantiated.\n\tDesign getDesign();\n\t\n\t//! @brief Returns the design in which this instance is instantiated.\n\tconst Design getDesign() const;\n\n\t//! @brief Returns the parent module in which this instance is instantiated.\n\tModule getParent();\n\n\t//! @brief Returns the parent module in which this instance is instantiated.\n\tconst Module getParent() const;\n\n\t//! @brief Returns the type of this instance.\n\tInstanceType getType() const;\n\n\t//! @brief Returns the name of this instance.\n\tconst std::string &getName() const;\n\n\t//! @brief Returns the hierarchical name of this instance.\n\tstd::string getHierarchicalName() const;\n\n\t//! @brief Returns the number of interface pin.\n\tint getNumPins() const;\n\n\t//! @brief Returns the number of interface pin of a given direction.\n\tint getNumPins(const Direction direction) const;\n\n\t//! @brief Returns the number of interface input pin.\n\tint getNumInputPins() const;\n\n\t//! @brief Returns the number of interface output pin.\n\tint getNumOutputPins() const;\n\n\t//! @brief Returns the number of interface bidirectional pin.\n\tint getNumBidirectionalPins() const;\n\n\t//! @brief Returns the number of arcs.\n\tint getNumArcs() const;\n\n\t//! @brief Returns a pin by its index.\n\tPin getPinByIndex(const int index) const;\n\n\t//! @brief Returns a pin by its name. If no pin matches, null is returned.\n\tPin getPinByName(const std::string &name) const;\n\n\t//! @brief Returns any input pin. Useful when handling buffers/inverters,\n\t//!        which have only one input pin.\n\tPin getAnyInputPin() const;\n\n\t//! @brief Returns any output pin. Useful when handling buffers/inverters,\n\t//!        which have only one output pin.\n\tPin getAnyOutputPin() const;\n\n\t//! @brief Returns the arc from the \"from\" pin to the \"to\" pin. Returns null\n\t//!        if the pins do not belong to this instance or if no such arc is\n\t//!        found.\n\tArc getArc(const Pin from, const Pin to);\n\n\t//! @brief Returns the arc from the \"from\" pin to the \"to\" pin. Returns null\n\t//!        if either pin is not found or if no such arc exist between the\n\t//!        pins.\n\tArc getArcByPinNames(const std::string &from, const std::string &to);\n\n\t//! @brief Returns any arc. Useful when handling buffers/inverters, which\n\t//!        have only one arc.\n\tArc getAnyArc();\n\n\t//! @brief Returns the library cell associated to this instance if any.\n\tLibraryCell getLibraryCell() const;\n\n\t//! @brief Returns the topological index of this instance.\n\t//! @note  Since the topological index of an instance may be ambiguous (e.g.\n\t//!        for register), some choice needed to be made here. Currently,\n\t//!        the topological index of an instance is the maximum topological\n\t//!        index of the \"from\" pins of its arcs. If no arcs, the topological\n\t//!        index is set to the maximum topological index of all pins.\n\t//!        In this way, the topological index of registers is given by their\n\t//!        clock pin rather than by their data pin.\n\tTopologicalIndex getTopologicalIndex() const;\n\n\t//! @brief Returns true if this instance represents a port.\n\tbool isPort() const;\n\n\t//! @brief Returns true if this instance represents a port and the port\n\t//!        matches the given direction.\n\tbool isPort(const Direction direction);\n\n\t//! @brief Returns an iterable collection of all interface pins of a given\n\t//!        direction.\n\t//! @note  The name of this method may be confusing for modules where one\n\t//!        may expect the collection of all pins inside the module. However\n\t//!        to be consistent, only the interface pins are returned that is\n\t//!        the outer pins of the module's ports.\n\tRange<CollectionOfPinsFilteredByDirection>\n\tallPins(const Direction direction, bool filterPG = true) const;\n\n\t//! @brief Returns an iterable collection of all interface pins.\n\t//! @see allPins(const Direction direction)\n\tRange<CollectionOfPins>\n\tallPins(bool filterPG = true) const;\t\n\n\t//! @brief Returns an iterable collection of all arcs.\n\tRange<CollectionOfArcs>\n\tallArcs() const;\n\n\t//! @brief Returns true if this instance represents a sequential cell and\n\t//!        false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isSequential() const;\n\n\t//! @brief Returns true if this instance represents a tie cell and false\n\t//!        otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isTie(const TieType type) const;\n\n\t//! @brief Returns true if this instance represents a buffer cell of a given\n\t//!        type and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isBuffer(const BufferType type) const;\n\n\t//! @brief Returns true if this instance represents a buffer cell of a given\n\t//!        type, which is driven by a clock network and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isClockBuffer(const BufferType type = ANY_BUFFER_TYPE, const bool local = false) const;\n\n\t//! @brief Returns true if this instance represents a local clock buffer of\n\t//!        a given type and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isLCB(const BufferType type = ANY_BUFFER_TYPE) const;\n\n\t//! @brief Returns true if this instance cannot be moved (i.e. has its\n\t//!        position fixed) and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isFixed() const;\n\n\t//! @brief Returns true if this instance can be moved and false otherwise.\n\t//! @see   isFixed()\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isMovable() const;\n\n\t//! @brief Returns true if this instance represents a non-standard-cell and\n\t//!        false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isMacroBlock() const;\n\n\t//! @brief Returns true if this instance orientation is flipped.\n\t//! @see   isFlipped()\n\tbool isFlipped() const;\n\t\n\t//! @brief Returns the x position (lower-left) of the instance.\n\tDBU getX() const;\n\n\t//! @brief Returns the y position (lower-left) of the instance.\n\tDBU getY() const;\n\n\t//! @brief Returns the height of this instance.\n\tDBU getHeight() const;\n\n\t//! @brief Returns the width of this instance.\n\tDBU getWidth() const;\n\n\t//! @brief Returns the size of this instance.\n\t//! @note  X is the length for abscissa (width) while in Y is the length for\n\t//!        ordinate (height).\n\tDBUxy getSize() const;\n\n\t//! @brief Returns the size of this instance.\n\t//! @todo Rename to getSize().\n\tDBU getSize(const Dimension dimension) const;\n\n\t//! @brief Returns the area of this instance.\n\tDBU getArea() const;\n\n\t//! @brief Returns the lower-left position of this instance.\n\tDBUxy getPosition() const;\n\n\t//! @brief Returns the lower-left position of this instance.\n\t//! that is defined as its position.\n\tDBU getPosition(const Dimension dim) const;\n\n\t//! @brief Returns the lower-left/upper-right position of this instance.\n\t//! @todo remove\n\tDBUxy getCoordinate(const Boundary bound) const;\n\n\t//! @brief Returns the lower-left/upper-right position of this instance.\n\t//! @todo remove\n\tDBU getCoordinate(const Boundary bound, const Dimension dim) const;\n\n\t//! @brief Returns the central point of the PhysicalInstance boundaries.\n\tDBUxy getCenter() const;\n\n\t//! @brief Returns the center position in a given dimension.\n\tDBU getCenter(const Dimension dim) const;\n\n\t//! @brief Returns the orientation of the cell.\n\tPhysicalOrientation getOrientation() const;\n\n\t//! @brief Returns a transformation that allows one to transform the\n\t//! coordinates from the library cell space to the cell space. The\n\t//! transformation accounts for translation and the orientation of the cell.\n\t//! @param origin If set to true, the transform is created w.r.t (0, 0) and\n\t//! not the current cell position.\n\tPhysicalTransform getTransform(const bool origin = false) const;\n\n\t//! @brief Returns the bound box Bounds that defines the limits of PhysicalInstance.\n\tconst Bounds &getBounds() const;\n\n}; // end class\n\n// =============================================================================\n// Tag\n// =============================================================================\n\n//! @brief TODO\nclass InstanceTag : public Proxy<InstanceTagData> {\nfriend class Design;\nprivate:\t\n\tInstanceTag(InstanceTagData * data) : Proxy(data) {}\n\t\npublic:\n\t\n\tInstanceTag() {}\n\tInstanceTag(std::nullptr_t) {}\n\n\tTristateFlag getFixed() const;\n\tTristateFlag getMacroBlock() const;\n\n\tvoid setFixed(const bool value);\n\tvoid setMacroBlock(const bool value);\n}; // end class\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Library.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\n//! @brief A proxy class representing the library (or set of libraries).\n//! @note  For now this class is kinda dummy and uses the design to do\n//! everything. It should gain importance when we separate more clearly design\n//! and library data.\nclass Library : public Proxy<LibraryData> {\nfriend class Session;\npublic:\n\tLibrary() {}\n\n\t//! @brief Returns an iterable collection of all library cells in the\n\t//!        design.\n\t//! @todo  This should be removed once we concentrate everything library\n\t//!        related in Rsyn::Library.\n\tRange<ListCollection<LibraryCellData, LibraryCell>>\n\tallLibraryCells();\n\nprivate:\n\n\tLibrary(LibraryData * data) : Proxy(data) {}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\n} // end method"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/LibraryArc.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a library arc.\nclass LibraryArc : public Proxy<LibraryArcData> {\n\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\n\nfriend class Design;\nfriend class Arc;\nfriend class Sandbox;\nfriend class SandboxArc;\n\nprivate:\n\tLibraryArc(LibraryArcData * data) : Proxy(data) {}\n\npublic:\n\n\t//! @brief Default constructor.\n\tLibraryArc() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tLibraryArc(std::nullptr_t) {}\t\n\n\t//! @brief Returns the design in which this library arc was created.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this library arc was created.\n\tconst Design getDesign() const;\t\n\n\t//! @brief Returns the name of this libary arc (e.g a -> o).\n\tstd::string getName() const;\n\n\t//! @brief Returns the full name of this libary arc (e.g nand:a -> nand:o).\n\tstd::string getFullName() const;\n\n\t//! @brief Returns the name of the \"from\" library pin.\n\tstd::string getFromName() const;\n\n\t//! @brief Returns the name of the \"to\" library pin.\n\tstd::string getToName() const;\n\n\t//! @brief Returns the library cell to which this library arc belongs to.\n\tLibraryCell getLibraryCell() const;\n\n\t//! @brief Returns the \"from\" library pin.\n\tLibraryPin getFromLibraryPin() const;\n\n\t//! @brief Returns the \"to\" library pin.\n\tLibraryPin getToLibraryPin() const;\n\n\t//! @brief Returns the index of this arc relative to the library cell.\n\tint getIndex() const;\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/LibraryCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a library cell.\nclass LibraryCell : public Proxy<LibraryCellData> {\n\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Pin;\nfriend class Cell;\nfriend class Sandbox;\nfriend class SandboxPin;\nfriend class SandboxCell;\nfriend class PhysicalDesign;\n\nprivate:\n\tLibraryCell(LibraryCellData * data) : Proxy(data) {}\n\npublic:\n\n\t//! @brief Default constructor.\n\tLibraryCell() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tLibraryCell(std::nullptr_t) {}\t\n\n\t//! @brief Returns the design in which this library cell was created.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this library cell was created.\n\tconst Design getDesign() const;\t\n\n\t//! @brief Returns the name of this library cell.\n\tconst std::string &getName() const;\n\n\t//! @brief Returns the number of interface pin.\n\tint getNumPins() const;\n\n\t//! @brief Returns the number of interface pin of a given direction.\n\tint getNumPins(const Direction direction) const;\n\n\t//! @brief Returns the number of interface input pin.\n\tint getNumInputPins() const;\n\n\t//! @brief Returns the number of interface output pin.\n\tint getNumOutputPins() const;\n\n\t//! @brief Returns the number of interface bidirectional pin.\n\tint getNumBidirectionalPins() const ;\t\n\n\t//! @brief Returns the number of arcs.\n\tint getNumArcs() const;\n\n\t//! @brief Returns a library pin by its index.\n\tLibraryPin getLibraryPinByIndex(const int index) const;\n\n\t//! @brief Returns a library pin by its name. If no pin matches, null is\n\t//!        returned.\n\tLibraryPin getLibraryPinByName(const std::string &name) const;\n\n\t//! @brief Returns any input library pin. Useful when handling\n\t//!        buffers/inverters, which have only one input pin.\n\tLibraryPin getAnyInputLibraryPin();\n\n\t//! @brief Returns any output library pin. Useful when handling \n\t//!        buffers/inverters, which have only one output pin.\n\tLibraryPin getAnyOutputLibraryPin();\n\n\t//! @brief Returns the library arc from the \"from\" pin to the \"to\" pin. \n\t//!        Returns null if the library pins do not belong to this instance\n\t//!        or if no such arc is found.\n\tLibraryArc getLibraryArc(const Rsyn::LibraryPin from, const Rsyn::LibraryPin to) const;\n\n\t//! @brief Returns the library arc by its index.\n\tLibraryArc getLibraryArcByIndex(const int index) const;\n\n\t//! @brief Returns the library arc from the \"from\" pin to the \"to\" pin. \n\t//!        Returns null if either pin is not found or if no such arc exist \n\t//!        between the pins.\n\tLibraryArc getLibraryArcByPinNames(const std::string &from, const std::string &to) const;\n\n\t//! @brief Returns any arc. Useful when handling buffers/inverters, which\n\t//!        have only one arc.\n\tLibraryArc getAnyLibraryArc() const;\n\n\t//! @brief Returns an iterable collection of all interface library pins of \n\t//!        a given direction.\n\tRange<CollectionOfLibraryPinsFilteredByDirection>\n\tallLibraryPins(const Direction direction) const;\n\n\t//! @brief Returns an iterable collection of all interface library pins.\n\tRange<CollectionOfLibraryPins>\n\tallLibraryPins() const;\t\t\n\t\n\t//! @brief Returns an iterable collection of all arcs.\n\tRange<CollectionOfLibraryArcs>\n\tallLibraryArcs() const;\t\n\n\t//! @brief Returns true if this library cell represents a sequential cell \n\t//!        and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isSequential() const;\n\n\t//! @brief Returns true if this library cell represents a combinational cell\n\t//!        and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isCombinational() const;\n\n\t//! @brief Returns true if this library cell represents a tie cell and false\n\t//!        otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isTie(const TieType type = ANY_TIE_TYPE) const;\n\n\t//! @brief Returns true if this library cell represents a buffer cell of a\n\t//!        given type and false otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isBuffer(const BufferType type) const;\n\n\t// Physical\n\t// --------\n\n\t//! @brief Returns the Instance height.\n\tDBU getHeight() const;\n\n\t//! @brief Returns the Instance width.\n\tDBU getWidth() const;\n\n\t//! @brief Returns the size of this library cell.\n\tDBUxy getSize() const;\n\n\t//! @brief Returns the size of the library cell in a given dimension.\n\tDBU getSize(const Dimension dimension) const;\n\n\t//! @brief Returns the area of this library cell.\n\tDBU getArea() const;\n\n}; // end class\n\n// =============================================================================\n// Tag\n// =============================================================================\n\n//! @brief TODO\nclass LibraryCellTag : public Proxy<LibraryCellTagData> {\nfriend class Design;\nprivate:\n\tLibraryCellTag(LibraryCellTagData * data) : Proxy(data) {}\n\npublic:\n\n\tLibraryCellTag() {}\n\tLibraryCellTag(std::nullptr_t) {}\n\n\tLogicTypeTag getLogicType() const;\n\tTieTypeTag getTieType() const;\n\tBufferTypeTag getBufferTypeTag() const;\n\n\tvoid setLogicType(const LogicTypeTag value);\n\tvoid setTieType(const TieTypeTag value);\n\tvoid setBufferType(const BufferTypeTag value);\n}; // end class\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/LibraryModule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a library module\n//! @note  This is not used yet.\nclass LibraryModule : public Proxy<LibraryModuleData> {\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\n\nprivate:\n\tLibraryModule(LibraryModuleData * data) : Proxy(data) {}\n\npublic:\n\n\t//! @brief Default constructor.\n\tLibraryModule() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tLibraryModule(std::nullptr_t) {}\t\n\n\t//! @brief Returns the design in which this library module was created.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this library module was created.\n\tconst Design getDesign() const;\t\n\t\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/LibraryPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a library arc.\nclass LibraryPin : public Proxy<LibraryPinData> {\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Cell;\nfriend class Sandbox;\nfriend class SandboxCell;\n\nprivate:\n\tLibraryPin(LibraryPinData * data) : Proxy(data) {}\n\t\npublic:\n\n\t//! @brief Default constructor.\n\tLibraryPin() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tLibraryPin(std::nullptr_t) {}\t\n\n\t//! @brief Returns the design in which this library pin was created.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this library pin was created.\n\tconst Design getDesign() const;\t\n\n\t//! @brief Returns the name of this library pin.\n\tconst std::string &getName() const;\n\n\t//! @brief Returns the names of this library cell and pin .\n\tstd::string getHierarchicalName(const std::string & separator = \":\") const;\n\t\n\t//! @brief Returns the direction name of this library pin.\n\tconst std::string &getDirectionName() const;\n\n\t//! @brief Returns the library cell name associated to this library pin.\n\tconst std::string &getLibraryCellName() const;\n\n\t//! @brief Returns the direction of this library pin.\n\tDirection getDirection() const;\n\n\t//! @brief Returns the library cell of this library pin.\n\tLibraryCell getLibraryCell() const;\n\n\t//! @brief Returns the index of this library pin inside its library cell.\n\tint getIndex() const;\n\n\t//! @brief Returns true if this library pin is an input and false otherwise.\n\tbool isInput() const;\n\n\t//! @brief Returns true if this library pin is an output and false\n\t//!        otherwise.\n\tbool isOutput() const;\n\n\t//! @brief Returns true if this library pin is a bidirectional and false\n\t//!        otherwise.\n\tbool isBidirectional() const;\n\t\n\t//! @Author Mateus\n\t//! @brief Returns the usage of the pin\n\tUse getUse() const;\n\t\n\t//! @Author Mateus\n\t//! @brief Returns true if the pin is used for power or ground or false\n\t//!        otherwise.\n\tbool isPowerOrGround() const;\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Module.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist module.\nclass Module : public Instance {\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Instance;\n\nprivate:\n\tModule(InstanceData * data) : Instance(data) {}\n\n\t//! @brief Generates the next sign to be used in some traversal algorithms\n\t//!        as topological sorting.\n\tint generateNextSign() const;\n\n\t//! @brief Gets the current sign to be used in some traversal algorithms as\n\t//!        topological sorting.\n\tint getSign() const;\n\n\t//! @brief This method is inherited from Instance. Hide to avoid confusion\n\t//!        with internal pins. See allInterfacePins() and allInternalPins().\n\tRange<CollectionOfPinsFilteredByDirection>\n\tallPins(const Direction direction) const;\n\n\t//! @brief This method is inherited from Instance. Hide to avoid confusion\n\t//!        with internal pins. See allInterfacePins() and allInternalPins().\n\tRange<CollectionOfPins>\n\tallPins() const;\n\n\t//! @brief This method is inherited from Instance. Hide to avoid confusion\n\t//!        with internal pins. See allInterfaceArcs() and allInternalArcs().\n\tRange<CollectionOfArcs>\n\tallArcs() const;\n\npublic:\n\n\t//! @brief Default constructor.\n\tModule() : Instance(nullptr) {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tModule(std::nullptr_t) : Instance(nullptr) {}\n\n\t//! @brief Returns the design in which this module is instantiated.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this module is instantiated.\n\tconst Design getDesign() const;\n\n\t//! @brief Creates a new cell in this module. If no name is provided, an\n\t//!        automatically generated name will be used.\n\tCell createCell(const std::string &libraryCellName, const std::string &cellName = \"\");\n\n\t//! @brief Creates a new cell in this module. If no name is provided, an\n\t//!        automatically generated name will be used.\n\tCell createCell(const LibraryCell lcell, const std::string &name = \"\");\n\n\t//! @brief Creates a new port in this module. If no name is provided, an\n\t//!        automatically generated name will be used.\n\tPort createPort(const Direction &direction, const std::string &name = \"\");\n\n\t//! @brief Creates a new net in this module. If no name is provided, an\n\t//!        automatically generated name will be used.\n\tNet createNet(const std::string &name = \"\");\n\n\t//! @brief Returns a port by its index.\n\tPort getPortByIndex(const int index);\n\n\t//! @brief Constructs a vector of instances stratified by logical depth such\n\t//!        that all cells with logical depth \"i\" will be at index \"i\".\n\t//! @note  See Instance::getTopologicalIndex() description to check how\n\t//!        the topological index of instances is defined.\n\tvoid getInstancesPerLogicalDepth(std::vector<std::vector<Rsyn::Instance>> &levels);\n\n\t//! @brief Constructs a vector of nets stratified by logical depth such\n\t//!        that all nets with logical depth \"i\" will be at index \"i\".\n\t//! @note  See Net::getTopologicalIndex() description to check how\n\t//!        the topological index of nets is defined.\n\tvoid getNetsPerLogicalDepth(std::vector<std::vector<Rsyn::Net>> &levels);\n\n\t//! @brief Returns the number of ports of a given directions.\n\tint getNumPorts(const Direction direction) const;\n\n\t//! @brief Returns an iterable collection of all instances instantiated in\n\t//!        this module.\n\tRange<ReferenceListCollection<Instance>>\n\tallInstances() const;\n\n\t//! @brief Returns an iterable collection of all ports instantiated in this\n\t//!        module.\n\tRange<ReferenceListCollection<Port>>\n\tallPorts() const;\n\n\t//! @brief Returns an iterable collection of all ports of a given direction\n\t//!        inside this module.\n\tstd::set<Port> &\n\tallPorts(const Rsyn::Direction direction) const;\n\n\t//! @brief Returns an iterable collection of all nets instantiated in this\n\t//!        module.\n\tRange<ReferenceListCollection<Net>>\n\tallNets() const;\n\n\t//! @brief Returns an iterable collection of all interface pins of a given\n\t//!        direction.\n\tRange<CollectionOfPinsFilteredByDirection>\n\tallInterfacePins(const Direction direction) const;\n\n\t//! @brief Returns an iterable collection of all interface pins (i.e. outer\n\t//!        pin of ports.\n\t//! @see   allInterfacePins(const Direction direction)\n\tRange<CollectionOfPins>\n\tallInterfacePins() const;\n\n\t//! @brief Returns an iterable collection of all arcs.\n\tRange<CollectionOfArcs>\n\tallInterfaceArcs() const;\n\n\t//! @brief Returns an iterable collection of all pins of instances that are\n\t//!        directly child of this module.\n\tRange<CollectionOfPinsFilteredByDirection>\n\tallInternalPins(const Direction direction) const;\n\n\t//! @brief Returns an iterable collection of all pins of instances that are\n\t//!        directly child of this module.\n\tRange<CollectionOfPins>\n\tallInternalPins() const;\n\n\t//! @brief Returns an iterable collection of all arcs of instances that are\n\t//!        directly child of this module.\n\tRange<CollectionOfArcs>\n\tallInternalArcs() const;\n\n\t//! @brief Returns an iterable collection of all pins instantiated in this\n\t//!        module in topological order (from inputs to outputs).\n\tstd::vector<TupleElement<1, TopologicalIndex, Pin>>\n\tallPinsInTopologicalOrder() const;\n\n\t//! @brief Returns an iterable collection of all pins instantiated in this\n\t//!        module in reverse topological order (from outputs to inputs).\n\tstd::vector<TupleElement<1, TopologicalIndex, Pin>>\n\tallPinsInReverseTopologicalOrder() const;\n\n\t//! @brief Returns an iterable collection of all nets instantiated in this\n\t//!        module in topological order (from inputs to outputs).\n\t//! @note  See Net::getTopologicalIndex() description to check how\n\t//!        the topological index of nets is defined.\n\tstd::vector<TupleElement<1, TopologicalIndex, Net>>\n\tallNetsInTopologicalOrder() const;\n\n\t//! @brief Returns an iterable collection of all nets instantiated in this\n\t//!        module in reverse topological order (from outputs to inputs).\n\t//! @note  See Net::getTopologicalIndex() description to check how\n\t//!        the topological index of nets is defined.\n\tstd::vector<TupleElement<1, TopologicalIndex, Net>>\n\tallNetsInReverseTopologicalOrder() const;\n\n\t//! @brief Returns an iterable collection of all instances instantiated in\n\t//!        this module in topological order (from inputs to outputs).\n\t//! @note  See Instance::getTopologicalIndex() description to check how\n\t//!        the topological index of instances is defined.\n\tstd::vector<TupleElement<1, TopologicalIndex, Instance>>\n\tallInstancesInTopologicalOrder() const;\n\n\t//! @brief Returns a vector with the nets in the fanout cone of a pin. The\n\t//!        nets are sorted in breadth-first order (which is not the same as\n\t//!        topological order). Breadth-first order is typically faster than\n\t//!        topological order. If not null, the first net is always the net\n\t//!        to which the seed pins is connected to.\n\tstd::vector<Rsyn::Net>\n\tgetFanoutConeNetsInBreadthFirstOrder(Rsyn::Pin seed) const;\n\n\t//! @brief Returns a vector with the nets in the fan-in cone of a pin. The \n\t//!        nets are sorted in breadth-first order (which is not the same as\n\t//!        topological order). Breadth-first order is typically faster than\n\t//!        topological order. If not null, the first net is always the net\n\t//!        to which the seed pins is connected to.\n\tstd::vector<Rsyn::Net>\n\tgetFaninConeNetsInBreadthFirstOrder(Rsyn::Pin seed) const;\n\t\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Net.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist net.\nclass Net : public Proxy<NetData> {\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Module;\nfriend class Pin;\nfriend class Arc;\n\nprivate:\n\tNet(NetData * data) : Proxy(data) {}\n\t\n\tDesign _getDesign() const;\n\tModule _getParent() const;\t\t\t\n\t\npublic:\n\n\t//! @brief Default constructor.\n\tNet() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tNet(std::nullptr_t) {}\n\n\t//! @brief Returns the design in which this net was instantiated.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this net was instantiated.\n\tconst Design getDesign() const;\n\n\t//! @brief Returns the parent module in which this net was instantiated.\n\tModule getParent();\n\n\t//! @brief Returns the parent module in which this net was instantiated.\n\tconst Module getParent() const;\n\n\t//! @brief Returns the name of this net.\n\tconst std::string &getName() const;\n\n\t//! @brief Returns the number of pins connected to this net.\n\tint getNumPins() const;\n\n\t//! @brief Returns the number of sinks (input) pins connected to this net.\n\tint getNumSinks() const;\n\n\t//! @brief Returns the number of drivers (output) pins connected to this\n\t//!        net.\n\tint getNumDrivers() const;\n\n\t//! @brief Returns any driver pin if any. Useful when there's an assumption\n\t//!        that nets have a single driver (most common case).\n\tPin getAnyDriver() const;\n\n\t//! @brief Returns the arc connecting the \"from\" pin to the \"to\" pin if any.\n\t//! @note  Net arcs only exist from driver to sink pins.\n\tArc getArc(const Pin from, const Pin to);\n\n\t//! @brief Returns the topological index of this net.\n\t//! @note  The topological index of a net is the maximum topological index\n\t//!        of its drivers. If no drivers, it's the maximum topological index\n\t//!        of its sinks. If this is a floating net (no pins), returns the\n\t//!        constant value Rsyn::MIN_TOPOLOGICAL_INDEX.\n\tTopologicalIndex getTopologicalIndex() const;\n\n\t//! @brief Returns true if this net has more than one driver pin and false\n\t//!        otherwise.\n\tbool hasMultipleDrivers() const;\n\n\t//! @brief Returns true if this net has only and only one driver and false\n\t//!        otherwise.\n\tbool hasSingleDriver() const;\n\n\t//! @brief Returns true if this net has at least one driver and false\n\t//!        otherwise.\n\tbool hasDriver() const;\n\n\t//! @brief Returns true if this net has at least one sink and false\n\t//!        otherwise.\n\tbool hasSink() const;\n\n\t//! @brief Returns an iterable collection of the pins connected to this\n\t//!        net.\n\tRange<CollectionOfPins>\n\tallPins(bool filterPG = true) const;\n\n\t//! @brief Returns an iterable collection of the pins of a given direction\n\t//!        connected to this net.\n\tRange<CollectionOfPinsFilteredByDirection>\n\tallPins(const Direction direction) const;\n\n\t//! @brief Returns an iterable collection of the arcs spanned by this net.\n\tRange<CollectionOfArcs>\n\tallArcs() const;\t\n\n\t//! @brief Returns true if this net should be considered as ideal and false\n\t//!        otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isIdeal() const;\n\n\t//! @brief Returns true if this net represents a clock network.\n\t//! @note  A clock network net does not need to be directly connected to the\n\t//!        clock port. Internal nets of a clock buffer tree should also be\n\t//!        considered as clock networks.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isClockNetwork() const;\n\n\t//! @brief Returns the type ot this net.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tNetTypeTag getNetTypeTag() const;\n\n\t//! @Author Mateus\n\t//! @brief Returns the usage of the net\n\tUse getUse() const;\n\t\n\t//! @Author Mateus\n\t//! @brief Returns the usage of the net\n\tvoid setUse(const Use use);\n}; // end class\n\n// =============================================================================\n// Tag\n// =============================================================================\n\n//! @brief TODO\nclass NetTag : public Proxy<NetTagData> {\nfriend class Design;\nprivate:\n\tNetTag(NetTagData * data) : Proxy(data) {}\n\npublic:\n\n\tNetTag() {}\n\tNetTag(std::nullptr_t) {}\n\n\tNetTypeTag getType() const;\n\tTristateFlag getIdeal() const;\n\n\tvoid setType(const NetTypeTag value);\n\tvoid setIdeal(const bool value);\n}; // end class\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Object.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n// TODO create a base class for everyone...\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Pin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist pin.\nclass Pin : public Proxy<PinData> {\t\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Port;\nfriend class Net;\n\nprivate:\n\tPin(PinData * data) : Proxy(data) {}\n\t\npublic:\n\n\t//! @brief Default constructor.\n\tPin() {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tPin(std::nullptr_t) {}\t\n\n\t//! @brief Returns the design in which this pin is instantiated.\n\tDesign getDesign();\n\n\t//! @brief Returns the design in which this pin is instantiated.\n\tconst Design getDesign() const;\t\n\n\t//! @brief Returns the direction of this pin.\n\tDirection getDirection() const;\n\n\t//! @brief Returns the index of this pin relative to its instance and\n\t//! library cell.\n\tint getIndex() const;\n\n\t//! @brief Returns the name of this pin.\n\tconst std::string getName() const;\n\n\t//! @brief Returns the full name of this pin (e.g. nand:a).\n\tconst std::string getFullName(const std::string::value_type separator = ':') const;\n\n\t//! @brief Returns the name of the instance which this pin belongs to.\n\tconst std::string getInstanceName() const;\n\n\t//! @brief Returns the name of the net which this pin connects to if any.\n\tconst std::string &getNetName() const;\n\n\t//! @brief Returns the direction name of this pin.\n\tconst std::string &getDirectionName() const;\n\n\t//! @brief Returns the net which this pin connects to if any.\n\tNet getNet() const;\n\n\t//! @brief Returns the instance which this pin belongs to.\n\tInstance getInstance() const;\n\n\t//! @brief Returns the type of the instance which this pin belongs to.\n\tInstanceType getInstanceType() const;\n\n\t//! @brief Returns the library pin associate to this pin if any.\n\t//! @note  Only pins from cells are associated to library pins.\n\tLibraryPin getLibraryPin() const;\n\n\t//! @brief Returns the library cell associate to this pin if any.\n\t//! @note  Only pins from cells are associated to library cells.\n\tLibraryCell getLibraryCell() const;\n\n\t//! @brief If this pin belongs to a port instance, returns the port and\n\t//!        null otherwise.\n\tPort getPort() const;\n\n\t//! @brief Returns the topological index of this pin.\n\tTopologicalIndex getTopologicalIndex() const;\n\n\t//! @brief Returns true if this pin belongs to a port instance.\n\tbool isPort() const;\n\n\t//! @brief Returns true if this pin belongs to a port instance of a given\n\t//!        direction.\n\tbool isPort(const Direction direction) const;\n\n\t//! @brief Returns true if this pin belongs to a port that connects to an\n\t//!        up-level hierarchy and false otherwise.\n\tbool isPortToUpLevelHierarchy() const;\n\n\t//! @brief Returns true if this pin belongs to a port that connects to an\n\t//!        down-level hierarchy and false otherwise.\n\tbool isPortToDownLevelHierarchy() const;\n\n\t//! @brief Returns true if this pin is connected to a net and false\n\t//!        otherwise.\n\tbool isConnected() const;\n\n\t//! @brief Returns true if this pin is not connected to a net and false\n\t//!        otherwise.\n\tbool isDisconnected() const;\n\n\t//! @brief Returns true if this pin is an input pin and false otherwise.\n\tbool isInput() const;\n\n\t//! @brief Returns true if this pin is an output pin and false otherwise.\n\tbool isOutput() const;\n\n\t//! @brief Returns true if this pin is a bidirectional pin and false\n\t//!        otherwise.\n\tbool isBidirectional() const;\t\n\n\t//! @brief Returns true if this pin is a driver (output) pin and false\n\t//!        otherwise.\n\tbool isDriver() const;\n\n\t//! @brief Returns true if this pin is a sink (input) pin and false\n\t//!        otherwise.\n\tbool isSink() const;\t\n\n\t//! @brief Returns the arc from this pin to the \"to\" pin if any.\n\tArc getArcTo(Pin to);\n\n\t//! @brief Returns the arc from the \"from\" pin to this pin if any.\n\tArc getArcFrom(Pin from);\n\n\t//! @brief Returns the number of arcs that have this pin as the \"to\" pin.\n\tint getNumIncomingArcs() const;\n\n\t//! @brief Returns the number of arcs that have this pin as the \"from\" pin.\n\tint getNumOutgomingArcs() const;\n\n\t//! @brief Returns an iterable collection of all pins that are directly\n\t//!        connected to this pin via incoming arcs (i.e. all \"from\" pins\n\t//!        of the arcs that have this pin as the \"to\" pin).\n\tRange<CollectionOfPredecessorPins>\n\tallPredecessorPins(const bool crossBoundaries = false) const;\n\n\t//! @brief Returns an iterable collection of all pins that are directly\n\t//!        connected to this pin via outgoing arcs (i.e. all \"to\" pins\n\t//!        of the arcs that have this pin as the \"from\" pin).\n\tRange<CollectionOfSuccessorPins>\n\tallSucessorPins(const bool crossBoundaries = false) const;\t\n\n\t//! @brief Returns an iterable collection of all arcs that have this pin as\n\t//!        the \"to\" pin.\n\tconst std::vector<Arc> &\n\tallIncomingArcs() const;\n\n\t//! @brief Returns an iterable collection of all arcs that have this pin as\n\t//!        the \"from\" pin.\n\tconst std::vector<Arc> &\n\tallOutgoingArcs() const;\n\n\t//! @brief Returns an iterable collection of all arcs given a traverse\n\t//!        direction.\n\tconst std::vector<Arc> &\n\tallArcs(const TraverseType direction) const;\n\n\t//! @brief Connects this pin to a net. If the pin is currently connected,\n\t//!        it will be first disconnected.\n\tvoid connect(Net net);\n\n\t//! @brief Disconnect this pin.\n\tvoid disconnect();\t\n\n\t//! @brief Returns true if this pin belongs to a non-standard-cell and false\n\t//!        otherwise.\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isMacroBlockPin() const;\n\n\t//! @brief Returns true if this pin is connected to a clock network and\n\t//!        false otherwise.\n\t//! @note  This should be true even if the pin is indirectly connected to\n\t//!        the clock (i.e. via buffers).\n\t//! @note  This is a user-defined flag. If the flag was not set, an exception\n\t//!        is raised.\n\tbool isConnectedToClockNetwork() const;\n\n\t//! @Author Mateus\n\t//! @brief Returns the usage of the pins\n\tUse getUse() const;\n\t\n\t//! @Author Mateus \n\t//! @brief Returns true if the pin is used for power or ground or false\n\t//!        otherwise.\n\tbool isPowerOrGround() const;\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/decl/Port.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n//! @brief A proxy class representing a netlist port.\nclass Port : public Instance {\n\t\nRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\n\nfriend class RawPointer;\nfriend class Design;\nfriend class Instance;\n\nprivate:\t\n\tPort(InstanceData * data) : Instance(data) {}\npublic:\n\n\t//! @brief Default constructor.\n\tPort() : Instance(nullptr) {}\n\n\t//! @brief Assignment constructor to allow null values.\n\tPort(std::nullptr_t) : Instance(nullptr) {}\t\n\n\t//! @brief Returns the pin inside the current level of hierarchy (module).\n\t//! @note  This pin belongs to the port instance.\n\tPin getInnerPin() const;\n\n\t//! @brief Returns the pin in the parent hierarchy (module).\n\t//! @note  This pin does not belongs to the port instance. It belongs to the\n\t//!        parent module instance. That is the outer pin is only virtually\n\t//!        associated to a port.\n\tPin getOuterPin() const; \n\n\t//! @brief Returns the inner/outer pin related to an outer/inner pin.\n\t//!        If the outer pin is passed, returns the inner pin.\n\t//!        If the inner pin is passed, returns the outer pin.\n\t//!        If the pin does not match both inner and outer pins, returns\n\t//!        null.\n\t//! @note  The outer pin may be null if the inner pin belongs to\n\t//!        a port in the top level hierarchy.\n\tPin getOtherPin(Rsyn::Pin pin) const;\n\n\t//! @brief Returns the direction of this port.\n\t//! @note  The direction of a port matches the direction of its inner pin.\n\tDirection getDirection() const;\n}; // end class\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Arc.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign \nArc::getDesign() {\n\treturn getFromPin().getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design \nArc::getDesign() const {\n\treturn getFromPin().getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArcType \nArc::getType() const {\n\treturn data->type;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nInstance \nArc::getInstance() const {\n\treturn data->type == INSTANCE_ARC? data->from.getInstance() : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet \nArc::getNet() const {\n\treturn data->type == NET_ARC? data->netData : nullptr;\n} // end method\n\t\n// -----------------------------------------------------------------------------\n\t\ninline\nLibraryArc\nArc::getLibraryArc() const {\n\treturn getType() == INSTANCE_ARC? data->libraryArcData : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell\nArc::getLibraryCell() const {\n\tRsyn::LibraryArc larc = getLibraryArc();\n\treturn larc? larc.getLibraryCell() : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin \nArc::getFromPin() const {\n\treturn data->from;\n} // end method\n\n// -----------------------------------------------------------------------------\t\n\t\ninline\nPin \nArc::getToPin() const {\n\treturn data->to;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nArc::getName() const {\n\treturn getFromName() + \"->\" + getToName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nArc::getFullName() const {\n\treturn getType() == NET_ARC?\n\t\t(getFromPin().getFullName() + \"->\" + getToPin().getFullName()) :\n\t\t(getInstance().getName() + \":\" + getName());\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string\nArc::getFromName() const {\n\treturn getFromPin().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string\nArc::getToName() const {\n\treturn getToPin().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet\nArc::getFromNet() const {\n\treturn getFromPin().getNet();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet\nArc::getToNet() const {\n\treturn getToPin().getNet();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nArc::getIndex() const {\n\treturn getLibraryArc()? getLibraryArc().getIndex() : -1;\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Cell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nconst std::string &\nCell::getLibraryCellName() const {\n\treturn data->lcell->name;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell\nCell::getLibraryCell() const {\n\treturn data->lcell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin\nCell::getPinByLibraryPin(const LibraryPin lpin) const {\n\treturn data->pins[lpin.data->index];\n} // end method\n\t\n// -----------------------------------------------------------------------------\n\ninline\nvoid \nCell::remap(LibraryCell libraryCell) {\n\tgetDesign().remap(*this, libraryCell);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid \nCell::remap(const std::string &libraryCellName) {\n\tgetDesign().remap(*this, libraryCellName);\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Design.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\t\ninline\nDesign::Design(const std::string &name) {\n\tcreate(name);\n} // end constructor\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nDesign::create(const std::string &name) {\n\t// Allocate memory for the new design.\n\t//data = std::make_shared<DesignData>();\n\tdata = new DesignData;\n\tdata->name = name;\n\t\n\t// If no top is specified, just create an empty top for the design.\n\tdata->topModule = createModule(nullptr, \"__root\");\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nModule \nDesign::getTopModule() {\n\treturn data->topModule;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nDesign::getName() const {\n\treturn data->name;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nvoid \nDesign::updateName(std::string name) {\n\tdata->name = name;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string \nDesign::generateUniqueInstanceName(const std::string &prefix) {\n\tstd::ostringstream oss;\n\toss << prefix << data->anonymousInstanceId; \n\tdata->anonymousInstanceId++;\t\n\treturn oss.str();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string \nDesign::generateUniqueNetName(const std::string &prefix) {\n\tstd::ostringstream oss;\n\toss << prefix << data->anonymousNetId; \n\tdata->anonymousNetId++;\t\n\treturn oss.str();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nDesign::generateNextSign() { \n\treturn ++data->sign; /*must be pre-increment*/ \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nDesign::getSign() const { \n\treturn data->sign; \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nInstance \nDesign::findInstanceByName(const std::string &name) const {\n\tauto it = data->instanceMapping.find(name);\n\treturn it != data->instanceMapping.end()? it->second : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nCell \nDesign::findCellByName(const std::string &name) const {\n\tRsyn::Instance instance = findInstanceByName(name);\n\tif (instance) {\n\t\treturn instance.getType() == Rsyn::CELL? instance.asCell() : nullptr;\n\t} else {\n\t\treturn nullptr;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nPort \nDesign::findPortByName(const std::string &name) const {\n\tRsyn::Instance instance = findInstanceByName(name);\n\tif (instance) {\n\t\treturn instance.getType() == Rsyn::PORT? instance.asPort() : nullptr;\n\t} else {\n\t\treturn nullptr;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nModule \nDesign::findModuleByName(const std::string &name) const {\n\tRsyn::Instance instance = findInstanceByName(name);\n\tif (instance) {\n\t\treturn instance.getType() == Rsyn::MODULE? instance.asModule() : nullptr;\n\t} else {\n\t\treturn nullptr;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell \nDesign::findLibraryCellByName(const std::string &name) const {\n\tauto it = data->libraryCellMapping.find(name);\n\treturn it != data->libraryCellMapping.end()? it->second : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet \nDesign::findNetByName(const std::string &name) const {\n\tauto it = data->netMapping.find(name);\n\treturn it != data->netMapping.end()? it->second : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nPin \nDesign::findPinByName(const std::string &cellName, const std::string &pinName) const {\n\tCell cell = findCellByName(cellName);\n\tif (cell) {\n\t\treturn cell.getPinByName(pinName);\n\t} else {\n\t\treturn nullptr;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nPin \nDesign::findPinByName(const std::string &name, const std::string::value_type separator) const {\n\tstd::size_t split = name.find_first_of(separator); \n\tif (split == std::string::npos)\n\t\treturn nullptr;\n\n\tconst std::string cellName = name.substr(0, split);\n\tconst std::string pinName = name.substr(split + 1, std::string::npos);\n\treturn findPinByName(cellName, pinName);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell \nDesign::createLibraryCell(const CellDescriptor &dscp, const bool ignoreDuplicated) {\n\tif (findLibraryCellByName(dscp.getName())) {\n\t\tif (!ignoreDuplicated) {\n\t\t\tthrow LibraryCellAlreadyExistsException(dscp.getName());\n\t\t} else {\n\t\t\treturn nullptr;\n\t\t} // end if\n\t} // end if\n\n\tconst int numPins = (int) dscp.pins.size();\n\tconst int numArcs = (int) dscp.arcs.size();\n\n\t// Check if it's valid descriptor.\n\tdscp.checkConsistency();\n\t\n\t// Creates a new cell in the data structure.\n\tLibraryCellData * lcell = &(data->libraryCells.create()->value); // TODO: awful\n\tLibraryCell libraryCell(lcell);\n\n\t// Initializes cell.\n\tlcell->id = data->libraryCells.lastId();\n\tlcell->design = *this;\n\tlcell->name = dscp.getName();\n\n\t// Stores library cell name.\n\tdata->libraryCellMapping[lcell->name] = libraryCell;\t\n\n\t// Sort pin by names to ensure same indexes among different cells with\n\t// the same footprint.\n\tstd::map<std::string, int> mapping;\n\n\tfor (int i = 0; i < numPins; i++) {\n\t\tconst std::tuple<std::string, Direction, Use> &t = dscp.pins[i];\n\t\tmapping[std::get<0>(t)] = i;\n\t} // end for\t\n\n\t// Initializes library cell's pins.\n\tlcell->pins.resize(numPins);\n\tfor (auto element : mapping) {\n\t\tconst int index = element.second;\n\t\tconst std::tuple<std::string, Direction, Use> &t = dscp.pins[index];\n\n\t\tLibraryPinData * lpin = &(data->libraryPins.create()->value); // TODO: awful\n\t\tlpin->id = data->libraryPins.lastId();\n\t\tlpin->design = *this;\n\t\tlpin->index = index;\n\t\tlpin->lcell = libraryCell;\n\t\tlpin->name = std::get<0>(t);\n\t\tlpin->direction = std::get<1>(t);\n\t\t// Mateus @ 20180917: Adding PinUse\n\t\tlpin->pinUse = std::get<2>(t);\n\n\t\tlcell->pins[index] = LibraryPin(lpin);\n\t\tswitch (std::get<1>(t)){\n\t\t\tcase IN :\n\t\t\t\tlcell->numInputPins++;\n\t\t\t\tbreak;\n\t\t\tcase OUT:\n\t\t\t\tlcell->numOutputPins++;\n\t\t\t\tbreak;\n\t\t\tcase BIDIRECTIONAL: \n\t\t\t\tlcell->numInOutPins++;\n\t\t\t\tbreak;\n\t\t} // end switch \n\t} // end for\n\n\t// Initializes library cell's pins.\n\tlcell->arcs.resize(numArcs);\n\tfor (int i = 0; i < numArcs; i++) {\t\n\t\tLibraryArcData * larc = &(data->libraryArcs.create()->value); // TODO: awful\n\t\tlarc->id = data->libraryArcs.lastId();\n\t\tlarc->design = *this;\n\t\tlarc->lcell = libraryCell;\n\t\tlarc->index = i;\n\t\tlarc->from = libraryCell.getLibraryPinByName(std::get<0>(dscp.arcs[i]));\n\t\tlarc->to = libraryCell.getLibraryPinByName(std::get<1>(dscp.arcs[i]));\n\t\t\n\t\tlcell->arcs[i] = larc;\n\t} // end for\n\t\n\treturn libraryCell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nCell \nDesign::createCell(const Module parent, const LibraryCell libraryCell, const std::string &name) {\n\tconst LibraryCellData * lcell = libraryCell.data;\n\t\n\tconst std::string &cellName = name == \"\"? \n\t\tgenerateUniqueInstanceName(\"__cell\") : name;\n\t\n\tconst int numPins = lcell->pins.size();\n\tconst int numArcs = lcell->arcs.size();\n\t\n\t// Creates a new cell in the data structure.\n\tInstanceData * instance = &(data->instances.create()->value); // TODO: awful\n\tCell cell(instance);\n\t\n\t// Initializes instance.\n\tinstance->id = data->instances.lastId();\n\tinstance->design = *this;\n\tinstance->parent = parent;\n\tinstance->lcell = const_cast<LibraryCellData *>(lcell);\n\tinstance->type = CELL;\n\tinstance->pins.resize(numPins);\n\tinstance->arcs.resize(numArcs);\n\n\t// Initializes instance's pins.\n\tfor (int i = 0; i < numPins; i++) {\n\t\tPinData * pin = &(data->pins.create()->value); // TODO: awful\n\t\tLibraryPin lpin = lcell->pins[i];\n\t\tpin->id = data->pins.lastId();\n\t\tpin->instance = cell;\n\t\tpin->direction = lpin.data->direction;\n\t\tpin->type = Rsyn::CELL;\n\t\tpin->index = lpin.data->index;\n\t\t\n\t\tinstance->pins[i] = pin;\n\t\t\n\t\tswitch (pin->direction) {\n\t\t\tcase Rsyn::IN:\n\t\t\t\tpin->order = 0;\n\t\t\t\tbreak;\n\t\t\tcase Rsyn::OUT:\n\t\t\t\tpin->order = TOPOLOGICAL_SORTING_SMALL_GAP;\n\t\t\t\tbreak;\n\t\t\tcase Rsyn::BIDIRECTIONAL:\n\t\t\t\tthrow Exception(\"Rsyn does not support bidirectional pins yet.\\n\");\n\t\t\tdefault:\n\t\t\t\tthrow Exception(\"Unknown pin direction.\\n\");\n\t\t} // end switch\n\t} // end for\n\t\n\t// Initializes cell's arcs.\n\tfor (int i = 0; i < numArcs; i++) {\n\t\tArcData * arc = &(data->arcs.create()->value); // TODO: awful\n\t\tLibraryArc larc = lcell->arcs[i];\n\t\tarc->id = data->arcs.lastId();\n\t\tarc->type = INSTANCE_ARC;\n\t\tarc->libraryArcData = larc.data;\n\t\tarc->from = cell.getPinByLibraryPin(larc.data->from);\n\t\tarc->to = cell.getPinByLibraryPin(larc.data->to);\n\t\t\t\n\t\tarc->from.data->arcs[FORWARD].push_back(Arc(arc));\n\t\tarc->to.data->arcs[BACKWARD].push_back(Arc(arc));\n\t\t\n\t\tinstance->arcs[i] = arc;\n\t} // end for\n\t\t\t\n\t// Stores cell name.\n\tif (data->instanceNames.size() <= instance->id) {\n\t\tdata->instanceNames.resize(instance->id+1);\n\t} // end if\n\n\tdata->instanceNames[instance->id] = cellName;\n\tdata->instanceMapping[cellName] = Instance(instance);\n\n\t// Records this cell in it's parent module.\n\tparent->moduleData->instances.add(cell);\n\tcell->mid = parent->moduleData->instances.lastId();\n\t\n\t// Trace the number of instances.\n\tdata->instanceCount[Rsyn::CELL]++;\n\t\n\t// Mark as dirty.\n\tdata->dirty = true;\n\t\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_POST_INSTANCE_CREATE])\n\t\tf->onPostInstanceCreate(cell);\n\t\n\t// Return\n\treturn cell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPort \nDesign::createPort(Module parent, const Direction direction, const std::string &name) {\n\tconst std::string &portName = name == \"\"? \n\t\tgenerateUniqueInstanceName(\"__cell\") : name;\n\t\n\tconst int numPins = 1;\n\tconst int numArcs = 0;\n\t\n\t// Creates a new cell in the data structure.\n\tPort port = &(data->instances.create()->value); // TODO: awful\n\n\t// Creates the outer pin which will be added to the parent module.\n\tPinData * outer = &(data->pins.create()->value); // TODO: awful\n\touter->id = data->pins.lastId();\n\touter->instance = parent;\n\touter->direction = direction;\n\touter->type = Rsyn::MODULE;\n\touter->boundary = true;\n\touter->index = parent->pins.size();\n\tparent->pins.push_back(outer);\n\t\n\t// Initializes port data.\n\tport->id = data->instances.lastId();\n\tport->design = *this;\n\tport->parent = parent;\n\tport->type = PORT;\n\tport->outerPin = outer;\n\tport->lcell = nullptr;\n\tport->pins.resize(numPins);\n\tport->arcs.resize(numArcs);\n\n\t// Creates the inner pin which will be added to the port.\n\tPinData * inner = &(data->pins.create()->value); // TODO: awful\n\tinner->id = data->pins.lastId();\n\tinner->instance = port;\n\tinner->direction = Global::getReverseDirection(direction);\n\tinner->type = Rsyn::PORT;\n\tinner->boundary = true;\n\tinner->index = 0;\n\tport->pins[0] = inner;\t\n\n\t// Topological index.\n\tswitch (direction) {\n\t\tcase Rsyn::IN:\n\t\t\touter->order = 0;\n\t\t\tinner->order = TOPOLOGICAL_SORTING_SMALL_GAP;\n\t\t\tbreak;\n\t\tcase Rsyn::OUT:\n\t\t\tinner->order = 1;\n\t\t\touter->order = 2;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow Exception(\"Port direction not supported.\");\n\t} // ens switch\n\t\n\t// Stores port (instance) name.\n\tif (data->instanceNames.size() <= port->id) {\n\t\tdata->instanceNames.resize(port->id+1);\n\t} // end if\n\n\tdata->instanceNames[port->id] = portName;\n\tdata->instanceMapping[portName] = Instance(port);\n\n\t// Records this cell in it's parent module.\n\tparent->moduleData->instances.add(port);\n\tport->mid = parent->moduleData->instances.lastId();\n\tparent->moduleData->ports.add(port);\n\tparent->moduleData->portsByDirection[direction].insert(port);\n\t\n\t// Trace the number of instances.\n\tdata->instanceCount[Rsyn::PORT]++;\t\n\t\n\t// Mark as dirty.\n\tdata->dirty = true;\t\n\t\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_POST_INSTANCE_CREATE])\n\t\tf->onPostInstanceCreate(port);\n\n\t// Return\n\treturn port;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nModule \nDesign::createModule(const LibraryModule lmoudle, const std::string &name) {\n\t// Creates a new cell in the data structure.\n\tInstanceData * instance = &(data->instances.create()->value); // TODO: awful\n\t\n\t// Initializes cell.\n\tinstance->id = data->instances.lastId();\n\tinstance->type = Rsyn::MODULE;\n\tinstance->design = *this;\n\tinstance->lcell = nullptr;\n\tinstance->moduleData = new ModuleData;\n\tinstance->moduleData->design = *this;\n\t\t\t\t\n\t// Stores instance name.\n\tif (data->instanceNames.size() <= instance->id) {\n\t\tdata->instanceNames.resize(instance->id+1);\n\t} // end if\n\n\tdata->instanceNames[instance->id] = name;\n\tdata->instanceMapping[name] = Instance(instance);\n\t\n\t// Trace the number of instances.\n\tdata->instanceCount[Rsyn::MODULE]++;\t\t\n\t\n\t// Mark as dirty.\n\tdata->dirty = true;\n\t\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_POST_INSTANCE_CREATE])\n\t\tf->onPostInstanceCreate(instance);\n\t\n\t// Return\n\treturn Module(instance);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet \nDesign::createNet(const Module parent, const std::string &name) {\n\t// Creates a new net in the data structure.\n\tNetData * net = &(data->nets.create()->value); // TODO: awful\n\t\n\t// Gets the net name.\n\tconst std::string &netName = name == \"\"? \n\t\tgenerateUniqueNetName(\"__net\") : name;\t\n\t\n\t// Initializes net.\n\tnet->id = data->nets.lastId();\n\tnet->parent = parent;\n\n\t// Stores net name.\n\tif (data->netNames.size() <= net->id) {\n\t\tdata->netNames.resize(net->id+1);\n\t} // end if\n\n\tdata->netNames[net->id] = netName;\n\tdata->netMapping[netName] = net;\n\t\t\n\t// Records this cell in it's parent module.\n\tparent->moduleData->nets.add(net);\n\tnet->mid = parent->moduleData->nets.lastId();\n\t\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_POST_NET_CREATE])\n\t\tf->onPostNetCreate(net);\n\t\n\t// Mark as dirty.\n\tdata->dirty = true;\t\n\t\n\t// Return.\n\treturn net;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid \nDesign::connectPin(Pin pin, Net net) {\n\tif (pin->net) {\n\t\tdisconnectPin(pin);\n\t} // end if\n\t\n\tnet->pins.push_back(pin);\n\tpin->net = net;\n\t\n\tnet->numPinsOfType[pin.getDirection()]++;\n\tif (pin.getDirection() == DRIVER) {\n\t\tnet->driver = pin; // cache the driver\n\t} // end if\n\n\t// Create net arcs as necessary.\n\tswitch (pin.getDirection()) {\n\t\tcase Rsyn::DRIVER: {\n\t\t\tfor (Rsyn::Pin sink : net.allPins(Rsyn::SINK)) {\n\t\t\t\tArc arc = &(data->arcs.create()->value); // TODO: awful\n\t\t\t\tarc->id = data->arcs.lastId();\n\t\t\t\tarc->type = NET_ARC;\n\t\t\t\tarc->netData = net.data;\n\t\t\t\tarc->from = pin;\n\t\t\t\tarc->to = sink;\n\n\t\t\t\tpin->arcs[FORWARD].push_back(arc);\n\t\t\t\tsink->arcs[BACKWARD].push_back(arc);\n\t\t\t} // end for\t\n\t\t\tbreak;\n\t\t} // end case\n\t\t\n\t\tcase Rsyn::SINK: {\n\t\t\tfor (Rsyn::Pin driver : net.allPins(Rsyn::DRIVER)) {\n\t\t\t\tArc arc = &(data->arcs.create()->value); // TODO: awful\n\t\t\t\tarc->id = data->arcs.lastId();\n\t\t\t\tarc->type = NET_ARC;\n\t\t\t\tarc->netData = net.data;\n\t\t\t\tarc->from = driver;\n\t\t\t\tarc->to = pin;\n\n\t\t\t\tdriver->arcs[FORWARD].push_back(arc);\n\t\t\t\tpin->arcs[BACKWARD].push_back(arc);\n\t\t\t} // end for\n\t\t\tbreak;\n\t\t} // end case\n\t\t\n\t\tdefault:\n\t\t\tthrow Exception(\"Unsupported direction.\");\n\t} // end switch\n\t\n\t// Mark as dirty.\n\tdata->dirty = true;\t\n\t\t\n\t// Update topological sorting.\n\tupdateTopologicalIndex(pin);\n\t\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_POST_PIN_CONNECT])\n\t\tf->onPostPinConnect(pin);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nDesign::disconnectPin(Pin pin) {\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_PRE_PIN_DISCONNECT])\n\t\tf->onPrePinDisconnect(pin);\n\t\n\tif (pin->net) {\n\t\t// Remove the pin from the net.\n\t\tNet net = pin->net;\n\t\tconst int numPins = net->pins.size();\n\t\tfor (int i = 0; i < numPins; i++) {\n\t\t\tif (net->pins[i] == pin) {\n\t\t\t\t// Swap the element to be delete with the last one and then shrink\n\t\t\t\t// the vector. Note that is affect the pin ordering inside the net.\t\t\t\n\t\t\t\tstd::swap(net->pins[i], net->pins.back());\n\t\t\t\tnet->pins.resize(net->pins.size() - 1);\n\t\t\t\tbreak;\n\t\t\t} // end if\n\t\t} // end for\n\t\t\n\t\t// Remove arcs from the pin.\n\t\tswitch (pin.getDirection()) {\n\t\t\tcase Rsyn::DRIVER:\n\t\t\t\tpin->arcs[FORWARD].clear();\n\t\t\t\tbreak;\n\t\t\tcase Rsyn::SINK:\n\t\t\t\tpin->arcs[BACKWARD].clear();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow Exception(\"Unsupported direction.\");\n\t\t} // end switch\n\n\t\t// Disconnect the pin.\n\t\tpin->net = nullptr;\n\n\t\t// Adjust pins count.\n\t\tnet->numPinsOfType[pin.getDirection()]--;\n\t\t\n\t\t// Update the cached driver if necessary.\n\t\tif (pin.getDirection() == Rsyn::DRIVER) {\n\t\t\tfor (Pin pin : net.allPins(Rsyn::OUT)) {\n\t\t\t\tnet->driver = pin;\n\t\t\t\tbreak;\n\t\t\t} // end for\t\t\t\n\t\t} // end if\n\n\t\t// Mark as dirty.\n\t\tdata->dirty = true;\n\t} // end if\n} // end method\n\n// -----------------------------------------------------------------------------\n\n// TODO: Improve performance of remaping. The first thing to do is to cache\n// the remaping table.\n\ninline\nvoid \nDesign::remap(Cell cell, LibraryCell newLibraryCell) {\n\tLibraryCell oldLibraryCell = cell.getLibraryCell();\n\t\n\t// Check if the cells have the same number of arcs...\n\t// TODO: a deep comparison is necessary.\n\tif (oldLibraryCell.getNumArcs() != newLibraryCell.getNumArcs()) {\n\t\tthrow IncompatibleLibraryCellForRemapping(\n\t\t\t\toldLibraryCell.getName(), newLibraryCell.getName());\n\t} // end if\n\t\n\t// Check if the cells have the same number of pins...\n\tif (oldLibraryCell.getNumPins() != newLibraryCell.getNumPins()) {\n\t\tthrow IncompatibleLibraryCellForRemapping(\n\t\t\t\toldLibraryCell.getName(), newLibraryCell.getName());\n\t} // end if\t\n\t\n\t// Create a mapping between the old and new pins.\n\t// TODO: Cache this!\n\tstd::unordered_map<Rsyn::LibraryPin, Rsyn::LibraryPin> mapLibraryPins;\n\tfor (LibraryPin oldLibraryPin : oldLibraryCell.allLibraryPins()) {\n\t\tLibraryPin newLibraryPin = \n\t\t\t\tnewLibraryCell.getLibraryPinByName(oldLibraryPin.getName());\n\t\t\n\t\tif (!newLibraryPin) {\n\t\t\tthrow IncompatibleLibraryCellForRemapping(\n\t\t\t\t\toldLibraryCell.getName(), newLibraryCell.getName());\n\t\t} // end if\n\t\t\n\t\tmapLibraryPins[oldLibraryPin] = newLibraryPin;\n\t} // end method\n\n\t// Create a mapping between the old and new arcs.\n\t// TODO: Cache this!\n\tstd::unordered_map<Rsyn::LibraryArc, Rsyn::LibraryArc> mapLibraryArcs;\n\tfor (LibraryArc oldLibraryArc : oldLibraryCell.allLibraryArcs()) {\n\t\tLibraryArc newLibraryArc =\n\t\t\t\tnewLibraryCell.getLibraryArcByPinNames(oldLibraryArc.getFromName(), oldLibraryArc.getToName());\n\n\t\tif (!newLibraryArc) {\n\t\t\tthrow IncompatibleLibraryCellForRemapping(\n\t\t\t\t\toldLibraryCell.getName(), newLibraryCell.getName());\n\t\t} // end if\n\n\t\tmapLibraryArcs[oldLibraryArc] = newLibraryArc;\n\t} // end method\n\n\t// Update library cell.\n\tcell->lcell = newLibraryCell.data;\n\n\t// Update pins.\n\tfor (Pin pin : cell.allPins()) {\n\t\tRsyn::LibraryPin newLibraryPin = mapLibraryPins[oldLibraryCell.getLibraryPinByIndex(pin->index)];\n\t\tpin->index = newLibraryPin->index;\n\t} // end for\n\n\t// Update arcs.\n\tfor (Arc arc : cell.allArcs()) {\n\t\tRsyn::LibraryArc newLibraryArc = mapLibraryArcs[arc.getLibraryArc()];\n\t\tarc->libraryArcData = newLibraryArc.data;\n\t} // end for\n\t\n\t// Notify observers.\n\tfor (auto f : data->observers[EVENT_POST_CELL_REMAP])\n\t\tf->onPostCellRemap(cell, oldLibraryCell);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid \nDesign::remap(Cell cell, const std::string &newLibraryCellName) {\n\tLibraryCell newLibraryCell = findLibraryCellByName(newLibraryCellName);\n\tif (!newLibraryCell) {\n\t\tthrow LibraryCellNotFoundException(newLibraryCellName);\n\t} // end if\n\tremap(cell, newLibraryCell);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nDesign::getNumInstances() const {\n\treturn data->instances.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<ReferenceListCollection<Cell>>\nDesign::getAllCells() const {\n    for (Instance inst : data->topModule.allInstances()){\n        if (inst.getType() != CELL)\n            continue;\n        data->cells.add(inst.asCell());\n    }\n    Range<ReferenceListCollection<Cell>> a = ReferenceListCollection<Cell>(data->cells);\n    for (Cell c : a){\n        std::cout << c.getName() << \"\\n\";\n        break;\n    }\n        return ReferenceListCollection<Cell>(data->cells); \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nDesign::getNumInstances(const InstanceType type) const {\n\treturn data->instanceCount[type];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nDesign::getNumNets() const {\n\treturn data->nets.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nDesign::getNumPins() const {\n\treturn data->pins.size();\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Topological Ordering\n////////////////////////////////////////////////////////////////////////////////\n\ninline\nvoid\nDesign::updateTopologicalIndex(Pin pin) {\n\t// Some checks...\n\tstatic_assert(std::is_integral<TopologicalIndex>::value, \"Integer required.\");\n\tstatic_assert(std::is_signed<TopologicalIndex>::value, \"Signed type required.\");\n\t\n\tstatic_assert(TOPOLOGICAL_SORTING_SMALL_GAP > 0, \"small < 0\");\n\tstatic_assert(TOPOLOGICAL_SORTING_LARGE_GAP > 0, \"large < 0\");\n\tstatic_assert(TOPOLOGICAL_SORTING_SMALL_GAP <= \n\t\t\tTOPOLOGICAL_SORTING_LARGE_GAP, \"small gap > large gap\");\n\t\n\t// Gets the signature for this update search.\n\tconst int sign = generateNextSign();\n\t\n\t// Gets the lower bound index.\n\tTopologicalIndex lower = \n\t\t\t-std::numeric_limits<TopologicalIndex>::infinity();\n\tbool hasLower = false;\n\tfor (Rsyn::Pin predecessor : pin.allPredecessorPins(true)) {\n\t\tlower = std::max(lower, predecessor.getTopologicalIndex());\n\t\thasLower = true;\n\t} // end for\n\t\n\t// Gets the upper bound index.\n\tTopologicalIndex upper = \t\t\t\n\t\t\t+std::numeric_limits<TopologicalIndex>::infinity();\n\tbool hasUpper = false;\n\tfor (Rsyn::Pin successor : pin.allSucessorPins(true)) {\n\t\tupper = std::min(upper, successor.getTopologicalIndex());\n\t\thasUpper = true;\n\t} // end for\n\t\n\t// Set pin's topological ordering.\n\tif (!hasLower && !hasUpper) {\n\t\tpin->order = 0;\n\t} else if (hasLower && !hasUpper) {\n\t\tpin->order = lower + TOPOLOGICAL_SORTING_SMALL_GAP;\n\t} else if (!hasLower && hasUpper) {\n\t\tpin->order = upper - TOPOLOGICAL_SORTING_SMALL_GAP;\n\t} else {\n\t\t// Ok, we got a lower and an upper bound...\t\n\t\t\n\t\tif (lower < upper && (upper - lower >= 2)) {\n\t\t\t// The easy case...\n\t\t\t// Since we use integral types, we must guarantee that there's room\n\t\t\t// for the new pin between the lower and upper bounds, that's why\n\t\t\t// we check if (upper - lower >= 2).\n\t\t\tpin->order = (lower + upper) / 2;\n\t\t} else {\n\t\t\t// We need to propagate the indexes...\n\t\t\tconst TopologicalIndex smallGap = TOPOLOGICAL_SORTING_SMALL_GAP;\n\t\t\tconst TopologicalIndex largeGap = TOPOLOGICAL_SORTING_LARGE_GAP;\n\t\t\t\n\t\t\tconst TopologicalIndex left0 = upper;\n\t\t\tconst TopologicalIndex left1 = lower + smallGap + 1;\n\t\t\tconst TopologicalIndex right = left1 + largeGap;\n\t\t\tconst TopologicalIndex w0 = (right - left0);\n\t\t\tconst TopologicalIndex w1 = (right - left1);\n\t\t\t\t\t\t\n\t\t\tpin->order = (lower + left1) / 2;\n\t\t\t\n\t\t\tstd::queue<std::tuple<Rsyn::Pin, TopologicalIndex>> open;\n\t\t\tfor (Rsyn::Pin successor : pin.allSucessorPins(true)) {\n\t\t\t\tif (successor->order < right) {\n\t\t\t\t\topen.push(std::make_tuple(successor, pin->order));\n\t\t\t\t} // end if\n\t\t\t} // end for\t\t\t\n\n\t\t\twhile (!open.empty()) {\n\t\t\t\tRsyn::Pin current = std::get<0>(open.front());\n\t\t\t\tconst TopologicalIndex generatorOrder = std::get<1>(open.front());\n\t\t\t\topen.pop();\n\n\t\t\t\tif (current == pin) {\n\t\t\t\t\t// loop detected;\n\t\t\t\t\tstd::cout << \"WARNING: Loop detected.\\n\";\n\t\t\t\t\tcontinue;\n\t\t\t\t} // end if\n\t\t\t\t\n\t\t\t\tif (current->order > generatorOrder) {\n\t\t\t\t\t// no need to continue propagating...\n\t\t\t\t\tcontinue;\n\t\t\t\t} // end if\n\t\t\t\t\t\n\t\t\t\tTopologicalIndex order;\n\t\t\t\tif (current->sign != sign) {\n\t\t\t\t\tcurrent->sign = sign;\n\t\t\t\t\torder = (TopologicalIndex) std::floor(\n\t\t\t\t\t\t\t(float((current->order - upper)*w1)/float(w0)) + left1);\n\t\t\t\t\tif (order <= generatorOrder) {\n\t\t\t\t\t\torder = generatorOrder + smallGap;\n\t\t\t\t\t} // end if\t\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\torder = generatorOrder + smallGap;\n\t\t\t\t} // end else\n\t\t\t\t\n\t\t\t\tcurrent->order = order;\n\t\t\t\t\n\t\t\t\tfor (Rsyn::Pin successor : current.allSucessorPins(true)) {\n\t\t\t\t\tif (successor->order <= order) {\n\t\t\t\t\t\topen.push(std::make_tuple(successor, order));\n\t\t\t\t\t} // end if\n\t\t\t\t} // end for\n\t\t\t} // end while\n\t\t} // end else\n\t} // end else\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Unique Identifiers for Rsyn Objects\n////////////////////////////////////////////////////////////////////////////////\n\ninline Index Design::getId(Net net) const { return net->id; }\ninline Index Design::getId(Instance instance) const { return instance->id; }\ninline Index Design::getId(Pin pin) const { return pin->id; }\ninline Index Design::getId(Arc arc) const { return arc->id; }\ninline Index Design::getId(LibraryCell lcell) const { return lcell->id; }\ninline Index Design::getId(LibraryPin lpin) const { return lpin->id; }\ninline Index Design::getId(LibraryArc larc) const { return larc->id; }\n\n////////////////////////////////////////////////////////////////////////////////\n// Events\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<class T>\ninline\nvoid\nDesign::registerObserver(T *observer) {\n\tstatic_assert(std::is_base_of<DesignObserver, T>::value,\n\t\t\t\"Unable to register class as observer. \"\n\t\t\t\"The observer class must inherit from Rsyn::Observer.\");\n\n\tobserver->DesignObserver::observedDesign = Design(data);\n\t\n\t// Check if the observer implements (overwrites) the event callbacks if so\n\t// register it to receive notifications of the respective event.\n\n\tif (typeid(&DesignObserver::onDesignDestruction) != typeid(&T::onDesignDestruction)) {\n\t\tdata->observers[EVENT_DESTRUCTION].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPostInstanceCreate) != typeid(&T::onPostInstanceCreate)) {\n\t\tdata->observers[EVENT_POST_INSTANCE_CREATE].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPreInstanceRemove) != typeid(&T::onPreInstanceRemove)) {\n\t\tdata->observers[EVENT_PRE_INSTANCE_REMOVE].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPostNetCreate) != typeid(&T::onPostNetCreate)) {\n\t\tdata->observers[EVENT_POST_NET_CREATE].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPreNetRemove) != typeid(&T::onPreNetRemove)) {\n\t\tdata->observers[EVENT_PRE_NET_REMOVE].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPostCellRemap) != typeid(&T::onPostCellRemap)) {\n\t\tdata->observers[EVENT_POST_CELL_REMAP].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPostPinConnect) != typeid(&T::onPostPinConnect)) {\n\t\tdata->observers[EVENT_POST_PIN_CONNECT].push_back(observer);\n\t} // end if\n\n\tif (typeid(&DesignObserver::onPrePinDisconnect) != typeid(&T::onPrePinDisconnect)) {\n\t\tdata->observers[EVENT_PRE_PIN_DISCONNECT].push_back(observer);\n\t} // end if\t\n\n\tif (typeid (&DesignObserver::onPostInstanceMove) != typeid (&T::onPostInstanceMove)) {\n\t\tdata->observers[EVENT_POST_INSTANCE_MOVE].push_back(observer);\n\t} // end if\n\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nDesign::unregisterObserver(DesignObserver *observer) {\n\tfor (int i = 0; i < NUM_DESIGN_EVENTS; i++) {\n\t\tdata->observers[i].remove(observer);\n\t} // end for\n\tobserver->DesignObserver::observedDesign = nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nDesign::notifyInstancePlaced(Rsyn::Instance instance, Rsyn::DesignObserver *ignoreObserver) {\n\tfor (DesignObserver * observer : data->observers[EVENT_POST_INSTANCE_MOVE]) {\n\t\tif (observer != ignoreObserver) {\n\t\t\tobserver->onPostInstanceMove(instance);\n\t\t} // end if\n\t} // end for\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Attributes\n////////////////////////////////////////////////////////////////////////////////\n\ninline \nAttributeInitializer \nDesign::createAttribute() { \n\treturn AttributeInitializer(*this); \n} // end method\n\n// -----------------------------------------------------------------------------\n \ntemplate<typename DefaultValueType>\ninline\nAttributeInitializerWithDefaultValue<DefaultValueType>\nDesign::createAttribute(const DefaultValueType &defaultValue) {\n\treturn AttributeInitializerWithDefaultValue<DefaultValueType>(*this, defaultValue); \n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Tags\n////////////////////////////////////////////////////////////////////////////////\n\ninline\nNetTag \nDesign::getTag(Rsyn::Net net) {\n\treturn NetTag(&net->tag);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nInstanceTag\nDesign::getTag(Rsyn::Instance instance) {\n\treturn InstanceTag(&instance->tag);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCellTag\nDesign::getTag(Rsyn::LibraryCell libraryCell) {\n\treturn LibraryCellTag(&libraryCell->tag);\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Range-Based Loop\n////////////////////////////////////////////////////////////////////////////////\n\ninline\nRange<ListCollection<LibraryCellData, LibraryCell>>\nDesign::allLibraryCells(const bool showDeprecatedMessage) {\n\tif (showDeprecatedMessage) {\n\t\tstd::cout << \"WARNING: Rsyn::Desing::allLibraryCells() is deprecated. \"\n\t\t\t\t\"Use Rsyn::Library::allLibraryCells() instead.\\n\";\n\t} // end method\n\treturn ListCollection<LibraryCellData, LibraryCell>(data->libraryCells);\n} // end method\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Instance.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <limits>\n\nnamespace Rsyn {\n\ninline\nDesignData *\nInstance::_getDesignData() const {\n\treturn getDesign().data;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDesignData *\nInstance::getDesignData() {\n\treturn _getDesignData();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst DesignData *\nInstance::getDesignData() const {\n\treturn _getDesignData();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDesign\nInstance::_getDesign() const {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDesign\nInstance::getDesign() {\n\treturn _getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design\nInstance::getDesign() const {\n\treturn _getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nModule\nInstance::_getParent() const {\n\treturn data->parent;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nModule\nInstance::getParent() {\n\treturn _getParent();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Module\nInstance::getParent() const {\n\treturn _getParent();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nCell\nInstance::asCell() const {\n#ifdef RSYN_SAFE_MODE\n\tif (getType() != Rsyn::CELL)\n\t\tthrow SafeModeException(\"Invalid instance casting. Instance is not a cell.\");\n#endif\n\treturn Cell(data);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPort\nInstance::asPort() const {\n#ifdef RSYN_SAFE_MODE\n\tif (getType() != Rsyn::PORT)\n\t\tthrow SafeModeException(\"Invalid instance casting. Instance is not a port.\");\n#endif\n\treturn Port(data);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nModule\nInstance::asModule() const {\n#ifdef RSYN_SAFE_MODE\n\tif (getType() != Rsyn::MODULE)\n\t\tthrow SafeModeException(\"Invalid instance casting. Instance is not a module.\");\n#endif\n\treturn Module(data);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nInstance::getHierarchicalName() const {\n\treturn (data->parent ? data->parent.getHierarchicalName() : \"\") + \"/\" + getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nInstanceType\nInstance::getType() const {\n\treturn data->type;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin\nInstance::getPinByName(const std::string &name) const {\n\tfor (Rsyn::Pin pin : allPins()) {\n\t\tif (pin.getName() == name)\n\t\t\treturn pin;\n\t} // end method\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nInstance::getName() const {\n\treturn data ? getDesign()->instanceNames[data->id] : NullName;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nInstance::getNumPins() const {\n\treturn (int) data->pins.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nInstance::getNumPins(const Direction direction) const {\n\t// TODO: optimize this using instance types (e.g. cell can get the number\n\t// of pins of certain direction via its library cell).\n\n\tint counter = 0;\n\tfor (Rsyn::Pin pin : allPins()) {\n\t\tif (pin.getDirection() == direction) {\n\t\t\tcounter++;\n\t\t} // end if\n\t} // end for\n\n\treturn counter;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nInstance::getNumInputPins() const {\n\treturn getNumPins(Rsyn::IN);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nInstance::getNumOutputPins() const {\n\treturn getNumPins(Rsyn::OUT);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nInstance::getNumBidirectionalPins() const {\n\treturn getNumPins(Rsyn::BIDIRECTIONAL);\n} // end method\n\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nInstance::getNumArcs() const {\n\treturn (int) data->arcs.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nTopologicalIndex\nInstance::getTopologicalIndex() const {\n\t// TODO: The topological order of an instance my be ambiguous in some cases\n\t// as in the case of registers. There's no arc between D and Q pins and \n\t// hence D may have a larger topological index than Q. In a forward traverse\n\t// of the netlist one may expect that Q would be used as the topological\n\t// index of the register while in a backward traverse one would expect\n\t// that the D pin was used.\n\n\t// NOTE: In the current implementation the topological order of register\n\t// is the topological order of the clock pin.\n\n\tTopologicalIndex order = MIN_TOPOLOGICAL_INDEX;\n\tfor (Rsyn::Arc arc : allArcs()) {\n\t\torder = std::max(order, arc.getFromPin().getTopologicalIndex());\n\t} // end for\n\n\t// Some cells may not have arcs, so as a fall back, get the largest\n\t// topological index of its pins.\n\tif (order == MIN_TOPOLOGICAL_INDEX) {\n\t\tfor (Rsyn::Pin pin : allPins()) {\n\t\t\torder = std::max(order, pin.getTopologicalIndex());\n\t\t} // end for\t\t\n\t} // end if\n\n\treturn order;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isPort() const {\n\treturn data->type == Rsyn::PORT;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isPort(const Direction direction) {\n\treturn isPort() && (asPort().getDirection() == direction);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin\nInstance::getPinByIndex(const int index) const {\n\treturn data->pins[index];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin\nInstance::getAnyInputPin() const {\n\tfor (Pin pin : allPins()) {\n\t\tif (pin.getDirection() == Rsyn::IN) {\n\t\t\treturn pin;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin\nInstance::getAnyOutputPin() const {\n\tfor (Pin pin : allPins()) {\n\t\tif (pin.getDirection() == Rsyn::OUT) {\n\t\t\treturn pin;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArc\nInstance::getArc(const Pin from, const Pin to) {\n\tfor (Arc arc : allArcs()) {\n\t\tif ((arc.getFromPin() == from) && (arc.getToPin() == to)) {\n\t\t\treturn arc;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArc\nInstance::getArcByPinNames(const std::string &from, const std::string &to) {\n\tfor (Arc arc : allArcs()) {\n\t\tif ((arc.getFromPin().getName() == from) && (arc.getToPin().getName() == to)) {\n\t\t\treturn arc;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArc\nInstance::getAnyArc() {\n\treturn !data->arcs.empty() ? data->arcs[0] : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell\nInstance::getLibraryCell() const {\n\treturn getType() == Rsyn::CELL? Cell(data).getLibraryCell() : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPinsFilteredByDirection>\nInstance::allPins(const Direction direction, bool filterPG) const {\n\treturn CollectionOfPinsFilteredByDirection(data->pins, direction, filterPG);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPins>\nInstance::allPins(bool filterPG) const {\n\treturn CollectionOfPins(data->pins, filterPG);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfArcs>\nInstance::allArcs() const {\n\treturn CollectionOfArcs(data->arcs);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isSequential() const {\n\treturn getType() == Rsyn::CELL ?\n\t\tasCell().getLibraryCell().isSequential() : false;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isTie(const TieType type) const {\n\treturn getType() == Rsyn::CELL ?\n\t\tasCell().getLibraryCell().isTie(type) : false;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isBuffer(const BufferType type) const {\n\treturn getType() == Rsyn::CELL ?\n\t\tasCell().getLibraryCell().isBuffer(type) : false;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isClockBuffer(const BufferType type, const bool local) const {\n\t// First check if this instance is a buffer.\n\tif (!isBuffer(type))\n\t\treturn false;\n\n\t// Now checks if this buffer belong to a clock network.\n\tRsyn::Pin pin = getAnyOutputPin();\n\tRsyn::Net net = pin.getNet();\n\n\tif (!net || !net.isClockNetwork())\n\t\treturn false;\n\n\t// Only consider a local clock buffer a clock buffer driving at least one\n\t// register.\n\tif (local) {\n\t\tfor (Rsyn::Pin sink : net.allPins(Rsyn::SINK)) {\n\t\t\tRsyn::Instance instance = sink.getInstance();\n\t\t\tif (instance.isSequential())\n\t\t\t\treturn true;\n\t\t} // end for\n\n\t\treturn false;\n\t} else {\n\t\treturn true;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isLCB(const BufferType type) const {\n\treturn isClockBuffer(type, true);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isFixed() const {\n\tif (data->tag.fixed.isNotSpecified())\n\t\tthrow TagNotSpecifiedException(\"Fixed\");\n\treturn data->tag.fixed;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isMovable() const {\n\treturn !isFixed();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nInstance::isMacroBlock() const {\n\tif (data->tag.block.isNotSpecified())\n\t\tthrow TagNotSpecifiedException(\"Block\");\n\treturn data->tag.block;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline \nbool\nInstance::isFlipped() const {\n\tPhysicalOrientation orient = getOrientation();\n\n\tconst bool fliped = orient == ORIENTATION_FN || orient == ORIENTATION_FS ||\n\t\torient == ORIENTATION_FW || orient == ORIENTATION_FE;\n\treturn fliped;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getX() const {\n\treturn getPosition(X);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getY() const {\n\treturn getPosition(Y);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getHeight() const {\n\treturn data->clsBounds.computeLength(Y);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getWidth() const {\n\treturn data->clsBounds.computeLength(X);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy Instance::getSize() const {\n\treturn DBUxy(getWidth(), getHeight());\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getSize(const Dimension dimension) const {\n\treturn data->clsBounds.computeLength(dimension);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy Instance::getPosition() const {\n\tif (isPort())\n\t\treturn data->clsPortPos;\n\treturn data->clsBounds[LOWER];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getPosition(const Dimension dim) const {\n\tif (isPort())\n\t\treturn data->clsPortPos[dim];\n\treturn data->clsBounds[LOWER][dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy Instance::getCoordinate(const Boundary bound) const {\n\tif (isPort())\n\t\treturn getPosition();\n\treturn data->clsBounds[bound];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getCoordinate(const Boundary bound, const Dimension dim) const {\n\tif (isPort())\n\t\tgetPosition(dim);\n\treturn data->clsBounds[bound][dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getArea() const {\n\treturn data->clsBounds.computeArea();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy Instance::getCenter() const {\n\tif (isPort())\n\t\treturn getPosition();\n\treturn getBounds().computeCenter();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU Instance::getCenter(const Dimension dim) const {\n\tif (isPort())\n\t\treturn getPosition(dim);\n\treturn getBounds().computeCenter(dim);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const Bounds &Instance::getBounds() const {\n\treturn data->clsBounds;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline PhysicalOrientation Instance::getOrientation() const {\n\treturn data->clsOrientation;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline PhysicalTransform Instance::getTransform(const bool origin) const {\n\tif (origin) {\n\t\tBounds bounds = getBounds();\n\t\tbounds.translate(-bounds.getLower());\n\t\treturn PhysicalTransform(bounds, getOrientation());\n\t} else {\n\t\treturn PhysicalTransform(getBounds(), getOrientation());\n\t} // end else\n} // end method\n\n// =============================================================================\n// Tag\n// =============================================================================\n\ninline\nTristateFlag\nInstanceTag::getFixed() const {\n\treturn data->fixed;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nInstanceTag::setFixed(const bool value) {\n\tdata->fixed = value;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nTristateFlag\nInstanceTag::getMacroBlock() const {\n\treturn data->block;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nInstanceTag::setMacroBlock(const bool value) {\n\tdata->block = value;\n} // end method\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Library.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Rsyn {\n\ninline\nRange<ListCollection<LibraryCellData, LibraryCell>>\nLibrary::allLibraryCells() {\n\treturn Rsyn::Design(data->designData).allLibraryCells(false);\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/LibraryArc.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign \nLibraryArc::getDesign() {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design \nLibraryArc::getDesign() const {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nLibraryArc::getName() const {\n\treturn getFromName() + \"->\" + getToName();\t\t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nLibraryArc::getFullName() const {\n\treturn getLibraryCell().getName() + \":\" + getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nLibraryArc::getFromName() const {\n\treturn getFromLibraryPin().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nLibraryArc::getToName() const {\n\treturn getToLibraryPin().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell\nLibraryArc::getLibraryCell() const {\n\treturn data->lcell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryPin\nLibraryArc::getFromLibraryPin() const {\n\treturn data->from;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryPin\nLibraryArc::getToLibraryPin() const {\n\treturn data->to;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nLibraryArc::getIndex() const {\n\treturn data->index;\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/LibraryCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign \nLibraryCell::getDesign() {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design \nLibraryCell::getDesign() const {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryPin \nLibraryCell::getLibraryPinByName(const std::string &name) const {\n\tfor (LibraryPin lpin : data->pins) {\n\t\tif (lpin.getName() == name) {\n\t\t\treturn lpin;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nLibraryCell::getName() const {\n\treturn data? data->name : NullName;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryCell::getNumPins() const {\n\treturn (int) data->pins.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryCell::getNumPins(const Direction direction) const {\n\t// TODO: use array\n\tswitch(direction) {\n\t\tcase IN : return data->numInputPins;\n\t\tcase OUT: return data->numOutputPins;\n\t\tcase BIDIRECTIONAL: return data->numInOutPins;\n\t\tdefault: throw std::string(\"invalid pin direction\"); // TODO: use a proper exception class\n\t} // end switch\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryCell::getNumInputPins() const {\n\treturn getNumPins(Rsyn::IN);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryCell::getNumOutputPins() const {\n\treturn getNumPins(Rsyn::OUT);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryCell::getNumBidirectionalPins() const  {\n\treturn getNumPins(Rsyn::BIDIRECTIONAL);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryCell::getNumArcs() const {\n\treturn (int) data->arcs.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\t\ninline\nLibraryPin \nLibraryCell::getLibraryPinByIndex(const int index) const {\n\treturn data->pins[index];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryPin\nLibraryCell::getAnyInputLibraryPin() {\n\tfor (LibraryPin lpin : allLibraryPins()) {\n\t\tif (lpin.getDirection() == Rsyn::IN) {\n\t\t\treturn lpin;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryPin\nLibraryCell::getAnyOutputLibraryPin() {\n\tfor (LibraryPin lpin : allLibraryPins()) {\n\t\tif (lpin.getDirection() == Rsyn::OUT) {\n\t\t\treturn lpin;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryArc \nLibraryCell::getLibraryArc(const Rsyn::LibraryPin from, const Rsyn::LibraryPin to) const {\n\tfor (LibraryArc larc : allLibraryArcs()) {\n\t\tif (larc.getFromLibraryPin() == from && larc.getToLibraryPin() == to) \n\t\t\treturn larc;\n\t} // end method\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryArc\nLibraryCell::getLibraryArcByIndex(const int index) const {\n\treturn data->arcs[index];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryArc \nLibraryCell::getLibraryArcByPinNames(const std::string &from, const std::string &to) const {\n\tfor (LibraryArc larc : allLibraryArcs()) {\n\t\tif (larc.getFromName() == from && larc.getToName() == to) \n\t\t\treturn larc;\n\t} // end method\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryArc \nLibraryCell::getAnyLibraryArc() const {\n\treturn getNumArcs() > 0? data->arcs.front() : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfLibraryPinsFilteredByDirection>\nLibraryCell::allLibraryPins(const Direction direction) const {\n\treturn CollectionOfLibraryPinsFilteredByDirection(data->pins, direction);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfLibraryPins>\nLibraryCell::allLibraryPins() const {\n\treturn CollectionOfLibraryPins(data->pins);\n} // end method\n\n// -----------------------------------------------------------------------------\n\t\t\ninline\nRange<CollectionOfLibraryArcs>\nLibraryCell::allLibraryArcs() const {\n\treturn CollectionOfLibraryArcs(data->arcs);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryCell::isSequential() const {\n\tif (data->tag.logicType == LOGIC_TYPE_TAG_NOT_SPECIFIED)\n\t\tthrow TagNotSpecifiedException(\"Logic Type\");\n\treturn data->tag.logicType == LOGIC_TYPE_TAG_SEQUENTIAL;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryCell::isCombinational() const {\n\tif (data->tag.logicType == LOGIC_TYPE_TAG_NOT_SPECIFIED)\n\t\tthrow TagNotSpecifiedException(\"Logic Type\");\n\treturn data->tag.logicType == LOGIC_TYPE_TAG_COMBINATIONAL;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryCell::isTie(const TieType type) const {\n\tif (data->tag.tieType == TIE_TYPE_TAG_NOT_SPECIFIED)\n\t\tthrow TagNotSpecifiedException(\"Tie Type\");\n\n\tconst TieTypeTag &tag = data->tag.tieType;\n\tswitch (type) {\n\t\tcase TIE_LOW     : return tag == TIE_TYPE_TAG_LOW;\n\t\tcase TIE_HIGH    : return tag == TIE_TYPE_TAG_HIGH;\n\t\tcase ANY_TIE_TYPE: return tag == TIE_TYPE_TAG_LOW || tag == TIE_TYPE_TAG_HIGH;\n\t\tdefault:\n\t\t\tassert(false);\n\t\t\treturn false;\n\t} // end switch\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryCell::isBuffer(const BufferType type) const {\n\tif (data->tag.bufferType == BUFFER_TYPE_TAG_NOT_SPECIFIED)\n\t\tthrow TagNotSpecifiedException(\"Buffer Type\");\n\n\tconst BufferTypeTag &tag = data->tag.bufferType;\n\tswitch (type) {\n\t\tcase NON_INVERTING  : return tag == BUFFER_TYPE_TAG_NON_INVERTING;\n\t\tcase INVERTING      : return tag == BUFFER_TYPE_TAG_INVERTING;\n\t\tcase ANY_BUFFER_TYPE: return tag == BUFFER_TYPE_TAG_NON_INVERTING || tag == BUFFER_TYPE_TAG_INVERTING;\n\t\tdefault:\n\t\t\tassert(false);\n\t\t\treturn false;\n\t} // end switch\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU LibraryCell::getHeight() const {\n\treturn data->size[Y];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU LibraryCell::getWidth() const {\n\treturn data->size[X];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy LibraryCell::getSize() const {\n\treturn data->size;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU LibraryCell::getSize(const Dimension dimension) const {\n\treturn data->size[dimension];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU LibraryCell::getArea() const {\n\treturn getWidth() * getHeight();\n} // end method\n\n// =============================================================================\n// Tag\n// =============================================================================\n\ninline\nLogicTypeTag\nLibraryCellTag::getLogicType() const {\n\treturn data->logicType;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nTieTypeTag\nLibraryCellTag::getTieType() const {\n\treturn data->tieType;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nBufferTypeTag\nLibraryCellTag::getBufferTypeTag() const {\n\treturn data->bufferType;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nLibraryCellTag::setLogicType(const LogicTypeTag value) {\n\tdata->logicType = value;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nLibraryCellTag::setTieType(const TieTypeTag value) {\n\tdata->tieType = value;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nLibraryCellTag::setBufferType(const BufferTypeTag value) {\n\tdata->bufferType = value;\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/LibraryModule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign \nLibraryModule::getDesign() {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design \nLibraryModule::getDesign() const {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/LibraryPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign \nLibraryPin::getDesign() {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design \nLibraryPin::getDesign() const {\n\treturn data->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nLibraryPin::getName() const {\n\treturn data? data->name : NullName;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::string\nLibraryPin::getHierarchicalName(const std::string & separator) const {\n\treturn data ? data->lcell.getName() + separator + data->name : NullName;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nLibraryPin::getDirectionName() const {\n\treturn Global::getDirectionName(getDirection());\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nLibraryPin::getLibraryCellName() const {\n\treturn getLibraryCell().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDirection \nLibraryPin::getDirection() const {\n\treturn data->direction;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell \nLibraryPin::getLibraryCell() const {\n\treturn data->lcell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nLibraryPin::getIndex() const {\n\treturn data->index;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nLibraryPin::isInput() const {\n\treturn getDirection() == Rsyn::IN;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryPin::isOutput() const {\n\treturn getDirection() == Rsyn::OUT;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryPin::isBidirectional() const {\n\treturn getDirection() == Rsyn::BIDIRECTIONAL;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nUse\nLibraryPin::getUse() const {\n\treturn data->pinUse;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nLibraryPin::isPowerOrGround() const {\n\treturn (getUse() == POWER || getUse() == GROUND);\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Module.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign \nModule::getDesign() {\n\treturn data->moduleData->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design \nModule::getDesign() const {\n\treturn data->moduleData->design;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nModule::generateNextSign() const {\n\treturn ++data->moduleData->sign; /*must be pre-increment*/ \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nModule::getSign() const { \n\treturn data->moduleData->sign; \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nCell \nModule::createCell(const std::string &libraryCellName, const std::string &name) {\n\tDesign design = getDesign(); \n\n\t// TODO: move this test to design...\n\tLibraryCell lcell = design.findLibraryCellByName(libraryCellName);\n\tif (!lcell) {\n\t\tthrow LibraryCellNotFoundException(libraryCellName);\n\t} // end if\n\t\n\treturn design.createCell(*this, lcell, name);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nCell \nModule::createCell(const LibraryCell lcell, const std::string &name) {\n\tDesign design = getDesign(); \n\treturn design.createCell(*this, lcell, name);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPort \nModule::createPort(const Direction &direction, const std::string &name) {\n\tDesign design = getDesign(); \n\treturn design.createPort(*this, direction, name);\t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet \nModule::createNet(const std::string &name) {\n\tDesign design = getDesign(); \n\t\n\t// Check net name.\n\tif (design.findNetByName(name)) {\n\t\tthrow NetAlreadyExistsException(name);\n\t} // end of\n\n\t// Creates and returns a new net;\n\treturn design.createNet(*this, name);\t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPort \nModule::getPortByIndex(const int index) {\n\treturn data->moduleData->ports.get(index)->value; // TODO: awful\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nModule::getInstancesPerLogicalDepth(std::vector<std::vector<Rsyn::Instance>> &levels) {\n\t// TODO: For now let's just do a simple method to levelize. When more\n\t// unit tests are create, we should revise this method to see if a more\n\t// efficient one can be devised.\n\t\n\tlevels.clear();\t\n\t\n\tRsyn::Attribute<Rsyn::Instance, int> depth = getDesign().createAttribute(-1);\n\tfor (Rsyn::Instance instance : allInstancesInTopologicalOrder()) {\n\t\t// Set the depth as the largest depth of the driver cells (if any) plus\n\t\t// one.\n\t\tint lower = -1;\n\t\t\n\t\tswitch (instance.getType()) {\n\t\t\tcase Rsyn::CELL: {\n\t\t\t\t// We check the from pin of arcs instead of just checking the\n\t\t\t\t// input pins to handle the D pin of registers. We want that\n\t\t\t\t// the depth of a register is based on the depth of its CK pin.\n\n\t\t\t\tbool hasArcs = false;\n\t\t\t\tfor (Rsyn::Arc arc : instance.allArcs()) {\n\t\t\t\t\tRsyn::Net net = arc.getFromNet();\n\t\t\t\t\tif (net) {\n\t\t\t\t\t\tfor (Rsyn::Pin driver : net.allPins(Rsyn::DRIVER)) {\n\t\t\t\t\t\t\tlower = std::max(lower, depth[driver.getInstance()]);\n\t\t\t\t\t\t} // end for\n\t\t\t\t\t} // end if\n\t\t\t\t\thasArcs = true;\n\t\t\t\t} // end for\n\t\t\t\t\n\t\t\t\t// If no arcs, as a fall back, get the depth from the input\n\t\t\t\t// pins.\n\t\t\t\tif (!hasArcs) {\n\t\t\t\t\tfor (Rsyn::Pin pin : instance.allPins()) {\n\t\t\t\t\t\tRsyn::Net net = pin.getNet();\n\t\t\t\t\t\tif (net) {\n\t\t\t\t\t\t\tfor (Rsyn::Pin driver : net.allPins(Rsyn::DRIVER)) {\n\t\t\t\t\t\t\t\tlower = std::max(lower, depth[driver.getInstance()]);\n\t\t\t\t\t\t\t} // end for\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end for\t\t\t\t\t\n\t\t\t\t} // end if\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t} // end case\n\t\t\t\n\t\t\tcase Rsyn::MODULE: {\n\t\t\t\tfor (Rsyn::Pin pin : instance.allPins()) {\n\t\t\t\t\tRsyn::Net net = pin.getNet();\n\t\t\t\t\tif (net) {\n\t\t\t\t\t\tfor (Rsyn::Pin driver : net.allPins(Rsyn::DRIVER)) {\n\t\t\t\t\t\t\tlower = std::max(lower, depth[driver.getInstance()]);\n\t\t\t\t\t\t} // end for\n\t\t\t\t\t} // end if\n\t\t\t\t} // end for\t\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t} // end case\n\t\t\t\n\t\t\tcase Rsyn::PORT: {\n\t\t\t\tRsyn::Port port = instance.asPort();\n\t\t\t\tswitch (port.getDirection()) {\n\t\t\t\t\tcase Rsyn::IN: {\n\t\t\t\t\t\t// Nothing to be done here... (depth = 0)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} // end case\n\t\t\t\t\t\n\t\t\t\t\tcase Rsyn::OUT: {\n\t\t\t\t\t\tRsyn::Net net = port.getInnerPin().getNet();\n\t\t\t\t\t\tif (net) {\n\t\t\t\t\t\t\tfor (Rsyn::Pin driver : net.allPins(Rsyn::DRIVER)) {\n\t\t\t\t\t\t\t\tlower = std::max(lower, depth[driver.getInstance()]);\n\t\t\t\t\t\t\t} // end for\n\t\t\t\t\t\t} // end if\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} // end case\n\t\t\t\t\t\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow Exception(\"Port direction not supported.\");\n\t\t\t\t} // end switch\n\t\t\t\n\t\t\t\tbreak;\n\t\t\t} // end case\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthrow Exception(\"unsupported type\");\n\t\t} // end switch\n\t\t\n\t\t// Increment lower to get the instance depth.\n\t\tlower += 1;\n\t\t\n\t\t// Stores the instance depth.\n\t\tdepth[instance] = lower;\n\t\t\n\t\t// Add instance to the level vector.\n\t\tif (levels.size() <= lower) {\n\t\t\tlevels.resize(lower + 1);\n\t\t} // end if\n\t\tlevels[lower].push_back(instance);\n\t} //  end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nModule::getNetsPerLogicalDepth(std::vector<std::vector<Rsyn::Net>> &levels) {\n\tlevels.clear();\n\tstd::cout << \"TODO: getNetsPerLogicalDepth() not implemented\\n\";\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint\nModule::getNumPorts(const Direction direction) const {\n\treturn data->moduleData->portsByDirection[direction].size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<ReferenceListCollection<Instance>>\nModule::allInstances() const {\n\treturn ReferenceListCollection<Instance>(data->moduleData->instances);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<ReferenceListCollection<Port>>\nModule::allPorts() const {\n\treturn ReferenceListCollection<Port>(data->moduleData->ports);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::set<Port> &\nModule::allPorts(const Rsyn::Direction direction) const {\n\treturn data->moduleData->portsByDirection[direction];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<ReferenceListCollection<Net>>\nModule::allNets() const {\n\treturn ReferenceListCollection<Net>(data->moduleData->nets);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPinsFilteredByDirection>\nModule::allInterfacePins(const Direction direction) const {\n\treturn Instance::allPins(direction);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPins>\nModule::allInterfacePins() const {\n\treturn Instance::allPins();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfArcs>\nModule::allInterfaceArcs() const {\n\treturn Instance::allArcs();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::vector<TupleElement<1, TopologicalIndex, Pin>>\nModule::allPinsInTopologicalOrder() const {\n\tconst int numNets = data->moduleData->nets.size();\n\n\tstd::vector<TupleElement<1, TopologicalIndex, Pin>> sortedPins;\n\tsortedPins.reserve(numNets*3);\n\n\tfor (Rsyn::Instance instance : allInstances()) {\n\t\tfor (Rsyn::Pin pin : instance.allPins())\n\t\t\tsortedPins.push_back(std::make_tuple(pin.getTopologicalIndex(), pin));\n\t} // end for\n\n\tstd::sort(sortedPins.begin(), sortedPins.end());\n\treturn sortedPins;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::vector<TupleElement<1, TopologicalIndex, Pin>>\nModule::allPinsInReverseTopologicalOrder() const {\n\tconst int numNets = data->moduleData->nets.size();\n\n\tstd::vector<TupleElement<1, TopologicalIndex, Pin>> sortedPins;\n\tsortedPins.reserve(numNets*3);\n\n\tfor (Rsyn::Instance instance : allInstances()) {\n\t\tfor (Rsyn::Pin pin : instance.allPins())\n\t\t\tsortedPins.push_back(std::make_tuple(-pin.getTopologicalIndex(), pin));\n\t} // end for\n\n\tstd::sort(sortedPins.begin(), sortedPins.end());\n\treturn sortedPins;\n} // end method\n// -----------------------------------------------------------------------------\n\ninline\nstd::vector<TupleElement<1, TopologicalIndex, Net>>\nModule::allNetsInTopologicalOrder() const {\n\tconst int numNets = data->moduleData->nets.size();\n\t\n\tstd::vector<TupleElement<1, TopologicalIndex, Net>> sortedNets;\n\tsortedNets.resize(numNets);\n\t\n\tint i = 0;\n\tfor (Rsyn::Net net : allNets()) {\n\t\tsortedNets[i++] = std::make_tuple(net.getTopologicalIndex(), net);\n\t} // end for\n\tsortedNets.resize(i);\n\tstd::sort(sortedNets.begin(), sortedNets.end());\n\t\t\n\treturn sortedNets;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::vector<TupleElement<1, TopologicalIndex, Net>>\nModule::allNetsInReverseTopologicalOrder() const {\n\tconst int numNets = data->moduleData->nets.size();\n\t\n\tstd::vector<TupleElement<1, TopologicalIndex, Net>> sortedNets;\n\tsortedNets.resize(numNets);\n\t\n\tint i = 0;\n\tfor (Rsyn::Net net : allNets()) {\n\t\tsortedNets[i++] = std::make_tuple(-net.getTopologicalIndex(), net);\n\t} // end for\n\tsortedNets.resize(i);\n\tstd::sort(sortedNets.begin(), sortedNets.end());\n\t\t\n\treturn sortedNets;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::vector<TupleElement<1, TopologicalIndex, Instance>>\nModule::allInstancesInTopologicalOrder() const {\n\tconst int numInstances = data->moduleData->instances.size();\n\t\n\tstd::vector<TupleElement<1, TopologicalIndex, Instance>> sortedInstances;\n\tsortedInstances.resize(numInstances);\n\t\n\tint i = 0;\n\tfor (Rsyn::Instance instance : allInstances()) {\n\t\tsortedInstances[i++] = std::make_tuple(instance.getTopologicalIndex(), instance);\n\t} // end for\n\tsortedInstances.resize(i);\n\tstd::sort(sortedInstances.begin(), sortedInstances.end());\n\t\t\n\treturn sortedInstances;\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Sorted Objects\n////////////////////////////////////////////////////////////////////////////////\t\n\ninline\nstd::vector<Rsyn::Net> \nModule::getFanoutConeNetsInBreadthFirstOrder(Rsyn::Pin seed) const {\n\tstd::vector<Rsyn::Net> result;\t\n\tstd::queue<Rsyn::Net> open;\n\t\n\t// Push seed net.\n\tRsyn::Net net = seed.getNet();\n\tif (net)\n\t\topen.push(net);\n\t\n\t// Breadth-first search.\n\tconst int sign = generateNextSign();\n\t\n\twhile (!open.empty()) {\n\t\tRsyn::Net currentNet = open.front();\n\t\topen.pop();\n\t\t\n\t\tif (currentNet->sign == sign)\n\t\t\tcontinue;\n\t\t\n\t\tcurrentNet->sign = sign;\n\t\tresult.push_back(currentNet);\n\t\t\n\t\t// Add neighbors.\n\t\tfor (Rsyn::Pin sink : currentNet.allPins(SINK)) {\n\t\t\tfor (Rsyn::Arc arc : sink.allOutgoingArcs()) {\n\t\t\t\tRsyn::Net net = arc.getToNet();\n\t\t\t\tif (net && net->sign != sign)\n\t\t\t\t\topen.push(net);\t\t\t\t\n\t\t\t} // end for\n\t\t} // end for\n\t} // end while\n\t\n\t// Return.\n\treturn result;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nstd::vector<Rsyn::Net>\nModule::getFaninConeNetsInBreadthFirstOrder(Rsyn::Pin seed) const {\n\tstd::vector<Rsyn::Net> result;\t\n\tstd::queue<Rsyn::Net> open;\n\t\n\t// Push seed net.\n\tRsyn::Net net = seed.getNet();\n\tif (net)\n\t\topen.push(net);\n\t\n\t// Breadth-first search.\n\tconst int sign = generateNextSign();\n\t\n\twhile (!open.empty()) {\n\t\tRsyn::Net currentNet = open.front();\n\t\topen.pop();\n\t\t\n\t\tif (currentNet->sign == sign)\n\t\t\tcontinue;\n\t\t\n\t\tcurrentNet->sign = sign;\n\t\tresult.push_back(currentNet);\n\t\t\n\t\t// Add neighbors.\n\t\tfor (Rsyn::Pin driver : currentNet.allPins(DRIVER)) {\n\t\t\tfor (Rsyn::Arc arc : driver.allIncomingArcs()) {\n\t\t\t\tRsyn::Net net = arc.getFromNet();\n\t\t\t\tif (net && net->sign != sign)\n\t\t\t\t\topen.push(net);\t\t\n\t\t\t} // end for\n\t\t} // end for\n\t} // end while\n\t\n\t// Return.\n\treturn result;\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Net.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nDesign\nNet::_getDesign() const {\n\t// TODO: too slow...\n\treturn _getParent().getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDesign\nNet::getDesign() {\n\treturn _getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design\nNet::getDesign() const {\n\treturn _getDesign();\n} // end method\n\t\n// -----------------------------------------------------------------------------\n\ninline\nModule\nNet::_getParent() const {\n\treturn data->parent;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nModule\nNet::getParent() {\n\treturn _getParent();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Module\nNet::getParent() const {\n\treturn _getParent();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nNet::getName() const {\n\treturn data? getDesign()->netNames[data->id] : NullName;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nNet::getNumPins() const {\n\treturn (int) data->pins.size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nNet::getNumSinks() const {\n\treturn data->numPinsOfType[SINK];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nNet::getNumDrivers() const {\n\treturn data->numPinsOfType[DRIVER];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin \nNet::getAnyDriver() const {\n\treturn data->driver;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArc\nNet::getArc(const Pin from, const Pin to) {\n\tfor (Arc arc : allArcs()) {\n\t\tif ((arc.getFromPin() == from) && (arc.getToPin() == to)) {\n\t\t\treturn arc;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nTopologicalIndex \nNet::getTopologicalIndex() const {\n\tTopologicalIndex order;\n\n\tif (hasMultipleDrivers()) {\n\t\t// Just to save runtime as this is not very common.\n\t\tfor (Rsyn::Pin driver : allPins(Rsyn::DRIVER)) {\n\t\t\torder = driver.getTopologicalIndex();\n\t\t} // end for\n\t} else if (hasDriver()) {\n\t\torder = getAnyDriver().getTopologicalIndex();\n\t} else {\n\t\t// No driver...\n\t\tif (hasSink()) {\n\t\t\torder = +std::numeric_limits<TopologicalIndex>::infinity();\n\t\t\tfor (Rsyn::Pin sink : allPins(Rsyn::SINK)) {\n\t\t\t\torder = std::min(order, sink.getTopologicalIndex());\n\t\t\t} // end for\n\t\t} else {\n\t\t\t// A floating ..\n\t\t\torder = MIN_TOPOLOGICAL_INDEX;\n\t\t} // end else\n\t} // end else\n\t\n\treturn order;\t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nNet::hasMultipleDrivers() const {\n\treturn getNumDrivers() > 1;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nNet::hasSingleDriver() const {\n\treturn getNumDrivers() == 1;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nNet::hasDriver() const {\n\treturn getNumDrivers() >= 1;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nNet::hasSink() const {\n\treturn getNumSinks() >= 1;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPins>\nNet::allPins(bool filterPG) const {\n\treturn CollectionOfPins(data->pins, filterPG);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPinsFilteredByDirection>\nNet::allPins(const Direction direction) const {\n\treturn CollectionOfPinsFilteredByDirection(data->pins, direction);\n} // end method\n\n// -----------------------------------------------------------------------------\n\t\ninline\nRange<CollectionOfArcs>\nNet::allArcs() const {\n \tif (hasMultipleDrivers()) {\n\t\tthrow Exception(\"Net::allArcs() does not support multiple drivers yet.\");\n\t} else {\n\t\tif (hasDriver()) {\n\t\t\treturn CollectionOfArcs(getAnyDriver()->arcs[FORWARD]);\n\t\t} else {\n\t\t\tstatic std::vector<Arc> emptyCollectionOfArcs; // dummy\n\t\t\treturn CollectionOfArcs(emptyCollectionOfArcs);\n\t\t} // end else\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\t\ninline\nbool\nNet::isIdeal() const {\n\tif (data->tag.ideal.isNotSpecified())\n\t\tthrow TagNotSpecifiedException(\"Ideal\");\n\treturn data->tag.ideal;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nNet::isClockNetwork() const {\n\tif (data->tag.type == NET_TYPE_TAG_NOT_SPECIFIED)\n\t\tthrow TagNotSpecifiedException(\"Net Type\");\n\treturn data->tag.type == NET_TYPE_TAG_CLOCK;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNetTypeTag\nNet::getNetTypeTag() const {\n\treturn data->tag.type;\n} // end method\n\n// =============================================================================\n// Tag\n// =============================================================================\n\ninline\nTristateFlag\nNetTag::getIdeal() const {\n\treturn data->type;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNetTypeTag\nNetTag::getType() const {\n\treturn data->type;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nNetTag::setType(const NetTypeTag value) {\n\tdata->type = value;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nNetTag::setIdeal(const bool value) {\n\tdata->ideal = value;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nUse\nNet::getUse() const {\n\treturn data->netUse;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid\nNet::setUse(const Use use) {\n\tdata->netUse = use;\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Object.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Pin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\ninline\nconst std::string\nPin::getName() const {\n\tswitch (getInstanceType()) {\n\t\tcase Rsyn::CELL:\n\t\t\treturn getLibraryPin().getName();\n\t\tcase Rsyn::PORT:\n\t\t\treturn getInstanceName();\n\t\tcase Rsyn::MODULE:\n\t\t\treturn getPort().getName();\n\t} // end switch\n\treturn \"<unknown>\";\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string \nPin::getFullName(const std::string::value_type separator) const {\n\tif (isPort()) {\n\t\treturn data? getName() : NullName;\n\t} else {\n\t\treturn data? (getInstance().getName() + separator + getName()) : NullName;\n\t} // end else\n} // end if\n\n// -----------------------------------------------------------------------------\n\ninline\nDesign\nPin::getDesign() {\n\t// TODO: too many indirection (more inside cell), maybe we need to cache \n\t// this.\n\treturn getInstance().getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst Design\nPin::getDesign() const {\n\t// TODO: too many indirection (more inside cell), maybe we need to cache \n\t// this.\n\treturn data->instance.getDesign();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nInstance\nPin::getInstance() const {\n\treturn data->instance;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nNet\nPin::getNet() const {\n\treturn data->net;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDirection\nPin::getDirection() const {\n\treturn data->direction; \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nPin::getIndex() const {\n\treturn data->index;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string\nPin::getInstanceName() const {\n\treturn getInstance().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nInstanceType\nPin::getInstanceType() const {\n\treturn data->type;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nPin::getNetName() const {\n\treturn getNet().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::string &\nPin::getDirectionName() const {\n\treturn Global::getDirectionName(getDirection());\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryPin \nPin::getLibraryPin() const {\n\tRsyn::LibraryCell lcell = getLibraryCell();\n\treturn lcell? lcell.getLibraryPinByIndex(data->index) : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nLibraryCell \nPin::getLibraryCell() const {\n\treturn getInstanceType() == Rsyn::CELL? \n\t\tdata->instance->lcell : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPort\nPin::getPort() const {\n\tswitch (getInstanceType()) {\n\t\tcase Rsyn::MODULE: \n\t\t\treturn getInstance().asModule().getPortByIndex(data->index);\n\t\tcase Rsyn::PORT:\n\t\t\treturn getInstance().asPort();\n\t\tdefault:\n\t\t\treturn nullptr;\n\t} // end if\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isPort() const {\n\treturn data->boundary;\n} // end method\n\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isPort(const Direction direction) const {\n\treturn isPort() && (getPort().getDirection() == direction);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nPin::isPortToUpLevelHierarchy() const {\n\treturn data->boundary && data->type == Rsyn::PORT;\n} // end method\n// -----------------------------------------------------------------------------\n\ninline\nbool \nPin::isPortToDownLevelHierarchy() const {\n\treturn data->boundary && data->type == Rsyn::MODULE;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isConnected() const {\n\treturn getNet();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nPin::isDisconnected() const {\n\treturn !getNet();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nPin::isInput() const {\n\treturn getDirection() == Rsyn::IN;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool \nPin::isOutput() const {\n\treturn getDirection() == Rsyn::OUT;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isBidirectional() const {\n\treturn getDirection() == Rsyn::BIDIRECTIONAL;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isDriver() const {\n\treturn isOutput();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isSink() const {\n\treturn isInput();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArc \nPin::getArcTo(Pin to) {\n\tfor (Arc arc : allOutgoingArcs()) {\n\t\tif (arc.getToPin() == to) {\n\t\t\treturn arc;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nArc \nPin::getArcFrom(Pin from) {\n\tfor (Arc arc : allIncomingArcs()) {\n\t\tif (arc.getFromPin() == from) {\n\t\t\treturn arc;\n\t\t} // end if\n\t} // end for\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\ninline\nint \nPin::getNumIncomingArcs() const {\n\treturn (int) data->arcs[BACKWARD].size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nint \nPin::getNumOutgomingArcs() const {\n\treturn (int) data->arcs[FORWARD].size();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfPredecessorPins>\nPin::allPredecessorPins(const bool crossBoundaries) const {\n\treturn CollectionOfPredecessorPins(*this, crossBoundaries);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nRange<CollectionOfSuccessorPins>\nPin::allSucessorPins(const bool crossBoundaries) const {\n\treturn CollectionOfSuccessorPins(*this, crossBoundaries);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::vector<Arc> &\nPin::allIncomingArcs() const {\n\treturn data->arcs[BACKWARD];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::vector<Arc> &\nPin::allOutgoingArcs() const {\n\treturn data->arcs[FORWARD];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nconst std::vector<Arc> &\nPin::allArcs(const TraverseType direction) const {\n\treturn data->arcs[direction];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid \nPin::connect(Net net) {\n\tgetDesign().connectPin(*this, net);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nvoid \nPin::disconnect() {\n\tgetDesign().disconnectPin(*this);\n} // end method\n\t\n// -----------------------------------------------------------------------------\n\ninline\nTopologicalIndex\nPin::getTopologicalIndex() const {\n\treturn data->order;\n} // end method\n\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isMacroBlockPin() const {\n\treturn data->instance.isMacroBlock();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isConnectedToClockNetwork() const {\n\treturn data->net? data->net.isClockNetwork() : false;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nUse\nPin::getUse() const {\n\tRsyn::LibraryPin lpin = getLibraryPin();\n\t\n\tif (!lpin) {\n\t\treturn Rsyn::UNKNOWN_USE;\n\t} // end if\n\t\n\treturn lpin.getUse();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nbool\nPin::isPowerOrGround() const {\n\tRsyn::LibraryPin lpin = getLibraryPin();\n\t\n\tif (!lpin) {\n\t\treturn false;\n\t} // end if\n\t\n\treturn (lpin.getUse() == POWER || lpin.getUse() == GROUND);\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/core/obj/impl/Port.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline\nPin \nPort::getInnerPin() const {\n\t// Ports have just one pin, which is the inner pin...\n\treturn data->pins[0];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin \nPort::getOuterPin() const {\n\treturn Pin(data->outerPin);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nPin \nPort::getOtherPin(Pin pin) const {\n\tRsyn::Pin inner = getInnerPin();\n\tRsyn::Pin outer = getOuterPin();\n\tif (inner == pin) return outer;\n\tif (outer == pin) return inner;\n\treturn nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline\nDirection\nPort::getDirection() const {\n\treturn Global::getReverseDirection(getInnerPin().getDirection());\n} // end method\n\t\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/db/Database.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/db/Database.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_DATABASE_H\n#define RSYN_DATABASE_H\n\n#include <string>\n\n#include <Serializable.h>\n#include <SerializationStream.h>\n\nnamespace Rsyn {\nclass Database {\npublic:\n\n\tvoid read(const std::string &key, Serializable &data);\n\tvoid write(const std::string &key, const Serializable &data);\n\n};\n} // end namespace\n\n#endif \n\n"
  },
  {
    "path": "rsyn/src/rsyn/db/Serializable.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_SERIALIZABLE_H\n#define RSYN_SERIALIZABLE_H\n\n#include \"SerializationStream.h\"\n\nnamespace Rsyn {\nclass Serializable {\npublic:\n\tvirtual void read(Rsyn::SerializationStream &stream) = 0;\n\tvirtual void write(Rsyn::SerializationStream &stream) = 0;\n}; // end class\n}\n\n#endif /* SERIALIZABLE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/db/SerializationStream.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_SERIALIZATION_STREAM_H\n#define RSYN_SERIALIZATION_STREAM_H\n\n#include <string>\n#include <vector>\n\n// Note: Reference types are special as they are stored as an id in the stream,\n// but as a pointer in the memory (for efficiency reasons). Hence they need to\n// be converted to pointers once the database is loaded. We accomplish that by\n// storing the id in the reference during the database loading and registering\n// it for  conversion once the database is fully read. Notice that an on-the-fly\n// conversion may not be always possible as the referenced value may not be\n// loaded yet (so we still don't know its position in the memory to get a\n// pointer).\n\nnamespace Rsyn {\nclass SerializationStream {\npublic:\n\n\ttemplate<class T>\n\tvoid read(T &value);\n\n\ttemplate<class T>\n\tvoid read(std::vector<T> &value);\n\n\ttemplate<class T>\n\tvoid read(std::vector<std::vector<T>> &value);\n\n\tvoid read(Rsyn::Instance &instance);\n\tvoid read(Rsyn::Net &net);\n\tvoid read(Rsyn::Pin &pin);\n\tvoid read(Rsyn::Arc &arc);\n\tvoid read(Rsyn::LibraryCell &lcell);\n\tvoid read(Rsyn::LibraryPin &lpin);\n\tvoid read(Rsyn::LibraryArc &larc);\n\n\ttemplate<class T>\n\tvoid write(const T &value);\n\n\ttemplate<class T>\n\tvoid write(const std::vector<T> &value);\n\n\ttemplate<class T>\n\tvoid write(const std::vector<std::vector<T>> &value);\n\n\tvoid write(const Rsyn::Instance &instance);\n\tvoid write(const Rsyn::Net &net);\n\tvoid write(const Rsyn::Pin &pin);\n\tvoid write(const Rsyn::Arc &arc);\n\tvoid write(const Rsyn::LibraryCell &lcell);\n\tvoid write(const Rsyn::LibraryPin &lpin);\n\tvoid write(const Rsyn::LibraryArc &larc);\n\nprivate:\n\n};\n}\n\n#endif /* SERIALIZATIONSTREAM_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/DesignObserver",
    "content": "#include \"rsyn/core/infra/Observer.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/PhysicalDesign",
    "content": "#include \"rsyn/phy/PhysicalDesign.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/PhysicalDesignObserver",
    "content": "#include \"rsyn/phy/infra/PhysicalObserver.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/Point",
    "content": "#include \"rsyn/util/geometry/Point.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/Polygon",
    "content": "#include \"rsyn/util/geometry/Polygon.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/Rect",
    "content": "#include \"rsyn/util/geometry/Rect.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/RoutingGuide",
    "content": "#include \"rsyn/ispd18/RoutingGuide.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/Scenario",
    "content": "#include \"rsyn/model/scenario/Scenario.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/Session",
    "content": "#include \"rsyn/session/Session.h\""
  },
  {
    "path": "rsyn/src/rsyn/export/Rsyn/Timer",
    "content": "#include \"rsyn/model/timing/Timer.h\""
  },
  {
    "path": "rsyn/src/rsyn/io/legacy/Legacy.h",
    "content": "/* Copyright 2014-2018 Rsyn\t\t\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_LEGACY_H\n#define RSYN_LEGACY_H\n\n#include <string>\n\n#include \"rsyn/core/Rsyn.h\"\n\nnamespace Legacy {\n\ninline Rsyn::Direction lefPinDirectionFromString(const std::string &direction) {\n\tif (direction == \"INPUT\"   ) return Rsyn::IN;\n\tif (direction.substr(0, 6) == \"OUTPUT\"  ) return Rsyn::OUT;\n\tif (direction == \"INOUT\"   ) return Rsyn::BIDIRECTIONAL;\n\tif (direction == \"FEEDTHRU\") return Rsyn::UNKNOWN_DIRECTION;\n\treturn Rsyn::UNKNOWN_DIRECTION;\n} // end function\n\ninline Rsyn::Use lefPinUseFromString(const std::string &direction) {\n\tif (direction == \"SIGNAL\"   ) return Rsyn::SIGNAL;\n\tif (direction == \"POWER\"    ) return Rsyn::POWER;\n\tif (direction == \"GROUND\"  ) return Rsyn::GROUND;\n\tif (direction == \"CLOCK\") return Rsyn::CLOCK;\n\tif (direction == \"TIEOFF\") return Rsyn::TIEOFF;\n\tif (direction == \"ANALOG\") return Rsyn::ANALOG;\n\tif (direction == \"SCAN\") return Rsyn::SCAN;\n\tif (direction == \"RESET\") return Rsyn::RESET;\n\treturn Rsyn::UNKNOWN_USE;\n} // end function\n\n\ninline Rsyn::Direction bookshelfPinDirectionFromString(const std::string &direction) {\n\tif (direction == \"I\") return Rsyn::IN;\n\tif (direction == \"O\") return Rsyn::OUT;\n\tif (direction == \"B\") return Rsyn::OUT; // Due to Rsyn restrictions, I am considering the Bidirectional is only output.\n\treturn Rsyn::UNKNOWN_DIRECTION;\n} // end function\n\ninline std::string bookshelfPinDirectionToString(const Rsyn::Direction direction) {\n\tif (direction == Rsyn::IN) return \"I\";\n\tif (direction == Rsyn::OUT) return \"O\";\n\tif (direction == Rsyn::BIDIRECTIONAL) return \"B\";\n\treturn \"<DIRECTION_UNKNOWN>\";\n} // end function\n\n} // end namespace\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/io/legacy/PlacerInternals.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef PLACER_INTERNALS_H\n#define\tPLACER_INTERNALS_H\n\n#include <string>\n#include <vector>\n\n////////////////////////////////////////////////////////////////////////////////\n// Design Descriptor\n////////////////////////////////////////////////////////////////////////////////\n#include \"rsyn/util/Bounds.h\"\n#include \"rsyn/util/dbu.h\"\n\nnamespace Legacy {\n\nstruct Design {\n\tstruct Component {\n\t\tstd::string id;\n\t\tstd::string name;\n\t\tbool fixed;\n\t\tbool placed;\n\t\tdouble x;\n\t\tdouble y;\n\t};\n\n\tstruct Connection {\n\t\tstd::string pin;\n\t\tstd::string instance;\n\t};\n\t\n\tstruct Net {\n\t\tstd::string name;\n\t\tstd::vector<Connection> connections;\n\t};\n\n\tstruct Row {\n\t\tdouble x;\n\t\tdouble y;\n\t\tint numSitesX;\n\t\tint numSitesY;\n\t\tstd::string site;\n\t\tstd::string name;\n\t\tdouble stepX;\n\t\tdouble stepY;\n\t};\n\t\n\tstruct Pin {\n\t\tstd::string name;\n\t\tstd::string net;\n\t\tstd::string metal;\n\t\tstd::string direction;\n\t\tdouble x;\n\t\tdouble y;\n\t\tDBUxy routingLower;\n\t\tDBUxy routingUpper;\n\t};\n\t\n\tstruct DieArea {\n\t\tint xmin;\n\t\tint ymin;\n\t\tint xmax;\n\t\tint ymax;\n\t};\n\n\tstruct Track {\n\t\tstd::string direction; //X or Y\n\t\tint doStart;\n\t\tint doCount;\n\t\tint doStep;\n\t\tint numLayers;\n\t\tstd::vector<std::string> layers;\n\t\tTrack () : direction(\"NULL\"), doStart(-1), doCount(-1), doStep(-1),\n\t\tnumLayers(-1) {}\n\t};\n\t\n\tstruct GCellGrid {\n\t\tstd::string master; // direction X or Y\n\t\tint doStart;\n\t\tint doCount;\n\t\tint doStep;\n\t\tGCellGrid () : master(\"null\"), doStart(-1), doCount(-1), doStep(-1) {}\n\t};\n\t\n\tstd::string name;\n\tdouble distanceUnit;\n\tdouble defVersion;\n\t\n\tstd::vector<Component> components;\n\tstd::vector<Pin> ports;\n\tstd::vector<Net> nets;\n\tstd::vector<Row> rows;\n\t\n\tstd::vector<std::string> primaryInputs;\n\tstd::vector<std::string> primaryOutputs;\n\t\n\tstd::vector<Track> tracks;\n\tstd::vector<GCellGrid> gCellGrids;\n\t\n\tDieArea dieArea;\n\t\n\tDesign() {\n\t\tdistanceUnit = 1;\n\t\tdefVersion = -1;\n\t}\n}; // end struct\n\n////////////////////////////////////////////////////////////////////////////////\n// Library Descriptor\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Library {\n\tstruct Site {\n\t\tstd::string name;\n\t\tstd::string classSite;\n\t\tbool hasClass;\n\t\tdouble w;\n\t\tdouble h;\n\t\t\n\t\tSite() :name(\"null\"), classSite(\"null\"), hasClass(false), w(0), h(0) {}\n\t};\n\t\n\tstruct Pin {\n\t\tstd::string name;\n\t\tstd::string direction;\n\t\tstd::string metalLayer;\n\t\tBounds bound;\n\t\tstd::vector<Bounds> routerPins;\n\t\tdouble dx;\n\t\tdouble dy;\n\t\t\n\t\tPin() : dx(0), dy(0), metalLayer(\"null\") {}\n\t};\n\t\n\tstruct Obstruction {\n\t\tstd::string layer; \n\t\tstd::vector<Bounds> rects;\n\t};\n\t\n\tstruct Macro {\n\t\tstd::string name;\n\t\tstd::string type;\n\t\tstd::string site;\n\t\tdouble w;\n\t\tdouble h;\n\t\tstd::vector<Pin> pins;\n\t\tstd::vector<Obstruction> obs;\n\t\tMacro () : w(0), h(0) {}\n\t}; // end struct\n\t\n\tstruct Layer { // for metals, vias and contacts\n\t\tstd::string name;\n\t\tstd::string type;\n\t\tstd::string direction;\n\t\tdouble pitch;\n\t\tdouble width;\n\t\tdouble spacing;\n\t\tLayer () : name(\"null\"), type(\"null\"), direction(\"null\"), \n\t\tpitch(-1), width(-1), spacing(-1) {}\n\t};\n\t\n\tstruct Spacing {\n\t\tstd::string name1;\n\t\tstd::string name2;\n\t\tdouble distance;\n\t};\n\t\t\n\tstd::string name;\n\tdouble distanceUnit;\n\tstd::vector<Macro> macros;\n\tstd::vector<Site> sites;\n\tstd::vector<Layer> layers;\n\tstd::vector<Spacing> metalSpaces;\n\t\n\tLibrary() : distanceUnit(1) {}\t\n}; // end struct\n\n\nstruct DefStruct1 {\n\t\n\tstruct DefMacro {\n\t\tstd::string  name;\n\t\tstd::string lefCellName;\n\t\tbool placed;\n\t\tbool fixed;\n\t\tDBUxy pos;\n\t};\n\t\n\tstruct DefPin {\n\t\tstd::string pinName;\n\t\tstd::string cellName;\n\t};\n\t\n\tstruct DefConnection {\n\t\tstd::string netName;\n\t\tstd::vector<DefPin> pins; //cell and pin\n\t};\n\t\n\tstruct DefRow {\n\t\tstd::string rowName;\n\t\tstd::string rowType;\n\t\tint origX;\n\t\tint origY;\n\t\tint orient;\n\t\tint doCount;\n\t\tint doIncrement;\n\t\tint xStep;\n\t\tint yStep;\n\t\tDefRow () : rowType(\"core\"), origX(0), origY(0), orient(0), doCount(0), doIncrement(0), xStep(0), yStep(0) {}\n\t\t// orient {0, 1, 2, 3, 4, 5, 6, 7} = {N, W, S, E, FN, FW, FS, FE} source: defapi.pdf version 5.8 \n\t};\n\n\tstruct DefPortLayer {\n\t\tstd::string layerName;\n\t\tint spacing;\n\t\tint designRuleWidth;\n\t\tBounds bounds;\n\t\tDefPortLayer() : spacing(0), designRuleWidth(0), layerName(\"NULL\") {}\n\t};\n\n\tstruct DefPort {\n\t\tstd::string portName;\n\t\tstd::string netName;\n\t\tint special; // 0 is ignored; 1 writes a SPECIAL statement\n\t\tstd::string direction; // {NULL, FEEDTHRU, INPUT, INOUT, OUTPUT}\n\t\tstd::string use; // {NULL, ANALOG, CLOCK, GROUND, POWER, RESET, SCAN, SIGNAL, TIEOFF}\n\t\tstd::string status; // {NULL, COVER, FIXED, PLACED} \n\t\tint statusX; // placement location; 0 ignore\n\t\tint statusY; // placement location; 0 ignore\n\t\tint orient;  // orient {-1, 0, 1, 2, 3, 4, 5, 6, 7} = {IGNORE, N, W, S, E, FN, FW, FS, FE} source: defapi.pdf version 5.8 \n\t\tDefPortLayer clsDefPortLayer;\n\t\tDefPort () : direction(\"NULL\"), orient(-1), special(0), status(\"NULL\"), use(\"NULL\") {}\n\t};\n\n\tstd::vector<DefMacro> clsDefMacros;\n\tstd::vector<DefPort> clsDefPorts;\n\tstd::vector<DefConnection> clsDefConnections;\n\tstd::vector<DefRow> clsDefRows;\n\t\n\tint majorDefVersion;\n\tint minorDefVersion;\n\tstd::string devideChar;\n\tstd::string busBitChar;\n\tstd::string designName;\n\tint designUnits;\n\tBounds dieArea;\n\t\n}; // end struct\n\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/guide-ispd18/GuideDescriptor.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef ISPD18GUIDEDESCRIPTOR_H\n#define ISPD18GUIDEDESCRIPTOR_H\n\n#include <deque>\n#include \"rsyn/util/Bounds.h\"\n\nclass GuideLayerDscp {\npublic:\n\tBounds clsLayerGuide;\n\tstd::string clsLayer = \"\";\n\tGuideLayerDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass GuideNetDscp {\npublic:\n\tstd::string clsNetName = \"\";\n\tstd::deque<GuideLayerDscp> clsLayerDscps;\n\tGuideNetDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass GuideDscp {\npublic:\n\tstd::deque<GuideNetDscp> clsNetGuides;\n\tGuideDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n#endif /* ISPD18GUIDEDESCRIPTOR_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/guide-ispd18/GuideParser.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#include <iostream>\n#include \"rsyn/io/parser/guide-ispd18/GuideParser.h\"\n\nvoid GuideParser::parse(std::string& guidePath, GuideDscp& guideDscp) {\n\tclsIS.open(guidePath.c_str());\n\tif (!clsIS.is_open()) {\n\t\tstd::cout << \"[ERROR] File '\" << guidePath << \"' could not be opened.\\n\";\n\t\texit(1);\n\t} // end if\n\n\twhile (!clsIS.eof()) {\n\t\tstd::string netName;\n\t\tif(!readNet(netName))\n\t\t\tcontinue;\n\t\tstd::deque<GuideNetDscp> & nets = guideDscp.clsNetGuides;\n\t\tnets.push_back(GuideNetDscp());\n\t\tGuideNetDscp & net = nets.back();\n\t\tnet.clsNetName = netName;\n\t\treadLayerGuide(net);\n\t} // end while \n\tclsIS.close();\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool GuideParser::readLine(std::vector<std::string>& tokens) {\n\ttokens.clear();\n\tstd::string line;\n\tstd::getline(clsIS, line);\n\tstd::string token = \"\";\n\n\tfor (unsigned i = 0; i < line.size(); ++i) {\n\t\tchar current = line[i];\n\t\tif (std::isspace(current)) {\n\t\t\tif (!token.empty()) {\n\t\t\t\ttokens.push_back(token);\n\t\t\t\ttoken.clear();\n\t\t\t} // end if \n\t\t} else {\n\t\t\ttoken.push_back(current);\n\t\t} //vend if-else \n\t} // end for \n\tif (!token.empty())\n\t\ttokens.push_back(token);\n\n\treturn !clsIS.eof();\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool GuideParser::readNet(std::string & net) {\n\tstd::vector<std::string> tokens;\n\treadLine(tokens);\n\tif (tokens.empty())\n\t\treturn false;\n\tnet = tokens.front();\n\treturn true;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool GuideParser::isStartLayer(std::string & token) {\n\treturn token.compare(\"(\") == 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool GuideParser::isEndLayer(std::string & token) {\n\treturn token.compare(\")\") == 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool GuideParser::readLayerGuide(GuideNetDscp & dscp) {\n\twhile (true) {\n\t\tstd::vector<std::string> tokens;\n\t\treadLine(tokens);\n\t\tif (isStartLayer(tokens.front()))\n\t\t\tcontinue;\n\t\tif (isEndLayer(tokens.front()))\n\t\t\treturn true;\n\t\tif(tokens.size() < 5) { \n\t\t\tstd::cout<<\"WARNING: skipping parsing a layer guide of net \"<<dscp.clsNetName\n\t\t\t\t<<\". The guide definition has less then four points or it do not has defined the layer name.\\n\";\n\t\t\tcontinue;\n\t\t} // end if \n\t\t\t\n\t\tdscp.clsLayerDscps.push_back(GuideLayerDscp());\n\t\tGuideLayerDscp & layer = dscp.clsLayerDscps.back();\n\t\tBounds & bds = layer.clsLayerGuide;\n\t\tbds[LOWER][X] = std::stoi(tokens[0]);\n\t\tbds[LOWER][Y] = std::stoi(tokens[1]);\n\t\tbds[UPPER][X] = std::stoi(tokens[2]);\n\t\tbds[UPPER][Y] = std::stoi(tokens[3]);\n\t\tlayer.clsLayer = tokens[4];\n\t} // end while \n\treturn false;\n} // end method \n\n// -----------------------------------------------------------------------------"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/guide-ispd18/GuideParser.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef ISPD18GUIDEPARSER_H\n#define\tISPD18GUIDEPARSER_H\n#include <fstream>\n#include <vector>\n#include \"GuideDescriptor.h\"\n#include \"rsyn/util/Bounds.h\"\n/*net1230\n(\n95010 71819 100710 91201 Metal2\n95010 83220 100710 91201 Metal1\n89310 71819 100710 77520 Metal3\n95010 71819 100710 77520 Metal2\n89310 71819 95010 77520 Metal2\n89310 71819 95010 77520 Metal2\n89310 71819 95010 77520 Metal1\n)\n */\n\nclass GuideParser {\nprotected:\n\t std::ifstream clsIS;\npublic:\n\tGuideParser() = default;\n\tvoid parse(std::string & guidePath, GuideDscp & guideDscp);\n\t\nprotected:\n\tbool readLine(std::vector<std::string>& tokens);\n\tbool readNet(std::string & net);\n\tbool isStartLayer(std::string & token);\n\tbool isEndLayer(std::string & token);\n\tbool readLayerGuide(GuideNetDscp & dscp);\n\t\n};\n\n\n\n\n#endif /* ISPD18GUIDEPARSER_H */"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/lef_def/DEFControlParser.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include \"DEFControlParser.h\"\n\n#ifndef WIN32\n#include <unistd.h>\n#else\n#include <windows.h>\n#endif /* not WIN32 */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n\n// DEF headers\n#include \"def5.8/defiComponent.hpp\"\n#include \"def5.8/defiNet.hpp\"\n#include \"def5.8/defiRowTrack.hpp\"\n\n#include \"def5.8/defwWriter.hpp\"\n\n#include \"def5.8/defrReader.hpp\"\n\nextern void freeCB(void* name);\nextern void* mallocCB(size_t size);\nextern void* reallocCB(void* name, size_t size);\n\n#include \"rsyn/util/Bounds.h\"\n#include \"rsyn/util/DoubleRectangle.h\"\n\n// -----------------------------------------------------------------------------\n\nDEFControlParser::DEFControlParser() {\n} // end constructor\n\n// -----------------------------------------------------------------------------\n\nDEFControlParser::~DEFControlParser() {\n\n} // end destructor\n\n// -----------------------------------------------------------------------------\n\n//DEF CALLBACKS\nchar* defAddress(const char* in);\nvoid defCheckType(defrCallbackType_e c);\nint defCompf(defrCallbackType_e c, defiComponent* co, defiUserData ud);\nint defComponentStart(defrCallbackType_e c, int num, defiUserData ud);\nint defDesignName(defrCallbackType_e c, const char* string, defiUserData ud);\nint defEndFunc(defrCallbackType_e c, void* dummy, defiUserData ud);\nint defExt(defrCallbackType_e t, const char* c, defiUserData ud);\nint defNetStart(defrCallbackType_e c, int num, defiUserData ud);\nint defNetWires(defiNet* net, DefNetDscp& netDscp);\nint defNet(defrCallbackType_e c, defiNet* net, defiUserData ud);\nint defUnits(defrCallbackType_e c, double d, defiUserData ud);\nint defVersion(defrCallbackType_e c, double d, defiUserData ud);\nint defRow(defrCallbackType_e type, defiRow* rowInfo, defiUserData userData);\nchar* defOrientStr(int orient);\nint defOrient(std::string orient);\nint defDieArea(defrCallbackType_e typ, defiBox* box, defiUserData ud);\nint defTrack(defrCallbackType_e typ, defiTrack * track, defiUserData data);\nint defGCellGrid(defrCallbackType_e typ, defiGcellGrid * gCell, defiUserData data);\nint defRegion(defrCallbackType_e type, defiRegion* region, defiUserData ud);\nint defRegionStart(defrCallbackType_e c, int num, defiUserData ud);\nint defGroupStart(defrCallbackType_e c, int num, defiUserData ud);\nint defGroupMember(defrCallbackType_e type, const char* name, defiUserData userData);\nint defGroupName(defrCallbackType_e type, const char* name, defiUserData ud);\nint defGroups(defrCallbackType_e type, defiGroup *group, defiUserData ud);\n\nint defPin(defrCallbackType_e, defiPin *pin, defiUserData ud);\nint defSpecialNetStart(defrCallbackType_e c, int num, defiUserData ud);\nint defSpecialNet(defrCallbackType_e c, defiNet* net, defiUserData ud);\nint defViaStart(defrCallbackType_e, int number, defiUserData);\nint defVia(defrCallbackType_e, defiVia *, defiUserData);\n\nDefDscp &getDesignFromUserData(defiUserData userData) {\n\treturn *((DefDscp *) userData);\n} // end function\n\n// =============================================================================\n// DEF Function Implementation\n// =============================================================================\n\nvoid DEFControlParser::parseDEF(const std::string &filename, DefDscp &defDscp) {\n\tdefrInit();\n\tdefrReset();\n\n\t//defrSetAddPathToNet();\n\tdefrSetComponentCbk(defCompf);\n\tdefrSetDesignCbk(defDesignName);\n\tdefrSetPinCbk(defPin);\n\tdefrSetUnitsCbk(defUnits);\n\tdefrSetVersionCbk(defVersion);\n\tdefrSetRowCbk(defRow);\n\tdefrSetComponentStartCbk(defComponentStart);\n\tdefrSetDieAreaCbk(defDieArea);\n\tdefrSetMallocFunction(mallocCB);\n\tdefrSetReallocFunction(reallocCB);\n\tdefrSetFreeFunction(freeCB);\n\tdefrSetNetStartCbk(defNetStart);\n\tdefrSetNetCbk(defNet);\n\n\n\t//defrSetSNetWireCbk();\n\n\tdefrSetGroupsStartCbk(defGroupStart);\n\tdefrSetGroupNameCbk(defGroupName);\n\tdefrSetGroupMemberCbk(defGroupMember);\n\tdefrSetGroupCbk(defGroups);\n\tdefrSetTrackCbk(defTrack);\n\tdefrSetGcellGridCbk(defGCellGrid);\n\tdefrSetRegionStartCbk(defRegionStart);\n\tdefrSetRegionCbk(defRegion);\n\n\t// register special net call backs\n\tdefrSetSNetStartCbk(defSpecialNetStart);\n\tdefrSetSNetCbk(defSpecialNet);\n\n\t// register via call backs\n\tdefrSetViaStartCbk(defViaStart);\n\tdefrSetViaCbk(defVia);\n\n\t//defrSetGcellGridWarnings(3);\n\n\tdefrSetAddPathToNet();\n\n\tFILE * f;\n\tint res;\n\n\t(void) defrSetOpenLogFileAppend();\n\n\n\n\tif ((f = fopen(filename.c_str(), \"r\")) == 0) {\n\t\tprintf(\"Couldn't open input file '%s'\\n\", filename.c_str());\n\t\treturn;\n\t}\n\t// Set case sensitive to 0 to start with, in History & PropertyDefinition\n\t// reset it to 1.\n\tres = defrRead(f, filename.c_str(), (void*) &defDscp, 1);\n\n\tif (res)\n\t\tprintf(\"Reader returns bad status. %s\\n\", filename.c_str());\n\n\t//(void) defrPrintUnusedCallbacks(fout);\n\t(void) defrReleaseNResetMemory();\n\t(void) defrUnsetNonDefaultCbk();\n\t(void) defrUnsetNonDefaultStartCbk();\n\t(void) defrUnsetNonDefaultEndCbk();\n\tdefrClear();\n\n}\n\n// -----------------------------------------------------------------------------\n\nchar* defAddress(const char* in) {\n\treturn ((char*) in);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid defCheckType(defrCallbackType_e c) {\n\tif (c >= 0 && c <= defrDesignEndCbkType) {\n\t\t// OK\n\t} else {\n\t\tprintf(\"ERROR: callback type is out of bounds!\\n\");\n\t}\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defRow(defrCallbackType_e type, defiRow* rowInfo, defiUserData userData) {\n\tDefDscp &defDscp = getDesignFromUserData(userData);\n\tdefDscp.clsRows.resize(defDscp.clsRows.size() + 1);\n\tDefRowDscp &defRow = defDscp.clsRows.back();\n\tdefRow.clsName = rowInfo->name();\n\tdefRow.clsSite = rowInfo->macro();\n\tdefRow.clsOrientation = rowInfo->orientStr();\n\tdefRow.clsOrigin[X] = static_cast<DBU> (rowInfo->x());\n\tdefRow.clsOrigin[Y] = static_cast<DBU> (rowInfo->y());\n\n\tif (rowInfo->hasDoStep()) {\n\t\tdefRow.clsNumX = static_cast<int> (rowInfo->xNum());\n\t\tdefRow.clsNumY = static_cast<int> (rowInfo->yNum());\n\t\tdefRow.clsStepX = static_cast<int> (rowInfo->xStep());\n\t\tdefRow.clsStepY = static_cast<int> (rowInfo->yStep());\n\t} else if (rowInfo->hasDo()) {\n\t\tdefRow.clsNumX = static_cast<int> (rowInfo->xNum());\n\t\tdefRow.clsNumY = static_cast<int> (rowInfo->yNum());\n\t\tdefRow.clsStepX = 0;\n\t\tdefRow.clsStepY = 0;\n\t} else {\n\t\tdefRow.clsNumX = 1;\n\t\tdefRow.clsNumY = 1;\n\t\tdefRow.clsStepX = 0;\n\t\tdefRow.clsStepY = 0;\n\t} // end else\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defPin(defrCallbackType_e, defiPin *pin, defiUserData userData) {\n\tDefDscp &defDscp = getDesignFromUserData(userData);\n\tdefDscp.clsPorts.resize(defDscp.clsPorts.size() + 1);\n\tDefPortDscp &defPin = defDscp.clsPorts.back();\n\n\tdefPin.clsName = pin->pinName();\n\tdefPin.clsNetName = pin->netName();\n\tdefPin.clsDirection = pin->direction();\n\tdefPin.clsPos[X] = pin->placementX();\n\tdefPin.clsPos[Y] = pin->placementY();\n\tdefPin.clsICCADPos = defPin.clsPos;\n\tdefPin.clsOrientation = pin->orientStr();\n\tif (pin->hasLayer()) {\n\t\tdefPin.clsLayerName = pin->layer(0);\n\t\tint xl, yl, xh, yh;\n\t\tpin->bounds(0, &xl, &yl, &xh, &yh);\n\t\tdefPin.clsLayerBounds[LOWER][X] = xl;\n\t\tdefPin.clsLayerBounds[LOWER][Y] = yl;\n\t\tdefPin.clsLayerBounds[UPPER][X] = xh;\n\t\tdefPin.clsLayerBounds[UPPER][Y] = yh;\n\t\tdefPin.clsICCADPos += defPin.clsLayerBounds.computeCenter(); // legacy iccad15 contest pin position\n\t} // end if \n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defCompf(defrCallbackType_e c, defiComponent* co, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsComps.push_back(DefComponentDscp());\n\tDefComponentDscp &defComp = defDscp.clsComps.back();\n\n\tdefComp.clsName = DEFControlParser::unescape(co->id());\n\tdefComp.clsMacroName = co->name();\n\tdefComp.clsIsFixed = co->isFixed();\n\tdefComp.clsIsPlaced = co->isPlaced();\n\tdefComp.clsPos[X] = co->placementX();\n\tdefComp.clsPos[Y] = co->placementY();\n\tdefComp.clsOrientation = co->placementOrientStr();\n\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defComponentStart(defrCallbackType_e c, int num, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsComps.reserve(num);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defNetStart(defrCallbackType_e c, int num, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsNets.reserve(num);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defDesignName(defrCallbackType_e c, const char* string, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsDesignName = string;\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defNetWires(defiNet* net, DefNetDscp& netDscp) {\n\tnetDscp.clsWires.resize(net->numWires());\n\tfor (unsigned i = 0; static_cast<int>(i) < net->numWires(); ++i) {\n\t\tDefWireDscp & wireDscp = netDscp.clsWires[i];\n\t\tdefiWire * wire = net->wire(i);\n\t\twireDscp.clsWireType = wire->wireType();\n\t\twireDscp.clsWireSegments.resize(wire->numPaths());\n\t\tfor (unsigned j = 0; static_cast<int>(j) < wire->numPaths(); ++j) {\n\t\t\tDefWireSegmentDscp & segmentDscp = wireDscp.clsWireSegments[j];\n\t\t\tdefiPath* path = wire->path(j);\n\t\t\tpath->initTraverse();\n\t\t\tint pathId = path->next();\n\t\t\tint x, y, extension;\n\t\t\tDefRoutingPointDscp * point;\n\t\t\twhile (pathId != DEFIPATH_DONE) {\n\t\t\t\tswitch (pathId) {\n\t\t\t\t\tcase DEFIPATH_LAYER:\n\t\t\t\t\t\tsegmentDscp.clsLayerName = path->getLayer();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_VIA:\n\t\t\t\t\t\tpoint->clsViaName = path->getVia();\n\t\t\t\t\t\tpoint->clsHasVia = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_VIAROTATION:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_VIAROTATION at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_WIDTH:\n\t\t\t\t\t\tsegmentDscp.clsRoutedWidth = static_cast<DBU> (path->getWidth());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_POINT:\n\t\t\t\t\t\tpath->getPoint(&x, &y);\n\t\t\t\t\t\tsegmentDscp.clsRoutingPoints.emplace_back();\n\t\t\t\t\t\tpoint = &segmentDscp.clsRoutingPoints.back();\n\t\t\t\t\t\tpoint->clsPos = DBUxy(static_cast<DBU> (x), static_cast<DBU> (y));\n\t\t\t\t\t\tpoint->clsExtension = -1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_FLUSHPOINT:\n\t\t\t\t\t\tpath->getFlushPoint(&x, &y, &extension);\n\t\t\t\t\t\tsegmentDscp.clsRoutingPoints.emplace_back();\n\t\t\t\t\t\tpoint = &segmentDscp.clsRoutingPoints.back();\n\t\t\t\t\t\tpoint->clsPos = DBUxy(static_cast<DBU> (x), static_cast<DBU> (y));\n\t\t\t\t\t\tpoint->clsExtension = extension;\n\t\t\t\t\t\tpoint->clsHasExtension = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_TAPER:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_TAPER at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_SHAPE:\n\t\t\t\t\t\tsegmentDscp.clsHasShape = true;\n\t\t\t\t\t\tsegmentDscp.clsShape = path->getShape();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_MASK:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_MASK at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_VIAMASK:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_VIAMASK at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_RECT:\n\t\t\t\t\t\tint deltaxl, deltayl, deltaxu, deltayu;\n\t\t\t\t\t\tpath->getViaRect(&deltaxl, &deltayl, &deltaxu, &deltayu);\n\t\t\t\t\t\tpoint->clsHasRectangle = true;\n\t\t\t\t\t\tpoint->clsRect[LOWER][X] = static_cast<DBU> (deltaxl);\n\t\t\t\t\t\tpoint->clsRect[LOWER][Y] = static_cast<DBU> (deltayl);\n\t\t\t\t\t\tpoint->clsRect[UPPER][X] = static_cast<DBU> (deltaxu);\n\t\t\t\t\t\tpoint->clsRect[UPPER][Y] = static_cast<DBU> (deltayu);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_VIRTUALPOINT:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_VIRTUALPOINT at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_TAPERRULE:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_TAPERRULE at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DEFIPATH_STYLE:\n\n\t\t\t\t\t{ // TEMPORARY WARNING MESSAGE // mateus @ 180528\n\t\t\t\t\t\tstatic bool warning = false;\n\t\t\t\t\t\tif (!warning) {\n\t\t\t\t\t\t\twarning = true;\n\t\t\t\t\t\t\tstd::cout << \"TODO DEFIPATH_STYLE at \" << __func__ << \"\\n\";\n\t\t\t\t\t\t} // end if\n\t\t\t\t\t} // end block\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t} // end switch\n\t\t\t\tpathId = path->next();\n\t\t\t} // end while \n\t\t} // end for \n\t} // end for \n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defNet(defrCallbackType_e c, defiNet* net, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsNets.emplace_back();\n\tDefNetDscp & netDscp = defDscp.clsNets.back();\n\tnetDscp.clsName = net->name();\n\tnetDscp.clsConnections.resize(net->numConnections());\n\tfor (unsigned i = 0; static_cast<int>(i) < net->numConnections(); ++i) {\n\t\tDefNetConnection &connection = netDscp.clsConnections[i];\n\t\tconnection.clsPinName = net->pin(i);\n\t\tconnection.clsComponentName = DEFControlParser::unescape(net->instance(i));\n\t} // end for\n    defNetWires(net, netDscp);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defSpecialNetStart(defrCallbackType_e c, int num, void* ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsSpecialNets.reserve(num);\n\treturn 0;\n}// end method\n\n// -----------------------------------------------------------------------------\n\nint defSpecialNet(defrCallbackType_e c, defiNet* net, void* ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsSpecialNets.emplace_back();\n\tDefNetDscp & netDscp = defDscp.clsSpecialNets.back();\n\tnetDscp.clsName = net->name();\n\tnetDscp.clsConnections.resize(net->numConnections());\n    if (net->hasUse()) {\n\t\tnetDscp.clsHasUse = true;\n\t\tnetDscp.clsUse = net->use();\n\t}\n\tfor (unsigned i = 0; static_cast<int>(i) < net->numConnections(); ++i) {\n\t\tDefNetConnection &connection = netDscp.clsConnections[i];\n\t\tconnection.clsPinName = net->pin(i);\n\t\tconnection.clsComponentName = DEFControlParser::unescape(net->instance(i));\n\t} // end for\n    defNetWires(net, netDscp);\n\treturn 0;\n}// end method\n\n// -----------------------------------------------------------------------------\n\nint defTrack(defrCallbackType_e typ, defiTrack * track, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsTracks.push_back(DefTrackDscp());\n\tDefTrackDscp & trackDscp = defDscp.clsTracks.back();\n\ttrackDscp.clsDirection = track->macro();\n\ttrackDscp.clsLocation = static_cast<DBU> (std::round(track->x()));\n\ttrackDscp.clsNumTracks = static_cast<DBU> (std::round(track->xNum()));\n\ttrackDscp.clsSpace = static_cast<DBU> (std::round(track->xStep()));\n\ttrackDscp.clsLayers.reserve(track->numLayers());\n\tfor (int i = 0; i < track->numLayers(); i++) {\n\t\ttrackDscp.clsLayers.push_back(track->layer(i));\n\t} // end for \n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nint defViaStart(defrCallbackType_e c, int number, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsVias.reserve(number);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defVia(defrCallbackType_e c, defiVia * via, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsVias.push_back(DefViaDscp());\n\tDefViaDscp & viaDscp = defDscp.clsVias.back();\n\tviaDscp.clsName = via->name();\n\tif (via->hasViaRule()) {\n\t\tviaDscp.clsHasViaRule = true;\n\t\tchar * name;\n\t\tint xSize, ySize, xCutSpacing, yCutSpacing, xBotEnc, yBotEnc, xTopEnc, yTopEnc;\n\t\tchar * bottom;\n\t\tchar * cut;\n\t\tchar * top;\n\t\tvia->viaRule(&name, &xSize, &ySize, &bottom, &cut, &top, &xCutSpacing, &yCutSpacing, &xBotEnc, &yBotEnc, &xTopEnc, &yTopEnc);\n\t\tviaDscp.clsViaRuleName = name;\n\t\tviaDscp.clsXCutSize = xSize;\n\t\tviaDscp.clsYCutSize = ySize;\n\t\tviaDscp.clsBottomLayer = bottom;\n\t\tviaDscp.clsCutLayer = cut;\n\t\tviaDscp.clsTopLayer = top;\n\t\tviaDscp.clsXCutSpacing = xCutSpacing;\n\t\tviaDscp.clsYCutSpacing = yCutSpacing;\n\t\tviaDscp.clsXBottomEnclosure = xBotEnc;\n\t\tviaDscp.clsYBottomEnclosure = yBotEnc;\n\t\tviaDscp.clsXTopEnclosure = xTopEnc;\n\t\tviaDscp.clsYTopEnclosure = yTopEnc;\n\t\tif (via->hasRowCol()) {\n\t\t\tviaDscp.clsHasRowCol = true;\n\t\t\tvia->rowCol(&viaDscp.clsNumCutRows, &viaDscp.clsNumCutCols);\n\t\t} // end if \n\t\tif (via->hasOrigin()) {\n\t\t\tviaDscp.clsHasOrigin = true;\n\t\t\tint xOrigen, yOrigen;\n\t\t\tvia->origin(&xOrigen, &yOrigen);\n\t\t\tviaDscp.clsXOffsetOrigin = xOrigen;\n\t\t\tviaDscp.clsYOffsetOrigin = yOrigen;\n\t\t} // end if \n\t\tif (via->hasOffset()) {\n\t\t\tviaDscp.clsHasOffset = true;\n\t\t\tint xBotOffset, yBotOffset, xTopOffset, yTopOffset;\n\t\t\tvia->offset(&xBotOffset, &yBotOffset, &xTopOffset, &yTopOffset);\n\t\t\tviaDscp.clsXBottomOffset = xBotOffset;\n\t\t\tviaDscp.clsYBottomOffset = yBotOffset;\n\t\t\tviaDscp.clsXTopOffset = xTopOffset;\n\t\t\tviaDscp.clsYTopOffset = yTopOffset;\n\t\t} // end if \n\t\tif (via->hasPattern()) {\n\t\t\tviaDscp.clsHasPattern = true;\n\t\t\tviaDscp.clsPattern = via->pattern();\n\t\t} // end if \n\t} else {\n\t\tviaDscp.clsHasViaRule = false;\n\t\tstd::map<std::string, std::deque < DefViaGeometryDscp>> &mapGeos = viaDscp.clsGeometries;\n\t\tint xl, yl, xh, yh;\n\t\tchar * layerName;\n\t\tfor (int i = 0; i < via->numLayers(); ++i) {\n\t\t\tvia->layer(i, &layerName, &xl, &yl, &xh, &yh);\n\t\t\tstd::string name = layerName;\n\t\t\tstd::deque<DefViaGeometryDscp> & geos = mapGeos[name];\n\t\t\tgeos.push_back(DefViaGeometryDscp());\n\t\t\tDefViaGeometryDscp & geoDscp = geos.back();\n\t\t\tgeoDscp.clsIsRect = true;\n\t\t\tgeoDscp.clsBounds[LOWER][X] = static_cast<DBU> (xl);\n\t\t\tgeoDscp.clsBounds[LOWER][Y] = static_cast<DBU> (yl);\n\t\t\tgeoDscp.clsBounds[UPPER][X] = static_cast<DBU> (xh);\n\t\t\tgeoDscp.clsBounds[UPPER][Y] = static_cast<DBU> (yh);\n\t\t\tif (via->hasRectMask(i)) {\n\t\t\t\tgeoDscp.clsHasMask = true;\n\t\t\t\tgeoDscp.clsMask = via->rectMask(i);\n\t\t\t} // end if \n\t\t} // end for \n\t} // end if-else\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defUnits(defrCallbackType_e c, double d, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsDatabaseUnits = static_cast<int> (d);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defVersion(defrCallbackType_e c, double d, defiUserData ud) {\n\tDefDscp &defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsVersion = d;\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nchar* defOrientStr(int orient) {\n\tswitch (orient) {\n\t\tcase 0: return ((char*) \"N\");\n\t\tcase 1: return ((char*) \"W\");\n\t\tcase 2: return ((char*) \"S\");\n\t\tcase 3: return ((char*) \"E\");\n\t\tcase 4: return ((char*) \"FN\");\n\t\tcase 5: return ((char*) \"FW\");\n\t\tcase 6: return ((char*) \"FS\");\n\t\tcase 7: return ((char*) \"FE\");\n\t};\n\treturn ((char*) \"BOGUS\");\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defOrient(std::string orient) {\n\tif (orient.compare(\"N\") == 0) return 0;\n\tif (orient.compare(\"W\") == 0) return 1;\n\tif (orient.compare(\"S\") == 0) return 2;\n\tif (orient.compare(\"E\") == 0) return 3;\n\tif (orient.compare(\"FN\") == 0) return 4;\n\tif (orient.compare(\"FW\") == 0) return 5;\n\tif (orient.compare(\"FS\") == 0) return 6;\n\tif (orient.compare(\"FE\") == 0) return 7;\n\treturn -1;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defDieArea(defrCallbackType_e typ, defiBox* box, defiUserData ud) {\n\tDefDscp &defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsDieBounds[LOWER][X] = box->defiBox::xl();\n\tdefDscp.clsDieBounds[LOWER][Y] = box->defiBox::yl();\n\tdefDscp.clsDieBounds[UPPER][X] = box->defiBox::xh();\n\tdefDscp.clsDieBounds[UPPER][Y] = box->defiBox::yh();\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defGCellGrid(defrCallbackType_e typ, defiGcellGrid * gcell, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsGcellGrids.emplace_back();\n\tDefGcellGridDscp & gcellGridDscp = defDscp.clsGcellGrids.back();\n\tgcellGridDscp.clsMacro = gcell->macro();\n\tgcellGridDscp.clsX = gcell->x();\n\tgcellGridDscp.clsXNum = gcell->xNum();\n\tgcellGridDscp.clsXStep = gcell->xStep();\n\treturn 0;\n} // end method \n\n\n// -----------------------------------------------------------------------------\n\nint defRegionStart(defrCallbackType_e c, int num, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsRegions.reserve(num);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defRegion(defrCallbackType_e type, defiRegion* region, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsRegions.push_back(DefRegionDscp());\n\tDefRegionDscp & regionDscp = defDscp.clsRegions.back();\n\tregionDscp.clsName = region->name();\n\tregionDscp.clsType = region->type();\n\tregionDscp.clsBounds.resize(region->numRectangles());\n\n\tfor (int i = 0; i < region->numRectangles(); i++) {\n\t\tBounds & bounds = regionDscp.clsBounds[i];\n\t\tbounds[LOWER][X] = region->xl(i);\n\t\tbounds[LOWER][Y] = region->yl(i);\n\t\tbounds[UPPER][X] = region->xh(i);\n\t\tbounds[UPPER][Y] = region->yh(i);\n\t}\n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nint defGroupStart(defrCallbackType_e c, int num, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsGroups.reserve(num);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defGroupName(defrCallbackType_e type, const char* name, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsGroups.push_back(DefGroupDscp());\n\tDefGroupDscp & defGroup = defDscp.clsGroups.back();\n\tdefGroup.clsName = name;\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defGroupMember(defrCallbackType_e type, const char* name, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tDefGroupDscp & defGroup = defDscp.clsGroups.back();\n\tdefGroup.clsPatterns.push_back(name);\n\treturn 0;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defGroups(defrCallbackType_e type, defiGroup *group, defiUserData ud) {\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tDefGroupDscp & defGroup = defDscp.clsGroups.back();\n\tdefGroup.clsRegion = group->regionName();\n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n#define CHECK_STATUS(status) \\\n\tif (status) { \\\n\t\tdefwPrintError(status); \\\n\t} // end if\n\n// -----------------------------------------------------------------------------\n\nvoid DEFControlParser::writeDEF(const std::string &filename, const std::string designName, const std::vector<DefComponentDscp> &components) {\n\tFILE * defFile;\n\tdefFile = fopen(filename.c_str(), \"w\");\n\tif (defFile == NULL) {\n\t\tprintf(\"ERROR: could not open output file: %s \\n\", filename.c_str());\n\t}\n\n\tint status;\n\tint numComponents = components.size();\n\n\tstatus = defwInitCbk(defFile);\n\tCHECK_STATUS(status);\n\tdefwAddComment(\"ICCAD 2015 contest - CADA085 Team solution\");\n\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\tstatus = defwVersion(5, 7);\n\tCHECK_STATUS(status);\n\tstatus = defwDesignName(designName.c_str());\n\tCHECK_STATUS(status);\n\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\tstatus = defwStartComponents(numComponents);\n\tCHECK_STATUS(status);\n\n\tfor (const DefComponentDscp & comp : components) {\n\t\t//int defwComponent(const char* name, const char* master, const char* eeq, const char* source, const char* status, int statusX, int statusY, int statusOrient, double weight, const char* region);\n\t\tstatus = defwComponent(comp.clsName.c_str(), comp.clsMacroName.c_str(),\n\t\t\t0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL,\n\t\t\tcomp.clsIsFixed ? \"FIXED\" : \"PLACED\", (int) comp.clsPos[X],\n\t\t\t(int) comp.clsPos[Y], 0, 0, NULL, 0, 0, 0, 0);\n\t\tCHECK_STATUS(status);\n\t}\n\t//defwEndComponents();\n\tstatus = defwEndComponents();\n\tCHECK_STATUS(status);\n\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\tstatus = defwEnd();\n\tCHECK_STATUS(status);\n\n\tfclose(defFile);\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid DEFControlParser::writeFullDEF(const string &filename, const DefDscp &defDscp) {\n\t//Opening \n\tFILE * defFile;\n\tint status;\n\tdefFile = fopen(filename.c_str(), \"w\");\n\tif (defFile == NULL) {\n\t\tprintf(\"ERROR: could not open output file: %s \\n\", filename.c_str());\n\t}\n\tstatus = defwInitCbk(defFile);\n\tCHECK_STATUS(status);\n\n\n\t//writing header\n\tdefwAddComment(\"DEF file generated by CUHK DR\");\n\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\tstatus = defwVersion(5, 8); // TODO get from design\n\tCHECK_STATUS(status);\n\tstatus = defwDividerChar(\"/\");\n\tCHECK_STATUS(status);\n\tstatus = defwBusBitChars(\"[]\");\n\tCHECK_STATUS(status);\n\tstatus = defwDesignName(defDscp.clsDesignName.c_str());\n\tCHECK_STATUS(status);\n\tif (defDscp.clsHasDatabaseUnits) {\n\t\tstatus = defwUnits(defDscp.clsDatabaseUnits);\n\t\tCHECK_STATUS(status);\n\t} // end if \n\tif (defDscp.clsHasDieBounds) {\n\t\tstatus = defwNewLine();\n\t\tCHECK_STATUS(status);\n\t\tstatus = defwDieArea(\n\t\t\t(int) defDscp.clsDieBounds[LOWER][X],\n\t\t\t(int) defDscp.clsDieBounds[LOWER][Y],\n\t\t\t(int) defDscp.clsDieBounds[UPPER][X],\n\t\t\t(int) defDscp.clsDieBounds[UPPER][Y]);\n\t\tCHECK_STATUS(status);\n\t} // end if \n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\tfor (const DefRowDscp & defRow : defDscp.clsRows) {\n\t\tstatus = defwRow(\n\t\t\tdefRow.clsName.c_str(),\n\t\t\tdefRow.clsSite.c_str(),\n\t\t\tdefRow.clsOrigin[X],\n\t\t\tdefRow.clsOrigin[Y],\n\t\t\tdefOrient(defRow.clsOrientation),\n\t\t\tdefRow.clsNumX,\n\t\t\tdefRow.clsNumY,\n\t\t\tdefRow.clsStepX,\n\t\t\tdefRow.clsStepY);\n\t\tCHECK_STATUS(status);\n\t\tstatus = defwNewLine();\n\t\tCHECK_STATUS(status);\n\t} // end for \n\n\t// Write tracks\n\tconst char** layers;\n\tfor (const DefTrackDscp & track : defDscp.clsTracks) {\n\t\tint numLayers = track.clsLayers.size();\n\t\tlayers = (const char**) malloc(sizeof (char*)*numLayers);\n\t\tfor (int i = 0; i < numLayers; i++) {\n\t\t\tlayers[i] = track.clsLayers[i].c_str();\n\t\t} // end for \n\t\tstatus = defwTracks(track.clsDirection.c_str(), track.clsLocation, track.clsNumTracks, track.clsSpace, numLayers, layers);\n\t\tCHECK_STATUS(status);\n\t\tfree((char*) layers);\n\t} // end for \n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\t// Write vias\n\tconst unsigned numVias = defDscp.clsVias.size();\n\tif (numVias > 0) {\n\t\tstatus = defwStartVias(numVias);\n\t\tCHECK_STATUS(status);\n\n\t\tfor (const DefViaDscp & via : defDscp.clsVias) {\n\t\t\tstatus = defwViaName(via.clsName.c_str());\n\t\t\tCHECK_STATUS(status);\n\t\t\tif (via.clsBottomLayer.size()) {\n                std::map<std::string, std::deque<DefViaGeometryDscp>>::const_iterator it = via.clsGeometries.find(via.clsBottomLayer);\n\t\t\t\tif (it != via.clsGeometries.end()) {\n\t\t\t\t\tfor (const DefViaGeometryDscp & geo : it->second) {\n\t\t\t\t\t\tconst Bounds& bounds = geo.clsBounds;\n\t\t\t\t\t\tstatus = defwViaRect(via.clsBottomLayer.c_str(), bounds[LOWER][X], bounds[LOWER][Y], bounds[UPPER][X], bounds[UPPER][Y]);\n\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (via.clsTopLayer.size()) {\n                std::map<std::string, std::deque<DefViaGeometryDscp>>::const_iterator it = via.clsGeometries.find(via.clsTopLayer);\n\t\t\t\tif (it != via.clsGeometries.end()) {\n\t\t\t\t\tfor (const DefViaGeometryDscp & geo : it->second) {\n\t\t\t\t\t\tconst Bounds& bounds = geo.clsBounds;\n\t\t\t\t\t\tstatus = defwViaRect(via.clsTopLayer.c_str(), bounds[LOWER][X], bounds[LOWER][Y], bounds[UPPER][X], bounds[UPPER][Y]);\n\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (via.clsCutLayer.size()) {\n                std::map<std::string, std::deque<DefViaGeometryDscp>>::const_iterator it = via.clsGeometries.find(via.clsCutLayer);\n\t\t\t\tif (it != via.clsGeometries.end()) {\n\t\t\t\t\tfor (const DefViaGeometryDscp & geo : it->second) {\n\t\t\t\t\t\tconst Bounds& bounds = geo.clsBounds;\n\t\t\t\t\t\tstatus = defwViaRect(via.clsCutLayer.c_str(), bounds[LOWER][X], bounds[LOWER][Y], bounds[UPPER][X], bounds[UPPER][Y]);\n\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (via.clsHasViaRule) {\n\t\t\t\tstatus = defwNewLine();\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t\tstatus = defwViaViarule(via.clsViaRuleName.c_str(), via.clsXCutSize, via.clsYCutSize, via.clsBottomLayer.c_str(), via.clsCutLayer.c_str(), via.clsTopLayer.c_str(), via.clsXCutSpacing, via.clsYCutSpacing, via.clsXBottomEnclosure, via.clsYBottomEnclosure, via.clsXTopEnclosure, via.clsYTopEnclosure);\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t}\n\t\t\tif (via.clsHasRowCol) {\n\t\t\t\tstatus = defwViaViaruleRowCol(via.clsNumCutRows, via.clsNumCutCols);\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t}\n\t\t\tif (via.clsHasOrigin) {\n\t\t\t\tstatus = defwViaViaruleOrigin(via.clsXOffsetOrigin, via.clsYOffsetOrigin);\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t}\n\t\t\tif (via.clsHasOffset) {\n\t\t\t\tstatus = defwViaViaruleOffset(via.clsXBottomOffset, via.clsYBottomOffset, via.clsXTopOffset, via.clsYTopOffset);\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t}\n\t\t\tif (via.clsHasPattern) {\n\t\t\t\tstatus = defwViaViarulePattern(via.clsPattern.c_str());\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t}\n\t\t\tstatus = defwNewLine();\n\t\t\tCHECK_STATUS(status);\n\t\t\tstatus = defwOneViaEnd();\n\t\t\tCHECK_STATUS(status);\n\t\t} // end for \n\n\t\tstatus = defwEndVias();\n\t\tCHECK_STATUS(status);\n\t} // end if \n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\t// Write components\n\tconst unsigned numComponents = defDscp.clsComps.size();\n\tif (numComponents > 0) {\n\t\tstatus = defwStartComponents(numComponents);\n\t\tCHECK_STATUS(status);\n\n\t\tfor (const DefComponentDscp & comp : defDscp.clsComps) {\n\t\t\tint orient = defOrient(comp.clsOrientation);\n\t\t\tstatus = defwComponent(comp.clsName.c_str(), comp.clsMacroName.c_str(), 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL,\n\t\t\t\tcomp.clsIsFixed ? \"FIXED\" : comp.clsIsPlaced ? \"PLACED\" : \"UNPLACED\",\n\t\t\t\t(int) comp.clsPos[X], (int) comp.clsPos[Y], orient, 0, NULL, 0, 0, 0, 0);\n\t\t\tCHECK_STATUS(status);\n\t\t} // end for \n\n\t\tstatus = defwEndComponents();\n\t\tCHECK_STATUS(status);\n\t} // end if \n\n\t// write ports\n\tstatus = defwStartPins(defDscp.clsPorts.size());\n\tCHECK_STATUS(status);\n\n\tfor (const DefPortDscp & port : defDscp.clsPorts) {\n\t\tstatus = defwPin(port.clsName.c_str(),\n\t\t\tport.clsNetName.c_str(),\n\t\t\t(port.clsSpecial ? 1 : 0), // 0 ignores, 1 set net as special\n\t\t\t(port.clsDirection.compare(INVALID_DEF_NAME) == 0 ? NULL : port.clsDirection.c_str()),\n\t\t\t(port.clsUse.compare(INVALID_DEF_NAME) == 0 ? NULL : port.clsUse.c_str()),\n\t\t\t(port.clsLocationType.compare(INVALID_DEF_NAME) == 0 ? NULL : port.clsLocationType.c_str()),\n\t\t\t(int) port.clsPos[X],\n\t\t\t(int) port.clsPos[Y],\n\t\t\tdefOrient(port.clsOrientation),\n\t\t\t(port.clsLayerName.compare(INVALID_DEF_NAME) == 0 ? NULL : port.clsLayerName.c_str()),\n\t\t\t(int) port.clsLayerBounds[LOWER][X],\n\t\t\t(int) port.clsLayerBounds[LOWER][Y],\n\t\t\t(int) port.clsLayerBounds[UPPER][X],\n\t\t\t(int) port.clsLayerBounds[UPPER][Y]);\n\t\tCHECK_STATUS(status);\n\t} // end for \n\n\tstatus = defwEndPins();\n\tCHECK_STATUS(status);\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\tstatus = defwNewLine();\n\tCHECK_STATUS(status);\n\n\tconst unsigned numSpecialNets = defDscp.clsSpecialNets.size();\n\tif (numSpecialNets > 0) {\n\t\tstatus = defwStartSpecialNets(numSpecialNets);\n\t\tCHECK_STATUS(status);\n\n\n\t\t// write special nets\n\t\tfor (const DefNetDscp & defNet : defDscp.clsSpecialNets) {\n\t\t\tstatus = defwSpecialNet(defNet.clsName.c_str());\n\t\t\tCHECK_STATUS(status);\n\t\t\t// Writing special net connections\n\t\t\tfor (const DefNetConnection & defConn : defNet.clsConnections) {\n\t\t\t\tstatus = defwSpecialNetConnection(defConn.clsComponentName.c_str(), defConn.clsPinName.c_str(), 0);\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t} // end for \n\t\t\tif (!defNet.clsWires.empty()) {\n\t\t\t\tbool routed = true;\n\t\t\t\tstatus = defwSpecialNetPathStart(\"ROUTED\");\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t\tfor (const DefWireDscp & wire : defNet.clsWires) {\n\t\t\t\t\tfor (const DefWireSegmentDscp & segment : wire.clsWireSegments) {\n\t\t\t\t\t\tif (!routed) {\n\t\t\t\t\t\t\tstatus = defwSpecialNetPathStart(\"NEW\");\n\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t}\n\t\t\t\t\t\trouted = false;\n\n\t\t\t\t\t\tbool hasVia = false;\n\t\t\t\t\t\tstd::string viaName = \"\";\n\t\t\t\t\t\tbool hasRect = false;\n\t\t\t\t\t\tBounds rect;\n\n\t\t\t\t\t\tstatus = defwSpecialNetPathLayer(segment.clsLayerName.c_str());\n\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\tstatus = defwSpecialNetPathWidth(segment.clsRoutedWidth);\n\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\tif (segment.clsHasShape) {\n\t\t\t\t\t\t\tstatus = defwSpecialNetPathShape(segment.clsShape.c_str());\n\t\t\t\t\t\t\tCHECK_STATUS(status);\n                        }\n\t\t\t\t\t\tfor (const DefRoutingPointDscp & pt : segment.clsRoutingPoints) {\n\t\t\t\t\t\t\tdouble posX = pt.clsPos[X];\n\t\t\t\t\t\t\tdouble posY = pt.clsPos[Y];\n\t\t\t\t\t\t\tif (pt.clsHasExtension) {\n\t\t\t\t\t\t\t\tdouble ext = pt.clsExtension;\n\t\t\t\t\t\t\t\tstatus = defwSpecialNetPathPointWithWireExt(1, &posX, &posY, &ext);\n\t\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstatus = defwSpecialNetPathPoint(1, &posX, &posY);\n\t\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t\t} // end if-else\n\t\t\t\t\t\t\tif (pt.clsHasVia) {\n\t\t\t\t\t\t\t\thasVia = true;\n\t\t\t\t\t\t\t\tviaName = pt.clsViaName;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} // end for \n\n\t\t\t\t\t\tif (hasVia) {\n\t\t\t\t\t\t\tstatus = defwSpecialNetPathVia(viaName.c_str());\n\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t}\n\t\t\t\t\t} // end for \n\n\t\t\t\t} // end for \n\t\t\t\tstatus = defwSpecialNetPathEnd();\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t} // end if\n\t\t\tif (defNet.clsHasUse) {\n\t\t\t\tstatus = defwSpecialNetUse(defNet.clsUse.c_str());\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t} // end if\n\t\t\tstatus = defwNewLine();\n\t\t\tCHECK_STATUS(status);\n\t\t\tstatus = defwSpecialNetEndOneNet();\n\t\t\tCHECK_STATUS(status);\n\t\t} // end for \n\n\t\tstatus = defwEndSpecialNets();\n\t\tCHECK_STATUS(status);\n\t} // end if \n\n\tconst unsigned numNets = defDscp.clsNets.size();\n\tif (numNets > 0) {\n\t\tstatus = defwStartNets(numNets);\n\t\tCHECK_STATUS(status);\n\t\n\n\t\t// write nets\n\t\tfor (const DefNetDscp & defNet : defDscp.clsNets) {\n\t\t\tstatus = defwNet(defNet.clsName.c_str());\n\t\t\tCHECK_STATUS(status);\n\t\t\t// Writing net connections\n\t\t\tfor (const DefNetConnection & defConn : defNet.clsConnections) {\n\t\t\t\tstatus = defwNetConnection(defConn.clsComponentName.c_str(), defConn.clsPinName.c_str(), 0);\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t} // end for \n\t\t\tif (!defNet.clsWires.empty()) {\n\t\t\t\tbool routed = true;\n\t\t\t\tstatus = defwNetPathStart(\"ROUTED\");\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t\tfor (const DefWireDscp & wire : defNet.clsWires) {\n\t\t\t\t\tfor (const DefWireSegmentDscp & segment : wire.clsWireSegments) {\n\t\t\t\t\t\tif (!routed) {\n\t\t\t\t\t\t\tstatus = defwNetPathStart(\"NEW\");\n\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t}\n\t\t\t\t\t\trouted = false;\n\n\t\t\t\t\t\tbool hasVia = false;\n\t\t\t\t\t\tstd::string viaName = \"\";\n\t\t\t\t\t\tbool hasRect = false;\n\t\t\t\t\t\tBounds rect;\n\n\t\t\t\t\t\tstatus = defwNetPathLayer(segment.clsLayerName.c_str(), 0, NULL);\n\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\tfor (const DefRoutingPointDscp & pt : segment.clsRoutingPoints) {\n\t\t\t\t\t\t\tdouble posX = pt.clsPos[X];\n\t\t\t\t\t\t\tdouble posY = pt.clsPos[Y];\n\t\t\t\t\t\t\tif (pt.clsHasExtension) {\n\t\t\t\t\t\t\t\tdouble ext = pt.clsExtension;\n\t\t\t\t\t\t\t\tstatus = defwNetPathPointWithExt(1, &posX, &posY, &ext);\n\t\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstatus = defwNetPathPoint(1, &posX, &posY);\n\t\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t\t} // end if-else\n\t\t\t\t\t\t\tif (pt.clsHasVia) {\n\t\t\t\t\t\t\t\thasVia = true;\n\t\t\t\t\t\t\t\tviaName = pt.clsViaName;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (pt.clsHasRectangle) {\n\t\t\t\t\t\t\t\thasRect = true;\n\t\t\t\t\t\t\t\trect = pt.clsRect;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} // end for \n\n\t\t\t\t\t\tif (hasVia) {\n\t\t\t\t\t\t\tstatus = defwNetPathViaWithOrient(viaName.c_str(), -1);\n\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasRect) {\n\t\t\t\t\t\t\tstatus = defwNetPathRect(rect[LOWER][X], rect[LOWER][Y], rect[UPPER][X], rect[UPPER][Y]);\n\t\t\t\t\t\t\tCHECK_STATUS(status);\n\t\t\t\t\t\t}\n\t\t\t\t\t} // end for \n\n\t\t\t\t} // end for\n\t\t\t\tstatus = defwNetPathEnd();\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t} // end if \n\t\t\t\n\t\t\tif (defNet.clsUse != INVALID_DEF_NAME) {\n\t\t\t\tstatus = defwNetUse(defNet.clsUse.c_str());\n\t\t\t\tstatus = defwNetPathEnd();\n\t\t\t\tCHECK_STATUS(status);\n\t\t\t} // end if \n\t\t\tstatus = defwNetEndOneNet();\n\t\t\tCHECK_STATUS(status);\n\t\t} // end for \n\n\t\tstatus = defwEndNets();\n\t\tCHECK_STATUS(status);\n\t} // end if \n\n\tstatus = defwEnd();\n\tCHECK_STATUS(status);\n\tfclose(defFile);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nstd::string DEFControlParser::unescape(const std::string &str) {\n\tstd::string result;\n\n\tbool scapeNext = false;\n\tfor (char ch : str) {\n\t\tif (scapeNext) {\n\t\t\tresult += ch;\n\t\t\tscapeNext = false;\n\t\t} else if (ch == '\\\\') {\n\t\t\tscapeNext = true;\n\t\t} else {\n\t\t\tresult += ch;\n\t\t\tscapeNext = false;\n\t\t} // end else\n\t} // end if\n\n\treturn result;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nint defVia(defrCallbackType_e c, int num, void* ud) {\n\tstd::cout << \"Entered here!\\n\";\n\tDefDscp & defDscp = getDesignFromUserData(ud);\n\tdefDscp.clsVias.reserve(num);\n\treturn 0;\n}// end method\n\n// -----------------------------------------------------------------------------\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/lef_def/DEFControlParser.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef DEFCONTROLPARSER_H\n#define\tDEFCONTROLPARSER_H\n\n#include <string>\n\tusing std::string;\n#include <iostream>\n\tusing std::cout;\n#include <vector>\n\tusing std::vector;\n\n#include \"rsyn/io/legacy/PlacerInternals.h\"\n\n//! DEF files must be parsed after LEF files\n\t\n#include \"rsyn/phy/util/DefDescriptors.h\"\n\nclass DEFControlParser {\npublic:\n\tDEFControlParser();\n\tvoid parseDEF(const std::string &filename, DefDscp &defDscp) ;\n\tvoid writeDEF(const std::string &filename, const std::string designName, const std::vector<DefComponentDscp> &components);\n\tvoid writeFullDEF(const std::string &filename, const DefDscp & defDscp);\n\tvirtual ~DEFControlParser();\n\t\n\tstatic std::string unescape(const std::string &str);\n\t\n}; // end class\n\n#endif\t/* DEFCONTROLPARSER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/lef_def/LEFControlParser.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include \"LEFControlParser.h\"\n\n#ifndef WIN32\n#include <unistd.h>\n#else\n#include <windows.h>\n#endif /* not WIN32 */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <map>\n#include <iostream>\n\n#include \"rsyn/util/DoubleRectangle.h\"\n#include \"rsyn/util/double2.h\"\n//LEF headers\n\n#include \"lef5.8/lefrReader.hpp\"\n#include \"lef5.8/lefwWriter.hpp\"\n#include \"lef5.8/lefiDebug.hpp\"\n#include \"lef5.8/lefiUtil.hpp\"\n\n#define BOOST_POLYGON_NO_DEPS\n#include <boost/polygon/polygon.hpp>\n\n// -----------------------------------------------------------------------------\n\n// =============================================================================\n// LEF/DEF Common Function for parser\n// =============================================================================\n\n//void freeCB(void* name);\n//void* mallocCB(size_t size);\n//void* reallocCB(void* name, int size);\n\nvoid* mallocCB(size_t size) { // DEF Parser version 5.8 \n\treturn malloc(size);\n}\n\nvoid* mallocCB(int size) { // LEF Parser version 5.8 \n\treturn malloc(size);\n}\n\n// -----------------------------------------------------------------------------\n\nvoid* reallocCB(void* name, size_t size) { // DEF Parser version 5.8 \n\treturn realloc(name, size);\n}\n\nvoid* reallocCB(void* name, int size) { // LEF Parser version 5.8 \n\treturn realloc(name, size);\n}\n\n// -----------------------------------------------------------------------------\n\nvoid freeCB(void* name) {\n\tfree(name);\n\treturn;\n}\n\n// -----------------------------------------------------------------------------\n\n\n\n//LEF CALLBACKS\nvoid lefCheckType(lefrCallbackType_e c);\nint lefMacroBeginCB(lefrCallbackType_e c, const char* macroName, lefiUserData ud);\nint lefMacroEndCB(lefrCallbackType_e c, const char* macroName, lefiUserData ud);\nint lefMacroCB(lefrCallbackType_e c, lefiMacro* macro, lefiUserData ud);\nint lefPinCB(lefrCallbackType_e c, lefiPin* pin, lefiUserData ud);\nint lefSiteCB(lefrCallbackType_e c, lefiSite* site, lefiUserData ud);\nint lefUnits(lefrCallbackType_e c, lefiUnits* units, lefiUserData ud);\nint lefObstructionCB(lefrCallbackType_e c, lefiObstruction* obs, lefiUserData ud);\nint lefLayerCB(lefrCallbackType_e c, lefiLayer* layer, lefiUserData ud);\nint lefSpacingCB(lefrCallbackType_e c, lefiSpacing* spacing, lefiUserData ud);\nint lefViaCb(lefrCallbackType_e typ, lefiVia* via, lefiUserData data);\nint lefViaRuleCb(lefrCallbackType_e typ, lefiViaRule* via, lefiUserData data);\n\nLefDscp &getLibraryFromUserData(lefiUserData userData) {\n\treturn *((LefDscp *) userData);\n} // end function\n\n// =============================================================================\n// LEF Function Implementation\n// =============================================================================\n\nvoid LEFControlParser::parseLEF(const std::string &filename, LefDscp & dscp) {\n\t//\tint retStr = 0;  unused variable\n\n\tFILE* lefFile;\n\tint res;\n\n\tlefrInit();\n\n\tlefrReset();\n\n\t(void) lefrSetOpenLogFileAppend();\n\n\t//(void) lefrSetShiftCase(); // will shift name to uppercase if caseinsensitive\n\t// is set to off or not set\n\n\tlefrSetMacroBeginCbk(lefMacroBeginCB);\n\tlefrSetMacroEndCbk(lefMacroEndCB);\n\tlefrSetMacroCbk(lefMacroCB);\n\tlefrSetPinCbk(lefPinCB);\n\tlefrSetSiteCbk(lefSiteCB);\n\tlefrSetUnitsCbk(lefUnits);\n\tlefrSetUserData((void*) 3);\n\tlefrSetMallocFunction(mallocCB);\n\tlefrSetReallocFunction(reallocCB);\n\tlefrSetFreeFunction(freeCB);\n\tlefrSetObstructionCbk(lefObstructionCB);\n\tlefrSetLayerCbk(lefLayerCB);\n\tlefrSetSpacingCbk(lefSpacingCB);\n\tlefrSetViaCbk(lefViaCb);\n\tlefrSetViaRuleCbk(lefViaRuleCb);\n\tlefrSetRegisterUnusedCallbacks();\n\n\t// Open the lef file for the reader to read\n\tif ((lefFile = fopen(filename.c_str(), \"r\")) == 0) {\n\t\tprintf(\"Couldn’t open input file ’%s’\\n\", filename.c_str());\n\t\texit(1);\n\t}\n\n\t// Invoke the parser\n\tres = lefrRead(lefFile, filename.c_str(), (void*) &dscp);\n\tif (res != 0) {\n\t\tprintf(\"LEF parser returns an error. #: %d \\n\", res);\n\n\t\treturn;\n\t}\n\t//(void) lefrPrintUnusedCallbacks(fout);\n\t(void) lefrReleaseNResetMemory();\n\tfclose(lefFile);\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid lefCheckType(lefrCallbackType_e c) {\n\tif (c >= 0 && c <= lefrLibraryEndCbkType) {\n\t\t// OK\n\t} else {\n\n\t\tprintf(\"ERROR: callback type is out of bounds!\\n\");\n\t}\n} // end call back \n\n// -----------------------------------------------------------------------------\n\nint lefMacroBeginCB(lefrCallbackType_e c, const char* macroName, lefiUserData ud) {\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tdscp.clsLefMacroDscps.resize(dscp.clsLefMacroDscps.size() + 1);\n\treturn 0;\n} // end function\n\n// -----------------------------------------------------------------------------\n\nint lefMacroEndCB(lefrCallbackType_e c, const char* macroName, lefiUserData ud) {\n\treturn 0;\n} // end function\n\n// -----------------------------------------------------------------------------\n\nint lefMacroCB(lefrCallbackType_e c, lefiMacro* macro, lefiUserData ud) {\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\n\tLefMacroDscp & lefMacro = dscp.clsLefMacroDscps.back();\n\n\tlefMacro.clsMacro->setClass(macro->macroClass());\n\tlefMacro.clsMacro->setName(macro->name());\n\tif (macro->hasOrigin()) {\n\t\tlefMacro.clsMacro->setOrigin(macro->originX(), macro->originY());\n\t}\n\tlefMacro.clsMacro->setSize(macro->sizeX(), macro->sizeY());\n\tif (macro->hasXSymmetry()) {\n\t\tlefMacro.clsMacro->setXSymmetry();\n\t} // end if \n\tif (macro->hasYSymmetry()) {\n\t\tlefMacro.clsMacro->setYSymmetry();\n\t} // end if \n\tif (macro->has90Symmetry()) {\n\t\tlefMacro.clsMacro->set90Symmetry();\n\t} // end if \n\treturn 0;\n} // end function\n\n// -----------------------------------------------------------------------------\nint numWarningsInoutPins = 0;\nint numWarningsTristatePins = 0;\n\nint lefPinCB(lefrCallbackType_e c, lefiPin* pin, lefiUserData ud) {\n\ttypedef boost::polygon::polygon_90_with_holes_data<double> Polygon90;\n\ttypedef boost::polygon::polygon_traits<Polygon90>::point_type BoostPoint;\n\t// Skip power and ground pins...\n\t//if (strcmp(pin->use(), \"GROUND\") == 0) return 0;\n\t//if (strcmp(pin->use(), \"POWER\") == 0) return 0;\n\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tLefMacroDscp & lefMacro = dscp.clsLefMacroDscps.back();\n\tlefMacro.clsPins.resize(lefMacro.clsPins.size() + 1);\n\tLefPinDscp & lefPin = lefMacro.clsPins.back();\n\t\n\tlefPin.clsPinName = pin->name();\n\tlefPin.clsPinDirection = pin->direction();\n\tlefPin.clsPinUse = pin->use();\n\n\t// WORKORUND to support inout data pin\n\tif (lefPin.clsPinDirection.compare(\"INOUT\") == 0) {\n\t\tlefPin.clsPinDirection = \"OUTPUT\";\n\t\t//  if (numWarningsInoutPins < 10)\n\t\t//  \tstd::cout << \"WARNING: Unsupported INOUT direction in data pin. \"\n\t\t//  \t<< lefPin.clsPinName << \". Pin direction is replaced to \" << lefPin.clsPinDirection\n\t\t//  \t<< \" [LEF CONTROL PARSER]\\n\";\n\t\tnumWarningsInoutPins++;\n\t} // end if\n\t// END WORKORUND to support inout data pin\n\n\t// Mateus @ 190108 -- WORKORUND to support tristate pin\n\tif (lefPin.clsPinDirection.compare(\"OUTPUT TRISTATE\") == 0) {\n\t\tlefPin.clsPinDirection = \"OUTPUT\";\n\t\tif (numWarningsTristatePins < 10)\n\t\t\tstd::cout << \"WARNING: Ignoring TRISTATE OUTPUT statement in pin \"\n\t\t\t<< lefPin.clsPinName << \". Pin direction is replaced to \" << lefPin.clsPinDirection\n\t\t\t<< \" [LEF CONTROL PARSER]\\n\";\n\t\tnumWarningsTristatePins++;\n\t} // end if\n\t// END WORKORUND to support tristate data pin\n\n\tlefPin.clsHasPort = pin->numPorts() > 0;\n\n\tif (lefPin.clsHasPort)\n\t\tlefPin.clsPorts.reserve(pin->numPorts());\n\n\tfor (int j = 0; j < pin->numPorts(); j++) {\n\t\tconst lefiGeometries* geometry = pin->port(j);\n\t\tlefPin.clsPorts.push_back(LefPortDscp());\n\n\t\tLefPortDscp & lefPort = lefPin.clsPorts.back();\n\t\tint numGeo = geometry->numItems();\n\t\tlefPort.clsLefPortGeoDscp.reserve(numGeo);\n\t\tLefPortGeometryDscp * geoDscp = nullptr;\n\t\tfor (int i = 0; i < numGeo; i++) {\n\n\t\t\tlefiGeomEnum geoType = geometry->itemType(i);\n\t\t\tlefiGeomRect* rect;\n\t\t\tDoubleRectangle * bound;\n\t\t\tlefiGeomPolygon * poly;\n\t\t\tLefPolygonDscp * polyDscp;\n\t\t\tdouble2 * point;\n\n\t\t\tstd::vector< boost::polygon::rectangle_data<double> > rects;\n\t\t\tPolygon90 polygon90;\n\t\t\tstd::vector<BoostPoint> pts;\n\t\t\tswitch (geoType) {\n\t\t\t\tcase lefiGeomLayerE:\n\t\t\t\t\tlefPort.clsLefPortGeoDscp.push_back(LefPortGeometryDscp());\n\t\t\t\t\tgeoDscp = &lefPort.clsLefPortGeoDscp.back();\n\t\t\t\t\tgeoDscp->clsMetalName = geometry->lefiGeometries::getLayer(i);\n\t\t\t\t\tbreak;\n\t\t\t\tcase lefiGeomRectE:\n\t\t\t\t\trect = geometry->getRect(i);\n\t\t\t\t\tgeoDscp->clsBounds.resize(geoDscp->clsBounds.size() + 1);\n\t\t\t\t\tbound = &geoDscp->clsBounds.back();\n\t\t\t\t\tbound->updatePoints(rect->xl, rect->yl, rect->xh, rect->yh);\n\t\t\t\t\tbreak;\n\t\t\t\tcase lefiGeomPolygonE:\n\t\t\t\t\t// Mateus @ 2018/09/13:\n\t\t\t\t\t// Support for polygon-shapped pins\n\t\t\t\t\tpoly = geometry->getPolygon(i);\n\n\t\t\t\t\tfor (int k = 0; k < poly->numPoints; k++) {\n\t\t\t\t\t\tpts.push_back(boost::polygon::construct<BoostPoint>(poly->x[k], poly->y[k]));\n\t\t\t\t\t} // end for \n\n\t\t\t\t\tboost::polygon::set_points(polygon90, pts.begin(), pts.end());\n\t\t\t\t\tboost::polygon::get_rectangles(rects, polygon90);\n\t\t\t\t\tfor (int k = 0; k < rects.size(); k++) {\n\t\t\t\t\t\tdouble xl = rects[k].get(boost::polygon::HORIZONTAL).low();\n\t\t\t\t\t\tdouble xh = rects[k].get(boost::polygon::HORIZONTAL).high();\n\t\t\t\t\t\tdouble yl = rects[k].get(boost::polygon::VERTICAL).low();\n\t\t\t\t\t\tdouble yh = rects[k].get(boost::polygon::VERTICAL).high();\n\t\t\t\t\t\t;\n\t\t\t\t\t\tgeoDscp->clsBounds.resize(geoDscp->clsBounds.size() + 1);\n\t\t\t\t\t\tbound = &geoDscp->clsBounds.back();\n\t\t\t\t\t\tbound->updatePoints(xl, yl, xh, yh);\n\t\t\t\t\t} // end for\n\t\t\t\t\t// end Mateus @ 2018/09/13\t\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstd::cout << \"WARNING: function \" << __func__ << \" does not supports pin geometry type in the LEF Parser Control.\\n\";\n\t\t\t\t\tbreak;\n\t\t\t} // end switch \n\t\t} // end for\n\t} // end for \n\treturn 0;\n} // end function\n\n// -----------------------------------------------------------------------------\n\nint lefSiteCB(lefrCallbackType_e c, lefiSite* site, lefiUserData ud) {\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tdscp.clsLefSiteDscps.resize(dscp.clsLefSiteDscps.size() + 1);\n\tLefSiteDscp &lefSite = dscp.clsLefSiteDscps.back();\n\tlefSite.clsName = site->name();\n\n\tlefSite.clsHasClass = site->hasClass();\n\tif (site->hasClass()) {\n\t\tlefSite.clsSiteClass = site->siteClass();\n\t} // end if \n\tlefSite.clsSize[X] = site->sizeX();\n\tlefSite.clsSize[Y] = site->sizeY();\n\tlefSite.clsSymmetry.clear();\n\tif (site->hasXSymmetry()) {\n\t\tlefSite.clsSymmetry.append(\"X\");\n\t} // end if \n\tif (site->hasYSymmetry()) {\n\t\tlefSite.clsSymmetry.append(\" Y\");\n\t} // end if \n\tif (site->has90Symmetry()) {\n\t\tlefSite.clsSymmetry.append(\" R90\");\n\t} // end if \n\tif (lefSite.clsSymmetry.empty()) {\n\t\tlefSite.clsSymmetry = INVALID_LEF_NAME;\n\t} // end if \n\n\treturn 0;\n} // end function\n\n// -----------------------------------------------------------------------------\n\nint lefUnits(lefrCallbackType_e c, lefiUnits* units, lefiUserData ud) {\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tLefUnitsDscp & lefUnits = dscp.clsLefUnitsDscp;\n\n\tif (units->hasDatabase()) {\n\t\tlefUnits.clsDatabase = (int) units->databaseNumber();\n\t\tlefUnits.clsHasDatabase = true;\n\t}\n\n\treturn 0;\n} // end function\n\n// -----------------------------------------------------------------------------\n\nint lefObstructionCB(lefrCallbackType_e c, lefiObstruction* obs, lefiUserData ud) {\n\t//std::cout << \"Reading lef obstacles\\n\";\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tLefMacroDscp & lefMacro = dscp.clsLefMacroDscps.back();\n\n\tlefiGeometries *geometry;\n\tlefiGeomRect *rect;\n\n\tgeometry = obs->lefiObstruction::geometries();\n\tconst int numItems = geometry->lefiGeometries::numItems();\n\tfor (int i = 0; i < numItems; i++) {\n\t\tif (geometry->lefiGeometries::itemType(i) == lefiGeomLayerE) {\n\t\t\tlefMacro.clsObs.resize(lefMacro.clsObs.size() + 1);\n\t\t\tLefObsDscp & lefObs = lefMacro.clsObs.back();\n\t\t\tlefObs.clsMetalLayer = geometry->getLayer(i);\n\t\t} else if (geometry->lefiGeometries::itemType(i) == lefiGeomRectE) {\n\t\t\tLefObsDscp & lefObs = lefMacro.clsObs.back();\n\t\t\trect = geometry->lefiGeometries::getRect(i);\n\t\t\tDoubleRectangle libRect = DoubleRectangle(rect->xl, rect->yl, rect->xh, rect->yh);\n\t\t\tlefObs.clsBounds.push_back(libRect);\n\t\t} // end if-else \n\t} // end for \n\t\n//\tif (lefMacro.clsMacroName == \"bufx2\" || lefMacro.clsMacroName == \"BUFX2\") {\n//\t\tstd::cout << \"#Obstacles\" << lefMacro.clsObs.size() << \"\\n\";\n//\t}\n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nint lefLayerCB(lefrCallbackType_e c, lefiLayer* layer, lefiUserData ud) {\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tlefiLayer* lefLayer = new lefiLayer();\n\tdscp.clsLefLayer.push_back(lefLayer);\n\tlefLayer->setName(layer->name());\n\tif (layer->lefiLayer::hasType()) {\n\t\tlefLayer->setType(layer->type());\n\t}\n\tif (layer->lefiLayer::hasPitch()) {\n\t\tlefLayer->setPitch(layer->pitch());\n\t}\n\tif (layer->lefiLayer::hasXYPitch()) {\n\t\tlefLayer->setPitchXY(layer->pitchX(), layer->pitchY());\n\t}\n\tif (layer->lefiLayer::hasWidth()) {\n\t\tlefLayer->setWidth(layer->width());\n\t}\n\tif (layer->lefiLayer::hasMinwidth()) {\n\t\tlefLayer->setMinwidth(layer->minwidth());\n\t}\n\tif (layer->lefiLayer::hasDirection()) {\n\t\tlefLayer->setDirection(layer->direction());\n\t}\n\tif (layer->lefiLayer::hasSpacingNumber()) {\n\t\tint numSpacing = layer->lefiLayer::numSpacing();\n\t\tfor (int i = 0; i < numSpacing; ++i) {\n\t\t\tlefLayer->setSpacingMin(layer->spacing(i));\n\t\t\tif (layer->hasSpacingEndOfLine(i)) {\n\t\t\t\tlefLayer->setSpacingEol(layer->spacingEolWidth(i), layer->spacingEolWithin(i));\n\t\t\t}\n\t\t\tif (layer->hasSpacingParellelEdge(i)) {\n\t\t\t\tlefLayer->setSpacingParSW(layer->spacingParSpace(i), layer->spacingParWithin(i));\n\t\t\t}\n\t\t} // end for \n\t} // end if \n\tfor (int i = 0; i < layer->lefiLayer::numSpacingTable(); ++i) {\n\t\tlefLayer->addSpacingTable();\n\t\tif (layer->lefiLayer::spacingTable(i)->isParallel()) {\n\t\t\tlefiParallel* parallel = layer->lefiLayer::spacingTable(i)->parallel();\n\t\t\tint numLength = parallel->numLength();\n\t\t\tint numWidth = parallel->numWidth();\n\t\t\tif (numLength > 0) {\n\t\t\t\tfor (int iLength = 0; iLength < numLength; ++iLength) {\n\t\t\t\t    lefLayer->addNumber(parallel->length(iLength));\n\t\t\t\t}\n\t\t\t\tlefLayer->addSpParallelLength();\n\t\t\t}\n\t\t\tif (numWidth > 0) {\n\t\t\t\tfor (int iWidth = 0; iWidth < numWidth; ++iWidth) {\n                    lefLayer->addSpParallelWidth(parallel->width(iWidth));\n                    for (int iLength = 0; iLength < numLength; ++iLength) {\n                        lefLayer->addNumber(parallel->widthSpacing(iWidth, iLength));\n                    }\n                    lefLayer->addSpParallelWidthSpacing();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (layer->lefiLayer::hasArea()) {\n\t\tlefLayer->setArea(layer->area());\n\t}\n\tfor (unsigned i = 0; static_cast<int>(i) < layer->lefiLayer::numProps(); ++i) {\n\t\tif (layer->lefiLayer::propIsNumber(i)) {\n\t\t\tlefLayer->addNumProp(layer->lefiLayer::propName(i), layer->lefiLayer::propNumber(i), layer->lefiLayer::propValue(i), layer->lefiLayer::propType(i));\n\t\t} else if (layer->lefiLayer::propIsString(i)) {\n\t\t\tlefLayer->addProp(layer->lefiLayer::propName(i), layer->lefiLayer::propValue(i), layer->lefiLayer::propType(i));\n\t\t} else {\n\t\t\tprintf(\"ERROR: LEF layer prop %u is neither number nor string!\\n\", i);\n\t\t}\n\t}\n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nint lefSpacingCB(lefrCallbackType_e c, lefiSpacing* spacing, lefiUserData ud) {\n\tLefDscp & dscp = getLibraryFromUserData(ud);\n\tdscp.clsLefSpacingDscps.resize(dscp.clsLefSpacingDscps.size() + 1);\n\tLefSpacingDscp & lefSpacing = dscp.clsLefSpacingDscps.back();\n\tlefSpacing.clsLayer1 = spacing->lefiSpacing::name1();\n\tlefSpacing.clsLayer2 = spacing->lefiSpacing::name2();\n\tlefSpacing.clsDistance = spacing->lefiSpacing::distance();\n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nint lefViaCb(lefrCallbackType_e typ, lefiVia* via, lefiUserData data) {\n\tLefDscp & dscp = getLibraryFromUserData(data);\n\tdscp.clsLefViaDscps.resize(dscp.clsLefViaDscps.size() + 1);\n\tLefViaDscp & viaDscp = dscp.clsLefViaDscps.back();\n\tviaDscp.clsIsDefault = via->hasDefault();\n\tviaDscp.clsName = via->name();\n\tviaDscp.clsHasViaRule = via->hasViaRule();\n\tif (viaDscp.clsHasViaRule) {\n\t\tviaDscp.clsViaRuleName = via->viaRuleName();\n\t\tviaDscp.clsXCutSize = via->xCutSize();\n\t\tviaDscp.clsYCutSize = via->yCutSize();\n\t\tviaDscp.clsXCutSpacing = via->xCutSpacing();\n\t\tviaDscp.clsYCutSpacing = via->yCutSpacing();\n\t\tviaDscp.clsXBottomEnclosure = via->xBotEnc();\n\t\tviaDscp.clsYBottomEnclosure = via->yBotEnc();\n\t\tviaDscp.clsXTopEnclosure = via->xTopEnc();\n\t\tviaDscp.clsYTopEnclosure = via->yTopEnc();\n\t\tviaDscp.clsBottomLayer = via->botMetalLayer();\n\t\tviaDscp.clsCutLayer = via->cutLayer();\n\t\tviaDscp.clsTopLayer = via->topMetalLayer();\n\t\tif (via->hasOrigin()) {\n\t\t\tviaDscp.clsHasOrigin = true;\n\t\t\tviaDscp.clsXOrigin = via->xOffset();\n\t\t\tviaDscp.clsYOrigin = via->yOffset();\n\t\t} // end if \n\t\tif (via->hasOffset()) {\n\t\t\tviaDscp.clsHasOffset = true;\n\t\t\tviaDscp.clsXBottomOffset = via->xBotOffset();\n\t\t\tviaDscp.clsYBottomOffset = via->yBotOffset();\n\t\t\tviaDscp.clsXTopOffset = via->xTopOffset();\n\t\t\tviaDscp.clsYTopOffset = via->yTopOffset();\n\t\t} // end if \n\t\tif (via->hasRowCol()) {\n\t\t\tviaDscp.clsHasRowCol = true;\n\t\t\tviaDscp.clsNumCutRows = via->numCutRows();\n\t\t\tviaDscp.clsNumCutCols = via->numCutCols();\n\t\t} // end if \n\t} else {\n\t\tif(via->hasResistance()) {\n\t\t\tviaDscp.clsHasResistance = true;\n\t\t\tviaDscp.clsCutResistance = via->resistance();\n\t\t} // end if \n\t\tfor (int i = 0; i < via->numLayers(); ++i) {\n\t\t\tstd::string layerName = via->layerName(i);\n\t\t\tstd::deque<LefViaGeometryDscp> & geoDscps = viaDscp.clsGeometries[layerName];\n\t\t\tfor (int j = 0; j < via->numRects(i); ++j) {\n\t\t\t\tgeoDscps.push_back(LefViaGeometryDscp());\n\t\t\t\tLefViaGeometryDscp & geoDscp = geoDscps.back();\n\t\t\t\tDoubleRectangle & bounds = geoDscp.clsBounds;\n\t\t\t\tbounds[LOWER][X] = via->xl(i, j);\n\t\t\t\tbounds[LOWER][Y] = via->yl(i, j);\n\t\t\t\tbounds[UPPER][X] = via->xh(i, j);\n\t\t\t\tbounds[UPPER][Y] = via->yh(i, j);\n\t\t\t} // end for \n\t\t} // end for\n\t} // end if-else\n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nint lefViaRuleCb(lefrCallbackType_e typ, lefiViaRule* via, lefiUserData data) {\n\tLefDscp & dscp = getLibraryFromUserData(data);\n\tdscp.clsLefViaRuleDscps.push_back(LefViaRuleDscp());\n\tLefViaRuleDscp & viaDscp = dscp.clsLefViaRuleDscps.back();\n\tviaDscp.clsName = via->name();\n\tviaDscp.clsIsDefault = via->hasDefault();\n\tviaDscp.clsIsGenerate = via->hasGenerate();\n\tstd::vector<LefViaRuleLayerDscp> & layers = viaDscp.clsLayers;\n\tlayers.resize(via->numLayers());\n\tfor (int i = 0; i < via->numLayers(); i++) {\n\t\tLefViaRuleLayerDscp & layer = layers[i];\n\t\tlefiViaRuleLayer * viaLayer = via->layer(i);\n\t\tlayer.clsName = viaLayer->name();\n\t\tif (viaLayer->hasDirection()) {\n\t\t\tlayer.clsHasDirection = true;\n\t\t\tlayer.clsIsHorizontal = viaLayer->isHorizontal();\n\t\t\tlayer.clsIsVertical = viaLayer->isVertical();\n\t\t} // end if \n\t\tif (viaLayer->hasEnclosure()) {\n\t\t\tlayer.clsHasEnclosure = true;\n\t\t\tlayer.clsEnclosure1 = viaLayer->enclosureOverhang1();\n\t\t\tlayer.clsEnclosure2 = viaLayer->enclosureOverhang2();\n\t\t} // end if\n\t\tif (viaLayer->hasRect()) {\n\t\t\tlayer.clsHasRect = true;\n\t\t\tDoubleRectangle & bounds = layer.clsRect;\n\t\t\tbounds[LOWER][X] = viaLayer->xl();\n\t\t\tbounds[LOWER][Y] = viaLayer->yl();\n\t\t\tbounds[UPPER][X] = viaLayer->xh();\n\t\t\tbounds[UPPER][Y] = viaLayer->yh();\n\t\t} // end if \n\t\tif (viaLayer->hasResistance()) {\n\t\t\tlayer.clsHasResistance = true;\n\t\t\tlayer.clsCutResistance = viaLayer->resistance();\n\t\t} // end if \n\t\tif (viaLayer->hasWidth()) {\n\t\t\tlayer.clsHasWidth = true;\n\t\t\tlayer.clsMinWidth = viaLayer->widthMin();\n\t\t\tlayer.clsMaxWidth = viaLayer->widthMax();\n\t\t} // end if \n\t\tif (viaLayer->hasSpacing()) {\n\t\t\tlayer.clsHasSpacing = true;\n\t\t\tlayer.clsXSpacing = viaLayer->spacingStepX();\n\t\t\tlayer.clsYSpacing = viaLayer->spacingStepY();\n\t\t} // end if \n\t} // end for \n\tstd::vector<std::string> & vias = viaDscp.clsVias;\n\tvias.reserve(via->numVias());\n\tfor (int i = 0; i < via->numVias(); ++i) {\n\t\tvias.push_back(via->viaName(i));\n\t} // end for \n\treturn 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/lef_def/LEFControlParser.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef LEFCONTROLPARSER_H\n#define LEFCONTROLPARSER_H\n\n#include <string>\n\n#include \"rsyn/phy/util/LefDescriptors.h\"\n\n//! LEF file must be parsed first than DEF file\n\nclass LEFControlParser {\npublic:\n\n\tLEFControlParser() {\n\t}\n\n\tvirtual ~LEFControlParser() = default;\n\tvoid parseLEF(const std::string &filename, LefDscp & dscp);\n}; // end class\n\n#endif /* LEFCONTROLPARSER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/parser_helper.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n//////////////////////////////////////////////////////////////////\n//\n//\n//  Helper functions and classes to parse the ISPD 2013 contest\n//  benchmark files.\n//\n//  This code is provided for description purposes only. The contest\n//  organizers cannot guarantee that the provided code is free of\n//  bugs or defects. !!!! USE THIS CODE AT YOUR OWN RISK !!!!!\n//\n//\n//  The contestants are free to use these functions as-is or make\n//  modifications. If the contestants choose to use the provided\n//  code, they are responsible for making sure that it works as\n//  expected.\n//\n//  The code provided here has no real or implied warranties.\n//\n//\n////////////////////////////////////////////////////////////////////\n\n#include <cstdlib>\n#include <limits>\n#include <cassert>\n#include <cctype>\n#include <cstring>\n#include <algorithm>\n#include <stdexcept>\n\n#include \"rsyn/io/parser/parser_helper.h\"\n\nnamespace ISPD13 {\n\nbool is_special_char (char c) {\n    \n    static const char specialChars[] = {'(', ')', ',', ';', '/', '#', '[', ']', '{', '}', '*', '\\\"', '\\\\'} ;\n    \n    for (unsigned i=0; i < sizeof(specialChars); ++i) {\n        if (c == specialChars[i])\n            return true ;\n    }\n    \n    return false ;\n}\n\n// Read the next line and return it as a list of tokens skipping white space and special characters\n// The return value indicates success/failure.\nbool read_line_as_tokens (istream& is, vector<string>& tokens,\n                          bool includeSpecialChars = false) {\n    \n    tokens.clear() ;\n    \n    string line ;\n    std::getline (is, line) ;\n    \n    while (is && tokens.empty()) {\n        \n        string token = \"\" ;\n        \n        for (unsigned i=0; i < line.size(); ++i) {\n            char currChar = line[i] ;\n            bool isSpecialChar = is_special_char(currChar) ;\n            \n            if (std::isspace (currChar) || isSpecialChar) {\n                \n                if (!token.empty()) {\n                    // Add the current token to the list of tokens\n                    tokens.push_back(token) ;\n                    token.clear() ;\n                }\n                \n                if (includeSpecialChars && isSpecialChar) {\n                    tokens.push_back(string(1, currChar)) ;\n                }\n                \n            } else {\n                // Add the char to the current token\n                token.push_back(currChar) ;\n            }\n            \n        }\n        \n        if (!token.empty())\n            tokens.push_back(token) ;\n        \n        \n        if (tokens.empty())\n            // Previous line read was empty. Read the next one.\n            std::getline (is, line) ;\n    }\n    \n    //for (int i=0; i < tokens.size(); ++i)\n    //  cout << tokens[i] << \" \" ;\n    //cout << endl ;\n    \n    return !tokens.empty() ;\n}\n\n\n\nbool VerilogParser::read_module (string& moduleName) {\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    while (valid) {\n        \n        if (tokens.size() == 2 && tokens[0] == \"module\") {\n            moduleName = tokens[1] ;\n            \n            break ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens) ;\n    }\n    \n    // Read and skip the port names in the module definition\n    // until we encounter the tokens {\"Start\", \"PIs\"}\n    while (valid && !(tokens.size() == 2 && tokens[0] == \"Start\" && tokens[1] == \"PIs\")) {\n        \n        valid = read_line_as_tokens (is, tokens) ;\n        assert (valid) ;\n    }\n    \n    return valid ;\n}\n\nbool VerilogParser::read_primary_input (string& primaryInput) {\n    \n    primaryInput = \"\" ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens.size() == 2) ;\n    \n    if (valid && tokens[0] == \"input\") {\n        primaryInput = tokens[1] ;\n        \n    } else {\n        assert (tokens[0] == \"Start\" && tokens[1] == \"POs\") ;\n        return false ;\n    }\n    \n    return valid ;\n}\n\n\n\nbool VerilogParser::read_primary_output (string& primaryOutput) {\n    \n    primaryOutput = \"\" ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens.size() == 2) ;\n    \n    if (valid && tokens[0] == \"output\") {\n        primaryOutput = tokens[1] ;\n        \n    } else {\n        assert (tokens[0] == \"Start\" && tokens[1] == \"wires\") ;\n        return false ;\n    }\n    \n    return valid ;\n}\n\n\nbool VerilogParser::read_wire (string& wire) {\n    \n    wire = \"\" ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens.size() == 2) ;\n    \n    if (valid && tokens[0] == \"wire\") {\n        wire = tokens[1] ;\n        \n    } else {\n        assert (tokens[0] == \"Start\" && tokens[1] == \"cells\") ;\n        return false ;\n    }\n    \n    return valid ;\n}\n\n\nbool VerilogParser::read_cell_inst (string& cellType, string& cellInstName,\n                                    vector<std::pair<string, string> >& pinNetPairs) {\n    \n    cellType = \"\" ;\n    cellInstName = \"\" ;\n    pinNetPairs.clear() ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    \n    if (tokens.size() == 1) {\n        assert (tokens[0] == \"endmodule\") ;\n        return false ;\n    }\n    \n    assert (tokens.size() >= 4) ; // We should have cellType, instName, and at least one pin-net pair\n    \n    cellType = tokens[0] ;\n    cellInstName = tokens[1] ;\n    \n    for (unsigned i=2; i < tokens.size()-1; i += 2) {\n        \n        assert (tokens[i][0] == '.') ; // pin names start with '.'\n        string pinName = tokens[i].substr(1) ; // skip the first character of tokens[i]\n        \n        pinNetPairs.push_back(std::make_pair(pinName, tokens[i+1])) ;\n    }\n    \n    return valid ;\n}\n\nbool VerilogParser::read_module_tau15 (string& moduleName) {\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    while (valid) {\n        \n        if (tokens.size() == 2 && tokens[0] == \"module\") {\n            moduleName = tokens[1] ;\n            \n            break ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens) ;\n    }\n    \n    // Read and skip the port names in the module definition\n    // until we encounter the tokens {\"Start\", \"PIs\"}\n    while (valid && !count(tokens.begin(), tokens.end(), \";\") == 1) {\n        valid = read_line_as_tokens (is, tokens, true) ;\n        assert (valid) ;\n    }\n    \n    return valid ;\n}\n\n\nbool VerilogParser::read_module_ispd15 (string& moduleName) {\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    while (valid) {\n        \n        if (tokens[0] == \"module\") {\n            moduleName = tokens[1] ;\n            \n            break ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens) ;\n    }\n    \n    // Read and skip the port names in the module definition\n    // until we encounter the tokens {\"Start\", \"PIs\"}\n    while (valid && !count(tokens.begin(), tokens.end(), \";\") == 1) {\n        valid = read_line_as_tokens (is, tokens, true) ;\n        assert (valid) ;\n    }\n    \n    return valid ;\n}\n\ntauVerilog VerilogParser::read_line_tau15(string &aux){\n\tbool valid;\n\tdo{\n\t\tvalid = read_line_as_tokens (is, tauTokens) ;\n\t\n\t\tif(tauTokens[0]  == \"input\"){\n\t\t\taux = tauTokens[1] ;\n\t\t\treturn INPUT_TAU15;\n\t\t} else if (tauTokens [0] == \"output\"){\n\t\t\taux = tauTokens[1] ;\n\t\t\treturn OUTPUT_TAU15;\n\t\t} else if (tauTokens [0] == \"Start\") {\n\t\t\tvalid = false;\n\t\t} else if (tauTokens [0] == \"wire\"){\n\t\t\taux = tauTokens[1] ;\n\t\t\treturn WIRE_TAU15;\n\t\t} else if(tauTokens [0] == \"endmodule\"){\n\t\t\treturn ENDMOD_TAU15;\n\t\t}\n\t\telse{\n\t\t\treturn GATE_TAU15;\n\t\t}\n\t}while(!valid);\n\t\n\tthrow std::runtime_error(\"parsing error\");\n}\n\nbool VerilogParser::read_cell_inst_tau15 (string& cellType, string& cellInstName,\n                                    vector<std::pair<string, string> >& pinNetPairs) {\n    \n    cellType = \"\" ;\n    cellInstName = \"\" ;\n    pinNetPairs.clear() ;\n    \n    assert (tauTokens.size() >= 4) ; // We should have cellType, instName, and at least one pin-net pair\n    \n    cellType = tauTokens[0] ;\n    cellInstName = tauTokens[1] ;\n    \n    for (unsigned i=2; i < tauTokens.size()-1; i += 2) {\n        \n        assert (tauTokens[i][0] == '.') ; // pin names start with '.'\n        string pinName = tauTokens[i].substr(1) ; // skip the first character of tokens[i]\n        \n        pinNetPairs.push_back(std::make_pair(pinName, tauTokens[i+1])) ;\n    }\n    \n    return true ;\n}\n\n\n// Read clock definition\n// Return value indicates if the last read was successful or not.\nbool SdcParser::read_clock (string& clockName, string& clockPort, double& period) {\n    \n    clockName = \"\" ;\n    clockPort = \"\" ;\n    period = 0.0 ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    while (valid) {\n        \n        if (tokens.size() == 7 && tokens[0] == \"create_clock\" && tokens[1] == \"-name\") {\n            \n            clockName = tokens[2] ;\n            \n            assert (tokens[3] == \"-period\") ;\n            period = std::atof(tokens[4].c_str()) ;\n            \n            assert (tokens[5] == \"get_ports\") ;\n            clockPort = tokens[6] ;\n            break ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens) ;\n    }\n    \n    // Skip the next comment line to prepare for the next stage\n    bool valid2 = read_line_as_tokens (is, tokens) ;\n    assert (valid2) ;\n    assert (tokens.size() == 2) ;\n    assert (tokens[0] == \"input\" && tokens[1] == \"delays\") ;\n    \n    return valid ;\n}\n\n// Read input delay\n// Return value indicates if the last read was successful or not.\nbool SdcParser::read_input_delay (string& portName, double& delay) {\n    \n    portName = \"\" ;\n    delay = 0.0 ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens.size() >= 2) ;\n    \n    if (valid && tokens[0] == \"set_input_delay\") {\n\t\t// Workaround.. a better parser must be implemented later\n\t\t//assert (tokens.size() == 6) ;\n        \n        delay = std::atof(tokens[1].c_str()) ;\n        \n        assert (tokens[2] == \"get_ports\") ;\n        \n        portName = tokens[3];\n\t\tif( tokens.size() > 6 )\n\t\t\tportName += \"[\" + tokens[4] + \"]\";\n        \n\t\t// Workaround.. a better parser must be implemented later\n        //assert (tokens[4] == \"-clock\") ;\n        \n    } else {\n        \n        assert (tokens.size() == 2) ;\n        assert (tokens[0] == \"input\" && tokens[1] == \"drivers\") ;\n        \n        return false ;\n        \n    }\n    \n    return valid ;\n}\n\n\n// Read output delay\n// Return value indicates if the last read was successful or not.\nbool SdcParser::read_output_delay (string& portName, double& delay) {\n    \n    portName = \"\" ;\n    delay = 0.0 ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens.size() >= 2) ;\n    \n    if (valid && tokens[0] == \"set_output_delay\") {\n\t\t// Workaround.. a better parser must be implemented later\n\t\t//assert (tokens.size() == 6) ;\n        \n        delay = std::atof(tokens[1].c_str()) ;\n        \n        assert (tokens[2] == \"get_ports\") ;\n        \n        portName = tokens[3];\n\t\tif( tokens.size() > 6 )\n\t\t\tportName += \"[\" + tokens[4] + \"]\";\n        \n\t\t// Workaround.. a better parser must be implemented later\n        //assert (tokens[4] == \"-clock\") ;\n        \n    } else {\n        \n        assert (tokens.size() == 2) ;\n        assert (tokens[0] == \"output\" && tokens[1] == \"loads\") ;\n        \n        return false ;\n        \n    }\n    \n    return valid ;\n}\n\n\n// Read driver info for the input port\n// Return value indicates if the last read was successful or not.\nbool SdcParser::read_driver_info (string& inPortName, string& driverSize, string& driverPin,\n                                  double& inputTransitionFall, double& inputTransitionRise) {\n    \n    inPortName = \"\" ;\n    driverSize = \"\" ;\n    driverPin = \"\" ;\n    inputTransitionFall = 0.0 ;\n    inputTransitionRise = 0.0 ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens.size() >= 2) ;\n    \n    if (valid && tokens[0] == \"set_driving_cell\") {\n\t\t// Workaround, a better parser must be implemented in the future\t\n\t\tassert( tokens.size() == 11 || tokens.size() == 12 );         \n\t\tif(tokens.size() == 11) {\n\t\t    assert (tokens[1] == \"-lib_cell\") ;\n\t\t    \n\t\t    driverSize = tokens[2] ;\n\t\t    \n\t\t    assert (tokens[3] == \"-pin\") ;\n\t\t    driverPin = tokens[4] ;\n\t\t    \n\t\t    assert (tokens[5] == \"get_ports\") ;\n\t\t    inPortName = tokens[6] ;\n\t\t    \n\t\t    assert (tokens[7] == \"-input_transition_fall\") ;\n\t\t    inputTransitionFall = std::atof(tokens[8].c_str()) ;\n\t\t    \n\t\t    assert (tokens[9] == \"-input_transition_rise\") ;\n\t\t    inputTransitionRise = std::atof(tokens[10].c_str()) ;\n\t\t}\n\t\telse if(tokens.size() != 11) {\n        \tassert (tokens[1] == \"-lib_cell\") ;\n\t\t    \n\t\t    driverSize = tokens[2] ;\n\t\t    \n\t\t    assert (tokens[3] == \"-pin\") ;\n\t\t    driverPin = tokens[4] ;\n\t\t    \n\t\t    assert (tokens[5] == \"get_ports\") ;\n\t\t    inPortName = tokens[6] + \"[\" + tokens[7] + \"]\";\n\t\t    \n\t\t    assert (tokens[8] == \"-input_transition_fall\") ;\n\t\t    inputTransitionFall = std::atof(tokens[9].c_str()) ;\n\t\t    \n\t\t    assert (tokens[10] == \"-input_transition_rise\") ;\n\t\t    inputTransitionRise = std::atof(tokens[11].c_str()) ;\n\t\t}\n    } else {\n        \n        assert (tokens.size() == 2) ;\n        assert (tokens[0] == \"output\" && tokens[1] == \"delays\") ;\n        \n        return false ;\n    }\n    \n    return valid ;\n}\n\n\n\n// Read output load\n// Return value indicates if the last read was successful or not.\nbool SdcParser::read_output_load (string& outPortName, double& load) {\n    \n    outPortName = \"\" ;\n    load = 0.0 ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    if (valid && tokens[0] == \"set_load\") {\n\t    // Workaround, a better parser must be implemented in the future\t\n\t\t//assert (tokens.size() == 5) ;\n        \n        assert (tokens[1] == \"-pin_load\") ;\n        load = std::atof(tokens[2].c_str()) ;\n        \n        assert (tokens[3] == \"get_ports\") ;\n        outPortName = tokens[4] ;\n        \n\t\tif( tokens.size() > 5 )\n\t\t\toutPortName += \"[\" + tokens[5] + \"]\";\n\t\t\n    } else {\n        \n        assert (!valid) ;\n        return false ;\n    }\n    \n    return valid ;\n}\n\n// The return value indicates whether the *CONN section has been read or not\nbool SpefParser::read_connections (vector<SpefConnection>& connections) {\n    \n    connections.clear() ; // in case the input is not empty\n    bool terminateEarly = false ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n    \n    // Skip the lines that are not \"*CONN\"\n    while (valid && !(tokens.size() == 2 && tokens[0] == \"*\" && tokens[1] == \"CONN\")) {\n        \n        // The following if condition checks for nets without any connections\n        // This is needed for clock nets.\n        if (tokens.size() == 2 && tokens[0] == \"*\" && tokens[1] == \"END\") {\n            terminateEarly = true ;\n            break ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n    }\n    \n    assert (valid) ; // end of file not expected here\n    \n    if (terminateEarly)\n        return false ;\n    \n    while (valid) {\n        valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n        \n        if (tokens.size() == 2 && tokens[0] == \"*\" && tokens[1] == \"CAP\")\n            break ; // the beginning of the next section\n\t\n\tif (tokens.size() == 2 && tokens[0] == \"*\" && tokens[1] == \"END\")\n           return false ; // spef file for iccad 2015 contest\n\t\n\t//for(auto str: tokens)\n\t//\tcout<<str<<endl;\n        //cout<<\"############################# \"<<__func__<<\" \"<<__FILE__<<endl;\n        // Line format: \"*nodeType nodeName direction\"\n        // Note that nodeName can be either a single token or 3 tokens\n        \n        assert (tokens.size() == 4 || tokens.size() == 6) ;\n        assert (tokens[0] == \"*\") ;\n        \n        SpefConnection curr ;\n        int tokenIndex = 1 ;\n        \n        assert (tokens[tokenIndex].size() == 1) ; // should be a single character\n        curr.nodeType = tokens[tokenIndex++][0] ;\n        assert (curr.nodeType == 'P' || curr.nodeType == 'I') ;\n        \n        curr.nodeName.n1 = tokens[tokenIndex++] ;\n        if (tokens[tokenIndex] == \":\") {\n            ++tokenIndex ; // skip the current token\n            curr.nodeName.n2 = tokens[tokenIndex++] ;\n        }\n        \n        assert (tokens[tokenIndex].size() == 1) ; // should be a single character\n        curr.direction = tokens[tokenIndex++][0] ;\n        assert (curr.direction == 'I' || curr.direction == 'O') ;\n        \n        connections.push_back(curr) ;\n    }\n    \n    return true ;\n}\n\nvoid SpefParser::read_capacitances (vector<SpefCapacitance>& capacitances) {\n    \n    capacitances.clear() ; // in case the input is not empty\n    \n    vector<string> tokens ;\n    bool valid = true ;\n    while (valid) {\n        \n        valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n        \n        if (tokens.size() == 2 && tokens[0] == \"*\" && tokens[1] == \"RES\")\n            break ; // the beginning of the next section\n        \n        // Line format: \"index nodeName cap\"\n        // Note that nodeName can be either a single token or 3 tokens\n        \n        assert (tokens.size() == 3 || tokens.size() == 5) ;\n        \n        SpefCapacitance curr ;\n        int tokenIndex = 1 ;\n        \n        curr.nodeName.n1 = tokens[tokenIndex++] ;\n        if (tokens[tokenIndex] == \":\") {\n            ++tokenIndex ; // skip the current token\n            curr.nodeName.n2 = tokens[tokenIndex++] ;\n        }\n        \n        curr.capacitance = std::atof(tokens[tokenIndex++].c_str()) ;\n        assert (curr.capacitance >= 0) ;\n        \n        capacitances.push_back(curr) ;\n    }\n}\n\nvoid SpefParser::read_resistances (vector<SpefResistance>& resistances) {\n    \n    resistances.clear() ; // in case the input is not empty\n    \n    vector<string> tokens ;\n    bool valid = true ;\n    while (valid) {\n        \n        valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n        \n        if (tokens.size() == 2 && tokens[0] == \"*\" && tokens[1] == \"END\")\n            break ; // end for this net\n        \n        // Line format: \"index fromNodeName toNodeName res\"\n        // Note that each nodeName can be either a single token or 3 tokens\n        \n        assert (tokens.size() >= 4 && tokens.size() <= 8) ;\n        \n        SpefResistance curr ;\n        int tokenIndex = 1 ;\n        \n        curr.fromNodeName.n1 = tokens[tokenIndex++] ;\n        if (tokens[tokenIndex] == \":\") {\n            ++tokenIndex ; // skip the current token\n            curr.fromNodeName.n2 = tokens[tokenIndex++] ;\n        }\n        \n        curr.toNodeName.n1 = tokens[tokenIndex++] ;\n        if (tokens[tokenIndex] == \":\") {\n            ++tokenIndex ; // skip the current token\n            curr.toNodeName.n2 = tokens[tokenIndex++] ;\n        }\n        \n        curr.resistance = std::atof(tokens[tokenIndex++].c_str()) ;\n        assert (curr.resistance >= 0) ;\n        \n        resistances.push_back(curr) ;\n    }\n}\n\n// Read the spef data for the next net.\n// Return value indicates if the last read was successful or not.\nbool SpefParser::read_net_data (SpefNet& spefNet) {\n    \n    spefNet.clear() ;\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n    \n    // Read until a valid D_NET line is found\n    while (valid) {\n        if (tokens.size() == 4 && tokens[0] == \"*\" && tokens[1] == \"D_NET\") {\n            spefNet.netName = tokens[2] ;\n            spefNet.netLumpedCap = std::atof(tokens[3].c_str()) ;\n            \n            bool readConns = read_connections (spefNet.connections) ;\n\n            if (readConns) {\n                read_capacitances (spefNet.capacitances) ;\n                read_resistances (spefNet.resistances) ;\n            }\n            \n            return true ;\n        } else {\n\t\t\tif ( tokens[0] == \"*\" && tokens[1] == \"D_NET\" )\n\t\t\t\tcout << \"[BUG] @ SpefParser::read_net_data: possibly wrong-named net starting with '\" << tokens[2] << \"'\\n\";\n\t\t} // end else\n        \n        valid = read_line_as_tokens (is, tokens, true /*include special chars*/) ;\n    }\n    \n    return false ; // a valid net was not read\n}\n\n\n// Read timing info for the next pin or port\n// Return value indicates if the last read was successful or not.\n// If the line read corresponds to a pin, then name1 and name2 will be set to the cell\n// instance name and the pin name, respectively.\n// If the line read corresponds to a port, then name1 will be set to the port name, and\n// name2 will be set to \"\".\nbool TimingParser::read_timing_line (string& name1, string& name2,\n                                     double& riseSlack, double& fallSlack,\n                                     double& riseTransition, double& fallTransition,\n                                     double& riseArrival, double& fallArrival) {\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    if (!valid)\n        return false ;\n    \n    assert (tokens.size() >= 7) ;\n    \n    int tokenIndex = 0 ;\n    name1 = tokens[tokenIndex++] ;\n    name2 = \"\" ;\n    if (tokens.size() == 8) {\n        // line corresponds to a cell pin\n        name2 = tokens[tokenIndex++] ;\n    }\n    \n    riseSlack = std::atof(tokens[tokenIndex++].c_str()) ;\n    fallSlack = std::atof(tokens[tokenIndex++].c_str()) ;\n    riseTransition = std::atof(tokens[tokenIndex++].c_str()) ;\n    fallTransition = std::atof(tokens[tokenIndex++].c_str()) ;\n    riseArrival = std::atof(tokens[tokenIndex++].c_str()) ;\n    fallArrival = std::atof(tokens[tokenIndex++].c_str()) ;\n    \n    return true ;\n    \n}\n\nbool TimingParser::read_timing_tau15 (\tstring & str1, string &str2, \n\t\t\t\t\tdouble &val1, double &val2, double &val3, double &val4){\n\t\n\tstr1 = \"\";\n\tstr2 = \"\";\n\tval1 = 0;\n\tval2 = 0;\n\tval3 = 0;\n\tval4 = 0;\n\t\n\tvector<string> tokens ;\n\tbool valid = read_line_as_tokens (is, tokens) ;\n\tint tokenSize = tokens.size();\n\t\n\tif (!valid)\n\t\treturn false ;\n\t\n\t int tokenIndex = 0 ;\n    str1 = tokens[tokenIndex++] ;\n    str2 = tokens[tokenIndex++] ;\n\n    val1 = std::atof(tokens[tokenIndex++].c_str()) ;\n    if(tokenIndex < tokenSize)\n\t    val2 = std::atof(tokens[tokenIndex++].c_str()) ;\n    if(tokenIndex < tokenSize)\n\t    val3 = std::atof(tokens[tokenIndex++].c_str()) ;\n    if(tokenIndex < tokenSize)\n\t    val4 = std::atof(tokens[tokenIndex++].c_str()) ;\n    \n    return true;\n}\n\nbool OperationsParser::read_ops_tau15 (\tISPD13::CommandTypeEnum &cmdType, ISPD13::QueryTypeEnum &queryType, \n\t\t\t\t\tstring &pin, string &net, string &file, string &gate, string &cell, bool &early, bool &rise, int &paths ){\n\t\n\tpin = net = file = gate = cell = \"\";\n\tearly = rise = true;\n\tpaths = 1;\n\tcmdType = UNKNOWN;\n\tqueryType = NOT_VALID;\n\t\n\tvector<string> tokens ;\n\tbool valid = read_line_as_tokens (is, tokens) ;\n\tint tokenSize = tokens.size();\n\t\n\tif (!valid)\n\t\treturn false ;\n\t\n\tint tokenIndex = 0 ;\n    string str1 = tokens[tokenIndex++];\n\t\t\n\tif ( str1 == \"report_at\" ) {\n\t\tqueryType = REPORT_AT;\n\t\tassert( tokens[tokenIndex++] == \"-pin\" );\n\t\tpin = tokens[tokenIndex++];\n\t\twhile ( tokenIndex < tokenSize ) {\n\t\t\tstring tmp = tokens[tokenIndex++];\n\t\t\tif ( tmp == \"-fall\") {\n\t\t\t\trise = false;\n\t\t\t} else if ( tmp == \"-late\" ) {\n\t\t\t\tearly = false;\n\t\t\t}\n\t\t}\n\t} else if ( str1 == \"report_rat\" ) {\n\t\tqueryType = REPORT_RAT;\n\t\tassert( tokens[tokenIndex++] == \"-pin\" );\n\t\tpin = tokens[tokenIndex++];\n\t\twhile ( tokenIndex < tokenSize ) {\n\t\t\tstring tmp = tokens[tokenIndex++];\n\t\t\tif ( tmp == \"-fall\") {\n\t\t\t\trise = false;\n\t\t\t} else if ( tmp == \"-late\" ) {\n\t\t\t\tearly = false;\n\t\t\t}\n\t\t}\n\t} else if ( str1 == \"report_slack\" ) {\n\t\tqueryType = REPORT_SLACK;\n\t\tassert( tokens[tokenIndex++] == \"-pin\" );\n\t\tpin = tokens[tokenIndex++];\n\t\twhile ( tokenIndex < tokenSize ) {\n\t\t\tstring tmp = tokens[tokenIndex++];\n\t\t\tif ( tmp == \"-fall\") {\n\t\t\t\trise = false;\n\t\t\t} else if ( tmp == \"-late\" ) {\n\t\t\t\tearly = false;\n\t\t\t}\n\t\t}\n\t} else if ( str1 == \"report_worst_paths\" ) {\n\t\tqueryType = REPORT_PATHS;\n\t\twhile ( tokenIndex < tokenSize ) {\n\t\t\tassert ( tokenIndex + 1 < tokenSize );\n\t\t\tstring tmp1 = tokens[tokenIndex++];\n\t\t\tstring tmp2 = tokens[tokenIndex++];\n\t\t\tif ( tmp1 == \"-pin\" ) {\n\t\t\t\t//read pin char after ':' when it's internal pin\n\t\t\t\tif ( tokenIndex == tokenSize-1 || tokenIndex == tokenSize-3 ) {\n\t\t\t\t\tpin = tmp2 + \":\" + tokens[tokenIndex++];\n\t\t\t\t} else\n\t\t\t\t\tpin = tmp2;\n\t\t\t} else if ( tmp1 == \"-numPaths\" ) {\n\t\t\t\tpaths = (int) std::atof(tmp2.c_str());\n\t\t\t}\n\t\t}\n\t} else if ( str1 == \"insert_gate\") {\n\t\t\n\t\tcmdType = INSERT_GATE;\n\t\tgate = tokens[tokenIndex++];\n\t\tcell = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"repower_gate\") {\n\t\t\n\t\tcmdType = REPOWER_GATE;\n\t\tgate = tokens[tokenIndex++];\n\t\tcell = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"remove_gate\") {\n\t\t\n\t\tcmdType = REMOVE_GATE;\n\t\tgate = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"insert_net\") {\n\t\t\n\t\tcmdType = INSERT_NET;\n\t\tnet = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"remove_net\") {\n\t\t\n\t\tcmdType = REMOVE_NET;\n\t\tnet = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"read_spef\") {\n\t\t\n\t\tcmdType = READ_SPEF;\n\t\tfile = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"connect_pin\") {\n\t\t\n\t\tcmdType = CONNECT_PIN;\n\t\tpin = tokens[tokenIndex++];\n\t\tnet = tokens[tokenIndex++];\n\t\t\n\t} else if ( str1 == \"disconnect_pin\") {\n\t\t\n\t\tcmdType = DISCONNECT_PIN;\n\t\tpin = tokens[tokenIndex++];\n\t\t\n\t}\n\t\t\n    \n    return true;\n}\n\n// Read ceff values for the next pin or port\n// Return value indicates if the last read was successful or not.\n// If the line read corresponds to a pin, then name1 and name2 will be set to the cell\n// instance name and the pin name, respectively.\n// If the line read corresponds to a port, then name1 will be set to the port name, and\n// name2 will be set to \"\".\nbool CeffParser::read_ceff_line (string& name1, string& name2, double& riseCeff, double& fallCeff) {\n    \n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    if (!valid)\n        return false ;\n    \n    assert (tokens.size() >= 3) ;\n    \n    int tokenIndex = 0 ;\n    name1 = tokens[tokenIndex++] ;\n    name2 = \"\" ;\n    if (tokens.size() == 4) {\n        // line corresponds to a cell pin\n        name2 = tokens[tokenIndex++] ;\n    }\n    \n    riseCeff = std::atof(tokens[tokenIndex++].c_str()) ;\n    fallCeff = std::atof(tokens[tokenIndex++].c_str()) ;\n    \n    return true ;\n}\n\n\n// No need to parse the 3D LUTs, because they will be ignored\nvoid LibParser::_skip_lut_3D () {\n    \n    std::vector<string> tokens ;\n    \n    bool valid = read_line_as_tokens (is, tokens) ;\n    assert (valid) ;\n    if ( tokens[0] == \"values\" ) return;\n    assert (tokens[0] == \"index_1\") ;\n    assert (tokens.size() >= 2) ;\n    unsigned size1 = tokens.size() - 1 ;\n    \n    valid = read_line_as_tokens (is, tokens) ;\n    assert (valid) ;\n    assert (tokens[0] == \"index_2\") ;\n    assert (tokens.size() >= 2) ;\n    unsigned size2 = tokens.size() - 1 ;\n    \n    valid = read_line_as_tokens (is, tokens) ;\n    assert (valid) ;\n    assert (tokens[0] == \"index_3\") ;\n    assert (tokens.size() >= 2) ;\n    unsigned size3 = tokens.size() - 1 ;\n    \n    valid = read_line_as_tokens (is, tokens) ;\n    assert (valid) ;\n    assert (tokens.size() == 1 && tokens[0] == \"values\") ;\n    \n    for (unsigned i=0; i < size1; ++i) {\n        for (unsigned j=0; j < size2; ++j) {\n            \n            valid = read_line_as_tokens (is, tokens) ;\n            assert (valid) ;\n            assert (tokens.size() == size3) ;\n        }\n    }\n    \n}\n\nvoid LibParser::_begin_read_lut (LibParserLUT& lut) {\n    \n    std::vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens[0] == \"index_1\") ;\n    assert (tokens.size() >= 2) ;\n    \n    unsigned size1 = tokens.size()-1 ;\n    lut.loadIndices.resize(size1) ;\n    for (unsigned i=0; i < tokens.size()-1; ++i) {\n        \n        lut.loadIndices[i] = std::atof(tokens[i+1].c_str()) ;\n    }\n    \n    valid = read_line_as_tokens (is, tokens) ;\n    \n    assert (valid) ;\n    assert (tokens[0] == \"index_2\") ;\n    assert (tokens.size() >= 2) ;\n    \n    int size2 = tokens.size()-1 ;\n    lut.transitionIndices.resize(size2) ;\n    for (unsigned i=0; i < tokens.size()-1; ++i) {\n        \n        lut.transitionIndices[i] = std::atof(tokens[i+1].c_str()) ;\n    }\n    \n    valid = read_line_as_tokens (is, tokens) ;\n    assert (valid) ;\n    assert (tokens.size() == 1 && tokens[0] == \"values\") ;\n    \n    lut.tableVals.initialize(size1, size2) ;\n    for (unsigned i=0 ; i < lut.loadIndices.size(); ++i) {\n        valid = read_line_as_tokens (is, tokens) ;\n        assert (valid) ;\n        assert (tokens.size() == lut.transitionIndices.size()) ;\n        \n        for (unsigned j=0; j < lut.transitionIndices.size(); ++j) {\n            lut.tableVals(i, j) = std::atof(tokens[j].c_str()) ;\n            \n        }\n    }\n    \n    \n}\n\nvoid LibParser::_begin_read_timing_info (string toPin, LibParserPinInfo& pin, LibParserTimingInfo& timing) {\n    \n    timing.toPin = toPin ;\n    \n    bool finishedReading = false ;\n\tbool setup = false;\n    \n    std::vector<string> tokens ;\n    while (!finishedReading) {\n        \n        bool valid = read_line_as_tokens (is, tokens) ;\n        assert (valid) ;\n        assert (tokens.size() >= 1) ;\n        \n        if (tokens[0] == \"cell_fall\") {\n            _begin_read_lut (timing.fallDelay) ;\n            \n        } else if (tokens[0] == \"cell_rise\") {\n            _begin_read_lut (timing.riseDelay) ;\n            \n        } else if (tokens[0] == \"fall_transition\") {\n            _begin_read_lut (timing.fallTransition) ;\n            \n        } else if (tokens[0] == \"rise_transition\") {\n            _begin_read_lut (timing.riseTransition) ;\n            \n        } else if (tokens[0] == \"fall_constraint\") {\n            \n            //_skip_lut_3D() ; // will ignore fall constraints\n            bool valid = read_line_as_tokens (is, tokens) ;\n            //assert (valid) ;\n            //assert ( tokens[0] == \"values\" );\n\t\t\tif ( setup )\n\t\t\t\t_begin_read_lut (pin.fallSetup) ;\n\t\t\t\t//pin.fallSetup = std::atof(tokens[1].c_str());\n\t\t\telse\n\t\t\t\t_begin_read_lut (pin.fallHold) ;\n\t\t\t\t//pin.fallHold = std::atof(tokens[1].c_str());\n\t\t\tpin.isTimingEndpoint = true;\n\t\t\t//cout << \"setup/hold: \" << std::atof(tokens[1].c_str()) << endl;\n        \t\t\n        } else if (tokens[0] == \"rise_constraint\") {\n            \n           // _skip_lut_3D() ; // will ignore rise constraints\n            bool valid = read_line_as_tokens (is, tokens) ;\n            assert (valid) ;\n            assert ( tokens[0] == \"values\" );\n\t\t\tif ( setup )\n\t\t\t\t_begin_read_lut (pin.riseSetup) ;\n\t\t\t\t//pin.riseSetup = std::atof(tokens[1].c_str());\n\t\t\telse\n\t\t\t\t_begin_read_lut (pin.riseHold) ;\n\t\t\t\t//pin.riseHold = std::atof(tokens[1].c_str());\n\t\t\t//cout << pin.name << \" \\tsetup/hold: \" << std::atof(tokens[1].c_str()) << endl;\n            \n        } else if (tokens[0] == \"timing_sense\") {\n            timing.timingSense = tokens[1] ;\n            \n        } else if (tokens[0] == \"related_pin\") {\n            \n            assert (tokens.size() == 2) ;\n            timing.fromPin = tokens[1] ;\n            \n        } else if (tokens[0] == \"End\") {\n            \n            assert (tokens.size() == 2) ;\n            assert (tokens[1] == \"timing\") ;\n            finishedReading = true ;\n            \n        } else if (tokens[0] == \"timing_type\") {\n\t\t\tif ( tokens[1] == \"setup_rising\") \n\t\t\t\tsetup = true;\n\t\t\telse setup = false;\n\t\t\t\n        } else if (tokens[0] == \"related_output_pin\") {\n            // ignore data\n            \n        } else {\n            \n            cout << \"Error: Unknown keyword: \" << tokens[0] << endl ;\n            assert (false) ; // unknown keyword\n        }\n        \n    }\n    \n    \n}\n\n\nvoid LibParser::_begin_read_pin_info (string pinName, LibParserCellInfo& cell, LibParserPinInfo& pin) {\n    \n    pin.name = pinName ;\n    pin.isClock = false ;\n    pin.maxCapacitance = std::numeric_limits<double>::max() ;\n\t//cout << \"\\tpin: \" << pinName << endl;\n    \n    bool finishedReading = false ;\n    \n    std::vector<string> tokens ;\n    while (!finishedReading) {\n        \n        bool valid = read_line_as_tokens (is, tokens) ;\n        assert (valid) ;\n        assert (tokens.size() >= 1) ;\n\t\t//cout << tokens[0] << \"\\t\" << tokens[1] << endl;\n        \n        if (tokens[0] == \"direction\") {\n            \n            assert (tokens.size() == 2) ;\n            if (tokens[1] == \"input\")\n                pin.isInput = true ;\n            else if (tokens[1] == \"output\")\n                pin.isInput = false ;\n            else\n                assert (false) ; // undefined direction\n            \n        } else if (tokens[0] == \"capacitance\") {\n            \n            assert (tokens.size() == 2) ;\n            pin.capacitance = std::atof(tokens[1].c_str()) ;\n            \n        } else if (tokens[0] == \"max_capacitance\") {\n            \n            assert (tokens.size() == 2) ;\n            pin.maxCapacitance = std::atof(tokens[1].c_str()) ;\n            \n            \n        } else if (tokens[0] == \"timing\") {\n            \n            cell.timingArcs.push_back(LibParserTimingInfo()) ; // add an empty TimingInfo object\n            _begin_read_timing_info (pinName, pin, cell.timingArcs.back()) ; // pass the empty object to the function to be filled\n            \n        } else if (tokens[0] == \"clock\") {\n            \n            pin.isClock = true ;\n\t\t\tcell.isSequential = true;\n            \n        } else if (tokens[0] == \"End\") {\n            \n            assert (tokens.size() == 2) ;\n            assert (tokens[1] == \"pin\") ;\n            finishedReading = true ;\n            \n        } else if (tokens[0] == \"function\") {\n            \n            // ignore data\n            \n        } else if (tokens[0] == \"min_capacitance\") {\n            \n            // ignore data\n            \n        } else if (tokens[0] == \"nextstate_type\") {\n            \n            // ignore data\n            \n        } else {\n            cout << \"Error: Unknown keyword: \" << tokens[0] << endl ;\n            assert (false) ; // unknown keyword\n            \n        }\n        \n    }\n    \n    \n}\n\nvoid LibParser::_begin_read_cell_info (string cellName, LibParserCellInfo& cell) {\n    \n    cell.name = cellName ;\n    cell.isSequential = false ;\n    cell.dontTouch = false ;\n    \n    bool finishedReading = false ;\n    //cout << \"Cell: \" << cellName << endl;\n\t\t\n    std::vector<string> tokens ;\n    while (!finishedReading) {\n        \n        bool valid = read_line_as_tokens (is, tokens) ;\n\t\t//cout << \"size: \" << tokens.size() << endl;\n        assert (valid) ;\n        assert (tokens.size() >= 1) ;\n\t\t\n\t\t//cout << tokens[0] << endl;\n        if (tokens[0] == \"cell_leakage_power\") {\n            \n            assert (tokens.size() == 2) ;\n            cell.leakagePower = std::atof(tokens[1].c_str()) ;\n            \n        } else if (tokens[0] == \"cell_footprint\") {\n            \n            assert (tokens.size() == 2) ;\n            cell.footprint = tokens[1] ;\n            \n        } else if (tokens[0] == \"area\") {\n            \n            assert (tokens.size() == 2) ;\n            cell.area = std::atof(tokens[1].c_str()) ;\n            \n        } else if (tokens[0] == \"clocked_on\") {\n            \n            cell.isSequential = true ;\n            \n        } else if (tokens[0] == \"dont_touch\") {\n            \n            cell.dontTouch = true ;\n            \n        } else if (tokens[0] == \"pin\") {\n            \n\t\t\tassert (tokens.size() == 2) ;\n\t\t\t\n            cell.pins.push_back(LibParserPinInfo()) ; // add empty PinInfo object\n            _begin_read_pin_info (tokens[1], cell, cell.pins.back()) ; // pass the new PinInfo object to be filled\n            \n        } else if (tokens[0] == \"End\") {\n            \n            assert (tokens.size() == 3) ;\n            assert (tokens[1] == \"cell\") ;\n            assert (tokens[2] == cellName) ;\n            finishedReading = true ;\n            \n        } else if (tokens[0] == \"cell_footprint\") {\n            \n            // ignore data\n            \n        } else if (tokens[0] == \"ff\") {\n            \n            // ignore data\n            \n        } else if (tokens[0] == \"next_state\") {\n            \n            // ignore data\n            \n        } else if (tokens[0] == \"dont_use\") {\n            \n            // ignore data\n            \n        } else {\n            \n            cout << \"Error: Unknown keyword: \" << tokens[0] << endl ;\n            assert (false) ; // unknown keyword\n        }\n    }\n    \n}\n\n\n// Read the default max_transition defined for the library.\n// Return value indicates if the last read was successful or not.\n// This function must be called in the beginning before any read_cell_info function call.\nbool LibParser::read_default_max_transition (double& maxTransition) {\n    \n    maxTransition = 0.0 ;\n    vector<string> tokens ;\n    \n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    while (valid) {\n        \n        if (tokens.size() == 2 && tokens[0] == \"default_max_transition\") {\n            maxTransition = std::atof(tokens[1].c_str()) ;\n            return true ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens) ;\n    }\n    \n    return false ;\n}\n\n\n\n// Read the next standard cell definition.\n// Return value indicates if the last read was successful or not.\nbool LibParser::read_cell_info (LibParserCellInfo& cell) {\n    \n    vector<string> tokens ;\n    bool valid = read_line_as_tokens (is, tokens) ;\n    \n    \n    while (valid) {\n        \n        if (tokens.size() == 2 && tokens[0] == \"cell\") {\n            _begin_read_cell_info (tokens[1], cell) ;\n            \n            return true ;\n        }\n        \n        valid = read_line_as_tokens (is, tokens) ;\n    }\n    \n    return false ;\n}\n\nostream& operator<< (ostream& os, LibParserLUT& lut) {\n    \n    if (lut.loadIndices.empty() && lut.transitionIndices.empty() && lut.tableVals.isEmpty())\n        return os ;\n    \n    // We should have either all empty or none empty.\n    assert (!lut.loadIndices.empty() && !lut.transitionIndices.empty() && !lut.tableVals.isEmpty()) ;\n    \n    assert (lut.tableVals.getNumElements() == lut.loadIndices.size()) ;\n    assert (lut.tableVals.getNumRows() == lut.transitionIndices.size()) ;\n    \n    cout << \"\\t\" ;\n    for (unsigned i=0; i < lut.transitionIndices.size(); ++i) {\n        cout << lut.transitionIndices[i] << \"\\t\" ;\n    }\n    cout << endl ;\n    \n    \n    for (unsigned i=0; i < lut.loadIndices.size(); ++i) {\n        cout << lut.loadIndices[i] << \"\\t\" ;\n        \n        for (unsigned j=0; j < lut.transitionIndices.size(); ++j)\n            cout << lut.tableVals(i, j) << \"\\t\" ;\n        \n        cout << endl ;\n        \n    }\n    \n    return os ;\n}\n\n\nostream& operator<< (ostream& os, LibParserTimingInfo& timing) {\n    \n    cout << \"Timing info from \" << timing.fromPin << \" to \" << timing.toPin << \": \" << endl ;\n    cout << \"Timing sense: \" << timing.timingSense << endl ;\n    \n    cout << \"Fall delay LUT: \" << endl ;\n    cout << timing.fallDelay ;\n    \n    cout << \"Rise delay LUT: \" << endl ;\n    cout << timing.riseDelay ;\n    \n    cout << \"Fall transition LUT: \" << endl ;\n    cout << timing.fallTransition ;\n    \n    cout << \"Rise transition LUT: \" << endl ;\n    cout << timing.riseTransition ;\n    \n    return os ;\n}\n\n\nostream& operator<< (ostream& os, LibParserPinInfo& pin) {\n    \n    cout << \"Pin \" << pin.name << \":\" << endl ;\n    cout << \"capacitance: \" << pin.capacitance << endl ;\n    cout << \"maxCapacitance: \" << pin.maxCapacitance << endl ;\n    cout << \"isInput? \" << (pin.isInput ? \"true\" : \"false\") << endl ;\n    cout << \"isClock? \" << (pin.isClock ? \"true\" : \"false\") << endl ;\n    cout << \"End pin\" << endl ;\n    \n    return os ;\n}\n\n\nostream& operator<< (ostream& os, LibParserCellInfo& cell) {\n    \n    cout << \"Library cell \" << cell.name << \": \" << endl ;\n    \n    cout << \"Footprint: \" << cell.footprint << endl ;\n    cout << \"Leakage power: \" << cell.leakagePower << endl ;\n    cout << \"Area: \" << cell.area << endl ;\n    cout << \"Sequential? \" << (cell.isSequential ? \"yes\" : \"no\") << endl ;\n    cout << \"Dont-touch? \" << (cell.dontTouch ? \"yes\" : \"no\") << endl ;\n    \n    cout << \"Cell has \" << cell.pins.size() << \" pins: \" << endl ;\n    for (unsigned i=0; i < cell.pins.size(); ++i) {\n        cout << cell.pins[i] << endl ;\n    }\n    \n    cout << \"Cell has \" << cell.timingArcs.size() << \" timing arcs: \" << endl ;\n    for (unsigned i=0; i < cell.timingArcs.size(); ++i) {\n        cout << cell.timingArcs[i] << endl ;\n    }\n    \n    cout << \"End of cell \" << cell.name << endl << endl ;\n    \n    return os ;\n}\n\n\n\n// Example function that uses VerilogParser class to parse the given ISPD-13 verilog\n// file. The extracted data is simply printed out in this example.\nvoid test_verilog_parser (string filename) {\n    \n    VerilogParser vp (filename) ;\n    \n    string moduleName ;\n    bool valid = vp.read_module (moduleName) ;\n    assert (valid) ;\n    \n    cout << \"Module \" << moduleName << endl << endl ;\n    \n    do {\n        string primaryInput ;\n        valid = vp.read_primary_input (primaryInput) ;\n        \n        if (valid)\n            cout << \"Primary input: \" << primaryInput << endl ;\n        \n    } while (valid) ;\n    \n    cout << endl ;\n    \n    do {\n        string primaryOutput ;\n        valid = vp.read_primary_output (primaryOutput) ;\n        \n        if (valid)\n            cout << \"Primary output: \" << primaryOutput << endl ;\n        \n    } while (valid) ;\n    \n    cout << endl ;\n    \n    do {\n        string net ;\n        valid = vp.read_wire (net) ;\n        \n        if (valid)\n            cout << \"Net: \" << net << endl ;\n        \n    } while (valid) ;\n    \n    \n    cout << endl ;\n    cout << \"Cell insts: \" << std::endl ;\n    \n    do {\n        string cellType, cellInst ;\n        vector<std::pair<string, string> > pinNetPairs ;\n        \n        valid = vp.read_cell_inst (cellType, cellInst, pinNetPairs) ;\n        \n        if (valid) {\n            cout << cellType << \" \" << cellInst << \" \" ;\n            for (unsigned i=0; i < pinNetPairs.size(); ++i) {\n                cout << \"(\" << pinNetPairs[i].first << \" \" << pinNetPairs[i].second << \") \" ;\n            }\n            \n            cout << endl ;\n        }\n        \n    } while (valid) ;\n    \n    \n}\n\n// Example function that uses SdcParser class to parse the given ISPD-13 sdc\n// file. The extracted data is simply printed out in this example.\nvoid test_sdc_parser (string filename) {\n    \n    SdcParser sp (filename) ;\n    \n    string clockName ;\n    string clockPort ;\n    double period ;\n    bool valid = sp.read_clock (clockName, clockPort, period) ;\n    \n    assert(valid) ;\n    cout << \"Clock \" << clockName << \" connected to port \" << clockPort\n    << \" has period \" << period << endl ;\n    \n    do {\n        string portName ;\n        double delay ;\n        \n        valid = sp.read_input_delay (portName, delay) ;\n        \n        if (valid)\n            cout << \"Input port \" << portName << \" has delay \" << delay << endl ;\n        \n    } while (valid) ;\n    \n    \n    do {\n        string portName ;\n        string driverSize ;\n        string driverPin ;\n        double inputTransitionFall ;\n        double inputTransitionRise ;\n        \n        valid = sp.read_driver_info (portName, driverSize, driverPin,\n                                     inputTransitionFall, inputTransitionRise) ;\n        \n        if (valid) {\n            cout << \"Input port \" << portName << \" is assumed to be connected to the \"\n            << driverPin << \" pin of lib cell \" << driverSize << endl ;\n            cout << \"This virtual driver is assumed to have input transitions: \"\n            << inputTransitionFall << \" (fall) and \" << inputTransitionRise\n            << \" (rise)\" << endl ;\n        }\n        \n        \n    } while (valid) ;\n    \n    do {\n        string portName ;\n        double delay ;\n        \n        valid = sp.read_output_delay (portName, delay) ;\n        \n        if (valid)\n            cout << \"Output port \" << portName << \" has delay \" << delay << endl ;\n        \n    } while (valid) ;\n    \n    \n    do {\n        string portName ;\n        double load ;\n        \n        valid = sp.read_output_load (portName, load) ;\n        \n        if (valid)\n            cout << \"Output port \" << portName << \" has load \" << load << endl ;\n        \n    } while (valid) ;\n    \n    \n}\n\n// Example function that uses SpefParser class to parse the given ISPD-13 spef\n// file. The extracted data is simply printed out in this example.\nvoid test_spef_parser (string filename) {\n    \n    SpefParser sp (filename) ;\n    \n    SpefNet spefNet ;\n    bool valid = sp.read_net_data (spefNet) ;\n    \n    int readCnt = 0 ;\n    while (valid) {\n        \n        ++readCnt ;\n        \n        // print out the contents of the spefNet just read\n        cout << \"Net: \" << spefNet.netName << endl ;\n        cout << \"Net lumped cap: \" << spefNet.netLumpedCap << endl ;\n        \n        cout << \"Connections: \" << endl ;\n        for (int i=0; i < spefNet.connections.size(); ++i) {\n            cout << spefNet.connections[i] << endl ;\n        }\n        \n        cout << \"Capacitances: \" << endl ;\n        for (int i=0; i < spefNet.capacitances.size(); ++i) {\n            cout << spefNet.capacitances[i] << endl ;\n        }\n        \n        cout << \"Resistances: \" << endl ;\n        for (int i=0; i < spefNet.resistances.size(); ++i) {\n            cout << spefNet.resistances[i] << endl ;\n        }\n        \n        cout << endl ;\n        valid = sp.read_net_data (spefNet) ;\n    }\n    \n    cout << \"Read \" << readCnt << \" nets in the spef file.\" << endl ;\n}\n\n// Example function that uses TimingParser class to parse the given ISPD-13 timing\n// file. The extracted data is simply printed out in this example.\nvoid test_timing_parser (string filename) {\n    \n    TimingParser tp (filename) ;\n    \n    bool valid = false ;\n    while (true) {\n        \n        string name1, name2 ;\n        double riseSlack, fallSlack, riseTransition, fallTransition, riseArrival, fallArrival ;\n        \n        valid = tp.read_timing_line (name1, name2, riseSlack, fallSlack,\n                                     riseTransition, fallTransition, riseArrival, fallArrival) ;\n        \n        if (!valid)\n            break ;\n        \n        if (name2 != \"\") {\n            // timing info of a pin\n            // name1: cellInstance, name2: pin\n            std::cout << name1 << \"/\" << name2 << \" \"\n            << riseSlack << \" \" << fallSlack << \" \"\n            << riseTransition << \" \" << fallTransition << \" \"\n            << riseArrival << \" \" << fallArrival << endl ;\n            \n        } else {\n            // timing of a port\n            // name1: port name\n            std::cout << name1 << \" \"\n            << riseSlack << \" \" << fallSlack << \" \"\n            << riseTransition << \" \" << fallTransition << \" \"\n            << riseArrival << \" \" << fallArrival << endl ;\n        }\n    }\n    \n}\n\n\n// Example function that uses CeffParser class to parse the given ISPD-13 ceff\n// file. The extracted data is simply printed out in this example.\nvoid test_ceff_parser (string filename) {\n    \n    CeffParser tp (filename) ;\n    \n    bool valid = false ;\n    while (true) {\n        \n        string name1, name2 ;\n        double riseCeff, fallCeff ;\n        \n        valid = tp.read_ceff_line (name1, name2, riseCeff, fallCeff) ;\n        \n        if (!valid)\n            break ;\n        \n        if (name2 != \"\") {\n            // ceff values of a pin\n            // name1: cellInstance, name2: pin\n            std::cout << name1 << \"/\" << name2 << \" \"\n            << riseCeff << \" \" << fallCeff << endl ;\n            \n        } else {\n            // timing of a port\n            // name1: port name\n            std::cout << name1 << \" \"\n            << riseCeff << \" \" << fallCeff << endl ;\n        }\n    }\n    \n}\n\n\n\n// Example function that uses LibParser class to parse the given ISPD-13 lib\n// file. The extracted data is simply printed out in this example.\nvoid test_lib_parser (string filename) {\n    \n    LibParser lp (filename) ;\n    \n    double maxTransition = 0.0 ;\n    bool valid = lp.read_default_max_transition(maxTransition) ;\n    \n    assert (valid) ;\n    cout << \"The default max transition defined is \" << maxTransition << endl ;\n    \n    int readCnt = 0 ;\n    do {\n        LibParserCellInfo cell ;\n        valid = lp.read_cell_info (cell) ;\n        \n        if (valid) {\n            ++readCnt ;\n            \n            cout << cell << endl ;\n        }\n        \n    } while (valid) ;\n    \n    cout << \"Read \" << readCnt << \" number of library cells\" << endl ;\n}\n\nostream& operator<< (ostream& os, const SpefNodeName& n) {\n    os << n.n1 << ((n.n2 != \"\") ? \":\" : \"\") << n.n2 ;\n    \n    return os ;\n}\n\nostream& operator<< (ostream& os, const SpefConnection& c) {\n    os << c.nodeType << \" \" << c.nodeName << \" \" << c.direction ;\n    return os ;\n};\n\nostream& operator<< (ostream& os, const SpefCapacitance& c) {\n    os << c.nodeName << \" \" << c.capacitance ;\n    return os ;\n}\n\nostream& operator<< (ostream& os, const SpefResistance& r) {\n    os << r.fromNodeName << \" \" << r.toNodeName << \" \" << r.resistance ;\n    return os ;\n}\n\n\n\nbool OPSParser::read_operation (OPSInfo &ops) {\n\n\tvector<string> tokens ;\n\tbool valid = read_line_as_tokens (is, tokens) ;\n\tint tokenSize = tokens.size();\n\t\n\tif (!valid)\n\t\treturn false ;\t\n\tstring opt = tokens[tokenSize++];\n\tops.opsType = opt;\n\t\n\tif(opt == \"report_at\"){\n\t\tops.pin = tokens[++tokenSize];\n\t\t//if()\n\t\t\n\t}\n\t//TODO\n\treturn true;\n}\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/io/parser/parser_helper.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n//////////////////////////////////////////////////////////////////\n//\n//\n//  Helper functions and classes to parse the ISPD 2012 contest\n//  benchmark files.\n//\n//  This code is provided for description purposes only. The contest\n//  organizers cannot guarantee that the provided code is free of\n//  bugs or defects. !!!! USE THIS CODE AT YOUR OWN RISK !!!!!\n//\n//\n//  The contestants are free to use these functions as-is or make\n//  modifications. If the contestants choose to use the provided\n//  code, they are responsible for making sure that it works as\n//  expected.\n//\n//  The code provided here has no real or implied warranties.\n//\n//\n////////////////////////////////////////////////////////////////////\n\n#ifndef _PARSER_HELPER_H\n#define _PARSER_HELPER_H\n\n#include <iostream>\n#include <fstream>\n#include <vector>\n#include <string>\n#include <limits>\n\n#include \"rsyn/util/Array.h\"\n\nusing std::cout ;\nusing std::endl ;\nusing std::istream ;\nusing std::ostream ;\nusing std::vector ;\nusing std::string ;\n\nnamespace ISPD13 {\n\nenum CommandTypeEnum {\n\t\tINSERT_GATE,\n                REPOWER_GATE,\n                REMOVE_GATE,\n                INSERT_NET,\n                READ_SPEF,\n                REMOVE_NET,\n                CONNECT_PIN,\n                DISCONNECT_PIN,\n                UNKNOWN\n\t}; // end enum\n\nenum QueryTypeEnum {\n\t\tREPORT_AT,\n\t\tREPORT_RAT,\n                REPORT_SLACK,\t\t\n\t\tREPORT_PATHS,\n                NOT_VALID\n\t}; // end enum\n        \nenum OpsType {CMD, QUERY, NONE};\n\n/////////////////////////////////////////////////////////////////////\n//\n// This class can be used to parse the specific verilog\n// format as defined in the ISPD-13 contest benchmarks. It is not\n// intended to be used as a generic verilog parser.\n//\n// See test_verilog_parser () function in parser_helper.cpp for an\n// example of how to use this class.\n//\n/////////////////////////////////////////////////////////////////////\nenum tauVerilog {INPUT_TAU15, OUTPUT_TAU15, WIRE_TAU15, GATE_TAU15, ENDMOD_TAU15};\n\nclass VerilogParser {\n    \n    std::ifstream is ;\n    \npublic:\n\tvector < string > tauTokens;\n    \n    // Constructor that opens the given filename\n    VerilogParser (string filename): is(filename.c_str()) {\n\t\tif (!is) {\n\t\t\tstd::cout << \"[ERROR] File '\" << filename << \"' could not be opened.\\n\"; \n\t\t} // end if\n\t}\n    \n    // The following functions must be issued in a particular order\n    // See test_verilog_parser function for an example\n    \n    // Read the module definition\n    bool read_module (string& moduleName) ;\n\n    \n    // Read the next primary input.\n    // Return value indicates if the last read was successful or not.\n    bool read_primary_input (string& primaryInput) ;\n    \n    // Read the next primary output.\n    // Return value indicates if the last read was successful or not.\n    bool read_primary_output (string& primaryInput) ;\n    \n    \n    // Read the next net.\n    // Return value indicates if the last read was successful or not.\n    bool read_wire (string& wire) ;\n    \n    // Read the next cell instance.\n    // Return value indicates if the last read was successful or not.\n    bool read_cell_inst (string& cellType, string& cellInstName,\n                         vector<std::pair<string, string> >& pinNetPairs) ;\n    \n    //function adapted for TAU 15 contest\n    tauVerilog read_line_tau15(string &aux);\n    bool read_module_tau15 (string& moduleName) ;\n     bool read_module_ispd15 (string& moduleName) ;\n    bool read_cell_inst_tau15 (string& cellType, string& cellInstName,\n                                    vector<std::pair<string, string> >& pinNetPairs);\n} ;\n\n\n/////////////////////////////////////////////////////////////////////\n//\n// This class can be used to parse the specific sdc\n// format as defined in the ISPD-13 contest benchmarks. It is not\n// intended to be used as a generic sdc parser.\n//\n// See test_sdc_parser () function in parser_helper.cpp for an\n// example of how to use this class.\n//\n/////////////////////////////////////////////////////////////////////\nclass SdcParser {\n    \n    std::ifstream is ;\n    \npublic:\n    \n    \n    // Constructor that opens the given filename\n    SdcParser (string filename): is(filename.c_str()) {\n\t\tif (!is) {\n\t\t\tstd::cout << \"ERROR: SDC file '\" << filename << \"' could not be opened.\\n\";\n\t\t\tstd::exit(1);\n\t\t} // end if\n\t} // end constructor\n    \n    // The following functions must be issued in a particular order\n    // See test_sdc_parser function for an example\n    \n    // Read clock definition\n    // Return value indicates if the last read was successful or not.\n    bool read_clock (string& clockName, string& clockPort, double& period) ;\n    \n    // Read input delay\n    // Return value indicates if the last read was successful or not.\n    bool read_input_delay (string& portName, double& delay) ;\n    \n    // Read driver info for the input port\n    // Return value indicates if the last read was successful or not.\n    bool read_driver_info (string& inPortName, string& driverSize, string& driverPin,\n                           double& inputTransitionFall, double& inputTransitionRise) ;\n    \n    // Read output delay\n    // Return value indicates if the last read was successful or not.\n    bool read_output_delay (string& portName, double& delay) ;\n    \n    // Read output load\n    // Return value indicates if the last read was successful or not.\n    bool read_output_load (string& outPortName, double& load) ;\n    \n    \n} ;\n\n\n\n/////////////////////////////////////////////////////////////////////\n//\n// The following classes can be used to parse the specific spef\n// format as defined in the ISPD-13 contest benchmarks. It is not\n// intended to be used as a generic spef parser.\n//\n// See test_spef_parser () function in parser_helper.cpp for an\n// example of how to use this class.\n//\n/////////////////////////////////////////////////////////////////////\nstruct SpefNodeName {\n    string n1 ;\n    string n2 ;\n    \n    // A node in the spef file can be defined in 3 different ways:\n    // 1. For the node corresponding to the connection to a port:\n    //       nodeName = \"portName\", i.e. n1 = \"portName\", n2 = \"\"\n    //\n    // 2. For the node corresponding to the connection to a cell pin:\n    //       nodeName = \"cellName\":\"pinName\", i.e. n1 = \"cellName\", n2 = \"pinName\"\n    //\n    // 3. For an internal node of an RC tree:\n    //       nodeName = \"netName\":\"index\", i.e. n1 = \"netName\", n2 = \"index\"\n\t\n\t// Added by Guilherme Flach\n\toperator string() const {return n1 + ((n2 != \"\") ? \":\" : \"\") + n2;}\n\t\n} ;\n\n    ostream& operator<< (ostream& os, const SpefNodeName& n) ;\n\n    struct SpefConnection {\n        char nodeType ; // either 'P' (port) or 'I' (internal)\n        SpefNodeName nodeName ;\n        char direction ; // either 'I' (receiver pin) or 'O' (driver pin)\n    };\n    \n    ostream& operator<< (ostream& os, const SpefConnection& c) ;\n    \n    struct SpefCapacitance {\n        SpefNodeName nodeName ;\n        double capacitance ;\n        \n    } ;\n    \n    ostream& operator<< (ostream& os, const SpefCapacitance& c) ;\n\n    struct SpefResistance {\n        SpefNodeName fromNodeName ;\n        SpefNodeName toNodeName ;\n        double resistance ;\n    } ;\n    \n    ostream& operator<< (ostream& os, const SpefResistance& r) ;\n\n    struct SpefNet {\n        string netName ;\n        double netLumpedCap ;\n        vector<SpefConnection> connections ;\n        vector<SpefCapacitance> capacitances ;\n        vector<SpefResistance> resistances ;\n        \n        void clear() {\n            netName = \"\" ;\n            netLumpedCap = 0.0 ;\n            connections.clear() ;\n            capacitances.clear() ;\n            resistances.clear() ;\n        }\n        \n    } ;\n    \n    class SpefParser {\n        \n        std::ifstream is ;\n        \n        bool read_connections (vector<SpefConnection>& connections) ;\n        void read_capacitances (vector<SpefCapacitance>& capacitances) ;\n        void read_resistances (vector<SpefResistance>& resistances) ;\n        \n    public:\n        \n        SpefParser (string filename): is(filename.c_str()) {}\n        \n        // Read the spef data for the next net.\n        // Return value indicates if the last read was successful or not.\n        bool read_net_data (SpefNet& spefNet) ;\n        \n        \n    } ;\n    \n    \n    /////////////////////////////////////////////////////////////////////\n    //\n    // This class can be used to parse the specific .timing\n    // format as defined in the ISPD-13 contest benchmarks.\n    //\n    // See test_timing_parser () function in parser_helper.cpp for an\n    // example of how to use this class.\n    //\n    /////////////////////////////////////////////////////////////////////\n    class TimingParser {\n        \n        std::ifstream is ;\n        \n    public:\n        \n        TimingParser (string filename): is(filename.c_str()) {}\n        \n        // Read timing info for the next pin or port\n        // Return value indicates if the last read was successful or not.\n        // If the line read corresponds to a pin, then name1 and name2 will be set to the cell\n        // instance name and the pin name, respectively.\n        // If the line read corresponds to a port, then name1 will be set to the port name, and\n        // name2 will be set to \"\".\n        bool read_timing_line (string& name1, string& name2, double& riseSlack, double& fallSlack,\n                               double& riseTransition, double& fallTransition,\n                               double& riseArrival, double& fallArrival) ;\n        \n        bool read_timing_tau15(string & str1, string &str2, double &val1, double &val2, double &val3, double &val4);\n    } ;\n    \n     /////////////////////////////////////////////////////////////////////\n    //\n    // This class can be used to parse the specific .ops\n    // format as defined in the TAU-15 contest benchmarks.\n    //\n    /////////////////////////////////////////////////////////////////////\n    class OperationsParser {\n        \n        std::ifstream is ;\n        \n    public:\n        \n        OperationsParser (string filename): is(filename.c_str()) {}\n        \n        // Read timing info for the next pin or port\n        // Return value indicates if the last read was successful or not.\n        // If the line read corresponds to a pin, then name1 and name2 will be set to the cell\n        // instance name and the pin name, respectively.\n        // If the line read corresponds to a port, then name1 will be set to the port name, and\n        // name2 will be set to \"\".\n        \n        bool read_ops_tau15(ISPD13::CommandTypeEnum &cmdType, ISPD13::QueryTypeEnum &queryType, \n\t\t\t    string &pin, string &net, string &file, string &gate, string &cell, bool &early, bool &rise, int &paths );\n    } ;\n    \n   \n    \n    /////////////////////////////////////////////////////////////////////\n    //\n    // This class can be used to parse the specific .ceff\n    // format as defined in the ISPD-13 contest benchmarks.\n    //\n    // See test_ceff_parser () function in parser_helper.cpp for an\n    // example of how to use this class.\n    //\n    /////////////////////////////////////////////////////////////////////\n    class CeffParser {\n        \n        std::ifstream is ;\n        \n    public:\n        \n        CeffParser (string filename): is(filename.c_str()) {}\n        \n        // Read ceff values for the next pin or port\n        // Return value indicates if the last read was successful or not.\n        // If the line read corresponds to a pin, then name1 and name2 will be set to the cell\n        // instance name and the pin name, respectively.\n        // If the line read corresponds to a port, then name1 will be set to the port name, and\n        // name2 will be set to \"\".\n        bool read_ceff_line (string& name1, string& name2, double& riseCeff, double& fallCeff) ;\n        \n        \n    } ;\n    \n    \n    \n    \n    \n    /////////////////////////////////////////////////////////////////////\n    //\n    // The following classes can be used to parse the specific lib\n    // format as defined in the ISPD-13 contest benchmarks. They are not\n    // intended to be used as a generic lib parser.\n    //\n    // See test_lib_parser () function in parser_helper.cpp for an\n    // example of how to use these classes.\n    //\n    /////////////////////////////////////////////////////////////////////\n    \n    // Look up table to store delay or slew functions\n    struct LibParserLUT {\n        \n        // Look up table is indexed by the output load and the input transition values\n        // Example:\n        //   Let L = loadIndices[i]\n        //       T = transitionIndices[j]\n        //   Then, the table value corresponding to L and T will be:\n        //       table[i][j]\n        //\n\tbool isScalar;\n        vector<double> loadIndices ;\n        vector<double> transitionIndices ;\n        Array2D<double> tableVals ;\n\t\n\tLibParserLUT() : isScalar(false) {};\n\t\n\tdouble getMaxLoad() const { return loadIndices[loadIndices.size() -1]; }\n\tdouble getMinLoad() const { return loadIndices[0]; }\n\tdouble getMaxTransition() const { return transitionIndices[transitionIndices.size() -1]; }\n\tdouble getMinTransition() const { return transitionIndices[0]; }\n\t      \n    } ;\n    \n    ostream& operator<< (ostream& os, LibParserLUT& lut) ;\n    \n    struct LibParserTimingInfo {\n        \n        string fromPin ;\n        string toPin ;\n        string timingSense ; // \"non_unate\" or \"negative_unate\" or \"positive_unate\".\n        // Note that ISPD-13 library will have only negative-unate combinational cells. The clock arcs\n        // for sequentials will be non_unate (which can be ignored because of the simplified sequential\n        // timing model for ISPD-13).\n        \n\t\t// Guilherme Flach - 2016/08/21\n\t\t// Added to identify non-common timing arcs (e.g. clear, preset, \n\t\t// three-state).\n\t\tstring timingType;\n\t\t\n        \n        LibParserLUT fallDelay ;\n        LibParserLUT riseDelay ;\n        LibParserLUT fallTransition ;\n        LibParserLUT riseTransition ;\n\t\n        \n    } ;\n    \n    ostream& operator<< (ostream& os, LibParserTimingInfo& timing) ;\n    \n    struct LibParserPinInfo {\n        \n        string name ; // pin name\n\tstring related;\n        double capacitance ; // input pin cap (not defined for output pins)\n        double maxCapacitance ; // the max load this pin can drive\n\tdouble maxTransition; // max input transition time\n        bool isInput ; // whether the pin is input or output pin\n        bool isClock ; // whether the pin is a clock pin or not\n        bool isTimingEndpoint;\n        bool risingEdge;\n        LibParserLUT riseSetup;\n        LibParserLUT fallSetup;\n        LibParserLUT riseHold;\n        LibParserLUT fallHold;\n        \n        LibParserPinInfo () : capacitance (0.0), maxCapacitance (std::numeric_limits<double>::max()),\n        maxTransition (-std::numeric_limits<double>::infinity()), isInput(true), isClock(false), isTimingEndpoint(false), risingEdge(false) {}\n        \n    } ;\n    \n    ostream& operator<< (ostream& os, LibParserPinInfo& pin) ;\n    \n    struct LibParserCellInfo {\n        \n        string name ; // cell name\n        string footprint ; // only the cells with the same footprint are swappable\n        double leakagePower ; // cell leakage power\n        double area ; // cell area (will not be a metric for ISPD-13)\n        bool isSequential ; // if true then sequential cell, else combinational\n        bool dontTouch ; // is the sizer allowed to size this cell?\n\t\tbool isTieLow; // Tie are cells that keeps output constantly in VDD or GND\n        bool isTieHigh;\n\n        vector<LibParserPinInfo> pins ;\n        vector<LibParserTimingInfo> timingArcs ;\n        \n        LibParserCellInfo () : leakagePower (0.0), area (0.0), isSequential (false), dontTouch(false), isTieLow(false), isTieHigh(false) {}\n        \n    } ;\n    \n    ostream& operator<< (ostream& os, LibParserCellInfo& cell) ;\n    \n    \n    // See test_lib_parser () function in parser_helper.cpp for an\n    // example of how to use this class.\n    class LibParser {\n        \n        std::ifstream is ;\n        \n        void _skip_lut_3D () ;\n        void _begin_read_lut (LibParserLUT& lut) ;\n        void _begin_read_timing_info (string pinName, LibParserPinInfo& pin, LibParserTimingInfo& cell) ;\n        void _begin_read_pin_info (string pinName, LibParserCellInfo& cell, LibParserPinInfo& pin) ;\n        void _begin_read_cell_info (string cellName, LibParserCellInfo& cell) ;\n        \n    public:\n        \n        LibParser (string filename): is(filename.c_str()) {}\n        \n        // Read the default max_transition defined for the library.\n        // Return value indicates if the last read was successful or not.\n        // This function must be called in the beginning before any read_cell_info function call.\n        bool read_default_max_transition (double& maxTransition) ;\n        \n        \n        // Read the next standard cell definition.\n        // Return value indicates if the last read was successful or not.\n        bool read_cell_info (LibParserCellInfo& cell) ;\n        \n        \n    } ;\n\n    \n    /*\n     * \n     * PArsing TAU 2015 operations\n     * \n     * \n     */\n            \n    enum propType {LATE, EARLY};\n    enum timeTransType {RISE, FALL};\n    \n    class OPSInfo{\n    public:\n\t    string opsType;\n\t    string pin;\n\t    string cell;\n\t    string gate;\n\t    string file;\n\t    propType prop;  \n\t    timeTransType timeTrans;\n\t    int numPaths;\n    };\n\n    class OPSParser {\n\t     std::ifstream is ;\n        \n\tpublic:\n\t\tOPSParser (string filename): is(filename.c_str()) {}\n        \n        // Read ceff values for the next pin or port\n        // Return value indicates if the last read was successful or not.\n        // If the line read corresponds to a pin, then name1 and name2 will be set to the cell\n        // instance name and the pin name, respectively.\n        // If the line read corresponds to a port, then name1 will be set to the port name, and\n        // name2 will be set to \"\".\n        bool read_operation (OPSInfo &ops) ;\n    };\n} // end namespace\n    \n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/io/reader/ISPD2018Reader.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#include \"ISPD2018Reader.h\"\n#include <Rsyn/PhysicalDesign>\n#include \"rsyn/ispd18/Guide.h\"\n#include \"rsyn/ispd18/RoutingGuide.h\"\n#include \"rsyn/io/parser/guide-ispd18/GuideParser.h\"\n#include \"rsyn/io/parser/lef_def/LEFControlParser.h\"\n#include \"rsyn/io/parser/lef_def/DEFControlParser.h\"\n\nnamespace Rsyn {\n\t\nbool ISPD2018Reader::load(const Rsyn::Json& params) {\n\tRsyn::Session session;\n\n\tstd::string path = params.value(\"path\", \"\");\n\t\t\t\t\n\tif (!params.count(\"lefFile\")) {\n\t\tstd::cout << \"[ERROR] LEF file not specified...\\n\";\n\t\treturn false;\n\t} // end if\n\tlefFile = session.findFile(params.value(\"lefFile\", \"\"), path);\n\t\n\tif (!params.count(\"defFile\")) {\n\t\tstd::cout << \"[ERROR] DEF file not specified...\\n\";\n\t\treturn false;\n\t} // end if\n\tdefFile = session.findFile(params.value(\"defFile\", \"\"), path);\n\t\n\t// if (!params.count(\"guideFile\")) {\n\t// \tstd::cout << \"[ERROR] Guide file not specified...\\n\";\n\t// \treturn false;\n\t// } // end if\n\t// guideFile = session.findFile(params.value(\"guideFile\", \"\"), path);\n\t\n\tparsingFlow();\n\treturn true;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid ISPD2018Reader::parsingFlow() {\n\tparseLEFFile();\n\tparseDEFFile();\n\tpopulateDesign();\n\t// parseGuideFile();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid ISPD2018Reader::parseLEFFile() {\n\tLEFControlParser lefParser;\n\tlefParser.parseLEF(lefFile, lefDescriptor);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid ISPD2018Reader::parseDEFFile() {\n\tDEFControlParser defParser;\n\tdefParser.parseDEF(defFile, defDescriptor);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid ISPD2018Reader::parseGuideFile() {\n\tGuideDscp guideDescriptor;\n\tGuideParser guideParser;\n\tguideParser.parse(guideFile, guideDescriptor);\n\tsession.startService(\"rsyn.routingGuide\");\n\troutingGuide = (RoutingGuide*) session.getService(\"rsyn.routingGuide\");\n\troutingGuide->loadGuides(guideDescriptor);\n} // end method\n\nvoid ISPD2018Reader::populateDesign() {\n\tRsyn::Design design = session.getDesign();\n\n\tReader::populateRsyn(lefDescriptor, defDescriptor, design);\n\n\tRsyn::Json physicalDesignConfiguration;\n\tphysicalDesignConfiguration[\"clsEnableMergeRectangles\"] = false;\n\tphysicalDesignConfiguration[\"clsEnableNetPinBoundaries\"] = true;\n\tphysicalDesignConfiguration[\"clsEnableRowSegments\"] = true;\n\tsession.startService(\"rsyn.physical\", physicalDesignConfiguration);\n\tRsyn::PhysicalDesign physicalDesign = session.getPhysicalDesign();\n\tphysicalDesign.loadLibrary(lefDescriptor);\n\tphysicalDesign.loadDesign(defDescriptor);\n\tphysicalDesign.updateAllNetBounds(false);\n} // end method\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/io/reader/ISPD2018Reader.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_ISPD2018_READER_H\n#define RSYN_ISPD2018_READER_H\n\n#include <Rsyn/Session>\n\nnamespace Rsyn  {\n\t\nclass RoutingGuide;\n\t\nclass ISPD2018Reader : public Reader {\npublic:\n\tISPD2018Reader() = default;\n\tvirtual bool load(const Rsyn::Json& params) override;\n\t\nprivate:\n\tSession session;\n\t\n\tstd::string lefFile;\n\tstd::string defFile;\n\tstd::string guideFile;\n\tLefDscp lefDescriptor;\n\tDefDscp defDescriptor;\n\tRoutingGuide *routingGuide;\n\t\n\tvoid parsingFlow();\n\tvoid parseLEFFile();\n\tvoid parseDEFFile();\n\tvoid parseGuideFile();\n\tvoid populateDesign();\n};\n\n}\n\n#endif /* ISPD2018READER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/io/reader/PopulateRsyn.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PopulateRsyn.cpp\n * Author: jucemar\n * \n * Created on 18 de Fevereiro de 2017, 15:21\n */\n\n#include \"PopulateRsyn.h\"\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\nvoid\nPopulateRsyn::populateRsynLibraryFromLef(\n\tconst LefDscp &lefDscp,\n\tRsyn::Design rsynDesign\n\t) {\n\tfor (const LefMacroDscp & macro : lefDscp.clsLefMacroDscps) {\n\t\tRsyn::CellDescriptor dscp;\n\t\tdscp.setMacro(macro.clsMacro);\n\t\tfor (const LefPinDscp &pin : macro.clsPins) {\n\t\t\t// Mateus @ 20180917: Adding PinUse\n\t\t\tdscp.addPin(pin.clsPinName, Legacy::lefPinDirectionFromString(pin.clsPinDirection), Legacy::lefPinUseFromString(pin.clsPinUse));\n\t\t} // end for\n\t\trsynDesign.createLibraryCell(dscp, true);\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PopulateRsyn::populateRsynNetlistFromVerilog(\n\tconst Legacy::Design &verilogDesign,\n\tRsyn::Design rsynDesign\n\t) {\n\n\tbool keepWarning;\n\tint keepWarningCounter;\n\n\tRsyn::Module top = rsynDesign.getTopModule();\n\trsynDesign.updateName(verilogDesign.name);\n\n\tkeepWarning = true;\n\tkeepWarningCounter = 0;\n\tfor (auto &port : verilogDesign.primaryInputs) {\n\t\tRsyn::Port rsynCell =\n\t\t\trsynDesign.findPortByName(port);\n\n\t\tif (!rsynCell) {\n\t\t\ttop.createPort(Rsyn::IN, port);\n\t\t} else {\n\t\t\tif (keepWarning) {\n\t\t\t\tif (++keepWarningCounter > 10) {\n\t\t\t\t\tkeepWarning = false;\n\t\t\t\t\tstd::cout << \"[WARNING] At leat one more duplicated port...\\n\";\n\t\t\t\t} else {\n\t\t\t\t\tstd::cout << \"[WARNING] The primary input port '\"\n\t\t\t\t\t\t<< port << \"' is already defined.\\n\";\n\t\t\t\t} // end else\n\t\t\t} // end if\n\t\t} // end else\n\t} // end for\n\n\tkeepWarning = true;\n\tkeepWarningCounter = 0;\n\n\tfor (auto &port : verilogDesign.primaryOutputs) {\n\t\tRsyn::Port rsynCell =\n\t\t\trsynDesign.findPortByName(port);\n\n\t\tif (!rsynCell) {\n\t\t\ttop.createPort(Rsyn::OUT, port);\n\t\t} else {\n\t\t\tif (keepWarning) {\n\t\t\t\tif (++keepWarningCounter > 10) {\n\t\t\t\t\tkeepWarning = false;\n\t\t\t\t\tstd::cout << \"[WARNING] At leat one more duplicated port...\\n\";\n\t\t\t\t} else {\n\t\t\t\t\tstd::cout << \"[WARNING] The primary output port '\"\n\t\t\t\t\t\t<< port << \"' is already defined.\\n\";\n\t\t\t\t} // end else\n\t\t\t} // end if\n\t\t} // end else\n\t} // end for\n\n\t// Creates cells.\n\tfor (auto &component : verilogDesign.components) {\n\t\tRsyn::LibraryCell lcell =\n\t\t\trsynDesign.findLibraryCellByName(component.id);\n\n\t\tif (!lcell) {\n            std::string str = \"Library cell \" + component.id + \" not found\\n\";\n\t\t\tthrow Exception(str);\n\t\t} // end if\n\t\ttop.createCell(lcell, component.name);\n\t} // end for\n\n\t// Creates nets and connections.\n\tfor (auto &net : verilogDesign.nets) {\n\t\tif (net.name == \"\") {\n\t\t\tstd::cout << \"[ERROR] Empty net name.\\n\";\n\t\t\tfor (unsigned i = 0; i < net.connections.size(); i++) {\n\t\t\t\tstd::cout << \"Connection: \" << net.connections[i].instance << \":\" << net.connections[i].pin << \"\\n\";\n\t\t\t} // end for\n\t\t\texit(1);\n\t\t} // end if\n\n\t\tRsyn::Net rsynNet =\n\t\t\ttop.createNet(net.name);\n\n\t\tfor (auto &connection : net.connections) {\n\n\t\t\tif (connection.instance == \"PIN\") {\n\t\t\t\tRsyn::Port rsynCell =\n\t\t\t\t\trsynDesign.findPortByName(connection.pin);\n\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] The primary input/ouput port '\"\n\t\t\t\t\t\t<< connection.pin << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin =\n\t\t\t\t\trsynCell.getInnerPin();\n\n\t\t\t\trsynPin.connect(rsynNet);\n\n\t\t\t} else {\n\t\t\t\tRsyn::Cell rsynCell =\n\t\t\t\t\trsynDesign.findCellByName(connection.instance);\n\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] Cell '\"\n\t\t\t\t\t\t<< connection.instance << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin =\n\t\t\t\t\trsynCell.getPinByName(connection.pin);\n\n\t\t\t\trsynPin.connect(rsynNet);\n\n\t\t\t} // end else\n\t\t} // end for\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PopulateRsyn::populateRsyn(\n\tconst LefDscp &lefDscp,\n\tconst DefDscp &defDscp,\n\tconst Legacy::Design &verilogDesign,\n\tRsyn::Design rsynDesign) {\n\n\tbool keepWarning;\n\tint keepWarningCounter;\n\n\tRsyn::Module top = rsynDesign.getTopModule();\n\trsynDesign.updateName(defDscp.clsDesignName);\n\n\t// Create library cells.\n\t// Some cells (e.g. TIE) only appears in the LEF, not in the Liberty\n\t// at least for ICCAD 15 benchmarks. That's why we need to try to create\n\t// also cells using LEF.\n\tpopulateRsynLibraryFromLef(lefDscp, rsynDesign);\n\n\t// Creates ports.\n\tfor (const DefPortDscp &port : defDscp.clsPorts) {\n\n\t\tconst Rsyn::Direction direction =\n\t\t\t(port.clsDirection == \"INPUT\") ? Rsyn::IN : Rsyn::OUT;\n\n\t\ttop.createPort(direction, port.clsName);\n\t} // end for\n\n\tkeepWarning = true;\n\tkeepWarningCounter = 0;\n\tfor (auto &port : verilogDesign.primaryInputs) {\n\t\tRsyn::Port rsynCell =\n\t\t\trsynDesign.findPortByName(port);\n\n\t\tif (!rsynCell) {\n\t\t\tif (keepWarning) {\n\t\t\t\tif (++keepWarningCounter > 10) {\n\t\t\t\t\tkeepWarning = false;\n\t\t\t\t\tstd::cout << \"[WARNING] At leat one more undefined port...\\n\";\n\t\t\t\t} else {\n\t\t\t\t\tstd::cout << \"[WARNING] The primary input port '\"\n\t\t\t\t\t\t<< port << \"' is defined in Verilog file but not in the DEF file.\\n\";\n\t\t\t\t} // end else\n\t\t\t} // end if\n\n\t\t\ttop.createPort(Rsyn::IN, port);\n\t\t} // end if\n\t} // end for\n\n\tkeepWarning = true;\n\tkeepWarningCounter = 0;\n\n\tfor (auto &port : verilogDesign.primaryOutputs) {\n\t\tRsyn::Port rsynCell =\n\t\t\trsynDesign.findPortByName(port);\n\n\t\tif (!rsynCell) {\n\t\t\tif (keepWarning) {\n\t\t\t\tif (++keepWarningCounter > 10) {\n\t\t\t\t\tkeepWarning = false;\n\t\t\t\t\tstd::cout << \"[WARNING] At leat one more undefined port...\\n\";\n\t\t\t\t} else {\n\t\t\t\t\tstd::cout << \"[WARNING] The primary output port '\"\n\t\t\t\t\t\t<< port << \"' is defined in Verilog file but not in the DEF file.\\n\";\n\t\t\t\t} // end else\n\t\t\t} // end if\n\n\t\t\ttop.createPort(Rsyn::OUT, port);\n\t\t} // end if\n\t} // end for\n\n\t// Creates cells.\n\tfor (const DefComponentDscp &component : defDscp.clsComps) {\n\t\tRsyn::LibraryCell lcell =\n\t\t\trsynDesign.findLibraryCellByName(component.clsMacroName);\n\n\t\tif (!lcell) {\n            std::string str = \"Library cell \" + component.clsMacroName + \" not found\\n\";\n\t\t\tthrow Exception(str);\n\t\t} // end if\n\t\ttop.createCell(lcell, component.clsName);\n\t} // end for\n\n\t// Creates nets and connections.\n\tfor (auto &net : verilogDesign.nets) {\n\t\tif (net.name == \"\") {\n\t\t\tstd::cout << \"[ERROR] Empty net name.\\n\";\n\t\t\tfor (unsigned i = 0; i < net.connections.size(); i++) {\n\t\t\t\tstd::cout << \"Connection: \" << net.connections[i].instance << \":\" << net.connections[i].pin << \"\\n\";\n\t\t\t} // end for\n\t\t\texit(1);\n\t\t} // end if\n\n\t\tRsyn::Net rsynNet =\n\t\t\ttop.createNet(net.name);\n\n\t\tfor (auto &connection : net.connections) {\n\n\t\t\tif (connection.instance == \"PIN\") {\n\t\t\t\tRsyn::Port rsynCell =\n\t\t\t\t\trsynDesign.findPortByName(connection.pin);\n\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] The primary input/ouput port '\"\n\t\t\t\t\t\t<< connection.pin << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin =\n\t\t\t\t\trsynCell.getInnerPin();\n\n\t\t\t\trsynPin.connect(rsynNet);\n\n\t\t\t} else {\n\t\t\t\tRsyn::Cell rsynCell =\n\t\t\t\t\trsynDesign.findCellByName(connection.instance);\n\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] Cell '\"\n\t\t\t\t\t\t<< connection.instance << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin =\n\t\t\t\t\trsynCell.getPinByName(connection.pin);\n\n\t\t\t\trsynPin.connect(rsynNet);\n\n\t\t\t} // end else\n\t\t} // end for\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PopulateRsyn::populateRsyn(\n\tconst LefDscp &lefDscp,\n\tconst DefDscp &defDscp,\n\tRsyn::Design rsynDesign) {\n\n\tbool keepWarning;\n\tint keepWarningCounter;\n\n\tRsyn::Module top = rsynDesign.getTopModule();\n\trsynDesign.updateName(defDscp.clsDesignName);\n\n\t// Create library cells.\n\t// Some cells (e.g. TIE) only appears in the LEF, not in the Liberty\n\t// at least for ICCAD 15 benchmarks. That's why we need to try to create\n\t// also cells using LEF.\n\tpopulateRsynLibraryFromLef(lefDscp, rsynDesign);\n\n\t// Creates ports.\n\tfor (const DefPortDscp &port : defDscp.clsPorts) {\n\n\t\tconst Rsyn::Direction direction =\n\t\t\t(port.clsDirection == \"INPUT\") ? Rsyn::IN : Rsyn::OUT;\n\n\t\ttop.createPort(direction, port.clsName);\n\t} // end for\n\n\n\t//\t// Creates cells.\n\tfor (const DefComponentDscp &component : defDscp.clsComps) {\n\t\tRsyn::LibraryCell lcell =\n\t\t\trsynDesign.findLibraryCellByName(component.clsMacroName);\n\n\t\tif (!lcell) {\n            std::string str = \"Library cell \" + component.clsMacroName + \" not found\\n\";\n\t\t\tthrow Exception(str);\n\t\t} // end if\n\t\ttop.createCell(lcell, component.clsName);\n\t} // end for\n\n\n\t// Creates nets and connections.\n\tfor (const DefNetDscp &net : defDscp.clsNets) {\n\t\tif (net.clsName == \"\") {\n\t\t\tstd::cout << \"[ERROR] Empty net name.\\n\";\n\t\t\tfor (unsigned i = 0; i < net.clsConnections.size(); i++) {\n\t\t\t\tstd::cout << \"Connection: \" << net.clsConnections[i].clsComponentName << \":\" << net.clsConnections[i].clsPinName << \"\\n\";\n\t\t\t} // end for\n\t\t\texit(1);\n\t\t} // end if\n\n\t\tRsyn::Net rsynNet = top.createNet(net.clsName);\n\n\t\tconst std::string use = net.clsUse;\n\t\tif (use == \"ANALOG\") {\n\t\t\trsynNet.setUse(Rsyn::ANALOG);\n\t\t} else if (use == \"CLOCK\") {\n\t\t\trsynNet.setUse(Rsyn::CLOCK);\n\t\t} else if (use == \"GROUND\") {\n\t\t\trsynNet.setUse(Rsyn::GROUND);\n\t\t} else if (use == \"POWER\") {\n\t\t\trsynNet.setUse(Rsyn::POWER);\n\t\t} else if (use == \"RESET\") {\n\t\t\trsynNet.setUse(Rsyn::RESET);\n\t\t} else if (use == \"SCAN\") {\n\t\t\trsynNet.setUse(Rsyn::SCAN);\n\t\t} else if (use == \"SIGNAL\") {\n\t\t\trsynNet.setUse(Rsyn::SIGNAL);\n\t\t} else if (use == \"TIEOFF\") {\n\t\t\trsynNet.setUse(Rsyn::TIEOFF);\n\t\t} // end if\n\t\t\t\n\t\tfor (const DefNetConnection &connection : net.clsConnections) {\n\n\t\t\tif (connection.clsComponentName == \"PIN\") {\n\t\t\t\tRsyn::Port rsynCell =\n\t\t\t\t\trsynDesign.findPortByName(connection.clsPinName);\n\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] The primary input/ouput port '\"\n\t\t\t\t\t\t<< connection.clsPinName << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin = rsynCell.getInnerPin();\n\t\t\t\trsynPin.connect(rsynNet);\n\t\t\t} else {\n\t\t\t\tRsyn::Cell rsynCell = rsynDesign.findCellByName(connection.clsComponentName);\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] Cell '\"\n\t\t\t\t\t\t<< connection.clsComponentName << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin = rsynCell.getPinByName(connection.clsPinName);\n\t\t\t\trsynPin.connect(rsynNet);\n\t\t\t} // end else\n\t\t} // end for\n\t} // end for\n\t\n\tfor (const DefNetDscp &net : defDscp.clsSpecialNets) {\n\t\tif (net.clsName == \"\") {\n\t\t\tstd::cout << \"[ERROR] Empty net name.\\n\";\n\t\t\tfor (unsigned i = 0; i < net.clsConnections.size(); i++) {\n\t\t\t\tstd::cout << \"Connection: \" << net.clsConnections[i].clsComponentName << \":\" << net.clsConnections[i].clsPinName << \"\\n\";\n\t\t\t} // end for\n\t\t\texit(1);\n\t\t} // end if\n\n\t\tRsyn::Net rsynNet = top.createNet(net.clsName);\n\t\t\n\t\tconst std::string use = net.clsUse;\n\t\tif (use == \"ANALOG\") {\n\t\t\trsynNet.setUse(Rsyn::ANALOG);\n\t\t} else if (use == \"CLOCK\") {\n\t\t\trsynNet.setUse(Rsyn::CLOCK);\n\t\t} else if (use == \"GROUND\") {\n\t\t\trsynNet.setUse(Rsyn::GROUND);\n\t\t} else if (use == \"POWER\") {\n\t\t\trsynNet.setUse(Rsyn::POWER);\n\t\t} else if (use == \"RESET\") {\n\t\t\trsynNet.setUse(Rsyn::RESET);\n\t\t} else if (use == \"SCAN\") {\n\t\t\trsynNet.setUse(Rsyn::SCAN);\n\t\t} else if (use == \"SIGNAL\") {\n\t\t\trsynNet.setUse(Rsyn::SIGNAL);\n\t\t} else if (use == \"TIEOFF\") {\n\t\t\trsynNet.setUse(Rsyn::TIEOFF);\n\t\t} // end if\n\t\t\t\t\n\t\tfor (const DefNetConnection &connection : net.clsConnections) {\n\t\t\tif (connection.clsComponentName == \"PIN\") {\n\t\t\t\tRsyn::Port rsynCell =\n\t\t\t\t\trsynDesign.findPortByName(connection.clsPinName);\n\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] The primary input/ouput port '\"\n\t\t\t\t\t\t<< connection.clsPinName << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin = rsynCell.getInnerPin();\n\t\t\t\trsynPin.connect(rsynNet);\n\t\t\t} else if (connection.clsComponentName == \"*\") {\n\t\t\t\tfor (Rsyn::Instance inst: rsynDesign.getTopModule().allInstances()) {\n\t\t\t\t\tRsyn::Pin rsynPin = inst.getPinByName(connection.clsPinName);\n\t\t\t\t\tif (!rsynPin) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} // end if\n\t\t\t\t\trsynPin.connect(rsynNet);\n\t\t\t\t} // end for\n\t\t\t} else {\n\t\t\t\tRsyn::Cell rsynCell = rsynDesign.findCellByName(connection.clsComponentName);\n\t\t\t\tif (!rsynCell) {\n\t\t\t\t\tstd::cout << \"[ERROR] Cell '\"\n\t\t\t\t\t\t<< connection.clsComponentName << \"' not found.\\n\";\n\t\t\t\t\texit(1);\n\t\t\t\t} // end if\n\n\t\t\t\tRsyn::Pin rsynPin = rsynCell.getPinByName(connection.clsPinName);\n\t\t\t\trsynPin.connect(rsynNet);\n\t\t\t} // end else\n\t\t} // end for\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n"
  },
  {
    "path": "rsyn/src/rsyn/io/reader/PopulateRsyn.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PopulateRsyn.h\n * Author: jucemar\n *\n * Created on 18 de Fevereiro de 2017, 15:21\n */\n\n#ifndef RSYN_POPULATERSYN_H\n#define RSYN_POPULATERSYN_H\n#include \"rsyn/phy/util/DefDescriptors.h\"\n#include \"rsyn/phy/util/LefDescriptors.h\"\n#include \"rsyn/core/Rsyn.h\"\n#include \"rsyn/io/legacy/PlacerInternals.h\"\n#include \"rsyn/io/legacy/Legacy.h\"\n\nnamespace Rsyn {\n\nclass PopulateRsyn {\npublic:\n\n\tPopulateRsyn() = default;\n\tPopulateRsyn(const PopulateRsyn& orig) = default;\n\tvirtual ~PopulateRsyn() = default;\nprotected:\n\tvirtual void populateRsynLibraryFromLef(\n\t\tconst LefDscp &lefDscp,\n\t\tRsyn::Design rsynDesign);\n\n\tvirtual void populateRsynNetlistFromVerilog(\n\t\tconst Legacy::Design &verilogDesign,\n\t\tRsyn::Design rsynDesign);\n\n\tvirtual void populateRsyn(\n\t\tconst LefDscp &lefDscp,\n\t\tconst DefDscp &defDscp,\n\t\tconst Legacy::Design &verilogDesign,\n\t\tRsyn::Design rsynDesign);\n\n\tvirtual void populateRsyn(\n\t\tconst LefDscp &lefDscp,\n\t\tconst DefDscp &defDscp,\n\t\tRsyn::Design rsynDesign);\n\n};\n\n} // end namespace \n#endif /* RSYN_POPULATERSYN_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/ispd18/Guide.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   Guide.h\n * Author: jucemar\n *\n * Created on 21 de Dezembro de 2016, 17:58\n */\n\n#ifndef ISPD18_GUIDE\n#define ISPD18_GUIDE\n\n#include <vector>\n#include <Rsyn/PhysicalDesign>\n\nnamespace Rsyn {\n\nclass LayerGuide {\n\tfriend class RoutingGuide;\n\tfriend class NetGuide;\nprotected:\n\tRsyn::PhysicalLayer  clsPhLayer;\n\tBounds clsBounds;\n        int clsId;\npublic:\n\tLayerGuide() = default;\n\tconst Bounds & getBounds() const { \n\t\treturn clsBounds;\n\t} // end method \n\tRsyn::PhysicalLayer getLayer() const {\n\t\treturn clsPhLayer;\n\t} // end method \n        int getId() const \n        {\n            return clsId;\n        }\n        void setBounds(Bounds bounds) {\n            clsBounds = bounds;\n        } // end method \n        void setLayer(Rsyn::PhysicalLayer layer) {\n            clsPhLayer = layer;\n        } // end method \n        void setId(int id)\n        {\n            clsId = id;\n        }//end method \n}; // end class\n\nclass NetGuide {\n\tfriend class RoutingGuide;\nprotected:\n\tstd::vector<LayerGuide> clsLayerGuides;\npublic:\n\tNetGuide() = default;\n        const LayerGuide& getGuide(int id) const { \n            if(id > clsLayerGuides.size())\n            {\n                std::cout << \"Invalid access to net guide\";\n                std::cout << \"layer guide vector size is: \" << clsLayerGuides.size()\n                        << \", index is: \" << id << std::endl;\n                getchar();\n            }//\n            return clsLayerGuides[id];\n\t} // end method \n\tconst std::vector<LayerGuide> & allLayerGuides() const { \n\t\treturn clsLayerGuides;\n\t} // end method \n        \n        void setLayerGuides(std::vector<LayerGuide> guides) {\n            clsLayerGuides = guides;\n        }\n}; // end class \n\n} // end namespace \n\n\n#endif /* ISPD18_ROUTINGGUIDE */"
  },
  {
    "path": "rsyn/src/rsyn/ispd18/RoutingGuide.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   RoutingGuide.cpp\n * Author: jucemar\n *\n * Created on 21 de Dezembro de 2016, 17:47\n */\n\n#include \"RoutingGuide.h\"\n#include <Rsyn/PhysicalDesign>\n\nnamespace Rsyn {\n\nvoid RoutingGuide::start(const Rsyn::Json &params) {\n\tif(clsInitialized)\n\t\treturn;\n\tclsDesign = clsSession.getDesign();\n\tclsModule = clsSession.getTopModule();\n\tclsPhDesign = clsSession.getPhysicalDesign();\n\n\tclsGuides = clsDesign.createAttribute();\n\n\tclsInitialized = true;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid RoutingGuide::stop() {\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid RoutingGuide::loadGuides(const GuideDscp & dscp) {\n\tfor (const GuideNetDscp & netDscp : dscp.clsNetGuides) {\n\t\tRsyn::Net net = clsDesign.findNetByName(netDscp.clsNetName);\n\t\tif (net) {\n                        int id = 0;\n\t\t\tNetGuide & netGuide = clsGuides[net];\n\t\t\tstd::vector<LayerGuide> & layerGuides= netGuide.clsLayerGuides;\n\t\t\tlayerGuides.reserve(netDscp.clsLayerDscps.size());\n\t\t\tfor (const GuideLayerDscp & layerDscp : netDscp.clsLayerDscps) {\n\t\t\t\tlayerGuides.push_back(LayerGuide());\n\t\t\t\tLayerGuide & layerGuide = layerGuides.back();\n                                layerGuide.clsId = id++;\n\t\t\t\tlayerGuide.clsBounds = layerDscp.clsLayerGuide;\n\t\t\t\tlayerGuide.clsPhLayer = clsPhDesign.getPhysicalLayerByName(layerDscp.clsLayer);\n\t\t\t} // end for\n\t\t} else {\n\t\t\tstd::cout << \"WARNING: Net '\" << netDscp.clsNetName << \"' does not exist and the routing guide is being ignored.\\n\";\n\t\t} // end else\n\t} // end for \n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/ispd18/RoutingGuide.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   RoutingGuide.h\n * Author: jucemar\n *\n * Created on 21 de Dezembro de 2016, 17:47\n */\n\n#ifndef RSYN_ISPD18_ROUTING_GUIDE_H\n#define RSYN_ISPD18_ROUTING_GUIDE_H\n\n#include \"rsyn/session/Service.h\"\n#include <Rsyn/Session>\n#include \"rsyn/ispd18/Guide.h\"\n#include \"rsyn/io/parser/guide-ispd18/GuideDescriptor.h\"\n\nnamespace Rsyn {\n\nclass RoutingGuide : public Rsyn::Service {\nprotected:\n\tRsyn::Session clsSession;\n\tRsyn::Design clsDesign;\n\tRsyn::Module clsModule;\n\tRsyn::PhysicalDesign clsPhDesign;\n\tRsyn::Attribute<Rsyn::Net, Rsyn::NetGuide> clsGuides;\n\tbool clsInitialized  = false;\npublic:\n\tRoutingGuide() = default;\n\tvoid start(const Rsyn::Json &params);\n\tvoid stop();\n\t\n\tvoid loadGuides(const GuideDscp & dscp);\n\t\n\tconst NetGuide & getGuide(Rsyn::Net net) const {\n\t\treturn clsGuides[net];\n\t}\n        \n        void updateGuide(Rsyn::Net net, Rsyn::NetGuide guide) {\n            clsGuides[net] = guide;\n        }\n}; // end class \n\n} // end namespace \n\n\n#endif /* ISPD18_ROUTINGGUIDE */"
  },
  {
    "path": "rsyn/src/rsyn/phy/PhysicalDesign.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICAL_DESIGN_H\n#define RSYN_PHYSICAL_DESIGN_H\n\n#include <string>\n#include <vector>\n#include <unordered_map>\n#include <map>\n#include <iostream>\n#include <stddef.h>\n#include <algorithm>\n#include <limits>\n\n#include <Rsyn/Point>\n#include <Rsyn/Rect>\n#include <Rsyn/Polygon>\n\n#include \"rsyn/core/Rsyn.h\"\n#include \"rsyn/util/Bounds.h\"\n#include \"rsyn/util/FloatingPoint.h\"\n#include \"rsyn/util/dbu.h\"\n#include \"rsyn/util/Proxy.h\"\n#include \"rsyn/phy/util/DefDescriptors.h\"\n#include \"rsyn/phy/util/LefDescriptors.h\"\n#include \"rsyn/phy/util/PhysicalTypes.h\"\n#include \"rsyn/phy/util/PhysicalUtil.h\"\n#include \"rsyn/phy/util/PhysicalTransform.h\"\n#include \"rsyn/util/Exception.h\"\n#include \"rsyn/util/Json.h\"\n\nnamespace Rsyn {\n\n// std::numeric_limts<PhysicalIndex>::max() reserved to invalid initialization object.\ntypedef std::uint32_t PhysicalIndex;\nstatic PhysicalIndex INVALID_PHYSICAL_INDEX = std::numeric_limits<PhysicalIndex>::max();\n\nclass PhysicalObject;\n\nclass PhysicalRoutingPointData;\nclass PhysicalDieData;\nclass PhysicalGCellData;\nclass PhysicalLayerData;\nclass PhysicalSpacingData;\nclass PhysicalSpacingRuleData;\nclass PhysicalSpacingTableData;\nclass PhysicalSiteData;\nclass PhysicalRowData;\nclass PhysicalObstacleData;\nclass PhysicalPinLayerData;\nclass PhysicalPinGeometryData;\nclass PhysicalLibraryPinData;\nclass PhysicalLibraryCellData;\nclass PhysicalPinData;\nclass PhysicalNetData;\nclass PhysicalInstanceData;\nclass PhysicalRegionData;\nclass PhysicalGroupData;\nclass PhysicalViaData;\nclass ViaGeometryData;\nclass ViaRuleData;\nclass PhysicalSpecialWireData;\nclass PhysicalSpecialNetData;\nclass PhysicalTracksData;\nclass PhysicalRoutingGridData;\nclass LayerViaManagerData;\nclass PhysicalDesignData;\n\nclass PhysicalRoutingPoint;\nclass PhysicalDie;\nclass PhysicalGCell;\nclass PhysicalLayer;\nclass PhysicalSpacing;\nclass PhysicalSite;\nclass PhysicalRow;\nclass PhysicalObstacle;\nclass PhysicalPinLayer;\nclass PhysicalPinGeometry;\nclass PhysicalLibraryPin;\nclass PhysicalLibraryCell;\nclass PhysicalPin;\nclass PhysicalNet;\nclass PhysicalInstance;\nclass PhysicalPort;\nclass PhysicalCell;\nclass PhysicalModule;\nclass PhysicalRegion;\nclass PhysicalGroup;\nclass PhysicalVia;\nclass PhysicalViaGeometry;\nclass PhysicalViaRuleBase;\nclass PhysicalViaRule;\nclass PhysicalViaRuleGenerate;\nclass PhysicalSpecialWire;\nclass PhysicalSpecialNet;\nclass PhysicalTracks;\nclass PhysicalRoutingGrid;\nclass LayerViaManager;\nclass PhysicalDesign;\n\nclass PhysicalAttributeInitializer;\ntemplate<typename DefaultPhysicalValueType>\nclass PhysicalAttributeInitializerWithDefaultValue;\n\nclass PhysicalDesignObserver;\nclass PhysicalRouting;\n\n} // end namespace \n\n// Object's Declarations (Proxies)\n#include \"rsyn/phy/obj/decl/PhysicalRoutingPoint.h\"\n#include \"rsyn/phy/obj/decl/PhysicalDie.h\"\n#include \"rsyn/phy/obj/decl/PhysicalGCell.h\"\n#include \"rsyn/phy/obj/decl/PhysicalLayer.h\"\n#include \"rsyn/phy/obj/decl/PhysicalSpacing.h\"\n#include \"rsyn/phy/obj/decl/PhysicalSite.h\"\n#include \"rsyn/phy/obj/decl/PhysicalRow.h\"\n#include \"rsyn/phy/obj/decl/PhysicalPinLayer.h\"\n#include \"rsyn/phy/obj/decl/PhysicalPinGeometry.h\"\n#include \"rsyn/phy/obj/decl/PhysicalObstacle.h\"\n#include \"rsyn/phy/obj/decl/PhysicalLibraryPin.h\"\n#include \"rsyn/phy/obj/decl/PhysicalLibraryCell.h\"\n#include \"rsyn/phy/obj/decl/PhysicalPin.h\"\n#include \"rsyn/phy/obj/decl/PhysicalNet.h\"\n#include \"rsyn/phy/obj/decl/PhysicalInstance.h\"\n#include \"rsyn/phy/obj/decl/PhysicalCell.h\"\n#include \"rsyn/phy/obj/decl/PhysicalModule.h\"\n#include \"rsyn/phy/obj/decl/PhysicalPort.h\"\n#include \"rsyn/phy/obj/decl/PhysicalRegion.h\"\n#include \"rsyn/phy/obj/decl/PhysicalGroup.h\"\n#include \"rsyn/phy/obj/decl/PhysicalVia.h\"\n#include \"rsyn/phy/obj/decl/PhysicalViaGeometry.h\"\n#include \"rsyn/phy/obj/decl/PhysicalViaRuleBase.h\"\n#include \"rsyn/phy/obj/decl/PhysicalViaRule.h\"\n#include \"rsyn/phy/obj/decl/PhysicalViaRuleGenerate.h\"\n#include \"rsyn/phy/obj/decl/PhysicalSpecialWire.h\"\n#include \"rsyn/phy/obj/decl/PhysicalSpecialNet.h\"\n#include \"rsyn/phy/obj/decl/PhysicalTracks.h\"\n#include \"rsyn/phy/obj/decl/PhysicalRoutingGrid.h\"\n#include \"rsyn/phy/obj/decl/LayerViaManager.h\"\n#include \"rsyn/phy/obj/decl/PhysicalDesign.h\"\n\n// Routing\n#include \"rsyn/phy/PhysicalRouting.h\"\n\n// Object's Data\n#include \"rsyn/phy/obj/data/PhysicalObject.h\"\n#include \"rsyn/phy/obj/data/PhysicalRoutingPointData.h\"\n#include \"rsyn/phy/obj/data/PhysicalDieData.h\"\n#include \"rsyn/phy/obj/data/PhysicalGCellData.h\"\n#include \"rsyn/phy/obj/data/PhysicalLayerData.h\"\n#include \"rsyn/phy/obj/data/PhysicalSpacingData.h\"\n#include \"rsyn/phy/obj/data/PhysicalSpacingRuleData.h\"\n#include \"rsyn/phy/obj/data/PhysicalSpacingTableData.h\"\n#include \"rsyn/phy/obj/data/PhysicalSiteData.h\"\n#include \"rsyn/phy/obj/data/PhysicalRowData.h\"\n#include \"rsyn/phy/obj/data/PhysicalPinLayerData.h\"\n#include \"rsyn/phy/obj/data/PhysicalPinGeometryData.h\"\n#include \"rsyn/phy/obj/data/PhysicalObstacleData.h\"\n#include \"rsyn/phy/obj/data/PhysicalLibraryPinData.h\"\n#include \"rsyn/phy/obj/data/PhysicalLibraryCellData.h\"\n#include \"rsyn/phy/obj/data/PhysicalPinData.h\"\n#include \"rsyn/phy/obj/data/PhysicalNetData.h\"\n#include \"rsyn/phy/obj/data/PhysicalInstanceData.h\"\n#include \"rsyn/phy/obj/data/PhysicalRegionData.h\"\n#include \"rsyn/phy/obj/data/PhysicalGroupData.h\"\n#include \"rsyn/phy/obj/data/PhysicalViaData.h\"\n#include \"rsyn/phy/obj/data/ViaGeometryData.h\"\n#include \"rsyn/phy/obj/data/ViaRuleData.h\"\n#include \"rsyn/phy/obj/data/PhysicalSpecialWireData.h\"\n#include \"rsyn/phy/obj/data/PhysicalSpecialNetData.h\"\n#include \"rsyn/phy/obj/data/PhysicalTracksData.h\"\n#include \"rsyn/phy/obj/data/PhysicalRoutingGridData.h\"\n#include \"rsyn/phy/obj/data/LayerViaManagerData.h\"\n#include \"rsyn/phy/obj/data/PhysicalDesign.h\"\n\n// Physical Infrastructure\n#include \"rsyn/phy/infra/PhysicalAttribute.h\"\n#include \"rsyn/phy/infra/PhysicalObserver.h\"\n\n// Object's Implementations\n#include \"rsyn/phy/obj/impl/PhysicalRoutingPoint.h\"\n#include \"rsyn/phy/obj/impl/PhysicalLayer.h\"\n#include \"rsyn/phy/obj/impl/PhysicalDie.h\"\n#include \"rsyn/phy/obj/impl/PhysicalGCell.h\"\n#include \"rsyn/phy/obj/impl/PhysicalSpacing.h\"\n#include \"rsyn/phy/obj/impl/PhysicalSite.h\"\n#include \"rsyn/phy/obj/impl/PhysicalRow.h\"\n#include \"rsyn/phy/obj/impl/PhysicalPinLayer.h\"\n#include \"rsyn/phy/obj/impl/PhysicalPinGeometry.h\"\n#include \"rsyn/phy/obj/impl/PhysicalObstacle.h\"\n#include \"rsyn/phy/obj/impl/PhysicalLibraryPin.h\"\n#include \"rsyn/phy/obj/impl/PhysicalLibraryCell.h\"\n#include \"rsyn/phy/obj/impl/PhysicalPin.h\"\n#include \"rsyn/phy/obj/impl/PhysicalNet.h\"\n#include \"rsyn/phy/obj/impl/PhysicalInstance.h\"\n#include \"rsyn/phy/obj/impl/PhysicalPort.h\"\n#include \"rsyn/phy/obj/impl/PhysicalCell.h\"\n#include \"rsyn/phy/obj/impl/PhysicalModule.h\"\n#include \"rsyn/phy/obj/impl/PhysicalRegion.h\"\n#include \"rsyn/phy/obj/impl/PhysicalGroup.h\"\n#include \"rsyn/phy/obj/impl/PhysicalVia.h\"\n#include \"rsyn/phy/obj/impl/PhysicalViaGeometry.h\"\n#include \"rsyn/phy/obj/impl/PhysicalViaRuleBase.h\"\n#include \"rsyn/phy/obj/impl/PhysicalViaRule.h\"\n#include \"rsyn/phy/obj/impl/PhysicalViaRuleGenerate.h\"\n#include \"rsyn/phy/obj/impl/PhysicalSpecialWire.h\"\n#include \"rsyn/phy/obj/impl/PhysicalSpecialNet.h\"\n#include \"rsyn/phy/obj/impl/PhysicalTracks.h\"\n#include \"rsyn/phy/obj/impl/PhysicalRoutingGrid.h\"\n#include \"rsyn/phy/obj/impl/LayerViaManager.h\"\n#include \"rsyn/phy/obj/impl/PhysicalDesign.h\"\n\n#endif /* PHYSICALDESIGN_PHYSICALDESIGN__H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/PhysicalRouting.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#include <Rsyn/PhysicalDesign>\n#include \"PhysicalRouting.h\"\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n// PhysicalRoutingWire\n// -----------------------------------------------------------------------------\n\nPhysicalRoutingWire::PhysicalRoutingWire(const PhysicalRoutingWire & wire) {\n\tclsLayer = wire.clsLayer;\n\tclsPoints = wire.clsPoints;\n\tclsSourceExtension = wire.clsSourceExtension;\n\tclsTargetExtension = wire.clsTargetExtension;\n\tclsWidth = wire.clsWidth;\n} // end constructor \n\n// -----------------------------------------------------------------------------\n\nDBUxy\nPhysicalRoutingWire::getExtendedSourcePosition() const {\n\tconst int numPoints = getNumPoints();\n\tif (numPoints == 0) {\n\t\treturn DBUxy(0, 0);\n\t} else if (numPoints == 1) {\n\t\treturn clsPoints[0];\n\t} else {\n\t\treturn getExtendedPosition(clsPoints[0], clsPoints[1], getSourceExtension());\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nDBUxy\nPhysicalRoutingWire::getExtendedTargetPosition() const {\n\tconst int numPoints = getNumPoints();\n\tif (numPoints == 0) {\n\t\treturn DBUxy(0, 0);\n\t} else if (numPoints == 1) {\n\t\treturn clsPoints[0];\n\t} else {\n\t\treturn getExtendedPosition(clsPoints[numPoints - 1], clsPoints[numPoints - 2], getTargetExtension());\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nDBU\nPhysicalRoutingWire::getSourceExtension() const {\n\treturn clsSourceExtension == DefaultRoutingWireExtension?\n\t\tgetLayer().getWidth() / 2 : clsSourceExtension;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nDBU\nPhysicalRoutingWire::getTargetExtension() const {\n\treturn clsTargetExtension == DefaultRoutingWireExtension?\n\t\tgetLayer().getWidth() / 2 : clsTargetExtension;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nstd::vector<DBUxy>\nPhysicalRoutingWire::getPoints(const bool useWireExtension) const {\n\tstd::vector<DBUxy> points = clsPoints;\n\tif (useWireExtension && getNumPoints() >= 1) {\n\t\tpoints.front() = getExtendedSourcePosition();\n\t\tpoints.back() = getExtendedTargetPosition();\n\t} // end method\n\treturn points;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingWire::hasNonDefaultWidth() const {\n\treturn clsWidth != DefaultRoutingWireWidth && clsWidth != clsLayer.getWidth();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingWire::hasNonDefaultSourceExtension() const {\n\treturn clsSourceExtension != DefaultRoutingWireExtension;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingWire::hasNonDefaultTargetExtension() const {\n\treturn clsTargetExtension != DefaultRoutingWireExtension;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalRoutingWire::getLayer() const {\n\treturn clsLayer;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nDBU \nPhysicalRoutingWire::getWidth() const {\n\treturn clsWidth == DefaultRoutingWireWidth?\n\t\tgetLayer().getWidth() : clsWidth;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nDBUxy\nPhysicalRoutingWire::getExtendedPosition(\n\t\tconst DBUxy p0,\n\t\tconst DBUxy p1,\n\t\tconst DBU extension\n) const {\n\tDBUxy pos = p0;\n\n\tconst DBUxy d = p1 - p0;\n\tconst bool horizontal = d.x != 0;\n\tconst bool vertical = d.y != 0;\n\tif (horizontal && !vertical) {\n\t\t// Horizontal\n\t\tif (d.x > 0) {\n\t\t\t// p0.x < p1.x\n\t\t\tpos.x -= extension;\n\t\t} else {\n\t\t\t// p0.x > p1.x\n\t\t\tpos.x += extension;\n\t\t} // end else\n\t} else if (vertical && !horizontal) {\n\t\t// Vertical\n\t\tif (d.y > 0) {\n\t\t\t// p0.y < p1.y\n\t\t\tpos.y -= extension;\n\t\t} else {\n\t\t\t// p0.y > p1.y\n\t\t\tpos.y += extension;\n\t\t} // end else\n\t} // end else-if\n\n\treturn pos;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingWire::isValid() const {\n\tif (!getLayer() || getLayer().getType() != Rsyn::ROUTING) return false;\n\tif (getNumPoints() < 2) return false;\n\treturn true;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRoutingWire::addRoutingPoint(const DBUxy p) {\n\tclsPoints.push_back(p);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRoutingWire::setLayer(Rsyn::PhysicalLayer layer) {\n\tclsLayer = layer;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRoutingWire::clear() {\n\t*this = PhysicalRoutingWire();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingWire::convertToPolygon(Rsyn::Polygon &polygon) const {\n\tif (isValid()) {\n\t\tpolygon = Polygon::createFromLineString(getPoints(true), getWidth());\n\t\treturn true;\n\t} else {\n\t\tpolygon.clear();\n\t\treturn false;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n// PhysicalRoutingVia\n// -----------------------------------------------------------------------------\n\nPhysicalRoutingVia::PhysicalRoutingVia(const PhysicalRoutingVia & via) {\n\tclsPosition = via.clsPosition;\n\tclsVia = via.clsVia;\n} // end constructor \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalVia\nPhysicalRoutingVia::getVia() const {\n\treturn clsVia;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalRoutingVia::getTopLayer() const {\n\treturn clsVia.getTopLayer();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalRoutingVia::getCutLayer() const {\n\treturn clsVia.getCutLayer();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalRoutingVia::getBottomLayer() const {\n\treturn clsVia.getBottomLayer();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRoutingVia::setVia(Rsyn::PhysicalVia via) {\n\tclsVia = via;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingVia::isValid() const {\n\treturn clsVia != nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n// PhysicalRoutingRect\n// -----------------------------------------------------------------------------\n\nPhysicalRoutingRect::PhysicalRoutingRect(const PhysicalRoutingRect & rect) {\n\tclsLayer = rect.clsLayer;\n\tclsRect = rect.clsRect;\n} // end constructor\n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalRoutingRect::getLayer() const {\n\treturn clsLayer;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nPhysicalRoutingRect::isValid() const {\n\treturn clsLayer;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRoutingRect::setLayer(Rsyn::PhysicalLayer layer) {\n\tclsLayer = layer;\n} // end method\n\n// -----------------------------------------------------------------------------\n// PhysicalRouting\n// -----------------------------------------------------------------------------\n\nPhysicalRouting::PhysicalRouting(const PhysicalRouting & routing) {\n\tclsWires = routing.clsWires;\n\tclsVias = routing.clsVias;\n\tclsRects = routing.clsRects;\n} // end constructor \n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addWire(const PhysicalRoutingWire &wire) {\n\tassert(wire.isValid());\n\tclsWires.push_back(wire);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addWire(\n\t\tRsyn::PhysicalLayer layer,\n\t\tconst DBUxy source,\n\t\tconst DBUxy target,\n\t\tconst DBU width,\n\t\tconst DBU sourceExtension,\n\t\tconst DBU targetExtension\n) {\n\tPhysicalRoutingWire wire;\n\twire.setLayer(layer);\n\twire.addRoutingPoint(source);\n\twire.addRoutingPoint(target);\n\twire.setWidth(width);\n\twire.setSourceExtension(sourceExtension);\n\twire.setTargetExtension(targetExtension);\n\taddWire(wire);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addWire(\n\t\tRsyn::PhysicalLayer layer,\n\t\tconst std::vector<DBUxy> &points,\n\t\tconst DBU width,\n\t\tconst DBU sourceExtension,\n\t\tconst DBU targetExtension\n) {\n\tPhysicalRoutingWire wire;\n\twire.setLayer(layer);\n\tfor (const DBUxy point : points)\n\t\twire.addRoutingPoint(point);\n\twire.setWidth(width);\n\twire.setSourceExtension(sourceExtension);\n\twire.setTargetExtension(targetExtension);\n\taddWire(wire);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addVia(\n\t\tconst PhysicalRoutingVia &via\n) {\n\tclsVias.push_back(via);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addVia(\n\t\tRsyn::PhysicalVia physicalVia,\n\t\tconst DBUxy position\n) {\n\tPhysicalRoutingVia via;\n\tvia.setVia(physicalVia);\n\tvia.setPosition(position);\n\taddVia(via);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addRect(\n\t\tconst PhysicalRoutingRect &rect\n) {\n\tclsRects.push_back(rect);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nPhysicalRouting::addRect(\n\t\tRsyn::PhysicalLayer layer,\n\t\tconst Bounds &rect\n) {\n\tPhysicalRoutingRect patch;\n\tpatch.setLayer(layer);\n\tpatch.setRect(rect);\n\taddRect(patch);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool PhysicalRouting::isValid() const {\n\tfor (const PhysicalRoutingWire &wire : allWires()) {\n\t\tif (!wire.isValid()) {\n\t\t\treturn false;\n\t\t} // end if\n\t} // end for\n\n\tfor (const PhysicalRoutingVia &via : allVias()) {\n\t\tif (!via.isValid()) {\n\t\t\treturn false;\n\t\t} // end if\n\t} // end for\n\n\treturn !(clsWires.empty() && clsVias.empty());\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool PhysicalRouting::isEmpty() const {\n\treturn clsWires.empty() && clsVias.empty() && clsRects.empty();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid \nPhysicalRouting::clear() {\n\tclsWires.clear();\n\tclsVias.clear();\n\tclsRects.clear();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nDBU PhysicalRouting::computeWirelength() const {\n\tDBU wirelength = 0;\n\tfor (Rsyn::PhysicalRoutingWire wire : allWires()) {\n\t\twirelength += DBUxy::computeManhattanDistance(wire.allPoints()[0], wire.allPoints()[1]);\n\t} // end for\n\treturn wirelength;\n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/PhysicalRouting.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICAL_ROUTING_H\n#define RSYN_PHYSICAL_ROUTING_H\n\n#include <vector>\n\n#include \"rsyn/util/dbu.h\"\n#include \"rsyn/util/Bounds.h\"\n\nnamespace Rsyn {\n\nclass PhysicalLayer;\nclass PhysicalVia;\n\nconst DBU DefaultRoutingWireExtension = -1;\nconst DBU DefaultRoutingWireWidth = -1;\n\n// -----------------------------------------------------------------------------\n// PhysicalRoutingWire\n// -----------------------------------------------------------------------------\n\nclass PhysicalRoutingWire {\npublic:\n\tPhysicalRoutingWire() {};\n\tPhysicalRoutingWire(const PhysicalRoutingWire & wire);\n\tint getNumPoints() const {return (int) clsPoints.size();}\n\tDBUxy getExtendedSourcePosition() const;\n\tDBUxy getExtendedTargetPosition() const;\n\n\tDBU getWidth() const;\n\tDBU getSourceExtension() const;\n\tDBU getTargetExtension() const;\n\n\tstd::vector<DBUxy> getPoints(const bool useWireExtension) const;\n\n\tbool hasNonDefaultWidth() const;\n\tbool hasNonDefaultSourceExtension() const;\n\tbool hasNonDefaultTargetExtension() const;\n\n\tRsyn::PhysicalLayer getLayer() const;\n\n\tbool isValid() const;\n\n\tvoid addRoutingPoint(const DBUxy p);\n\n\tvoid setLayer(Rsyn::PhysicalLayer layer);\n\tvoid setWidth(const DBU width) {clsWidth = width;}\n\tvoid setSourceExtension(const DBU extension) {clsSourceExtension = extension;}\n\tvoid setTargetExtension(const DBU extension) {clsTargetExtension = extension;}\n\n\tbool convertToPolygon(Rsyn::Polygon &polygon) const;\n\n\tvoid clear();\n\n\tconst std::vector<DBUxy> &allPoints() const {return clsPoints;}\n\nprivate:\n\n\tDBUxy getExtendedPosition(const DBUxy p0, const DBUxy p1, const DBU extension) const;\n\n\tRsyn::PhysicalLayer clsLayer;\n\tstd::vector<DBUxy> clsPoints;\n\tDBU clsSourceExtension = DefaultRoutingWireExtension;\n\tDBU clsTargetExtension = DefaultRoutingWireExtension;\n\tDBU clsWidth = DefaultRoutingWireWidth;\n}; // end class\n\n// -----------------------------------------------------------------------------\n// PhysicalRoutingVia\n// -----------------------------------------------------------------------------\n\nclass PhysicalRoutingVia {\npublic:\n\tPhysicalRoutingVia(){};\n\tPhysicalRoutingVia(const PhysicalRoutingVia & via);\n\t\n\tRsyn::PhysicalVia getVia() const;\n\n\tRsyn::PhysicalLayer getTopLayer() const;\n\tRsyn::PhysicalLayer getCutLayer() const;\n\tRsyn::PhysicalLayer getBottomLayer() const;\n\n\tDBUxy getPosition() const {return clsPosition;}\n\n\tvoid setPosition(const DBUxy p) {clsPosition = p;}\n\tvoid setVia(Rsyn::PhysicalVia via);\n\n\tbool isValid() const;\n\nprivate:\n\n\tDBUxy clsPosition;\n\tRsyn::PhysicalVia clsVia;\n}; // end class\n\n// -----------------------------------------------------------------------------\n// PhysicalRoutingRect\n// -----------------------------------------------------------------------------\n\nclass PhysicalRoutingRect {\npublic:\n\tPhysicalRoutingRect() {};\n\tPhysicalRoutingRect(const PhysicalRoutingRect & rect);\n\n\tDBU getX() const {return clsRect.getX();}\n\tDBU getY() const { return clsRect.getY(); }\n\tDBU getWidth() const { return clsRect.getWidth(); }\n\tDBU getHeight() const { return clsRect.getHeight(); }\n\n\tconst Bounds &getRect() const {return clsRect;}\n\tRsyn::PhysicalLayer getLayer() const;\n\n\tbool isValid() const;\n\n\tvoid setRect(const Bounds &rect) {clsRect = rect;}\n\tvoid setLayer(Rsyn::PhysicalLayer layer);\n\t\nprivate:\n\n\tBounds clsRect;\n\tRsyn::PhysicalLayer clsLayer;\n}; // end class\n\n// -----------------------------------------------------------------------------\n// PhysicalRouting\n// -----------------------------------------------------------------------------\n\nclass PhysicalRouting {\npublic:\n\t\n\tPhysicalRouting() {}\n\tPhysicalRouting(const PhysicalRouting & routing);\n\t\n\t//! @brief Adds a wire.\n\tvoid\n\taddWire(\n\t\t\tconst PhysicalRoutingWire &wire);\n\n\t//! @brief Adds a wire.\n\tvoid \n\taddWire(\n\t\t\tRsyn::PhysicalLayer layer,\n\t\t\tconst DBUxy source,\n\t\t\tconst DBUxy target,\n\t\t\tconst DBU width = DefaultRoutingWireWidth,\n\t\t\tconst DBU sourceExtension = DefaultRoutingWireExtension,\n\t\t\tconst DBU targetExtension = DefaultRoutingWireExtension);\n\n\t//! @brief Adds a wire.\n\tvoid\n\taddWire(\n\t\t\tRsyn::PhysicalLayer layer,\n\t\t\tconst std::vector<DBUxy> &points,\n\t\t\tconst DBU width = DefaultRoutingWireWidth,\n\t\t\tconst DBU sourceExtension = DefaultRoutingWireExtension,\n\t\t\tconst DBU targetExtension = DefaultRoutingWireExtension);\n\n\t//! @brief Adds a via.\n\tvoid\n\taddVia(\n\t\t\tconst PhysicalRoutingVia &via);\n\n\t//! @brief Adds a via.\n\tvoid\n\taddVia(\n\t\t\tRsyn::PhysicalVia via,\n\t\t\tconst DBUxy position);\n\n\t//! @brief Adds a patch rectangle.\n\tvoid\n\taddRect(\n\t\t\tconst PhysicalRoutingRect &rect);\n\n\t//! @brief Adds a patch rectangle.\n\tvoid\n\taddRect(\n\t\t\tRsyn::PhysicalLayer layer,\n\t\t\tconst Bounds &rect);\n\n\t//! @brief Checks if this physical routing is valid by visiting all routing\n\t//! elements (e.g. wires and vias) and checking if they are valid.\n\tbool isValid() const;\n\n\t//! @brief Checks if this physical routing is empty (i.e. no wires, vias, \n\t//! etc.)\n\tbool isEmpty() const;\n\n\t//! @brief Iterates over all wires.\n\tconst std::vector<PhysicalRoutingWire> &\n\tallWires() const {return clsWires;}\n\n\t//! @brief Iterates over all vias.\n\tconst std::vector<PhysicalRoutingVia> &\n\tallVias() const {return clsVias;}\n\n\t//! @brief Iterates over all patch rectangles.\n\tconst std::vector<PhysicalRoutingRect> &\n\tallRects() const {return clsRects;}\n\n\t//! @brief Removes all the wires, vias and rects.\n\tvoid clear();\n        \n        //! @brief Computes net routed wirelength\n        DBU computeWirelength() const;\n\t\nprivate:\n\n\tstd::vector<PhysicalRoutingWire> clsWires;\n\tstd::vector<PhysicalRoutingVia> clsVias;\n\tstd::vector<PhysicalRoutingRect> clsRects;\n\n}; // end class\n\n} // end namespace\n\n\n#endif /* PHYSICALROUTING_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/PhysicalService.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#include <Rsyn/Session>\n#include \"rsyn/phy/PhysicalService.h\"\n\nnamespace Rsyn {\n\nvoid PhysicalService::start(const Rsyn::Json &params) {\n\tRsyn::Session session;\n\t\n\tclsDesign = session.getDesign();\n\tclsPhysicalDesign.initPhysicalDesign(clsDesign, params);\n\t// Observe changes in the design.\n\tclsDesign.registerObserver(this);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalService::stop() {\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalService::onPostCellRemap(Rsyn::Cell cell, Rsyn::LibraryCell oldLibraryCell) {\n\tPhysicalDesignData *data = clsPhysicalDesign.data;\n\n\tPhysicalLibraryCellData &oldPhysicalLibraryCell =\n\t\t\tdata->clsPhysicalLibraryCells[oldLibraryCell];\n\tPhysicalLibraryCellData &newPhysicalLibraryCell =\n\t\t\tdata->clsPhysicalLibraryCells[cell.getLibraryCell()];\n\tPhysicalInstanceData &physicalCell = data->clsPhysicalInstances[cell];\n\n\tconst DBU newWidth = newPhysicalLibraryCell.clsSize[X];\n\tconst DBU newHeight = newPhysicalLibraryCell.clsSize[Y];\n\n\tconst DBU oldWidth = oldPhysicalLibraryCell.clsSize[X];\n\tconst DBU oldHeight = oldPhysicalLibraryCell.clsSize[Y];\n\n\t// Update physical cell size.\n\tphysicalCell.clsInstance->clsBounds.setLength(X, newWidth);\n\tphysicalCell.clsInstance->clsBounds.setLength(Y, newHeight);\n\n\t// Update area.\n\tconst DBU oldArea = oldWidth * oldHeight;\n\tif (physicalCell.clsBlock)\n\t\tdata->clsTotalAreas[PHYSICAL_BLOCK] -= oldArea;\n\tif (cell.isFixed()) {\n\t\tif (cell.isPort())\n\t\t\tdata->clsTotalAreas[PHYSICAL_PORT] -= oldArea;\n\t\telse\n\t\t\tdata->clsTotalAreas[PHYSICAL_FIXED] -= oldArea;\n\t} else {\n\t\tdata->clsTotalAreas[PHYSICAL_MOVABLE] -= oldArea;\n\t} // end if-else\n\n\tconst DBU newArea = newWidth * newHeight;\n\tif (physicalCell.clsBlock)\n\t\tdata->clsTotalAreas[PHYSICAL_BLOCK] += newArea;\n\tif (cell.isFixed()) {\n\t\tif (cell.isPort())\n\t\t\tdata->clsTotalAreas[PHYSICAL_PORT] += newArea;\n\t\telse\n\t\t\tdata->clsTotalAreas[PHYSICAL_FIXED] += newArea;\n\t} else {\n\t\tdata->clsTotalAreas[PHYSICAL_MOVABLE] += newArea;\n\t} // end if-else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalService::onPostInstanceCreate(Rsyn::Instance instance) {\n\tif (instance.getType() != Rsyn::CELL) {\n\t\tstd::cout << \"[WARNING] Created instance is not a cell.\\n\";\n\t\treturn;\t\t\n\t} // end if\n\n\tPhysicalDesignData *data = clsPhysicalDesign.data;\n\t\n\tPhysicalLibraryCellData &physicalLibraryCell =\n\t\t\tdata->clsPhysicalLibraryCells[instance.asCell().getLibraryCell()];\t\n\n\tPhysicalInstanceData &physicalCell = data->clsPhysicalInstances[instance.asCell()];\n\tphysicalCell.clsInstance = instance;\n\tRsyn::InstanceTag tag = clsDesign.getTag(instance);\n\ttag.setFixed(false);\n\ttag.setMacroBlock(!strcmp(physicalLibraryCell.clsMacro->macroClass(), \"BLOCK\"));\n\tphysicalCell.clsHasLayerBounds = false;\n\tphysicalCell.clsPlaced = true;\n\tphysicalCell.clsBlock = false;\n\tphysicalCell.clsInstance->clsOrientation = PhysicalOrientation::ORIENTATION_N;\n\t\n\tconst DBUxy dieOrigin = data->clsPhysicalDie.clsBounds[LOWER];\n\tphysicalCell.clsInitialPos = DBUxy(dieOrigin);\n\t\n\tconst DBU width = physicalLibraryCell.clsSize[X];\n\tconst DBU height = physicalLibraryCell.clsSize[Y];\n\t\n\tphysicalCell.clsInstance->clsBounds.updatePoints(\n\t\tdieOrigin.x, dieOrigin.y, dieOrigin.x + width, dieOrigin.y + height);\n\t\n\tDBU area = width * height;\n\tdata->clsTotalAreas[PHYSICAL_MOVABLE] += area;\n} // end method\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/PhysicalService.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICAL_SERVICE_H\n#define RSYN_PHYSICAL_SERVICE_H\n\n#include \"rsyn/session/Service.h\"\n#include <Rsyn/PhysicalDesign>\n\nnamespace Rsyn {\n\nclass PhysicalService : public Rsyn::Service, public DesignObserver {\nprivate:\n\t\n\tRsyn::PhysicalDesign clsPhysicalDesign;\n\tRsyn::Design clsDesign;\n\t\npublic:\n\t\n\t//! @brief Start method to the Rsyn::PhysicalDesign service\n\tvirtual void start(const Rsyn::Json &params);\n\t\n\t//! @brief Stop method to the Rsyn::PhysicalDesign service\n\tvirtual void stop();\n\t\n\t//! @brief Getting the Rsyn::PhysicalDesign object.\n\tRsyn::PhysicalDesign getPhysicalDesign() { return clsPhysicalDesign; }\n\t\n\t// Events\n\tvirtual void\n\tonPostCellRemap(Rsyn::Cell cell, Rsyn::LibraryCell oldLibraryCell) override;\n\t\n\tvirtual void \n\tonPostInstanceCreate(Rsyn::Instance instance) override;\n}; // end class\n\n} // end namespace\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/phy/infra/PhysicalAttribute.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICALDESIGN_ATTRIBUTE_H\n#define RSYN_PHYSICALDESIGN_ATTRIBUTE_H\n\n#include <deque>\n\nnamespace Rsyn {\n\nclass PhysicalAttributeInitializer {\n\tfriend class PhysicalDesign;\nprivate:\n\tPhysicalDesign design;\n\n\tPhysicalAttributeInitializer(PhysicalDesign design) : design(design) {\n\t};\npublic:\n\n\tPhysicalDesign getPhysicalDesign() {\n\t\treturn design;\n\t} // end method \n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename PhysicalDefaultValueType>\nclass PhysicalAttributeInitializerWithDefaultValue {\n\tfriend class PhysicalDesign;\nprivate:\n\tPhysicalDesign design;\n\tPhysicalDefaultValueType defaultValue;\n\n\tPhysicalAttributeInitializerWithDefaultValue(PhysicalDesign design, PhysicalDefaultValueType defaultValue)\n\t: design(design), defaultValue(defaultValue) {\n\t};\npublic:\n\n\tPhysicalDesign getPhysicalDesign() {\n\t\treturn design;\n\t}\n\n\tPhysicalDefaultValueType &getDefaultValue() {\n\t\treturn defaultValue;\n\t}\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename _PhysicalObject, typename _PhysicalObjectExtension>\nclass PhysicalAttributeImplementation;\n\n// -----------------------------------------------------------------------------\n\ntemplate <typename RsynPhysicalObject, typename RsynPhysicalObjectExtension>\nclass PhysicalAttribute : public std::shared_ptr<PhysicalAttributeImplementation<RsynPhysicalObject, RsynPhysicalObjectExtension>>\n{\n\tpublic:\n\n\tPhysicalAttribute() {\n\t}\n\n\tPhysicalAttribute(PhysicalAttributeInitializer initializer) {\n\t\toperator=(initializer);\n\t}\n\tvoid operator=(PhysicalAttributeInitializer initializer);\n\n\ttemplate<typename PhysicalDefaultValueType >\n\t\tPhysicalAttribute(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\toperator=(initializer);\n\t}\n\ttemplate<typename PhysicalDefaultValueType>\n\t\tvoid operator=(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer);\n\n\tRsynPhysicalObjectExtension &operator[](RsynPhysicalObject obj);\n\tconst RsynPhysicalObjectExtension &operator[](RsynPhysicalObject obj) const;\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename _PhysicalObject, typename _PhysicalObjectReference, typename _PhysicalObjectExtension>\nclass PhysicalAttributeBase {\nprivate:\n\t// [TODO] Make design and list const.\n\n\tPhysicalDesign clsPhysicalDesign;\n\tList<_PhysicalObject> *clsListPtr;\n\t_PhysicalObjectExtension clsDefaultValue;\n\n\ttypename List<_PhysicalObject>::CreateElementCallbackHandler clsHandlerOnCreate;\n\ttypename List<_PhysicalObject>::DestructorCallbackHandler clsListDestructorCallbackHandler;\n\n\tstd::deque<_PhysicalObjectExtension> clsData;\n\n\tvoid accommodate(const Index index) {\n\t\tif (index >= clsData.size()) {\n\t\t\tclsData.resize(index + 1, clsDefaultValue);\n\t\t} // end if\n\t} // end method\n\nprotected:\n\n\tvoid setupCallbacks() {\n\t\tclsHandlerOnCreate = clsListPtr->addCreateCallback([&](const int index) {\n\t\t\taccommodate(clsListPtr->largestId());\n\t\t}); // end method\n\n\t\tclsListDestructorCallbackHandler = clsListPtr->addDestructorEventCallback([&]() {\n\t\t\tclsListPtr = nullptr;\n\t\t}); // end method\t\t\n\n\t} // end method\n\n\tvoid load(PhysicalDesign design, List<_PhysicalObject> &list, _PhysicalObjectExtension defaultValue = _PhysicalObjectExtension()) {\n\t\tclsPhysicalDesign = design;\n\t\tclsListPtr = &list;\n\t\tclsDefaultValue = defaultValue;\n\t\taccommodate(clsListPtr->largestId());\n\t\tsetupCallbacks();\n\t} // end method\t\t\n\npublic:\n\n\tPhysicalAttributeBase() : clsPhysicalDesign(nullptr), clsListPtr(nullptr) {\n\t} // end constructor\n\n\tPhysicalAttributeBase(const PhysicalAttributeBase<_PhysicalObject, _PhysicalObjectReference, _PhysicalObjectExtension> &other) {\n\t\toperator=(other);\n\t} // end constructor\n\n\tPhysicalAttributeBase(PhysicalDesign design, List<_PhysicalObject> &list) {\n\t\tload(design, list);\n\t} // end constructor\n\n\tPhysicalAttributeBase<_PhysicalObject, _PhysicalObjectReference, _PhysicalObjectExtension> &\n\t\toperator=(const PhysicalAttributeBase<_PhysicalObject, _PhysicalObjectReference, _PhysicalObjectExtension> &other) {\n\t\tunload();\n\n\t\tclsPhysicalDesign = other.clsPhysicalDesign;\n\t\tclsListPtr = other.clsListPtr;\n\t\tclsData = other.clsData;\n\n\t\t// When a layer gets copied, we need to setup new callbacks.\n\t\tsetupCallbacks();\n\n\t\treturn *this;\n\t} // end method\n\n\t~PhysicalAttributeBase() {\n\t\tunload();\n\t} // end constructor\n\n\tvoid unload() {\n\t\tif (clsPhysicalDesign) {\n\t\t\tclsPhysicalDesign = nullptr;\n\t\t} // end if\n\n\t\tif (clsListPtr) {\n\t\t\tclsListPtr->deleteCreateCallback(clsHandlerOnCreate);\n\t\t\tclsListPtr->deleteDestructorCallback(clsListDestructorCallbackHandler);\n\t\t\tclsListPtr = nullptr;\n\t\t} // end if\n\n\t\tclsData.clear();\n\t\tclsData.shrink_to_fit();\n\t} // end method\t\n\n\tinline _PhysicalObjectExtension &operator[](_PhysicalObjectReference obj) {\n\t\treturn clsData[clsPhysicalDesign.getId(obj)];\n\t}\n\n\tinline const _PhysicalObjectExtension &operator[](_PhysicalObjectReference obj) const {\n\t\treturn clsData[clsPhysicalDesign.getId(obj)];\n\t}\n\n}; // end class\t\n\n////////////////////////////////////////////////////////////////////////////////\n// PhysicalAttribute Layer: (Generic) - Internal Use Only\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _PhysicalObject, typename _PhysicalObjectExtension>\nclass PhysicalAttributeImplementation {\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// PhysicalAttribute Layer: PhysicalRow\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _PhysicalObjectExtension>\nclass PhysicalAttributeImplementation<Rsyn::PhysicalRow, _PhysicalObjectExtension>\n: public Rsyn::PhysicalAttributeBase<PhysicalRowData, PhysicalRow, _PhysicalObjectExtension> {\npublic:\n\n\tPhysicalAttributeImplementation() {\n\t}\n\n\tPhysicalAttributeImplementation(PhysicalAttributeInitializer initializer) {\n\t\toperator=(initializer);\n\t}\n\n\tvoid operator=(PhysicalAttributeInitializer initializer) {\n\t\tPhysicalDesign design = initializer.getPhysicalDesign();\n\t\tPhysicalAttributeBase<PhysicalRowData, PhysicalRow, _PhysicalObjectExtension>::load(design, design.data->clsPhysicalRows);\n\t} // end operator\n\n\ttemplate<typename PhysicalDefaultValueType>\n\tPhysicalAttributeImplementation(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\toperator=(initializer);\n\t}\n\n\ttemplate<typename PhysicalDefaultValueType>\n\tvoid operator=(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\tPhysicalDesign design = initializer.getPhysicalDesign();\n\t\tPhysicalAttributeBase<PhysicalRowData, PhysicalRow, _PhysicalObjectExtension>::load(design, design.data->clsPhysicalRows, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n\n////////////////////////////////////////////////////////////////////////////////\n// PhysicalAttribute Layer: PhysicalLayer\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _PhysicalObjectExtension>\nclass PhysicalAttributeImplementation<Rsyn::PhysicalLayer, _PhysicalObjectExtension>\n: public Rsyn::PhysicalAttributeBase<PhysicalLayerData, PhysicalLayer, _PhysicalObjectExtension> {\npublic:\n\n\tPhysicalAttributeImplementation() {\n\t}\n\n\tPhysicalAttributeImplementation(PhysicalAttributeInitializer initializer) {\n\t\toperator=(initializer);\n\t}\n\n\tvoid operator=(PhysicalAttributeInitializer initializer) {\n\t\tPhysicalDesign design = initializer.getPhysicalDesign();\n\t\tPhysicalAttributeBase<PhysicalLayerData, PhysicalLayer, _PhysicalObjectExtension>::load(design, design.data->clsPhysicalLayers);\n\t} // end operator\n\n\ttemplate<typename PhysicalDefaultValueType>\n\tPhysicalAttributeImplementation(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\toperator=(initializer);\n\t}\n\n\ttemplate<typename PhysicalDefaultValueType>\n\tvoid operator=(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\tPhysicalDesign design = initializer.getPhysicalDesign();\n\t\tPhysicalAttributeBase<PhysicalLayerData, PhysicalLayer, _PhysicalObjectExtension>::load(design, design.data->clsPhysicalLayers, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n\n////////////////////////////////////////////////////////////////////////////////\n// PhysicalAttribute Layer: PhysicalSpacing\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename _PhysicalObjectExtension>\nclass PhysicalAttributeImplementation<Rsyn::PhysicalSpacing, _PhysicalObjectExtension>\n: public Rsyn::PhysicalAttributeBase<PhysicalSpacingData, PhysicalSpacing, _PhysicalObjectExtension> {\npublic:\n\n\tPhysicalAttributeImplementation() {\n\t}\n\n\tPhysicalAttributeImplementation(PhysicalAttributeInitializer initializer) {\n\t\toperator=(initializer);\n\t}\n\n\tvoid operator=(PhysicalAttributeInitializer initializer) {\n\t\tPhysicalDesign design = initializer.getPhysicalDesign();\n\t\tPhysicalAttributeBase<PhysicalSpacingData, PhysicalSpacing, _PhysicalObjectExtension>::load(design, design.data->clsPhysicalSpacing);\n\t} // end operator\n\n\ttemplate<typename PhysicalDefaultValueType>\n\tPhysicalAttributeImplementation(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\toperator=(initializer);\n\t}\n\n\ttemplate<typename PhysicalDefaultValueType>\n\tvoid operator=(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\t\tPhysicalDesign design = initializer.getPhysicalDesign();\n\t\tPhysicalAttributeBase<PhysicalSpacingData, PhysicalSpacing, _PhysicalObjectExtension>::load(design, design.data->clsPhysicalSpacing, initializer.getDefaultValue());\n\t} // end operator\t\t\n}; // end class\n\n\n////////////////////////////////////////////////////////////////////////////////\n// PhysicalAttribute\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename RsynPhysicalObject, typename RsynPhysicalObjectExtension>\ninline\nvoid PhysicalAttribute<RsynPhysicalObject, RsynPhysicalObjectExtension>::operator=(PhysicalAttributeInitializer initializer) {\n\tthis->reset(new PhysicalAttributeImplementation<RsynPhysicalObject, RsynPhysicalObjectExtension>(initializer));\n} // end method\n\ntemplate<typename RsynPhysicalObject, typename RsynPhysicalObjectExtension>\ntemplate<typename PhysicalDefaultValueType>\ninline\nvoid PhysicalAttribute<RsynPhysicalObject, RsynPhysicalObjectExtension>::operator=(PhysicalAttributeInitializerWithDefaultValue<PhysicalDefaultValueType> initializer) {\n\tthis->reset(new PhysicalAttributeImplementation<RsynPhysicalObject, RsynPhysicalObjectExtension>(initializer));\n} // end method\n\ntemplate<typename RsynPhysicalObject, typename RsynPhysicalObjectExtension>\ninline\nRsynPhysicalObjectExtension &PhysicalAttribute<RsynPhysicalObject, RsynPhysicalObjectExtension>::operator[](RsynPhysicalObject obj) {\n\treturn (*this)->operator[](obj);\n} // end method\n\ntemplate<typename RsynPhysicalObject, typename RsynPhysicalObjectExtension>\ninline\nconst RsynPhysicalObjectExtension &PhysicalAttribute<RsynPhysicalObject, RsynPhysicalObjectExtension>::operator[](RsynPhysicalObject obj) const {\n\treturn (*this)->operator[](obj);\n} // end method\n\n} // end namespace\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/infra/PhysicalObserver.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICAL_OBSERVER_H\n#define RSYN_PHYSICAL_OBSERVER_H\n\nnamespace Rsyn {\n\nclass PhysicalDesignObserver {\nfriend class Rsyn::PhysicalDesign;\nprivate:\n\tPhysicalDesign clsPhDesign;\n\npublic:\n\t\n\t// Note: The observer will not be registered to receive notifications for\n\t// methods that it does not overwrite. Therefore, no runtime overhead for\n\t// handling undesired notifications.\n\n\tvirtual void\n\tonPhysicalDesignDestruction() {}\n\n\tvirtual void\n\tonPostNetRoutingChange(Rsyn::PhysicalNet physicalNet) {}\n\t\n\tvirtual\n\t~PhysicalDesignObserver() {\n\t\tif (clsPhDesign)\n\t\t\tclsPhDesign.unregisterObserver(this);\n\t} // end destructor\n\n}; // end class\n\n} // end namespace\n\n\n#endif /* RSYN_PHYSICALOBSERVER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/LayerViaManagerData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalLayerViaManagerData.h\n * Author: jucemar\n *\n * Created on February 3, 2018, 9:17 AM\n */\n\n#ifndef PHYSICALLAYERVIAMANAGERDATA_H\n#define PHYSICALLAYERVIAMANAGERDATA_H\n\nnamespace Rsyn {\n\nclass LayerViaManagerData : public PhysicalObject {\npublic:\n\tstd::map<Rsyn::PhysicalLayer, std::vector<Rsyn::PhysicalVia>>  clsVias;\n\tstd::map<Rsyn::PhysicalLayer, std::vector<Rsyn::PhysicalVia>>  clsBottomVias;\n\tstd::map<Rsyn::PhysicalLayer, std::vector<Rsyn::PhysicalVia>>  clsTopVias;\n\tLayerViaManagerData() = default;\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALLAYERVIAMANAGERDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalDesign.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICALDESIGN_PHYSICALDESIGNDATA_H\n#define RSYN_PHYSICALDESIGN_PHYSICALDESIGNDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalDesignData : public PhysicalObject {\n\tfriend class PhysicalDesign;\npublic:\n\tRsyn::Design clsDesign;\n\tRsyn::Module clsModule;\n\tRsyn::LayerViaManagerData clsLayerViaManager;\n\n\tstd::list<std::function<void(Rsyn::Instance cell) >> callbackAddCreatePhysicalCell;\n\tstd::list<std::function<void(Rsyn::Instance cell) >> callbackOnPreCellRemoveEvent;\n\tRsyn::Attribute<Rsyn::LibraryPin, PhysicalLibraryPinData> clsPhysicalLibraryPins;\n\tRsyn::Attribute<Rsyn::Pin, PhysicalPinData> clsPhysicalPins;\n\tRsyn::Attribute<Rsyn::Instance, PhysicalInstanceData> clsPhysicalInstances;\n\tRsyn::Attribute<Rsyn::LibraryCell, PhysicalLibraryCellData> clsPhysicalLibraryCells;\n\tRsyn::Attribute<Rsyn::Net, PhysicalNetData> clsPhysicalNets;\n\tRsyn::List<PhysicalRowData> clsPhysicalRows;\n\tRsyn::List<PhysicalLayerData> clsPhysicalLayers;\n\tRsyn::List<PhysicalSpacingData> clsPhysicalSpacing;\n\tstd::vector<PhysicalRegion> clsPhysicalRegions;\n\tstd::vector<PhysicalGroup> clsPhysicalGroups;\n\tstd::vector<PhysicalSite> clsPhysicalSites;\n\tstd::vector<PhysicalVia> clsPhysicalVias;\n\tstd::vector<Rsyn::PhysicalViaRuleBase> clsPhysicalViaRuleBases;\n\tstd::vector<Rsyn::PhysicalViaRule> clsPhysicalViaRules;\n\tstd::vector<Rsyn::PhysicalViaRuleGenerate> clsPhysicalViaRuleGenerates;\n\tstd::vector<PhysicalSpecialNet> clsPhysicalSpecialNets;\n\tstd::vector<PhysicalTracks> clsPhysicalTracks;\n\tstd::vector<PhysicalGCell> clsPhysicalGCell;\n\tstd::vector<Rsyn::PhysicalRoutingGrid> clsPhysicalRoutingGrids;\n\tstd::unordered_map<std::string, int> clsMapPhysicalSites;\n\tstd::unordered_map<std::string, std::size_t> clsMapPhysicalRegions;\n\tstd::unordered_map<std::string, std::size_t> clsMapPhysicalGroups;\n\tstd::unordered_map<std::string, std::size_t> clsMapPhysicalSpecialNets;\n\tstd::map<Rsyn::PhysicalLayer, std::vector<Rsyn::PhysicalTracks>> clsMapLayerToTracks;\n\tstd::map<Rsyn::PhysicalLayer, Rsyn::PhysicalRoutingGrid> clsMapLayerToRoutingGrid;\n\t\n\t//From LEF file\n\tstd::unordered_map<std::string, std::size_t> clsMapPhysicalLayers;\n\tstd::unordered_map<std::string, std::size_t> clsMapPhysicalVias;\n\tstd::unordered_map<std::string, std::size_t> clsMapPhysicalViaRuleBases;\n\tstd::vector<std::size_t> clsPhysicalRoutingLayerIndeces;\n\t//std::vector<PhysicalSpacing> clsPhysicalSpacing;\n\n\tRsyn::PhysicalDieData clsPhysicalDie; // total area of the circuit including core bound. \n\n\tDBU clsTotalAreas[NUM_PHYSICAL_TYPES];\n\tint clsNumElements[NUM_PHYSICAL_TYPES];\n\tint clsNumLayers[NUM_PHY_LAYER];\n\n\tDBUxy clsHPWL;\n\tDBU clsDBUs[NUM_DBU]; // LEF and DEF data base units resolution and DEF/LEF multiplier factor\n\n\tbool clsLoadDesign : 1;\n\tbool clsEnablePhysicalPins : 1;\n\tbool clsEnableMergeRectangles : 1;\n\tbool clsEnableNetPinBoundaries : 1;\n\n\tRsyn::Net clsClkNet;\n\t\n\t// Physical design mode \n\tPhysicalDesignMode clsMode = PhysicalDesignMode::ALL;\n\t\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Observerss\n\t////////////////////////////////////////////////////////////////////////////\n\n\tstd::array<std::list<PhysicalDesignObserver *>, NUM_PHYSICAL_EVENTS> clsPhysicalObservers;\n\n\tPhysicalDesignData() : clsClkNet(nullptr), clsDesign(nullptr), clsModule(nullptr) {\n\n\t\tclsLoadDesign = false;\n\t\tclsEnablePhysicalPins = false;\n\t\tclsEnableMergeRectangles = false;\n\t\tclsEnableNetPinBoundaries = false;\n\t\tfor (int index = 0; index < NUM_DBU; index++) {\n\t\t\tclsDBUs[index] = 0;\n\t\t} // end for \n\t\tfor (int index = 0; index < NUM_PHYSICAL_TYPES; index++) {\n\t\t\tclsTotalAreas[index] = 0.0;\n\t\t\tclsNumElements[index] = 0;\n\t\t} // end for  \n\t\tfor (int index = 0; index < NUM_PHY_LAYER; index++) {\n\t\t\tclsNumLayers[index] = 0;\n\t\t}\n\t} // end constructor \n}; // end class \n\n} // end namespace\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalDieData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalDieData.h\n * Author: jucemar\n *\n * Created on 4 de Fevereiro de 2017, 08:40\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALDIEDATA_H\n#define PHYSICALDESIGN_PHYSICALDIEDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalDieData {\n\tfriend class PhysicalDesign;\npublic:\n\t//! @brief\tRectangular PhysicalDie Bounds in DBU  units.\n\tBounds clsBounds;\n\t//! @brief\tIt constructs the default Bounds(DBUxy(0,0), DBUxy(0,0)).\n\tPhysicalDieData() = default;\n}; // end class \n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALDIEDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalGCellData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef PHYSICALGCELLDATA_H\n#define PHYSICALGCELLDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalGCellData {\n\tfriend class PhysicalDesign;\npublic:\n\t//! @brief Direction of the GCell\n\t//! HORIZONTAL is equal to Y in DEF and VERTICAL is equal to X in DEF\n\tPhysicalGCellDirection clsDirection;\n\t//! @brief Each GCELLGRID statement specifies the location of the first vertical (x) and first horizontal (y) track. Source: DEF Manual.\n\tDBU clsLocation = 0;\n\t//! @brief Specifies the number of columns in the grid if Direction is VERTICAL\n\t//! Specifies the number of rows in the grid if Direction is HORIZONTAL\n\tint clsNumTracks = 0;\n\t//! @brief Specifies the spacing between tracks.\n\tDBU clsStep = 0;\n\t//! @brief\tdefault constructor\n\tPhysicalGCellData() = default;\n}; // end class \n} // end namespace \n\n#endif /* PHYSICALGCELLDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalGroupData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalGroupData.h\n * Author: jucemar\n *\n * Created on 09 de Abril de 2017, 16:45\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALGROUPDATA_H\n#define PHYSICALDESIGN_PHYSICALGROUPDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalGroupData : public PhysicalObject {\npublic:\n\n\tstd::string clsName = Rsyn::getPhysicalInvalidName();\n\tstd::vector<std::string> clsPatterns; // e.g. \"name/*\"\n\tRsyn::PhysicalRegion clsRegion;\n\tPhysicalGroupData() = default;\n}; // end class  \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALGROUPDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalInstanceData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalCellData.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 21:01\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALINSTANCEDATA_H\n#define PHYSICALDESIGN_PHYSICALINSTANCEDATA_H\nnamespace Rsyn {\n\nclass PhysicalInstanceData {\n\tfriend class PhysicalDesign;\npublic:\n\tbool clsBlock : 1;\n\tbool clsPlaced : 1;\n\tbool clsPort : 1;\n\tbool clsHasLayerBounds : 1; //  the bounds of a cell is defined by one of the layers. \n\n\tDBUxy clsInitialPos; // Initial position from global placement when in detailed placement has maximal displacement\n\tPhysicalLayer clsPortLayer;\n\tRsyn::Instance clsInstance;\n\n\tPhysicalInstanceData() {\n\t\tclsBlock = false;\n\t\tclsPlaced = false;\n\t\tclsPort = false;\n\t\tclsHasLayerBounds = false;\n\t} // end constructor \n}; // end class\n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALINSTANCEDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalLayerData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalLayerData.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 19:09\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALLAYERDATA_H\n#define PHYSICALDESIGN_PHYSICALLAYERDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalLayerData : public PhysicalObject {\npublic:\n    lefiLayer* clsLayer = nullptr;\n\tDBU clsWidth = 0;\n\tint clsIndex = -1;\n\tint clsRelativeIndex = -1;\n\tRsyn::PhysicalLayerType clsType = INVALID_PHY_LAYER_TYPE;\n\tstd::string clsName = Rsyn::getPhysicalInvalidName();\n\tRsyn::PhysicalLayerData * clsLower = nullptr;\n\tRsyn::PhysicalLayerData * clsUpper = nullptr;\n\tPhysicalLayerData() = default;\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALLAYERDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalLibraryCellData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalLibraryCellData.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 22:08\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALLIBRARYCELLDATA_H\n#define PHYSICALDESIGN_PHYSICALLIBRARYCELLDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalLibraryCellData {\npublic:\n\tlefiMacro* clsMacro = nullptr;\n\tPhysicalSite clsMacroSite;\n\tDBUxy clsSize;\n\tint clsLayerBoundIndex = -1; // The cell bound is defined by one of the layers.\n\tstd::vector<Rsyn::PhysicalObstacle> clsObs;\n\tPolygon clsPolygonBounds;\n\tRsyn::PhysicalObstacle clsTopLayerObs;\n\tPhysicalLibraryCellData() = default;\n\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALLIBRARYCELLDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalLibraryPinData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalLibraryPinData.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 21:04\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALLIBRARYPINDATA_H\n#define PHYSICALDESIGN_PHYSICALLIBRARYPINDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalLibraryPinData {\npublic:\n\tBounds clsLayerBound; // The layer bound is defined by one of the layer.\n\tPhysicalLibraryCell clsLibraryCell;\n\tPhysicalPinUse clsUse = PIN_INVALID_USE;\n\tPhysicalPinDirection clsDirection = PIN_INVALID_DIRECTION;\n\t// A pin may have several ports. However, each port is weakly connected to other. \n\t// It is assumed that they have high resistance among them. \n\tstd::vector<PhysicalPinGeometry> clsPhysicalPinGeometries;\n\t\n\tPhysicalLibraryPinData() = default;\n}; // class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALLIBRARYPINDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalNetData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   PhysicalNetData.h\n * Author: jucemar\n *\n * Created on 15 de Setembro de 2016, 19:15\n */\n\n#ifndef RSYN_PHYSICAL_NET_DATA_H\n#define RSYN_PHYSICAL_NET_DATA_H\n\nnamespace Rsyn {\n\nclass PhysicalNetData {\npublic:\n\tBounds clsBounds;\n\tRsyn::Net clsNet;\n\tRsyn::Pin clsBoundPins[2][2];\n\tPhysicalRouting clsRouting;\n\n\tPhysicalNetData() {\n\t\tclsBoundPins[LOWER][X] = nullptr;\n\t\tclsBoundPins[LOWER][Y] = nullptr;\n\t\tclsBoundPins[UPPER][X] = nullptr;\n\t\tclsBoundPins[UPPER][Y] = nullptr;\n\t} // end constructor \n}; // end class\n\n} // end class \n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalObject.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalObject.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 19:59\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALOBJECT_H\n#define PHYSICALDESIGN_PHYSICALOBJECT_H\n\n\nnamespace Rsyn {\n\nclass PhysicalObject {\npublic:\n\t//! @brief Unique identifier of the Physical Objects. \n\t//! @details It is used to avoid compare pointer when sorting physical objects. \n\t//! The id variable is protected from users access outside of Physical classes. \n\tPhysicalIndex id = INVALID_PHYSICAL_INDEX;\n\n\tPhysicalObject() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALOBJECT_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalObstacleData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalObstacleData.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 20:02\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALOBSTACLEDATA_H\n#define PHYSICALDESIGN_PHYSICALOBSTACLEDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalObstacleData : public PhysicalObject {\npublic:\n\tRsyn::PhysicalLayer clsLayer;\n\tstd::vector<Bounds> clsBounds;\n\tPhysicalObstacleData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALOBSTACLEDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalPinData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPinData.h\n * Author: jucemar\n *\n * Created on 14 de Setembro de 2016, 21:24\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPINDATA_H\n#define PHYSICALDESIGN_PHYSICALPINDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalPinData {\npublic:\n\tDBUxy clsDisplacement;\n\t//! @details A pin may have several ports. However, each port is weakly connected to other. \n\t//! It is assumed that they have high resistance among them. \n\tstd::vector<PhysicalPinGeometry> clsPhysicalPinGeometries;\n\tPhysicalPinDirection clsDirection = PIN_INVALID_DIRECTION;\n\tBounds clsLayerBound; // The pin bounds is defined by one of the layers\n\tPhysicalPinData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALPINDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalPinGeometryData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPinGeometryData.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 21:10\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPINGEOMETRYDATA_H\n#define PHYSICALDESIGN_PHYSICALPINGEOMETRYDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalPinGeometryData : public PhysicalObject {\npublic:\n\t//! @brief An enum PhysicalPinGeometryClass that determines the class of the PhysicalPinGeometry object.\n\tPhysicalPinGeometryClass clsPinPortClass = PINGEOMETRYCLASS_NONE;\n\t//! @brief PhysicalPinLayers associated to the PhysicalPinGeometry.\n\tstd::vector<PhysicalPinLayer> clsPinLayers;\n\t//! @brief Default constructor.\n\t//! @details Users do not have access to this constructor. The reference to \n\t//! PhysicalPinGeometryData is a protected variable in PhysicalPinGeometry.\n\n\tPhysicalPinGeometryData() = default;\n\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALPINGEOMETRYDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalPinLayerData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPinLayerData.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 21:16\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPINLAYERDATA_H\n#define PHYSICALDESIGN_PHYSICALPINLAYERDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalPinLayerData : public PhysicalObject {\npublic:\n\tstd::vector<Bounds> clsBounds;\n\tstd::vector<Polygon> clsPolygons;\n\tRsyn::PhysicalLayer clsLibLayer;\n\tPhysicalPinLayerData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALPINLAYERDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalRegionData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRegionData.h\n * Author: jucemar\n *\n * Created on 09 de Abril de 2017, 14:55\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALREGIONDATA_H\n#define PHYSICALDESIGN_PHYSICALREGIONDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalRegionData : public PhysicalObject {\npublic:\n\n\tstd::string clsName = Rsyn::getPhysicalInvalidName();\n\tRegionType clsType = RegionType::INVALID; // FENCE or GUIDE\n\tstd::vector<Bounds> clsBounds;\n\tPhysicalRegionData() = default;\n}; // end class  \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALREGIONDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalRoutingGridData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalRoutingGridData.h\n * Author: jucemar\n *\n * Created on February 2, 2018, 9:00 PM\n */\n\n#ifndef PHYSICALROUTINGGRIDDATA_H\n#define PHYSICALROUTINGGRIDDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalRoutingGridData : public PhysicalObject {\n\tfriend class PhysicalDesign;\npublic:\n\tstd::vector<Rsyn::PhysicalTracks> clsTracks;\n\tRsyn::PhysicalLayer clsLayer;\n\tDBUxy clsSpacing;\n\tint clsNumTracks[2];\n\tBounds clsBounds;\n\tRsyn::PhysicalRoutingGrid clsBottomRoutingGrid;\n\tRsyn::PhysicalRoutingGrid clsTopRoutingGrid;\n\tPhysicalRoutingGridData() = default;\n}; // end class\n\n} // end namespace\n\n#endif /* PHYSICALROUTINGGRIDDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalRoutingPointData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRoutingPointData.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 20:27\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALROUTINGPOINTDATA_H\n#define PHYSICALDESIGN_PHYSICALROUTINGPOINTDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalRoutingPointData : public PhysicalObject {\npublic:\n\tPhysicalVia clsVia;\n\tDBUxy clsPos;\n\tBounds clsRectangle;\n\tDBU clsExtension = -1;\n\tPhysicalOrientation clsOrientation = ORIENTATION_N; // default routing point orientation\n\tbool clsHasRectangle : 1;\n\tbool clsHasMask : 1;\n\tbool clsHasVirtual : 1;\n\tPhysicalRoutingPointData() {\n\t\tclsHasRectangle = false;\n\t\tclsHasMask = false;\n\t\tclsHasVirtual = false;\n\t} // end constructor \n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALROUTINGPOINTDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalRowData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRowData.h\n * Author: jucemar\n *\n * Created on 14 de Setembro de 2016, 22:26\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALROWDATA_H\n#define PHYSICALDESIGN_PHYSICALROWDATA_H\n\n\nnamespace Rsyn {\n\nclass PhysicalRowData : public PhysicalObject {\npublic:\n\tBounds clsBounds;\n\tPhysicalSite clsPhysicalSite;\n\tPhysicalOrientation clsSiteOrientation = Rsyn::PhysicalOrientation::ORIENTATION_INVALID;\n\tDBUxy clsOrigin;\n\tint clsNumSites[2] = {0, 0};\n\tDBUxy clsStep;\n\tstd::string clsRowName;\n\n\tPhysicalRowData() {\n\t\tclsRowName = Rsyn::getPhysicalInvalidName();\n\t} // end constructor \n\n\t// these methods are required in several parts of Physical Design.\n\t// Therefore, they are provided by physical row data\n\t// another solution was to create a variable to store each information.\n\n\tinline DBU getWidth() const {\n\t\treturn clsNumSites[X] * clsStep[X];\n\t} // end method \n\n\tinline DBU getHeight() const {\n\t\treturn clsNumSites[Y] * clsStep[Y];\n\t} // end method \n}; // end class  \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALROWDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalSiteData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSiteData.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 22:44\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSITEDATA_H\n#define PHYSICALDESIGN_PHYSICALSITEDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalSiteData : public PhysicalObject {\npublic:\n\tRsyn::PhysicalSiteClass clsSiteClass = INVALID_SITECLASS;\n\tDBUxy clsSize;\n\tstd::string clsSiteName = Rsyn::getPhysicalInvalidName();\n\tRsyn::PhysicalSymmetry clsSymmetry = Rsyn::PhysicalSymmetry::SYMMETRY_INVALID;\n\tPhysicalSiteData() = default;\n}; // end namespace \n\n} // end namespace  \n\n#endif /* PHYSICALDESIGN_PHYSICALSITEDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalSpacingData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpacingData.h\n * Author: jucemar\n *\n * Created on 15 de Setembro de 2016, 18:55\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPACINGDATA_H\n#define PHYSICALDESIGN_PHYSICALSPACINGDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalSpacingData : public PhysicalObject {\npublic:\n\tPhysicalLayer clsLayer1;\n\tPhysicalLayer clsLayer2;\n\tDBU clsDistance = 0;\n\tPhysicalSpacingData() = default;\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALSPACINGDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalSpacingRuleData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpacingRuleData.h\n * Author: jucemar\n *\n * Created on 17 de dezembro de 2017, 14:10\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPACINGRULEDATA_H\n#define PHYSICALDESIGN_PHYSICALSPACINGRULEDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalSpacingRuleData {\npublic:\n\tDBU clsSpacing = 0;\n\tDBU clsEOL = 0;\n\tDBU clsEOLWithin = 0;\n\tPhysicalSpacingRuleData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPACINGRULEDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalSpacingTableData.h",
    "content": "\n/* \n * File:   PhysicalSpacingTableData.h\n * Author: \n *\n * Created on 12/2/2018, 17:35\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPACINGTABLEDATA_H\n#define PHYSICALDESIGN_PHYSICALSPACINGTABLEDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalSpacingTableData {\npublic:\n\tDBU clsParallelLength = 0;\n\tstd::vector<DBU> clsParallelWidth;\n\tstd::vector<DBU> clsParallelWidthSpacing;\n\tPhysicalSpacingTableData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPACINGTABLEDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalSpecialNetData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpecialNetData.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 20:23\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPECIALNETDATA_H\n#define PHYSICALDESIGN_PHYSICALSPECIALNETDATA_H\n\nnamespace Rsyn {\nclass PhysicalSpecialNetData : public PhysicalObject {\npublic:\n\tDefNetDscp clsNet;\n\t\n\tPhysicalSpecialNetData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPECIALNETDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalSpecialWireData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpecialWireData.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 21:08\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPECIALWIREDATA_H\n#define PHYSICALDESIGN_PHYSICALSPECIALWIREDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalSpecialWireData : public PhysicalObject {\npublic:\n\tRsyn::PhysicalLayer clsPhysicalLayer;\n\tDBU clsWireWidth;\n\tstd::vector<PhysicalRoutingPoint> clsRoutingPoints;\n\tPhysicalSpecialWireData() = default;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPECIALWIREDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalTracksData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalTracksData.h\n * Author: jucemar\n *\n * Created on 24 de Maio de 2017, 21:47\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALTRACKSDATA_H\n#define PHYSICALDESIGN_PHYSICALTRACKSDATA_H\n\nnamespace Rsyn {\n\nclass PhysicalTracksData : public PhysicalObject {\npublic:\n\tPhysicalTrackDirection clsDirection = PhysicalTrackDirection::INVALID_PHY_TRACK_DIRECTION;\n\tDBU clsLocation = 0;\n\tDBU clsSpace = 0;\n\tint clsNumTracks = 0;\n\tstd::vector<PhysicalLayer> clsLayers;\n}; // end class \n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALTRACKSDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/PhysicalViaData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalViaData.h\n * Author: jucemar\n *\n * Created on 14 de Maio de 2017, 14:49\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALVIADATA_H\n#define PHYSICALDESIGN_PHYSICALVIADATA_H\n\nnamespace Rsyn {\n\nclass PhysicalViaData : public PhysicalObject {\npublic:\n\tbool clsIsDefault : 1;\n\tbool clsIsViaDesign : 1;\n\tbool clsHasViaRule : 1;\n\tbool clsHasRowCol : 1;\n\tbool clsHasOrigin : 1;\n\tbool clsHasOffset : 1;\n\tbool clsHasPattern : 1;\n\tbool clsHasCutResistance : 1;\n\tViaType clsType = INVALID_VIA_TYPE;\n\tRsyn::ViaRuleData * clsViaRuleData = nullptr;\n\tDBU clsCutSize [2] = {0, 0}; // xCutSize, yCutSize\n\tDBU clsSpacing [2] = {0, 0}; // xSpacing, ySpacing\n\tDBU clsEnclosure[NUM_VIA_LEVELS][2]; // bottomXEnclosure, bottomYEnclosure, topXEnclosure, topYEnclosure\n\tDBU clsOrigin[2] = {0, 0}; // xOrigin, yOrigin\n\tDBU clsOffset[NUM_VIA_LEVELS][2]; // bottomXOffset, bottomYOffset, topXOffset, topYOffset\n\tint clsNumRows = 0;\n\tint clsNumCols = 0;\n    std::string clsPattern = \"\";\n\tfloat clsCutResistance = 0.0;\n\tRsyn::PhysicalLayerData *clsLayers[NUM_VIA_LAYERS]; // bottom, cut, top\n\tstd::vector<Rsyn::PhysicalViaGeometry>  clsViaGeometries [NUM_VIA_LAYERS]; // bottom, cut, top\n\tstd::string clsName;\n\t\n\tPhysicalViaData() {\n\t\tclsIsDefault = false;\n\t\tclsIsViaDesign = false;\n\t\tclsHasViaRule = false;\n\t\tclsHasRowCol = false;\n\t\tclsHasOrigin = false;\n\t\tclsHasOffset = false;\n\t\tclsHasPattern = false;\n\t\tclsHasCutResistance = false;\n\t} // end constructor \n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALVIADATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/ViaGeometryData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   ViaGeometryData.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 5:44 PM\n */\n\n#ifndef RSYN_DATABASE_VIAGEOMETRYDATA_H\n#define RSYN_DATABASE_VIAGEOMETRYDATA_H\n\nnamespace Rsyn {\nclass ViaGeometryData : public PhysicalObject {\npublic:\n\tBounds clsBounds;\n\tint clsMaskNumber = -1;\n\t// Polygon\n}; // end class \n\n} // end namespace \n#endif /* RSYN_DATABASE_VIAGEOMETRYDATA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/data/ViaRuleData.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   ViaRule.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 4:55 PM\n */\n\n#ifndef RSYN_DATABASE_VIARULE_H\n#define RSYN_DATABASE_VIARULE_H\n\n\nnamespace Rsyn {\n\nclass ViaRuleData : public PhysicalObject {\npublic:\n\tbool clsIsDefault : 1; \n\tbool clsIsGenerate : 1;\n\tbool clsHasCutResistance : 1;\n\tbool clsHasWidth [NUM_VIA_LEVELS];\n\tint clsRelativeIndex = -1;\n\tRsyn::PhysicalLayerData * clsLayers [NUM_VIA_LAYERS]; // top or bottom layer levels. Cut is only for generate type\n\tRsyn::PhysicalLayerDirection clsLayerDirection [NUM_VIA_LEVELS]; // Directions for top or bottom layer levels.\n\tDBU clsWidth[NUM_VIA_LEVELS][NUM_VIA_RANGES]; // Specifies a wire width range  for bottom and top layer levels. \n\tDBU clsEnclosure1 [NUM_VIA_LEVELS];\n\tDBU clsEnclosure2 [NUM_VIA_LEVELS];\n\tBounds clsCutBounds;\n\tDBU clsCutSpacing [2] = {0, 0}; // xCutSpacing, yCutSpacing\n\tfloat clsCutResistance = 0.0;\n\tstd::vector<Rsyn::PhysicalVia>  clsVias;\n//\tstd::vector<Rsyn::Property> clsProperties; // TODO\n\tstd::string clsName; // Via rule name\n\n\t\n\t\n\tvoid init() {\n\t\tclsIsDefault = false;\n\t\tclsIsGenerate = false;\n\t\tclsHasCutResistance = false;\n\t\tfor(int i = 0; i < NUM_VIA_LAYERS; ++i) {\n\t\t\tclsLayers[i] = nullptr;\n\t\t} // end for \n\t\tfor(int i = 0; i < NUM_VIA_LEVELS; ++i) {\n\t\t\tclsHasWidth[i] = false;\n\t\t\tclsLayerDirection[i] = UNKNOWN_PREFERRED_DIRECTION;\n\t\t\tfor(int j = 0; j < NUM_VIA_RANGES; ++j) {\n\t\t\t\tclsWidth[i][j] = -std::numeric_limits<DBU>::max();\n\t\t\t} // end for \n\t\t} // end for \n\t} // end method \n\t\n\tViaRuleData() = default;\n}; // end class \n\n} // end namespace \n#endif /* RSYN_DATABASE_VIARULE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/LayerViaManager.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   LayerViaManager.h\n * Author: jucemar\n *\n * Created on February 3, 2018, 9:26 AM\n */\n\n#ifndef LAYERVIAMANAGER_H\n#define LAYERVIAMANAGER_H\n\nnamespace Rsyn {\n\nclass LayerViaManager : public Proxy<LayerViaManagerData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::LayerViaManager object with a pointer to Rsyn::LayerViaManagerData.\n\n\tLayerViaManager(LayerViaManagerData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::LayerViaManager object with a null pointer to Rsyn::LayerViaManagerData.\n\n\tLayerViaManager() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::LayerViaManager object with a null pointer to Rsyn::LayerViaManagerData.\n\n\tLayerViaManager(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\tconst std::vector<Rsyn::PhysicalVia> & allVias(Rsyn::PhysicalLayer layer) const;\n\tconst std::vector<Rsyn::PhysicalVia> & allBottomVias(Rsyn::PhysicalLayer layer) const;\n\tconst std::vector<Rsyn::PhysicalVia> & allTopVias(Rsyn::PhysicalLayer layer) const;\n\tbool hasVias(Rsyn::PhysicalLayer layer) const;\n\tbool hasBottomVias(Rsyn::PhysicalLayer layer) const;\n\tbool hasTopVias(Rsyn::PhysicalLayer layer) const;\n\t\n}; // end class\n\n} // end namespace \n\n#endif /* LAYERVIAMANAGER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalCell.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 21:04\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALCELL_H\n#define PHYSICALDESIGN_PHYSICALCELL_H\n\nnamespace Rsyn {\n\nclass PhysicalCell : public PhysicalInstance {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalInstance;\nprotected:\n\tPhysicalCell(PhysicalInstanceData * data) : PhysicalInstance(data) {}\npublic:\n\tPhysicalCell() : PhysicalInstance(nullptr) {}\n\tPhysicalCell(std::nullptr_t): PhysicalInstance(nullptr)   {} \n\n\t//! @brief Returns the cell associated to this physical cell.\n\tRsyn::Cell getCell() const;\n\t//! @brief Returns true if cell is fixed. Otherwise, returns false.\n\tbool isFixed() const;\n\t//! @brief Returns true if cell is MACRO type. Otherwise, returns false.\n\tbool isMacroBlock() const;\n\t//! @brief Returns true if cell is placed. Otherwise, returns false. \n\tbool isPlaced() const;\n\t//! @brief Returns initial position of the cell. \n\t//! @details Initial position is defined in the circuit placement files. \n\t//! Otherwise, it is defined to the coordinate DBUxy(0,0);\n\tDBUxy getInitialPosition() const;\n\t//! @brief Returns initial position of the cell for the given dimension. \n\t//! @details Initial position is defined in the circuit placement files. \n\t//! Otherwise, it is defined to the coordinate DBUxy(0,0);\n\tDBU getInitialPosition(const Dimension dim) const;\n\t//! @brief Returns cell displacement. \n\t//! @details Cell displacement is the difference between the current position of the cell \n\t//! and the initial position of the cell.\n\tDBU getDisplacement() const;\n\t//! @brief Returns cell displacement. \n\t//! @details Cell displacement is the difference between the current position of the cell \n\t//! and the initial position of the cell.\n\tDBU getDisplacement(const Dimension dim) const;\n\t//! @brief Returns cell displacement for the given dimension. \n\t//! @details Cell displacement is the difference between the current position of the cell \n\t//! and the given position.\n\tDBU getDisplacement(const DBUxy pos) const;\n\t//! @brief Returns cell displacement to the given position and given dimension. \n\t//! @details Cell displacement is the difference between the current position of the cell \n\t//! and the given position in the given dimension.\n\tDBU getDisplacement(const DBU pos, const Dimension dim) const;\n\t//! @brief Returns cell displacement for the given dimension. \n\t//! @details Cell displacement is the difference between the current position of the cell \n\t//! and the given position.\n\tDBU getDisplacementFromCurrentPosition(const DBUxy pos) const;\n\t//! @brief Returns cell displacement to the given position and given dimension. \n\t//! @details Cell displacement is the difference between the current position of the cell \n\t//! and the given position in the given dimension.\n\tDBU getDisplacementFromCurrentPosition(const DBU pos, const Dimension dim) const;\n\tDBU getDisplacementFromInitialPosition(const DBUxy pos) const;\n\tDBU getDisplacementFromInitialPosition(const DBU pos, const Dimension dim) const;\n\t//! @brief Returns a transformation that allows one to transform the\n\t//! coordinates from the library cell space to the cell space. The\n\t//! transformation accounts for translation and the orientation of the cell.\n\t//! @param origin If set to true, the transform is created w.r.t (0, 0) and\n\t//! not the current cell position.\n\tPhysicalTransform getTransform(const bool origin = false) const;\n\t//! @brief Returns true if the cell boundaries is defined by a PhysicalLayer. Otherwise, returns false.\n\t//! @details Cell boundaries may be defined by some PhysicalLayer instead of rectangular Bounds.\n\t//! In the 2015 ICCAD contest, some macro have their boundaries defined by metal1 layer.\n\tbool hasLayerBounds() const; \n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALCELL_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalDesign.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALDESIGN_H\n#define PHYSICALDESIGN_PHYSICALDESIGN_H\n\nnamespace Rsyn {\n\nclass PhysicalDesign : public Proxy<PhysicalDesignData> {\n\tfriend class PhysicalService;\n\n\ttemplate<typename _PhysicalObject, typename _PhysicalObjectReference, typename _PhysicalObjectExtension> friend class PhysicalAttributeBase;\n\ttemplate<typename _PhysicalObject, typename _PhysicalObjectExtension> friend class PhysicalAttributeImplementation;\n\n\nprotected:\n\t//! @brief Internal constructs a Rsyn::PhysicalDesign object with a pointer to the Rsyn::PhysicalDesignData.\n\t//! @details The data and methods in physical design are split into two different objects. \n\t//! One, the object that is passed as parameter to the methods contains only the methods implementation. \n\t//! while the data is inherent from a Proxy object that have a pointer to the object that stores data. \n\n\tPhysicalDesign(PhysicalDesignData * dsg) : Proxy(dsg) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalDesign object with null pointer to the Rsyn::PhysicalDesignData.\n\t//! @details The data and methods in physical design are split into two different objects. \n\t//! One, the object that is passed as parameter to the methods contains only the methods implementation. \n\t//! while the data is inherent from a Proxy object that have a pointer to the object that stores data. \n\n\tPhysicalDesign() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalDesign object with null pointer to the Rsyn::PhysicalDesignData.\n\t//! @details The data and methods in physical design are split into two different objects. \n\t//! One, the object that is passed as parameter to the methods contains only the methods implementation. \n\t//! while the data is inherent from a Proxy object that have a pointer to the object that stores data. \n\n\tPhysicalDesign(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\n\t//! @brief\tloading the technology library specified as LEF to the PhysicalDesign\n\t//! @param\tlibrary is a reference to the descriptor of the technology library inspired in LEF architecture.\n\tvoid loadLibrary(const LefDscp & library);\n\n\n\t//! @brief\tloading the design specified as DEF format to the PhysicalDesign. \n\t//! @details\tPhysicalDesign stores the dimensions of design elements using LEF Database Units resolution. \n\t//! @param\tdesign is a DefDscp reference to the descriptor of the design inspired in DEF architecture.\n\tvoid loadDesign(const DefDscp & design);\n\n\t//! @brief\tInitializes the Rsyn::PhysicalDesignData, the attributes to the Rsyn::Design elements and control parameters.\n\t//! @param\tRsyn::Json &params may be: 1) \"clsEnablePhysicalPins\" true enables Rsyn::PhysicalPin, \n\t//! 2) \"clsEnableMergeRectangles\" true enables merging rectangle bounds to be merged. It does not work to bounds defined as polygon, and \n\t//! 3) \"clsEnableNetPinBoundaries\" true enables storing the pins (Rsyn::Pin) that defines the Bound box boundaries of the nets.\n\t//! 4) \"clsContestMode\" {NONE, ICCAD15} enables legacy support to the contest benchmark.\n\tvoid initPhysicalDesign(Rsyn::Design dsg, const Rsyn::Json &params = {});\n\n\t//! @brief\tSetting the net clock. Otherwise, it is defined as nullptr.\n\tvoid setClockNet(Rsyn::Net net);\n\n\t//! @brief\tUpdating the Bound Box of all design nets. \n\t//! @param\tskipClockNet default is value false. Otherwise, the Bound Box of the clock network is skipped to update and is not added to total HPWL.\n\tvoid updateAllNetBounds(const bool skipClockNet = false);\n\n\t//! @brief\tUpdating the Bound box of method parameter net of the Design.\n\t//! @param\tnet A valid net of the Design.\n\tvoid updateNetBound(Rsyn::Net net);\n\n\t//! @brief\tReturns the Data base resolution. \n\t//! @param\ttype \n\t//! @details\ttype is an enum defined as: Rsyn::LIBRARY_DBU to technology library data base resolution, \n\t//! Rsyn::DESIGN_DBU to the design data base resolution, or \n\t//! Rsyn::MULT_FACTOR_DBU is the integer multiplier of the design data base and library data base resolutions \n\t//! (e.g. 2000 = 1000 * 2 -> DESIGN_DBU = LIBRARY_DBU * MULT_FACTOR_DBU).\n\t//! @return DBU data base resolution of the parameter type.\n\tDBU getDatabaseUnits(const DBUType type) const;\n\t\n\t//! @brief Converts micron value into library database units\n\tDBU convertMicronToLibraryDatabaseUnits(const double value) const;\n\t\n\t//! @brief Converts micron value into design database units\n\tDBU convertMicronToDesignDatabaseUnits(const double value) const;\n\t\n\t//! @brief Returning a DBUxy object that has total nets Bound Box HPWL for abscissa (X dimension in DBUxy) and ordinate (Y dimension in DBUxy).\n\tDBUxy getHPWL() const;\n\n\t//! @param dim\tIt is an enum Dimension X or Y. \n\t//! @brief\tReturning total nets Bound Box HPWL for the parameter dim.\n\tDBU getHPWL(const Dimension dim) const;\n\t//! @brief\tIt returns the number of elements of the parameter type\n\t//! @param\ttype may be: \n\t//! 1) PHYSICAL_FIXED      -> Returning total area of the fixed cells inside of core bounds.\n\t//! 2) PHYSICAL_MOVABLE    -> Returning total area of the movable cells inside of core bounds.\n\t//! 3) PHYSICAL_BLOCK      -> Returning total area of the block cells inside of the core bounds.\n\t//! 4) PHYSICAL_PORT       -> Returning total area of the circuit ports.\n\t//! 5) PHYSICAL_PLACEABLE  -> Returning total area of the rows.\n\t//! @return an integer number\n\tint getNumElements(const PhysicalType type) const;\n\t//! @brief\tIt returns the total area from elements of the parameter type\n\t//! @param\ttype may be: \n\t//! PHYSICAL_FIXED      -> Returning total area of the fixed cells inside of core bounds\n\t//! PHYSICAL_MOVABLE    -> Returning total area of the movable cells inside of core bounds\n\t//! PHYSICAL_BLOCK      -> Returning total area of the block cells inside of the core bounds\n\t//! PHYSICAL_PORT       -> Returning total area of the circuit ports\n\t//! PHYSICAL_PLACEABLE  -> Returning total area of the rows\n\t//! @return The total area in DBU \n\tDBU getArea(const PhysicalType type) const;\n\n\t//! @brief Returns true if the Rsyn::PhysicalPin was enabled. Otherwise, it returns false.\n\t//! @details For some circuits is irrelevant to initialized Rsyn::PhysicalPin. It will only consume memory.\n\tbool isEnablePhysicalPins() const;\n\t//! @brief Returns true if the rectangles that defines the boundary were merged in a small set of them.\n\t//! @details For some circuits, e.g. 2015 ICCAD contest, the boundaries of macros are defined by a set of rectangles. \n\t//! They may be merged into a small set. \n\tbool isEnableMergeRectangles() const;\n\t//! @brief Returns true if the pins that define the Bound box boundaries of the nets were enabled to be stored. \n\t//! Otherwise, it returns false.\n\t//! @details For some circuits or some improvement algorithms \n\t//! is irrelevant to store the pins that defined the boundaries of the bound box of the net. \n\t//! It will only consume memory and runtime.\n\tbool isEnableNetPinBoundaries() const;\n\n\t//! @brief Rsyn::PhysicalLibraryPin related to the Rsyn::LibraryPin libPin.\n\tRsyn::PhysicalLibraryPin getPhysicalLibraryPin(Rsyn::LibraryPin libPin) const;\n\t//! @brief Rsyn::PhysicalLibraryPin related to the Rsyn::Pin pin.\n\tRsyn::PhysicalLibraryPin getPhysicalLibraryPin(Rsyn::Pin pin) const;\n\t//! @brief Rsyn::PhysicalLibraryCell related to the Rsyn::LibraryCell libCell.\n\tRsyn::PhysicalLibraryCell getPhysicalLibraryCell(Rsyn::LibraryCell libCell) const;\n\t//! @brief Rsyn::PhysicalLibraryCell related to the Rsyn::Cell cell.\n\tRsyn::PhysicalLibraryCell getPhysicalLibraryCell(Rsyn::Cell cell) const;\n\n\t//! @brief Update physical data of the Rsyn::PhysicalCell related to cell.\n\tvoid updatePhysicalCell(Rsyn::Cell cell);\n\t//! @brief Remove physical data of the Rsyn::PhysicalCell related to cell.\n\tvoid removePhysicalCell(Rsyn::Cell cell);\n\t//! @brief Rsyn::PhysicalCell related to the Rsyn::Cell cell\n\tRsyn::PhysicalCell getPhysicalCell(Rsyn::Cell cell) const;\n\t//! @brief Rsyn::PhysicalCell related to the Rsyn::Pin pin\n\tRsyn::PhysicalCell getPhysicalCell(Rsyn::Pin pin) const;\n\t//! @brief Rsyn::PhysicalInstance related to the Rsyn::Instance instance\n\tRsyn::PhysicalInstance getPhysicalInstance(Rsyn::Instance instance) const;\n\t//! @brief Rsyn::PhysicalInstance related to the Rsyn::Pin pin\n\tRsyn::PhysicalInstance getPhysicalInstance(Rsyn::Pin pin) const;\n\t//! @brief Rsyn::PhysicalPort related to the Rsyn::Port port\n\tRsyn::PhysicalPort getPhysicalPort(Rsyn::Port port) const;\n\t//! @brief Rsyn::PhysicalPort related to the Rsyn::Pin pin\n\tRsyn::PhysicalPort getPhysicalPort(Rsyn::Pin pin) const;\n\t//! @brief Rsyn::PhysicalModule related to the Rsyn::Module module\n\tRsyn::PhysicalModule getPhysicalModule(Rsyn::Module module) const;\n\t//! @brief Rsyn::PhysicalModule related to the Rsyn::Pin pin\n\tRsyn::PhysicalModule getPhysicalModule(Rsyn::Pin pin) const;\n\t//! @brief return total number of the movable physical cells.\n\t//! @return An integer that is the number of the movable physical cells.\n\tint getNumMovedCells() const;\n\n\t//! @brief Returns the object that store the physical data of the Rsyn::PhysicalDie.\n\tRsyn::PhysicalDie getPhysicalDie() const;\n\t//! @brief if Rsyn::PhysicalPin was initialized, then returns a valid object. Otherwise, returns nullptr.\n\t//! @return Rsyn::PhysicalPin related to the Rsyn::Design Rsyn::Pin pin\n\tRsyn::PhysicalPin getPhysicalPin(Rsyn::Pin pin) const;\n\n\t//! @brief Returns the pin displacement from its cell origen. \n\t//! @details Pin displacement is the distance from cell origen to the pin position inside of cell.\n\t//! The cell origin is the LOWER and LEFT corner. \n\t//! @return Pin displacement in a DBUxy. The distance unit is DBU.\n\tDBUxy getPinDisplacement(Rsyn::Pin pin) const;\n\n\t//! @brief Returns the pin position. The position is the summation of pin displacement and its cell position.\n\tDBUxy getPinPosition(Rsyn::Pin pin) const;\n\t//! @brief Returns the relaxed pin position. \n\t//! @details If pin is related to a physical cell, \n\t//! the pin position is the cell position. Otherwise, the pin position is the summation \n\t//! of the pin displacement and its physical cell position.\n\tDBUxy getRelaxedPinPosition(Rsyn::Pin pin) const;\n\t//! @brief Returns the pin displacement for abscissa or ordinate.\n\t//! @details Pin displacement is the distance from cell origen to the pin position inside of cell.\n\t//! The cell origin is the LOWER and LEFT corner. \n\tDBU getPinDisplacement(Rsyn::Pin pin, const Dimension dim) const;\n\t//! @brief Returns the pin position. The position is the summation of pin displacement and its cell position.\n\tDBU getPinPosition(Rsyn::Pin pin, const Dimension dim) const;\n\n\t//! @brief\tReturns the Rsyn::PhysicalNet object related to the net parameter.\n\tRsyn::PhysicalNet getPhysicalNet(Rsyn::Net net) const;\n\n\t//! @brief\tReturns the Rsyn::PhysicalLayer object associated to the parameter layer name.\n\tRsyn::PhysicalLayer getPhysicalLayerByName(const std::string & layerName);\n\n\t//! @brief\tReturns the Rsyn::PhysicalLayer object associated to the parameter layer index.\n\t//! @details\tThe index is a integer from 0 to less than the number of layers.\n\t//!\t\tIf the the index number is outside of the ranger, than a null reference is returned. \n\tRsyn::PhysicalLayer getPhysicalLayerByIndex(const int index);\n\n\t//! @brief\tReturns the Rsyn::PhysicalLayer object associated to the parameter layer index.\n\t//! @details\tThe index is a integer from 0 to less than the number of layers of the parameter type.\n\t//!\t\tIf the the index number is outside of the ranger, than a null reference is returned. \n\tRsyn::PhysicalLayer getPhysicalLayerByIndex(const Rsyn::PhysicalLayerType layerType, const int index);\n\t//! @brief\tReturns the Rsyn::PhysicalSite object associated to the parameter site name.\n\tRsyn::PhysicalSite getPhysicalSiteByName(const std::string &siteName);\n\t//! @brief\tReturns the Rsyn::PhysicalRegion object associated to the parameter region name.\n\tRsyn::PhysicalRegion getPhysicalRegionByName(const std::string &siteName);\n\t//! @brief\tReturns the Rsyn::PhysicalGroup object associated to the parameter group name.\n\tRsyn::PhysicalGroup getPhysicalGroupByName(const std::string &siteName);\n\t//! @brief\tReturns the Rsyn::PhysicalVia object associated to the parameter vias name.\n\tRsyn::PhysicalVia getPhysicalViaByName(const std::string &viaName);\n\t\n\t//! @brief\tReturns the Rsyn::PhysicalViaRuleBase object associated to the parameter via's name.\n\tRsyn::PhysicalViaRuleBase getPhysicalViaRuleBaseByName(const std::string &viaName);\n\t//! @brief\tReturns the Rsyn::PhysicalViaRule object associated to the parameter via's name.\n\tRsyn::PhysicalViaRule getPhysicalViaRuleByName(const std::string &viaName);\n\t//! @brief\tReturns the Rsyn::PhysicalViaRuleGenerate object associated to the parameter via's name.\n\tRsyn::PhysicalViaRuleGenerate getPhysicalViaRuleGenerateByName(const std::string &viaName);\n\n\t//! @brief\tReturns the total number of layers. It is the summation of routing, overlap, cut, and so forth layers.\n\tint getNumLayers(const Rsyn::PhysicalLayerType type) const;\n\tint getNumLayers() const;\n\t//! @brief\tReturns a reference to the vector of PhysicalLayers. \n\tRange<ListCollection<PhysicalLayerData, PhysicalLayer>> allPhysicalLayers();\n\n\t//! @brief\tReturns the total number of vias.\n\tstd::size_t getNumPhysicalVias() const;\n\t//! @brief\tReturns a vector reference to the vector of PhysicalVias. \n\tconst std::vector<Rsyn::PhysicalVia> & allPhysicalVias() const;\n\n\t\n\t\n\tstd::size_t getNumPhysicalTracks()const;\n\n\tint getNumPhysicalTracks(Rsyn::PhysicalLayer layer) const;\n\n\tconst std::vector<Rsyn::PhysicalTracks> & allPhysicalTracks() const;\n\n\tconst std::vector<Rsyn::PhysicalTracks> & allPhysicalTracks(Rsyn::PhysicalLayer layer) const;\n\n\tbool hasPhysicalTracks(Rsyn::PhysicalLayer layer) const;\n\n    const std::vector<Rsyn::PhysicalGCell>& allPhysicalGCell() const;\n\n    const std::vector<Rsyn::PhysicalRoutingGrid> & allPhysicalRoutingGrids() const;\n\n\tRsyn::PhysicalRoutingGrid getPhysicalRoutingGrid(Rsyn::PhysicalLayer layer) const;\n\n\tbool hasPhysicalRoutingGrid(Rsyn::PhysicalLayer layer) const;\n\n\tint getNumPhysicalRoutingGrids() const;\n\t\n\t//! @brief check if the orientations are equivalent based on symmetry.\n\tbool checkEquivalentOrientations(Rsyn::PhysicalSymmetry symmetry, Rsyn::PhysicalOrientation orient1, Rsyn::PhysicalOrientation orient2) const;\n\n\t//! @brief\tReturns the total number of spacing objects.  \n\tstd::size_t getNumPhysicalSpacing() const;\n\t//! @brief\tReturns a reference to the vector of PhysicalSpacing. \n\tRange<ListCollection<PhysicalSpacingData, PhysicalSpacing>> allPhysicalSpacing() const;\n\n\t//! @brief\tReturns the total number of region objects.  \n\tstd::size_t getNumPhysicalRegions() const;\n\t//! @brief\tReturns a reference to the range list of PhysicalRegion. \n\tstd::vector<PhysicalRegion> & allPhysicalRegions() const;\n\n\t//! @brief\tReturns the total number of group objects.  \n\tstd::size_t getNumPhysicalGroups() const noexcept;\n\t//! @brief\tReturns a reference to the range list of PhysicalGroup. \n\tstd::vector<PhysicalGroup> & allPhysicalGroups() const;\n\t//! @brief\tReturns the total number of physical special nets.  \n\tstd::size_t getNumPhysicalSpecialNets() const noexcept;\n\t//! @brief Returns a constant reference to a vector of physical special nets.\n\tstd::vector<PhysicalSpecialNet> & allPhysicalSpecialNets() const;\n\n\t//! @brief Returns the row height. It is assumed all rows have the same height.\n\t//! The row height of the first row is returned.\n\t//I'm assuming all rows have the same height.\n\tDBU getRowHeight() const;\n\t//! @brief Returns the row site width. It is assumed all rows have the same site width.\n\t//! The row site width of the first row is returned.\n\tDBU getRowSiteWidth() const;\n\t//! @brief Returns the total number of row objects.\n\tstd::size_t getNumRows() const;\n\t//! @brief Iterates over all Physical Rows. \n\tRange<ListCollection<PhysicalRowData, PhysicalRow>> allPhysicalRows();\n\n\t//! @brief Returns the LayersViasManager\n\t//! @comment Given a layer is possible to get all vias which connect to the bottom or top routing layers.\n\tRsyn::LayerViaManager getLayerViaManager() const;\n\nprotected:\n\t//! @brief initializes the Rsyn::PhysicalSite objects into Rsyn::PhysicalDesign.\n\tvoid addPhysicalSite(const LefSiteDscp & site);\n\t//! @brief initializes the Rsyn::PhysicalLayer objects into Rsyn::PhysicalDesign.\n\tRsyn::PhysicalLayerData * addPhysicalLayer(lefiLayer* layer, Rsyn::PhysicalLayerData * lower);\n\t//! @brief initializes the Rsyn::PhysicalVia objects into Rsyn::PhysicalDesign.\n\tvoid addPhysicalVia(const LefViaDscp & via);\n\t//! @brief initializes the Rsyn::PhysicalViaRule objects\n\tvoid addPhysicalViaRule(const LefViaRuleDscp & via);\n\t//! @brief initializes the Rsyn::PhysicalLibraryCell objects into Rsyn::PhysicalDesign.\n\tRsyn::LibraryCell addPhysicalLibraryCell(const LefMacroDscp& macro);\n\t//! @brief initializes the Rsyn::PhysicalLibraryPin objects of the library cell into \n\t//! Rsyn::PhysicalDesign.\n\tvoid addPhysicalLibraryPin(Rsyn::LibraryCell libCell, const LefPinDscp& lefPin);\n\t//! @brief initializes the Rsyn::PhysicalInstance object as Rsyn::PhysicalCell into Rsyn::PhysicalDesign.\n\tvoid addPhysicalCell(Rsyn::Instance cell, const DefComponentDscp& component);\n\t//! @brief initializes the Rsyn::PhysicalInstance object as Rsyn::PhysicalPort into Rsyn::PhysicalDesign.\n\tvoid addPhysicalPort(Rsyn::Instance cell, const DefPortDscp& port);\n\t//! @brief initializes the Rsyn::PhysicalRow objects into Rsyn::PhysicalDesign.\n\tvoid addPhysicalRow(const DefRowDscp& defRow);\n\t//! @brief initializes the Rsyn::PhysicalRegion objects into Rsyn::PhysicalDesign.\n\tvoid addPhysicalRegion(const DefRegionDscp& defRegion);\n\t//! @brief initializes the Rsyn::PhysicalGroup objects into Rsyn::PhysicalDesign.\n\tvoid addPhysicalGroup(const DefGroupDscp& defGroup);\n\t//! @brief Initializes Rsyn::PhysicalNetObject into Ryn::PhysicalDesign.\n\t//! @warning Only initializes routed wires.\npublic: // Temporary for the contest debug\n\tvoid addPhysicalNet(const DefNetDscp & netDscp);\nprotected:\n\t//! @brief Initializes Rsyn::PhysicalSpecialNet into Ryn::PhysicalDesign.\n\tvoid addPhysicalSpecialNet(const DefNetDscp & specialNet);\n\t//! @brief Adds a track.\n\tvoid addPhysicalTracks(const DefTrackDscp &track);\n\t//! @brief Inits routing grid\n\tvoid initRoutingGrid();\n\t//! @brief Adds a gcell.\n\tvoid addPhysicalGCell(const DefGcellGridDscp &gcell);\n\t//! @brief Adds design via.\n\tvoid addPhysicalDesignVia(const DefViaDscp & via);\n\t//! @brief initializes the Rsyn::PhysicalSpacing objects into Rsyn::PhysicalDesign.\n\tvoid addPhysicalSpacing(const LefSpacingDscp & spacing);\n\t//! @brief initializes the Rsyn::PhysicalPin objects into Rsyn::PhysicalDesign.\n\t//! @todo Implements this method\n\tvoid addPhysicalPin();\n\n\t//! @brief Merges the rectangles that defines the boundary in a small set of them.\n\t//! @details For some circuits, e.g. 2015 ICCAD contest, the boundaries of macros are defined by a set of rectangles. \n\t//! They may be merged into a small set.\n\t//! @warning works only for rectangles \n\tvoid mergeBounds(const std::vector<Bounds> & source, std::vector<Bounds> & target, const Dimension dim = X);\n\n\t//! @brief inits the manager of the layers and vias.\n\tvoid initLayerViaManager();\n\nprivate:\n\t//! @brief Returns the Rsyn::PhysicalRow unique identifier.\n\tPhysicalIndex getId(Rsyn::PhysicalRow phRow) const;\n\n\t//! @brief Returns the Rsyn::PhysicalLayer unique identifier.\n\tPhysicalIndex getId(Rsyn::PhysicalLayer phLayer) const;\n\n\t//! @brief Returns the Rsyn::PhysicalSpacing unique identifier.\n\tPhysicalIndex getId(Rsyn::PhysicalSpacing spacing) const;\n\npublic:\n\t//! @details Creates the physical object to handle the physical object extensions.\n\t//! The extension maps the physical object to a null reference.\n\tPhysicalAttributeInitializer createPhysicalAttribute();\n\n\t//! @details Creates the physical object to handle the physical object extensions.\n\t//! The extension maps the physical object to the default parameter data.\n\ttemplate<typename DefaultPhysicalValueType>\n\tPhysicalAttributeInitializerWithDefaultValue<DefaultPhysicalValueType>\n\tcreatePhysicalAttribute(const DefaultPhysicalValueType &defaultValue);\n\npublic:\n\n\t//! @brief typedef for callback to the moved instances. \n\ttypedef std::function<void(Rsyn::PhysicalInstance instance) > PostInstanceMovedCallback;\n\t//! @brief list of registered call backs. \n\ttypedef std::list<std::tuple<int, PostInstanceMovedCallback>>::iterator PostInstanceMovedCallbackHandler;\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Placement\n\t////////////////////////////////////////////////////////////////////////////\t\n\t//! @brief places the Rsyn::PhysicalCell at defined position.\n\t//! @warning Caution when using dontNotifyObservers.\n\t//! We can use it when you may expect the move to be rolled back, but it is\n\t//! not, recall to mark the cell as dirty.\n\tvoid placeCell(Rsyn::PhysicalCell physicalCell, const DBU x, const DBU y,\n\t\tRsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool dontNotifyObservers = false);\n\t//! @brief places the Rsyn::PhysicalCell at defined position.\n\t//! @warning Caution when using dontNotifyObservers.\n\t//! We can use it when you may expect the move to be rolled back, but it is\n\t//! not, recall to mark the cell as dirty.\n\tvoid placeCell(Rsyn::Cell cell, const DBU x, const DBU y,\n\t\tRsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool dontNotifyObservers = false);\n\t//! @brief places the Rsyn::PhysicalCell at defined position.\n\t//! @warning Caution when using dontNotifyObservers.\n\t//! We can use it when you may expect the move to be rolled back, but it is\n\t//! not, recall to mark the cell as dirty.\n\tvoid placeCell(Rsyn::PhysicalCell physicalCell, const DBUxy pos,\n\t\tRsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool dontNotifyObservers = false);\n\t//! @brief places the Rsyn::PhysicalCell at defined position.\n\t//! @warning Caution when using dontNotifyObservers.\n\t//! We can use it when you may expect the move to be rolled back, but it is\n\t//! not, recall to mark the cell as dirty.\n\tvoid placeCell(Rsyn::Cell cell, const DBUxy pos,\n\t\tRsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool dontNotifyObservers = false);\n        \n        //Place Port \n        \n        Rsyn::PhysicalOrientation checkOrientation(Rsyn::PhysicalPort physicalPort, \n                const DBU x, const DBU y);\n        \n        DBUxy checkPosition(const DBU x, const DBU y);\n        \n        bool getPhysicalPortByName(std::string name, Rsyn::PhysicalPort &phPort);\n        \n        void placePort(Rsyn::PhysicalPort physicalPort, const DBU x, const DBU y, \n                Rsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n                const bool disableSnapping = false, const bool dontNotifyObservers = false);\n        \n        void placePort(Rsyn::Port port, const DBU x, const DBU y,\n                Rsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool disableSnapping = false, const bool dontNotifyObservers = false);\n        \n        void placePort(Rsyn::PhysicalPort physicalPort, const DBUxy pos,\n\t\tRsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool disableSnapping = false, const bool dontNotifyObservers = false);\n        \n        void placePort(Rsyn::Port port, const DBUxy pos,\n\t\tRsyn::PhysicalOrientation orient = ORIENTATION_INVALID,\n\t\tconst bool disableSnapping = false, const bool dontNotifyObservers = false);\n\t\n\t//! @brief set cell orientation.\n\t//! @warning Caution when using dontNotifyObservers.\n\t//! We can use it when you may expect the move to be rolled back, but it is\n\t//! not, recall to mark the cell as dirty.\n\tvoid setCellOrientation(Rsyn::PhysicalCell physicalCell, Rsyn::PhysicalOrientation orient,\n\t\tconst bool dontNotifyObservers = false);\n\t//! @brief set cell orientation.\n\t//! @warning Caution when using dontNotifyObservers.\n\t//! We can use it when you may expect the move to be rolled back, but it is\n\t//! not, recall to mark the cell as dirty.\n\tvoid setCellOrientation(Rsyn::Cell cell, Rsyn::PhysicalOrientation orient,\n\t\tconst bool dontNotifyObservers = false);\n\t\n\tvoid flipCell(Rsyn::PhysicalCell physicalCell, const bool dontNotifyObservers = false);\n\t\n\tvoid flipCell(Rsyn::Cell cell, const bool dontNotifyObservers = false);\n\n\t//! @brief Explicitly notify observer that a cell was moved. This is only necessary\n\t//! if \"dontNotifyObservers = true\" in \"placeCell\" methods.\n\t//! @todo Remove\n\tvoid notifyInstancePlaced(Rsyn::Instance instance, Rsyn::DesignObserver *ignoreObserver = nullptr);\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Routing\n\t////////////////////////////////////////////////////////////////////////////\n\n\tvoid setNetRouting(Rsyn::Net net, const PhysicalRouting &routing);\n\tvoid clearNetRouting(Rsyn::Net net);\n\tconst PhysicalRouting &getNetRouting(Rsyn::Net net) const;\n\tbool isNetRouted(Rsyn::Net net) const;\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Notifications\n\t////////////////////////////////////////////////////////////////////////////\t\npublic:\n\n\t//! @brief Registers an observer to be notified about changes in the\n\t//!        netlist.\n\ttemplate<class T>\n\tvoid registerObserver(T *observer);\n\n\t//! @brief Unregisters an observer so it will no longer receives\n\t//!        notifications about changes in the netlist.\n\tvoid unregisterObserver(PhysicalDesignObserver *observer);\n\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALDESIGN_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalDie.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalDie.h\n * Author: jucemar\n *\n * Created on 4 de Fevereiro de 2017, 08:45\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALDIE_H\n#define PHYSICALDESIGN_PHYSICALDIE_H\n\nnamespace Rsyn {\n\nclass PhysicalDie : public Proxy<PhysicalDieData> {\n\tfriend class PhysicalDesign;\nprotected:\n\tPhysicalDie(PhysicalDieData * data) : Proxy(data) {}\npublic:\n\t//! @brief\tDefault constructor. Rectangular bounds are initialized to Bounds(DBUxy(0,0), DBUxy(0,0)).\n\t//!\t\tPhysicalDieData pointer is initialized to nullptr.\t\t\n\t//! @note\tDie is assumed to be a rectangle. It does not support die defined as a polygon.\n\tPhysicalDie()  {}\n\t//! @brief \n\tPhysicalDie(std::nullptr_t)  {}\n\n\t//! @brief\tReturns the coordinate (x,y) of the boundary Rsyn::LOWER or Rsyn::UPPER of the die.\n\tDBUxy getCoordinate(const Boundary bound) const;\n\t//! @brief\tReturns the coordinate X or Y of the boundary Rsyn::LOWER or Rsyn::UPPER of the die.\n\tDBU getCoordinate(const Boundary bound, const Dimension dim) const;\n\t//! @brief\tReturns constant reference to Bounds objects.\n\tconst Bounds & getBounds() const;\n\t//! @brief\tReturns the dimension length for abscissa (X) or ordinate (Y).\n\tDBU getLength(const Dimension dim) const;\n\t//! @brief\tReturns the coordinate X or Y of the boundary LOWER or UPPER of the die.\n\tDBUxy getPosition(const Boundary boundary = LOWER) const;\n\t//! @brief\tReturns the central position (X, Y) in DBU units of the die bounds.\n\tDBUxy getCenterPosition() const;\n\t//! @brief\tReturns total area of the PhysicalDie Bounds.\n\tDBU getArea() const;\n}; //end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALDIE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalGCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef PHYSICALGCELL_H\n#define PHYSICALGCELL_H\n\nnamespace Rsyn {\n\nclass PhysicalGCell : public Proxy<PhysicalGCellData> {\n\tfriend class PhysicalDesign;\nprotected:\n\tPhysicalGCell(PhysicalGCellData * data) : Proxy(data) {}\npublic:\n\t//! @brief\tDefault constructor. \n\t//!\t\tPhysicalGCellData pointer is initialized to nullptr.\t\t\n\tPhysicalGCell()  {}\n\t//! @brief \n\tPhysicalGCell(std::nullptr_t)  {}\n\t\n\t//! @brief Returns GCell direction\n\tRsyn::PhysicalGCellDirection getDirection() const;\n\t\n\t//! @brief If direction is vertical, then numTracks means the number of columns\n\t//! If direction is Horizontal, then numTracks means the number of rows\n\tint getNumTracks() const;\n\t//! @brief If direction is Horizontal, then location is Y value.\n\t//! If direction is vertical, then location is X value.\n\tDBU getLocation() const;\n\n\t//! @brief Returns the spacing between GCell tracks. \n\tDBU getStep() const;\n}; // end class \n} // end namespace \n\n#endif /* PHYSICALGCELL_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalGroup.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalGroup.h\n * Author: jucemar\n *\n * Created on 09 de Abril de 2017, 16:45\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALGROUP_H\n#define PHYSICALDESIGN_PHYSICALGROUP_H\n\nnamespace Rsyn {\n\nclass PhysicalGroup : public Proxy<PhysicalGroupData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalGroup object with a pointer to Rsyn::PhysicalGroupData.\n\n\tPhysicalGroup(PhysicalGroupData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalGroup object with a null pointer to Rsyn::PhysicalGroupData.\n\n\tPhysicalGroup() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalGroup object with a null pointer to Rsyn::PhysicalGroupData.\n\n\tPhysicalGroup(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\n\t//! @brief Returns region's name\n\tconst std::string & getName() const;\n\t//! @brief Returns the PhysicalRegion object associated to PhysicalGroup.\n\tRsyn::PhysicalRegion getPhysicalRegion() const;\n\t//! @brief Returns the constant reference to the Region patters vector.\n\tconst std::vector<std::string> & allPatterns() const;\n\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALGROUP_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalInstance.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalInstance.h\n * Author: jucemar\n *\n * Created on 4 de Outubro de 2016, 13:22\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALINSTANCE_H\n#define PHYSICALDESIGN_PHYSICALINSTANCE_H\n\nnamespace Rsyn {\nclass PhysicalInstance : public Proxy<PhysicalInstanceData> {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalInstance object with a pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalInstance(PhysicalInstanceData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalInstance object with a null pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalInstance()  {}\n\t//! @brief Constructs a Rsyn::PhysicalInstance object with a null pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalInstance(std::nullptr_t)  {}\n\t\n\t//! @brief Returns the Instance associated to PhysicalInstance \n\tRsyn::Instance getInstance() const;\n\t//! @brief Returns the name of this instance.\n\tconst std::string &getName() const;\n\t//! @brief Returns the instance area in DBU.\n\tDBU getArea() const;\n\t//! @brief Returns the central point of the PhysicalInstance boundaries.\n\tDBUxy getCenter() const;\n\t//! @brief Returns the central position of the PhysicalInstance boundaries for the given dimension.\n\tDBU getCenter(const Dimension dim) const;\n\t//! @brief Returns the x position of the instance.\n\tDBU getX() const;\n\t//! @brief Returns the y position of the instance.\n\tDBU getY() const;\n\t//! @brief Returns the Instance height. It is the length of PhysicalInstance boundaries is Y dimension.\n\tDBU getHeight() const;\n\t//! @brief Returns the Instance width. It is the length of PhysicalInstance boundaries is X dimension.\n\tDBU getWidth() const;\n\t//! @brief Returns the length of PhysicalInstance boundaries for given dimension\n\tDBU getSize(const Dimension dimension) const;\n\t//! @brief Returns the length of PhysicalInstance boundaries. \n\t//! In X is the length for abscissa (width) while in Y is the length for ordinate (height).\n\tDBUxy getSize() const;\n\t//! @brief Returns the left-lower PhysicalInstance point that is defined as its position.\n\tDBUxy getPosition() const;\n\t//! @brief Returns the left-lower PhysicalInstance point for the given dimension \n\t//! that is defined as its position.\n\tDBU getPosition(const Dimension dim) const;\n\t//! @brief Returns the PhysicalInstance point for the given boundary (LOWER or UPPER).\n\tDBUxy getCoordinate(const Boundary bound) const;\n\t//! @brief Returns the PhysicalInstance point for the given boundary (LOWER or UPPER) and dimension (X or Y).\n\tDBU getCoordinate(const Boundary bound, const Dimension dim) const;\n\t//! @brief Returns the orientation of the cell.\n\tPhysicalOrientation getOrientation() const;\n\t//! @brief Returns the bound box Bounds that defines the limits of PhysicalInstance.\n\tconst Bounds &getBounds() const;\n\t\n\tRsyn::PhysicalCell asPhysicalCell() const;\n\t\n\t// Mateus and Isadora @ 2018/03/19\n\t// Maybe it should be moved to PhysicalInstanceData?\n\t// Used in map-like data structures.\n\tfriend bool operator<(const PhysicalInstance &left, const PhysicalInstance &right) {\n\t\t// [IMPORTANT] We don't use the pointer (e) directly to avoid\n\t\t// non-determinism behavior. Note that the pointer address may change\n\t\t// from execution to execution and hence the mapping function may return\n\t\t// elements in different order leading to different results.\n\t\treturn left.getInstance() < right.getInstance();\n\t} // end method\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALINSTANCE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalLayer.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalLayer.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 19:12\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALLAYER_H\n#define PHYSICALDESIGN_PHYSICALLAYER_H\n\n\n\nnamespace Rsyn {\n\nclass PhysicalLayer : public Proxy<PhysicalLayerData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tfriend class PhysicalViaGeometry;\n\tfriend class PhysicalViaRuleBase;\n\tfriend class PhysicalViaRule;\n\tfriend class PhysicalViaRuleGenerate;\n\tfriend class PhysicalVia;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalLayer object with a pointer to Rsyn::PhysicalLayerData.\n\tPhysicalLayer(PhysicalLayerData * data) : Proxy(data) {\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalLayer object with a null pointer to Rsyn::PhysicalLayerData.\n\tPhysicalLayer() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalLayer object with a null pointer to Rsyn::PhysicalLayerData.\n\tPhysicalLayer(std::nullptr_t) : Proxy(nullptr) {}\n\t\n\t//! @brief Returns the Rsyn::PhysicalLayer layer.\n\tlefiLayer* getLayer() const;\n\t//! @brief Returns the Rsyn::PhysicalLayer name.\n\tstd::string getName() const;\n\t//! @brief Returns the layer type (ROUTING, CUT, OVERLAP, MASTERSLICE, or IMPLANT).\n\tRsyn::PhysicalLayerType getType() const;\n\t//! @brief Returns the layer width in DBU.\n\tDBU getWidth() const;\n\t//! @brief Returns the layer index w.r.t to all physical layers. It starts\n\t//!        from 0 that is the bottom layer\n\t//! @note  If you need an index relative to the layer type, see\n\t//!        getRelativeIndex().\n\tint getIndex() const;\n\t//! @brief Returns the relative layer index w.r.t. the layers of same type.\n\tint getRelativeIndex() const;\n\t\n\tRsyn::PhysicalLayer getPhysicalLayerLower() const;\n\tRsyn::PhysicalLayer getPhysicalLayerUpper() const;\n\t\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALLAYER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalLibraryCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalLibraryCell.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 22:10\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALLIBRARYCELL_H\n#define PHYSICALDESIGN_PHYSICALLIBRARYCELL_H\n\nnamespace Rsyn {\n\nclass PhysicalLibraryCell : public Proxy<PhysicalLibraryCellData> {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalLibraryCell object with a pointer to Rsyn::PhysicalLibraryCellData.\n\tPhysicalLibraryCell(PhysicalLibraryCellData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalLibraryCell object with a null pointer to Rsyn::PhysicalLibraryCellData.\n\tPhysicalLibraryCell() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalLibraryCell object with a null pointer to Rsyn::PhysicalLibraryCellData.\n\tPhysicalLibraryCell(std::nullptr_t) : Proxy(nullptr) {}\n\t\n\t//! @brief Returns the PhysicalLibraryCell macro. \n\tlefiMacro* getMacro() const;\n\t//! @brief Returns the PhysicalLibraryCell size. \n\t//! @brief In dimension X is the PhysicalLibraryCell width while in Y is the PhysicalLibraryCell height.\n\tDBUxy getSize() const;\n\t//! @brief Returns a DBU type that represents the PhysicalLibraryCell width.\n\tDBU getWidth() const;\n\t//! @brief Returns a DBU type that represents the PhysicalLibraryCell height.\n\tDBU getHeight() const;\n\t//! @brief Returns a DBU type that represents the PhysicalLibraryCell length in Dimension parameter dim.\n\tDBU getLength(const Dimension dim) const;\n\t//! @brief Returns the library cell bounds.\n\tBounds getBounds() const;\n\t//! @brief Returns true if the PhysicalLibraryCell has defined rectangular obstacle Bounds.\n\tbool hasLayerObstacles() const;\n\tbool hasObstacles() const;\n\t//! @brief Returns PhysicalSite object related to the PhysicalLibraryCell.\n\tRsyn::PhysicalSite getSite() const;\n\t//! @breif Returns true if there is a top layer obstacle. The top layer obs is the highest metal layer blockage.\n\tbool hasTopLayerObstacle() const;\n\t//! @breif Returns the top layer obstacle. The top layer obs is the highest metal layer blockage.\n\tRsyn::PhysicalObstacle getTopLayerObstracle() const;\n\t//! @brief Returns a constant vector reference to PhysicalObstacle objects that \n\t//! represent the  metal layers blocked in the top of the PhysicalLibraryCell.\n\tconst std::vector<Rsyn::PhysicalObstacle> & allObstacles() const ;\n\t//! @brief Returns the total number of metal layer (PhysicalObstacle) blocked in the top of the PhysicalLibraryCell.\n\tstd::size_t getNumObstacles() const; \n\t\n\t//! @brief Returns the number of cell layer boundaries. \n\t//! @details In 2015 ICCAD contest, the boundaries for some macros are defined by one of the PhysicalLayer, \n\t//! i.e., the PhysicalLibaryCellboundaries are defined by metal1 boundaries. \n\t//! return 0  if the cell boundaries is not defined by one of layer metal. \n\t//! Otherwise returns the number of rectangles that composes the cell boundary\n\t//! @warning This method affects 2015 ICCAD contest benchmark.\n\tstd::size_t getNumPhysicalCellLayerBoundaries() const; \n\t//! @brief Returns the PhysicalObstacle  that defines the cell boundary for 2015 ICCAD contest benchmark.\n\t//! @details In 2015 ICCAD contest, the boundaries for some macros are defined by one of the PhysicalLayer, \n\t//! i.e., the PhysicalLibaryCellboundaries are defined by metal1 boundaries. \n\t//! @warning This method affects 2015 ICCAD contest benchmark.\n\tRsyn::PhysicalObstacle getLayerObstacles() const;\n\t//! @brief Returns a transformation that allows one to transform the\n\t//! coordinates according to a cell orientation.\n\tPhysicalTransform getTransform(const Rsyn::PhysicalOrientation &orientation) const;\n\t//! @brief Returns a constant reference vector to all Bounds that defines the cell boundary for 2015 ICCAD contest benchmark.\n\t//! @details In 2015 ICCAD contest, the boundaries for some macros are defined by one of the PhysicalLayer, \n\t//! i.e., the PhysicalLibaryCellboundaries are defined by metal1 boundaries. \n\t//! @warning This method affects 2015 ICCAD contest benchmark.\n\tconst std::vector<Bounds> & allLayerObstacles() const;\n\t\n\t\n\t\n\tbool hasPolygonBoundaries() const;\n\tconst Polygon & getPolygonBoundaries() const;\n\t\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALLIBRARYCELL_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalLibraryPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalLibraryPin.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 21:06\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALLIBRARYPIN_H\n#define PHYSICALDESIGN_PHYSICALLIBRARYPIN_H\n\nnamespace Rsyn {\n\nclass PhysicalLibraryPin : public Proxy<PhysicalLibraryPinData> {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalLibraryPin object with a pointer to Rsyn::PhysicalLibraryPinData.\n\tPhysicalLibraryPin(PhysicalLibraryPinData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalLibraryPin object with a null pointer to Rsyn::PhysicalLibraryPinData.\n\tPhysicalLibraryPin() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalLibraryPin object with a null pointer to Rsyn::PhysicalLibraryPinData.\n\tPhysicalLibraryPin(std::nullptr_t) : Proxy(nullptr) {}\n\n\t//! @brief REturns the physical library cell of this pin.\n\tPhysicalLibraryCell getPhysicalLibraryCell() const;\n\t//! @brief Returns the pin rectangular boundaries defined at 2015 ICCAD contest.\n\tBounds getICCADBounds();\n\t//! @brief Returns the pin rectangular boundaries reference defined at 2015 ICCAD contest.\n\tconst Bounds & getICCADBounds() const;\n\t//! @brief Returns a vector reference to PhysicalPinGeometry objects related to the PhysicalLibraryPin.\n\tstd::vector<PhysicalPinGeometry> & allPinGeometries();\n\t//! @brief Returns a constant vector reference to PhysicalPinGeometry objects related to the PhysicalLibraryPin.\n\tconst std::vector<PhysicalPinGeometry> & allPinGeometries() const;\n\t//! @brief Returns an integer number that is the total number of PhysicalPinGeometry related to the PhysicalLibraryPin.\n\tstd::size_t getNumPinGeometries() const;\n\t//! @brief Returns true if PhysicalLibraryPin has PhysicalPinGeometry objects. Otherwise, returns false.\n\tbool hasPinGeometries() const;\n\t//! @brief Returns true if PhysicalLibraryPin has no PhysicalPinGeometry objects. Otherwise, returns false.\n\tbool isEmptyPinGeometries() const;\n\t//! @brief Returns an enum indicating the pin direction. \n\tPhysicalPinDirection getPinDirection() const;\n\t//! @brief Returns an enum of PhysicalPinUse that gives the PhysicalPin usage type.\n\tPhysicalPinUse getUse() const;\n}; // end class  \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALLIBRARYPIN_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalModule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalModule.h\n * Author: jucemar\n *\n * Created on 4 de Outubro de 2016, 20:34\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALMODULE_H\n#define PHYSICALDESIGN_PHYSICALMODULE_H\n\nnamespace Rsyn {\n\nclass PhysicalModule : public PhysicalInstance {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalModule object with a pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalModule(PhysicalInstanceData * data) : PhysicalInstance(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalModule object with a null pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalModule() : PhysicalInstance(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalModule object with a null pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalModule(std::nullptr_t) : PhysicalInstance(nullptr) {}\n}; // end class\n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALMODULE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalNet.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   PhysicalNet.h\n * Author: jucemar\n *\n * Created on 15 de Setembro de 2016, 19:16\n */\n\n#ifndef RSYN_PHYSICAL_NET_H\n#define RSYN_PHYSICAL_NET_H\n\nnamespace Rsyn { \n\nclass PhysicalNet : public Proxy<PhysicalNetData> {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalNet object with a pointer to Rsyn::PhysicalNetData.\n\tPhysicalNet(PhysicalNetData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalNet object with a null pointer to Rsyn::PhysicalNetData.\n\tPhysicalNet() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalNet object with a null pointer to Rsyn::PhysicalNetData.\n\tPhysicalNet(std::nullptr_t) : Proxy(nullptr) {}\n\n\t//! @brief Returns the net associated to this physical net.\n\tRsyn::Net getNet() const;\n\t//! @brief Returns the name of the physical net.\n\tstd::string getName() const;\n\t//! @brief Returns the semi perimeter of the Bound Box from PhysicalNet.\n\t//! @details In X is the length of net Bound Box for abscissa and in Y is \n\t//! the length of net Bound Box for ordinate. \n\tDBUxy getHPWL() const;\n\t//! @brief Returns the length of the Bound Box from PhysicalNet in the given dimension.\n\tDBU getHPWL(const Dimension dim);\n\t//! @brief Returns a constant reference to the bound box of the PhysicalNet.\n\t//! @details Bound box units is DBU. Its boundary limits are defined by the two most\n\t//! distant each other pins for each dimension. \n\tconst Bounds & getBounds() const;\n\t//! @brief Returns the point coordinate of the net bound box. The points that \n\t//! determine the Bounds are left-lower and upper-right.\n\tDBUxy getCoordinate(const Boundary bound) const ;\n\t//! @brief Returns the point coordinate for the given dimension of the net bound box.\n\t//! The points that determine the Bounds are left-lower and upper-right.\n\tDBU getCoordinate(const Boundary bound, const Dimension dim) const;\n\t//! @brief Return the PhysicalPin object that determines the boundary of PhysicalNet \n\t//! in one of its demensions.\n\tRsyn::Pin getPinBoundary(const Boundary bound, const Dimension dim) const;\n\t//! @brief Returns the physical routing of this net.\n\tconst PhysicalRouting &getRouting() const;\n\t//! @brief Returns true if the net is routed (has a non-empty routing).\n\tbool isRouted() const;\n}; // end class \n\n} // end namespace \n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalObstacle.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalObstacle.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 20:08\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALOBSTACLE_H\n#define PHYSICALDESIGN_PHYSICALOBSTACLE_H\n\nnamespace Rsyn {\n\nclass PhysicalObstacle : public Proxy < PhysicalObstacleData > { \n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalObstacle object with a pointer to Rsyn::PhysicalObstacleData.\n\tPhysicalObstacle(PhysicalObstacleData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalObstacle object with a null pointer to Rsyn::PhysicalObstacleData.\n\tPhysicalObstacle() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalObstacle object with a null pointer to Rsyn::PhysicalObstacleData.\n\tPhysicalObstacle(std::nullptr_t) : Proxy(nullptr) {}\n\t\n\t//! @brief Returns the Rsyn::PhysicalLayer object related to the current Rsyn::PhysicalObstacle.\n\tRsyn::PhysicalLayer getLayer() const;\n\t//! @brief Returns the vector of rectangular Bounds in the Rsyn::PhysicalObstacle.\n\tconst std::vector<Bounds> & allBounds() const;\n\t//! @brief Returns the total number of rectangular Bounds in the Rsyn::PhysicalObstacle.\n\tstd::size_t getNumObs() const;\n\t//! @brief Returns true if Rsyn::PhysicalObstacle has a Rsyn::PhysicalLayer object defined. \n\t//! Otherwise, returns false.\n\tbool hasLayer() const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALOBSTACLE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPin.h\n * Author: jucemar\n *\n * Created on 14 de Setembro de 2016, 21:26\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPIN_H\n#define PHYSICALDESIGN_PHYSICALPIN_H\n\nnamespace Rsyn {\n\nclass PhysicalPin : public Proxy<PhysicalPinData> {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalPin object with a pointer to Rsyn::PhysicalPinData.\n\tPhysicalPin(PhysicalPinData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalPin object with a null pointer to Rsyn::PhysicalPinData.\n\tPhysicalPin() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalPin object with a null pointer to Rsyn::PhysicalPinData.\n\tPhysicalPin(std::nullptr_t) : Proxy(nullptr) {}\n\n\t//! @brief Returns the pin displacement. \n\t//! @details The displacement are independent to abscissa (X) and ordinate (X).\n\t//! The origin to compute pin displacement is the Left-Lower cell point and it is assumed to be (0,0). \n\t//! @warning It was assumed the pin has a fixed position in the cell.\n\tDBUxy getDisplacement () const;\n\t//! @brief Returns the pin displacement to the Dimension parameter dim.\n\t//! @details The displacement are independent to abscissa (X) and ordinate (X).\n\t//! The origin to compute pin displacement is the Left-Lower cell point and it is assumed to be (0,0). \n\t//! @warning It was assumed the pin has a fixed position in the cell.\n\tDBU getDisplacement(const Dimension dim);\n\t//! @brief Returns a vector reference to PhysicalPinGeometry objects related to PhysicalPin. \n\tstd::vector<PhysicalPinGeometry> & allPinGeometries();\n\t//! @brief Returns a constant vector reference to PhysicalPinGeometry objects related to PhysicalPin.\n\tconst std::vector<PhysicalPinGeometry> & allPinGeometries() const;\n\t//! @brief Returns the total number of PhysicalPinGeometry objects related to PhysicalPin.\n\tstd::size_t getNumPinGeometries() const;\n\t//! @brief Returns true if PhysicalPin has PhysicalPinGeometry objects. Otherwise, returns false.\n\tbool hasPinGeometries() const;\n\t//! @brief Returns true if PhysicalPin has no PhysicalPinGeometry objects. Otherwise, returns false.\n\tbool isEmptyPinGeometries() const;\n\t//! @brief Returns an enum of PhysicalPinDirection that gives the PhysicalPin direction.\n\tPhysicalPinDirection getDirection () const;\n\t//! @brief Returns a constant reference to the Bounds object that defines the PhysicalPin boundaries.\n\t//! it is is defined by one of the layer.\n\tconst Bounds & getLayerBounds() const;\n\t\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALPIN_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalPinGeometry.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPinGeometry.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 21:13\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPINGEOMETRY_H\n#define PHYSICALDESIGN_PHYSICALPINGEOMETRY_H\n\nnamespace Rsyn {\n\nclass PhysicalPinGeometry : public Proxy<PhysicalPinGeometryData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalPinGeometry object with a pointer to Rsyn::PhysicalPinGeometryData.\n\tPhysicalPinGeometry(PhysicalPinGeometryData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalPinGeometry object with a null pointer to Rsyn::PhysicalPinGeometryData.\n\tPhysicalPinGeometry() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalPinGeometry object with a null pointer to Rsyn::PhysicalPinGeometryData.\n\tPhysicalPinGeometry(std::nullptr_t) : Proxy(nullptr) {}\n\t\n\t//! @brief Returns the PhysicalPinGeometryClass type of the PhysicalPinLayer.\n\t//! @details A PhysicalPinGeometryClass may be: 1) PINGEOMETRYCLASS_NONE (default), 2) PINGEOMETRYCLASS_CORE, or PINGEOMETRYCLASS_BUMP.\n\tRsyn::PhysicalPinGeometryClass getPinGeometryClass() const;\n\t//! @brief Returns true if a PhysicalPinLayer was associated to the PhysicalPinGeometry. \n\t//! Otherwise, returns false.\n\tbool hasPinLayer() const ;\n\t\n\t//! @brief Returns the number if pin layers\n\tstd::size_t getNumPinLayers() const;\n\t//! @brief Returns the PhysicalPinLayers associated to the PhysicalPinGeometry.\n\tconst std::vector<Rsyn::PhysicalPinLayer> & allPinLayers() const;\n\t\n\t//! @brief Returns the lower pin layer. It is sorted by physical layer.\n\t//! If a pin layer is not defined, than returns a physical pin layer with nullptr data\n\tRsyn::PhysicalPinLayer getLowerPinLayer() const;\n\t\n\t//! @brief Returns the upper pin layer. It is sorted by physical layer.\n\t//! If a pin layer is not defined, than returns a physical pin layer with nullptr data\n\tRsyn::PhysicalPinLayer getUpperPinLayer() const;\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALPINGEOMETRY_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalPinLayer.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPinLayer.h\n * Author: jucemar\n *\n * Created on 13 de Setembro de 2016, 21:19\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPINLAYER_H\n#define PHYSICALDESIGN_PHYSICALPINLAYER_H\n\nnamespace Rsyn {\n\nclass PhysicalPinLayer : public Proxy<PhysicalPinLayerData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalPinLayer object with a pointer to Rsyn::PhysicalPinLayerData.\n\tPhysicalPinLayer(PhysicalPinLayerData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalPinLayer object with a null pointer to Rsyn::PhysicalPinLayerData.\n\tPhysicalPinLayer() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalPinLayer object with a null pointer to Rsyn::PhysicalPinLayerData.\n\tPhysicalPinLayer(std::nullptr_t) : Proxy(nullptr) {}\n\n\t//! @brief Returns the vector reference of rectangular bounds to the Rsyn::PhysicalPinLayer.\n\tconst std::vector<Bounds> & allBounds() const;\n\t//! @brief Returns the vector reference of polygons to the PhysicalPinLayer.\n\tconst std::vector<Polygon> & allPolygons() const;\n\t//! @brief Returns the Rsyn::PhysicalLayer object related to the  Rsyn::PhysicalPinLayer.\n\tRsyn::PhysicalLayer getLayer() const;\n\t//! @brief Returns the total number of rectangular Bounds that defines Rsyn::PhysicalPinLayer\n\tstd::size_t getNumBounds() const;\n\t//! @brief Returns the total number of Polygons that defines Rsyn::PhysicalPinLayer\n\tstd::size_t getNumPolygons() const;\n\t//! @brief Returns true if the Rsyn::PhysicalPinLayer has rectangular Bounds.\n\t//! Otherwise, returns false.\n\tbool hasRectangleBounds() const;\n\t//! @brief Returns true if the Rsyn::PhysicalPinLayer has Polygons.\n\t//! Otherwise, returns false.\n\tbool hasPolygonBounds() const;\n\t//! @brief Returns true if the Rsyn::PhysicalPinLayer has no rectangular Bounds.\n\t//! Otherwise, returns false.\n\tbool isRectangleBoundsEmpty() const;\n\t//! @brief Returns true if the Rsyn::PhysicalPinLayer has no Polygons.\n\t//! Otherwise, returns false.\n\tbool isPolygonBoundsEmpty() const;\n\t//! @brief Returns true if a Rsyn::PhysicalLayer object is associated to the Rsyn::PhysicalPinLayer.\n\t//! Otherwise, returns false.\n\tbool hasLayer() const;\n\t\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALPINLAYER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalPort.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPort.h\n * Author: jucemar\n *\n * Created on 4 de Outubro de 2016, 13:23\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALPORT_H\n#define PHYSICALDESIGN_PHYSICALPORT_H\n\n\nnamespace Rsyn {\n\nclass PhysicalPort : public PhysicalInstance {\n\tfriend class PhysicalDesign;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalPort object with a pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalPort(PhysicalInstanceData * data) : PhysicalInstance(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalPort object with a null pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalPort() : PhysicalInstance(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalPort object with a null pointer to Rsyn::PhysicalInstanceData.\n\tPhysicalPort(std::nullptr_t) : PhysicalInstance(nullptr) {}\n\n\t// Methods for physical cell when a circuit pin (port) is mapped to it\n\t// In the Rsyn the circuit pins (ports) and cells are the same object. Therefore,\n\t// in the mapping to physical object they must be the same object.\n\t//! @brief Returns the object of the layer associated to the PhysicalPort\n\tPhysicalLayer getLayer() const;\n\t//! @brief Returns true if the PhysicalPort has an associated layer. Otherwise, returns false.\n\tbool hasLayer() const;\n\t\n\tPhysicalOrientation getOrientation() const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALPORT_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalRegion.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRegion.h\n * Author: jucemar\n *\n * Created on 09 de Abril de 2017, 14:55\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALREGION_H\n#define PHYSICALDESIGN_PHYSICALREGION_H\n\nnamespace Rsyn {\n\nclass PhysicalRegion : public Proxy<PhysicalRegionData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalRegion object with a pointer to Rsyn::PhysicalRegionData.\n\n\tPhysicalRegion(PhysicalRegionData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalRegion object with a null pointer to Rsyn::PhysicalRegionData.\n\n\tPhysicalRegion() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalRegion object with a null pointer to Rsyn::PhysicalRegionData.\n\n\tPhysicalRegion(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\n\t//! @brief Returns region's name\n\tconst std::string & getName() const;\n\t//! @brief Returns region's type that may be FENCE or GUIDE.\n\tRegionType getType() const;\n\t//! @brief Returns the constant reference to the boundaries vector.\n\tconst std::vector<Bounds> & allBounds() const;\n\t//! @brief Returns total number of boundaries. \n\tstd::size_t getNumBounds() const;\n\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALREGION_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalRoutingGrid.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalRoutingGrid.h\n * Author: jucemar\n *\n * Created on February 2, 2018, 9:01 PM\n */\n\n#ifndef RSYN_PHYSICAL_ROUTING_GRID_H\n#define RSYN_PHYSICAL_ROUTING_GRID_H\n\nnamespace Rsyn {\n\nclass PhysicalRoutingGrid : public Proxy<PhysicalRoutingGridData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalRoutingGrid object with a pointer to Rsyn::PhysicalRoutingGridData.\n\n\tPhysicalRoutingGrid(PhysicalRoutingGridData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalRoutingGrid object with a null pointer to Rsyn::PhysicalRoutingGridData.\n\n\tPhysicalRoutingGrid() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalRoutingGrid object with a null pointer to Rsyn::PhysicalRoutingGridData.\n\n\tPhysicalRoutingGrid(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\tRsyn::PhysicalLayer getLayer() const;\n\tconst std::vector<Rsyn::PhysicalTracks> & allTracks() const;\n\t\n\tconst Bounds & getBounds() const;\n\tDBUxy getPosition() const;\n\tDBU getPosition(const Dimension dim) const;\n\tDBUxy getSpacing() const;\n\tDBU getSpacing(const Dimension dim) const;\n\tint getNumTracks(const Dimension dim) const;\n\tint getNumRows() const;\n\tint getNumCols() const;\n\tint getNumTracks() const;\n\tint getRow(const DBU posY, const RoundingStrategy roudingStrategy = ROUND_NEAREST, const bool clamp = false) const;\n\tint getCol(const DBU posX, const RoundingStrategy roudingStrategy = ROUND_NEAREST, const bool clamp = false) const;\n\tDBUxy getPosition(const int col, const int row) const;\n\tDBUxy getSnappedPosition(const DBUxy pos, const RoundingStrategy roudingStrategy = ROUND_NEAREST, const bool clamp = false) const;\n\tDBU getRowPosition(const int row) const;\n\tDBU getRowMaxPosition() const;\n\tDBU getColPosition(const int col) const;\n\tDBU getColMaxPosition() const;\n\tDBUxy getTrackMaxPosition() const;\n\tDBU getTrackMaxPosition(const Dimension dim) const;\n\tRsyn::PhysicalRoutingGrid getBottomRoutingGrid() const;\n\tRsyn::PhysicalRoutingGrid getTopRoutingGrid() const;\n\tbool hasBottomRoutingGrid() const;\n\tbool hasTopRoutingGrid() const;\n\n\tDBUxy getGridMinPosition() const;\n\tDBUxy getGridMaxPosition() const;\n\tDBUxy getTrackMinPosition(const PhysicalLayerDirection dir, const int index) const;\n\tDBUxy getTrackMaxPosition(const PhysicalLayerDirection dir, const int index) const;\n\t\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALROUTINGGRID_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalRoutingPoint.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRoutingPoint.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 20:32\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALROUTINGPOINT_H\n#define PHYSICALDESIGN_PHYSICALROUTINGPOINT_H\n\nnamespace Rsyn {\n\nclass PhysicalRoutingPoint : public Proxy<PhysicalRoutingPointData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalRoutingPoint object with a pointer to Rsyn::PhysicalRoutingPointData.\n\n\tPhysicalRoutingPoint(PhysicalRoutingPointData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalRoutingPoint object with a null pointer to Rsyn::PhysicalRoutingPointData.\n\n\tPhysicalRoutingPoint() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalRoutingPoint object with a null pointer to Rsyn::PhysicalRoutingPointData.\n\n\tPhysicalRoutingPoint(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\n\tDBUxy getPosition() const;\n\tDBU getPosition(const Dimension dim) const;\n\tDBU getExtension() const;\n\tRsyn::PhysicalVia getVia() const;\n\t\n\t/*! @details\n\t \"RECT ( deltax1 deltay1 deltax2 deltay2 )\n\t Indicates that a rectangle is created from the previous ( x y ) \n\t routing point using the delta values. The RECT values leave the \n\t current point and layer unchanged.\" Source: LEf/DEf Reference Manual 5.8\n\t */\n\tconst Bounds & getRectangle() const;\n\tbool hasExtension() const;\n\tbool hasRectangle() const;\n\tbool hasVia() const;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass PhysicalRoutingPointPair {\nfriend class PhysicalWireSegment;\npublic:\n\n\tPhysicalRoutingPoint getSource() const {return clsSourcePoint;}\n\tPhysicalRoutingPoint getTarget() const {return clsTargetPoint;}\n\n\tDBUxy getExtendedSourcePosition() const {return clsExtendedSourcePosition;}\n\tDBUxy getExtendedTargetPosition() const {return clsExtendedTargetPosition;}\n\nprivate:\n\t\n\tPhysicalRoutingPoint clsSourcePoint;\n\tPhysicalRoutingPoint clsTargetPoint;\n\n\tDBUxy clsExtendedSourcePosition;\n\tDBUxy clsExtendedTargetPosition;\n}; // end class\n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALROUTINGPOINT_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalRow.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRow.h\n * Author: jucemar\n *\n * Created on 14 de Setembro de 2016, 22:29\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALROW_H\n#define PHYSICALDESIGN_PHYSICALROW_H\n\nnamespace Rsyn {\n\nclass PhysicalRow : public Proxy<PhysicalRowData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalRow object with a pointer to Rsyn::PhysicalRowData.\n\tPhysicalRow(PhysicalRowData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalRow object with a null pointer to Rsyn::PhysicalRowData.\n\tPhysicalRow() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalRow object with a null pointer to Rsyn::PhysicalRowData.\n\tPhysicalRow(std::nullptr_t) : Proxy(nullptr) {}\n\n\t//! @brief Returns the Rsyn::PhysicalRow name. \n\tstd::string getName() const;\n\t//! @brief Returns the Rsyn::PhysicalRow site name. \n\tstd::string getSiteName() const;\n\t//! @brief Returns the Rsyn::PhysicalRow width in DBU. \n\tDBU getWidth() const;\n\t//! @brief Returns the Rsyn::PhysicalRow height in DBU. \n\tDBU getHeight() const ;\n\t//! @brief Returns the Rsyn::PhysicalRow lower-left X or Y point. \n\tDBU getOrigin(const Dimension dim) const;\n\t//! @brief Returns the Rsyn::PhysicalRow lower-left point.\n\tDBUxy getOrigin() const;\n\t//! @brief Returns the Rsyn::PhysicalRow step length for X or Y.\n\tDBU getStep(const Dimension dim) const;\n\t//! @brief Returns the Rsyn::PhysicalRow step length. In X is the width while in Y is the height.\n\tDBUxy getStep() const;\n\t//! @brief Returns the total number of sites in the Rsyn::PhsyicalRow\n\tint getNumSites(const Dimension dim) const ;\n\t//! @brief Returns the Rsyn::PhysicalSite object.\n\tRsyn::PhysicalSite getPhysicalSite() const;\n\t//! @brief Returns the site width in DBU.\n\tDBU getSiteWidth() const ;\n\t//! @brief Returns the site height in DBU.\n\tDBU getSiteHeight() const;\n\t//! @brief Returns the coordinate point in the left-lower (LOWER parameter) or right-upper (UPPER parameter) corner.\n\tDBUxy getCoordinate(const Boundary bound) const;\n\t//! @brief Returns the coordinate point in the left-lower (LOWER parameter) or right-upper (UPPER parameter) corner\n\t//! and for X or Y dimensions.\n\tDBU getCoordinate(const Boundary bound, const Dimension dim) const ;\n\t//! @brief Returns the rectangular Bounds of the Rsyn:PhsyicalRow.\n\tconst Bounds &getBounds() const;\n\t//! @brief Returns the Rsyn::PhysicalOrientation of th eRsyn::PhysicalRow.\n\t//! @details Rsyn::PhysicalOrientation may be: 1) ORIENTATION_N, 2) ORIENTATION_E, \n\t//! 3) ORIENTATION_S, 4) ORIENTATION_W, 5) ORIENTATION_FN, 6) ORIENTATION_FE,\n\t//! 7) ORIENTATION_FS, or 8) ORIENTATION_FW.\n\tRsyn::PhysicalOrientation getSiteOrientation() const ;\n\t//! @brief Returns the Rsyn::PhysicalSymmetry of Rsyn::PhysicalRow.\n\t//! @details Rsyn::PhysicalSymmetry may be: 1) SYMMETRY_X, or 2) SYMMETRY_Y.\n\tRsyn::PhysicalSymmetry getSymmetry() const;\n\n}; // end class \n\n} // end namespace \n\n\n#endif /* PHYSICALDESIGN_PHYSICALROW_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalSite.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSite.h\n * Author: jucemar\n *\n * Created on 12 de Setembro de 2016, 22:47\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSITE_H\n#define PHYSICALDESIGN_PHYSICALSITE_H\n\nnamespace Rsyn {\n\nclass PhysicalSite : public Proxy<PhysicalSiteData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalSite object with a pointer to Rsyn::PhysicalSiteData.\n\tPhysicalSite(PhysicalSiteData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalSite object with a null pointer to Rsyn::PhysicalSiteData.\n\tPhysicalSite() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalSite object with a null pointer to Rsyn::PhysicalSiteData.\n\tPhysicalSite(std::nullptr_t) : Proxy(nullptr) {}\n\t//! @brief Returns the Rsyn::PhysicalSite name.\n\tstd::string getName() const;\n\t//! @brief Returns the Rsyn::PhysicalSit class.\n\t//! @param Rsyn::PhysicalSiteClass may be 1) PAD or 2) CORE.\n\tRsyn::PhysicalSiteClass getClass() const;\n\t//! @brief Returns the site size. In X is the width and in Y is the height.\n\tDBUxy getSize() const;\n\t//! @brief Returns the site width.\n\tDBU getWidth() const;\n\t//! @brief Returns the site heigth.\n\tDBU getHeight() const;\n\t//! @brief Returns site width if Dimension is X. Otherwise, returns the site height.\n\tDBU getLength(const Dimension dim) const;\n\t//! @brief Returns the site symmetry\n\tRsyn::PhysicalSymmetry getSymmetry() const;\n}; // end class\n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSITE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalSpacing.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpacing.h\n * Author: jucemar\n *\n * Created on 15 de Setembro de 2016, 18:56\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPACING_H\n#define PHYSICALDESIGN_PHYSICALSPACING_H\n\nnamespace Rsyn {\n\nclass PhysicalSpacing : public Proxy<PhysicalSpacingData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalSpacing object with a pointer to Rsyn::PhysicalSpacingData.\n\tPhysicalSpacing(PhysicalSpacingData * data) : Proxy(data) {}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalSpacing object with a null pointer to Rsyn::PhysicalSpacingData.\n\tPhysicalSpacing() : Proxy(nullptr) {}\n\t//! @brief Constructs a Rsyn::PhysicalSpacing object with a null pointer to Rsyn::PhysicalSpacingData.\n\tPhysicalSpacing(std::nullptr_t) : Proxy(nullptr) {}\n\t//! @brief Returns the first Rsyn::PhysicalLayer object.\n\tRsyn::PhysicalLayer getLayer1() const;\n\t//! @brief Returns the second Rsyn::PhysicalLayer object.\n\tRsyn::PhysicalLayer getLayer2() const;\n\t//! @brief Returns the distance in DBU \n\tDBU getDistance() const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPACING_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalSpecialNet.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpecialNet.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 20:58\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPECIALNET_H\n#define PHYSICALDESIGN_PHYSICALSPECIALNET_H\n\nnamespace Rsyn { \n\nclass PhysicalSpecialNet : public Proxy<PhysicalSpecialNetData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalSpecialNet object with a pointer to Rsyn::PhysicalSpecialNetData.\n\n\tPhysicalSpecialNet(PhysicalSpecialNetData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalSpecialNet object with a null pointer to Rsyn::PhysicalSpecialNetData.\n\n\tPhysicalSpecialNet() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalSpecialNet object with a null pointer to Rsyn::PhysicalSpecialNetData.\n\n\tPhysicalSpecialNet(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\tconst DefNetDscp & getNet() const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPECIALNET_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalSpecialWire.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpecialWire.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 21:11\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALSPECIALWIRE_H\n#define PHYSICALDESIGN_PHYSICALSPECIALWIRE_H\n\nnamespace Rsyn {\nclass PhysicalSpecialWire : public Proxy<PhysicalSpecialWireData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalSpecialWire object with a pointer to Rsyn::PhysicalSpecialWireData.\n\n\tPhysicalSpecialWire(PhysicalSpecialWireData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalSpecialWire object with a null pointer to Rsyn::PhysicalSpecialWireData.\n\n\tPhysicalSpecialWire() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalSpecialWire object with a null pointer to Rsyn::PhysicalSpecialWireData.\n\n\tPhysicalSpecialWire(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\tRsyn::PhysicalLayer getPhysicalLayer();\n\tDBU getWireWidth() const;\n\tconst std::vector<PhysicalRoutingPoint> & allRoutingPoints() const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALSPECIALWIRE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalTracks.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalTracks.h\n * Author: jucemar\n *\n * Created on 24 de Maio de 2017, 21:51\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALTRACKS_H\n#define PHYSICALDESIGN_PHYSICALTRACKS_H\n\nnamespace Rsyn {\n\nclass PhysicalTracks : public Proxy<PhysicalTracksData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalTracks object with a pointer to Rsyn::PhysicalTracksData.\n\n\tPhysicalTracks(PhysicalTracksData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalTracks object with a null pointer to Rsyn::PhysicalTracksData.\n\n\tPhysicalTracks() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalTracks object with a null pointer to Rsyn::PhysicalTracksData.\n\n\tPhysicalTracks(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\tPhysicalTrackDirection getDirection() const;\n\tDBU getLocation() const;\n\tDBU getSpace() const;\n\tint getNumberOfTracks() const;\n\tstd::size_t getNumberOfLayers() const;\n\tconst std::vector<PhysicalLayer> & allLayers() const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALTRACKS_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalVia.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalVia.h\n * Author: jucemar\n *\n * Created on 14 de Maio de 2017, 15:03\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALVIA_H\n#define PHYSICALDESIGN_PHYSICALVIA_H\n\nnamespace Rsyn {\n\nclass PhysicalVia : public Proxy<PhysicalViaData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalDesignData;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalVia object with a pointer to Rsyn::PhysicalViaData.\n\n\tPhysicalVia(PhysicalViaData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalVia object with a null pointer to Rsyn::PhysicalViaData.\n\n\tPhysicalVia() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalVia object with a null pointer to Rsyn::PhysicalViaData.\n\n\tPhysicalVia(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\n\t//! @brief Returns via name\n\tconst std::string & getName() const;\n\n\t//! @brief returns the top layer of the via\n\tRsyn::PhysicalLayer getTopLayer() const;\n\t//! @brief returns the cut layer of the via\n\tRsyn::PhysicalLayer getCutLayer() const;\n\t//! @brief returns the bottom layer of the via\n\tRsyn::PhysicalLayer getBottomLayer() const;\n\t//! @brief returns the respective layer\n\tRsyn::PhysicalLayer getLayer(const PhysicalViaLayerType type) const;\n\t\n\tbool isViaDesign() const;\n\tbool isViaRule() const;\n\tbool isViaGeometry() const;\n\tbool hasViaRule() const;\n\tbool hasRowCol() const;\n\tbool hasOrigin() const;\n\tbool hasOffset() const;\n\tbool hasPattern() const;\n\tViaType getViaType() const;\n\tRsyn::PhysicalViaRuleBase getViaRule() const;\n\tDBU getCutSize(const Dimension dim) const;\n\tDBU getSpacing(const Dimension dim) const;\n\tDBU getEnclosure(const ViaLevel level, const Dimension dim) const;\n\tDBU getOrigin(const Dimension dim) const;\n\tDBU getOffset(const ViaLevel level, const Dimension dim) const;\n\tint getNumRows() const;\n\tint getNumCols() const;\n\tconst std::string & getPattern() const;\n\tconst std::vector<Rsyn::PhysicalViaGeometry>  & allBottomGeometries() const;\n\tconst std::vector<Rsyn::PhysicalViaGeometry>  & allCutGeometries() const;\n\tconst std::vector<Rsyn::PhysicalViaGeometry>  & allTopGeometries() const;\n\tconst std::vector<Rsyn::PhysicalViaGeometry>  & allGeometries(const PhysicalViaLayerType layer) const;\n}; // end class \n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALVIA_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalViaGeometry.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaGeometry.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 5:52 PM\n */\n\n#ifndef RSYN_DATABASE_PHYSICALVIAGEOMETRY_H\n#define RSYN_DATABASE_PHYSICALVIAGEOMETRY_H\n\nnamespace Rsyn {\n\nclass PhysicalViaGeometry : public Proxy<ViaGeometryData> {\n\tfriend class PhysicalDesign;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalViaGeometry object with a pointer to Rsyn::ViaGeometryData.\n\n\tPhysicalViaGeometry(ViaGeometryData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalViaGeometry object with a null pointer to Rsyn::ViaGeometryData.\n\n\tPhysicalViaGeometry() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalViaGeometry object with a null pointer to Rsyn::ViaGeometryData.\n\n\tPhysicalViaGeometry(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\tconst Bounds & getBounds() const;\n\tint getMaskNumber() const;\n\t\n}; // end class\n\n} // end namespace\n\n#endif /* RSYN_DATABASE_PHYSICALVIAGEOMETRY_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalViaRule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaRule.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 5:53 PM\n */\n\n#ifndef RSYN_DATABASE_PHYSICALVIARULE_H\n#define RSYN_DATABASE_PHYSICALVIARULE_H\n\nnamespace Rsyn {\n\nclass PhysicalViaRule : public PhysicalViaRuleBase {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalViaRuleBase;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalViaRule object with a pointer to Rsyn::ViaRuleData.\n\n\tPhysicalViaRule(ViaRuleData * data) : PhysicalViaRuleBase(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalViaRule object with a null pointer to Rsyn::ViaRuleData.\n\n\tPhysicalViaRule() : PhysicalViaRuleBase(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalViaRule object with a null pointer to Rsyn::ViaRuleData.\n\n\tPhysicalViaRule(std::nullptr_t) : PhysicalViaRuleBase(nullptr) {\n\t}\n\t\n\t//! @brief Returns the via rule relative index\n\tint getRelativeIndex() const;\n\t\n\t//! @brief Returns the top or bottom routing layers in the via rule.\n\tRsyn::PhysicalLayer getLayer(const Rsyn::ViaLevel level) const;\n\t//! @brief Returns the top or bottom routing layer directions in the via rule.\n\tRsyn::PhysicalLayerDirection getLayerDirection(const Rsyn::ViaLevel level) const;\n\t//! @brief Returns all cut layers defined in via rule.\n\tconst std::vector<Rsyn::PhysicalVia> & allVias() const;\n\n}; // end class\n\n} // end namespace\n\n#endif /* RSYN_DATABASE_PHYSICALVIARULE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalViaRuleBase.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaRuleBase.h\n * Author: jucemar\n *\n * Created on November 13, 2018, 3:37 PM\n */\n\n#ifndef RSYN_DATABASE_PHYSICALVIARULEBASE_H\n#define RSYN_DATABASE_PHYSICALVIARULEBASE_H\n\nnamespace Rsyn {\n\nclass PhysicalViaRuleBase : public Proxy<ViaRuleData> {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalVia;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalViaRule object with a pointer to Rsyn::ViaRuleData.\n\n\tPhysicalViaRuleBase(ViaRuleData * data) : Proxy(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalViaRule object with a null pointer to Rsyn::ViaRuleData.\n\n\tPhysicalViaRuleBase() : Proxy(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalViaRule object with a null pointer to Rsyn::ViaRuleData.\n\n\tPhysicalViaRuleBase(std::nullptr_t) : Proxy(nullptr) {\n\t}\n\t\n\t//! @brief Returns the via rule base index \n\tint getIndex() const;\n\t\n\t//! @brief Returns the via rule base as via rule generate\n\tPhysicalViaRule asViaRule() const;\n\t//! @brief Returns the via rule base as via rule generate\n\tPhysicalViaRuleGenerate asViaRuleGenerate() const;\n\t\n\t//! @brief Returns if via rule base is only via rule\n\tbool isViaRule() const;\n\t//! @brief Returns if the via rule is generate\n\tbool isViaRuleGenerate() const;\n\t\n\t//! @brief Returns the via rule name\n\tconst std::string & getName() const;\n\t\n\t//! @brief Returns the min and max range of the top or bottom routing layer directions in the via rule has been defined.\n\tbool hasWidth(const Rsyn::ViaLevel level) const;\n\t//! @brief Returns the min and max range of the top or bottom routing layer directions in the via rule.\n\tDBU getWidth(const Rsyn::ViaLevel level, const Rsyn::ViaRange range) const;\n}; // end class\n\n} // end namespace\n\n\n#endif /* RSYN_DATABASE_PHYSICALVIARULEBASE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/decl/PhysicalViaRuleGenerate.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaGenerate.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 5:53 PM\n */\n\n#ifndef RSYN_DATABASE_PHYSICALVIAGENERATE_H\n#define RSYN_DATABASE_PHYSICALVIAGENERATE_H\n\nnamespace Rsyn {\n\nclass PhysicalViaRuleGenerate : public PhysicalViaRuleBase {\n\tfriend class PhysicalDesign;\n\tfriend class PhysicalViaRuleBase;\n\tRSYN_FRIEND_OF_GENERIC_LIST_COLLECTION;\nprotected:\n\t//! @brief Constructs a Rsyn::PhysicalViaRuleGenerate object with a pointer to Rsyn::ViaRuleGenerateData.\n\n\tPhysicalViaRuleGenerate(ViaRuleData * data) : PhysicalViaRuleBase(data) {\n\t}\npublic:\n\t//! @brief Constructs a Rsyn::PhysicalViaRuleGenerate object with a null pointer to Rsyn::ViaRuleGenerateData.\n\n\tPhysicalViaRuleGenerate() : PhysicalViaRuleBase(nullptr) {\n\t}\n\t//! @brief Constructs a Rsyn::PhysicalViaRuleGenerate object with a null pointer to Rsyn::ViaRuleGenerateData.\n\n\tPhysicalViaRuleGenerate(std::nullptr_t) : PhysicalViaRuleBase(nullptr) {\n\t}\n\n\t//! @brief Returns the via rule relative index\n\tint getRelativeIndex() const;\n\t\n\t//! @brief Returns if the via rule generate can be used to regular routing\n\tbool isDefault() const;\n\t//! @brief Returns the via rule generate layer. It can be bottom, top or cut layer types \n\tRsyn::PhysicalLayer getLayer(const Rsyn::PhysicalViaLayerType layer) const;\n\tDBU getEnclosure1(const Rsyn::ViaLevel level) const;\n\tDBU getEnclosure2(const Rsyn::ViaLevel level) const;\n\tBounds getCutBounds() const;\n\tDBU getCutSpacing(const Dimension dim) const;\n\tbool hasCutResistance() const;\n\tfloat getCutResistance() const;\nprivate:\n}; // end class\n\n} // end namespace \n\n#endif /* PHYSICALVIAGENERATE_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/LayerViaManager.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   LayerViaManager.h\n * Author: jucemar\n *\n * Created on February 3, 2018, 9:31 AM\n */\nnamespace Rsyn {\n\ninline const std::vector<Rsyn::PhysicalVia> & LayerViaManager::allVias(Rsyn::PhysicalLayer layer) const {\n\treturn data->clsVias[layer];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalVia> & LayerViaManager::allBottomVias(Rsyn::PhysicalLayer layer) const {\n\treturn data->clsBottomVias[layer];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalVia> & LayerViaManager::allTopVias(Rsyn::PhysicalLayer layer) const {\n\treturn data->clsTopVias[layer];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool LayerViaManager::hasVias(Rsyn::PhysicalLayer layer) const {\n\tif(layer == nullptr)\n\t\treturn false;\n\tif(layer.getType() != Rsyn::PhysicalLayerType::ROUTING)\n\t\treturn false;\n\tconst std::vector<Rsyn::PhysicalVia> & vias  = data->clsVias[layer];\n\treturn vias.size() > 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool LayerViaManager::hasBottomVias(Rsyn::PhysicalLayer layer) const {\n\tif(layer == nullptr)\n\t\treturn false;\n\tif(layer.getType() != Rsyn::PhysicalLayerType::ROUTING)\n\t\treturn false;\n\tconst std::vector<Rsyn::PhysicalVia> & vias  = data->clsBottomVias[layer];\n\treturn vias.size() > 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool LayerViaManager::hasTopVias(Rsyn::PhysicalLayer layer) const {\n\tif(layer == nullptr)\n\t\treturn false;\n\tif(layer.getType() != Rsyn::PhysicalLayerType::ROUTING)\n\t\treturn false;\n\tconst std::vector<Rsyn::PhysicalVia> & vias  = data->clsTopVias[layer];\n\treturn vias.size() > 0;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::Cell PhysicalCell::getCell() const {\n\treturn data->clsInstance.asCell();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalCell::isFixed() const {\n\treturn data->clsInstance.isFixed();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalCell::isMacroBlock() const {\n\treturn data->clsInstance.isMacroBlock();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalCell::isPlaced() const {\n\treturn data->clsPlaced;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalCell::getInitialPosition() const {\n\treturn data->clsInitialPos;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getInitialPosition(const Dimension dim) const {\n\treturn data->clsInitialPos[dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacement() const {\n\tconst DBUxy pos = getPosition();\n\tconst DBUxy initial = getInitialPosition();\n\treturn std::abs(pos[X] - initial[X]) + std::abs(pos[Y] - initial[Y]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacement(const Dimension dim) const {\n\tconst DBU pos = getPosition(dim);\n\tconst DBU initial = getInitialPosition(dim);\n\treturn std::abs(initial - pos);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacement(const DBUxy pos) const {\n\tconst DBUxy lower = getPosition();\n\treturn std::abs(lower[X] - pos[X]) + std::abs(lower[Y] - pos[Y]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacement(const DBU pos, const Dimension dim) const {\n\tconst DBU lower = getPosition(dim);\n\treturn std::abs(lower - pos);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacementFromCurrentPosition(const DBUxy pos) const {\n\tconst DBUxy lower = getPosition();\n\treturn std::abs(lower[X] - pos[X]) + std::abs(lower[Y] - pos[Y]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacementFromCurrentPosition(const DBU pos, const Dimension dim) const {\n\tconst DBU lower = getPosition(dim);\n\treturn std::abs(lower - pos);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacementFromInitialPosition(const DBUxy pos) const {\n\tconst DBUxy lower = getInitialPosition();\n\treturn std::abs(lower[X] - pos[X]) + std::abs(lower[Y] - pos[Y]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalCell::getDisplacementFromInitialPosition(const DBU pos, const Dimension dim) const {\n\tconst DBU lower = getInitialPosition(dim);\n\treturn std::abs(lower - pos);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalTransform PhysicalCell::getTransform(const bool origin) const {\n\treturn getInstance().getTransform(origin);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalCell::hasLayerBounds() const {\n\treturn data->clsHasLayerBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalDesign.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n#include <Rsyn/PhysicalDesign>\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::loadLibrary(const LefDscp & library) {\n\tif (!data) {\n\t\tstd::cout << \"ERROR: Physical Design was not configured!\\n\"\n\t\t\t<< \"Please call first initPhysicalDesign!\"\n\t\t\t<< std::endl;\n\t\treturn;\n\t} // end if \n\n\tif (library.clsLefUnitsDscp.clsHasDatabase) {\n\t\tif (getDatabaseUnits(LIBRARY_DBU) == 0) {\n\t\t\tdata->clsDBUs[LIBRARY_DBU] = library.clsLefUnitsDscp.clsDatabase;\n\t\t} else {\n\t\t\tif (getDatabaseUnits(LIBRARY_DBU) != library.clsLefUnitsDscp.clsDatabase) {\n\t\t\t\tstd::cout << \"WARNING: Stored LEF database units \"\n\t\t\t\t\t<< getDatabaseUnits(LIBRARY_DBU)\n\t\t\t\t\t<< \" is not equal to LEF database units defined in Library \"\n\t\t\t\t\t<< library.clsLefUnitsDscp.clsDatabase\n\t\t\t\t\t<< \".\\n\";\n\t\t\t\tstd::cout << \"WARNING: Lef library elements were NOT initialized!\\n\";\n\t\t\t\treturn;\n\t\t\t} // end if \n\t\t} // end if-else\n\t} // end if \n\n\t// Initializing physical sites\n\tdata->clsPhysicalSites.reserve(library.clsLefSiteDscps.size());\n\tfor (const LefSiteDscp & lefSite : library.clsLefSiteDscps) {\n\t\taddPhysicalSite(lefSite);\n\t} // end for\n\n\t// Initializing physical layers\n\tdata->clsPhysicalLayers.reserve(library.clsLefLayer.size());\n\tRsyn::PhysicalLayerData * lower = nullptr;\n\tfor (lefiLayer* lefLayer : library.clsLefLayer) {\n\t\tlower = addPhysicalLayer(lefLayer, lower);\n\t} // end for \n\n\t// Initializing physical vias\n\tdata->clsPhysicalVias.reserve(library.clsLefViaDscps.size());\n\tfor (const LefViaDscp & via : library.clsLefViaDscps) {\n\t\taddPhysicalVia(via);\n\t} // end for \n\n\t// Initialize rule and generate physical vias\n\tconst int numViaRules = library.clsLefViaRuleDscps.size();\n\tdata->clsPhysicalViaRuleBases.reserve(numViaRules);\n\tdata->clsPhysicalViaRules.reserve(numViaRules);\n\tdata->clsPhysicalViaRuleGenerates.reserve(numViaRules);\n\tfor (const LefViaRuleDscp & viaRuleDscp : library.clsLefViaRuleDscps) {\n\t\taddPhysicalViaRule(viaRuleDscp);\n\t} // end for \n\tdata->clsPhysicalViaRules.shrink_to_fit();\n\tdata->clsPhysicalViaRuleGenerates.shrink_to_fit();\n\n\t// initializing physical spacing \n\tfor (const LefSpacingDscp & spc : library.clsLefSpacingDscps) {\n\t\taddPhysicalSpacing(spc);\n\t} // end for \n\n\t// initializing physical cells (LEF macros)\n\tfor (const LefMacroDscp & macro : library.clsLefMacroDscps) {\n\t\t// Adding Physical Library cell to Physical Layer\n\t\tRsyn::LibraryCell libCell = addPhysicalLibraryCell(macro);\n\n\t\t// Adding Physical Library pins to Physical Layer\n\t\tfor (const LefPinDscp &lpin : macro.clsPins) {\n\t\t\taddPhysicalLibraryPin(libCell, lpin);\n\t\t} // end for\t\n\t} // end for\n\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::loadDesign(const DefDscp & design) {\n\tif (data->clsLoadDesign) {\n\t\tstd::cout << \"WARNING: Design was already loaded. Skipping ... \\n\";\n\t\treturn;\n\t} // end if\n\tdata->clsLoadDesign = true;\n\n\t// Adding Library cell to Physical Layer\n\tdata->clsDBUs[DESIGN_DBU] = design.clsDatabaseUnits;\n\tdata->clsPhysicalDie.clsBounds = design.clsDieBounds;\n\n\tif (getDatabaseUnits(LIBRARY_DBU) % getDatabaseUnits(DESIGN_DBU) != 0) {\n\t\tstd::cout << \"ERROR: Invalid DEF database units \" << getDatabaseUnits(DESIGN_DBU) << \" (LEF database units: \" << getDatabaseUnits(LIBRARY_DBU) << \").\\n\";\n\t\tstd::cout << \"DEF design units should be lower or equal to LEF design units and must have a integer multiple. Physical design was not initialized!\\n\";\n\t\treturn;\n\t} // end if \n\n\t// This operation always results in an integer number factor. \n\t// LEF/DEF specifications prohibit division that results in a real number factor.\n\tdata->clsDBUs[MULT_FACTOR_DBU] = getDatabaseUnits(LIBRARY_DBU) / getDatabaseUnits(DESIGN_DBU);\n\n\t// Adding design defined vias\n\tstd::size_t numVias = data->clsPhysicalVias.size() + design.clsVias.size();\n\tdata->clsPhysicalVias.reserve(numVias);\n\tfor (const DefViaDscp & via : design.clsVias) {\n\t\taddPhysicalDesignVia(via);\n\t} // end for \n\n\t// initializing physical cells (DEF Components)\n\tfor (const DefComponentDscp & component : design.clsComps) {\n\t\t// Adding Physical cell to Physical Layer\n\t\tRsyn::Cell cell = data->clsDesign.findCellByName(component.clsName);\n\t\tif (!cell) {\n\t\t\tthrow Exception(\"Cell \" + component.clsName + \" not found.\\n\");\n\t\t} // end if\n\t\taddPhysicalCell(cell, component);\n\t} // end for\n\n\t// Initializing circuit ports\n\tfor (const DefPortDscp & pin_port : design.clsPorts) {\n\t\t// Adding Library cell to Physical Layer\n\t\tRsyn::Port cell = data->clsDesign.findPortByName(pin_port.clsName);\n\t\tif (!cell) {\n\t\t\tthrow Exception(\"Port \" + pin_port.clsName + \" not found.\\n\");\n\t\t} // end if\n\t\taddPhysicalPort(cell, pin_port);\n\t} // end for\n\n\t//Initializing circuit rows and defining circuit bounds\n\tRsyn::PhysicalModule phModule = getPhysicalModule(data->clsModule);\n\tBounds & bounds = phModule->clsInstance->clsBounds;\n\tbounds[LOWER].apply(+std::numeric_limits<DBU>::max());\n\tbounds[UPPER].apply(-std::numeric_limits<DBU>::max());\n\tdata->clsPhysicalRows.reserve(design.clsRows.size()); // reserving space for rows\n\tfor (const DefRowDscp & defRow : design.clsRows) {\n\t\taddPhysicalRow(defRow);\n\t} // end for \n\n\tdata->clsMapPhysicalRegions.reserve(design.clsRegions.size());\n\tdata->clsPhysicalRegions.reserve(design.clsRegions.size());\n\tfor (const DefRegionDscp & defRegion : design.clsRegions)\n\t\taddPhysicalRegion(defRegion);\n\n\tdata->clsMapPhysicalGroups.reserve(design.clsGroups.size());\n\tdata->clsPhysicalGroups.reserve(design.clsGroups.size());\n\tfor (const DefGroupDscp & defGroup : design.clsGroups)\n\t\taddPhysicalGroup(defGroup);\n\n\tfor (const DefNetDscp & net : design.clsNets)\n\t\taddPhysicalNet(net);\n\n\tdata->clsPhysicalSpecialNets.reserve(design.clsSpecialNets.size());\n\tfor (const DefNetDscp & specialNet : design.clsSpecialNets)\n\t\taddPhysicalSpecialNet(specialNet);\n\n\tdata->clsPhysicalTracks.reserve(design.clsTracks.size());\n\tfor (const DefTrackDscp & track : design.clsTracks)\n\t\taddPhysicalTracks(track);\n\tinitRoutingGrid();\n\tinitLayerViaManager();\n\t// only to keep coherence in the design;\n\tdata->clsNumElements[PHYSICAL_PORT] = data->clsDesign.getNumInstances(Rsyn::PORT);\n\n\tdata->clsPhysicalGCell.reserve(design.clsGcellGrids.size());\n\tfor (const DefGcellGridDscp & gcell : design.clsGcellGrids) {\n            addPhysicalGCell(gcell);\n\t} // end for\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::initPhysicalDesign(Rsyn::Design dsg, const Rsyn::Json &params) {\n\tif (data) {\n\t\tstd::cout << \"ERROR: design already set.\\nSkipping initialize Physical Design\\n\";\n\t\treturn;\n\t} // end if\n\tthis->data = new PhysicalDesignData();\n\n\tif (!params.is_null()) {\n\t\tdata->clsEnablePhysicalPins = params.value(\"clsEnablePhysicalPins\", data->clsEnablePhysicalPins);\n\t\tdata->clsEnableMergeRectangles = params.value(\"clsEnableMergeRectangles\", data->clsEnableMergeRectangles);\n\t\tdata->clsEnableNetPinBoundaries = params.value(\"clsEnableNetPinBoundaries\", data->clsEnableNetPinBoundaries);\n\t\tdata->clsMode = getPhysicalDesignModeType(params.value(\"clsPhysicalDesignMode\", \"ALL\"));\n\t} // end if \n\n\tdata->clsDesign = dsg;\n\tdata->clsModule = dsg.getTopModule();\n\tdata->clsPhysicalInstances = dsg.createAttribute();\n\tdata->clsPhysicalLibraryCells = dsg.createAttribute();\n\tdata->clsPhysicalLibraryPins = dsg.createAttribute();\n\tif (data->clsEnablePhysicalPins)\n\t\tdata->clsPhysicalPins = dsg.createAttribute();\n\tdata->clsPhysicalNets = dsg.createAttribute();\n\n\t// Initialize data of top module.\n\tPhysicalInstanceData &phTopModule = data->clsPhysicalInstances[dsg.getTopModule()];\n\tphTopModule.clsInstance = dsg.getTopModule();\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::updateAllNetBounds(const bool skipClockNet) {\n\tif (skipClockNet && data->clsClkNet) {\n\t\tRsyn::PhysicalNet phNet = getPhysicalNet(data->clsClkNet);\n\t\tdata->clsHPWL -= phNet.getHPWL();\n\t} // end if \n\n\tfor (Rsyn::Net net : data->clsModule.allNets()) {\n\t\t//skipping clock network\n\t\tif (skipClockNet && (data->clsClkNet == net))\n\t\t\tcontinue;\n\n\t\tupdateNetBound(net);\n\t} // end for\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::updateNetBound(Rsyn::Net net) {\n\t// net has not pins. The boundaries are defined by default to 0.\n\tif (net.getNumPins() == 0)\n\t\treturn;\n\n\tPhysicalNetData &phNet = data->clsPhysicalNets[net];\n\tBounds &bound = phNet.clsBounds;\n\tdata->clsHPWL -= bound.computeLength(); // remove old net wirelength\n\tbound[UPPER].apply(-std::numeric_limits<DBU>::max());\n\tbound[LOWER].apply(+std::numeric_limits<DBU>::max());\n\tconst bool updatePinBound = data->clsEnableNetPinBoundaries;\n\tfor (Rsyn::Pin pin : net.allPins()) {\n\t\tDBUxy pos = getPinPosition(pin);\n\n\t\t// upper x corner pos\n\t\tif (pos[X] >= bound[UPPER][X]) {\n\t\t\tbound[UPPER][X] = pos[X];\n\t\t\tif (updatePinBound)\n\t\t\t\tphNet.clsBoundPins[UPPER][X] = pin;\n\t\t} // end if \n\n\t\t// lower x corner pos \n\t\tif (pos[X] <= bound[LOWER][X]) {\n\t\t\tbound[LOWER][X] = pos[X];\n\t\t\tif (updatePinBound)\n\t\t\t\tphNet.clsBoundPins[LOWER][X] = pin;\n\t\t} // end if \n\n\t\t// upper y corner pos \n\t\tif (pos[Y] >= bound[UPPER][Y]) {\n\t\t\tbound[UPPER][Y] = pos[Y];\n\t\t\tif (updatePinBound)\n\t\t\t\tphNet.clsBoundPins[UPPER][Y] = pin;\n\t\t} // end if \n\n\t\t// lower y corner pos \n\t\tif (pos[Y] <= bound[LOWER][Y]) {\n\t\t\tbound[LOWER][Y] = pos[Y];\n\t\t\tif (updatePinBound)\n\t\t\t\tphNet.clsBoundPins[LOWER][Y] = pin;\n\t\t} // end if \n\t} // end for\n\tdata->clsHPWL += bound.computeLength(); // update hpwl \n} // end method \n\n// -----------------------------------------------------------------------------\n\n// Adding the new Site parameter to PhysicalDesign data structure.\n\nvoid PhysicalDesign::addPhysicalSite(const LefSiteDscp & site) {\n\tstd::unordered_map<std::string, int>::iterator it = data->clsMapPhysicalSites.find(site.clsName);\n\tif (it != data->clsMapPhysicalSites.end()) {\n\t\tstd::cout << \"WARNING: Site \" << site.clsName << \" was already defined. Skipping ...\\n\";\n\t\treturn;\n\t} // end if \n\n\t// Adding new lib site\n\tdata->clsPhysicalSites.push_back(PhysicalSite(new PhysicalSiteData()));\n\tPhysicalSite phSite = data->clsPhysicalSites.back();\n\tdata->clsMapPhysicalSites[site.clsName] = data->clsPhysicalSites.size() - 1;\n\tphSite->id = data->clsPhysicalSites.size() - 1;\n\tphSite->clsSiteName = site.clsName;\n\tdouble2 size = site.clsSize;\n\tsize.scale(static_cast<double> (getDatabaseUnits(LIBRARY_DBU)));\n\tphSite->clsSize[X] = static_cast<DBU> (std::round(size[X]));\n\tphSite->clsSize[Y] = static_cast<DBU> (std::round(size[Y]));\n\tphSite->clsSiteClass = Rsyn::getPhysicalSiteClass(site.clsSiteClass);\n\tphSite->clsSymmetry = Rsyn::getPhysicalSymmetry(site.clsSymmetry);\n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayerData * PhysicalDesign::addPhysicalLayer(lefiLayer* layer, Rsyn::PhysicalLayerData * lower) {\n\tconst std::string name(layer->name());\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalLayers.find(name);\n\tif (it != data->clsMapPhysicalLayers.end()) {\n\t\tstd::cout << \"WARNING: Layer \" << name << \" was already defined. Skipping ...\\n\";\n\t\t// TODO -> return the pointer to the phLayerData of already defined physical layer.\n\t\treturn nullptr;\n\t} // end if \n\n\tDBU libDBU = getDatabaseUnits(LIBRARY_DBU);\n\tElement<PhysicalLayerData> *element = data->clsPhysicalLayers.create();\n\tRsyn::PhysicalLayerData * phLayer = &(element->value);\n\tphLayer->clsLayer = layer;\n\tphLayer->id = data->clsPhysicalLayers.lastId();\n\tphLayer->clsName = name;\n\tconst Rsyn::PhysicalLayerType type = Rsyn::getPhysicalLayerType(layer->type());\n\tphLayer->clsType = type;\n\tphLayer->clsWidth = static_cast<DBU> (std::round(layer->width() * libDBU));\n\tphLayer->clsRelativeIndex = data->clsNumLayers[type];\n\tdata->clsMapPhysicalLayers[name] = phLayer->id;\n\tdata->clsNumLayers[type]++;\n\tif (lower) {\n\t\tlower->clsUpper = phLayer;\n\t\tphLayer->clsLower = lower;\n\t} // end if\n\tif (type == Rsyn::PhysicalLayerType::ROUTING)\n\t\tdata->clsPhysicalRoutingLayerIndeces.push_back(phLayer->id);\n\treturn phLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalVia(const LefViaDscp & via) {\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalVias.find(via.clsName);\n\tif (it != data->clsMapPhysicalVias.end()) {\n\t\tstd::cout << \"WARNING: Via \" << via.clsName << \" was already defined. Skipping ...\\n\";\n\t\treturn;\n\t} // end if \n\n\t// Adding new via\n\tdata->clsMapPhysicalVias[via.clsName] = data->clsPhysicalVias.size();\n\tdata->clsPhysicalVias.push_back(PhysicalVia(new PhysicalViaData()));\n\tPhysicalVia phVia = data->clsPhysicalVias.back();\n\tphVia->id = data->clsPhysicalVias.size() - 1;\n\tphVia->clsName = via.clsName;\n\tphVia->clsIsDefault = via.clsIsDefault;\n\tphVia->clsIsViaDesign = false;\n\tphVia->clsHasViaRule = via.clsHasViaRule;\n\n\tif (via.clsHasViaRule) {\n\t\tRsyn::PhysicalViaRuleBase phViaRuleBase = getPhysicalViaRuleBaseByName(via.clsViaRuleName);\n\t\tphVia->clsViaRuleData = phViaRuleBase.data;\n\t\tphVia->clsCutSize[X] = convertMicronToLibraryDatabaseUnits(via.clsXCutSize);\n\t\tphVia->clsCutSize[Y] = convertMicronToLibraryDatabaseUnits(via.clsYCutSize);\n\t\tphVia->clsSpacing[X] = convertMicronToLibraryDatabaseUnits(via.clsXCutSpacing);\n\t\tphVia->clsSpacing[Y] = convertMicronToLibraryDatabaseUnits(via.clsYCutSpacing);\n\t\tphVia->clsEnclosure[BOTTOM_VIA_LEVEL][X] = convertMicronToLibraryDatabaseUnits(via.clsXBottomEnclosure);\n\t\tphVia->clsEnclosure[TOP_VIA_LEVEL][Y] = convertMicronToLibraryDatabaseUnits(via.clsYBottomEnclosure);\n\t\tphVia->clsEnclosure[BOTTOM_VIA_LEVEL][X] = convertMicronToLibraryDatabaseUnits(via.clsXTopEnclosure);\n\t\tphVia->clsEnclosure[TOP_VIA_LEVEL][Y] = convertMicronToLibraryDatabaseUnits(via.clsYTopEnclosure);\n\n\t\tRsyn::PhysicalLayer bottom = getPhysicalLayerByName(via.clsBottomLayer);\n\t\tRsyn::PhysicalLayer cut = getPhysicalLayerByName(via.clsCutLayer);\n\t\tRsyn::PhysicalLayer top = getPhysicalLayerByName(via.clsTopLayer);\n\t\tphVia->clsLayers[BOTTOM_VIA_LAYER] = bottom.data;\n\t\tphVia->clsLayers[CUT_VIA_LAYER] = cut.data;\n\t\tphVia->clsLayers[TOP_VIA_LAYER] = top.data;\n\n\t\tif (via.clsHasRowCol) {\n\t\t\tphVia->clsHasRowCol = true;\n\t\t\tphVia->clsNumRows = via.clsNumCutRows;\n\t\t\tphVia->clsNumCols = via.clsNumCutCols;\n\t\t} // end if \n\t\tif (via.clsHasOrigin) {\n\t\t\tphVia->clsHasOrigin = true;\n\t\t\tphVia->clsOrigin[X] = convertMicronToLibraryDatabaseUnits(via.clsXOrigin);\n\t\t\tphVia->clsOrigin[Y] = convertMicronToLibraryDatabaseUnits(via.clsYOrigin);\n\t\t} // end if \n\t\tif (via.clsHasOffset) {\n\t\t\tphVia->clsHasOffset = true;\n\t\t\tphVia->clsOffset[BOTTOM_VIA_LEVEL][X] = convertMicronToLibraryDatabaseUnits(via.clsXBottomOffset);\n\t\t\tphVia->clsOffset[TOP_VIA_LEVEL][Y] = convertMicronToLibraryDatabaseUnits(via.clsYBottomOffset);\n\t\t\tphVia->clsOffset[BOTTOM_VIA_LEVEL][X] = convertMicronToLibraryDatabaseUnits(via.clsXTopOffset);\n\t\t\tphVia->clsOffset[TOP_VIA_LEVEL][Y] = convertMicronToLibraryDatabaseUnits(via.clsYTopOffset);\n\t\t} // end if \n\t} else {\n\t\tif (via.clsHasResistance) {\n\t\t\tphVia->clsHasCutResistance = true;\n\t\t\tphVia->clsCutResistance = via.clsCutResistance;\n\t\t} // end if \n\n\t\tstd::vector<std::tuple<int, PhysicalLayerData *>> layers;\n\t\tfor (const std::pair < std::string, std::deque < LefViaGeometryDscp>> &geoPair : via.clsGeometries) {\n\t\t\tconst std::string & layerName = geoPair.first;\n\t\t\tRsyn::PhysicalLayer layer = getPhysicalLayerByName(layerName);\n\t\t\tassert(layer);\n\t\t\tlayers.push_back(std::make_tuple(layer.getIndex(), layer.data));\n\t\t} // end for \n\t\tstd::sort(layers.begin(), layers.end());\n\t\t//\tassert(layers.size() == NUM_VIA_LAYERS);\n\t\tfor (int i = 0; i < NUM_VIA_LAYERS; i++) {\n\t\t\tPhysicalLayerData * layerData = std::get<1>(layers[i]);\n\t\t\tphVia->clsLayers[i] = layerData;\n\t\t\tstd::vector<Rsyn::PhysicalViaGeometry>  & viaGeos = phVia->clsViaGeometries[i];\n\t\t\tauto iterator = via.clsGeometries.find(layerData->clsName);\n\t\t\tconst std::deque<LefViaGeometryDscp> & geoDscps = iterator->second;\n\t\t\tviaGeos.reserve(geoDscps.size());\n\t\t\tfor (const LefViaGeometryDscp & geoDscp : geoDscps) {\n\t\t\t\tviaGeos.push_back(Rsyn::PhysicalViaGeometry(new ViaGeometryData()));\n\t\t\t\tRsyn::PhysicalViaGeometry viaGeo = viaGeos.back();\n\t\t\t\tviaGeo->id = viaGeos.size() -1;\n\t\t\t\tconst DoubleRectangle & doubleRect = geoDscp.clsBounds;\n\t\t\t\tBounds & bds = viaGeo->clsBounds;\n\t\t\t\tbds[LOWER][X] = convertMicronToLibraryDatabaseUnits(doubleRect[LOWER][X]);\n\t\t\t\tbds[LOWER][Y] = convertMicronToLibraryDatabaseUnits(doubleRect[LOWER][Y]);\n\t\t\t\tbds[UPPER][X] = convertMicronToLibraryDatabaseUnits(doubleRect[UPPER][X]);\n\t\t\t\tbds[UPPER][Y] = convertMicronToLibraryDatabaseUnits(doubleRect[UPPER][Y]);\n\t\t\t} // end for \n\t\t} // end for\n\t} // end if-else \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalViaRule(const LefViaRuleDscp & via) {\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalViaRuleBases.find(via.clsName);\n\tif (it != data->clsMapPhysicalViaRuleBases.end()) {\n\t\tstd::cout << \"WARNING: Via Rule \" << via.clsName << \" was already defined. Skipping ...\\n\";\n\t\treturn;\n\t} // end if \n\n\t// Adding new lib site\n\tdata->clsMapPhysicalViaRuleBases[via.clsName] = data->clsPhysicalViaRuleBases.size();\n\tdata->clsPhysicalViaRuleBases.push_back(PhysicalViaRuleBase(new ViaRuleData()));\n\tPhysicalViaRuleBase phViaRuleBase = data->clsPhysicalViaRuleBases.back();\n\tphViaRuleBase->init();\n\tphViaRuleBase->id = data->clsPhysicalViaRuleBases.size() - 1;\n\tphViaRuleBase->clsName = via.clsName;\n\n\n\t// get index for the routing and cut layers.\n\tstd::set<int> layerIds;\n\tint cutLayerId;\n\tfor (int i = 0; i < via.clsLayers.size(); i++) {\n\t\tconst LefViaRuleLayerDscp & viaLayerDscp = via.clsLayers[i];\n\t\tRsyn::PhysicalLayer viaLayer = getPhysicalLayerByName(viaLayerDscp.clsName);\n\t\tif (viaLayer.getType() == Rsyn::PhysicalLayerType::CUT) {\n\t\t\tcutLayerId = i;\n\t\t} else {\n\t\t\tlayerIds.insert(i);\n\t\t} // end if \n\t} // end for \n\n\t// Routing layers\n\tconst LefViaRuleLayerDscp & viaLayerDscp0 = via.clsLayers[*layerIds.begin()];\n\tconst LefViaRuleLayerDscp & viaLayerDscp1 = via.clsLayers[*layerIds.rbegin()];\n\tRsyn::PhysicalLayer layer0 = getPhysicalLayerByName(viaLayerDscp0.clsName);\n\tRsyn::PhysicalLayer layer1 = getPhysicalLayerByName(viaLayerDscp1.clsName);\n\n\tPhysicalViaLayerType layerType0 = BOTTOM_VIA_LAYER;\n\tPhysicalViaLayerType layerType1 = TOP_VIA_LAYER;\n\tViaLevel layerLevel0 = BOTTOM_VIA_LEVEL;\n\tViaLevel layerLevel1 = TOP_VIA_LEVEL;\n\tif (layer0.getRelativeIndex() > layer1.getRelativeIndex()) {\n\t\tlayerType0 = TOP_VIA_LAYER;\n\t\tlayerLevel0 = TOP_VIA_LEVEL;\n\t\tlayerType1 = BOTTOM_VIA_LAYER;\n\t\tlayerLevel1 = BOTTOM_VIA_LEVEL;\n\t} // end if \n\n\tif (viaLayerDscp0.clsHasWidth) {\n\t\tphViaRuleBase->clsHasWidth[layerLevel0] = true;\n\t\tphViaRuleBase->clsWidth[layerLevel0][ViaRange::VIA_RANGE_MIN] = convertMicronToLibraryDatabaseUnits(viaLayerDscp0.clsMinWidth);\n\t\tphViaRuleBase->clsWidth[layerLevel0][ViaRange::VIA_RANGE_MAX] = convertMicronToLibraryDatabaseUnits(viaLayerDscp0.clsMaxWidth);\n\t} // end if \n\tif (viaLayerDscp1.clsHasWidth) {\n\t\tphViaRuleBase->clsHasWidth[layerLevel1] = true;\n\t\tphViaRuleBase->clsWidth[layerLevel1][ViaRange::VIA_RANGE_MIN] = convertMicronToLibraryDatabaseUnits(viaLayerDscp1.clsMinWidth);\n\t\tphViaRuleBase->clsWidth[layerLevel1][ViaRange::VIA_RANGE_MAX] = convertMicronToLibraryDatabaseUnits(viaLayerDscp1.clsMaxWidth);\n\t} // end if \n\n\n\tif (!via.clsIsGenerate) {\n\t\tphViaRuleBase->clsIsGenerate = false;\n\t\tphViaRuleBase->clsRelativeIndex = data->clsPhysicalViaRules.size();\n\t\tdata->clsPhysicalViaRules.push_back(Rsyn::PhysicalViaRule(phViaRuleBase.data));\n\t\tphViaRuleBase->clsLayers[layerLevel0] = layer0.data;\n\t\tphViaRuleBase->clsLayers[layerLevel1] = layer1.data;\n\t\tphViaRuleBase->clsLayerDirection[layerLevel0] = viaLayerDscp0.clsIsHorizontal ? PhysicalLayerDirection::HORIZONTAL : PhysicalLayerDirection::VERTICAL;\n\t\tphViaRuleBase->clsLayerDirection[layerLevel1] = viaLayerDscp1.clsIsHorizontal ? PhysicalLayerDirection::HORIZONTAL : PhysicalLayerDirection::VERTICAL;\n\n\n\t\tif (!via.clsVias.empty()) {\n\t\t\tphViaRuleBase->clsVias.reserve(via.clsVias.size());\n\t\t\tfor (const std::string & viaName : via.clsVias) {\n\t\t\t\tRsyn::PhysicalVia phVia = getPhysicalViaByName(viaName);\n\t\t\t\tif (phVia == nullptr) {\n\t\t\t\t\tstd::cout << \"Via \" << viaName << \" is not defined in library. Skipping ...\\n\";\n\t\t\t\t\tcontinue;\n\t\t\t\t} // end if \n\t\t\t\tphViaRuleBase->clsVias.push_back(phVia);\n\t\t\t} // end for \n\t\t} // end if \n\t} else {\n\t\tphViaRuleBase->clsIsGenerate = true;\n\t\tphViaRuleBase->clsIsDefault = via.clsIsDefault;\n\t\tphViaRuleBase->clsRelativeIndex = data->clsPhysicalViaRuleGenerates.size();\n\t\tdata->clsPhysicalViaRuleGenerates.push_back(Rsyn::PhysicalViaRuleGenerate(phViaRuleBase.data));\n\n\t\t// cut layer\n\t\tconst LefViaRuleLayerDscp & cutLayerDscp = via.clsLayers[cutLayerId];\n\t\tRsyn::PhysicalLayer cutLayer = getPhysicalLayerByName(cutLayerDscp.clsName);\n\t\tphViaRuleBase->clsLayers[CUT_VIA_LAYER] = cutLayer.data;\n\n\t\tDoubleRectangle doubleRect = cutLayerDscp.clsRect;\n\t\tBounds & bds = phViaRuleBase->clsCutBounds;\n\t\tbds[LOWER][X] = convertMicronToLibraryDatabaseUnits(doubleRect[LOWER][X]);\n\t\tbds[LOWER][Y] = convertMicronToLibraryDatabaseUnits(doubleRect[LOWER][Y]);\n\t\tbds[UPPER][X] = convertMicronToLibraryDatabaseUnits(doubleRect[UPPER][X]);\n\t\tbds[UPPER][Y] = convertMicronToLibraryDatabaseUnits(doubleRect[UPPER][Y]);\n\t\tphViaRuleBase->clsCutSpacing[X] = convertMicronToLibraryDatabaseUnits(cutLayerDscp.clsXSpacing);\n\t\tphViaRuleBase->clsCutSpacing[Y] = convertMicronToLibraryDatabaseUnits(cutLayerDscp.clsYSpacing);\n\t\tif (cutLayerDscp.clsHasResistance) {\n\t\t\tphViaRuleBase->clsHasCutResistance = true;\n\t\t\tphViaRuleBase->clsCutResistance = cutLayerDscp.clsCutResistance;\n\t\t} // end if \n\n\n\t\tphViaRuleBase->clsLayers[layerType0] = layer0.data;\n\t\tphViaRuleBase->clsLayers[layerType1] = layer1.data;\n\t\tphViaRuleBase->clsEnclosure1[layerLevel0] = convertMicronToLibraryDatabaseUnits(viaLayerDscp0.clsEnclosure1);\n\t\tphViaRuleBase->clsEnclosure1[layerLevel1] = convertMicronToLibraryDatabaseUnits(viaLayerDscp1.clsEnclosure1);\n\t\tphViaRuleBase->clsEnclosure2[layerLevel0] = convertMicronToLibraryDatabaseUnits(viaLayerDscp0.clsEnclosure2);\n\t\tphViaRuleBase->clsEnclosure2[layerLevel1] = convertMicronToLibraryDatabaseUnits(viaLayerDscp1.clsEnclosure2);\n\t} // end if-else \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::LibraryCell PhysicalDesign::addPhysicalLibraryCell(const LefMacroDscp& macro) {\n\tconst std::string& name = macro.clsMacro->name();\n\tRsyn::LibraryCell lCell = data->clsDesign.findLibraryCellByName(name);\n\tif (!lCell) {\n\t\tthrow Exception(\"Library Cell \" + name + \" not found.\\n\");\n\t} // end if\n\tRsyn::PhysicalLibraryCellData &phlCell = data->clsPhysicalLibraryCells[lCell];\n    phlCell.clsMacro = macro.clsMacro;\n\tdouble2 size(macro.clsMacro->sizeX(), macro.clsMacro->sizeY());\n\tsize.scale(static_cast<double> (getDatabaseUnits(LIBRARY_DBU)));\n\tphlCell.clsSize[X] = static_cast<DBU> (std::round(size[X]));\n\tphlCell.clsSize[Y] = static_cast<DBU> (std::round(size[Y]));\n\t// Initializing obstacles in the physical library cell\n\tphlCell.clsObs.reserve(macro.clsObs.size());\n\tfor (const LefObsDscp &libObs : macro.clsObs) {\n\t\tPhysicalObstacle phObs(new PhysicalObstacleData());\n\n\t\t// Guilherme Flach - 2016/11/04 - micron to dbu\n\t\tstd::vector<Bounds> scaledBounds;\n\t\tscaledBounds.reserve(libObs.clsBounds.size());\n\t\tfor (DoubleRectangle doubleRect : libObs.clsBounds) {\n\t\t\t// Jucemar Monteiro - 2017/05/20 - Avoiding cast round errors.\n\t\t\tdoubleRect.scaleCoordinates(static_cast<double> (getDatabaseUnits(LIBRARY_DBU)));\n\t\t\tscaledBounds.push_back(Bounds());\n\t\t\tBounds & bds = scaledBounds.back();\n\t\t\tbds[LOWER][X] = static_cast<DBU> (std::round(doubleRect[LOWER][X]));\n\t\t\tbds[LOWER][Y] = static_cast<DBU> (std::round(doubleRect[LOWER][Y]));\n\t\t\tbds[UPPER][X] = static_cast<DBU> (std::round(doubleRect[UPPER][X]));\n\t\t\tbds[UPPER][Y] = static_cast<DBU> (std::round(doubleRect[UPPER][Y]));\n\t\t} // end for\n\n\t\tphlCell.clsObs.push_back(phObs);\n//\t\tif (macro.clsMacroName == \"bufx2\" || macro.clsMacroName == \"BUFX2\") {\n//\t\t\tstd::cout << \"----#Obstacles: \" << macro.clsObs.size() << \"\\n\";\n//\t\t\tstd::cout << \"\" << macro.clsObs[0].clsBounds.size() << \"\\n\";\n//\t\t}\n\t\tif (data->clsEnableMergeRectangles && libObs.clsBounds.size() > 1) {\n\t\t\tstd::vector<Bounds> bounds;\n\t\t\tmergeBounds(scaledBounds, bounds);\n\t\t\tphObs->clsBounds.reserve(bounds.size());\n\t\t\tfor (Bounds & rect : bounds) {\n\t\t\t\t//rect.scaleCoordinates(data->clsDesignUnits);\n\t\t\t\tphObs->clsBounds.push_back(rect);\n\t\t\t} // end for \n\t\t} else {\n\t\t\tphObs->clsBounds = scaledBounds;\n\t\t} // end if-else \n\t\tphObs->clsLayer = getPhysicalLayerByName(libObs.clsMetalLayer);\n\n\t\t// Mateus - 2018/03/11 - Defensive programming to avoid crashes in ICCAD15 benchmarks.\n\t\tif (!phObs->clsLayer)\n\t\t\tcontinue;\n\n\t\tphObs->id = phlCell.clsObs.size() - 1;\n\t\t// Hard code. After implementing mapping structure in Rsyn, remove this line.\n\t\tif (libObs.clsMetalLayer.compare(\"metal1\") == 0) {\n\t\t\tphlCell.clsLayerBoundIndex = phlCell.clsObs.size() - 1;\n\t\t} // end if \n\t\tRsyn::PhysicalObstacle topPhObs = phlCell.clsTopLayerObs;\n\t\tif (topPhObs != nullptr) {\n\t\t\tif (topPhObs.getLayer().getIndex() < phObs->clsLayer.getIndex())\n\t\t\t\tphlCell.clsTopLayerObs = phObs;\n\t\t} else {\n\t\t\tphlCell.clsTopLayerObs = phObs;\n\t\t}\n\t} // end for\n\n\t// adding physical library cell boundaries defined as a polygon\n\t// benchmarks of ICCAD contest define some macro boundaries as metal 1 blockages\n\tif (phlCell.clsLayerBoundIndex >= 0) {\n\t\tPhysicalObstacle phObs = phlCell.clsObs[phlCell.clsLayerBoundIndex];\n\n\t\tif (phObs.getNumObs() > 1) { // if boundaries are defined by a rectangle. Then boundaries number is one because it is rectangle.\n\t\t\tDBUxy lower, upper;\n\t\t\tconst Bounds & fst = phObs.allBounds().front();\n\t\t\tlower = fst[LOWER];\n\t\t\tupper = fst[UPPER];\n\t\t\tupper[Y] = lower[Y];\n\t\t\tstd::list<DBUxy> upperPoints;\n\t\t\tupperPoints.push_back(upper);\n\t\t\tphlCell.clsPolygonBounds.addPoint(lower[X], lower[Y]);\n\t\t\tfor (const Bounds & bds : phObs.allBounds()) {\n\t\t\t\tDBUxy lowPt = bds[LOWER];\n\t\t\t\tDBUxy uppPt = bds[UPPER];\n\t\t\t\tif (lowPt[X] != lower[X]) {\n\t\t\t\t\tphlCell.clsPolygonBounds.addPoint(lower[X], lowPt[Y]);\n\t\t\t\t\tlower = lowPt;\n\t\t\t\t\tphlCell.clsPolygonBounds.addPoint(lower[X], lower[Y]);\n\t\t\t\t} // end if \n\t\t\t\tif (uppPt[X] != upper[X]) {\n\t\t\t\t\tupperPoints.push_front(DBUxy(upper[X], lowPt[Y]));\n\t\t\t\t\tupper = uppPt;\n\t\t\t\t\tupper[Y] = lowPt[Y];\n\t\t\t\t\tupperPoints.push_front(upper);\n\t\t\t\t} // en if \n\t\t\t} // end for \n\t\t\tupperPoints.push_front(phObs.allBounds().back()[UPPER]);\n\t\t\tphlCell.clsPolygonBounds.addPoint(phObs.allBounds().back()[LOWER][X],\n\t\t\t\tphObs.allBounds().back()[UPPER][Y]);\n\n\t\t\tfor (DBUxy point : upperPoints) {\n\t\t\t\tphlCell.clsPolygonBounds.addPoint(point[X], point[Y]);\n\t\t\t} // end for \n\t\t} // end if \n\t} // end if\n\n\treturn lCell;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalLibraryPin(Rsyn::LibraryCell libCell, const LefPinDscp& lefPin) {\n\tRsyn::LibraryPin rsynLibraryPin = libCell.getLibraryPinByName(lefPin.clsPinName);\n\tif (!rsynLibraryPin) {\n\t\tthrow Exception(\"Pin '\" + lefPin.clsPinName + \"' not found in library cell '\" + libCell.getName() + \"'.\\n\");\n\t} // end if\n\tRsyn::PhysicalLibraryPinData &phyPin = data->clsPhysicalLibraryPins[rsynLibraryPin];\n\tphyPin.clsLibraryCell = getPhysicalLibraryCell(libCell);\n\n\tphyPin.clsDirection = Rsyn::getPhysicalPinDirection(lefPin.clsPinDirection);\n\tphyPin.clsUse = Rsyn::getPhysicalPinUseType(lefPin.clsPinUse);\n\t//Assuming that the pin has only one port.\n\tphyPin.clsPhysicalPinGeometries.reserve(lefPin.clsPorts.size());\n\tfor (const LefPortDscp & lefPort : lefPin.clsPorts) {\n\t\tphyPin.clsPhysicalPinGeometries.push_back(PhysicalPinGeometry(new PhysicalPinGeometryData()));\n\t\tPhysicalPinGeometry phPinPort = phyPin.clsPhysicalPinGeometries.back();\n\t\tphPinPort->id = phyPin.clsPhysicalPinGeometries.size() - 1;\n\n\t\tphyPin.clsLayerBound[LOWER] = DBUxy(std::numeric_limits<DBU>::max(), std::numeric_limits<DBU>::max());\n\t\tphyPin.clsLayerBound[UPPER] = DBUxy(std::numeric_limits<DBU>::min(), std::numeric_limits<DBU>::min());\n\n\t\tphPinPort->clsPinLayers.reserve(lefPort.clsLefPortGeoDscp.size());\n\t\tfor (const LefPortGeometryDscp & lefPortGeo : lefPort.clsLefPortGeoDscp) {\n\t\t\tphPinPort->clsPinLayers.push_back(PhysicalPinLayer(new PhysicalPinLayerData()));\n\t\t\tPhysicalPinLayer phPinLayer = phPinPort->clsPinLayers.back();\n\t\t\tphPinLayer->id = phPinPort->clsPinLayers.size() - 1;\n\t\t\tphPinLayer->clsLibLayer = getPhysicalLayerByName(lefPortGeo.clsMetalName);\n\n\t\t\t//ICCAD 2015 contest pin bounds definition\n\t\t\tif (!lefPortGeo.clsBounds.empty()) {\n\t\t\t\tphPinLayer->clsBounds.reserve(lefPortGeo.clsBounds.size());\n\t\t\t\tfor (DoubleRectangle doubleRect : lefPortGeo.clsBounds) {\n\t\t\t\t\tdoubleRect.scaleCoordinates(static_cast<double> (getDatabaseUnits(LIBRARY_DBU)));\n\t\t\t\t\tphPinLayer->clsBounds.push_back(Bounds());\n\t\t\t\t\tBounds & bds = phPinLayer->clsBounds.back();\n\t\t\t\t\tbds[LOWER][X] = static_cast<DBU> (std::round(doubleRect[LOWER][X]));\n\t\t\t\t\tbds[LOWER][Y] = static_cast<DBU> (std::round(doubleRect[LOWER][Y]));\n\t\t\t\t\tbds[UPPER][X] = static_cast<DBU> (std::round(doubleRect[UPPER][X]));\n\t\t\t\t\tbds[UPPER][Y] = static_cast<DBU> (std::round(doubleRect[UPPER][Y]));\n\n\t\t\t\t\tphyPin.clsLayerBound[LOWER][X] = std::min(phyPin.clsLayerBound[LOWER][X], bds[LOWER][X]);\n\t\t\t\t\tphyPin.clsLayerBound[LOWER][Y] = std::min(phyPin.clsLayerBound[LOWER][Y], bds[LOWER][Y]);\n\t\t\t\t\tphyPin.clsLayerBound[UPPER][X] = std::max(phyPin.clsLayerBound[UPPER][X], bds[UPPER][X]);\n\t\t\t\t\tphyPin.clsLayerBound[UPPER][Y] = std::max(phyPin.clsLayerBound[UPPER][Y], bds[UPPER][Y]);\n\t\t\t\t} // end for\n\t\t\t} // end if \n\t\t\tif (!lefPortGeo.clsLefPolygonDscp.empty()) {\n\t\t\t\tphyPin.clsLayerBound[LOWER] = DBUxy(std::numeric_limits<DBU>::max(), std::numeric_limits<DBU>::max());\n\t\t\t\tphyPin.clsLayerBound[UPPER] = DBUxy(std::numeric_limits<DBU>::min(), std::numeric_limits<DBU>::min());\n\t\t\t\tphPinLayer->clsPolygons.reserve(lefPortGeo.clsLefPolygonDscp.size());\n\t\t\t\tfor (const LefPolygonDscp & poly : lefPortGeo.clsLefPolygonDscp) {\n\t\t\t\t\tphPinLayer->clsPolygons.resize(phPinLayer->clsPolygons.size() + 1);\n\t\t\t\t\tPolygon &polygon = phPinLayer->clsPolygons.back();\n\n\t\t\t\t\tfor (double2 point : poly.clsPolygonPoints) {\n\t\t\t\t\t\tpoint.scale(static_cast<double> (getDatabaseUnits(LIBRARY_DBU)));\n\t\t\t\t\t\tDBUxy pt(static_cast<DBU> (std::round(point[X])), static_cast<DBU> (std::round(point[Y])));\n\t\t\t\t\t\tpolygon.addPoint(pt[X], pt[Y]);\n\t\t\t\t\t\tphyPin.clsLayerBound[LOWER][X] = std::min(phyPin.clsLayerBound[LOWER][X], pt[X]);\n\t\t\t\t\t\tphyPin.clsLayerBound[LOWER][Y] = std::min(phyPin.clsLayerBound[LOWER][Y], pt[Y]);\n\t\t\t\t\t\tphyPin.clsLayerBound[UPPER][X] = std::max(phyPin.clsLayerBound[UPPER][X], pt[X]);\n\t\t\t\t\t\tphyPin.clsLayerBound[UPPER][Y] = std::max(phyPin.clsLayerBound[UPPER][Y], pt[Y]);\n\t\t\t\t\t} // end for\n\t\t\t\t} // end for \n\t\t\t} // end if \n\t\t} //  end for \n\t\tif (phPinPort.getNumPinLayers() > 1) {\n\t\t\tstd::sort(phPinPort->clsPinLayers.begin(), phPinPort->clsPinLayers.end(),\n\t\t\t\t[](PhysicalPinLayer phPinLayer0, PhysicalPinLayer phPinLayer1) {\n\t\t\t\t\tRsyn::PhysicalLayer phLayer0 = phPinLayer0.getLayer();\n\t\t\t\t\tRsyn::PhysicalLayer phLayer1 = phPinLayer1.getLayer();\n\t\t\t\t\treturn phLayer0.getIndex() < phLayer1.getIndex();\n\t\t\t\t}); // end sort \n\t\t} // end if \n\t} // end for \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalCell(Rsyn::Instance cell, const DefComponentDscp& component) {\n\tPhysicalLibraryCellData &phLibCell = data->clsPhysicalLibraryCells[cell.asCell().getLibraryCell()]; // TODO: assuming instance is a cell\n\n\tPhysicalInstanceData & physicalCell = data->clsPhysicalInstances[cell];\n\tphysicalCell.clsInstance = cell;\n\tRsyn::InstanceTag tag = data->clsDesign.getTag(cell);\n\ttag.setFixed(component.clsIsFixed);\n\tconst bool isBlock = !strcmp(phLibCell.clsMacro->macroClass(), \"BLOCK\");\n\tconst bool isRing = !strcmp(phLibCell.clsMacro->macroClass(), \"RING\");\n\ttag.setMacroBlock(isBlock || isRing);\n\tif (component.clsIsFixed) {\n\t\tif (phLibCell.clsLayerBoundIndex > -1) {\n\t\t\tPhysicalObstacle obs = phLibCell.clsObs[phLibCell.clsLayerBoundIndex];\n\t\t\tdata->clsNumElements[PHYSICAL_FIXEDBOUNDS] += obs->clsBounds.size();\n\t\t} else {\n\t\t\tdata->clsNumElements[PHYSICAL_FIXEDBOUNDS]++;\n\t\t} // end if-else\n\t\tdata->clsNumElements[PHYSICAL_FIXED]++;\n\t} // end if \n\tphysicalCell.clsPlaced = component.clsIsPlaced;\n\tphysicalCell.clsBlock = isBlock;\n\tif (physicalCell.clsBlock)\n\t\tdata->clsNumElements[PHYSICAL_BLOCK]++;\n\tif (cell.isMovable())\n\t\tdata->clsNumElements[PHYSICAL_MOVABLE]++;\n\tphysicalCell.clsHasLayerBounds = phLibCell.clsLayerBoundIndex > -1;\n\tphysicalCell.clsInstance->clsOrientation = getPhysicalOrientation(component.clsOrientation);\n\n\tconst DBU width = phLibCell.clsSize[X];\n\tconst DBU height = phLibCell.clsSize[Y];\n\n\tDBUxy pos = component.clsPos;\n\tphysicalCell.clsInitialPos = pos;\n\tpos[X] += width;\n\tpos[Y] += height;\n\tphysicalCell.clsInstance->clsBounds.updatePoints(physicalCell.clsInitialPos, pos);\n\n\tDBU area = width * height;\n\tif (physicalCell.clsBlock)\n\t\tdata->clsTotalAreas[PHYSICAL_BLOCK] += area;\n\tif (cell.isFixed()) {\n\t\tif (cell.isPort())\n\t\t\tdata->clsTotalAreas[PHYSICAL_PORT] += area;\n\t\telse\n\t\t\tdata->clsTotalAreas[PHYSICAL_FIXED] += area;\n\t} else {\n\t\tdata->clsTotalAreas[PHYSICAL_MOVABLE] += area;\n\t} // end if-else \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalPort(Rsyn::Instance cell, const DefPortDscp& port) {\n\tPhysicalInstanceData & physicalGate = data->clsPhysicalInstances[cell];\n\tphysicalGate.clsPortLayer = getPhysicalLayerByName(port.clsLayerName);\n\tphysicalGate.clsInstance = cell;\n\tphysicalGate.clsInstance->clsOrientation = getPhysicalOrientation(port.clsOrientation);\n\tphysicalGate.clsInstance->clsBounds = port.clsLayerBounds;\n\tphysicalGate.clsInstance->clsPortPos = port.clsPos;\n\tphysicalGate.clsPort = true;\n\tRsyn::InstanceTag tag = data->clsDesign.getTag(cell);\n\t// TODO Getting from port descriptor if it is fixed.\n\ttag.setFixed(true);\n\ttag.setMacroBlock(false);\n} // end method  \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalRow(const DefRowDscp& defRow) {\n\tPhysicalSite phSite = getPhysicalSiteByName(defRow.clsSite);\n\tif (!phSite)\n\t\tthrow Exception(\"Site \" + defRow.clsSite + \" was not find for row \" + defRow.clsName);\n\n\t// Creates a new cell in the data structure.\n\tPhysicalRowData * phRowData = &(data->clsPhysicalRows.create()->value); // TODO: awful\n\tphRowData->id = data->clsPhysicalRows.lastId();\n\tphRowData->clsRowName = defRow.clsName;\n\tphRowData->clsPhysicalSite = phSite;\n\tphRowData->clsSiteOrientation = Rsyn::getPhysicalOrientation(defRow.clsOrientation);\n\tphRowData->clsOrigin = defRow.clsOrigin;\n\tphRowData->clsStep[X] = phSite.getWidth();\n\tphRowData->clsStep[Y] = phSite.getHeight();\n\tphRowData->clsNumSites[X] = defRow.clsNumX;\n\tphRowData->clsNumSites[Y] = defRow.clsNumY;\n\tphRowData->clsBounds[LOWER][X] = defRow.clsOrigin[X];\n\tphRowData->clsBounds[LOWER][Y] = defRow.clsOrigin[Y];\n\tphRowData->clsBounds[UPPER][X] = defRow.clsOrigin[X] + phRowData->getWidth();\n\tphRowData->clsBounds[UPPER][Y] = defRow.clsOrigin[Y] + phRowData->getHeight();\n\tRsyn::PhysicalModule phModule = getPhysicalModule(data->clsModule);\n\tBounds & bounds = phModule->clsInstance->clsBounds;\n\tbounds[LOWER] = min(bounds[LOWER], phRowData->clsBounds[LOWER]);\n\tbounds[UPPER] = max(bounds[UPPER], phRowData->clsBounds[UPPER]);\n\tdata->clsTotalAreas[PHYSICAL_PLACEABLE] += phRowData->clsBounds.computeArea();\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalRegion(const DefRegionDscp& defRegion) {\n\tdata->clsPhysicalRegions.push_back(PhysicalRegion(new PhysicalRegionData()));\n\tRsyn::PhysicalRegion phRegion = data->clsPhysicalRegions.back();\n\tphRegion->id = data->clsPhysicalRegions.size() - 1;\n\tphRegion->clsName = defRegion.clsName;\n\tphRegion->clsType = Rsyn::getPhysicalRegionType(defRegion.clsType);\n\tphRegion->clsBounds = defRegion.clsBounds;\n\tdata->clsMapPhysicalRegions[defRegion.clsName] = phRegion->id;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalGroup(const DefGroupDscp& defGroup) {\n\tdata->clsPhysicalGroups.push_back(PhysicalGroup(new PhysicalGroupData()));\n\tRsyn::PhysicalGroup phGroup = data->clsPhysicalGroups.back();\n\tphGroup->id = data->clsPhysicalGroups.size() - 1;\n\tphGroup->clsName = defGroup.clsName;\n\tphGroup->clsPatterns = defGroup.clsPatterns;\n\tphGroup->clsRegion = getPhysicalRegionByName(defGroup.clsRegion);\n\tdata->clsMapPhysicalGroups[defGroup.clsName] = phGroup->id;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalNet(const DefNetDscp & netDscp) {\n\tRsyn::Net net = data->clsDesign.findNetByName(netDscp.clsName);\n\tPhysicalNetData & netData = data->clsPhysicalNets[net];\n\tRsyn::PhysicalRouting & routing = netData.clsRouting;\n\tnetData.clsNet = net;\n\tfor (const DefWireDscp & wireDscp : netDscp.clsWires) {\n\t\tfor (const DefWireSegmentDscp & segmentDscp : wireDscp.clsWireSegments) {\n\t\t\tRsyn::PhysicalLayer physicalLayer = getPhysicalLayerByName(segmentDscp.clsLayerName);\n\n\t\t\tint numPoints = segmentDscp.clsRoutingPoints.size();\n\t\t\tRsyn::PhysicalRoutingWire wire;\n\t\t\tfor (const DefRoutingPointDscp & point : segmentDscp.clsRoutingPoints) {\n\t\t\t\tif (point.clsHasRectangle) {\n\t\t\t\t\tBounds bds = point.clsRect;\n\t\t\t\t\tbds.translate(point.clsPos);\n\t\t\t\t\trouting.addRect(physicalLayer, bds);\n\t\t\t\t} else if (point.clsHasVia) {\n\t\t\t\t\tDBUxy pos = segmentDscp.clsRoutingPoints.back().clsPos;\n\t\t\t\t\tRsyn::PhysicalVia physicalVia = getPhysicalViaByName(point.clsViaName);\n\t\t\t\t\trouting.addVia(physicalVia, pos);\n\t\t\t\t} // end if-else \n\t\t\t\tif (numPoints > 1) {\n\t\t\t\t\twire.addRoutingPoint(point.clsPos);\n\t\t\t\t} // end if \n\t\t\t} // end for \n\t\t\t// it is a wire \n\t\t\tif (numPoints > 1) {\n\t\t\t\twire.setLayer(physicalLayer);\n\t\t\t\tconst DefRoutingPointDscp & source = segmentDscp.clsRoutingPoints.front();\n\t\t\t\tconst DefRoutingPointDscp & target = segmentDscp.clsRoutingPoints.back();\n\t\t\t\tif (source.clsHasExtension)\n\t\t\t\t\twire.setSourceExtension(source.clsExtension);\n\t\t\t\tif (target.clsHasExtension)\n\t\t\t\t\twire.setTargetExtension(target.clsExtension);\n\t\t\t\tif (segmentDscp.clsRoutedWidth > 0) {\n\t\t\t\t\twire.setWidth(segmentDscp.clsRoutedWidth);\n\t\t\t\t} // end if\n\t\t\t\trouting.addWire(wire);\n\t\t\t} // end if \n\t\t} // end for\n\t} // end for\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalSpecialNet(const DefNetDscp & specialNet) {\n\tdata->clsPhysicalSpecialNets.push_back(PhysicalSpecialNet(new PhysicalSpecialNetData()));\n\tRsyn::PhysicalSpecialNet phSpecialNet = data->clsPhysicalSpecialNets.back();\n\tphSpecialNet->id = data->clsPhysicalSpecialNets.size() - 1;\n\tdata->clsMapPhysicalSpecialNets[specialNet.clsName] = data->clsPhysicalSpecialNets.size() - 1;\n\tphSpecialNet->clsNet = specialNet;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalTracks(const DefTrackDscp &track) {\n\tdata->clsPhysicalTracks.push_back(PhysicalTracks(new PhysicalTracksData()));\n\tRsyn::PhysicalTracks phTrack = data->clsPhysicalTracks.back();\n\tphTrack->id = data->clsPhysicalTracks.size() - 1;\n\tphTrack->clsDirection = Rsyn::getPhysicalTrackDirectionDEF(track.clsDirection);\n\tphTrack->clsLocation = track.clsLocation;\n\tphTrack->clsNumTracks = track.clsNumTracks;\n\tphTrack->clsSpace = track.clsSpace;\n\tphTrack->clsLayers.reserve(track.clsLayers.size());\n\tfor (const std::string & layerName : track.clsLayers) {\n\t\tRsyn::PhysicalLayer phLayer = getPhysicalLayerByName(layerName);\n\t\tif (phLayer) {\n\t\t\tphTrack->clsLayers.push_back(phLayer);\n\t\t\tstd::vector<Rsyn::PhysicalTracks> & trackLayer = data->clsMapLayerToTracks[phLayer];\n\t\t\ttrackLayer.push_back(phTrack);\n\t\t} // end if\n\t} // end for\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::initRoutingGrid() {\n\tfor (Rsyn::PhysicalTracks track : allPhysicalTracks()) {\n\t\tfor (Rsyn::PhysicalLayer phLayer : track.allLayers()) {\n\t\t\tif (data->clsMapLayerToRoutingGrid.find(phLayer) == data->clsMapLayerToRoutingGrid.end()) {\n\t\t\t\tdata->clsPhysicalRoutingGrids.push_back(PhysicalRoutingGrid(new PhysicalRoutingGridData()));\n\t\t\t\tdata->clsMapLayerToRoutingGrid[phLayer] = data->clsPhysicalRoutingGrids.back();\n\t\t\t} // end if \n\t\t\tRsyn::PhysicalRoutingGrid routingGrid = data->clsMapLayerToRoutingGrid[phLayer];\n\t\t\troutingGrid->clsLayer = phLayer;\n\t\t\troutingGrid->clsTracks.push_back(track);\n\t\t} // end for \n\t} // end for \n\n\t// to use std::sort algorithm, the operator int() const in Proxy must be public. Otherwise, there is a compiler error\n\tdata->clsPhysicalRoutingGrids.clear();\n\tfor (Rsyn::PhysicalLayer layer : allPhysicalLayers()) {\n\t\tif (!hasPhysicalRoutingGrid(layer))\n\t\t\tcontinue;\n\t\tPhysicalRoutingGrid routing = data->clsMapLayerToRoutingGrid[layer];\n\t\tdata->clsPhysicalRoutingGrids.push_back(routing);\n\t} // end for \n\n\tRsyn::PhysicalRoutingGrid bottom;\n\tfor (Rsyn::PhysicalRoutingGrid routing : allPhysicalRoutingGrids()) {\n\t\tfor (Rsyn::PhysicalTracks track : routing.allTracks()) {\n\t\t\tif (track.getDirection() == Rsyn::TRACK_HORIZONTAL) {\n\t\t\t\trouting->clsBounds[LOWER][Y] = track->clsLocation;\n\t\t\t\trouting->clsNumTracks[Y] = track->clsNumTracks;\n\t\t\t\trouting->clsSpacing[Y] = track->clsSpace;\n\t\t\t} else if (track.getDirection() == Rsyn::TRACK_VERTICAL) {\n\t\t\t\trouting->clsBounds[LOWER][X] = track->clsLocation;\n\t\t\t\trouting->clsNumTracks[X] = track->clsNumTracks;\n\t\t\t\trouting->clsSpacing[X] = track->clsSpace;\n\t\t\t} else {\n\t\t\t\tstd::cout << \"ERROR: Invalid track direction \" << track.getDirection() << \"\\n\";\n\t\t\t} // end if-else \n\t\t} // end for \n\t\trouting->clsBounds[UPPER][X] = routing->clsBounds[LOWER][X] +\n\t\t\t(routing->clsSpacing[X] * (routing->clsNumTracks[X] - 1));\n\t\trouting->clsBounds[UPPER][Y] = routing->clsBounds[LOWER][Y] +\n\t\t\t(routing->clsSpacing[Y] * (routing->clsNumTracks[Y] - 1));\n\t\trouting->clsBottomRoutingGrid = bottom;\n\t\tif (bottom != nullptr)\n\t\t\tbottom->clsTopRoutingGrid = routing;\n\t\tbottom = routing;\n\t} // end for \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalGCell(const DefGcellGridDscp &gcell) {\n    data->clsPhysicalGCell.push_back(PhysicalGCell(new PhysicalGCellData()));\n    PhysicalGCell phyGCell = data->clsPhysicalGCell.back();\n    phyGCell->clsLocation = gcell.clsX;\n    phyGCell->clsNumTracks = gcell.clsXNum;\n    phyGCell->clsStep = gcell.clsXStep;\n    phyGCell->clsDirection = gcell.clsMacro == \"X\" ? PhysicalGCellDirection::VERTICAL : PhysicalGCellDirection::HORIZONTAL;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalDesignVia(const DefViaDscp & via) {\n\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalVias.find(via.clsName);\n\tif (it != data->clsMapPhysicalVias.end()) {\n\t\tstd::cout << \"WARNING: Via \" << via.clsName << \" was already defined. Skipping ...\\n\";\n\t\treturn;\n\t} // end if \n\n\t// Adding new via\n\tdata->clsMapPhysicalVias[via.clsName] = data->clsPhysicalVias.size();\n\tdata->clsPhysicalVias.push_back(PhysicalVia(new PhysicalViaData()));\n\tPhysicalVia phVia = data->clsPhysicalVias.back();\n\tphVia->id = data->clsPhysicalVias.size() - 1;\n\tphVia->clsName = via.clsName;\n\tphVia->clsIsDefault = false; // only available in lef via\n\tphVia->clsHasCutResistance = false; // only available in lef via\n\tphVia->clsIsViaDesign = true;\n\tphVia->clsHasViaRule = via.clsHasViaRule;\n\n\tif (via.clsHasViaRule) {\n\t\tRsyn::PhysicalViaRuleBase phViaRuleBase = getPhysicalViaRuleBaseByName(via.clsViaRuleName);\n\t\tphVia->clsHasViaRule = true;\n\t\tphVia->clsType = VIA_RULE_TYPE;\n\t\tphVia->clsViaRuleData = phViaRuleBase.data;\n\t\tphVia->clsCutSize[X] = via.clsXCutSize;\n\t\tphVia->clsCutSize[Y] = via.clsYCutSize;\n\t\tphVia->clsSpacing[X] = via.clsXCutSpacing;\n\t\tphVia->clsSpacing[Y] = via.clsYCutSpacing;\n\t\tphVia->clsEnclosure[BOTTOM_VIA_LEVEL][X] = via.clsXBottomEnclosure;\n\t\tphVia->clsEnclosure[BOTTOM_VIA_LEVEL][Y] = via.clsYBottomEnclosure;\n\t\tphVia->clsEnclosure[TOP_VIA_LEVEL][X] = via.clsXTopEnclosure;\n\t\tphVia->clsEnclosure[TOP_VIA_LEVEL][Y] = via.clsYTopEnclosure;\n\n\t\tRsyn::PhysicalLayer bottom = getPhysicalLayerByName(via.clsBottomLayer);\n\t\tRsyn::PhysicalLayer cut = getPhysicalLayerByName(via.clsCutLayer);\n\t\tRsyn::PhysicalLayer top = getPhysicalLayerByName(via.clsTopLayer);\n\t\tphVia->clsLayers[BOTTOM_VIA_LAYER] = bottom.data;\n\t\tphVia->clsLayers[CUT_VIA_LAYER] = cut.data;\n\t\tphVia->clsLayers[TOP_VIA_LAYER] = top.data;\n\n\t\tif (via.clsHasRowCol) {\n\t\t\tphVia->clsHasRowCol = true;\n\t\t\tphVia->clsNumRows = via.clsNumCutRows;\n\t\t\tphVia->clsNumCols = via.clsNumCutCols;\n\t\t} // end if \n\t\tif (via.clsHasOrigin) {\n\t\t\tphVia->clsHasOrigin = true;\n\t\t\tphVia->clsOrigin[X] = via.clsXOffsetOrigin;\n\t\t\tphVia->clsOrigin[Y] = via.clsYOffsetOrigin;\n\t\t} // end if \n\t\tif (via.clsHasOffset) {\n\t\t\tphVia->clsHasOffset = true;\n\t\t\tphVia->clsOffset[BOTTOM_VIA_LEVEL][X] = via.clsXBottomOffset;\n\t\t\tphVia->clsOffset[BOTTOM_VIA_LEVEL][Y] = via.clsYBottomOffset;\n\t\t\tphVia->clsOffset[TOP_VIA_LEVEL][X] = via.clsXTopOffset;\n\t\t\tphVia->clsOffset[TOP_VIA_LEVEL][Y] = via.clsYTopOffset;\n\t\t} // end if \n\t\tif (via.clsHasPattern) {\n\t\t\tphVia->clsHasPattern = true;\n\t\t\tphVia->clsPattern = via.clsPattern;\n\t\t} // end if \n\t} else {\n\t\tphVia->clsHasViaRule = false;\n\t\tphVia->clsType = VIA_GEOMETRY_TYPE;\n\t\tstd::vector<std::tuple<int, PhysicalLayerData *>> layers;\n\t\tfor (const std::pair < std::string, std::deque < DefViaGeometryDscp>> &geoPair : via.clsGeometries) {\n\t\t\tconst std::string & layerName = geoPair.first;\n\t\t\tRsyn::PhysicalLayer layer = getPhysicalLayerByName(layerName);\n\t\t\t// assert(layer);\n\t\t\tlayers.push_back(std::make_tuple(layer.getIndex(), layer.data));\n\t\t} // end for \n\t\tstd::sort(layers.begin(), layers.end());\n\t\t//\tassert(layers.size() == NUM_VIA_LAYERS);\n\t\tfor (int i = 0; i < NUM_VIA_LAYERS; i++) {\n\t\t\tPhysicalLayerData * layerData = std::get<1>(layers[i]);\n\t\t\tphVia->clsLayers[i] = layerData;\n\t\t\tstd::vector<Rsyn::PhysicalViaGeometry>  & viaGeos = phVia->clsViaGeometries[i];\n\t\t\tauto iterator = via.clsGeometries.find(layerData->clsName);\n\t\t\tconst std::deque<DefViaGeometryDscp> & geoDscps = iterator->second;\n\t\t\tviaGeos.reserve(geoDscps.size());\n\t\t\tfor (const DefViaGeometryDscp & geoDscp : geoDscps) {\n\t\t\t\tviaGeos.push_back(Rsyn::PhysicalViaGeometry(new ViaGeometryData()));\n\t\t\t\tRsyn::PhysicalViaGeometry viaGeo = viaGeos.back();\n\t\t\t\tviaGeo->id = viaGeos.size() -1;\n\t\t\t\tconst DoubleRectangle & doubleRect = geoDscp.clsBounds;\n\t\t\t\tBounds & bds = viaGeo->clsBounds;\n\t\t\t\tbds[LOWER][X] = doubleRect[LOWER][X];\n\t\t\t\tbds[LOWER][Y] = doubleRect[LOWER][Y];\n\t\t\t\tbds[UPPER][X] = doubleRect[UPPER][X];\n\t\t\t\tbds[UPPER][Y] = doubleRect[UPPER][Y];\n\t\t\t} // end for \n\t\t} // end for\n\t} // end if-else \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::addPhysicalSpacing(const LefSpacingDscp & spacing) {\n\tElement<PhysicalSpacingData> *element = data->clsPhysicalSpacing.create();\n\tRsyn::PhysicalSpacingData * phSpacing = &(element->value);\n\tphSpacing->id = data->clsPhysicalSpacing.lastId();\n\tphSpacing->clsLayer1 = getPhysicalLayerByName(spacing.clsLayer1);\n\tphSpacing->clsLayer2 = getPhysicalLayerByName(spacing.clsLayer2);\n\tphSpacing->clsDistance = static_cast<DBU> (std::round(spacing.clsDistance * getDatabaseUnits(LIBRARY_DBU)));\n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalDesign::getPhysicalLayerByIndex(const int index) {\n\tconst int numLayers = data->clsPhysicalLayers.size();\n\tif (index < 0 || index >= numLayers)\n\t\treturn PhysicalLayer(nullptr);\n\tElement<PhysicalLayerData> * phLayerDataElement = data->clsPhysicalLayers.get(index);\n\treturn PhysicalLayer(&phLayerDataElement->value);\n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayer\nPhysicalDesign::getPhysicalLayerByIndex(const Rsyn::PhysicalLayerType layerType,\n\tconst int index) {\n\tif (index < 0)\n\t\treturn PhysicalLayer(nullptr);\n\tint numLayers;\n\tint layerId;\n\tElement<PhysicalLayerData> * phLayerDataElement;\n\tswitch (layerType) {\n\t\tcase PhysicalLayerType::ROUTING:\n\t\t\tnumLayers = data->clsPhysicalRoutingLayerIndeces.size();\n\t\t\tif (index >= numLayers)\n\t\t\t\treturn PhysicalLayer(nullptr);\n\t\t\tlayerId = data->clsPhysicalRoutingLayerIndeces[index];\n\t\t\tphLayerDataElement = data->clsPhysicalLayers.get(layerId);\n\t\t\treturn PhysicalLayer(&phLayerDataElement->value);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tstd::cout << \"TODO \" << layerType << \"\\n\";\n\t\t\treturn PhysicalLayer(nullptr);\n\t} // end switch \n\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::updatePhysicalCell(Rsyn::Cell cell) {\n\tPhysicalInstanceData & phCell = data->clsPhysicalInstances[cell.asCell()];\n\tPhysicalLibraryCellData &phLibCell = data->clsPhysicalLibraryCells[cell.asCell().getLibraryCell()]; // TODO: assuming instance is a cell\n\n\tconst DBU width = phLibCell.clsSize[X];\n\tconst DBU height = phLibCell.clsSize[Y];\n\tconst DBUxy pos = phCell.clsInstance->clsBounds[LOWER];\n\n\tDBU area = (width * height) - phCell.clsInstance->clsBounds.computeArea();\n\tif (!strcmp(phLibCell.clsMacro->macroClass(), \"BLOCK\"))\n\t\tdata->clsTotalAreas[PHYSICAL_BLOCK] += area;\n\tif (cell.isFixed()) {\n\t\tif (cell.isPort())\n\t\t\tdata->clsTotalAreas[PHYSICAL_PORT] += area;\n\t\telse\n\t\t\tdata->clsTotalAreas[PHYSICAL_FIXED] += area;\n\t} else {\n\t\tdata->clsTotalAreas[PHYSICAL_MOVABLE] += area;\n\t} // end if-else \n\n\tphCell.clsInstance->clsBounds.updatePoints(pos, DBUxy(pos[X] + width, pos[Y] + height));\n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::removePhysicalCell(Rsyn::Cell cell) {\n\tPhysicalInstanceData & physicalCell = data->clsPhysicalInstances[cell.asCell()];\n\tDBU area = physicalCell.clsInstance->clsBounds.computeArea();\n\tif (physicalCell.clsBlock)\n\t\tdata->clsTotalAreas[PHYSICAL_BLOCK] -= area;\n\tif (cell.isFixed()) {\n\t\tif (cell.isPort())\n\t\t\tdata->clsTotalAreas[PHYSICAL_PORT] -= area;\n\t\telse\n\t\t\tdata->clsTotalAreas[PHYSICAL_FIXED] -= area;\n\t} else {\n\t\tdata->clsTotalAreas[PHYSICAL_MOVABLE] -= area;\n\t} // end if-else \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::mergeBounds(const std::vector<Bounds> & source,\n\tstd::vector<Bounds> & target, const Dimension dim) {\n\n\ttarget.reserve(source.size());\n\tstd::set<DBU> stripes;\n\tconst Dimension reverse = REVERSE_DIMENSION[dim];\n\tDBUxy lower, upper;\n\tlower[reverse] = +std::numeric_limits<DBU>::max();\n\tupper[reverse] = -std::numeric_limits<DBU>::max();\n\n\tfor (const Bounds & bound : source) {\n\t\tstripes.insert(bound[LOWER][dim]);\n\t\tstripes.insert(bound[UPPER][dim]);\n\t\tlower[reverse] = std::min(bound[LOWER][reverse], lower[reverse]);\n\t\tupper[reverse] = std::max(bound[UPPER][reverse], upper[reverse]);\n\t} // end for \n\n\tlower[dim] = *stripes.begin();\n\tstripes.erase(0);\n\tfor (DBU val : stripes) {\n\t\tupper[dim] = val;\n\t\tBounds stripe(lower, upper);\n\t\tDBU low, upp;\n\t\tbool firstMatch = true;\n\t\tfor (const Bounds & rect : source) {\n\t\t\tif (!rect.overlap(stripe)) {\n\t\t\t\tif (!firstMatch) {\n\t\t\t\t\tBounds merged = stripe;\n\t\t\t\t\tmerged[LOWER][reverse] = low;\n\t\t\t\t\tmerged[UPPER][reverse] = upp;\n\t\t\t\t\ttarget.push_back(merged);\n\t\t\t\t\tfirstMatch = true;\n\t\t\t\t} // end if \n\t\t\t\tcontinue;\n\t\t\t} // end if \n\t\t\tif (firstMatch) {\n\t\t\t\tlow = rect[LOWER][reverse];\n\t\t\t\tupp = rect[UPPER][reverse];\n\t\t\t\tfirstMatch = false;\n\t\t\t} else {\n\t\t\t\tif (upp == rect[LOWER][reverse]) {\n\t\t\t\t\tupp = rect[UPPER][reverse];\n\t\t\t\t} // end if \n\t\t\t} // end if-else \n\t\t} // end for \n\t\tif (!firstMatch) {\n\t\t\tBounds merged = stripe;\n\t\t\tmerged[LOWER][reverse] = low;\n\t\t\tmerged[UPPER][reverse] = upp;\n\t\t\ttarget.push_back(merged);\n\t\t\tfirstMatch = true;\n\t\t} // end if \n\t\tlower[dim] = val;\n\t} // end for \n} // end method \n\n// -----------------------------------------------------------------------------\n\nvoid PhysicalDesign::initLayerViaManager() {\n\tfor (PhysicalVia via : allPhysicalVias()) {\n\t\tRsyn::PhysicalLayer bottom = via.getBottomLayer();\n\t\tRsyn::PhysicalLayer top = via.getTopLayer();\n\n\t\tstd::vector<PhysicalVia> &bottomAll = data->clsLayerViaManager.clsVias[bottom];\n\t\tstd::vector<PhysicalVia> &bottomTop = data->clsLayerViaManager.clsTopVias[bottom];\n\t\tbottomAll.push_back(via);\n\t\tbottomTop.push_back(via);\n\n\t\tstd::vector<PhysicalVia> &topAll = data->clsLayerViaManager.clsVias[top];\n\t\tstd::vector<PhysicalVia> &topBottom = data->clsLayerViaManager.clsBottomVias[top];\n\t\ttopAll.push_back(via);\n\t\ttopBottom.push_back(via);\n\t} // end for \n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool PhysicalDesign::checkEquivalentOrientations(Rsyn::PhysicalSymmetry symmetry, Rsyn::PhysicalOrientation orient1,\n\tRsyn::PhysicalOrientation orient2) const {\n\n\tstd::cout << \"TODO \" << __func__ << \" at \" << __FILE__ << \"\\n\";\n\t//\tif(Rsyn::isPhysicalSymmetryX(symmetry)) {\n\t//\t\treturn orient1 == Rsyn::ORIENTATION_N ||\n\t//\t} // end if \n\n\treturn false;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalDesign.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::setClockNet(Rsyn::Net net) {\n\tdata->clsClkNet = net;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::getDatabaseUnits(const DBUType type) const {\n\treturn data->clsDBUs[type];\n} // end method  \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::convertMicronToLibraryDatabaseUnits(const double value) const {\n\treturn static_cast<DBU> (std::round(value * getDatabaseUnits(LIBRARY_DBU)));\n} // end method  \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::convertMicronToDesignDatabaseUnits(const double value) const {\n\treturn static_cast<DBU> (std::round(value * getDatabaseUnits(DESIGN_DBU)));\n} // end method  \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalDesign::getHPWL() const {\n\treturn data->clsHPWL;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::getHPWL(const Dimension dim) const {\n\treturn data->clsHPWL[dim];\n}// end method\n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalDesign::getNumElements(PhysicalType type) const {\n\treturn data->clsNumElements[type];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::getArea(const PhysicalType type) const {\n\treturn data->clsTotalAreas[type];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalDesign::isEnablePhysicalPins() const {\n\treturn data->clsEnablePhysicalPins;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalDesign::isEnableMergeRectangles() const {\n\treturn data->clsEnableMergeRectangles;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalDesign::isEnableNetPinBoundaries() const {\n\treturn data->clsEnableNetPinBoundaries;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::addPhysicalPin() {\n\tstd::cout << \"TODO \" << __func__ << \"\\n\";\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalDesign::getPhysicalLayerByName(const std::string & layerName) {\n\tstd::unordered_map<std::string, std::size_t>::iterator element = data->clsMapPhysicalLayers.find(layerName);\n\tif (element == data->clsMapPhysicalLayers.end())\n\t\treturn nullptr;\n\tconst int id = element->second;\n\tElement<PhysicalLayerData> * phLayerDataElement = data->clsPhysicalLayers.get(id);\n\treturn PhysicalLayer(&phLayerDataElement->value);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalSite PhysicalDesign::getPhysicalSiteByName(const std::string & siteName) {\n\tstd::unordered_map<std::string, int>::iterator it = data->clsMapPhysicalSites.find(siteName);\n\treturn it != data->clsMapPhysicalSites.end() ? data->clsPhysicalSites[it->second] : nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalRegion PhysicalDesign::getPhysicalRegionByName(const std::string &siteName) {\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalRegions.find(siteName);\n\tif (it == data->clsMapPhysicalRegions.end())\n\t\treturn nullptr;\n\treturn data->clsPhysicalRegions[it->second];\n} // end method \n\n// -----------------------------------------------------------------------------\t\n\ninline Rsyn::PhysicalGroup PhysicalDesign::getPhysicalGroupByName(const std::string &siteName) {\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalGroups.find(siteName);\n\tif (it == data->clsMapPhysicalGroups.end())\n\t\treturn nullptr;\n\treturn data->clsPhysicalGroups[it->second];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalVia PhysicalDesign::getPhysicalViaByName(const std::string &viaName) {\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalVias.find(viaName);\n\tif (it == data->clsMapPhysicalVias.end())\n\t\treturn nullptr;\n\treturn data->clsPhysicalVias[it->second];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalViaRuleBase PhysicalDesign::getPhysicalViaRuleBaseByName(const std::string &viaName) {\n\tstd::unordered_map<std::string, std::size_t>::iterator it = data->clsMapPhysicalViaRuleBases.find(viaName);\n\tif (it == data->clsMapPhysicalVias.end())\n\t\treturn nullptr;\n\treturn data->clsPhysicalViaRuleBases[it->second];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalViaRule PhysicalDesign::getPhysicalViaRuleByName(const std::string &viaName) {\n\tRsyn::PhysicalViaRuleBase viaRuleBase = getPhysicalViaRuleBaseByName(viaName);\n\tif (viaRuleBase == nullptr) {\n\t\treturn nullptr;\n\t} // end if \n\treturn viaRuleBase.isViaRule() ? viaRuleBase.asViaRule() : nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalViaRuleGenerate PhysicalDesign::getPhysicalViaRuleGenerateByName(const std::string &viaName) {\n\tRsyn::PhysicalViaRuleBase viaRuleBase = getPhysicalViaRuleBaseByName(viaName);\n\tif (viaRuleBase == nullptr) {\n\t\treturn nullptr;\n\t} // end if \n\treturn viaRuleBase.isViaRuleGenerate() ? viaRuleBase.asViaRuleGenerate() : nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalDesign::getNumLayers(const Rsyn::PhysicalLayerType type) const {\n\treturn data->clsNumLayers[type];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalDesign::getNumLayers() const {\n\treturn data->clsPhysicalLayers.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Range<ListCollection<PhysicalLayerData, PhysicalLayer>>\nPhysicalDesign::allPhysicalLayers() {\n\treturn ListCollection<PhysicalLayerData, PhysicalLayer>(data->clsPhysicalLayers);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumPhysicalVias() const {\n\treturn data->clsPhysicalVias.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<PhysicalVia> & PhysicalDesign::allPhysicalVias() const {\n\treturn data->clsPhysicalVias;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumPhysicalTracks()const {\n\treturn data->clsPhysicalTracks.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalDesign::getNumPhysicalTracks(Rsyn::PhysicalLayer layer) const {\n\tif (!hasPhysicalTracks(layer))\n\t\treturn 0;\n\tconst std::vector<Rsyn::PhysicalTracks> & tracks = allPhysicalTracks(layer);\n\treturn tracks.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalTracks> & PhysicalDesign::allPhysicalTracks() const {\n\treturn data->clsPhysicalTracks;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalTracks> & PhysicalDesign::allPhysicalTracks(Rsyn::PhysicalLayer layer) const {\n\treturn data->clsMapLayerToTracks[layer];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalDesign::hasPhysicalTracks(Rsyn::PhysicalLayer layer) const {\n\tif (layer == nullptr)\n\t\treturn false;\n\tif (layer.getType() != Rsyn::PhysicalLayerType::ROUTING)\n\t\treturn false;\n\tif (data->clsMapLayerToTracks.find(layer) == data->clsMapLayerToTracks.end())\n\t\treturn false;\n\tconst std::vector<Rsyn::PhysicalTracks> & tracks = allPhysicalTracks(layer);\n\treturn tracks.size() > 0;\n} // end method\n\n// -----------------------------------------------------------------------------\ninline const std::vector<Rsyn::PhysicalGCell>& PhysicalDesign::allPhysicalGCell() const {\n    return data->clsPhysicalGCell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\n// -----------------------------------------------------------------------------\n\n    inline const std::vector<Rsyn::PhysicalRoutingGrid>& PhysicalDesign::allPhysicalRoutingGrids() const\n{\n    return data->clsPhysicalRoutingGrids;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalRoutingGrid PhysicalDesign::getPhysicalRoutingGrid(Rsyn::PhysicalLayer layer) const {\n\tif (layer && layer.getType() == Rsyn::PhysicalLayerType::ROUTING) {\n\t\tauto it = data->clsMapLayerToRoutingGrid.find(layer);\n\t\tif (it != data->clsMapLayerToRoutingGrid.end()) {\n\t\t\treturn it->second;\n\t\t} // end if\n\t} // end if\n\treturn nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalDesign::hasPhysicalRoutingGrid(Rsyn::PhysicalLayer layer) const {\n\tif (layer == nullptr)\n\t\treturn false;\n\tif (layer.getType() != Rsyn::PhysicalLayerType::ROUTING)\n\t\treturn false;\n\tif (data->clsMapLayerToRoutingGrid.find(layer) == data->clsMapLayerToRoutingGrid.end())\n\t\treturn false;\n\treturn true;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalDesign::getNumPhysicalRoutingGrids() const {\n\treturn data->clsPhysicalRoutingGrids.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumPhysicalSpacing() const {\n\treturn data->clsPhysicalSpacing.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Range<ListCollection<PhysicalSpacingData, PhysicalSpacing>>\nPhysicalDesign::allPhysicalSpacing() const {\n\treturn ListCollection<PhysicalSpacingData, PhysicalSpacing>(data->clsPhysicalSpacing);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumPhysicalRegions() const {\n\treturn data->clsPhysicalRegions.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::vector<PhysicalRegion> & PhysicalDesign::allPhysicalRegions() const {\n\treturn data->clsPhysicalRegions;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumPhysicalGroups() const noexcept {\n\treturn data->clsPhysicalGroups.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::vector<PhysicalGroup> & PhysicalDesign::allPhysicalGroups() const {\n\treturn data->clsPhysicalGroups;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumPhysicalSpecialNets() const noexcept {\n\treturn data->clsPhysicalSpecialNets.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::vector<PhysicalSpecialNet> & PhysicalDesign::allPhysicalSpecialNets() const {\n\treturn data->clsPhysicalSpecialNets;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n//I'm assuming all rows have the same height.\n\ninline DBU PhysicalDesign::getRowHeight() const {\n\treturn data->clsPhysicalRows.get(0)->value.getHeight();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::getRowSiteWidth() const {\n\treturn data->clsPhysicalRows.get(0)->value.clsPhysicalSite.getWidth();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalDesign::getNumRows() const {\n\treturn data->clsPhysicalRows.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Range<ListCollection<PhysicalRowData, PhysicalRow>>\nPhysicalDesign::allPhysicalRows() {\n\treturn ListCollection<PhysicalRowData, PhysicalRow>(data->clsPhysicalRows);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::LayerViaManager PhysicalDesign::getLayerViaManager() const {\n\treturn LayerViaManager(&data->clsLayerViaManager);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLibraryPin PhysicalDesign::getPhysicalLibraryPin(Rsyn::LibraryPin libPin) const {\n\treturn PhysicalLibraryPin(&data->clsPhysicalLibraryPins[libPin]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLibraryPin PhysicalDesign::getPhysicalLibraryPin(Rsyn::Pin pin) const {\n\tif (pin.getInstanceType() != Rsyn::CELL)\n\t\treturn nullptr;\n\treturn PhysicalLibraryPin(&data->clsPhysicalLibraryPins[pin.getLibraryPin()]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLibraryCell PhysicalDesign::getPhysicalLibraryCell(Rsyn::Cell cell) const {\n\tRsyn::LibraryCell libCell = cell.getLibraryCell();\n\treturn PhysicalLibraryCell(&data->clsPhysicalLibraryCells[libCell]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLibraryCell PhysicalDesign::getPhysicalLibraryCell(Rsyn::LibraryCell libCell) const {\n\treturn PhysicalLibraryCell(&data->clsPhysicalLibraryCells[libCell]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalCell PhysicalDesign::getPhysicalCell(Rsyn::Cell cell) const {\n\treturn PhysicalCell(&data->clsPhysicalInstances[cell]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalCell PhysicalDesign::getPhysicalCell(Rsyn::Pin pin) const {\n\tRsyn::Instance instance = pin.getInstance();\n\treturn instance.getType() == Rsyn::CELL ? getPhysicalCell(instance.asCell()) : nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalInstance PhysicalDesign::getPhysicalInstance(Rsyn::Instance instance) const {\n\treturn PhysicalInstance(&data->clsPhysicalInstances[instance]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalInstance PhysicalDesign::getPhysicalInstance(Rsyn::Pin pin) const {\n\treturn getPhysicalInstance(pin.getInstance());\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalPort PhysicalDesign::getPhysicalPort(Rsyn::Port port) const {\n\treturn PhysicalPort(&data->clsPhysicalInstances[port]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalPort PhysicalDesign::getPhysicalPort(Rsyn::Pin pin) const {\n\tRsyn::Instance instance = pin.getInstance();\n\treturn getPhysicalPort(instance.asPort());\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalModule PhysicalDesign::getPhysicalModule(Rsyn::Module module) const {\n\treturn PhysicalModule(&data->clsPhysicalInstances[module]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalDesign::getNumMovedCells() const {\n\tint count = 0;\n\tfor (Rsyn::Instance instance : data->clsModule.allInstances()) {\n\t\tif (instance.getType() != Rsyn::CELL)\n\t\t\tcontinue;\n\t\tRsyn::Cell cell = instance.asCell(); // TODO: hack, assuming that the instance is a cell\n\t\tRsyn::PhysicalCell phCell = getPhysicalCell(cell);\n\t\tif (instance.isFixed() || instance.isMacroBlock())\n\t\t\tcontinue;\n\n\t\tconst DBUxy initialPos = phCell.getInitialPosition();\n\t\tconst DBUxy currentPos = phCell.getPosition();\n\t\tif (initialPos[X] != currentPos[X] || initialPos[Y] != currentPos[Y])\n\t\t\tcount++;\n\t} // end for\n\treturn count;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalModule PhysicalDesign::getPhysicalModule(Rsyn::Pin pin) const {\n\tRsyn::Instance instance = pin.getInstance();\n\treturn getPhysicalModule(instance.asModule());\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalDie PhysicalDesign::getPhysicalDie() const {\n\treturn PhysicalDie(&data->clsPhysicalDie);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalPin PhysicalDesign::getPhysicalPin(Rsyn::Pin pin) const {\n\tif (!data->clsEnablePhysicalPins)\n\t\treturn nullptr;\n\treturn PhysicalPin(&data->clsPhysicalPins[pin]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalDesign::getPinDisplacement(Rsyn::Pin pin) const {\n\tRsyn::Instance inst = pin.getInstance();\n\tif (inst.getType() == Rsyn::CELL) {\n\t\tRsyn::LibraryPin libPin = pin.getLibraryPin();\n\t\tDBUxy displacement = data->clsPhysicalLibraryPins[libPin].clsLayerBound.computeCenter();\n\t\treturn displacement;\n\t} // end if \n\treturn DBUxy(0, 0);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalDesign::getPinPosition(Rsyn::Pin pin) const {\n\t// Position may be defined if the instance has info. \n\t// I'm assuming the instance doesn't know what is its position. \n\tDBUxy pos;\n\tRsyn::InstanceType type = pin.getInstanceType();\n\tswitch (type) {\n\t\tcase Rsyn::CELL:\n\t\t\tpos = getPhysicalCell(pin).getPosition();\n\t\t\tbreak;\n\t\tcase Rsyn::MODULE:\n\t\t\tpos = getPhysicalModule(pin).getPosition();\n\t\t\tbreak;\n\t\tcase Rsyn::PORT:\n\t\t\tpos = getPhysicalPort(pin).getPosition();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpos.apply(std::numeric_limits<DBU>::infinity());\n\t\t\tstd::cout << \"WARNING: Position for \" << pin.getFullName() << \" was not defined for the instance type\\n\";\n\t} // end switch \n\treturn pos + getPinDisplacement(pin);\n} // end method \n\n// -----------------------------------------------------------------------------\n\n// For pins of standard-cells, returns the cell position. For macro-blocks,\n// returns the pin position itself.\n\ninline DBUxy PhysicalDesign::getRelaxedPinPosition(Rsyn::Pin pin) const {\n\t// Position may be defined if the instance has info. \n\t// I'm assuming the instance doesn't know what is its position. \n\tDBUxy pos;\n\tRsyn::InstanceType type = pin.getInstanceType();\n\tRsyn::PhysicalCell phCell;\n\tswitch (type) {\n\t\tcase Rsyn::CELL:\n\t\t\tphCell = getPhysicalCell(pin);\n\t\t\tpos = phCell.getPosition();\n\t\t\tif (pin.isMacroBlockPin())\n\t\t\t\tpos += getPinDisplacement(pin);\n\t\t\tbreak;\n\t\tcase Rsyn::MODULE:\n\t\t\tpos = getPhysicalModule(pin).getPosition();\n\t\t\tpos += getPinDisplacement(pin);\n\t\t\tbreak;\n\t\tcase Rsyn::PORT:\n\t\t\tpos = getPhysicalPort(pin).getPosition();\n\t\t\tpos += getPinDisplacement(pin);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpos.apply(std::numeric_limits<DBU>::infinity());\n\t\t\tstd::cout << \"WARNING: Position for \" << pin.getFullName() << \" was not defined for the instance type\\n\";\n\t} // end switch \n\treturn pos;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::getPinDisplacement(Rsyn::Pin pin, const Dimension dim) const {\n\tDBUxy disp = getPinDisplacement(pin);\n\treturn disp[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDesign::getPinPosition(Rsyn::Pin pin, const Dimension dim) const {\n\tDBUxy pos = getPinPosition(pin);\n\treturn pos[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalNet PhysicalDesign::getPhysicalNet(Rsyn::Net net) const {\n\treturn PhysicalNet(&data->clsPhysicalNets[net]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalIndex PhysicalDesign::getId(Rsyn::PhysicalRow phRow) const {\n\treturn phRow->id;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalIndex PhysicalDesign::getId(Rsyn::PhysicalLayer phLayer) const {\n\treturn phLayer->id;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalIndex PhysicalDesign::getId(Rsyn::PhysicalSpacing spacing) const {\n\treturn spacing->id;\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Placement\n////////////////////////////////////////////////////////////////////////////////\n\ninline PhysicalAttributeInitializer PhysicalDesign::createPhysicalAttribute() {\n\treturn PhysicalAttributeInitializer(*this);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ntemplate<typename DefaultPhysicalValueType>\ninline PhysicalAttributeInitializerWithDefaultValue<DefaultPhysicalValueType>\nPhysicalDesign::createPhysicalAttribute(const DefaultPhysicalValueType &defaultValue) {\n\treturn PhysicalAttributeInitializerWithDefaultValue<DefaultPhysicalValueType>(*this, defaultValue);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalOrientation PhysicalDesign::checkOrientation(Rsyn::PhysicalPort physicalPort, \n        const DBU x, const DBU y){\n        \n        Rsyn::PhysicalDie die = getPhysicalDie();\n        Bounds dieBounds = die.getBounds();\n        DBU lowerXBound = dieBounds[LOWER][X];\n        DBU lowerYBound = dieBounds[LOWER][Y];\n        DBU upperXBound = dieBounds[UPPER][X];\n        DBU upperYBound = dieBounds[UPPER][Y];\n        \n        if (x == lowerXBound){\n            if (y == upperYBound)\n                return ORIENTATION_S;\n            return ORIENTATION_E;\n        }\n        if (x == upperXBound){\n            if (y == lowerYBound)\n                return ORIENTATION_N;\n            return ORIENTATION_W;\n        }\n        if (y == lowerYBound)\n            return ORIENTATION_N;\n        if (y == upperYBound)\n            return ORIENTATION_S;\n        \n        return physicalPort.getOrientation();\n}\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalDesign::checkPosition(const DBU x, const DBU y) {\n        DBUxy newPosition(x, y);\n        Rsyn::PhysicalDie die = getPhysicalDie();\n        Bounds dieBounds = die.getBounds();\n        DBU lowerXBound = dieBounds[LOWER][X];\n        DBU lowerYBound = dieBounds[LOWER][Y];\n        DBU upperXBound = dieBounds[UPPER][X];\n        DBU upperYBound = dieBounds[UPPER][Y];\n        \n        int distToLowerX = std::abs(lowerXBound - x);\n        int distToLowerY = std::abs(lowerYBound - y);\n        int distToUpperX = std::abs(upperXBound - x);\n        int distToUpperY = std::abs(upperYBound - y);\n\n        int minX = std::min(distToLowerX, distToUpperX);\n        int minY = std::min(distToLowerY, distToUpperY);\n\n        int minDist = std::min(minX, minY);\n  \n        if (minDist == distToLowerX) {\n            newPosition = DBUxy(lowerXBound, y);\n        } else if (minDist == distToLowerY) {\n            newPosition = DBUxy(x, lowerYBound);\n        } else if (minDist == distToUpperX) {\n            newPosition = DBUxy(upperXBound, y);\n        } else if (minDist == distToUpperY) {\n            newPosition = DBUxy(x, upperYBound);\n        } // end if-else\n\n        return newPosition;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool Rsyn::PhysicalDesign::getPhysicalPortByName(std::string name, Rsyn::PhysicalPort &phPort) {\n    for (Rsyn::Port port : data->clsModule.allPorts()) {\n        if (port.getName() == name) {\n            phPort = getPhysicalPort(port);\n            return true;\n        }\n    }\n    return false;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placePort(Rsyn::PhysicalPort physicalPort, const DBU x, const DBU y, \n        Rsyn::PhysicalOrientation orient, const bool disableSnapping, \n        const bool dontNotifyObservers) {\n        Rsyn::PhysicalOrientation newOrient;\n        const bool moved = (x != physicalPort.getPosition(X)) ||\n\t\t(y != physicalPort.getPosition(Y));\n        DBUxy finalPosition;\n        \n        if (disableSnapping) {\n            finalPosition = DBUxy(x, y);\n        } else {\n            finalPosition = checkPosition(x, y);\n        } // end if\n        \n        if (orient != ORIENTATION_INVALID) {\n            newOrient = orient;\n        } else {\n            newOrient = checkOrientation(physicalPort, finalPosition[X], finalPosition[Y]);\n        }// end if\n\n        physicalPort->clsInstance->clsOrientation = newOrient;\n\n        // Notify observers.\n        if (moved) {\n                physicalPort->clsInstance->clsPortPos.set(finalPosition[X], finalPosition[Y]);\n                if (!dontNotifyObservers) {\n                        data->clsDesign.notifyInstancePlaced(physicalPort.getInstance());\n                } // end if\n        } // end if \t\n            \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placePort(Rsyn::Port port, const DBU x, const DBU y,\n\tRsyn::PhysicalOrientation orient, const bool disableSnapping, \n        const bool dontNotifyObservers) {\n\tplacePort(getPhysicalPort(port), x, y, orient, disableSnapping, dontNotifyObservers);\n} // end method\t\n\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placePort(Rsyn::PhysicalPort physicalPort, const DBUxy pos,\n\tRsyn::PhysicalOrientation orient, const bool disableSnapping, \n        const bool dontNotifyObservers) {\n\tplacePort(physicalPort, pos[X], pos[Y], orient, disableSnapping, dontNotifyObservers);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placePort(Rsyn::Port port, const DBUxy pos,\n\tRsyn::PhysicalOrientation orient, const bool disableSnapping, \n        const bool dontNotifyObservers) {\n\tplacePort(getPhysicalPort(port), pos[X], pos[Y], orient, disableSnapping, dontNotifyObservers);\n} // end method\n\n\n// -----------------------------------------------------------------------------\n\n// Caution when using dontNotifyObservers.\n// We can use it when you may expect the move to be rolled back, but it is\n// not, recall to mark the cell as dirty.\n\ninline void PhysicalDesign::placeCell(Rsyn::PhysicalCell physicalCell, const DBU x, const DBU y,\n\tRsyn::PhysicalOrientation orient, const bool dontNotifyObservers) {\n\tconst bool moved = (x != physicalCell.getPosition(X)) ||\n\t\t(y != physicalCell.getPosition(Y));\n\n\t// Notify observers.\n\tif (moved) {\n\t\tphysicalCell->clsInstance->clsBounds.moveTo(x, y);\n\t\tif (orient != ORIENTATION_INVALID) {\n\t\t\tphysicalCell->clsInstance->clsOrientation = orient;\n\t\t} // end if \n\t\tif (!dontNotifyObservers) {\n\t\t\tdata->clsDesign.notifyInstancePlaced(physicalCell.getInstance());\n\t\t} // end if\n\t} // end if \t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placeCell(Rsyn::Cell cell, const DBU x, const DBU y,\n\tRsyn::PhysicalOrientation orient, const bool dontNotifyObservers) {\n\tplaceCell(getPhysicalCell(cell), x, y, orient, dontNotifyObservers);\n} // end method\t\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placeCell(Rsyn::PhysicalCell physicalCell, const DBUxy pos,\n\tRsyn::PhysicalOrientation orient, const bool dontNotifyObservers) {\n\tplaceCell(physicalCell, pos[X], pos[Y], orient, dontNotifyObservers);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::placeCell(Rsyn::Cell cell, const DBUxy pos,\n\tRsyn::PhysicalOrientation orient, const bool dontNotifyObservers) {\n\tplaceCell(getPhysicalCell(cell), pos[X], pos[Y], orient, dontNotifyObservers);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::setCellOrientation(Rsyn::PhysicalCell physicalCell,\n\tRsyn::PhysicalOrientation orient, const bool dontNotifyObservers) {\n\tif (orient != ORIENTATION_INVALID) {\n\t\tphysicalCell->clsInstance->clsOrientation = orient;\n\t} // end if \n\tif (!dontNotifyObservers) {\n\t\tdata->clsDesign.notifyInstancePlaced(physicalCell.getInstance());\n\t} // end if\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::setCellOrientation(Rsyn::Cell cell, Rsyn::PhysicalOrientation orient,\n\tconst bool dontNotifyObservers) {\n\tsetCellOrientation(getPhysicalCell(cell), orient, dontNotifyObservers);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::flipCell(Rsyn::PhysicalCell physicalCell, const bool dontNotifyObservers) {\n\tRsyn::PhysicalOrientation orient = physicalCell.getOrientation();\n\tRsyn::PhysicalOrientation flippedOrient = ORIENTATION_INVALID;\n\n\tswitch (orient) {\n\t\tcase ORIENTATION_N: flippedOrient = ORIENTATION_FN;\n\t\t\tbreak;\n\t\tcase ORIENTATION_S: flippedOrient = ORIENTATION_FS;\n\t\t\tbreak;\n\t\tcase ORIENTATION_W: flippedOrient = ORIENTATION_FW;\n\t\t\tbreak;\n\t\tcase ORIENTATION_E: flippedOrient = ORIENTATION_FE;\n\t\t\tbreak;\n\t\tcase ORIENTATION_FN: flippedOrient = ORIENTATION_N;\n\t\t\tbreak;\n\t\tcase ORIENTATION_FS: flippedOrient = ORIENTATION_S;\n\t\t\tbreak;\n\t\tcase ORIENTATION_FW: flippedOrient = ORIENTATION_W;\n\t\t\tbreak;\n\t\tcase ORIENTATION_FE: flippedOrient = ORIENTATION_E;\n\t\t\tbreak;\n\t\tdefault: flippedOrient = ORIENTATION_INVALID;\n\t} // end switch \n\n\tif (flippedOrient != ORIENTATION_INVALID) {\n\t\tsetCellOrientation(physicalCell, flippedOrient, dontNotifyObservers);\n\t} // end if \n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::flipCell(Rsyn::Cell cell, const bool dontNotifyObservers) {\n\tflipCell(getPhysicalCell(cell), dontNotifyObservers);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::notifyInstancePlaced(Rsyn::Instance instance, Rsyn::DesignObserver *ignoreObserver) {\n\tdata->clsDesign.notifyInstancePlaced(instance, ignoreObserver);\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Routing\n////////////////////////////////////////////////////////////////////////////////\n\ninline void PhysicalDesign::setNetRouting(Rsyn::Net net, const PhysicalRouting &routing) {\n\tRsyn::PhysicalNet physicalNet = getPhysicalNet(net);\n\tphysicalNet->clsRouting = routing;\n\n\tfor (PhysicalDesignObserver * observer : data->clsPhysicalObservers[PHYSICAL_EVENT_POST_NET_ROUTING_CHANGE]) {\n\t\tobserver->onPostNetRoutingChange(physicalNet);\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::clearNetRouting(Rsyn::Net net) {\n\tPhysicalRouting emptyRouting;\n\tsetNetRouting(net, emptyRouting);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const PhysicalRouting &PhysicalDesign::getNetRouting(Rsyn::Net net) const {\n\tRsyn::PhysicalNet physicalNet = getPhysicalNet(net);\n\treturn physicalNet->clsRouting;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalDesign::isNetRouted(Rsyn::Net net) const {\n\tRsyn::PhysicalNet physicalNet = getPhysicalNet(net);\n\treturn !physicalNet->clsRouting.isEmpty();\n} // end method\n\n////////////////////////////////////////////////////////////////////////////////\n// Notification\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<class T>\ninline void PhysicalDesign::registerObserver(T *observer) {\n\tstatic_assert(std::is_base_of<PhysicalDesignObserver, T>::value,\n\t\t\"Unable to register class as observer. \"\n\t\t\"The observer class must inherit from Rsyn::PhysicalObserver.\");\n\n\tobserver->PhysicalDesignObserver::clsPhDesign = PhysicalDesign(data);\n\n\t// Check if the observer implements (overwrites) the event callbacks if so\n\t// register it to receive notifications of the respective event.\n\n\tif (typeid (&PhysicalDesignObserver::onPhysicalDesignDestruction) != typeid (&T::onPhysicalDesignDestruction)) {\n\t\tdata->clsPhysicalObservers[PHYSICAL_EVENT_DESTRUCTION].push_back(observer);\n\t} // end if\n\n\tif (typeid (&PhysicalDesignObserver::onPostNetRoutingChange) != typeid (&T::onPostNetRoutingChange)) {\n\t\tdata->clsPhysicalObservers[PHYSICAL_EVENT_POST_NET_ROUTING_CHANGE] .push_back(observer);\n\t} // end if\n\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void PhysicalDesign::unregisterObserver(PhysicalDesignObserver *observer) {\n\tfor (int i = 0; i < NUM_PHYSICAL_EVENTS; i++) {\n\t\tdata->clsPhysicalObservers[i].remove(observer);\n\t} // end for\n\tobserver->PhysicalDesignObserver::clsPhDesign = nullptr;\n} // end method\n\n} // end namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalDie.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalDie.h\n * Author: jucemar\n *\n * Created on 4 de Fevereiro de 2017, 08:49\n */\n\nnamespace Rsyn {\n\ninline DBUxy PhysicalDie::getCoordinate(const Boundary bound) const {\n\treturn data->clsBounds[bound];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDie::getCoordinate(const Boundary bound, const Dimension dim) const {\n\treturn data->clsBounds[bound][dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds & PhysicalDie::getBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDie::getLength(const Dimension dim) const {\n\treturn data->clsBounds.computeLength(dim);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalDie::getPosition(const Boundary boundary) const {\n\treturn data->clsBounds[boundary];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalDie::getCenterPosition() const {\n\treturn data->clsBounds.computeCenter();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalDie::getArea() const {\n\treturn data->clsBounds.computeArea();\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalGCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalGCell.h\n * Author: jucemar\n *\n * Created on January 22, 2018, 9:23 PM\n */\n\nnamespace Rsyn {\n//! @brief Returns GCell direction\n\ninline Rsyn::PhysicalGCellDirection PhysicalGCell::getDirection() const {\n\treturn data->clsDirection;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n//! @brief If direction is vertical, then numTracks means the number of columns\n//! If direction is Horizontal, then numTracks means the number of rows\n\ninline int PhysicalGCell::getNumTracks() const {\n\treturn data->clsNumTracks;\n} // end method \n\n// -----------------------------------------------------------------------------\n//! @brief If direction is Horizontal, then location is Y value.\n//! If direction is vertical, then location is X value.\n\ninline DBU PhysicalGCell::getLocation() const {\n\treturn data->clsLocation;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n//! @brief Returns the spacing between GCell tracks. \n\ninline DBU PhysicalGCell::getStep() const {\n\treturn data->clsStep;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalGroup.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalGroup.h\n * Author: jucemar\n *\n * Created on 09 de Abril de 2017, 16:45\n */\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline const std::string & PhysicalGroup::getName() const {\n\treturn data->clsName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalRegion PhysicalGroup::getPhysicalRegion() const {\n\treturn data->clsRegion;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<std::string> & PhysicalGroup::allPatterns() const {\n\treturn data->clsPatterns;\n} // end method \n\n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalInstance.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   PhysicalInstance.h\n * Author: jucemar\n *\n * Created on 4 de Outubro de 2016, 19:37\n */\n\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::Instance PhysicalInstance::getInstance() const {\n\treturn data->clsInstance;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::string &PhysicalInstance::getName() const {\n\treturn data? getInstance().getName() : NullName;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getArea() const {\n\treturn getInstance().getArea();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalInstance::getCenter() const {\n\treturn getInstance().getCenter();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getCenter(const Dimension dim) const {\n\treturn getInstance().getCenter(dim);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getX() const {\n\treturn getInstance().getX();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getY() const {\n\treturn getInstance().getY();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getHeight() const {\n\treturn getInstance().getHeight();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getWidth() const {\n\treturn getInstance().getWidth();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getSize(const Dimension dimension) const {\n\treturn getInstance().getSize(dimension);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalInstance::getSize() const {\n\treturn getInstance().getSize();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalInstance::getPosition() const {\n\treturn getInstance().getPosition();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getPosition(const Dimension dim) const {\n\treturn getInstance().getPosition(dim);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalInstance::getCoordinate(const Boundary bound) const {\n\treturn getInstance().getCoordinate(bound);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalInstance::getCoordinate(const Boundary bound, const Dimension dim) const {\n\treturn getInstance().getCoordinate(bound, dim);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds &PhysicalInstance::getBounds() const {\n\treturn getInstance().getBounds();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalOrientation PhysicalInstance::getOrientation() const {\n\treturn getInstance().getOrientation();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalCell PhysicalInstance::asPhysicalCell() const {\n//#ifdef RSYN_SAFE_MODE\n\tif (data->clsInstance.getType() != Rsyn::CELL)\n\t\tthrow SafeModeException(\"Invalid instance casting. Instance is not a cell.\");\n//#endif\n\treturn PhysicalCell(data);\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalLayer.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\nnamespace Rsyn {\n\ninline lefiLayer* PhysicalLayer::getLayer() const {\n\treturn data->clsLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::string PhysicalLayer::getName() const {\n\treturn data->clsName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayerType PhysicalLayer::getType() const {\n\treturn data->clsType;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalLayer::getWidth() const {\n\treturn data->clsWidth;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalLayer::getIndex() const {\n\treturn data->id;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalLayer::getRelativeIndex() const {\n\treturn data->clsRelativeIndex;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalLayer::getPhysicalLayerLower() const {\n\treturn Rsyn::PhysicalLayer(data->clsLower);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalLayer::getPhysicalLayerUpper() const {\n\treturn Rsyn::PhysicalLayer(data->clsUpper);\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalLibraryCell.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\nnamespace Rsyn {\n\ninline lefiMacro* PhysicalLibraryCell::getMacro() const {\n\treturn data->clsMacro;\n} // end method \n\n//-----------------------------------------------------------------------------\n\ninline DBUxy PhysicalLibraryCell::getSize() const {\n\treturn data->clsSize;\n} // end method \n\n//-----------------------------------------------------------------------------\n\ninline DBU PhysicalLibraryCell::getWidth() const {\n\treturn data->clsSize[X];\n} // end  method \n\n//-----------------------------------------------------------------------------\n\ninline DBU PhysicalLibraryCell::getHeight() const {\n\treturn data->clsSize[Y];\n} // end  method \n\n//-----------------------------------------------------------------------------\n\ninline DBU PhysicalLibraryCell::getLength(const Dimension dim) const {\n\treturn data->clsSize[dim];\n} // end  method \n\n// -----------------------------------------------------------------------------\n\ninline Bounds PhysicalLibraryCell::getBounds() const {\n\treturn Bounds(0, 0, getWidth(), getHeight());\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalLibraryCell::hasLayerObstacles() const {\n\treturn data->clsLayerBoundIndex > -1;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalLibraryCell::hasObstacles() const {\n\treturn !data->clsObs.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Bounds> & PhysicalLibraryCell::allLayerObstacles() const {\n\treturn data->clsObs[data->clsLayerBoundIndex].allBounds();\n} // end method \n\n//-----------------------------------------------------------------------------\n\ninline PhysicalSite PhysicalLibraryCell::getSite() const {\n\treturn data->clsMacroSite;\n} // end  method \n\n// -----------------------------------------------------------------------------\n\ninline \tbool PhysicalLibraryCell::hasTopLayerObstacle() const{\n\treturn data->clsTopLayerObs != nullptr;\n} // end  method \n\n//-----------------------------------------------------------------------------\ninline \tRsyn::PhysicalObstacle PhysicalLibraryCell::getTopLayerObstracle() const {\n\treturn data->clsTopLayerObs;\n} // end  method \n\n//-----------------------------------------------------------------------------\n\t\t\ninline const std::vector<PhysicalObstacle> & PhysicalLibraryCell::allObstacles() const {\n\treturn data->clsObs;\n} // end  method \n\n//-----------------------------------------------------------------------------\n\ninline std::size_t PhysicalLibraryCell::getNumObstacles() const {\n\treturn data->clsObs.size();\n} // end  method \n\n//-----------------------------------------------------------------------------\n\ninline std::size_t PhysicalLibraryCell::getNumPhysicalCellLayerBoundaries() const {\n\tif (data->clsLayerBoundIndex < 0)\n\t\treturn 0;\n\treturn data->clsObs[data->clsLayerBoundIndex].getNumObs();\n} // end  method \n\n//-----------------------------------------------------------------------------\n\ninline PhysicalObstacle PhysicalLibraryCell::getLayerObstacles() const {\n\treturn data->clsObs[data->clsLayerBoundIndex];\n} // end  method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalTransform PhysicalLibraryCell::getTransform(const Rsyn::PhysicalOrientation &orientation) const {\n\treturn PhysicalTransform(getBounds(), orientation);\n} // end method\n\n//-----------------------------------------------------------------------------\n\ninline bool PhysicalLibraryCell::hasPolygonBoundaries() const {\n\treturn data->clsPolygonBounds.getNumPoints() > 0;\n} // end method \n\n//-----------------------------------------------------------------------------\n\ninline const Polygon & PhysicalLibraryCell::getPolygonBoundaries() const {\n\treturn data->clsPolygonBounds;\n} // end method \n\n//-----------------------------------------------------------------------------\n\n} // end  namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalLibraryPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline PhysicalLibraryCell PhysicalLibraryPin::getPhysicalLibraryCell() const {\n\treturn data->clsLibraryCell;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Bounds PhysicalLibraryPin::getICCADBounds() {\n\treturn data->clsLayerBound;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds & PhysicalLibraryPin::getICCADBounds() const {\n\treturn data->clsLayerBound;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::vector<PhysicalPinGeometry> & PhysicalLibraryPin::allPinGeometries() {\n\treturn data->clsPhysicalPinGeometries;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<PhysicalPinGeometry> & PhysicalLibraryPin::allPinGeometries() const {\n\treturn data->clsPhysicalPinGeometries;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalLibraryPin::getNumPinGeometries() const {\n\treturn data->clsPhysicalPinGeometries.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalLibraryPin::hasPinGeometries() const {\n\treturn !data->clsPhysicalPinGeometries.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalLibraryPin::isEmptyPinGeometries() const {\n\treturn data->clsPhysicalPinGeometries.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalPinDirection PhysicalLibraryPin::getPinDirection() const {\n\treturn data->clsDirection;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalPinUse PhysicalLibraryPin::getUse () const {\n\treturn data->clsUse;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalModule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalModule.h\n * Author: jucemar\n *\n * Created on 4 de Outubro de 2016, 20:35\n */\n\nnamespace Rsyn {\n} // end namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalNet.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalNet.h\n * Author: jucemar\n *\n * Created on 18 de Setembro de 2016, 09:03\n */\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::Net PhysicalNet::getNet() const {\n\treturn data? data->clsNet : nullptr;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline std::string PhysicalNet::getName() const {\n\treturn getNet().getName();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalNet::getHPWL() const {\n\treturn data->clsBounds.computeLength();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalNet::getHPWL(const Dimension dim) {\n\treturn data->clsBounds.computeLength(dim);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds & PhysicalNet::getBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalNet::getCoordinate(const Boundary bound) const {\n\treturn data->clsBounds[bound];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalNet::getCoordinate(const Boundary bound, const Dimension dim) const {\n\treturn data->clsBounds[bound][dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::Pin PhysicalNet::getPinBoundary(const Boundary bound, const Dimension dim) const {\n\treturn data->clsBoundPins[bound][dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const PhysicalRouting &PhysicalNet::getRouting() const {\n\treturn data->clsRouting;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalNet::isRouted() const {\n\treturn !data->clsRouting.isEmpty();\n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalObstacle.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\nnamespace Rsyn {\n\ninline Rsyn::PhysicalLayer PhysicalObstacle::getLayer() const {\n\treturn data->clsLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Bounds> & PhysicalObstacle::allBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalObstacle::getNumObs() const {\n\treturn data->clsBounds.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalObstacle::hasLayer() const {\n\treturn data->clsLayer != nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalPin.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPin.h\n * Author: jucemar\n *\n * Created on 18 de Setembro de 2016, 09:00\n */\n\nnamespace Rsyn {\n\ninline DBUxy PhysicalPin::getDisplacement() const {\n\treturn data->clsDisplacement;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalPin::getDisplacement(const Dimension dim) {\n\treturn data->clsDisplacement[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::vector<PhysicalPinGeometry> & PhysicalPin::allPinGeometries() {\n\treturn data->clsPhysicalPinGeometries;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<PhysicalPinGeometry> & PhysicalPin::allPinGeometries() const {\n\treturn data->clsPhysicalPinGeometries;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalPin::getNumPinGeometries() const {\n\treturn data->clsPhysicalPinGeometries.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPin::hasPinGeometries() const {\n\treturn !data->clsPhysicalPinGeometries.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPin::isEmptyPinGeometries() const {\n\treturn data->clsPhysicalPinGeometries.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalPinDirection PhysicalPin::getDirection() const {\n\treturn data->clsDirection;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds & PhysicalPin::getLayerBounds() const {\n\treturn data->clsLayerBound;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalPinGeometry.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n/* \n * File:   PhysicalPinGeometry.h\n * Author: jucemar\n *\n * Created on 18 de Setembro de 2016, 08:50\n */\n\nnamespace Rsyn {\n\ninline PhysicalPinGeometryClass PhysicalPinGeometry::getPinGeometryClass() const {\n\treturn data->clsPinPortClass;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPinGeometry::hasPinLayer() const {\n\treturn !data->clsPinLayers.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalPinGeometry::getNumPinLayers() const{\n\treturn data->clsPinLayers.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalPinLayer> &  PhysicalPinGeometry::allPinLayers() const {\n\treturn data->clsPinLayers;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalPinLayer PhysicalPinGeometry::getLowerPinLayer() const {\n\tif(data->clsPinLayers.empty())\n\t\treturn Rsyn::PhysicalPinLayer(nullptr);\n\treturn data->clsPinLayers.front();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalPinLayer PhysicalPinGeometry::getUpperPinLayer() const {\n\tif(data->clsPinLayers.empty())\n\t\treturn Rsyn::PhysicalPinLayer(nullptr);\n\treturn data->clsPinLayers.back();\n\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalPinLayer.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n/* \n * File:   PhysicalPinLayer.h\n * Author: jucemar\n *\n * Created on 18 de Setembro de 2016, 08:46\n */\nnamespace Rsyn {\n\ninline const std::vector<Bounds> & PhysicalPinLayer::allBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Polygon> & PhysicalPinLayer::allPolygons() const {\n\treturn data->clsPolygons;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalLayer PhysicalPinLayer::getLayer() const {\n\treturn data->clsLibLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalPinLayer::getNumBounds() const {\n\treturn data->clsBounds.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalPinLayer::getNumPolygons() const {\n\treturn data->clsPolygons.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPinLayer::hasRectangleBounds() const {\n\treturn !data->clsBounds.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPinLayer::hasPolygonBounds() const {\n\treturn !data->clsPolygons.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPinLayer::isRectangleBoundsEmpty() const {\n\treturn data->clsBounds.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPinLayer::isPolygonBoundsEmpty() const {\n\treturn data->clsPolygons.empty();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPinLayer::hasLayer() const {\n\treturn data->clsLibLayer != nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalPort.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalPort.h\n * Author: jucemar\n *\n * Created on 4 de Outubro de 2016, 19:34\n */\n\nnamespace Rsyn {\n// -----------------------------------------------------------------------------\n\ninline PhysicalLayer PhysicalPort::getLayer() const {\n\treturn data->clsPortLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalPort::hasLayer() const {\n\treturn data->clsPortLayer != nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalOrientation PhysicalPort::getOrientation() const {\n\treturn getInstance().getOrientation();\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalRegion.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRegion.h\n * Author: jucemar\n *\n * Created on 09 de Abril de 2017, 14:55\n */\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline const std::string & PhysicalRegion::getName() const {\n\treturn data->clsName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline RegionType PhysicalRegion::getType() const {\n\treturn data->clsType;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Bounds> & PhysicalRegion::allBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalRegion::getNumBounds() const {\n\treturn data->clsBounds.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalRoutingGrid.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalRoutingGrid.h\n * Author: jucemar\n *\n * Created on February 2, 2018, 9:06 PM\n */\n\nnamespace Rsyn {\n\ninline Rsyn::PhysicalLayer PhysicalRoutingGrid::getLayer() const {\n\treturn data->clsLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalTracks> & PhysicalRoutingGrid::allTracks() const {\n\treturn data->clsTracks;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds & PhysicalRoutingGrid::getBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getPosition() const {\n\treturn data->clsBounds[LOWER];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getPosition(const Dimension dim) const {\n\treturn data->clsBounds[LOWER][dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getSpacing() const {\n\treturn data->clsSpacing;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getSpacing(const Dimension dim) const {\n\treturn data->clsSpacing[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRoutingGrid::getNumTracks(const Dimension dim) const {\n\treturn data->clsNumTracks[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRoutingGrid::getNumRows() const {\n\treturn data->clsNumTracks[Y];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRoutingGrid::getNumCols() const {\n\treturn data->clsNumTracks[X];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRoutingGrid::getNumTracks() const {\n\treturn data->clsNumTracks[X] + data->clsNumTracks[Y];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRoutingGrid::getRow(const DBU posY, const RoundingStrategy roudingStrategy, const bool clamp) const {\n\tconst DBU pos = posY - getPosition(Y);\n\tconst int index = FloatingPoint::round(pos / float(getSpacing(Y)), roudingStrategy);\n\treturn clamp? std::max(0, std::min(index, getNumRows() - 1)) : index;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRoutingGrid::getCol(const DBU posX, const RoundingStrategy roudingStrategy, const bool clamp) const {\n\tconst DBU pos = posX - getPosition(X);\n\tconst int index = FloatingPoint::round(pos / float(getSpacing(X)), roudingStrategy);\n\treturn clamp? std::max(0, std::min(index, getNumCols() - 1)) : index;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getPosition(const int col, const int row) const {\n\tconst DBU x = getColPosition(col);\n\tconst DBU y = getRowPosition(row);\n\treturn DBUxy(x, y);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getSnappedPosition(const DBUxy pos, const RoundingStrategy roudingStrategy, const bool clamp) const {\n\tconst int col = getCol(pos.x, roudingStrategy, clamp);\n\tconst int row = getRow(pos.y, roudingStrategy, clamp);\n\treturn getPosition(col, row);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getRowPosition(const int row) const {\n\treturn getPosition(Y) + (getSpacing(Y) * row);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getRowMaxPosition() const {\n\treturn getRowPosition(getNumRows());\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getColPosition(const int col) const {\n\treturn getPosition(X) + (getSpacing(X) * col);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getColMaxPosition() const {\n\treturn getColPosition(getNumCols());\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getTrackMaxPosition() const {\n\tDBUxy pos;\n\tpos[X] = getColMaxPosition();\n\tpos[Y] = getRowMaxPosition();\n\treturn pos;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingGrid::getTrackMaxPosition(const Dimension dim) const {\n\tDBU pos = std::numeric_limits<DBU>::max();\n\tif (dim == X)\n\t\tpos = getColMaxPosition();\n\tif (dim == Y)\n\t\tpos = getRowMaxPosition();\n\treturn pos;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalRoutingGrid PhysicalRoutingGrid::getBottomRoutingGrid() const {\n\treturn data->clsBottomRoutingGrid;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalRoutingGrid PhysicalRoutingGrid::getTopRoutingGrid() const {\n\treturn data->clsTopRoutingGrid;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalRoutingGrid::hasBottomRoutingGrid() const {\n\treturn data->clsBottomRoutingGrid != nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalRoutingGrid::hasTopRoutingGrid() const {\n\treturn data->clsTopRoutingGrid != nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getGridMinPosition() const {\n\treturn data->clsBounds[LOWER];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getGridMaxPosition() const {\n\treturn data->clsBounds[UPPER];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getTrackMinPosition(const PhysicalLayerDirection dir, const int index) const {\n\tDBU x = 0;\n\tDBU y = 0;\n\tif (dir == Rsyn::VERTICAL) {\n\t\tx = getColPosition(index);\n\t\ty = getGridMinPosition().y;\n\t} else {\n\t\tx = getGridMinPosition().x;\n\t\ty = getRowPosition(index);\n\t} // end else\n\treturn DBUxy(x, y);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingGrid::getTrackMaxPosition(const PhysicalLayerDirection dir, const int index) const {\n\tDBU x = 0;\n\tDBU y = 0;\n\tif (dir == Rsyn::VERTICAL) {\n\t\tx = getColPosition(index);\n\t\ty = getGridMaxPosition().y;\n\t} else {\n\t\tx = getGridMaxPosition().x;\n\t\ty = getRowPosition(index);\n\t} // end else\n\treturn DBUxy(x, y);\n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalRoutingPoint.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRoutingPoint.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 20:52\n */\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRoutingPoint::getPosition() const {\n\treturn data->clsPos;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingPoint::getPosition(const Dimension dim) const {\n\treturn data->clsPos[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRoutingPoint::getExtension() const {\n\treturn data->clsExtension;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalVia PhysicalRoutingPoint::getVia() const {\n\treturn data->clsVia;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds & PhysicalRoutingPoint::getRectangle() const {\n\treturn data->clsRectangle;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalRoutingPoint::hasExtension() const {\n\treturn data->clsExtension > -1;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalRoutingPoint::hasRectangle() const {\n\treturn data->clsHasRectangle;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalRoutingPoint::hasVia() const {\n\treturn data->clsVia != nullptr;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalRow.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalRow.h\n * Author: jucemar\n *\n * Created on 18 de Setembro de 2016, 09:27\n */\nnamespace Rsyn {\n\ninline std::string PhysicalRow::getName() const {\n\treturn data->clsRowName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::string PhysicalRow::getSiteName() const {\n\treturn data->clsPhysicalSite.getName();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRow::getWidth() const {\n\treturn data->clsNumSites[X] * data->clsStep[X];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRow::getHeight() const {\n\treturn data->clsNumSites[Y] * data->clsStep[Y];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRow::getOrigin(const Dimension dim) const {\n\treturn data->clsOrigin[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRow::getOrigin() const {\n\treturn data->clsOrigin;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRow::getStep(const Dimension dim) const {\n\treturn data->clsStep[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRow::getStep() const {\n\treturn data->clsStep;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalRow::getNumSites(const Dimension dim) const  {\n\treturn data->clsNumSites[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalSite PhysicalRow::getPhysicalSite() const {\n\treturn data->clsPhysicalSite;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRow::getSiteWidth() const {\n\treturn data->clsPhysicalSite.getWidth();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalRow::getSiteHeight() const {\n\treturn data->clsPhysicalSite.getHeight();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalRow::getCoordinate(const Boundary bound) const {\n\treturn data->clsBounds[bound];\n} // end method \n\n// ----------------------------------------------------------------------------- \n\ninline DBU PhysicalRow::getCoordinate(const Boundary bound, const Dimension dim) const {\n\treturn data->clsBounds[bound][dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const Bounds &PhysicalRow::getBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalOrientation PhysicalRow::getSiteOrientation() const {\n\treturn data->clsSiteOrientation;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalSymmetry PhysicalRow::getSymmetry() const {\n\treturn data->clsPhysicalSite ? data->clsPhysicalSite.getSymmetry() : Rsyn::PhysicalSymmetry::SYMMETRY_INVALID;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalSite.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSite.h\n * Author: jucemar\n *\n * Created on 18 de Setembro de 2016, 08:42\n */\n\nnamespace Rsyn {\n\ninline std::string PhysicalSite::getName() const {\n\treturn data->clsSiteName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalSiteClass PhysicalSite::getClass() const {\n\treturn data->clsSiteClass;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBUxy PhysicalSite::getSize() const {\n\treturn data->clsSize;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalSite::getWidth() const {\n\treturn data->clsSize[X];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalSite::getHeight() const {\n\treturn data->clsSize[Y];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalSite::getLength(const Dimension dim) const {\n\treturn data->clsSize[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalSymmetry PhysicalSite::getSymmetry() const {\n\treturn data->clsSymmetry;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalSpacing.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\nnamespace Rsyn {\n\ninline PhysicalLayer PhysicalSpacing::getLayer1() const {\n\treturn data->clsLayer1;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalLayer PhysicalSpacing::getLayer2() const {\n\treturn data->clsLayer2;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalSpacing::getDistance() const {\n\treturn data->clsDistance;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalSpecialNet.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpecialNet.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 20:58\n */\n\nnamespace Rsyn {\n\ninline const DefNetDscp & PhysicalSpecialNet::getNet() const { return data->clsNet; }\n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalSpecialWire.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalSpecialWire.h\n * Author: jucemar\n *\n * Created on 23 de Maio de 2017, 21:12\n */\n\n\nnamespace Rsyn {\n\ninline Rsyn::PhysicalLayer PhysicalSpecialWire::getPhysicalLayer() {\n\treturn data->clsPhysicalLayer;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalSpecialWire::getWireWidth() const {\n\treturn data->clsWireWidth;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<PhysicalRoutingPoint> & PhysicalSpecialWire::allRoutingPoints() const {\n\treturn data->clsRoutingPoints;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n\n\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalTracks.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalTracks.h\n * Author: jucemar\n *\n * Created on 24 de Maio de 2017, 21:53\n */\n\nnamespace Rsyn {\n\ninline PhysicalTrackDirection PhysicalTracks::getDirection() const {\n\treturn data->clsDirection;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalTracks::getLocation() const {\n\treturn data->clsLocation;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalTracks::getSpace() const {\n\treturn data->clsSpace;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalTracks::getNumberOfTracks() const {\n\treturn data->clsNumTracks;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline std::size_t PhysicalTracks::getNumberOfLayers() const {\n\treturn data->clsLayers.size();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<PhysicalLayer> & PhysicalTracks::allLayers() const {\n\treturn data->clsLayers;\n} // end method \n\n// -----------------------------------------------------------------------------\n} // end namespace \n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalVia.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalVia.h\n * Author: jucemar\n *\n * Created on 14 de Maio de 2017, 15:25\n */\n\nnamespace Rsyn {\n\ninline const std::string & PhysicalVia::getName() const {\n\treturn data->clsName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalVia::getTopLayer() const {\n\treturn PhysicalLayer(data->clsLayers[TOP_VIA_LAYER]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalVia::getCutLayer() const {\n\treturn PhysicalLayer(data->clsLayers[CUT_VIA_LAYER]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalVia::getBottomLayer() const {\n\treturn PhysicalLayer(data->clsLayers[BOTTOM_VIA_LAYER]);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalVia::getLayer(const PhysicalViaLayerType type) const {\n\treturn PhysicalLayer(data->clsLayers[type]);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::isViaDesign() const {\n\treturn data->clsIsViaDesign;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::isViaRule() const {\n\treturn data->clsType == VIA_RULE_TYPE;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::isViaGeometry() const {\n\treturn data->clsType == VIA_GEOMETRY_TYPE;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::hasViaRule() const {\n\treturn data->clsHasViaRule;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::hasRowCol() const {\n\treturn data->clsHasRowCol;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::hasOrigin() const {\n\treturn data->clsHasOrigin;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::hasOffset() const {\n\treturn data->clsHasOffset;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalVia::hasPattern() const {\n\treturn data->clsHasPattern;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline ViaType PhysicalVia::getViaType() const {\n\treturn data->clsType;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalViaRuleBase PhysicalVia::getViaRule() const {\n\treturn PhysicalViaRuleBase(data->clsViaRuleData);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalVia::getCutSize(const Dimension dim) const {\n\treturn data->clsCutSize[dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalVia::getSpacing(const Dimension dim) const {\n\treturn data->clsSpacing[dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalVia::getEnclosure(const ViaLevel level, const Dimension dim) const {\n\treturn data->clsEnclosure[level][dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalVia::getOrigin(const Dimension dim) const {\n\treturn data->clsOrigin[dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalVia::getOffset(const ViaLevel level, const Dimension dim) const {\n\treturn data->clsOffset[level][dim];\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalVia::getNumRows() const {\n\treturn data->clsNumRows;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalVia::getNumCols() const {\n\treturn data->clsNumCols;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const std::string & PhysicalVia::getPattern() const {\n\treturn data->clsPattern;\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalViaGeometry> & PhysicalVia::allBottomGeometries() const {\n\treturn allGeometries(BOTTOM_VIA_LAYER);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalViaGeometry> & PhysicalVia::allCutGeometries() const {\n\treturn allGeometries(CUT_VIA_LAYER);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalViaGeometry> & PhysicalVia::allTopGeometries() const {\n\treturn allGeometries(TOP_VIA_LAYER);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalViaGeometry> & PhysicalVia::allGeometries(const PhysicalViaLayerType layer) const {\n\treturn data->clsViaGeometries[layer];\n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalViaGeometry.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaGeometry.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 10:14 PM\n */\n\nnamespace Rsyn {\n\ninline const Bounds & PhysicalViaGeometry::getBounds() const {\n\treturn data->clsBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline int PhysicalViaGeometry::getMaskNumber() const {\n\treturn data->clsMaskNumber;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalViaRule.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaRule.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 9:24 PM\n */\n\nnamespace Rsyn {\n\ninline int PhysicalViaRule::getRelativeIndex() const {\n\treturn data->clsRelativeIndex;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalViaRule::getLayer(const Rsyn::ViaLevel level) const {\n\treturn Rsyn::PhysicalLayer(data->clsLayers[level]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayerDirection PhysicalViaRule::getLayerDirection(const Rsyn::ViaLevel level) const {\n\treturn data->clsLayerDirection[level];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::vector<Rsyn::PhysicalVia> & PhysicalViaRule::allVias() const {\n\treturn data->clsVias;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n}\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalViaRuleBase.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaRuleBase.h\n * Author: jucemar\n *\n * Created on November 13, 2018, 3:42 PM\n */\n\nnamespace Rsyn {\n\ninline int PhysicalViaRuleBase::getIndex() const {\n\treturn data->id;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalViaRule PhysicalViaRuleBase::asViaRule() const {\n\treturn isViaRule() ? PhysicalViaRule(data) : PhysicalViaRule();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline PhysicalViaRuleGenerate PhysicalViaRuleBase::asViaRuleGenerate() const {\n\treturn isViaRuleGenerate() ? PhysicalViaRuleGenerate(data) : PhysicalViaRuleGenerate();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalViaRuleBase::isViaRule() const {\n\treturn !isViaRuleGenerate();\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalViaRuleBase::isViaRuleGenerate() const {\n\treturn data->clsIsGenerate;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline const std::string & PhysicalViaRuleBase::getName() const {\n\treturn data->clsName;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalViaRuleBase::hasWidth(const Rsyn::ViaLevel level) const {\n\treturn data->clsHasWidth[level];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalViaRuleBase::getWidth(const Rsyn::ViaLevel level, const Rsyn::ViaRange range) const {\n\treturn data->clsWidth[level][range];\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/phy/obj/impl/PhysicalViaRuleGenerate.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* \n * File:   PhysicalViaGenerate.h\n * Author: jucemar\n *\n * Created on November 12, 2018, 9:56 PM\n */\n\nnamespace Rsyn {\n\ninline int PhysicalViaRuleGenerate::getRelativeIndex() const {\n\treturn data->clsRelativeIndex;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalViaRuleGenerate::isDefault() const {\n\treturn data->clsIsDefault;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Rsyn::PhysicalLayer PhysicalViaRuleGenerate::getLayer(const Rsyn::PhysicalViaLayerType layer) const {\n\treturn Rsyn::PhysicalLayer(data->clsLayers[layer]);\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalViaRuleGenerate::getEnclosure1(const Rsyn::ViaLevel level) const {\n\treturn data->clsEnclosure1[level];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalViaRuleGenerate::getEnclosure2(const Rsyn::ViaLevel level) const {\n\treturn data->clsEnclosure2[level];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline Bounds PhysicalViaRuleGenerate::getCutBounds() const {\n\treturn data->clsCutBounds;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline DBU PhysicalViaRuleGenerate::getCutSpacing(const Dimension dim) const {\n\treturn data->clsCutSpacing[dim];\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline bool PhysicalViaRuleGenerate::hasCutResistance() const {\n\treturn data->clsHasCutResistance;\n} // end method \n\n// -----------------------------------------------------------------------------\n\ninline float PhysicalViaRuleGenerate::getCutResistance() const {\n\treturn data->clsCutResistance;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n\n} // end namespace "
  },
  {
    "path": "rsyn/src/rsyn/phy/util/DefDescriptors.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   DefDescriptors.h\n * Author: jucemar\n *\n * Created on 6 de Julho de 2016, 18:24\n */\n\n#ifndef DEFDESCRIPTORS_H\n#define DEFDESCRIPTORS_H\n\n#include <vector>\n#include <deque>\n#include <map>\n\n#include \"rsyn/util/Bounds.h\"\n#include \"rsyn/util/dbu.h\"\n\nstatic const std::string INVALID_DEF_NAME = \"*<INVALID_DEF_NAME>*\";\n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF components\n\nclass DefComponentDscp {\npublic:\n\tstd::string clsName = INVALID_DEF_NAME;\n\tstd::string clsMacroName = INVALID_DEF_NAME;\n\tstd::string clsLocationType = INVALID_DEF_NAME; // {FIXED | COVER | PLACED | UNPLACED }\n\tDBUxy clsPos;\n\tstd::string clsOrientation = INVALID_DEF_NAME;\n\tbool clsIsFixed = false;\n\tbool clsIsPlaced = false;\n\tDefComponentDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for Def Groups \n\nclass DefGroupDscp {\npublic:\n\tstd::string clsName = INVALID_DEF_NAME;\n\tstd::vector<std::string> clsPatterns; // It may be a pattern, e.g. \"name/*\"\n\tstd::string clsRegion = INVALID_DEF_NAME;\n\tDefGroupDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF ports\n\nclass DefPortDscp {\npublic:\n\tstd::string clsName = INVALID_DEF_NAME;\n\tstd::string clsNetName = INVALID_DEF_NAME;\n\tstd::string clsDirection = INVALID_DEF_NAME; // {INPUT | OUTPUT | INOUT | FEEDTHRU}\n\tstd::string clsLocationType = INVALID_DEF_NAME; // {FIXED | COVER | PLACED }\n\tstd::string clsOrientation = INVALID_DEF_NAME;\n\tstd::string clsLayerName = INVALID_DEF_NAME;\n\tstd::string clsUse = INVALID_DEF_NAME; // { SIGNAL | POWER | GROUND | CLOCK | TIEOFF | ANALOG}\n\tDBUxy clsPos;\n\tDBUxy clsICCADPos;\n\tBounds clsLayerBounds;\n\tbool clsSpecial = false;\n\tDefPortDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF Net connections\n\nclass DefNetConnection {\npublic:\n\tstd::string clsPinName = INVALID_DEF_NAME;\n\tstd::string clsComponentName = INVALID_DEF_NAME;\n\tDefNetConnection() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass DefRoutingPointDscp {\npublic:\n\tstd::string clsViaName = INVALID_DEF_NAME;\n\tstd::string clsOrientation = \"N\"; // Default orientation\n\tDBU clsExtension = 0;\n\tDBUxy clsPos;\n\tbool clsHasMask : 1;\n\tbool clsHasRectangle : 1;\n\tbool clsHasVirtual : 1;\n\tbool clsHasVia : 1;\n\tbool clsHasExtension : 1;\n\t/*\n\t * \"RECT ( deltax1 deltay1 deltax2 deltay2 )\n\t * Indicates that a rectangle is created from the previous ( x y ) \n\t * routing point using the delta values. The RECT values leave the \n\t * current point and layer unchanged.\" Source: LEf/DEf Reference Manual 5.8\n\t */\n\tBounds clsRect;\n\n\tDefRoutingPointDscp() {\n\t\tclsHasMask = false;\n\t\tclsHasRectangle = false;\n\t\tclsHasVirtual = false;\n\t\tclsHasVia = false;\n\t\tclsHasExtension = false;\n\t} // end constructor \n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for wire path associated to wires \n\nclass DefWireSegmentDscp {\npublic:\n\tstd::string clsLayerName = INVALID_DEF_NAME;\n\tstd::vector<DefRoutingPointDscp> clsRoutingPoints;\n\t//  only valid to special nets.\n\tDBU clsRoutedWidth = 0;\n\tbool clsHasShape = false;\n\tstd::string clsShape = \"\";\n\tDefWireSegmentDscp() = default;\n}; // end class \n\n//! Descriptor for routed wires \n\nclass DefWireDscp {\npublic:\n\tstd::vector<DefWireSegmentDscp> clsWireSegments;\n\tstd::string clsWireType = INVALID_DEF_NAME;\n\tDefWireDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF Nets\n\nclass DefNetDscp {\npublic:\n\tstd::string clsName = INVALID_DEF_NAME;\n\tbool clsHasUse = false;\n\tstd::string clsUse = INVALID_DEF_NAME;\n\tstd::vector<DefNetConnection> clsConnections;\n\tstd::vector<DefWireDscp> clsWires;\n\tDefNetDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF Regions\n\nclass DefRegionDscp {\npublic:\n\tstd::string clsName = INVALID_DEF_NAME;\n\tstd::string clsType = INVALID_DEF_NAME; // FENCE or GUIDE\n\tstd::vector<Bounds> clsBounds;\n\tDefRegionDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF rows.\n\nclass DefRowDscp {\npublic:\n\tstd::string clsName = INVALID_DEF_NAME;\n\tstd::string clsSite = INVALID_DEF_NAME;\n\tDBUxy clsOrigin;\n\tstd::string clsOrientation = INVALID_DEF_NAME;\n\tint clsNumX = 0;\n\tint clsNumY = 0;\n\tint clsStepX = 0;\n\tint clsStepY = 0;\n\tDefRowDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass DefTrackDscp {\npublic:\n\tbool clsHasRect : 1;\n\tbool clsHasPolygon : 1;\n\tstd::string clsDirection = INVALID_DEF_NAME;\n\tDBU clsLocation = 0;\n\tint clsNumTracks = 0;\n\tstd::vector<std::string> clsLayers;\n\tDBU clsSpace = 0;\n\tDefTrackDscp() {\n\t\tclsHasRect = false;\n\t\tclsHasPolygon = false;\n\t} // end constructor\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass DefGcellGridDscp {\npublic:\n\tstd::string clsMacro = \"\";\n\tint clsX = 0;\n\tint clsXNum = 0;\n\tdouble clsXStep = 0.0;\n\tDefGcellGridDscp () = default;\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass DefViaGeometryDscp {\npublic:\n\tbool clsIsPolygon : 1;\n\tbool clsIsRect : 1;\n\tint clsMask = 0;\n\tbool clsHasMask = false;\n\tBounds clsBounds;\n\t\n\t// TODO Polygon\n\tDefViaGeometryDscp (){\n\t\tclsIsPolygon = false;\n\t\tclsIsRect = false;\n\t} // end constructor\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass DefViaDscp {\npublic:\n\tbool clsHasViaRule : 1;\n\tbool clsHasRowCol : 1;\n\tbool clsHasOrigin : 1;\n\tbool clsHasOffset : 1;\n\tbool clsHasPattern : 1;\n\tDBU clsXOffsetOrigin = 0;\n\tDBU clsYOffsetOrigin = 0;\n\tDBU clsXCutSize = 0;\n\tDBU clsYCutSize = 0;\n\tDBU clsXCutSpacing = 0;\n\tDBU clsYCutSpacing = 0;\n\tDBU clsXBottomEnclosure = 0;\n\tDBU clsYBottomEnclosure = 0;\n\tDBU clsXTopEnclosure = 0;\n\tDBU clsYTopEnclosure = 0;\n\tDBU clsXBottomOffset = 0;\n\tDBU clsYBottomOffset = 0;\n\tDBU clsXTopOffset = 0;\n\tDBU clsYTopOffset = 0;\n\tint clsNumCutRows = 0;\n\tint clsNumCutCols = 0;\n\tstd::string clsName = INVALID_DEF_NAME;\n\tstd::string clsViaRuleName = INVALID_DEF_NAME;\n\tstd::string clsBottomLayer;\n\tstd::string clsCutLayer;\n\tstd::string clsTopLayer;\n\tstd::string clsPattern;\n\t// map->first = layerName; map->second = list of geometry rects or polygons.\n\tstd::map<std::string, std::deque<DefViaGeometryDscp>> clsGeometries;\n\tDefViaDscp() {\n\t\tclsHasViaRule = false;\n\t\tclsHasRowCol = false;\n\t\tclsHasOrigin = false;\n\t\tclsHasOffset = false;\n\t\tclsHasPattern = false;\n\t} // end constructor \n}; // end class\n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for DEF Design\n\nclass DefDscp {\npublic:\n\tbool clsHasVersion : 1;\n\tbool clsHasDevideChar : 1;\n\tbool clsHasBusBitChar : 1;\n\tbool clsHasDieBounds : 1;\n\tbool clsHasDatabaseUnits : 1;\n\tdouble clsVersion = 0.0;\n\tstd::string clsDeviderChar = INVALID_DEF_NAME;\n\tstd::string clsBusBitChars = INVALID_DEF_NAME;\n\tstd::string clsDesignName = INVALID_DEF_NAME;\n\tBounds clsDieBounds;\n\tint clsDatabaseUnits = 0;\n\tstd::vector<DefRowDscp> clsRows;\n\tstd::vector<DefComponentDscp> clsComps;\n\tstd::vector<DefPortDscp> clsPorts;\n\tstd::vector<DefNetDscp> clsNets;\n\tstd::vector<DefRegionDscp> clsRegions;\n\tstd::vector<DefGroupDscp> clsGroups;\n\tstd::vector<DefNetDscp> clsSpecialNets;\n\tstd::vector<DefViaDscp> clsVias;\n\tstd::vector<DefTrackDscp> clsTracks;\n\tstd::vector<DefGcellGridDscp> clsGcellGrids;\n\tDefDscp() {\n\t\tclsHasVersion = false;\n\t\tclsHasDevideChar = false;\n\t\tclsHasBusBitChar = false;\n\t\tclsHasDieBounds = false;\n\t\tclsHasDatabaseUnits = false;\n\t} // end constructor \n}; // end class \n\n// -----------------------------------------------------------------------------\n\n#endif /* DEFDESCRIPTORS_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/util/LefDescriptors.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n/* \n * File:   PhysicalDescriptors.h\n * Author: jucemar\n *\n * Created on 6 de Julho de 2016, 15:29\n */\n\n\n#ifndef LEFDESCRIPTORS_H\n#define LEFDESCRIPTORS_H\n\n#include <map>\n#include <deque>\n\n#include \"rsyn/util/DoubleRectangle.h\"\n#include \"rsyn/util/double2.h\"\n\n#include \"lef5.8/lefrReader.hpp\"\n\n// NOTE: Guilherme Flach - 2016/11/04\n// I did not change here from double to dbu because the data is load from\n// lef as is and therefore it's in micron. The conversion to dbu is currently\n// done in the physical layer initialization.\n\nstatic const std::string INVALID_LEF_NAME = \"*<INVALID_LEF_NAME>*\";\nstatic const std::string DEFAULT_PIN_DIRECTION = \"INPUT\";\n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Polygon\n\nclass LefPolygonDscp {\npublic:\n\tstd::vector<double2> clsPolygonPoints;\n\tLefPolygonDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\nclass LefPortGeometryDscp {\npublic:\n\tstd::string clsMetalName = INVALID_LEF_NAME;\n\tstd::vector<DoubleRectangle> clsBounds;\n\tstd::vector<LefPolygonDscp> clsLefPolygonDscp;\n}; // end class \n\n//! Descriptor for LEF Port\n\nclass LefPortDscp {\npublic:\n\tstd::vector<LefPortGeometryDscp> clsLefPortGeoDscp;\n\tLefPortDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Pin\n\nclass LefPinDscp {\npublic:\n\tbool clsHasPort = false;\n\tstd::string clsPinName = INVALID_LEF_NAME;\n\tstd::string clsPinDirection = DEFAULT_PIN_DIRECTION;\n\tstd::string clsPinUse = INVALID_LEF_NAME;\n\tDoubleRectangle clsBounds;\n\tstd::vector<LefPortDscp> clsPorts;\n\tLefPinDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Obstruction\n\nclass LefObsDscp {\npublic:\n\tstd::string clsMetalLayer = INVALID_LEF_NAME;\n\tstd::vector<DoubleRectangle> clsBounds;\n\tLefObsDscp() = default;\n};\n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Macro\n\nclass LefMacroDscp {\npublic:\n\tlefiMacro* clsMacro = nullptr;\n\tstd::vector<LefPinDscp> clsPins;\n\tstd::vector<LefObsDscp> clsObs;\n\tLefMacroDscp() { clsMacro = new lefiMacro(); }\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Site\n\nclass LefSiteDscp {\npublic:\n\tstd::string clsName = INVALID_LEF_NAME;\n\tdouble2 clsSize;\n\tbool clsHasClass = false;\n\tstd::string clsSiteClass = INVALID_LEF_NAME;\n\tstd::string clsSymmetry = INVALID_LEF_NAME;\n\tLefSiteDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Spacing\n\nclass LefSpacingDscp {\npublic:\n\tstd::string clsLayer1 = INVALID_LEF_NAME;\n\tstd::string clsLayer2 = INVALID_LEF_NAME;\n\tdouble clsDistance = 0.0;\n\tLefSpacingDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Via Layer. A via layer is composed by a layer and a set of rectangles.\n\nclass LefViaGeometryDscp {\npublic:\n\tDoubleRectangle clsBounds;\n\tint clsMask = 0;\n\tLefViaGeometryDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Via\n\nclass LefViaDscp {\npublic:\n\tbool clsIsDefault : 1;\n\tbool clsHasViaRule : 1;\n\tbool clsHasRowCol : 1;\n\tbool clsHasOrigin : 1;\n\tbool clsHasOffset : 1;\n\tbool clsHasResistance : 1;\n\tdouble clsXCutSize = 0;\n\tdouble clsYCutSize = 0;\n\tdouble clsXCutSpacing = 0;\n\tdouble clsYCutSpacing = 0;\n\tdouble clsXBottomEnclosure = 0;\n\tdouble clsYBottomEnclosure = 0;\n\tdouble clsXTopEnclosure = 0;\n\tdouble clsYTopEnclosure = 0;\n\tdouble clsXOrigin = 0;\n\tdouble clsYOrigin = 0;\n\tdouble clsXBottomOffset = 0;\n\tdouble clsYBottomOffset = 0;\n\tdouble clsXTopOffset = 0;\n\tdouble clsYTopOffset = 0;\n\tdouble clsCutResistance = 0.0;\n\tint clsNumCutRows = 0;\n\tint clsNumCutCols = 0;\n\t// map->first = layerName; map->second = list of geometry rects or polygons.\n\tstd::map<std::string, std::deque<LefViaGeometryDscp>> clsGeometries;\n\tstd::string clsName = INVALID_LEF_NAME;\n\tstd::string clsViaRuleName = INVALID_LEF_NAME;\n\tstd::string clsBottomLayer = INVALID_LEF_NAME;\n\tstd::string clsCutLayer = INVALID_LEF_NAME;\n\tstd::string clsTopLayer = INVALID_LEF_NAME;\n\t\n\tLefViaDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Layer of Via Rule and Via Rule Generate\n\nclass LefViaRuleLayerDscp {\npublic:\n\tbool clsHasDirection : 1;\n\tbool clsHasEnclosure : 1;\n\tbool clsHasWidth : 1;\n\tbool clsHasResistance : 1;\n\tbool clsHasOverhang : 1;\n\tbool clsHasMetalOverhang : 1;\n\tbool clsHasSpacing : 1;\n\tbool clsHasRect : 1;\n\tbool clsIsHorizontal : 1;\n\tbool clsIsVertical : 1;\n\n\tstd::string clsName = INVALID_LEF_NAME;\n\tdouble clsEnclosure1 = 0.0;\n\tdouble clsEnclosure2 = 0.0;\n\tdouble clsCutResistance = 0.0;\n\tdouble clsMinWidth = 0.0;\n\tdouble clsMaxWidth = 0.0;\n\tdouble clsXSpacing  = 0.0;\n\tdouble clsYSpacing = 0.0;\n\tDoubleRectangle clsRect;\n\tLefViaRuleLayerDscp() {\n\t\tclsHasDirection = false;\n\t\tclsHasEnclosure = false;\n\t\tclsHasWidth = false;\n\t\tclsHasResistance = false;\n\t\tclsHasOverhang = false;\n\t\tclsHasMetalOverhang = false;\n\t\tclsHasSpacing = false;\n\t\tclsHasRect = false;\n\t\tclsIsHorizontal = false;\n\t\tclsIsVertical = false;\n\t} // end constructor\n}; // end class \n\n//! Descriptor for LEF Via Rule and Via Rule Generate\n\nclass LefViaRuleDscp {\npublic:\n\tstd::string clsName = INVALID_LEF_NAME;\n\tbool clsIsGenerate = false;\n\tbool clsIsDefault = false;\n\tstd::vector<LefViaRuleLayerDscp> clsLayers;\n\tstd::vector<std::string> clsVias;\n\tLefViaRuleDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF Units\n\nclass LefUnitsDscp {\npublic:\n\tbool clsHasTime = false;\n\tbool clsHasCapacitance = false;\n\tbool clsHasResitance = false;\n\tbool clsHasPower = false;\n\tbool clsHasCurrent = false;\n\tbool clsHasVoltage = false;\n\tbool clsHasDatabase = false;\n\tbool clsHasFrequency = false;\n\n\tint clsTime = 0;\n\tint clsCapacitance = 0;\n\tint clsResitance = 0;\n\tint clsPower = 0;\n\tint clsCurrent = 0;\n\tint clsVoltage = 0;\n\tint clsDatabase = 100; // default value at LEF/DEF reference\n\tint clsFrequency = 0;\n\n\tLefUnitsDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n//! Descriptor for LEF. The LEF elements are kept in the units defined at LefUnitsDscp.\n\nclass LefDscp {\npublic:\n\tint clsMajorVersion = 0;\n\tint clsMinorVersion = 0;\n\tstd::string clsCaseSensitive = INVALID_LEF_NAME;\n\tstd::string clsBusBitChars = INVALID_LEF_NAME;\n\tstd::string clsDivideChar = INVALID_LEF_NAME;\n\tdouble clsManufactGrid = 0.0;\n\tLefUnitsDscp clsLefUnitsDscp;\n\tstd::vector<LefSiteDscp> clsLefSiteDscps;\n\tstd::vector<lefiLayer*> clsLefLayer;\n\tstd::vector<LefMacroDscp> clsLefMacroDscps;\n\tstd::vector<LefSpacingDscp> clsLefSpacingDscps;\n\tstd::vector<LefViaDscp> clsLefViaDscps;\n\tstd::deque<LefViaRuleDscp> clsLefViaRuleDscps;\n\tLefDscp() = default;\n}; // end class \n\n// -----------------------------------------------------------------------------\n\n#endif /* PHYSICALDESCRIPTORS_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/util/PhysicalLayerUtil.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n#include \"PhysicalUtil.h\"\n\nnamespace Rsyn {\n\nstatic const std::string NULL_PHY_NAME = \"*<NULL_PHY_NAME>*\";\nstatic const std::string GEN_NAME = \"*<GEN_NAME>*_\";\nstatic const std::string INVALID_NAME = \"*<INVALID_NAME>*\";\n\nRsyn::PhysicalLayerType getPhysicalLayerType(const std::string & type) {\n\tif (type.compare(\"ROUTING\") == 0) return ROUTING;\n\tif (type.compare(\"CUT\") == 0) return CUT;\n\tif (type.compare(\"OVERLAP\") == 0) return OVERLAP;\n\tif (type.compare(\"MASTERSLICE\") == 0) return MASTERSLICE;\n\tif (type.compare(\"IMPLANT\") == 0) return IMPLANT;\n\treturn INVALID_PHY_LAYER_TYPE;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalLayerType(const Rsyn::PhysicalLayerType type) {\n\tswitch (type) {\n\t\tcase ROUTING: return \"ROUTING\";\n\t\tcase CUT: return \"CUT\";\n\t\tcase OVERLAP: return \"OVERLAP\";\n\t\tcase MASTERSLICE: return \"MASTERSLICE\";\n\t\tcase IMPLANT: return \"IMPLANT\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalLayerDirection getPhysicalLayerDirection(const std::string & direction) {\n\tif (direction.compare(\"HORIZONTAL\") == 0) return HORIZONTAL;\n\tif (direction.compare(\"VERTICAL\") == 0) return VERTICAL;\n\treturn UNKNOWN_PREFERRED_DIRECTION;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalLayerDirection(const PhysicalLayerDirection direction) {\n\tswitch (direction) {\n\t\tcase HORIZONTAL: return \"HORIZONTAL\";\n\t\tcase VERTICAL: return \"VERTICAL\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalOrientation getPhysicalOrientation(const std::string &orientation) {\n\tif (orientation.compare(\"N\") == 0) return ORIENTATION_N;\n\tif (orientation.compare(\"S\") == 0) return ORIENTATION_S;\n\tif (orientation.compare(\"E\") == 0) return ORIENTATION_E;\n\tif (orientation.compare(\"W\") == 0) return ORIENTATION_W;\n\n\tif (orientation.compare(\"FN\") == 0) return ORIENTATION_FN;\n\tif (orientation.compare(\"FS\") == 0) return ORIENTATION_FS;\n\tif (orientation.compare(\"FE\") == 0) return ORIENTATION_FE;\n\tif (orientation.compare(\"FW\") == 0) return ORIENTATION_FW;\n\n\treturn ORIENTATION_INVALID;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalOrientation(const Rsyn::PhysicalOrientation orientation) {\n\tswitch (orientation) {\n\t\tcase ORIENTATION_N: return \"N\";\n\t\tcase ORIENTATION_S: return \"S\";\n\t\tcase ORIENTATION_E: return \"E\";\n\t\tcase ORIENTATION_W: return \"W\";\n\n\t\tcase ORIENTATION_FN: return \"FN\";\n\t\tcase ORIENTATION_FS: return \"FS\";\n\t\tcase ORIENTATION_FE: return \"FE\";\n\t\tcase ORIENTATION_FW: return \"FW\";\n\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalMacroClass getPhysicalMacroClass(const std::string & macroClass) {\n\tif (macroClass.compare(\"COVER\") == 0) return MACRO_COVER;\n\tif (macroClass.compare(\"RING\") == 0) return MACRO_RING;\n\tif (macroClass.compare(\"BLOCK\") == 0) return MACRO_BLOCK;\n\tif (macroClass.compare(\"PAD\") == 0) return MACRO_PAD;\n\tif (macroClass.compare(\"CORE\") == 0) return MACRO_CORE;\n\tif (macroClass.compare(\"ENDCAP\") == 0) return MACRO_ENDCAP;\n\n\treturn MACRO_INVALID_CLASS;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalMacroClass(const Rsyn::PhysicalMacroClass macroClass) {\n\tswitch (macroClass) {\n\t\tcase MACRO_COVER: return \"COVER\";\n\t\tcase MACRO_RING: return \"RING\";\n\t\tcase MACRO_BLOCK: return \"BLOCK\";\n\t\tcase MACRO_PAD: return \"PAD\";\n\t\tcase MACRO_CORE: return \"CORE\";\n\t\tcase MACRO_ENDCAP: return \"ENDCAP\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch\n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalSymmetry getPhysicalSymmetry(const std::string &rowSymmetry) {\n\tbool hasX = std::string::npos != rowSymmetry.find(\"X\");\n\tbool hasY = std::string::npos != rowSymmetry.find(\"Y\");\n\tbool hasR90 = std::string::npos != rowSymmetry.find(\"R90\");\n\n\n\tif (hasX && hasY && hasR90) return SYMMETRY_XYR90;\n\n\tif (hasY && hasR90) return SYMMETRY_YR90;\n\tif (hasX && hasR90) return SYMMETRY_XR90;\n\tif (hasX && hasY) return SYMMETRY_XY;\n\n\tif (hasR90) return SYMMETRY_R90;\n\tif (hasY) return SYMMETRY_Y;\n\tif (hasX) return SYMMETRY_X;\n\n\treturn SYMMETRY_INVALID;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalSymmetry(const Rsyn::PhysicalSymmetry rowSymmetry) {\n\tswitch (rowSymmetry) {\n\t\tcase SYMMETRY_X: return \"X\";\n\t\t\tbreak;\n\t\tcase SYMMETRY_Y: return \"Y\";\n\t\t\tbreak;\n\t\tcase SYMMETRY_R90: return \"R90\";\n\t\t\tbreak;\n\t\tcase SYMMETRY_XY: return \"X Y\";\n\t\t\tbreak;\n\t\tcase SYMMETRY_XR90: return \"X R90\";\n\t\t\tbreak;\n\t\tcase SYMMETRY_YR90: return \"Y R90\";\n\t\t\tbreak;\n\t\tcase SYMMETRY_XYR90: return \"X Y R90\";\n\t\t\tbreak;\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool isPhysicalSymmetryX(const Rsyn::PhysicalSymmetry symmetry) {\n\treturn symmetry == SYMMETRY_X || symmetry == SYMMETRY_XY || \n\t\tsymmetry == SYMMETRY_XR90 || SYMMETRY_XYR90;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool isPhysicalSymmetryY(const Rsyn::PhysicalSymmetry symmetry) {\n\treturn symmetry == SYMMETRY_Y || symmetry == SYMMETRY_XY || \n\t\tsymmetry == SYMMETRY_YR90 || SYMMETRY_XYR90;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nbool isPhysicalSymmetryR90(const Rsyn::PhysicalSymmetry symmetry) {\n\treturn symmetry == SYMMETRY_R90 || symmetry == SYMMETRY_XR90 || \n\t\tsymmetry == SYMMETRY_YR90 || SYMMETRY_XYR90;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalSiteClass getPhysicalSiteClass(const std::string & siteClass) {\n\tif (siteClass.compare(\"CORE\") == 0) return PhysicalSiteClass::CORE;\n\tif (siteClass.compare(\"PAD\") == 0) return PhysicalSiteClass::PAD;\n\n\treturn PhysicalSiteClass::INVALID_SITECLASS;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalSiteClass(const Rsyn::PhysicalSiteClass siteClass) {\n\tswitch (siteClass) {\n\t\tcase CORE: return \"CORE\";\n\t\t\tbreak;\n\t\tcase PAD: return \"PAD\";\n\t\t\tbreak;\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\nRsyn::PhysicalPinDirection getPhysicalPinDirection(const std::string &direction) {\n\tif (direction.compare(\"INPUT\") == 0) return PIN_INPUT;\n\tif (direction.compare(\"OUTPUT\") == 0) return PIN_OUTPUT;\n\n\treturn PIN_INVALID_DIRECTION;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalPinDirection(const Rsyn::PhysicalPinDirection pinDirection) {\n\tswitch (pinDirection) {\n\t\tcase PIN_INPUT: return \"INPUT\";\n\t\tcase PIN_OUTPUT: return \"OUTPUT\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\nRsyn::PhysicalPinGeometryClass getPhysicalPinGeometryClass(const std::string & geometryClass) {\n\tif (geometryClass.compare(\"NONE\") == 0) return PINGEOMETRYCLASS_NONE;\n\tif (geometryClass.compare(\"CORE\") == 0) return PINGEOMETRYCLASS_CORE;\n\tif (geometryClass.compare(\"BUMP\") == 0) return PINGEOMETRYCLASS_BUMP;\n\n\treturn PINGEOMETRYCLASS_INVALID;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalPinGeometryClass(const Rsyn::PhysicalPinGeometryClass geometryClass) {\n\tswitch (geometryClass) {\n\t\tcase PINGEOMETRYCLASS_NONE: return \"NONE\";\n\t\tcase PINGEOMETRYCLASS_CORE: return \"CORE\";\n\t\tcase PINGEOMETRYCLASS_BUMP: return \"BUMP\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::RegionType getPhysicalRegionType(const std::string & type) {\n\tif (type.compare(\"FENCE\") == 0) return RegionType::FENCE;\n\tif (type.compare(\"GUIDE\") == 0) return RegionType::GUIDE;\n\treturn RegionType::INVALID;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalRegionType(const Rsyn::RegionType type) {\n\tswitch (type) {\n\t\tcase RegionType::FENCE: return \"FENCE\";\n\t\tcase RegionType::GUIDE: return \"GUIDE\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalDesignMode getPhysicalDesignModeType(const std::string & type) {\n\tif (type.compare(\"ALL\") == 0) return PhysicalDesignMode::ALL;\n\tif (type.compare(\"CTS\") == 0) return PhysicalDesignMode::CTS;\n\tif (type.compare(\"FLOORPLANNING\") == 0) return PhysicalDesignMode::FLOORPLANNING;\n\tif (type.compare(\"PLACEMENT\") == 0) return PhysicalDesignMode::PLACEMENT;\n\tif (type.compare(\"ROUTING\") == 0) return PhysicalDesignMode::ROUTING;\n\treturn PhysicalDesignMode::INVALID;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalDesignModeType(const Rsyn::PhysicalDesignMode type) {\n\tswitch (type) {\n\t\tcase PhysicalDesignMode::ALL: return \"ALL\";\n\t\tcase PhysicalDesignMode::CTS: return \"CTS\";\n\t\tcase PhysicalDesignMode::FLOORPLANNING: return \"FLOORPLANNING\";\n\t\tcase PhysicalDesignMode::PLACEMENT: return \"PLACEMENT\";\n\t\tcase PhysicalDesignMode::ROUTING: return \"ROUTING\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\n//! Converts Physical Pin Use type from string to enum, respectively.\n\nRsyn::PhysicalPinUse getPhysicalPinUseType(const std::string & type) {\n\tif (type.compare(\"SIGNAL\") == 0) return PhysicalPinUse::PIN_USE_SIGNAL;\n\tif (type.compare(\"ANALOG\") == 0) return PhysicalPinUse::PIN_USE_ANALOG;\n\tif (type.compare(\"POWER\") == 0) return PhysicalPinUse::PIN_USE_POWER;\n\tif (type.compare(\"GROUND\") == 0) return PhysicalPinUse::PIN_USE_GROUND;\n\tif (type.compare(\"CLOCK\") == 0) return PhysicalPinUse::PIN_USE_CLOCK;\n\treturn PhysicalPinUse::PIN_INVALID_USE;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n//! Converts Physical Pin Use type from enum to string, respectively.\n\nstd::string getPhysicalPinUseType(const Rsyn::PhysicalPinUse type) {\n\tswitch (type) {\n\t\tcase PhysicalPinUse::PIN_USE_SIGNAL: return \"SIGNAL\";\n\t\tcase PhysicalPinUse::PIN_USE_ANALOG: return \"ANALOG\";\n\t\tcase PhysicalPinUse::PIN_USE_POWER: return \"POWER\";\n\t\tcase PhysicalPinUse::PIN_USE_GROUND: return \"GROUND\";\n\t\tcase PhysicalPinUse::PIN_USE_CLOCK: return \"CLOCK\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalTrackDirection getPhysicalTrackDirectionDEF(const std::string & type) {\n\tif (type.compare(\"X\") == 0) return Rsyn::PhysicalTrackDirection::TRACK_VERTICAL;\n\tif (type.compare(\"Y\") == 0) return Rsyn::PhysicalTrackDirection::TRACK_HORIZONTAL;\n\treturn Rsyn::PhysicalTrackDirection::INVALID_PHY_TRACK_DIRECTION;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalTrackDirectionDEF(const Rsyn::PhysicalTrackDirection type) {\n\tswitch (type) {\n\t\tcase PhysicalTrackDirection::TRACK_VERTICAL: return \"X\";\n\t\tcase PhysicalTrackDirection::TRACK_HORIZONTAL: return \"Y\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalTrackDirection(const Rsyn::PhysicalTrackDirection type) {\n\tswitch (type) {\n\t\tcase PhysicalTrackDirection::TRACK_VERTICAL: return \"HORIZONTAL\";\n\t\tcase PhysicalTrackDirection::TRACK_HORIZONTAL: return \"VERTICAL\";\n\t\tdefault: return Rsyn::getPhysicalInvalidName();\n\t} // end switch \n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalGeneratedNamePrefix() {\n\treturn GEN_NAME;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalInvalidPrefix() {\n\treturn INVALID_NAME;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalInvalidName() {\n\treturn INVALID_NAME;\n} // end method \n\n// -----------------------------------------------------------------------------\n\nstd::string getPhysicalNullName() {\n\treturn NULL_PHY_NAME;\n} // end method \n\n// -----------------------------------------------------------------------------\n\n} // end namespace \n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/util/PhysicalTransform.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#include \"PhysicalTransform.h\"\n\nnamespace Rsyn {\nconst DBU PhysicalTransform::TRANSFORMATION_MATRIXES[NUM_PHY_ORIENTATION][2][2] = {\n\t// NORTH (R0)\n\t{{ 1,  0},             // | cos(0)  sin(0)|\n\t { 0,  1}},            // |-sin(0)  cos(0)|\n\n\t// SOUTH (R180)\n\t{{-1,  0},             // | cos(-180)  sin(-180)|\n\t { 0, -1}},            // |-sin(-180)  cos(-180)|\n\n\t// WEST (R90)\n\t{{ 0, -1},             // | cos(-90)  sin(-90)|\n\t { 1,  0}},            // |-sin(-90)  cos(-90)|\n\n\t// EAST (R270)\n\t{{ 0,  1},             // | cos(-270)  sin(-270)|\n\t {-1,  0}},            // |-sin(-270)  cos(-270)|\n\n\t// FLIPPED NORTH (MY)\n\t{{-1,  0},             // |-1  0|\n\t { 0,  1}},            // | 0  1|\n\n\t// FLIPPED SOUTH (MX)\n\t{{ 1,  0},             // |1   0|\n\t { 0, -1}},            // |0  -1|\n\n\t// FLIPPED WEST (MX90)\n\t{{ 0,  1},             // |1   0| | cos(90)  sin(90)|\n\t { 1,  0}},            // |0  -1| |-sin(90)  cos(90)|\n\n\t// FLIPPED EAST (MY90)\n\t{{ 0, -1},             // |-1  0| | cos(90)  sin(90)|\n\t {-1,  0}}             // | 0  1| |-sin(90)  cos(90)|\n}; // end array\n\n\nconst DBU PhysicalTransform::TRANSLATION_MATRIXES[NUM_PHY_ORIENTATION][2][2] = {\n\t// NORTH (R0)\n\t{{ 0,  0},             // 0\n\t { 0,  0}},            // 0\n\n\t// SOUTH (R180)\n\t{{ 1,  0},             // w\n\t { 0,  1}},            // h\n\n\t// WEST (R90)\n\t{{ 0,  1},             // h\n\t { 0,  0}},            // 0\n\n\t// EAST (R270)\n\t{{ 0,  0},             // 0\n\t { 1,  0}},            // w\n\n\t// FLIPPED NORTH (MY)\n\t{{ 1,  0},             // w\n\t { 0,  0}},            // 0\n\n\t// FLIPPED SOUTH (MX)\n\t{{ 0,  0},             // 0\n\t { 0,  1}},            // h\n\n\t// FLIPPED WEST (MX90)\n\t{{ 0,  0},             // 0\n\t { 0,  0}},            // 0\n\n\t// FLIPPED EAST (MY90)\n\t{{ 0,  1},             // h\n\t { 1,  0}}             // w\n}; // end array\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/phy/util/PhysicalTransform.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PHYSICAL_TRANSFORMATION_H\n#define RSYN_PHYSICAL_TRANSFORMATION_H\n\n#include \"rsyn/core/RsynTypes.h\"\n#include \"rsyn/util/dbu.h\"\n#include \"rsyn/util/Bounds.h\"\n\n#include <Rsyn/Polygon>\n\nnamespace Rsyn {\n\nclass PhysicalTransform {\npublic:\n\n\tPhysicalTransform() : clsOrientation(ORIENTATION_INVALID) {}\n\n\t//! @brief Creates a transform with origin at (0, 0).\n\t//! Example of Use: Transform port geometries.\n\tPhysicalTransform(const PhysicalOrientation orientation) : clsBounds(0, 0, 0, 0), clsOrientation(orientation) {}\n\t\n\t//! @brief Creates a transform with origin at (origin.x, origin.y).\n\tPhysicalTransform(const DBUxy origin, const PhysicalOrientation orientation) : clsBounds(origin.x, origin.y, 0, 0), clsOrientation(orientation) {}\n\n\t//! @briief Creates a transform with origin at the lower-left point of the\n\t//! bounds with the necessary translation, obtained from the bounds size, to\n\t//! keep the lower-left position of the transformed bounds at the same\n\t//! position of the lower-left of the original bounds.\n\t//! Example of Use: Handle cell transformation where one expects that the\n\t//! cell position (lower-left) to be kept at the same position after the\n\t//! transformation. For instance, if one is flipping the boundary of a cell\n\t//! at (0, 0), the flipped cell boundary should still be at (0, 0) after the\n\t//! transformation.\n\tPhysicalTransform(const Bounds bounds, const PhysicalOrientation orientation) : clsBounds(bounds), clsOrientation(orientation) {}\n\n\tDBUxy apply(const DBUxy &point) const {\n\t\tconst DBU &x = point.x - clsBounds.getX();\n\t\tconst DBU &y = point.y - clsBounds.getY();\n\t\tconst DBU &w = clsBounds.getWidth();\n\t\tconst DBU &h = clsBounds.getHeight();\n\t\tconst PhysicalOrientation &o =  clsOrientation == ORIENTATION_INVALID?\n\t\t\tORIENTATION_N : clsOrientation;\n\n\t\t// Compute transformation.\n\t\tconst DBU (&M)[2][2] = TRANSFORMATION_MATRIXES[o];\n\t\tconst DBU mx = (x*M[0][0]) + (y*M[0][1]);\n\t\tconst DBU my = (x*M[1][0]) + (y*M[1][1]);\n\n\t\t// Compute translation.\n\t\tconst DBU (&T)[2][2] = TRANSLATION_MATRIXES[o];\n\t\tconst DBU tx = (w*T[0][0]) + (h*T[0][1]);\n\t\tconst DBU ty = (w*T[1][0]) + (h*T[1][1]);\n\n\t\t// Compute transformed point.\n\t\treturn DBUxy(mx, my) + DBUxy(tx, ty) + clsBounds.getLower();\n\t} // end method\n\n\tDBUxy apply(const DBU &x, const DBU &y) const {\n\t\treturn apply(DBUxy(x, y));\n\t} // end method\n\n\tBounds apply(const Bounds &bounds) const {\n\t\tconst DBUxy p0 = apply(bounds.getLower());\n\t\tconst DBUxy p1 = apply(bounds.getUpper());\n\t\treturn Bounds(min(p0, p1), max(p0, p1));\n\t} // end method\n\n\tPolygon apply(const Polygon &polygon) const {\n\t\tPolygon transformedPolygon;\n\t\tfor (const Rsyn::Point &point : polygon.allPoints()) {\n\t\t\ttransformedPolygon.addPoint(apply(point));\n\t\t} // end for\n\t\treturn transformedPolygon;\n\t} // end method\n\n\tBounds getBounds() const {return clsBounds;}\n\tPhysicalOrientation getOrientation() const {return clsOrientation;}\n\n\tvoid setBounds(const Bounds &bounds) {clsBounds = bounds;}\n\tvoid setOrientation(const PhysicalOrientation &orientation) {clsOrientation = orientation;}\n\nprivate:\n\n\tBounds clsBounds;\n\tPhysicalOrientation clsOrientation;\n\n\tstatic const DBU TRANSFORMATION_MATRIXES[NUM_PHY_ORIENTATION][2][2];\n\tstatic const DBU TRANSLATION_MATRIXES[NUM_PHY_ORIENTATION][2][2];\n}; // end class\n\n} // end namespace\n\n#endif /* TRANSFORMATION_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/util/PhysicalTypes.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   PhysicalTypes.h\n * Author: jucemar\n *\n * Created on 29 de Outubro de 2015, 13:29\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALTYPES_H\n#define PHYSICALDESIGN_PHYSICALTYPES_H\n\n#include <cstdint>\n\n\n//! @file PhysicalTypes.h \n//! @brief This file aggregates all Enum definitions for Rsyn::PhysicalDesign.\n\nnamespace Rsyn {\n\n//! @brief Enum type associated to the Database Units of the LEF and DEF resolutions.\n\nenum DBUType : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control. */\n\tINVALID_DBU = -1,\n\t/*! \\brief Database Units (DBU) defined on LEF technology Library. */\n\tLIBRARY_DBU = 0,\n\t/*! \\brief Database Units (DBU) defined on DEF.  */\n\tDESIGN_DBU = 1,\n\t/*! \\brief LEF_DBU = DEF_DBU * DEF_MULT, e.g. 2000 = 1000 x 2. \n\t * LEF/DEF rules allow only integer multiple between LEF and DEF DBU resolutions.*/\n\tMULT_FACTOR_DBU = 2,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_DBU = 3\n}; // end enum \n\n// -----------------------------------------------------------------------------\n\n//! @brief Enum type associated to the Rsyn::PhysicalInstance.\n\nenum PhysicalType : std::int8_t {\n\t//! @brief Only used for Rsyn internal control.\n\tINVALID_PHYSICAL_TYPE = -1,\n\t//! @brief A Rsyn::PhysicalInstance is defined as fixed.\n\tPHYSICAL_FIXED = 0,\n\t//! @brief A Rsyn::PhysicalInstance is defined as movable.\n\tPHYSICAL_MOVABLE = 1,\n\t//! @brief A Rsyn::PhysicalInstance is defined as block.\n\tPHYSICAL_BLOCK = 2,\n\t//! @brief A Rsyn::PhysicalInstance is defined as port.\n\tPHYSICAL_PORT = 3,\n\t//! @brief A Rsyn::PhysicalInstance is defined as fixed bounds.\n\tPHYSICAL_FIXEDBOUNDS = 4,\n\t//! @brief A Rsyn::PhysicalInstance is defined as placeable.\n\tPHYSICAL_PLACEABLE = 5,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_PHYSICAL_TYPES = 6\n}; // end enum \n\n// -----------------------------------------------------------------------------\n\n//! @brief Layer type. \n\nenum PhysicalLayerType : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tINVALID_PHY_LAYER_TYPE = -1,\n\t//! @brief Layer is defined as Routing type.\n\tROUTING = 0,\n\t//! @brief Layer is defined as cut type.\n\tCUT = 1,\n\t//! @brief Layer is defined as overlap type.\n\tOVERLAP = 2,\n\t//! @brief Layer is defined as master slice type . They are typically polysilicon. \n\tMASTERSLICE = 3,\n\t//! @brief Layer is defined as implant type.\n\tIMPLANT = 4,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_PHY_LAYER = 5\n};\n\n\nenum PhysicalViaLayerType : std::int8_t {\n\tINVALID_VIA_LAYER_TYPE = -1,\n\t\n\tBOTTOM_VIA_LAYER = 0,\n\tCUT_VIA_LAYER = 1,\n\tTOP_VIA_LAYER = 2,\n\n\tNUM_VIA_LAYERS = 3\n}; // end enum \n\nenum ViaType : std::int8_t {\n\tINVALID_VIA_TYPE = -1,\n\tVIA_RULE_TYPE = 0,\n\tVIA_GEOMETRY_TYPE = 1,\n\tNUM_VIA_TYPES = 2\n}; // end enum \n\nenum ViaLevel : std::int8_t {\n\tINVALID_VIA_LEVEL = -1,\n\tBOTTOM_VIA_LEVEL = 0,\n\tTOP_VIA_LEVEL = 1,\n\tNUM_VIA_LEVELS = 2\n}; // end enum \n\nenum ViaRange : std::int8_t {\n\tINVALID_VIA_RANGE = -1,\n\tVIA_RANGE_MIN = 0,\n\tVIA_RANGE_MAX = 1,\n\tNUM_VIA_RANGES = 2\n}; // end enum \n\n//! @brief Layer direction. \n\nenum PhysicalLayerDirection : std::int8_t {\n\tUNKNOWN_PREFERRED_DIRECTION = -1,\n\t//! @brief Layer preferred direction is defined as horizontal.\n\tHORIZONTAL = 0,\n\t//! @brief Layer preference direction is defined as vertical.\n\tVERTICAL = 1,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_PREFERRED_DIRECTIONS = 2\n};\n\n// -----------------------------------------------------------------------------\n\nenum PhysicalTrackDirection : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tINVALID_PHY_TRACK_DIRECTION = -1,\n\t//! @brief track direction is defined as vertical.\n\t//! TRACK_VERTICAL is equal to X direction defined in DEF file.\n\tTRACK_VERTICAL = 0,\n\t//! @brief track direction is defined as horizontal.\n\t//! TRACK_HORIZONTAL is equal to Y direction defined in DEF file.\n\tTRACK_HORIZONTAL = 1,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_PHY_TRACK_DIRECTION = 2\n};\n\n// -----------------------------------------------------------------------------\n\n//! @brief Class types of the sites.\n\nenum PhysicalSiteClass : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tINVALID_SITECLASS = -1,\n\t//! @brief The site is defined as PAD type. Sites are typically used in rows. \n\tPAD = 0,\n\t//! @brief The site is defined as Core type. Sites are typically used in rows. \n\tCORE = 1,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_PHY_SITECLASS = 2\n};\n\n// -----------------------------------------------------------------------------\n\n//! @brief Pin direction\n\nenum PhysicalPinDirection : std::int8_t {\n\t//! @brief Only used for Rsyn internal control.\n\tPIN_INVALID_DIRECTION = -1,\n\t//! @brief Pin direction is input. \n\tPIN_INPUT = 0,\n\t//! @brief Pin direction is output. \n\tPIN_OUTPUT = 1,\n\t//! @brief Only used for Rsyn internal control.\n\tNUM_PHY_PIN_DIRECTION = 2\n}; // end enum \n\n// -----------------------------------------------------------------------------\n\n//! @brief Pin use type\n\nenum PhysicalPinUse : std::int8_t {\n\t//! @brief Only used for Rsyn internal control.\n\tPIN_INVALID_USE = -1,\n\t//! @brief Pin use is signal type. \n\tPIN_USE_SIGNAL = 0,\n\t//! @brief Pin use is analog type.\n\tPIN_USE_ANALOG = 1,\n\t//! @brief Pin use is power type.\n\tPIN_USE_POWER = 2,\n\t//! @brief Pin use is ground type.\n\tPIN_USE_GROUND = 3,\n\t//! @brief Pin use is clock type.\n\tPIN_USE_CLOCK = 4,\n\t//! @brief Only used for Rsyn internal control.\n\tNUM_PHY_PIN_USE = 5\n}; // end enum \n\n// -----------------------------------------------------------------------------\n\n//! @brief  The class type of macros.\n\nenum PhysicalMacroClass : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tMACRO_INVALID_CLASS = -1,\n\t//! @brief Macro is Cover class.\n\tMACRO_COVER = 0,\n\t//! @brief Macro is Ring class.\n\tMACRO_RING = 1,\n\t//! @brief  Macro is Block class. It may have a subtype of PhysicalMacroBlockClass\n\tMACRO_BLOCK = 2,\n\t//! @brief Macro is Pad class.\n\tMACRO_PAD = 3,\n\t//! @brief Macro is Core class.\n\tMACRO_CORE = 4,\n\t//! @brief Macro is Endcap class.\n\tMACRO_ENDCAP = 5,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_PHY_MACRO_CLASS = 6\n};\n\n// -----------------------------------------------------------------------------\n\n//! @brief The subtype of MACRO_BLOCK type from PhysicalMacroClass.\n\nenum PhysicalMacroBlockClass : std::int8_t {\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tMACRO_INVALID_BLOCK_CLASS = -1,\n\t//! @brief The Block is defined as black block.\n\tMACRO_BLOCK_BLACKBOX = 0,\n\t//! @brief The Block is defined as soft block.\n\tMACRO_BLOCK_SOFT = 1,\n\t/*! \\brief Only used for Rsyn internal control.*/\n\tNUM_MACRO_BLOCK_CLASS = 2\n};\n\n// -----------------------------------------------------------------------------\n\n//! @brief Symmetry based on Cartesian coordinate system\n//! @details X and Y - allows flips around axis, ROT90 - allows any of \n//!        rotations by 0, 90, 180 or 270 degrees.\n//!\t   Source: http://vlsicad.ucsd.edu/GSRC/bookshelf/Slots/Fundamental/HGraph/\n//! @todo ROT90\n\nenum PhysicalSymmetry : std::int8_t {\n\t//! @brief Only used for Rsyn internal control.\n\tSYMMETRY_INVALID = -1,\n\t//! @brief Defines the symmetry in the abscissa (X).\n\tSYMMETRY_X = 0,\n\t//! @brief Defines the symmetry in the ordinate (Y).\n\tSYMMETRY_Y = 1,\n\t//! @brief Defines the symmetry 90 degrees rotation.\n\tSYMMETRY_R90 = 2,\n\t//! @brief Defines the symmetry in the abscissa (X) and ordinate (Y).\n\tSYMMETRY_XY = 3,\n\t//! @brief Defines the symmetry in the abscissa (X) and 90 degrees rotation.\n\tSYMMETRY_XR90 = 4,\n\t//! @brief Defines the symmetry in the ordinate (Y) and 90 degrees rotation.\n\tSYMMETRY_YR90 = 5,\n\t//! @brief Defines the symmetry in the abscissa (X), ordinate (Y) and 90 degrees rotation.\n\tSYMMETRY_XYR90 = 6,\n\t//! @brief Only used for Rsyn internal control.\n\tNUM_PHY_SYMMETRY = 7\n}; // end enum\n\n// -----------------------------------------------------------------------------\n\n//! @brief Class type for the Pin geometry object. \n\nenum PhysicalPinGeometryClass : std::int8_t {\n\t//! @brief Only used for Rsyn internal control.\n\tPINGEOMETRYCLASS_INVALID = -1,\n\t//! @brief A pin geometry has none class defined. It is the default geometry class type.\n\tPINGEOMETRYCLASS_NONE = 0,\n\t//! @brief A pin geometry has Core class defined. \n\tPINGEOMETRYCLASS_CORE = 1,\n\t//! @brief A pin geometry has Bump class defined. \n\tPINGEOMETRYCLASS_BUMP = 2,\n\t//! @brief Only used for Rsyn internal control.\n\tNUM_PINGEOMETRYCLASS = 3\n}; // end enum \n\n// -----------------------------------------------------------------------------\n\n//! @brief Region type for the Region object.\n\nenum class RegionType : std::int8_t {\n\tINVALID = -1,\n\tFENCE = 0,\n\tGUIDE = 1\n}; // end enum class \n\n// -----------------------------------------------------------------------------\n\n//! @brief Layout may be upload in physical design only for Floorplanning,\n//! Placement, CTS or Routing. It avoids loading unnecessary data.\n\nenum class PhysicalDesignMode : std::int8_t {\n\tINVALID = -1,\n\tALL = 0,\n\tFLOORPLANNING = 1,\n\tPLACEMENT = 2,\n\tCTS = 3,\n\tROUTING = 4,\n}; // end enum class \n\n// -----------------------------------------------------------------------------\n\n\n//! @brief Layout may be upload in physical design only for Floorplanning,\n//! Placement, CTS or Routing. It avoids loading unnecessary data.\n\nenum class PhysicalGCellDirection : std::int8_t {\n\tINVALID = -1,\n\tVERTICAL = 0,\n\tHORIZONTAL = 1\n}; // end enum class \n\n// -----------------------------------------------------------------------------\n\n\nenum PhysicalEventType {\n\tPHYSICAL_EVENT_DESTRUCTION,\n\tPHYSICAL_EVENT_POST_NET_ROUTING_CHANGE,\n\n\tNUM_PHYSICAL_EVENTS\n}; // end enum\n\n} // end namespace \n\n#endif /* PHYSICALDESIGN_PHYSICALTYPES_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/phy/util/PhysicalUtil.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef PHYSICALDESIGN_PHYSICALUTIL_H\n#define PHYSICALDESIGN_PHYSICALUTIL_H\n\n#include <string>\n\n#include \"rsyn/core/RsynTypes.h\"\n#include \"rsyn/phy/util/PhysicalTypes.h\"\n\nnamespace Rsyn {\n\n//! @file PhysicalUtil.h \n//! @brief This file aggregates conversion methods from/to Enum to/from string for Rsyn::PhysicalDesign.\n\n//! Converts Layer type from string to enum, respectively.\nRsyn::PhysicalLayerType getPhysicalLayerType(const std::string &type);\n\n//! Converts Layer type from enum to string, respectively.\nstd::string getPhysicalLayerType(const Rsyn::PhysicalLayerType type);\n\n//! Converts Layer direction from string to enum, respectively.\nRsyn::PhysicalLayerDirection getPhysicalLayerDirection(const std::string &direction);\n\n//! Converts Layer direction from enum to string, respectively.\nstd::string getPhysicalLayerDirection(const Rsyn::PhysicalLayerDirection direction);\n\n//! Converts Orientation from string to enum, respectively.\nRsyn::PhysicalOrientation getPhysicalOrientation(const std::string &orientation);\n\n//! Converts Orientation from enum to string, respectively.\nstd::string getPhysicalOrientation(const Rsyn::PhysicalOrientation orientation);\n\n//! Converts Macro Class from string to enum, respectively.\nRsyn::PhysicalMacroClass getPhysicalMacroClass(const std::string & macroClass);\n\n//! Converts Macro Class from enum to string, respectively.\nstd::string getPhysicalMacroClass(const Rsyn::PhysicalMacroClass macroClass);\n\n//! Converts Symmetry from string to enum, respectively.\nRsyn::PhysicalSymmetry getPhysicalSymmetry(const std::string &rowSymmetry);\n\n//! Converts Symmetry from enum to string, respectively.\nstd::string getPhysicalSymmetry(const Rsyn::PhysicalSymmetry rowSymmetry);\n\n// ! @brief check if PhysicalSymmetry has symmetry to X.\nbool isPhysicalSymmetryX(const Rsyn::PhysicalSymmetry symmetry);\n\n// ! @brief check if PhysicalSymmetry has symmetry to Y.\nbool isPhysicalSymmetryY(const Rsyn::PhysicalSymmetry symmetry);\n\n// ! @brief check if PhysicalSymmetry has symmetry to XR90.\nbool isPhysicalSymmetryR90(const Rsyn::PhysicalSymmetry symmetry);\n\n//! Converts Site Class from string to enum, respectively.\nRsyn::PhysicalSiteClass getPhysicalSiteClass(const std::string & siteClass);\n\n//! Converts Site Class from enum to string, respectively.\nstd::string getPhysicalSiteClass(const Rsyn::PhysicalSiteClass siteClass);\n\n//! Converts Pin Direction from string to enum, respectively.\nRsyn::PhysicalPinDirection getPhysicalPinDirection(const std::string &direction);\n\n//! Converts Pin Direction from enum to string, respectively.\nstd::string getPhysicalPinDirection(const Rsyn::PhysicalPinDirection pinDirection);\n\n//! Converts Pin Geometry Class from string to enum, respectively.\nRsyn::PhysicalPinGeometryClass getPhysicalPinGeometryClass(const std::string & geometryClass);\n\n//! Converts Pin Port Class from enum to string, respectively.\nstd::string getPhysicalPinGeometryClass(const Rsyn::PhysicalPinGeometryClass geometryClass);\n\n//! Converts Region type from string to enum, respectively.\nRsyn::RegionType getPhysicalRegionType(const std::string & type);\n\n//! Converts Region type from enum to string, respectively.\nstd::string getPhysicalRegionType(const Rsyn::RegionType type);\n\n//! Converts Physical Design Mode type from string to enum, respectively.\nRsyn::PhysicalDesignMode getPhysicalDesignModeType(const std::string & type);\n\n//! Converts Physical Design Mode type from enum to string, respectively.\nstd::string getPhysicalDesignModeType(const Rsyn::PhysicalDesignMode type);\n\n//! Converts Physical Pin Use type from string to enum, respectively.\nRsyn::PhysicalPinUse getPhysicalPinUseType(const std::string & type);\n\n//! Converts Physical Pin Use type from enum to string, respectively.\nstd::string getPhysicalPinUseType(const Rsyn::PhysicalPinUse type);\n\nRsyn::PhysicalTrackDirection getPhysicalTrackDirectionDEF(const std::string & type);\n\nstd::string getPhysicalTrackDirectionDEF(const Rsyn::PhysicalTrackDirection type);\n\nstd::string getPhysicalTrackDirection(const Rsyn::PhysicalTrackDirection type);\n\n\n//! Returns a prefix key word to generated names.\nstd::string getPhysicalGeneratedNamePrefix();\n\n//! Returns a prefix key word to invalid prefix.\nstd::string getPhysicalInvalidPrefix();\n\n//! Returns a prefix key word to invalid name.\nstd::string getPhysicalInvalidName();\n\n//! Returns a prefix key word to null name.\nstd::string getPhysicalNullName();\n\n\n\n// *****************************************************************************\n// *\n// *         Overloading operator<<\n// *\n// *\n// *****************************************************************************\n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Symmetry.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalSymmetry symmetry) {\n\treturn out << getPhysicalSymmetry(symmetry);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Layer type.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalLayerType layerType) {\n\treturn out << getPhysicalLayerType(layerType);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Layer Direction.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalLayerDirection direction) {\n\treturn out << getPhysicalLayerDirection(direction);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Orientation.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalOrientation orientation) {\n\treturn out << getPhysicalOrientation(orientation);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Macro Class.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalMacroClass macroClass) {\n\treturn out << getPhysicalMacroClass(macroClass);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Site Class.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalSiteClass siteClass) {\n\treturn out << getPhysicalSiteClass(siteClass);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Pin Direction.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalPinDirection pinDirection) {\n\treturn out << getPhysicalPinDirection(pinDirection);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Pin Port Class.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalPinGeometryClass pinPortClass) {\n\treturn out << getPhysicalPinGeometryClass(pinPortClass);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Region type.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::RegionType type) {\n\treturn out << getPhysicalRegionType(type);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n\n//! Overloads operator << to Physical Pin Use type.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalPinUse type) {\n\treturn out << getPhysicalPinUseType(type);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n//! Overloads operator << to Physical Track direction.\n\ninline std::ostream& operator<<(std::ostream& out, const Rsyn::PhysicalTrackDirection type) {\n\treturn out << getPhysicalTrackDirection(type);\n} // end operator overloading \n\n// -----------------------------------------------------------------------------\n\n} // end namespace\n\n#endif /* PHYSICALDESIGN_PHYSICALUTIL_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/session/Reader.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   Reader.h\n * Author: jucemar\n *\n * Created on 18 de Fevereiro de 2017, 08:20\n */\n\n#ifndef RSYN_READER_H\n#define RSYN_READER_H\n\n#include \"rsyn/util/Json.h\"\n#include \"rsyn/io/reader/PopulateRsyn.h\"\n\nnamespace Rsyn {\n\nclass Session;\n\n\nclass Reader : public PopulateRsyn {\npublic:\n\tvirtual bool load(const Rsyn::Json &params) = 0;\n}; // end class\n\n} // end namespace\n\n\n#endif /* RSYN_READER_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/session/Service.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_SERVICE_H\n#define RSYN_SERVICE_H\n\n#include \"rsyn/util/Json.h\"\n\nnamespace Rsyn {\n\nclass Session;\n\n\nenum ServiceRequestType {\n\tSERVICE_OPTIONAL,\n\tSERVICE_MANDATORY\n}; // end enum\n\nclass Service {\npublic:\n\tvirtual void start(const Rsyn::Json &params) = 0;\n\tvirtual void stop() = 0;\n}; // end class\n\n} // end namespace\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/session/Session.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#include <thread>\n#include <iosfwd>\n#include <mutex>\n#include <boost/filesystem.hpp>\n\n#include \"Session.h\"\n\n#include \"rsyn/util/Json.h\"\n#include \"rsyn/phy/PhysicalService.h\"\n#include \"rsyn/util/Environment.h\"\n\nnamespace Rsyn {\n\nstatic Startup initEngine([]{\n\t// This will ensure the engine singleton gets initialized when the program\n\t// starts.\n});\n\n// -----------------------------------------------------------------------------\n\nSessionData * Session::sessionData = nullptr;\n\n// -----------------------------------------------------------------------------\n\nvoid Session::init() {\n\tif (checkInitialized()) return;\n\n\tstd::setlocale(LC_ALL, \"en_US.UTF-8\");\n\n\tsessionData = new SessionData();\n\n\t// TODO: hard coded\n\tsessionData->clsInstallationPath = \"../../rsyn/install\";\n\n\t// Register services\n\tregisterServices();\n\n\t// Register readers.\n\tregisterReaders();\n\t\n\t// Create design.\n\tsessionData->clsDesign.create(\"__Root_Design__\");\n\n\t// Create library\n\tsessionData->clsLibrary = Library(new LibraryData);\n\tsessionData->clsLibrary->designData = sessionData->clsDesign.data;\n\n\tcheckInitialized(true);\n} // end constructor\n\n// -----------------------------------------------------------------------------\n\nRsyn::Design Session::getDesign() {\n\treturn sessionData->clsDesign;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::Library Session::getLibrary() {\n\treturn sessionData->clsLibrary;\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::Module Session::getTopModule() {\n\treturn getDesign().getTopModule();\n} // end method\n\n// -----------------------------------------------------------------------------\n\nRsyn::PhysicalDesign Session::getPhysicalDesign() {\n\tif (isServiceRunning(\"rsyn.physical\")) {\n\t\tPhysicalService *service = getService(\"rsyn.physical\");\n\t\treturn service->getPhysicalDesign();\n\t} else {\n\t\treturn nullptr;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nstd::string Session::mergePathAndFileName(const std::string &path, const std::string &fileName) {\n\tconst char separator = boost::filesystem::path::preferred_separator;\n\tif (!path.empty() &&  (path.back() != separator && path.back() != '/')) {\n\t\treturn path + separator + fileName;\n\t} else {\n\t\treturn path + fileName;\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nstd::string Session::findFile(const std::string fileName, const std::string extraPath) {\n\t// Check if the file exists without any path.\n\tif (boost::filesystem::exists(fileName)) {\n\t\treturn fileName;\n\t} // end if\n\n\t// Check if the file exists in the extra path.\n\tif (!extraPath.empty()) {\n\t\tconst std::string fullFileName = mergePathAndFileName(extraPath, fileName);\n\t\tif (boost::filesystem::exists(fullFileName)) {\n\t\t\treturn fullFileName;\n\t\t} // end if\n\t} // end if\n\n\t// Check if the file exists in the paths.\n\tfor (const std::string &path : sessionData->clsPaths) {\n\t\tconst std::string fullFileName = mergePathAndFileName(path, fileName);\n\t\tif (boost::filesystem::exists(fullFileName)) {\n\t\t\treturn fullFileName;\n\t\t} // end if\n\t} // end for\n\n\t// File not found.\n\treturn \"\";\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\nSession::runReader(const std::string &name, const Rsyn::Json &params) {\n\tauto it = sessionData->clsReaders.find(name);\n\tif (it == sessionData->clsReaders.end()) {\n\t\tstd::cout << \"ERROR: Reader '\" << name << \"' was not \"\n\t\t\t\t\"registered.\\n\";\n\t} else {\n\t\tstd::unique_ptr<Reader> reader(it->second());\n\t\treader->load(params);\n\t} // end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nbool\nSession::startService(const std::string &name, const Rsyn::Json &params, const bool dontErrorOut) {\n\tauto it = sessionData->clsServiceInstanciationFunctions.find(name);\n\tif (it == sessionData->clsServiceInstanciationFunctions.end()) {\n\t\tif (!dontErrorOut) {\n\t\t\tstd::cout << \"ERROR: Service '\" << name << \"' was not \"\n\t\t\t\t\t\"registered.\\n\";\n\t\t\tstd::exit(1);\n\t\t} // end if\n\t\treturn false;\n\t} else {\n\t\tService * service = getServiceInternal(name);\n\t\tif (!service) {\n\t\t\tservice = it->second();\n\t\t\tservice->start(params);\n\t\t\tsessionData->clsRunningServices[name] = service;\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\tif (!dontErrorOut) {\n\t\t\t\tstd::cout << \"WARNING: Service '\" << name << \"' is already running.\\n\";\n\t\t\t} // end if\n\t\t\treturn false;\n\t\t} // end else\n\t} // end else\n} // end method\n\n\n} /* namespace Rsyn */\n"
  },
  {
    "path": "rsyn/src/rsyn/session/Session.h",
    "content": "    /* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_SESSION_H\n#define RSYN_SESSION_H\n\n#include <string>\n\n#include \"rsyn/session/Service.h\"\n#include \"rsyn/session/Reader.h\"\n\n#include \"rsyn/util/Json.h\"\n\n#include \"rsyn/core/Rsyn.h\"\n#include \"rsyn/util/Units.h\"\n\nnamespace Rsyn {\n\nclass PhysicalDesign;\n\ntypedef std::function<Service *()> ServiceInstantiatonFunction;\ntypedef std::function<Reader *()> ReaderInstantiatonFunction;\n\n////////////////////////////////////////////////////////////////////////////////\n// Session Data\n////////////////////////////////////////////////////////////////////////////////\n\nstruct SessionData {\n\t////////////////////////////////////////////////////////////////////////////\n\t// Session Variables\n\t////////////////////////////////////////////////////////////////////////////\n\t\n\tstd::map<std::string, Rsyn::Json> clsSessionVariables;\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Services\n\t////////////////////////////////////////////////////////////////////////////\n\t\n\t// Generic functions used to instantiate optimizers by name.\n\tstd::unordered_map<std::string, ServiceInstantiatonFunction> clsServiceInstanciationFunctions;\n\tstd::unordered_map<std::string, Service *> clsRunningServices;\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Loader\n\t////////////////////////////////////////////////////////////////////////////\n\t\n\t// Generic functions used to instantiate optimizers by name.\n\tstd::unordered_map<std::string, ReaderInstantiatonFunction> clsReaders;\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Design/Library\n\t////////////////////////////////////////////////////////////////////////////\n\n\tRsyn::Design clsDesign;\n\tRsyn::Library clsLibrary;\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Configuration\n\t////////////////////////////////////////////////////////////////////////////\n\tstd::string clsInstallationPath;\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Misc\n\t////////////////////////////////////////////////////////////////////////////\n\tstd::list<std::string> clsPaths;\n}; // end struct\n\n////////////////////////////////////////////////////////////////////////////////\n// Session Proxy\n////////////////////////////////////////////////////////////////////////////////\n\nclass Session : public Rsyn::Proxy<SessionData> {\npublic:\n\tSession() {\n\t\tdata = sessionData;\n\t};\n\t\n\tSession(std::nullptr_t) { \n\t\tdata = nullptr;\n\t}\n\t\n\tSession &operator=(const Session &other) {\n\t\tdata = other.data;\n\t\treturn *this;\n\t}\t\n\t\n\tstatic void init();\n\n\t//! @note To prevent \"static variable order initialization fiasco\", the\n\t//        static variable signaling that the engine was initialized is\n\t//        stored inside this function. In this way, we can guarantee it will\n\t//        be initialized to false before being used.\n\tstatic bool checkInitialized(const bool markAsInitialized = false) {\n\t\tstatic bool sessionInitialized = false;\n\t\tif (markAsInitialized)\n\t\t\tsessionInitialized = true;\n\t\treturn sessionInitialized;\n\t} // end method\n\nprivate:\n\n\tstatic SessionData * sessionData;\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Session Variables\n\t////////////////////////////////////////////////////////////////////////////\n\npublic:\n\n\tstatic void setSessionVariable(const std::string &name, const Rsyn::Json &value) {\n\t\tsessionData->clsSessionVariables[name] = value;\n\t} // end method\n\n\tstatic void unsetSessionVariable(const std::string &name) {\n\t\tsessionData->clsSessionVariables.erase(name);\n\t} // end method\n\n\tstatic const bool getSessionVariableAsBool(const std::string &name, const bool defaultValue = false) {\n\t\tauto it = sessionData->clsSessionVariables.find(name);\n\t\treturn (it != sessionData->clsSessionVariables.end())? it->second.get<bool>() : defaultValue;\n\t} // end method\n\n\tstatic const int getSessionVariableAsInteger(const std::string &name, const int defaultValue = 0) {\n\t\tauto it = sessionData->clsSessionVariables.find(name);\n\t\treturn (it != sessionData->clsSessionVariables.end())? it->second.get<int>() : defaultValue;\n\t} // end method\n\n\tstatic const float getSessionVariableAsFloat(const std::string &name, const float defaultValue = 0.0f) {\n\t\tauto it = sessionData->clsSessionVariables.find(name);\n\t\treturn (it != sessionData->clsSessionVariables.end())? it->second.get<float>() : defaultValue;\n\t} // end method\n\n\tstatic const std::string getSessionVariableAsString(const std::string &name, const std::string &defaultValue = \"\") {\n\t\tauto it = sessionData->clsSessionVariables.find(name);\n\t\treturn (it != sessionData->clsSessionVariables.end())? it->second.get<std::string>() : defaultValue;\n\t} // end method\n\n\tstatic const Rsyn::Json getSessionVariableAsJson(const std::string &name, const Rsyn::Json &defaultValue = {}) {\n\t\tauto it = sessionData->clsSessionVariables.find(name);\n\t\treturn (it != sessionData->clsSessionVariables.end())? it->second : defaultValue;\n\t} // end method\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Services\n\t////////////////////////////////////////////////////////////////////////////\n\n\t// Register services.\n\tstatic void registerServices();\n\npublic:\n\t\n\t// Helper class to allow seamless casting from a Service pointer to any type\n\t// which implements operator=(Service *) is is directly compatible.\n\t\n\tclass ServiceHandler {\n\tprivate:\n\t\tService *clsService;\n\t\t\n\tpublic:\n\t\tServiceHandler(Service *service) : clsService(service) {}\n\t\t\n\t\ttemplate<typename T>\n\t\toperator T *() {\n\t\t\tT * pointer = dynamic_cast<T *>(clsService);\n\t\t\tif (pointer != clsService) {\n\t\t\t\tstd::cout << \"ERROR: Trying to cast a service to the wrong type.\\n\";\n\t\t\t\tthrow Exception(\"Trying to cast a service to the wrong type.\");\n\t\t\t} // end if\n\t\t\treturn pointer;\n\t\t} // end operator\n\t}; // end class\n\t\t\n\t// Register a service.\n\ttemplate<typename T>\n\tstatic void registerService(const std::string &name) {\n\t\tauto it = sessionData->clsServiceInstanciationFunctions.find(name);\n\t\tif (it != sessionData->clsServiceInstanciationFunctions.end()) {\n\t\t\tstd::cout << \"ERROR: Service '\" << name << \"' was already \"\n\t\t\t\t\t\"registered.\\n\";\n\t\t\tstd::exit(1);\n\t\t} else {\n\t\t\tsessionData->clsServiceInstanciationFunctions[name] = []() -> Service *{\n\t\t\t\treturn new T();\n\t\t\t};\n\t\t} // end else\n\t} // end method\n\t\n\t// Start a service.\n\tstatic bool startService(const std::string &name, const Rsyn::Json &params = {}, const bool dontErrorOut = false);\n\t\n\t// Gets a running service.\n\tstatic ServiceHandler getService(const std::string &name,\n\t\t\tconst ServiceRequestType requestType = SERVICE_MANDATORY) {\n\t\tService *service = getServiceInternal(name);\n\t\tif (!service && (requestType == SERVICE_MANDATORY)) {\n\t\t\tstd::cout << \"ERROR: Service '\" << name << \"' was not started.\\n\";\n\t\t\tthrow Exception(\"ERROR: Service '\" + name + \"' was not started\");\n\t\t} // end if\n\t\treturn ServiceHandler(service);\n\t} // end method\n\n\t// Checks if a service is registered.\n\tstatic bool isServiceRegistered(const std::string &name) {\n\t\tauto it = sessionData->clsServiceInstanciationFunctions.find(name);\n\t\treturn  (it != sessionData->clsServiceInstanciationFunctions.end());\n\t} // end method\n\n\t// Checks if a service is running.\n\tstatic bool isServiceRunning(const std::string &name) {\n\t\treturn getServiceInternal(name) != nullptr;\n\t} // end method\n\t\nprivate:\n\t\n\tstatic Service * getServiceInternal(const std::string &name) {\n\t\tauto it = sessionData->clsRunningServices.find(name);\n\t\treturn it == sessionData->clsRunningServices.end()? nullptr : it->second;\n\t} // end method\n\n\tstatic void listService(std::ostream & out = std::cout) {\n\t\tout<<\"List of services \";\n\t\tout<<\"([R] -> Running, [S] -> Stopped):\\n\";\n\t\t// print only running services\n\t\tfor (std::pair<std::string, ServiceInstantiatonFunction> srv : sessionData->clsServiceInstanciationFunctions) {\n\t\t\tif (!isServiceRunning(srv.first))\n\t\t\t\tcontinue;\n\t\t\tout << \"\\t[R] \" << srv.first << \"\\n\";\n\t\t} // end for \n\t\t// print only stopped services \n\t\tfor (std::pair<std::string, ServiceInstantiatonFunction> srv : sessionData->clsServiceInstanciationFunctions) {\n\t\t\tif (isServiceRunning(srv.first))\n\t\t\t\tcontinue;\n\t\t\tout << \"\\t[S] \"<<srv.first << \"\\n\";\n\t\t} // end for \n\t\tout << \"--------------------------------------\\n\";\n\t} /// end method \n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Reader\n\t////////////////////////////////////////////////////////////////////////////\nprivate:\n\tstatic void listReader(std::ostream & out = std::cout) {\n\t\tout<<\"List of registered Readers:\\n\";\n\t\tfor(std::pair<std::string, ReaderInstantiatonFunction> reader : sessionData->clsReaders) {\n\t\t\tout<<\"\\t\"<<reader.first<<\"\\n\";\n\t\t} // end for \n\t\tout<<\"--------------------------------------\\n\";\n\t} /// end method\n\n\t// Register loader.\n\tstatic void registerReaders();\n\npublic:\n\t\t\n\t// Register a loader.\n\ttemplate<typename T>\n\tstatic void registerReader(const std::string &name) {\n\t\tauto it = sessionData->clsReaders.find(name);\n\t\tif (it != sessionData->clsReaders.end()) {\n\t\t\tstd::cout << \"ERROR: Reader '\" << name << \"' was already \"\n\t\t\t\t\t\"registered.\\n\";\n\t\t\tstd::exit(1);\n\t\t} else {\n\t\t\tsessionData->clsReaders[name] = []() -> Reader *{\n\t\t\t\treturn new T();\n\t\t\t};\n\t\t} // end else\n\t} // end method\n\t\n\t// Run an loader.\n\tstatic void runReader(const std::string &name, const Rsyn::Json &params = {});\n\t\n\t////////////////////////////////////////////////////////////////////////////\n\t// Misc\n\t////////////////////////////////////////////////////////////////////////////\n\n\tstatic Rsyn::Design getDesign();\n\tstatic Rsyn::Library getLibrary();\n\tstatic Rsyn::Module getTopModule();\n\tstatic Rsyn::PhysicalDesign getPhysicalDesign();\n\n\tstatic const std::string &getInstallationPath() { return sessionData->clsInstallationPath; }\n\n\t////////////////////////////////////////////////////////////////////////////\n\t// Utilities\n\t////////////////////////////////////////////////////////////////////////////\n\nprivate:\n\n\tstatic std::string mergePathAndFileName(const std::string &path, const std::string &fileName);\n\npublic:\n\n\t//! @brief Find a file in the current path. If found, returns its absolute\n\t//!        path, an empty string otherwise.\n\t//! @param extraPath can be used to specify an extra path location besides\n\t//!        the one stored internally in the current path list.\n\tstd::string findFile(const std::string fileName, const std::string extraPath = \"\");\n\t\n}; // end class\n\n////////////////////////////////////////////////////////////////////////////////\n// Startup\n////////////////////////////////////////////////////////////////////////////////\n\n// Helper class used to perform component initialization during the application\n// startup. Declare a startup object in a cpp file:\n//\n// Rsyn::Startup startup([]{\n//     Rsyn::Session::registerService(...);\n//     Rsyn::Session::registerMessage(...);\n// }); // end startup\n//\n// This will construct a global object that will be called during the\n// application initialization.\n\nclass Startup {\npublic:\n\tStartup(std::function<void()> f) {\n\t\tif (!Session::checkInitialized())\n\t\t\tSession::init();\n\t\tf();\n\t} // end constructor\n}; // end class\n\n} // end namespace\n\n#endif /* INFRA_ICCAD15_SESSION_H_ */\n"
  },
  {
    "path": "rsyn/src/rsyn/setup/reader.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/*\n * To change this license header, choose License Headers in Project Properties.\n * To change this template file, choose Tools | Templates\n * and open the template in the editor.\n */\n\n#include <Rsyn/Session>\n\n// Readers\n#include \"rsyn/io/reader/ISPD2018Reader.h\"\n\n// Registration\nnamespace Rsyn {\n\nvoid Session::registerReaders() {\n\tregisterReader<Rsyn::ISPD2018Reader>(\"ispd18\");\n\tregisterReader<Rsyn::ISPD2018Reader>(\"ispd19\"); // ispd19 files are the same from ispd18 contest\n} // end method\n} // end namespace\n"
  },
  {
    "path": "rsyn/src/rsyn/setup/service.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n// HOW-TO\n// To register a step, just include its .h below and add a call to\n// \"registerService<T>(name)\" where T is the service class name and name how\n// the service will be referred to.\n\n#include <Rsyn/Session>\n\n// Services\n#include \"rsyn/phy/PhysicalService.h\"\n#include \"rsyn/ispd18/RoutingGuide.h\"\n\n// Registration\nnamespace Rsyn {\nvoid Session::registerServices() {\n\tregisterService<Rsyn::PhysicalService>(\"rsyn.physical\");\n\tregisterService<Rsyn::RoutingGuide>(\"rsyn.routingGuide\");\n} // end method\n} // end namespace\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Array.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_MULTIDIMENSIONAL_ARRAY_H\n#define\tRSYN_MULTIDIMENSIONAL_ARRAY_H\n\n#include <vector>\n#include <string>\n#include <fstream>\n#include <algorithm>\n#include <array>\n\n// @todo make it generic to work with any number of dimensions\n\n// =============================================================================\n// Array2D\n// =============================================================================\n\ntemplate< class T >\nclass Array2D {\nprivate:\n\tstd::vector<T> clsElements;\n\n\tint clsNumCols;\n\tint clsNumRows;\n\npublic:\n\n\tArray2D() {\n\t\tclsNumCols = 0;\n\t\tclsNumRows = 0;\n\t} // end constructor\n\n\tvoid initialize( const int numCols, const int numRows ) {\n\t\tclsNumCols = numCols;\n\t\tclsNumRows = numRows;\n\t\tclsElements.clear();\n\t\tclsElements.resize(clsNumCols * clsNumRows);\n\t} // end method\n\n\tvoid initialize( const int numCols, const int numRows, const T value ) {\n\t\tclsNumCols = numCols;\n\t\tclsNumRows = numRows;\n\t\tclsElements.clear();\n\t\tclsElements.resize(clsNumCols * clsNumRows, value);\n\t} // end method\n\n\tvoid initialize( const int dimension ) {\n\t\tinitialize( dimension, dimension );\n\t} // end method\n\n\tvoid assign(const T value) {\n\t\tclsElements.assign(clsElements.size(), value);\n\t} // end method\n\n\t\t  T & operator()( const int col, const int row )       { return clsElements[ computeLinearIndex(col,row) ]; }\n\tconst T & operator()( const int col, const int row ) const { return clsElements[ computeLinearIndex(col,row) ]; }\n\n\t\t  T & operator()( const int linearIndex )       { return clsElements[ linearIndex ]; }\n\tconst T & operator()( const int linearIndex ) const { return clsElements[ linearIndex ]; }\n\n\tint getNumElements() const { return clsElements.size(); }\n\tint getNumCols() const { return clsNumCols; }\n\tint getNumRows() const { return clsNumRows; }\n\n\tint getCol( const int linearIndex ) const { return linearIndex % clsNumCols; }\n\tint getRow( const int linearIndex ) const { return linearIndex / clsNumCols; }\n\n\tint clampCol(const int col) const { return std::max(0, std::min(col, clsNumCols - 1)); }\n\tint clampRow(const int row) const { return std::max(0, std::min(row, clsNumRows - 1)); }\n\n\tbool isValidIndex(const int col, const int row) const {\n\t\treturn (col>=0 && col<clsNumCols) && (row>=0 && row<clsNumRows);\n\t} // end method\n\n\tbool isEmpty() const {return clsElements.empty();}\n\n\tint computeLinearIndex( const int col, const int row ) const {\n\t\treturn col + (row*clsNumCols);\n\t} // end method\n\n\tvoid gnuplotColorMap(const std::string &filename) const {\n\t\tstd::ofstream plotfile(filename.c_str());\n\t\tif (!plotfile)\n\t\t\treturn;\n\n\t\tplotfile << \"set term png\\n\";\n\t\tplotfile << \"set output \\\"\" << filename << \".png\\\"\\n\";\n\t\tplotfile << \"set autoscale fix\\n\";\n\t\tplotfile << \"\\n\";\n\t\tplotfile <<\n\t\t\t\"set palette defined ( 0 '#000090',\\\\\\n\"\n\t\t\t\"                      1 '#000fff',\\\\\\n\"\n\t\t\t\"                      2 '#0090ff',\\\\\\n\"\n\t\t\t\"                      3 '#0fffee',\\\\\\n\"\n\t\t\t\"                      4 '#90ff70',\\\\\\n\"\n\t\t\t\"                      5 '#ffee00',\\\\\\n\"\n\t\t\t\"                      6 '#ff7000',\\\\\\n\"\n\t\t\t\"                      7 '#ee0000',\\\\\\n\"\n\t\t\t\"                      8 '#7f0000')\\n\\n\"\n\t\t;\n\n\t\tplotfile << \"plot '-' matrix with image t ''\\n\";\n\n\t\tfor ( int row = 0; row < clsNumRows; row++ ) {\n\t\t\tfor ( int col = 0; col < clsNumCols; col++ ) {\n\t\t\t\tplotfile << (*this)(col,row) << \" \";\n\t\t\t} // end for\n\t\t\tplotfile << \"\\n\";\n\t\t} // end for\n\n\t\tplotfile.close();\n\t} // end method\n\n\tvoid gnuplot3DMap(const std::string &filename) const {\n\t\tstd::ofstream plotfile(filename.c_str());\n\n\t\tif (!plotfile)\n\t\t\treturn;\n\n\t\tplotfile << \"set style data lines\t\t\t\t\t\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"set pm3d\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"set view 15, 30, 1, 1\t\t\t\t\t\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"set xlabel \\\"Bin x\\\"\t\t\t\t\t\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"set ylabel \\\"Bin Y\\\"\t\t\t\t\t\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"set zlabel \\\"Utilization\\\" offset -4,0,0\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"set terminal epscairo enhanced color size 75in,50in font \\\"Arial,100\\\"\t\\n\"\n\t\t\t\t\t\"set output \\\"\" << filename << \".eps\t\t\t\t\t\t\t\t\t\\n\"\n\t\t\t\t\t\"splot \\\"-\\\" using 2:1:3 notitle\t\t\t\t\t\t\t\t\t\t\\n\\n\";\n\n\t\tfor ( int row = 0; row < clsNumRows; row++ ) {\n\t\t\tfor ( int col = 0; col < clsNumCols; col++ ) {\n\t\t\t\tplotfile << row << \" \" << col << \" \" << (*this)(col,row) << \"\\n\";\n\t\t\t} // end for\n\n\t\t\tplotfile << \"\\n\";\n\t\t} // end for\n\t}\n\t\t\n}; // end class\n\n// =============================================================================\n// Array3D\n// =============================================================================\n\ntemplate<typename T>\nclass Array3D {\npublic:\n\n\tvoid initialize(const int length0, const int length1, const int length2) {\n\t\tinitialize(length0, length1, length2, false, T());\n\t} // end method\n\n\tvoid initialize(const int length0, const int length1, const int length2, const T &defaultValue) {\n\t\tinitialize(length0, length1, length2, true, defaultValue);\n\t} // end method\n\n\tT &operator()(const int i, const int j, const int k) {\n\t\treturn _data[getLinearIndex(i, j, k)];\n\t} // end method\n\n\tconst T &operator()(const int i, const int j, const int k) const {\n\t\treturn _data[getLinearIndex(i, j, k)];\n\t} // end method\n\n\tint getNumElements() const {\n\t\treturn _data.size();\n\t} // end method\n\n\tint getLength(const int dimension) const {\n\t\treturn _length[dimension];\n\t} // end method\n\n\t//! @brief Assigns all elements to a certain value.\n\tvoid assign(const T &value) {\n\t\t_data.assign(getNumElements(), value);\n\t} // end method\n\n\tbool isValidIndex(const int i, const int j, const int k) const {\n\t\treturn\n\t\t\t\ti >= 0 && i < _length[0] &&\n\t\t\t\tj >= 0 && j < _length[1] &&\n\t\t\t\tk >= 0 && k < _length[2];\n\t} // end method\n\n\tbool isEmpty() const {return _data.empty();}\n\nprivate:\n\n\tvoid initialize(const int length0, const int length1, const int length2, const bool setDefaultValue, const T &defaultValue) {\n\t\t_length[0] = length0;\n\t\t_length[1] = length1;\n\t\t_length[2] = length2;\n\n\t\t_data.clear();\n\t\tif (setDefaultValue) {\n\t\t\t_data.assign(getNumElements(), defaultValue);\n\t\t} else {\n\t\t\t_data.resize(getNumElements());\n\t\t} // end else\n\t} // end method\n\n\t//! @brief Computes a linear index given a multi-dimensional index.\n\tint getLinearIndex(const int i, const int j, const int k) const {\n\t\treturn i + j*_length[0] + k*(_length[0]*_length[1]);\n\t} // end method\n\n\tstd::array<int, 3> _length;\n\tstd::vector<T> _data;\n}; // end class\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/util/AsciiProgressBar.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   AsciiProgressBar.h\n * Author: gaflach\n *\n * Created on September 6, 2015, 1:11 AM\n */\n\n#ifndef ASCII_PROGRESS_BAR_H\n#define\tASCII_PROGRESS_BAR_H\n\n#include <algorithm>\n#include <sstream>\n#include <iomanip>\n\nstatic const int DEFAULT_N = 40;\n\nclass AsciiProgressBar {\nprivate:\n\tconst int N;\n\t\n\tint clsMaxValue;\n\tint clsCurrentValue;\n\tint clsDrawingThreshold;\n\tint clsNextDraw;\n\t\n\tvoid updateDrawingThreshold() {\n\t\tconst double precision = 1.0 / N;\n\t\tclsDrawingThreshold = (int) (precision * clsMaxValue);\n\t} // end method\n\t\n\tvoid draw() {\n\t\tconst int percentage = clsMaxValue > 0? (100*clsCurrentValue)/clsMaxValue : 100;\n\t\tconst int middle = (N*percentage) / 100;\n\t\t\n\t\tstd::cout << \"\\r\";\n\t\tstd::cout << std::setw(3) << percentage << \"% \";\n\t\tstd::cout << \"[\";\n\t\tfor (int i = 0; i < middle; i++) {\n\t\t\tstd::cout << \"=\";\n\t\t} // end for\n\t\tfor (int i = middle; i < N; i++) {\n\t\t\tstd::cout << \" \";\n\t\t} // end for\n\t\tstd::cout << \"]\";\n\t\tstd::cout << std::flush;\n\t} // end method\n\t\n\tvoid reset(const int maxValue = 0) {\n\t\tclsMaxValue = maxValue;\n\t\tclsCurrentValue = 0;\n\t\tupdateDrawingThreshold();\n\t\tclsNextDraw = clsDrawingThreshold;\n\t} // end method\n\t\npublic:\n\t\n\tAsciiProgressBar() : N(DEFAULT_N) {\n\t\treset();\n\t} // end constructor\n\t\t\t \n\tAsciiProgressBar(const int maxValue, const int numColumns = DEFAULT_N) : N(numColumns) {\n\t\treset(maxValue);\n\t} // end constructor\n\t\n\tvoid setMaxValue(const int maxValue) { \n\t\tclsMaxValue = maxValue; \n\t\tupdateDrawingThreshold();\n\t} // end method\n\t\n\tvoid setCurrentValue(const int value) { \n\t\tclsCurrentValue = std::min(value, clsMaxValue); \n\t} // end method\n\t\n\tvoid progress(const int increment = 1) { \n\t\tclsCurrentValue = std::min(clsCurrentValue + increment, clsMaxValue);\n\t\tif (clsNextDraw >= clsDrawingThreshold) {\n\t\t\tdraw();\n\t\t\tclsNextDraw = 0;\n\t\t} else {\n\t\t\tclsNextDraw += increment;\n\t\t} // end else\n\t} // end method\n\t\n\tvoid finish() {\n\t\tclsCurrentValue = clsMaxValue;\n\t\tclsNextDraw = 0;\n\t\tdraw();\n\t\tstd::cout << \"\\n\";\n\t} // end method\n\t\n}; // end class\n\n#endif\t/* ASCIIPROGRESSBAR_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Bounds.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_BOUNDS_H\n#define RSYN_BOUNDS_H\n\n#include <algorithm>\n#include <limits>\n\n#include \"dim.h\"\n#include \"dbu.h\"\n\n// -----------------------------------------------------------------------------\n\nclass Bounds {\n\tfriend ostream &operator<<( std::ostream &out, const Bounds &r ) {\n\t\treturn out << \"[\" << r[LOWER] << \", \" << r[UPPER] << \"]\";\n\t} // end function\t\t\n\t\nprivate:\n\tDBUxy clsPoints[2];\npublic:\n\t\n\tBounds() {\n\t\tclsPoints[0] = DBUxy();\n\t\tclsPoints[1] = DBUxy();\n\t}\n\t\n\tBounds(const DBU xmin, const DBU ymin, const DBU xmax, const DBU ymax ) {\n\t\t(*this)[LOWER].set(xmin,ymin);\n\t\t(*this)[UPPER].set(xmax,ymax);\n\t} // end constructor\t\n\t\n\tBounds(const DBUxy pmin, const DBUxy pmax ) {\n\t\t(*this)[LOWER] = pmin;\n\t\t(*this)[UPPER] = pmax;\n\t} // end constructor\t\n\t\n\tvoid updatePoints(const DBUxy pmin, const DBUxy pmax){\n\t\t(*this)[LOWER] = pmin;\n\t\t(*this)[UPPER] = pmax;\n\t}\n\tvoid updatePoints(const DBU xMin, const DBU yMin, const DBU xMax, const DBU yMax){\n\t\t(*this)[LOWER][X] = xMin;\n\t\t(*this)[LOWER][Y] = yMin;\n\t\t(*this)[UPPER][X] = xMax;\n\t\t(*this)[UPPER][Y] = yMax;\n\t}\n\tDBUxy &operator[](const int boundary) { return clsPoints[boundary]; }\n\tconst DBUxy &operator[](const int boundary) const { return clsPoints[boundary]; }\n\t\n\tDBU computeLength(const int dimension) const { return (*this)[UPPER][dimension] - (*this)[LOWER][dimension]; }\n\tDBUxy computeLength() const { return (*this)[UPPER] - (*this)[LOWER]; }\n\t\n\tFloatingPointDBU computeDiagonal() const { return std::sqrt( std::pow(computeLength(X), 2) + std::pow(computeLength(Y), 2) ); }\n\t\n\tDBU computeCenter(const int dimension) const { return ( (*this)[UPPER][dimension] + (*this)[LOWER][dimension] ) / 2; }\n\tDBUxy computeCenter() const { return ( (*this)[UPPER] + (*this)[LOWER] ) / 2; }\n\t\n\tDBU computeArea() const { return computeLength(0)*computeLength(1); }\n\tDBU computeSemiperimeter() const { return computeLength(0)+computeLength(1); }\n\t\n\tDBU randomInnerPoint(const int dimension) const {\n\t\tconst FloatingPointDBU random = rand()/double(RAND_MAX);\n\t\treturn (DBU) ((*this)[LOWER][dimension] + random*computeLength(dimension));\n\t} // end method\n\n\tDBU overlapArea( const Bounds &rect ) const {\n\t\tconst DBU dx = std::max( (*this)[LOWER][X], rect[LOWER][X] ) - std::min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst DBU dy = std::max( (*this)[LOWER][Y], rect[LOWER][Y] ) - std::min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\treturn (dx<0 && dy<0) ? dx*dy : 0;\n\t} // end method\n\t\n\tDBU getCoordinate(const Boundary bound, const Dimension dim ) const { return (*this)[bound][dim]; }\n\tDBUxy getCoordinate(const Boundary bound ) const { return (*this)[bound]; }\n\n\tDBU getX() const { return (*this)[LOWER][X]; }\n\tDBU getY() const { return (*this)[LOWER][Y]; }\n\tDBU getWidth() const { return computeLength(X); }\n\tDBU getHeight() const { return computeLength(Y); }\n\n\tDBUxy getLower() const { return (*this)[LOWER]; }\n\tDBUxy getUpper() const { return (*this)[UPPER]; }\n\n\tbool overlap(const Bounds &rect) const {\n\t\tconst DBU dx = std::max( (*this)[LOWER][X], rect[LOWER][X] ) - std::min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst DBU dy = std::max( (*this)[LOWER][Y], rect[LOWER][Y] ) - std::min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\treturn (dx<0 && dy<0);\n\t} // end method\t\n\n\t// Returns the rectangle formed by the intersection of this and other \n\t// rectangle. If they don't overlap returns a degenerated rectangle (zero\n\t// area) at half way between the two rectangles.\n\tBounds overlapRectangle(const Bounds &rect) const {\n\t\tconst DBU dx = std::max( (*this)[LOWER][X], rect[LOWER][X] ) - std::min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst DBU dy = std::max( (*this)[LOWER][Y], rect[LOWER][Y] ) - std::min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\tBounds overlap;\n\t\tif ( dx<0 && dy<0 ) {\n\t\t\toverlap[LOWER] = max( (*this)[LOWER], rect[LOWER] );\n\t\t\toverlap[UPPER] = min( (*this)[UPPER], rect[UPPER] );\n\t\t} else {\n\t\t\t// Returns a zero-area rectangle at half the way of the two\n\t\t\t// rectangles.\n\t\t\tconst DBUxy upper = max( (*this)[LOWER], rect[LOWER] );\n\t\t\tconst DBUxy lower = min( (*this)[UPPER], rect[UPPER] );\n\t\t\t\n\t\t\toverlap[LOWER] = (upper+lower) / 2;\n\t\t\toverlap[UPPER] = overlap[LOWER];\n\t\t} // end else\n\n\t\treturn overlap;\n\t} // end method\n\t\n\t// Returns the dimension length overlap of this and other rectangle. Otherwise, returns zero \n\tDBU overlapDimensionLength(const Bounds &rect, const Dimension dim ) const {\n\t\tconst DBU delta = std::max( (*this)[LOWER][dim], rect[LOWER][dim] ) - std::min( (*this)[UPPER][dim], rect[UPPER][dim] );\n\t\treturn delta < 0 ? -delta : 0;\n\t} // end method\n\t\n\n\t// Check if a value is in between the lower and upper bounds of this \n\t// rectangle.\n\tbool between( const DBU pos, const Dimension DIMENSION ) const {\n\t\treturn ( pos >= (*this)[LOWER][DIMENSION] && pos <= (*this)[UPPER][DIMENSION] );\n\t} // end method\n\n\t// Check if a point is inside this rectangle.\n\t\n\tbool inside( const DBU x, const DBU y ) const {\n\t\treturn \n\t\t\t( x >= (*this)[LOWER][X] && x <= (*this)[UPPER][X] ) && \n\t\t\t( y >= (*this)[LOWER][Y] && y <= (*this)[UPPER][Y] );\n\t} // end method\t\n\t\n\tbool inside( const DBUxy pos ) const {\n\t\treturn between(pos[X],X) && between(pos[Y],Y);\n\t} // end method\n\t\n\tbool inside( const Bounds & bounds ) const {\n\t\treturn inside(bounds[LOWER]) && inside(bounds[UPPER]);\n\t} // end method\n\t// Change the position of this rectangle.\n\t\n\tvoid moveTo( const DBU position, const Dimension DIMENSION ) {\n\t\tconst DBU length = computeLength(DIMENSION);\n\t\t(*this)[LOWER][DIMENSION] = position;\n\t\t(*this)[UPPER][DIMENSION] = position + length;\n\t} // end method\t\n\t\n\tvoid moveTo( const DBUxy position ) {\n\t\tconst DBUxy length = computeLength();\n\t\t(*this)[LOWER] = position;\n\t\t(*this)[UPPER] = position + length; \n\t} // end method\n\t\n\tvoid moveCenterTo( const DBUxy position ) {\n\t\tconst DBUxy halfLength = computeLength() / 2;\n\t\t(*this)[LOWER] = position - halfLength;\n\t\t(*this)[UPPER] = position + halfLength; \n\t} // end method\t\n\t\n\tvoid translate( const DBUxy displacement ) {\n\t\t(*this)[LOWER] += displacement;\n\t\t(*this)[UPPER] += displacement;\n\t} // end method\n\t\n\tvoid moveTo( const DBU x, const DBU y ) { moveTo(DBUxy(x,y)); }\n\tvoid moveCenterTo( const DBU x, const DBU y ) { moveCenterTo(DBUxy(x,y)); }\n\tvoid translate( const DBU x, const DBU y ) { translate(DBUxy(x,y)); }\n\n\tBounds getTranslated(const DBUxy displacement) const {\n\t\tBounds bounds = *this;\n\t\tbounds.translate(displacement);\n\t\treturn bounds;\n\t} // end method\n\n\tBounds getTranslated(const DBU x, const DBU y) const {\n\t\treturn getTranslated(DBUxy(x, y));\n\t} // end method\n\n\t// Multiple each coordinates by a scale factor. Useful when change the\n\t// coordinate system.\n\tvoid scaleCoordinates(const FloatingPointDBU scaling) {\n\t\tclsPoints[LOWER].scale(scaling);\n\t\tclsPoints[UPPER].scale(scaling);\n\t} // end method \n\t\n\t// Scale this rectangle using its center as the point of reference. Note\n\t// that this will keep the center of the rectangle in the same position.\n\t\n\tvoid scaleCentralized(const FloatingPointDBU xFactor, const FloatingPointDBU yFactor) {\n\t\tconst DBUxy p = computeCenter();\n\t\ttranslate(-p);\n\t\tclsPoints[LOWER].scale(xFactor, yFactor);\n\t\tclsPoints[UPPER].scale(xFactor, yFactor);\n\t\ttranslate(+p);\n\t} // end method\n\t\n\tvoid scaleCentralized(const FloatingPointDBU factor) {\n\t\tscaleCentralized(factor, factor);\n\t} // end method\n\n\t// Change size.\n\tvoid setLength(const Dimension DIMENSION, const DBU length) {\n\t\tclsPoints[UPPER][DIMENSION] = clsPoints[LOWER][DIMENSION] + length;\n\t} // end method\n\n\t// Check if this rectangle is valid, that is the lower coordinates are\n\t// smaller than the upper coordinates.\n\tbool isValid() const {\n\t\treturn \n\t\t\t(*this)[LOWER][X] <= (*this)[UPPER][X] &&\n\t\t\t(*this)[LOWER][Y] <= (*this)[UPPER][Y];\n\t} // end method\n\t\n\t// Get the point inside the rectangle which is closest to p.\n\tDBUxy closestPoint(const DBUxy p) const {\n\t\tDBUxy lower = getCoordinate(LOWER);\n\t\tDBUxy upper = getCoordinate(UPPER);\n\t\treturn max(min(p, upper), lower);\n\t} // end method\n\n\t// Make the lower be +inf and upper be -inf. Useful when computing the\n\t// bounding box of a set of points.\n\tvoid degenerate() {\n\t\t(*this)[LOWER][X] = std::numeric_limits<DBU>::max();\n\t\t(*this)[LOWER][Y] = std::numeric_limits<DBU>::max();\n\t\t(*this)[UPPER][X] = std::numeric_limits<DBU>::min();\n\t\t(*this)[UPPER][Y] = std::numeric_limits<DBU>::min();\n\t} // end method\n\t\n\t// Increases this rectangle so that the point x, y will be inside it.\n\t\n\tvoid stretchToFit(const DBU x, const DBU y) {\n\t\t(*this)[LOWER] = min((*this)[LOWER], DBUxy(x, y));\n\t\t(*this)[UPPER] = max((*this)[UPPER], DBUxy(x, y));\n\t} // end method\n\t\n\tvoid stretchToFit(const DBUxy p) {\n\t\tstretchToFit(p.x, p.y);\n\t} // end method\n\t\n\tvoid clear () {\n\t\tclsPoints[0].clear();\n\t\tclsPoints[1].clear();\n\t} // end method \n\t\n}; // end struct\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Color.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   Color.h\n * Author: jucemar\n *\n * Created on March 19, 2015, 1:52 PM\n */\n\n#ifndef COLOR_H\n#define\tCOLOR_H\n\nclass Color {\npublic:\n\tunsigned char r, g, b;\n\n\tbool operator == (const Color& c) const { return r == c.r && g == c.g && b == c.b; };\n\t\n\tbool transparent;\n\t\n\tColor() {\n\t\tr = 255;\n\t\tg = 255;\n\t\tb = 255;\n\t\ttransparent = false;\n\t}\n\n\tColor(const unsigned char red, const unsigned char green, const unsigned char blue) {\n\t\tsetRGB(red, green, blue);\n\t}\n\n\tvoid setRGB(const unsigned char red, const unsigned char green, const unsigned char blue) {\n\t\tr = red;\n\t\tg = green;\n\t\tb = blue;\n\t} // end method\n\t\n\tvoid setRGB(Color color) {\n\t\tr = color.r;\n\t\tg = color.g;\n\t\tb = color.b;\n\t} // end method\n}; // end class\n\n\n#endif\t/* COLOR_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Colorize.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef COLORIZE_H\n#define\tCOLORIZE_H\n\n#include <cmath>\n#include <array>\n\n// Diverging Color Maps for Scientific Visualization\n// http://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf\n\nclass Colorize {\npublic:\n\n\tstatic void colorTemperature( const double weight, int &r, int &g, int &b ) {\n\t\t// Mangeta <-> Blue <-> Cian <-> Green <-> Yellow <-> Red\n\t\tconst int numColors = 6;\n\t\tstatic const int R[numColors] = { 255,   0,   0,   0, 255, 255 };\n\t\tstatic const int G[numColors] = {   0,   0, 255, 255, 255,   0 };\n\t\tstatic const int B[numColors] = { 255, 255, 255,   0,   0,   0 };\n\t\t\n\t\t/* Color Range based on weight\n\t\t * 1.0 -> Vermelho - Red\n\t\t * 0.9 -> Laranja - Orange\n\t\t * 0.8 -> Amarelo - Yellow\n\t\t * 0.7 -> Verde Claro - Light Green\n\t\t * 0.6 -> Verde Harlequin - Harlequin green\n\t\t * 0.5 -> Verde Spring  - Spring Green\n\t\t * 0.4 -> Azul Ciano - Ciano Blue\n\t\t * 0.3 -> Azul Azure - Azure Blue\n\t\t * 0.2 -> Azul - Blue\n\t\t * 0.1 -> Azul Indigo - Indigo Blue\n\t\t * 0.0 -> Rosa - Pink \n\t\t */\n\n//\t\t// Baseado no mapa de cores \"jet\" do Matlab\n//\t\tconst int numColors = 16;\n//\t\tstatic const int R[numColors] = {   0,   0,   0,   0,   0,   0,  66, 132, 189, 255, 255, 255, 255, 255, 189, 132};\n//\t\tstatic const int G[numColors] = {   0,   0,  66, 132, 189, 255, 255, 255, 255, 255, 189, 132,  66,   0,   0,   0};\n//\t\tstatic const int B[numColors] = { 189, 255, 255, 255, 255, 255, 189, 132,  66,   0,   0,   0,   0,   0,   0,   0};\t\t\n\t\t\n\t\tdouble temp;\n\t\t\n\t\tif ( std::isnan(weight) ) {\n\t\t\tr = g = b = 0;\n\t\t} else if ( std::isinf(weight) ) {\n\t\t\tr = g = b = 255;\n\t\t} else {\n\t\t\tif ( weight > 1.0 )\n\t\t\t\ttemp = (numColors-1);\n\t\t\telse if ( weight < 0 )\n\t\t\t\ttemp = 0;\n\t\t\telse\n\t\t\t\ttemp = (numColors-1)*weight;\n\n\t\t\tconst int i0 = (int) std::floor( temp );\n\t\t\tconst int i1 = (int) std::ceil( temp );\n\t\t\tconst double alpha = temp - (int)(temp);\n\n\t\t\tr = (int) std::floor( R[i0]*(1-alpha) + R[i1]*(alpha) + 0.5 );\n\t\t\tg = (int) std::floor( G[i0]*(1-alpha) + G[i1]*(alpha) + 0.5 );\n\t\t\tb = (int) std::floor( B[i0]*(1-alpha) + B[i1]*(alpha) + 0.5 );\n\t\t} // end else\n\t} // end method\n\t\n\t\n\tstatic void colorTemperatureWarmCold( const double weight, int &r, int &g, int &b ) {\n\t\tstatic const std::array<int, 33> R{59, 68, 77, 87, 98, 108, 119, 130, 141, 152, 163, 174, 184, 194, 204, 213, 221, 229, 236, 241, 245, 247, 247, 247, 244, 241, 236, 229, 222, 213, 203, 192, 180}; \n\t\tstatic const std::array<int, 33> G{76, 90, 104, 117, 130, 142, 154, 165, 176, 185, 194, 201, 208, 213, 217, 219, 221, 216, 211, 204, 196, 187, 177, 166, 154, 141, 127, 112, 96, 80, 62, 40, 4};\n\t\tstatic const std::array<int, 33> B{192, 204, 215, 225, 234, 241, 247, 251, 254, 255, 255, 253, 249, 244, 238, 230, 221, 209, 197, 185, 173, 160, 148, 135, 123, 111, 99, 88, 77, 66, 56, 47, 38}; \n\n\t\tconst int numColors = R.size();\n\t\t\n\t\tdouble temp;\n\t\t\n\t\tif ( std::isnan(weight) ) {\n\t\t\tr = g = b = 0;\n\t\t} else if ( std::isinf(weight) ) {\n\t\t\tr = g = b = 255;\n\t\t} else {\n\t\t\tif ( weight > 1.0 )\n\t\t\t\ttemp = (numColors-1);\n\t\t\telse if ( weight < 0 )\n\t\t\t\ttemp = 0;\n\t\t\telse\n\t\t\t\ttemp = (numColors-1)*weight;\n\n\t\t\tconst int i0 = (int) std::floor( temp );\n\t\t\tconst int i1 = (int) std::ceil( temp );\n\t\t\tconst double alpha = temp - (int)(temp);\n\n\t\t\tr = (int) std::floor( R[i0]*(1-alpha) + R[i1]*(alpha) + 0.5 );\n\t\t\tg = (int) std::floor( G[i0]*(1-alpha) + G[i1]*(alpha) + 0.5 );\n\t\t\tb = (int) std::floor( B[i0]*(1-alpha) + B[i1]*(alpha) + 0.5 );\n\t\t} // end else\n\t} // end method\t\n\t\n\t\n};\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Debug.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_ASSERT_H\n#define RSYN_ASSERT_H\n\n#include <iostream>\n\n#define rsynAbort(msg) \\\n\tstd::cout << \"\\n\"; \\\n\tstd::cout << \"ASSERTION: \" << msg << \"\\n\"; \\\n\tstd::cout << __FILE__  << \":\" << __LINE__ << \"\\n\"; \\\n\tstd::cout << std::flush; \\\n\tstd::exit(1);\n\n#define rsynAssert(condition, msg) \\\n\tif (!(condition)) { \\\n\t\tstd::cout << \"\\n\"; \\\n\t\tstd::cout << \"ASSERTION: \" << #condition << \"\\n\"; \\\n\t\tstd::cout << __FILE__  << \":\" << __LINE__ << \"\\n\"; \\\n\t\tstd::cout << msg << \"\\n\"; \\\n\t\tstd::cout << std::flush; \\\n\t\tstd::exit(1); \\\n\t} // end if\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/DoubleRectangle.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_DOUBLE_RECTANGLE_H\n#define RSYN_DOUBLE_RECTANGLE_H\n\n#include <algorithm>\nusing std::max;\nusing std::min;\n#include <limits>\n\n#include \"dim.h\"\n#include \"double2.h\"\n#include \"Bounds.h\"\n\n// -----------------------------------------------------------------------------\n\nclass DoubleRectangle {\n\tfriend ostream &operator<<( ostream &out, const DoubleRectangle &r ) {\n\t\treturn out << \"[\" << r[LOWER] << \", \" << r[UPPER] << \"]\";\n\t} // end function\n\nprivate:\n\tdouble2 clsPoints[2];\npublic:\n\n\tDoubleRectangle() {\n\t\tclsPoints[0] = double2();\n\t\tclsPoints[1] = double2();\n\t}\n\n\tDoubleRectangle(const double xmin, const double ymin, const double xmax, const double ymax ) {\n\t\t(*this)[LOWER].set(xmin,ymin);\n\t\t(*this)[UPPER].set(xmax,ymax);\n\t} // end constructor\n\n\tDoubleRectangle(const double2 pmin, const double2 pmax ) {\n\t\t(*this)[LOWER] = pmin;\n\t\t(*this)[UPPER] = pmax;\n\t} // end constructor\n\n\tDoubleRectangle(const Bounds &bounds) {\n\t\toperator=(bounds);\n\t} // end constructor\n\n\tvoid operator=(const Bounds &bounds) {\n\t\tclsPoints[0].x = bounds[0].x;\n\t\tclsPoints[0].y = bounds[0].y;\n\t\tclsPoints[1].x = bounds[1].x;\n\t\tclsPoints[1].y = bounds[1].y;\n\t} // end constructor\n\n\tBounds scaleAndConvertToDbu(const double scale, \n\t\t\tconst RoundingStrategy roundingLower,\n\t\t\tconst RoundingStrategy roundingUpper) const {\n\t\tDoubleRectangle copy = *this;\n\t\tcopy.scaleCoordinates(scale);\n\t\treturn copy.convertToDbu(roundingLower, roundingUpper);\n\t} // end method\n\n\tBounds convertToDbu(\n\t\t\tconst RoundingStrategy roundingLower,\n\t\t\tconst RoundingStrategy roundingUpper) const {\n\t\treturn Bounds(clsPoints[0].convertToDbu(roundingLower), clsPoints[1].convertToDbu(roundingUpper));\n\t} // end method\n\n\tBounds scaleAndConvertToDbu(const double scale,\n\t\t\tconst RoundingStrategy rounding = ROUND_DOWN) const {\n\t\treturn scaleAndConvertToDbu(scale, rounding, rounding);\n\t} // end method\n\n\tBounds convertToDbu(const RoundingStrategy rounding = ROUND_DOWN) const {\n\t\treturn convertToDbu(rounding, rounding);\n\t} // end method\n\n\tvoid updatePoints(const double2 pmin, const double2 pmax){\n\t\t(*this)[LOWER] = pmin;\n\t\t(*this)[UPPER] = pmax;\n\t}\n\tvoid updatePoints(const double xMin, const double yMin, const double xMax, const double yMax){\n\t\t(*this)[LOWER][X] = xMin;\n\t\t(*this)[LOWER][Y] = yMin;\n\t\t(*this)[UPPER][X] = xMax;\n\t\t(*this)[UPPER][Y] = yMax;\n\t}\n\tdouble2 &operator[](const int boundary)       { return clsPoints[boundary]; }\n\tconst double2 &operator[](const int boundary) const { return clsPoints[boundary]; }\n\n\tdouble computeLength(const int dimension) const { return (*this)[UPPER][dimension] - (*this)[LOWER][dimension]; }\n\tdouble2 computeLength() const { return (*this)[UPPER] - (*this)[LOWER]; }\n\n\tdouble computeDiagonal() const { return std::sqrt( std::pow(computeLength(X), 2.0) + std::pow(computeLength(Y), 2.0) ); }\n\n\tdouble computeCenter(const int dimension) const { return ( (*this)[UPPER][dimension] + (*this)[LOWER][dimension] ) / 2.0; }\n\tdouble2 computeCenter() const { return ( (*this)[UPPER] + (*this)[LOWER] ) / 2.0; }\n\n\tdouble computeArea() const { return computeLength(0)*computeLength(1); }\n\tdouble computeSemiperimeter() const { return computeLength(0)+computeLength(1); }\n\n\tdouble randomInnerPoint(const int dimension) const {\n\t\tconst double random = rand()/double(RAND_MAX);\n\t\treturn (*this)[LOWER][dimension] + random*computeLength(dimension);\n\t} // end method\n\n\tdouble overlapArea( const DoubleRectangle &rect ) const {\n\t\tconst double dx = max( (*this)[LOWER][X], rect[LOWER][X] ) - min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst double dy = max( (*this)[LOWER][Y], rect[LOWER][Y] ) - min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\treturn (dx<0 && dy<0) ? dx*dy : 0;\n\t} // end method\n\n\tdouble getCoordinate(const Boundary bound, const Dimension dim ) const { return (*this)[bound][dim]; }\n\tdouble2 getCoordinate(const Boundary bound ) const { return (*this)[bound]; }\n\n\tbool overlap( const DoubleRectangle &rect ) const {\n\t\tconst double dx = max( (*this)[LOWER][X], rect[LOWER][X] ) - min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst double dy = max( (*this)[LOWER][Y], rect[LOWER][Y] ) - min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\treturn (dx<0 && dy<0);\n\t} // end method\n\n\t// Returns the rectangle formed by the intersection of this and other\n\t// rectangle. If they don't overlap returns a degenerated rectangle (zero\n\t// area) at half way between the two rectangles.\n\tDoubleRectangle overlapRectangle( const DoubleRectangle &rect ) const {\n\t\tconst double dx = max( (*this)[LOWER][X], rect[LOWER][X] ) - min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst double dy = max( (*this)[LOWER][Y], rect[LOWER][Y] ) - min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\tDoubleRectangle overlap;\n\t\tif ( dx<0 && dy<0 ) {\n\t\t\toverlap[LOWER] = max( (*this)[LOWER], rect[LOWER] );\n\t\t\toverlap[UPPER] = min( (*this)[UPPER], rect[UPPER] );\n\t\t} else {\n\t\t\t// Returns a zero-area rectangle at half the way of the two\n\t\t\t// rectangles.\n\t\t\tconst double2 upper = max( (*this)[LOWER], rect[LOWER] );\n\t\t\tconst double2 lower = min( (*this)[UPPER], rect[UPPER] );\n\n\t\t\toverlap[LOWER] = (upper+lower) / 2.0;\n\t\t\toverlap[UPPER] = overlap[LOWER];\n\t\t} // end else\n\n\t\treturn overlap;\n\t} // end method\n\n\t// Check if a value is in between the lower and upper bounds of this\n\t// rectangle.\n\tbool between( const double pos, const Dimension DIMENSION ) const {\n\t\treturn ( pos >= (*this)[LOWER][DIMENSION] && pos <= (*this)[UPPER][DIMENSION] );\n\t} // end method\n\n\t// Check if a point is inside this rectangle.\n\n\tbool inside( const double x, const double y ) const {\n\t\treturn\n\t\t\t( x >= (*this)[LOWER][X] && x <= (*this)[UPPER][X] ) &&\n\t\t\t( y >= (*this)[LOWER][Y] && y <= (*this)[UPPER][Y] );\n\t} // end method\n\n\tbool inside( const double2 pos ) const {\n\t\treturn between(pos[X],X) && between(pos[Y],Y);\n\t} // end method\n\n\t// Change the position of this rectangle.\n\n\tvoid moveTo( const double position, const Dimension DIMENSION ) {\n\t\tconst double length = computeLength(DIMENSION);\n\t\t(*this)[LOWER][DIMENSION] = position;\n\t\t(*this)[UPPER][DIMENSION] = position + length;\n\t} // end method\n\n\tvoid moveTo( const double2 position ) {\n\t\tconst double2 length = computeLength();\n\t\t(*this)[LOWER] = position;\n\t\t(*this)[UPPER] = position + length;\n\t} // end method\n\n\tvoid moveCenterTo( const double2 position ) {\n\t\tconst double2 halfLength = computeLength() / 2.0;\n\t\t(*this)[LOWER] = position - halfLength;\n\t\t(*this)[UPPER] = position + halfLength;\n\t} // end method\n\n\tvoid translate( const double2 displacement ) {\n\t\t(*this)[LOWER] += displacement;\n\t\t(*this)[UPPER] += displacement;\n\t} // end method\n\n\tvoid moveTo( const double x, const double y ) { moveTo(double2(x,y)); }\n\tvoid moveCenterTo( const double x, const double y ) { moveCenterTo(double2(x,y)); }\n\tvoid translate( const double x, const double y ) { translate(double2(x,y)); }\n\n\t// Multiple each coordinates by a scale factor. Useful when change the\n\t// coordinate system.\n\tvoid scaleCoordinates(const double numb){\n\t\tclsPoints[LOWER].scale(numb);\n\t\tclsPoints[UPPER].scale(numb);\n\t} // end method\n\n\t// Scale this rectangle using its center as the point of reference. Note\n\t// that this will keep the center of the rectangle in the same position.\n\n\tvoid scaleCentralized(const double2 factor) {\n\t\tconst double2 p = computeCenter();\n\t\ttranslate(-p);\n\t\tclsPoints[LOWER] *= factor;\n\t\tclsPoints[UPPER] *= factor;\n\t\ttranslate(+p);\n\t} // end method\n\n\tvoid scaleCentralized(const double factor) {\n\t\tscaleCentralized(double2(factor, factor));\n\t} // end method\n\n\t// Check if this rectangle is valid, that is the lower coordinates are\n\t// smaller than the upper coordinates.\n\tbool isValid() const {\n\t\treturn\n\t\t\t(*this)[LOWER][X] <= (*this)[UPPER][X] &&\n\t\t\t(*this)[LOWER][Y] <= (*this)[UPPER][Y];\n\t} // end method\n\n\t// Get the point inside the rectangle which is closest to p.\n\tdouble2 closestPoint(const double2 p) const {\n\t\tdouble2 lower = getCoordinate(LOWER);\n\t\tdouble2 upper = getCoordinate(UPPER);\n\t\treturn max(min(p, upper), lower);\n\t} // end method\n\n\t// Make the lower be +inf and upper be -inf. Useful when computing the\n\t// bounding box of a set of points.\n\tvoid degenerate() {\n\t\t(*this)[LOWER][X] = +std::numeric_limits<double>::infinity();\n\t\t(*this)[LOWER][Y] = +std::numeric_limits<double>::infinity();\n\t\t(*this)[UPPER][X] = -std::numeric_limits<double>::infinity();\n\t\t(*this)[UPPER][Y] = -std::numeric_limits<double>::infinity();\n\t} // end method\n\n\t// Increases this rectangle so that the point x, y will be inside it.\n\n\tvoid stretchToFit(const double x, const double y) {\n\t\t(*this)[LOWER] = min((*this)[LOWER], double2(x, y));\n\t\t(*this)[UPPER] = max((*this)[UPPER], double2(x, y));\n\t} // end method\n\n\tvoid stretchToFit(const double2 p) {\n\t\tstretchToFit(p.x, p.y);\n\t} // end method\n\n\tvoid clear () {\n\t\tclsPoints[0].clear();\n\t\tclsPoints[1].clear();\n\t} // end method\n\n}; // end struct\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Environment.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* \n * File:   Environment.h\n * Author: gaflach\n *\n * Created on February 25, 2016, 6:56 PM\n */\n\n#ifndef UTIL_ENVIRONMENT_H\n#define UTIL_ENVIRONMENT_H\n\n#include <sstream>\n#include <cstdlib>\n\nclass Environment {\nprivate:\n\t\n\ttemplate<typename T>\n\tstatic bool parse(const std::string &str, T &data) {\n\t\tstd::istringstream iss( str );\n\t\tiss >> data;\n\t\treturn !iss.fail();\n\t} // end method\t\t\n\t\n\ttemplate<typename T>\n\tstatic T get(const std::string &name, const T &defaultValue) {\n\t\tT data;\n\t\tconst char *value = std::getenv(name.c_str());\n\t\treturn value && parse(value, data)? data : defaultValue;\n\t} // end method\n\t\t\npublic:\n\n\tstatic int getBoolean(const std::string &name, const bool defaultValue) { return get(name, defaultValue); }\n\tstatic int getInteger(const std::string &name, const int defaultValue) { return get(name, defaultValue); }\n\tstatic float getFloat(const std::string &name, const float defaultValue) { return get(name, defaultValue); }\n\tstatic double getDouble(const std::string &name, const double defaultValue) { return get(name, defaultValue); }\n\tstatic std::string getString(const std::string &name, const std::string &defaultValue) { return get(name, defaultValue); }\n\t\n}; // end class\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Exception.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef EXCEPTION_H\n#define\tEXCEPTION_H\n\n#include <exception>\n#include <string>\n#include <ostream>\n\nclass Exception: public std::exception {\n\tfriend std::ostream &operator<<(std::ostream &out, const Exception &e) { \n\t\treturn out << e.what();\n\t} // end method\t\n\t\npublic:\n\n\texplicit Exception(const std::string& message) :  clsMsg(message) {}\n\tvirtual ~Exception() throw (){}\n\n\tvirtual const char* what() const throw (){\n       return clsMsg.c_str();\n    } // end method\n\t\nprotected:\n    std::string clsMsg;\n}; // end class\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/FloatRectangle.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_FLOAT_RECTANGLE_H\n#define RSYN_FLOAT_RECTANGLE_H\n\n#include <algorithm>\nusing std::max;\nusing std::min;\n#include <limits>\n\n#include \"dim.h\"\n#include \"float2.h\"\n#include \"Bounds.h\"\n\n// -----------------------------------------------------------------------------\n\nclass FloatRectangle {\n\tfriend ostream &operator<<( ostream &out, const FloatRectangle &r ) {\n\t\treturn out << \"[\" << r[LOWER] << \", \" << r[UPPER] << \"]\";\n\t} // end function\n\nprivate:\n\tfloat2 clsPoints[2];\npublic:\n\n\tFloatRectangle() {\n\t\tclsPoints[0] = float2();\n\t\tclsPoints[1] = float2();\n\t}\n\n\tFloatRectangle(const float xmin, const float ymin, const float xmax, const float ymax ) {\n\t\t(*this)[LOWER].set(xmin,ymin);\n\t\t(*this)[UPPER].set(xmax,ymax);\n\t} // end constructor\n\n\tFloatRectangle(const float2 pmin, const float2 pmax ) {\n\t\t(*this)[LOWER] = pmin;\n\t\t(*this)[UPPER] = pmax;\n\t} // end constructor\n\n\tFloatRectangle(const Bounds &bounds) {\n\t\toperator=(bounds);\n\t} // end constructor\n\n\tvoid operator=(const Bounds &bounds) {\n\t\tclsPoints[0].x = bounds[0].x;\n\t\tclsPoints[0].y = bounds[0].y;\n\t\tclsPoints[1].x = bounds[1].x;\n\t\tclsPoints[1].y = bounds[1].y;\n\t} // end constructor\n\n\tBounds scaleAndConvertToDbu(const float scale,\n\t\t\tconst RoundingStrategy roundingLower,\n\t\t\tconst RoundingStrategy roundingUpper) const {\n\t\tFloatRectangle copy = *this;\n\t\tcopy.scaleCoordinates(scale);\n\t\treturn copy.convertToDbu(roundingLower, roundingUpper);\n\t} // end method\n\n\tBounds convertToDbu(\n\t\t\tconst RoundingStrategy roundingLower,\n\t\t\tconst RoundingStrategy roundingUpper) const {\n\t\treturn Bounds(clsPoints[0].convertToDbu(roundingLower), clsPoints[1].convertToDbu(roundingUpper));\n\t} // end method\n\n\tBounds scaleAndConvertToDbu(const float scale,\n\t\t\tconst RoundingStrategy rounding = ROUND_DOWN) const {\n\t\treturn scaleAndConvertToDbu(scale, rounding, rounding);\n\t} // end method\n\n\tBounds convertToDbu(const RoundingStrategy rounding = ROUND_DOWN) const {\n\t\treturn convertToDbu(rounding, rounding);\n\t} // end method\n\n\tvoid updatePoints(const float2 pmin, const float2 pmax){\n\t\t(*this)[LOWER] = pmin;\n\t\t(*this)[UPPER] = pmax;\n\t}\n\tvoid updatePoints(const float xMin, const float yMin, const float xMax, const float yMax){\n\t\t(*this)[LOWER][X] = xMin;\n\t\t(*this)[LOWER][Y] = yMin;\n\t\t(*this)[UPPER][X] = xMax;\n\t\t(*this)[UPPER][Y] = yMax;\n\t}\n\tfloat2 &operator[](const int boundary)       { return clsPoints[boundary]; }\n\tconst float2 &operator[](const int boundary) const { return clsPoints[boundary]; }\n\n\tfloat computeLength(const int dimension) const { return (*this)[UPPER][dimension] - (*this)[LOWER][dimension]; }\n\tfloat2 computeLength() const { return (*this)[UPPER] - (*this)[LOWER]; }\n\n\tfloat computeDiagonal() const { return std::sqrt( std::pow(computeLength(X), 2.0f) + std::pow(computeLength(Y), 2.0f) ); }\n\n\tfloat computeCenter(const int dimension) const { return ( (*this)[UPPER][dimension] + (*this)[LOWER][dimension] ) / 2.0f; }\n\tfloat2 computeCenter() const { return ( (*this)[UPPER] + (*this)[LOWER] ) / 2.0f; }\n\n\tfloat computeArea() const { return computeLength(0)*computeLength(1); }\n\tfloat computeSemiperimeter() const { return computeLength(0)+computeLength(1); }\n\n\tfloat randomInnerPoint(const int dimension) const {\n\t\tconst float random = rand()/float(RAND_MAX);\n\t\treturn (*this)[LOWER][dimension] + random*computeLength(dimension);\n\t} // end method\n\n\tfloat overlapArea( const FloatRectangle &rect ) const {\n\t\tconst float dx = max( (*this)[LOWER][X], rect[LOWER][X] ) - min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst float dy = max( (*this)[LOWER][Y], rect[LOWER][Y] ) - min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\treturn (dx<0 && dy<0) ? dx*dy : 0;\n\t} // end method\n\n\tfloat getCoordinate(const Boundary bound, const Dimension dim ) const { return (*this)[bound][dim]; }\n\tfloat2 getCoordinate(const Boundary bound ) const { return (*this)[bound]; }\n\n\tbool overlap( const FloatRectangle &rect ) const {\n\t\tconst float dx = max( (*this)[LOWER][X], rect[LOWER][X] ) - min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst float dy = max( (*this)[LOWER][Y], rect[LOWER][Y] ) - min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\treturn (dx<0 && dy<0);\n\t} // end method\n\n\t// Returns the rectangle formed by the intersection of this and other\n\t// rectangle. If they don't overlap returns a degenerated rectangle (zero\n\t// area) at half way between the two rectangles.\n\tFloatRectangle overlapRectangle( const FloatRectangle &rect ) const {\n\t\tconst float dx = max( (*this)[LOWER][X], rect[LOWER][X] ) - min( (*this)[UPPER][X], rect[UPPER][X] );\n\t\tconst float dy = max( (*this)[LOWER][Y], rect[LOWER][Y] ) - min( (*this)[UPPER][Y], rect[UPPER][Y] );\n\n\t\tFloatRectangle overlap;\n\t\tif ( dx<0 && dy<0 ) {\n\t\t\toverlap[LOWER] = max( (*this)[LOWER], rect[LOWER] );\n\t\t\toverlap[UPPER] = min( (*this)[UPPER], rect[UPPER] );\n\t\t} else {\n\t\t\t// Returns a zero-area rectangle at half the way of the two\n\t\t\t// rectangles.\n\t\t\tconst float2 upper = max( (*this)[LOWER], rect[LOWER] );\n\t\t\tconst float2 lower = min( (*this)[UPPER], rect[UPPER] );\n\n\t\t\toverlap[LOWER] = (upper+lower) / 2.0;\n\t\t\toverlap[UPPER] = overlap[LOWER];\n\t\t} // end else\n\n\t\treturn overlap;\n\t} // end method\n\n\t// Check if a value is in between the lower and upper bounds of this\n\t// rectangle.\n\tbool between( const float pos, const Dimension DIMENSION ) const {\n\t\treturn ( pos >= (*this)[LOWER][DIMENSION] && pos <= (*this)[UPPER][DIMENSION] );\n\t} // end method\n\n\t// Check if a point is inside this rectangle.\n\n\tbool inside( const float x, const float y ) const {\n\t\treturn\n\t\t\t( x >= (*this)[LOWER][X] && x <= (*this)[UPPER][X] ) &&\n\t\t\t( y >= (*this)[LOWER][Y] && y <= (*this)[UPPER][Y] );\n\t} // end method\n\n\tbool inside( const float2 pos ) const {\n\t\treturn between(pos[X],X) && between(pos[Y],Y);\n\t} // end method\n\n\t// Change the position of this rectangle.\n\n\tvoid moveTo( const float position, const Dimension DIMENSION ) {\n\t\tconst float length = computeLength(DIMENSION);\n\t\t(*this)[LOWER][DIMENSION] = position;\n\t\t(*this)[UPPER][DIMENSION] = position + length;\n\t} // end method\n\n\tvoid moveTo( const float2 position ) {\n\t\tconst float2 length = computeLength();\n\t\t(*this)[LOWER] = position;\n\t\t(*this)[UPPER] = position + length;\n\t} // end method\n\n\tvoid moveCenterTo( const float2 position ) {\n\t\tconst float2 halfLength = computeLength() / 2.0;\n\t\t(*this)[LOWER] = position - halfLength;\n\t\t(*this)[UPPER] = position + halfLength;\n\t} // end method\n\n\tvoid translate( const float2 displacement ) {\n\t\t(*this)[LOWER] += displacement;\n\t\t(*this)[UPPER] += displacement;\n\t} // end method\n\n\tvoid moveTo( const float x, const float y ) { moveTo(float2(x,y)); }\n\tvoid moveCenterTo( const float x, const float y ) { moveCenterTo(float2(x,y)); }\n\tvoid translate( const float x, const float y ) { translate(float2(x,y)); }\n\n\t// Multiple each coordinates by a scale factor. Useful when change the\n\t// coordinate system.\n\tvoid scaleCoordinates(const float numb){\n\t\tclsPoints[LOWER].scale(numb);\n\t\tclsPoints[UPPER].scale(numb);\n\t} // end method\n\n\t// Scale this rectangle using its center as the point of reference. Note\n\t// that this will keep the center of the rectangle in the same position.\n\n\tvoid scaleCentralized(const float2 factor) {\n\t\tconst float2 p = computeCenter();\n\t\ttranslate(-p);\n\t\tclsPoints[LOWER] *= factor;\n\t\tclsPoints[UPPER] *= factor;\n\t\ttranslate(+p);\n\t} // end method\n\n\tvoid scaleCentralized(const float factor) {\n\t\tscaleCentralized(float2(factor, factor));\n\t} // end method\n\n\t// Check if this rectangle is valid, that is the lower coordinates are\n\t// smaller than the upper coordinates.\n\tbool isValid() const {\n\t\treturn\n\t\t\t(*this)[LOWER][X] <= (*this)[UPPER][X] &&\n\t\t\t(*this)[LOWER][Y] <= (*this)[UPPER][Y];\n\t} // end method\n\n\t// Get the point inside the rectangle which is closest to p.\n\tfloat2 closestPoint(const float2 p) const {\n\t\tfloat2 lower = getCoordinate(LOWER);\n\t\tfloat2 upper = getCoordinate(UPPER);\n\t\treturn max(min(p, upper), lower);\n\t} // end method\n\n\t// Make the lower be +inf and upper be -inf. Useful when computing the\n\t// bounding box of a set of points.\n\tvoid degenerate() {\n\t\t(*this)[LOWER][X] = +std::numeric_limits<float>::infinity();\n\t\t(*this)[LOWER][Y] = +std::numeric_limits<float>::infinity();\n\t\t(*this)[UPPER][X] = -std::numeric_limits<float>::infinity();\n\t\t(*this)[UPPER][Y] = -std::numeric_limits<float>::infinity();\n\t} // end method\n\n\t// Increases this rectangle so that the point x, y will be inside it.\n\n\tvoid stretchToFit(const float x, const float y) {\n\t\t(*this)[LOWER] = min((*this)[LOWER], float2(x, y));\n\t\t(*this)[UPPER] = max((*this)[UPPER], float2(x, y));\n\t} // end method\n\n\tvoid stretchToFit(const float2 p) {\n\t\tstretchToFit(p.x, p.y);\n\t} // end method\n\n\tvoid clear () {\n\t\tclsPoints[0].clear();\n\t\tclsPoints[1].clear();\n\t} // end method\n\n}; // end struct\n\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/FloatingPoint.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_FLOATING_POINT_H\n#define\tRSYN_FLOATING_POINT_H\n\n#include <limits>\n#include <cmath>\n#include <cassert>\n\nenum RoundingStrategy {\n\tROUND_DOWN,\n\tROUND_UP,\n\tROUND_NEAREST\n}; // end enum\n\nnamespace Rsyn {\nclass Uninit {\npublic:\n\toperator float() const { return std::numeric_limits<float>::quiet_NaN();}\n\toperator double() const { return std::numeric_limits<double>::quiet_NaN();}\n}; // end class\n\nclass Infinity {\npublic:\n\toperator float() const { return std::numeric_limits<float>::infinity();}\n\toperator double() const { return std::numeric_limits<double>::infinity();}\n}; // end class\n} // end namespace\n\nclass FloatingPoint {\npublic:\n\n\ttemplate<typename T>\n\tstatic bool approximatelyZero(const T a, const T precision = 1e-6f) {\n\t\treturn std::abs(a) <= precision;\n\t} // end method\t\n\t\n\ttemplate<typename T>\n\tstatic bool notApproximatelyZero(const T a, const T precision = 1e-6f) {\n\t\treturn !approximatelyZero(a);\n\t} // end method\t\t\n\t\n\t// Source: The Art of Computer Programming by Knuth\n\n\t// [TODO] It seems these functions break down when one operator is zero (0).\n\t// [TODO] Those function may not work with infinity!\n\n\ttemplate<typename T>\n\tstatic bool approximatelyEqual(const T a, const T b, const T precision = 1e-6f) {\n\t\treturn std::abs(a - b) <= \n\t\t\t\t((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * precision);\n\t} // end method\t\n\t\n\ttemplate<typename T>\n\tstatic bool notApproximatelyEqual(const T a, const T b, const T precision = 1e-6f) {\n\t\treturn !approximatelyEqual(a, b, precision);\n\t} // end method\t\t\n\t\n\ttemplate<typename T>\n\tstatic bool definitelyGreaterThan(const T a, const T b, const T precision = 1e-6f) {\n\t\treturn (a - b) > \n\t\t\t\t((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * precision);\n\t} // end method\n\n\ttemplate<typename T> // added by Jucemar. Check if is correct\n\tstatic bool definitelyGreaterEqualThan(const T a, const T b, const T precision = 1e-6f) {\n\t\treturn (a - b) >= \n\t\t\t\t((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * precision);\n\t} // end method\n\ttemplate<typename T>\n\tstatic bool definitelyLessThan(const T a, const T b, const T precision = 1e-6f) {\n\t\treturn (b - a) > \n\t\t\t\t((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * precision);\n\t} // end method\n\n\tstatic bool isInit(const float value) {return isInit<float>(value);}\n\tstatic bool isInit(const double value) {return isInit<double>(value);}\n\n\tstatic bool isUninit(const float value) {return isUninit<float>(value);}\n\tstatic bool isUninit(const double value) {return isUninit<double>(value);}\n\n\tstatic bool isInfinity(const float value) {return isInfinity<float>(value);}\n\tstatic bool isInfinity(const double value) {return isInfinity<double>(value);}\n\n\tstatic int round(const float value, const RoundingStrategy roudingStrategy) {return round<float, int>(value, roudingStrategy);}\n\tstatic long round(const double value, const RoundingStrategy roudingStrategy) {return round<double, long>(value, roudingStrategy);}\n\n\tstatic Rsyn::Infinity getInfinity() {return Rsyn::Infinity();}\n\tstatic Rsyn::Uninit getUninit() {return Rsyn::Uninit();}\n\nprivate:\n\n\ttemplate<typename T, typename R> inline\n\tstatic\n\tR round(const T value, const RoundingStrategy roudingStrategy) {\n\t\tswitch (roudingStrategy) {\n\t\t\tcase ROUND_DOWN:    return (R) std::floor(value);\n\t\t\tcase ROUND_UP:      return (R) std::ceil (value);\n\t\t\tcase ROUND_NEAREST: return (R) std::round(value);\n\t\t\tdefault: assert(false); return 0;\n\t\t} // end switch\n\t} // end method\n\n\ttemplate<typename T>\n\tstatic bool isInit(const T value) {\n\t\treturn !std::isnan(value);\n\t} // end method\n\n\ttemplate<typename T>\n\tstatic bool isUninit(const T value) {\n\t\treturn std::isnan(value);\n\t} // end method\n\n\ttemplate<typename T>\n\tstatic bool isInfinity(const T value) {\n\t\treturn std::isinf(value);\n\t} // end method\n\n}; // end class\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Json.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_JSON_H\n#define RSYN_JSON_H\n\n#include \"rsyn/3rdparty/json/json.hpp\"\n\nnamespace Rsyn {\ntypedef nlohmann::json Json;\n} // end namespace\n\n#endif /* JSON_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/MD5.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/* MD5\n converted to C++ class by Frank Thilo (thilo@unix-ag.org)\n for bzflag (http://www.bzflag.org)\n \n   based on:\n \n   md5.h and md5.c\n   reference implementation of RFC 1321\n \n   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All\nrights reserved.\n \nLicense to copy and use this software is granted provided that it\nis identified as the \"RSA Data Security, Inc. MD5 Message-Digest\nAlgorithm\" in all material mentioning or referencing this software\nor this function.\n \nLicense is also granted to make and use derivative works provided\nthat such works are identified as \"derived from the RSA Data\nSecurity, Inc. MD5 Message-Digest Algorithm\" in all material\nmentioning or referencing the derived work.\n \nRSA Data Security, Inc. makes no representations concerning either\nthe merchantability of this software or the suitability of this\nsoftware for any particular purpose. It is provided \"as is\"\nwithout express or implied warranty of any kind.\n \nThese notices must be retained in any copies of any part of this\ndocumentation and/or software.\n \n*/\n \n#ifndef BZF_MD5_H\n#define BZF_MD5_H\n \n#include <cstring>\n#include <cstdio>\n#include <iostream>\n \n////////////////////////////////////////////////////////////////////////////////\n// Interface\n////////////////////////////////////////////////////////////////////////////////\n\n// a small class for calculating MD5 hashes of strings or byte arrays\n// it is not meant to be fast or secure\n//\n// usage: 1) feed it blocks of uchars with update()\n//      2) finalize()\n//      3) get hexdigest() string\n//      or\n//      MD5(std::string).hexdigest()\n//\n// assumes that char is 8 bit and int is 32 bit\nclass MD5\n{\npublic:\n  typedef unsigned int size_type; // must be 32bit\n \n  MD5();\n  MD5(const std::string& text);\n  void update(const unsigned char *buf, size_type length);\n  void update(const char *buf, size_type length);\n  MD5& finalize();\n  std::string hexdigest() const;\n  friend std::ostream& operator<<(std::ostream&, MD5 md5);\n \nprivate:\n  void init();\n  typedef unsigned char uint1; //  8bit\n  typedef unsigned int uint4;  // 32bit\n  enum {blocksize = 64}; // VC6 won't eat a const static int here\n \n  void transform(const uint1 block[blocksize]);\n  static void decode(uint4 output[], const uint1 input[], size_type len);\n  static void encode(uint1 output[], const uint4 input[], size_type len);\n \n  bool finalized;\n  uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk\n  uint4 count[2];   // 64bit counter for number of bits (lo, hi)\n  uint4 state[4];   // digest so far\n  uint1 digest[16]; // the result\n \n  // low level logic operations\n  static inline uint4 F(uint4 x, uint4 y, uint4 z);\n  static inline uint4 G(uint4 x, uint4 y, uint4 z);\n  static inline uint4 H(uint4 x, uint4 y, uint4 z);\n  static inline uint4 I(uint4 x, uint4 y, uint4 z);\n  static inline uint4 rotate_left(uint4 x, int n);\n  static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n  static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n  static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n  static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n};\n \n////////////////////////////////////////////////////////////////////////////////\n// Implementation\n////////////////////////////////////////////////////////////////////////////////\n\n/* MD5\n converted to C++ class by Frank Thilo (thilo@unix-ag.org)\n for bzflag (http://www.bzflag.org)\n \n   based on:\n \n   md5.h and md5.c\n   reference implemantion of RFC 1321\n \n   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All\nrights reserved.\n \nLicense to copy and use this software is granted provided that it\nis identified as the \"RSA Data Security, Inc. MD5 Message-Digest\nAlgorithm\" in all material mentioning or referencing this software\nor this function.\n \nLicense is also granted to make and use derivative works provided\nthat such works are identified as \"derived from the RSA Data\nSecurity, Inc. MD5 Message-Digest Algorithm\" in all material\nmentioning or referencing the derived work.\n \nRSA Data Security, Inc. makes no representations concerning either\nthe merchantability of this software or the suitability of this\nsoftware for any particular purpose. It is provided \"as is\"\nwithout express or implied warranty of any kind.\n \nThese notices must be retained in any copies of any part of this\ndocumentation and/or software.\n \n*/\n \n// Constants for MD5Transform routine.\n#define S11 7\n#define S12 12\n#define S13 17\n#define S14 22\n#define S21 5\n#define S22 9\n#define S23 14\n#define S24 20\n#define S31 4\n#define S32 11\n#define S33 16\n#define S34 23\n#define S41 6\n#define S42 10\n#define S43 15\n#define S44 21\n \n///////////////////////////////////////////////\n \n// F, G, H and I are basic MD5 functions.\ninline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {\n  return x&y | ~x&z;\n}\n \ninline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {\n  return x&z | y&~z;\n}\n \ninline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {\n  return x^y^z;\n}\n \ninline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {\n  return y ^ (x | ~z);\n}\n \n// rotate_left rotates x left n bits.\ninline MD5::uint4 MD5::rotate_left(uint4 x, int n) {\n  return (x << n) | (x >> (32-n));\n}\n \n// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.\n// Rotation is separate from addition to prevent recomputation.\ninline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;\n}\n \ninline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a + G(b,c,d) + x + ac, s) + b;\n}\n \ninline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a + H(b,c,d) + x + ac, s) + b;\n}\n \ninline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a + I(b,c,d) + x + ac, s) + b;\n}\n \n//////////////////////////////////////////////\n \n// default ctor, just initailize\ninline MD5::MD5()\n{\n  init();\n}\n \n//////////////////////////////////////////////\n \n// nifty shortcut ctor, compute MD5 for string and finalize it right away\ninline MD5::MD5(const std::string &text)\n{\n  init();\n  update(text.c_str(), text.length());\n  finalize();\n}\n \n//////////////////////////////\n \ninline void MD5::init()\n{\n  finalized=false;\n \n  count[0] = 0;\n  count[1] = 0;\n \n  // load magic initialization constants.\n  state[0] = 0x67452301;\n  state[1] = 0xefcdab89;\n  state[2] = 0x98badcfe;\n  state[3] = 0x10325476;\n}\n \n//////////////////////////////\n \n// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.\ninline void MD5::decode(uint4 output[], const uint1 input[], size_type len)\n{\n  for (unsigned int i = 0, j = 0; j < len; i++, j += 4)\n    output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |\n      (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);\n}\n \n//////////////////////////////\n \n// encodes input (uint4) into output (unsigned char). Assumes len is\n// a multiple of 4.\ninline void MD5::encode(uint1 output[], const uint4 input[], size_type len)\n{\n  for (size_type i = 0, j = 0; j < len; i++, j += 4) {\n    output[j] = input[i] & 0xff;\n    output[j+1] = (input[i] >> 8) & 0xff;\n    output[j+2] = (input[i] >> 16) & 0xff;\n    output[j+3] = (input[i] >> 24) & 0xff;\n  }\n}\n \n//////////////////////////////\n \n// apply MD5 algo on a block\ninline void MD5::transform(const uint1 block[blocksize])\n{\n  uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];\n  decode (x, block, blocksize);\n \n  /* Round 1 */\n  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */\n  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */\n  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */\n  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */\n  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */\n  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */\n  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */\n  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */\n  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */\n  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */\n  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */\n  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */\n  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */\n  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */\n  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */\n  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */\n \n  /* Round 2 */\n  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */\n  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */\n  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */\n  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */\n  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */\n  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */\n  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */\n  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */\n  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */\n  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */\n  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */\n  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */\n  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */\n  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */\n  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */\n  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */\n \n  /* Round 3 */\n  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */\n  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */\n  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */\n  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */\n  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */\n  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */\n  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */\n  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */\n  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */\n  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */\n  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */\n  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */\n  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */\n  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */\n  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */\n  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */\n \n  /* Round 4 */\n  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */\n  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */\n  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */\n  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */\n  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */\n  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */\n  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */\n  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */\n  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */\n  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */\n  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */\n  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */\n  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */\n  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */\n  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */\n  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */\n \n  state[0] += a;\n  state[1] += b;\n  state[2] += c;\n  state[3] += d;\n \n  // Zeroize sensitive information.\n  memset(x, 0, sizeof x);\n}\n \n//////////////////////////////\n \n// MD5 block update operation. Continues an MD5 message-digest\n// operation, processing another message block\ninline void MD5::update(const unsigned char input[], size_type length)\n{\n  // compute number of bytes mod 64\n  size_type index = count[0] / 8 % blocksize;\n \n  // Update number of bits\n  if ((count[0] += (length << 3)) < (length << 3))\n    count[1]++;\n  count[1] += (length >> 29);\n \n  // number of bytes we need to fill in buffer\n  size_type firstpart = 64 - index;\n \n  size_type i;\n \n  // transform as many times as possible.\n  if (length >= firstpart)\n  {\n    // fill buffer first, transform\n    memcpy(&buffer[index], input, firstpart);\n    transform(buffer);\n \n    // transform chunks of blocksize (64 bytes)\n    for (i = firstpart; i + blocksize <= length; i += blocksize)\n      transform(&input[i]);\n \n    index = 0;\n  }\n  else\n    i = 0;\n \n  // buffer remaining input\n  memcpy(&buffer[index], &input[i], length-i);\n}\n \n//////////////////////////////\n \n// for convenience provide a verson with signed char\ninline void MD5::update(const char input[], size_type length)\n{\n  update((const unsigned char*)input, length);\n}\n \n//////////////////////////////\n \n// MD5 finalization. Ends an MD5 message-digest operation, writing the\n// the message digest and zeroizing the context.\ninline MD5& MD5::finalize()\n{\n  static unsigned char padding[64] = {\n    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n  };\n \n  if (!finalized) {\n    // Save number of bits\n    unsigned char bits[8];\n    encode(bits, count, 8);\n \n    // pad out to 56 mod 64.\n    size_type index = count[0] / 8 % 64;\n    size_type padLen = (index < 56) ? (56 - index) : (120 - index);\n    update(padding, padLen);\n \n    // Append length (before padding)\n    update(bits, 8);\n \n    // Store state in digest\n    encode(digest, state, 16);\n \n    // Zeroize sensitive information.\n    memset(buffer, 0, sizeof buffer);\n    memset(count, 0, sizeof count);\n \n    finalized=true;\n  }\n \n  return *this;\n}\n \n//////////////////////////////\n \n// return hex representation of digest as string\ninline std::string MD5::hexdigest() const\n{\n  if (!finalized)\n    return \"\";\n \n  char buf[33];\n  for (int i=0; i<16; i++)\n    sprintf(buf+i*2, \"%02x\", digest[i]);\n  buf[32]=0;\n \n  return std::string(buf);\n}\n \n//////////////////////////////\n \ninline std::ostream& operator<<(std::ostream& out, MD5 md5)\n{\n  return out << md5.hexdigest();\n}\n \n//////////////////////////////\n \ninline std::string md5(const std::string str)\n{\n    MD5 md5 = MD5(str);\n \n    return md5.hexdigest();\n}\n\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/util/MemoryUsage.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef MEMORY_USAGE_H\n#define\tMEMORY_USAGE_H\n\n#ifdef __linux__\n#include <sys/time.h>\n#include <sys/resource.h>\n\nclass MemoryUsage {\npublic:\t\n\t// Retrieve memory usage in MB.\n\tstatic int getMemoryUsage() {\n\t\tstruct rusage usage; \n\t\tint ret; \n\t\tret = getrusage(RUSAGE_SELF, &usage);\n\t\treturn usage.ru_maxrss / 1000;\t\t\n\t} // end method\n}; // end class\n\n#else\n\nclass MemoryUsage {\npublic:\n\tstatic int getMemoryUsage() { return 0; }\n}; // end class\n\n#endif\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Proxy.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_PROXY_H\n#define RSYN_PROXY_H\n\nnamespace Rsyn {\n\ntemplate<class T>\nclass Proxy {\nfriend struct std::hash<Rsyn::Proxy<T>>;\nprotected:\n\tT * data;\n\n\tT *operator->() { return data; }\n\tconst T *operator->() const { return data; }\n\n\t// For some reason the compiler allows ElementPointer to be silently casted\n\t// to int, which led to hard to find bugs. Now we explicitly tell the\n\t// compiler to not allow such conversion by making the cast operator\n\t// private.\n\toperator int() const; // not implemented\n\n\t// Returns the pointer to the data stored by this proxy.\n\tT *getData() { return data; }\n\tconst T *getData() const { return data; }\n\npublic:\n\n\tProxy() : data(nullptr) {}\n\tProxy(std::nullptr_t) : data(nullptr) {}\n\tProxy(T * data) : data(data) {}\n\n\tbool operator!() const { return data == nullptr; };\n\toperator bool() const { return data; }\n\n\tbool operator==(const Proxy<T> &other) const { return data == other.data; }\n\tbool operator!=(const Proxy<T> &other) const { return data != other.data; }\n\n\t// Used in map-like data structures.\n\tfriend bool operator<(const Proxy<T> &left, const Proxy<T> &right) {\n\t\t// [IMPORTANT] We don't use the pointer (e) directly to avoid\n\t\t// non-determinism behavior. Note that the pointer address may change\n\t\t// from execution to execution and hence the mapping function may return\n\t\t// elements in different order leading to different results.\n\t\treturn left.data->id < right.data->id;\n\t} // end method\n}; // end class\n\n} // end namespace\n\nnamespace std {\n//! @brief Specialization of hash functor to allow Rsyn objects to be used\n//!        in unordered collections.\ntemplate <typename T>\nstruct hash<Rsyn::Proxy<T>> {\n\tsize_t operator()(const Rsyn::Proxy<T> &proxy) const {\n\t\treturn hash<int>()(proxy.data->id);\n\t} // end operator\n}; // end struct\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/RangeBasedLoop.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef UTIL_RANGEBASEDLOOP_H\n#define\tUTIL_RANGEBASEDLOOP_H\n\n////////////////////////////////////////////////////////////////////////////////\n// Author: Guilherme Flach\n// Date: 2015-02-17\n//\n// Description\n// -----------\n// This class makes it easier to create range-based loops.\n//\n// How To Use It\n// -------------\n// Create a class/struct with the following methods:\n//     1) Object current() {...}\n//     2) void next() {...}\n//     3) bool filter() {...}\n//     4) bool stop() {...}\n//\n// which the following meaning\n//\n//     1) returns the current object in the collection;\n//     2) moves to the next object in the collection;\n//     3) indicates if the current object should be filtered (i.e. not\n//        processed), this class will call next() until filter() returns true\n//        or the end of collection is reached;\n//     4) indicates if we reached the end of the collection.\n//\n// Example\n// -------\n// Traverse only non-zero elements of a vector (i.e. filter out zeros):\n//\n//    // This is the class the user (you) needs to provide to create a\n//    // ranged-based loop.\n//    class NonZeroElementsCollection {\n//    private:\n//        const std::vector<int> &v;\n//        std::size_t index;\n//    public:\n//        NonZeroElementsCollection(const std::vector<int> &v) \n//            : v(v), index(0) {}\n//\n//        int current() {return v[index];}\n//        void next() {index++;}\n//        bool filter() {return current() == 0;}\n//        bool stop() {return index >= v.size();}        \n//    }; // end class\n//\n//    // Give it a nice name...\n//    typedef Range<NonZeroElementsCollection> allNonZeroElements;\n//\n//    // Testing...\n//    int main() {\n//        std::vector<int> v = {0, 1, 0, 2, 0, 3, 4, 0, 0, 0, 5};\n//\n//        for (int value : allNonZeroElements(v)) {\n//            std::cout << value << \" \";\n//        } // end for\n//        std::cout << \"\\n\";\n//\n//        return 1;\n//    } // end function\n//\n////////////////////////////////////////////////////////////////////////////////\n\n////////////////////////////////////////////////////////////////////////////////\n// According to the C++11 standard, the following range-loop statement\n// \n//        for ( declaration : expression ) statement\n//\n// is equivalent to the the following statament\n//\n//        {\n//            auto&& __range = expression;\n//            for (auto __begin = begin-expression,\n//                      __end = end-expression;\n//                 __begin != __end;\n//                 ++__begin\n//            ) {\n//                declaration = *__begin;\n//                statement\n//            }\n//        }\n//\n// So that, we can override the operator != of an iterator to make it\n// return false whenever the stop condition was reached in the begin \n// iterator in code above.\n//\n// Source: http://en.cppreference.com/w/cpp/language/range-for\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate<class Collection>\nclass Range {\nprivate:\n\tCollection collection;\n\n\tstruct RangeIterator {\n\t\tCollection *collection;\n\n\t\tRangeIterator() : collection(nullptr) {}\n\t\tRangeIterator(Collection &collection_) : collection(&collection_) {\n\t\t\twhile (!collection->stop() && collection->filter()) { // stop must be first\n\t\t\t\tcollection->next();\n\t\t\t} // end while\n\t\t} // end constructor\n\n\t\tvoid operator++() { \n\t\t\tdo {\n\t\t\t\tcollection->next();\n\t\t\t} while (!collection->stop() && collection->filter()); // stop must be first\n\t\t} // end method\n\n\t\tbool operator!=(const RangeIterator &) {\n\t\t\treturn !collection->stop();\n\t\t} // end method\n\n\t\tauto operator*() -> decltype(collection->current()) {\n\t\t\treturn collection->current();\n\t\t} // end method\t\n\n\t}; // end class\n\npublic:\n\n\tRange(Collection &&collection) : collection(collection) {}\n\n\tRangeIterator begin() { return RangeIterator(collection); }\n\tRangeIterator end() { return RangeIterator(); /*dummy, not used */}\n}; // end class\t\n\n////////////////////////////////////////////////////////////////////////////////\n// Traverse a collection backwards.\n////////////////////////////////////////////////////////////////////////////////\n\ntemplate <typename Collection>\nclass BackwardsCollection {\nprivate:\n    const Collection &collection;\npublic:\n    explicit BackwardsCollection(const Collection &t) : collection(t) {}\n    typename Collection::const_reverse_iterator begin() const { return collection.rbegin(); }\n    typename Collection::const_reverse_iterator end()   const { return collection.rend(); }\n}; // end class\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Stipple.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_STIPPLE_MASK_H\n#define RSYN_STIPPLE_MASK_H\n\nenum LineStippleMask : std::uint8_t {\n\tLINE_STIPPLE_NONE,\n\tLINE_STIPPLE_SOLID,\n\tLINE_STIPPLE_DASHED\n};\n\nenum FillStippleMask : std::uint8_t {\n\tSTIPPLE_MASK_EMPTY,\n\tSTIPPLE_MASK_FILL,\n\tSTIPPLE_MASK_YACIF1,\n\tSTIPPLE_MASK_YACIF2,\n\tSTIPPLE_MASK_YACIF3,\n\tSTIPPLE_MASK_YACIF4,\n\tSTIPPLE_MASK_YACIF5,\n\tSTIPPLE_MASK_YACIF6,\n\tSTIPPLE_MASK_CROSS,\n\tSTIPPLE_MASK_HALFTONE,\n\tSTIPPLE_MASK_CHESS,\n\tSTIPPLE_MASK_DOT,\n\tSTIPPLE_MASK_DIAGONAL_DOWN_1,\n\tSTIPPLE_MASK_DIAGONAL_DOWN_2,\n\tSTIPPLE_MASK_DIAGONAL_DOWN_3,\n\tSTIPPLE_MASK_DIAGONAL_DOWN_4,\n\tSTIPPLE_MASK_DIAGONAL_DOWN_5,\n\tSTIPPLE_MASK_DIAGONAL_UP_1,\n\tSTIPPLE_MASK_DIAGONAL_UP_2,\n\tSTIPPLE_MASK_DIAGONAL_UP_3,\n\tSTIPPLE_MASK_DIAGONAL_UP_4,\n\tSTIPPLE_MASK_DIAGONAL_UP_5,\n\n\tSTIPPLE_MASK_NUM_MASKS\n};\n\nconst unsigned char STIPPLE_MASKS[ STIPPLE_MASK_NUM_MASKS ][4*32] = {\n\n{\t// Empty\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0 },\n\n{\t// Fill, no stipple\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255,\n255, \t255, \t255, \t255 },\n\n{\t// Yacif Texture 1\n192, \t192, \t192, \t192,\n64, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12,\n192, \t192, \t192, \t192,\n192, \t192, \t192, \t192,\n12, \t12, \t12, \t12,\n12, \t12, \t12, \t12 },\n\n{ // Yacif Texture 2\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n240, \t240, \t240, \t240,\n15, \t15, \t15, \t15,\n15, \t15, \t15, \t15,\n15, \t15, \t15, \t15,\n15, \t15, \t15, \t15,\n15, \t240, \t0, \t0,\n15, \t240, \t0, \t0,\n15, \t240, \t0, \t0,\n15, \t240, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n15, \t255, \t255, \t15,\n15, \t255, \t255, \t15,\n15, \t255, \t255, \t15,\n15, \t255, \t255, \t15,\n15, \t255, \t255, \t15,\n15, \t15, \t15, \t15,\n15, \t15, \t15, \t15,\n15, \t15, \t15, \t15,\n15, \t15, \t15, \t0,\n15, \t15, \t15, \t0,\n15, \t15, \t15, \t0,\n15, \t15, \t15, \t0 },\n\n{ // Yacif Texture 3\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n0, \t123, \t0, \t123,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0,\n123, \t0, \t123, \t0 },\n\n{\t// Yacif Texture 4 (not implemented yet)\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1,\n1, \t1, \t1, \t1 },\n\n{\t// Yacif Texture 5\n0, \t0, \t0, \t0,\n128, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240,\n255, \t15, \t255, \t240 },\n\n{\t// Yacif Texture 6\n0, \t0, \t255, \t240,\n0, \t0, \t255, \t240,\n0, \t0, \t255, \t240,\n0, \t0, \t255, \t240,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0,\n0, \t0, \t0, \t0 },\n\n{ // Cross\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187,\n85, \t85, \t85, \t85,\n238, \t238, \t238, \t238,\n85, \t85, \t85, \t85,\n187, \t187, \t187, \t187 },\n\n{ // Halftone\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170,\n85,     85,     85,     85,\n170,    170,    170,    170 },\n\n{ // Chess\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102,\n153, \t153, \t153, \t153,\n153, \t153, \t153, \t153,\n102, \t102, \t102, \t102,\n102, \t102, \t102, \t102 },\n\n{ // dot\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68,\n0, \t0, \t0, \t0,\n17, \t17, \t17, \t17,\n0, \t0, \t0, \t0,\n68, \t68, \t68, \t68 },\n\n{ // Diagonal Down 1\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170 },\n\n{ // Diagonal Down 2\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68,\n34, \t34, \t34, \t34,\n17, \t17, \t17, \t17,\n136, \t136, \t136, \t136,\n68, \t68, \t68, \t68 },\n\n{ // Diagonal Down 3\n8, \t8, \t8, \t8,\n4, \t4, \t4, \t4,\n2, \t2, \t2, \t2,\n1, \t1, \t1, \t1,\n128, \t128, \t128, \t128,\n64, \t64, \t64, \t64,\n32, \t32, \t32, \t32,\n16, \t16, \t16, \t16,\n8, \t8, \t8, \t8,\n4, \t4, \t4, \t4,\n2, \t2, \t2, \t2,\n1, \t1, \t1, \t1,\n128, \t128, \t128, \t128,\n64, \t64, \t64, \t64,\n32, \t32, \t32, \t32,\n16, \t16, \t16, \t16,\n8, \t8, \t8, \t8,\n4, \t4, \t4, \t4,\n2, \t2, \t2, \t2,\n1, \t1, \t1, \t1,\n128, \t128, \t128, \t128,\n64, \t64, \t64, \t64,\n32, \t32, \t32, \t32,\n16, \t16, \t16, \t16,\n8, \t8, \t8, \t8,\n4, \t4, \t4, \t4,\n2, \t2, \t2, \t2,\n1, \t1, \t1, \t1,\n128, \t128, \t128, \t128,\n64, \t64, \t64, \t64,\n32, \t32, \t32, \t32,\n16, \t16, \t16, \t16 },\n\n{ // Diagonal Down 4\n0, \t128, \t0, \t128,\n0, \t64, \t0, \t64,\n0, \t32, \t0, \t32,\n0, \t16, \t0, \t16,\n0, \t8, \t0, \t8,\n0, \t4, \t0, \t4,\n0, \t2, \t0, \t2,\n0, \t1, \t0, \t1,\n128, \t0, \t128, \t0,\n64, \t0, \t64, \t0,\n32, \t0, \t32, \t0,\n16, \t0, \t16, \t0,\n8, \t0, \t8, \t0,\n4, \t0, \t4, \t0,\n2, \t0, \t2, \t0,\n1, \t0, \t1, \t0,\n0, \t128, \t0, \t128,\n0, \t64, \t0, \t64,\n0, \t32, \t0, \t32,\n0, \t16, \t0, \t16,\n0, \t8, \t0, \t8,\n0, \t4, \t0, \t4,\n0, \t2, \t0, \t2,\n0, \t1, \t0, \t1,\n128, \t0, \t128, \t0,\n64, \t0, \t64, \t0,\n32, \t0, \t32, \t0,\n16, \t0, \t16, \t0,\n8, \t0, \t8, \t0,\n4, \t0, \t4, \t0,\n2, \t0, \t2, \t0,\n1, \t0, \t1, \t0 },\n\n{ // Diagonal Down 5\n0, \t0, \t128, \t0,\n0, \t0, \t64, \t0,\n0, \t0, \t32, \t0,\n0, \t0, \t16, \t0,\n0, \t0, \t8, \t0,\n0, \t0, \t4, \t0,\n0, \t0, \t2, \t0,\n0, \t0, \t1, \t0,\n0, \t0, \t0, \t128,\n0, \t0, \t0, \t64,\n0, \t0, \t0, \t32,\n0, \t0, \t0, \t16,\n0, \t0, \t0, \t8,\n0, \t0, \t0, \t4,\n0, \t0, \t0, \t2,\n0, \t0, \t0, \t1,\n128, \t0, \t0, \t0,\n64, \t0, \t0, \t0,\n32, \t0, \t0, \t0,\n16, \t0, \t0, \t0,\n8, \t0, \t0, \t0,\n4, \t0, \t0, \t0,\n2, \t0, \t0, \t0,\n1, \t0, \t0, \t0,\n0, \t128, \t0, \t0,\n0, \t64, \t0, \t0,\n0, \t32, \t0, \t0,\n0, \t16, \t0, \t0,\n0, \t8, \t0, \t0,\n0, \t4, \t0, \t0,\n0, \t2, \t0, \t0,\n0, \t1, \t0, \t0 },\n\n\n\n\n\n\n\n{ // Diagonal Up 1\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85,\n170, \t170, \t170, \t170,\n85, \t85, \t85, \t85 },\n\n{ // Diagonal Up 2\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34,\n68, \t68, \t68, \t68,\n136, \t136, \t136, \t136,\n17, \t17, \t17, \t17,\n34, \t34, \t34, \t34 },\n\n{ // Diagonal Up 3\n16, \t16, \t16, \t16,\n32, \t32, \t32, \t32,\n64, \t64, \t64, \t64,\n128, \t128, \t128, \t128,\n1, \t1, \t1, \t1,\n2, \t2, \t2, \t2,\n4, \t4, \t4, \t4,\n8, \t8, \t8, \t8,\n16, \t16, \t16, \t16,\n32, \t32, \t32, \t32,\n64, \t64, \t64, \t64,\n128, \t128, \t128, \t128,\n1, \t1, \t1, \t1,\n2, \t2, \t2, \t2,\n4, \t4, \t4, \t4,\n8, \t8, \t8, \t8,\n16, \t16, \t16, \t16,\n32, \t32, \t32, \t32,\n64, \t64, \t64, \t64,\n128, \t128, \t128, \t128,\n1, \t1, \t1, \t1,\n2, \t2, \t2, \t2,\n4, \t4, \t4, \t4,\n8, \t8, \t8, \t8,\n16, \t16, \t16, \t16,\n32, \t32, \t32, \t32,\n64, \t64, \t64, \t64,\n128, \t128, \t128, \t128,\n1, \t1, \t1, \t1,\n2, \t2, \t2, \t2,\n4, \t4, \t4, \t4,\n8, \t8, \t8, \t8 },\n\n{ // Diagonal Up 4\n1, \t0, \t1, \t0,\n2, \t0, \t2, \t0,\n4, \t0, \t4, \t0,\n8, \t0, \t8, \t0,\n16, \t0, \t16, \t0,\n32, \t0, \t32, \t0,\n64, \t0, \t64, \t0,\n128, \t0, \t128, \t0,\n0, \t1, \t0, \t1,\n0, \t2, \t0, \t2,\n0, \t4, \t0, \t4,\n0, \t8, \t0, \t8,\n0, \t16, \t0, \t16,\n0, \t32, \t0, \t32,\n0, \t64, \t0, \t64,\n0, \t128, \t0, \t128,\n1, \t0, \t1, \t0,\n2, \t0, \t2, \t0,\n4, \t0, \t4, \t0,\n8, \t0, \t8, \t0,\n16, \t0, \t16, \t0,\n32, \t0, \t32, \t0,\n64, \t0, \t64, \t0,\n128, \t0, \t128, \t0,\n0, \t1, \t0, \t1,\n0, \t2, \t0, \t2,\n0, \t4, \t0, \t4,\n0, \t8, \t0, \t8,\n0, \t16, \t0, \t16,\n0, \t32, \t0, \t32,\n0, \t64, \t0, \t64,\n0, \t128, \t0, \t128 },\n\n{ // Diagonal Up 5\n0, \t1, \t0, \t0,\n0, \t2, \t0, \t0,\n0, \t4, \t0, \t0,\n0, \t8, \t0, \t0,\n0, \t16, \t0, \t0,\n0, \t32, \t0, \t0,\n0, \t64, \t0, \t0,\n0, \t128, \t0, \t0,\n1, \t0, \t0, \t0,\n2, \t0, \t0, \t0,\n4, \t0, \t0, \t0,\n8, \t0, \t0, \t0,\n16, \t0, \t0, \t0,\n32, \t0, \t0, \t0,\n64, \t0, \t0, \t0,\n128, \t0, \t0, \t0,\n0, \t0, \t0, \t1,\n0, \t0, \t0, \t2,\n0, \t0, \t0, \t4,\n0, \t0, \t0, \t8,\n0, \t0, \t0, \t16,\n0, \t0, \t0, \t32,\n0, \t0, \t0, \t64,\n0, \t0, \t0, \t128,\n0, \t0, \t1, \t0,\n0, \t0, \t2, \t0,\n0, \t0, \t4, \t0,\n0, \t0, \t8, \t0,\n0, \t0, \t16, \t0,\n0, \t0, \t32, \t0,\n0, \t0, \t64, \t0,\n0, \t0, \t128, \t0 }\n\n};\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/util/Stopwatch.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef STOPWATCH_H\n#define STOPWATCH_H\n\n// UFRGS - Guilherme Flach\n// This class was based on http://pocoproject.org/.\n\n#if _WIN32\n#include <ctime>\n#include <windows.h>\n#else\n#include <time.h>\n#include <unistd.h>\n#include <sys/time.h>\n#include <sys/times.h>\n#endif\n\n#include <cmath>\n#include <sstream>\nusing std::ostringstream;\n#include <string>\nusing std::string;\n#include <iomanip>\nusing std::setfill;\nusing std::setw;\n\nclass Stopwatch {\n\tprivate:\n\n\t\t#if _WIN32\n\n\t\t#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)\n\t\t  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64\n\t\t#else\n\t\t  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL\n\t\t#endif\n\n\t\tstruct timezone {\n\t\t  int  tz_minuteswest; /* minutes W of Greenwich */\n\t\t  int  tz_dsttime;     /* type of dst correction */\n\t\t};\n\n\t\tinline int gettimeofday(struct timeval *tv, struct timezone *tz) {\n\t\t  FILETIME ft;\n\t\t  unsigned __int64 tmpres = 0;\n\t\t  static int tzflag;\n\n\t\t  if (NULL != tv) {\n\t\t\tGetSystemTimeAsFileTime(&ft);\n\n\t\t\ttmpres |= ft.dwHighDateTime;\n\t\t\ttmpres <<= 32;\n\t\t\ttmpres |= ft.dwLowDateTime;\n\n\t\t\t/*converting file time to unix epoch*/\n\t\t\ttmpres -= DELTA_EPOCH_IN_MICROSECS;\n\t\t\ttmpres /= 10;  /*convert into microseconds*/\n\t\t\ttv->tv_sec = (long)(tmpres / 1000000UL);\n\t\t\ttv->tv_usec = (long)(tmpres % 1000000UL);\n\t\t  }\n\n\t\t  if (NULL != tz) {\n\t\t\tif (!tzflag) {\n\t\t\t  _tzset();\n\t\t\t  tzflag++;\n\t\t\t}\n\t\t\ttz->tz_minuteswest = _timezone / 60;\n\t\t\ttz->tz_dsttime = _daylight;\n\t\t  }\n\n\t\t  return 0;\n\t\t} // end function\n\n\t\t#endif\n\n\t\tbool clsRunning;\n\t\t\n\t\tdouble clsElapsedTime;\n\t\ttimeval clsCheckpoint;\n\t\t\n\t\tvoid update() {\n\t\t\tgettimeofday( &clsCheckpoint, NULL );\n\t\t} // end method\n\t\t\n\t\tdouble computeElapsedTimeWithRespectToCurrentTime() const {\n\t\t\ttimeval t;\n\t\t\tgettimeofday( &t, NULL );\n\t\t\t\n\t\t\treturn \n\t\t\t\t( t.tv_sec  - clsCheckpoint.tv_sec  ) + \n\t\t\t\t( t.tv_usec - clsCheckpoint.tv_usec )/1000000.0;\n\t\t} // end method\n\t\t\n\tpublic:\n\t\n\t\tStopwatch() { reset(); }\n\n\t\tvoid reset() {\n\t\t\tclsElapsedTime = 0;\n\t\t\tclsRunning = false;\n\t\t} // end method\n\n\t\tvoid start() {\n\t\t\tclsRunning = true;\n\t\t\tupdate();\n\t\t} // end method\n\n\t\tvoid restart() {\n\t\t\treset();\n\t\t\tstart();\n\t\t} // end method\n\n\t\tvoid stop() {\n\t\t\tclsRunning = false;\n\t\t\tclsElapsedTime += computeElapsedTimeWithRespectToCurrentTime();\n\t\t} // end method\n\n\t\tdouble getElapsedTime() const {\n\t\t\tif ( clsRunning )\n\t\t\t\treturn computeElapsedTimeWithRespectToCurrentTime();\n\t\t\telse\n\t\t\t\treturn clsElapsedTime; \n\t\t} // end method\n\t\t\n\t\tstring getFormattedTime() const {\n\t\t\tconst double hours = getElapsedTime()/(60*60);\n\t\t\tconst double minutes = (hours - floor(hours)) * 60;\n\t\t\tconst double seconds = (minutes - floor(minutes)) * 60;\n\t\t\t\n\t\t\tconst int hh = (int) hours;\n\t\t\tconst int mm = (int) minutes;\n\t\t\tconst int ss = (int) seconds;\n\t\t\t\n\t\t\tostringstream oss;\n\t\t\toss << setfill('0') << hh << \":\" << setw(2) << mm << \":\" << setw(2) << ss;\n\t\t\t\n\t\t\treturn oss.str();\n\t\t} // end method\n\t\t\n\t\tbool isRunning() const { return clsRunning; }\n\t\t\n}; // end class\n\n// -----------------------------------------------------------------------------\n\nclass StopwatchGuard {\nprivate:\n\tStopwatch &clsStopwatch;\npublic:\n\tStopwatchGuard(Stopwatch &stopwatch) : clsStopwatch(stopwatch) {clsStopwatch.start(); }\n\t~StopwatchGuard() { clsStopwatch.stop(); }\n}; // end class\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/util/String.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef UTIL_STRING_H\n#define\tUTIL_STRING_H\n\n#include <string>\n#include <iostream>\n#include <iomanip>\n#include <sstream>\n\nclass String {\npublic:\n\t\n\ttemplate< typename T >\n\tstatic bool parse(const std::string &str, T &data) {\n\t\tstd::istringstream iss( str );\n\t\tiss >> data;\n\t\treturn !iss.fail();\n\t} // end function\t\n\n\tstatic bool parse(const std::string &str, std::string &data) { \n\t\treturn (data=str, true); \n\t} // end function\n\t\n\tstatic void printCentered(std::ostream &out, const std::string &text, const int width = 80) {\n\t\t// DOES NOT WORKS WHEN TEXT HAS \\t\n\t\tconst int start = (width - text.size()) / 2;\n\t\tif ( start > 0 )\n\t\t\tout << std::setw(start) << std::setfill( ' ' ) << ' ';\n\t\tout << text;\n\t} // end function\t\t\n\t\n}; // end class\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/ThreadPool.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef UTIL_THREAD_POOL_H\n#define UTIL_THREAD_POOL_H\n\n////////////////////////////////////////////////////////////////////////////////\n// Guilherme Flach: 2012-02-24\n//\n// This code was an adaptation from\n// https://github.com/progschj/ThreadPool/\n//\n// The main change I did was to make to task not required to return a \n// std::future and added a method to wait for all threads to finish. Note that \n// with std::future one did not need a wait method. But this was weird when the\n// task should not return anything (i.e. void).\n////////////////////////////////////////////////////////////////////////////////\n\n////////////////////////////////////////////////////////////////////////////////\n// Example\n////////////////////////////////////////////////////////////////////////////////\n//\n//\tThreadPool pool;\n//\tfor (int i = 0; i < 10; ++i) {\n//\t\tpool.addTask([i] {\n//\t\t\tstd::cout << \"hello \" << i << std::endl;\n//\t\t\tstd::this_thread::sleep_for(std::chrono::seconds(1));\n//\t\t\tstd::cout << \"world \" << i << std::endl;\n//\t\t});\n//\t} // end for\n//\n//\tpool.wait(); // wait for all tasks to be finished\n//\n////////////////////////////////////////////////////////////////////////////////\n\n#include <vector>\n#include <queue>\n#include <memory>\n#include <thread>\n#include <mutex>\n#include <condition_variable>\n#include <future>\n#include <functional>\n#include <stdexcept>\n\nclass ThreadPool {\npublic:\n\n\t// Start the thread pool with the number of available threads in the\n\t// computer (using std::thread::hardware_concurrency()). If it fails to\n\t// query the number of threads, the thread pool is initialized with 2 \n\t// threads\n\tThreadPool();\n\n\t// Start the thread pool with the specified number of threads.\n\tThreadPool(const std::size_t numThreads);\n\n\t// Add a task.\n\ttemplate<class F, class... Args>\n\tvoid addTask(F&& f, Args&&... args);\n\n\t// Wait for all threads to finish.\n\tvoid wait();\n\t\n\t// Get the number of working threads.\n\tstd::size_t getNumThreads() const { return workers.size(); }\n\t\n\t// Stop all threads.\n\t~ThreadPool();\n\nprivate:\n\t// need to keep track of threads so we can join them\n\tstd::vector<std::thread> workers;\n\t// the task queue\n\tstd::queue<std::function<void()>> tasks;\n\n\t// synchronization\n\tstd::mutex queue_mutex;\n\tstd::condition_variable condition;\n\tstd::condition_variable condition_wait_task;\n\tbool stop;\n\tstd::atomic<int> running;\n\n\t// Manage workers.\n\tvoid startWorkers(const std::size_t numThreads);\n\tvoid stopWorkers();\n}; // end class\n\n// -----------------------------------------------------------------------------\n\ninline ThreadPool::ThreadPool(const std::size_t numThreads) {\n\tstartWorkers(numThreads);\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline ThreadPool::ThreadPool() {\n\tstartWorkers(std::max(2u, std::thread::hardware_concurrency()));\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void ThreadPool::startWorkers(const std::size_t numThreads) {\n\tstop = false;\n\trunning = 0;\n\n\tfor (std::size_t i = 0; i < numThreads; i++) {\n\t\tworkers.emplace_back([this] {\n\t\t\twhile (true) {\n\t\t\t\tstd::function<void() > task;\n\n\t\t\t\t{ // mutual exclusion block\n\t\t\t\t\tstd::unique_lock<std::mutex> lock(queue_mutex);\n\t\t\t\t\tcondition.wait(lock, [this] {return stop || !tasks.empty();});\n\t\t\t\t\tif (stop && tasks.empty())\n\t\t\t\t\t\treturn;\n\t\t\t\t\ttask = std::move(tasks.front());\n\t\t\t\t\ttasks.pop();\n\t\t\t\t} // end block\n\n\t\t\t\trunning++;\n\t\t\t\ttask();\n\t\t\t\trunning--;\n\t\t\t\tcondition_wait_task.notify_one();\n\t\t\t} // end while\n\t\t});\n\t} // end method\t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void ThreadPool::stopWorkers() {\n\t{ // mutual exclusion block\n\t\tstd::unique_lock<std::mutex> lock(queue_mutex);\n\t\tstop = true;\n\t} // end block\n\n\tcondition.notify_all();\n\tfor (std::thread &worker : workers) {\n\t\tworker.join();\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\ntemplate<class F, class... Args>\nvoid ThreadPool::addTask(F&& f, Args&&... args) {\n\tauto task = std::make_shared<std::packaged_task<void()>>(\n\t\t\tstd::bind(std::forward<F>(f), std::forward<Args>(args)...));\n\n\t{ // mutual exclusion block\n\t\tstd::unique_lock<std::mutex> lock(queue_mutex);\n\n\t\t// don't allow enqueueing after stopping the pool\n\t\tif (stop) {\n\t\t\tthrow std::runtime_error(\"Adding a task on a stopped ThreadPool.\");\n\t\t} // end if\n\n\t\ttasks.emplace([task](){(*task)();});\n\t} // end block\n\tcondition.notify_one();\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline void ThreadPool::wait() {\n\tstd::unique_lock<std::mutex> lock(queue_mutex);\n\tcondition_wait_task.wait(lock, [this] {return running == 0;});\t\t\n} // end method\n\n// -----------------------------------------------------------------------------\n\ninline ThreadPool::~ThreadPool() {\n\tstopWorkers();\n} // end destructor\n\n#endif"
  },
  {
    "path": "rsyn/src/rsyn/util/TristateFlag.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_TRISTATE_FLAG_H\n#define RSYN_TRISTATE_FLAG_H\n\nnamespace Rsyn {\n\nclass TristateFlag {\nprivate:\n\tbool specified : 1;\n\tbool flag : 1;\n\npublic:\n\n\tTristateFlag() : specified(false), flag(false) {}\n\tTristateFlag(const bool value) : specified(true), flag(value) {}\n\n\tbool get() const {\n\t\treturn flag;\n\t} // end method\n\n\tvoid set(const bool value) {\n\t\tspecified = true;\n\t\tflag = value;\n\t} // end method\n\n\tvoid clear() {\n\t\tspecified = false;\n\t\tflag = false;\n\t} // end method\n\n\tbool isSpecified() const {\n\t\treturn specified;\n\t} // end method\n\n\tbool isNotSpecified() const {\n\t\treturn !specified;\n\t} // end method\n\n\toperator bool() const { \n\t\treturn get();\n\t} // end method\n}; // end class\n\n} // end namespace\n\n#endif \n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/Units.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_INTERNAL_UNITS_H\n#define RSYN_INTERNAL_UNITS_H\n\n#include <cassert>\n#include <cmath>\n\nnamespace Rsyn {\n\nenum Measure {\n\tMEASURE_INVALID = -1,\n\t\n\tMEASURE_POWER,       // mW\n\tMEASURE_CURRENT,     // mA\n\tMEASURE_CAPACITANCE, // fF\n\tMEASURE_RESISTANCE,  // kOhm\n\tMEASURE_TIME,        // ps     Note: Time(ps) = Resistance(kOhm) * Capacitance(fF)\n\tMEASURE_DISTANCE,    // dbu    Note: no prefix, not measured in meters\n\tMEASURE_VOLTAGE,     // V      Note: no prefix\n\t\n\tNUM_MEASURES\n}; // end enum\n\nenum UnitPrefix {\n\tYOCTO = -24,\n\tZEPTO = -21,\n\tATTO  = -18,\n\tFEMTO = -15,\n\tPICO  = -12,\n\tNANO  = -9,\n\tMICRO = -6,\n\tMILLI = -3,\n\tCENTI = -2,\n\tDECI  = -1,\n\tNO_UNIT_PREFIX = 0,\n\tDEKA  = 1,\n\tHECTO = 2,\n\tKILO  = 3,\n\tMEGA  = 6,\n\tGIGA  = 9,\n\tTERA  = 12,\n\tPETA  = 15,\n\tEXA   = 18,\n\tZETTA = 21,\n\tYOTTA = 24\n}; // end enum\n\nclass Units {\npublic:\n\t\n\tstatic UnitPrefix getInternalUnitPrefix(const Measure measure) {\n\t\tswitch (measure) {\n\t\t\tcase MEASURE_POWER: return MILLI;\n\t\t\tcase MEASURE_CURRENT: return MILLI;\n\t\t\tcase MEASURE_CAPACITANCE: return FEMTO;\n\t\t\tcase MEASURE_RESISTANCE: return KILO;\n\t\t\tcase MEASURE_TIME: return PICO;\n\t\t\tcase MEASURE_DISTANCE: return NO_UNIT_PREFIX;\n\t\t\tcase MEASURE_VOLTAGE: return NO_UNIT_PREFIX;\n\t\t\tdefault: assert(false);\n\t\t} // end switch\n\t\treturn NO_UNIT_PREFIX; // just for warning sake\n\t} // end method\n\t\n\tstatic std::string getMeasureSymbol(const Measure measure) {\n\t\tswitch (measure) {\n\t\t\tcase MEASURE_POWER: return \"W\";\n\t\t\tcase MEASURE_CAPACITANCE: return \"C\";\n\t\t\tcase MEASURE_CURRENT: return \"A\";\n\t\t\tcase MEASURE_RESISTANCE: return \"Ohm\";\n\t\t\tcase MEASURE_TIME: return \"s\";\n\t\t\tcase MEASURE_DISTANCE: return \"dbu\";\n\t\t\tcase MEASURE_VOLTAGE: return \"V\";\n\t\t\tdefault: assert(false);\n\t\t} // end switch\n\t\treturn \"\"; // just for warning sake\t\t\n\t} // end method\n\t\n\tstatic std::string getUnitPrefixSymbol(const UnitPrefix prefix) {\n\t\tswitch (prefix) {\n\t\t\tcase YOCTO : return \"y\";\n\t\t\tcase ZEPTO : return \"z\";\n\t\t\tcase ATTO  : return \"a\";\n\t\t\tcase FEMTO : return \"f\";\n\t\t\tcase PICO  : return \"p\";\n\t\t\tcase NANO  : return \"n\";\n\t\t\tcase MICRO : return \"u\";\n\t\t\tcase MILLI : return \"m\";\n\t\t\tcase CENTI : return \"c\";\n\t\t\tcase DECI  : return \"d\";\n\t\t\tcase NO_UNIT_PREFIX : return \"\";\n\t\t\tcase DEKA  : return \"da\";\n\t\t\tcase HECTO : return \"h\";\n\t\t\tcase KILO  : return \"k\";\n\t\t\tcase MEGA  : return \"M\";\n\t\t\tcase GIGA  : return \"G\";\n\t\t\tcase TERA  : return \"T\";\n\t\t\tcase PETA  : return \"P\";\n\t\t\tcase EXA   : return \"E\";\n\t\t\tcase ZETTA : return \"Z\";\n\t\t\tcase YOTTA : return \"Y\";\t\t\n\t\t\tdefault : assert(false);\n\t\t} // end switch\n\t\treturn \"\";  // just for warning sake\n\t} // end method\n\n\t//! @brief Returns the default unit string given a measure. For instance,\n\t//!        return \"fC\" for capacitance and \"mW\" for power.\n\tstatic std::string getDefaultInternalUnitString(const Measure measure) {\n\t\treturn getUnitPrefixSymbol(getInternalUnitPrefix(measure)) + getMeasureSymbol(measure);\n\t} // end method\n\n\tstatic double convertUnits(\n\t\t\tconst double sourceValue,\n\t\t\tconst UnitPrefix sourceUnitPrefix, \n\t\t\tconst UnitPrefix targetUnitPrefix) {\n\t\treturn sourceValue * std::pow(10, sourceUnitPrefix - targetUnitPrefix);\n\t} // end method\n\t\n\tstatic double convertToInternalUnits(\n\t\t\tconst Measure measure, \n\t\t\tconst double sourceValue,\n\t\t\tconst UnitPrefix sourceUnitPrefix) {\n\t\tconst UnitPrefix targetUnitPrefix = getInternalUnitPrefix(measure);\n\t\treturn convertUnits(sourceValue, sourceUnitPrefix, targetUnitPrefix);\n\t} // end method\n\n\tstatic double convertFromInternalUnits(\n\t\t\tconst Measure measure,\n\t\t\tconst double sourceValue,\n\t\t\tconst UnitPrefix targetUnitPrefix) {\n\t\tconst UnitPrefix sourceUnitPrefix = getInternalUnitPrefix(measure);\n\t\treturn convertUnits(sourceValue, sourceUnitPrefix, targetUnitPrefix);\n\t} // end method\n\t\n}; // end class\n\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/dbu.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_DBU_H\n#define RSYN_DBU_H\n\n#include <cstdint>\n#include <cmath>\n\n#include <algorithm>\nusing std::max;\nusing std::min;\n#include <ostream>\nusing std::ostream;\n\n#include \"dim.h\"\n\n// -----------------------------------------------------------------------------\n\ntypedef std::int64_t DBU;\ntypedef double FloatingPointDBU;\n\n// -----------------------------------------------------------------------------\n\n#define MAKE_SELF_OPERATOR( OP ) \\\n\tinline void operator OP ( const DBUxy right ) { x OP right.x; y OP right.y; }\n\n#define MAKE_OPERATOR( OP ) \\\n\tinline DBUxy operator OP ( const DBUxy v0, const DBUxy v1 ) { \\\n\t\treturn DBUxy( v0.x OP v1.x, v0.y OP v1.y ); \\\n\t}\n\n#define MAKE_FUNCTION_1( FUNC ) \\\n\tinline DBUxy FUNC ( const DBUxy v ) { \\\n\t\treturn DBUxy( FUNC (v.x), FUNC (v.y) ); \\\n\t}\n\n#define MAKE_FUNCTION_2( FUNC ) \\\n\tinline DBUxy FUNC ( const DBUxy v0, const DBUxy v1 ) { \\\n\t\treturn DBUxy( FUNC (v0.x, v1.x), FUNC (v0.y, v1.y) ); \\\n\t}\n\nstruct DBUxy {\n\tfriend ostream &operator<<( ostream &out, const DBUxy &v ) {\n\t\treturn out << \"(\" << v.x << \", \" << v.y << \")\";\n\t} // end function\n\n\tunion {\n\t\tstruct { DBU x, y; };\n\t\tDBU xy[2];\n\t};\n\n\t// Construtctors.\n\tDBUxy(): x(0), y(0)  {}\n\tDBUxy( const DBU x, const DBU y ) : x(x), y(y) {}\n\n\texplicit DBUxy( const DBU scalar ) : x(scalar), y(scalar) {} // explicit to avoid accidentally assigning to scalar\n\n\t// Operators.\n\tMAKE_SELF_OPERATOR( += );\n\tMAKE_SELF_OPERATOR( -= );\n\tMAKE_SELF_OPERATOR( *= );\n\tMAKE_SELF_OPERATOR( /= );\n\n\tMAKE_SELF_OPERATOR( = );\n\n\tinline const bool operator == ( const DBUxy v ) const {\n\t\treturn x == v.x && y == v.y;\n\t} // end method\n\t\n\tinline const bool operator != ( const DBUxy v ) const {\n\t\treturn x != v.x || y != v.y;\n\t} // end method\n\n\tinline void operator *= ( const FloatingPointDBU scalar) {\n\t\tx = (DBU) (x * scalar);\n\t\ty = (DBU) (y * scalar);\n\t} // end method\n\n\tinline void operator /= ( const FloatingPointDBU scalar) {\n\t\tx = (DBU) (x / scalar);\n\t\ty = (DBU) (y / scalar);\n\t} // end method\n\t\n\t      DBU &operator[](const int dimension)       { return xy[dimension]; }\n\tconst DBU &operator[](const int dimension) const { return xy[dimension]; }\n\n\t// Methods.\n\tFloatingPointDBU norm() const {\n\t\treturn std::sqrt( x*x + y*y );\n\t} // end method\n\n\tDBUxy normalized() const {\n\t\tconst FloatingPointDBU v = norm();\n\t\treturn DBUxy( (DBU) (x/v), (DBU) (y/v) );\n\t} // end method\n\n\tDBUxy safeNormalized() const {\n\t\tconst FloatingPointDBU v = norm();\n\t\tif ( v == 0.0 )\n\t\t\treturn DBUxy(0,0);\n\t\telse\n\t\t\treturn DBUxy( (DBU) (x/v), (DBU) (y/v) );\n\t} // end method\n\n\tvoid apply(const DBU scalar) {\n\t\tx = scalar;\n\t\ty = scalar;\n\t} // end method\n\n\tvoid set(const DBU x, const DBU y ) {\n\t\tthis->x = x;\n\t\tthis->y = y;\n\t} // end method\n\n\tvoid scale(const FloatingPointDBU xScaling, const FloatingPointDBU yScaling){\n\t\tx = (DBU) (x*xScaling);\n\t\ty = (DBU) (y*yScaling);\n\t} // end method\n\n\tvoid scale(const FloatingPointDBU scaling){\n\t\tx = (DBU) (x*scaling);\n\t\ty = (DBU) (y*scaling);\n\t} // end method\n\n\tDBU aggregated() const {\n\t\treturn x + y;\n\t} // end method\n\n\tvoid abs() {\n\t\tx = std::abs(x);\n\t\ty = std::abs(y);\n\t} // end method\n\n\tvoid clear () {\n\t\tx = 0;\n\t\ty = 0;\n\t} // end method\n\n\tstatic DBU computeManhattanDistance(const DBUxy p0, const DBUxy p1) {\n\t\treturn std::abs(p0.x - p1.x) + std::abs(p0.y - p1.y);\n\t} // end method\n\n}; // end struct\n\nMAKE_OPERATOR( + );\nMAKE_OPERATOR( - );\nMAKE_OPERATOR( * );\nMAKE_OPERATOR( / );\n\n// Guilherme Flach - 2017/03/18\n// These template functions were added to resolve ambiguity related to trying to\n// cast int to DBU (aka std::int64_t) or FloatingPointDBU (aka double).\n\ntemplate<typename T>\nDBUxy operator*( const T scalar, const DBUxy v ) {\n\tstatic_assert(std::is_arithmetic<T>::value,\n\t\t\t\"Arithmetic value required.\");\n\tstatic_assert(std::is_integral<T>::value || std::is_floating_point<T>::value,\n\t\t\t\"Integer or floating point required.\");\n\n\t// Cast must be performed after the multiplication to avoid wrong results\n\t// when the scaling factor is in the (0, 1) range.\n\treturn DBUxy( (DBU) (v.x * scalar), (DBU) (v.y * scalar) );\n} // end method\n\ntemplate<typename T>\nDBUxy operator*( const DBUxy v, const T scalar ) {\n\treturn scalar*v;\n} // end method\n\ntemplate<typename T>\nDBUxy operator/( const T scalar, const DBUxy v ) {\n\tstatic_assert(std::is_arithmetic<T>::value, \n\t\t\t\"Arithmetic value required.\");\n\tstatic_assert(std::is_integral<T>::value || std::is_floating_point<T>::value,\n\t\t\t\"Integer or floating point required.\");\n\n\t// Cast must be performed after the division to avoid wrong results\n\t// when the scaling factor is in the (0, 1) range.\n\treturn DBUxy( (DBU) (v.x / scalar), (DBU) (v.y / scalar) );\n} // end method\n\ntemplate<typename T>\nDBUxy operator/( const DBUxy v, const T scalar ) {\n\treturn scalar/v;\n} // end method\n\nMAKE_FUNCTION_2(max);\nMAKE_FUNCTION_2(min);\n\n// Unary operators.\ninline DBUxy operator-( const DBUxy value ) {\n\treturn DBUxy( -value.x, -value.y );\n} // end operator\n\ninline DBUxy operator+( const DBUxy value ) {\n\treturn DBUxy( +value.x, +value.y );\n} // end operator\n\n// -----------------------------------------------------------------------------\n// TODO: Move to a better place...\n\ntemplate<typename T> inline T\nroundedUpIntegralDivision(const T numerator, const T denominator) {\n\tstatic_assert(std::is_integral<T>::value, \"Integer required.\");\n    return numerator / denominator + (numerator % denominator? 1 : 0);\n} // end function\n\n// -----------------------------------------------------------------------------\n\n#undef MAKE_OPERATOR\n#undef MAKE_OPERATOR_SCALAR\n#undef MAKE_SELF_OPERATOR\n#undef MAKE_SELF_OPERATOR_SCALAR\n#undef MAKE_FUNCTION_1\n#undef MAKE_FUNCTION_2\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/dim.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_DIM_H\n#define RSYN_DIM_H\n\n#include <string>\n\n// -----------------------------------------------------------------------------\n\n// [NOTE] Although this class use indexing for accessing data members, most of\n//        time the indexing can be resolved in compiling time so that there's\n//        no overhead. When it's not possible to do so, by using indexing an\n//        \"if\" is likely to be avoided which is good for code optimization since\n//        it prevents the pipeline to be flushed.\n\n// -----------------------------------------------------------------------------\n\nenum Dimension {\n\tX = 0,\n\tY = 1\n}; // end enum\n\ninline std::string getDimension(const Dimension dim ) {\n\tswitch(dim) {\n\t\tcase X  : return \"X\";\n\t\tcase Y  : return \"Y\";\n\t\tdefault : return \"?\";\n\t} // end switch\n} // end method\n\nconst Dimension REVERSE_DIMENSION[2] = {Y,X};\n\n#define for_each_dimension(variable) for ( int variable = 0; variable < 2; variable++ )\n\n// -----------------------------------------------------------------------------\n\nenum Boundary {\n\tLOWER = 0,\n\tUPPER = 1,\n\n\tINNER = 2,\n\tOUTER = 3\n}; // end enum\n\n#define for_each_boundary(variable) for ( int variable = 0; variable < 2; variable++ )\n\n#endif /* DIM_H */\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/double2.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_DOUBLE2_H\n#define\tRSYN_DOUBLE2_H\n\n#include <cmath>\n\n#include <algorithm>\nusing std::max;\nusing std::min;\n#include <ostream>\nusing std::ostream;\n#include <vector>\nusing std::vector;\n\n#include \"dim.h\"\n#include \"dbu.h\"\n#include \"FloatingPoint.h\"\n\n// -----------------------------------------------------------------------------\n\n#define MAKE_SELF_OPERATOR( OP ) \\\n\tinline void operator OP ( const double2 right ) { x OP right.x; y OP right.y; } \n\n#define MAKE_SELF_OPERATOR_SCALAR( OP ) \\\n\tinline void operator OP ( const double right ) { x OP right; y OP right; }\n\n#define MAKE_OPERATOR( OP ) \\\n\tinline double2 operator OP ( const double2 v0, const double2 v1 ) { \\\n\t\treturn double2( v0.x OP v1.x, v0.y OP v1.y ); \\\n\t}\n\n#define MAKE_OPERATOR_SCALAR( OP ) \\\n\tinline double2 operator OP ( const double scalar, const double2 v ) { \\\n\t\treturn double2( v.x OP scalar, v.y OP scalar ); \\\n\t} \\\n\tinline double2 operator OP ( const double2 v, const double scalar ) { \\\n\t\treturn double2( v.x OP scalar, v.y OP scalar ); \\\n\t}\n\n#define MAKE_FUNCTION_1( FUNC ) \\\n\tinline double2 FUNC ( const double2 v ) { \\\n\t\treturn double2( FUNC (v.x), FUNC (v.y) ); \\\n\t}\n\n#define MAKE_FUNCTION_2( FUNC ) \\\n\tinline double2 FUNC ( const double2 v0, const double2 v1 ) { \\\n\t\treturn double2( FUNC (v0.x, v1.x), FUNC (v0.y, v1.y) ); \\\n\t}\n\t\nstruct double2 {\n\tfriend ostream &operator<<( ostream &out, const double2 &v ) {\n\t\treturn out << \"(\" << v.x << \", \" << v.y << \")\";\n\t} // end function\t\n\t\n\tunion {\n\t\tstruct { double x, y; };\n\t\tdouble xy[2];\n\t};\n\n\t// Construtctors.\n\tdouble2(): x(0.0), y(0.0)  {}\n\tdouble2( const double x, const double y ) : x(x), y(y) {}\n\n\texplicit double2( const DBUxy &xy ) : x(xy.x), y(xy.y) {}\n\texplicit double2( const double scalar ) : x(scalar), y(scalar) {} // explicit to avoid accidentally assigning to scalar\n\n\tDBUxy scaleAndConvertToDbu(const double scale, const RoundingStrategy roundingStrategy = ROUND_DOWN) const {\n\t\treturn DBUxy(\n\t\t\t\t(DBU) FloatingPoint::round(x*scale, roundingStrategy),\n\t\t\t\t(DBU) FloatingPoint::round(y*scale, roundingStrategy));\n\t} // end method\n\n\tDBUxy convertToDbu(const RoundingStrategy roundingStrategy = ROUND_DOWN) const {\n\t\treturn DBUxy(\n\t\t\t\t(DBU) FloatingPoint::round(x, roundingStrategy),\n\t\t\t\t(DBU) FloatingPoint::round(y, roundingStrategy));\n\t} // end method\n\n\t// Operators.\n\tMAKE_SELF_OPERATOR( += );\n\tMAKE_SELF_OPERATOR( -= );\n\tMAKE_SELF_OPERATOR( *= );\n\tMAKE_SELF_OPERATOR( /= );\n\t\n\tMAKE_SELF_OPERATOR( = );\n\t\n\tinline const bool operator == ( const double2 v ) const {\n\t\treturn x == v.x && y == v.y;\n\t} // end method\n\t\n\tinline const bool operator != ( const double2 v ) const {\n\t\treturn x != v.x || y != v.y;\n\t} // end method\n\t\n\tMAKE_SELF_OPERATOR_SCALAR( *= );\n\tMAKE_SELF_OPERATOR_SCALAR( /= );\n\t\n\t      double &operator[](const int dimension)       { return xy[dimension]; }\n\tconst double &operator[](const int dimension) const { return xy[dimension]; }\n\t\n\t// Methods.\n\tdouble norm() const {\n\t\treturn sqrt( x*x + y*y );\n\t} // end method\n\t\n\tdouble2 normalized() const {\n\t\tconst double v = norm();\n\t\treturn double2( x/v, y/v );\n\t} // end method\n\n\tdouble2 safeNormalized() const {\n\t\tconst double v = norm();\n\t\tif ( v == 0.0 )\n\t\t\treturn double2(0,0);\n\t\telse\n\t\t\treturn double2( x/v, y/v );\n\t} // end method\t\n\t\n\tvoid apply(const double scalar) {\n\t\tx = scalar;\n\t\ty = scalar;\n\t} // end method\n\t\n\tvoid set( const double x, const double y ) {\n\t\tthis->x = x;\n\t\tthis->y = y;\n\t} // end method\n\t\n\tvoid scale(const double numb){\n\t\tx = x*numb;\n\t\ty = y*numb;\n\t} // end method \n\t\n\tdouble aggregated() const { \n\t\treturn x + y; \n\t} // end method \n\t\n\tvoid abs () {\n\t\tx = std::abs(x);\n\t\ty = std::abs(y);\n\t} // end method \n\t\n\tvoid clear () {\n\t\tx = 0;\n\t\ty = 0;\n\t} // end method \n\t\n\tinline bool approximatelyEqual(const double2 other, const double precision = 1e-6) const;\n\t\n}; // end struct\n\nMAKE_OPERATOR( + );\nMAKE_OPERATOR( - );\nMAKE_OPERATOR( * );\nMAKE_OPERATOR( / );\n\nMAKE_OPERATOR_SCALAR( * );\nMAKE_OPERATOR_SCALAR( / );\n\nMAKE_FUNCTION_2(max);\nMAKE_FUNCTION_2(min);\n\nMAKE_FUNCTION_1(sqrt);\n\n// Unary operators.\ninline double2 operator-( const double2 value ) {\n\treturn double2( -value.x, -value.y );\n} // end operator\n\ninline double2 operator+( const double2 value ) {\n\treturn double2( +value.x, +value.y );\n} // end operator\n\n// Element-wise power.\ninline double2 pow( const double2 base, const double exp ) {\n\treturn double2( pow( base.x, exp ), pow( base.y, exp ) );\n} // end function\n\n// -----------------------------------------------------------------------------\n\ninline bool double2::approximatelyEqual(const double2 other, const double precision) const {\n\treturn (*this - other).norm() <= precision;\n} // end method\n\n// -----------------------------------------------------------------------------\n\n// The split vector class emulates in some extent a vector<double2>. However\n// x and y values are stored in two separated arrays (vector<double>). When\n// accessing elements through [] operator, the split vector class creates a \n// special reference to double2 which allows seamlessly operation with double2\n// variables. But, as x and y are split, the split vector class keeps\n// compatibility with frameworks which do not support double2 (e.g. linear \n// algebra ones).\n\n// @note Deprecated...\n\nclass double2_split_vector {\npublic:\t\n\tstruct double2_ref {\n\t\tdouble &x;\n\t\tdouble &y;\n\n\t\tdouble2_ref( double &x, double &y ) : x(x), y(y) {}\n\n\t\tMAKE_SELF_OPERATOR( += );\n\t\tMAKE_SELF_OPERATOR( -= );\n\t\tMAKE_SELF_OPERATOR( *= );\n\t\tMAKE_SELF_OPERATOR( /= );\n\n\t\tMAKE_SELF_OPERATOR( = );\n\n\t\t      double &operator[](const int dimension)       { return (dimension==X)? x : ( (dimension==Y)? y : *((double *)NULL) ); }\n\t\tconst double &operator[](const int dimension) const { return (dimension==X)? x : ( (dimension==Y)? y : *((double *)NULL) ); }\n\n\t\t// Returns a const double2 to avoid accidentally trying to assign to a\n\t\t// temporary.\n\t\toperator const double2() const { return double2(x,y); } \n\t}; // end struct\t\n\n\tvector<double> xy[2];\n\t\n\tconst double2 operator[](const int index) const { return double2(xy[0][index],xy[1][index]); }\n\tdouble2_ref operator[](const int index) { return double2_ref(xy[0][index],xy[1][index]); }\n\t\n\tvoid resize(size_t size) { xy[0].resize(size); xy[1].resize(size); }\n\tvoid resize(size_t size, double2 val) { xy[0].resize(size, val.x); xy[1].resize(size, val.y); }\n\t\n\tvoid assign(size_t n, double2 val ) { xy[0].assign(n, val.x); xy[1].assign(n, val.y); }\n\t\n\tvoid clear() { xy[0].clear(); xy[1].clear(); } \n\t\n\tsize_t size() const { return xy[0].size(); }\n\t\n}; // end class\n\n// -----------------------------------------------------------------------------\n\n#undef MAKE_OPERATOR\n#undef MAKE_OPERATOR_SCALAR\n#undef MAKE_SELF_OPERATOR\n#undef MAKE_SELF_OPERATOR_SCALAR\n#undef MAKE_FUNCTION_1\n#undef MAKE_FUNCTION_2\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/util/float2.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n#ifndef RSYN_FLOAT2_H\n#define\tRSYN_FLOAT2_H\n\n#include <cmath>\n\n#include <algorithm>\nusing std::max;\nusing std::min;\n#include <ostream>\nusing std::ostream;\n#include <vector>\nusing std::vector;\n\n#include \"dim.h\"\n#include \"dbu.h\"\n#include \"FloatingPoint.h\"\n\n// -----------------------------------------------------------------------------\n\n#define MAKE_SELF_OPERATOR( OP ) \\\n\tinline void operator OP ( const float2 right ) { x OP right.x; y OP right.y; }\n\n#define MAKE_SELF_OPERATOR_SCALAR( OP ) \\\n\tinline void operator OP ( const float right ) { x OP right; y OP right; }\n\n#define MAKE_OPERATOR( OP ) \\\n\tinline float2 operator OP ( const float2 v0, const float2 v1 ) { \\\n\t\treturn float2( v0.x OP v1.x, v0.y OP v1.y ); \\\n\t}\n\n#define MAKE_OPERATOR_SCALAR( OP ) \\\n\tinline float2 operator OP ( const float scalar, const float2 v ) { \\\n\t\treturn float2( v.x OP scalar, v.y OP scalar ); \\\n\t} \\\n\tinline float2 operator OP ( const float2 v, const float scalar ) { \\\n\t\treturn float2( v.x OP scalar, v.y OP scalar ); \\\n\t}\n\n#define MAKE_FUNCTION_1( FUNC ) \\\n\tinline float2 FUNC ( const float2 v ) { \\\n\t\treturn float2( std::FUNC (v.x), std::FUNC (v.y) ); \\\n\t}\n\n#define MAKE_FUNCTION_2( FUNC ) \\\n\tinline float2 FUNC ( const float2 v0, const float2 v1 ) { \\\n\t\treturn float2( std::FUNC (v0.x, v1.x), std::FUNC (v0.y, v1.y) ); \\\n\t}\n\t\nstruct float2 {\n\tfriend ostream &operator<<( ostream &out, const float2 &v ) {\n\t\treturn out << \"(\" << v.x << \", \" << v.y << \")\";\n\t} // end function\t\n\t\n\tunion {\n\t\tstruct { float x, y; };\n\t\tfloat xy[2];\n\t};\n\n\t// Construtctors.\n\tfloat2(): x(0), y(0)  {}\n\tfloat2( const float x, const float y ) : x(x), y(y) {}\n\n\texplicit float2( const DBUxy &xy ) : x(xy.x), y(xy.y) {}\n\texplicit float2( const float scalar ) : x(scalar), y(scalar) {} // explicit to avoid accidentally assigning to scalar\n\n\tDBUxy scaleAndConvertToDbu(const float scale, const RoundingStrategy roundingStrategy = ROUND_DOWN) const {\n\t\treturn DBUxy(\n\t\t\t\t(DBU) FloatingPoint::round(x*scale, roundingStrategy),\n\t\t\t\t(DBU) FloatingPoint::round(y*scale, roundingStrategy));\n\t} // end method\n\n\tDBUxy convertToDbu(const RoundingStrategy roundingStrategy = ROUND_DOWN) const {\n\t\treturn DBUxy(\n\t\t\t\t(DBU) FloatingPoint::round(x, roundingStrategy),\n\t\t\t\t(DBU) FloatingPoint::round(y, roundingStrategy));\n\t} // end method\n\n\t// Operators.\n\tMAKE_SELF_OPERATOR( += );\n\tMAKE_SELF_OPERATOR( -= );\n\tMAKE_SELF_OPERATOR( *= );\n\tMAKE_SELF_OPERATOR( /= );\n\t\n\tMAKE_SELF_OPERATOR( = );\n\t\n\tinline const bool operator == ( const float2 v ) const {\n\t\treturn x == v.x && y == v.y;\n\t} // end method\n\t\n\tinline const bool operator != ( const float2 v ) const {\n\t\treturn x != v.x || y != v.y;\n\t} // end method\n\t\n\tMAKE_SELF_OPERATOR_SCALAR( *= );\n\tMAKE_SELF_OPERATOR_SCALAR( /= );\n\t\n\t      float &operator[](const int dimension)       { return xy[dimension]; }\n\tconst float &operator[](const int dimension) const { return xy[dimension]; }\n\t\n\t// Methods.\n\tfloat norm() const {\n\t\treturn std::sqrt( x*x + y*y );\n\t} // end method\n\t\n\tfloat2 normalized() const {\n\t\tconst float v = norm();\n\t\treturn float2( x/v, y/v );\n\t} // end method\n\n\tfloat2 safeNormalized() const {\n\t\tconst float v = norm();\n\t\tif ( v == 0.0 )\n\t\t\treturn float2(0,0);\n\t\telse\n\t\t\treturn float2( x/v, y/v );\n\t} // end method\n\n\t// clockwise\n\tfloat2 perpendicular() const {\n\t\treturn float2( y, -x );\n\t} // end method\n\n\tvoid apply(const float scalar) {\n\t\tx = scalar;\n\t\ty = scalar;\n\t} // end method\n\t\n\tvoid set( const float x, const float y ) {\n\t\tthis->x = x;\n\t\tthis->y = y;\n\t} // end method\n\t\n\tvoid scale(const float numb){\n\t\tx = x*numb;\n\t\ty = y*numb;\n\t} // end method \n\t\n\tfloat aggregated() const {\n\t\treturn x + y; \n\t} // end method \n\t\n\tvoid abs () {\n\t\tx = std::abs(x);\n\t\ty = std::abs(y);\n\t} // end method \n\t\n\tvoid clear () {\n\t\tx = 0;\n\t\ty = 0;\n\t} // end method \n\t\n\tinline bool approximatelyEqual(const float2 other, const float precision = 1e-6f) const;\n\t\n}; // end struct\n\nMAKE_OPERATOR( + );\nMAKE_OPERATOR( - );\nMAKE_OPERATOR( * );\nMAKE_OPERATOR( / );\n\nMAKE_OPERATOR_SCALAR( * );\nMAKE_OPERATOR_SCALAR( / );\n\nMAKE_FUNCTION_2(max);\nMAKE_FUNCTION_2(min);\n\nMAKE_FUNCTION_1(sqrt);\n\n// Unary operators.\ninline float2 operator-( const float2 value ) {\n\treturn float2( -value.x, -value.y );\n} // end operator\n\ninline float2 operator+( const float2 value ) {\n\treturn float2( +value.x, +value.y );\n} // end operator\n\n// Element-wise power.\ninline float2 pow( const float2 base, const float exp ) {\n\treturn float2( std::pow( base.x, exp ), std::pow( base.y, exp ) );\n} // end function\n\n// -----------------------------------------------------------------------------\n\ninline bool float2::approximatelyEqual(const float2 other, const float precision) const {\n\treturn (*this - other).norm() <= precision;\n} // end method\n\n// -----------------------------------------------------------------------------\n\n#undef MAKE_OPERATOR\n#undef MAKE_OPERATOR_SCALAR\n#undef MAKE_SELF_OPERATOR\n#undef MAKE_SELF_OPERATOR_SCALAR\n#undef MAKE_FUNCTION_1\n#undef MAKE_FUNCTION_2\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/util/geometry/Point.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_GEOMETRY_POINT_H\n#define RSYN_GEOMETRY_POINT_H\n\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/register/point.hpp>\n#include <boost/geometry/geometries/geometries.hpp>\n\n#include \"rsyn/util/dbu.h\"\n\nnamespace Rsyn {\n\nclass Point {\npublic:\n\n\tPoint() {}\n\tPoint(const DBU x, const DBU y) : clsX(x), clsY(y) {}\n\tPoint(const DBUxy p) : clsX(p.x), clsY(p.y) {}\n\n\tDBU getX() const {return clsX;}\n\tDBU getY() const {return clsY;}\n\n\tvoid setX(const DBU x) {clsX = x;}\n\tvoid setY(const DBU y) {clsY = y;}\n\n\t//! @brief Translates this point by (dx, dy).\n\tvoid translate(const DBU dx, const DBU dy) {\n\t\tclsX += dx;\n\t\tclsY += dy;\n\t} // end method\n\n\t//! @brief Translates this point by displacement.\n\tvoid translate(const DBUxy displacement) {\n\t\ttranslate(displacement.x, displacement.y);\n\t} // end method\n\n\t//! @brief Returns copy of this point translated by (dx, dy).\n\tPoint translated(const DBU dx, const DBU dy) const {\n\t\tPoint point = *this;\n\t\tpoint.translate(dx, dy);\n\t\treturn point;\n\t} // end method\n\n\t//! @brief Returns copy of this point translated by displacement.\n\tPoint translated(const DBUxy displacement) const {\n\t\treturn translated(displacement.x, displacement.y);\n\t} // end method\n\n\toperator DBUxy() const {return DBUxy(clsX, clsY);}\n\nprivate:\n\n\tDBU clsX = 0;\n\tDBU clsY = 0;\n\n}; // end class\n\n} // end namespace\n\nBOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(Rsyn::Point, DBU, \n\t\tboost::geometry::cs::cartesian, getX, getY, setX, setY);\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/geometry/Polygon.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include \"Polygon.h\"\n\n#include <cmath>\n\n// Note: Comment the macro below if you have some problems with\n// boost::geometry::strategy::buffer.\n\n#define USE_BOOST_TO_CONVERT_LINE_STRING_TO_POLYGON\n\n// -----------------------------------------------------------------------------\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\nvoid \nPolygon::translate(const DBU dx, const DBU dy) {\n\tfor (Point &point : clsBoostPolygon.outer()) {\n\t\tpoint.translate(dx, dy);\n\t} // end for\n} // end method\n\n// -----------------------------------------------------------------------------\n\nPolygon\nPolygon::translated(const DBU dx, const DBU dy) const {\n\tPolygon poly = *this;\n\tpoly.translate(dx, dy);\n\treturn poly;\n} // end method\n\n// -----------------------------------------------------------------------------\n\n} // end namespace\n\n// #############################################################################\n#ifdef USE_BOOST_TO_CONVERT_LINE_STRING_TO_POLYGON\n// #############################################################################\n\n#include <boost/geometry/geometries/point_xy.hpp>\n#include <boost/geometry/geometries/polygon.hpp>\n#include <boost/geometry/algorithms/buffer.hpp>\n\nnamespace Rsyn {\n\nPolygon\nPolygon::createFromLineString(const std::vector<DBUxy> &points, const DBU width) {\n\tPolygon rsynPolygon;\n\n\ttypedef double coordinate_type;\n\ttypedef boost::geometry::model::d2::point_xy<coordinate_type> point;\n\ttypedef boost::geometry::model::polygon<point> polygon;\n\n\t// Declare strategies\n\tconst double buffer_distance = width/2.0;\n\tboost::geometry::strategy::buffer::distance_symmetric<coordinate_type> distance_strategy(buffer_distance);\n\tboost::geometry::strategy::buffer::join_miter join_strategy;\n\tboost::geometry::strategy::buffer::end_flat end_strategy;\n\tboost::geometry::strategy::buffer::point_square point_strategy;\n\tboost::geometry::strategy::buffer::side_straight side_strategy;\n\n\t// Declare output\n\tboost::geometry::model::multi_polygon<polygon> result;\n\n\t// Declare/fill a linestring\n\tboost::geometry::model::linestring<point> ls;\n\tfor (const DBUxy &p : points)\n\t\tboost::geometry::append(ls, point(p.x, p.y));\n\n\t// Create the buffer of a linestring\n\tboost::geometry::buffer(ls, result,\n\t\t\t\tdistance_strategy, side_strategy,\n\t\t\t\tjoin_strategy, end_strategy, point_strategy);\n\n\tfor (const polygon &poly : result) {\n\t\tfor (const point &p : poly.outer()) {\n\t\t\trsynPolygon.addPoint(DBUxy(\n\t\t\t\t\tstatic_cast<DBU>(std::round(p.x())),\n\t\t\t\t\tstatic_cast<DBU>(std::round(p.y()))));\n\t\t} // end for\n\t\t\n\t\t// Defensive programming: this operation should not return more than one\n\t\t// polygon.\n\t\tbreak;\n\t} // end for\n\n\treturn rsynPolygon;\n} // end method\n\n} // end namespace\n\n#endif\n\n// #############################################################################\n#ifndef USE_BOOST_TO_CONVERT_LINE_STRING_TO_POLYGON\n// #############################################################################\n// Uses the old way to convert a line string to a thick polygon inherited from\n// wxSightGL implemented by Marilena Maule (Lenna) and Guilherme Flach at UFRGS\n// around 2007. \n//\n// Use this only if you have issues using boost::geometry::strategy::buffer,\n// which is a more robust implementation and hence the preferred method.\n// #############################################################################\n\n#include \"rsyn/util/float2.h\"\n\nnamespace Rsyn {\n\nfloat2\nfindIntersection(\n\t\tfloat2 p1,\n\t\tfloat2 p2,\n\t\tfloat2 d1,\n\t\tfloat2 d2\n) {\n\n\tconst float a = p1.x;\n\tconst float e = p1.y;\n\tconst float b = d1.x;\n\tconst float f = d1.y;\n\tconst float c = p2.x;\n\tconst float g = p2.y;\n\tconst float d = d2.x;\n\tconst float h = d2.y;\n\n\tfloat t;\n\tif ((b * h - d * f) == 0) t = 0;\n\telse t = ((c - a) * h + (e - g) * d) / (b * h - d * f);\n\tfloat2 q = p1 + (d1 * t);\n\n\tbool bug;\n\tif ((t < 0 || t > 1)) {\n\t\tbug = true;\n\t} else {\n\t\tbug = false;\n\t} // end else\n\n\treturn q;\n} // end function\n\n// -----------------------------------------------------------------------------\n\nbool\nfindPoint(\n\t\tfloat2 v0,\n\t\tfloat2 v1,\n\t\tfloat2 v2,\n\t\tconst float thickness,\n\t\tstd::vector<float2> &outlinePoints\n) {\n\n\t// Direction vectors.\n\tfloat2 d1 = v1 - v0;\n\tfloat2 d2 = v2 - v1;\n\n\t// Points over the lines.\n\tfloat2 p1 = v1 + (d1.perpendicular().normalized()) * thickness;\n\tfloat2 p2 = v1 + (d2.perpendicular().normalized()) * thickness;\n\n\tfloat m1 = (v0.x - v1.x) == 0 ? (v0.y - v1.y) : (v0.y - v1.y) / (v0.x - v1.x);\n\tfloat m2 = (v1.x - v2.x) == 0 ? (v1.y - v2.y) : (v1.y - v2.y) / (v1.x - v2.x);\n\n\tfloat tg = (m1 - m2) / (1 + m1 * m2);\n\tfloat distancia = std::sqrt(std::pow((p1.x - p2.x), 2.0f) + std::pow((p1.y - p2.y), 2.0f));\n\tfloat limite = std::sqrt(2.0f * std::pow(thickness, 2.0f));\n\n\tif (distancia > limite && tg > 0.0f) { // dois\n\t\toutlinePoints.push_back(p1);\n\t\toutlinePoints.push_back(p2);\n\t\treturn true;\n\t} else {\n\t\tfloat2 q = findIntersection(p1, p2, d1, d2); // um\n\t\toutlinePoints.push_back(q);\n\t\treturn true;\n\t}//end else\n} // end method\n\n// -----------------------------------------------------------------------------\n\nvoid\ntracePathOutline(\n\t\tconst std::vector<DBUxy> &pathPoints,\n\t\tconst float halfThickness,\n\t\tstd::vector<float2> &outlinePoints\n) {\n\n\t// Historical Note: This function was adapted from wxSightGL developed by\n\t// Lenna and Guilherme around 2007.\n\n\tfloat2 v1;\n\n\t// First point\n\tv1 = float2( pathPoints[0] ) +\n\t\t\t( float2( pathPoints[1] ) - float2( pathPoints[0] ) ).perpendicular().normalized() * halfThickness;\n\toutlinePoints.push_back(v1);\n\n\t// Forward traversal.\n\tbool control = true;\n\tfor( size_t i = 1; i < pathPoints.size() - 1; i++){\n\t\tcontrol = findPoint(\n\t\t\t\tfloat2(pathPoints[i-1]),\n\t\t\t\tfloat2(pathPoints[i  ]),\n\t\t\t\tfloat2(pathPoints[i+1]),\n\t\t\t\thalfThickness, outlinePoints);\n\t} // end for\n\n\t// Control point.\n\tif (control) {\n\t\tv1 = float2(pathPoints.back()) + float2( float2( pathPoints.back() ) -\n\t\t\t\tfloat2( pathPoints[pathPoints.size()-2] ) ).perpendicular().normalized() * halfThickness ;\n\t\toutlinePoints.push_back(v1);\n\t} // end if\n\n\t// Last point.\n\tv1 = float2( pathPoints.back() ) + float2( float2( pathPoints[pathPoints.size()-2] ) -\n\t\t\tfloat2( pathPoints.back() ) ).perpendicular().normalized() * halfThickness;\n\toutlinePoints.push_back(v1);\n\n\t// Backward traversal.\n\tfor( int i = pathPoints.size() - 2; i >= 1; i--){\n\t\tfindPoint(\n\t\t\t\tfloat2(pathPoints[i+1]),\n\t\t\t\tfloat2(pathPoints[i  ]),\n\t\t\t\tfloat2(pathPoints[i-1]),\n\t\t\t\thalfThickness, outlinePoints );\n\t} // end if\n\n\tv1 = float2( pathPoints[0] ) + float2( float2( pathPoints[0] ) -\n\t\t\tfloat2( pathPoints[1] ) ).perpendicular().normalized() * halfThickness ;\n\toutlinePoints.push_back(v1);\n\tv1 = float2( pathPoints[0] ) + float2( float2( pathPoints[1] ) -\n\t\t\tfloat2( pathPoints[0] ) ).perpendicular().normalized() * halfThickness ;\n\toutlinePoints.push_back(v1);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nPolygon\nPolygon::createFromLineString(const std::vector<DBUxy> &points, const DBU width) {\n\tstd::vector<float2> outline;\n\ttracePathOutline(points, width/2.0, outline);\n\n\tPolygon rsynPolygon;\n\tfor (const float2 &p : outline) {\n\t\trsynPolygon.addPoint(DBUxy(\n\t\t\t\tstatic_cast<DBU>(std::round(p.x)),\n\t\t\t\tstatic_cast<DBU>(std::round(p.y))));\n\t} // end for\n\n\treturn rsynPolygon;\n} // end method\n\n} // end namespace\n\n#endif\n"
  },
  {
    "path": "rsyn/src/rsyn/util/geometry/Polygon.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_GEOMETRY_POLYGON_H\n#define RSYN_GEOMETRY_POLYGON_H\n\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/geometries.hpp>\n#include <boost/geometry/algorithms/within.hpp>\n\n#include \"rsyn/util/dbu.h\"\n\n#include <Rsyn/Point>\n#include <Rsyn/Rect>\n\nnamespace Rsyn {\n\nclass Polygon {\npublic:\n\n\tPolygon() : clsDirty(true) {}\n\n\t//! @brief Creates a polygon from a line string.\n\tstatic Polygon createFromLineString(const std::vector<DBUxy> &points, const DBU width);\n\n\t//! @brief Returns true if this a non-empty polygon.\n\tbool isValid() const {\n\t\treturn getNumPoints() > 0;\n\t} // end method\n\n\t//! @brief Adds a point to this polygon.\n\tvoid addPoint(const DBU x, const DBU y) {\n\t\taddPoint(Point(x, y));\n\t} // end method\n\n\t//! @brief Adds a point to this polygon.\n\tvoid addPoint(const Point &point) {\n\t\tboost::geometry::append(clsBoostPolygon.outer(), point);\n\t\tclsDirty = true;\n\t} // end method\n\n\t//! @brief Translates this polygon by (dx, dy).\n\tvoid translate(const DBU dx, const DBU dy);\n\n\t//! @brief Translates this polygon by displacement.\n\tvoid translate(const DBUxy displacement) {\n\t\ttranslate(displacement.x, displacement.y);\n\t} // end method\n\n\t//! @brief Returns copy of this polygon translated by (dx, dy).\n\tPolygon translated(const DBU dx, const DBU dy) const;\n\n\t//! @brief Returns copy of this polygon translated by displacement.\n\tPolygon translated(const DBUxy displacement) const {\n\t\treturn translated(displacement.x, displacement.y);\n\t} // end method\n\n\t//! @brief Returns true if (x, y) is inside this polygon.\n\tbool contains(const DBU x, const DBU y) const {\n\t\treturn contains(Point(x, y));\n\t} // end method\n\n\t//! @brief Returns true if point is inside this polygon.\n\tbool contains(const Point &point) const {\n\t\tcorrect();\n\t\treturn boost::geometry::within(point, clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Returns the shortest distance from (x, y) to this polygon.\n\tFloatingPointDBU distance(const DBU x, const DBU y) const {\n\t\tcorrect();\n\t\treturn distance(Point(x, y));\n\t} // end method\n\n\t//! @brief Returns the shortest distance from a point to this polygon.\n\tFloatingPointDBU distance(const Point &point) const {\n\t\tcorrect();\n\t\treturn boost::geometry::distance(point, clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Returns the shortest distance from a rectangle to this polygon.\n\tFloatingPointDBU distance(const Rect &rect) const {\n\t\tcorrect();\n\t\treturn boost::geometry::distance(rect, clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Returns the shortest distance from a polygon to this polygon.\n\tFloatingPointDBU distance(const Polygon &poly) const {\n\t\tcorrect();\n\t\treturn boost::geometry::distance(poly.clsBoostPolygon, clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Returns true if a polygon to overlaps this polygon.\n\tbool overlaps(const Rect &rect) const {\n\t\tcorrect();\n\t\t// Boost 1.58 does not support overlap among a box and a polygon\n\t\t// directly so we first convert the rectangle to an equivalent polygon.\n\t\treturn boost::geometry::overlaps(rect.toPolygon().clsBoostPolygon, clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Returns true if a polygon to overlaps this polygon.\n\tbool overlaps(const Polygon &poly) const {\n\t\tcorrect();\n\t\treturn boost::geometry::overlaps(poly.clsBoostPolygon, clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Removes all points from this polygon.\n\tvoid clear() {\n\t\tclsBoostPolygon.clear();\n\t\tclsDirty = true;\n\t} // end method\n\n\t//! @brief Returns the number of points in this polygon.\n\tint getNumPoints() const {\n\t\treturn boost::geometry::num_points(clsBoostPolygon);\n\t} // end method\n\n\t//! @brief Gets the i-th point of this polygon.\n\t//! @note Currently the points maybe stored in a different order than\n\t//! inserted as the points are corrected to be in the order boost::geometry\n\t//! assumes they to be.\n\tPoint getPoint(const int index) const {\n\t\tcorrect();\n\t\treturn clsBoostPolygon.outer()[index];\n\t} // end method\n\n\t//! @brief Returns a vector with all points in this polygon.\n\tconst std::vector<Point> &getPoints() const {\n\t\tcorrect();\n\t\treturn clsBoostPolygon.outer();\n\t} // end method\n\n\t//! @brief Used to iterate over all points using for-ranged loops.\n\tconst std::vector<Point> &allPoints() const {\n\t\tcorrect();\n\t\treturn clsBoostPolygon.outer();\n\t} // end method\n\nprivate:\n\n\t// @todo change to boost::geometry::model::ring\n\ttypedef boost::geometry::model::polygon<Rsyn::Point,\n\t\t\tfalse /*clock-wise*/, false /*closed*/> BoostPolygon;\n\n\t//! @brief Corrects the order of points in this polygon.\n\t//! @note This is necessary to comply with boost::geometry, which assumes\n\t//! the points of polygons are given in a specific order (e.g. clockwise).\n\tvoid correct() const {\n\t\tif (clsDirty) {\n\t\t\tboost::geometry::correct(clsBoostPolygon);\n\t\t\tclsDirty = false;\n\t\t} // end if\n\t} // end method\n\n\t//! @brief Indicates that this polygon may need correction as boost requires\n\t//! the point of a polygon to be in a certain order (e.g. clockwise).\n\tmutable bool clsDirty : 1;\n\n\t//! @brief The underlying Boost polygon.\n\tmutable BoostPolygon clsBoostPolygon;\n}; // end class\n\n} // end namespace\n\n#endif\n\n"
  },
  {
    "path": "rsyn/src/rsyn/util/geometry/Rect.cpp",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include \"Rect.h\"\n#include \"Polygon.h\"\n\nnamespace Rsyn {\n\n// -----------------------------------------------------------------------------\n\nbool\nRect::overlaps(const Polygon &polygon) const {\n\treturn polygon.overlaps(*this);\n} // end method\n\n// -----------------------------------------------------------------------------\n\nPolygon\nRect::toPolygon() const {\n\tPolygon polygon;\n\tpolygon.addPoint(getLower().getX(), getLower().getY());\n\tpolygon.addPoint(getUpper().getX(), getLower().getY());\n\tpolygon.addPoint(getUpper().getX(), getUpper().getY());\n\tpolygon.addPoint(getLower().getX(), getUpper().getY());\n\treturn polygon;\n} // end method\n\n} // end namespace"
  },
  {
    "path": "rsyn/src/rsyn/util/geometry/Rect.h",
    "content": "/* Copyright 2014-2018 Rsyn\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef RSYN_GEOMETRY_RECT_H\n#define RSYN_GEOMETRY_RECT_H\n\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/register/box.hpp>\n#include <boost/geometry/geometries/geometries.hpp>\n\n#include \"rsyn/util/dbu.h\"\n#include \"rsyn/util/Bounds.h\"\n#include \"Point.h\"\n\nnamespace Rsyn {\n\nclass Polygon;\n\nclass Rect {\npublic:\n\n\tRect() : clsLower(0, 0), clsUpper(0, 0) {}\n\tRect(const DBU x, const DBU y, const DBU w, const DBU h) : clsLower(x, y), clsUpper(x + w, y + h) {}\n\tRect(const Bounds &bounds) : clsLower(bounds.getLower()), clsUpper(bounds.getUpper()) {}\n\n\tDBU getX() const {return clsLower.getX();}\n\tDBU getY() const {return clsLower.getY();}\n\tDBU getWidth() const {return clsUpper.getX() - clsLower.getX();}\n\tDBU getHeight() const {return clsUpper.getY() - clsLower.getY();}\n\n\tPoint getLower() const {return clsLower;}\n\tPoint getUpper() const {return clsUpper;}\n\n\tDBU getArea() const {return getWidth() * getHeight();}\n\t\n\tvoid setX(const DBU x) {\n\t\tconst DBU w = getWidth();\n\t\tclsLower.setX(x);\n\t\tclsUpper.setX(x + w);\n\t} // end method\n\n\tvoid setY(const DBU y) {\n\t\tconst DBU h = getHeight();\n\t\tclsLower.setY(y);\n\t\tclsUpper.setY(y + h);\n\t} // end method\n\n\tvoid setWidth(const DBU w) {\n\t\tclsUpper.setX(clsLower.getX() + w);\n\t} // end method\n\n\tvoid setHeight(const DBU h) {\n\t\tclsUpper.setY(clsLower.getY() + h);\n\t} // end method\n\n\t//! @brief Translates this rectangle by (dx, dy).\n\tvoid translate(const DBU dx, const DBU dy) {\n\t\tclsLower.translate(dx, dy);\n\t\tclsUpper.translate(dx, dy);\n\t} // end method\n\n\t//! @brief Translates this rectangle by displacement.\n\tvoid translate(const DBUxy displacement) {\n\t\ttranslate(displacement.x, displacement.y);\n\t} // end method\n\n\t//! @brief Returns copy of this rectangle translated by (dx, dy).\n\tRect translated(const DBU dx, const DBU dy) const {\n\t\tRect rect = *this;\n\t\trect.translate(dx, dy);\n\t\treturn rect;\n\t} // end method\n\n\t//! @brief Returns copy of this rectangle translated by displacement.\n\tRect translated(const DBUxy displacement) const {\n\t\treturn translated(displacement.x, displacement.y);\n\t} // end method\n\n\tbool contains(const DBU x, const DBU y) const {\n\t\treturn (x >= clsLower.getX() && x <= clsUpper.getX()) &&\n\t\t\t\t(y >= clsLower.getY() && y <= clsUpper.getY());\n\t} // end method\n\n\tbool contains(const Point &point) const {\n\t\treturn contains(point.getX(), point.getY());\n\t} // end method\n\n\tbool overlaps(const Rect &rect) const {\n\t\tconst DBU dx = std::max(getLower().getX(), rect.getLower().getX()) -\n\t\t\t\tstd::min(getUpper().getX(), rect.getUpper().getX());\n\t\tconst DBU dy = std::max(getLower().getY(), rect.getLower().getY()) -\n\t\t\t\tstd::min(getUpper().getY(), rect.getUpper().getY());\n\t\treturn (dx<=0 && dy<=0);\n\t} // end method\n\n\tbool overlaps(const Polygon &polygon) const;\n\n\toperator Bounds() const {return Bounds(getLower(), getUpper());}\n\t\n\tBounds getBounds() const { return Bounds(getLower(), getUpper()); }\n\n\tPolygon toPolygon() const;\n\nprivate:\n\n\tPoint clsUpper;\n\tPoint clsLower;\n\n}; // end class\n\n} // end namespace\n\nBOOST_GEOMETRY_REGISTER_BOX(Rsyn::Rect, Rsyn::Point, getLower(), getUpper());\n\n#endif\n\n"
  },
  {
    "path": "scripts/build.py",
    "content": "#!/usr/bin/env python\n\nimport argparse\nimport os\n\nall_targets = ['iccad19gr']\nrun_files = 'scripts/*.py ispd18eval ispd19eval drcu'\n\n\ndef run(command):\n    if args.print_commands:\n        print(command)\n    if os.system(command) is not 0:\n        if not args.print_commands:\n            print(command)\n        quit()\n\n\n# cmake & copy run files\n# for sanitize, need to remove -static from src/CMakeLists.txt\nmode_cmake_options = {\n    None: '',\n    'debug': '-DCMAKE_BUILD_TYPE=Debug',\n    'release': '-DCMAKE_BUILD_TYPE=Release',\n    'profile': '-DCMAKE_CXX_FLAGS=-pg',\n    'release_profile': '-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-pg',\n    'asan': '-DCMAKE_CXX_FLAGS=-fsanitize=address',\n    'debug_asan': '-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-fsanitize=address',\n    'tsan': '-DCMAKE_CXX_FLAGS=-fsanitize=thread',\n    'debug_tsan': '-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-fsanitize=thread'\n}\n\n# argparse\nparser = argparse.ArgumentParser(description='Build iccad19gr in Linux')\nparser.add_argument('-t', '--targets', choices=all_targets, nargs='+')\nparser.add_argument('-o', '--mode', choices=mode_cmake_options.keys())\nparser.add_argument('-c', '--cmake_options', default='')\nparser.add_argument('-m', '--make_options', default='-j 6')\nparser.add_argument('-u', '--unittest', action='store_true')\nparser.add_argument('-p', '--print_commands', action='store_true')\nparser.add_argument('-b', '--build_dir', default='build')\nparser.add_argument('-r', '--run_dir', default='run')\nargs = parser.parse_args()\n\n# targets\nif args.unittest:\n    build_targets = ['unittest_salt']\nelif args.targets is None:\n    build_targets = ['']\nelse:\n    build_targets = args.targets\n\nrun('cmake src -B{} {} {}'.format(args.build_dir,\n                                  mode_cmake_options[args.mode], args.cmake_options))\nrun('mkdir -p {}'.format(args.run_dir))\nrun('cp -u -R {} {}'.format(run_files, args.run_dir))\n\n# make\nfor target in build_targets:\n    run('cmake --build {} --target {} -- {}'.format(args.build_dir,\n                                                    target, args.make_options))\ncp_targets = all_targets if build_targets == [''] else build_targets\nfor target in cp_targets:\n    run('cp -u {}/{} {}'.format(args.build_dir, target, args.run_dir))\n\n# flute LUT\nrun('cp src/flute/*.dat {}'.format(args.run_dir))\n\n# unit test\nif args.unittest:\n    root_dir = os.path.curdir\n    os.chdir(args.run_dir)\n    run('./{}'.format('unittest_salt'))\n    os.chdir(root_dir)\n"
  },
  {
    "path": "scripts/gprof2dot.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright 2008-2017 Jose Fonseca\n#\n# This program is free software: you can redistribute it and/or modify it\n# under the terms of the GNU Lesser General Public License as published\n# by the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n\n\"\"\"Generate a dot graph from the output of several profilers.\"\"\"\n\n__author__ = \"Jose Fonseca et al\"\n\n\nimport sys\nimport math\nimport os.path\nimport re\nimport textwrap\nimport optparse\nimport xml.parsers.expat\nimport collections\nimport locale\nimport json\nimport fnmatch\n\n# Python 2.x/3.x compatibility\nif sys.version_info[0] >= 3:\n    PYTHON_3 = True\n    def compat_iteritems(x): return x.items()  # No iteritems() in Python 3\n    def compat_itervalues(x): return x.values()  # No itervalues() in Python 3\n    def compat_keys(x): return list(x.keys())  # keys() is a generator in Python 3\n    basestring = str  # No class basestring in Python 3\n    unichr = chr # No unichr in Python 3\n    xrange = range # No xrange in Python 3\nelse:\n    PYTHON_3 = False\n    def compat_iteritems(x): return x.iteritems()\n    def compat_itervalues(x): return x.itervalues()\n    def compat_keys(x): return x.keys()\n\n\n\n########################################################################\n# Model\n\n\nMULTIPLICATION_SIGN = unichr(0xd7)\n\n\ndef times(x):\n    return \"%u%s\" % (x, MULTIPLICATION_SIGN)\n\ndef percentage(p):\n    return \"%.02f%%\" % (p*100.0,)\n\ndef add(a, b):\n    return a + b\n\ndef fail(a, b):\n    assert False\n\n\ntol = 2 ** -23\n\ndef ratio(numerator, denominator):\n    try:\n        ratio = float(numerator)/float(denominator)\n    except ZeroDivisionError:\n        # 0/0 is undefined, but 1.0 yields more useful results\n        return 1.0\n    if ratio < 0.0:\n        if ratio < -tol:\n            sys.stderr.write('warning: negative ratio (%s/%s)\\n' % (numerator, denominator))\n        return 0.0\n    if ratio > 1.0:\n        if ratio > 1.0 + tol:\n            sys.stderr.write('warning: ratio greater than one (%s/%s)\\n' % (numerator, denominator))\n        return 1.0\n    return ratio\n\n\nclass UndefinedEvent(Exception):\n    \"\"\"Raised when attempting to get an event which is undefined.\"\"\"\n    \n    def __init__(self, event):\n        Exception.__init__(self)\n        self.event = event\n\n    def __str__(self):\n        return 'unspecified event %s' % self.event.name\n\n\nclass Event(object):\n    \"\"\"Describe a kind of event, and its basic operations.\"\"\"\n\n    def __init__(self, name, null, aggregator, formatter = str):\n        self.name = name\n        self._null = null\n        self._aggregator = aggregator\n        self._formatter = formatter\n\n    def __eq__(self, other):\n        return self is other\n\n    def __hash__(self):\n        return id(self)\n\n    def null(self):\n        return self._null\n\n    def aggregate(self, val1, val2):\n        \"\"\"Aggregate two event values.\"\"\"\n        assert val1 is not None\n        assert val2 is not None\n        return self._aggregator(val1, val2)\n    \n    def format(self, val):\n        \"\"\"Format an event value.\"\"\"\n        assert val is not None\n        return self._formatter(val)\n\n\nCALLS = Event(\"Calls\", 0, add, times)\nSAMPLES = Event(\"Samples\", 0, add, times)\nSAMPLES2 = Event(\"Samples\", 0, add, times)\n\n# Count of samples where a given function was either executing or on the stack.\n# This is used to calculate the total time ratio according to the\n# straightforward method described in Mike Dunlavey's answer to\n# stackoverflow.com/questions/1777556/alternatives-to-gprof, item 4 (the myth\n# \"that recursion is a tricky confusing issue\"), last edited 2012-08-30: it's\n# just the ratio of TOTAL_SAMPLES over the number of samples in the profile.\n#\n# Used only when totalMethod == callstacks\nTOTAL_SAMPLES = Event(\"Samples\", 0, add, times)\n\nTIME = Event(\"Time\", 0.0, add, lambda x: '(' + str(x) + ')')\nTIME_RATIO = Event(\"Time ratio\", 0.0, add, lambda x: '(' + percentage(x) + ')')\nTOTAL_TIME = Event(\"Total time\", 0.0, fail)\nTOTAL_TIME_RATIO = Event(\"Total time ratio\", 0.0, fail, percentage)\n\ntotalMethod = 'callratios'\n\n\nclass Object(object):\n    \"\"\"Base class for all objects in profile which can store events.\"\"\"\n\n    def __init__(self, events=None):\n        if events is None:\n            self.events = {}\n        else:\n            self.events = events\n\n    def __hash__(self):\n        return id(self)\n\n    def __eq__(self, other):\n        return self is other\n\n    def __lt__(self, other):\n        return id(self) < id(other)\n\n    def __contains__(self, event):\n        return event in self.events\n    \n    def __getitem__(self, event):\n        try:\n            return self.events[event]\n        except KeyError:\n            raise UndefinedEvent(event)\n    \n    def __setitem__(self, event, value):\n        if value is None:\n            if event in self.events:\n                del self.events[event]\n        else:\n            self.events[event] = value\n\n\nclass Call(Object):\n    \"\"\"A call between functions.\n    \n    There should be at most one call object for every pair of functions.\n    \"\"\"\n\n    def __init__(self, callee_id):\n        Object.__init__(self)\n        self.callee_id = callee_id\n        self.ratio = None\n        self.weight = None\n\n\nclass Function(Object):\n    \"\"\"A function.\"\"\"\n\n    def __init__(self, id, name):\n        Object.__init__(self)\n        self.id = id\n        self.name = name\n        self.module = None\n        self.process = None\n        self.calls = {}\n        self.called = None\n        self.weight = None\n        self.cycle = None\n        self.filename = None\n    \n    def add_call(self, call):\n        if call.callee_id in self.calls:\n            sys.stderr.write('warning: overwriting call from function %s to %s\\n' % (str(self.id), str(call.callee_id)))\n        self.calls[call.callee_id] = call\n\n    def get_call(self, callee_id):\n        if not callee_id in self.calls:\n            call = Call(callee_id)\n            call[SAMPLES] = 0\n            call[SAMPLES2] = 0\n            call[CALLS] = 0\n            self.calls[callee_id] = call\n        return self.calls[callee_id]\n\n    _parenthesis_re = re.compile(r'\\([^()]*\\)')\n    _angles_re = re.compile(r'<[^<>]*>')\n    _const_re = re.compile(r'\\s+const$')\n\n    def stripped_name(self):\n        \"\"\"Remove extraneous information from C++ demangled function names.\"\"\"\n\n        name = self.name\n\n        # Strip function parameters from name by recursively removing paired parenthesis\n        while True:\n            name, n = self._parenthesis_re.subn('', name)\n            if not n:\n                break\n\n        # Strip const qualifier\n        name = self._const_re.sub('', name)\n\n        # Strip template parameters from name by recursively removing paired angles\n        while True:\n            name, n = self._angles_re.subn('', name)\n            if not n:\n                break\n\n        return name\n\n    # TODO: write utility functions\n\n    def __repr__(self):\n        return self.name\n\n\nclass Cycle(Object):\n    \"\"\"A cycle made from recursive function calls.\"\"\"\n\n    def __init__(self):\n        Object.__init__(self)\n        self.functions = set()\n\n    def add_function(self, function):\n        assert function not in self.functions\n        self.functions.add(function)\n        if function.cycle is not None:\n            for other in function.cycle.functions:\n                if function not in self.functions:\n                    self.add_function(other)\n        function.cycle = self\n\n\nclass Profile(Object):\n    \"\"\"The whole profile.\"\"\"\n\n    def __init__(self):\n        Object.__init__(self)\n        self.functions = {}\n        self.cycles = []\n\n    def add_function(self, function):\n        if function.id in self.functions:\n            sys.stderr.write('warning: overwriting function %s (id %s)\\n' % (function.name, str(function.id)))\n        self.functions[function.id] = function\n\n    def add_cycle(self, cycle):\n        self.cycles.append(cycle)\n\n    def validate(self):\n        \"\"\"Validate the edges.\"\"\"\n\n        for function in compat_itervalues(self.functions):\n            for callee_id in compat_keys(function.calls):\n                assert function.calls[callee_id].callee_id == callee_id\n                if callee_id not in self.functions:\n                    sys.stderr.write('warning: call to undefined function %s from function %s\\n' % (str(callee_id), function.name))\n                    del function.calls[callee_id]\n\n    def find_cycles(self):\n        \"\"\"Find cycles using Tarjan's strongly connected components algorithm.\"\"\"\n\n        # Apply the Tarjan's algorithm successively until all functions are visited\n        stack = []\n        data = {}\n        order = 0\n        for function in compat_itervalues(self.functions):\n            order = self._tarjan(function, order, stack, data)\n        cycles = []\n        for function in compat_itervalues(self.functions):\n            if function.cycle is not None and function.cycle not in cycles:\n                cycles.append(function.cycle)\n        self.cycles = cycles\n        if 0:\n            for cycle in cycles:\n                sys.stderr.write(\"Cycle:\\n\")\n                for member in cycle.functions:\n                    sys.stderr.write(\"\\tFunction %s\\n\" % member.name)\n\n    def prune_root(self, roots, depth=-1):\n        visited = set()\n        frontier = set([(root_node, depth) for root_node in roots])\n        while len(frontier) > 0:\n            node, node_depth = frontier.pop()\n            visited.add(node)\n            if node_depth == 0:\n                continue\n            f = self.functions[node]\n            newNodes = set(f.calls.keys()) - visited\n            frontier = frontier.union({(new_node, node_depth - 1) for new_node in newNodes})\n        subtreeFunctions = {}\n        for n in visited:\n            f = self.functions[n]\n            newCalls = {}\n            for c in f.calls.keys():\n                if c in visited:\n                    newCalls[c] = f.calls[c]\n            f.calls = newCalls\n            subtreeFunctions[n] = f\n        self.functions = subtreeFunctions\n\n    def prune_leaf(self, leafs, depth=-1):\n        edgesUp = collections.defaultdict(set)\n        for f in self.functions.keys():\n            for n in self.functions[f].calls.keys():\n                edgesUp[n].add(f)\n        # build the tree up\n        visited = set()\n        frontier = set([(leaf_node, depth) for leaf_node in leafs])\n        while len(frontier) > 0:\n            node, node_depth = frontier.pop()\n            visited.add(node)\n            if node_depth == 0:\n                continue\n            newNodes = edgesUp[node] - visited\n            frontier = frontier.union({(new_node, node_depth - 1) for new_node in newNodes})\n        downTree = set(self.functions.keys())\n        upTree = visited\n        path = downTree.intersection(upTree)\n        pathFunctions = {}\n        for n in path:\n            f = self.functions[n]\n            newCalls = {}\n            for c in f.calls.keys():\n                if c in path:\n                    newCalls[c] = f.calls[c]\n            f.calls = newCalls\n            pathFunctions[n] = f\n        self.functions = pathFunctions\n\n    def getFunctionIds(self, funcName):\n        function_names = {v.name: k for (k, v) in self.functions.items()}\n        return [function_names[name] for name in fnmatch.filter(function_names.keys(), funcName)]\n\n    def getFunctionId(self, funcName):\n        for f in self.functions:\n            if self.functions[f].name == funcName:\n                return f\n        return False\n\n    class _TarjanData:\n        def __init__(self, order):\n            self.order = order\n            self.lowlink = order\n            self.onstack = False\n\n    def _tarjan(self, function, order, stack, data):\n        \"\"\"Tarjan's strongly connected components algorithm.\n\n        See also:\n        - http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm\n        \"\"\"\n\n        try:\n            func_data = data[function.id]\n            return order\n        except KeyError:\n            func_data = self._TarjanData(order)\n            data[function.id] = func_data\n        order += 1\n        pos = len(stack)\n        stack.append(function)\n        func_data.onstack = True\n        for call in compat_itervalues(function.calls):\n            try:\n                callee_data = data[call.callee_id]\n                if callee_data.onstack:\n                    func_data.lowlink = min(func_data.lowlink, callee_data.order)\n            except KeyError:\n                callee = self.functions[call.callee_id]\n                order = self._tarjan(callee, order, stack, data)\n                callee_data = data[call.callee_id]\n                func_data.lowlink = min(func_data.lowlink, callee_data.lowlink)\n        if func_data.lowlink == func_data.order:\n            # Strongly connected component found\n            members = stack[pos:]\n            del stack[pos:]\n            if len(members) > 1:\n                cycle = Cycle()\n                for member in members:\n                    cycle.add_function(member)\n                    data[member.id].onstack = False\n            else:\n                for member in members:\n                    data[member.id].onstack = False\n        return order\n\n    def call_ratios(self, event):\n        # Aggregate for incoming calls\n        cycle_totals = {}\n        for cycle in self.cycles:\n            cycle_totals[cycle] = 0.0\n        function_totals = {}\n        for function in compat_itervalues(self.functions):\n            function_totals[function] = 0.0\n\n        # Pass 1:  function_total gets the sum of call[event] for all\n        #          incoming arrows.  Same for cycle_total for all arrows\n        #          that are coming into the *cycle* but are not part of it.\n        for function in compat_itervalues(self.functions):\n            for call in compat_itervalues(function.calls):\n                if call.callee_id != function.id:\n                    callee = self.functions[call.callee_id]\n                    if event in call.events:\n                        function_totals[callee] += call[event]\n                        if callee.cycle is not None and callee.cycle is not function.cycle:\n                            cycle_totals[callee.cycle] += call[event]\n                    else:\n                        sys.stderr.write(\"call_ratios: No data for \" + function.name + \" call to \" + callee.name + \"\\n\")\n\n        # Pass 2:  Compute the ratios.  Each call[event] is scaled by the\n        #          function_total of the callee.  Calls into cycles use the\n        #          cycle_total, but not calls within cycles.\n        for function in compat_itervalues(self.functions):\n            for call in compat_itervalues(function.calls):\n                assert call.ratio is None\n                if call.callee_id != function.id:\n                    callee = self.functions[call.callee_id]\n                    if event in call.events:\n                        if callee.cycle is not None and callee.cycle is not function.cycle:\n                            total = cycle_totals[callee.cycle]\n                        else:\n                            total = function_totals[callee]\n                        call.ratio = ratio(call[event], total)\n                    else:\n                        # Warnings here would only repeat those issued above.\n                        call.ratio = 0.0\n\n    def integrate(self, outevent, inevent):\n        \"\"\"Propagate function time ratio along the function calls.\n\n        Must be called after finding the cycles.\n\n        See also:\n        - http://citeseer.ist.psu.edu/graham82gprof.html\n        \"\"\"\n\n        # Sanity checking\n        assert outevent not in self\n        for function in compat_itervalues(self.functions):\n            assert outevent not in function\n            assert inevent in function\n            for call in compat_itervalues(function.calls):\n                assert outevent not in call\n                if call.callee_id != function.id:\n                    assert call.ratio is not None\n\n        # Aggregate the input for each cycle \n        for cycle in self.cycles:\n            total = inevent.null()\n            for function in compat_itervalues(self.functions):\n                total = inevent.aggregate(total, function[inevent])\n            self[inevent] = total\n\n        # Integrate along the edges\n        total = inevent.null()\n        for function in compat_itervalues(self.functions):\n            total = inevent.aggregate(total, function[inevent])\n            self._integrate_function(function, outevent, inevent)\n        self[outevent] = total\n\n    def _integrate_function(self, function, outevent, inevent):\n        if function.cycle is not None:\n            return self._integrate_cycle(function.cycle, outevent, inevent)\n        else:\n            if outevent not in function:\n                total = function[inevent]\n                for call in compat_itervalues(function.calls):\n                    if call.callee_id != function.id:\n                        total += self._integrate_call(call, outevent, inevent)\n                function[outevent] = total\n            return function[outevent]\n    \n    def _integrate_call(self, call, outevent, inevent):\n        assert outevent not in call\n        assert call.ratio is not None\n        callee = self.functions[call.callee_id]\n        subtotal = call.ratio *self._integrate_function(callee, outevent, inevent)\n        call[outevent] = subtotal\n        return subtotal\n\n    def _integrate_cycle(self, cycle, outevent, inevent):\n        if outevent not in cycle:\n\n            # Compute the outevent for the whole cycle\n            total = inevent.null()\n            for member in cycle.functions:\n                subtotal = member[inevent]\n                for call in compat_itervalues(member.calls):\n                    callee = self.functions[call.callee_id]\n                    if callee.cycle is not cycle:\n                        subtotal += self._integrate_call(call, outevent, inevent)\n                total += subtotal\n            cycle[outevent] = total\n            \n            # Compute the time propagated to callers of this cycle\n            callees = {}\n            for function in compat_itervalues(self.functions):\n                if function.cycle is not cycle:\n                    for call in compat_itervalues(function.calls):\n                        callee = self.functions[call.callee_id]\n                        if callee.cycle is cycle:\n                            try:\n                                callees[callee] += call.ratio\n                            except KeyError:\n                                callees[callee] = call.ratio\n            \n            for member in cycle.functions:\n                member[outevent] = outevent.null()\n\n            for callee, call_ratio in compat_iteritems(callees):\n                ranks = {}\n                call_ratios = {}\n                partials = {}\n                self._rank_cycle_function(cycle, callee, ranks)\n                self._call_ratios_cycle(cycle, callee, ranks, call_ratios, set())\n                partial = self._integrate_cycle_function(cycle, callee, call_ratio, partials, ranks, call_ratios, outevent, inevent)\n\n                # Ensure `partial == max(partials.values())`, but with round-off tolerance\n                max_partial = max(partials.values())\n                assert abs(partial - max_partial) <= 1e-7*max_partial\n\n                assert abs(call_ratio*total - partial) <= 0.001*call_ratio*total\n\n        return cycle[outevent]\n\n    def _rank_cycle_function(self, cycle, function, ranks):\n        \"\"\"Dijkstra's shortest paths algorithm.\n\n        See also:\n        - http://en.wikipedia.org/wiki/Dijkstra's_algorithm\n        \"\"\"\n\n        import heapq\n        Q = []\n        Qd = {}\n        p = {}\n        visited = set([function])\n\n        ranks[function] = 0\n        for call in compat_itervalues(function.calls):\n            if call.callee_id != function.id:\n                callee = self.functions[call.callee_id]\n                if callee.cycle is cycle:\n                    ranks[callee] = 1\n                    item = [ranks[callee], function, callee]\n                    heapq.heappush(Q, item)\n                    Qd[callee] = item\n\n        while Q:\n            cost, parent, member = heapq.heappop(Q)\n            if member not in visited:\n                p[member]= parent\n                visited.add(member)\n                for call in compat_itervalues(member.calls):\n                    if call.callee_id != member.id:\n                        callee = self.functions[call.callee_id]\n                        if callee.cycle is cycle:\n                            member_rank = ranks[member]\n                            rank = ranks.get(callee)\n                            if rank is not None:\n                                if rank > 1 + member_rank:\n                                    rank = 1 + member_rank\n                                    ranks[callee] = rank\n                                    Qd_callee = Qd[callee]\n                                    Qd_callee[0] = rank\n                                    Qd_callee[1] = member\n                                    heapq._siftdown(Q, 0, Q.index(Qd_callee))\n                            else:\n                                rank = 1 + member_rank\n                                ranks[callee] = rank\n                                item = [rank, member, callee]\n                                heapq.heappush(Q, item)\n                                Qd[callee] = item\n\n    def _call_ratios_cycle(self, cycle, function, ranks, call_ratios, visited):\n        if function not in visited:\n            visited.add(function)\n            for call in compat_itervalues(function.calls):\n                if call.callee_id != function.id:\n                    callee = self.functions[call.callee_id]\n                    if callee.cycle is cycle:\n                        if ranks[callee] > ranks[function]:\n                            call_ratios[callee] = call_ratios.get(callee, 0.0) + call.ratio\n                            self._call_ratios_cycle(cycle, callee, ranks, call_ratios, visited)\n\n    def _integrate_cycle_function(self, cycle, function, partial_ratio, partials, ranks, call_ratios, outevent, inevent):\n        if function not in partials:\n            partial = partial_ratio*function[inevent]\n            for call in compat_itervalues(function.calls):\n                if call.callee_id != function.id:\n                    callee = self.functions[call.callee_id]\n                    if callee.cycle is not cycle:\n                        assert outevent in call\n                        partial += partial_ratio*call[outevent]\n                    else:\n                        if ranks[callee] > ranks[function]:\n                            callee_partial = self._integrate_cycle_function(cycle, callee, partial_ratio, partials, ranks, call_ratios, outevent, inevent)\n                            call_ratio = ratio(call.ratio, call_ratios[callee])\n                            call_partial = call_ratio*callee_partial\n                            try:\n                                call[outevent] += call_partial\n                            except UndefinedEvent:\n                                call[outevent] = call_partial\n                            partial += call_partial\n            partials[function] = partial\n            try:\n                function[outevent] += partial\n            except UndefinedEvent:\n                function[outevent] = partial\n        return partials[function]\n\n    def aggregate(self, event):\n        \"\"\"Aggregate an event for the whole profile.\"\"\"\n\n        total = event.null()\n        for function in compat_itervalues(self.functions):\n            try:\n                total = event.aggregate(total, function[event])\n            except UndefinedEvent:\n                return\n        self[event] = total\n\n    def ratio(self, outevent, inevent):\n        assert outevent not in self\n        assert inevent in self\n        for function in compat_itervalues(self.functions):\n            assert outevent not in function\n            assert inevent in function\n            function[outevent] = ratio(function[inevent], self[inevent])\n            for call in compat_itervalues(function.calls):\n                assert outevent not in call\n                if inevent in call:\n                    call[outevent] = ratio(call[inevent], self[inevent])\n        self[outevent] = 1.0\n\n    def prune(self, node_thres, edge_thres, paths, color_nodes_by_selftime):\n        \"\"\"Prune the profile\"\"\"\n\n        # compute the prune ratios\n        for function in compat_itervalues(self.functions):\n            try:\n                function.weight = function[TOTAL_TIME_RATIO]\n            except UndefinedEvent:\n                pass\n\n            for call in compat_itervalues(function.calls):\n                callee = self.functions[call.callee_id]\n\n                if TOTAL_TIME_RATIO in call:\n                    # handle exact cases first\n                    call.weight = call[TOTAL_TIME_RATIO] \n                else:\n                    try:\n                        # make a safe estimate\n                        call.weight = min(function[TOTAL_TIME_RATIO], callee[TOTAL_TIME_RATIO]) \n                    except UndefinedEvent:\n                        pass\n\n        # prune the nodes\n        for function_id in compat_keys(self.functions):\n            function = self.functions[function_id]\n            if function.weight is not None:\n                if function.weight < node_thres:\n                    del self.functions[function_id]\n        \n        # prune file paths\n        for function_id in compat_keys(self.functions):\n            function = self.functions[function_id]\n            if paths and not any(function.filename.startswith(path) for path in paths):\n                del self.functions[function_id]\n\n        # prune the egdes\n        for function in compat_itervalues(self.functions):\n            for callee_id in compat_keys(function.calls):\n                call = function.calls[callee_id]\n                if callee_id not in self.functions or call.weight is not None and call.weight < edge_thres:\n                    del function.calls[callee_id]\n\n        if color_nodes_by_selftime:\n            weights = []\n            for function in compat_itervalues(self.functions):\n                try:\n                    weights.append(function[TIME_RATIO])\n                except UndefinedEvent:\n                    pass\n            max_ratio = max(weights or [1])\n\n            # apply rescaled weights for coloriung\n            for function in compat_itervalues(self.functions):\n                try:\n                    function.weight = function[TIME_RATIO] / max_ratio\n                except (ZeroDivisionError, UndefinedEvent):\n                    pass\n    \n    def dump(self):\n        for function in compat_itervalues(self.functions):\n            sys.stderr.write('Function %s:\\n' % (function.name,))\n            self._dump_events(function.events)\n            for call in compat_itervalues(function.calls):\n                callee = self.functions[call.callee_id]\n                sys.stderr.write('  Call %s:\\n' % (callee.name,))\n                self._dump_events(call.events)\n        for cycle in self.cycles:\n            sys.stderr.write('Cycle:\\n')\n            self._dump_events(cycle.events)\n            for function in cycle.functions:\n                sys.stderr.write('  Function %s\\n' % (function.name,))\n\n    def _dump_events(self, events):\n        for event, value in compat_iteritems(events):\n            sys.stderr.write('    %s: %s\\n' % (event.name, event.format(value)))\n\n\n\n########################################################################\n# Parsers\n\n\nclass Struct:\n    \"\"\"Masquerade a dictionary with a structure-like behavior.\"\"\"\n\n    def __init__(self, attrs = None):\n        if attrs is None:\n            attrs = {}\n        self.__dict__['_attrs'] = attrs\n    \n    def __getattr__(self, name):\n        try:\n            return self._attrs[name]\n        except KeyError:\n            raise AttributeError(name)\n\n    def __setattr__(self, name, value):\n        self._attrs[name] = value\n\n    def __str__(self):\n        return str(self._attrs)\n\n    def __repr__(self):\n        return repr(self._attrs)\n    \n\nclass ParseError(Exception):\n    \"\"\"Raised when parsing to signal mismatches.\"\"\"\n\n    def __init__(self, msg, line):\n        Exception.__init__(self)\n        self.msg = msg\n        # TODO: store more source line information\n        self.line = line\n\n    def __str__(self):\n        return '%s: %r' % (self.msg, self.line)\n\n\nclass Parser:\n    \"\"\"Parser interface.\"\"\"\n\n    stdinInput = True\n    multipleInput = False\n\n    def __init__(self):\n        pass\n\n    def parse(self):\n        raise NotImplementedError\n\n    \nclass JsonParser(Parser):\n    \"\"\"Parser for a custom JSON representation of profile data.\n\n    See schema.json for details.\n    \"\"\"\n\n\n    def __init__(self, stream):\n        Parser.__init__(self)\n        self.stream = stream\n\n    def parse(self):\n\n        obj = json.load(self.stream)\n\n        assert obj['version'] == 0\n\n        profile = Profile()\n        profile[SAMPLES] = 0\n\n        fns = obj['functions']\n\n        for functionIndex in range(len(fns)):\n            fn = fns[functionIndex]\n            function = Function(functionIndex, fn['name'])\n            try:\n                function.module = fn['module']\n            except KeyError:\n                pass\n            try:\n                function.process = fn['process']\n            except KeyError:\n                pass\n            function[SAMPLES] = 0\n            profile.add_function(function)\n\n        for event in obj['events']:\n            callchain = []\n\n            for functionIndex in event['callchain']:\n                function = profile.functions[functionIndex]\n                callchain.append(function)\n\n            cost = event['cost'][0]\n\n            callee = callchain[0]\n            callee[SAMPLES] += cost\n            profile[SAMPLES] += cost\n\n            for caller in callchain[1:]:\n                try:\n                    call = caller.calls[callee.id]\n                except KeyError:\n                    call = Call(callee.id)\n                    call[SAMPLES2] = cost\n                    caller.add_call(call)\n                else:\n                    call[SAMPLES2] += cost\n\n                callee = caller\n\n        if False:\n            profile.dump()\n\n        # compute derived data\n        profile.validate()\n        profile.find_cycles()\n        profile.ratio(TIME_RATIO, SAMPLES)\n        profile.call_ratios(SAMPLES2)\n        profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return profile\n\n\nclass LineParser(Parser):\n    \"\"\"Base class for parsers that read line-based formats.\"\"\"\n\n    def __init__(self, stream):\n        Parser.__init__(self)\n        self._stream = stream\n        self.__line = None\n        self.__eof = False\n        self.line_no = 0\n\n    def readline(self):\n        line = self._stream.readline()\n        if not line:\n            self.__line = ''\n            self.__eof = True\n        else:\n            self.line_no += 1\n        line = line.rstrip('\\r\\n')\n        if not PYTHON_3:\n            encoding = self._stream.encoding\n            if encoding is None:\n                encoding = locale.getpreferredencoding()\n            line = line.decode(encoding)\n        self.__line = line\n\n    def lookahead(self):\n        assert self.__line is not None\n        return self.__line\n\n    def consume(self):\n        assert self.__line is not None\n        line = self.__line\n        self.readline()\n        return line\n\n    def eof(self):\n        assert self.__line is not None\n        return self.__eof\n\n\nXML_ELEMENT_START, XML_ELEMENT_END, XML_CHARACTER_DATA, XML_EOF = range(4)\n\n\nclass XmlToken:\n\n    def __init__(self, type, name_or_data, attrs = None, line = None, column = None):\n        assert type in (XML_ELEMENT_START, XML_ELEMENT_END, XML_CHARACTER_DATA, XML_EOF)\n        self.type = type\n        self.name_or_data = name_or_data\n        self.attrs = attrs\n        self.line = line\n        self.column = column\n\n    def __str__(self):\n        if self.type == XML_ELEMENT_START:\n            return '<' + self.name_or_data + ' ...>'\n        if self.type == XML_ELEMENT_END:\n            return '</' + self.name_or_data + '>'\n        if self.type == XML_CHARACTER_DATA:\n            return self.name_or_data\n        if self.type == XML_EOF:\n            return 'end of file'\n        assert 0\n\n\nclass XmlTokenizer:\n    \"\"\"Expat based XML tokenizer.\"\"\"\n\n    def __init__(self, fp, skip_ws = True):\n        self.fp = fp\n        self.tokens = []\n        self.index = 0\n        self.final = False\n        self.skip_ws = skip_ws\n        \n        self.character_pos = 0, 0\n        self.character_data = ''\n        \n        self.parser = xml.parsers.expat.ParserCreate()\n        self.parser.StartElementHandler  = self.handle_element_start\n        self.parser.EndElementHandler    = self.handle_element_end\n        self.parser.CharacterDataHandler = self.handle_character_data\n    \n    def handle_element_start(self, name, attributes):\n        self.finish_character_data()\n        line, column = self.pos()\n        token = XmlToken(XML_ELEMENT_START, name, attributes, line, column)\n        self.tokens.append(token)\n    \n    def handle_element_end(self, name):\n        self.finish_character_data()\n        line, column = self.pos()\n        token = XmlToken(XML_ELEMENT_END, name, None, line, column)\n        self.tokens.append(token)\n\n    def handle_character_data(self, data):\n        if not self.character_data:\n            self.character_pos = self.pos()\n        self.character_data += data\n    \n    def finish_character_data(self):\n        if self.character_data:\n            if not self.skip_ws or not self.character_data.isspace(): \n                line, column = self.character_pos\n                token = XmlToken(XML_CHARACTER_DATA, self.character_data, None, line, column)\n                self.tokens.append(token)\n            self.character_data = ''\n    \n    def next(self):\n        size = 16*1024\n        while self.index >= len(self.tokens) and not self.final:\n            self.tokens = []\n            self.index = 0\n            data = self.fp.read(size)\n            self.final = len(data) < size\n            self.parser.Parse(data, self.final)\n        if self.index >= len(self.tokens):\n            line, column = self.pos()\n            token = XmlToken(XML_EOF, None, None, line, column)\n        else:\n            token = self.tokens[self.index]\n            self.index += 1\n        return token\n\n    def pos(self):\n        return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber\n\n\nclass XmlTokenMismatch(Exception):\n\n    def __init__(self, expected, found):\n        Exception.__init__(self)\n        self.expected = expected\n        self.found = found\n\n    def __str__(self):\n        return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found))\n\n\nclass XmlParser(Parser):\n    \"\"\"Base XML document parser.\"\"\"\n\n    def __init__(self, fp):\n        Parser.__init__(self)\n        self.tokenizer = XmlTokenizer(fp)\n        self.consume()\n    \n    def consume(self):\n        self.token = self.tokenizer.next()\n\n    def match_element_start(self, name):\n        return self.token.type == XML_ELEMENT_START and self.token.name_or_data == name\n    \n    def match_element_end(self, name):\n        return self.token.type == XML_ELEMENT_END and self.token.name_or_data == name\n\n    def element_start(self, name):\n        while self.token.type == XML_CHARACTER_DATA:\n            self.consume()\n        if self.token.type != XML_ELEMENT_START:\n            raise XmlTokenMismatch(XmlToken(XML_ELEMENT_START, name), self.token)\n        if self.token.name_or_data != name:\n            raise XmlTokenMismatch(XmlToken(XML_ELEMENT_START, name), self.token)\n        attrs = self.token.attrs\n        self.consume()\n        return attrs\n    \n    def element_end(self, name):\n        while self.token.type == XML_CHARACTER_DATA:\n            self.consume()\n        if self.token.type != XML_ELEMENT_END:\n            raise XmlTokenMismatch(XmlToken(XML_ELEMENT_END, name), self.token)\n        if self.token.name_or_data != name:\n            raise XmlTokenMismatch(XmlToken(XML_ELEMENT_END, name), self.token)\n        self.consume()\n\n    def character_data(self, strip = True):\n        data = ''\n        while self.token.type == XML_CHARACTER_DATA:\n            data += self.token.name_or_data\n            self.consume()\n        if strip:\n            data = data.strip()\n        return data\n\n\nclass GprofParser(Parser):\n    \"\"\"Parser for GNU gprof output.\n\n    See also:\n    - Chapter \"Interpreting gprof's Output\" from the GNU gprof manual\n      http://sourceware.org/binutils/docs-2.18/gprof/Call-Graph.html#Call-Graph\n    - File \"cg_print.c\" from the GNU gprof source code\n      http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/src/gprof/cg_print.c?rev=1.12&cvsroot=src\n    \"\"\"\n\n    def __init__(self, fp):\n        Parser.__init__(self)\n        self.fp = fp\n        self.functions = {}\n        self.cycles = {}\n\n    def readline(self):\n        line = self.fp.readline()\n        if not line:\n            sys.stderr.write('error: unexpected end of file\\n')\n            sys.exit(1)\n        line = line.rstrip('\\r\\n')\n        return line\n\n    _int_re = re.compile(r'^\\d+$')\n    _float_re = re.compile(r'^\\d+\\.\\d+$')\n\n    def translate(self, mo):\n        \"\"\"Extract a structure from a match object, while translating the types in the process.\"\"\"\n        attrs = {}\n        groupdict = mo.groupdict()\n        for name, value in compat_iteritems(groupdict):\n            if value is None:\n                value = None\n            elif self._int_re.match(value):\n                value = int(value)\n            elif self._float_re.match(value):\n                value = float(value)\n            attrs[name] = (value)\n        return Struct(attrs)\n\n    _cg_header_re = re.compile(\n        # original gprof header\n        r'^\\s+called/total\\s+parents\\s*$|' +\n        r'^index\\s+%time\\s+self\\s+descendents\\s+called\\+self\\s+name\\s+index\\s*$|' +\n        r'^\\s+called/total\\s+children\\s*$|' +\n        # GNU gprof header\n        r'^index\\s+%\\s+time\\s+self\\s+children\\s+called\\s+name\\s*$'\n    )\n\n    _cg_ignore_re = re.compile(\n        # spontaneous\n        r'^\\s+<spontaneous>\\s*$|'\n        # internal calls (such as \"mcount\")\n        r'^.*\\((\\d+)\\)$'\n    )\n\n    _cg_primary_re = re.compile(\n        r'^\\[(?P<index>\\d+)\\]?' + \n        r'\\s+(?P<percentage_time>\\d+\\.\\d+)' + \n        r'\\s+(?P<self>\\d+\\.\\d+)' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)' + \n        r'\\s+(?:(?P<called>\\d+)(?:\\+(?P<called_self>\\d+))?)?' + \n        r'\\s+(?P<name>\\S.*?)' +\n        r'(?:\\s+<cycle\\s(?P<cycle>\\d+)>)?' +\n        r'\\s\\[(\\d+)\\]$'\n    )\n\n    _cg_parent_re = re.compile(\n        r'^\\s+(?P<self>\\d+\\.\\d+)?' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)?' + \n        r'\\s+(?P<called>\\d+)(?:/(?P<called_total>\\d+))?' + \n        r'\\s+(?P<name>\\S.*?)' +\n        r'(?:\\s+<cycle\\s(?P<cycle>\\d+)>)?' +\n        r'\\s\\[(?P<index>\\d+)\\]$'\n    )\n\n    _cg_child_re = _cg_parent_re\n\n    _cg_cycle_header_re = re.compile(\n        r'^\\[(?P<index>\\d+)\\]?' + \n        r'\\s+(?P<percentage_time>\\d+\\.\\d+)' + \n        r'\\s+(?P<self>\\d+\\.\\d+)' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)' + \n        r'\\s+(?:(?P<called>\\d+)(?:\\+(?P<called_self>\\d+))?)?' + \n        r'\\s+<cycle\\s(?P<cycle>\\d+)\\sas\\sa\\swhole>' +\n        r'\\s\\[(\\d+)\\]$'\n    )\n\n    _cg_cycle_member_re = re.compile(\n        r'^\\s+(?P<self>\\d+\\.\\d+)?' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)?' + \n        r'\\s+(?P<called>\\d+)(?:\\+(?P<called_self>\\d+))?' + \n        r'\\s+(?P<name>\\S.*?)' +\n        r'(?:\\s+<cycle\\s(?P<cycle>\\d+)>)?' +\n        r'\\s\\[(?P<index>\\d+)\\]$'\n    )\n\n    _cg_sep_re = re.compile(r'^--+$')\n\n    def parse_function_entry(self, lines):\n        parents = []\n        children = []\n\n        while True:\n            if not lines:\n                sys.stderr.write('warning: unexpected end of entry\\n')\n            line = lines.pop(0)\n            if line.startswith('['):\n                break\n        \n            # read function parent line\n            mo = self._cg_parent_re.match(line)\n            if not mo:\n                if self._cg_ignore_re.match(line):\n                    continue\n                sys.stderr.write('warning: unrecognized call graph entry: %r\\n' % line)\n            else:\n                parent = self.translate(mo)\n                parents.append(parent)\n\n        # read primary line\n        mo = self._cg_primary_re.match(line)\n        if not mo:\n            sys.stderr.write('warning: unrecognized call graph entry: %r\\n' % line)\n            return\n        else:\n            function = self.translate(mo)\n\n        while lines:\n            line = lines.pop(0)\n            \n            # read function subroutine line\n            mo = self._cg_child_re.match(line)\n            if not mo:\n                if self._cg_ignore_re.match(line):\n                    continue\n                sys.stderr.write('warning: unrecognized call graph entry: %r\\n' % line)\n            else:\n                child = self.translate(mo)\n                children.append(child)\n        \n        function.parents = parents\n        function.children = children\n\n        self.functions[function.index] = function\n\n    def parse_cycle_entry(self, lines):\n\n        # read cycle header line\n        line = lines[0]\n        mo = self._cg_cycle_header_re.match(line)\n        if not mo:\n            sys.stderr.write('warning: unrecognized call graph entry: %r\\n' % line)\n            return\n        cycle = self.translate(mo)\n\n        # read cycle member lines\n        cycle.functions = []\n        for line in lines[1:]:\n            mo = self._cg_cycle_member_re.match(line)\n            if not mo:\n                sys.stderr.write('warning: unrecognized call graph entry: %r\\n' % line)\n                continue\n            call = self.translate(mo)\n            cycle.functions.append(call)\n        \n        self.cycles[cycle.cycle] = cycle\n\n    def parse_cg_entry(self, lines):\n        if lines[0].startswith(\"[\"):\n            self.parse_cycle_entry(lines)\n        else:\n            self.parse_function_entry(lines)\n\n    def parse_cg(self):\n        \"\"\"Parse the call graph.\"\"\"\n\n        # skip call graph header\n        while not self._cg_header_re.match(self.readline()):\n            pass\n        line = self.readline()\n        while self._cg_header_re.match(line):\n            line = self.readline()\n\n        # process call graph entries\n        entry_lines = []\n        while line != '\\014': # form feed\n            if line and not line.isspace():\n                if self._cg_sep_re.match(line):\n                    self.parse_cg_entry(entry_lines)\n                    entry_lines = []\n                else:\n                    entry_lines.append(line)            \n            line = self.readline()\n    \n    def parse(self):\n        self.parse_cg()\n        self.fp.close()\n\n        profile = Profile()\n        profile[TIME] = 0.0\n        \n        cycles = {}\n        for index in self.cycles:\n            cycles[index] = Cycle()\n\n        for entry in compat_itervalues(self.functions):\n            # populate the function\n            function = Function(entry.index, entry.name)\n            function[TIME] = entry.self\n            if entry.called is not None:\n                function.called = entry.called\n            if entry.called_self is not None:\n                call = Call(entry.index)\n                call[CALLS] = entry.called_self\n                function.called += entry.called_self\n            \n            # populate the function calls\n            for child in entry.children:\n                call = Call(child.index)\n                \n                assert child.called is not None\n                call[CALLS] = child.called\n\n                if child.index not in self.functions:\n                    # NOTE: functions that were never called but were discovered by gprof's \n                    # static call graph analysis dont have a call graph entry so we need\n                    # to add them here\n                    missing = Function(child.index, child.name)\n                    function[TIME] = 0.0\n                    function.called = 0\n                    profile.add_function(missing)\n\n                function.add_call(call)\n\n            profile.add_function(function)\n\n            if entry.cycle is not None:\n                try:\n                    cycle = cycles[entry.cycle]\n                except KeyError:\n                    sys.stderr.write('warning: <cycle %u as a whole> entry missing\\n' % entry.cycle) \n                    cycle = Cycle()\n                    cycles[entry.cycle] = cycle\n                cycle.add_function(function)\n\n            profile[TIME] = profile[TIME] + function[TIME]\n\n        for cycle in compat_itervalues(cycles):\n            profile.add_cycle(cycle)\n\n        # Compute derived events\n        profile.validate()\n        profile.ratio(TIME_RATIO, TIME)\n        profile.call_ratios(CALLS)\n        profile.integrate(TOTAL_TIME, TIME)\n        profile.ratio(TOTAL_TIME_RATIO, TOTAL_TIME)\n\n        return profile\n\n\n# Clone&hack of GprofParser for VTune Amplifier XE 2013 gprof-cc output.\n# Tested only with AXE 2013 for Windows.\n#   - Use total times as reported by AXE.\n#   - In the absence of call counts, call ratios are faked from the relative\n#     proportions of total time.  This affects only the weighting of the calls.\n#   - Different header, separator, and end marker.\n#   - Extra whitespace after function names.\n#   - You get a full entry for <spontaneous>, which does not have parents.\n#   - Cycles do have parents.  These are saved but unused (as they are\n#     for functions).\n#   - Disambiguated \"unrecognized call graph entry\" error messages.\n# Notes:\n#   - Total time of functions as reported by AXE passes the val3 test.\n#   - CPU Time:Children in the input is sometimes a negative number.  This\n#     value goes to the variable descendants, which is unused.\n#   - The format of gprof-cc reports is unaffected by the use of\n#       -knob enable-call-counts=true (no call counts, ever), or\n#       -show-as=samples (results are quoted in seconds regardless).\nclass AXEParser(Parser):\n    \"Parser for VTune Amplifier XE 2013 gprof-cc report output.\"\n\n    def __init__(self, fp):\n        Parser.__init__(self)\n        self.fp = fp\n        self.functions = {}\n        self.cycles = {}\n\n    def readline(self):\n        line = self.fp.readline()\n        if not line:\n            sys.stderr.write('error: unexpected end of file\\n')\n            sys.exit(1)\n        line = line.rstrip('\\r\\n')\n        return line\n\n    _int_re = re.compile(r'^\\d+$')\n    _float_re = re.compile(r'^\\d+\\.\\d+$')\n\n    def translate(self, mo):\n        \"\"\"Extract a structure from a match object, while translating the types in the process.\"\"\"\n        attrs = {}\n        groupdict = mo.groupdict()\n        for name, value in compat_iteritems(groupdict):\n            if value is None:\n                value = None\n            elif self._int_re.match(value):\n                value = int(value)\n            elif self._float_re.match(value):\n                value = float(value)\n            attrs[name] = (value)\n        return Struct(attrs)\n\n    _cg_header_re = re.compile(\n        '^Index |'\n        '^-----+ '\n    )\n\n    _cg_footer_re = re.compile(r'^Index\\s+Function\\s*$')\n\n    _cg_primary_re = re.compile(\n        r'^\\[(?P<index>\\d+)\\]?' + \n        r'\\s+(?P<percentage_time>\\d+\\.\\d+)' + \n        r'\\s+(?P<self>\\d+\\.\\d+)' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)' + \n        r'\\s+(?P<name>\\S.*?)' +\n        r'(?:\\s+<cycle\\s(?P<cycle>\\d+)>)?' +\n        r'\\s+\\[(\\d+)\\]' +\n        r'\\s*$'\n    )\n\n    _cg_parent_re = re.compile(\n        r'^\\s+(?P<self>\\d+\\.\\d+)?' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)?' + \n        r'\\s+(?P<name>\\S.*?)' +\n        r'(?:\\s+<cycle\\s(?P<cycle>\\d+)>)?' +\n        r'(?:\\s+\\[(?P<index>\\d+)\\]\\s*)?' +\n        r'\\s*$'\n    )\n\n    _cg_child_re = _cg_parent_re\n\n    _cg_cycle_header_re = re.compile(\n        r'^\\[(?P<index>\\d+)\\]?' + \n        r'\\s+(?P<percentage_time>\\d+\\.\\d+)' + \n        r'\\s+(?P<self>\\d+\\.\\d+)' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)' + \n        r'\\s+<cycle\\s(?P<cycle>\\d+)\\sas\\sa\\swhole>' +\n        r'\\s+\\[(\\d+)\\]' +\n        r'\\s*$'\n    )\n\n    _cg_cycle_member_re = re.compile(\n        r'^\\s+(?P<self>\\d+\\.\\d+)?' + \n        r'\\s+(?P<descendants>\\d+\\.\\d+)?' + \n        r'\\s+(?P<name>\\S.*?)' +\n        r'(?:\\s+<cycle\\s(?P<cycle>\\d+)>)?' +\n        r'\\s+\\[(?P<index>\\d+)\\]' +\n        r'\\s*$'\n    )\n\n    def parse_function_entry(self, lines):\n        parents = []\n        children = []\n\n        while True:\n            if not lines:\n                sys.stderr.write('warning: unexpected end of entry\\n')\n                return\n            line = lines.pop(0)\n            if line.startswith('['):\n                break\n        \n            # read function parent line\n            mo = self._cg_parent_re.match(line)\n            if not mo:\n                sys.stderr.write('warning: unrecognized call graph entry (1): %r\\n' % line)\n            else:\n                parent = self.translate(mo)\n                if parent.name != '<spontaneous>':\n                    parents.append(parent)\n\n        # read primary line\n        mo = self._cg_primary_re.match(line)\n        if not mo:\n            sys.stderr.write('warning: unrecognized call graph entry (2): %r\\n' % line)\n            return\n        else:\n            function = self.translate(mo)\n\n        while lines:\n            line = lines.pop(0)\n            \n            # read function subroutine line\n            mo = self._cg_child_re.match(line)\n            if not mo:\n                sys.stderr.write('warning: unrecognized call graph entry (3): %r\\n' % line)\n            else:\n                child = self.translate(mo)\n                if child.name != '<spontaneous>':\n                    children.append(child)\n\n        if function.name != '<spontaneous>':\n            function.parents = parents\n            function.children = children\n\n            self.functions[function.index] = function\n\n    def parse_cycle_entry(self, lines):\n\n        # Process the parents that were not there in gprof format.\n        parents = []\n        while True:\n            if not lines:\n                sys.stderr.write('warning: unexpected end of cycle entry\\n')\n                return\n            line = lines.pop(0)\n            if line.startswith('['):\n                break\n            mo = self._cg_parent_re.match(line)\n            if not mo:\n                sys.stderr.write('warning: unrecognized call graph entry (6): %r\\n' % line)\n            else:\n                parent = self.translate(mo)\n                if parent.name != '<spontaneous>':\n                    parents.append(parent)\n\n        # read cycle header line\n        mo = self._cg_cycle_header_re.match(line)\n        if not mo:\n            sys.stderr.write('warning: unrecognized call graph entry (4): %r\\n' % line)\n            return\n        cycle = self.translate(mo)\n\n        # read cycle member lines\n        cycle.functions = []\n        for line in lines[1:]:\n            mo = self._cg_cycle_member_re.match(line)\n            if not mo:\n                sys.stderr.write('warning: unrecognized call graph entry (5): %r\\n' % line)\n                continue\n            call = self.translate(mo)\n            cycle.functions.append(call)\n        \n        cycle.parents = parents\n        self.cycles[cycle.cycle] = cycle\n\n    def parse_cg_entry(self, lines):\n        if any(\"as a whole\" in linelooper for linelooper in lines):\n            self.parse_cycle_entry(lines)\n        else:\n            self.parse_function_entry(lines)\n\n    def parse_cg(self):\n        \"\"\"Parse the call graph.\"\"\"\n\n        # skip call graph header\n        line = self.readline()\n        while self._cg_header_re.match(line):\n            line = self.readline()\n\n        # process call graph entries\n        entry_lines = []\n        # An EOF in readline terminates the program without returning.\n        while not self._cg_footer_re.match(line):\n            if line.isspace():\n                self.parse_cg_entry(entry_lines)\n                entry_lines = []\n            else:\n                entry_lines.append(line)            \n            line = self.readline()\n\n    def parse(self):\n        sys.stderr.write('warning: for axe format, edge weights are unreliable estimates derived from function total times.\\n')\n        self.parse_cg()\n        self.fp.close()\n\n        profile = Profile()\n        profile[TIME] = 0.0\n        \n        cycles = {}\n        for index in self.cycles:\n            cycles[index] = Cycle()\n\n        for entry in compat_itervalues(self.functions):\n            # populate the function\n            function = Function(entry.index, entry.name)\n            function[TIME] = entry.self\n            function[TOTAL_TIME_RATIO] = entry.percentage_time / 100.0\n            \n            # populate the function calls\n            for child in entry.children:\n                call = Call(child.index)\n                # The following bogus value affects only the weighting of\n                # the calls.\n                call[TOTAL_TIME_RATIO] = function[TOTAL_TIME_RATIO]\n\n                if child.index not in self.functions:\n                    # NOTE: functions that were never called but were discovered by gprof's \n                    # static call graph analysis dont have a call graph entry so we need\n                    # to add them here\n                    # FIXME: Is this applicable?\n                    missing = Function(child.index, child.name)\n                    function[TIME] = 0.0\n                    profile.add_function(missing)\n\n                function.add_call(call)\n\n            profile.add_function(function)\n\n            if entry.cycle is not None:\n                try:\n                    cycle = cycles[entry.cycle]\n                except KeyError:\n                    sys.stderr.write('warning: <cycle %u as a whole> entry missing\\n' % entry.cycle) \n                    cycle = Cycle()\n                    cycles[entry.cycle] = cycle\n                cycle.add_function(function)\n\n            profile[TIME] = profile[TIME] + function[TIME]\n\n        for cycle in compat_itervalues(cycles):\n            profile.add_cycle(cycle)\n\n        # Compute derived events.\n        profile.validate()\n        profile.ratio(TIME_RATIO, TIME)\n        # Lacking call counts, fake call ratios based on total times.\n        profile.call_ratios(TOTAL_TIME_RATIO)\n        # The TOTAL_TIME_RATIO of functions is already set.  Propagate that\n        # total time to the calls.  (TOTAL_TIME is neither set nor used.)\n        for function in compat_itervalues(profile.functions):\n            for call in compat_itervalues(function.calls):\n                if call.ratio is not None:\n                    callee = profile.functions[call.callee_id]\n                    call[TOTAL_TIME_RATIO] = call.ratio * callee[TOTAL_TIME_RATIO]\n\n        return profile\n\n\nclass CallgrindParser(LineParser):\n    \"\"\"Parser for valgrind's callgrind tool.\n    \n    See also:\n    - http://valgrind.org/docs/manual/cl-format.html\n    \"\"\"\n\n    _call_re = re.compile(r'^calls=\\s*(\\d+)\\s+((\\d+|\\+\\d+|-\\d+|\\*)\\s+)+$')\n\n    def __init__(self, infile):\n        LineParser.__init__(self, infile)\n\n        # Textual positions\n        self.position_ids = {}\n        self.positions = {}\n\n        # Numeric positions\n        self.num_positions = 1\n        self.cost_positions = ['line']\n        self.last_positions = [0]\n\n        # Events\n        self.num_events = 0\n        self.cost_events = []\n\n        self.profile = Profile()\n        self.profile[SAMPLES] = 0\n\n    def parse(self):\n        # read lookahead\n        self.readline()\n\n        self.parse_key('version')\n        self.parse_key('creator')\n        while self.parse_part():\n            pass\n        if not self.eof():\n            sys.stderr.write('warning: line %u: unexpected line\\n' % self.line_no)\n            sys.stderr.write('%s\\n' % self.lookahead())\n\n        # compute derived data\n        self.profile.validate()\n        self.profile.find_cycles()\n        self.profile.ratio(TIME_RATIO, SAMPLES)\n        self.profile.call_ratios(SAMPLES2)\n        self.profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return self.profile\n\n    def parse_part(self):\n        if not self.parse_header_line():\n            return False\n        while self.parse_header_line():\n            pass\n        if not self.parse_body_line():\n            return False\n        while self.parse_body_line():\n            pass\n        return True\n\n    def parse_header_line(self):\n        return \\\n            self.parse_empty() or \\\n            self.parse_comment() or \\\n            self.parse_part_detail() or \\\n            self.parse_description() or \\\n            self.parse_event_specification() or \\\n            self.parse_cost_line_def() or \\\n            self.parse_cost_summary()\n\n    _detail_keys = set(('cmd', 'pid', 'thread', 'part'))\n\n    def parse_part_detail(self):\n        return self.parse_keys(self._detail_keys)\n\n    def parse_description(self):\n        return self.parse_key('desc') is not None\n\n    def parse_event_specification(self):\n        event = self.parse_key('event')\n        if event is None:\n            return False\n        return True\n\n    def parse_cost_line_def(self):\n        pair = self.parse_keys(('events', 'positions'))\n        if pair is None:\n            return False\n        key, value = pair\n        items = value.split()\n        if key == 'events':\n            self.num_events = len(items)\n            self.cost_events = items\n        if key == 'positions':\n            self.num_positions = len(items)\n            self.cost_positions = items\n            self.last_positions = [0]*self.num_positions\n        return True\n\n    def parse_cost_summary(self):\n        pair = self.parse_keys(('summary', 'totals'))\n        if pair is None:\n            return False\n        return True\n\n    def parse_body_line(self):\n        return \\\n            self.parse_empty() or \\\n            self.parse_comment() or \\\n            self.parse_cost_line() or \\\n            self.parse_position_spec() or \\\n            self.parse_association_spec()\n\n    __subpos_re = r'(0x[0-9a-fA-F]+|\\d+|\\+\\d+|-\\d+|\\*)'\n    _cost_re = re.compile(r'^' + \n        __subpos_re + r'( +' + __subpos_re + r')*' +\n        r'( +\\d+)*' +\n    '$')\n\n    def parse_cost_line(self, calls=None):\n        line = self.lookahead().rstrip()\n        mo = self._cost_re.match(line)\n        if not mo:\n            return False\n\n        function = self.get_function()\n\n        if calls is None:\n            # Unlike other aspects, call object (cob) is relative not to the\n            # last call object, but to the caller's object (ob), so try to\n            # update it when processing a functions cost line\n            try:\n                self.positions['cob'] = self.positions['ob']\n            except KeyError:\n                pass\n\n        values = line.split()\n        assert len(values) <= self.num_positions + self.num_events\n\n        positions = values[0 : self.num_positions]\n        events = values[self.num_positions : ]\n        events += ['0']*(self.num_events - len(events))\n\n        for i in range(self.num_positions):\n            position = positions[i]\n            if position == '*':\n                position = self.last_positions[i]\n            elif position[0] in '-+':\n                position = self.last_positions[i] + int(position)\n            elif position.startswith('0x'):\n                position = int(position, 16)\n            else:\n                position = int(position)\n            self.last_positions[i] = position\n\n        events = [float(event) for event in events]\n\n        if calls is None:\n            function[SAMPLES] += events[0] \n            self.profile[SAMPLES] += events[0]\n        else:\n            callee = self.get_callee()\n            callee.called += calls\n    \n            try:\n                call = function.calls[callee.id]\n            except KeyError:\n                call = Call(callee.id)\n                call[CALLS] = calls\n                call[SAMPLES2] = events[0]\n                function.add_call(call)\n            else:\n                call[CALLS] += calls\n                call[SAMPLES2] += events[0]\n\n        self.consume()\n        return True\n\n    def parse_association_spec(self):\n        line = self.lookahead()\n        if not line.startswith('calls='):\n            return False\n\n        _, values = line.split('=', 1)\n        values = values.strip().split()\n        calls = int(values[0])\n        call_position = values[1:]\n        self.consume()\n\n        self.parse_cost_line(calls)\n\n        return True\n\n    _position_re = re.compile(r'^(?P<position>[cj]?(?:ob|fl|fi|fe|fn))=\\s*(?:\\((?P<id>\\d+)\\))?(?:\\s*(?P<name>.+))?')\n\n    _position_table_map = {\n        'ob': 'ob',\n        'fl': 'fl',\n        'fi': 'fl',\n        'fe': 'fl',\n        'fn': 'fn',\n        'cob': 'ob',\n        'cfl': 'fl',\n        'cfi': 'fl',\n        'cfe': 'fl',\n        'cfn': 'fn',\n        'jfi': 'fl',\n    }\n\n    _position_map = {\n        'ob': 'ob',\n        'fl': 'fl',\n        'fi': 'fl',\n        'fe': 'fl',\n        'fn': 'fn',\n        'cob': 'cob',\n        'cfl': 'cfl',\n        'cfi': 'cfl',\n        'cfe': 'cfl',\n        'cfn': 'cfn',\n        'jfi': 'jfi',\n    }\n\n    def parse_position_spec(self):\n        line = self.lookahead()\n        \n        if line.startswith('jump=') or line.startswith('jcnd='):\n            self.consume()\n            return True\n\n        mo = self._position_re.match(line)\n        if not mo:\n            return False\n\n        position, id, name = mo.groups()\n        if id:\n            table = self._position_table_map[position]\n            if name:\n                self.position_ids[(table, id)] = name\n            else:\n                name = self.position_ids.get((table, id), '')\n        self.positions[self._position_map[position]] = name\n\n        self.consume()\n        return True\n\n    def parse_empty(self):\n        if self.eof():\n            return False\n        line = self.lookahead()\n        if line.strip():\n            return False\n        self.consume()\n        return True\n\n    def parse_comment(self):\n        line = self.lookahead()\n        if not line.startswith('#'):\n            return False\n        self.consume()\n        return True\n\n    _key_re = re.compile(r'^(\\w+):')\n\n    def parse_key(self, key):\n        pair = self.parse_keys((key,))\n        if not pair:\n            return None\n        key, value = pair\n        return value\n\n    def parse_keys(self, keys):\n        line = self.lookahead()\n        mo = self._key_re.match(line)\n        if not mo:\n            return None\n        key, value = line.split(':', 1)\n        if key not in keys:\n            return None\n        value = value.strip()\n        self.consume()\n        return key, value\n\n    def make_function(self, module, filename, name):\n        # FIXME: module and filename are not being tracked reliably\n        #id = '|'.join((module, filename, name))\n        id = name\n        try:\n            function = self.profile.functions[id]\n        except KeyError:\n            function = Function(id, name)\n            if module:\n                function.module = os.path.basename(module)\n            function[SAMPLES] = 0\n            function.called = 0\n            self.profile.add_function(function)\n        return function\n\n    def get_function(self):\n        module = self.positions.get('ob', '')\n        filename = self.positions.get('fl', '') \n        function = self.positions.get('fn', '') \n        return self.make_function(module, filename, function)\n\n    def get_callee(self):\n        module = self.positions.get('cob', '')\n        filename = self.positions.get('cfi', '') \n        function = self.positions.get('cfn', '') \n        return self.make_function(module, filename, function)\n\n    def readline(self):\n        # Override LineParser.readline to ignore comment lines\n        while True:\n            LineParser.readline(self)\n            if self.eof() or not self.lookahead().startswith('#'):\n                break\n\n\nclass PerfParser(LineParser):\n    \"\"\"Parser for linux perf callgraph output.\n\n    It expects output generated with\n\n        perf record -g\n        perf script | gprof2dot.py --format=perf\n    \"\"\"\n\n    def __init__(self, infile):\n        LineParser.__init__(self, infile)\n        self.profile = Profile()\n\n    def readline(self):\n        # Override LineParser.readline to ignore comment lines\n        while True:\n            LineParser.readline(self)\n            if self.eof() or not self.lookahead().startswith('#'):\n                break\n\n    def parse(self):\n        # read lookahead\n        self.readline()\n\n        profile = self.profile\n        profile[SAMPLES] = 0\n        while not self.eof():\n            self.parse_event()\n\n        # compute derived data\n        profile.validate()\n        profile.find_cycles()\n        profile.ratio(TIME_RATIO, SAMPLES)\n        profile.call_ratios(SAMPLES2)\n        if totalMethod == \"callratios\":\n            # Heuristic approach.  TOTAL_SAMPLES is unused.\n            profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n        elif totalMethod == \"callstacks\":\n            # Use the actual call chains for functions.\n            profile[TOTAL_SAMPLES] = profile[SAMPLES]\n            profile.ratio(TOTAL_TIME_RATIO, TOTAL_SAMPLES)\n            # Then propagate that total time to the calls.\n            for function in compat_itervalues(profile.functions):\n                for call in compat_itervalues(function.calls):\n                    if call.ratio is not None:\n                        callee = profile.functions[call.callee_id]\n                        call[TOTAL_TIME_RATIO] = call.ratio * callee[TOTAL_TIME_RATIO]\n        else:\n            assert False\n\n        return profile\n\n    def parse_event(self):\n        if self.eof():\n            return\n\n        line = self.consume()\n        assert line\n\n        callchain = self.parse_callchain()\n        if not callchain:\n            return\n\n        callee = callchain[0]\n        callee[SAMPLES] += 1\n        self.profile[SAMPLES] += 1\n\n        for caller in callchain[1:]:\n            try:\n                call = caller.calls[callee.id]\n            except KeyError:\n                call = Call(callee.id)\n                call[SAMPLES2] = 1\n                caller.add_call(call)\n            else:\n                call[SAMPLES2] += 1\n\n            callee = caller\n\n        # Increment TOTAL_SAMPLES only once on each function.\n        stack = set(callchain)\n        for function in stack:\n            function[TOTAL_SAMPLES] += 1\n\n    def parse_callchain(self):\n        callchain = []\n        while self.lookahead():\n            function = self.parse_call()\n            if function is None:\n                break\n            callchain.append(function)\n        if self.lookahead() == '':\n            self.consume()\n        return callchain\n\n    call_re = re.compile(r'^\\s+(?P<address>[0-9a-fA-F]+)\\s+(?P<symbol>.*)\\s+\\((?P<module>.*)\\)$')\n    addr2_re = re.compile(r'\\+0x[0-9a-fA-F]+$')\n\n    def parse_call(self):\n        line = self.consume()\n        mo = self.call_re.match(line)\n        assert mo\n        if not mo:\n            return None\n\n        function_name = mo.group('symbol')\n\n        # If present, amputate program counter from function name.\n        if function_name:\n            function_name = re.sub(self.addr2_re, '', function_name)\n\n        if not function_name or function_name == '[unknown]':\n            function_name = mo.group('address')\n\n        module = mo.group('module')\n\n        function_id = function_name + ':' + module\n\n        try:\n            function = self.profile.functions[function_id]\n        except KeyError:\n            function = Function(function_id, function_name)\n            function.module = os.path.basename(module)\n            function[SAMPLES] = 0\n            function[TOTAL_SAMPLES] = 0\n            self.profile.add_function(function)\n\n        return function\n\n\nclass OprofileParser(LineParser):\n    \"\"\"Parser for oprofile callgraph output.\n    \n    See also:\n    - http://oprofile.sourceforge.net/doc/opreport.html#opreport-callgraph\n    \"\"\"\n\n    _fields_re = {\n        'samples': r'(\\d+)',\n        '%': r'(\\S+)',\n        'linenr info': r'(?P<source>\\(no location information\\)|\\S+:\\d+)',\n        'image name': r'(?P<image>\\S+(?:\\s\\(tgid:[^)]*\\))?)',\n        'app name': r'(?P<application>\\S+)',\n        'symbol name': r'(?P<symbol>\\(no symbols\\)|.+?)',\n    }\n\n    def __init__(self, infile):\n        LineParser.__init__(self, infile)\n        self.entries = {}\n        self.entry_re = None\n\n    def add_entry(self, callers, function, callees):\n        try:\n            entry = self.entries[function.id]\n        except KeyError:\n            self.entries[function.id] = (callers, function, callees)\n        else:\n            callers_total, function_total, callees_total = entry\n            self.update_subentries_dict(callers_total, callers)\n            function_total.samples += function.samples\n            self.update_subentries_dict(callees_total, callees)\n    \n    def update_subentries_dict(self, totals, partials):\n        for partial in compat_itervalues(partials):\n            try:\n                total = totals[partial.id]\n            except KeyError:\n                totals[partial.id] = partial\n            else:\n                total.samples += partial.samples\n        \n    def parse(self):\n        # read lookahead\n        self.readline()\n\n        self.parse_header()\n        while self.lookahead():\n            self.parse_entry()\n\n        profile = Profile()\n\n        reverse_call_samples = {}\n        \n        # populate the profile\n        profile[SAMPLES] = 0\n        for _callers, _function, _callees in compat_itervalues(self.entries):\n            function = Function(_function.id, _function.name)\n            function[SAMPLES] = _function.samples\n            profile.add_function(function)\n            profile[SAMPLES] += _function.samples\n\n            if _function.application:\n                function.process = os.path.basename(_function.application)\n            if _function.image:\n                function.module = os.path.basename(_function.image)\n\n            total_callee_samples = 0\n            for _callee in compat_itervalues(_callees):\n                total_callee_samples += _callee.samples\n\n            for _callee in compat_itervalues(_callees):\n                if not _callee.self:\n                    call = Call(_callee.id)\n                    call[SAMPLES2] = _callee.samples\n                    function.add_call(call)\n                \n        # compute derived data\n        profile.validate()\n        profile.find_cycles()\n        profile.ratio(TIME_RATIO, SAMPLES)\n        profile.call_ratios(SAMPLES2)\n        profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return profile\n\n    def parse_header(self):\n        while not self.match_header():\n            self.consume()\n        line = self.lookahead()\n        fields = re.split(r'\\s\\s+', line)\n        entry_re = r'^\\s*' + r'\\s+'.join([self._fields_re[field] for field in fields]) + r'(?P<self>\\s+\\[self\\])?$'\n        self.entry_re = re.compile(entry_re)\n        self.skip_separator()\n\n    def parse_entry(self):\n        callers = self.parse_subentries()\n        if self.match_primary():\n            function = self.parse_subentry()\n            if function is not None:\n                callees = self.parse_subentries()\n                self.add_entry(callers, function, callees)\n        self.skip_separator()\n\n    def parse_subentries(self):\n        subentries = {}\n        while self.match_secondary():\n            subentry = self.parse_subentry()\n            subentries[subentry.id] = subentry\n        return subentries\n\n    def parse_subentry(self):\n        entry = Struct()\n        line = self.consume()\n        mo = self.entry_re.match(line)\n        if not mo:\n            raise ParseError('failed to parse', line)\n        fields = mo.groupdict()\n        entry.samples = int(mo.group(1))\n        if 'source' in fields and fields['source'] != '(no location information)':\n            source = fields['source']\n            filename, lineno = source.split(':')\n            entry.filename = filename\n            entry.lineno = int(lineno)\n        else:\n            source = ''\n            entry.filename = None\n            entry.lineno = None\n        entry.image = fields.get('image', '')\n        entry.application = fields.get('application', '')\n        if 'symbol' in fields and fields['symbol'] != '(no symbols)':\n            entry.symbol = fields['symbol']\n        else:\n            entry.symbol = ''\n        if entry.symbol.startswith('\"') and entry.symbol.endswith('\"'):\n            entry.symbol = entry.symbol[1:-1]\n        entry.id = ':'.join((entry.application, entry.image, source, entry.symbol))\n        entry.self = fields.get('self', None) != None\n        if entry.self:\n            entry.id += ':self'\n        if entry.symbol:\n            entry.name = entry.symbol\n        else:\n            entry.name = entry.image\n        return entry\n\n    def skip_separator(self):\n        while not self.match_separator():\n            self.consume()\n        self.consume()\n\n    def match_header(self):\n        line = self.lookahead()\n        return line.startswith('samples')\n\n    def match_separator(self):\n        line = self.lookahead()\n        return line == '-'*len(line)\n\n    def match_primary(self):\n        line = self.lookahead()\n        return not line[:1].isspace()\n    \n    def match_secondary(self):\n        line = self.lookahead()\n        return line[:1].isspace()\n\n\nclass HProfParser(LineParser):\n    \"\"\"Parser for java hprof output\n    \n    See also:\n    - http://java.sun.com/developer/technicalArticles/Programming/HPROF.html\n    \"\"\"\n\n    trace_re = re.compile(r'\\t(.*)\\((.*):(.*)\\)')\n    trace_id_re = re.compile(r'^TRACE (\\d+):$')\n\n    def __init__(self, infile):\n        LineParser.__init__(self, infile)\n        self.traces = {}\n        self.samples = {}\n\n    def parse(self):\n        # read lookahead\n        self.readline()\n\n        while not self.lookahead().startswith('------'): self.consume()\n        while not self.lookahead().startswith('TRACE '): self.consume()\n\n        self.parse_traces()\n\n        while not self.lookahead().startswith('CPU'):\n            self.consume()\n\n        self.parse_samples()\n\n        # populate the profile\n        profile = Profile()\n        profile[SAMPLES] = 0\n\n        functions = {}\n\n        # build up callgraph\n        for id, trace in compat_iteritems(self.traces):\n            if not id in self.samples: continue\n            mtime = self.samples[id][0]\n            last = None\n\n            for func, file, line in trace:\n                if not func in functions:\n                    function = Function(func, func)\n                    function[SAMPLES] = 0\n                    profile.add_function(function)\n                    functions[func] = function\n\n                function = functions[func]\n                # allocate time to the deepest method in the trace\n                if not last:\n                    function[SAMPLES] += mtime\n                    profile[SAMPLES] += mtime\n                else:\n                    c = function.get_call(last)\n                    c[SAMPLES2] += mtime\n\n                last = func\n\n        # compute derived data\n        profile.validate()\n        profile.find_cycles()\n        profile.ratio(TIME_RATIO, SAMPLES)\n        profile.call_ratios(SAMPLES2)\n        profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return profile\n\n    def parse_traces(self):\n        while self.lookahead().startswith('TRACE '):\n            self.parse_trace()\n\n    def parse_trace(self):\n        l = self.consume()\n        mo = self.trace_id_re.match(l)\n        tid = mo.group(1)\n        last = None\n        trace = []\n\n        while self.lookahead().startswith('\\t'):\n            l = self.consume()\n            match = self.trace_re.search(l)\n            if not match:\n                #sys.stderr.write('Invalid line: %s\\n' % l)\n                break\n            else:\n                function_name, file, line = match.groups()\n                trace += [(function_name, file, line)]\n\n        self.traces[int(tid)] = trace\n\n    def parse_samples(self):\n        self.consume()\n        self.consume()\n\n        while not self.lookahead().startswith('CPU'):\n            rank, percent_self, percent_accum, count, traceid, method = self.lookahead().split()\n            self.samples[int(traceid)] = (int(count), method)\n            self.consume()\n\n\nclass SysprofParser(XmlParser):\n\n    def __init__(self, stream):\n        XmlParser.__init__(self, stream)\n\n    def parse(self):\n        objects = {}\n        nodes = {}\n\n        self.element_start('profile')\n        while self.token.type == XML_ELEMENT_START:\n            if self.token.name_or_data == 'objects':\n                assert not objects\n                objects = self.parse_items('objects')\n            elif self.token.name_or_data == 'nodes':\n                assert not nodes\n                nodes = self.parse_items('nodes')\n            else:\n                self.parse_value(self.token.name_or_data)\n        self.element_end('profile')\n\n        return self.build_profile(objects, nodes)\n\n    def parse_items(self, name):\n        assert name[-1] == 's'\n        items = {}\n        self.element_start(name)\n        while self.token.type == XML_ELEMENT_START:\n            id, values = self.parse_item(name[:-1])\n            assert id not in items\n            items[id] = values\n        self.element_end(name)\n        return items\n\n    def parse_item(self, name):\n        attrs = self.element_start(name)\n        id = int(attrs['id'])\n        values = self.parse_values()\n        self.element_end(name)\n        return id, values\n\n    def parse_values(self):\n        values = {}\n        while self.token.type == XML_ELEMENT_START:\n            name = self.token.name_or_data\n            value = self.parse_value(name)\n            assert name not in values\n            values[name] = value\n        return values\n\n    def parse_value(self, tag):\n        self.element_start(tag)\n        value = self.character_data()\n        self.element_end(tag)\n        if value.isdigit():\n            return int(value)\n        if value.startswith('\"') and value.endswith('\"'):\n            return value[1:-1]\n        return value\n\n    def build_profile(self, objects, nodes):\n        profile = Profile()\n        \n        profile[SAMPLES] = 0\n        for id, object in compat_iteritems(objects):\n            # Ignore fake objects (process names, modules, \"Everything\", \"kernel\", etc.)\n            if object['self'] == 0:\n                continue\n\n            function = Function(id, object['name'])\n            function[SAMPLES] = object['self']\n            profile.add_function(function)\n            profile[SAMPLES] += function[SAMPLES]\n\n        for id, node in compat_iteritems(nodes):\n            # Ignore fake calls\n            if node['self'] == 0:\n                continue\n\n            # Find a non-ignored parent\n            parent_id = node['parent']\n            while parent_id != 0:\n                parent = nodes[parent_id]\n                caller_id = parent['object']\n                if objects[caller_id]['self'] != 0:\n                    break\n                parent_id = parent['parent']\n            if parent_id == 0:\n                continue\n\n            callee_id = node['object']\n\n            assert objects[caller_id]['self']\n            assert objects[callee_id]['self']\n\n            function = profile.functions[caller_id]\n\n            samples = node['self']\n            try:\n                call = function.calls[callee_id]\n            except KeyError:\n                call = Call(callee_id)\n                call[SAMPLES2] = samples\n                function.add_call(call)\n            else:\n                call[SAMPLES2] += samples\n\n        # Compute derived events\n        profile.validate()\n        profile.find_cycles()\n        profile.ratio(TIME_RATIO, SAMPLES)\n        profile.call_ratios(SAMPLES2)\n        profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return profile\n\n\nclass XPerfParser(Parser):\n    \"\"\"Parser for CSVs generted by XPerf, from Microsoft Windows Performance Tools.\n    \"\"\"\n\n    def __init__(self, stream):\n        Parser.__init__(self)\n        self.stream = stream\n        self.profile = Profile()\n        self.profile[SAMPLES] = 0\n        self.column = {}\n\n    def parse(self):\n        import csv\n        reader = csv.reader(\n            self.stream, \n            delimiter = ',',\n            quotechar = None,\n            escapechar = None,\n            doublequote = False,\n            skipinitialspace = True,\n            lineterminator = '\\r\\n',\n            quoting = csv.QUOTE_NONE)\n        header = True\n        for row in reader:\n            if header:\n                self.parse_header(row)\n                header = False\n            else:\n                self.parse_row(row)\n                \n        # compute derived data\n        self.profile.validate()\n        self.profile.find_cycles()\n        self.profile.ratio(TIME_RATIO, SAMPLES)\n        self.profile.call_ratios(SAMPLES2)\n        self.profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return self.profile\n\n    def parse_header(self, row):\n        for column in range(len(row)):\n            name = row[column]\n            assert name not in self.column\n            self.column[name] = column\n\n    def parse_row(self, row):\n        fields = {}\n        for name, column in compat_iteritems(self.column):\n            value = row[column]\n            for factory in int, float:\n                try:\n                    value = factory(value)\n                except ValueError:\n                    pass\n                else:\n                    break\n            fields[name] = value\n        \n        process = fields['Process Name']\n        symbol = fields['Module'] + '!' + fields['Function']\n        weight = fields['Weight']\n        count = fields['Count']\n\n        if process == 'Idle':\n            return\n\n        function = self.get_function(process, symbol)\n        function[SAMPLES] += weight * count\n        self.profile[SAMPLES] += weight * count\n\n        stack = fields['Stack']\n        if stack != '?':\n            stack = stack.split('/')\n            assert stack[0] == '[Root]'\n            if stack[-1] != symbol:\n                # XXX: some cases the sampled function does not appear in the stack\n                stack.append(symbol)\n            caller = None\n            for symbol in stack[1:]:\n                callee = self.get_function(process, symbol)\n                if caller is not None:\n                    try:\n                        call = caller.calls[callee.id]\n                    except KeyError:\n                        call = Call(callee.id)\n                        call[SAMPLES2] = count\n                        caller.add_call(call)\n                    else:\n                        call[SAMPLES2] += count\n                caller = callee\n\n    def get_function(self, process, symbol):\n        function_id = process + '!' + symbol\n\n        try:\n            function = self.profile.functions[function_id]\n        except KeyError:\n            module, name = symbol.split('!', 1)\n            function = Function(function_id, name)\n            function.process = process\n            function.module = module\n            function[SAMPLES] = 0\n            self.profile.add_function(function)\n\n        return function\n\n\nclass SleepyParser(Parser):\n    \"\"\"Parser for GNU gprof output.\n\n    See also:\n    - http://www.codersnotes.com/sleepy/\n    - http://sleepygraph.sourceforge.net/\n    \"\"\"\n\n    stdinInput = False\n\n    def __init__(self, filename):\n        Parser.__init__(self)\n\n        from zipfile import ZipFile\n\n        self.database = ZipFile(filename)\n\n        self.symbols = {}\n        self.calls = {}\n\n        self.profile = Profile()\n    \n    _symbol_re = re.compile(\n        r'^(?P<id>\\w+)' + \n        r'\\s+\"(?P<module>[^\"]*)\"' + \n        r'\\s+\"(?P<procname>[^\"]*)\"' + \n        r'\\s+\"(?P<sourcefile>[^\"]*)\"' + \n        r'\\s+(?P<sourceline>\\d+)$'\n    )\n\n    def openEntry(self, name):\n        # Some versions of verysleepy use lowercase filenames\n        for database_name in self.database.namelist():\n            if name.lower() == database_name.lower():\n                name = database_name\n                break\n\n        return self.database.open(name, 'r')\n\n    def parse_symbols(self):\n        for line in self.openEntry('Symbols.txt'):\n            line = line.decode('UTF-8').rstrip('\\r\\n')\n\n            mo = self._symbol_re.match(line)\n            if mo:\n                symbol_id, module, procname, sourcefile, sourceline = mo.groups()\n    \n                function_id = ':'.join([module, procname])\n\n                try:\n                    function = self.profile.functions[function_id]\n                except KeyError:\n                    function = Function(function_id, procname)\n                    function.module = module\n                    function[SAMPLES] = 0\n                    self.profile.add_function(function)\n\n                self.symbols[symbol_id] = function\n\n    def parse_callstacks(self):\n        for line in self.openEntry('Callstacks.txt'):\n            line = line.decode('UTF-8').rstrip('\\r\\n')\n\n            fields = line.split()\n            samples = float(fields[0])\n            callstack = fields[1:]\n\n            callstack = [self.symbols[symbol_id] for symbol_id in callstack]\n\n            callee = callstack[0]\n\n            callee[SAMPLES] += samples\n            self.profile[SAMPLES] += samples\n            \n            for caller in callstack[1:]:\n                try:\n                    call = caller.calls[callee.id]\n                except KeyError:\n                    call = Call(callee.id)\n                    call[SAMPLES2] = samples\n                    caller.add_call(call)\n                else:\n                    call[SAMPLES2] += samples\n\n                callee = caller\n\n    def parse(self):\n        profile = self.profile\n        profile[SAMPLES] = 0\n\n        self.parse_symbols()\n        self.parse_callstacks()\n\n        # Compute derived events\n        profile.validate()\n        profile.find_cycles()\n        profile.ratio(TIME_RATIO, SAMPLES)\n        profile.call_ratios(SAMPLES2)\n        profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)\n\n        return profile\n\n\nclass PstatsParser:\n    \"\"\"Parser python profiling statistics saved with te pstats module.\"\"\"\n\n    stdinInput = False\n    multipleInput = True\n\n    def __init__(self, *filename):\n        import pstats\n        try:\n            self.stats = pstats.Stats(*filename)\n        except ValueError:\n            if PYTHON_3:\n                sys.stderr.write('error: failed to load %s\\n' % ', '.join(filename))\n                sys.exit(1)\n            import hotshot.stats\n            self.stats = hotshot.stats.load(filename[0])\n        self.profile = Profile()\n        self.function_ids = {}\n\n    def get_function_name(self, key):\n        filename, line, name = key\n        module = os.path.splitext(filename)[0]\n        module = os.path.basename(module)\n        return \"%s:%d:%s\" % (module, line, name)\n\n    def get_function(self, key):\n        try:\n            id = self.function_ids[key]\n        except KeyError:\n            id = len(self.function_ids)\n            name = self.get_function_name(key)\n            function = Function(id, name)\n            function.filename = key[0]\n            self.profile.functions[id] = function\n            self.function_ids[key] = id\n        else:\n            function = self.profile.functions[id]\n        return function\n\n    def parse(self):\n        self.profile[TIME] = 0.0\n        self.profile[TOTAL_TIME] = self.stats.total_tt\n        for fn, (cc, nc, tt, ct, callers) in compat_iteritems(self.stats.stats):\n            callee = self.get_function(fn)\n            callee.called = nc\n            callee[TOTAL_TIME] = ct\n            callee[TIME] = tt\n            self.profile[TIME] += tt\n            self.profile[TOTAL_TIME] = max(self.profile[TOTAL_TIME], ct)\n            for fn, value in compat_iteritems(callers):\n                caller = self.get_function(fn)\n                call = Call(callee.id)\n                if isinstance(value, tuple):\n                    for i in xrange(0, len(value), 4):\n                        nc, cc, tt, ct = value[i:i+4]\n                        if CALLS in call:\n                            call[CALLS] += cc\n                        else:\n                            call[CALLS] = cc\n\n                        if TOTAL_TIME in call:\n                            call[TOTAL_TIME] += ct\n                        else:\n                            call[TOTAL_TIME] = ct\n\n                else:\n                    call[CALLS] = value\n                    call[TOTAL_TIME] = ratio(value, nc)*ct\n\n                caller.add_call(call)\n\n        if False:\n            self.stats.print_stats()\n            self.stats.print_callees()\n\n        # Compute derived events\n        self.profile.validate()\n        self.profile.ratio(TIME_RATIO, TIME)\n        self.profile.ratio(TOTAL_TIME_RATIO, TOTAL_TIME)\n\n        return self.profile\n\n\nformats = {\n    \"axe\": AXEParser,\n    \"callgrind\": CallgrindParser,\n    \"hprof\": HProfParser,\n    \"json\": JsonParser,\n    \"oprofile\": OprofileParser,\n    \"perf\": PerfParser,\n    \"prof\": GprofParser,\n    \"pstats\": PstatsParser,\n    \"sleepy\": SleepyParser,\n    \"sysprof\": SysprofParser,\n    \"xperf\": XPerfParser,\n}\n\n\n########################################################################\n# Output\n\n\nclass Theme:\n\n    def __init__(self, \n            bgcolor = (0.0, 0.0, 1.0),\n            mincolor = (0.0, 0.0, 0.0),\n            maxcolor = (0.0, 0.0, 1.0),\n            fontname = \"Arial\",\n            fontcolor = \"white\",\n            nodestyle = \"filled\",\n            minfontsize = 10.0,\n            maxfontsize = 10.0,\n            minpenwidth = 0.5,\n            maxpenwidth = 4.0,\n            gamma = 2.2,\n            skew = 1.0):\n        self.bgcolor = bgcolor\n        self.mincolor = mincolor\n        self.maxcolor = maxcolor\n        self.fontname = fontname\n        self.fontcolor = fontcolor\n        self.nodestyle = nodestyle\n        self.minfontsize = minfontsize\n        self.maxfontsize = maxfontsize\n        self.minpenwidth = minpenwidth\n        self.maxpenwidth = maxpenwidth\n        self.gamma = gamma\n        self.skew = skew\n\n    def graph_bgcolor(self):\n        return self.hsl_to_rgb(*self.bgcolor)\n\n    def graph_fontname(self):\n        return self.fontname\n\n    def graph_fontcolor(self):\n        return self.fontcolor\n\n    def graph_fontsize(self):\n        return self.minfontsize\n\n    def node_bgcolor(self, weight):\n        return self.color(weight)\n\n    def node_fgcolor(self, weight):\n        if self.nodestyle == \"filled\":\n            return self.graph_bgcolor()\n        else:\n            return self.color(weight)\n\n    def node_fontsize(self, weight):\n        return self.fontsize(weight)\n\n    def node_style(self):\n        return self.nodestyle\n\n    def edge_color(self, weight):\n        return self.color(weight)\n\n    def edge_fontsize(self, weight):\n        return self.fontsize(weight)\n\n    def edge_penwidth(self, weight):\n        return max(weight*self.maxpenwidth, self.minpenwidth)\n\n    def edge_arrowsize(self, weight):\n        return 0.5 * math.sqrt(self.edge_penwidth(weight))\n\n    def fontsize(self, weight):\n        return max(weight**2 * self.maxfontsize, self.minfontsize)\n\n    def color(self, weight):\n        weight = min(max(weight, 0.0), 1.0)\n    \n        hmin, smin, lmin = self.mincolor\n        hmax, smax, lmax = self.maxcolor\n        \n        if self.skew < 0:\n            raise ValueError(\"Skew must be greater than 0\")\n        elif self.skew == 1.0:\n            h = hmin + weight*(hmax - hmin)\n            s = smin + weight*(smax - smin)\n            l = lmin + weight*(lmax - lmin)\n        else:\n            base = self.skew\n            h = hmin + ((hmax-hmin)*(-1.0 + (base ** weight)) / (base - 1.0))\n            s = smin + ((smax-smin)*(-1.0 + (base ** weight)) / (base - 1.0))\n            l = lmin + ((lmax-lmin)*(-1.0 + (base ** weight)) / (base - 1.0))\n\n        return self.hsl_to_rgb(h, s, l)\n\n    def hsl_to_rgb(self, h, s, l):\n        \"\"\"Convert a color from HSL color-model to RGB.\n\n        See also:\n        - http://www.w3.org/TR/css3-color/#hsl-color\n        \"\"\"\n\n        h = h % 1.0\n        s = min(max(s, 0.0), 1.0)\n        l = min(max(l, 0.0), 1.0)\n\n        if l <= 0.5:\n            m2 = l*(s + 1.0)\n        else:\n            m2 = l + s - l*s\n        m1 = l*2.0 - m2\n        r = self._hue_to_rgb(m1, m2, h + 1.0/3.0)\n        g = self._hue_to_rgb(m1, m2, h)\n        b = self._hue_to_rgb(m1, m2, h - 1.0/3.0)\n\n        # Apply gamma correction\n        r **= self.gamma\n        g **= self.gamma\n        b **= self.gamma\n\n        return (r, g, b)\n\n    def _hue_to_rgb(self, m1, m2, h):\n        if h < 0.0:\n            h += 1.0\n        elif h > 1.0:\n            h -= 1.0\n        if h*6 < 1.0:\n            return m1 + (m2 - m1)*h*6.0\n        elif h*2 < 1.0:\n            return m2\n        elif h*3 < 2.0:\n            return m1 + (m2 - m1)*(2.0/3.0 - h)*6.0\n        else:\n            return m1\n\n\nTEMPERATURE_COLORMAP = Theme(\n    mincolor = (2.0/3.0, 0.80, 0.25), # dark blue\n    maxcolor = (0.0, 1.0, 0.5), # satured red\n    gamma = 1.0\n)\n\nPINK_COLORMAP = Theme(\n    mincolor = (0.0, 1.0, 0.90), # pink\n    maxcolor = (0.0, 1.0, 0.5), # satured red\n)\n\nGRAY_COLORMAP = Theme(\n    mincolor = (0.0, 0.0, 0.85), # light gray\n    maxcolor = (0.0, 0.0, 0.0), # black\n)\n\nBW_COLORMAP = Theme(\n    minfontsize = 8.0,\n    maxfontsize = 24.0,\n    mincolor = (0.0, 0.0, 0.0), # black\n    maxcolor = (0.0, 0.0, 0.0), # black\n    minpenwidth = 0.1,\n    maxpenwidth = 8.0,\n)\n\nPRINT_COLORMAP = Theme(\n    minfontsize = 18.0,\n    maxfontsize = 30.0,\n    fontcolor = \"black\",\n    nodestyle = \"solid\",\n    mincolor = (0.0, 0.0, 0.0), # black\n    maxcolor = (0.0, 0.0, 0.0), # black\n    minpenwidth = 0.1,\n    maxpenwidth = 8.0,\n)\n\n\nthemes = {\n    \"color\": TEMPERATURE_COLORMAP,\n    \"pink\": PINK_COLORMAP,\n    \"gray\": GRAY_COLORMAP,\n    \"bw\": BW_COLORMAP,\n    \"print\": PRINT_COLORMAP,\n}\n\n\ndef sorted_iteritems(d):\n    # Used mostly for result reproducibility (while testing.)\n    keys = compat_keys(d)\n    keys.sort()\n    for key in keys:\n        value = d[key]\n        yield key, value\n\n\nclass DotWriter:\n    \"\"\"Writer for the DOT language.\n\n    See also:\n    - \"The DOT Language\" specification\n      http://www.graphviz.org/doc/info/lang.html\n    \"\"\"\n\n    strip = False\n    wrap = False\n\n    def __init__(self, fp):\n        self.fp = fp\n\n    def wrap_function_name(self, name):\n        \"\"\"Split the function name on multiple lines.\"\"\"\n\n        if len(name) > 32:\n            ratio = 2.0/3.0\n            height = max(int(len(name)/(1.0 - ratio) + 0.5), 1)\n            width = max(len(name)/height, 32)\n            # TODO: break lines in symbols\n            name = textwrap.fill(name, width, break_long_words=False)\n\n        # Take away spaces\n        name = name.replace(\", \", \",\")\n        name = name.replace(\"> >\", \">>\")\n        name = name.replace(\"> >\", \">>\") # catch consecutive\n\n        return name\n\n    show_function_events = [TOTAL_TIME_RATIO, TIME_RATIO]\n    show_edge_events = [TOTAL_TIME_RATIO, CALLS]\n\n    def graph(self, profile, theme):\n        self.begin_graph()\n\n        fontname = theme.graph_fontname()\n        fontcolor = theme.graph_fontcolor()\n        nodestyle = theme.node_style()\n\n        self.attr('graph', fontname=fontname, ranksep=0.25, nodesep=0.125)\n        self.attr('node', fontname=fontname, shape=\"box\", style=nodestyle, fontcolor=fontcolor, width=0, height=0)\n        self.attr('edge', fontname=fontname)\n\n        for _, function in sorted_iteritems(profile.functions):\n            labels = []\n            if function.process is not None:\n                labels.append(function.process)\n            if function.module is not None:\n                labels.append(function.module)\n\n            if self.strip:\n                function_name = function.stripped_name()\n            else:\n                function_name = function.name\n\n            # dot can't parse quoted strings longer than YY_BUF_SIZE, which\n            # defaults to 16K. But some annotated C++ functions (e.g., boost,\n            # https://github.com/jrfonseca/gprof2dot/issues/30) can exceed that\n            MAX_FUNCTION_NAME = 4096\n            if len(function_name) >= MAX_FUNCTION_NAME:\n                sys.stderr.write('warning: truncating function name with %u chars (%s)\\n' % (len(function_name), function_name[:32] + '...'))\n                function_name = function_name[:MAX_FUNCTION_NAME - 1] + unichr(0x2026)\n\n            if self.wrap:\n                function_name = self.wrap_function_name(function_name)\n            labels.append(function_name)\n\n            for event in self.show_function_events:\n                if event in function.events:\n                    label = event.format(function[event])\n                    labels.append(label)\n            if function.called is not None:\n                labels.append(\"%u%s\" % (function.called, MULTIPLICATION_SIGN))\n\n            if function.weight is not None:\n                weight = function.weight\n            else:\n                weight = 0.0\n\n            label = '\\n'.join(labels)\n            self.node(function.id, \n                label = label, \n                color = self.color(theme.node_bgcolor(weight)), \n                fontcolor = self.color(theme.node_fgcolor(weight)), \n                fontsize = \"%.2f\" % theme.node_fontsize(weight),\n                tooltip = function.filename,\n            )\n\n            for _, call in sorted_iteritems(function.calls):\n                callee = profile.functions[call.callee_id]\n\n                labels = []\n                for event in self.show_edge_events:\n                    if event in call.events:\n                        label = event.format(call[event])\n                        labels.append(label)\n\n                if call.weight is not None:\n                    weight = call.weight\n                elif callee.weight is not None:\n                    weight = callee.weight\n                else:\n                    weight = 0.0\n\n                label = '\\n'.join(labels)\n\n                self.edge(function.id, call.callee_id, \n                    label = label, \n                    color = self.color(theme.edge_color(weight)), \n                    fontcolor = self.color(theme.edge_color(weight)),\n                    fontsize = \"%.2f\" % theme.edge_fontsize(weight), \n                    penwidth = \"%.2f\" % theme.edge_penwidth(weight), \n                    labeldistance = \"%.2f\" % theme.edge_penwidth(weight), \n                    arrowsize = \"%.2f\" % theme.edge_arrowsize(weight),\n                )\n\n        self.end_graph()\n\n    def begin_graph(self):\n        self.write('digraph {\\n')\n\n    def end_graph(self):\n        self.write('}\\n')\n\n    def attr(self, what, **attrs):\n        self.write(\"\\t\")\n        self.write(what)\n        self.attr_list(attrs)\n        self.write(\";\\n\")\n\n    def node(self, node, **attrs):\n        self.write(\"\\t\")\n        self.id(node)\n        self.attr_list(attrs)\n        self.write(\";\\n\")\n\n    def edge(self, src, dst, **attrs):\n        self.write(\"\\t\")\n        self.id(src)\n        self.write(\" -> \")\n        self.id(dst)\n        self.attr_list(attrs)\n        self.write(\";\\n\")\n\n    def attr_list(self, attrs):\n        if not attrs:\n            return\n        self.write(' [')\n        first = True\n        for name, value in sorted_iteritems(attrs):\n            if value is None:\n                continue\n            if first:\n                first = False\n            else:\n                self.write(\", \")\n            self.id(name)\n            self.write('=')\n            self.id(value)\n        self.write(']')\n\n    def id(self, id):\n        if isinstance(id, (int, float)):\n            s = str(id)\n        elif isinstance(id, basestring):\n            if id.isalnum() and not id.startswith('0x'):\n                s = id\n            else:\n                s = self.escape(id)\n        else:\n            raise TypeError\n        self.write(s)\n\n    def color(self, rgb):\n        r, g, b = rgb\n\n        def float2int(f):\n            if f <= 0.0:\n                return 0\n            if f >= 1.0:\n                return 255\n            return int(255.0*f + 0.5)\n\n        return \"#\" + \"\".join([\"%02x\" % float2int(c) for c in (r, g, b)])\n\n    def escape(self, s):\n        if not PYTHON_3:\n            s = s.encode('utf-8')\n        s = s.replace('\\\\', r'\\\\')\n        s = s.replace('\\n', r'\\n')\n        s = s.replace('\\t', r'\\t')\n        s = s.replace('\"', r'\\\"')\n        return '\"' + s + '\"'\n\n    def write(self, s):\n        self.fp.write(s)\n\n\n\n########################################################################\n# Main program\n\n\ndef naturalJoin(values):\n    if len(values) >= 2:\n        return ', '.join(values[:-1]) + ' or ' + values[-1]\n\n    else:\n        return ''.join(values)\n\n\ndef main():\n    \"\"\"Main program.\"\"\"\n\n    global totalMethod\n\n    formatNames = list(formats.keys())\n    formatNames.sort()\n\n    optparser = optparse.OptionParser(\n        usage=\"\\n\\t%prog [options] [file] ...\")\n    optparser.add_option(\n        '-o', '--output', metavar='FILE',\n        type=\"string\", dest=\"output\",\n        help=\"output filename [stdout]\")\n    optparser.add_option(\n        '-n', '--node-thres', metavar='PERCENTAGE',\n        type=\"float\", dest=\"node_thres\", default=0.5,\n        help=\"eliminate nodes below this threshold [default: %default]\")\n    optparser.add_option(\n        '-e', '--edge-thres', metavar='PERCENTAGE',\n        type=\"float\", dest=\"edge_thres\", default=0.1,\n        help=\"eliminate edges below this threshold [default: %default]\")\n    optparser.add_option(\n        '-f', '--format',\n        type=\"choice\", choices=formatNames,\n        dest=\"format\", default=\"prof\",\n        help=\"profile format: %s [default: %%default]\" % naturalJoin(formatNames))\n    optparser.add_option(\n        '--total',\n        type=\"choice\", choices=('callratios', 'callstacks'),\n        dest=\"totalMethod\", default=totalMethod,\n        help=\"preferred method of calculating total time: callratios or callstacks (currently affects only perf format) [default: %default]\")\n    optparser.add_option(\n        '-c', '--colormap',\n        type=\"choice\", choices=('color', 'pink', 'gray', 'bw', 'print'),\n        dest=\"theme\", default=\"color\",\n        help=\"color map: color, pink, gray, bw, or print [default: %default]\")\n    optparser.add_option(\n        '-s', '--strip',\n        action=\"store_true\",\n        dest=\"strip\", default=False,\n        help=\"strip function parameters, template parameters, and const modifiers from demangled C++ function names\")\n    optparser.add_option(\n        '--color-nodes-by-selftime',\n        action=\"store_true\",\n        dest=\"color_nodes_by_selftime\", default=False,\n        help=\"color nodes by self time, rather than by total time (sum of self and descendants)\")\n    optparser.add_option(\n        '--colour-nodes-by-selftime',\n        action=\"store_true\",\n        dest=\"color_nodes_by_selftime\",\n        help=optparse.SUPPRESS_HELP)\n    optparser.add_option(\n        '-w', '--wrap',\n        action=\"store_true\",\n        dest=\"wrap\", default=False,\n        help=\"wrap function names\")\n    optparser.add_option(\n        '--show-samples',\n        action=\"store_true\",\n        dest=\"show_samples\", default=False,\n        help=\"show function samples\")\n    # add option to create subtree or show paths\n    optparser.add_option(\n        '-z', '--root',\n        type=\"string\",\n        dest=\"root\", default=\"\",\n        help=\"prune call graph to show only descendants of specified root function\")\n    optparser.add_option(\n        '-l', '--leaf',\n        type=\"string\",\n        dest=\"leaf\", default=\"\",\n        help=\"prune call graph to show only ancestors of specified leaf function\")\n    optparser.add_option(\n        '--depth',\n        type=\"int\",\n        dest=\"depth\", default=-1,\n        help=\"prune call graph to show only descendants or ancestors until specified depth\")\n    # add a new option to control skew of the colorization curve\n    optparser.add_option(\n        '--skew',\n        type=\"float\", dest=\"theme_skew\", default=1.0,\n        help=\"skew the colorization curve.  Values < 1.0 give more variety to lower percentages.  Values > 1.0 give less variety to lower percentages\")\n    # add option for filtering by file path\n    optparser.add_option(\n        '-p', '--path', action=\"append\",\n        type=\"string\", dest=\"filter_paths\",\n        help=\"Filter all modules not in a specified path\")\n    (options, args) = optparser.parse_args(sys.argv[1:])\n\n    if len(args) > 1 and options.format != 'pstats':\n        optparser.error('incorrect number of arguments')\n\n    try:\n        theme = themes[options.theme]\n    except KeyError:\n        optparser.error('invalid colormap \\'%s\\'' % options.theme)\n\n    # set skew on the theme now that it has been picked.\n    if options.theme_skew:\n        theme.skew = options.theme_skew\n\n    totalMethod = options.totalMethod\n\n    try:\n        Format = formats[options.format]\n    except KeyError:\n        optparser.error('invalid format \\'%s\\'' % options.format)\n\n    if Format.stdinInput:\n        if not args:\n            fp = sys.stdin\n        elif PYTHON_3:\n            fp = open(args[0], 'rt', encoding='UTF-8')\n        else:\n            fp = open(args[0], 'rt')\n        parser = Format(fp)\n    elif Format.multipleInput:\n        if not args:\n            optparser.error('at least a file must be specified for %s input' % options.format)\n        parser = Format(*args)\n    else:\n        if len(args) != 1:\n            optparser.error('exactly one file must be specified for %s input' % options.format)\n        parser = Format(args[0])\n\n    profile = parser.parse()\n\n    if options.output is None:\n        if PYTHON_3:\n            output = open(sys.stdout.fileno(), mode='wt', encoding='UTF-8', closefd=False)\n        else:\n            output = sys.stdout\n    else:\n        if PYTHON_3:\n            output = open(options.output, 'wt', encoding='UTF-8')\n        else:\n            output = open(options.output, 'wt')\n\n    dot = DotWriter(output)\n    dot.strip = options.strip\n    dot.wrap = options.wrap\n    if options.show_samples:\n        dot.show_function_events.append(SAMPLES)\n\n    profile = profile\n    profile.prune(options.node_thres/100.0, options.edge_thres/100.0, options.filter_paths, options.color_nodes_by_selftime)\n\n    if options.root:\n        rootIds = profile.getFunctionIds(options.root)\n        if not rootIds:\n            sys.stderr.write('root node ' + options.root + ' not found (might already be pruned : try -e0 -n0 flags)\\n')\n            sys.exit(1)\n        profile.prune_root(rootIds, options.depth)\n    if options.leaf:\n        leafIds = profile.getFunctionIds(options.leaf)\n        if not leafIds:\n            sys.stderr.write('leaf node ' + options.leaf + ' not found (maybe already pruned : try -e0 -n0 flags)\\n')\n            sys.exit(1)\n        profile.prune_leaf(leafIds, options.depth)\n\n    dot.graph(profile, theme)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "scripts/run.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport os\nimport datetime\nfrom run_base import *\n\n# constants\nbinary = 'iccad19gr'\n\n# argparse\nparser = argparse.ArgumentParser()\nparser.add_argument('benchmarks', choices=all_benchmarks.get_choices(), nargs='+', metavar='BENCHMARK',\n                    help='Choices are ' + ', '.join(all_benchmarks.get_choices()))\nparser.add_argument('-m', '--mode', choices=modes)\nparser.add_argument(\n    '-s', '--steps', choices=['route', 'eval', 'view'], nargs='+', default=['route'])\nparser.add_argument('-p', '--benchmark_path')\nparser.add_argument('-t', '--threads', type=int, default=8)\nargs = parser.parse_args()\n\n# seleted benchmarks\nbms = all_benchmarks.get_selected(args.benchmarks)\nbm_path = args.benchmark_path\nif bm_path is None:\n    bm_path = os.environ.get('BENCHMARK_PATH')\n    if bm_path is None:\n        print('Benchmark path is not specified.')\n        quit()\n\n\n# mode cmd_prefix\ncmd_prefix = mode_prefixes[args.mode]\nif args.mode == 'valgrind':\n    print('Please make sure the binary is not compiled with static linking to avoid false alarm')\n\n# run\nif True:\n    now = datetime.datetime.now()\n    log_dir = 'run{:02d}{:02d}'.format(now.month, now.day)\n\nrun('mkdir -p {}'.format(log_dir))\nprint('The following benchmarks will be ran: ', bms)\n\n\ndef route():\n    guide_file = '{0}/{1}.solution.guide'.format(bm_log_dir, bm.full_name)\n    log_file = '{0}/{1}.log'.format(bm_log_dir, bm.full_name)\n    \n    run('{cmd_prefix} ./{0} -lef {1}.input.lef -def {1}.input.def -threads {2} -output {3} |& tee {4}'.format(\n        binary, file_name_prefix, args.threads, guide_file, log_file, cmd_prefix=cmd_prefix))\n\n    if args.mode == 'gprof':\n        run('gprof {} > {}.gprof'.format(binary, bm.full_name))\n        run('./gprof2dot.py -s {0}.gprof | dot -Tpdf -o {0}.pdf'.format(bm.full_name))\n\n    run('mv *.solution.guide* *.log *.gprof *.pdf {} 2>/dev/null'.format(bm_log_dir))\n\n\ndef evaluate():\n    guide_file = '{0}/{1}.solution.guide'.format(bm_log_dir, bm.full_name)\n    sol_file = '{0}/{1}.solution.def'.format(bm_log_dir, bm.full_name)\n    dr_log_file = '{0}/{1}_dr_eval.log'.format(bm_log_dir, bm.full_name)\n    log_file = '{0}/{1}_eval.log'.format(bm_log_dir, bm.full_name)\n    dr_file = 'drcu'\n    bm_yy = int(bm.full_name[4:6])\n    run('cp ispd{0}eval/ispd{0}eval* ./'.format(bm_yy))\n\n    def evaluate_once():\n        run('./{0} -lef {1}.input.lef -def {1}.input.def -guide {2} -threads {3} -tat 2000000000 -output {4} |& tee {5}'.format(\n            dr_file, file_name_prefix, guide_file, args.threads, sol_file, dr_log_file))\n\n        if bm_yy == 18:\n            run('./ispd{0}eval.sh -lef {1}.input.lef -guide {2} -def {3} -thread {4} |& tee {5}'.format(\n                bm_yy, file_name_prefix, guide_file, sol_file, args.threads, log_file))\n        else:\n            run('./ispd{0}eval.sh -lef {1}.input.lef -guide {2} -idef {1}.input.def -odef {3} -thread {4} |& tee {5}'.format(\n                bm_yy, file_name_prefix, guide_file, sol_file, args.threads, log_file))\n\n    evaluate_once()\n\n    run('rm ispd{0}eval_bin ispd{0}eval.sh ispd{0}eval.tcl ispd{0}eval.w *.def.v eval.def'.format(bm_yy))\n    run('mv *.log innovus.* *.solution.def* eval.*.rpt {} 2>/dev/null'.format(bm_log_dir))\n\n\ndef view():\n    file = open(\"tmp.tcl\", \"w\")\n    file.write(\"loadLefFile {}.input.lef\\n\".format(file_name_prefix))\n    file.write(\"loadDefFile {}/{}.solution.def\\n\".format(bm_log_dir, bm.full_name))\n    file.write(\"setMultiCpuUsage -localCpu {}\\n\".format(args.threads))\n    file.write(\"win\\n\")\n    file.close()\n    run('innovus -init tmp.tcl')\n    run('rm innovus.* *.drc.rpt *.solution.def.v tmp.tcl')\n\n\nfor bm in bms:\n    bm_log_dir = '{}/{}'.format(log_dir, bm.abbr_name)\n    file_name_prefix = '{0}/iccad2019c/{1}/{1}'.format(bm_path, bm.full_name)\n\n    run('mkdir -p {}'.format(bm_log_dir))\n    if 'route' in args.steps:\n        route()\n    if 'eval' in args.steps:\n        evaluate()\n    if 'view' in args.steps:\n        view()\n"
  },
  {
    "path": "scripts/run_base.py",
    "content": "import os\n\n# run command\ndef run(command):\n    print(command)\n    os.system('/bin/bash -c \\'{0}\\''.format(command))\n\n# run modes\nmodes = ['gdb', 'valgrind', 'vgdb', 'gprof']\nmode_prefixes = {\n    None        : '',\n    'gprof'     : '',\n    'gdb'       : 'gdb --args',\n    'valgrind'  : 'valgrind',\n    'vgdb'      : 'valgrind --vgdb-error=0'\n}\n\n# benchmarks\nclass Benchmark:\n    def __init__(self, full_name, abbr_name):\n        self.full_name = full_name\n        self.abbr_name = abbr_name\n    def __repr__(self):\n        return self.full_name\n\nclass Benchmarks:\n    def __init__(self):\n        self.__bms = []\n        self.__bm_sets = dict()\n\n    def add(self, full_name_pat, abbr_name_pat, ids):\n        for id in ids:\n            self.__bms.append(Benchmark(full_name_pat.format(id), abbr_name_pat.format(id)))\n\n    def get_bm(self, name):\n        # TODO: can be faster by using hash table\n        for bm in self.__bms:\n            if name == bm.abbr_name or name == bm.full_name:\n                return bm\n        print('Error: benchmark', name, 'cannot be found')\n        quit()\n\n    def add_set(self, set_name, bm_names):\n        bms = []\n        for name in bm_names:\n            bms.append(self.get_bm(name))\n        self.__bm_sets[set_name] = bms\n\n    def get_choices(self):\n        choices = []\n        for bm in self.__bms:\n            choices.append(bm.full_name)\n            choices.append(bm.abbr_name)\n        for bm_set in self.__bm_sets:\n            choices.append(bm_set)\n        choices.append('all')\n        return choices\n\n    def get_selected(self, names):\n        if 'all' in names:\n            return self.__bms\n        else:\n            selected = []\n            for name in names:\n                if name in self.__bm_sets:\n                    selected += self.__bm_sets[name]\n                else:\n                    selected.append(self.get_bm(name))\n            return selected\n\n\n######################################\n# Below is project-dependant setting #\n######################################\n\n\n# all benchmarks\nall_benchmarks = Benchmarks()\nall_benchmarks.add('ispd18_test{}', '8t{}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])\nall_benchmarks.add('ispd19_test{}', '9t{}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])\nall_benchmarks.add('ispd18_test{}_metal5', '8t{}m', ['5', '8', '10'])\nall_benchmarks.add('ispd19_test{}_metal5', '9t{}m', ['7', '8', '9'])\n\nall_benchmarks.add_set('contest', ['8t5', '8t8', '8t10', '9t7', '9t8', '9t9', '8t5m', '8t8m', '8t10m', '9t7m', '9t8m', '9t9m'])\nall_benchmarks.add_set('all18', ['8t1', '8t2', '8t3', '8t4', '8t5', '8t6', '8t7', '8t8', '8t9', '8t10', '8t5m', '8t8m', '8t10m'])\nall_benchmarks.add_set('all19', ['9t1', '9t2', '9t3', '9t4', '9t5', '9t6', '9t7', '9t8', '9t9', '9t10', '9t7m', '9t8m', '9t9m'])\n"
  },
  {
    "path": "src/.clang-format",
    "content": "BasedOnStyle: Google\nIndentWidth: 4\nAccessModifierOffset: -4\nBinPackArguments: false\nBinPackParameters: false\nColumnLimit: 120\nSortIncludes: false"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "#########\n# Setup #\n#########\n\n# Specify the minimum version for CMake\ncmake_minimum_required(VERSION 2.8)\n\n# Message\nmessage(STATUS \"ICCAD19 GR CUHK\")\nmessage(STATUS ${CMAKE_CURRENT_SOURCE_DIR})\nmessage(STATUS ${PROJECT_SOURCE_DIR})\n\n# Find includes in the build directories\nset(CMAKE_INCLUDE_CURRENT_DIR ON)\n\n# Project's name\nproject(iccad19gr)\n\n# Set the output folder where your program will be created\nset(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})\nset(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})\n\nset(CMAKE_CXX_STANDARD 14)\n\nset(PATH_RSYN ${CMAKE_CURRENT_SOURCE_DIR}/../rsyn)\nset(PATH_ICCAD19 ${CMAKE_CURRENT_SOURCE_DIR})\n\n###################\n# Warnings/Errors #\n###################\n\nset(CMAKE_CXX_FLAGS  \"${CMAKE_CXX_FLAGS} -Werror=return-type\")\n\n######################\n# Check Dependencies #\n######################\n# uncommment this line if you are using self-compiled boost lib\nset(Boost_USE_STATIC_LIBS ON)\nfind_package(Boost COMPONENTS system filesystem program_options REQUIRED)\n# find_package(Threads)\n\n###############\n# Source Code #\n###############\nfile(GLOB_RECURSE SRC_FILES_RSYN\n    ${PATH_RSYN}/src/*.cpp\n    ${PATH_RSYN}/src/*.cc\n    ${PATH_RSYN}/src/*.c)\n\nfile(GLOB_RECURSE SRC_FILES_ICCAD19\n    ${PATH_ICCAD19}/*.cpp\n    ${PATH_ICCAD19}/*.c)\n\nset(SRC_FILES ${SRC_FILES_RSYN} ${SRC_FILES_ICCAD19})\n\n#################\n# Library Paths #\n#################\n# Need to come before target is created.\n\nif(${CMAKE_SYSTEM_NAME} MATCHES \"Linux\")\nlink_directories(${PATH_RSYN}/lib/linux)\nendif()\n\nif(${CMAKE_SYSTEM_NAME} MATCHES \"Darwin\")\nlink_directories(${PATH_RSYN}/lib/macosx)\nendif()\n\n###########\n# Targets #\n###########\n\nadd_executable(iccad19gr ${SRC_FILES})\n\n#######################\n# Include Directories #\n#######################\n\ninclude_directories(${PATH_RSYN}/src)\ninclude_directories(${PATH_RSYN}/src/rsyn/export)\ninclude_directories(${PATH_RSYN}/include)\ninclude_directories(${PATH_ICCAD19})\n\n#################\n# Linker Flags  #\n#################\n\n# TODO: set static under release mode only\nset_target_properties(iccad19gr PROPERTIES LINK_FLAGS \"-static -Wl,--whole-archive -rdynamic -lpthread -Wl,--no-whole-archive\")\n\n# LEF/DEF\ntarget_link_libraries(iccad19gr lef)\ntarget_link_libraries(iccad19gr def)\n\n# Boost\ntarget_include_directories(iccad19gr PUBLIC ${Boost_INCLUDE_DIR})\ntarget_link_libraries(iccad19gr ${Boost_LIBRARIES})\n"
  },
  {
    "path": "src/db/CutLayer.cpp",
    "content": "#include \"CutLayer.h\"\n#include \"Setting.h\"\n\nnamespace db {\n\nViaType::ViaType(Rsyn::PhysicalVia rsynVia) {\n    if (rsynVia.allCutGeometries().size() > 1) hasMultiCut = true;\n\n    bot = getBoxFromRsynGeometries(rsynVia.allBottomGeometries());\n    cut = getBoxFromRsynGeometries(rsynVia.allCutGeometries());\n    top = getBoxFromRsynGeometries(rsynVia.allTopGeometries());\n    name = rsynVia.getName();\n\n    if (rsynVia.hasRowCol()) {\n        const DBU xBotEnc = rsynVia.getEnclosure(Rsyn::BOTTOM_VIA_LEVEL, X);\n        const DBU yBotEnc = rsynVia.getEnclosure(Rsyn::BOTTOM_VIA_LEVEL, Y);\n        const DBU xTopEnc = rsynVia.getEnclosure(Rsyn::TOP_VIA_LEVEL, X);\n        const DBU yTopEnc = rsynVia.getEnclosure(Rsyn::TOP_VIA_LEVEL, Y);\n        const int numRows = rsynVia.getNumRows();\n        const int numCols = rsynVia.getNumCols();\n        const DBU xCut = (rsynVia.getCutSize(X) * numCols + rsynVia.getSpacing(X) * (numCols - 1) + 1) / 2;\n        const DBU yCut = (rsynVia.getCutSize(Y) * numRows + rsynVia.getSpacing(Y) * (numRows - 1) + 1) / 2;\n        bot = {-xCut - xBotEnc, -yCut - yBotEnc, xCut + xBotEnc, yCut + yBotEnc};\n        cut = {-xCut, -yCut, xCut, yCut};\n        top = {-xCut - xTopEnc, -yCut - yTopEnc, xCut + xTopEnc, yCut + yTopEnc};\n    }\n\n    if (!bot.IsStrictValid() || !cut.IsStrictValid() || !top.IsStrictValid()) {\n        log() << \"Warning in \" << __func__ << \": For \" << rsynVia.getName()\n              << \" , has non strict valid via layer bound... \" << std::endl;\n    }\n}\n\nstd::tuple<DBU, DBU, DBU, DBU> ViaType::getDefaultScore(const Dimension botDim, const Dimension topDim) const {\n    return std::tuple<DBU, DBU, DBU, DBU>(bot[botDim].range(),       // belowWidth\n                                          top[topDim].range(),       // aboveWidth\n                                          bot[1 - botDim].range(),   // belowWidth\n                                          top[1 - topDim].range());  // aboveLength\n}\n\nutils::BoxT<DBU> ViaType::getShiftedBotMetal(const utils::PointT<DBU>& viaPos) const {\n    utils::BoxT<DBU> metal = bot;\n    metal.ShiftBy(viaPos);\n    return metal;\n}\nutils::BoxT<DBU> ViaType::getShiftedTopMetal(const utils::PointT<DBU>& viaPos) const {\n    utils::BoxT<DBU> metal = top;\n    metal.ShiftBy(viaPos);\n    return metal;\n}\n\nCutLayer::CutLayer(const Rsyn::PhysicalLayer& rsynLayer,\n                   const vector<Rsyn::PhysicalVia>& rsynVias,\n                   const Dimension botDim,\n                   const Dimension topDim,\n                   const DBU libDBU)\n    : name(rsynLayer.getName()), idx(rsynLayer.getRelativeIndex()), width(rsynLayer.getWidth()) {\n    //  Rsyn::PhysicalLayer (LEF)\n    const lefiLayer* layer = rsynLayer.getLayer();\n    if (!layer->hasSpacingNumber() || !layer->numSpacing()) {\n        log() << \"Error in \" << __func__ << \": For \" << rsynLayer.getName()\n              << \" CutLayer::init, rsynSpacingRule is empty, init all rules with default 0... \" << std::endl;\n    } else {\n        spacing = static_cast<DBU>(std::round(layer->spacing(0) * libDBU));\n    }\n    delete rsynLayer.getLayer();\n\n    //  Rsyn::PhysicalVia (LEF)\n    if (rsynVias.empty()) {\n        log() << \"Error in \" << __func__ << \": For \" << name << \" rsynVias is empty... \" << std::endl;\n    }\n\n    int defaultViaTypeIdx = -1;\n    const DBU dbuMax =\n        std::numeric_limits<DBU>::has_infinity ? std::numeric_limits<DBU>::infinity() : std::numeric_limits<DBU>::max();\n    std::tuple<DBU, DBU, DBU, DBU> bestScore(dbuMax, dbuMax, dbuMax, dbuMax);\n    for (const Rsyn::PhysicalVia& rsynVia : rsynVias) {\n        if (rsynVia.isViaDesign()) continue;\n\n        if ((rsynVia.allBottomGeometries().size() != 1 ||\n             rsynVia.allCutGeometries().size() != 1 ||\n             rsynVia.allTopGeometries().size() != 1)) {\n            if (setting.dbVerbose >= +VerboseLevelT::MIDDLE) {\n                log() << \"Warning in \" << __func__ << \": For \" << rsynVia.getName()\n                      << \" , has not exactly one metal layer bound or more than one cut layer bound... \" << std::endl;\n            }\n            continue;\n        }\n\n        allViaTypes.emplace_back(rsynVia);\n        const std::tuple<DBU, DBU, DBU, DBU>& score = allViaTypes.back().getDefaultScore(botDim, topDim);\n        if (score < bestScore) {\n            bestScore = score;\n            defaultViaTypeIdx = allViaTypes.size() - 1;\n        }\n    }\n\n    if (defaultViaTypeIdx == -1) {\n        log() << \"Error in \" << __func__ << \": For \" << name << \" all rsyn vias have not exactly one via bound... \"\n              << std::endl;\n    }\n\n    // make default via the first one\n    if (defaultViaTypeIdx > 0) {\n        std::swap(allViaTypes[0], allViaTypes[defaultViaTypeIdx]);\n    }\n    // init ViaType::idx\n    for (unsigned i = 0; i != allViaTypes.size(); ++i) {\n        allViaTypes[i].idx = i;\n    }\n}\n\nostream& CutLayer::printBasics(ostream& os) const {\n    os << name << \": idx=\" << idx << \", viaTypes=\" << defaultViaType().name << \" (\";\n    for (auto via : allViaTypes) {\n        if (via.name != defaultViaType().name) {\n            os << via.name << \" \";\n        }\n    }\n    os << \")\";\n    return os;\n}\n\nostream& CutLayer::printDesignRules(ostream& os) const {\n    os << name << \": width=\" << width << \", space=\" << spacing;\n    return os;\n}\n\nostream& CutLayer::printViaOccupancyLUT(ostream& os) const {\n    os << name << \": viaCut(\" << viaCut().size() / 2 + 1 << ',' << viaCut()[0].size() / 2 + 1 << \")\";\n    os << \", viaMetal(\" << viaMetal().size() / 2 + 1 << ',' << viaMetal()[0].size() / 2 + 1 << \")\";\n    // TODO: make xSize member variables, since they will be the same in a LUT over all cps\n    auto getMaxSize = [](const vector<vector<vector<bool>>>& LUT, size_t& xSize, size_t& ySize) {\n        xSize = 0;\n        ySize = 0;\n        for (const vector<vector<bool>>& cpLUT : LUT) {\n            if (cpLUT.size()) {\n                xSize = max(xSize, cpLUT.size());\n                ySize = max(ySize, cpLUT[0].size());\n            }\n        }\n    };\n    size_t xSize, ySize;\n    os << \", viaBotVia(\";\n    if (defaultViaType().allViaBotVia.size()) {\n        getMaxSize(viaBotVia(), xSize, ySize);\n        os << viaBotVia().size() << ',' << xSize << ',' << ySize << \")\";\n    }\n    else os << \"-,-,-)\";\n    os << \", viaTopVia(\";\n    if (defaultViaType().allViaTopVia.size()) {\n        getMaxSize(viaTopVia(), xSize, ySize);\n        os << viaTopVia().size() << ',' << xSize << ',' << ySize << \")\";\n    }\n    else os << \"-,-,-)\";\n    getMaxSize(viaBotWire(), xSize, ySize);\n    os << \", viaBotWire(\" << viaBotWire().size() << ',' << xSize << ',' << ySize << \")\";\n    getMaxSize(viaTopWire(), xSize, ySize);\n    os << \", viaTopWire(\" << viaTopWire().size() << ',' << xSize << ',' << ySize << \")\";\n    return os;\n}\n\nostream& operator<<(ostream& os, const CutLayer& layer) { return layer.printBasics(os); }\n\n}  //   namespace db\n"
  },
  {
    "path": "src/db/CutLayer.h",
    "content": "#pragma once\n\n#include \"GeoPrimitive.h\"\n\nnamespace db {\n\nclass ViaType {\npublic:\n    bool hasMultiCut = false;\n    utils::BoxT<DBU> bot;  // box on bottom metal layer\n    utils::BoxT<DBU> top;  // box on top metal layer\n    utils::BoxT<DBU> cut;  // box on cut layer\n    std::string name;\n    int idx;\n\n    vector<utils::BoxT<DBU>> botForbidRegions;\n    vector<utils::BoxT<DBU>> topForbidRegions;\n\n    // via-wire conflict (crossPointIdx, trackIdx, crossPointIdx)\n    vector<vector<vector<bool>>> viaBotWire;\n    vector<vector<vector<bool>>> viaTopWire;\n\n    // same-layer via-via conflict (viaTypeIdx, lowerTrackIdx, upperTrackIdx)\n    // TODO: remove allViaMetal, rename allViaMetalNum to allViaMetal\n    vector<vector<vector<bool>>> allViaCut;      // due to cut spacing\n    vector<vector<vector<bool>>> allViaMetal;    // due to metal spacing\n    vector<vector<vector<int>>> allViaMetalNum;  // due to metal spacing, integer version\n\n    // cross-layer via-via conflict (viaTypeIdx, crossPointIdx, trackIdx, crossPointIdx)\n    vector<vector<vector<vector<bool>>>> allViaBotVia;\n    vector<vector<vector<vector<bool>>>> allViaTopVia;\n\n    // merged LUTs\n    vector<vector<bool>> mergedAllViaMetal;\n    vector<vector<vector<bool>>> mergedAllViaBotVia;\n    vector<vector<vector<bool>>> mergedAllViaTopVia;\n\n    ViaType() {}\n    ViaType(Rsyn::PhysicalVia rsynVia);\n\n    // alphabetical score tuple (belowWidth, aboveWidth, belowLength, aboveLength)\n    std::tuple<DBU, DBU, DBU, DBU> getDefaultScore(const Dimension botDim, const Dimension topDim) const;\n\n    // shifted bot/top metal\n    utils::BoxT<DBU> getShiftedBotMetal(const utils::PointT<DBU>& viaPos) const;\n    utils::BoxT<DBU> getShiftedTopMetal(const utils::PointT<DBU>& viaPos) const;\n};\n\nclass CutLayer {\npublic:\n    CutLayer(const Rsyn::PhysicalLayer& rsynLayer,\n             const vector<Rsyn::PhysicalVia>& rsynVias,\n             const Dimension botDim,\n             const Dimension topDim,\n             const DBU libDBU);\n\n    // Basic infomation\n    std::string name;\n    int idx;  // layerIdx (consistent with Rsyn::xxx::getRelativeIndex())\n\n    // Design rules\n    DBU width = 0;\n    DBU spacing = 0;\n\n    // Via types\n    vector<ViaType> allViaTypes;\n    const ViaType& defaultViaType() const { return allViaTypes[0]; }\n    bool isDefaultViaType(const ViaType& viaType) const { return viaType.idx == defaultViaType().idx; }\n    utils::BoxT<DBU> topMaxForbidRegion;\n    utils::BoxT<DBU> botMaxForbidRegion;\n\n    // Via conflict lookup table (true means \"not available\" / with conflict)\n    // 1. same-layer via-via conflict (lowerTrackIdx, upperTrackIdx)\n    //  due to cut spacing\n    const vector<vector<bool>>& viaCut() const { return defaultViaType().allViaCut[0]; }\n    //  due to metal spacing\n    const vector<vector<bool>>& viaMetal() const { return defaultViaType().allViaMetal[0]; }\n    const vector<vector<int>>& viaMetalNum() const { return defaultViaType().allViaMetalNum[0]; }\n    // 2. via-via conflict (crossPointIdx, trackIdx, crossPointIdx)\n    const vector<vector<vector<bool>>>& viaBotVia() const { return defaultViaType().allViaBotVia[0]; }\n    const vector<vector<vector<bool>>>& viaTopVia() const { return defaultViaType().allViaTopVia[0]; }\n    // 3. via-wire conflict (crossPointIdx, trackIdx, crossPointIdx)\n    const vector<vector<vector<bool>>>& viaBotWire() const { return defaultViaType().viaBotWire; }\n    const vector<vector<vector<bool>>>& viaTopWire() const { return defaultViaType().viaTopWire; }\n\n    ostream& printBasics(ostream& os) const;\n    ostream& printDesignRules(ostream& os) const;\n    ostream& printViaOccupancyLUT(ostream& os) const;\n    friend ostream& operator<<(ostream& os, const CutLayer& layer);\n};\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/Database.cpp",
    "content": "#include \"Database.h\"\n#include \"rsyn/io/parser/lef_def/DEFControlParser.h\"\n\ndb::Database database;\n\nnamespace db {\n\nvoid Database::init() {\n    log() << std::endl;\n    log() << \"################################################################\" << std::endl;\n    log() << \"Start initializing database\" << std::endl;\n    log() << std::endl;\n\n    rsynService.init();\n\n    auto dieBound = rsynService.physicalDesign.getPhysicalDie().getBounds();\n    dieRegion = getBoxFromRsynBounds(dieBound);\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"Die region (in DBU): \" << dieRegion << std::endl;\n        log() << std::endl;\n    }\n\n    RouteGrid::init();\n\n    NetList::init(rsynService);\n\n    markPinAndObsOccupancy();\n\n    initMTSafeMargin();\n\n    log() << \"Finish initializing database\" << std::endl;\n    log() << \"MEM: cur=\" << utils::mem_use::get_current() << \"MB, peak=\" << utils::mem_use::get_peak() << \"MB\"\n          << std::endl;\n    log() << std::endl;\n}\n\nvoid Database::markPinAndObsOccupancy() {\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"Mark pin & obs occupancy on RouteGrid ...\" << std::endl;\n    }\n    vector<std::pair<BoxOnLayer, int>> fixedMetalVec;\n\n    // STEP 1: get fixed objects\n    // Mark pins associated with nets\n    for (const auto& net : nets) {\n        for (const auto& accessBoxes : net.pinAccessBoxes) {\n            for (const auto& box : accessBoxes) {\n                fixedMetalVec.emplace_back(box, net.idx);\n            }\n        }\n    }\n    // Mark dangling pins\n    // minor TODO: port?\n    const Rsyn::Session session;\n    const Rsyn::PhysicalDesign& physicalDesign =\n        static_cast<Rsyn::PhysicalService*>(session.getService(\"rsyn.physical\"))->getPhysicalDesign();\n    const DBU libDBU = physicalDesign.getDatabaseUnits(Rsyn::LIBRARY_DBU);\n    unsigned numUnusedPins = 0;\n    unsigned numObs = 0;\n    unsigned numSNetObs = 0;\n    for (Rsyn::Instance instance : rsynService.module.allInstances()) {\n        if (instance.getType() != Rsyn::CELL) continue;\n        // phCell\n        Rsyn::Cell cell = instance.asCell();\n        Rsyn::PhysicalCell phCell = rsynService.physicalDesign.getPhysicalCell(cell);\n        Rsyn::PhysicalLibraryCell phLibCell = rsynService.physicalDesign.getPhysicalLibraryCell(cell);\n        const DBUxy origin(static_cast<DBU>(std::round(phLibCell.getMacro()->originX() * libDBU)),\n                           static_cast<DBU>(std::round(phLibCell.getMacro()->originY() * libDBU)));\n        // libPin\n        for (Rsyn::Pin pin : instance.allPins(false)) {\n            if (!pin.getNet()) {  // no associated net\n                Rsyn::PhysicalLibraryPin phLibPin = rsynService.physicalDesign.getPhysicalLibraryPin(pin);\n                vector<BoxOnLayer> accessBoxes;\n                Net::getPinAccessBoxes(phLibPin, phCell, accessBoxes, origin);\n                for (const auto& box : accessBoxes) {\n                    fixedMetalVec.emplace_back(box, OBS_NET_IDX);\n                }\n                ++numUnusedPins;\n            }\n        }\n        // libObs\n        DBUxy displacement = phCell.getPosition() + origin;\n        auto transform = phCell.getTransform();\n        for (const Rsyn::PhysicalObstacle& phObs : phLibCell.allObstacles()) {\n            if (phObs.getLayer().getType() != Rsyn::PhysicalLayerType::ROUTING) continue;\n            const int layerIdx = phObs.getLayer().getRelativeIndex();\n            for (auto bounds : phObs.allBounds()) {\n                bounds.translate(displacement);\n                bounds = transform.apply(bounds);\n                const BoxOnLayer box(layerIdx, getBoxFromRsynBounds(bounds));\n                fixedMetalVec.emplace_back(box, OBS_NET_IDX);\n                ++numObs;\n            }\n        }\n    }\n    // Mark special nets\n    for (Rsyn::PhysicalSpecialNet specialNet : rsynService.physicalDesign.allPhysicalSpecialNets()) {\n        for (const DefWireDscp& wire : specialNet.getNet().clsWires) {\n            for (const DefWireSegmentDscp& segment : wire.clsWireSegments) {\n                int layerIdx =\n                    rsynService.physicalDesign.getPhysicalLayerByName(segment.clsLayerName).getRelativeIndex();\n                const DBU width = segment.clsRoutedWidth;\n                DBUxy pos;\n                DBU ext = 0;\n                for (unsigned i = 0; i != segment.clsRoutingPoints.size(); ++i) {\n                    const DefRoutingPointDscp& pt = segment.clsRoutingPoints[i];\n                    const DBUxy& nextPos = pt.clsPos;\n                    const DBU nextExt = pt.clsHasExtension ? pt.clsExtension : 0;\n                    if (i >= 1) {\n                        for (unsigned dim = 0; dim != 2; ++dim) {\n                            if (pos[dim] == nextPos[dim]) continue;\n                            const DBU l = pos[dim] < nextPos[dim] ? pos[dim] - ext : nextPos[dim] - nextExt;\n                            const DBU h = pos[dim] < nextPos[dim] ? nextPos[dim] + nextExt : pos[dim] + ext;\n                            BoxOnLayer box(layerIdx);\n                            box[dim].Set(l, h);\n                            box[1 - dim].Set(pos[1 - dim] - width / 2, pos[1 - dim] + width / 2);\n                            fixedMetalVec.emplace_back(box, OBS_NET_IDX);\n                            ++numSNetObs;\n                            break;\n                        }\n                    }\n                    pos = nextPos;\n                    ext = nextExt;\n                    if (!pt.clsHasVia) continue;\n                    const Rsyn::PhysicalVia& via = rsynService.physicalDesign.getPhysicalViaByName(pt.clsViaName);\n                    const int botLayerIdx = via.getBottomLayer().getRelativeIndex();\n                    for (const Rsyn::PhysicalViaGeometry& geo : via.allBottomGeometries()) {\n                        Bounds bounds = geo.getBounds();\n                        bounds.translate(pos);\n                        const BoxOnLayer box(botLayerIdx, getBoxFromRsynBounds(bounds));\n                        fixedMetalVec.emplace_back(box, OBS_NET_IDX);\n                        ++numSNetObs;\n                    }\n                    const int topLayerIdx = via.getTopLayer().getRelativeIndex();\n                    for (const Rsyn::PhysicalViaGeometry& geo : via.allTopGeometries()) {\n                        Bounds bounds = geo.getBounds();\n                        bounds.translate(pos);\n                        const BoxOnLayer box(topLayerIdx, getBoxFromRsynBounds(bounds));\n                        fixedMetalVec.emplace_back(box, OBS_NET_IDX);\n                        ++numSNetObs;\n                    }\n                    if (via.hasViaRule()) {\n                        const utils::PointT<int> numRowCol =\n                            via.hasRowCol() ? utils::PointT<int>(via.getNumCols(), via.getNumRows())\n                                            : utils::PointT<int>(1, 1);\n                        BoxOnLayer botBox(botLayerIdx);\n                        BoxOnLayer topBox(topLayerIdx);\n                        for (unsigned dimIdx = 0; dimIdx != 2; ++dimIdx) {\n                            const Dimension dim = static_cast<Dimension>(dimIdx);\n                            const DBU origin = via.hasOrigin() ? pos[dim] + via.getOrigin(dim) : pos[dim];\n                            const DBU botOff =\n                                via.hasOffset() ? origin + via.getOffset(Rsyn::BOTTOM_VIA_LEVEL, dim) : origin;\n                            const DBU topOff =\n                                via.hasOffset() ? origin + via.getOffset(Rsyn::TOP_VIA_LEVEL, dim) : origin;\n                            const DBU length =\n                                (via.getCutSize(dim) * numRowCol[dim] + via.getSpacing(dim) * (numRowCol[dim] - 1)) / 2;\n                            const DBU botEnc = length + via.getEnclosure(Rsyn::BOTTOM_VIA_LEVEL, dim);\n                            const DBU topEnc = length + via.getEnclosure(Rsyn::TOP_VIA_LEVEL, dim);\n                            botBox[dim].Set(botOff - botEnc, botOff + botEnc);\n                            topBox[dim].Set(topOff - topEnc, topOff + topEnc);\n                        }\n                        fixedMetalVec.emplace_back(botBox, OBS_NET_IDX);\n                        fixedMetalVec.emplace_back(topBox, OBS_NET_IDX);\n                        numSNetObs += 2;\n                    }\n                    if (layerIdx == botLayerIdx)\n                        layerIdx = topLayerIdx;\n                    else if (layerIdx == topLayerIdx)\n                        layerIdx = botLayerIdx;\n                    else {\n                        log() << \"Error: Special net \" << specialNet.getNet().clsName << \" via \" << pt.clsViaName\n                              << \" on wrong layer \" << layerIdx << std::endl;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    // Stat\n    vector<int> layerNumFixedObjects(getLayerNum(), 0);\n    for (const auto& fixedMetal : fixedMetalVec) {\n        layerNumFixedObjects[fixedMetal.first.layerIdx]++;\n    }\n    // Print\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"The number of unused pins is \" << numUnusedPins << std::endl;\n        log() << \"The number of OBS is \" << numObs << std::endl;\n        log() << \"The number of special net OBS is \" << numSNetObs << std::endl;\n        log() << \"The number of fixed objects on each layers:\" << std::endl;\n        for (unsigned i = 0; i < getLayerNum(); i++) {\n            if (layerNumFixedObjects[i] > 0) log() << getLayer(i).name << \": \" << layerNumFixedObjects[i] << std::endl;\n        }\n    }\n    log() << std::endl;\n\n    // STEP 2: mark\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        printlog(\"mark fixed metal rtrees...\");\n    }\n\n    markFixedMetalBatch(fixedMetalVec, 0, fixedMetalVec.size());\n}\n\nvoid Database::initMTSafeMargin() {\n    for (auto& layer : layers) {\n        layer.mtSafeMargin = max({layer.minAreaMargin, layer.confLutMargin, layer.fixedMetalQueryMargin});\n        if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n            printlog(layer.name,\n                     \"mtSafeMargin = max {\",\n                     layer.minAreaMargin,\n                     layer.confLutMargin,\n                     layer.fixedMetalQueryMargin,\n                     \"} =\",\n                     layer.mtSafeMargin);\n        }\n    }\n}\n\nvoid Database::getGridPinAccessBoxes(const Net& net, vector<vector<db::GridBoxOnLayer>>& gridPinAccessBoxes) const {\n    gridPinAccessBoxes.resize(net.numOfPins());\n    for (unsigned pinIdx = 0; pinIdx != net.numOfPins(); ++pinIdx) {\n        vector<vector<db::GridBoxOnLayer>> pins(getLayerNum());\n        for (const db::BoxOnLayer& pinAccessBox : net.pinAccessBoxes[pinIdx]) {\n            int dir = getLayerDir(pinAccessBox.layerIdx);\n            DBU pitch = getLayer(pinAccessBox.layerIdx).pitch;\n            // pinForbidRegion\n            auto pinForbidRegion = getMetalRectForbidRegion(pinAccessBox, AggrParaRunSpace::DEFAULT);\n            const db::GridBoxOnLayer& gridPinForbidRegion = rangeSearch(pinForbidRegion);\n            if (isValid(gridPinForbidRegion)) {\n                pins[pinAccessBox.layerIdx].push_back(gridPinForbidRegion);\n            }\n            // One-pitch extension\n            auto pinExtension = pinAccessBox;\n            for (int d = 0; d < 2; ++d) {\n                pinExtension[d].low -= pitch;\n                pinExtension[d].high += pitch;\n            }\n            const db::GridBoxOnLayer& gridPinExtension = rangeSearch(pinExtension);\n            for (int trackIdx = gridPinExtension.trackRange.low; trackIdx <= gridPinExtension.trackRange.high;\n                 ++trackIdx) {\n                for (int cpIdx = gridPinExtension.crossPointRange.low; cpIdx <= gridPinExtension.crossPointRange.high;\n                     ++cpIdx) {\n                    db::GridPoint pt(pinAccessBox.layerIdx, trackIdx, cpIdx);\n                    if (!gridPinForbidRegion.includePoint(pt) && Dist(pinAccessBox, getLoc(pt)) <= pitch) {\n                        pins[pinAccessBox.layerIdx].emplace_back(pinAccessBox.layerIdx,\n                                                                 utils::IntervalT<int>{trackIdx, trackIdx},\n                                                                 utils::IntervalT<int>{cpIdx, cpIdx});\n                    }\n                }\n            }\n        }\n\n        // assign a relatively far grid access box if none (rarely happen)\n        unsigned numBoxes = 0;\n        for (const vector<db::GridBoxOnLayer>& pin : pins) {\n            numBoxes += pin.size();\n        }\n        if (!numBoxes) {\n            for (const db::BoxOnLayer& pinAccessBox : net.pinAccessBoxes[pinIdx]) {\n                db::GridBoxOnLayer gridBox = rangeSearch(pinAccessBox);\n                if (gridBox.trackRange.low > gridBox.trackRange.high) {\n                    if (gridBox.trackRange.low == 0) {\n                        gridBox.trackRange.high = 0;\n                    } else {\n                        gridBox.trackRange.low = gridBox.trackRange.high;\n                    }\n                }\n                if (gridBox.crossPointRange.low > gridBox.crossPointRange.high) {\n                    if (gridBox.crossPointRange.low == 0) {\n                        gridBox.crossPointRange.high = 0;\n                    } else {\n                        gridBox.crossPointRange.low = gridBox.crossPointRange.high;\n                    }\n                }\n                pins[pinAccessBox.layerIdx].push_back(gridBox);\n            }\n        }\n\n        // slice\n        gridPinAccessBoxes[pinIdx].clear();\n        for (vector<db::GridBoxOnLayer>& pin : pins) {\n            if (!pin.empty()) {\n                db::GridBoxOnLayer::sliceGridPolygons(pin);\n                for (const db::GridBoxOnLayer& box : pin) {\n                    if (isValid(box)) {\n                        gridPinAccessBoxes[pinIdx].push_back(box);\n                    }\n                }\n            }\n        }\n        if (gridPinAccessBoxes[pinIdx].empty()) {\n            log() << \"Error: Net \" << net.getName() << \" Pin \" << pinIdx << \" has empty grid pin access boxes\\n\";\n        }\n    }\n}\n\n}  // namespace db\n\nMTStat runJobsMT(int numJobs, const std::function<void(int)>& handle) {\n    int numThreads = min(numJobs, db::setting.numThreads);\n    MTStat mtStat(max(1, db::setting.numThreads));\n    if (numThreads <= 1) {\n        utils::timer threadTimer;\n        for (int i = 0; i < numJobs; ++i) {\n            handle(i);\n        }\n        mtStat.durations[0] = threadTimer.elapsed();\n    } else {\n        int globalJobIdx = 0;\n        std::mutex mtx;\n        utils::timer threadTimer;\n        auto thread_func = [&](int threadIdx) {\n            int jobIdx;\n            while (true) {\n                mtx.lock();\n                jobIdx = globalJobIdx++;\n                mtx.unlock();\n                if (jobIdx >= numJobs) {\n                    mtStat.durations[threadIdx] = threadTimer.elapsed();\n                    break;\n                }\n                handle(jobIdx);\n            }\n        };\n\n        std::thread threads[numThreads];\n        for (int i = 0; i < numThreads; i++) {\n            threads[i] = std::thread(thread_func, i);\n        }\n        for (int i = 0; i < numThreads; i++) {\n            threads[i].join();\n        }\n    }\n    return mtStat;\n}\n"
  },
  {
    "path": "src/db/Database.h",
    "content": "#pragma once\n\n#include \"RsynService.h\"\n#include \"RouteGrid.h\"\n#include \"Net.h\"\n#include \"Setting.h\"\n#include \"Stat.h\"\n\nclass MTStat {\npublic:\n    vector<double> durations;\n    MTStat(int numOfThreads = 0) : durations(numOfThreads, 0.0) {}\n    const MTStat& operator+=(const MTStat& rhs);\n    friend ostream& operator<<(ostream& os, const MTStat mtStat);\n};\n\nnamespace db {\n\nclass Database : public RouteGrid, public NetList {\npublic:\n    utils::BoxT<DBU> dieRegion;\n\n    void init();\n    void clear() { RouteGrid::clear(); }\n\n    // get girdPinAccessBoxes\n    // TODO: better way to differetiate same-layer and diff-layer girdPinAccessBoxes\n    void getGridPinAccessBoxes(const Net& net, vector<vector<db::GridBoxOnLayer>>& gridPinAccessBoxes) const;\n\nprivate:\n    RsynService rsynService;\n\n    // mark pin and obstacle occupancy on RouteGrid\n    void markPinAndObsOccupancy();\n\n    // init safe margin for multi-thread\n    void initMTSafeMargin();\n};\n\n}  //   namespace db\n\nextern db::Database database;\n\nnamespace std {\n\n//  hash function for Dimension\ntemplate <>\nstruct hash<Dimension> {\n    std::size_t operator()(const Dimension d) const { return (hash<unsigned>()(d)); }\n};\n\n//  hash function for std::tuple<typename t0, typename t1, typename t2>\ntemplate <typename t0, typename t1, typename t2>\nstruct hash<std::tuple<t0, t1, t2>> {\n    std::size_t operator()(const std::tuple<t0, t1, t2>& t) const {\n        return (hash<t0>()(std::get<0>(t)) ^ hash<t1>()(std::get<1>(t)) ^ hash<t2>()(std::get<2>(t)));\n    }\n};\n\n}  // namespace std\n\nMTStat runJobsMT(int numJobs, const std::function<void(int)>& handle);\n"
  },
  {
    "path": "src/db/GeoPrimitive.cpp",
    "content": "#include \"GeoPrimitive.h\"\n#include \"Database.h\"\n\nnamespace db {\n\n// BoxOnLayer\n\nbool BoxOnLayer::isConnected(const BoxOnLayer& rhs) const {\n    return abs(rhs.layerIdx - layerIdx) < 2 && HasIntersectWith(rhs);\n}\n\nostream& operator<<(ostream& os, const BoxOnLayer& box) {\n    os << \"box(l=\" << box.layerIdx << \", x=\" << box[0] << \", y=\" << box[1] << \")\";\n    return os;\n}\n\nutils::BoxT<DBU> getBoxFromRsynBounds(const Bounds& bounds) {\n    return {bounds.getLower().x, bounds.getLower().y, bounds.getUpper().x, bounds.getUpper().y};\n}\n\nutils::BoxT<DBU> getBoxFromRsynGeometries(const vector<Rsyn::PhysicalViaGeometry>& geos) {\n    utils::BoxT<DBU> box;\n    for (const Rsyn::PhysicalViaGeometry& geo : geos) {\n        box = box.UnionWith(getBoxFromRsynBounds(geo.getBounds()));\n    }\n    return box;\n}\n\n// GridPoint\n\nbool GridPoint::operator==(const GridPoint& rhs) const {\n    return layerIdx == rhs.layerIdx && crossPointIdx == rhs.crossPointIdx && trackIdx == rhs.trackIdx;\n}\n\nbool GridPoint::operator!=(const GridPoint& rhs) const {\n    return layerIdx != rhs.layerIdx || crossPointIdx != rhs.crossPointIdx || trackIdx != rhs.trackIdx;\n}\n\nostream& operator<<(ostream& os, const GridPoint& gp) {\n    os << \"gPt(l=\" << gp.layerIdx << \", t=\" << gp.trackIdx << \", c=\" << gp.crossPointIdx << \")\";\n    return os;\n}\n\n// GridEdge\n\nostream& operator<<(ostream& os, const GridEdge& edge) {\n    os << \"gEdge(\" << edge.u << \" \" << edge.v << \")\";\n    return os;\n}\n\nbool GridEdge::isVia() const {\n    const auto& lower = (u.layerIdx <= v.layerIdx) ? u : v;\n    const auto& upper = (u.layerIdx > v.layerIdx) ? u : v;\n    if ((lower.layerIdx + 1) == database.getLayerNum()) {\n        return false;\n    }\n    return database.getUpper(lower) == upper;\n}\n\nbool GridEdge::isTrackSegment() const { return u.layerIdx == v.layerIdx && u.trackIdx == v.trackIdx; }\n\nbool GridEdge::isWrongWaySegment() const { return u.layerIdx == v.layerIdx && u.crossPointIdx == v.crossPointIdx; }\n\nbool GridEdge::operator==(const GridEdge& rhs) const { return u == rhs.u && v == rhs.v; }\n\n// GridBoxOnLayer\n\nbool GridBoxOnLayer::operator==(const GridBoxOnLayer& rhs) const {\n    return layerIdx == rhs.layerIdx && trackRange == rhs.trackRange && crossPointRange == rhs.crossPointRange;\n}\n\nostream& operator<<(ostream& os, const GridBoxOnLayer& gb) {\n    os << \"gBox(l=\" << gb.layerIdx << \", t=\" << gb.trackRange << \", c=\" << gb.crossPointRange << \")\";\n    return os;\n}\n\n// slice polygons along sliceDir\n// sliceDir: 0 for x/vertical, 1 for y/horizontal\nvoid GridBoxOnLayer::sliceGridPolygons(vector<GridBoxOnLayer>& boxes) {\n    if (boxes.size() <= 1) return;\n\n    vector<int> locs;\n    for (const auto& box : boxes) {\n        locs.push_back(box.trackRange.low);\n        locs.push_back(box.trackRange.high);\n    }\n    sort(locs.begin(), locs.end());\n    locs.erase(unique(locs.begin(), locs.end()), locs.end());\n\n    // slice each box\n    vector<GridBoxOnLayer> slicedBoxes;\n    for (const auto& box : boxes) {\n        GridBoxOnLayer slicedBox = box;\n        auto itLoc = lower_bound(locs.begin(), locs.end(), box.trackRange.low);\n        auto itEnd = upper_bound(itLoc, locs.end(), box.trackRange.high);\n        slicedBox.trackRange.Set(*itLoc);\n        slicedBoxes.push_back(slicedBox);  // front boundary\n        while ((itLoc + 1) != itEnd) {\n            int left = *itLoc, right = *(itLoc + 1);\n            if ((right - left) > 1) {\n                slicedBox.trackRange.Set(left + 1, right - 1);\n                slicedBoxes.push_back(slicedBox);  // middle\n            }\n            slicedBox.trackRange.Set(right);\n            slicedBoxes.push_back(slicedBox);  // back boundary\n            ++itLoc;\n        }\n    }\n    boxes = move(slicedBoxes);\n\n    // merge overlaped boxes over crossPoints\n    utils::MergeRects(boxes, 1);\n\n    // stitch boxes over tracks\n    utils::MergeRects(boxes, 0);\n}\n\n// TrackSegment\n\nostream& operator<<(ostream& os, const TrackSegment& ts) {\n    os << \"tSeg(l=\" << ts.layerIdx << \", t\" << ts.trackIdx << \", c=\" << ts.crossPointRange << \")\";\n    return os;\n}\n\n// ViaBox\n\nostream& operator<<(ostream& os, const ViaBox& vb) {\n    os << \"viaBox(lower=\" << vb.lower << \", upper=\" << vb.upper << \")\";\n    return os;\n}\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/GeoPrimitive.h",
    "content": "#pragma once\n\n#include \"global.h\"\n\nnamespace db {\n\n//  BoxOnLayer\n//  A box on a certain layer: primitive for route guide and pin acesss box\n\nclass BoxOnLayer : public utils::BoxT<DBU> {\npublic:\n    int layerIdx;\n\n    //  constructors\n    template <typename... Args>\n    BoxOnLayer(int layerIndex = -1, Args... params) : layerIdx(layerIndex), utils::BoxT<DBU>(params...) {}\n\n    // inherit setters from utils::BoxT in batch\n    template <typename... Args>\n    void Set(int layerIndex = -1, Args... params) {\n        layerIdx = layerIndex;\n        utils::BoxT<DBU>::Set(params...);\n    }\n\n    bool isConnected(const BoxOnLayer& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const BoxOnLayer& box);\n};\n\n// helper\nutils::BoxT<DBU> getBoxFromRsynBounds(const Bounds& bounds);\nutils::BoxT<DBU> getBoxFromRsynGeometries(const vector<Rsyn::PhysicalViaGeometry>& geos);\n\n// GridPoint\n\nclass GridPoint {\npublic:\n    int layerIdx;\n    int trackIdx;\n    int crossPointIdx;\n\n    GridPoint(int layerIndex = -1, int trackIndex = -1, int crossPointIndex = -1)\n        : layerIdx(layerIndex), trackIdx(trackIndex), crossPointIdx(crossPointIndex) {}\n\n    bool operator==(const GridPoint& rhs) const;\n    bool operator!=(const GridPoint& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const GridPoint& gp);\n};\n\n}  // namespace db\n\nnamespace std {\n\n// hash function for GridPoint\ntemplate <>\nstruct hash<db::GridPoint> {\n    std::size_t operator()(const db::GridPoint& gp) const {\n        return (std::hash<int>()(gp.layerIdx) ^ std::hash<int>()(gp.trackIdx) ^ std::hash<int>()(gp.crossPointIdx));\n    }\n};\n\n}  // namespace std\n\nnamespace db {\n\n// GridEdge\n\nclass GridEdge {\npublic:\n    GridPoint u, v;\n\n    GridEdge(const GridPoint& nodeU, const GridPoint& nodeV) : u(nodeU), v(nodeV) {}\n\n    // two types of GridEdge: 1. via, 2. track segment\n    bool isVia() const;\n    const GridPoint& lowerGridPoint() const { return u.layerIdx <= v.layerIdx ? u : v; }\n    bool isTrackSegment() const;\n    bool isWrongWaySegment() const;\n\n    bool operator==(const GridEdge& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const GridEdge& edge);\n};\n\nclass TrackSegment {\npublic:\n    int layerIdx;\n    int trackIdx;\n    utils::IntervalT<int> crossPointRange;\n\n    // assume edge.isTrackSegment()\n    TrackSegment(const GridEdge edge)\n        : layerIdx(edge.u.layerIdx),\n          trackIdx(edge.u.trackIdx),\n          crossPointRange(edge.u.crossPointIdx, edge.v.crossPointIdx) {\n        if (!crossPointRange.IsValid()) std::swap(crossPointRange.low, crossPointRange.high);\n    }\n\n    TrackSegment(int layerIndex, int trackIndex, const utils::IntervalT<int>& crossPointIndexRange)\n        : layerIdx(layerIndex), trackIdx(trackIndex), crossPointRange(crossPointIndexRange) {}\n\n    friend ostream& operator<<(ostream& os, const TrackSegment& ts);\n};\n\n// GridBoxOnLayer\n\nclass GridBoxOnLayer {\npublic:\n    int layerIdx;\n    utils::IntervalT<int> trackRange;\n    utils::IntervalT<int> crossPointRange;\n\n    GridBoxOnLayer() : layerIdx(-1) {}  // default to be invalid\n\n    GridBoxOnLayer(int layerIndex,\n                   const utils::IntervalT<int>& trackIdxRange,\n                   const utils::IntervalT<int>& crossPointIdxRange)\n        : layerIdx(layerIndex), trackRange(trackIdxRange), crossPointRange(crossPointIdxRange) {}\n\n    bool includePoint(const GridPoint& point) const {\n        return layerIdx == point.layerIdx && trackRange.Contain(point.trackIdx) &&\n               crossPointRange.Contain(point.crossPointIdx);\n    }\n\n    // slice polygons along sliceDir\n    // sliceDir: 0 for x/vertical, 1 for y/horizontal\n    // assume boxes are on the same layer\n    static void sliceGridPolygons(vector<GridBoxOnLayer>& boxes);\n    const utils::IntervalT<int>& operator[](unsigned i) const {\n        assert(i == 0 || i == 1);\n        return (i == 0) ? trackRange : crossPointRange;\n    }\n    utils::IntervalT<int>& operator[](unsigned i) {\n        assert(i == 0 || i == 1);\n        return (i == 0) ? trackRange : crossPointRange;\n    }\n\n    bool operator==(const GridBoxOnLayer& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const GridBoxOnLayer& gb);\n};\n\n// ViaBox\n\nclass ViaBox {\npublic:\n    GridBoxOnLayer lower, upper;\n\n    ViaBox() {}  // default to be invalid\n\n    ViaBox(const GridBoxOnLayer& lowerGridBox, const GridBoxOnLayer& upperGridBox)\n        : lower(lowerGridBox), upper(upperGridBox) {}\n\n    friend ostream& operator<<(ostream& os, const ViaBox& vb);\n};\n\n}  // namespace db"
  },
  {
    "path": "src/db/LayerList.cpp",
    "content": "#include <fstream>\n\n#include \"LayerList.h\"\n\nnamespace db {\n\nvoid LayerList::init() {\n    const Rsyn::Session session;\n    Rsyn::PhysicalDesign physicalDesign =\n        static_cast<Rsyn::PhysicalService*>(session.getService(\"rsyn.physical\"))->getPhysicalDesign();\n    const DBU libDBU = physicalDesign.getDatabaseUnits(Rsyn::LIBRARY_DBU);\n\n    //  Rsyn::PhysicalLayer (LEF)\n    vector<Rsyn::PhysicalLayer> rsynLayers;\n    vector<Rsyn::PhysicalLayer> rsynCutLayers;\n    for (const Rsyn::PhysicalLayer& rsynLayer : physicalDesign.allPhysicalLayers()) {\n        switch (rsynLayer.getType()) {\n            case Rsyn::ROUTING:\n                rsynLayers.push_back(rsynLayer);\n                break;\n            case Rsyn::CUT:\n                rsynCutLayers.push_back(rsynLayer);\n                break;\n            default:\n                break;\n        }\n    }\n    if (rsynCutLayers.size() + 1 != rsynLayers.size()) {\n        log() << \"Error in \" << __func__ << \": rsynCutLayers.size() is \" << rsynCutLayers.size()\n              << \" , rsynLayers.size() is \" << rsynLayers.size() << \" , not matched... \" << std::endl;\n    }\n\n    //  Rsyn::PhysicalVia (LEF)\n    vector<vector<Rsyn::PhysicalVia>> rsynVias(rsynCutLayers.size());\n    for (const Rsyn::PhysicalVia& rsynVia : physicalDesign.allPhysicalVias()) {\n        rsynVias[rsynVia.getCutLayer().getRelativeIndex()].push_back(rsynVia);\n    }\n\n    //  Rsyn::PhysicalTracks (DEF)\n    vector<Rsyn::PhysicalTracks> rsynTracks(rsynLayers.size());\n    for (const Rsyn::PhysicalTracks& rsynTrack : physicalDesign.allPhysicalTracks()) {\n        int idx = rsynTrack.allLayers().front().getRelativeIndex();\n        if ((rsynTrack.getDirection() == Rsyn::TRACK_HORIZONTAL) ==\n            !strcmp(rsynLayers[idx].getLayer()->direction(), \"HORIZONTAL\")) {\n            assert(rsynLayers[idx].getRelativeIndex() == idx);\n            rsynTracks[idx] = (rsynTrack);\n        }\n    }\n\n    // init each MetalLayer\n    layers.clear();\n    for (unsigned i = 0; i != rsynLayers.size(); ++i) {\n        layers.emplace_back(rsynLayers[i], rsynTracks[i], libDBU);\n    }\n\n    //  init MetalLayer::CrossPointSet\n    initCrossPoints();\n\n    cutLayers.clear();\n    for (unsigned i = 0; i != rsynCutLayers.size(); ++i) {\n        cutLayers.emplace_back(rsynCutLayers[i], rsynVias[i], layers[i].direction, layers[i + 1].direction, libDBU);\n    }\n    \n    /* DR Lagacy Not Used\n    // via area equivalent length (conservative)\n    for (int i = 0, sz = rsynLayers.size(); i < sz; i++) {\n        MetalLayer& layer = layers[i];\n\n        auto dir = layer.direction;\n        auto width = layer.width;\n\n        auto getEqLen = [&](const utils::BoxT<DBU>& rect, DBU& viaLenEqLen, DBU& viaWidthEqLen) {\n            DBU minViaLen = min(abs(rect[1 - dir].low), abs(rect[1 - dir].high));  // conservative\n            DBU viaWidth = rect[dir].range();\n            DBU viaLen = rect[1 - dir].range();\n            viaWidthEqLen = viaLen * max((DBU)0, viaWidth - width) / width;\n            viaLenEqLen = max((DBU)0, minViaLen - width / 2);\n        };\n\n        DBU topViaLenEqLen = INT_MAX;\n        DBU botViaLenEqLen = INT_MAX;\n        DBU topViaWidthEqLen = INT_MAX;\n        DBU botViaWidthEqLen = INT_MAX;\n\n        if (i != 0) getEqLen(cutLayers[i - 1].defaultViaType().top, botViaLenEqLen, botViaWidthEqLen);\n        if (i != sz - 1) getEqLen(cutLayers[i].defaultViaType().bot, topViaLenEqLen, topViaWidthEqLen);\n\n        layer.viaLenEqLen = min(topViaLenEqLen, botViaLenEqLen);\n        layer.viaWidthEqLen = min(topViaWidthEqLen, botViaWidthEqLen);\n\n        layer.minLenRaw = layer.minLenRaw - layer.viaWidthEqLen;\n        layer.minLenOneVia = layer.minLenRaw - 2 * layer.viaLenEqLen;\n        layer.minLenTwoVia = layer.minLenOneVia - layer.viaWidthEqLen;\n\n        if (i == 0) {\n            layer.viaOvlpDist = 0;\n        } else if (i == sz - 1) {\n            layer.viaOvlpDist = 0;\n        } else {\n            auto intvl1 = cutLayers[i - 1].defaultViaType().top[1 - dir];\n            auto intvl2 = cutLayers[i].defaultViaType().bot[1 - dir];\n            layer.viaOvlpDist = max(abs(intvl1.high) + abs(intvl2.low), abs(intvl1.low) + abs(intvl2.high));\n            layer.viaOvlpDist = min(layer.viaOvlpDist, intvl1.range());\n            layer.viaOvlpDist = min(layer.viaOvlpDist, intvl2.range());\n        }\n\n        layer.minLenOneVia = max((DBU)0, layer.minLenOneVia);\n        layer.minLenTwoVia = max((DBU)0, layer.minLenTwoVia);\n        layer.minLenRaw = max((DBU)0, layer.minLenRaw);\n    }\n\n    //  init CutLayer::viaAccess\n    initViaForbidRegions();\n    initViaConfLUT();\n    */\n}\n\nbool LayerList::isValid(const GridPoint& gridPt) const {\n    return gridPt.layerIdx >= 0 && gridPt.layerIdx < layers.size() && layers[gridPt.layerIdx].isValid(gridPt);\n}\n\nbool LayerList::isValid(const GridBoxOnLayer& gridBox) const {\n    return gridBox.layerIdx >= 0 && gridBox.layerIdx < layers.size() && layers[gridBox.layerIdx].isValid(gridBox);\n}\n\nbool LayerList::isValid(const ViaBox& viaBox) const {\n    return isValid(viaBox.lower) && isValid(viaBox.upper) &&                                  // seperately\n           getUpper(viaBox.lower) == viaBox.upper && getLower(viaBox.upper) == viaBox.lower;  // consistent\n}\n\nBoxOnLayer LayerList::getMetalRectForbidRegion(const BoxOnLayer& metalRect, AggrParaRunSpace aggr) const {\n    const MetalLayer& layer = layers[metalRect.layerIdx];\n    DBU margin[2];  // x, y\n    for (int dir = 0; dir < 2; ++dir) {\n        margin[dir] = layer.getSpace(metalRect, dir, aggr);\n        margin[dir] += layer.width / 2;\n    }\n    return {metalRect.layerIdx,\n            metalRect.lx() - margin[0],\n            metalRect.ly() - margin[1],\n            metalRect.hx() + margin[0],\n            metalRect.hy() + margin[1]};\n}\n\nvector<utils::BoxT<DBU>> LayerList::getAccurateMetalRectForbidRegions(const BoxOnLayer& metalRect) const {\n    const MetalLayer& layer = layers[metalRect.layerIdx];\n    vector<utils::BoxT<DBU>> results;\n    for (int dir = 0; dir < 2; ++dir) {\n        const DBU range = metalRect[1 - dir].range();\n        if (range < layer.maxEolWidth) {\n            utils::BoxT<DBU> region = metalRect;\n            region[1 - dir].low -= layer.maxEolWithin;\n            region[1 - dir].high += layer.maxEolWithin;\n            region[dir].low -= layer.maxEolSpace;\n            region[dir].high += layer.maxEolSpace;\n            results.push_back(region);\n        } else {\n            DBU space = layer.getParaRunSpace(metalRect);\n            utils::BoxT<DBU> region = metalRect;\n            region[dir].low -= space;\n            region[dir].high += space;\n            results.push_back(region);\n        }\n    }\n    return results;\n}\n\nvoid LayerList::expandBox(BoxOnLayer& box, int numPitchToExtend) const {\n    DBU margin = layers[box.layerIdx].pitch * numPitchToExtend;\n    box.lx() -= margin;\n    box.ly() -= margin;\n    box.hx() += margin;\n    box.hy() += margin;\n}\n\nvoid LayerList::expandBox(BoxOnLayer& box, int numPitchToExtend, int dir) const {\n    DBU margin = layers[box.layerIdx].pitch * numPitchToExtend;\n    box[dir].low -= margin;\n    box[dir].high += margin;\n}\n\nutils::IntervalT<int> LayerList::getSurroundingTrack(int layerIdx, DBU loc) const {\n    assert(layerIdx >= 0 && layerIdx < layers.size());\n    return layers[layerIdx].getSurroundingTrack(loc);\n}\n\nutils::IntervalT<int> LayerList::getSurroundingCrossPoint(int layerIdx, DBU loc) const {\n    if (layerIdx == 0) {\n        return layers[1].getSurroundingTrack(loc);\n    } else if (layerIdx == layers.size() - 1) {\n        return layers[layerIdx - 1].getSurroundingTrack(loc);\n    } else {\n        const utils::IntervalT<int>& upperTrack = layers[layerIdx + 1].getSurroundingTrack(loc);\n        const utils::IntervalT<int>& lowerTrack = layers[layerIdx - 1].getSurroundingTrack(loc);\n        const utils::IntervalT<int>& fromUpperTrack = layers[layerIdx + 1].getLowerCrossPointRange(upperTrack);\n        const utils::IntervalT<int>& fromLowerTrack = layers[layerIdx - 1].getUpperCrossPointRange(lowerTrack);\n        return fromUpperTrack.IntersectWith(fromLowerTrack);\n    }\n}\n\nGridBoxOnLayer LayerList::getSurroundingGrid(int layerIdx, utils::PointT<DBU> loc) const {\n    auto dir = layers[layerIdx].direction;\n    return {layerIdx, getSurroundingTrack(layerIdx, loc[dir]), getSurroundingCrossPoint(layerIdx, loc[1 - dir])};\n}\n\nutils::IntervalT<int> LayerList::rangeSearchTrack(int layerIdx,\n                                                  const utils::IntervalT<DBU>& locRange,\n                                                  bool includeBound) const {\n    assert(layerIdx >= 0 && layerIdx < layers.size());\n    return layers[layerIdx].rangeSearchTrack(locRange, includeBound);\n}\n\nutils::IntervalT<int> LayerList::rangeSearchCrossPoint(int layerIdx,\n                                                       const utils::IntervalT<DBU>& locRange,\n                                                       bool includeBound) const {\n    assert(layerIdx >= 0 && layerIdx < layers.size());\n    if (layerIdx == 0) {\n        return layers[1].rangeSearchTrack(locRange, includeBound);\n    } else if (layerIdx == layers.size() - 1) {\n        return layers[layerIdx - 1].rangeSearchTrack(locRange, includeBound);\n    } else {\n        const utils::IntervalT<int>& upperTrack = layers[layerIdx + 1].rangeSearchTrack(locRange, includeBound);\n        const utils::IntervalT<int>& lowerTrack = layers[layerIdx - 1].rangeSearchTrack(locRange, includeBound);\n        bool upperValid = layers[layerIdx + 1].isTrackRangeValid(upperTrack);\n        bool lowerValid = layers[layerIdx - 1].isTrackRangeValid(lowerTrack);\n        if (upperValid && lowerValid) {\n            // the most typical case\n            const utils::IntervalT<int>& fromUpperTrack = layers[layerIdx + 1].getLowerCrossPointRange(upperTrack);\n            const utils::IntervalT<int>& fromLowerTrack = layers[layerIdx - 1].getUpperCrossPointRange(lowerTrack);\n            return fromUpperTrack.UnionWith(fromLowerTrack);\n        } else if (upperValid || (!lowerValid && layers[layerIdx + 1].isTrackRangeWeaklyValid(upperTrack))) {\n            return layers[layerIdx + 1].getLowerCrossPointRange(upperTrack);\n        } else if (layers[layerIdx - 1].isTrackRangeWeaklyValid(lowerTrack)) {\n            return layers[layerIdx - 1].getUpperCrossPointRange(lowerTrack);\n        } else {\n            return {0, -1};  // a little bit safer than default {inf, -inf}\n        }\n    }\n}\n\nGridBoxOnLayer LayerList::rangeSearch(const BoxOnLayer& box, bool includeBound) const {\n    auto dir = layers[box.layerIdx].direction;\n    return {box.layerIdx,\n            rangeSearchTrack(box.layerIdx, box[dir], includeBound),\n            rangeSearchCrossPoint(box.layerIdx, box[1 - dir], includeBound)};\n}\n\nutils::PointT<DBU> LayerList::getLoc(const GridPoint& gridPt) const {\n    assert(isValid(gridPt));\n    return layers[gridPt.layerIdx].getLoc(gridPt);\n}\n\nBoxOnLayer LayerList::getLoc(const GridBoxOnLayer& gridBox) const {\n    assert(isValid(gridBox));\n    return layers[gridBox.layerIdx].getLoc(gridBox);\n}\n\nstd::pair<utils::PointT<DBU>, utils::PointT<DBU>> LayerList::getLoc(const GridEdge& edge) const {\n    assert(edge.isTrackSegment() || edge.isWrongWaySegment());\n    return layers[edge.u.layerIdx].getLoc(edge);\n}\n\nGridPoint LayerList::getUpper(const GridPoint& cur) const {\n    assert(isValid(cur) && cur.layerIdx < (int)layers.size() - 1);\n    return layers[cur.layerIdx].getUpper(cur);\n}\n\nGridPoint LayerList::getLower(const GridPoint& cur) const {\n    assert(isValid(cur) && cur.layerIdx > 0);\n    return layers[cur.layerIdx].getLower(cur);\n}\n\nGridBoxOnLayer LayerList::getUpper(const GridBoxOnLayer& cur) const {\n    assert(isValid(cur) && cur.layerIdx < (int)layers.size() - 1);\n    return GridBoxOnLayer(\n        // layer\n        cur.layerIdx + 1,\n        // track\n        layers[cur.layerIdx + 1].rangeSearchTrack(\n            {layers[cur.layerIdx].crossPoints[cur.crossPointRange.low].location,\n             layers[cur.layerIdx].crossPoints[cur.crossPointRange.high].location}),\n        // cross point\n        layers[cur.layerIdx].getUpperCrossPointRange(cur.trackRange));\n}\n\nGridBoxOnLayer LayerList::getLower(const GridBoxOnLayer& cur) const {\n    assert(isValid(cur) && cur.layerIdx > 0);\n    return GridBoxOnLayer(\n        // layer\n        cur.layerIdx - 1,\n        // track\n        layers[cur.layerIdx - 1].rangeSearchTrack(\n            {layers[cur.layerIdx].crossPoints[cur.crossPointRange.low].location,\n             layers[cur.layerIdx].crossPoints[cur.crossPointRange.high].location}),\n        // cross point\n        layers[cur.layerIdx].getLowerCrossPointRange(cur.trackRange));\n}\n\nViaBox LayerList::getViaBoxBetween(const BoxOnLayer& lower, const BoxOnLayer& upper) {\n    assert((lower.layerIdx + 1) == upper.layerIdx);\n    auto box2d = lower.IntersectWith(upper);\n    auto lowerGridBoxTmp = rangeSearch({lower.layerIdx, box2d});\n    if (!isValid(lowerGridBoxTmp)) return ViaBox();  // invalid\n    auto upperGridBox = getUpper(lowerGridBoxTmp);\n    if (!isValid(upperGridBox)) return ViaBox();  // invalid\n    auto lowerGridBox = getLower(upperGridBox);\n    if (!isValid(lowerGridBox)) return ViaBox();  // invalid\n    return ViaBox(lowerGridBox, upperGridBox);\n}\n\nbool LayerList::isConnected(const GridBoxOnLayer& lhs, const GridBoxOnLayer& rhs) {\n    if (!isValid(lhs) || !isValid(rhs)) {\n        return false;\n    } else if ((lhs.layerIdx + 1) == rhs.layerIdx) {\n        return isValid(getViaBoxBetween(lhs, rhs));\n    } else if (lhs.layerIdx == (rhs.layerIdx + 1)) {\n        return isValid(getViaBoxBetween(rhs, lhs));\n    } else if (lhs.layerIdx == rhs.layerIdx) {\n        return lhs.trackRange.HasIntersectWith(rhs.trackRange) &&\n               lhs.crossPointRange.HasIntersectWith(rhs.crossPointRange);\n    } else {\n        return false;\n    }\n}\n\nbool LayerList::isAdjacent(const GridBoxOnLayer& lhs, const GridBoxOnLayer& rhs) {\n    if (!isValid(lhs) || !isValid(rhs)) {\n        return false;\n    } else if (lhs.layerIdx == rhs.layerIdx) {\n        return (abs(lhs.trackRange.low - rhs.trackRange.high) == 1 ||\n                abs(rhs.trackRange.low - lhs.trackRange.high) == 1) &&\n               lhs.crossPointRange.HasIntersectWith(rhs.crossPointRange);\n    } else {\n        return false;\n    }\n}\n\nvoid LayerList::initCrossPoints() {\n    for (unsigned i = 0; i != layers.size(); ++i) {\n        vector<CrossPoint>& crossPoints = layers[i].crossPoints;\n        vector<Track> emptyTrackSet;\n        vector<Track>& lowerTrackSet = (i > 0) ? layers[i - 1].tracks : emptyTrackSet;\n        vector<Track>& upperTrackSet = (i < (layers.size() - 1)) ? layers[i + 1].tracks : emptyTrackSet;\n\n        // merge cross points to lower and upper layers\n        int iLo = 0, iUp = 0;  // track indexes\n        DBU lastBoth = 0;\n        while (iLo < lowerTrackSet.size() || iUp < upperTrackSet.size()) {\n            if (iUp >= upperTrackSet.size()) {\n                crossPoints.emplace_back(lowerTrackSet[iLo].location, iLo, -1);\n                lowerTrackSet[iLo].upperCPIdx = crossPoints.size() - 1;\n                ++iLo;\n            } else if (iLo >= lowerTrackSet.size()) {\n                crossPoints.emplace_back(upperTrackSet[iUp].location, -1, iUp);\n                upperTrackSet[iUp].lowerCPIdx = crossPoints.size() - 1;\n                ++iUp;\n            }  // boundaries should be checked first\n            else if (lowerTrackSet[iLo].location < upperTrackSet[iUp].location) {\n                crossPoints.emplace_back(lowerTrackSet[iLo].location, iLo, -1);\n                lowerTrackSet[iLo].upperCPIdx = crossPoints.size() - 1;\n                ++iLo;\n            } else if (lowerTrackSet[iLo].location > upperTrackSet[iUp].location) {\n                crossPoints.emplace_back(upperTrackSet[iUp].location, -1, iUp);\n                upperTrackSet[iUp].lowerCPIdx = crossPoints.size() - 1;\n                ++iUp;\n            } else {  // iLo < lowerTrackSet.size() && iUp < lowerTrackSet.size() && lowerTrackSet[iLo].location ==\n                      // lowerTrackSet[iUp].location\n                crossPoints.emplace_back(lowerTrackSet[iLo].location, iLo, iUp);\n                lowerTrackSet[iLo].upperCPIdx = crossPoints.size() - 1;\n                upperTrackSet[iUp].lowerCPIdx = crossPoints.size() - 1;\n                ++iLo;\n                ++iUp;\n            }\n        }\n\n        layers[i].initAccCrossPointDistCost();\n    }\n}\n\nvoid LayerList::initOppLUT(const vector<vector<vector<bool>>>& ori, vector<vector<vector<bool>>>& opp) {\n    const size_t nCPs = ori.size();\n    size_t xSize = 0;\n    for (const vector<vector<bool>>& orig : ori) {\n        xSize = orig.size();\n        if (xSize) {\n            break;\n        }\n    }\n\n    auto travelCPs = [&](std::function<void(const unsigned, const unsigned, const unsigned, const unsigned)> handle) {\n        for (unsigned i = 0; i != nCPs; ++i) {\n            if (ori[i].empty()) {\n                continue;\n            }\n            for (unsigned j = 0; j != xSize; ++j) {\n                const int ySize = ((int)ori[i][0].size() - 1) / 2;\n                for (unsigned k = max(0, ySize - (int)i); k < min(ySize * 2 + 1, int(nCPs + ySize - i)); ++k) {\n                    if (ori[i][j][k]) {\n                        handle(i, j, ySize, k);\n                    }\n                }\n            }\n        }\n    };\n\n    vector<int> ySizes(nCPs, -1);\n    auto updateSize = [&](const unsigned i, const unsigned j, const unsigned ySize, const unsigned k) {\n        ySizes[i + k - ySize] = max(ySizes[i + k - ySize], abs((int)ySize - (int)k));\n    };\n    auto fillTable = [&](const unsigned i, const unsigned j, const unsigned ySize, const unsigned k) {\n        vector<bool>& tmpOpp = opp[i + k - ySize][xSize - j - 1];\n        const int tmpYSize = ((int)tmpOpp.size() - 1) / 2;\n        tmpOpp[tmpYSize + ySize - k] = true;\n    };\n\n    travelCPs(updateSize);\n    opp.clear();\n    opp.resize(nCPs);\n    for (unsigned i = 0; i != nCPs; ++i) {\n        if (ySizes[i] >= 0) {\n            opp[i].resize(xSize, vector<bool>(ySizes[i] * 2 + 1, false));\n        } else if (ori[i].empty()) {\n            opp[i].resize(xSize, vector<bool>(1, false));\n        }\n        assert(ori[i].size() + opp[i].size());\n    }\n    travelCPs(fillTable);\n}\n\nvoid LayerList::initViaWire(const int layerIdx,\n                            const utils::BoxT<DBU>& viaMetal,\n                            vector<vector<vector<bool>>>& viaWireLUT) {\n    const MetalLayer& layer = layers[layerIdx];\n    const DBU halfWidth = ceil(layer.width / 2.0);\n    const DBU viaMetalWidth = viaMetal[layer.direction].range();\n    const DBU viaMetalHeight = viaMetal[1 - layer.direction].range();\n    const DBU pSpace = layer.getParaRunSpace(viaMetal);\n    const DBU space = max({pSpace, layer.maxEolSpace, layer.maxEolWithin});\n    const size_t xSize = max(ceil((space + halfWidth + viaMetal[layer.direction].high) / (double)layer.pitch),\n                             ceil((space + halfWidth - viaMetal[layer.direction].low) / (double)layer.pitch)) -\n                         1;\n    const utils::IntervalT<DBU> locRange(-space - halfWidth + viaMetal[1 - layer.direction].low + 1,\n                                         +space + halfWidth + viaMetal[1 - layer.direction].high - 1);\n    viaWireLUT.resize(layer.numCrossPoints());\n    vector<bool> viaTrack(xSize + 1, false);\n    for (unsigned i = 0; i != layer.numCrossPoints(); ++i) {\n        const CrossPoint& cp = layer.crossPoints[i];\n        utils::IntervalT<DBU> tmpLocRange(locRange);\n        tmpLocRange.ShiftBy(layer.crossPoints[i].location);\n        const utils::IntervalT<int>& cpRange = rangeSearchCrossPoint(layerIdx, tmpLocRange);\n        const size_t ySize = max((int)i - cpRange.low, cpRange.high - (int)i);\n        viaWireLUT[i].resize(xSize * 2 + 1, vector<bool>(ySize * 2 + 1, false));\n        for (unsigned j = 0; j != xSize * 2 + 1; ++j) {\n            DBU xDist = 0;\n            if (j < xSize) {\n                xDist = max(0L, int(xSize - j) * layer.pitch - halfWidth + viaMetal[layer.direction].low);\n            } else if (j > xSize) {\n                xDist = max(0L, int(j - xSize) * layer.pitch - halfWidth - viaMetal[layer.direction].high);\n            }\n            for (unsigned k = max(0, (int)ySize - (int)i); k < min(ySize * 2 + 1, layer.numCrossPoints() + ySize - i);\n                 ++k) {\n                const CrossPoint& tmpCP = layer.crossPoints[i + k - ySize];\n                DBU yDist = 0;\n                if (k < ySize) {\n                    yDist = max(0L, cp.location - tmpCP.location - halfWidth + viaMetal[1 - layer.direction].low);\n                } else if (k > ySize) {\n                    yDist = max(0L, tmpCP.location - cp.location - halfWidth - viaMetal[1 - layer.direction].high);\n                }\n                if (pow(xDist, 2) + pow(yDist, 2) < pow(pSpace, 2) ||\n                    layer.isEolViolation(xDist, viaMetalHeight, yDist) ||\n                    layer.isEolViolation(yDist, viaMetalWidth, xDist)) {\n                    viaTrack[abs((int)j - (int)xSize)] = true;\n                    viaWireLUT[i][j][k] = true;\n                }\n            }\n        }\n    }\n    size_t minXSize = xSize;\n    for (; minXSize && !viaTrack[minXSize]; --minXSize) {\n    }\n    unsigned d = xSize - minXSize;\n    if (!d) {\n        return;\n    }\n    for (vector<vector<bool>>& vvb : viaWireLUT) {\n        for (unsigned i = 0; i != minXSize * 2 + 1; ++i) {\n            vvb[i] = vvb[i + d];\n        }\n        vvb.resize(minXSize * 2 + 1);\n    }\n}\n\nvoid LayerList::initViaConfLUT() {\n    for (unsigned i = 0; i != cutLayers.size(); ++i) {\n        CutLayer& cutLayer = cutLayers[i];\n        // Loops for init all-all via-via LUTs\n        for (unsigned j = 0; j != cutLayer.allViaTypes.size(); ++j) {\n            ViaType& viaType1 = cutLayer.allViaTypes[j];\n            viaType1.allViaCut.resize(cutLayer.allViaTypes.size());\n            viaType1.allViaMetal.resize(cutLayer.allViaTypes.size());\n            viaType1.allViaMetalNum.resize(cutLayer.allViaTypes.size());\n            for (unsigned k = 0; k != cutLayer.allViaTypes.size(); ++k) {\n                ViaType& viaType2 = cutLayer.allViaTypes[k];\n                auto& viaCut = viaType1.allViaCut[k];\n                auto& viaMetal = viaType1.allViaMetal[k];\n                auto& viaMetalNum = viaType1.allViaMetalNum[k];\n                initSameLayerViaConfLUT(i, viaType1, viaType2, viaCut, viaMetal, viaMetalNum);\n            }\n        }\n\n        //  2. init viaTopVia & viaBotVia\n        if (i > 0) {\n            // Loops for init all-all via-via LUTs\n            for (unsigned j = 0; j != cutLayer.allViaTypes.size(); ++j) {\n                ViaType& viaType1 = cutLayer.allViaTypes[j];\n                viaType1.allViaBotVia.resize(cutLayers[i - 1].allViaTypes.size());\n                for (unsigned k = 0; k != cutLayers[i - 1].allViaTypes.size(); ++k) {\n                    ViaType& viaType2 = cutLayers[i - 1].allViaTypes[k];\n                    viaType2.allViaTopVia.resize(cutLayer.allViaTypes.size());\n                    auto& viaBotVia = viaType1.allViaBotVia[k];\n                    auto& viaTopVia = viaType2.allViaTopVia[j];\n                    initDiffLayerViaConfLUT(i, viaType1, viaType2, viaBotVia, viaTopVia);\n                }\n            }\n        }\n\n        //  3. init viaBotWire & viaTopWire\n        layers[i].wireTopVia.resize(cutLayer.allViaTypes.size());\n        layers[i + 1].wireBotVia.resize(cutLayer.allViaTypes.size());\n        for (auto& viaType : cutLayer.allViaTypes) {\n            initViaWire(i, viaType.bot, viaType.viaBotWire);\n            initViaWire(i + 1, viaType.top, viaType.viaTopWire);\n            LayerList::initOppLUT(viaType.viaBotWire, layers[i].wireTopVia[viaType.idx]);\n            LayerList::initOppLUT(viaType.viaTopWire, layers[i + 1].wireBotVia[viaType.idx]);\n        }\n    }\n\n    // 4. init wireRange\n    for (MetalLayer& layer : layers) {\n        layer.initWireRange();\n    }\n\n    // Merge LUTs\n    for (unsigned i = 0; i != cutLayers.size(); ++i) {\n        CutLayer& cutLayer = cutLayers[i];\n        for (unsigned j = 0; j != cutLayer.allViaTypes.size(); ++j) {\n            ViaType& viaType = cutLayer.allViaTypes[j];\n            viaType.mergedAllViaMetal = mergeLUTs(viaType.allViaMetal);\n            if (i > 0) {\n                for (int k = 0; k != viaType.allViaBotVia.size(); ++k) {\n                    viaType.mergedAllViaBotVia = mergeLUTsCP(viaType.allViaBotVia);\n                }\n            }\n            if (i < cutLayers.size()) {\n                for (int k = 0; k != viaType.allViaTopVia.size(); ++k) {\n                    viaType.mergedAllViaTopVia = mergeLUTsCP(viaType.allViaTopVia);\n                }\n            }\n        }\n    }\n    for (int i = 0; i < layers.size(); ++i) {\n        MetalLayer& layer = layers[i];\n        if (i > 0) {\n            layer.mergedWireBotVia = mergeLUTsCP(layer.wireBotVia);\n        }\n        if ((i + 1) < layers.size()) {\n            layer.mergedWireTopVia = mergeLUTsCP(layer.wireTopVia);\n        }\n    }\n\n    // Set isWireViaMultiTrack\n    for (int i = 0; i < layers.size(); ++i) {\n        if (i > 0 && layers[i].wireBotVia[0][0].size() > 1 ||\n            (i + 1) < layers.size() && layers[i].wireTopVia[0][0].size() > 1)\n            layers[i].isWireViaMultiTrack = true;\n    }\n\n    //  writeDefConflictLUTs(\"debugConflictLUTa.log\");\n    //  exit(0);\n}\n\nvoid LayerList::initSameLayerViaConfLUT(const int layerIdx,\n                                        ViaType& viaT1,\n                                        ViaType& viaT2,\n                                        vector<vector<bool>>& viaCut,\n                                        vector<vector<bool>>& viaMetal,\n                                        vector<vector<int>>& viaMetalNum) {\n    CutLayer& cutLayer = cutLayers[layerIdx];\n    MetalLayer& botLayer = layers[layerIdx];\n    MetalLayer& topLayer = layers[layerIdx + 1];\n    const Dimension botDim = botLayer.direction;\n    const Dimension topDim = topLayer.direction;\n    const DBU cutSpacing = cutLayer.spacing;\n\n    const utils::BoxT<DBU>& botT1 = viaT1.bot;\n    const utils::BoxT<DBU>& cutT1 = viaT1.cut;\n    const utils::BoxT<DBU>& topT1 = viaT1.top;\n    const utils::BoxT<DBU>& botT2 = viaT2.bot;\n    const utils::BoxT<DBU>& cutT2 = viaT2.cut;\n    const utils::BoxT<DBU>& topT2 = viaT2.top;\n\n    const DBU botPSpace = max(botLayer.getParaRunSpace(botT1), botLayer.getParaRunSpace(botT2));\n    const DBU topPSpace = max(topLayer.getParaRunSpace(topT1), topLayer.getParaRunSpace(topT2));\n    const DBU botCSpace = 0;  // max(botLayer.getCornerSpace(botT1), botLayer.getCornerSpace(botT2));\n    const DBU topCSpace = 0;  // max(topLayer.getCornerSpace(topT1), topLayer.getCornerSpace(topT2));\n    const DBU botSpace = max({botPSpace, botCSpace, botLayer.maxEolSpace, botLayer.maxEolWithin});\n    const DBU topSpace = max({topPSpace, topCSpace, topLayer.maxEolSpace, topLayer.maxEolWithin});\n    const DBU botPitch = botLayer.pitch;\n    const DBU topPitch = topLayer.pitch;\n    // init viaCut & viaMetal\n    const size_t cutXSize = max(ceil((cutSpacing + cutT1[botDim].high - cutT2[botDim].low) / (double)botPitch),\n                                ceil((cutSpacing + cutT2[botDim].high - cutT1[botDim].low) / (double)botPitch)) -\n                            1;\n    const size_t cutYSize = max(ceil((cutSpacing + cutT1[topDim].high - cutT2[topDim].low) / (double)topPitch),\n                                ceil((cutSpacing + cutT2[topDim].high - cutT1[topDim].low) / (double)topPitch)) -\n                            1;\n    const DBU metalXLength = max({botSpace + botT2[botDim].high - botT1[botDim].low,\n                                  botSpace + botT1[botDim].high - botT2[botDim].low,\n                                  topSpace + topT2[botDim].high - topT1[botDim].low,\n                                  topSpace + topT1[botDim].high - topT2[botDim].low});\n    const DBU metalYLength = max({botSpace + botT2[topDim].high - botT1[topDim].low,\n                                  botSpace + botT1[topDim].high - botT2[topDim].low,\n                                  topSpace + topT2[topDim].high - topT1[topDim].low,\n                                  topSpace + topT1[topDim].high - topT2[topDim].low});\n    const size_t metalXSize = max(cutXSize, (size_t)ceil((metalXLength) / (double)botPitch) - 1);\n    const size_t metalYSize = max(cutYSize, (size_t)ceil((metalYLength) / (double)topPitch) - 1);\n    const DBU maxLength = max(metalXLength, metalYLength);\n    botLayer.confLutMargin = max(botLayer.confLutMargin, maxLength);\n    topLayer.confLutMargin = max(topLayer.confLutMargin, maxLength);\n    viaCut.resize(2 * cutXSize + 1, vector<bool>(2 * cutYSize + 1, false));\n    viaMetal.resize(2 * metalXSize + 1, vector<bool>(2 * metalYSize + 1, false));\n    viaMetalNum.resize(2 * metalXSize + 1, vector<int>(2 * metalYSize + 1, 0));\n    vector<bool> viaMetalTrack(2 * metalXSize + 1, false);\n\n    utils::PointT<DBU> delta;\n    for (unsigned j = 0; j != 2 * cutXSize + 1; ++j) {\n        delta[botDim] = botPitch * (static_cast<int>(j) - static_cast<int>(cutXSize));\n        for (unsigned k = 0; k != 2 * cutYSize + 1; ++k) {\n            delta[topDim] = topPitch * (static_cast<int>(k) - static_cast<int>(cutYSize));\n            utils::BoxT<DBU> tmpT2(cutT2);\n            tmpT2.ShiftBy(delta);\n            if (utils::L2Dist(tmpT2, cutT1) < cutSpacing) viaCut[j][k] = true;\n        }\n    }\n\n    const size_t offsetX{metalXSize - cutXSize};\n    const size_t offsetY{metalYSize - cutYSize};\n    for (unsigned j = 0; j != 2 * metalXSize + 1; ++j) {\n        delta[botDim] = botPitch * (static_cast<int>(j) - static_cast<int>(metalXSize));\n        for (unsigned k = 0; k != 2 * metalYSize + 1; ++k) {\n            delta[topDim] = topPitch * (static_cast<int>(k) - static_cast<int>(metalYSize));\n            utils::BoxT<DBU> tmpBotT2(botT2);\n            utils::BoxT<DBU> tmpTopT2(topT2);\n            tmpBotT2.ShiftBy(delta);\n            tmpTopT2.ShiftBy(delta);\n            viaMetalNum[j][k] +=\n                static_cast<int>(j <= 2 * cutXSize + offsetX && k <= 2 * cutYSize + offsetY && j >= offsetX &&\n                                 k >= offsetY && viaCut[j - offsetX][k - offsetY]) +\n                static_cast<int>(\n                    L2Dist(tmpBotT2, botT1) < botPSpace || L2Dist(tmpTopT2, topT1) < topPSpace ||\n                    botLayer.isEolViolation(tmpBotT2, botT1) || topLayer.isEolViolation(tmpTopT2, topT1));  // ||\n                    // utils::ParaRunLength(tmpBotT2, botT1) <= 0 && utils::LInfDist(tmpBotT2, botT1) < botCSpace ||\n                    // utils::ParaRunLength(tmpTopT2, topT1) <= 0 && utils::LInfDist(tmpTopT2, topT1) < topCSpace);\n            if (viaMetalNum[j][k]) {\n                viaMetalTrack[j] = true;\n                viaMetal[j][k] = true;\n            }\n        }\n    }\n\n    size_t minMetalXSize = 2 * metalXSize + 1;\n    for (; minMetalXSize && !viaMetalTrack[minMetalXSize]; --minMetalXSize) {\n    }\n    if (minMetalXSize < metalXSize) viaMetal.resize(minMetalXSize + 1);\n}\n\nvoid LayerList::initDiffLayerViaConfLUT(const int layerIdx,\n                                        ViaType& viaT1,\n                                        ViaType& viaT2,\n                                        vector<vector<vector<bool>>>& viaBotVia,\n                                        vector<vector<vector<bool>>>& viaTopVia) {\n    MetalLayer& botLayer = layers[layerIdx];\n    const Dimension botDim = botLayer.direction;\n\n    const utils::BoxT<DBU>& botT1 = viaT1.bot;\n    const utils::BoxT<DBU>& topT2 = viaT2.top;\n\n    const DBU botPSpace = max(botLayer.getParaRunSpace(botT1), botLayer.getParaRunSpace(topT2));\n    const DBU botCSpace = 0;  // max(botLayer.getCornerSpace(botT1), botLayer.getCornerSpace(topT2));\n    const DBU botSpace = max({botPSpace, botCSpace, botLayer.maxEolSpace, botLayer.maxEolWithin});\n    const DBU botPitch = botLayer.pitch;\n\n    const unsigned nBotCPs = botLayer.numCrossPoints();\n\n    const DBU xLength = botSpace + max(botT1[botDim].high - topT2[botDim].low, topT2[botDim].high - botT1[botDim].low);\n    const size_t xSize = ceil(xLength / (double)botPitch) - 1;\n    const utils::IntervalT<DBU> botLocRange(-topT2[1 - botDim].high + botT1[1 - botDim].low - botSpace + 1,\n                                            +botT1[1 - botDim].high - topT2[1 - botDim].low + botSpace - 1);\n                                            \n    const DBU maxLength = max<DBU>({xLength, -botLocRange.low, botLocRange.high});\n    botLayer.confLutMargin = max(botLayer.confLutMargin, maxLength);\n    viaBotVia.resize(nBotCPs);\n    for (unsigned j = 0; j != nBotCPs; ++j) {\n        utils::IntervalT<DBU> tmpLocRange(botLocRange);\n        tmpLocRange.ShiftBy(botLayer.crossPoints[j].location);\n        const utils::IntervalT<int>& cpRange = rangeSearchCrossPoint(layerIdx, tmpLocRange);\n        const size_t ySize = max((int)j - cpRange.low, cpRange.high - (int)j);\n        if (botLayer.crossPoints[j].upperTrackIdx >= 0) {\n            viaBotVia[j].resize(xSize * 2 + 1, vector<bool>(ySize * 2 + 1, false));\n        } else {\n            viaBotVia[j].resize(xSize * 2 + 1, vector<bool>(ySize * 2 + 1, true));\n        }\n    }\n\n    utils::PointT<DBU> delta;\n    for (unsigned j = 0; j != nBotCPs; ++j) {\n        const CrossPoint& cp = botLayer.crossPoints[j];\n        if (cp.upperTrackIdx == -1) {\n            continue;\n        }\n        const unsigned ySize = (viaBotVia[j][0].size() - 1) / 2;\n        for (unsigned k = 0; k != xSize * 2 + 1; ++k) {\n            delta[botDim] = botPitch * (static_cast<int>(k) - static_cast<int>(xSize));\n            for (unsigned l = max(0, (int)ySize - (int)j); l < min(ySize * 2 + 1, nBotCPs + ySize - j); ++l) {\n                const CrossPoint& tmpCP = botLayer.crossPoints[j + l - ySize];\n                if (tmpCP.lowerTrackIdx == -1) {\n                    viaBotVia[j][k][l] = true;\n                    continue;\n                }\n                delta[1 - botDim] = tmpCP.location - cp.location;\n                utils::BoxT<DBU> tmpTopT2(topT2);\n                tmpTopT2.ShiftBy(delta);\n                if (L2Dist(tmpTopT2, botT1) < botPSpace || botLayer.isEolViolation(tmpTopT2, botT1)) {  // ||\n                    // utils::ParaRunLength(tmpTopT2, botT1) <= 0 && utils::LInfDist(tmpTopT2, botT1) < botCSpace) {\n                    viaBotVia[j][k][l] = true;\n                }\n            }\n        }\n    }\n    LayerList::initOppLUT(viaBotVia, viaTopVia);\n}\n\nvoid LayerList::initViaForbidRegions() {\n    for (int i = 0; i < cutLayers.size(); ++i) {\n        auto& cutLayer = cutLayers[i];\n        cutLayer.botMaxForbidRegion = cutLayer.defaultViaType().bot;\n        cutLayer.topMaxForbidRegion = cutLayer.defaultViaType().top;\n        for (auto& viaType : cutLayer.allViaTypes) {\n            viaType.botForbidRegions = getAccurateMetalRectForbidRegions({i, viaType.bot});\n            for (const auto& region : viaType.botForbidRegions) {\n                cutLayer.botMaxForbidRegion = cutLayer.botMaxForbidRegion.UnionWith(region);\n            }\n            viaType.topForbidRegions = getAccurateMetalRectForbidRegions({i + 1, viaType.top});\n            for (const auto& region : viaType.topForbidRegions) {\n                cutLayer.topMaxForbidRegion = cutLayer.topMaxForbidRegion.UnionWith(region);\n            }\n        }\n    }\n}\n\nvoid LayerList::mergeLUT(vector<vector<bool>>& lhs, const vector<vector<bool>>& rhs) {\n    const unsigned lhsXSize = lhs.size() / 2;\n    const unsigned lhsYSize = lhs[0].size() / 2;\n    const unsigned rhsXSize = rhs.size() / 2;\n    const unsigned rhsYSize = rhs[0].size() / 2;\n    const unsigned offsetX = lhsXSize - rhsXSize;\n    const unsigned offsetY = lhsYSize - rhsYSize;\n    for (unsigned j = 0; j != rhs.size(); ++j) {\n        for (unsigned k = 0; k != rhs[0].size(); ++k) {\n            if (rhs[j][k]) lhs[j + offsetX][k + offsetY] = true;\n        }\n    }\n}\n\nvector<vector<bool>> LayerList::mergeLUTs(const vector<vector<vector<bool>>>& LUTs) {\n    int XSize = 0, YSize = 0;\n    vector<vector<bool>> mergedLUT;\n    for (auto& LUT : LUTs) {\n        XSize = max(XSize, int(LUT.size()));\n        YSize = max(YSize, int(LUT[0].size()));\n    }\n    mergedLUT.resize(XSize, vector<bool>(YSize, false));\n    for (auto& LUT : LUTs) {\n        mergeLUT(mergedLUT, LUT);\n    }\n    return mergedLUT;\n}\n\nvector<vector<vector<bool>>> LayerList::mergeLUTsCP(const vector<vector<vector<vector<bool>>>>& LUTs) {\n    vector<int> XSizes(LUTs[0].size(), 0);\n    vector<int> YSizes(LUTs[0].size(), 0);\n    // crossPointIdx, trackIdx, crossPointIdx\n    vector<vector<vector<bool>>> mergedLUTs(LUTs[0].size());\n    for (unsigned cpIdx = 0; cpIdx != LUTs[0].size(); ++cpIdx) {\n        for (unsigned typeIdx = 0; typeIdx != LUTs.size(); ++typeIdx) {\n            XSizes[cpIdx] = max(XSizes[cpIdx], int(LUTs[typeIdx][cpIdx].size()));\n            YSizes[cpIdx] = max(YSizes[cpIdx], int(LUTs[typeIdx][cpIdx][0].size()));\n        }\n        mergedLUTs[cpIdx].resize(XSizes[cpIdx], vector<bool>(YSizes[cpIdx], false));\n    }\n\n    for (unsigned cpIdx = 0; cpIdx != LUTs[0].size(); ++cpIdx) {\n        for (unsigned typeIdx = 0; typeIdx != LUTs.size(); ++typeIdx) {\n            mergeLUT(mergedLUTs[cpIdx], LUTs[typeIdx][cpIdx]);\n        }\n    }\n\n    return mergedLUTs;\n}\n\nvoid LayerList::print() {\n    log() << \"METAL LAYERS\" << std::endl;\n    numGridPoints = 0;\n    totalTrackLength = 0;\n    for (const MetalLayer& layer : layers) {\n        log() << layer << std::endl;\n        numGridPoints += layer.numGridPoints();\n        totalTrackLength += layer.numTracks() * layer.getCrossPointRangeDistCost({0, layer.numCrossPoints() - 1});\n    }\n    log() << \"The total number of grid points is \" << numGridPoints << std::endl;\n    log() << \"The total length of tracks is \" << totalTrackLength << \" DBU \" << std::endl;\n    log() << \"(Note: dir=Y means that each track is horizontal and has differnt Y)\" << std::endl;\n    log() << \"Metal layer design rules: \" << std::endl;\n    for (const MetalLayer& layer : layers) {\n        layer.printDesignRules(log()) << std::endl;\n    }\n    log() << \"Wire conflict LUT: \" << std::endl;\n    for (const MetalLayer& layer : layers) {\n        layer.printViaOccupancyLUT(log()) << std::endl;\n    }\n\n    log() << \"CUT LAYERS\" << std::endl;\n    numVias = 0;\n    for (int i = 0; i < getLayerNum() - 1; ++i) {\n        int num = layers[i].numTracks() * layers[i + 1].numTracks();\n        const auto& cutLayer = cutLayers[i];\n        log() << cutLayer << \", #vias=\" << num << std::endl;\n        numVias += num;\n    }\n    log() << \"Cut layer design rules: \" << std::endl;\n    for (const CutLayer& layer : cutLayers) {\n        layer.printDesignRules(log()) << std::endl;\n    }\n    log() << \"Via conflict LUT: \" << std::endl;\n    for (const CutLayer& layer : cutLayers) {\n        layer.printViaOccupancyLUT(log()) << std::endl;\n    }\n    log() << \"The total number of via candidates is \" << numVias << std::endl;\n}\n\nvoid LayerList::writeDefConflictLUTs(const std::string& debugFileName) const {\n    std::ofstream ofs(debugFileName);\n    int cpIdx = 0;\n    for (const auto& cutLayer : cutLayers) {\n        cutLayer.printBasics(ofs);\n        cutLayer.printDesignRules(ofs);\n        cutLayer.printViaOccupancyLUT(ofs);\n        ofs << \"viaCut\" << std::endl;\n        int xSize = ((int)cutLayer.allViaTypes[0].allViaCut[0].size() - 1) / 2;\n        int ySize = ((int)cutLayer.allViaTypes[0].allViaCut[0][0].size() - 1) / 2;\n        for (int j = xSize; j != cutLayer.allViaTypes[0].allViaCut[0].size(); ++j) {\n            for (int k = ySize; k != cutLayer.allViaTypes[0].allViaCut[0][0].size(); ++k) {\n                ofs << (int)(cutLayer.allViaTypes[0].allViaCut[0][j][k]) << \" \";\n            }\n            ofs << std::endl;\n        }\n        ofs << std::endl;\n        ofs << \"viaMetal\" << std::endl;\n        xSize = ((int)cutLayer.allViaTypes[0].allViaMetal[0].size() - 1) / 2;\n        ySize = ((int)cutLayer.allViaTypes[0].allViaMetal[0][0].size() - 1) / 2;\n        for (int j = xSize; j != cutLayer.allViaTypes[0].allViaMetal[0].size(); ++j) {\n            for (int k = ySize; k != cutLayer.allViaTypes[0].allViaMetal[0][0].size(); ++k) {\n                ofs << (int)(cutLayer.allViaTypes[0].allViaMetal[0][j][k]) << \" \";\n            }\n            ofs << std::endl;\n        }\n        ofs << std::endl;\n        ofs << \"viaBotVia\" << std::endl;\n        cpIdx = 0;\n        if (cutLayer.idx > 0) {\n            for (const auto& cp : cutLayer.allViaTypes[0].allViaBotVia[0]) {\n                ofs << \"cpidx is: \" << cpIdx++ << std::endl;\n                for (auto a : cp) {\n                    for (auto b : a) {\n                        ofs << (int)(b) << \" \";\n                    }\n                    ofs << std::endl;\n                }\n            }\n        }\n        ofs << \"viaTopVia\" << std::endl;\n        cpIdx = 0;\n        if (cutLayer.idx < cutLayers.size() - 1) {\n            for (const auto& cp : cutLayer.allViaTypes[0].allViaTopVia[0]) {\n                ofs << \"cpidx is: \" << cpIdx++ << std::endl;\n                for (auto a : cp) {\n                    for (auto b : a) {\n                        ofs << (int)(b) << \" \";\n                    }\n                    ofs << std::endl;\n                }\n            }\n        }\n        ofs << std::endl;\n    }\n}\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/LayerList.h",
    "content": "#pragma once\n\n#include \"CutLayer.h\"\n#include \"MetalLayer.h\"\n#include \"RsynService.h\"\n\nnamespace db {\n\nclass LayerList {\npublic:\n    void init();\n\n    // Check whether a geo primitive is valid\n    bool isValid(const GridPoint& gridPt) const;\n    bool isValid(const GridBoxOnLayer& gridBox) const;\n    bool isValid(const ViaBox& viaBox) const;\n\n    // Get metal rectangle (diff-net) forbidding region\n    // 1. for pin taps\n    BoxOnLayer getMetalRectForbidRegion(const BoxOnLayer& metalRect, AggrParaRunSpace aggr) const;\n    // 2. for via forbid regions\n    vector<utils::BoxT<DBU>> getAccurateMetalRectForbidRegions(const BoxOnLayer& metalRect) const;\n\n    // Expand box by several pitches\n    void expandBox(BoxOnLayer& box, int numPitchToExtend) const;\n    void expandBox(BoxOnLayer& box, int numPitchToExtend, int dir) const;\n\n    // NOTE: the functions below assume valid input geo primitive(s)\n\n    // Search by location\n    utils::IntervalT<int> getSurroundingTrack(int layerIdx, DBU loc) const;\n    utils::IntervalT<int> getSurroundingCrossPoint(int layerIdx, DBU loc) const;\n    GridBoxOnLayer getSurroundingGrid(int layerIdx, utils::PointT<DBU> loc) const;\n\n    // Search by location range\n    // input: layer (a valid one is assumed), location range [min, max] (inclusive)\n    // output: index range of Track/CrossPoint\n    // note: if out of range, assign the nearest endpoint\n    utils::IntervalT<int> rangeSearchTrack(int layerIdx,\n                                           const utils::IntervalT<DBU>& locRange,\n                                           bool includeBound = true) const;\n    utils::IntervalT<int> rangeSearchCrossPoint(int layerIdx,\n                                                const utils::IntervalT<DBU>& locRange,\n                                                bool includeBound = true) const;\n    GridBoxOnLayer rangeSearch(const BoxOnLayer& box, bool includeBound = true) const;\n\n    // Get (x, y) location of GridPoint/GridBoxOnLayer\n    utils::PointT<DBU> getLoc(const GridPoint& gridPt) const;\n    BoxOnLayer getLoc(const GridBoxOnLayer& gridBox) const;\n    std::pair<utils::PointT<DBU>, utils::PointT<DBU>> getLoc(const GridEdge& edge) const;\n\n    // Find the upper/lower GridPoint/GridBoxOnLayer of the current GridPoint/GridBoxOnLayer\n    // note: 1. valid layer is assumed, 2. upper/lower GridPoint/GridBoxOnLayer may not exist.\n    GridPoint getUpper(const GridPoint& cur) const;\n    GridPoint getLower(const GridPoint& cur) const;\n    GridBoxOnLayer getUpper(const GridBoxOnLayer& cur) const;\n    GridBoxOnLayer getLower(const GridBoxOnLayer& cur) const;\n\n    // Get ViaBox from the intersection of two BoxOnLayer (in neighboring layers)\n    // note: 1. should be on neighboring layers, 2. ViaBox may be empty.\n    ViaBox getViaBoxBetween(const BoxOnLayer& lower, const BoxOnLayer& upper);\n    ViaBox getViaBoxBetween(const GridBoxOnLayer& lower, const GridBoxOnLayer& upper) {\n        return getViaBoxBetween(getLoc(lower), getLoc(upper));\n    }\n    bool isConnected(const GridBoxOnLayer& lhs, const GridBoxOnLayer& rhs);\n    bool isAdjacent(const GridBoxOnLayer& lhs, const GridBoxOnLayer& rhs);\n\n    Dimension getLayerDir(int layerIdx) const { return layers[layerIdx].direction; }\n    const MetalLayer& getLayer(int layerIdx) const { return layers[layerIdx]; }\n    const CutLayer& getCutLayer(int cutLayerIdx) const { return cutLayers[cutLayerIdx]; }\n    unsigned getLayerNum() const noexcept { return layers.size(); }\n\n    // Merge LUTs\n    void mergeLUT(vector<vector<bool>>& lhs, const vector<vector<bool>>& rhs);\n    vector<vector<bool>> mergeLUTs(const vector<vector<vector<bool>>>& LUTs);\n    vector<vector<vector<bool>>> mergeLUTsCP(const vector<vector<vector<vector<bool>>>>& LUTs);\n\nprotected:\n    vector<MetalLayer> layers;\n    vector<CutLayer> cutLayers;\n\n    int numGridPoints;\n    DBU totalTrackLength;\n    int numVias;\n\n    void initCrossPoints();\n    static void initOppLUT(const vector<vector<vector<bool>>>& ori, vector<vector<vector<bool>>>& opp);\n    void initViaWire(const int layerIdx, const utils::BoxT<DBU>& viaMetal, vector<vector<vector<bool>>>& viaWireLUT);\n    void initSameLayerViaConfLUT(const int layerIdx,\n                                 ViaType& viaT1,\n                                 ViaType& viaT2,\n                                 vector<vector<bool>>& viaCut,\n                                 vector<vector<bool>>& viaMetal,\n                                 vector<vector<int>>& viaMetalNum);\n    void initDiffLayerViaConfLUT(const int layerIdx,\n                                 ViaType& viaT1,\n                                 ViaType& viaT2,\n                                 vector<vector<vector<bool>>>& viaBotVia,\n                                 vector<vector<vector<bool>>>& viaTopVia);\n    void initViaConfLUT();\n    void initViaForbidRegions();\n    void print();\n    void writeDefConflictLUTs(const std::string& debugFileName) const;\n};\n\n}  //   namespace db\n"
  },
  {
    "path": "src/db/MetalLayer.cpp",
    "content": "#include \"MetalLayer.h\"\n\nnamespace db {\n\nostream& operator<<(ostream& os, const Track& track) {\n    os << \"track(lo=\" << track.lowerCPIdx << \", up=\" << track.upperCPIdx << \", loc=\" << track.location << \")\";\n    return os;\n}\n\nostream& operator<<(ostream& os, const CrossPoint& cp) {\n    os << \"crossPt(lo=\" << cp.lowerTrackIdx << \", up=\" << cp.upperTrackIdx << \", loc=\" << cp.location << \")\";\n    return os;\n}\n\nMetalLayer::MetalLayer(Rsyn::PhysicalLayer rsynLayer, Rsyn::PhysicalTracks rsynTrack, const DBU libDBU) {\n    // Rsyn::PhysicalLayer (LEF)\n    lefiLayer* layer = rsynLayer.getLayer();\n    name = layer->name();\n    direction = strcmp(layer->direction(), \"HORIZONTAL\") ? X : Y;\n    assert((rsynTrack.getDirection() == Rsyn::TRACK_HORIZONTAL) == (direction == Y));\n    idx = rsynLayer.getRelativeIndex();\n    width = static_cast<DBU>(std::round(layer->width() * libDBU));\n    minWidth = static_cast<DBU>(std::round(layer->minwidth() * libDBU));\n    widthForSuffOvlp = std::ceil(minWidth * 0.7071);\n    shrinkForSuffOvlp = std::max<DBU>(0, std::ceil(widthForSuffOvlp - width * 0.5));\n    minArea = static_cast<DBU>(std::round(layer->area() * libDBU * libDBU));\n    minLenRaw = minArea / width - width;\n    // default spacing\n    const int numSpaceTable = layer->numSpacingTable();\n    if (!numSpaceTable) {\n        log() << \"Warning in \" << __func__ << \": For \" << name << \", no run spacing table...\" << std::endl;\n    } else {\n        for (int iSpaceTable = 0; iSpaceTable < numSpaceTable; ++iSpaceTable) {\n            if (!layer->spacingTable(iSpaceTable)->isParallel()) {\n                continue;\n            }\n\n            const lefiParallel* parallel = layer->spacingTable(iSpaceTable)->parallel();\n            const int numLength = parallel->numLength();\n            if (numLength > 0) {\n                parallelLength.resize(numLength);\n                for (unsigned iLength = 0; iLength != (unsigned)numLength; ++iLength) {\n                    parallelLength[iLength] = static_cast<DBU>(std::round(parallel->length(iLength) * libDBU));\n                }\n            }\n            const int numWidth = parallel->numWidth();\n            if (numWidth > 0) {\n                parallelWidth.resize(numWidth);\n                parallelWidthSpace.resize(numWidth);\n                for (unsigned iWidth = 0; iWidth != (unsigned)numWidth; ++iWidth) {\n                    parallelWidth[iWidth] = static_cast<DBU>(std::round(parallel->width(iWidth) * libDBU));\n                    parallelWidthSpace[iWidth].resize(std::max(1, numLength), 0);\n                    for (int iLength = 0; iLength < numLength; ++iLength) {\n                        parallelWidthSpace[iWidth][iLength] =\n                            static_cast<DBU>(std::round(parallel->widthSpacing(iWidth, iLength) * libDBU));\n                    }\n                }\n                defaultSpace = getParaRunSpace(width);\n                paraRunSpaceForLargerWidth = (parallelWidthSpace.size() > 1) ? parallelWidthSpace[1][0] : defaultSpace;\n            }\n        }\n    }\n    //  eol spacing\n    if (!layer->hasSpacingNumber()) {\n        log() << \"Warning in \" << __func__ << \": For \" << name << \", no spacing rules...\" << std::endl;\n    } else {\n        const int numSpace = layer->numSpacing();\n        spaceRules.reserve(numSpace);\n        for (int iSpace = 0; iSpace < numSpace; ++iSpace) {\n            const DBU space = static_cast<DBU>(std::round(layer->spacing(iSpace) * libDBU));\n            const DBU eolWidth = static_cast<DBU>(std::round(layer->spacingEolWidth(iSpace) * libDBU));\n            const DBU eolWithin = static_cast<DBU>(std::round(layer->spacingEolWithin(iSpace) * libDBU));\n            const DBU parSpace = static_cast<DBU>(std::round(layer->spacingParSpace(iSpace) * libDBU));\n            const DBU parWithin = static_cast<DBU>(std::round(layer->spacingParWithin(iSpace) * libDBU));\n            if (layer->hasSpacingParellelEdge(iSpace)) {\n                spaceRules.emplace_back(space, eolWidth, eolWithin, parSpace, parWithin);\n                maxEolSpace = std::max(maxEolSpace, space);\n                maxEolWidth = std::max(maxEolWidth, eolWidth);\n                maxEolWithin = std::max(maxEolWithin, eolWithin);\n            } else if (layer->hasSpacingEndOfLine(iSpace)) {\n                spaceRules.emplace_back(space, eolWidth, eolWithin);\n                maxEolSpace = std::max(maxEolSpace, space);\n                maxEolWidth = std::max(maxEolWidth, eolWidth);\n                maxEolWithin = std::max(maxEolWithin, eolWithin);\n            } else if (space != defaultSpace) {\n                log() << \"Warning in \" << __func__ << \": For \" << rsynLayer.getName()\n                      << \", mismatched defaultSpace & spacingTable... \" << std::endl;\n            }\n        }\n        if (spaceRules.empty()) {\n            log() << \"Warning in \" << __func__ << \": For \" << name << \", no eol spacing rules...\" << std::endl;\n        }\n    }\n    fixedMetalQueryMargin = std::max(maxEolSpace, maxEolWithin);\n\n    //  corner spacing\n    const int numProps = layer->numProps();\n    for (unsigned iProp = 0; static_cast<int>(iProp) < numProps; ++iProp) {\n        if (strcmp(layer->propName(iProp), \"LEF58_CORNERSPACING\")) continue;\n\n        if (hasCornerSpace()) {\n            log() << \"Warning in \" << __func__ << \": For \" << name\n                  << \", multiple corner spacing rules: \" << layer->propValue(iProp) << \"...\\n\";\n            continue;\n        }\n\n        std::istringstream iss(layer->propValue(iProp));\n        std::string sBuf(\"\");\n        double fBuf1{0};\n        double fBuf2{0};\n        while (iss) {\n            iss >> sBuf;\n            if (sBuf == \"CORNERSPACING\" || sBuf == \"CONVEXCORNER\" || sBuf == \";\") continue;\n            if (sBuf == \"EXCEPTEOL\") {\n                cornerExceptEol = true;\n                iss >> fBuf1;\n                cornerEolWidth = static_cast<DBU>(std::round(fBuf1 * libDBU));\n            } else if (sBuf == \"WIDTH\") {\n                iss >> fBuf1 >> sBuf >> fBuf2;\n                if (fBuf1) {\n                    cornerWidth.push_back(static_cast<DBU>(std::round(fBuf1 * libDBU)));\n                    cornerWidthSpace.push_back(static_cast<DBU>(std::round(fBuf2 * libDBU)));\n                } else {\n                    cornerWidthSpace[0] = static_cast<DBU>(std::round(fBuf2 * libDBU));\n                }\n            } else {\n                log() << \"Warning in \" << __func__ << \": For \" << name << \", corner spacing not identified: \" << sBuf\n                      << \"...\\n\";\n            }\n        }\n    }\n    delete rsynLayer.getLayer();\n\n    // Rsyn::PhysicalTracks (DEF)\n    // note: crossPoints will be initialized in LayerList\n    pitch = rsynTrack.getSpace();\n    DBU location = rsynTrack.getLocation();\n    for (int i = 0; i < rsynTrack.getNumberOfTracks(); ++i) {\n        tracks.emplace_back(location);\n        location += pitch;\n    }\n\n    // safe margin\n    minAreaMargin = ceil(((minArea / width) + width) * 1.0 / pitch) * pitch * 2;\n\n    // Check consistency between LEF and DEF\n    check();\n}\n\nbool MetalLayer::isTrackRangeValid(const utils::IntervalT<int>& trackRange) const {\n    return trackRange.low >= 0 && trackRange.high < tracks.size() && trackRange.IsValid();\n}\n\nbool MetalLayer::isTrackRangeWeaklyValid(const utils::IntervalT<int>& trackRange) const {\n    return trackRange.low >= 0 && trackRange.low < tracks.size() && trackRange.high >= 0 &&\n           trackRange.high < tracks.size();\n}\n\nutils::IntervalT<int> MetalLayer::getUpperCrossPointRange(const utils::IntervalT<int>& trackRange) const {\n    return {tracks[trackRange.low].upperCPIdx, tracks[trackRange.high].upperCPIdx};\n}\n\nutils::IntervalT<int> MetalLayer::getLowerCrossPointRange(const utils::IntervalT<int>& trackRange) const {\n    return {tracks[trackRange.low].lowerCPIdx, tracks[trackRange.high].lowerCPIdx};\n}\n\nutils::IntervalT<int> MetalLayer::getSurroundingTrack(DBU loc) const {\n    // offset by firstTrackLoc(), make it within track range, and round\n    const double floatingTrackIdx =\n        (std::min(std::max(firstTrackLoc(), loc), lastTrackLoc()) - firstTrackLoc()) / static_cast<double>(pitch);\n    return {floor(floatingTrackIdx), ceil(floatingTrackIdx)};\n}\n\nutils::IntervalT<int> MetalLayer::rangeSearchTrack(const utils::IntervalT<DBU>& locRange, bool includeBound) const {\n    auto locRangeCopy = locRange;\n    // invalid range (low >= high) will still be invalid\n    if (locRangeCopy.low < firstTrackLoc()) {\n        locRangeCopy.low = firstTrackLoc();\n    }\n    if (locRangeCopy.high > lastTrackLoc()) {\n        locRangeCopy.high = lastTrackLoc();\n    }\n\n    utils::IntervalT<int> res{ceil(double(locRangeCopy.low - firstTrackLoc()) / double(pitch)),\n                              floor(double(locRangeCopy.high - firstTrackLoc()) / double(pitch))};\n\n    if (!includeBound) {\n        if (res.high >= 0 && res.high < numTracks() && tracks[res.high].location == locRange.high) --res.high;\n        if (res.low >= 0 && res.low < numTracks() && tracks[res.low].location == locRange.low) ++res.low;\n    }\n\n    return res;\n}\n\nbool MetalLayer::isCrossPointRangeValid(const utils::IntervalT<int>& crossPointRange) const {\n    return crossPointRange.low >= 0 && crossPointRange.high < crossPoints.size() && crossPointRange.IsValid();\n}\n\nvoid MetalLayer::initAccCrossPointDistCost() {\n    accCrossPointDistCost.resize(numCrossPoints() + 1);\n    accCrossPointDistCost[0] = 0;\n    // For four uniform-distributed crossPoints with dist 1:\n    // accCrossPointCost = {0, 0.5, 1.5, 2.5, 3}\n    for (int cpIdx = 0; cpIdx < numCrossPoints(); ++cpIdx) {\n        DBU delta = 0;\n        if ((cpIdx + 1) < numCrossPoints()) {\n            delta = (crossPoints[cpIdx + 1].location - crossPoints[cpIdx].location) / 2;\n        }\n        accCrossPointDistCost[cpIdx + 1] = crossPoints[cpIdx].location - crossPoints[0].location + delta;\n    }\n}\n\nDBU MetalLayer::getCrossPointRangeDistCost(const utils::IntervalT<int>& crossPointRange) const {\n    assert(crossPointRange.IsValid());\n    return accCrossPointDistCost[crossPointRange.high + 1] - accCrossPointDistCost[crossPointRange.low];\n}\n\nDBU MetalLayer::getCrossPointRangeDist(const utils::IntervalT<int>& crossPointRange) const {\n    return crossPoints[crossPointRange.high].location - crossPoints[crossPointRange.low].location;\n}\n\nutils::PointT<DBU> MetalLayer::getLoc(const GridPoint& grid) const {\n    utils::PointT<DBU> loc;\n    loc[direction] = tracks[grid.trackIdx].location;\n    loc[1 - direction] = crossPoints[grid.crossPointIdx].location;\n    return loc;\n}\n\nstd::pair<utils::PointT<DBU>, utils::PointT<DBU>> MetalLayer::getLoc(const GridEdge& edge) const {\n    utils::PointT<DBU> loc1 = getLoc(edge.u);\n    utils::PointT<DBU> loc2 = getLoc(edge.v);\n\n    if (loc1.x == loc2.x) {\n        if (loc1.y < loc2.y)\n            return {loc1, loc2};\n        else\n            return {loc2, loc1};\n    } else {\n        if (loc1.x < loc2.x)\n            return {loc1, loc2};\n        else\n            return {loc2, loc1};\n    }\n}\n\nBoxOnLayer MetalLayer::getLoc(const GridBoxOnLayer& gridBox) const {\n    BoxOnLayer box;\n    box.layerIdx = gridBox.layerIdx;\n    box[direction].Set(tracks[gridBox.trackRange.low].location, tracks[gridBox.trackRange.high].location);\n    box[1 - direction].Set(crossPoints[gridBox.crossPointRange.low].location,\n                           crossPoints[gridBox.crossPointRange.high].location);\n    return box;\n}\n\nGridPoint MetalLayer::getUpper(const GridPoint& cur) const {\n    return {cur.layerIdx + 1, crossPoints[cur.crossPointIdx].upperTrackIdx, tracks[cur.trackIdx].upperCPIdx};\n}\n\nGridPoint MetalLayer::getLower(const GridPoint& cur) const {\n    return {cur.layerIdx - 1, crossPoints[cur.crossPointIdx].lowerTrackIdx, tracks[cur.trackIdx].lowerCPIdx};\n}\n\nbool MetalLayer::isValid(const GridPoint& gridPt) const {\n    return gridPt.trackIdx >= 0 && gridPt.trackIdx < tracks.size() &&               // track\n           gridPt.crossPointIdx >= 0 && gridPt.crossPointIdx < crossPoints.size();  // cross point\n}\n\nbool MetalLayer::isValid(const GridBoxOnLayer& gridBox) const {\n    return isTrackRangeValid(gridBox.trackRange) && isCrossPointRangeValid(gridBox.crossPointRange);\n}\n\nDBU MetalLayer::getParaRunSpace(const DBU width, const DBU length) const {\n    int iWidth = parallelWidth.size() - 1;  // first smaller than or equal to\n    while (iWidth > 0 && parallelWidth[iWidth] >= width) {\n        --iWidth;\n    }\n    if (length == 0) return parallelWidthSpace[iWidth][0];  // fast return\n    int iLength = parallelLength.size() - 1;                // first smaller than or equal to\n    while (iLength > 0 && parallelLength[iLength] >= length) {\n        --iLength;\n    }\n    return parallelWidthSpace[iWidth][iLength];\n}\n\nDBU MetalLayer::getParaRunSpace(const utils::BoxT<DBU>& targetMetal, const DBU length) const {\n    return getParaRunSpace(min(targetMetal.width(), targetMetal.height()), length);\n}\n\nDBU MetalLayer::getSpace(const utils::BoxT<DBU>& targetMetal, int dir, AggrParaRunSpace aggr) const {\n    const DBU range = targetMetal[1 - dir].range();\n    DBU space = getEolSpace(range);\n    if (!space) {\n        // parallel run spacing\n        DBU length = 0;\n        if (aggr == AggrParaRunSpace::LARGER_LENGTH && targetMetal[1 - dir].range() > 100 * pitch) {\n            // hack: assume at least two-pitch parallel run length\n            length = (pitch * 2 + width);\n        }\n        space = getParaRunSpace(targetMetal, length);\n    }\n    // do not know the width of neighbor, so paraRunSpaceForLargerWidth\n    if (aggr == AggrParaRunSpace::LARGER_WIDTH && paraRunSpaceForLargerWidth > space) {\n        space = paraRunSpaceForLargerWidth;\n    }\n    return space;\n}\n\nDBU MetalLayer::getEolSpace(const DBU width) const { return (width < maxEolWidth) ? maxEolSpace : 0; }\n\nbool MetalLayer::isEolViolation(const DBU space, const DBU width, const DBU within) const {\n    return (space < maxEolSpace && width < maxEolWidth && within < maxEolWithin);\n}\n\nbool MetalLayer::isEolViolation(const utils::BoxT<DBU>& lhs, const utils::BoxT<DBU>& rhs) const {\n    for (unsigned dim = 0; dim != 2; ++dim) {\n        const DBU space = utils::Dist(lhs[1 - dim], rhs[1 - dim]);\n        const DBU width = min(lhs[dim].range(), rhs[dim].range());\n        const DBU within = utils::Dist(lhs[dim], rhs[dim]);\n        if (isEolViolation(space, width, within)) return true;\n    }\n    return false;\n}\n\nDBU MetalLayer::getCornerSpace(const DBU width) const {\n    if (cornerExceptEol && width < cornerEolWidth) return 0;\n\n    int iWidth = cornerWidth.size() - 1;  // first smaller than or equal to\n    while (iWidth > 0 && cornerWidth[iWidth] >= width) {\n        --iWidth;\n    }\n    return cornerWidthSpace[iWidth];\n}\n\nDBU MetalLayer::getCornerSpace(const utils::BoxT<DBU>& targetMetal) const {\n    return getCornerSpace(min(targetMetal.width(), targetMetal.height()));\n}\n\nvoid MetalLayer::initWireRange() {\n    const DBU eolSpace = getEolSpace(width);\n    const DBU wireEndPointSpace = eolSpace ? eolSpace + width : defaultSpace + width;  // consider two half width\n    wireRange.resize(numCrossPoints(), {0, 0});\n    int i, j;\n    for (int cpIdx = 0; cpIdx < numCrossPoints(); ++cpIdx) {\n        i = 0;\n        while (cpIdx + i >= 0 && crossPoints[cpIdx].location - crossPoints[cpIdx + i].location < wireEndPointSpace) {\n            --i;\n        }\n        j = 0;\n        while (cpIdx + j < numCrossPoints() &&\n               crossPoints[cpIdx + j].location - crossPoints[cpIdx].location < wireEndPointSpace) {\n            ++j;\n        }\n        wireRange[cpIdx] = {i + 1, j - 1};\n    }\n}\n\nostream& MetalLayer::printBasics(ostream& os) const {\n    os << name << \": dir=\" << getDimension(direction) << \", idx=\" << idx;\n    os << \", tracks=(locs=\" << firstTrackLoc() << \"-\" << lastTrackLoc() << \",pitch=\" << pitch << \",#=\" << numTracks()\n       << \")\";\n    os << \", crossPts=(locs=\" << firstCrossPointLoc() << \"-\" << lastCrossPointLoc() << \",#=\" << numCrossPoints() << \")\";\n    os << \", #grids=\" << numGridPoints() << \")\";\n    return os;\n}\n\nostream& MetalLayer::printDesignRules(ostream& os) const {\n    os << name << \": width=\" << width << \", paraSpace=(default=\" << defaultSpace;\n    for (int i = 0; i < parallelWidth.size(); ++i) {\n        os << \", \" << parallelWidth[i] << \":\" << parallelWidthSpace[i];\n    }\n    os << \"), eolSpace=(\";\n    for (const SpaceRule& spaceRule : spaceRules) {\n        if (spaceRule.hasEol /* && !spaceRule.hasPar */) {\n            os << spaceRule.eolWidth << ':' << spaceRule.space << \", \";\n        }\n    }\n    os << \"), minArea=\" << minArea;\n    return os;\n}\n\nostream& MetalLayer::printViaOccupancyLUT(ostream& os) const {\n    auto getMaxSize2d = [](const vector<vector<vector<bool>>>& LUT, size_t& xSize, size_t& ySize) {\n        xSize = 0;\n        ySize = 0;\n        for (const vector<vector<bool>>& cpLUT : LUT) {\n            if (cpLUT.size()) {\n                xSize = max(xSize, cpLUT.size());\n                ySize = max(ySize, cpLUT[0].size());\n            }\n        }\n    };\n    auto getMaxSize1d = [](const vector<utils::IntervalT<int>>& ranges, utils::IntervalT<int>& yRange) {\n        yRange = {0, 0};\n        for (const auto& rangeCP : ranges) {\n            yRange = yRange.UnionWith(rangeCP);\n        }\n    };\n    size_t xSize, ySize;\n    utils::IntervalT<int> yRange;\n    getMaxSize1d(wireRange, yRange);\n    os << name << \": wire(\" << wireRange.size() << ',' << yRange << ')';\n    if (wireBotVia.size()) {\n        getMaxSize2d(wireBotVia[0], xSize, ySize);  // TODO: print default\n        os << \", wireBotVia(\" << wireBotVia.size() << ',' << xSize << ',' << ySize << ')';\n    }\n    if (wireTopVia.size()) {\n        getMaxSize2d(wireTopVia[0], xSize, ySize);\n        os << \", wireTopVia(\" << wireTopVia.size() << ',' << xSize << ',' << ySize << ')';\n    }\n    return os;\n}\n\nostream& operator<<(ostream& os, const MetalLayer& layer) { return layer.printBasics(os); }\n\nvoid MetalLayer::check() const {\n    if (width < minWidth) {\n        log() << \"Warning: In layer \" << name << \", width = \" << width << \" < minWidth = \" << minWidth << std::endl;\n    }\n    if (width > maxEolWidth) {\n        log() << \"Warning: In layer \" << name << \", width = \" << width << \" > maxEolWidth = \" << maxEolWidth\n              << std::endl;\n    }\n    if (width + defaultSpace > pitch) {\n        log() << \"Warning: In layer \" << name << \", width + defaultSpace =\" << width + defaultSpace\n              << \" > picth = \" << pitch << std::endl;\n    }\n}\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/MetalLayer.h",
    "content": "#pragma once\n\n#include \"GeoPrimitive.h\"\n\nnamespace db {\n\nclass Track {\npublic:\n    Track(DBU loc, int lowerIdx = -1, int upperIdx = -1) : location(loc), lowerCPIdx(lowerIdx), upperCPIdx(upperIdx) {}\n    DBU location;\n    int lowerCPIdx;\n    int upperCPIdx;\n\n    friend ostream& operator<<(ostream& os, const Track& track);\n};\n\n// Cross points are projection of tracks from upper and lower layers\nclass CrossPoint {\npublic:\n    CrossPoint(DBU loc, int lowerIdx = -1, int upperIdx = -1)\n        : location(loc), lowerTrackIdx(lowerIdx), upperTrackIdx(upperIdx) {}\n    DBU location;\n    int lowerTrackIdx;\n    int upperTrackIdx;\n\n    friend ostream& operator<<(ostream& os, const CrossPoint& cp);\n};\n\nclass SpaceRule {\npublic:\n    SpaceRule(const DBU space, const DBU eolWidth, const DBU eolWithin)\n        : space(space), hasEol(true), eolWidth(eolWidth), eolWithin(eolWithin) {}\n    SpaceRule(const DBU space, const DBU eolWidth, const DBU eolWithin, const DBU parSpace, const DBU parWithin)\n        : space(space),\n          hasEol(true),\n          eolWidth(eolWidth),\n          eolWithin(eolWithin),\n          hasPar(true),\n          parSpace(parSpace),\n          parWithin(parWithin) {}\n\n    DBU space = 0;\n    bool hasEol = false;\n    DBU eolWidth = 0;\n    DBU eolWithin = 0;\n    bool hasPar = false;\n    DBU parSpace = 0;\n    DBU parWithin = 0;\n};\n\nenum class AggrParaRunSpace { DEFAULT, LARGER_WIDTH, LARGER_LENGTH };\n\n// note: for operations on GeoPrimitives, all checking is down in LayerList for low level efficiency\nclass MetalLayer {\npublic:\n    MetalLayer(Rsyn::PhysicalLayer rsynLayer, Rsyn::PhysicalTracks rsynTrack, const DBU libDBU);\n\n    // Basic infomation\n    std::string name;\n    Dimension direction;  // direction of track dimension\n    int idx;              // layerIdx (consistent with Rsyn::xxx::getRelativeIndex())\n\n    // Track (1D)\n    DBU pitch = 0;\n    vector<Track> tracks;\n    int numTracks() const { return tracks.size(); }\n    DBU firstTrackLoc() const { return tracks.front().location; }\n    DBU lastTrackLoc() const { return tracks.back().location; }\n    bool isTrackRangeValid(const utils::IntervalT<int>& trackRange) const;\n    bool isTrackRangeWeaklyValid(const utils::IntervalT<int>& trackRange) const;\n    utils::IntervalT<int> getUpperCrossPointRange(const utils::IntervalT<int>& trackRange) const;\n    utils::IntervalT<int> getLowerCrossPointRange(const utils::IntervalT<int>& trackRange) const;\n    // search by location (range) (result may be invalid/empty)\n    utils::IntervalT<int> getSurroundingTrack(DBU loc) const;\n    utils::IntervalT<int> rangeSearchTrack(const utils::IntervalT<DBU>& locRange, bool includeBound = true) const;\n\n    // CrossPoint (1D)\n    vector<CrossPoint> crossPoints;\n    int numCrossPoints() const { return crossPoints.size(); }\n    DBU firstCrossPointLoc() const { return crossPoints.front().location; }\n    DBU lastCrossPointLoc() const { return crossPoints.back().location; }\n    bool isCrossPointRangeValid(const utils::IntervalT<int>& crossPointRange) const;\n    // base grid cost without congestion penalty\n    // edge cost = accCrossPointCost[crossPointRange.high + 1] - accCrossPointCost[crossPointRange.low]\n    // cost is directly posed on grids instead of edges (easier to cross layers & handle corners)\n    vector<DBU> accCrossPointDistCost;\n    void initAccCrossPointDistCost();\n    DBU getCrossPointRangeDistCost(const utils::IntervalT<int>& crossPointRange) const;\n    DBU getCrossPointRangeDist(const utils::IntervalT<int>& crossPointRange) const;\n\n    // GridPoint (2D) = Track (1D) x CrossPoint (1D)\n    int numGridPoints() const { return tracks.size() * crossPoints.size(); }\n    bool isValid(const GridPoint& gridPt) const;\n    bool isValid(const GridBoxOnLayer& gridBox) const;\n    utils::PointT<DBU> getLoc(const GridPoint& grid) const;\n    BoxOnLayer getLoc(const GridBoxOnLayer& gridBox) const;\n    std::pair<utils::PointT<DBU>, utils::PointT<DBU>> getLoc(const GridEdge& edge) const;\n    GridPoint getUpper(const GridPoint& cur) const;\n    GridPoint getLower(const GridPoint& cur) const;\n\n    // Design rules\n    // width\n    DBU width = 0;\n    DBU minWidth = 0;\n    DBU widthForSuffOvlp = 0;\n    DBU shrinkForSuffOvlp = 0;\n    // minArea\n    DBU minArea = 0;\n    DBU minLenRaw = 0;\n    DBU minLenOneVia = 0;\n    DBU minLenTwoVia = 0;\n    DBU viaOvlpDist = 0;\n    DBU viaLenEqLen = 0;\n    DBU viaWidthEqLen = 0;\n    bool hasMinLenVio(DBU len) const { return len < getMinLen(); }\n    bool hasMinLenVioAcc(DBU len) const { return len < getMinLenAcc(len); }\n    DBU getMinLen() const { return minLenRaw; }\n    DBU getMinLenAcc(DBU len) const { return len < viaOvlpDist ? minLenOneVia : minLenTwoVia; }\n    // parallel spacing\n    vector<DBU> parallelWidth{0};\n    vector<DBU> parallelLength{0};\n    vector<vector<DBU>> parallelWidthSpace{{0}};\n    DBU defaultSpace = 0;\n    DBU paraRunSpaceForLargerWidth = 0;\n    DBU getParaRunSpace(const DBU width, const DBU length = 0) const;\n    DBU getParaRunSpace(const utils::BoxT<DBU>& targetMetal, const DBU length = 0) const;\n    // eol spacing\n    // TODO: handle multiple spaceRules\n    vector<SpaceRule> spaceRules;\n    DBU maxEolSpace = 0;\n    DBU maxEolWidth = 0;\n    DBU maxEolWithin = 0;\n    DBU getEolSpace(const DBU width) const;\n    bool isEolViolation(const DBU space, const DBU width, const DBU within) const;\n    bool isEolViolation(const utils::BoxT<DBU>& lhs, const utils::BoxT<DBU>& rhs) const;\n    // corner spacing\n    bool cornerExceptEol = false;\n    DBU cornerEolWidth = 0;\n    vector<DBU> cornerWidth{0};\n    vector<DBU> cornerWidthSpace{0};\n    bool hasCornerSpace() const { return cornerWidthSpace.size() > 1 || cornerWidthSpace[0]; }\n    DBU getCornerSpace(const DBU width) const;\n    DBU getCornerSpace(const utils::BoxT<DBU>& targetMetal) const;\n\n    // Translate design rule\n    // either both parallel-run spacing or eol spacing\n    DBU getSpace(const utils::BoxT<DBU>& targetMetal, int dir, AggrParaRunSpace aggr) const;\n    // there is parallel-run spacing with negative length if the targetMetal is not eol dominated\n    bool isEolDominated(const utils::BoxT<DBU>& targetMetal) const {\n        return max(targetMetal.x.range(), targetMetal.y.range()) < maxEolWidth;\n    }\n    // margin for multi-thread safe and others\n    DBU minAreaMargin = 0;\n    DBU confLutMargin = 0;\n    DBU fixedMetalQueryMargin = 0;\n    DBU mtSafeMargin = 0;\n\n    // Via conflict lookup table (true means \"available\" / no conflict)\n    // 1. wire-via conflict (viaTypeIdx, crossPointIdx, trackIdx, crossPointIdx)\n    vector<vector<vector<vector<bool>>>> wireBotVia;\n    vector<vector<vector<vector<bool>>>> wireTopVia;\n    vector<vector<vector<bool>>> mergedWireBotVia;\n    vector<vector<vector<bool>>> mergedWireTopVia;\n    bool isWireViaMultiTrack = false;\n    // 2. wire-wire conflict (crossPointIdx, crossPointIdx)\n    vector<utils::IntervalT<int>> wireRange;\n\n    void initWireRange();\n\n    ostream& printBasics(ostream& os) const;\n    ostream& printDesignRules(ostream& os) const;\n    ostream& printViaOccupancyLUT(ostream& os) const;\n    friend ostream& operator<<(ostream& os, const MetalLayer& layer);\n\nprivate:\n    void check() const;\n};\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/Net.cpp",
    "content": "#include \"Net.h\"\n\n#include <fstream>\n\n#include \"Setting.h\"\n\nnamespace db {\n\nNetBase::~NetBase() {}\n\nBoxOnLayer NetBase::getMaxAccessBox(int pinIdx) const {\n    DBU maxArea = std::numeric_limits<DBU>::min();\n    db::BoxOnLayer bestBox;\n    for (const auto& box : pinAccessBoxes[pinIdx]) {\n        if (maxArea < box.area()) {\n            maxArea = box.area();\n            bestBox = box;\n        }\n    }\n    return bestBox;\n}\n\nvoid NetBase::print(ostream& os) const {\n    os << \"Net \" << getName() << \" (idx = \" << idx << \") with \" << numOfPins() << \" pins \" << std::endl;\n    for (int i = 0; i < numOfPins(); ++i) {\n        os << \"pin \" << i << \" \" << rsynPins[i].getInstanceName() << std::endl;\n        for (auto& accessBox : pinAccessBoxes[i]) {\n            os << accessBox << std::endl;\n        }\n    }\n\n    os << routeGuides.size() << \" route guides\" << std::endl;\n    if (routeGuides.size() == gridRouteGuides.size()) {\n        for (int i = 0; i < routeGuides.size(); ++i) {\n            os << routeGuides[i] << \" \" << gridRouteGuides[i] << std::endl;\n        }\n    } else {\n        for (auto& routeGuide : routeGuides) {\n            os << routeGuide << std::endl;\n        }\n    }\n\n    os << std::endl;\n}\n\nNet::Net(int i, Rsyn::Net net, RsynService& rsynService) {\n    idx = i;\n    rsynNet = net;\n\n    // pins\n    pinAccessBoxes.reserve(net.getNumPins());\n    const Rsyn::Session session;\n    const Rsyn::PhysicalDesign& physicalDesign =\n        static_cast<Rsyn::PhysicalService*>(session.getService(\"rsyn.physical\"))->getPhysicalDesign();\n    const DBU libDBU = physicalDesign.getDatabaseUnits(Rsyn::LIBRARY_DBU);\n    for (auto RsynPin : net.allPins()) {\n        rsynPins.push_back(RsynPin);\n        pinAccessBoxes.emplace_back();\n        initPinAccessBoxes(RsynPin, rsynService, pinAccessBoxes.back(), libDBU);\n    }\n}\n\nvoid Net::initPinAccessBoxes(Rsyn::Pin rsynPin,\n                             RsynService& rsynService,\n                             vector<BoxOnLayer>& accessBoxes,\n                             const DBU libDBU) {\n    // PhysicalPort\n    if (rsynPin.isPort()) {\n        Rsyn::PhysicalPort phPort = rsynService.physicalDesign.getPhysicalPort(rsynPin.getPort());\n        getPinAccessBoxes(phPort, accessBoxes);\n        return;\n    }\n\n    // PhysicalLibraryPin\n    Rsyn::PhysicalLibraryPin phLibPin = rsynService.physicalDesign.getPhysicalLibraryPin(rsynPin);\n\n    // PhysicalCell\n    Rsyn::Instance instance = rsynPin.getInstance();\n    if (instance.getType() != Rsyn::CELL) {\n        log() << \"Warning: pin is not on a cell \" << rsynPin.getNetName() << \" \" << rsynPin.getInstanceName()\n              << std::endl;\n        return;\n    }\n    Rsyn::Cell cell = instance.asCell();\n    Rsyn::PhysicalCell phCell = rsynService.physicalDesign.getPhysicalCell(cell);\n    Rsyn::PhysicalLibraryCell phLibCell = rsynService.physicalDesign.getPhysicalLibraryCell(cell);\n    const DBUxy origin(static_cast<DBU>(std::round(phLibCell.getMacro()->originX() * libDBU)),\n                       static_cast<DBU>(std::round(phLibCell.getMacro()->originY() * libDBU)));\n\n    // fill accessBoxes\n    getPinAccessBoxes(phLibPin, phCell, accessBoxes, origin);\n};\n\nvoid Net::getPinAccessBoxes(Rsyn::PhysicalPort phPort, vector<BoxOnLayer>& accessBoxes) {\n    auto displacement = phPort.getPosition();\n    auto bounds = phPort.getBounds();\n    Bounds dummyCellBounds(displacement, displacement);\n    Rsyn::PhysicalTransform transform(dummyCellBounds, phPort.getOrientation());\n    bounds.translate(displacement);\n    bounds = transform.apply(bounds);\n    accessBoxes.emplace_back(phPort.getLayer().getRelativeIndex(), getBoxFromRsynBounds(bounds));\n}\n\nvoid Net::getPinAccessBoxes(Rsyn::PhysicalLibraryPin phLibPin,\n                            Rsyn::PhysicalCell phCell,\n                            vector<BoxOnLayer>& accessBoxes,\n                            const DBUxy& origin) {\n    if (!phLibPin.hasPinGeometries()) {\n        log() << \"Warning: pin of \" << phCell.getName() << \" has no pinGeometries\" << std::endl;\n        return;\n    }\n\n    const DBUxy displacement = phCell.getPosition() + origin;\n    auto transform = phCell.getTransform();\n    // for (Rsyn::PhysicalPinGeometry phPinGeo : phLibPin.allPinGeometries()) {\n    // TODO: check why multiple PinGeometry on 8t4 inst60849\n    auto phPinGeo = phLibPin.allPinGeometries()[0];\n    for (Rsyn::PhysicalPinLayer phPinLayer : phPinGeo.allPinLayers()) {\n        if (!phPinLayer.hasRectangleBounds()) {\n            log() << \"Warning: pin has no RectangleBounds\" << std::endl;\n            continue;\n        }\n        int layerIdx = phPinLayer.getLayer().getRelativeIndex();\n        for (auto bounds : phPinLayer.allBounds()) {\n            bounds.translate(displacement);\n            bounds = transform.apply(bounds);\n            accessBoxes.emplace_back(layerIdx, getBoxFromRsynBounds(bounds));\n        }\n    }\n}\n\nvoid NetList::init(RsynService& rsynService) {\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"Init NetList ...\" << std::endl;\n    }\n    nets.reserve(rsynService.design.getNumNets());\n    int numPins = 0;\n    for (Rsyn::Net net : rsynService.module.allNets()) {\n        switch (net.getUse()) {\n            case Rsyn::POWER:\n                continue;\n            case Rsyn::GROUND:\n                continue;\n            default:\n                break;\n        }\n        nets.emplace_back(nets.size(), net, rsynService);\n        numPins += nets.back().pinAccessBoxes.size();\n    }\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"The number of nets is \" << nets.size() << std::endl;\n        log() << \"The number of pins is \" << numPins << std::endl;\n        log() << std::endl;\n    }\n}\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/Net.h",
    "content": "#pragma once\n\n#include \"RsynService.h\"\n#include \"GeoPrimitive.h\"\n\nnamespace db {\n\nclass NetBase {\npublic:\n    ~NetBase();\n\n    int idx;\n    Rsyn::Net rsynNet;\n    const std::string& getName() const { return rsynNet.getName(); }\n\n    // pins\n    vector<Rsyn::Pin> rsynPins;\n    vector<vector<BoxOnLayer>> pinAccessBoxes;  // (pinIdx, accessBoxIdx) -> BoxOnLayer\n    unsigned numOfPins() const noexcept { return pinAccessBoxes.size(); }\n    BoxOnLayer getMaxAccessBox(int pinIdx) const;\n\n    // route guides\n    vector<BoxOnLayer> routeGuides;\n    vector<GridBoxOnLayer> gridRouteGuides;\n\n    void print(ostream& os = std::cout) const;\n};\n\nclass Net : public NetBase {\npublic:\n    Net(int i, Rsyn::Net net, RsynService& rsynService);\n\n    // more route guide information\n    vector<int> routeGuideVios;\n    RTrees routeGuideRTrees;\n\n    // for initialization\n    void initPinAccessBoxes(Rsyn::Pin rsynPin,\n                            RsynService& rsynService,\n                            vector<BoxOnLayer>& accessBoxes,\n                            const DBU libDBU);\n    static void getPinAccessBoxes(Rsyn::PhysicalPort phPort, vector<BoxOnLayer>& accessBoxes);\n    static void getPinAccessBoxes(Rsyn::PhysicalLibraryPin phLibPin,\n                                  Rsyn::PhysicalCell phCell,\n                                  vector<BoxOnLayer>& accessBoxes,\n                                  const DBUxy& origin);\n\n    void clearPostRouteResult();\n    void clearResult();\n};\n\nclass NetList {\npublic:\n    vector<Net> nets;\n\n    void init(RsynService& rsynService);\n};\n\n}  // namespace db"
  },
  {
    "path": "src/db/RouteGrid.cpp",
    "content": "#include \"RouteGrid.h\"\n\nnamespace db {\n\nvoid RouteGrid::init() {\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"Init RouteGrid ...\" << std::endl;\n    }\n    LayerList::init();\n    // Fixed metal\n    fixedMetals.resize(layers.size());\n\n    DBU m2Pitch = layers[1].pitch;\n    unitWireCostRaw = db::Setting::weightWirelength / m2Pitch;\n    unitViaCostRaw = db::Setting::weightViaNum;\n    unitViaCost = unitViaCostRaw / unitWireCostRaw;\n\n    unitShortVioCostRaw = db::Setting::weightShortArea;\n\n    // note: a short of M2 track segments will be charged by\n    // (shortLength * unitWireCostRaw) * unitShortVioCost\n    // which should be unitShortVioCostRaw * (shortLength / m2Pitch) * (layers[i].width / m2Pitch)\n    // Therefore, unitShortVioCost = unitShortVioCostRaw * layers[i].width / m2Pitch / m2Pitch / unitWireCostRaw\n    unitShortVioCost.resize(layers.size());\n    for (int i = 0; i < layers.size(); ++i) {\n        unitShortVioCost[i] = unitShortVioCostRaw * layers[i].width / m2Pitch / m2Pitch / unitWireCostRaw;\n    }\n\n    unitShortVioCostDiscounted.resize(unitShortVioCost.size());\n    setUnitVioCost();\n\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        // LayerList::print();\n        log() << \"ROUTE GRID COST\" << std::endl;\n        log() << \"unitWireCostRaw (score / DBU) = \" << unitWireCostRaw << std::endl;\n        log() << \"unitViaCostRaw (score for each via) = \" << unitViaCostRaw << std::endl;\n        log() << \"unitShortVioCostRaw (score for each area of m2Pitch * m2Pitch) = \" << unitShortVioCostRaw\n              << std::endl;\n        log() << \"After normalization by unitWireCostRaw: \" << std::endl;\n        log() << \"unitWireCost (in DBU) = 1\" << std::endl;\n        log() << \"unitViaCost (in DBU) = \" << unitViaCost << std::endl;\n        log() << \"unitShortVioCost (coeff for \\\"normal\\\" short) = \" << unitShortVioCost << std::endl;\n        log() << std::endl;\n    }\n}\n\nvoid RouteGrid::clear() {\n    // Fixed metal\n    fixedMetals.clear();\n}\n\nvoid RouteGrid::setUnitVioCost(double discount) {\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        printlog(\"Set unit vio cost with discount of\", discount);\n    }\n    for (int i = 0; i < unitShortVioCost.size(); ++i) {\n        unitShortVioCostDiscounted[i] = unitShortVioCost[i] * discount;\n    }\n}\n\nint RouteGrid::getFixedMetalVio(const BoxOnLayer& box, int netIdx) const {\n    auto regions = getAccurateMetalRectForbidRegions(box);\n    utils::BoxT<DBU> queryBox = box;\n    queryBox.x.low -= layers[box.layerIdx].fixedMetalQueryMargin;\n    queryBox.x.high += layers[box.layerIdx].fixedMetalQueryMargin;\n    queryBox.y.low -= layers[box.layerIdx].fixedMetalQueryMargin;\n    queryBox.y.high += layers[box.layerIdx].fixedMetalQueryMargin;\n\n    for (const auto& region : regions) {\n        queryBox = queryBox.UnionWith(region);\n    }\n\n    boostBox rtreeQueryBox(boostPoint(queryBox.x.low, queryBox.y.low), boostPoint(queryBox.x.high, queryBox.y.high));\n    vector<std::pair<boostBox, int>> queryResults;\n    fixedMetals[box.layerIdx].query(bgi::intersects(rtreeQueryBox), std::back_inserter(queryResults));\n    vector<std::pair<utils::BoxT<DBU>, int>> neighMetals;\n    for (const auto& queryResult : queryResults) {\n        if (queryResult.second != netIdx) {\n            const auto& b = queryResult.first;\n            neighMetals.emplace_back(utils::BoxT<DBU>(bg::get<bg::min_corner, 0>(b),\n                                                      bg::get<bg::min_corner, 1>(b),\n                                                      bg::get<bg::max_corner, 0>(b),\n                                                      bg::get<bg::max_corner, 1>(b)),\n                                     queryResult.second);\n        }\n    }\n\n    int numOvlp = 0;\n    for (const auto& neighMetal : neighMetals) {\n        // getOvlpFixedMetals\n        for (auto forbidRegion : regions) {\n            auto ovlp = forbidRegion.IntersectWith(neighMetal.first);\n            if (ovlp.IsValid()) {\n                numOvlp += (ovlp.area() > 0);\n            }\n        }\n\n        // getOvlpFixedMetalForbidRegions\n        auto forbidRegions = getAccurateMetalRectForbidRegions({box.layerIdx, neighMetal.first});\n        for (auto forbidRegion : forbidRegions) {\n            auto ovlp = forbidRegion.IntersectWith(box);\n            if (ovlp.IsValid()) {\n                numOvlp += (ovlp.area() > 0);\n            }\n        }\n\n        // getOvlpC2CMetals\n        if (!layers[box.layerIdx].isEolDominated(neighMetal.first)) {\n            DBU space = layers[box.layerIdx].getParaRunSpace(neighMetal.first);\n            numOvlp += (utils::L2Dist(box, neighMetal.first) < space);\n        }\n    }\n    return numOvlp;\n}\n\nDBU RouteGrid::getOvlpFixedMetalArea(const BoxOnLayer& box, int netIdx) const {\n    utils::BoxT<DBU> queryBox = box;\n\n    boostBox rtreeQueryBox(boostPoint(queryBox.x.low, queryBox.y.low), boostPoint(queryBox.x.high, queryBox.y.high));\n    vector<std::pair<boostBox, int>> queryResults;\n    fixedMetals[box.layerIdx].query(bgi::intersects(rtreeQueryBox), std::back_inserter(queryResults));\n    vector<std::pair<utils::BoxT<DBU>, int>> neighMetals;\n    for (const auto& queryResult : queryResults) {\n        if (queryResult.second != netIdx) {\n            const auto& b = queryResult.first;\n            neighMetals.emplace_back(utils::BoxT<DBU>(bg::get<bg::min_corner, 0>(b),\n                                                      bg::get<bg::min_corner, 1>(b),\n                                                      bg::get<bg::max_corner, 0>(b),\n                                                      bg::get<bg::max_corner, 1>(b)),\n                                     queryResult.second);\n        }\n    }\n\n    DBU area = 0;\n    for (const auto& neighMetal : neighMetals) {\n        auto ovlp = queryBox.IntersectWith(neighMetal.first);\n        if (ovlp.IsValid()) area += ovlp.area();\n    }\n    return area;\n}\n\nvector<std::pair<utils::BoxT<DBU>, int>> RouteGrid::getOvlpBoxes(const BoxOnLayer& box,\n                                                                 int idx,\n                                                                 const RTrees& rtrees) const {\n    boostBox queryBox(boostPoint(box.x.low, box.y.low), boostPoint(box.x.high, box.y.high));\n    vector<std::pair<boostBox, int>> queryResults;\n    rtrees[box.layerIdx].query(bgi::intersects(queryBox), std::back_inserter(queryResults));\n    vector<std::pair<utils::BoxT<DBU>, int>> results;\n    for (const auto& queryResult : queryResults) {\n        if (queryResult.second != idx) {\n            const auto& b = queryResult.first;\n            results.emplace_back(utils::BoxT<DBU>(bg::get<bg::min_corner, 0>(b),\n                                                  bg::get<bg::min_corner, 1>(b),\n                                                  bg::get<bg::max_corner, 0>(b),\n                                                  bg::get<bg::max_corner, 1>(b)),\n                                 queryResult.second);\n        }\n    }\n    return results;\n}\n\nvector<std::pair<utils::BoxT<DBU>, int>> RouteGrid::getOvlpFixedMetals(const BoxOnLayer& box, int netIdx) const {\n    return getOvlpBoxes(box, netIdx, fixedMetals);\n}\n\nvoid RouteGrid::markFixedMetalBatch(vector<std::pair<BoxOnLayer, int>>& fixedMetalVec, int beginIdx, int endIdx) {\n    vector<vector<std::pair<boostBox, int>>> fixedMetalsRtreeItems;\n    fixedMetalsRtreeItems.resize(layers.size());\n\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"mark fixed metal batch ...\" << std::endl;\n    }\n    const int initMem = utils::mem_use::get_current();\n\n    vector<vector<int>> layerToObjIdx(getLayerNum());\n    for (unsigned i = beginIdx; i < endIdx; i++) layerToObjIdx[fixedMetalVec[i].first.layerIdx].push_back(i);\n\n    int curLayer = 0;\n    std::mutex layer_mutex;\n\n    auto thread_func = [&]() {\n        while (true) {\n            layer_mutex.lock();\n            int l = curLayer++;\n            layer_mutex.unlock();\n\n            if (l >= getLayerNum()) return;\n\n            for (auto idx : layerToObjIdx[l]) {\n                // fixedMetals\n                const BoxOnLayer& box = fixedMetalVec[idx].first;\n                int netIdx = fixedMetalVec[idx].second;\n\n                boostBox markBox(boostPoint(box.x.low, box.y.low), boostPoint(box.x.high, box.y.high));\n                fixedMetalsRtreeItems[box.layerIdx].push_back({markBox, netIdx});\n\n                DBU space = layers[box.layerIdx].getParaRunSpace(box);\n                if (space > layers[box.layerIdx].fixedMetalQueryMargin) {\n                    layers[box.layerIdx].fixedMetalQueryMargin = space;\n                }\n            }\n        }\n    };\n\n    const int numThreads = max(1, db::setting.numThreads);\n    std::thread threads[numThreads];\n    for (int i = 0; i < numThreads; i++) threads[i] = std::thread(thread_func);\n    for (int i = 0; i < numThreads; i++) threads[i].join();\n\n    const int curMem = utils::mem_use::get_current();\n    if (setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        printflog(\"MEM(MB): init/cur=%d/%d, incr=%d\\n\", initMem, curMem, curMem - initMem);\n        log() << std::endl;\n    }\n\n    if (!beginIdx) {\n        for (int layerIdx = 0; layerIdx < layers.size(); layerIdx++) {\n            RTree tRtree(fixedMetalsRtreeItems[layerIdx]);\n            fixedMetals[layerIdx] = boost::move(tRtree);\n        }\n    } else {\n        for (int layerIdx = 0; layerIdx < layers.size(); layerIdx++) {\n            for (auto& item : fixedMetalsRtreeItems[layerIdx]) fixedMetals[layerIdx].insert(item);\n        }\n    }\n}\n}  // namespace db\n"
  },
  {
    "path": "src/db/RouteGrid.h",
    "content": "#pragma once\n\n#include \"LayerList.h\"\n#include \"Net.h\"\n#include \"Setting.h\"\n\nnamespace db {\n\nclass ViaData;\n\nusing CostT = double;\n\nstruct mutex_wrapper : std::mutex {\n    mutex_wrapper() = default;\n    mutex_wrapper(mutex_wrapper const&) noexcept : std::mutex() {}\n    bool operator==(mutex_wrapper const& other) noexcept { return this == &other; }\n};\n\n// net index\n// a valid net idx >= 0\nconst int OBS_NET_IDX = -1;   // for obstacles\nconst int NULL_NET_IDX = -2;  // for neither net nor obstacle\n\nclass RouteGrid : public LayerList {\npublic:\n    using ViaMapT = vector<vector<std::multimap<int, int>>>;\n    using NDViaMapT = std::unordered_map<GridPoint, const ViaType*>;\n\n    void init();\n    void clear();\n    void setUnitVioCost(double discount = 1.0);\n\n    // Query fixed metals\n    vector<std::pair<utils::BoxT<DBU>, int>> getOvlpBoxes(const BoxOnLayer& box, int idx, const RTrees& rtree) const;\n    vector<std::pair<utils::BoxT<DBU>, int>> getOvlpFixedMetals(const BoxOnLayer& box, int netIdx) const;\n\n    int getFixedMetalVio(const BoxOnLayer& box, int netIdx) const;\n    DBU getOvlpFixedMetalArea(const BoxOnLayer& box, int netIdx) const;\n\n    void markFixedMetalBatch(vector<std::pair<BoxOnLayer, int>>& fixedMetalVec, int beginIdx, int endIdx);\n    const RTree& getFixedMetals(int layerIdx) const { return fixedMetals[layerIdx]; }\n\n    DBU getUnitViaCost() const { return unitViaCost; }\n    DBU getUnitShortCost(int layerIdx) const { return unitShortVioCostDiscounted[layerIdx]; }\n\nprotected:\n    // Unit cost\n    // in contest metric\n    CostT unitWireCostRaw;                                       // for each DBU\n    CostT unitViaCostRaw;                                        // for each occurrence\n    CostT unitShortVioCostRaw;                                   // for each area of m2Pitch * m2Pitch\n    vector<CostT> unitShortVioCost, unitShortVioCostDiscounted;  // ceoff (no unit), a M2 short will charged by\n                                                                 // (shortLength * unitWireCostRaw) * unitShortVioCost\n    // in DBU\n    CostT unitViaCost;  // for each occurrence\n\n    // Fixed metals (e.g., cell pins, blockage)\n    RTrees fixedMetals;  // box -> netIdx\n};\n\n}  //   namespace db\n"
  },
  {
    "path": "src/db/RsynService.h",
    "content": "#pragma once\n\n#include \"global.h\"\n\nnamespace db {\n\nclass RsynService {\npublic:\n    Rsyn::PhysicalService* physicalService;\n    // Rsyn::RoutingGuide* routeGuideService;\n    Rsyn::PhysicalDesign physicalDesign;\n    Rsyn::Design design;\n    Rsyn::Module module;\n\n    void init() {\n        Rsyn::Session session;\n\n        physicalService = session.getService(\"rsyn.physical\");\n        // routeGuideService = session.getService(\"rsyn.routingGuide\");\n\n        physicalDesign = physicalService->getPhysicalDesign();\n        design = session.getDesign();\n        module = design.getTopModule();\n    }\n};\n\n}"
  },
  {
    "path": "src/db/Setting.cpp",
    "content": "#include \"Setting.h\"\n#include \"Database.h\"\n\nnamespace db {\n\nvoid Setting::makeItSilent() {\n    multiNetVerbose = VerboseLevelT::LOW;\n    dbVerbose = VerboseLevelT::LOW;\n}\n\nvoid Setting::adapt() {\n    if (database.nets.size() > 800000) {\n         --rrrIterLimit;\n    \n    }\n}\n\nSetting setting;\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/Setting.h",
    "content": "#pragma once\n\n#include \"global.h\"\n\nnamespace db {\n\nBETTER_ENUM(VerboseLevelT, int, LOW = 0, MIDDLE = 1, HIGH = 2);\n\n// global setting\nclass Setting {\npublic:\n    // basic\n    std::string outputFile;\n    std::string name;\n    int numThreads = 1;  // 0 for simple scheduling\n    int tat = std::numeric_limits<int>::max();\n\n    // multi_net\n    VerboseLevelT multiNetVerbose = VerboseLevelT::MIDDLE;\n    bool multiNetScheduleSortAll = true;\n    bool multiNetScheduleSort = true;\n    bool multiNetScheduleReverse = true;\n    int multiNetSelectViaTypesIter = 3;\n    int rrrIterLimit = 4;\n    bool rrrWriteEachIter = false;\n    double rrrInitVioCostDiscount = 0.1;\n    double rrrFadeCoeff = 0.01;  // should be <= 0.5 to make sure fade/(1-fade) <= 1\n\n    int edgeShiftingIter = 2;\n\n    // single_net\n    VerboseLevelT singleNetVerbose = VerboseLevelT::MIDDLE;\n    bool fixOpenBySST = true;\n    double unitSqrtViaUsage = 1.5;   // # of tracks that unit sqrt(via) uses\n    double initLogisticSlope = 1.0;  // the slope of the logistic func in cost func\n\n    // db\n    VerboseLevelT dbVerbose = VerboseLevelT::MIDDLE;\n    int maxNumWarnForEachRouteStatus = 5;\n    bool dbWriteDebugFile = false;\n    double dbInitHistUsageForPinAccess = 0.1;\n\n    //  Metric weights of ISPD 2018 Contest\n    //  Wirelength unit is M2 pitch\n    //  1. basic objective\n    static constexpr double weightWirelength = 0.5;\n    static constexpr int weightViaNum = 4;\n    //  2. routing preference\n    static constexpr int weightOutOfGuideWirelength = 1;\n    static constexpr int weightOutOfGuideViaNum = 1;\n    static constexpr double weightOffTrackWirelength = 0.5;\n    static constexpr int weightOffTrackViaNum = 1;\n    static constexpr int weightWrongWayWirelength = 1;\n    static constexpr int wirelenCostWeight = 4;\n\n    //  3. violation\n    //  normalized by square of M2 pitch\n    static constexpr int weightShortArea = 500;\n    //  including wire spacing, eol spacing, cut spacing\n    static constexpr int weightSpaceVioNum = 500;\n    static constexpr int weightMinAreaVioNum = 500;\n\n    void makeItSilent();\n    void adapt();\n};\n\nextern Setting setting;\n\n}  //   namespace db\n"
  },
  {
    "path": "src/db/Stat.cpp",
    "content": "#include \"Stat.h\"\n#include \"Setting.h\"\n\nnamespace db {\n\nRouteStat routeStat;\n\nRouteStatus operator&(const RouteStatus& lhs, const RouteStatus& rhs) {\n    for (auto status : {lhs, rhs}) {\n        if (!isSucc(status)) {\n            return status;\n        }\n    }\n    for (auto status : {lhs, rhs}) {\n        if (status != +RouteStatus::SUCC_NORMAL) {\n            return status;\n        }\n    }\n    return RouteStatus::SUCC_NORMAL;\n}\n\nRouteStatus& operator&=(RouteStatus& lhs, const RouteStatus& rhs) {\n    lhs = lhs & rhs;\n    return lhs;\n}\n\nstd::unordered_map<int, std::string> descriptions = {\n    {(+db::RouteStatus::FAIL_PIN_OUT_OF_GRID)._to_integral(), \"has pin not on grid, skip\"},\n    {(+db::RouteStatus::FAIL_DETACHED_GUIDE)._to_integral(), \"has route guide detached from others, skip\"},\n    {(+db::RouteStatus::FAIL_DETACHED_PIN)._to_integral(),\n     \"has pin detached from route guides, cannot fix by expanding route guides\"},\n    {(+db::RouteStatus::FAIL_CONN_EXT_PIN)._to_integral(),\n     \"has unconnected pin due to access box inflation, cannot fix by add linking wire\"},\n    {(+db::RouteStatus::FAIL_DISCONNECTED_GRID_GRAPH)._to_integral(), \"has disconnected grid graph, skip\"}};\n\nstd::mutex printWarnMsgMutex;\n\nvoid printWarnMsg(RouteStatus status, const Net& net) {\n    if (setting.dbVerbose < +db::VerboseLevelT::MIDDLE || isSucc(status)) {\n        return;\n    }\n    printWarnMsgMutex.lock();\n    static std::unordered_map<int, int> counts;\n    int& count = counts[status._to_integral()];\n    if (count >= db::setting.maxNumWarnForEachRouteStatus) {\n        printWarnMsgMutex.unlock();\n        return;\n    }\n    std::string desc;\n    auto it = descriptions.find(status._to_integral());\n    if (it != descriptions.end()) {\n        desc = \" (\" + it->second + \")\";\n    }\n    log() << \"Warning: Net \" << net.getName() << \" gets \" << status._to_string() << desc << std::endl;\n    ++count;\n    if (count == db::setting.maxNumWarnForEachRouteStatus) {\n        log() << \"More warnings on \" << status._to_string() << \" will be suppressed\" << std::endl;\n        log() << std::endl;\n    }\n    printWarnMsgMutex.unlock();\n}\n\nvoid StageRouteStat::clear() {\n    allNetStatusCounters.clear();\n    miscEventCounters.clear();\n}\n\nstd::mutex stageRouteStatusMutex;\nstd::mutex miscEventMutex;\n\nvoid StageRouteStat::increment(RouteStatus status) {\n    stageRouteStatusMutex.lock();\n    ++allNetStatusCounters[status._to_integral()];\n    stageRouteStatusMutex.unlock();\n}\n\nvoid StageRouteStat::increment(MiscRouteEvent misc, int count) {\n    miscEventMutex.lock();\n    miscEventCounters[misc._to_integral()] += count;\n    miscEventMutex.unlock();\n}\n\nvoid StageRouteStat::print(const std::string& stageStr) const {\n    // allNetStatusCounters\n    int numTotal = 0, numSucc = 0;\n    iterateEnumCountersInOrder<RouteStatus, int>(allNetStatusCounters, [&](RouteStatus status, int count) {\n        numTotal += count;\n        if (isSucc(status)) {\n            numSucc += count;\n        }\n    });\n    int numFail = numTotal - numSucc;\n    log() << stageStr << \": #nets = \" << numTotal << std::endl;\n    log() << \"\\t#succ = \" << numSucc << \" (\";\n    int i = 0;\n    iterateEnumCountersInOrder<RouteStatus, int>(allNetStatusCounters, [&](RouteStatus status, int count) {\n        if (isSucc(status)) {\n            std::cout << \"#\" << status << \" = \" << count << \" \";\n        }\n        ++i;\n    });\n    std::cout << \")\" << std::endl;\n    if (numFail > 0) {\n        log() << \"\\t#fail = \" << numFail << \" (\";\n        i = 0;\n        iterateEnumCountersInOrder<RouteStatus, int>(allNetStatusCounters, [&](RouteStatus status, int count) {\n            if (!isSucc(status)) {\n                std::cout << \"#\" << status << \" = \" << count << \" \";\n            }\n            ++i;\n        });\n        std::cout << \")\" << std::endl;\n    }\n\n    // miscEventCounters\n    if (!miscEventCounters.empty()) {\n        log() << \"\\tmisc (\";\n        iterateEnumCountersInOrder<MiscRouteEvent, int>(miscEventCounters, [&](MiscRouteEvent event, int count) {\n            std::cout << \"#\" << event << \" = \" << count << \" \";\n        });\n        std::cout << \")\" << std::endl;\n    }\n}\n\nvoid RouteStat::clear() { stages.clear(); }\n\nvoid RouteStat::print() const {\n    iterateEnumCountersInOrder<RouteStage, StageRouteStat>(stages, [](RouteStage stage, StageRouteStat stageStat) {\n        stageStat.print(\"Stage \" + std::string(stage._to_string()));\n    });\n}\n\n}  // namespace db\n"
  },
  {
    "path": "src/db/Stat.h",
    "content": "#pragma once\n\n#include \"Net.h\"\n#include \"global.h\"\n\nnamespace db {\n\nBETTER_ENUM(RouteStatus,\n            int,\n            // 1. Succ\n            SUCC_NORMAL,\n            // 1.1 pre-route\n            SUCC_ONE_PIN,\n            // 1.2 post-route\n            SUCC_CONN_EXT_PIN,\n            // 2. Fail\n            // 2.0\n            FAIL_UNPROCESSED,\n            // 2.1 pre route\n            FAIL_PIN_OUT_OF_GRID,\n            FAIL_DETACHED_GUIDE,\n            FAIL_DETACHED_PIN,\n            // 2.2 maze route\n            FAIL_DISCONNECTED_GRID_GRAPH,\n            // 2.3 post route\n            FAIL_CONN_EXT_PIN);\n\nBETTER_ENUM(MiscRouteEvent,\n            int,\n            // pre route\n            ADD_DIFF_LAYER_GUIDE_1,\n            ADD_DIFF_LAYER_GUIDE_2,\n            FIX_DETACHED_PIN,\n            // post maze route\n            MIN_AREA_VIO,\n            MIN_AREA_SHADOWED_VIO,\n            REMOVE_TRACK_SWITCH_PIN,\n            REMOVE_TRACK_SWITCH_NORMAL,\n            REMOVE_TRACK_SWITCH_HORSESHOE,\n            // post route\n            LINK_PIN_VIO,\n            FILL_SAME_NET_SPACE,\n            REMOVE_CORNER);\n\nBETTER_ENUM(RouteStage, int, INIT, MAZE, ALL);\n\ntemplate <typename EnumT, typename MappedT>\nvoid iterateEnumCountersInOrder(const std::unordered_map<int, MappedT>& counters,\n                                const std::function<void(EnumT, MappedT)>& handle) {\n    for (EnumT enumType : EnumT::_values()) {\n        auto it = counters.find(enumType._to_integral());\n        if (it != counters.end()) {\n            handle(EnumT::_from_integral(it->first), it->second);\n        }\n    }\n}\n\n// switch syntax is not supported by gcc 5 ...\nconstexpr bool isSucc(RouteStatus status) {\n    return status == +RouteStatus::SUCC_NORMAL || status == +RouteStatus::SUCC_ONE_PIN ||\n           status == +RouteStatus::SUCC_CONN_EXT_PIN;\n}\n\n// constexpr auto succ = better_enums::make_map(isSucc);  // more efficient if many\n\nRouteStatus operator&(const RouteStatus& lhs, const RouteStatus& rhs);\nRouteStatus& operator&=(RouteStatus& lhs, const RouteStatus& rhs);\n\nvoid printWarnMsg(RouteStatus status, const Net& net);\n\nclass StageRouteStat {\npublic:\n    void clear();\n    void increment(RouteStatus status);\n    void increment(MiscRouteEvent misc, int count);\n    void print(const std::string& stageStr) const;\n\nprivate:\n    std::unordered_map<int, int> allNetStatusCounters;\n    std::unordered_map<int, int> miscEventCounters;\n};\n\nclass RouteStat {\npublic:\n    template <typename... Args>\n    void increment(RouteStage stage, Args... params) {\n        routeStatusMutex.lock();\n        stages[stage._to_integral()].increment(params...);\n        routeStatusMutex.unlock();\n    }\n    void clear();\n    void print() const;\n\nprivate:\n    std::unordered_map<int, StageRouteStat> stages;\n    std::mutex routeStatusMutex;\n};\n\nextern RouteStat routeStat;\n\n}  // namespace db\n"
  },
  {
    "path": "src/flute/ChangeLog.txt",
    "content": "Version 1.0 [Apr. 2004]\n * Wirelength estimation based on the idea of ICCAD 04 paper.\n\nVersion 2.0 [Feb. 16, 2005]\n * RSMT construction and Wirelength estimation based on the idea of ISPD\n   05 paper.\n\nVersion 2.1 [Mar. 18, 2005]\n * The program flute-ckt and associated files are added to compute the\n   FLUTE wirelength for a circuit in bookshelf format.\n\nVersion 2.2 [Oct. 16, 2005]  \n * The net breaking technique is improved by incorporating the HPWL based\n   estimation in ICCAD 04 paper.\n * The option to remove duplicated pins is added.\n * The code is reorganized.\n\nVersion 2.3 [Sep. 23, 2006]  \n * PORT is renamed to POST (Potentially Optimal Steiner Tree)\n * The function readLUT() is rewritten to significantly cut the POWV \n   and POST reading time.\n\nVersion 2.4 [Jan. 16, 2007]  \n * Internal parameters of flutes_wl_MD() and flutes_MD() are tuned to\n   improve runtime-quality tradeoff.\n * The file size of POST9.dat is reduced by improved encoding.\n * The function readLUT() is improved to speed up the reading of POST9.dat.\n * Bookshelf files for ibm01 is included to demonstrate program flute-ckt.\n\nVersion 2.5 [Jun. 20, 2007] \n * Local refinement technique is added to improve runtime-accuracy\n   tradeoff for high accuracy.\n\nVersion 3.0 [Apr. 10, 2008]\n * Implemented the net breaking and merging ideas of VLSIDAT 08 paper to\n   achieve much better scalability and accuracy for high-degree nets.\n\nVersion 3.1 [Feb. 28, 2011]\n * Functions in bookshelf_IO.c and memAlloc.c used by flute-ckt are\n   improved to speed up the reading of GSRC Bookshelf format circuits.\n"
  },
  {
    "path": "src/flute/Readme",
    "content": "-------------- FLUTE - Version 3.1 -----------------\n                       by\n                Chris C.-N. Chu\n       Dept. of ECpE, Iowa State University\n             Copyright (c) - 2005\n  Iowa State University Research Foundation, Inc.\n----------------------------------------------------\n\nThis package contains the following files:\n\n flute.c -- The rectilinear Steiner minimal tree and wirelength estimation\n\t    algorithm described in the ICCAD 04 and ISPD 05 papers with\n\t    some improvements described in TCAD 07 paper.\n flute.h -- The interface to use flute.\n flute_mst.c -- The net breaking and merging techniques described in the\n\t    VLSIDAT 08 paper.\n dist.[ch], dl.[ch], err.[ch], heap.[ch], mst2.[ch], neighbors.[ch],\n\t    global.h -- Utility functions used by flute_mst.c\n POWV9.dat -- The lookup-table of optimal POWVs up to degree 9.\n POST9.dat -- The lookup-table for optimal Steiner trees up to degree 9.\n flute-net.c -- A program to evaluate the wirelength of a net. It takes\n\t    input from stdin as a list of points.\n rand-pts.c -- A program to generate a list of random points.\n flute-ckt.c -- A program to find FLUTE and half-perimeter wirelength\n\t    of a circuit in bookshelf format.\n bookshelf_IO.[ch] -- Functions for flute-ckt.c to read bookshelf files.\n memAlloc.[ch] -- Functions for flute-ckt.c to allocate memory.\n ibm01/ibm01.* -- ibm01 bookshelf files that can be read by flute-ckt.c\n license.txt -- License agreement.\n ChangeLog.txt\n Makefile\n Readme\n\nTo run the programs, first do a 'make'. POWV9.dat and POST9.dat is assume\nto be in the current directory.  Some example commands:\n\n rand-pts | flute-net\n rand-pts 20 | flute-net\t    // 20-pin nets\n rand-pts -r 20 | flute-net\t    // randomized\n flute-ckt ibm01 ibm01.aux ibm01/ibm01.pl\n"
  },
  {
    "path": "src/flute/dist.c",
    "content": "#include \"global.h\"\n\n/*********************************************************************/\n/*\n   Return the Manhattan distance between two points\n*/\n\nlong  dist(\n  Point  p,\n  Point  q\n)\n{\n  long  dx, dy;\n    \n  dx = (p.x) - (q.x);\n  if( dx < 0 )  dx = -dx;\n  dy = (p.y) - (q.y);\n  if( dy < 0 )  dy = -dy;\n\n  return  dx + dy; \n}\n\n/*********************************************************************/\n/*\n   Return the Manhattan distance between two points\n*/\n\nlong  dist2(\n  Point*  p,\n  Point*  q\n)\n{\n  long  dx, dy;\n    \n  dx = (p->x) - (q->x);\n  if( dx < 0 )  dx = -dx;\n  dy = (p->y) - (q->y);\n  if( dy < 0 )  dy = -dy;\n\n  return  dx + dy; \n}\n\n/*********************************************************************/\n/*********************************************************************/\n"
  },
  {
    "path": "src/flute/dist.h",
    "content": "#ifndef _DIST_H_\n#define _DIST_H_\n\n#include \"global.h\"\n\nlong  dist(\n  Point  p,\n  Point  q\n);\n\nlong  dist2(   \n  Point*  p,\n  Point*  q\n);\n\n#endif\n"
  },
  {
    "path": "src/flute/dl.c",
    "content": "#include \"dl.h\"\n#include <assert.h>\n#include <stdio.h>\n\ndl_t dl_alloc()\n{\n  dl_t dl = (dl_t)malloc(sizeof(dl_s));\n  if (!dl) {\n      printf(\"Out of memory!!\\n\");\n  } else {\n    dl->first = dl->last = 0; dl->count = 0;\n  }\n  return dl;\n}\n\nvoid dl_delete(dl_t dl, dl_el *el)\n{\n  if (dl->first == el) {\n    dl->first = el->next;\n  }\n  if (dl->last == el) {\n    dl->last = el->prev;\n  }\n  if (el->next) {\n    el->next->prev = el->prev;\n  }\n  if (el->prev) {\n    el->prev->next = el->next;\n  }\n  free(el); dl->count--;\n}\n\nvoid dl_clear(dl_t dl)\n{\n  dl_el *el, *next;\n  if (dl->count > 0) {\n    for (el=dl->first; el; el=next) {\n      next = el->next;\n      free(el);\n    }\n  }\n  dl->first = dl->last = 0;\n  dl->count = 0;\n}\n\nvoid dl_concat(dl_t first_list, dl_t second_list)\n{\n  if (first_list->count <= 0) {\n    *first_list = *second_list;\n  } else if (second_list->count > 0) {\n    first_list->last->next = second_list->first;\n    second_list->first->prev = first_list->last;\n    first_list->last = second_list->last;\n    first_list->count += second_list->count;\n  }\n\n  free(second_list);\n}\n\nstatic void dl_insertion_sort(dl_t dl, size_t el_size,\n\t\t\t      int(*compar)(void *, void *))\n{\n  char *buf;\n  void *curr_d, *srch_d;\n  dl_el *curr, *srch;\n\n  if (dl_length(dl) <= 1) {\n    return;\n  }\n\n  buf = (char*)malloc(el_size);\n\n  for (curr=dl->first; curr!=dl->last; curr=curr->next) {\n    curr_d = (void*)(((dl_el*)curr)+1);\n\n    for (srch=dl->last; srch!=curr; srch=srch->prev) {\n      srch_d = (void*)(((dl_el*)srch)+1);\n      if (compar(curr_d, srch_d) > 0) {\n\tmemcpy((void*)buf, curr_d, el_size);\n\tmemcpy(curr_d, srch_d, el_size);\n\tmemcpy(srch_d, (void*)buf, el_size);\n      }\n    }\n  }\n\n\n  free(buf);\n}\n\nvoid dl_sort(dl_t dl, size_t el_size, int(*compar)(void *, void *))\n{\n  dl_el *el, *first_head, *second_head;\n  dl_s first_list, second_list;\n  void *first_item, *second_item;\n  int i, len;\n\n  if (dl_length(dl) <= 25) {\n    dl_insertion_sort(dl, el_size, compar);\n    return;\n  }\n\n  len = dl_length(dl)/2;\n  for (i=0, el=dl->first; i<len; i++) {\n    el = el->next;\n  }\n\n  first_list.first = dl->first;\n  first_list.last = el->prev;\n  first_list.count = len;\n  first_list.last->next = 0;\n\n  second_list.first = el;\n  second_list.last = dl->last;\n  second_list.count = dl_length(dl)-len;\n  second_list.first->prev = 0;\n\n  dl_sort(&first_list, el_size, compar);\n  dl_sort(&second_list, el_size, compar);\n\n  /* in-place merging */\n  first_head = first_list.first;\n  second_head = second_list.first;\n\n  first_item = (void*)(((dl_el*)first_head)+1);\n  second_item = (void*)(((dl_el*)second_head)+1);\n  if (compar(first_item, second_item) <= 0) {\n    dl->first = el = first_head;\n    first_head = first_head->next;\n  } else {\n    dl->first = el = second_head;\n    second_head = second_head->next;\n  }\n\n  while (1) {\n    first_item = (void*)(((dl_el*)first_head)+1);\n    second_item = (void*)(((dl_el*)second_head)+1);\n    if (compar(first_item, second_item) <= 0) {\n      el->next = first_head;\n      first_head->prev = el;\n      el = first_head;\n      first_head = first_head->next;\n      if (!first_head) {\n\tel->next = second_head;\n\tsecond_head->prev = el;\n\tdl->last = second_list.last;\n\tbreak;\n      }\n    } else {\n      el->next = second_head;\n      second_head->prev = el;\n      el = second_head;\n      second_head = second_head->next;\n      if (!second_head) {\n\tel->next = first_head;\n\tfirst_head->prev = el;\n\tdl->last = first_list.last;\n\tbreak;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/flute/dl.h",
    "content": "#ifndef DL_H\n#define DL_H\n\n#include <string.h>\n#include <stdlib.h>\n\ntypedef struct dl_el_s {\n  struct dl_el_s *prev, *next;\n} dl_el;\n\ntypedef struct {\n  dl_el *first, *last;\n  unsigned int count;\n} dl_s, *dl_t;\n\ndl_t dl_alloc(void);\nvoid dl_delete(dl_t dl, dl_el *el);\nvoid dl_clear(dl_t dl);\nvoid dl_concat(dl_t list1, dl_t list2);\nvoid dl_sort(dl_t dl, size_t el_size, int(*compar)(void *, void *));\n\n#define dl_length(dl) (dl)->count\n\n#define dl_empty(dl) ((dl)->count <= 0)\n\n#define dl_data(type, el) \\\n  *(type*)(((dl_el*)(el))+1)\n\n#define dl_data_p(type, el) \\\n  ((type*)(((dl_el*)(el))+1))\n\n#define dl_forall(type, dl, data) \\\n{ \\\n  dl_el *_el, *_next; \\\n  dl_t _curr_dl = (dl); \\\n  for (_el=_curr_dl->first; _el; _el=_next) { \\\n    _next = _el->next; \\\n    (data) = dl_data(type, _el);\n\n#define dl_forall_p(type, dl, data_p) \\\n{ \\\n  dl_el *_el, *_next; \\\n  dl_t _curr_dl = (dl); \\\n  for (_el=_curr_dl->first; _el; _el=_next) { \\\n    _next = _el->next; \\\n    (data_p) = dl_data_p(type, _el);\n\n#define dl_current() _el\n#define dl_delete_current() dl_delete(_curr_dl, _el)\n\n#define dl_endfor \\\n  } \\\n}\n\n#define dl_forall_reverse(type, dl, data) \\\n{ \\\n  dl_el *_el, *_next; \\\n  dl_t _curr_dl = (dl); \\\n  for (_el=_curr_dl->last; _el; _el=_next) { \\\n    _next = _el->prev; \\\n    (data) = dl_data(type, _el);\n\n#define dl_forall_reverse_p(type, dl, data_p) \\\n{ \\\n  dl_el *_el, *_next; \\\n  dl_t _curr_dl = (dl); \\\n  for (_el=_curr_dl->last; _el; _el=_next) { \\\n    _next = _el->prev; \\\n    (data_p) = dl_data_p(type, _el);\n\n#define dl_first(type, dl) \\\n  dl_data(type, (dl)->first)\n\n      \n#define dl_first_element(dl) (dl)->first \n\n      \n#define dl_last(type, dl) \\\n  dl_data(type, (dl)->last)\n\n#define dl_pop_first(type, dl, data) \\\n{ \\\n  (data) = dl_first(type, dl); \\\n  dl_delete((dl), (dl)->first); \\\n}\n\n#define dl_pop_last(type, dl, data) \\\n{ (data) = dl_last(type, dl);  dl_delete((dl), (dl)->last); }\n\n#define dl_insert_before(type, dl, element, data) \\\n{ \\\n  if ((element) == (dl)->first) { \\\n    dl_prepend(type, dl, data); \\\n  } else { \\\n    dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \\\n    if (!_el) { \\\n      printf(\"Out of memory!!\\n\"); \\\n    } else { \\\n      memcpy(_el+1, &(data), sizeof(type)); \\\n      _el->prev = (element)->prev; _el->next = (element); \\\n      (element)->prev->next = _el; (element)->prev = _el; \\\n      (dl)->count++; \\\n    } \\\n  } \\\n}\n\n#define dl_insert_after(type, dl, element, data) \\\n{ \\\n  if ((element) == (dl)->last) { \\\n    dl_append(type, dl, data); \\\n  } else { \\\n    dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \\\n    if (!_el) { \\\n\tprintf(\"Out of memory!!\\n\"); \\\n    } else { \\\n      memcpy(_el+1, &(data), sizeof(type)); \\\n      _el->next = (element)->next; _el->prev = (element); \\\n      (element)->next->prev = _el; (element)->next = _el; \\\n      (dl)->count++; \\\n    } \\\n  } \\\n}\n\n#define dl_append(type, dl, data) \\\n{ \\\n  dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \\\n  if (!_el) { \\\n      printf(\"Out of memory!!\\n\"); \\\n  } else { \\\n    memcpy(_el+1, &(data), sizeof(type)); \\\n    _el->next = 0; \\\n    if ((dl)->count <= 0) { \\\n      _el->prev = 0; \\\n      (dl)->first = (dl)->last = _el; \\\n      (dl)->count = 1; \\\n    } else { \\\n      _el->prev = (dl)->last; \\\n      (dl)->last->next = _el; \\\n      (dl)->last = _el; \\\n      (dl)->count++; \\\n    } \\\n  } \\\n}\n\n#define dl_prepend(type, dl, data) \\\n{ \\\n  dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \\\n  if (!_el) { \\\n    printf(\"Out of memory!!\\n\"); \\\n  } else { \\\n    memcpy(_el+1, &(data), sizeof(type)); \\\n    _el->prev = 0; \\\n    if ((dl)->count <= 0) { \\\n      _el->next = 0; \\\n      (dl)->first = (dl)->last = _el; \\\n      (dl)->count = 1; \\\n    } else { \\\n      _el->next = (dl)->first; \\\n      (dl)->first->prev = _el; \\\n      (dl)->first = _el; \\\n      (dl)->count++; \\\n    } \\\n  } \\\n} \n\n#define dl_free(dl) \\\n{ \\\n  dl_clear(dl);  free(dl);  dl = 0; \\\n}\n\n#define dl_duplicate(dest, src, type) \\\n{ \\\n  dest = dl_alloc(); \\\n  type _data_el; \\\n  dl_forall(type, src, _data_el) { \\\n    dl_append(type, dest, _data_el); \\\n  } dl_endfor; \\\n}\n\n#endif\n"
  },
  {
    "path": "src/flute/err.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n\n/**************************************************************************/\n/*\n  print error message and continue\n*/\n\nvoid  err_msg(\nchar* msg\n)\n{\n  fprintf(stderr, \"%s\\n\", msg);\n}\n\n/**************************************************************************/\n/*\n  print error message and  exit\n*/\n\nvoid  err_exit(\nchar* msg\n)\n{\n  fprintf(stderr, \"%s\\n\", msg);\n  exit(1);\n}\n\n"
  },
  {
    "path": "src/flute/err.h",
    "content": "#ifndef _ERR_H_\n#define _ERR_H_\n\nvoid  err_msg(\nchar* msg\n);\n\nvoid  err_exit(\nchar* msg\n);\n\n#endif\n"
  },
  {
    "path": "src/flute/flute.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <limits.h>\n#include <math.h>\n#include \"flute.h\"\n\n#if D<=7\n#define MGROUP 5040/4  // Max. # of groups, 7! = 5040\n#define MPOWV 15  // Max. # of POWVs per group\n#elif D==8\n#define MGROUP 40320/4  // Max. # of groups, 8! = 40320\n#define MPOWV 33  // Max. # of POWVs per group\n#elif D==9\n#define MGROUP 362880/4  // Max. # of groups, 9! = 362880\n#define MPOWV 79  // Max. # of POWVs per group\n#endif\nint numgrp[10]={0,0,0,0,6,30,180,1260,10080,90720};\n\nstruct csoln\n{\n    unsigned char parent;\n    unsigned char seg[11];  // Add: 0..i, Sub: j..10; seg[i+1]=seg[j-1]=0\n    unsigned char rowcol[D-2];  // row = rowcol[]/16, col = rowcol[]%16,\n    unsigned char neighbor[2*D-2];\n};\nstruct csoln *LUT[D+1][MGROUP];  // storing 4 .. D\nint numsoln[D+1][MGROUP];\n\nstruct point\n{\n    DTYPE x, y;\n    int o;\n};\n\nvoid readLUT();\nDTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc);\nDTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[]);\nDTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nDTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nTree flute(int d, DTYPE x[], DTYPE y[], int acc);\nTree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[]);\nTree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nTree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nTree dmergetree(Tree t1, Tree t2);\nTree hmergetree(Tree t1, Tree t2, int s[]);\nTree vmergetree(Tree t1, Tree t2);\nvoid local_refinement(Tree *tp, int p);\nDTYPE wirelength(Tree t);\nvoid printtree(Tree t);\nvoid plottree(Tree t);\n\nvoid readLUT()\n{\n    unsigned char charnum[256], line[32], *linep, c;\n    FILE *fpwv, *fprt;\n    struct csoln *p;\n    int d, i, j, k, kk, ns, nn;\n\n    init_param();\n\n    for (i=0; i<=255; i++) {\n        if ('0'<=i && i<='9')\n            charnum[i] = i - '0';\n        else if (i>='A')\n            charnum[i] = i - 'A' + 10;\n        else // if (i=='$' || i=='\\n' || ... )\n            charnum[i] = 0;\n    }\n\n    fpwv=fopen(POWVFILE, \"r\");\n    if (fpwv == NULL) {\n        printf(\"Error in opening %s\\n\", POWVFILE);\n        exit(1);\n    }\n\n#if ROUTING==1\n    fprt=fopen(POSTFILE, \"r\");\n    if (fprt == NULL) {\n        printf(\"Error in opening %s\\n\", POSTFILE);\n        exit(1);\n    }\n#endif\n\n    int status_code; // useles, just to stop compile warning\n    for (d=4; d<=D; d++) {\n        status_code = fscanf(fpwv, \"d=%d\\n\", &d);\n#if ROUTING==1\n        status_code = fscanf(fprt, \"d=%d\\n\", &d);\n#endif\n        for (k=0; k<numgrp[d]; k++) {\n            ns = (int) charnum[fgetc(fpwv)];\n\n            if (ns==0) {  // same as some previous group\n                status_code = fscanf(fpwv, \"%d\\n\", &kk);\n                numsoln[d][k] = numsoln[d][kk];\n                LUT[d][k] = LUT[d][kk];\n            }\n            else {\n                fgetc(fpwv);  // '\\n'\n                numsoln[d][k] = ns;\n                p = (struct csoln*) malloc(ns*sizeof(struct csoln));\n                LUT[d][k] = p;\n                for (i=1; i<=ns; i++) {\n                    linep = (unsigned char *) fgets((char *) line, 32, fpwv);\n                    p->parent = charnum[*(linep++)];\n                    j = 0;\n                    while ((p->seg[j++] = charnum[*(linep++)]) != 0) ;\n                    j = 10;\n                    while ((p->seg[j--] = charnum[*(linep++)]) != 0) ;\n#if ROUTING==1\n                    nn = 2*d-2;\n                    status_code = fread(line, 1, d-2, fprt); linep=line;\n                    for (j=d; j<nn; j++) {\n                        c = charnum[*(linep++)];\n                        p->rowcol[j-d] = c;\n                    }\n                    status_code = fread(line, 1, nn/2+1, fprt); linep=line;  // last char \\n\n                    for (j=0; j<nn; ) {\n                        c = *(linep++);\n                        p->neighbor[j++] = c/16;\n                        p->neighbor[j++] = c%16;\n                    }\n#endif\n                    p++;\n                }\n            }\n        }\n    }\n}\n\nDTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc)\n{\n    DTYPE xs[MAXD], ys[MAXD], minval, l, xu, xl, yu, yl;\n    int s[MAXD];\n    int i, j, k, minidx;\n    struct point pt[MAXD], *ptp[MAXD], *tmpp;\n\n    if (d==2)\n        l = ADIFF(x[0], x[1]) + ADIFF(y[0], y[1]);\n    else if (d==3) {\n        if (x[0] > x[1]) {\n            xu = flute_max(x[0], x[2]);\n            xl = flute_min(x[1], x[2]);\n        }\n        else {\n            xu = flute_max(x[1], x[2]);\n            xl = flute_min(x[0], x[2]);\n        }\n        if (y[0] > y[1]) {\n            yu = flute_max(y[0], y[2]);\n            yl = flute_min(y[1], y[2]);\n        }\n        else {\n            yu = flute_max(y[1], y[2]);\n            yl = flute_min(y[0], y[2]);\n        }\n        l = (xu-xl) + (yu-yl);\n    }\n    else {\n        for (i=0; i<d; i++) {\n            pt[i].x = x[i];\n            pt[i].y = y[i];\n            ptp[i] = &pt[i];\n        }\n\n        // sort x\n        for (i=0; i<d-1; i++) {\n            minval = ptp[i]->x;\n            minidx = i;\n            for (j=i+1; j<d; j++) {\n                if (minval > ptp[j]->x) {\n                    minval = ptp[j]->x;\n                    minidx = j;\n                }\n            }\n            tmpp = ptp[i];\n            ptp[i] = ptp[minidx];\n            ptp[minidx] = tmpp;\n        }\n\n#if REMOVE_DUPLICATE_PIN==1\n        ptp[d] = &pt[d];\n        ptp[d]->x = ptp[d]->y = -999999;\n        j = 0;\n        for (i=0; i<d; i++) {\n            for (k=i+1; ptp[k]->x == ptp[i]->x; k++)\n                if (ptp[k]->y == ptp[i]->y)  // pins k and i are the same\n                    break;\n            if (ptp[k]->x != ptp[i]->x)\n                ptp[j++] = ptp[i];\n        }\n        d = j;\n#endif\n\n        for (i=0; i<d; i++) {\n            xs[i] = ptp[i]->x;\n            ptp[i]->o = i;\n        }\n\n        // sort y to find s[]\n        for (i=0; i<d-1; i++) {\n            minval = ptp[i]->y;\n            minidx = i;\n            for (j=i+1; j<d; j++) {\n                if (minval > ptp[j]->y) {\n                    minval = ptp[j]->y;\n                    minidx = j;\n                }\n            }\n            ys[i] = ptp[minidx]->y;\n            s[i] = ptp[minidx]->o;\n            ptp[minidx] = ptp[i];\n        }\n        ys[d-1] = ptp[d-1]->y;\n        s[d-1] = ptp[d-1]->o;\n\n        l = flutes_wl(d, xs, ys, s, acc);\n    }\n    return l;\n}\n\n// xs[] and ys[] are coords in x and y in sorted order\n// s[] is a list of nodes in increasing y direction\n//   if nodes are indexed in the order of increasing x coord\n//   i.e., s[i] = s_i as defined in paper\n// The points are (xs[s[i]], ys[i]) for i=0..d-1\n//             or (xs[i], ys[si[i]]) for i=0..d-1\n\nDTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc)\n{\n    int i, j, ss;\n\n    for (i=0; i<d-1; i++) {\n        if (xs[s[i]]==xs[s[i+1]] && ys[i]==ys[i+1]) {\n            if (s[i] < s[i+1])\n                ss = s[i+1];\n            else {\n                ss = s[i];\n                s[i] = s[i+1];\n            }\n            for (j=i+2; j<d; j++) {\n                ys[j-1] = ys[j];\n                s[j-1] = s[j];\n            }\n            for (j=ss+1; j<d; j++)\n                xs[j-1] = xs[j];\n            for (j=0; j<=d-2; j++)\n                if (s[j] > ss) s[j]--;\n            i--;\n            d--;\n        }\n    }\n    return flutes_wl_ALLD(d, xs, ys, s, acc);\n}\n\n// For low-degree, i.e., 2 <= d <= D\nDTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[])\n{\n    int k, pi, i, j;\n    struct csoln *rlist;\n    DTYPE dd[2*D-2];  // 0..D-2 for v, D-1..2*D-3 for h\n    DTYPE minl, sum, l[MPOWV+1];\n\n    if (d <= 3)\n        minl = xs[d-1]-xs[0]+ys[d-1]-ys[0];\n    else {\n        k = 0;\n        if (s[0] < s[2]) k++;\n        if (s[1] < s[2]) k++;\n\n        for (i=3; i<=d-1; i++) {  // p0=0 always, skip i=1 for symmetry\n            pi = s[i];\n            for (j=d-1; j>i; j--)\n                if (s[j] < s[i])\n                    pi--;\n            k = pi + (i+1)*k;\n        }\n\n        if (k < numgrp[d])  // no horizontal flip\n            for (i=1; i<=d-3; i++) {\n                dd[i]=ys[i+1]-ys[i];\n                dd[d-1+i]=xs[i+1]-xs[i];\n            }\n        else {\n            k=2*numgrp[d]-1-k;\n            for (i=1; i<=d-3; i++) {\n                dd[i]=ys[i+1]-ys[i];\n                dd[d-1+i]=xs[d-1-i]-xs[d-2-i];\n            }\n        }\n\n        minl = l[0] = xs[d-1]-xs[0]+ys[d-1]-ys[0];\n        rlist = LUT[d][k];\n        for (i=0; rlist->seg[i]>0; i++)\n            minl += dd[rlist->seg[i]];\n\n        l[1] = minl;\n        j = 2;\n        while (j <= numsoln[d][k]) {\n            rlist++;\n            sum = l[rlist->parent];\n            for (i=0; rlist->seg[i]>0; i++)\n                sum += dd[rlist->seg[i]];\n            for (i=10; rlist->seg[i]>0; i--)\n                sum -= dd[rlist->seg[i]];\n            minl = flute_min(minl, sum);\n            l[j++] = sum;\n        }\n    }\n\n    return minl;\n}\n\n// For medium-degree, i.e., D+1 <= d\nDTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc)\n{\n    DTYPE x1[MAXD], x2[MAXD], y1[MAXD], y2[MAXD];\n    int si[MAXD], s1[MAXD], s2[MAXD];\n    float score[2*MAXD], penalty[MAXD], pnlty, dx, dy;\n    DTYPE ll, minl, extral;\n    int i, r, p, maxbp, nbp, bp, ub, lb, n1, n2, newacc;\n    int ms, mins, maxs, minsi, maxsi;\n    DTYPE distx[MAXD], disty[MAXD], xydiff;\n\n    if (s[0] < s[d-1]) {\n        ms = flute_max(s[0], s[1]);\n        for (i=2; i<=ms; i++)\n            ms = flute_max(ms, s[i]);\n        if (ms <= d-3) {\n            for (i=0; i<=ms; i++) {\n                x1[i] = xs[i];\n                y1[i] = ys[i];\n                s1[i] = s[i];\n            }\n            x1[ms+1] = xs[ms];\n            y1[ms+1] = ys[ms];\n            s1[ms+1] = ms+1;\n\n            s2[0] = 0;\n            for (i=1; i<=d-1-ms; i++)\n                s2[i] = s[i+ms]-ms;\n\n            return flutes_wl_LMD(ms+2, x1, y1, s1, acc)\n                + flutes_wl_LMD(d-ms, xs+ms, ys+ms, s2, acc);\n        }\n    }\n    else {  // (s[0] > s[d-1])\n        ms = flute_min(s[0], s[1]);\n        for (i=2; i<=d-1-ms; i++)\n            ms = flute_min(ms, s[i]);\n        if (ms >= 2) {\n            x1[0] = xs[ms];\n            y1[0] = ys[0];\n            s1[0] = s[0]-ms+1;\n            for (i=1; i<=d-1-ms; i++) {\n                x1[i] = xs[i+ms-1];\n                y1[i] = ys[i];\n                s1[i] = s[i]-ms+1;\n            }\n            x1[d-ms] = xs[d-1];\n            y1[d-ms] = ys[d-1-ms];\n            s1[d-ms] = 0;\n\n            s2[0] = ms;\n            for (i=1; i<=ms; i++)\n                s2[i] = s[i+d-1-ms];\n\n            return flutes_wl_LMD(d+1-ms, x1, y1, s1, acc)\n                + flutes_wl_LMD(ms+1, xs, ys+d-1-ms, s2, acc);\n        }\n    }\n\n// Find inverse si[] of s[]\n    for (r=0; r<d; r++)\n        si[s[r]] = r;\n\n// Determine breaking directions and positions dp[]\n    lb=(d-2*acc+2)/4;\n    if (lb < 2) lb = 2;\n    ub=d-1-lb;\n\n// Compute scores\n#define AAWL 0.6\n#define BBWL 0.3\n    float CCWL = 7.4/((d+10.)*(d-3.));\n    float DDWL = 4.8/(d-1);\n\n    // Compute penalty[]\n    dx = CCWL*(xs[d-2]-xs[1]);\n    dy = CCWL*(ys[d-2]-ys[1]);\n    for (r = d/2, pnlty = 0; r>=0; r--, pnlty += dx)\n        penalty[r] = pnlty,  penalty[d-1-r] = pnlty;\n    for (r = d/2-1, pnlty = dy; r>=0; r--, pnlty += dy)\n        penalty[s[r]] += pnlty,  penalty[s[d-1-r]] += pnlty;\n//#define CCWL 0.16\n//    for (r=0; r<d; r++)\n//        penalty[r] = flute_abs(d-1-r-r)*dx + flute_abs(d-1-si[r]-si[r])*dy;\n\n    // Compute distx[], disty[]\n    xydiff = (xs[d-1] - xs[0]) - (ys[d-1] - ys[0]);\n    if (s[0] < s[1])\n        mins = s[0], maxs = s[1];\n    else mins = s[1], maxs = s[0];\n    if (si[0] < si[1])\n        minsi = si[0], maxsi = si[1];\n    else minsi = si[1], maxsi = si[0];\n    for (r=2; r<=ub; r++) {\n        if (s[r] < mins)\n            mins = s[r];\n        else if (s[r] > maxs)\n            maxs = s[r];\n        distx[r] = xs[maxs] - xs[mins];\n        if (si[r] < minsi)\n            minsi = si[r];\n        else if (si[r] > maxsi)\n            maxsi = si[r];\n        disty[r] = ys[maxsi] - ys[minsi] + xydiff;\n    }\n\n    if (s[d-2] < s[d-1])\n        mins = s[d-2], maxs = s[d-1];\n    else mins = s[d-1], maxs = s[d-2];\n    if (si[d-2] < si[d-1])\n        minsi = si[d-2], maxsi = si[d-1];\n    else minsi = si[d-1], maxsi = si[d-2];\n    for (r=d-3; r>=lb; r--) {\n        if (s[r] < mins)\n            mins = s[r];\n        else if (s[r] > maxs)\n            maxs = s[r];\n        distx[r] += xs[maxs] - xs[mins];\n        if (si[r] < minsi)\n            minsi = si[r];\n        else if (si[r] > maxsi)\n            maxsi = si[r];\n        disty[r] += ys[maxsi] - ys[minsi];\n    }\n\n    nbp=0;\n    for (r=lb; r<=ub; r++) {\n        if (si[r]==0 || si[r]==d-1)\n            score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r]\n                - AAWL*(ys[d-2]-ys[1]) - DDWL*disty[r];\n        else score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r]\n                 - BBWL*(ys[si[r]+1]-ys[si[r]-1]) - DDWL*disty[r];\n        nbp++;\n\n        if (s[r]==0 || s[r]==d-1)\n            score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]]\n                - AAWL*(xs[d-2]-xs[1]) - DDWL*distx[r];\n        else score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]]\n                 - BBWL*(xs[s[r]+1]-xs[s[r]-1]) - DDWL*distx[r];\n        nbp++;\n    }\n\n    if (acc <= 3)\n        newacc = 1;\n    else {\n        newacc = acc/2;\n        if (acc >= nbp) acc = nbp-1;\n    }\n\n    minl = (DTYPE) INT_MAX;\n    for (i=0; i<acc; i++) {\n        maxbp = 0;\n        for (bp=1; bp<nbp; bp++)\n            if (score[maxbp] < score[bp]) maxbp = bp;\n        score[maxbp] = -9e9;\n\n#define BreakPt(bp) ((bp)/2+lb)\n#define BreakInX(bp) ((bp)%2==0)\n        p = BreakPt(maxbp);\n// Breaking in p\n        if (BreakInX(maxbp)) {  // break in x\n            n1 = n2 = 0;\n            for (r=0; r<d; r++) {\n                if (s[r] < p) {\n                    s1[n1] = s[r];\n                    y1[n1] = ys[r];\n                    n1++;\n                }\n                else if (s[r] > p) {\n                    s2[n2] = s[r]-p;\n                    y2[n2] = ys[r];\n                    n2++;\n                }\n                else { // if (s[r] == p)  i.e.,  r = si[p]\n                    s1[n1] = p;  s2[n2] = 0;\n                    if (r == d-1 || r == d-2) {\n                        y1[n1] = y2[n2] = ys[r-1];\n                        extral = ys[r] - ys[r-1];\n                    }\n                    if (r == 0 || r == 1) {\n                        y1[n1] = y2[n2] = ys[r+1];\n                        extral = ys[r+1] - ys[r];\n                    }\n                    else {\n                        y1[n1] = y2[n2] = ys[r];\n                        extral = 0;\n                    }\n                    n1++;  n2++;\n                }\n            }\n            ll = extral + flutes_wl_LMD(p+1, xs, y1, s1, newacc)\n                + flutes_wl_LMD(d-p, xs+p, y2, s2, newacc);\n        }\n        else {  // if (!BreakInX(maxbp))\n            n1 = n2 = 0;\n            for (r=0; r<d; r++) {\n                if (si[r] < p) {\n                    s1[si[r]] = n1;\n                    x1[n1] = xs[r];\n                    n1++;\n                }\n                else if (si[r] > p) {\n                    s2[si[r]-p] = n2;\n                    x2[n2] = xs[r];\n                    n2++;\n                }\n                else { // if (si[r] == p)  i.e.,  r = s[p]\n                    s1[p] = n1;  s2[0] = n2;\n                    if (r == d-1 || r == d-2) {\n                        x1[n1] = x2[n2] = xs[r-1];\n                        extral = xs[r] - xs[r-1];\n                    }\n                    if (r == 0 || r == 1) {\n                        x1[n1] = x2[n2] = xs[r+1];\n                        extral = xs[r+1] - xs[r];\n                    }\n                    else {\n                        x1[n1] = x2[n2] = xs[r];\n                        extral = 0;\n                    }\n                    n1++;  n2++;\n                }\n            }\n            ll = extral + flutes_wl_LMD(p+1, x1, ys, s1, newacc)\n                + flutes_wl_LMD(d-p, x2, ys+p, s2, newacc);\n        }\n        if (minl > ll) minl = ll;\n    }\n    return minl;\n}\n\nstatic int orderx(const void *a, const void *b)\n{\n    struct point *pa, *pb;\n\n    pa = *(struct point**)a;\n    pb = *(struct point**)b;\n\n    if (pa->x < pb->x) return -1;\n    if (pa->x > pb->x) return 1;\n    return 0;\n}\n\nstatic int ordery(const void *a, const void *b)\n{\n    struct point *pa, *pb;\n\n    pa = *(struct point**)a;\n    pb = *(struct point**)b;\n\n    if (pa->y < pb->y) return -1;\n    if (pa->y > pb->y) return 1;\n    return 0;\n}\n\nTree flute(int d, DTYPE x[], DTYPE y[], int acc)\n{\n    DTYPE *xs, *ys, minval;\n    int *s;\n    int i, j, k, minidx;\n    struct point *pt, **ptp, *tmpp;\n    Tree t;\n\n    if (d==2) {\n        t.deg = 2;\n        t.length = ADIFF(x[0], x[1]) + ADIFF(y[0], y[1]);\n        t.branch = (Branch *) malloc(2*sizeof(Branch));\n        t.branch[0].x = x[0];\n        t.branch[0].y = y[0];\n        t.branch[0].n = 1;\n        t.branch[1].x = x[1];\n        t.branch[1].y = y[1];\n        t.branch[1].n = 1;\n    }\n    else {\n        xs = (DTYPE *)malloc(sizeof(DTYPE)*(d));\n        ys = (DTYPE *)malloc(sizeof(DTYPE)*(d));\n        s = (int *)malloc(sizeof(int)*(d));\n        pt = (struct point *)malloc(sizeof(struct point)*(d+1));\n        ptp = (struct point **)malloc(sizeof(struct point*)*(d+1));\n\n        for (i=0; i<d; i++) {\n            pt[i].x = x[i];\n            pt[i].y = y[i];\n            ptp[i] = &pt[i];\n        }\n\n        // sort x\n        if (d<200) {\n            for (i=0; i<d-1; i++) {\n                minval = ptp[i]->x;\n                minidx = i;\n                for (j=i+1; j<d; j++) {\n                    if (minval > ptp[j]->x) {\n                        minval = ptp[j]->x;\n                        minidx = j;\n                    }\n                }\n                tmpp = ptp[i];\n                ptp[i] = ptp[minidx];\n                ptp[minidx] = tmpp;\n            }\n        } else {\n            qsort(ptp, d, sizeof(struct point *), orderx);\n        }\n\n#if REMOVE_DUPLICATE_PIN==1\n        ptp[d] = &pt[d];\n        ptp[d]->x = ptp[d]->y = -999999;\n        j = 0;\n        for (i=0; i<d; i++) {\n            for (k=i+1; ptp[k]->x == ptp[i]->x; k++)\n                if (ptp[k]->y == ptp[i]->y)  // pins k and i are the same\n                    break;\n            if (ptp[k]->x != ptp[i]->x)\n                ptp[j++] = ptp[i];\n        }\n        d = j;\n#endif\n\n        for (i=0; i<d; i++) {\n            xs[i] = ptp[i]->x;\n            ptp[i]->o = i;\n        }\n\n        // sort y to find s[]\n        if (d<200) {\n            for (i=0; i<d-1; i++) {\n                minval = ptp[i]->y;\n                minidx = i;\n                for (j=i+1; j<d; j++) {\n                    if (minval > ptp[j]->y) {\n                        minval = ptp[j]->y;\n                        minidx = j;\n                    }\n                }\n                ys[i] = ptp[minidx]->y;\n                s[i] = ptp[minidx]->o;\n                ptp[minidx] = ptp[i];\n            }\n            ys[d-1] = ptp[d-1]->y;\n            s[d-1] = ptp[d-1]->o;\n        } else {\n            qsort(ptp, d, sizeof(struct point *), ordery);\n            for (i=0; i<d; i++) {\n                ys[i] = ptp[i]->y;\n                s[i] = ptp[i]->o;\n            }\n        }\n\n        t = flutes(d, xs, ys, s, acc);\n\n        free(xs);\n        free(ys);\n        free(s);\n        free(pt);\n        free(ptp);\n    }\n\n    return t;\n}\n\n// xs[] and ys[] are coords in x and y in sorted order\n// s[] is a list of nodes in increasing y direction\n//   if nodes are indexed in the order of increasing x coord\n//   i.e., s[i] = s_i as defined in paper\n// The points are (xs[s[i]], ys[i]) for i=0..d-1\n//             or (xs[i], ys[si[i]]) for i=0..d-1\n\nTree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc)\n{\n    int i, j, ss;\n\n    for (i=0; i<d-1; i++) {\n        if (xs[s[i]]==xs[s[i+1]] && ys[i]==ys[i+1]) {\n            if (s[i] < s[i+1])\n                ss = s[i+1];\n            else {\n                ss = s[i];\n                s[i] = s[i+1];\n            }\n            for (j=i+2; j<d; j++) {\n                ys[j-1] = ys[j];\n                s[j-1] = s[j];\n            }\n            for (j=ss+1; j<d; j++)\n                xs[j-1] = xs[j];\n            for (j=0; j<=d-2; j++)\n                if (s[j] > ss) s[j]--;\n            i--;\n            d--;\n        }\n    }\n    return flutes_ALLD(d, xs, ys, s, acc);\n}\n\n// For low-degree, i.e., 2 <= d <= D\nTree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[])\n{\n    int k, pi, i, j;\n    struct csoln *rlist, *bestrlist;\n    DTYPE dd[2*D-2];  // 0..D-2 for v, D-1..2*D-3 for h\n    DTYPE minl, sum, l[MPOWV+1];\n    int hflip;\n    Tree t;\n\n    t.deg = d;\n    t.branch = (Branch *) malloc((2*d-2)*sizeof(Branch));\n    if (d == 2) {\n        minl = xs[1]-xs[0]+ys[1]-ys[0];\n        t.branch[0].x = xs[s[0]];\n        t.branch[0].y = ys[0];\n        t.branch[0].n = 1;\n        t.branch[1].x = xs[s[1]];\n        t.branch[1].y = ys[1];\n        t.branch[1].n = 1;\n    }\n    else if (d == 3) {\n        minl = xs[2]-xs[0]+ys[2]-ys[0];\n        t.branch[0].x = xs[s[0]];\n        t.branch[0].y = ys[0];\n        t.branch[0].n = 3;\n        t.branch[1].x = xs[s[1]];\n        t.branch[1].y = ys[1];\n        t.branch[1].n = 3;\n        t.branch[2].x = xs[s[2]];\n        t.branch[2].y = ys[2];\n        t.branch[2].n = 3;\n        t.branch[3].x = xs[1];\n        t.branch[3].y = ys[1];\n        t.branch[3].n = 3;\n    }\n    else {\n        k = 0;\n        if (s[0] < s[2]) k++;\n        if (s[1] < s[2]) k++;\n\n        for (i=3; i<=d-1; i++) {  // p0=0 always, skip i=1 for symmetry\n            pi = s[i];\n            for (j=d-1; j>i; j--)\n                if (s[j] < s[i])\n                    pi--;\n            k = pi + (i+1)*k;\n        }\n\n        if (k < numgrp[d]) { // no horizontal flip\n            hflip = 0;\n            for (i=1; i<=d-3; i++) {\n                dd[i]=ys[i+1]-ys[i];\n                dd[d-1+i]=xs[i+1]-xs[i];\n            }\n        }\n        else {\n            hflip = 1;\n            k=2*numgrp[d]-1-k;\n            for (i=1; i<=d-3; i++) {\n                dd[i]=ys[i+1]-ys[i];\n                dd[d-1+i]=xs[d-1-i]-xs[d-2-i];\n            }\n        }\n\n        minl = l[0] = xs[d-1]-xs[0]+ys[d-1]-ys[0];\n        rlist = LUT[d][k];\n        for (i=0; rlist->seg[i]>0; i++)\n            minl += dd[rlist->seg[i]];\n        bestrlist = rlist;\n        l[1] = minl;\n        j = 2;\n        while (j <= numsoln[d][k]) {\n            rlist++;\n            sum = l[rlist->parent];\n            for (i=0; rlist->seg[i]>0; i++)\n                sum += dd[rlist->seg[i]];\n            for (i=10; rlist->seg[i]>0; i--)\n                sum -= dd[rlist->seg[i]];\n            if (sum < minl) {\n                minl = sum;\n                bestrlist = rlist;\n            }\n            l[j++] = sum;\n        }\n\n        t.branch[0].x = xs[s[0]];\n        t.branch[0].y = ys[0];\n        t.branch[1].x = xs[s[1]];\n        t.branch[1].y = ys[1];\n        for (i=2; i<d-2; i++) {\n            t.branch[i].x = xs[s[i]];\n            t.branch[i].y = ys[i];\n            t.branch[i].n = bestrlist->neighbor[i];\n        }\n        t.branch[d-2].x = xs[s[d-2]];\n        t.branch[d-2].y = ys[d-2];\n        t.branch[d-1].x = xs[s[d-1]];\n        t.branch[d-1].y = ys[d-1];\n        if (hflip) {\n            if (s[1] < s[0]) {\n                t.branch[0].n = bestrlist->neighbor[1];\n                t.branch[1].n = bestrlist->neighbor[0];\n            }\n            else {\n                t.branch[0].n = bestrlist->neighbor[0];\n                t.branch[1].n = bestrlist->neighbor[1];\n            }\n            if (s[d-1] < s[d-2]) {\n                t.branch[d-2].n = bestrlist->neighbor[d-1];\n                t.branch[d-1].n = bestrlist->neighbor[d-2];\n            }\n            else {\n                t.branch[d-2].n = bestrlist->neighbor[d-2];\n                t.branch[d-1].n = bestrlist->neighbor[d-1];\n            }\n            for (i=d; i<2*d-2; i++) {\n                t.branch[i].x = xs[d-1-bestrlist->rowcol[i-d]%16];\n                t.branch[i].y = ys[bestrlist->rowcol[i-d]/16];\n                t.branch[i].n = bestrlist->neighbor[i];\n                }\n        }\n        else {  // !hflip\n            if (s[0] < s[1]) {\n                t.branch[0].n = bestrlist->neighbor[1];\n                t.branch[1].n = bestrlist->neighbor[0];\n            }\n            else {\n                t.branch[0].n = bestrlist->neighbor[0];\n                t.branch[1].n = bestrlist->neighbor[1];\n            }\n            if (s[d-2] < s[d-1]) {\n                t.branch[d-2].n = bestrlist->neighbor[d-1];\n                t.branch[d-1].n = bestrlist->neighbor[d-2];\n            }\n            else {\n                t.branch[d-2].n = bestrlist->neighbor[d-2];\n                t.branch[d-1].n = bestrlist->neighbor[d-1];\n            }\n            for (i=d; i<2*d-2; i++) {\n                t.branch[i].x = xs[bestrlist->rowcol[i-d]%16];\n                t.branch[i].y = ys[bestrlist->rowcol[i-d]/16];\n                t.branch[i].n = bestrlist->neighbor[i];\n            }\n        }\n    }\n    t.length = minl;\n\n    return t;\n}\n\n// For medium-degree, i.e., D+1 <= d\nTree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc)\n{\n    DTYPE x1[MAXD], x2[MAXD], y1[MAXD], y2[MAXD];\n    int si[MAXD], s1[MAXD], s2[MAXD];\n    float score[2*MAXD], penalty[MAXD], pnlty, dx, dy;\n    DTYPE ll, minl, coord1, coord2;\n    int i, r, p, maxbp, bestbp, bp, nbp, ub, lb, n1, n2, nn1, nn2, newacc;\n    Tree t, t1, t2, bestt1, bestt2;\n    int ms, mins, maxs, minsi, maxsi;\n    DTYPE distx[MAXD], disty[MAXD], xydiff;\n\n    if (s[0] < s[d-1]) {\n        ms = flute_max(s[0], s[1]);\n        for (i=2; i<=ms; i++)\n            ms = flute_max(ms, s[i]);\n        if (ms <= d-3) {\n            for (i=0; i<=ms; i++) {\n                x1[i] = xs[i];\n                y1[i] = ys[i];\n                s1[i] = s[i];\n            }\n            x1[ms+1] = xs[ms];\n            y1[ms+1] = ys[ms];\n            s1[ms+1] = ms+1;\n\n            s2[0] = 0;\n            for (i=1; i<=d-1-ms; i++)\n                s2[i] = s[i+ms]-ms;\n\n            t1 = flutes_LMD(ms+2, x1, y1, s1, acc);\n            t2 = flutes_LMD(d-ms, xs+ms, ys+ms, s2, acc);\n            t = dmergetree(t1, t2);\n            free(t1.branch);\n            free(t2.branch);\n\n            return t;\n        }\n    }\n    else {  // (s[0] > s[d-1])\n        ms = flute_min(s[0], s[1]);\n        for (i=2; i<=d-1-ms; i++)\n            ms = flute_min(ms, s[i]);\n        if (ms >= 2) {\n            x1[0] = xs[ms];\n            y1[0] = ys[0];\n            s1[0] = s[0]-ms+1;\n            for (i=1; i<=d-1-ms; i++) {\n                x1[i] = xs[i+ms-1];\n                y1[i] = ys[i];\n                s1[i] = s[i]-ms+1;\n            }\n            x1[d-ms] = xs[d-1];\n            y1[d-ms] = ys[d-1-ms];\n            s1[d-ms] = 0;\n\n            s2[0] = ms;\n            for (i=1; i<=ms; i++)\n                s2[i] = s[i+d-1-ms];\n\n            t1 = flutes_LMD(d+1-ms, x1, y1, s1, acc);\n            t2 = flutes_LMD(ms+1, xs, ys+d-1-ms, s2, acc);\n            t = dmergetree(t1, t2);\n            free(t1.branch);\n            free(t2.branch);\n\n            return t;\n        }\n    }\n\n// Find inverse si[] of s[]\n    for (r=0; r<d; r++)\n        si[s[r]] = r;\n\n// Determine breaking directions and positions dp[]\n    lb=(d-2*acc+2)/4;\n    if (lb < 2) lb = 2;\n    ub=d-1-lb;\n\n// Compute scores\n#define AA 0.6  // 2.0*BB\n#define BB 0.3\n    float CC = 7.4/((d+10.)*(d-3.));\n    float DD = 4.8/(d-1);\n\n    // Compute penalty[]\n    dx = CC*(xs[d-2]-xs[1]);\n    dy = CC*(ys[d-2]-ys[1]);\n    for (r = d/2, pnlty = 0; r>=2; r--, pnlty += dx)\n        penalty[r] = pnlty,  penalty[d-1-r] = pnlty;\n    penalty[1] = pnlty,  penalty[d-2] = pnlty;\n    penalty[0] = pnlty,  penalty[d-1] = pnlty;\n    for (r = d/2-1, pnlty = dy; r>=2; r--, pnlty += dy)\n        penalty[s[r]] += pnlty,  penalty[s[d-1-r]] += pnlty;\n    penalty[s[1]] += pnlty,  penalty[s[d-2]] += pnlty;\n    penalty[s[0]] += pnlty,  penalty[s[d-1]] += pnlty;\n//#define CC 0.16\n//#define v(r) ((r==0||r==1||r==d-2||r==d-1) ? d-3 : flute_abs(d-1-r-r))\n//    for (r=0; r<d; r++)\n//        penalty[r] = v(r)*dx + v(si[r])*dy;\n\n    // Compute distx[], disty[]\n    xydiff = (xs[d-1] - xs[0]) - (ys[d-1] - ys[0]);\n    if (s[0] < s[1])\n        mins = s[0], maxs = s[1];\n    else mins = s[1], maxs = s[0];\n    if (si[0] < si[1])\n        minsi = si[0], maxsi = si[1];\n    else minsi = si[1], maxsi = si[0];\n    for (r=2; r<=ub; r++) {\n        if (s[r] < mins)\n            mins = s[r];\n        else if (s[r] > maxs)\n            maxs = s[r];\n        distx[r] = xs[maxs] - xs[mins];\n        if (si[r] < minsi)\n            minsi = si[r];\n        else if (si[r] > maxsi)\n            maxsi = si[r];\n        disty[r] = ys[maxsi] - ys[minsi] + xydiff;\n    }\n\n    if (s[d-2] < s[d-1])\n        mins = s[d-2], maxs = s[d-1];\n    else mins = s[d-1], maxs = s[d-2];\n    if (si[d-2] < si[d-1])\n        minsi = si[d-2], maxsi = si[d-1];\n    else minsi = si[d-1], maxsi = si[d-2];\n    for (r=d-3; r>=lb; r--) {\n        if (s[r] < mins)\n            mins = s[r];\n        else if (s[r] > maxs)\n            maxs = s[r];\n        distx[r] += xs[maxs] - xs[mins];\n        if (si[r] < minsi)\n            minsi = si[r];\n        else if (si[r] > maxsi)\n            maxsi = si[r];\n        disty[r] += ys[maxsi] - ys[minsi];\n    }\n\n    nbp=0;\n    for (r=lb; r<=ub; r++) {\n        if (si[r]<=1)\n            score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r]\n                - AA*(ys[2]-ys[1]) - DD*disty[r];\n        else if (si[r]>=d-2)\n            score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r]\n                - AA*(ys[d-2]-ys[d-3]) - DD*disty[r];\n        else score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r]\n                 - BB*(ys[si[r]+1]-ys[si[r]-1]) - DD*disty[r];\n        nbp++;\n\n        if (s[r]<=1)\n            score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]]\n                - AA*(xs[2]-xs[1]) - DD*distx[r];\n        else if (s[r]>=d-2)\n            score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]]\n                - AA*(xs[d-2]-xs[d-3]) - DD*distx[r];\n        else score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]]\n                 - BB*(xs[s[r]+1]-xs[s[r]-1]) - DD*distx[r];\n        nbp++;\n    }\n\n    if (acc <= 3)\n        newacc = 1;\n    else {\n        newacc = acc/2;\n        if (acc >= nbp) acc = nbp-1;\n    }\n\n    minl = (DTYPE) INT_MAX;\n    bestt1.branch = bestt2.branch = NULL;\n    for (i=0; i<acc; i++) {\n        maxbp = 0;\n        for (bp=1; bp<nbp; bp++)\n            if (score[maxbp] < score[bp]) maxbp = bp;\n        score[maxbp] = -9e9;\n\n#define BreakPt(bp) ((bp)/2+lb)\n#define BreakInX(bp) ((bp)%2==0)\n        p = BreakPt(maxbp);\n// Breaking in p\n        if (BreakInX(maxbp)) {  // break in x\n            n1 = n2 = 0;\n            for (r=0; r<d; r++) {\n                if (s[r] < p) {\n                    s1[n1] = s[r];\n                    y1[n1] = ys[r];\n                    n1++;\n                }\n                else if (s[r] > p) {\n                    s2[n2] = s[r]-p;\n                    y2[n2] = ys[r];\n                    n2++;\n                }\n                else { // if (s[r] == p)  i.e.,  r = si[p]\n                    s1[n1] = p;  s2[n2] = 0;\n                    y1[n1] = y2[n2] = ys[r];\n                    nn1 = n1;  nn2 = n2;\n                    n1++;  n2++;\n                }\n            }\n\n            t1 = flutes_LMD(p+1, xs, y1, s1, newacc);\n            t2 = flutes_LMD(d-p, xs+p, y2, s2, newacc);\n            ll = t1.length + t2.length;\n            coord1 = t1.branch[t1.branch[nn1].n].y;\n            coord2 = t2.branch[t2.branch[nn2].n].y;\n            if (t2.branch[nn2].y > flute_max(coord1, coord2))\n                ll -= t2.branch[nn2].y - flute_max(coord1, coord2);\n            else if (t2.branch[nn2].y < flute_min(coord1, coord2))\n                ll -= flute_min(coord1, coord2) - t2.branch[nn2].y;\n        }\n        else {  // if (!BreakInX(maxbp))\n            n1 = n2 = 0;\n            for (r=0; r<d; r++) {\n                if (si[r] < p) {\n                    s1[si[r]] = n1;\n                    x1[n1] = xs[r];\n                    n1++;\n                }\n                else if (si[r] > p) {\n                    s2[si[r]-p] = n2;\n                    x2[n2] = xs[r];\n                    n2++;\n                }\n                else { // if (si[r] == p)  i.e.,  r = s[p]\n                    s1[p] = n1;  s2[0] = n2;\n                    x1[n1] = x2[n2] = xs[r];\n                    n1++;  n2++;\n                }\n            }\n\n            t1 = flutes_LMD(p+1, x1, ys, s1, newacc);\n            t2 = flutes_LMD(d-p, x2, ys+p, s2, newacc);\n            ll = t1.length + t2.length;\n            coord1 = t1.branch[t1.branch[p].n].x;\n            coord2 = t2.branch[t2.branch[0].n].x;\n            if (t2.branch[0].x > flute_max(coord1, coord2))\n                ll -= t2.branch[0].x - flute_max(coord1, coord2);\n            else if (t2.branch[0].x < flute_min(coord1, coord2))\n                ll -= flute_min(coord1, coord2) - t2.branch[0].x;\n        }\n        if (minl > ll) {\n            minl = ll;\n            free(bestt1.branch);\n            free(bestt2.branch);\n            bestt1 = t1;\n            bestt2 = t2;\n            bestbp = maxbp;\n        }\n        else {\n            free(t1.branch);\n            free(t2.branch);\n        }\n    }\n\n#if LOCAL_REFINEMENT==1\n    if (BreakInX(bestbp)) {\n        t = hmergetree(bestt1, bestt2, s);\n        local_refinement(&t, si[BreakPt(bestbp)]);\n    } else {\n        t = vmergetree(bestt1, bestt2);\n        local_refinement(&t, BreakPt(bestbp));\n    }\n#else\n    if (BreakInX(bestbp)) {\n        t = hmergetree(bestt1, bestt2, s);\n    } else {\n        t = vmergetree(bestt1, bestt2);\n    }\n#endif\n\n    free(bestt1.branch);\n    free(bestt2.branch);\n\n    return t;\n}\n\nTree dmergetree(Tree t1, Tree t2)\n{\n    int i, d, prev, curr, next, offset1, offset2;\n    Tree t;\n\n    t.deg = d = t1.deg + t2.deg - 2;\n    t.length = t1.length + t2.length;\n    t.branch = (Branch *) malloc((2*d-2)*sizeof(Branch));\n    offset1 = t2.deg-2;\n    offset2 = 2*t1.deg-4;\n\n    for (i=0; i<=t1.deg-2; i++) {\n        t.branch[i].x = t1.branch[i].x;\n        t.branch[i].y = t1.branch[i].y;\n        t.branch[i].n = t1.branch[i].n + offset1;\n    }\n    for (i=t1.deg-1; i<=d-1; i++) {\n        t.branch[i].x = t2.branch[i-t1.deg+2].x;\n        t.branch[i].y = t2.branch[i-t1.deg+2].y;\n        t.branch[i].n = t2.branch[i-t1.deg+2].n + offset2;\n    }\n    for (i=d; i<=d+t1.deg-3; i++) {\n        t.branch[i].x = t1.branch[i-offset1].x;\n        t.branch[i].y = t1.branch[i-offset1].y;\n        t.branch[i].n = t1.branch[i-offset1].n + offset1;\n    }\n    for (i=d+t1.deg-2; i<=2*d-3; i++) {\n        t.branch[i].x = t2.branch[i-offset2].x;\n        t.branch[i].y = t2.branch[i-offset2].y;\n        t.branch[i].n = t2.branch[i-offset2].n + offset2;\n    }\n\n    prev = t2.branch[0].n + offset2;\n    curr = t1.branch[t1.deg-1].n + offset1;\n    next = t.branch[curr].n;\n    while (curr != next) {\n        t.branch[curr].n = prev;\n        prev = curr;\n        curr = next;\n        next = t.branch[curr].n;\n    }\n    t.branch[curr].n = prev;\n\n    return t;\n}\n\nTree hmergetree(Tree t1, Tree t2, int s[])\n{\n    int i, prev, curr, next, extra, offset1, offset2;\n    int p, ii, n1, n2, nn1, nn2;\n    DTYPE coord1, coord2;\n    Tree t;\n\n    t.deg = t1.deg + t2.deg - 1;\n    t.length = t1.length + t2.length;\n    t.branch = (Branch *) malloc((2*t.deg-2)*sizeof(Branch));\n    offset1 = t2.deg-1;\n    offset2 = 2*t1.deg-3;\n\n    p = t1.deg - 1;\n    n1 = n2 = 0;\n    for (i=0; i<t.deg; i++) {\n        if (s[i] < p) {\n            t.branch[i].x = t1.branch[n1].x;\n            t.branch[i].y = t1.branch[n1].y;\n            t.branch[i].n = t1.branch[n1].n + offset1;\n            n1++;\n        }\n        else if (s[i] > p) {\n            t.branch[i].x = t2.branch[n2].x;\n            t.branch[i].y = t2.branch[n2].y;\n            t.branch[i].n = t2.branch[n2].n + offset2;\n            n2++;\n        }\n        else {\n            t.branch[i].x = t2.branch[n2].x;\n            t.branch[i].y = t2.branch[n2].y;\n            t.branch[i].n = t2.branch[n2].n + offset2;\n            nn1 = n1;  nn2 = n2;  ii = i;\n            n1++;  n2++;\n        }\n    }\n    for (i=t.deg; i<=t.deg+t1.deg-3; i++) {\n        t.branch[i].x = t1.branch[i-offset1].x;\n        t.branch[i].y = t1.branch[i-offset1].y;\n        t.branch[i].n = t1.branch[i-offset1].n + offset1;\n    }\n    for (i=t.deg+t1.deg-2; i<=2*t.deg-4; i++) {\n        t.branch[i].x = t2.branch[i-offset2].x;\n        t.branch[i].y = t2.branch[i-offset2].y;\n        t.branch[i].n = t2.branch[i-offset2].n + offset2;\n    }\n    extra = 2*t.deg-3;\n    coord1 = t1.branch[t1.branch[nn1].n].y;\n    coord2 = t2.branch[t2.branch[nn2].n].y;\n    if (t2.branch[nn2].y > flute_max(coord1, coord2)) {\n        t.branch[extra].y = flute_max(coord1, coord2);\n        t.length -= t2.branch[nn2].y - t.branch[extra].y;\n    }\n    else if (t2.branch[nn2].y < flute_min(coord1, coord2)) {\n        t.branch[extra].y = flute_min(coord1, coord2);\n        t.length -= t.branch[extra].y - t2.branch[nn2].y;\n    }\n    else t.branch[extra].y = t2.branch[nn2].y;\n    t.branch[extra].x = t2.branch[nn2].x;\n    t.branch[extra].n = t.branch[ii].n;\n    t.branch[ii].n = extra;\n\n    prev = extra;\n    curr = t1.branch[nn1].n + offset1;\n    next = t.branch[curr].n;\n    while (curr != next) {\n        t.branch[curr].n = prev;\n        prev = curr;\n        curr = next;\n        next = t.branch[curr].n;\n    }\n    t.branch[curr].n = prev;\n\n    return t;\n}\n\nTree vmergetree(Tree t1, Tree t2)\n{\n    int i, prev, curr, next, extra, offset1, offset2;\n    DTYPE coord1, coord2;\n    Tree t;\n\n    t.deg = t1.deg + t2.deg - 1;\n    t.length = t1.length + t2.length;\n    t.branch = (Branch *) malloc((2*t.deg-2)*sizeof(Branch));\n    offset1 = t2.deg-1;\n    offset2 = 2*t1.deg-3;\n\n    for (i=0; i<=t1.deg-2; i++) {\n        t.branch[i].x = t1.branch[i].x;\n        t.branch[i].y = t1.branch[i].y;\n        t.branch[i].n = t1.branch[i].n + offset1;\n    }\n    for (i=t1.deg-1; i<=t.deg-1; i++) {\n        t.branch[i].x = t2.branch[i-t1.deg+1].x;\n        t.branch[i].y = t2.branch[i-t1.deg+1].y;\n        t.branch[i].n = t2.branch[i-t1.deg+1].n + offset2;\n    }\n    for (i=t.deg; i<=t.deg+t1.deg-3; i++) {\n        t.branch[i].x = t1.branch[i-offset1].x;\n        t.branch[i].y = t1.branch[i-offset1].y;\n        t.branch[i].n = t1.branch[i-offset1].n + offset1;\n    }\n    for (i=t.deg+t1.deg-2; i<=2*t.deg-4; i++) {\n        t.branch[i].x = t2.branch[i-offset2].x;\n        t.branch[i].y = t2.branch[i-offset2].y;\n        t.branch[i].n = t2.branch[i-offset2].n + offset2;\n    }\n    extra = 2*t.deg-3;\n    coord1 = t1.branch[t1.branch[t1.deg-1].n].x;\n    coord2 = t2.branch[t2.branch[0].n].x;\n    if (t2.branch[0].x > flute_max(coord1, coord2)) {\n        t.branch[extra].x = flute_max(coord1, coord2);\n        t.length -= t2.branch[0].x - t.branch[extra].x;\n    }\n    else if (t2.branch[0].x < flute_min(coord1, coord2)) {\n        t.branch[extra].x = flute_min(coord1, coord2);\n        t.length -= t.branch[extra].x - t2.branch[0].x;\n    }\n    else t.branch[extra].x = t2.branch[0].x;\n    t.branch[extra].y = t2.branch[0].y;\n    t.branch[extra].n = t.branch[t1.deg-1].n;\n    t.branch[t1.deg-1].n = extra;\n\n    prev = extra;\n    curr = t1.branch[t1.deg-1].n + offset1;\n    next = t.branch[curr].n;\n    while (curr != next) {\n        t.branch[curr].n = prev;\n        prev = curr;\n        curr = next;\n        next = t.branch[curr].n;\n    }\n    t.branch[curr].n = prev;\n\n    return t;\n}\n\nvoid local_refinement(Tree *tp, int p)\n{\n    int d, dd, i, ii, j, prev, curr, next, root;\n    int SteinerPin[2*MAXD], index[2*MAXD];\n    DTYPE x[MAXD], xs[D], ys[D];\n    int ss[D];\n    Tree tt;\n\n    d = tp->deg;\n    root = tp->branch[p].n;\n\n// Reverse edges to point to root\n    prev = root;\n    curr = tp->branch[prev].n;\n    next = tp->branch[curr].n;\n    while (curr != next) {\n        tp->branch[curr].n = prev;\n        prev = curr;\n        curr = next;\n        next = tp->branch[curr].n;\n    }\n    tp->branch[curr].n = prev;\n    tp->branch[root].n = root;\n\n// Find Steiner nodes that are at pins\n    for (i=d; i<=2*d-3; i++)\n        SteinerPin[i] = -1;\n    for (i=0; i<d; i++) {\n        next = tp->branch[i].n;\n        if (tp->branch[i].x == tp->branch[next].x &&\n            tp->branch[i].y == tp->branch[next].y)\n            SteinerPin[next] = i; // Steiner 'next' at Pin 'i'\n    }\n    SteinerPin[root] = p;\n\n// Find pins that are directly connected to root\n    dd = 0;\n    for (i=0; i<d; i++) {\n        curr = tp->branch[i].n;\n        if (SteinerPin[curr] == i)\n            curr = tp->branch[curr].n;\n        while (SteinerPin[curr] < 0)\n            curr = tp->branch[curr].n;\n        if (curr == root) {\n            x[dd] = tp->branch[i].x;\n            if (SteinerPin[tp->branch[i].n] == i && tp->branch[i].n != root)\n                index[dd++] = tp->branch[i].n;  // Steiner node\n            else index[dd++] = i;  // Pin\n        }\n    }\n\n    if (4 <= dd && dd <= D) {\n// Find Steiner nodes that are directly connected to root\n        ii=dd;\n        for (i=0; i<dd; i++) {\n            curr = tp->branch[index[i]].n;\n            while (SteinerPin[curr] < 0) {\n                index[ii++] = curr;\n                SteinerPin[curr] = INT_MAX;\n                curr = tp->branch[curr].n;\n            }\n        }\n        index[ii] = root;\n\n        for (ii=0; ii<dd; ii++) {\n            ss[ii] = 0;\n            for (j=0; j<ii; j++)\n                if (x[j] < x[ii])\n                    ss[ii]++;\n            for (j=ii+1; j<dd; j++)\n                if (x[j] <= x[ii])\n                    ss[ii]++;\n            xs[ss[ii]] = x[ii];\n            ys[ii] = tp->branch[index[ii]].y;\n        }\n\n        tt = flutes_LD(dd, xs, ys, ss);\n\n// Find new wirelength\n        tp->length += tt.length;\n        for (ii=0; ii<2*dd-3; ii++) {\n            i = index[ii];\n            j = tp->branch[i].n;\n            tp->length -= ADIFF(tp->branch[i].x, tp->branch[j].x)\n                + ADIFF(tp->branch[i].y, tp->branch[j].y);\n        }\n\n// Copy tt into t\n        for (ii=0; ii<dd; ii++) {\n            tp->branch[index[ii]].n = index[tt.branch[ii].n];\n        }\n        for (; ii<=2*dd-3; ii++) {\n            tp->branch[index[ii]].x = tt.branch[ii].x;\n            tp->branch[index[ii]].y = tt.branch[ii].y;\n            tp->branch[index[ii]].n = index[tt.branch[ii].n];\n        }\n        free(tt.branch);\n    }\n\n    return;\n}\n\nDTYPE wirelength(Tree t)\n{\n    int i, j;\n    DTYPE l=0;\n\n    for (i=0; i<2*t.deg-2; i++) {\n        j = t.branch[i].n;\n        l += ADIFF(t.branch[i].x, t.branch[j].x)\n            + ADIFF(t.branch[i].y, t.branch[j].y);\n    }\n\n    return l;\n}\n\nvoid printtree(Tree t)\n{\n    int i;\n\n    for (i=0; i<t.deg; i++)\n        printf(\" %-2d:  x=%4g  y=%4g  e=%d\\n\",\n               i, (float) t.branch[i].x, (float) t.branch[i].y, t.branch[i].n);\n    for (i=t.deg; i<2*t.deg-2; i++)\n        printf(\"s%-2d:  x=%4g  y=%4g  e=%d\\n\",\n               i, (float) t.branch[i].x, (float) t.branch[i].y, t.branch[i].n);\n    printf(\"\\n\");\n}\n\n// Output in a format that can be plotted by gnuplot\nvoid plottree(Tree t)\n{\n    int i;\n\n    for (i=0; i<2*t.deg-2; i++) {\n        printf(\"%d %d\\n\", t.branch[i].x, t.branch[i].y);\n        printf(\"%d %d\\n\\n\", t.branch[t.branch[i].n].x,\n               t.branch[t.branch[i].n].y);\n    }\n}\n"
  },
  {
    "path": "src/flute/flute.h",
    "content": "#pragma once\n/*****************************/\n/*  User-Defined Parameters  */\n/*****************************/\n#define MAXD 150    // max. degree that can be handled\n#define ACCURACY 3  // Default accuracy\n#define ROUTING 1   // 1 to construct routing, 0 to estimate WL only\n#define LOCAL_REFINEMENT 0      // Suggestion: Set to 1 if ACCURACY >= 5\n#define REMOVE_DUPLICATE_PIN 0  // Remove dup. pin for flute_wl() & flute()\n\n#ifndef DTYPE   // Data type for distance\n#define DTYPE int\n#endif\n\n\n/*****************************/\n/*  User-Callable Functions  */\n/*****************************/\n// void readLUT();\n// DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc);\n// DTYPE flutes_wl(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\n// Tree flute(int d, DTYPE x[], DTYPE y[], int acc);\n// Tree flutes(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\n// DTYPE wirelength(Tree t);\n// void printtree(Tree t);\n// void plottree(Tree t);\n\n\n/*************************************/\n/* Internal Parameters and Functions */\n/*************************************/\n#define POWVFILE \"POWV9.dat\"        // LUT for POWV (Wirelength Vector)\n#define POSTFILE \"POST9.dat\"        // LUT for POST (Steiner Tree)\n#define D 9                         // LUT is used for d <= D, D <= 9\n#define TAU(A) (8+1.3*(A))\n#define D1(A) (25+120/((A)*(A)))     // flute_mr is used for D1 < d <= D2\n#define D2(A) ((A)<=6 ? 500 : 75+5*(A))\n\ntypedef struct\n{\n    DTYPE x, y;   // starting point of the branch\n    int n;   // index of neighbor\n} Branch;\n\ntypedef struct\n{\n    int deg;   // degree\n    DTYPE length;   // total wirelength\n    Branch *branch;   // array of tree branches\n} Tree;\n\n// User-Callable Functions\n// extern void readLUT();\nextern DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc);\n//Macro: DTYPE flutes_wl(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\n// extern Tree flute(int d, DTYPE x[], DTYPE y[], int acc);\n//Macro: Tree flutes(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nextern DTYPE wirelength(Tree t);\nextern void printtree(Tree t);\nextern void plottree(Tree t);\n\n// Other useful functions\nextern void init_param();\nextern DTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[]);\nextern DTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nextern DTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nextern Tree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[]);\nextern Tree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nextern Tree flutes_HD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\nextern Tree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);\n\n#if REMOVE_DUPLICATE_PIN==1\n  #define flutes_wl(d, xs, ys, s, acc) flutes_wl_RDP(d, xs, ys, s, acc)\n  #define flutes(d, xs, ys, s, acc) flutes_RDP(d, xs, ys, s, acc)\n#else\n  #define flutes_wl(d, xs, ys, s, acc) flutes_wl_ALLD(d, xs, ys, s, acc)\n  #define flutes(d, xs, ys, s, acc) flutes_ALLD(d, xs, ys, s, acc)\n#endif\n\n#define flutes_wl_ALLD(d, xs, ys, s, acc) flutes_wl_LMD(d, xs, ys, s, acc)\n#define flutes_ALLD(d, xs, ys, s, acc) \\\n    (d<=D ? flutes_LD(d, xs, ys, s) \\\n          : (d<=D1(acc) ? flutes_MD(d, xs, ys, s, acc) \\\n                        : flutes_HD(d, xs, ys, s, acc)))\n\n#define flutes_wl_LMD(d, xs, ys, s, acc) \\\n    (d<=D ? flutes_wl_LD(d, xs, ys, s) : flutes_wl_MD(d, xs, ys, s, acc))\n#define flutes_LMD(d, xs, ys, s, acc) \\\n    (d<=D ? flutes_LD(d, xs, ys, s) : flutes_MD(d, xs, ys, s, acc))\n\n#define flute_max(x,y) ((x)>(y)?(x):(y))\n#define flute_min(x,y) ((x)<(y)?(x):(y))\n#define flute_abs(x) ((x)<0?(-x):(x))\n#define ADIFF(x,y) ((x)>(y)?(x-y):(y-x))  // Absolute difference\n"
  },
  {
    "path": "src/flute/flute_mst.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <limits.h>\n#include <math.h>\n#include <string.h>\n#include <assert.h>\n#include \"dl.h\"\n#include \"flute.h\"\n\n#include \"mst2.h\"\n\n#define INFNTY INT_MAX\n\n#define D2M D2(1)     // Max net degree that flute_mr will handle\n#define MR_FOR_SMALL_CASES_ONLY 1\n#if MR_FOR_SMALL_CASES_ONLY\n#define MAXPART D2M    // max partition of an MST\n#define MAXT (D2M/D*2)\n#else\n#define MAXPART (d/9*2) //(MAXD/THD*2) // max partition of an MST\n#define MAXPART2 ((t1.deg+t2.deg)/9*2)\n#define MAXT (d/5)\n#endif\n\nint D3=INFNTY;\n\nint FIRST_ROUND=2; // note that num of total rounds = 1+FIRST_ROUND\nint EARLY_QUIT_CRITERIA=1;\n\n#define DEFAULT_QSIZE (3+flute_min(d,1000))\n\n#define USE_HASHING 1\n#if USE_HASHING\n#define new_ht 1\n//int new_ht=1;\ndl_t ht[D2M+1]; // hash table of subtrees indexed by degree\n#endif\n\nunsigned int curr_mark=0;\n\nTree wmergetree(Tree t1, Tree t2, int *order1, int *order2, DTYPE cx, DTYPE cy, int acc);\nTree xmergetree(Tree t1, Tree t2, int *order1, int *order2, DTYPE cx, DTYPE cy);\nvoid color_tree(Tree t, int *color);\nint longest_path_edge(int i, int j, int *e, int *p, int *es);\nvoid preprocess_edges(int num_edges, int *edges, DTYPE *len,\n\t\t      int *e, int *p, int *es);\n\n#define init_queue(q) { q[1] = 2; }\nvoid enqueue(int **q, int e)\n{\n  int _qsize;\n  if ((*q)[0]==(*q)[1]) {\n    _qsize=2*((*q)[0]+1);\n    (*q)=(int*)realloc((*q), _qsize*sizeof(int));\n    (*q)[0]=_qsize;\n  }\n  (*q)[(*q)[1]++]=e;\n}\n\n#define MAX_HEAP_SIZE (MAXD*2)\nDTYPE **hdist;\ntypedef struct node_pair_s { // pair of nodes representing an edge\n  int node1, node2;\n} node_pair;\nnode_pair *heap; //heap[MAXD*MAXD];\nint heap_size=0;\nint max_heap_size = MAX_HEAP_SIZE;\n\nint in_heap_order(int e1, int e2)\n{\n  if (hdist[heap[e1].node1][heap[e1].node2] <\n      hdist[heap[e2].node1][heap[e2].node2]) {\n    return 1;\n  } else {\n    return 0;\n  }\n}\n\nvoid sift_up(int i)\n{\n  node_pair tmp;\n  int j;\n\n  for (j=i/2; j>=1 && in_heap_order(i, j); i=j, j/=2) {\n    tmp = heap[j];\n    heap[j] = heap[i];\n    heap[i] = tmp;\n  }\n}\n\nvoid sift_down(int i)\n{\n  int left, right, j;\n  node_pair tmp;\n\n  left = i*2;\n  right = left+1;\n\n  while (left <= heap_size) {\n    if (left == heap_size || in_heap_order(left, right)) {\n      j = left;\n    } else {\n      j = right;\n    }\n    if (in_heap_order(j, i)) {\n      tmp = heap[j];\n      heap[j] = heap[i];\n      heap[i] = tmp;\n      i = j;\n      left = i*2;\n      right = left+1;\n    } else {\n      break;\n    }\n  }\n}\n\nvoid insert_heap(node_pair *np)\n{\n  if (heap_size >= max_heap_size) {\n    max_heap_size *= 2;\n    heap = (node_pair*)realloc(heap, sizeof(node_pair)*(max_heap_size+1));\n  }\n  heap[++heap_size] = *np;\n  sift_up(heap_size);\n}\n\nvoid extract_heap(node_pair *np)\n{\n  // caller has to make sure heap is not empty\n  *np = heap[1];\n  heap[1] = heap[heap_size--];\n  sift_down(1);\n}\n\nvoid init_param()\n{\n  int i;\n\n  heap = (node_pair*)malloc(sizeof(node_pair)*(max_heap_size+1));\n}\n\nTree reftree;  // reference for qsort\nint cmp_branch(const void *a, const void *b) {\n  int n;\n  DTYPE x1, x2, x3;\n\n  x1 = reftree.branch[*(int*)a].x;\n  n = reftree.branch[*(int*)a].n;\n  x3 = reftree.branch[n].x;\n  if (x3 < x1) x1=x3;\n\n  x2 = reftree.branch[*(int*)b].x;\n  n = reftree.branch[*(int*)b].n;\n  x3 = reftree.branch[n].x;\n  if (x3 < x2) x2=x3;\n\n  return (x1 <= x2) ? -1 : 1;\n}\n\nvoid update_dist2(Tree t, DTYPE **dist, DTYPE longest,\n\t\t  int *host, int *min_node1, int *min_node2,\n\t\t  int **nb)\n{\n  int i, j, m, n, dd, node1, node2, node3, node4, p1, p2, pi, pn;\n  DTYPE min_dist, smallest;\n  DTYPE x1, x2, x3, x4, y1, y2, y3, y4;\n  DTYPE threshold_x, threshold_y;\n  DTYPE md = dist[*min_node1][*min_node2];\n\n#if MR_FOR_SMALL_CASES_ONLY\n  int isPin_base[D2M], *isPin, id[2*D2M];\n  int u, v, b[D2M*2];\n#else\n  int *isPin_base, *isPin, *id;\n  int u, v, *b;\n\n  isPin_base = (int*)malloc(sizeof(int)*t.deg);\n  id = (int*)malloc(sizeof(int)*t.deg*2);\n  b = (int*)malloc(sizeof(int)*t.deg*2);\n#endif\n\n  isPin = &(isPin_base[0]) - t.deg;\n  dd = t.deg*2-2;\n\n  for (i=0; i<t.deg; i++) {\n    isPin_base[i] = -1;\n  }\n\n  for (i=t.deg; i<dd; i++) {\n    host[i] = -1;\n  }\n\n  for (i=0; i<t.deg; i++) {\n    n = t.branch[i].n;\n    if (isPin[n] < 0 &&\n\tt.branch[n].x == t.branch[i].x && t.branch[n].y == t.branch[i].y) {\n      isPin[n] = i;  // this steiner node coincides with a pin\n    }\n    host[i] = i;\n\n    if (isPin[n]==i) {\n      host[n] = host[i];\n    }\n\n  }\n\n  for (i=0; i<dd; i++) {\n    id[i] = i;\n  }\n\n  for (i=0; i<dd; i++) {\n    n = t.branch[i].n;\n    if (isPin[n]>=0 || n==i) {\n      continue;\n    }\n\n    if (id[i] < id[n]) {\n      id[n] = id[i];\n    } else {\n      id[i] = id[n];\n    }\n\n  }\n\n  for (i=0; i<dd; i++) {\n    while (id[i]!=id[id[i]]) {\n      id[i] = id[id[i]];\n    }\n  }\n\n  x1 = y1 = INFNTY;\n  x2 = y2 = 0;\n  for (i=0; i<t.deg; i++) {\n    x1 = flute_min(x1, t.branch[i].x);\n    y1 = flute_min(y1, t.branch[i].y);\n    x2 = flute_max(x2, t.branch[i].x);\n    y2 = flute_max(y2, t.branch[i].y);\n  }\n\n  threshold_x = (x2 - x1)/4;\n  threshold_y = (y2 - y1)/4;\n  threshold_x = flute_min(threshold_x, longest);\n  threshold_y = flute_min(threshold_y, longest);\n\n  for (i=0; i<dd; i++) {\n    b[i] = i;\n  }\n  reftree = t;\n  qsort(b, dd, sizeof(int), cmp_branch);\n\n  for (u=0; u<dd; u++) {\n    i = b[u];\n    n = t.branch[i].n;\n    node1 = host[i];\n    node2 = host[n];\n    if (node1 < 0 && node2 < 0) {\n      continue;\n    }\n    if (t.branch[i].x <= t.branch[n].x) {\n      x3 = t.branch[i].x;\n      x4 = t.branch[n].x;\n    } else {\n      x3 = t.branch[n].x;\n      x4 = t.branch[i].x;\n    }\n    if (t.branch[i].y <= t.branch[n].y) {\n      y3 = t.branch[i].y;\n      y4 = t.branch[n].y;\n    } else {\n      y3 = t.branch[n].y;\n      y4 = t.branch[i].y;\n    }\n\n    for (v=u+1; v<dd; v++) {\n      j=b[v];\n      if (id[i]==id[j]) { // in the same connecting subtree\n\tcontinue;\n      }\n      if (ADIFF(t.branch[i].x, t.branch[j].x)>threshold_x ||\n\t  ADIFF(t.branch[i].y, t.branch[j].y)>threshold_y)\n\tcontinue;\n      m = t.branch[j].n;\n      node3 = host[j];\n      node4 = host[m];\n      if (node3 < 0 && node4 < 0) {\n\tcontinue;\n      }\n\n      if (t.branch[j].x <= t.branch[m].x) {\n\tx1 = t.branch[j].x;\n\tx2 = t.branch[m].x;\n      } else {\n\tx1 = t.branch[m].x;\n\tx2 = t.branch[j].x;\n      }\n      if (t.branch[j].y <= t.branch[m].y) {\n\ty1 = t.branch[j].y;\n\ty2 = t.branch[m].y;\n      } else {\n\ty1 = t.branch[m].y;\n\ty2 = t.branch[j].y;\n      }\n\n      if (x2 < x3) {\n\tmin_dist = x3 - x2;\n      } else if (x4 < x1) {\n\tmin_dist = x1 - x4;\n      } else {\n\tmin_dist = 0;\n      }\n\n      if (min_dist >= threshold_x) {\n\tbreak;\n      }\n\n      if (y2 < y3) {\n\tmin_dist += y3 - y2;\n      } else if (y4 < y1) {\n\tmin_dist += y1 - y4;\n      }\n\n      if (min_dist >= longest) {\n\tcontinue;\n      }\n\n      p1 = (node1 < 0) ? node2 : ((node2 < 0) ? node1 : -1);\n      p2 = (node3 < 0) ? node4 : ((node4 < 0) ? node3 : -1);\n\n      if (p1 >= 0 && p2 < 0) {\n\tdist[p1][node3] =\n\t  ADIFF(t.branch[p1].x, t.branch[node3].x) +\n\t  ADIFF(t.branch[p1].y, t.branch[node3].y);\n\tdist[p1][node4] =\n\t  ADIFF(t.branch[p1].x, t.branch[node4].x) +\n\t  ADIFF(t.branch[p1].y, t.branch[node4].y);\n\tp2 = (dist[p1][node3] <= dist[p1][node4]) ? node3 : node4;\n      } else if (p1 < 0 && p2 >= 0) {\n\tdist[node1][p2] =\n\t  ADIFF(t.branch[node1].x, t.branch[p2].x) +\n\t  ADIFF(t.branch[node1].y, t.branch[p2].y);\n\tdist[node2][p2] =\n\t  ADIFF(t.branch[node2].x, t.branch[p2].x) +\n\t  ADIFF(t.branch[node2].y, t.branch[p2].y);\n\tp1 = (dist[node1][p2] <= dist[node2][p2]) ? node1 : node2;\n      } else if (p1 < 0 && p2 < 0) {\n\t// all 4 nodes are real, pick the closest pair\n\n\tdist[node1][node3] =\n\t  ADIFF(t.branch[node1].x, t.branch[node3].x) +\n\t  ADIFF(t.branch[node1].y, t.branch[node3].y);\n\tdist[node1][node4] =\n\t  ADIFF(t.branch[node1].x, t.branch[node4].x) +\n\t  ADIFF(t.branch[node1].y, t.branch[node4].y);\n\tdist[node2][node3] =\n\t  ADIFF(t.branch[node2].x, t.branch[node3].x) +\n\t  ADIFF(t.branch[node2].y, t.branch[node3].y);\n\tdist[node2][node4] =\n\t  ADIFF(t.branch[node2].x, t.branch[node4].x) +\n\t  ADIFF(t.branch[node2].y, t.branch[node4].y);\n\n\tp1 = node1;\n\tp2 = node3;\n\tsmallest = dist[p1][p2];\n\n\tif (dist[node2][node3] < smallest) {\n\t  p1 = node2;\n\t  smallest = dist[p1][p2];\n\t}\n\tif (dist[node1][node4] < smallest) {\n\t  p1 = node1;\n\t  p2 = node4;\n\t  smallest = dist[p1][p2];\n\t}\n\tif (dist[node2][node4] < smallest) {\n\t  p1 = node2;\n\t  p2 = node4;\n\t  smallest = dist[p1][p2];\n\t}\n      } else {\n\tdist[p1][p2] =\n\t  ADIFF(t.branch[p1].x, t.branch[p2].x) +\n\t  ADIFF(t.branch[p1].y, t.branch[p2].y);\n      }\n\n      if (min_dist < dist[p1][p2]) {\n\tdist[p1][p2] = dist[p2][p1] = min_dist;\n\tenqueue(&nb[p1], p2);\n\tenqueue(&nb[p2], p1);\n\n\tif (min_dist < md) {\n\t  md = min_dist;\n\t  *min_node1 = p1;\n\t  *min_node2 = p2;\n\t}\n      }\n    }\n  }\n\n#if !(MR_FOR_SMALL_CASES_ONLY)\n  free(isPin_base); free(id); free(b);\n#endif\n}\n\nvoid mst_from_heap(int d, DTYPE **dist, int node1, int node2, int **nb,\n\t\t   int *edges, int *tree_id)\n{\n  int i, j, itr, idx;\n  node_pair e;\n\n  hdist = dist;\n  heap_size=0;\n\n  for (i=0; i<d; i++) {\n    tree_id[i] = 0;\n  }\n\n  tree_id[node1] = 1;\n  tree_id[node2] = 1;\n  e.node1 = edges[0] = node1;\n  e.node2 = edges[1] = node2;\n  idx = 2;\n\n  insert_heap(&e);\n\n  for (j=nb[node1][1]-1; j>1; j--) {\n    i=nb[node1][j];\n    if (tree_id[i]) continue;\n    {\n      e.node2 = i;\n      insert_heap(&e);\n    }\n  }\n  for (itr=d-2; itr>=1; itr--) {\n    e.node1 = node2;\n\n    for (j=nb[node2][1]-1; j>1; j--) {\n      i=nb[node2][j];\n      if (tree_id[i]) continue;\n      {\n\te.node2 = i;\n\tinsert_heap(&e);\n      }\n    }\n\n    do {\n      //assert(heap_size>0);\n      //extract_heap(&e);\n      e = heap[1];\n      while (tree_id[heap[heap_size].node2]) {\n\theap_size--;\n      }\n      heap[1] = heap[heap_size--];\n      sift_down(1);\n      node2 = e.node2;\n    } while (tree_id[node2]);\n    node1 = e.node1;\n    tree_id[node2] = tree_id[node1];\n    edges[idx++] = node1;\n    edges[idx++] = node2;\n  }\n  //assert(idx==2*d-2);\n}\n\nvoid build_rmst(long d, DTYPE *x, DTYPE *y, int *edges, int *inMST)\n{\n  int i, j, idx, n;\n  int *map = (int*)calloc(d, sizeof(int));\n  Point *pt = (Point*)calloc( 4*d, sizeof(Point) );\n  long *parent = (long*)calloc( 4*d, sizeof(long) );\n  long *par = (long*)calloc( 4*d, sizeof(long) );\n  int *size = (int*)calloc(d, sizeof(int));\n\n  for (i=0; i<d; i++) {\n    pt[i].x = x[i];\n    pt[i].y = y[i];\n    parent[i] = par[i] = -1;\n    size[i] = 1;\n    inMST[i] = 0;\n  }\n\n  map[0]=0;\n  for (i=n=1; i<d; i++) {\n    if (x[i]!=x[i-1] || y[i]!=y[i-1]) {\n      pt[n].x = pt[i].x;\n      pt[n].y = pt[i].y;\n      map[n] = i;\n      n++;\n    } else {\n      parent[i] = i-1;\n    }\n  }\n\n  //mst2( d, pt, parent );\n  mst2_package_init(n);\n\n  mst2( n, pt, par );\n\n  mst2_package_done();\n\n  /* special treatment for duplicated points not filtered in previous loop */\n  for (i=1; i<n; i++) {\n    if (par[i]<0) {\n      for (j=n-1; j>=0; j--) {\n\tif (pt[j].x==pt[i].x && pt[j].y==pt[i].y && par[j]>=0) {\n\t  par[i]=j;\n\t  break;\n\t}\n      }\n    }\n  }\n\n  for (i=0; i<n; i++) {\n    parent[map[i]] = map[par[i]];\n  }\n\n  for (i=0; i<d; i++) {\n    //assert(parent[i]>=0);\n    size[parent[i]]++;\n  }\n\n  idx = 2*d-3;\n  for (i=0; i<d; i++) {\n    if (inMST[i]) continue;\n    j = i;\n    while (size[j]<=1 && idx>0) {\n      //assert(!inMST[j]);\n      inMST[j] = 1;\n      edges[idx--] = j;\n      edges[idx--] = j = parent[j];\n      size[j]--;\n    }\n  }\n  //assert(idx==-1);\n\n  inMST[edges[0]]=1;\n\n  free(pt);\n  free(map);\n  free(parent);\n  free(par);\n  free(size);\n}\n\n\n/* cached version */\nTree flutes_c(int d, DTYPE *xs, DTYPE *ys, int *s, int acc)\n{\n  int i;\n  //int orig_ht_flag;\n  Tree t, tdup;\n\n#if USE_HASHING\n  dl_forall(Tree, ht[d], t) {\n    for (i=0; i<d; i++) {\n      if (t.branch[i].y != ys[i] || t.branch[i].x != xs[s[i]]) {\n\tbreak;\n      }\n    }\n    if (i >= d) { // found a match\n      tdup = t;\n      tdup.branch = (Branch*)malloc(sizeof(Branch)*(2*d-2));\n      for (i=2*d-3; i>=0; i--) {\n\ttdup.branch[i] = t.branch[i];\n      }\n      return tdup;\n    }\n  } dl_endfor;\n\n  //orig_ht_flag = new_ht;\n  //new_ht = 0;\n#endif\n\n  t = flutes_LMD(d, xs, ys, s, acc);\n\n#if USE_HASHING\n  //new_ht = orig_ht_flag;\n\n  tdup = t;\n  tdup.branch = (Branch*)malloc(sizeof(Branch)*(2*d-2));\n  for (i=2*d-3; i>=0; i--) {\n    tdup.branch[i] = t.branch[i];\n  }\n  dl_prepend(Tree, ht[d], tdup);\n#endif\n\n  return t;\n}\n\nTree flute_mr(int d, DTYPE *xs, DTYPE *ys, int *s,\n\t      int acc, int rounds, DTYPE **dist,\n\t      DTYPE *threshold_x, DTYPE *threshold_y,\n\t      DTYPE *threshold,\n\t      int *best_round,\n\t      int *min_node1, int *min_node2,\n\t      int **nb)\n{\n  int i, j, k, m, n, itr, node1, node2;\n  DTYPE min_dist, longest;\n  DTYPE dist1, dist2;\n  Tree t, best_t, *subtree, ttmp;\n  DTYPE min_x, max_x;\n\n#if MR_FOR_SMALL_CASES_ONLY\n  int num_subtree, subroot[MAXPART], suproot[MAXPART], isSuperRoot[D2M];\n  int tree_id[D2M], tid, tree_size[D2M], edges[2*D2M];\n  int idx[MAXPART], offset[MAXPART], *order[MAXT], order_base[MAXT*D2M];\n  DTYPE x[D2M+MAXPART], y[D2M+MAXPART];\n  int new_s[D2M+MAXPART], si[D2M], xmap[D2M+MAXPART];\n#else\n  int num_subtree, *subroot, *suproot, *isSuperRoot;\n  int *tree_id, tid, *tree_size, *edges;\n  int *idx, *offset, **order, *order_base;\n  DTYPE *x, *y;\n  int *new_s, *si, *xmap;\n\n  subroot = (int*)malloc(sizeof(int)*MAXPART);\n  suproot = (int*)malloc(sizeof(int)*MAXPART);\n  idx = (int*)malloc(sizeof(int)*MAXPART);\n  offset = (int*)malloc(sizeof(int)*MAXPART);\n  order = (int**)malloc(sizeof(int*)*MAXT);\n\n  isSuperRoot = (int*)malloc(sizeof(int)*d);\n  tree_id = (int*)malloc(sizeof(int)*d);\n  tree_size = (int*)malloc(sizeof(int)*d);\n  edges = (int*)malloc(sizeof(int)*d*2);\n  order_base = (int*)malloc(sizeof(int)*d*MAXT);\n  new_s = (int*)malloc(sizeof(int)*(d+MAXPART));\n  si = (int*)malloc(sizeof(int)*d);\n  xmap = (int*)malloc(sizeof(int)*(d+MAXPART));\n  x = (DTYPE*)malloc(sizeof(DTYPE)*(d+MAXPART));\n  y = (DTYPE*)malloc(sizeof(DTYPE)*(d+MAXPART));\n#endif\n\n#if USE_HASHING\n  if (new_ht) {\n    for (i=0; i<=d; i++) {\n      ht[i] = dl_alloc();\n    }\n  }\n#endif\n\n  best_t.branch = NULL;\n  best_t.length = INFNTY;\n\n  for (i=0; i<MAXT; i++) {\n    //order[i] = &(order_base[i*D2(acc)]);\n    order[i] = &(order_base[i*d]);\n  }\n\n  while (rounds>=0) {\n    for (i=0; i<d; i++) {\n      x[i] = xs[s[i]];\n      y[i] = ys[i];\n      isSuperRoot[i] = 0;\n    }\n\n    if (rounds==FIRST_ROUND) {\n      build_rmst((long)d, x, y, edges, tree_id);\n      for (i=0; i<d; i++) dist[i][i]=0;\n    } else {\n      mst_from_heap(d, dist, *min_node1, *min_node2, nb, edges, tree_id);\n    }\n\n    if (rounds!=0) {\n      longest = 0;\n      for (i=0; i<d; i++) {\n\tinit_queue(nb[i]);\n      }\n    }\n\n    for (i=0; i<2*d-2; ) {\n      node1 = edges[i++];\n      node2 = edges[i++];\n      if (rounds!=0) {\n\tenqueue(&nb[node1], node2);\n\tenqueue(&nb[node2], node1);\n\tdist[node1][node2] = dist[node2][node1] =\n\t  ADIFF(x[node1], x[node2]) + ADIFF(y[node1], y[node2]);\n\tif (longest < dist[node1][node2]) {\n\t  longest = dist[node1][node2];\n\t}\n      }\n    }\n\n    for (i=0; i<d; i++) {\n      tree_size[i] = 1;  // the node itself\n    }\n\n    suproot[0] = subroot[0] = edges[0];\n    num_subtree=1;\n\n    for (i=2*d-3; i>=0; ) {\n      node2 = edges[i--];\n      node1 = edges[i--];\n      j = tree_size[node1]+tree_size[node2];\n      //Chris\n      if (j >= TAU(acc)) {\n\tisSuperRoot[node1] = 1;\n\tsuproot[num_subtree] = node1;\n\tsubroot[num_subtree++] = node2;\n      } else {\n\ttree_size[node1] = j;\n      }\n    }\n\n    //assert(num_subtree<=MAXT);\n\n    for (i=1; i<num_subtree; i++) {\n      tree_id[subroot[i]] = i+1;\n      tree_size[subroot[i]] += 1;  // to account for the link to parent tree\n    }\n\n    for (i=0; i<2*d-2; ) {\n      node1 = edges[i++];\n      node2 = edges[i++];\n      if (tree_id[node2]==1) { // non-root node\n\ttree_id[node2] = tree_id[node1];\n      }\n    }\n\n    // Find inverse si[] of s[]\n    for (i=0; i<d; i++)\n      si[s[i]] = i;\n\n    offset[1] = 0;\n    for (i=1; i<num_subtree; i++) {\n      offset[i+1] = offset[i] + tree_size[subroot[i-1]];\n    }\n    //assert(offset[num_subtree]==d+num_subtree-1-tree_size[subroot[num_subtree-1]]);\n\n    for (i=0; i<=num_subtree; i++)\n      idx[i] = 0;\n\n    for (i=0; i<d; i++) {\n      tid = tree_id[si[i]];\n      j = idx[tid]++;\n      x[offset[tid]+j] = xs[i];\n      xmap[i] = j;\n\n      if (isSuperRoot[si[i]]) {\n\tfor (k=1; k<num_subtree; k++) {\n\t  if (suproot[k]==si[i]) {\n\t    tid = k+1;\n\t    j = idx[tid]++;\n\t    x[offset[tid]+j] = xs[i];\n\t    xmap[d-1+tid] = j;\n\t  }\n\t}\n      }\n    }\n\n    for (i=0; i<=num_subtree; i++)\n      idx[i] = 0;\n\n    for (i=0; i<d; i++) {\n      tid = tree_id[i];\n      j = idx[tid]++;\n      y[offset[tid]+j] = ys[i];\n      new_s[offset[tid]+j] = xmap[s[i]];\n      order[tid-1][j] = i;\n\n      if (isSuperRoot[i]) {\n\tfor (k=1; k<num_subtree; k++) {\n\t  if (suproot[k]==i) {\n\t    tid = k+1;\n\t    j = idx[tid]++;\n\t    y[offset[tid]+j] = ys[i];\n\t    new_s[offset[tid]+j] = xmap[d-1+tid];\n\t    order[tid-1][j] = i;\n\t  }\n\t}\n      }\n    }\n\n    subtree = (Tree*)malloc(num_subtree*sizeof(Tree));\n    for (i=1; i<=num_subtree; i++) {\n      if (tree_size[subroot[i-1]] <= 1) {\n\tsubtree[i-1].deg = 0;\n\tcontinue;\n      }\n\n      t = flutes_c(tree_size[subroot[i-1]], x+offset[i], y+offset[i],\n\t\t   new_s+offset[i], acc);\n\n      subtree[i-1] = t;\n    }\n\n\n    for (i=1; i<num_subtree; i++) {\n      //assert(tree_id[suproot[i]] != tree_id[subroot[i]]);\n\n      t = wmergetree(subtree[tree_id[suproot[i]]-1],\n\t\t     subtree[tree_id[subroot[i]]-1],\n\t\t     order[tree_id[suproot[i]]-1],\n\t\t     order[tree_id[subroot[i]]-1],\n\t\t     xs[s[suproot[i]]], ys[suproot[i]], acc);\n\n      subtree[tree_id[subroot[i]]-1].deg = 0;\n      subtree[tree_id[suproot[i]]-1] = t;\n    }\n\n    t = subtree[0];\n    free(subtree);\n\n    if (best_t.length < t.length) {\n      if (*best_round-rounds >= EARLY_QUIT_CRITERIA) {\n\tif (t.branch) {\n\t  free(t.branch);\n\t}\n\tbreak;\n      }\n    } else if (best_t.length == t.length) {\n      *best_round = rounds;\n    } else if (best_t.length > t.length) {\n      if (best_t.branch) {\n\tfree(best_t.branch);\n      }\n      best_t = t;\n      *best_round = rounds;\n    }\n\n    if (rounds > 0) {\n      for (i=0; i<d; i++) {\n\tx[i] = xs[s[i]];\n\ty[i] = ys[i];\n      }\n\n      *min_node1 = edges[0];\n      *min_node2 = edges[1];\n\n      update_dist2(t, dist, longest, edges, min_node1, min_node2, nb);\n    }\n\n    if (t.branch != 0 && best_t.branch != t.branch) {\n      free(t.branch);\n    }\n\n    rounds--;\n  }\n\n#if !(MR_FOR_SMALL_CASES_ONLY)\n  free(subroot); free(suproot); free(idx); free(offset); free(order);\n  free(isSuperRoot); free(tree_id); free(tree_size); free(edges);\n  free(order_base); free(new_s); free(si); free(xmap); free(x); free(y);\n#endif\n\n#if USE_HASHING\n  if (new_ht) {\n    for (i=0; i<=d; i++) {\n      dl_forall(Tree, ht[i], ttmp) {\n\tfree(ttmp.branch);\n      } dl_endfor;\n      dl_free(ht[i]);\n    }\n  }\n#endif\n\n  return best_t;\n}\n\nTree flute_am(int d, DTYPE *xs, DTYPE *ys, int *s, int acc,\n\t      DTYPE *threshold_x, DTYPE *threshold_y, DTYPE *threshold)\n{\n  int i, j, k, m, n, itr, node1, node2;\n  DTYPE smallest_gap, gap;\n  Tree t, t0, *subtree;\n  int prev_effort;\n  /*\n  int num_subtree, subroot[MAXPART], suproot[MAXPART], isSuperRoot[MAXD];\n  int tree_id[MAXD], tid, tree_size[MAXD], edges[2*MAXD];\n  int idx[MAXPART], offset[MAXPART], *order[MAXT],\n        order_base[MAXD+10]; //order_base[MAXT*MAXD];\n  DTYPE x[MAXD+MAXPART], y[MAXD+MAXPART];\n  int new_s[MAXD+MAXPART], si[MAXD], xmap[MAXD+MAXPART];\n  */\n  DTYPE *x, *y;\n  int num_subtree, subroot[3], suproot[3], *isSuperRoot;\n  int *tree_id, tid, *tree_size, *edges;\n  int idx[3], offset[3], *order[3], *order_base;\n  int *new_s, *si, *xmap;\n\n  int maxd = d+1;\n  x = (DTYPE*)malloc(sizeof(DTYPE)*(maxd+3));\n  y = (DTYPE*)malloc(sizeof(DTYPE)*(maxd+3));\n  isSuperRoot = (int*)malloc(sizeof(int)*maxd);\n  tree_id = (int*)malloc(sizeof(int)*maxd);\n  tree_size = (int*)malloc(sizeof(int)*maxd);\n  edges = (int*)malloc(sizeof(int)*maxd*2);\n  order_base = (int*)malloc(sizeof(int)*(maxd+10));\n  new_s = (int*)malloc(sizeof(int)*(maxd+3));\n  si = (int*)malloc(sizeof(int)*maxd);\n  xmap = (int*)malloc(sizeof(int)*(maxd+3));\n\n  /*\n  for (i=0; i<MAXT; i++) {\n    order[i] = &(order_base[i*MAXD]);\n  }\n  */\n\n  for (i=0; i<d; i++) {\n    x[i] = xs[s[i]];\n    y[i] = ys[i];\n    isSuperRoot[i] = 0;\n  }\n\n  build_rmst((long)d, x, y, edges, tree_id);\n\n  for (i=0; i<d; i++) {\n    tree_size[i] = 1;  // the node itself\n  }\n\n  suproot[0] = subroot[0] = edges[0];\n  num_subtree=1;\n\n  /*\n  for (i=2*d-3; i>=0; ) {\n    node2 = edges[i--];\n    node1 = edges[i--];\n    j = tree_size[node1]+tree_size[node2];\n    //if (j >= d/2) {\n    if (j >= d/2 && num_subtree<2) {\n      isSuperRoot[node1] = 1;\n      suproot[num_subtree] = node1;\n      subroot[num_subtree++] = node2;\n    } else {\n      tree_size[node1] = j;\n    }\n  }\n  */\n\n  for (i=2*d-3; i>=0; ) {\n    node2 = edges[i--];\n    node1 = edges[i--];\n    tree_size[node1] += tree_size[node2];\n  }\n\n  j = 0;\n  smallest_gap = ADIFF(tree_size[j], d/2);\n  for (i=1; i<d; i++) {\n    gap = ADIFF(tree_size[i], d/2);\n    if (gap < smallest_gap) {\n      j = i;\n      smallest_gap = gap;\n    }\n  }\n\n  for (i=2*d-3; i>=0; ) {\n    node2 = edges[i--];\n    node1 = edges[i--];\n    if (node2==j) {\n      isSuperRoot[node1] = 1;\n      suproot[num_subtree] = node1;\n      subroot[num_subtree++] = node2;\n      tree_size[subroot[0]] -= tree_size[j];\n      break;\n    }\n  }\n\n  //assert(num_subtree<=MAXT);\n\n  for (i=1; i<num_subtree; i++) {\n    tree_id[subroot[i]] = i+1;\n    tree_size[subroot[i]] += 1;  // to account for the link to parent tree\n  }\n\n  for (i=0; i<2*d-2; ) {\n    node1 = edges[i++];\n    node2 = edges[i++];\n    if (tree_id[node2]==1) { // non-root node\n      tree_id[node2] = tree_id[node1];\n    }\n  }\n\n  // Find inverse si[] of s[]\n  for (i=0; i<d; i++)\n    si[s[i]] = i;\n\n  offset[1] = 0;\n  for (i=1; i<num_subtree; i++) {\n    offset[i+1] = offset[i] + tree_size[subroot[i-1]];\n  }\n  //assert(offset[num_subtree]==d+num_subtree-1-tree_size[subroot[num_subtree-1]]);\n\n  for (i=0; i<num_subtree; i++) {\n    order[i] = &(order_base[offset[i+1]]);\n  }\n\n  for (i=0; i<=num_subtree; i++)\n    idx[i] = 0;\n\n  for (i=0; i<d; i++) {\n    tid = tree_id[si[i]];\n    j = idx[tid]++;\n    x[offset[tid]+j] = xs[i];\n    xmap[i] = j;\n\n    if (isSuperRoot[si[i]]) {\n      for (k=1; k<num_subtree; k++) {\n\tif (suproot[k]==si[i]) {\n\t  tid = k+1;\n\t  j = idx[tid]++;\n\t  x[offset[tid]+j] = xs[i];\n\t  xmap[d-1+tid] = j;\n\t}\n      }\n    }\n  }\n\n  for (i=0; i<=num_subtree; i++)\n    idx[i] = 0;\n\n  for (i=0; i<d; i++) {\n    tid = tree_id[i];\n    j = idx[tid]++;\n    y[offset[tid]+j] = ys[i];\n    new_s[offset[tid]+j] = xmap[s[i]];\n    order[tid-1][j] = i;\n\n    if (isSuperRoot[i]) {\n      for (k=1; k<num_subtree; k++) {\n\tif (suproot[k]==i) {\n\t  tid = k+1;\n\t  j = idx[tid]++;\n\t  y[offset[tid]+j] = ys[i];\n\t  new_s[offset[tid]+j] = xmap[d-1+tid];\n\t  order[tid-1][j] = i;\n\t}\n      }\n    }\n  }\n\n  subtree = (Tree*)malloc(num_subtree*sizeof(Tree));\n  for (i=1; i<=num_subtree; i++) {\n    if (tree_size[subroot[i-1]] <= 1) {\n      subtree[i-1].deg = 0;\n      continue;\n    }\n\n    t = flutes_ALLD(tree_size[subroot[i-1]], x+offset[i], y+offset[i],\n\t\t    new_s+offset[i], acc);\n    subtree[i-1] = t;\n  }\n\n  for (i=1; i<num_subtree; i++) {\n    //assert(tree_id[suproot[i]] != tree_id[subroot[i]]);\n\n    t = xmergetree(subtree[tree_id[suproot[i]]-1],\n\t\t   subtree[tree_id[subroot[i]]-1],\n\t\t   order[tree_id[suproot[i]]-1],\n\t\t   order[tree_id[subroot[i]]-1],\n\t\t   xs[s[suproot[i]]], ys[suproot[i]]);\n\n    subtree[tree_id[subroot[i]]-1].deg = 0;\n    subtree[tree_id[suproot[i]]-1] = t;\n  }\n\n  t0 = subtree[0];\n  free(subtree);\n\n  t = t0;\n\n  free(x); free(y); free(isSuperRoot); free(tree_id); free(tree_size);\n  free(edges); free(order_base); free(new_s); free(si); free(xmap);\n\n  return t;\n}\n\nTree flutes_HD(int d, DTYPE *xs, DTYPE *ys, int *s, int acc)\n{\n  int i, A, orig_D3;\n  Tree t;\n  //DTYPE *dist[MAXD], *dist_base;\n  DTYPE **dist, *dist_base;\n  DTYPE threshold, threshold_x, threshold_y;\n  int best_round, min_node1, min_node2;\n  int **nb;\n  DTYPE prev_len;\n\n  //Chris\n  if (d<=D2(acc)) {\n      if (acc <= 6) {\n          FIRST_ROUND = 0;\n          A = acc;\n      }\n      else {\n          FIRST_ROUND = acc-6;\n          A = 6 + ((acc-5)/4)*2;  // Even A is better\n      }\n      EARLY_QUIT_CRITERIA = (int) (0.75*FIRST_ROUND + 0.5);\n\n      dist_base = (DTYPE*)malloc(d*d*sizeof(DTYPE));\n      dist = (DTYPE**)malloc(d*sizeof(DTYPE*));\n      nb = (int**)malloc(d*sizeof(int*));\n      for (i=0; i<d; i++) {\n\tdist[i] = &(dist_base[i*d]);\n\tnb[i] = (int*)malloc(DEFAULT_QSIZE*sizeof(int));\n\tnb[i][0] = DEFAULT_QSIZE;\n\tnb[i][1] = 2; // queue head\n      }\n\n      t = flute_mr(d, xs, ys, s, A, FIRST_ROUND,\n\t\t   dist, &threshold_x, &threshold_y, &threshold,\n\t\t   &best_round, &min_node1,\n\t\t   &min_node2, nb);\n\n      free(dist_base);\n      free(dist);\n      for (i=0; i<d; i++) {\n\tfree(nb[i]);\n      }\n      free(nb);\n  }\n  else {\n      A = acc;\n      orig_D3 = D3;\n      if (orig_D3 >= INFNTY && d > 1000) {\n\tD3 = (d <= 10000) ? 1000 : 10000;\n      }\n      t = flute_am(d, xs, ys, s, A,\n\t\t   &threshold_x, &threshold_y, &threshold);\n      if (orig_D3 >= INFNTY) {\n\tD3 = orig_D3;\n      }\n  }\n\n  return t;\n}\n\nint pickWin(Tree t, DTYPE cx, DTYPE cy, int inWin[])\n{\n#if MR_FOR_SMALL_CASES_ONLY\n  int i, j, n, dd, cnt, stack[D2M*2], top=0, prev, curr, next;\n  int isPin_base[D2M], *isPin, nghbr_base[D2M], *nghbr, q[2*D2M];\n#else\n  int i, j, n, dd, cnt, *stack, top=0, prev, curr, next;\n  int *isPin_base, *isPin, *nghbr_base, *nghbr, *q;\n\n  stack = (int*)malloc(sizeof(int)*t.deg*2);\n  isPin_base = (int*)malloc(sizeof(int)*t.deg);\n  nghbr_base = (int*)malloc(sizeof(int)*t.deg);\n  q = (int*)malloc(sizeof(int)*t.deg*2);\n#endif\n\n  if (t.deg <= 3) {\n    for (i=0; i<t.deg*2-2; i++) {\n      inWin[i] = 1;\n    }\n#if !(MR_FOR_SMALL_CASES_ONLY)\n    free(stack); free(isPin_base); free(nghbr_base); free(q);\n#endif\n    return t.deg;\n  }\n\n  memset(nghbr_base, 0, sizeof(int)*t.deg);\n  nghbr = &(nghbr_base[0]) - t.deg;\n  isPin = &(isPin_base[0]) - t.deg;\n\n  for (i=0; i<t.deg; i++) {\n    isPin_base[i] = -1;\n  }\n\n  dd = t.deg*2-2;\n  for (i=0; i<dd; i++) {\n    inWin[i] = 0;\n    nghbr[t.branch[i].n]++;\n  }\n\n  for (i=t.deg+1; i<dd; i++) {\n    nghbr[i] += nghbr[i-1];\n  }\n  nghbr[dd] = nghbr[dd-1];\n\n  for (i=0; i<dd; i++) {\n    q[--nghbr[t.branch[i].n]] = i;\n  }\n\n  cnt = 0;\n  for (i=0; i<t.deg; i++) {\n    n = t.branch[i].n;\n    if (t.branch[n].x == t.branch[i].x && t.branch[n].y == t.branch[i].y) {\n      isPin[n] = i;  // this steiner node coincides with a pin\n    }\n    if (t.branch[i].x == cx && t.branch[i].y == cy) {\n      inWin[i] = 1;\n      cnt++;\n      if (isPin[n]==i) {\n\tinWin[n] = 1;\n\tstack[top++] = t.branch[n].n;\n\tfor (j=nghbr[n]; j<nghbr[n+1]; j++) {\n\t  if (q[j]==i) {\n\t    continue;\n\t  }\n\t  stack[top++] = q[j];\n\t}\n      } else {\n\tstack[top++] = n;\n      }\n    }\n  }\n  //assert(top > 0);\n\n  while (top > 0) {\n    i = stack[--top];\n    if (inWin[i]) {\n      continue;\n    }\n    inWin[i] = 1;\n    if (i < t.deg) {\n      cnt++;\n      continue;\n    }\n    n = isPin[i];\n    if (n >= 0) {\n      if (!inWin[n]) {\n\tinWin[n] = 1;\n\tcnt++;\n      }\n    } else {\n      stack[top++] = t.branch[i].n;\n      for (j=nghbr[i]; j<nghbr[i+1]; j++) {\n\tstack[top++] = q[j];\n      }\n    }\n  }\n\n  for (i=0; i<t.deg; i++) {\n    if (inWin[i]) {\n      n = t.branch[i].n;\n      if (isPin[n]!=i) {\n\tcontinue;\n      }\n      prev = n;\n      curr = t.branch[n].n;\n      next = t.branch[curr].n;\n      while (curr != next) {\n        t.branch[curr].n = prev;\n        prev = curr;\n        curr = next;\n        next = t.branch[curr].n;\n      }\n      t.branch[curr].n = prev;\n      t.branch[n].n = n;\n    }\n  }\n\n  //assert(cnt>0);\n#if !(MR_FOR_SMALL_CASES_ONLY)\n  free(stack); free(isPin_base); free(nghbr_base); free(q);\n#endif\n  return cnt;\n}\n\n/* merge tree t2 into tree t1, which have shared common nodes.  The intention\n   is to add the non-common tree nodes of t2 into t1, as well as the\n   associated steiner nodes */\nTree merge_into(Tree t1, Tree t2, int common[], int nc, int *o1, int *o2)\n{\n  Tree t;\n  DTYPE cx, cy;\n#if MR_FOR_SMALL_CASES_ONLY\n  int i, j, k, d, n, offset, map[2*D2M], reachable[2*D2M];\n  int o[D2M+MAXPART];\n#else\n  int i, j, k, d, n, offset, *map, *reachable;\n  int *o;\n\n  map = (int*)malloc(sizeof(int)*(t1.deg+t2.deg)*2);\n  reachable = (int*)malloc(sizeof(int)*(t1.deg+t2.deg)*2);\n  o = (int*)malloc(sizeof(int)*(t1.deg+t2.deg+MAXPART2));\n#endif\n\n  if (t2.deg <= nc) {\n    free(t2.branch);\n#if !(MR_FOR_SMALL_CASES_ONLY)\n    free(map); free(reachable); free(o);\n#endif\n    return t1;\n  }\n\n  t.deg = t1.deg + t2.deg - nc;\n  t.branch = (Branch *) malloc((2*t.deg-2)*sizeof(Branch));\n\n  offset = t2.deg - nc;\n\n  for (i=t1.deg; i<t1.deg*2-2; i++) {\n    t.branch[i+offset] = t1.branch[i];\n    t.branch[i+offset].n = t1.branch[i].n + offset;\n  }\n\n  memset(reachable, 0, sizeof(int)*2*t2.deg);\n  for (i=2*t2.deg-3; i>=0; i--) {\n    if (!common[i] && t2.branch[i].n!=i) {\n      reachable[t2.branch[i].n] = 1;\n    }\n  }\n\n  for (i=2*t2.deg-3; i>=0; i--) {\n    map[i] = -1;\n  }\n\n  d = t1.deg*2 - 2;\n\n  /* a slow method; could be sped up here */\n  for (i=0; i<t2.deg; i++) {\n    if (common[i]) {\n      n = t2.branch[i].n;\n      if (map[n]!=-1 || !reachable[n]) {\n\tcontinue;\n      }\n      if (t2.branch[i].x != t2.branch[n].x ||\n\t  t2.branch[i].y != t2.branch[n].y) {\n\tcontinue;\n      }\n      for (j=0; j<t1.deg; j++) {\n\tif (t1.branch[j].x == t2.branch[i].x &&\n\t    t1.branch[j].y == t2.branch[i].y) {\n\t  break;\n\t}\n      }\n      //assert(j<t1.deg);\n      n = t1.branch[j].n;\n      if (t1.branch[j].x == t1.branch[n].x &&\n\t  t1.branch[j].y == t1.branch[n].y) {\n\t/* pin j in t1 is also a steiner node */\n\tmap[i] = n;\n      } else { // create a steiner node for the common pin in t1\n\tt.branch[d+offset] = t1.branch[j];\n\tt.branch[d+offset].n += offset;\n\tt1.branch[j].n = d;\n\tmap[i] = d;\n\td++;\n\t//assert(d+offset<=t.deg*2-2);\n      }\n\n      map[t2.branch[i].n] = map[i];\n    }\n  }\n\n  for (; i<2*t2.deg-2; i++) {\n    if (map[i]==-1 && !common[i] && reachable[i]) {\n      map[i] = d++;\n      //assert(d+offset<=t.deg*2-2);\n    }\n  }\n\n  /* merge the pin nodes in the correct order */\n  j = i = k = 0;\n  while (k<t2.deg && common[k]) { k++; }\n\n  do {\n    if (k>=t2.deg) {\n      for (; i<t1.deg; i++) {\n\tt.branch[j] = t1.branch[i];\n\tt.branch[j].n = t1.branch[i].n + offset;\n\to[j] = o1[i];\n\tj++;\n      }\n    } else if (i>=t1.deg) {\n      for (; k<t2.deg; k++) {\n\tif (common[k]) {\n\t  continue;\n\t}\n\tt.branch[j] = t2.branch[k];\n\tn = t2.branch[k].n;\n\t//assert(map[n]>=t1.deg);\n\tt.branch[j].n = map[n] + offset;\n\to[j] = o2[k];\n\tj++;\n      }\n    } else if (o1[i] < o2[k]) {\n      t.branch[j] = t1.branch[i];\n      t.branch[j].n = t1.branch[i].n + offset;\n      o[j] = o1[i];\n      j++;\n      i++;\n    } else {\n      t.branch[j] = t2.branch[k];\n      n = t2.branch[k].n;\n      //assert(map[n]>=t1.deg);\n      t.branch[j].n = map[n] + offset;\n      o[j] = o2[k];\n      j++;\n      do {\n\tk++;\n      } while (k<t2.deg && common[k]);\n    }\n  }while (i<t1.deg || k<t2.deg);\n  //assert(j==t.deg);\n\n  for (i=0; i<j; i++) {\n    o1[i] = o[i];\n  }\n\n  j += t1.deg - 2;\n  for (i=t2.deg; i<2*t2.deg-2; i++) {\n    if (!common[i] && reachable[i]) {\n      t.branch[map[i]+offset] = t2.branch[i];\n      n = t2.branch[i].n;\n      //assert(map[n]>=t1.deg);\n      t.branch[map[i]+offset].n = map[n] + offset;\n      j++;\n    }\n  }\n\n  j = d+offset;\n  //assert(j <= t.deg*2-2);\n  while (j < t.deg*2-2) {\n    /* redundant steiner nodes */\n    t.branch[j] = t2.branch[0];\n    t.branch[j].n = j;\n    j++;\n  }\n\n  /*\n  for (i=0; i<t.deg; i++) {\n    assert(t.branch[i].n>=t.deg);\n  }\n  */\n\n  t.length = wirelength(t);\n\n  free(t1.branch);\n  free(t2.branch);\n\n#if !(MR_FOR_SMALL_CASES_ONLY)\n  free(map); free(reachable); free(o);\n#endif\n  return t;\n}\n\n/* simply merge two trees at their common node */\nTree smergetree(Tree t1, Tree t2, int *o1, int *o2,\n\t\tDTYPE cx, DTYPE cy)\n{\n  Tree t;\n  int d, i, j, k, n, ci, cn, mapped_cn, prev, curr, next, offset;\n#if MR_FOR_SMALL_CASES_ONLY\n  int o[D2M+MAXPART], map[2*D2M];\n#else\n  int *o, *map;\n\n  map = (int*)malloc(sizeof(int)*(t1.deg+t2.deg)*2);\n  o = (int*)malloc(sizeof(int)*(t1.deg+t2.deg+MAXPART2));\n#endif\n\n  t.deg = t1.deg + t2.deg - 1;\n  t.branch = (Branch *) malloc((2*t.deg-2)*sizeof(Branch));\n\n  offset = t2.deg - 1;\n  d = t1.deg*2-2;\n\n  for (i=0; i<t1.deg; i++) {\n    if (t1.branch[i].x==cx && t1.branch[i].y==cy) {\n      break;\n    }\n  }\n  n = t1.branch[i].n;\n  if (t1.branch[n].x==cx && t1.branch[n].y==cy) {\n    mapped_cn = n;\n  } else {\n    t.branch[d+offset] = t1.branch[i];\n    t.branch[d+offset].n += offset;\n    t1.branch[i].n = d;\n    mapped_cn = d;\n    d++;\n  }\n\n  for (i=t2.deg; i<t2.deg*2-2; i++) {\n    map[i] = -1;\n  }\n  for (i=0; i<t2.deg; i++) {\n    if (t2.branch[i].x==cx && t2.branch[i].y==cy) {\n      ci = i;\n      break;\n    }\n  }\n\n  n = t2.branch[i].n;\n\n  if (t2.branch[n].x==cx && t2.branch[n].y==cy) {\n    cn = n;\n  } else {\n    cn = i;\n  }\n\n  prev = n;\n  curr = t2.branch[n].n;\n  next = t2.branch[curr].n;\n  while (curr != next) {\n    t2.branch[curr].n = prev;\n    prev = curr;\n    curr = next;\n    next = t2.branch[curr].n;\n  }\n  t2.branch[curr].n = prev;\n  t2.branch[n].n = cn;\n\n  for (i=t2.deg; i<2*t2.deg-2; i++) {\n    if (i!=cn) {\n      map[i] = d++;\n    }\n  }\n  map[cn] = mapped_cn;\n\n  /* merge the pin nodes in the correct order */\n  j = i = k = 0;\n  if (k==ci) { k++; }\n\n  do {\n    if (k>=t2.deg) {\n      for (; i<t1.deg; i++) {\n\tt.branch[j] = t1.branch[i];\n\tt.branch[j].n = t1.branch[i].n + offset;\n\to[j] = o1[i];\n\tj++;\n      }\n    } else if (i>=t1.deg) {\n      for (; k<t2.deg; k++) {\n\tif (k==ci) {\n\t  continue;\n\t}\n\tt.branch[j] = t2.branch[k];\n\tn = t2.branch[k].n;\n\tt.branch[j].n = map[n] + offset;\n\to[j] = o2[k];\n\tj++;\n      }\n    } else if (o1[i] < o2[k]) {\n      t.branch[j] = t1.branch[i];\n      t.branch[j].n = t1.branch[i].n + offset;\n      o[j] = o1[i];\n      j++;\n      i++;\n    } else {\n      t.branch[j] = t2.branch[k];\n      n = t2.branch[k].n;\n      t.branch[j].n = map[n] + offset;\n      o[j] = o2[k];\n      j++;\n      k++;\n      if (k==ci) { k++; }\n    }\n  }while (i<t1.deg || k<t2.deg);\n  //assert(j==t.deg);\n\n  for (i=0; i<j; i++) {\n    o1[i] = o[i];\n  }\n\n  for (i=t1.deg; i<t1.deg*2-2; i++) {\n    t.branch[i+offset] = t1.branch[i];\n    t.branch[i+offset].n = t1.branch[i].n + offset;\n  }\n\n  for (i=t2.deg; i<2*t2.deg-2; i++) {\n    if (i != cn) {\n      t.branch[map[i]+offset] = t2.branch[i];\n      n = t2.branch[i].n;\n      t.branch[map[i]+offset].n = map[n] + offset;\n    }\n  }\n\n  for (i=d+offset; i<t.deg*2-2; i++) {\n    t.branch[i] = t2.branch[0];\n    t.branch[i].n = i;\n  }\n\n  free(t1.branch);\n  free(t2.branch);\n\n  t.length = wirelength(t);\n\n#if !(MR_FOR_SMALL_CASES_ONLY)\n  free(map); free(o);\n#endif\n  return t;\n}\n\n/* window-based heuristics */\nTree wmergetree(Tree t1, Tree t2, int *order1, int *order2,\n\t\tDTYPE cx, DTYPE cy, int acc)\n{\n  Tree t, t3, t4;\n#if MR_FOR_SMALL_CASES_ONLY\n  int s[D2M], inWin[2*D2M], d, d2, i, ci, n;\n  int i1, i2, o[D2M], os[D2M], si[D2M];\n  DTYPE x[D2M], y[D2M], tmp;\n#else\n  int *s, *inWin, d, d2, i, ci, n;\n  int i1, i2, *o, *os, *si;\n  DTYPE *x, *y, tmp;\n\n  s = (int*)malloc(sizeof(int)*(t1.deg+t2.deg));\n  inWin = (int*)malloc(sizeof(int)*(t1.deg+t2.deg)*2);\n  o = (int*)malloc(sizeof(int)*(t1.deg+t2.deg));\n  os = (int*)malloc(sizeof(int)*(t1.deg+t2.deg));\n  si = (int*)malloc(sizeof(int)*(t1.deg+t2.deg));\n  x = (DTYPE*)malloc(sizeof(DTYPE)*(t1.deg+t2.deg));\n  y = (DTYPE*)malloc(sizeof(DTYPE)*(t1.deg+t2.deg));\n#endif\n\n  if (t1.deg <= 0) {\n    for (i=0; i<t2.deg; i++) {\n      order1[i] = order2[i];\n    }\n#if !(MR_FOR_SMALL_CASES_ONLY)\n    free(s); free(inWin); free(o); free(os); free(si); free(x); free(y);\n#endif\n    return t2;\n  } else if (t2.deg <= 0) {\n#if !(MR_FOR_SMALL_CASES_ONLY)\n    free(s); free(inWin); free(o); free(os); free(si); free(x); free(y);\n#endif\n    return t1;\n  }\n\n  d = pickWin(t1, cx, cy, inWin);\n  d2 = pickWin(t2, cx, cy, inWin+2*t1.deg);\n  d += d2;\n\n  //if (d<t1.deg+t2.deg && t1.deg>2 && t2.deg>2) {\n  if (d<t1.deg+t2.deg) {\n    for (i=0; i<t2.deg; i++) {\n      if (t2.branch[i].x == cx && t2.branch[i].y == cy) {\n\tci = i;\n\tbreak;\n      }\n    }\n\n    d--;  // to exclude the duplicated common point (cx, cy)\n\n    n = 0;\n\n    i1 = i2 = 0;\n    while (i1<t1.deg && !inWin[i1]) { i1++; }\n    while (i2<t2.deg && (!inWin[i2+2*t1.deg] || i2==ci)) { i2++; }\n    do {\n      if (i2 >= t2.deg) {\n\tfor (; i1<t1.deg; i1++) {\n\t  if (inWin[i1]) {\n\t    x[n] = t1.branch[i1].x;\n\t    y[n] = t1.branch[i1].y;\n\t    o[n] = order1[i1];\n\t    n++;\n\t  }\n\t}\n      } else if (i1 >= t1.deg) {\n\tfor (; i2<t2.deg; i2++) {\n\t  if (inWin[i2+2*t1.deg] && i2!=ci) {\n\t    x[n] = t2.branch[i2].x;\n\t    y[n] = t2.branch[i2].y;\n\t    o[n] = order2[i2];\n\t    n++;\n\t  }\n\t}\n      } else if (order1[i1] < order2[i2]) {\n\tx[n] = t1.branch[i1].x;\n\ty[n] = t1.branch[i1].y;\n\to[n] = order1[i1];\n\tn++;\n\ti1++;\n\twhile (i1<t1.deg && !inWin[i1]) { i1++; }\n      } else {\n\tx[n] = t2.branch[i2].x;\n\ty[n] = t2.branch[i2].y;\n\to[n] = order2[i2];\n\tn++;\n\ti2++;\n\twhile (i2<t2.deg && (!inWin[i2+2*t1.deg] || i2==ci)) { i2++; }\n      }\n    } while (i1 < t1.deg || i2 < t2.deg);\n    //assert(n==d);\n\n    for (i=0; i<d; i++) {\n      si[i]=i;\n    }\n    for (i=0; i<d; i++) {\n      n = i;\n      for (i1=i+1; i1<d; i1++) {\n\tif (x[i1] < x[n]) {\n\t  n=i1;\n\t}\n      }\n      tmp = x[i];\n      x[i] = x[n];\n      x[n] = tmp;\n      tmp = si[n];\n      si[n] = si[i];\n      si[i] = tmp;\n    }\n    for (i=0; i<d; i++) {\n      os[si[i]] = i;\n    }\n    t3 = flutes_LMD(d, x, y, os, acc);\n    t = merge_into(t3, t2, inWin+2*t1.deg, d2, o, order2);\n    t4 = merge_into(t, t1, inWin, d+1-d2, o, order1);\n  } else\n  if (t2.deg > 2) {\n    for (i=0; i<t2.deg; i++) {\n      o[i]=order2[i];\n    }\n    t4 = smergetree(t2, t1, o, order1, cx, cy);\n  } else {\n    for (i=0; i<t1.deg; i++) {\n      o[i]=order1[i];\n    }\n    t4 = smergetree(t1, t2, o, order2, cx, cy);\n  }\n\n  for (i=0; i<t4.deg; i++) {\n    order1[i] = o[i];\n  }\n\n#if !(MR_FOR_SMALL_CASES_ONLY)\n    free(s); free(inWin); free(o); free(os); free(si); free(x); free(y);\n#endif\n\n  return t4;\n}\n\n/* xmerge heuristics */\ntypedef struct TreeNode_s{\n  struct TreeNode_s *parent;\n  dl_t children;\n  int order, id;\n  unsigned int mark;\n  DTYPE x, y;\n  DTYPE blen;  // length of this edge (i.e. branch length)\n  // longest edge from here, use child node of an edge to represent it\n  struct TreeNode_s *e;\n  DTYPE len;  // len of current e\n} TreeNode;\n\nvoid redirect(Tree t, DTYPE cx, DTYPE cy)\n{\n  int i, root, prev, curr, next;\n\n  /* assume that one of the nodes must match (cx, cy) */\n  root = 0;\n  for (i=1; i<t.deg; i++) {\n    if (t.branch[i].x==cx && t.branch[i].y==cy) {\n      root = i;\n      break;\n    }\n  }\n\n  prev = root;\n  curr = t.branch[root].n;\n  next = t.branch[curr].n;\n  while (curr != next) {\n    t.branch[curr].n = prev;\n    prev = curr;\n    curr = next;\n    next = t.branch[curr].n;\n  }\n  t.branch[curr].n = prev;\n\n  t.branch[root].n = root;\n}\n\nvoid update_subtree(TreeNode *p, int id)\n{\n  TreeNode *child, *grandp;\n  dl_t subtree=dl_alloc();\n\n  dl_append(TreeNode*, subtree, p);\n\n  while (dl_length(subtree)>0) {\n    dl_pop_first(TreeNode*, subtree, p);\n    p->e = p;\n    grandp = p->parent;\n    if (grandp) {\n      p->len = p->blen = ADIFF(p->x, grandp->x) + ADIFF(p->y, grandp->y);\n      if (p->len < grandp->len) {\n\tp->len = grandp->len;\n\tp->e = grandp->e;\n      }\n    } else {\n      p->len = 0;\n    }\n\n    if (id) {\n      p->id = id;\n    }\n\n    dl_forall(TreeNode*, p->children, child) {\n      dl_prepend(TreeNode*, subtree, child);\n    } dl_endfor;\n  }\n\n  dl_free(subtree);\n}\n\nTreeNode *createRootedTree(Tree t, int *order, int id, dl_t list_of_nodes)\n{\n  int i, dd, n;\n  TreeNode *root=0, **nodes, *p;\n\n  dd = t.deg*2-2;\n  nodes = (TreeNode**)malloc(sizeof(TreeNode*)*dd);\n  for (i=0; i<dd; i++) {\n    nodes[i] = (TreeNode*)malloc(sizeof(TreeNode));\n    nodes[i]->mark = curr_mark;\n    nodes[i]->children = dl_alloc();\n  }\n\n  curr_mark++;\n  for (i=0; i<dd; i++) {\n    nodes[i]->mark = curr_mark;\n    n = t.branch[i].n;\n    if (i==n) {\n      if (i < t.deg) {\n\t//assert(root==0);\n\tnodes[i]->parent = 0;\n\troot = nodes[i];\n      } else {  /* must be redundant */\n\tdl_free(nodes[i]->children);\n\tfree(nodes[i]);\n\tnodes[i] = 0;\n\tcontinue;\n      }\n    } else {\n      p = nodes[n];\n      nodes[i]->parent = p;\n      dl_append(TreeNode*, p->children, nodes[i]);\n    }\n    nodes[i]->order = (i < t.deg) ? order[i] : -1;\n    nodes[i]->id = id;\n    nodes[i]->x = t.branch[i].x;\n    nodes[i]->y = t.branch[i].y;\n\n    /* len will be computed in update_subtree\n    nodes[i]->blen =\n      ADIFF(t.branch[i].x, t.branch[n].x)+ADIFF(t.branch[i].y, t.branch[n].y);\n\n    nodes[i]->e = nodes[i];\n    nodes[i]->len =\n      ADIFF(t.branch[i].x, t.branch[n].x)+ADIFF(t.branch[i].y, t.branch[n].y);\n    */\n\n    dl_append(TreeNode*, list_of_nodes, nodes[i]);\n  }\n\n  //assert(root);\n\n  update_subtree(root, 0);\n\n  for (i=0; i<dd; i++) {\n    if (nodes[i] && nodes[i]->mark!=curr_mark) {\n      dl_free(nodes[i]->children);\n      free(nodes[i]);\n    }\n  }\n\n  free(nodes);\n  return root;\n}\n\nvoid freeTree(TreeNode *t)\n{\n  TreeNode *child;\n  dl_forall(TreeNode *, t->children, child) {\n    freeTree(child);\n  } dl_endfor;\n  dl_free(t->children);\n  free(t);\n}\n\nint cmpNodeByYX(const void* a, const void* b)\n{\n  DTYPE ay = (*(TreeNode**)a)->y;\n  DTYPE by = (*(TreeNode**)b)->y;\n  DTYPE ax, bx;\n\n  if (ay < by) return -1;\n  if (ay > by) return 1;\n\n  ax = (*(TreeNode**)a)->x;\n  bx = (*(TreeNode**)b)->x;\n\n  if (ax < bx) return -1;\n  if (ax > bx) return 1;\n  return 0;\n}\n\nint cmpNodeByXY(const void* a, const void* b)\n{\n  DTYPE ax = (*(TreeNode**)a)->x;\n  DTYPE bx = (*(TreeNode**)b)->x;\n  DTYPE ay, by;\n\n  if (ax < bx) return -1;\n  if (ax > bx) return 1;\n\n  ay = (*(TreeNode**)a)->y;\n  by = (*(TreeNode**)b)->y;\n\n  if (ay < by) return -1;\n  if (ay > by) return 1;\n  return 0;\n}\n\nvoid remove_child(dl_t children_list, TreeNode* c)\n{\n  TreeNode *child;\n  dl_forall(TreeNode*, children_list, child) {\n    if (child==c) {\n      dl_delete_current();\n      break;\n    }\n  } dl_endfor;\n}\n\nvoid cleanTree(TreeNode* tn)\n{\n  /*\n  TreeNode *c, *p;\n\n  dl_forall(TreeNode*, tn->children, c) {\n    cleanTree(c);\n  } dl_endfor;\n\n  p = tn->parent;\n  if (!p) return;\n\n  if (tn->order >= 0) return;  // don't clean pin nodes\n\n  if (dl_length(tn->children)<=0) {\n    remove_child(p->children, tn);\n    dl_free(tn->children);\n    free(tn);\n  } else if (dl_length(tn->children)<=1) {\n    c = dl_first(TreeNode*, tn->children);\n    c->parent = p;\n    dl_append(TreeNode*, p->children, c);\n    remove_child(p->children, tn);\n    dl_free(tn->children);\n    free(tn);\n  }\n  */\n\n  // non-recursive version\n  TreeNode *c, *p;\n  dl_t nlist=dl_alloc();\n\n  dl_append(TreeNode*, nlist, tn);\n\n  while (dl_length(nlist)>0) {\n    dl_pop_first(TreeNode*, nlist, tn);\n    dl_forall(TreeNode*, tn->children, c) {\n      dl_append(TreeNode*, nlist, c);\n    } dl_endfor;\n\n    p = tn->parent;\n    if (p && tn->order < 0) {\n      if (dl_length(tn->children)<=0) {\n\tremove_child(p->children, tn);\n\tdl_free(tn->children);\n\tfree(tn);\n      } else if (dl_length(tn->children)<=1) {\n\tc = dl_first(TreeNode*, tn->children);\n\tc->parent = p;\n\tdl_append(TreeNode*, p->children, c);\n\tremove_child(p->children, tn);\n\tdl_free(tn->children);\n\tfree(tn);\n      }\n    }\n  }\n\n  dl_free(nlist);\n}\n\nint cmpNodeByOrder(void* a, void* b)\n{\n  int ax = (*(TreeNode**)a)->order;\n  int bx = (*(TreeNode**)b)->order;\n\n  if (ax < bx) return -1;\n  if (ax > bx) return 1;\n  return 0;\n}\n\nTree mergeRootedTrees(TreeNode *tn1, TreeNode *tn2, int *order1)\n{\n  int i, n, redundant;\n  Tree t;\n  TreeNode *child, *p;\n  dl_t list_of_nodes=dl_alloc();\n  dl_t pin_nodes=dl_alloc(), steiner_nodes=dl_alloc();\n\n  //assert(tn1->x==tn2->x && tn1->y==tn2->y);\n\n  /* merge tn2 to tn1 */\n  while (dl_length(tn2->children)>0) {\n    dl_pop_first(TreeNode*, tn2->children, child);\n    child->parent = tn1;\n    dl_append(TreeNode*, tn1->children, child);\n  }\n  dl_free(tn2->children);\n  free(tn2);\n\n  cleanTree(tn1);\n\n  /* convert tn1 back to a Tree */\n\n  dl_append(TreeNode*, list_of_nodes, tn1);\n  do {\n    dl_pop_first(TreeNode*, list_of_nodes, child);\n    if (child->order < 0) {\n      if (dl_length(child->children)==1) { /* redundant steiner node */\n\tp = dl_first(TreeNode*, child->children);\n\tp->parent = child->parent;\n\t/* note that p->parent's children list is already gone */\n\tdl_append(TreeNode*, list_of_nodes, p);\n\tdl_free(child->children);\n\tfree(child);\n\tcontinue;\n      } else if (dl_length(child->children)==0) {\n\tdl_free(child->children);\n\tfree(child);\n\tcontinue;\n      }\n      dl_append(TreeNode*, steiner_nodes, child);\n    } else {\n      dl_append(TreeNode*, pin_nodes, child);\n    }\n    dl_concat(list_of_nodes, child->children);\n  } while (dl_length(list_of_nodes)>0);\n  dl_free(list_of_nodes);\n\n  dl_sort(pin_nodes, sizeof(TreeNode*), cmpNodeByOrder);\n\n  i=0;\n  dl_forall(TreeNode*, pin_nodes, child) {\n    child->id = i++;\n  } dl_endfor;\n\n  t.deg = i;\n\n  dl_forall(TreeNode*, steiner_nodes, child) {\n    child->id = i++;\n  } dl_endfor;\n\n  //assert(i<=2*t.deg-2);\n\n  t.branch = (Branch*)malloc(sizeof(Branch)*(t.deg*2-2));\n\n  redundant = i;\n  for (; i<2*t.deg-2; i++) {\n    t.branch[i].n = i;\n    t.branch[i].x = tn1->x;\n    t.branch[i].y = tn1->y;\n  }\n\n  t.branch[tn1->id].n = -1;\n\n  dl_forall(TreeNode*, pin_nodes, child) {\n    i = child->id;\n    if (child->order >= 0) {\n      order1[i] = child->order;\n    }\n    t.branch[i].x = child->x;\n    t.branch[i].y = child->y;\n    p = child->parent;\n    if (p) {\n      if (p->id >= t.deg) {\n\tt.branch[i].n = p->id;\n      } else {\n\t//assert(p==tn1);\n\t//assert(redundant<t.deg*2-2);\n\tt.branch[i].n = redundant;\n\tt.branch[p->id].n = redundant;\n\tt.branch[redundant].x = p->x;\n\tt.branch[redundant].y = p->y;\n\tredundant++;\n      }\n    }\n  } dl_endfor;\n  dl_forall(TreeNode*, steiner_nodes, child) {\n    i = child->id;\n    if (child->order >= 0) {\n      order1[i] = child->order;\n    }\n    t.branch[i].x = child->x;\n    t.branch[i].y = child->y;\n    p = child->parent;\n    if (p->id < t.deg) { // must be the root\n      if (t.branch[p->id].n < 0) {\n\tt.branch[p->id].n = i;\n\tt.branch[i].n = i;\n      } else {\n\tn = t.branch[p->id].n;\n\tif (t.branch[p->id].x==t.branch[n].x &&\n\t    t.branch[p->id].y==t.branch[n].y) {\n\t  t.branch[i].n = n;\n\t} else {\n\t  //assert(redundant<t.deg*2-2);\n\t  t.branch[redundant].x = t.branch[p->id].x;\n\t  t.branch[redundant].y = t.branch[p->id].y;\n\t  t.branch[redundant].n = t.branch[p->id].n;\n\t  t.branch[p->id].n = redundant;\n\t  t.branch[i].n = redundant;\n\t  redundant++;\n\t}\n      }\n    } else {\n      t.branch[i].n = p->id;\n    }\n  } dl_endfor;\n\n  dl_forall(TreeNode*, pin_nodes, child) {\n    free(child);\n  } dl_endfor;\n  dl_free(pin_nodes);\n\n  dl_forall(TreeNode*, steiner_nodes, child) {\n    free(child);\n  } dl_endfor;\n  dl_free(steiner_nodes);\n\n  t.length = wirelength(t);\n  return t;\n}\n\nvoid collect_nodes(TreeNode* tn, dl_t nlist)\n{\n  /*\n  TreeNode* c;\n\n  dl_append(TreeNode*, nlist, tn);\n  dl_forall(TreeNode*, tn->children, c) {\n    collect_nodes(c, nlist);\n  }dl_endfor;\n  */\n  // non-recursive version\n  TreeNode* c;\n  dl_el *curr;\n\n  dl_append(TreeNode*, nlist, tn);\n\n  for (curr=nlist->last; curr; curr=curr->next) {\n    tn = dl_data(TreeNode*, curr);\n    dl_forall(TreeNode*, tn->children, c) {\n      dl_append(TreeNode*, nlist, c);\n    }dl_endfor;\n  }\n}\n\ntypedef struct {\n  TreeNode *n1, *n2;\n  DTYPE new_x, new_y, gain;\n} xdata;\n\nint cmpXdata(void *a, void *b)\n{\n  DTYPE ga = (*(xdata*)a).gain;\n  DTYPE gb = (*(xdata*)b).gain;\n  if (ga > gb) return -1;\n  if (ga < gb) return 1;\n  return 0;\n}\n\nTreeNode *cedge_lca(TreeNode* n1, TreeNode* n2, DTYPE *len, int *n2ton1)\n{\n  int i;\n  TreeNode *curr, *lca, *e;\n\n  curr_mark++;\n\n  curr = n1;\n  while (curr) {\n    curr->mark = curr_mark;\n    curr = curr->parent;\n  }\n\n  lca = n2;\n  while (lca && lca->mark!=curr_mark) {\n    lca->mark = curr_mark;\n    lca = lca->parent;\n  }\n\n  if (!lca) {\n    n1 = n1->parent;\n    if (n1 && n1!=lca && (n1->len > n2->len)) {\n      *n2ton1 = 0;\n      *len = n1->len;\n      return n1->e;\n    } else {\n      *n2ton1 = 1;\n      *len = n2->len;\n      return n2->e;\n    }\n  }\n\n  if (lca==n1 || lca==n1->parent || lca==n2) {\n    if (lca!=n2) {\n      *n2ton1 = 1;\n      *len = n2->blen;\n      e = n2;\n      curr = n2->parent;\n    } else {\n      *n2ton1 = 0;\n      *len = n1->blen;\n      e = n1;\n      curr = n1->parent;\n    }\n    while (curr != lca) {\n      if (*len < curr->blen) {\n\t*len = curr->blen;\n\te = curr;\n      }\n      curr = curr->parent;\n    }\n    return e;\n  }\n\n  /* lca is above both n1 and n2 */\n  *n2ton1 = 0;\n  n1 = n1->parent;\n  *len = n1->blen;\n  e = n1;\n  curr = n1;\n  for (i=0; i<2; i++, curr=n2) {\n    while (curr != lca) {\n      if (*len < curr->blen) {\n\tif (i>0) {\n\t  *n2ton1 = 1;\n\t}\n\t*len = curr->blen;\n\te = curr;\n      }\n      curr = curr->parent;\n    }\n  }\n\n  return e;\n\n}\n\nTreeNode *critical_edge(TreeNode* n1, TreeNode* n2, DTYPE *len, int *n2ton1)\n{\n  if (n1->id != n2->id) {\n    n1 = n1->parent;\n    if (n1 && (n1->len > n2->len)) {\n      *n2ton1 = 0;\n      *len = n1->len;\n      return n1->e;\n    } else {\n      *n2ton1 = 1;\n      *len = n2->len;\n      return n2->e;\n    }\n  }\n\n  return cedge_lca(n1, n2, len, n2ton1);\n}\n\nvoid splice2(TreeNode *n1, TreeNode *n2, TreeNode *e)\n{\n  TreeNode *curr, *prev, *next, *s;\n\n  //assert(n2->parent);\n  //assert(e->id==n2->id);\n\n  prev = n2;\n  curr = n2->parent;\n  next = curr->parent;\n  while (prev != e) {\n    remove_child(curr->children, prev);\n    curr->parent = prev;\n    dl_append(TreeNode*, prev->children, curr);\n    prev = curr;\n    curr = next;\n    next = curr->parent;\n  }\n  remove_child(curr->children, prev);\n\n  n2->parent = n1;\n  dl_append(TreeNode*, n1->children, n2);\n\n  update_subtree(n1, n1->parent->id);\n}\n\nvoid cut_and_splice(TreeNode *n1, TreeNode *n2,\n\t\t    DTYPE new_x, DTYPE new_y,\n\t\t    DTYPE *x1, DTYPE *y1, DTYPE *x2, DTYPE *y2,\n\t\t    TreeNode *e, int n2ton1)\n{\n  TreeNode *p1, *node, *s;\n\n  /* new steiner node */\n  p1 = n1->parent;\n  remove_child(p1->children, n1);\n  node = (TreeNode*)malloc(sizeof(TreeNode));\n  node->x = new_x;\n  node->y = new_y;\n  node->mark = curr_mark;\n\n  node->parent = p1;\n  dl_append(TreeNode*, p1->children, node);\n  n1->parent = node;\n  node->children = dl_alloc();\n  dl_append(TreeNode*, node->children, n1);\n  node->order = -1;\n\n  node->e = n1->e;\n  node->id = n1->id;\n\n  if (*x1==n1->x) {\n    *x2 = new_x;\n  } else {\n    *x1 = new_x;\n  }\n  if (*y1==n1->y) {\n    *y2 = new_y;\n  } else {\n    *y1 = new_y;\n  }\n\n  if (n2->order >= 0) {\n    /* n2 is a pin, need to replicate a steiner node */\n    s = n2->parent;\n    if (s->x!=n2->x || s->y!=n2->y) {\n      s = (TreeNode*)malloc(sizeof(TreeNode));\n      s->mark = curr_mark;\n      s->order = -1;\n      s->id = n2->id;\n      s->x = n2->x;\n      s->y = n2->y;\n      s->e = n2->e;\n      if (s->e == n2) {\n\ts->e = s;\n      }\n      if (e == n2) {\n\te = s;\n      }\n      s->len = n2->len;\n      s->blen = n2->blen;\n      n2->blen = 0;\n\n      remove_child(n2->parent->children, n2);\n      dl_append(TreeNode*, n2->parent->children, s);\n      s->parent = n2->parent;\n      n2->parent = s;\n      s->children = dl_alloc();\n      dl_append(TreeNode*, s->children, n2);\n    }\n    n2 = s;\n  }\n\n  if (n2ton1) {\n    splice2(node, n2, e);\n  } else {\n    splice2(n2, node, e);\n  }\n}\n\ntypedef struct {\n  TreeNode *n1, *n2;\n  DTYPE min_dist, new_x, new_y;\n  int n2ton1;\n} splice_info;\n\nDTYPE exchange_branches_order_x(int num_nodes, TreeNode **nodes,\n\t\t\t\tDTYPE threshold_x, DTYPE threshold_y,\n\t\t\t\tDTYPE max_len)\n{\n  int n2ton1;\n  TreeNode *n1, *p1, *n2, *p2, *node, *e, *s;\n  DTYPE  x1, x2, y1, y2, min_dist, new_x, new_y, len;\n  DTYPE gain=0;\n  int i, j, curr_row, next_header, num_rows, start, end, mid;\n  int *header=(int*)malloc(sizeof(int)*(num_nodes+1));\n  dl_t batch_list=dl_alloc();\n  splice_info sinfo;\n\n  int batch_mode = (num_nodes >= D3);\n\n  header[0]=0;\n\n  y1 = nodes[0]->y;\n  for (i=num_rows=1; i<num_nodes; i++) {\n    if (nodes[i]->y == y1) {\n      continue;\n    }\n    header[num_rows++] = i;\n    y1 = nodes[i]->y;\n  }\n  header[num_rows] = i;\n\n  curr_row = 0;\n  next_header = header[1];\n  for (i=0; i<num_nodes; i++) {\n    if (i >= next_header) {\n      curr_row++;\n      next_header = header[curr_row+1];\n    }\n    n1 = nodes[i];\n    p1 = n1->parent;\n    if (!p1) {\n      continue;\n    }\n    if (p1->x == n1->x && p1->y == n1->y) {\n      continue;\n    }\n    if (n1->x <= p1->x) {\n      x1 = n1->x;  x2 = p1->x;\n    } else {\n      x1 = p1->x;  x2 = n1->x;\n    }\n    if (n1->y <= p1->y) {\n      y1 = n1->y;  y2 = p1->y;\n    } else {\n      y1 = p1->y;  y2 = n1->y;\n    }\n\n    if (curr_row > 0) {\n      for (j=curr_row-1; j>0; j--) {\n\tif (y1 - threshold_y > nodes[header[j]]->y) {\n\t  j++;\n\t  break;\n\t}\n      }\n    } else {\n      j = 0;\n    }\n    for (;j < num_rows && nodes[header[j]]->y <= y2 + threshold_y; j++) {\n      /* find the closest node on row j */\n      start = header[j];\n      end = header[j+1];\n      while (start < end) {\n\tmid = (start+end)/2;\n\tif (nodes[mid]->x <= x1) {\n\t  start = mid + 1;\n\t} else {\n\t  end = mid;\n\t}\n      }\n      //assert(start==end);\n\n      if (start >= header[j+1]) {\n\tcontinue;\n      }\n      n2 = nodes[start];\n\n      if (batch_mode && n1->id==n2->id) continue;\n\n      if (!n2->parent) {\n\tcontinue;\n      }\n\n      min_dist = n2->x - x2;\n\n      if (flute_abs(min_dist) > threshold_x) {\n\tcontinue;\n      } else if (min_dist < 0) {\n\tmin_dist = 0;\n\tnew_x = n2->x;\n      } else {\n\tnew_x = x2;\n      }\n\n      if (n2->y < y1) {\n\tmin_dist += y1 - n2->y;\n\tnew_y = y1;\n      } else if (n2->y > y2) {\n\tmin_dist += n2->y - y2;\n\tnew_y = y2;\n      } else {\n\tnew_y = n2->y;\n      }\n\n      if (min_dist ==0 || min_dist > max_len) {\n\tcontinue;\n      }\n\n      e = critical_edge(n1, n2, &len, &n2ton1);\n      if (min_dist < len && e!=n1) {\n\tif (batch_mode) {\n\t  sinfo.n1 = n1;\n\t  sinfo.n2 = n2;\n\t  sinfo.min_dist = min_dist;\n\t  sinfo.new_x = new_x;\n\t  sinfo.new_y = new_y;\n\t  sinfo.n2ton1 = n2ton1;\n\t  dl_append(splice_info, batch_list, sinfo);\n\t} else {\n\t  gain += len - min_dist;\n\t  cut_and_splice(n1, n2, new_x, new_y, &x1, &y1, &x2, &y2, e, n2ton1);\n\t}\n      }\n    }\n  }\n\n  dl_forall(splice_info, batch_list, sinfo) {\n    n1 = sinfo.n1;\n    n2 = sinfo.n2;\n    n2ton1 = sinfo.n2ton1;\n    min_dist = sinfo.min_dist;\n\n    e = critical_edge(n1, n2, &len, &n2ton1);\n    if (min_dist < len && e!=n1) {\n      gain += len - min_dist;\n      cut_and_splice(n1, n2, sinfo.new_x, sinfo.new_y,\n\t\t     &x1, &y1, &x2, &y2, e, n2ton1);\n    }\n  } dl_endfor;\n\n  dl_free(batch_list);\n\n  free(header);\n\n  return gain;\n}\n\nDTYPE exchange_branches_order_y(int num_nodes, TreeNode **nodes,\n\t\t\t\tDTYPE threshold_x, DTYPE threshold_y,\n\t\t\t\tDTYPE max_len)\n{\n  int n2ton1;\n  TreeNode *n1, *p1, *n2, *p2, *node, *e, *s;\n  DTYPE  x1, x2, y1, y2, min_dist, new_x, new_y, len;\n  DTYPE gain=0;\n  int i, j, curr_row, next_header, num_rows, start, end, mid;\n  int *header=(int*)malloc(sizeof(int)*(num_nodes+1));\n  dl_t batch_list=dl_alloc();\n  splice_info sinfo;\n\n  int batch_mode = (num_nodes >= D3);\n\n  header[0]=0;\n\n  x1 = nodes[0]->x;\n  for (i=num_rows=1; i<num_nodes; i++) {\n    if (nodes[i]->x == x1) {\n      continue;\n    }\n    header[num_rows++] = i;\n    x1 = nodes[i]->x;\n  }\n  header[num_rows] = i;\n\n  curr_row = 0;\n  next_header = header[1];\n  for (i=0; i<num_nodes; i++) {\n    if (i >= next_header) {\n      curr_row++;\n      next_header = header[curr_row+1];\n    }\n    n1 = nodes[i];\n    p1 = n1->parent;\n    if (!p1) {\n      continue;\n    }\n    if (p1->x == n1->x && p1->y == n1->y) {\n      continue;\n    }\n    if (n1->x <= p1->x) {\n      x1 = n1->x;  x2 = p1->x;\n    } else {\n      x1 = p1->x;  x2 = n1->x;\n    }\n    if (n1->y <= p1->y) {\n      y1 = n1->y;  y2 = p1->y;\n    } else {\n      y1 = p1->y;  y2 = n1->y;\n    }\n\n    if (curr_row > 0) {\n      for (j=curr_row-1; j>0; j--) {\n\tif (x1 - threshold_x > nodes[header[j]]->x) {\n\t  j++;\n\t  break;\n\t}\n      }\n    } else {\n      j = 0;\n    }\n    for (;j < num_rows && nodes[header[j]]->x <= x2 + threshold_x; j++) {\n      /* find the closest node on row j */\n      start = header[j];\n      end = header[j+1];\n      while (start < end) {\n\tmid = (start+end)/2;\n\tif (nodes[mid]->y <= y1) {\n\t  start = mid + 1;\n\t} else {\n\t  end = mid;\n\t}\n      }\n      //assert(start==end);\n      if (start >= header[j+1]) {\n\tcontinue;\n      }\n      n2 = nodes[start];\n\n      if (batch_mode && n1->id==n2->id) continue;\n\n      if (!n2->parent) {\n\tcontinue;\n      }\n\n      min_dist = n2->y - y2;\n\n      if (flute_abs(min_dist) > threshold_y) {\n\tcontinue;\n      } else if (min_dist < 0) {\n\tmin_dist = 0;\n\tnew_y = n2->y;\n      } else {\n\tnew_y = y2;\n      }\n\n      if (n2->x < x1) {\n\tmin_dist += x1 - n2->x;\n\tnew_x = x1;\n      } else if (n2->x > x2) {\n\tmin_dist += n2->x - x2;\n\tnew_x = x2;\n      } else {\n\tnew_x = n2->x;\n      }\n\n      if (min_dist ==0 || min_dist > max_len) {\n\tcontinue;\n      }\n\n      e = critical_edge(n1, n2, &len, &n2ton1);\n      if (min_dist < len && e!=n1) {\n\tif (batch_mode) {\n\t  sinfo.n1 = n1;\n\t  sinfo.n2 = n2;\n\t  sinfo.min_dist = min_dist;\n\t  sinfo.new_x = new_x;\n\t  sinfo.new_y = new_y;\n\t  sinfo.n2ton1 = n2ton1;\n\t  dl_append(splice_info, batch_list, sinfo);\n\t} else {\n\t  gain += len - min_dist;\n\t  cut_and_splice(n1, n2, new_x, new_y, &x1, &y1, &x2, &y2, e, n2ton1);\n\t}\n      }\n    }\n  }\n\n  dl_forall(splice_info, batch_list, sinfo) {\n    n1 = sinfo.n1;\n    n2 = sinfo.n2;\n    n2ton1 = sinfo.n2ton1;\n    min_dist = sinfo.min_dist;\n\n    e = critical_edge(n1, n2, &len, &n2ton1);\n    if (min_dist < len && e!=n1) {\n      gain += len - min_dist;\n      cut_and_splice(n1, n2, sinfo.new_x, sinfo.new_y,\n\t\t     &x1, &y1, &x2, &y2, e, n2ton1);\n    }\n  } dl_endfor;\n\n  dl_free(batch_list);\n\n  free(header);\n\n  return gain;\n}\n\n/* cross exchange branches after merging */\nTree xmergetree(Tree t1, Tree t2, int *order1, int *order2,\n\t\tDTYPE cx, DTYPE cy)\n{\n  int i, num, cnt, order_by_x=1;\n  Tree t;\n  TreeNode *tn1, *tn2, *n1, *p1, **nodes;\n  dl_t list_of_nodes=dl_alloc();\n  DTYPE threshold_x, threshold_y;\n  DTYPE min_x, max_x, max_len, len, gain;\n\n  if (t1.deg <= 0) {\n    for (i=0; i<t2.deg; i++) {\n      order1[i] = order2[i];\n    }\n    return t2;\n  } else if (t2.deg <= 0) {\n    return t1;\n  }\n\n  redirect(t1, cx, cy);\n  redirect(t2, cx, cy);\n\n  curr_mark = 0;\n  tn1 = createRootedTree(t1, order1, 1, list_of_nodes);\n  tn2 = createRootedTree(t2, order2, 2, list_of_nodes);\n\n  num = dl_length(list_of_nodes);\n  nodes = (TreeNode**)malloc(sizeof(TreeNode*)*num);\n  i = 0;\n  dl_forall(TreeNode*, list_of_nodes, n1) {\n    nodes[i++] = n1;\n  } dl_endfor;\n  dl_clear(list_of_nodes);\n\n  qsort(nodes, num, sizeof(TreeNode*), cmpNodeByYX);\n\n  max_len = 0;\n  min_x = max_x = nodes[0]->x;\n  for (i=0; i<num; i++) {\n    n1 = nodes[i];\n    p1 = n1->parent;\n    if (p1) {\n      len = ADIFF(n1->x, p1->x) + ADIFF(n1->y, p1->y);\n      if (len > max_len) {\n\tmax_len = len;\n      }\n    }\n    if (n1->x < min_x) {\n      min_x = n1->x;\n    } else if (n1->x > max_x) {\n      max_x = n1->x;\n    }\n  }\n\n  threshold_x = (max_x - min_x)/4;\n  threshold_y = (nodes[num-1]->y - nodes[0]->y)/4;\n\n  threshold_x = flute_min(threshold_x, max_len);\n  threshold_y = flute_min(threshold_y, max_len);\n\n  for (cnt=(t1.deg+t2.deg)/2; cnt>0; cnt--) {\n    gain = (order_by_x) ?\n      exchange_branches_order_x(num, nodes, threshold_x, threshold_y, max_len):\n      exchange_branches_order_y(num, nodes, threshold_x, threshold_y, max_len);\n\n    //assert(gain>=0);\n\n    if (gain <= 0 && !order_by_x) {\n       break;\n    }\n    if (cnt>1) {\n      collect_nodes(tn1, list_of_nodes);\n      num = dl_length(list_of_nodes);\n      if (num <= 1) {\n\tbreak;\n      }\n\n      collect_nodes(tn2, list_of_nodes);\n      if (dl_length(list_of_nodes)-num <= 1) {\n\tbreak;\n      }\n\n      free(nodes);\n      num = dl_length(list_of_nodes);\n      nodes = (TreeNode**)malloc(sizeof(TreeNode*)*num);\n      i = 0;\n      dl_forall(TreeNode*, list_of_nodes, n1) {\n\tnodes[i++] = n1;\n      } dl_endfor;\n      dl_clear(list_of_nodes);\n\n      if (order_by_x) {\n\torder_by_x = 0;\n\tqsort(nodes, num, sizeof(TreeNode*), cmpNodeByXY);\n      } else {\n\torder_by_x = 1;\n\tqsort(nodes, num, sizeof(TreeNode*), cmpNodeByYX);\n      }\n    }\n  }\n\n  dl_free(list_of_nodes);\n  free(nodes);\n\n  t = mergeRootedTrees(tn1, tn2, order1);\n\n  free(t1.branch);\n  free(t2.branch);\n\n  return t;\n}\n"
  },
  {
    "path": "src/flute/global.h",
    "content": "#ifndef  _GLOBAL_H_\n#define  _GLOBAL_H_\n\n#include <stdio.h>\n\n#define  TRUE   1\n#define  FALSE  0\n#define  MAXLONG  0x7fffffffL\n\nstruct point\n{\n  long    x, y;\n};\n\ntypedef  struct point Point;\n\ntypedef  long nn_array[8];\n\n#endif  /* _GLOBAL_H_ */\n"
  },
  {
    "path": "src/flute/heap.c",
    "content": "/****************************************************************************/\n/*\n  Binary heap routines for use in Prim's algorithm, \n  with points are numbered from 0 to n-1\n*/\n\n#include <stdlib.h>\n#include \"heap.h\"\n#include \"err.h\"\n\n\nHeap*   _heap = (Heap*)NULL;\nlong    _max_heap_size = 0;\nlong    _heap_size = 0;\n\n/****************************************************************************/\n/*\n*/\n\nvoid  allocate_heap( long n )\n{\n  if( _max_heap_size < n ) \n  {\n    _heap = (Heap*)realloc( (void*)_heap, (size_t)(n+1)*sizeof(Heap) ); \n    if( ! _heap )\n    {\n      err_exit( \"Cannot reallocate memory in allocate_heap!\" );\n    } \n    _max_heap_size = n;\n  }\n}\n/****************************************************************************/\n/*\n*/\n\nvoid  deallocate_heap()\n{\n  _max_heap_size = 0; \n  if( _heap )\n  {\n    free( (void*)_heap );\n    _heap = (Heap*)NULL;\n  }\n}\n\n/****************************************************************************/\n\nvoid  heap_init( long  n )\n{\n  register long  p;\n\n  allocate_heap( n );\n  _heap_size = 0;\n  for( p = 0;  p < n;  p++ )\n  { \n    heap_idx( p ) = 0;\n  }\n \n} /* END heap_init() */\n\n/****************************************************************************/\n\nvoid  heap_insert( \n  long   p, \n  long   key \n)\n{\n  register long  k;       /* hole in the heap     */   \n  register long  j;       /* parent of the hole   */\n  register long  q;       /* heap_elt(j)          */\n\n  heap_key( p ) = key;\n\n  if( _heap_size == 0 )\n  {\n    _heap_size = 1;\n    heap_elt( 1 ) = p;\n    heap_idx( p ) = 1;          \n    return;\n  }\n\n  k = ++ _heap_size;\n  j = k >> 1;            /* k/2 */\n\n  while( (j > 0) && (heap_key(q=heap_elt(j)) > key) ) { \n\n    heap_elt( k ) = q;\n    heap_idx( q ) = k;\n    k = j;\n    j = k>>1;    /* k/2 */\n\n  }\n \n  /* store p in the position of the hole */\n  heap_elt( k ) = p;\n  heap_idx( p ) = k;      \n\n} /* END heap_insert() */\n\n\n/****************************************************************************/\n\nvoid  heap_decrease_key\n( \n  long   p, \n  long   new_key \n)\n{\n  register long    k;       /* hole in the heap     */   \n  register long    j;       /* parent of the hole   */\n  register long    q;       /* heap_elt(j)          */\n\n  heap_key( p ) = new_key;\n  k = heap_idx( p ); \n  j = k >> 1;            /* k/2 */\n\n  if( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) ) { /* change is needed */\n    do {\n\n      heap_elt( k ) = q;\n      heap_idx( q ) = k;\n      k = j;\n      j = k>>1;    /* k/2 */\n\n    } while( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) );\n\n    /* store p in the position of the hole */\n    heap_elt( k ) = p;\n    heap_idx( p ) = k;      \n  }\n\n} /* END heap_decrease_key() */\n\n\n/****************************************************************************/\n\nlong  heap_delete_min()\n{\n  long    min, last;  \n  register long  k;         /* hole in the heap     */   \n  register long  j;         /* child of the hole    */\n  register long  l_key;     /* key of last point    */\n\n  if( _heap_size == 0 )            /* heap is empty */\n    return( -1 );\n\n  min  = heap_elt( 1 );\n  last = heap_elt( _heap_size -- );\n  l_key = heap_key( last );\n\n  k = 1;  j = 2;\n  while( j <= _heap_size ) {\n\n    if( heap_key(heap_elt(j)) > heap_key(heap_elt(j+1)) ) \n      j++;\n\n    if( heap_key(heap_elt(j)) >= l_key)  \n      break;                     /* found a position to insert 'last' */\n\n    /* else, sift hole down */ \n    heap_elt(k) = heap_elt(j);    /* Note that j <= _heap_size */\n    heap_idx( heap_elt(k) ) = k;\n    k = j;\n    j = k << 1;\n  }\n\n  heap_elt( k ) = last;\n  heap_idx( last ) = k;\n\n  heap_idx( min ) = -1;   /* mark the point visited */\n  return( min );\n\n} /* END heap_delete_min() */\n\n\n/****************************************************************************/\n\n"
  },
  {
    "path": "src/flute/heap.h",
    "content": "#ifndef  _HEAP_H_\n#define  _HEAP_H_\n\n#include \"global.h\"\n\nstruct  heap_info\n{\n  long  key;\n  long  idx;\n  long  elt;\n};\n\ntypedef  struct heap_info  Heap;\n\nextern Heap*   _heap;\n\n#define  heap_key( p )     ( _heap[p].key )\n#define  heap_idx( p )     ( _heap[p].idx )\n#define  heap_elt( k )     ( _heap[k].elt )\n\n#define  in_heap( p )    ( heap_idx(p) > 0 )\n#define  never_seen( p ) ( heap_idx(p) == 0 ) \n\nvoid   allocate_heap( long n );\nvoid   deallocate_heap();\nvoid   heap_init( long  n );\nvoid   heap_insert( long  p,  long key );\nvoid   heap_decrease_key( long  p,  long new_key );\nlong   heap_delete_min();\n\n#endif /* _HEAP_H_ */\n"
  },
  {
    "path": "src/flute/license.txt",
    "content": "READ THIS LICENSE AGREEMENT CAREFULLY BEFORE USING THIS PRODUCT. BY USING\r\nTHIS PRODUCT YOU INDICATE YOUR ACCEPTANCE OF THE TERMS OF THE FOLLOWING\r\nAGREEMENT. THESE TERMS APPLY TO YOU AND ANY SUBSEQUENT LICENSEE OF THIS\r\nPRODUCT.\r\n\r\nLicense Agreement for FLUTE\r\n\r\nCopyright (c) 2004 by Dr. Chris C. N. Chu\r\nAll rights reserved\r\n\r\nATTRIBUTION ASSURANCE LICENSE (adapted from the original BSD license)\r\nRedistribution and use in source and binary forms, with or without\r\nmodification, are permitted provided that the conditions below are\r\nmet. These conditions require a modest attribution to Dr. Chris C. N. Chu\r\n(the \"Author\").\r\n\r\n1. Redistributions of the source code, with or without modification (the\r\n   \"Code\"), must be accompanied by any documentation and, each time\r\n   the resulting executable program or a program dependent thereon is\r\n   launched, a prominent display (e.g., splash screen or banner text) of\r\n   the Author's attribution information, which includes:\r\n   (a) Dr. Chris C. N. Chu (\"AUTHOR\"),\r\n   (b) Iowa State University (\"PROFESSIONAL IDENTIFICATION\"), and\r\n   (c) http://home.engineering.iastate.edu/~cnchu/ (\"URL\").\r\n\r\n2. Users who intend to use the Code for commercial purposes will notify\r\n   Author prior to such commercial use.\r\n\r\n3. Neither the name nor any trademark of the Author may be used to\r\n   endorse or promote products derived from this software without\r\n   specific prior written permission.\r\n\r\n4. Users are entirely responsible, to the exclusion of the Author and any\r\n   other persons, for compliance with (1) regulations set by owners or\r\n   administrators of employed equipment, (2) licensing terms of any other\r\n   software, and (3) local, national, and international regulations\r\n   regarding use, including those regarding import, export, and use of\r\n   encryption software.\r\n\r\nTHIS FREE SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS OR\r\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r\nIN NO EVENT SHALL THE AUTHOR OR ANY CONTRIBUTOR BE LIABLE FOR ANY DIRECT,\r\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r\n(INCLUDING, BUT NOT LIMITED TO, EFFECTS OF UNAUTHORIZED OR MALICIOUS\r\nNETWORK ACCESS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n"
  },
  {
    "path": "src/flute/memAlloc.c",
    "content": "/* --------------------------------------------------------------------------\n   Public domain memory allocation and de-allocation routines.\n   Taken from Appendix B of: \n   Numerical Recipes in C: The Art of Scientific Computing, Second Edition,\n   Cambridge University Press, 1992\n----------------------------------------------------------------------------*/\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n\n#include \"memAlloc.h\"\n\n#define MEM_END 1\n#define FREE_ARG char*\n\nvoid runtimeError(char error_text[])\n/* error handler */\n{\n  fprintf(stderr, \"ERROR: %s \\n\", error_text);\n  fprintf(stderr, \"Aborting !! \\n\");\n  fflush(stdout);\n  fflush(stderr);\n  exit(1);\n}\n\nfloat *vector(long nl, long nh)\n/* allocate a float vector with subscript range v[nl..nh] */\n{\n  float *v;\n  v=(float *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(float)));\n  if (!v) runtimeError(\"allocation failure in vector()\");\n  return v-nl+MEM_END;\n}\n\nint *ivector(long nl, long nh)\n/* allocate an int vector with subscript range v[nl..nh] */\n{\n  int *v;\n  v=(int *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(int)));\n  if (!v) runtimeError(\"allocation failure in ivector()\");\n  return v-nl+MEM_END;\n}\n\nunsigned char *cvector(long nl, long nh)\n/* allocate an unsigned char vector with subscript range v[nl..nh] */\n{\n  unsigned char *v;\n  v=(unsigned char *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(unsigned char)));\n  if (!v) runtimeError(\"allocation failure in cvector()\");\n  return v-nl+MEM_END;\n}\n\nunsigned long *lvector(long nl, long nh)\n/* allocate an unsigned long vector with subscript range v[nl..nh] */\n{\n  unsigned long *v;\n  v=(unsigned long *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(long)));\n  if (!v) runtimeError(\"allocation failure in lvector()\");\n  return v-nl+MEM_END;\n}\n\ndouble *dvector(long nl, long nh)\n/* allocate a double vector with subscript range v[nl..nh] */\n{\n  double *v;\n  v=(double *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(double)));\n  if (!v) runtimeError(\"allocation failure in dvector()\");\n  return v-nl+MEM_END;\n}\n\nfloat **matrix(long nrl, long nrh, long ncl, long nch)\n/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */\n{\n  long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;\n  float **m;\n  \n  /* allocate pointers to rows */\n  m=(float **) malloc((size_t)((nrow+MEM_END)*sizeof(float*)));\n  if (!m) runtimeError(\"allocation failure 1 in matrix()\");\n  m += MEM_END;\n  m -= nrl;\n  \n  /* allocate rows and set pointers to them */\n  m[nrl]=(float *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(float)));\n  if (!m[nrl]) runtimeError(\"allocation failure 2 in matrix()\");\n  m[nrl] += MEM_END;\n  m[nrl] -= ncl;\n  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;\n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\ndouble **dmatrix(long nrl, long nrh, long ncl, long nch)\n/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */\n{\n  long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;\n  double **m;\n\n  /* allocate pointers to rows */\n  m=(double **) malloc((size_t)((nrow+MEM_END)*sizeof(double*)));\n  if (!m) runtimeError(\"allocation failure 1 in dmatrix()\");\n  m += MEM_END;\n  m -= nrl;\n  \n  /* allocate rows and set pointers to them */\n  m[nrl]=(double *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(double)));\n  if (!m[nrl]) runtimeError(\"allocation failure 2 in dmatrix()\");\n  m[nrl] += MEM_END;\n  m[nrl] -= ncl;\n  \n  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;\n  \n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\nint **imatrix(long nrl, long nrh, long ncl, long nch)\n/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */\n{\n  long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;\n  int **m;\n\n  /* allocate pointers to rows */\n  m=(int **) malloc((size_t)((nrow+MEM_END)*sizeof(int*)));\n  if (!m) runtimeError(\"allocation failure 1 in imatrix()\");\n  m += MEM_END;\n  m -= nrl;\n  \n  /* allocate rows and set pointers to them */\n  m[nrl]=(int *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(int)));\n  if (!m[nrl]) runtimeError(\"allocation failure 2 in imatrix()\");\n  m[nrl] += MEM_END;\n  m[nrl] -= ncl;\n  \n  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;\n  \n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\n\nchar **cmatrix(long nrl, long nrh, long ncl, long nch)\n/* allocate a char matrix with subscript range m[nrl..nrh][ncl..nch] */\n{\n  long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;\n  char **m;\n\n  /* allocate pointers to rows */\n  m=(char **) malloc((size_t)((nrow+MEM_END)*sizeof(char*)));\n  if (!m) runtimeError(\"allocation failure 1 in cmatrix()\");\n  m += MEM_END;\n  m -= nrl;\n  \n  /* allocate rows and set pointers to them */\n  m[nrl]=(char *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(char)));\n  if (!m[nrl]) runtimeError(\"allocation failure 2 in cmatrix()\");\n  m[nrl] += MEM_END;\n  m[nrl] -= ncl;\n  \n  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;\n  \n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\n\nunsigned long **lmatrix(long nrl, long nrh, long ncl, long nch)\n/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */\n{\n  long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;\n  unsigned long **m;\n\n  /* allocate pointers to rows */\n  m=(unsigned long **) malloc((size_t)((nrow+MEM_END)*sizeof(long*)));\n  if (!m) runtimeError(\"allocation failure 1 in lmatrix()\");\n  m += MEM_END;\n  m -= nrl;\n  \n  /* allocate rows and set pointers to them */\n  m[nrl]=(unsigned long *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(long)));\n  if (!m[nrl]) runtimeError(\"allocation failure 2 in lmatrix()\");\n  m[nrl] += MEM_END;\n  m[nrl] -= ncl;\n  \n  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;\n  \n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\n\nfloat **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, \n  long newrl, long newcl)\n/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */\n{\n  long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl;\n  float **m;\n  \n  /* allocate array of pointers to rows */\n  m=(float **) malloc((size_t) ((nrow+MEM_END)*sizeof(float*)));\n  if (!m) runtimeError(\"allocation failure in submatrix()\");\n  m += MEM_END;\n  m -= newrl;\n  \n  /* set pointers to rows */\n  for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol;\n  \n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\nfloat **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch)\n/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix\ndeclared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1\nand ncol=nch-ncl+1. The routine should be called with the address\n&a[0][0] as the first argument. */\n{\n  long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;\n  float **m;\n\n  /* allocate pointers to rows */\n  m=(float **) malloc((size_t) ((nrow+MEM_END)*sizeof(float*)));\n  if (!m) runtimeError(\"allocation failure in convert_matrix()\");\n  m += MEM_END;\n  m -= nrl;\n  \n  /* set pointers to rows */\n  m[nrl]=a-ncl;\n  for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;\n  \n  /* return pointer to array of pointers to rows */\n  return m;\n}\n\nfloat ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh)\n/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */\n{\n  long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;\n  float ***t;\n\n  /* allocate pointers to pointers to rows */\n  t=(float ***) malloc((size_t)((nrow+MEM_END)*sizeof(float**)));\n  if (!t) runtimeError(\"allocation failure 1 in f3tensor()\");\n  t += MEM_END;\n  t -= nrl;\n  \n  /* allocate pointers to rows and set pointers to them */\n  t[nrl]=(float **) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(float*)));\n  if (!t[nrl]) runtimeError(\"allocation failure 2 in f3tensor()\");\n  t[nrl] += MEM_END;\n  t[nrl] -= ncl;\n  \n  /* allocate rows and set pointers to them */\n  t[nrl][ncl]=(float *) malloc((size_t)((nrow*ncol*ndep+MEM_END)*sizeof(float)));\n  if (!t[nrl][ncl]) runtimeError(\"allocation failure 3 in f3tensor()\");\n  t[nrl][ncl] += MEM_END;\n  t[nrl][ncl] -= ndl;\n  \n  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;\n  for(i=nrl+1;i<=nrh;i++) {\n    t[i]=t[i-1]+ncol;\n    t[i][ncl]=t[i-1][ncl]+ncol*ndep;\n    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;\n  }\n  \n  /* return pointer to array of pointers to rows */\n  return t;\n}\n\n\nunsigned long ***lmatrix3D(long nrl, long nrh, long ncl, long nch, long ndl, long ndh)\n/* allocate an unsigned long 3D matrix with range t[nrl..nrh][ncl..nch][ndl..ndh] */\n{\n  long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;\n  unsigned long ***t;\n  long d1, d2, d3;\n  \n  /* allocate pointers to pointers to rows */\n  t=(unsigned long ***) malloc((size_t)((nrow+MEM_END)*sizeof(long**)));\n  if (!t) runtimeError(\"allocation failure 1 in lmatrix3D()\");\n  t += MEM_END;\n  t -= nrl;\n  \n  /* allocate pointers to rows and set pointers to them */\n  t[nrl]=(unsigned long **) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(long*)));\n  if (!t[nrl]) runtimeError(\"allocation failure 2 in lmatrix3D()\");\n  t[nrl] += MEM_END;\n  t[nrl] -= ncl;\n  \n  /* allocate rows and set pointers to them */\n  t[nrl][ncl]=(unsigned long *) malloc((size_t)((nrow*ncol*ndep+MEM_END)*sizeof(long)));\n  if (!t[nrl][ncl]) runtimeError(\"allocation failure 3 in lmatrix3D()\");\n  t[nrl][ncl] += MEM_END;\n  t[nrl][ncl] -= ndl;\n  \n  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;\n  for(i=nrl+1;i<=nrh;i++) {\n    t[i]=t[i-1]+ncol;\n    t[i][ncl]=t[i-1][ncl]+ncol*ndep;\n    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;\n  }  \n  \n  /* return pointer to array of pointers to rows */\n  return t;\n}\n\n\nint ***imatrix3D(int nrl, int nrh, int ncl, int nch, int ndl, int ndh)\n/* allocate an int 3D matrix with range t[nrl..nrh][ncl..nch][ndl..ndh] */\n{\n  int i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;\n  int ***t;\n  int d1, d2, d3;\n  \n  /* allocate pointers to pointers to rows */\n  t=(int ***) malloc((size_t)((nrow+MEM_END)*sizeof(int**)));\n  if (!t) runtimeError(\"allocation failure 1 in imatrix3D()\");\n  t += MEM_END;\n  t -= nrl;\n  \n  /* allocate pointers to rows and set pointers to them */\n  t[nrl]=(int **) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(int*)));\n  if (!t[nrl]) runtimeError(\"allocation failure 2 in imatrix3D()\");\n  t[nrl] += MEM_END;\n  t[nrl] -= ncl;\n  \n  /* allocate rows and set pointers to them */\n  t[nrl][ncl]=(int *) malloc((size_t)((nrow*ncol*ndep+MEM_END)*sizeof(int)));\n  if (!t[nrl][ncl]) runtimeError(\"allocation failure 3 in imatrix3D()\");\n  t[nrl][ncl] += MEM_END;\n  t[nrl][ncl] -= ndl;\n  \n  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;\n  for(i=nrl+1;i<=nrh;i++) {\n    t[i]=t[i-1]+ncol;\n    t[i][ncl]=t[i-1][ncl]+ncol*ndep;\n    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;\n  }  \n  \n  /* return pointer to array of pointers to rows */\n  return t;\n}\n\n\nvoid free_vector(float *v, long nl, long nh)\n/* free a float vector allocated with vector() */\n{\n  free((FREE_ARG) (v+nl-MEM_END));\n}\n\nvoid free_ivector(int *v, long nl, long nh)\n/* free an int vector allocated with ivector() */\n{\n  free((FREE_ARG) (v+nl-MEM_END));\n}\n\nvoid free_cvector(unsigned char *v, long nl, long nh)\n/* free an unsigned char vector allocated with cvector() */\n{\n  free((FREE_ARG) (v+nl-MEM_END));\n}\n\nvoid free_lvector(unsigned long *v, long nl, long nh)\n/* free an unsigned long vector allocated with lvector() */\n{\n  free((FREE_ARG) (v+nl-MEM_END));\n}\n\nvoid free_dvector(double *v, long nl, long nh)\n/* free a double vector allocated with dvector() */\n{\n  free((FREE_ARG) (v+nl-MEM_END));\n}\n\nvoid free_matrix(float **m, long nrl, long nrh, long ncl, long nch)\n/* free a float matrix allocated by matrix() */\n{\n  free((FREE_ARG) (m[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (m+nrl-MEM_END));\n}\n\nvoid free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch)\n/* free a double matrix allocated by dmatrix() */\n{\n  free((FREE_ARG) (m[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (m+nrl-MEM_END));\n}\n\nvoid free_imatrix(int **m, long nrl, long nrh, long ncl, long nch)\n/* free an int matrix allocated by imatrix() */\n{\n  free((FREE_ARG) (m[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (m+nrl-MEM_END));\n}\n\nvoid free_cmatrix(char **m, long nrl, long nrh, long ncl, long nch)\n/* free a char matrix allocated by imatrix() */\n{\n  free((FREE_ARG) (m[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (m+nrl-MEM_END));\n}\n\nvoid free_lmatrix(unsigned long **m, long nrl, long nrh, long ncl, long nch)\n/* free an unsigned long matrix allocated by lmatrix() */\n{\n  free((FREE_ARG) (m[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (m+nrl-MEM_END));\n}\n\nvoid free_submatrix(float **b, long nrl, long nrh, long ncl, long nch)\n/* free a submatrix allocated by submatrix() */\n{\n  free((FREE_ARG) (b+nrl-MEM_END));\n}\n\nvoid free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch)\n/* free a matrix allocated by convert_matrix() */\n{\n  free((FREE_ARG) (b+nrl-MEM_END));\n}\n\nvoid free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch,\n  long ndl, long ndh)\n/* free a float f3tensor allocated by f3tensor() */\n{\n  free((FREE_ARG) (t[nrl][ncl]+ndl-MEM_END));\n  free((FREE_ARG) (t[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (t+nrl-MEM_END));\n}\n\n\nvoid free_lmatrix3D(unsigned long ***t, long nrl, long nrh, long ncl, long nch,\n  long ndl, long ndh)\n/* free an unsigned long 3D matrix allocated by lmatrix3D() */\n{\n  free((FREE_ARG) (t[nrl][ncl]+ndl-MEM_END));\n  free((FREE_ARG) (t[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (t+nrl-MEM_END));\n}\n\n\nvoid free_imatrix3D(int ***t, int nrl, int nrh, int ncl, int nch,\n  int ndl, int ndh)\n/* free an unsigned int 3D matrix allocated by imatrix3D() */\n{\n  free((FREE_ARG) (t[nrl][ncl]+ndl-MEM_END));\n  free((FREE_ARG) (t[nrl]+ncl-MEM_END));\n  free((FREE_ARG) (t+nrl-MEM_END));\n}\n\n\nint comp_float(const void *i, const void *j) {\n    if(*(float *)i < *(float *)j)\n        return -1;\n    else if(*(float *)i > *(float *)j)\n        return 1;\n    else\n        return 0;\n}\n\n\nint comp_int(const void *i, const void *j) {\n    return *(int *)i - *(int *)j;\n}\n"
  },
  {
    "path": "src/flute/memAlloc.h",
    "content": "/* --------------------------------------------------------------------------\n   Public domain memory allocation and de-allocation routine header file.\n   Taken from Appendix B of: \n   Numerical Recipes in C: The Art of Scientific Computing, Second Edition,\n   Cambridge University Press, 1992\n----------------------------------------------------------------------------*/\n#ifndef _MEMALLOC_H_\n#define _MEMALLOC_H_\n\nstatic float sqrarg;\n#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)\n\nstatic double dsqrarg;\n#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)\n\nstatic double dmaxarg1,dmaxarg2;\n#define DMAX(a,b) (dmaxarg1=(a),dmaxarg2=(b),(dmaxarg1) > (dmaxarg2) ?\\\n(dmaxarg1) : (dmaxarg2))\n\nstatic double dminarg1,dminarg2;\n#define DMIN(a,b) (dminarg1=(a),dminarg2=(b),(dminarg1) < (dminarg2) ?\\\n(dminarg1) : (dminarg2))\n\nstatic float maxarg1,maxarg2;\n#define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\\\n(maxarg1) : (maxarg2))\n\nstatic float minarg1,minarg2;\n#define FMIN(a,b) (minarg1=(a),minarg2=(b),(minarg1) < (minarg2) ?\\\n(minarg1) : (minarg2))\n\nstatic long lmaxarg1,lmaxarg2;\n#define LMAX(a,b) (lmaxarg1=(a),lmaxarg2=(b),(lmaxarg1) > (lmaxarg2) ?\\\n(lmaxarg1) : (lmaxarg2))\n\nstatic long lminarg1,lminarg2;\n#define LMIN(a,b) (lminarg1=(a),lminarg2=(b),(lminarg1) < (lminarg2) ?\\\n(lminarg1) : (lminarg2))\n\nstatic int imaxarg1,imaxarg2;\n#define IMAX(a,b) (imaxarg1=(a),imaxarg2=(b),(imaxarg1) > (imaxarg2) ?\\\n(imaxarg1) : (imaxarg2))\n\nstatic int iminarg1,iminarg2;\n#define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\\\n(iminarg1) : (iminarg2))\n\n#define SIGN(a,b) ((b) >= 0.0 ? fflute_abs(a) : -fflute_abs(a))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n\nvoid runtimeError(char error_text[]);\nfloat *vector(long nl, long nh);\nint *ivector(long nl, long nh);\nunsigned char *cvector(long nl, long nh);\nunsigned long *lvector(long nl, long nh);\ndouble *dvector(long nl, long nh);\nfloat **matrix(long nrl, long nrh, long ncl, long nch);\ndouble **dmatrix(long nrl, long nrh, long ncl, long nch);\nint **imatrix(long nrl, long nrh, long ncl, long nch);\nchar **cmatrix(long nrl, long nrh, long ncl, long nch);\nunsigned long **lmatrix(long nrl, long nrh, long ncl, long nch);\nfloat **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch,\n                  long newrl, long newcl);\nfloat **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch);\nfloat ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh);\nunsigned long ***lmatrix3D(long nrl, long nrh, long ncl, long nch, long ndl, long ndh);\nint ***imatrix3D(int nrl, int nrh, int ncl, int nch, int ndl, int ndh);\n\nvoid free_vector(float *v, long nl, long nh);\nvoid free_ivector(int *v, long nl, long nh);\nvoid free_cvector(unsigned char *v, long nl, long nh);\nvoid free_lvector(unsigned long *v, long nl, long nh);\nvoid free_dvector(double *v, long nl, long nh);\nvoid free_matrix(float **m, long nrl, long nrh, long ncl, long nch);\nvoid free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch);\nvoid free_imatrix(int **m, long nrl, long nrh, long ncl, long nch);\nvoid free_cmatrix(char **m, long nrl, long nrh, long ncl, long nch);\nvoid free_lmatrix(unsigned long **m, long nrl, long nrh, long ncl, long nch);\nvoid free_submatrix(float **b, long nrl, long nrh, long ncl, long nch);\nvoid free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch);\nvoid free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch,\n                   long ndl, long ndh);\nvoid free_lmatrix3D(unsigned long ***t, long nrl, long nrh, long ncl, long nch,\n                   long ndl, long ndh);\nvoid free_imatrix3D(int ***t, int nrl, int nrh, int ncl, int nch, int ndl, int ndh);\nint comp_float(const void *i, const void *j);\nint comp_int(const void *i, const void *j);\n\n#endif /* _MEMALLOC_H_ */\n"
  },
  {
    "path": "src/flute/mst2.c",
    "content": "#include  <stdlib.h>\n#include  <stdio.h>\n#include   <assert.h>\n#include  \"global.h\"\n#include  \"neighbors.h\"\n#include  \"dist.h\"\n#include  \"heap.h\"\n#include  \"err.h\"\n\n\n\nvoid  mst2_package_init( long  n )\n{\n  allocate_heap( n );\n  allocate_nn_arrays( n );\n}\n\n/****************************************************************************/\n/*\n*/\n\nvoid  mst2_package_done()\n{\n  deallocate_heap();\n  deallocate_nn_arrays();\n}  \n\n/****************************************************************************/\n/*\n*/\n\nvoid  mst2\n( \n  long    n,\n  Point*  pt, \n  long*   parent\n)\n{\n  long  i, k, nn1;\n  long  d;\n  long  oct;\n  long  root = 0;\n  extern  nn_array*  nn;\n\n//  brute_force_nearest_neighbors( n, pt, nn );\n  dq_nearest_neighbors( n, pt, nn );\n\n  /* \n     Binary heap implementation of Prim's algorithm.\n     Runs in O(n*log(n)) time since at most 8n edges are considered\n  */\n\n  heap_init( n );\n  heap_insert( root, 0 );\n  parent[root] = root;\n\n  for( k = 0;  k < n;  k++ )   /* n points to be extracted from heap */\n  {\n    i = heap_delete_min();\n\n    if (i<0) break;\n#ifdef DEBUG\n    assert( i >= 0 );\n#endif \n\n    /*\n      pt[i] entered the tree, update heap keys for its neighbors\n    */\n    for( oct = 0;  oct < 8;  oct++ )\n    {\n      nn1 = nn[i][oct]; \n      if( nn1 >= 0 )\n      {\n        d  = dist( pt[i], pt[nn1] );\n        if( in_heap(nn1) && (d < heap_key(nn1)) )\n        {\n          heap_decrease_key( nn1, d );\n          parent[nn1] = i;\n        } \n        else if( never_seen(nn1) )\n        {\n          heap_insert( nn1, d );\n          parent[nn1] = i;\n        }\n      }\n    }\n  }\n}\n\n/****************************************************************************/\n/****************************************************************************/\n\n"
  },
  {
    "path": "src/flute/mst2.h",
    "content": "#ifndef _MST2_H_\n#define _MST2_H_\n\n#include \"global.h\"\n\nvoid  mst2_package_init( long  n );\nvoid  mst2_package_done();\nvoid  mst2( long n, Point* pt, long* parent );\n\n#endif \n\n"
  },
  {
    "path": "src/flute/neighbors.c",
    "content": "#include  <assert.h>\n#include  <string.h>\n#include  <stdlib.h>\n#include  \"global.h\"\n#include  \"err.h\"\n#include  \"dist.h\"\n\nlong  octant\n(\n  Point  from,\n  Point  to\n);\n\nstatic Point* _pt;\n\n/***************************************************************************/\n/*\n  For efficiency purposes auxiliary arrays are allocated as globals \n*/\n\nlong    max_arrays_size = 0;\nnn_array*  nn   = (nn_array*)NULL;\nPoint*  sheared = (Point*)NULL;\nlong*  sorted   = (long*)NULL;\nlong*  aux      = (long*)NULL;  \n\n/***************************************************************************/\n/*\n  resize the auxiliary arrays to fit the specified number of points \n*/\n\nvoid  allocate_nn_arrays( long  n )\n{\n  if( max_arrays_size < n ) \n  {\n    nn      = (nn_array*)realloc( (void*)nn, (size_t)n*sizeof(nn_array) );\n    sheared = (Point*)realloc( (void*)sheared, (size_t)n*sizeof(Point) );\n    sorted  = (long*)realloc( (void*)sorted, (size_t)n*sizeof(long) );\n    aux     = (long*)realloc( (void*)aux, (size_t)n*sizeof(long) );\n    if( !nn || !sheared || !sorted || !aux )\n    {\n      err_exit( \"Cannot allocate memory in allocate_nn_arrays!\" );\n    }\n    max_arrays_size = n;\n  }\n}\n\n/***************************************************************************/\n/*\n  free memory used by auxiliary arrays\n*/\n\nvoid  deallocate_nn_arrays()\n{\n  max_arrays_size = 0;\n  if( nn )\n  {\n    free( (void*)nn );\n    nn = (nn_array*)NULL;\n  }\n  if( sheared )\n  {\n    free( (void*)sheared );\n    sheared = (Point*)NULL;\n  }\n  if( sorted )\n  {\n    free( (void*)sorted );\n    sorted = (long*)NULL;\n  }\n  if( aux )\n  {\n    free( (void*)aux );\n    aux = (long*)NULL;\n  }\n\n}\n\n/***************************************************************************/\n/*\n  comparison function for use in quicksort\n*/\n\nstatic  int compare_x\n( \n  const void*  i, \n  const void*  j \n)\n{\n  /*\n    points with the same x must appear in increasing order of y \n  */\n  if( sheared[*((long*)i)].x == sheared[*((long*)j)].x)\n  {\n    return  sheared[*((long*)i)].y - sheared[*((long*)j)].y;\n  }\n  else\n  {\n    return  sheared[*((long*)i)].x - sheared[*((long*)j)].x;\n  }\n}\n\n\n/***************************************************************************/\n/*\n  Combine step of the Guibas-Stolfi divide-and-conquer NE nearest neighbor\n  algorithm. For efficiency purposes SW nearest neighbors are computed \n  at the same time.\n*/\n\nvoid  ne_sw_combine\n(\n  long    left,\n  long    mid,\n  long    right,\n  Point*  pt,\n  long*   sorted,\n  long*   aux,\n  long    oct,\n  nn_array*  nn\n)\n{\n  long   i, j, k, y2; \n  long   i1;\n  long   i2; \n  long   best_i2;     /* index of current best nearest-neighbor */\n  long   best_dist;   /* distance to best nearest-neighbor      */\n  long   d;\n\n#ifdef DEBUG\n  assert( right > mid );\n  assert( mid > left );\n#endif\n\n  /*\n    update north-east nearest neighbors accross the mid-line\n  */\n\n  i1 = left;\n  i2 = mid;   y2 = pt[ sorted[i2] ].y;\n\n  while( (i1 < mid) && (pt[ sorted[i1] ].y >= y2) )\n  {\n    i1++;\n  }\n  \n  if( i1 < mid )\n  {\n    best_i2   = i2;\n    best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );\n    i2++;\n\n    while( (i1 < mid) && (i2 < right) )\n    {\n      if( pt[ sorted[i1] ].y < pt[ sorted[i2] ].y )\n      {\n        d = dist2( pt + sorted[i1], pt + sorted[i2] );\n        if( d < best_dist ) \n        {\n          best_i2   = i2;\n          best_dist = d;\n        }\n        i2++;\n      }\n      else \n      {\n        if( (nn[ sorted[i1] ][oct] == -1) || \n            ( best_dist < dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) \n           )\n        {\n          nn[ sorted[i1] ][oct] = sorted[best_i2];\n        }\n        i1++;\n        if( i1 < mid )\n        {\n          best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );\n        }\n      }    \n    }\n\n    while( i1 < mid )\n    {\n      if( (nn[ sorted[i1] ][oct] == -1) || \n          ( dist2( pt + sorted[i1], pt + sorted[best_i2] ) < \n            dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) \n        )\n      {\n        nn[ sorted[i1] ][oct] = sorted[best_i2];\n      }\n      i1++;\n    }\n  }\n  /*\n    repeat for south-west nearest neighbors\n  */\n\n  oct = (oct + 4) % 8;\n\n  i1 = right - 1;\n  i2 = mid - 1;   y2 = pt[ sorted[i2] ].y;\n     \n  while( (i1 >= mid) && (pt[ sorted[i1] ].y <= y2) )\n  {\n    i1--;\n  }\n\n  if( i1 >= mid )\n  {\n    best_i2   = i2;\n    best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );\n    i2--;\n\n    while( (i1 >= mid) && (i2 >= left) )\n    {\n      if( pt[ sorted[i1] ].y > pt[ sorted[i2] ].y )\n      {\n        d = dist2( pt + sorted[i1], pt + sorted[i2] );\n        if( d < best_dist ) \n        {\n          best_i2   = i2;   \n          best_dist = d;\n        }\n        i2--;\n      }\n      else \n      {\n        if( (nn[ sorted[i1] ][oct] == -1) || \n            ( best_dist < dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) \n           )\n        {\n          nn[ sorted[i1] ][oct] = sorted[best_i2];\n        }\n        i1--;\n        if( i1 >= mid )\n        {\n          best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );\n        }\n      }    \n    }\n\n    while( i1 >= mid )\n    {\n      if( (nn[ sorted[i1] ][oct] == -1) || \n          ( dist2( pt + sorted[i1], pt + sorted[best_i2] ) < \n            dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) \n        )\n      {\n        nn[ sorted[i1] ][oct] = sorted[best_i2];\n      }\n      i1--;\n    }\n  }\n\n  /*\n    merge sorted[left..mid-1] with sorted[mid..right-1] by y-coordinate\n  */\n\n  i = left;  /* first unprocessed element in left  list  */\n  j = mid;   /* first unprocessed element in right list  */\n  k = left;  /* first free available slot in output list */\n\n  while( (i < mid) && (j < right) )\n  {\n    if( pt[ sorted[i] ].y >= pt[ sorted[j] ].y )\n    {\n      aux[k++] = sorted[i++]; \n    }\n    else \n    {\n      aux[k++] = sorted[j++]; \n    }\n  }\n\n  /*\n    copy leftovers \n  */\n  while( i < mid   ) {  aux[k++] = sorted[i++]; }\n  while( j < right ) {  aux[k++] = sorted[j++]; }\n\n  /*\n    now copy sorted points from 'aux' to 'sorted' \n  */\n\n  for( i = left;  i < right;  i++ )  { sorted[i] = aux[i]; }\n\n#if 0\n  memcpy( (void*)(sorted+left),             /* destination */\n          (void*)(aux+left),             /* source      */\n          (size_t)(right-left)*sizeof(long) /* number of bytes */ \n        );\n#endif\n\n}\n\n/***************************************************************************/\n/*\n   compute north-east and south-west nearest neighbors for points indexed \n   by {sorted[left],...,sorted[right-1]} \n*/\n\nvoid  ne_sw_nearest_neighbors\n(\n  long    left,\n  long    right,\n  Point*  pt,\n  long*   sorted,\n  long*   aux,\n  long    oct,\n  nn_array*  nn\n)\n{\n  long   mid;\n\n#ifdef DEBUG\n  assert( right > left );\n#endif\n\n  if( right == left + 1 )  \n  {\n    nn[ sorted[left] ][oct] = nn[ sorted[left]][(oct+4) % 8] = -1;\n  }\n  else\n  {\n    mid = (left + right) / 2;\n    ne_sw_nearest_neighbors( left, mid, pt, sorted, aux, oct, nn );\n    ne_sw_nearest_neighbors( mid, right, pt, sorted, aux, oct, nn );\n    ne_sw_combine( left, mid, right, pt, sorted, aux, oct, nn );\n  }\n}\n\n/***************************************************************************/\n/*\n  Guibas-Stolfi algorithm for computing nearest NE neighbors\n*/\n\nvoid  dq_nearest_neighbors\n(\n  long      n,\n  Point*    pt,\n  nn_array*  nn\n)\n{\n  long   i, oct;\n  void  check_nn( long, Point*, nn_array* );\n\n  long   shear[4][4] = {\n                         {1, -1,  0,  2}, \n                         {2,  0, -1,  1}, \n                         {1,  1, -2,  0}, \n                         {0,  2, -1, -1} \n                       };\n\n\n\n_pt = pt;\n\n  for( oct = 0;  oct < 4;  oct++ )\n  {\n    for( i = 0;   i < n;   i++ )\n    {\n      sheared[i].x = shear[oct][0]*pt[i].x + shear[oct][1]*pt[i].y;\n      sheared[i].y = shear[oct][2]*pt[i].x + shear[oct][3]*pt[i].y;\n      sorted[i] = i;\n    }\n    \n    qsort( sorted, n, sizeof(long), compare_x );\n    ne_sw_nearest_neighbors( 0, n, sheared, sorted, aux, oct, nn );\n  }\n\n#ifdef DEBUG\n  check_nn( n, pt, nn );\n#endif\n\n}\n\n/***************************************************************************/\n/***************************************************************************/\n/*\n  Brute-force nearest-neighbor computation for debugging purposes\n*/\n\n/***************************************************************************/\n/*\n  Half-open octants are numbered from 0 to 7 in anti-clockwise order \n  starting from ( dx >= dy > 0 ).\n*/\n\n#define sgn(x)  ( x>0 ? 1 : (x < 0 ? -1 : 0) )\n\nlong  octant\n( \n  Point  from,\n  Point  to\n)\n{\n  long  dx = to.x - from.x;\n  long  dy = to.y - from.y;\n  long  sgn1 = sgn(dx)*sgn(dy);\n  long  sgn2 = sgn(dx+dy)*sgn(dx-dy);\n  long   oct = 0x0;\n\n  \n  if( (dy < 0) || ((dy==0) && (dx>0)) )        oct += 4;\n  if( (sgn1 < 0) || (dy==0) )                  oct += 2;\n  if( (sgn1*sgn2 < 0) || (dy==0) || (dx==0) )  oct += 1;\n\n  return  oct;\n}\n\n/***************************************************************************/\n/*\n  O(n^2) algorithm for computing all nearest neighbors\n*/\n\nvoid  brute_force_nearest_neighbors\n(\n  long    n,\n  Point*  pt,\n  nn_array*  nn\n)\n{\n  long  i, j, oct;\n  long  d;\n\n  /*\n    compute nearest neighbors by inspecting all pairs of points \n  */\n  for( i = 0;   i < n;   i++ )\n  {\n    for( oct = 0;  oct < 8;  oct++ )\n    {\n      nn[i][oct]   = -1;\n    }\n  }\n\n  for( i = 0;   i < n;  i++ )\n  {\n    for( j = i+1;   j < n;  j++ )\n    {\n      d = dist(pt[i], pt[j]);\n\n      oct = octant( pt[i], pt[j] ); \n      if( ( nn[i][oct] == -1 ) ||\n          ( d < dist(pt[i], pt[ nn[i][oct] ]) )\n        )\n      {\n        nn[i][oct]  = j;\n      }\n\n      oct = (oct + 4) % 8;       \n      if( ( nn[j][oct] == -1 ) ||\n          ( d < dist(pt[j], pt[ nn[j][oct] ]) )\n        )\n      {\n        nn[j][oct]  = i;\n      }\n    }\n  }\n}\n\n\n/***************************************************************************/\n/*\n  compare nearest neighbors against those computed by brute force\n*/\n\nvoid  check_nn\n(\n  long    n,\n  Point*  pt,\n  nn_array*  nn\n)\n{\n  long       i, j, oct;\n  nn_array*  nn1;\n\n  nn1  = (nn_array*)calloc( (size_t)n, (size_t)sizeof(nn_array) );\n  brute_force_nearest_neighbors( n, pt, nn1 );\n\n  for( i = 0;   i < n;   i++ )\n  {\n    for( oct = 0;  oct < 8;  oct++ )\n    {\n      if( nn[i][oct] == -1 )\n      {\n        assert( nn1[i][oct] == -1 );\n      }\n      else\n      {\n        assert( nn1[i][oct] != -1 );\n\n        if( octant(pt[i], pt[ nn[i][oct] ]) != oct )\n        {\n        printf( \"WRONG OCTANT!\\noct=%ld\\n\", oct );\n        printf( \"i=%ld, x=%ld, y=%ld\\n\", i, pt[i].x, pt[i].y );\n        j = nn[i][oct];\n        printf( \"nn=%ld, x=%ld, y=%ld, dist = %ld\\n\", j, pt[j].x, pt[j].y,\n                 dist(pt[i], pt[j ]) );          \n        }\n//        assert( octant(pt[i], pt[ nn[i][oct] ]) == oct );\n\n        assert( octant(pt[i], pt[ nn1[i][oct] ]) == oct );\n\n        if( dist(pt[i], pt[ nn[i][oct] ]) != \n                dist(pt[i], pt[ nn1[i][oct] ]) ) \n       {\n        printf( \"NNs DON'T MATCH!\\noct=%ld\\n\", oct );\n        printf( \"i=%ld, x=%ld, y=%ld\\n\", i, pt[i].x, pt[i].y );\n        j = nn[i][oct];\n        printf( \"nn=%ld, x=%ld, y=%ld, dist = %ld\\n\", j, pt[j].x, pt[j].y,\n                 dist(pt[i], pt[j ]) );\n        j = nn1[i][oct];\n        printf( \"nn1=%ld, x=%ld, y=%ld, dist = %ld\\n\", j, pt[j].x, pt[j].y,\n                 dist(pt[i], pt[ j ]) );\n       }\n//        assert( dist(pt[i], pt[ nn[i][oct] ]) == \n//                dist(pt[i], pt[ nn1[i][oct] ]) );\n      }\n    }\n  }\n  \n  free( nn1 );\n}\n\n/***************************************************************************/\n/***************************************************************************/\n\n"
  },
  {
    "path": "src/flute/neighbors.h",
    "content": "#include \"global.h\"\n\nvoid  allocate_nn_arrays( long n );\nvoid  deallocate_nn_arrays();\n\nvoid  brute_force_nearest_neighbors\n(\n  long       n,\n  Point*     pt,\n  nn_array*  nn\n);\n\nvoid  dq_nearest_neighbors\n(\n  long       n,\n  Point*     pt,\n  nn_array*  nn\n);\n\n"
  },
  {
    "path": "src/global.h",
    "content": "#pragma once\n\n#include \"utils/utils.h\"\n\nusing utils::log;\nusing utils::print;\nusing utils::printflog;\nusing utils::printlog;\n\n// STL libraries\n#include <iostream>\n#include <string>\n#include <csignal>\n#include <vector>\n#include <unordered_map>\n#include <unordered_set>\n#include <thread>\n#include <mutex>\n#include <set>\n#include <tuple>\n#include <bitset>\n#include <sstream>\n#include <fstream>\n\n// Boost libraries\n#include <boost/program_options.hpp>\n#include <boost/icl/split_interval_map.hpp>\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/point.hpp>\n#include <boost/geometry/geometries/box.hpp>\n#include <boost/geometry/index/rtree.hpp>\n#include <boost/foreach.hpp>\n#include <boost/functional/hash.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\n\n// Rsyn\n#include \"rsyn/session/Session.h\"\n#define RSYN_NO_GUI\n#include \"rsyn/core/Rsyn.h\"\n#include \"rsyn/phy/PhysicalService.h\"\n#include \"rsyn/ispd18/RoutingGuide.h\"\n#include \"rsyn/io/reader/ISPD2018Reader.h\"\n\nusing boostPoint = bg::model::point<DBU, 2, bg::cs::cartesian>;\nusing boostBox = bg::model::box<boostPoint>;\nusing RTree = bgi::rtree<std::pair<boostBox, int>, bgi::rstar<32>>;\nusing RTrees = vector<bgi::rtree<std::pair<boostBox, int>, bgi::rstar<32>>>;\n\nextern double LARGE_NUM;"
  },
  {
    "path": "src/gr_db/GCell.cpp",
    "content": "#include \"GCell.h\"\n\nnamespace gr {\n\nvoid GCellGrid::init() {\n    db::RsynService rsynService;\n    rsynService.init();\n    const Rsyn::Session session;\n    Rsyn::PhysicalDesign physicalDesign =\n        static_cast<Rsyn::PhysicalService *>(session.getService(\"rsyn.physical\"))->getPhysicalDesign();\n    const DBU libDBU = physicalDesign.getDatabaseUnits(Rsyn::LIBRARY_DBU);\n\n    grid.resize(2);\n    grid[0].push_back(database.dieRegion[X].low);\n    grid[1].push_back(database.dieRegion[Y].low);\n\n    for (const Rsyn::PhysicalGCell &rsynGCell : physicalDesign.allPhysicalGCell()) {\n        int location = rsynGCell.getLocation();\n        int step = rsynGCell.getStep();\n        int numStep = rsynGCell.getNumTracks();\n        Dimension direction = rsynGCell.getDirection() == Rsyn::PhysicalGCellDirection::VERTICAL ? X : Y;\n\n        for (int i = 1; i < numStep; i++) grid[direction].push_back(location + step * i);\n    }\n\n    sort(grid[X].begin(), grid[X].end());\n    sort(grid[Y].begin(), grid[Y].end());\n\n    if (grid[X].back() != database.dieRegion[X].high) grid[X].push_back(database.dieRegion[X].high);\n    if (grid[Y].back() != database.dieRegion[Y].high) grid[Y].push_back(database.dieRegion[Y].high);\n\n    numTracks.resize(database.getLayerNum());\n    for (int i = 0; i < database.getLayerNum(); i++) {\n        Dimension dir = database.getLayerDir(i);\n        numTracks[i].resize(grid[dir].size() - 1);\n        for (unsigned g = 0; g < grid[dir].size() - 1; g++) {\n            utils::IntervalT<DBU> coorIntvl(grid[dir][g], grid[dir][g + 1]);\n            if (grid[dir][g] >= database.getLayer(i).lastTrackLoc()) {\n                numTracks[i][g] = numTracks[i][g - 1];\n            } else {\n                auto trackIntvl = database.rangeSearchTrack(i, coorIntvl);\n                bool includeBnd = database.getLayer(i).tracks[trackIntvl.high].location == coorIntvl.high;\n                numTracks[i][g] = (g == 0 ? 0 : numTracks[i][g - 1]) + trackIntvl.range() + 1 - includeBnd;\n            }\n        }\n    }\n}\n\nGrBoxOnLayer GCellGrid::rangeSearchGCell(const db::BoxOnLayer &box) const {\n    return GrBoxOnLayer(box.layerIdx, rangeSearchGCell(box[X], X), rangeSearchGCell(box[Y], Y));\n}\n\nutils::IntervalT<int> GCellGrid::rangeSearchGCell(const utils::IntervalT<DBU> &intvl, Dimension dir) const {\n    int lo_idx = lower_bound(grid[dir].begin(), grid[dir].end(), intvl.low) - grid[dir].begin();\n    if (grid[dir][lo_idx] > intvl.low) lo_idx--;\n    int hi_idx = lower_bound(grid[dir].begin(), grid[dir].end(), intvl.high) - grid[dir].begin();\n    hi_idx--;\n\n    return utils::IntervalT<int>(lo_idx, hi_idx);\n}\n\nvector<vector<GrEdge>> GCellGrid::rangeSearchGCellEdge(const db::BoxOnLayer &box) const {\n    Dimension dir = database.getLayerDir(box.layerIdx);\n\n    auto grBox = rangeSearchGCell(box);\n\n    vector<vector<GrEdge>> edges;\n    edges.resize(grBox[dir].range() + 1);\n\n    int jMin = max(grBox[1 - dir].low, 0);\n    int jMax = min(grBox[1 - dir].high, getNumGrPoint(1 - dir) - 2);\n    for (int i = grBox[dir].low; i < grBox[dir].high; i++) {\n        for (int j = jMin; j <= jMax; j++) {\n            int lx, ly, hx, hy;\n            if (dir == X) {\n                lx = hx = i;\n                ly = j;\n                hy = j + 1;\n            } else {\n                ly = hy = i;\n                lx = j;\n                hx = j + 1;\n            }\n            GrPoint p1(box.layerIdx, lx, ly), p2(box.layerIdx, hx, hy);\n            edges[i].emplace_back(p1, p2);\n        }\n    }\n\n    return edges;\n}\n\nutils::IntervalT<int> GCellGrid::getTrackIntvl(const GrPoint &point) const {\n    return getTrackIntvl(point.layerIdx, point[database.getLayerDir(point.layerIdx)]);\n}\n\nutils::IntervalT<int> GCellGrid::getTrackIntvl(int layerIdx, int idx) const {\n    return {idx == 0 ? 0 : numTracks[layerIdx][idx - 1], numTracks[layerIdx][idx] - 1};\n}\n\nvoid GCellGrid::print() const {\n    log() << \"========= gcell grid info ============\" << std::endl;\n    printflog(\"#gcell=%d*%d=%d, #edge=%d/%d\\n\",\n              getNumGrLine(X) - 1,\n              getNumGrLine(Y) - 1,\n              (getNumGrLine(X) - 1) * (getNumGrLine(Y) - 1),\n              (getNumGrLine(X) - 1) * (getNumGrLine(Y) - 2),\n              (getNumGrLine(X) - 2) * (getNumGrLine(Y) - 1));\n    for (int l = 0; l < database.getLayerNum(); l++) {\n        int totTrackNum = 0;\n        for (unsigned i = 0; i < numTracks[l].size(); i++) totTrackNum += getNumTracks(l, i);\n\n        printlog(database.getLayer(l).name, \": avg #track=\", totTrackNum / numTracks[l].size());\n    }\n}\n}  // namespace gr"
  },
  {
    "path": "src/gr_db/GCell.h",
    "content": "#pragma once\n\n#include \"db/RsynService.h\"\n#include \"global.h\"\n#include \"GrGeoPrimitive.h\"\n#include \"db/Database.h\"\n\nnamespace gr {\nclass GCellGrid {\npublic:\n    void init();\n\n    int getNumTracks(int layerIdx, int idx) const { return getTrackIntvl(layerIdx, idx).range() + 1; }\n    utils::IntervalT<int> getTrackIntvl(const GrPoint &point) const;\n\n    utils::IntervalT<DBU> getCoorIntvl(const GrPoint &point, Dimension dir) const {\n        return getCoorIntvl(point, (int)dir);\n    }\n    utils::IntervalT<DBU> getCoorIntvl(const GrPoint &point, int dir) const {\n        return {getCoor(point[dir], dir), getCoor(point[dir] + 1, dir)};\n    }\n    DBU getDist(const GrPoint &point1, const GrPoint &point2) const {\n        return getDist(point1, point2, X) + getDist(point1, point2, Y);\n    }\n    DBU getDist(const GrPoint &point1, const GrPoint &point2, Dimension dir) const {\n        return getDist(point1, point2, (int)dir);\n    }\n    DBU getDist(const GrPoint &point1, const GrPoint &point2, int dir) const {\n        return abs(getCoorIntvl(point1, dir).center() - getCoorIntvl(point2, dir).center());\n    }\n\n    DBU getCoor(int idx, Dimension dir) const { return getCoor(idx, (int)dir); }\n    DBU getCoor(int idx, int dir) const { return grid[dir][idx]; }\n\n    int getNumGrPoint(Dimension dir) const { return getNumGrPoint((int)dir); }\n    int getNumGrPoint(int dir) const { return grid[dir].size() - 1; }\n    int getNumGrLine(Dimension dir) const { return getNumGrLine((int)dir); }\n    int getNumGrLine(int dir) const { return grid[dir].size(); }\n    int getNumGrEdge(int layerIdx) const { return getNumGrPoint(1 - database.getLayerDir(layerIdx)) - 1; }\n\n    GrBoxOnLayer rangeSearchGCell(const db::BoxOnLayer &box) const;\n    utils::IntervalT<int> rangeSearchGCell(const utils::IntervalT<DBU> &intvl, Dimension dir) const;\n    vector<vector<GrEdge>> rangeSearchGCellEdge(const db::BoxOnLayer &box) const;\n\n    void print() const;\n\nprotected:\n    vector<vector<int>> numTracks;\n    vector<vector<DBU>> grid;\n\n    utils::IntervalT<DBU> getXIntvl(int idx) const { return {getX(idx), getX(idx + 1)}; }\n    utils::IntervalT<DBU> getYIntvl(int idx) const { return {getY(idx), getY(idx + 1)}; }\n\n    DBU getX(int idx) const { return getCoor(idx, X); }\n    DBU getY(int idx) const { return getCoor(idx, Y); }\n\n    utils::IntervalT<int> getTrackIntvl(int layerIdx, int idx) const;\n};\n\n}  // namespace gr"
  },
  {
    "path": "src/gr_db/GrDatabase.cpp",
    "content": "#include \"GrDatabase.h\"\n#include <fstream>\n\ngr::GrDatabase grDatabase;\n\nnamespace gr {\nvoid GrDatabase::init() {\n    GrRouteGrid::init();\n    GrNetlist::init(*this);\n\n    GrRouteGrid::print();\n}\n\nvoid GrDatabase::writeGuides(std::string filename) {\n    log() << \"Writing guides to file...\" << std::endl;\n\n    std::stringstream ss;\n\n    auto printGrGuides = [&](const vector<GrBoxOnLayer>& guides) {\n        for (const auto& guide : guides) {\n            ss << getCoor(guide[X].low, X) << \" \";\n            ss << getCoor(guide[Y].low, Y) << \" \";\n            ss << getCoor(guide[X].high + 1, X) << \" \";\n            ss << getCoor(guide[Y].high + 1, Y) << \" \";\n            ss << database.getLayer(guide.layerIdx).name << std::endl;\n        }\n    };\n\n    for (const auto& net : grDatabase.nets) {\n        ss << net.getName() << std::endl;\n        ss << \"(\" << std::endl;\n        printGrGuides(net.wireRouteGuides);\n        printGrGuides(net.viaRouteGuides);\n        printGrGuides(net.patchRouteGuides);\n        ss << \")\" << std::endl;\n    }\n\n    std::ofstream fout(filename);\n    fout << ss.str();\n    fout.close();\n}\n}  // namespace gr\n"
  },
  {
    "path": "src/gr_db/GrDatabase.h",
    "content": "#pragma once\n\n#include \"db/Database.h\"\n#include \"GrRouteGrid.h\"\n#include \"global.h\"\n#include \"GrNet.h\"\n\nnamespace gr {\nclass GrDatabase : public GrRouteGrid, public GrRouteGrid2D, public GrNetlist {\npublic:\n    void init();\n    void writeGuides(std::string filename);\n\nprivate:\n};\n\n}  // namespace gr\n\nextern gr::GrDatabase grDatabase;"
  },
  {
    "path": "src/gr_db/GrGeoPrimitive.cpp",
    "content": "#include \"GrGeoPrimitive.h\"\n\nnamespace gr {\n// GrPoint\n\nbool GrPoint::operator==(const GrPoint& rhs) const { return layerIdx == rhs.layerIdx && x == rhs.x && y == rhs.y; }\n\nbool GrPoint::operator!=(const GrPoint& rhs) const { return layerIdx != rhs.layerIdx || x != rhs.x || y != rhs.y; }\n\nostream& operator<<(ostream& os, const GrPoint& gp) {\n    os << \"gPt(l=\" << gp.layerIdx << \", xIdx=\" << gp.x << \", yIdx=\" << gp.y << \")\";\n    return os;\n}\n\n// PointOnLayer\n\nbool PointOnLayer::operator==(const PointOnLayer& rhs) const {\n    return layerIdx == rhs.layerIdx && x == rhs.x && y == rhs.y;\n}\n\nbool PointOnLayer::operator!=(const PointOnLayer& rhs) const {\n    return layerIdx != rhs.layerIdx || x != rhs.x || y != rhs.y;\n}\n\nostream& operator<<(ostream& os, const PointOnLayer& gp) {\n    os << \"gPt(l=\" << gp.layerIdx << \", xIdx=\" << gp.x << \", yIdx=\" << gp.y << \")\";\n    return os;\n}\n\n// GrEdge\n\nostream& operator<<(ostream& os, const GrEdge& edge) {\n    os << \"gEdge(\" << edge.u << \" \" << edge.v << \")\";\n    return os;\n}\n\nbool GrEdge::operator==(const GrEdge& rhs) const { return u == rhs.u && v == rhs.v; }\n\n// GrBoxOnLayer\n\nbool GrBoxOnLayer::operator==(const GrBoxOnLayer& rhs) const {\n    return layerIdx == rhs.layerIdx && x == rhs.x && y == rhs.y;\n}\n\nostream& operator<<(ostream& os, const GrBoxOnLayer& gb) {\n    os << \"gBox(l=\" << gb.layerIdx << \", xIdx=\" << gb.x << \", yIdx=\" << gb.y << \")\";\n    return os;\n}\n\n// slice polygons along sliceDir\n// sliceDir: 0 for x/vertical, 1 for y/horizontal\nvoid GrBoxOnLayer::sliceGrPolygons(vector<GrBoxOnLayer>& boxes, bool mergeAdj) {\n    if (boxes.size() <= 1) return;\n\n    auto dir = database.getLayerDir(boxes[0].layerIdx);\n\n    vector<int> locs;\n    for (const auto& box : boxes) {\n        locs.push_back(box[dir].low);\n        locs.push_back(box[dir].high);\n    }\n    sort(locs.begin(), locs.end());\n    locs.erase(unique(locs.begin(), locs.end()), locs.end());\n\n    // slice each box\n    vector<GrBoxOnLayer> slicedBoxes;\n    for (const auto& box : boxes) {\n        GrBoxOnLayer slicedBox = box;\n        auto itLoc = lower_bound(locs.begin(), locs.end(), box[dir].low);\n        auto itEnd = upper_bound(itLoc, locs.end(), box[dir].high);\n        slicedBox[dir].Set(*itLoc);\n        slicedBoxes.push_back(slicedBox);  // front boundary\n        while ((itLoc + 1) != itEnd) {\n            int left = *itLoc, right = *(itLoc + 1);\n            if ((right - left) > 1) {\n                slicedBox[dir].Set(left + 1, right - 1);\n                slicedBoxes.push_back(slicedBox);  // middle\n            }\n            slicedBox[dir].Set(right);\n            slicedBoxes.push_back(slicedBox);  // back boundary\n            ++itLoc;\n        }\n    }\n    boxes = move(slicedBoxes);\n\n    // merge overlaped boxes over crossPoints\n    utils::MergeRects(boxes, 1 - dir);\n\n    // stitch boxes over tracks\n    utils::MergeRects(boxes, dir);\n\n    if (mergeAdj) {\n        // merge box on adjacent gridline\n        std::sort(boxes.begin(), boxes.end(), [&](const BoxT& lhs, const BoxT& rhs) {\n            return lhs[dir].low < rhs[dir].low || (lhs[dir].low == rhs[dir].low && lhs[1 - dir].low < rhs[1 - dir].low);\n        });\n        std::vector<GrBoxOnLayer> mergedBoxes;\n        mergedBoxes.push_back(boxes.front());\n        for (int i = 1; i < boxes.size(); ++i) {\n            auto& lastBox = mergedBoxes.back();\n            auto& slicedBox = boxes[i];\n            if (abs(slicedBox[dir].high - lastBox[dir].low) <= 1 && slicedBox[1 - dir] == lastBox[1 - dir]) {\n                lastBox[dir] = lastBox[dir].UnionWith(slicedBox[dir]);\n            } else {  // neither misaligned not seperated\n                mergedBoxes.push_back(slicedBox);\n            }\n        }\n\n        boxes = move(mergedBoxes);\n    }\n}\n\n}  // namespace gr\n"
  },
  {
    "path": "src/gr_db/GrGeoPrimitive.h",
    "content": "#pragma once\n\n#include \"global.h\"\n#include \"db/Database.h\"\n\nnamespace gr {\n// GrPoint\nclass GrPoint : public utils::PointT<int> {\npublic:\n    int layerIdx;\n\n    GrPoint(int layerIndex = -1, int xx = -1, int yy = -1) : PointT<int>(xx, yy), layerIdx(layerIndex) {}\n\n    int getPrefIdx() const { return database.getLayerDir(layerIdx) == X ? x : y; }\n\n    bool operator==(const GrPoint& rhs) const;\n    bool operator!=(const GrPoint& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const GrPoint& gp);\n};\n\n// PointOnLayer\nclass PointOnLayer : public utils::PointT<int> {\npublic:\n    int layerIdx;\n\n    PointOnLayer(int layerIndex = -1, int xx = -1, int yy = -1) : PointT<int>(xx, yy), layerIdx(layerIndex) {}\n    PointOnLayer(const GrPoint& point) : PointT<int>(point[X], point[Y]), layerIdx(point.layerIdx) {}\n\n    bool operator==(const PointOnLayer& rhs) const;\n    bool operator!=(const PointOnLayer& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const PointOnLayer& gp);\n};\n\n// GrEdge\nclass GrEdge {\npublic:\n    GrPoint u, v;\n\n    GrEdge(const GrPoint& nodeU, const GrPoint& nodeV) {\n        // ensure u is always smaller than v\n        if (nodeU[0] <= nodeV[0] && nodeU[1] <= nodeV[1]) {\n            u = nodeU;\n            v = nodeV;\n        } else {\n            u = nodeV;\n            v = nodeU;\n        }\n    }\n\n    GrEdge(int layerIdx, int g, int cp) {\n        auto dir = database.getLayerDir(layerIdx);\n        if (dir == X) {\n            u = GrPoint(layerIdx, g, cp);\n            v = GrPoint(layerIdx, g, cp + 1);\n        } else {\n            u = GrPoint(layerIdx, cp, g);\n            v = GrPoint(layerIdx, cp + 1, g);\n        }\n    }\n\n    GrEdge(int layerIdx, int g, int lo_cp, int hi_cp) {\n        auto dir = database.getLayerDir(layerIdx);\n        if (dir == X) {\n            u = GrPoint(layerIdx, g, lo_cp);\n            v = GrPoint(layerIdx, g, hi_cp);\n        } else {\n            u = GrPoint(layerIdx, lo_cp, g);\n            v = GrPoint(layerIdx, hi_cp, g);\n        }\n    }\n\n    int getLayerIdx() const {\n        if (isVia())\n            return -1;\n        else\n            return u.layerIdx;\n    }\n    int getCutLayerIdx() const {\n        if (isVia())\n            return lowerGrPoint().layerIdx;\n        else\n            return -1;\n    }\n    DBU getGrLen() const {\n        DBU len = 0;\n        if (!isVia()) len = v[X] - u[X] + v[Y] - u[Y];\n        return len;\n    }\n\n    // two types of GridEdge: 1. via, 2. segment\n    bool isVia() const { return u.layerIdx != v.layerIdx; }\n    const GrPoint& lowerGrPoint() const { return u.layerIdx <= v.layerIdx ? u : v; }\n    const GrPoint& upperGrPoint() const { return u.layerIdx > v.layerIdx ? u : v; }\n\n    bool operator==(const GrEdge& rhs) const;\n\n    friend ostream& operator<<(ostream& os, const GrEdge& edge);\n};\n\n// GrBoxOnLayer\nclass GrBoxOnLayer : public utils::BoxT<int> {\npublic:\n    int layerIdx;\n\n    GrBoxOnLayer() : layerIdx(-1) {}  // default to be invalid\n\n    GrBoxOnLayer(int layerIndex, const utils::IntervalT<int>& xx, const utils::IntervalT<int>& yy)\n        : layerIdx(layerIndex), utils::BoxT<int>(xx, yy) {}\n\n    bool includePoint(const GrPoint& point, bool ignoreLayer = false) const {\n        return (ignoreLayer || layerIdx == point.layerIdx) && x.Contain(point[X]) && y.Contain(point[Y]);\n    }\n    // slice polygons along pref direction\n    // assume boxes are on the same layer\n    static void sliceGrPolygons(vector<GrBoxOnLayer>& boxes, bool mergeAdj);\n\n    bool operator==(const GrBoxOnLayer& rhs) const;\n    friend ostream& operator<<(ostream& os, const GrBoxOnLayer& gb);\n};\n\n}  // namespace gr\n\nnamespace std {\n\n// hash function for GrPoint\ntemplate <>\nstruct hash<gr::GrPoint> {\n    std::size_t operator()(const gr::GrPoint& gp) const {\n        return (std::hash<int>()(gp.layerIdx) ^ std::hash<int>()(gp.x) ^ std::hash<int>()(gp.y));\n    }\n};\n\n// hash for gr::GrEdge\ntemplate <>\nstruct hash<gr::GrEdge> {\n    std::size_t operator()(const gr::GrEdge edge) const {\n        // return 0;\n        return std::hash<int>()(edge.u.layerIdx) ^ std::hash<int>()(edge.u.x) ^ std::hash<int>()(edge.u.y) ^\n               std::hash<int>()(edge.v.x) ^ std::hash<int>()(edge.v.y);\n    }\n};\n\n// hash function for PointOnLayer\ntemplate <>\nstruct hash<gr::PointOnLayer> {\n    std::size_t operator()(const gr::PointOnLayer& point) const {\n        return (std::hash<int>()(point.layerIdx) ^ std::hash<int>()(point.x) ^ std::hash<int>()(point.y));\n    }\n};\n\n}  // namespace std"
  },
  {
    "path": "src/gr_db/GrNet.cpp",
    "content": "#include \"GrNet.h\"\n#include \"GrDatabase.h\"\n\nnamespace gr {\n\nvoid GrNet::init(const GCellGrid& gcellGrid) {\n    initPinAccessBoxes(gcellGrid);\n\n    // get overlap points\n    for (int p1 = 0; p1 < numOfPins(); p1++) {\n        for (int p2 = p1 + 1; p2 < numOfPins(); p2++) {\n            for (const auto& point1 : pinAccessBoxes[p1]) {\n                for (const auto& point2 : pinAccessBoxes[p2]) {\n                    if (point1 == point2) ovlpPoints.insert(point1);\n                }\n            }\n        }\n    }\n\n    // judge if it is one pin net\n    std::unordered_map<gr::GrPoint, int> pointSet;\n    for (const auto& pin : pinAccessBoxes) {\n        for (const auto& point : pin) pointSet[point]++;\n    }\n\n    for (const auto& pair : pointSet) {\n        if (pair.second == numOfPins()) {\n            isOnePin = true;\n            break;\n        }\n    }\n\n    for (const auto& pinBox : pinAccessBoxes) {\n        for (const auto& grpnt : pinBox) {\n            boundingBox[X].Update(grpnt[X]);\n            boundingBox[Y].Update(grpnt[Y]);\n        }\n    }\n}\n\n// merged pins with same coor\nvector<vector<PointOnLayer>> GrNet::getMergedPinAccessBoxes(\n    const std::function<PointOnLayer(GrPoint)>& pointHash) const {\n    vector<vector<PointOnLayer>> mergedPinAccessBoxes;\n\n    vector<vector<PointOnLayer>> hashedPinAccessBoxes(numOfPins());\n    for (int p = 0; p < numOfPins(); p++)\n        for (const auto& point : pinAccessBoxes[p]) hashedPinAccessBoxes[p].push_back(pointHash(point));\n\n    vector<vector<int>> pinConn(numOfPins());\n    for (int p1 = 0; p1 < numOfPins(); p1++) {\n        for (int p2 = p1 + 1; p2 < numOfPins(); p2++) {\n            bool overlap = false;\n            for (const auto& point1 : hashedPinAccessBoxes[p1]) {\n                if (overlap) break;\n                for (const auto& point2 : hashedPinAccessBoxes[p2]) {\n                    if (overlap) break;\n                    if (point1 == point2) {\n                        pinConn[p1].push_back(p2);\n                        pinConn[p2].push_back(p1);\n                        overlap = true;\n                    }\n                }\n            }\n        }\n    }\n    vector<bool> visited(numOfPins(), false);\n    for (int p = 0; p < numOfPins(); p++) {\n        if (visited[p]) continue;\n        std::queue<int> q;\n        q.push(p);\n        vector<PointOnLayer> points;\n        while (!q.empty()) {\n            int node = q.front();\n            q.pop();\n            copy(hashedPinAccessBoxes[node].begin(), hashedPinAccessBoxes[node].end(), std::back_inserter(points));\n            visited[node] = true;\n            for (auto child : pinConn[node])\n                if (!visited[child]) q.push(child);\n        }\n        mergedPinAccessBoxes.resize(mergedPinAccessBoxes.size() + 1);\n        mergedPinAccessBoxes.back() = move(points);\n    }\n    for (auto& points : mergedPinAccessBoxes) {\n        std::sort(points.begin(), points.end(), [&](const PointOnLayer& lhs, const PointOnLayer& rhs) {\n            if (lhs.layerIdx != rhs.layerIdx) {\n                return lhs.layerIdx < rhs.layerIdx;\n            } else {\n                if (lhs[X] != rhs[X]) {\n                    return lhs[X] < rhs[X];\n                } else {\n                    return lhs[Y] < rhs[Y];\n                }\n            }\n        });\n        points.erase(std::unique(points.begin(), points.end()), points.end());\n    }\n\n    return mergedPinAccessBoxes;\n}\n\nvoid GrNet::initPinAccessBoxes(const GCellGrid& gcellGrid) {\n    // transform coor to grPoint, construct pinAccessBoxes\n    pinAccessBoxes.resize(numOfPins());\n    for (int i = 0; i < numOfPins(); i++) {\n        const auto& boxes = dbNet.pinAccessBoxes[i];\n        std::unordered_set<GrPoint> pointSet;\n\n        DBU smallestVio = std::numeric_limits<DBU>::max();\n        vector<const db::BoxOnLayer*> smallestBoxes;\n\n        for (const auto& box : boxes) {\n            int vio = database.getOvlpFixedMetalArea(box, dbNet.idx);\n            if (vio <= smallestVio) {\n                if (vio < smallestVio) smallestBoxes.clear();\n                smallestVio = vio;\n                smallestBoxes.push_back(&box);\n            }\n\n            if (vio == 0) {\n                auto grBox = gcellGrid.rangeSearchGCell(box);\n                for (int x = grBox[X].low; x <= grBox[X].high; x++)\n                    for (int y = grBox[Y].low; y <= grBox[Y].high; y++) pointSet.emplace(box.layerIdx, x, y);\n            }\n        }\n        // all have vio, add those with smallest vio\n        if (pointSet.empty()) {\n            for (auto box : smallestBoxes) {\n                auto grBox = gcellGrid.rangeSearchGCell(*box);\n                for (int x = grBox[X].low; x <= grBox[X].high; x++)\n                    for (int y = grBox[Y].low; y <= grBox[Y].high; y++) pointSet.emplace(box->layerIdx, x, y);\n            }\n        }\n\n        for (auto& point : pointSet) pinAccessBoxes[i].push_back(point);\n    }\n}\n\nvoid GrNetlist::init(const GCellGrid& gcellGrid) {\n    for (int i = 0, sz = database.nets.size(); i < sz; i++) nets.emplace_back(i);\n    runJobsMT(database.nets.size(), [&](int i) { nets[i].init(gcellGrid); });\n}\n\nvoid GrNet::postOrderVisitGridTopo(const std::function<void(std::shared_ptr<GrSteiner>)>& visit) const {\n    for (const std::shared_ptr<GrSteiner>& tree : gridTopo) {\n        GrSteiner::postOrder(tree, visit);\n    }\n}\n\nvoid GrNet::preOrderVisitGridTopo(const std::function<void(std::shared_ptr<GrSteiner>)>& visit) const {\n    for (const std::shared_ptr<GrSteiner>& tree : gridTopo) {\n        GrSteiner::preOrder(tree, visit);\n    }\n}\n\nDBU GrNet::getWirelength() const {\n    DBU wirelength = 0;\n    postOrderVisitGridTopo([&](std::shared_ptr<gr::GrSteiner> node) {\n        auto parent = node;\n        for (auto child : parent->children) {\n            if (parent->layerIdx == child->layerIdx) wirelength += grDatabase.getDist(*parent, *child);\n        }\n    });\n    return wirelength;\n}\n\n}  // namespace gr"
  },
  {
    "path": "src/gr_db/GrNet.h",
    "content": "#pragma once\n\n#include \"db/Database.h\"\n#include \"GrGeoPrimitive.h\"\n#include \"GCell.h\"\n#include \"GridTopo.h\"\n\nnamespace gr {\nclass GrNet {\npublic:\n    db::Net& dbNet;\n\n    vector<vector<GrPoint>> pinAccessBoxes;\n    std::unordered_set<GrPoint> ovlpPoints;\n    GrBoxOnLayer boundingBox;\n\n    vector<std::shared_ptr<GrSteiner>> gridTopo;\n\n    vector<GrBoxOnLayer> wireRouteGuides;\n    vector<GrBoxOnLayer> viaRouteGuides;\n    vector<GrBoxOnLayer> patchRouteGuides;\n\n    GrNet(int i) : dbNet(database.nets[i]) {}\n    void init(const GCellGrid& gcellGrid);\n\n    unsigned numOfPins() const { return dbNet.numOfPins(); }\n    const std::string& getName() const { return dbNet.getName(); }\n\n    void postOrderVisitGridTopo(const std::function<void(std::shared_ptr<GrSteiner>)>& visit) const;\n    void preOrderVisitGridTopo(const std::function<void(std::shared_ptr<GrSteiner>)>& visit) const;\n    DBU getWirelength() const;\n\n    vector<vector<PointOnLayer>> getMergedPinAccessBoxes(const std::function<PointOnLayer(GrPoint)>& pointHash) const;\n\n    bool needToRoute() { return !isOnePin; }\n\nprivate:\n    void initPinAccessBoxes(const GCellGrid& gcellGrid);\n\n    bool isOnePin = false;\n};\n\nclass GrNetlist {\npublic:\n    vector<GrNet> nets;\n\n    void init(const GCellGrid& gcellGrid);\n};\n}  // namespace gr\n"
  },
  {
    "path": "src/gr_db/GrRouteGrid.cpp",
    "content": "#include \"GrRouteGrid.h\"\n#include \"db/Database.h\"\n#include \"GrDatabase.h\"\n#include \"db/Setting.h\"\n\nnamespace gr {\nvoid GrRouteGrid::init() {\n    int numLayers = database.getLayerNum();\n    routedWireMap.resize(numLayers);\n    fixedMetalMap.resize(numLayers);\n    histWireUsageMap.resize(numLayers);\n    routedViaMap.resize(numLayers);\n\n    GCellGrid::init();\n\n    for (int l = 0; l < numLayers; l++) {\n        auto dir = database.getLayerDir(l);\n        routedWireMap[l].resize(getNumGrPoint(dir), vector<UsageT>(getNumGrEdge(l)));\n        fixedMetalMap[l].resize(getNumGrPoint(dir), vector<std::pair<int, DBU>>(getNumGrEdge(l)));\n        histWireUsageMap[l].resize(getNumGrPoint(dir), vector<double>(getNumGrEdge(l), 0));\n        routedViaMap[l].resize(getNumGrPoint(X), vector<UsageT>(getNumGrPoint(Y)));\n    }\n\n    markFixedMetals();\n}\n\nvoid GrRouteGrid::clear() {\n    routedWireMap.clear();\n    fixedMetalMap.clear();\n    histWireUsageMap.clear();\n    routedViaMap.clear();\n}\n\nvoid GrRouteGrid::markFixed(int layerIdx, int gridline, int cp, int num_track, DBU avg_length) {\n    fixedMetalMap[layerIdx][gridline][cp] = std::make_pair(num_track, avg_length);\n}\n\nvoid GrRouteGrid::useWire(int layerIdx, int gridline, int cp, double usage) {\n    routedWireMap[layerIdx][gridline][cp] += usage;\n}\n\nvoid GrRouteGrid::useVia(int layerIdx, int x, int y, double usage) { routedViaMap[layerIdx][x][y] += usage; }\n\nvoid GrRouteGrid::useWire(const GrBoxOnLayer& box) {\n    int layerIdx = box.layerIdx;\n    auto dir = database.getLayerDir(layerIdx);\n    double usage = 1.0 / (box[dir].range() + 1);\n    for (int gridline = box[dir].low; gridline <= box[dir].high; gridline++)\n        for (int cp = box[1 - dir].low; cp < box[1 - dir].high; cp++) useWire(layerIdx, gridline, cp, usage);\n}\n\nvoid GrRouteGrid::useVia(const GrBoxOnLayer& box) {\n    double usage = 1.0 / ((box[X].range() + 1) * (box[Y].range() + 1));\n    for (int x = box[X].low; x <= box[X].high; x++)\n        for (int y = box[Y].low; y <= box[Y].high; y++) useVia(box.layerIdx, x, y, usage);\n}\n\nvoid GrRouteGrid::useNet(const GrNet& net) {\n    for (const auto& guide : net.wireRouteGuides) useWire(guide);\n\n    const auto& viaGuides = net.viaRouteGuides;\n    for (int g1 = 0; g1 < viaGuides.size(); g1++) {\n        for (int g2 = g1 + 1; g2 < viaGuides.size(); g2++) {\n            if (abs(viaGuides[g1].layerIdx - viaGuides[g2].layerIdx) != 1) continue;\n\n            auto xIntvl = viaGuides[g1][X].IntersectWith(viaGuides[g2][X]);\n            auto yIntvl = viaGuides[g1][Y].IntersectWith(viaGuides[g2][Y]);\n\n            if (xIntvl.IsValid() && yIntvl.IsValid())\n                useVia({min(viaGuides[g1].layerIdx, viaGuides[g2].layerIdx), xIntvl, yIntvl});\n        }\n    }\n}\n\n// Note: may accumulate the size of each recorder\n\nvoid GrRouteGrid::removeWire(const GrBoxOnLayer& box) {\n    int layerIdx = box.layerIdx;\n    auto dir = database.getLayerDir(layerIdx);\n    double usage = 1.0 / (box[dir].range() + 1);\n    for (int gridline = box[dir].low; gridline <= box[dir].high; gridline++)\n        for (int cp = box[1 - dir].low; cp < box[1 - dir].high; cp++) routedWireMap[layerIdx][gridline][cp] -= usage;\n}\n\nvoid GrRouteGrid::removeVia(const GrBoxOnLayer& box) {\n    double usage = 1.0 / ((box[X].range() + 1) * (box[Y].range() + 1));\n    for (int x = box[X].low; x <= box[X].high; x++)\n        for (int y = box[Y].low; y <= box[Y].high; y++) routedViaMap[box.layerIdx][x][y] -= usage;\n    // for (auto& pair : routedViaMap[box.layerIdx][x][y])\n    //     if (pair.first == netIdx) pair.second = 0;\n}\n\nvoid GrRouteGrid::removeNet(GrNet& net) {\n    for (const auto& guide : net.wireRouteGuides) removeWire(guide);\n\n    const auto& viaGuides = net.viaRouteGuides;\n    for (int g1 = 0; g1 < viaGuides.size(); g1++) {\n        for (int g2 = g1 + 1; g2 < viaGuides.size(); g2++) {\n            if (abs(viaGuides[g1].layerIdx - viaGuides[g2].layerIdx) != 1) continue;\n\n            auto xIntvl = viaGuides[g1][X].IntersectWith(viaGuides[g2][X]);\n            auto yIntvl = viaGuides[g1][Y].IntersectWith(viaGuides[g2][Y]);\n\n            if (xIntvl.IsValid() && yIntvl.IsValid())\n                removeVia({min(viaGuides[g1].layerIdx, viaGuides[g2].layerIdx), xIntvl, yIntvl});\n        }\n    }\n\n    net.wireRouteGuides.clear();\n    net.viaRouteGuides.clear();\n}\n\ndouble GrRouteGrid::getWireCapacity(const GrEdge& edge) const {\n    if (abs(edge.u[X] - edge.v[X]) > 1 || abs(edge.u[Y] - edge.v[Y]) > 1)\n        printlog(\"ERROR: in GrRouteGrid::getWireCapacity, edge len > 1\");\n    int layerIdx = edge.getLayerIdx();\n    return getNumTracks(layerIdx, edge.u[database.getLayerDir(layerIdx)]) * wireCapDiscount;\n}\n\ndouble GrRouteGrid::getInCellArea(const GrPoint& point) const {\n    int layerIdx = point.layerIdx;\n    auto dir = database.getLayerDir(layerIdx);\n    return getNumTracks(layerIdx, point[dir]);\n}\n\ndouble GrRouteGrid::getFixedUsage(const GrEdge& edge) const {  // get num of tracks blocked by fixed metal\n    if (edge.getGrLen() != 1) printlog(\"Error\");\n    auto dir = database.getLayerDir(edge.getLayerIdx());\n    return getFixedUsage(edge.getLayerIdx(), edge.u[dir], edge.u[1 - dir]);\n}\n\nDBU GrRouteGrid::getFixedLength(const GrEdge& edge) const {  // get avg length of the tracks blocked by fixed metal\n    if (edge.getGrLen() != 1) printlog(\"Error\");\n    auto dir = database.getLayerDir(edge.getLayerIdx());\n    return fixedMetalMap[edge.getLayerIdx()][edge.u[dir]][edge.u[1 - dir]].second;\n}\n\ndouble GrRouteGrid::getWireUsage(const GrEdge& edge) const {\n    if (edge.getGrLen() != 1) printlog(\"Error\");\n    auto dir = database.getLayerDir(edge.getLayerIdx());\n    return getWireUsage(edge.getLayerIdx(), edge.u[dir], edge.u[1 - dir]);\n}\n\ndouble GrRouteGrid::getViaUsage(const GrPoint& via) const { return getViaUsage(via.layerIdx, via[X], via[Y]); }\n\ndouble GrRouteGrid::getCellUsage(const GrPoint& point) const { return getCellUsage(point.layerIdx, point.x, point.y); }\n\ndouble GrRouteGrid::getInCellUsedArea(const GrPoint& point) const {\n    // note: the area defined here = # of used tracks * avg_used_length (total used length of tracks in the gcell)\n    // todo: consider boundary effect\n    double used_area = 0;\n    int layerIdx = point.layerIdx;\n    auto dir = database.getLayerDir(layerIdx);\n    int low_x = point.x - (dir == Y);\n    int low_y = point.y - (dir == X);\n    auto low_edge = GrEdge({layerIdx, low_x, low_y}, point);\n    if (low_x >= 0 && low_y >= 0) {\n        used_area += getFixedUsage(low_edge) + getWireUsage(low_edge);\n    }\n    int high_x = point.x + (dir == Y);\n    int high_y = point.y + (dir == X);\n    auto high_edge = GrEdge(point, {layerIdx, high_x, high_y});\n    if (high_x < getNumGrPoint(X) && high_y < getNumGrPoint(Y)) {\n        used_area += getFixedUsage(high_edge) + getWireUsage(high_edge);\n    }\n    return used_area / 2;\n}\n\ndouble GrRouteGrid::getFixedUsedArea(const GrEdge& edge) const {\n    // a little different to the area of a point, this is the area of an edge, which is half of 2 gcell's area combined\n    return getFixedUsage(edge) * getFixedLength(edge);\n}\n\ndouble GrRouteGrid::getInCellViaNum(const GrPoint& point) const {  // get the num of vias passing through the gcell\n    double num = 0;\n    for (int side = -1; side <= 0;\n         side++) {  // a cell is used by both the via from lower layer and that from higher layer\n        // side = -1, from lower layer to current layer; side = 0 from current layer to upper layer\n        auto via_point = GrPoint({point.layerIdx + side, point.x, point.y});\n        if (via_point.layerIdx < 0 || via_point.layerIdx >= database.getLayerNum() - 1) continue;\n        num += getViaUsage(via_point);\n    }\n    return num;\n}\n\n// double GrRouteGrid::getUnitViaArea(const GrPoint& point, int side) const {\n//     // side = -1, from lower layer to current layer; side = 0 from current layer to upper layer\n//     auto& viaType = database.getCutLayer(point.layerIdx).defaultViaType();\n//     auto viaBox = (side == 1 ? viaType.top : viaType.bot);\n//\n//     auto dir = database.getLayerDir(point.layerIdx);\n//     int nBlockedTrack = viaBox[dir].range() * grDatabase.getNumTracks(point.layerIdx, point[dir]) /\n//     grDatabase.getCoorIntvl(point, dir).range() + 1; return viaBox[1 - dir].range() * nBlockedTrack;\n// }\n\ndouble GrRouteGrid::getFixedUsage(int layerIdx,\n                                  int gridline,\n                                  int cp) const {  // get num of tracks blocked by fixed metal\n    return fixedMetalMap[layerIdx][gridline][cp].first;\n}\n\ndouble GrRouteGrid::getWireUsage(int layerIdx, int gridline, int cp) const {\n    return routedWireMap[layerIdx][gridline][cp];\n}\n\ndouble GrRouteGrid::getViaUsage(int layerIdx, int x, int y) const { return routedViaMap[layerIdx][x][y]; }\n\ndouble GrRouteGrid::GrRouteGrid::getCellUsage(int layerIdx, int x, int y) const {\n    auto layerDir = database.getLayerDir(layerIdx);\n    double totalRsrc = grDatabase.getNumTracks(layerIdx, layerDir == X ? x : y);\n    double cellUsage = 0;\n    int low_x = x - (layerDir == Y);\n    int low_y = y - (layerDir == X);\n    if (low_x >= 0 && low_y >= 0) {\n        auto low_edge = gr::GrEdge({layerIdx, low_x, low_y}, {layerIdx, x, y});\n        cellUsage += grDatabase.getFixedUsage(low_edge) + grDatabase.getWireUsage(low_edge);\n    }\n    int high_x = x + (layerDir == Y);\n    int high_y = y + (layerDir == X);\n    if (high_x < grDatabase.getNumGrPoint(X) && high_y < grDatabase.getNumGrPoint(Y)) {\n        auto high_edge = gr::GrEdge({layerIdx, x, y}, {layerIdx, high_x, high_y});\n        cellUsage += grDatabase.getFixedUsage(high_edge) + grDatabase.getWireUsage(high_edge);\n    }\n    cellUsage /= 2;\n    cellUsage += sqrt(grDatabase.getInCellViaNum({layerIdx, x, y})) * db::setting.unitSqrtViaUsage;\n    return totalRsrc - cellUsage;\n}\n\nvoid GrRouteGrid::print() const { GCellGrid::print(); }\n\nvoid GrRouteGrid::printAllUsageAndVio() const {\n    const int width = 10;\n    auto wlVia = printAllUsage();\n    double numShort = printAllVio();\n    log() << \"--- Estimated Scores ---\" << std::endl;\n    vector<std::string> items = {\"wirelength\", \"# vias\", \"short\"};\n    vector<double> metrics = {wlVia.first, wlVia.second, numShort};\n    vector<double> weights = {db::setting.weightWirelength, db::setting.weightViaNum, db::setting.weightShortArea};\n    double totalScore = 0;\n    for (int i = 0; i < items.size(); ++i) {\n        totalScore += metrics[i] * weights[i];\n    }\n    log() << std::setw(width) << \"item\"\n          << \" | \" << std::setw(width + 2) << \"metric\"\n          << \" | \" << std::setw(width) << \"weight\"\n          << \" | \" << std::setw(width + 2) << \"score\"\n          << \" | \" << std::setw(width) << \"\\%\" << std::endl;\n    for (int i = 0; i < items.size(); ++i) {\n        double score = metrics[i] * weights[i];\n        log() << std::setw(width) << items[i] << \" | \" << std::setw(width + 2) << metrics[i] << \" | \"\n              << std::setw(width) << weights[i] << \" | \" << std::setw(width + 2) << score << \" | \" << std::setw(width)\n              << score / totalScore << std::endl;\n    }\n    log() << \"total score = \" << totalScore << std::endl;\n}\n\ndouble GrRouteGrid::getAllWireUsage(const vector<double>& buckets,\n                                    vector<int>& wireUsageGrid,\n                                    vector<DBU>& wireUsageLength) const {\n    double wirelength = 0;\n    wireUsageGrid.assign(buckets.size(), 0);\n    wireUsageLength.assign(buckets.size(), 0);\n    for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n        Dimension dir = database.getLayerDir(layerIdx);\n\n        for (int gridline = 0; gridline < getNumGrPoint(dir); gridline++) {\n            for (int cp = 0; cp < getNumGrEdge(layerIdx); cp++) {\n                double numWire = getWireUsage(layerIdx, gridline, cp);\n                double usage = (numWire + getFixedUsage({layerIdx, gridline, cp})) / getNumTracks(layerIdx, gridline);\n                DBU dist = (getCoor(cp + 2, 1 - dir) - getCoor(cp, 1 - dir)) / 2;\n                int bucketIdx = buckets.size() - 1;\n                while (buckets[bucketIdx] >= usage) --bucketIdx;\n                bucketIdx = max(bucketIdx, 0);\n                wireUsageGrid[bucketIdx]++;\n                wireUsageLength[bucketIdx] += dist;\n                wirelength += dist * numWire;\n            }\n        }\n    }\n\n    return wirelength;\n}\n\ndouble GrRouteGrid::getWirelength() const {\n    double wirelength = 0;\n    for (auto& net : grDatabase.nets) wirelength += net.getWirelength();\n    return wirelength;\n}\n\nvoid GrRouteGrid::getAllInCellUsage(const vector<double>& buckets, vector<int>& inCellUsage) const {\n    inCellUsage.assign(buckets.size(), 0);\n    for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n        for (int x = 0; x < getNumGrPoint(X); x++) {\n            for (int y = 0; y < getNumGrPoint(Y); y++) {\n                double usage = getInCellUsedArea({layerIdx, x, y}) / getInCellArea({layerIdx, x, y});\n                int bucketIdx = buckets.size() - 1;\n                while (buckets[bucketIdx] >= usage) --bucketIdx;\n                bucketIdx = max(bucketIdx, 0);\n                inCellUsage[bucketIdx]++;\n            }\n        }\n    }\n}\n\ndouble GrRouteGrid::getTotViaNum() const {\n    double viaNum = 0;\n    for (int layerIdx = 0; (layerIdx + 1) < database.getLayerNum(); ++layerIdx) {\n        for (int x = 0; x < getNumGrPoint(X); x++) {\n            for (int y = 0; y < getNumGrPoint(Y); y++) {\n                viaNum += getViaUsage(layerIdx, x, y);\n            }\n        }\n    }\n    return viaNum;\n}\n\nstd::pair<double, double> GrRouteGrid::printAllUsage() const {\n    const int width = 10;\n    vector<double> buckets = {\n        -1, 0, 0.3, 0.6, 0.8, 0.9, 1, 1.1, 1.3, 1.5, 2, 3};  // the i-th bucket: buckets[i] <= x < buckets[i+1]\n\n    auto getRangeStr = [](const vector<double>& buckets, int i) {\n        std::string range;\n        if (i == 0) {\n            range = \"      \" + std::to_string_with_precision(0.0, 2) + \" \";\n        } else if ((i + 1) < buckets.size()) {\n            range = \"(\" + std::to_string_with_precision(buckets[i], 2) + \"~\" +\n                    std::to_string_with_precision(buckets[i + 1], 2) + \"]\";\n        } else {\n            range = \"(\" + std::to_string_with_precision(buckets[i], 2) + \"~inf\" + \")\";\n        }\n        return range;\n    };\n\n    // Wire\n    vector<int> routedWireUsageGrid;\n    vector<DBU> routedWireUsageLength;\n    double wireLength = getAllWireUsage(buckets, routedWireUsageGrid, routedWireUsageLength);\n    log() << \"--- Wire Usage ---\" << std::endl;\n    log() << std::setw(width) << \"usage\"\n          << \" | \" << std::setw(width) << \"   grid   \"\n          << \" | \" << std::setw(width) << \"  length  \" << std::endl;\n    for (int i = 0; i < buckets.size(); ++i) {\n        if (routedWireUsageGrid[i] == 0 && routedWireUsageLength[i] == 0) continue;\n\n        log() << std::setw(width) << getRangeStr(buckets, i) << \" | \" << std::setw(width) << routedWireUsageGrid[i]\n              << \" | \" << std::setw(width) << routedWireUsageLength[i] / double(database.getLayer(1).pitch)\n              << std::endl;\n    }\n    wireLength /= double(database.getLayer(1).pitch);\n\n    // in-Cell\n    vector<int> routedViaUsage;\n    getAllInCellUsage(buckets, routedViaUsage);\n    log() << \"--- in-Cell Usage ---\" << std::endl;\n    log() << std::setw(width) << \"usage\"\n          << \" | \" << std::setw(width) << \"routed\" << std::endl;\n    for (int i = 0; i < buckets.size(); ++i) {\n        if (routedViaUsage[i] == 0) continue;\n\n        log() << std::setw(width) << getRangeStr(buckets, i) << \" | \" << std::setw(width) << routedViaUsage[i]\n              << std::endl;\n    }\n\n    double viaNum = getTotViaNum();\n    return {wireLength, viaNum};\n}\n\ndouble GrRouteGrid::printAllVio() const {\n    const int width = 10;\n    auto sumVec = [](const vector<int>& vec) {\n        int sum = 0;\n        for (int val : vec) {\n            sum += val;\n        }\n        return sum;\n    };\n\n    // Wire violations\n    vector<double> shortLen(database.getLayerNum(), 0.0);\n    for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n        Dimension dir = database.getLayerDir(layerIdx);\n\n        for (int gridline = 0; gridline < getNumGrPoint(dir); gridline++) {\n            for (int cp = 0; cp < getNumGrEdge(layerIdx); cp++) {\n                double numWire = getWireUsage(layerIdx, gridline, cp) + getFixedUsage(layerIdx, gridline, cp);\n                DBU dist = (getCoor(cp + 2, 1 - dir) - getCoor(cp, 1 - dir)) / 2;\n\n                double overflow = max(0.0, numWire - getNumTracks(layerIdx, gridline));\n                shortLen[layerIdx] += overflow * dist;\n            }\n        }\n    }\n\n    log() << \"--- Wire-Wire Short Vios ---\" << std::endl;\n    log() << std::setw(width) << \"usage\"\n          << \" | \" << std::setw(width * 2 + 3) << \"      short area     \" << std::endl;\n    log() << std::setw(width) << \"layer\"\n          << \" | \" << std::setw(width) << \"wire-wire\" << std::endl;\n    double routedShortArea = 0;\n    for (int i = 0; i < database.getLayerNum(); ++i) {\n        if (shortLen[i] == 0) continue;\n        const auto& layer = database.getLayer(i);\n        double routedArea = double(shortLen[i]) * layer.width / database.getLayer(1).pitch / database.getLayer(1).pitch;\n        log() << std::setw(width) << database.getLayer(i).name << \" | \" << std::setw(width) << routedArea << std::endl;\n        routedShortArea += routedArea;\n    }\n    log() << std::setw(width) << \"SumW\"\n          << \" | \" << std::setw(width) << routedShortArea << std::endl;\n\n    // Via violations\n    vector<double> shortNum(database.getLayerNum() - 1, 0.0);\n    for (int layerIdx = 0; layerIdx < database.getLayerNum() - 1; ++layerIdx) {\n        for (int x = 0; x < getNumGrPoint(X); x++) {\n            for (int y = 0; y < getNumGrPoint(Y); y++) {\n                double overflow = getNumVio(GrPoint({layerIdx, x, y}), 0);\n                shortNum[layerIdx] += overflow;\n            }\n        }\n    }\n\n    log() << \"--- Via-Via Short Vios ---\" << std::endl;\n    log() << std::setw(width) << \"usage\"\n          << \" | \" << std::setw(width * 2 + 3) << \"      #short     \" << std::endl;\n    log() << std::setw(width) << \"layer\"\n          << \" | \" << std::setw(width) << \"via-via\" << std::endl;\n    double routedShortViaNum = 0;\n    for (int i = 0; i < database.getLayerNum() - 1; ++i) {\n        if (shortNum[i] == 0) continue;\n        log() << std::setw(width) << database.getCutLayer(i).name << \" | \" << std::setw(width) << shortNum[i]\n              << std::endl;\n        routedShortViaNum += shortNum[i];\n    }\n    log() << std::setw(width) << \"SumW\"\n          << \" | \" << std::setw(width) << routedShortViaNum << std::endl;\n    routedShortArea += routedShortViaNum;\n    return routedShortArea;\n}\n\nvoid GrRouteGrid::markFixedMetals() {\n    for (int l = 0; l < database.getLayerNum(); l++) {\n        std::unordered_map<std::pair<int, int>,\n                           vector<std::pair<utils::IntervalT<int>, DBU>>,\n                           boost::hash<std::pair<int, int>>>\n            markingBuffer;  // (gridline, cp) -> (interval,netIdx)\n\n        Dimension dir = database.getLayerDir(l);\n        const RTree& tree = database.getFixedMetals(l);\n        auto bit = tree.qbegin(bgi::satisfies([](auto const&) { return true; })), eit = tree.qend();\n        for (auto iter = bit; iter != eit; iter++) {\n            const auto& pair = *iter;\n            int netIdx = pair.second;\n\n            db::BoxOnLayer box(l,\n                               bg::get<bg::min_corner, 0>(pair.first),\n                               bg::get<bg::min_corner, 1>(pair.first),\n                               bg::get<bg::max_corner, 0>(pair.first),\n                               bg::get<bg::max_corner, 1>(pair.first));\n\n            // compute the forbid region of a fixed metal\n            db::AggrParaRunSpace aggr = db::AggrParaRunSpace::DEFAULT;\n            if (database.getLayer(0).parallelLength.size() <= 1) {\n                // hack for ISPD'18 test cases\n                aggr = db::AggrParaRunSpace::LARGER_WIDTH;\n                if (min(box.width(), box.height()) == database.getLayer(box.layerIdx).width &&\n                    database.getOvlpFixedMetals(box, -2).size() == 1) {\n                    aggr = db::AggrParaRunSpace::DEFAULT;\n                }\n            } else {\n                // hack for ISPD'19 test cases\n                aggr = db::AggrParaRunSpace::LARGER_LENGTH;\n            }\n            auto forbidRegion = database.getMetalRectForbidRegion(box, aggr);\n            auto gridBox = database.rangeSearch(forbidRegion,\n                                                aggr == db::AggrParaRunSpace::LARGER_WIDTH);  // TODO: change to false\n            if (!database.isValid(gridBox)) continue;\n            box = database.getLoc(gridBox);\n\n            auto grBox = rangeSearchGCell(box);\n            auto trackIntvl = database.rangeSearchTrack(l, box[dir]);\n            if (!trackIntvl.IsValid()) continue;\n\n            // mark wire usage\n            int jMin = max(grBox[1 - dir].low - 1, 0);\n            int jMax = min(grBox[1 - dir].high, getNumGrPoint(1 - dir) - 2);\n            for (int i = grBox[dir].low; i <= grBox[dir].high; i++) {\n                for (int j = jMin; j <= jMax; j++) {\n                    utils::IntervalT<DBU> gcellIntvl1 = {getCoor(j, 1 - dir), getCoor(j + 1, 1 - dir)};\n                    utils::IntervalT<DBU> gcellIntvl2 = {getCoor(j + 1, 1 - dir), getCoor(j + 2, 1 - dir)};\n                    utils::IntervalT<DBU> edgeIntvl = {gcellIntvl1.center(), gcellIntvl2.center()};\n\n                    auto blocked_length = box[1 - dir].IntersectWith(edgeIntvl).range();\n                    if (blocked_length > 0) {\n                        auto gcellTrackIntvl = getTrackIntvl(l, i);\n                        auto blockedIntvl = gcellTrackIntvl.IntersectWith(trackIntvl);\n                        if (blockedIntvl.IsValid())\n                            markingBuffer[std::make_pair(i, j)].emplace_back(\n                                std::make_pair(blockedIntvl, blocked_length));\n                    }\n                }\n            }\n        }\n\n        for (auto& buf : markingBuffer) {\n            auto gcellTrackIntvl = getTrackIntvl(l, buf.first.first);\n            vector<DBU> trackBlocked(gcellTrackIntvl.range() + 1, 0);  // blocked track length\n            for (auto& pair : buf.second) {\n                for (int t = pair.first.low; t <= pair.first.high; t++)\n                    trackBlocked[t - gcellTrackIntvl.low] += pair.second;\n            }\n            int num_blocked = 0;\n            DBU avg_blocked_len = 0;\n\n            for (auto& len : trackBlocked) {\n                if (len > 0) {\n                    num_blocked++;\n                    avg_blocked_len += len;\n                }\n            }\n            avg_blocked_len /= num_blocked;\n            markFixed(l, buf.first.first, buf.first.second, num_blocked, avg_blocked_len);\n        }\n    }\n}\n\ndb::CostT GrRouteGrid::getViaCost(const GrPoint& via) const {\n    return database.getUnitViaCost() * (unitViaMultiplier + getViaShortCost(via));\n}\n\ndb::CostT GrRouteGrid::getStackViaCost(const GrPoint& via, int height) const {\n    db::CostT cost = 0;\n    for (int i = 0; i < height; i++) {\n        cost += getViaCost(gr::GrPoint(via.layerIdx + i, via.x, via.y));\n    }\n    return cost;\n};\n\ndb::CostT GrRouteGrid::getWireDistCost(const GrEdge& edge) const {\n    Dimension dir = database.getLayerDir(edge.getLayerIdx());\n    return getDist(edge.lowerGrPoint(), edge.upperGrPoint(), 1 - dir);\n}\n\n// logistic cost, ref: nctugr (8)\n// \" With a growing number of rip-up and rerouting iterations,\n// the value of slope also grows to free the edge usage constraint. \"\n\ndb::CostT GrRouteGrid::getWireShortCost(const GrEdge& edge) const {\n    // Note: didn't consider occurrence penalty\n    int layerIdx = edge.getLayerIdx();\n    auto dir = database.getLayerDir(layerIdx);\n\n    db::CostT cost = 0;\n\n    int gridline = edge.u[dir];\n    for (int i = edge.u[1 - dir]; i < edge.v[1 - dir]; i++) {\n        GrEdge tempEdge(layerIdx, gridline, i);\n\n        auto fixed_used = getFixedUsage(tempEdge);\n\n        auto wire_used = getWireUsage(tempEdge);\n        DBU expected_of_len = fixed_used * getFixedLength(tempEdge) + wire_used * getWireDistCost(tempEdge);\n        expected_of_len /= grDatabase.getNumTracks(layerIdx, edge.u[dir]);\n        auto demand = fixed_used + wire_used + 1;\n        demand += sqrt((getInCellViaNum(tempEdge.u) + getInCellViaNum(tempEdge.v)) / 2) * db::setting.unitSqrtViaUsage;\n        auto capacity = getWireCapacity(tempEdge);\n\n        cost += expected_of_len / (1.0 + exp(-logisticSlope * (demand - capacity)));\n    }\n\n    return cost * database.getUnitShortCost(layerIdx);\n}\n\ndb::CostT GrRouteGrid::getViaShortCost(const GrPoint& via) const {\n    double cost = 0;\n    for (int side = 0; side <= 1; side++) {\n        auto side_point = GrPoint({via.layerIdx + side, via.x, via.y});\n        double incell_used = getInCellUsedArea(side_point);\n        double incell_area = getInCellArea(side_point);\n        cost += 1.0 / (1.0 + exp(-logisticSlope * (incell_used - incell_area)));\n    }\n    return cost;\n    // return cost;\n}\n\ndb::CostT GrRouteGrid::getWireCost(const GrEdge& edge) const {\n    if (edge.getLayerIdx() == 0) return LARGE_NUM;\n    return getWireDistCost(edge) + getWireShortCost(edge);\n    // return db::setting.wirelenCostWeight*getWireDistCost(edge) + getWireShortCost(edge);\n}\n\nbool GrRouteGrid::hasVio(const GrNet& net, bool hasCommit) const { return getNumVio(net, hasCommit) > 0; }\n\nbool GrRouteGrid::hasVio(const GrEdge& edge, bool hasCommit) const { return getNumVio(edge, !hasCommit) > 0; }\n\nbool GrRouteGrid::hasVio(const GrPoint& via, bool hasCommit) const { return getNumVio(via, !hasCommit) > 0; }\n\ndouble GrRouteGrid::getNumVio(const GrNet& net, bool hasCommit) const {\n    double numVio = 0;\n\n    const auto& guides = net.wireRouteGuides;\n    for (const auto& guide : guides) {\n        auto dir = database.getLayerDir(guide.layerIdx);\n        double usage = 1.0 / (guide[dir].range() + 1);\n        for (int gridline = guide[dir].low; gridline <= guide[dir].high; gridline++) {\n            GrEdge tempEdge = (dir == X) ? GrEdge(guide.layerIdx, gridline, guide[Y].low, guide[Y].high)\n                                         : GrEdge(guide.layerIdx, gridline, guide[X].low, guide[X].high);\n            numVio += getNumVio(tempEdge, hasCommit ? 0 : usage);\n        }\n    }\n\n    const auto& viaGuides = net.viaRouteGuides;\n    for (int g1 = 0; g1 < viaGuides.size(); g1++) {\n        for (int g2 = g1 + 1; g2 < viaGuides.size(); g2++) {\n            if (abs(viaGuides[g1].layerIdx - viaGuides[g2].layerIdx) != 1) continue;\n\n            auto xIntvl = viaGuides[g1][X].IntersectWith(viaGuides[g2][X]);\n            auto yIntvl = viaGuides[g1][Y].IntersectWith(viaGuides[g2][Y]);\n\n            if (xIntvl.IsValid() && yIntvl.IsValid()) {\n                double usage = 1.0 / ((xIntvl.range() + 1) * (yIntvl.range() + 1));\n\n                for (int x = xIntvl.low; x <= xIntvl.high; x++)\n                    for (int y = yIntvl.low; y <= yIntvl.high; y++)\n                        numVio += getNumVio(GrPoint(min(viaGuides[g1].layerIdx, viaGuides[g2].layerIdx), x, y),\n                                            hasCommit ? 0 : usage);\n            }\n        }\n    }\n\n    return numVio;\n}\n\ndouble GrRouteGrid::getNumVio(const GrEdge& edge, double selfUsage) const {\n    int layerIdx = edge.getLayerIdx();\n    auto dir = database.getLayerDir(layerIdx);\n    int gridline = edge.u[dir];\n\n    double numVio = 0;\n\n    for (int i = edge.u[1 - dir]; i < edge.v[1 - dir]; i++) {\n        GrEdge tempEdge(layerIdx, gridline, i);\n        numVio += max(\n            0.0,\n            getWireUsage(tempEdge) + selfUsage + getFixedUsage(tempEdge) +\n                sqrt((getInCellViaNum(tempEdge.u) + getInCellViaNum(tempEdge.v)) / 2) * db::setting.unitSqrtViaUsage -\n                getWireCapacity(tempEdge));\n    }\n    return numVio;\n}\n\ndouble GrRouteGrid::getNumVio(const GrPoint& via, double selfUsage) const {\n    double via_usage = getViaUsage(via) + selfUsage;\n    double numVio = 0;\n    for (int side = 0; side <= 1; side++) {\n        auto side_point = GrPoint({via.layerIdx + side, via.x, via.y});\n        auto incell_area = getInCellArea(side_point);\n        auto incell_used_area = getInCellUsedArea(side_point);\n        if (incell_area >= incell_used_area) {  // have remaining area\n\n        } else {  // have no remaining area\n            numVio += via_usage;\n        }\n    }\n    // if (numVio != 0)\n    // log() << numVio << std::endl;\n    return numVio;\n}\n\nvoid GrRouteGrid::setViaCapDiscount(double discount) {\n    printflog(\"viaCapDiscount change: %.2f->%.2f\\n\", viaCapDiscount, discount);\n    viaCapDiscount = discount;\n}\n\nvoid GrRouteGrid::setWireCapDiscount(double discount) {\n    printflog(\"wireCapDiscount change: %.2f->%.2f\\n\", wireCapDiscount, discount);\n    wireCapDiscount = discount;\n}\n\nvoid GrRouteGrid::setUnitViaMultiplier(double multiplier) {\n    printflog(\"unitViaMultiplier change: %.2f->%.2f\\n\", unitViaMultiplier, multiplier);\n    unitViaMultiplier = multiplier;\n}\n\nvoid GrRouteGrid::setLogisticSlope(double slope) {\n    printflog(\"logisticSlope change: %.2f->%.2f\\n\", logisticSlope, slope);\n    logisticSlope = slope;\n}\n\nvoid GrRouteGrid::addHistCost() {\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        printlog(\"Add hist cost\");\n    }\n\n    for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n        auto dir = database.getLayerDir(layerIdx);\n        for (int g = 0; g < getNumGrPoint(dir); ++g) {\n            for (int cp = 0; cp < getNumGrEdge(layerIdx); ++cp) {\n                GrEdge tempEdge(layerIdx, g, cp);\n                if (hasVio(tempEdge)) useHistWire(layerIdx, g, cp, 1);\n            }\n        }\n    }\n}\n\nvoid GrRouteGrid::useHistWire(int layerIdx, int gridline, int cp, double usage) {\n    histWireUsageMap[layerIdx][gridline][cp] += usage;\n}\n\nvoid GrRouteGrid::fadeHistCost() {\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        printlog(\"Fade hist cost by\", db::setting.rrrFadeCoeff, \"...\");\n    }\n    for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n        auto dir = database.getLayerDir(layerIdx);\n        // wire\n        for (int g = 0; g < getNumGrPoint(dir); ++g)\n            for (int cp = 0; cp < getNumGrEdge(layerIdx); ++cp)\n                histWireUsageMap[layerIdx][g][cp] *= db::setting.rrrFadeCoeff;\n    }\n}\n\nvoid GrRouteGrid::statHistCost() const {\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::MIDDLE) {\n        std::map<db::CostT, int> histWireUsage, histViaUsage;\n        for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n            auto dir = database.getLayerDir(layerIdx);\n            // wire\n            for (int g = 0; g < getNumGrPoint(dir); ++g)\n                for (int cp = 0; cp < getNumGrEdge(layerIdx); ++cp) ++histWireUsage[histWireUsageMap[layerIdx][g][cp]];\n            // via\n        }\n        printlog(\"Hist wire usage is\", histWireUsage);\n        printlog(\"Hist via usage is\", histViaUsage);\n    }\n}\n\nvoid GrRouteGrid2D::init2DMaps(const GrRouteGrid& routeGrid) {\n    int numLayers = database.getLayerNum();\n    wireUsageMap2D.resize(2);\n    fixedMetalMap2D.resize(2);\n    capacityMap2D.resize(2);\n\n    int xNumGrPoint = routeGrid.getNumGrPoint(X);\n    int yNumGrPoint = routeGrid.getNumGrPoint(Y);\n    int xNumGrEdge = yNumGrPoint - 1;\n    int yNumGrEdge = xNumGrPoint - 1;\n    wireUsageMap2D[X].resize(xNumGrPoint, vector<double>(xNumGrEdge, 0));\n    fixedMetalMap2D[X].resize(xNumGrPoint, vector<double>(xNumGrEdge, 0));\n    capacityMap2D[X].resize(xNumGrPoint, vector<double>(xNumGrEdge, 0));\n\n    wireUsageMap2D[Y].resize(yNumGrPoint, vector<double>(yNumGrEdge, 0));\n    fixedMetalMap2D[Y].resize(yNumGrPoint, vector<double>(yNumGrEdge, 0));\n    capacityMap2D[Y].resize(yNumGrPoint, vector<double>(yNumGrEdge, 0));\n\n    for (int l = 0; l < numLayers; l++) {\n        auto dir = database.getLayerDir(l);\n        if (dir == X) {\n            for (int gridline = 0; gridline < xNumGrPoint; gridline++) {\n                for (int cp = 0; cp < xNumGrEdge; cp++) {\n                    GrEdge tempEdge(l, gridline, cp);\n                    fixedMetalMap2D[X][gridline][cp] += routeGrid.getFixedUsage(tempEdge);\n                    capacityMap2D[X][gridline][cp] += routeGrid.getWireCapacity(tempEdge);\n                }\n            }\n        } else {\n            for (int gridline = 0; gridline < yNumGrPoint; gridline++) {\n                for (int cp = 0; cp < yNumGrEdge; cp++) {\n                    GrEdge tempEdge(l, gridline, cp);\n                    fixedMetalMap2D[Y][gridline][cp] += routeGrid.getFixedUsage(tempEdge);\n                    capacityMap2D[Y][gridline][cp] += routeGrid.getWireCapacity(tempEdge);\n                }\n            }\n        }\n    }\n}\n\nvoid GrRouteGrid2D::useWire2D(int dir, int gridline, int cp, double usage) {\n    wireUsageMap2D[dir][gridline][cp] += usage;\n}\nvoid GrRouteGrid2D::removeUsage2D(int dir, int gridline, int cp, double usage) {\n    wireUsageMap2D[dir][gridline][cp] -= usage;\n}\ndouble GrRouteGrid2D::getCost2D(int dir, int gridline, int cp) const {\n    double cost = 0;\n\n    double fixed_usage = fixedMetalMap2D[dir][gridline][cp];\n    double wire_usage = wireUsageMap2D[dir][gridline][cp];\n    double cap = capacityMap2D[dir][gridline][cp];\n\n    double demand = fixed_usage + wire_usage;\n    cost += 1 / (1.0 + exp(-1 * grDatabase.getLogisticSlope() * (demand - cap)));\n    return cost;\n}\n\n}  // namespace gr\n"
  },
  {
    "path": "src/gr_db/GrRouteGrid.h",
    "content": "#pragma once\n\n#include \"GCell.h\"\n#include \"GrGeoPrimitive.h\"\n#include \"GrNet.h\"\n\nnamespace gr {\nclass GrRouteGrid : public GCellGrid {\npublic:\n    using UsageT = double;\n    using UsageMapT = vector<vector<vector<UsageT>>>;\n    int edge_shifted =0;\n    int tot_edge = 0;\n\n    void init();\n    void clear();\n\n    void useNet(const GrNet& net);\n    void removeNet(GrNet& net);\n\n    db::CostT getViaCost(const GrPoint& via) const;\n    db::CostT getStackViaCost(const GrPoint& via, int height) const;\n    db::CostT getWireCost(const GrEdge& edge) const;\n    db::CostT getHistCost(int layerIdx, int gridline, int cp) const;\n\n    double getCellUsage(const GrPoint& point) const;  // Note: simplified version\n\n    bool hasVio(const GrNet& net, bool hasCommit = true) const;\n    bool hasVio(const GrEdge& edge, bool hasCommit = true) const;\n    bool hasVio(const GrPoint& via, bool hasCommit = true) const;\n\n    void print() const;\n    void printAllUsageAndVio() const;\n\n    double getWirelength() const;\n\n    void setViaCapDiscount(double discount = 1);\n    void setWireCapDiscount(double discount = 1);\n    void setUnitViaMultiplier(double multiplier = 1);\n    void setLogisticSlope(double slope = 1);\n\n    double getLogisticSlope() const { return logisticSlope; }\n\n    // for ripup and reroute\n    void addHistCost();\n    void fadeHistCost();\n    void statHistCost() const;\n\n    friend class GrRouteGrid2D;\n\nprivate:\n    // only pref-dir is modeled\n    UsageMapT routedWireMap;  // model cross-cell routing\n    UsageMapT routedViaMap;\n    vector<vector<vector<std::pair<int, DBU>>>> fixedMetalMap;  // layer, x, y, (# blocked tracks, avg blocked length)\n    vector<vector<vector<double>>> histWireUsageMap;\n\n    db::CostT getWireDistCost(const GrEdge& edge) const;\n    db::CostT getWireShortCost(const GrEdge& edge) const;\n    db::CostT getViaShortCost(const GrPoint& via) const;\n\n    double viaCapDiscount = 1;\n    double wireCapDiscount = 1;\n    double unitViaMultiplier = 1;\n    double logisticSlope = 1;\n\n    std::pair<double, double> printAllUsage() const;\n    double printAllVio() const;\n\n    double getAllWireUsage(const vector<double>& buckets,\n                           vector<int>& wireUsageGrid,\n                           vector<DBU>& wireUsageLength) const;\n    void getAllInCellUsage(const vector<double>& buckets, vector<int>& viaUsage) const;\n    double getTotViaNum() const;\n\n    void markFixedMetals();\n    void markFixed(int layerIdx, int gridline, int cp, int num_track, DBU avg_length);\n\n    double getNumVio(const GrNet& net, bool hasCommit) const;\n    double getNumVio(const GrEdge& edge, double selfUsage) const;\n    double getNumVio(const GrPoint& via, double selfUsage) const;\n\n    double getFixedUsage(int layerIdx, int gridline, int cp) const;\n    double getFixedUsage(const GrEdge& edge) const;\n    double getWireUsage(int layerIdx, int gridline, int cp) const;\n    double getWireUsage(const GrEdge& edge) const;\n\n    double getViaUsage(int layerIdx, int x, int y) const;\n    double getViaUsage(const GrPoint& via) const;\n    double getCellUsage(int layerIdx, int x, int y) const;\n\n    double getWireCapacity(const GrEdge& edge) const;\n    double getInCellArea(const GrPoint& point) const;\n\n    double getInCellUsedArea(const GrPoint& point) const;\n    double getFixedUsedArea(const GrEdge& edge) const;  // fixed used area of the area of an edge\n    DBU getFixedLength(const GrEdge& edge) const;\n    double getInCellViaNum(const GrPoint& point) const;\n    // double getUnitViaArea(const GrPoint& point, int side) const;\n\n    void removeWire(const GrBoxOnLayer& box);\n    void removeVia(const GrBoxOnLayer& box);\n\n    void useWire(const GrBoxOnLayer& box);\n    void useWire(int layerIdx, int gridline, int cp, double usage = 1);\n    void useVia(const GrBoxOnLayer& box);\n    void useVia(int layerIdx, int x, int y, double usage = 1);\n    void useHistWire(int layerIdx, int gridline, int cp, double usage);\n};\n\nclass GrRouteGrid2D {\npublic:\n    using UsageT = double;\n    using UsageMapT = vector<vector<vector<UsageT>>>;\n\n    void init2DMaps(const GrRouteGrid& routeGrid);\n    void useWire2D(int dir, int gridline, int cp, double usage = 1);\n    void removeUsage2D(int dir, int gridline, int cp, double usage = 1);\n    double getCost2D(int dir, int gridline, int cp) const;\n\nprivate:\n    UsageMapT wireUsageMap2D;   // 2d, first dim show X,Y\n    UsageMapT fixedMetalMap2D;  // 2d, first dim show X,Y\n    UsageMapT capacityMap2D;    // 2d, first dim show X,Y\n};\n\n}  // namespace gr\n"
  },
  {
    "path": "src/gr_db/GridTopo.cpp",
    "content": "#include \"GridTopo.h\"\n\nnamespace gr {\n\nvoid GrSteiner::setParent(std::shared_ptr<GrSteiner> childNode, std::shared_ptr<GrSteiner> parentNode) {\n    parentNode->children.push_back(childNode);\n    childNode->parent = parentNode;\n}\n\nvoid GrSteiner::resetParent(std::shared_ptr<GrSteiner> node) {\n    assert(node->parent);\n\n    auto& n = node->parent->children;\n    auto it = find(n.begin(), n.end(), node);\n    assert(it != n.end());\n    *it = n.back();\n    n.pop_back();\n\n    node->parent.reset();\n}\n\nvoid GrSteiner::preOrder(std::shared_ptr<GrSteiner> node,\n                         const std::function<void(std::shared_ptr<GrSteiner>)>& visit) {\n    visit(node);\n    for (auto c : node->children) preOrder(c, visit);\n}\n\nvoid GrSteiner::postOrder(std::shared_ptr<GrSteiner> node,\n                          const std::function<void(std::shared_ptr<GrSteiner>)>& visit) {\n    for (auto c : node->children) postOrder(c, visit);\n    visit(node);\n}\n\nvoid GrSteiner::postOrderCopy(std::shared_ptr<GrSteiner> node,\n                              const std::function<void(std::shared_ptr<GrSteiner>)>& visit) {\n    auto tmp = node->children;\n    for (auto c : tmp) postOrderCopy(c, visit);\n    visit(node);\n}\n\nvoid GrSteiner::mergeNodes(std::shared_ptr<GrSteiner> root) {\n    postOrderCopy(root, [](std::shared_ptr<GrSteiner> node) {\n        // parent - node - child\n        if (node->parent && node->parent->layerIdx == node->layerIdx && node->children.size() == 1 &&\n            node->pinIdx < 0) {\n            auto oldChild = node->children[0];\n            if (node->layerIdx == oldChild->layerIdx && node->getPrefIdx() == oldChild->getPrefIdx() &&\n                node->parent->getPrefIdx() == node->getPrefIdx()) {\n                auto oldParent = node->parent;\n                resetParent(node);\n                resetParent(oldChild);\n                setParent(oldChild, oldParent);\n            }\n        }\n    });\n}\n\nvoid GrSteiner::removeRedundancy(std::shared_ptr<GrSteiner> root) {\n    for (int i = 0; i < root->children.size(); i++) {\n        if (GrPoint(*root) == GrPoint(*root->children[i])) {\n            auto child_ptr = root->children[i];\n            root->children.erase(root->children.begin() + i);\n            i--;\n            for (auto& grand_child : child_ptr->children) {\n                setParent(grand_child, root);\n            }\n        }\n    }\n    for (auto& child : root->children) {\n        removeRedundancy(child);\n    }\n}\n\nbool GrSteiner::checkConnectivity(std::shared_ptr<GrSteiner> root, vector<GrPoint>& pins) {\n    bool detached_node = false;\n    std::unordered_map<GrPoint, bool> pin_visited;\n    for (int i = 0; i < pins.size(); i++) {\n        pin_visited[pins[i]] = false;\n    }\n    preOrder(root, [&](std::shared_ptr<GrSteiner> node) {\n        if (pin_visited.find(GrPoint(*node)) != pin_visited.end()) {\n            node->pinIdx = 1;\n            pin_visited[GrPoint(*node)] = true;\n        }\n        for (auto& child : node->children) {\n            // If two nodes are connected, at least 2 of their coordinates should be the same\n            if (node->layerIdx == child->layerIdx) {\n                if (node->x != child->x && node->y != child->y) {\n                    detached_node = true;\n                }\n            } else if (abs(node->layerIdx - child->layerIdx) <= 1) {\n                if (node->x != child->x || node->y != child->y) {\n                    detached_node = true;\n                }\n            } else {\n                detached_node = true;\n            }\n            int match_cnt = 0;\n            if (node->x == child->x) match_cnt++;\n            if (node->y == child->y) match_cnt++;\n            if (node->layerIdx == child->layerIdx) match_cnt++;\n            if (match_cnt < 2) detached_node = true;\n        }\n    });\n    for (auto& p_v : pin_visited) {\n        if (p_v.second == false) return false;\n    }\n    if (detached_node) return false;\n    return true;\n}\n\nostream& operator<<(ostream& os, const GrSteiner& node) {\n    os << GrPoint(node);\n    if (node.pinIdx >= 0) os << \" pin\" << node.pinIdx;\n    return os;\n}\n\nvoid GrSteiner::printTree(ostream& os, int depth) {\n    os << *this << \", \";\n    bool first = true;\n    for (auto child : children) {\n        if (!first) {\n            for (int i = 0; i < depth; ++i) os << '.';\n            os << *this << \", \";\n        }\n        child->printTree(os, depth + 1);\n        if (children.size() > 1) {\n            os << std::endl;\n        }\n        first = false;\n    }\n}\n\n}  // namespace gr\n"
  },
  {
    "path": "src/gr_db/GridTopo.h",
    "content": "#pragma once\n\n#include \"GrGeoPrimitive.h\"\n\nnamespace gr {\n\nclass GrSteiner : public GrPoint {\npublic:\n    int pinIdx;  // -1 stands for \"not pin\"\n    std::shared_ptr<GrSteiner> parent;\n    vector<std::shared_ptr<GrSteiner>> children;\n\n    GrSteiner(const GrPoint& grPoint, int pinIndex = -1) : GrPoint(grPoint), pinIdx(pinIndex) {}\n    bool isRealPin() const { return pinIdx >= 0; }\n\n    // Set/reset parent\n    static void setParent(std::shared_ptr<GrSteiner> childNode, std::shared_ptr<GrSteiner> parentNode);\n    static void resetParent(std::shared_ptr<GrSteiner> node);\n\n    // Traverse\n    static void preOrder(std::shared_ptr<GrSteiner> node, const std::function<void(std::shared_ptr<GrSteiner>)>& visit);\n    static void postOrder(std::shared_ptr<GrSteiner> node,\n                          const std::function<void(std::shared_ptr<GrSteiner>)>& visit);\n    static void postOrderCopy(std::shared_ptr<GrSteiner> node,\n                              const std::function<void(std::shared_ptr<GrSteiner>)>& visit);\n\n    // Merge two same-layer edges (assume they are on the same track)\n    static void mergeNodes(std::shared_ptr<GrSteiner> root);\n\n    // Remove redundant nodes\n    static void removeRedundancy(std::shared_ptr<GrSteiner> root);\n    static bool checkConnectivity(std::shared_ptr<GrSteiner> root, vector<GrPoint>& pins);\n\n    friend ostream& operator<<(ostream& os, const GrSteiner& node);\n    void printTree(ostream& os = std::cout, int depth = 0);\n};\n\n}  // namespace gr\n"
  },
  {
    "path": "src/main.cpp",
    "content": "#include \"db/Database.h\"\n#include \"global.h\"\n#include \"multi_net/Router.h\"\n#include \"gr_db/GrDatabase.h\"\n\ndouble LARGE_NUM = 100000000;\n\n// -----------------------------------------------------------------------------\n\nvoid signalHandler(int signum) {\n    std::cout << \"Signal (\" << signum << \") received. Exiting...\\n\";\n\n    // cleanup and close up stuff here\n\n    std::exit(signum);\n}\n\n// -----------------------------------------------------------------------------\n\nvoid runISPD18Flow(const boost::program_options::variables_map& vm) {\n    // db::setting.makeItSilent();\n\n    Rsyn::Session session;\n\n    // Parse options\n    // required\n    std::string lefFile = vm.at(\"lef\").as<std::string>();\n    std::string defFile = vm.at(\"def\").as<std::string>();\n    db::setting.numThreads = vm.at(\"threads\").as<int>();\n    db::setting.outputFile = vm.at(\"output\").as<std::string>();\n    // optional\n    if (vm.count(\"tat\")) {\n        db::setting.tat = vm.at(\"tat\").as<int>();\n    }\n    // multi_net\n    if (vm.count(\"multiNetVerbose\")) {\n        db::setting.multiNetVerbose =\n            db::VerboseLevelT::_from_string(vm.at(\"multiNetVerbose\").as<std::string>().c_str());\n    }\n    if (vm.count(\"multiNetScheduleSortAll\")) {\n        db::setting.multiNetScheduleSortAll = vm.at(\"multiNetScheduleSortAll\").as<bool>();\n    }\n    if (vm.count(\"multiNetScheduleReverse\")) {\n        db::setting.multiNetScheduleReverse = vm.at(\"multiNetScheduleReverse\").as<bool>();\n    }\n    if (vm.count(\"multiNetScheduleSort\")) {\n        db::setting.multiNetScheduleSort = vm.at(\"multiNetScheduleSort\").as<bool>();\n    }\n    if (vm.count(\"rrrIters\")) {\n        db::setting.rrrIterLimit = vm.at(\"rrrIters\").as<int>();\n    }\n    if (vm.count(\"rrrWriteEachIter\")) {\n        db::setting.rrrWriteEachIter = vm.at(\"rrrWriteEachIter\").as<bool>();\n    }\n    if (vm.count(\"rrrInitVioCostDiscount\")) {\n        db::setting.rrrInitVioCostDiscount = vm.at(\"rrrInitVioCostDiscount\").as<double>();\n    }\n    if (vm.count(\"rrrFadeCoeff\")) {\n        db::setting.rrrFadeCoeff = vm.at(\"rrrFadeCoeff\").as<double>();\n    }\n    if (vm.count(\"edgeShiftingIter\")) {\n        db::setting.edgeShiftingIter = vm.at(\"edgeShiftingIter\").as<int>();\n    }\n    // single_net\n    if (vm.count(\"fixOpenBySST\")) {\n        db::setting.fixOpenBySST = vm.at(\"fixOpenBySST\").as<bool>();\n    }\n    // db\n    if (vm.count(\"dbVerbose\")) {\n        db::setting.dbVerbose = db::VerboseLevelT::_from_string(vm.at(\"dbVerbose\").as<std::string>().c_str());\n    }\n    if (vm.count(\"dbInitHistUsageForPinAccess\")) {\n        db::setting.dbInitHistUsageForPinAccess = vm.at(\"dbInitHistUsageForPinAccess\").as<double>();\n    }\n\n    vector<std ::string> strs;\n    boost::split(strs, db::setting.outputFile, boost::is_any_of(\".\"));\n    db::setting.name = strs[0];\n\n    // Read benchmarks\n    Rsyn::ISPD2018Reader reader;\n    const Rsyn::Json params = {\n        {\"lefFile\", lefFile},\n        {\"defFile\", defFile},\n    };\n    log() << std::endl;\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::HIGH) {\n        log() << \"################################################################\" << std::endl;\n        log() << \"Start reading benchmarks\" << std::endl;\n    }\n    reader.load(params);\n    if (db::setting.dbVerbose >= +db::VerboseLevelT::HIGH) {\n        log() << \"Finish reading benchmarks\" << std::endl;\n        log() << \"MEM: cur=\" << utils::mem_use::get_current() << \"MB, peak=\" << utils::mem_use::get_peak() << \"MB\"\n              << std::endl;\n        log() << std::endl;\n    }\n\n    // Route\n    database.init();\n    db::setting.adapt();\n    grDatabase.init();\n\n    log() << \"finish reading benchmark\" << std::endl;\n\n    Router router;\n    router.run();\n\n    grDatabase.writeGuides(db::setting.outputFile);\n\n    database.clear();\n    grDatabase.clear();\n\n    log() << \"MEM: cur=\" << utils::mem_use::get_current() << \"MB, peak=\" << utils::mem_use::get_peak() << \"MB\"\n          << std::endl;\n    log() << std::endl;\n}\n\n// -----------------------------------------------------------------------------\n\nint main(int argc, char* argv[]) {\n    signal(SIGINT, signalHandler);\n    signal(SIGTERM, signalHandler);\n\n    Rsyn::Session::init();\n\n    printlog(\"------------------------------------------------------------------------------\");\n    printlog(\"                     ICCAD 2019 - Global Routing Contest                      \");\n    printlog(\"                             Team number : 15                                 \");\n    printlog(\"                             Team name : CU-GR                                \");\n    printlog(\"        Members: Jinwei Liu, Chak-Wa Pui, Fangzhou Wang,                      \");\n    printlog(\"                 Evangeline F.Y. Young                                        \");\n    printlog(\"        Affiliation: The Chinese University of Hong Kong                      \");\n    printlog(\"------------------------------------------------------------------------------\");\n\n    std::cout << std::boolalpha;  // set std::boolalpha to std::cout\n\n    try {\n        using namespace boost::program_options;\n        options_description desc{\"Options\"};\n        // clang-format off\n        desc.add_options()\n                (\"help\", \"Help message.\")\n                (\"lef\", value<std::string>()->required(), \"Input .lef file\")\n                (\"def\", value<std::string>()->required(), \"Input .def file.\")\n                (\"threads\", value<int>()->required(), \"# of threads\")\n                (\"output\", value<std::string>()->required(), \"Output file name\")\n                // optional\n                (\"tat\", value<int>(), \"Runtime limit (sec)\")\n                (\"multiNetVerbose\", value<std::string>())\n                (\"multiNetScheduleSortAll\", value<bool>())\n                (\"multiNetScheduleReverse\", value<bool>())\n                (\"multiNetScheduleSort\", value<bool>())\n                (\"rrrIters\", value<int>())\n                (\"rrrWriteEachIter\", value<bool>())\n                (\"rrrInitVioCostDiscount\", value<double>())\n                (\"rrrFadeCoeff\", value<double>())\n                (\"edgeShiftingIter\", value<int>())\n                (\"fixOpenBySST\", value<bool>())\n                (\"dbVerbose\", value<std::string>())\n                (\"dbInitHistUsageForPinAccess\", value<double>())\n                ;\n        // clang-format on\n        variables_map vm;\n        store(command_line_parser(argc, argv)\n                  .options(desc)\n                  .style(command_line_style::unix_style | command_line_style::allow_long_disguise)\n                  .run(),\n              vm);\n        notify(vm);\n        if (vm.count(\"help\")) {\n            std::cout << desc << std::endl;\n            return 0;\n        }\n        for (const auto& option : desc.options()) {\n            if (vm.count(option->long_name())) {\n                std::string name = option->description().empty() ? option->long_name() : option->description();\n                log() << std::left << std::setw(18) << name << \": \";\n                const auto& value = vm.at(option->long_name()).value();\n                if (auto v = boost::any_cast<double>(&value)) {\n                    std::cout << *v;\n                } else if (auto v = boost::any_cast<int>(&value)) {\n                    std::cout << *v;\n                } else if (auto v = boost::any_cast<std::string>(&value)) {\n                    std::cout << *v;\n                } else if (auto v = boost::any_cast<bool>(&value)) {\n                    std::cout << *v;\n                } else {\n                    std::cout << \"unresolved type\";\n                }\n                std::cout << std::endl;\n            }\n        }\n        runISPD18Flow(vm);\n    } catch (const boost::program_options::error& e) {\n        printlog(e.what());\n    }\n\n    printlog(\"---------------------------------------------------------------------------\");\n    printlog(\"                               Terminated...                               \");\n    printlog(\"---------------------------------------------------------------------------\");\n\n    return 0;\n}\n"
  },
  {
    "path": "src/multi_net/CongestionMap.cpp",
    "content": "#include \"CongestionMap.h\"\r\n#include \"global.h\"\r\n\r\ndouble CongestionMap::calcCrsnEdgeCost(const gr::PointOnLayer& u, const gr::PointOnLayer& v) {\r\n    if (u.layerIdx != v.layerIdx && abs(u[X] - v[X]) + abs(u[Y] - v[Y]) != 1) {\r\n        printlog(\"Warning: CongestionMap::calcCrsnEdgeCost,\", \"edge longer than one,\", u, v);\r\n        return std::numeric_limits<double>::max();\r\n    }\r\n\r\n    int layerIdx = u.layerIdx;\r\n    auto layerDir = database.getLayerDir(layerIdx);\r\n\r\n    if (layerIdx == 0) return LARGE_NUM;\r\n\r\n    utils::BoxT<int> box;\r\n    auto u_box = getGrBox(u);\r\n    auto v_box = getGrBox(v);\r\n\r\n    double cost = 0;\r\n    box = u_box;\r\n    double avgRsrc = 0;\r\n    for (int x_idx = box.x.low; x_idx <= box.x.high; x_idx++) {\r\n        for (int y_idx = box.y.low; y_idx <= box.y.high; y_idx++) {\r\n            avgRsrc += rsrcMap[layerIdx][x_idx][y_idx];\r\n        }\r\n    }\r\n    avgRsrc /= (box.x.range() + 1) * (box.y.range() + 1);\r\n    cost += double(layerDir == X ? yCrsnScale : xCrsnScale) * 1.0 / max(avgRsrc, 0.1);\r\n\r\n    box = v_box;\r\n    avgRsrc = 0;\r\n    for (int x_idx = box.x.low; x_idx <= box.x.high; x_idx++) {\r\n        for (int y_idx = box.y.low; y_idx <= box.y.high; y_idx++) {\r\n            avgRsrc += rsrcMap[layerIdx][x_idx][y_idx];\r\n        }\r\n    }\r\n    avgRsrc /= (box.x.range() + 1) * (box.y.range() + 1);\r\n    cost += double(layerDir == X ? yCrsnScale : xCrsnScale) * 1.0 / max(avgRsrc, 0.1);\r\n\r\n    return cost;\r\n}\r\n\r\ndouble CongestionMap::calcCrsnViaCost(const gr::PointOnLayer& via) {\r\n    utils::BoxT<int> box = getGrBox(via);\r\n    double cost = 0;\r\n    for (int l_idx = via.layerIdx; l_idx <= via.layerIdx + 1; l_idx++) {\r\n        double avgRsrc = 0;\r\n        for (int x_idx = box.x.low; x_idx <= box.x.high; x_idx++) {\r\n            for (int y_idx = box.y.low; y_idx <= box.y.high; y_idx++) {\r\n                avgRsrc += rsrcMap[l_idx][x_idx][y_idx];\r\n            }\r\n        }\r\n        avgRsrc /= (box.x.range() + 1) * (box.y.range() + 1);\r\n        cost += 1.0 / max(avgRsrc, 0.1);\r\n    }\r\n\r\n    return cost;\r\n}\r\n\r\ndouble CongestionMap::getCrsnEdgeCost(const gr::PointOnLayer& u, const gr::PointOnLayer& v) const {\r\n    if (u.layerIdx != v.layerIdx && abs(u[X] - v[X]) + abs(u[Y] - v[Y]) != 1) {\r\n        printlog(\"Warning: CongestionMap::calcCrsnEdgeCost,\", \"edge longer than one,\", u, v);\r\n        return std::numeric_limits<double>::max();\r\n    }\r\n\r\n    int layerIdx = u.layerIdx;\r\n    auto layerDir = database.getLayerDir(layerIdx);\r\n    int gridline = u[layerDir];\r\n    int cp = min(u[1 - layerDir], v[1 - layerDir]);\r\n\r\n    return crsnEdgeCostMap[layerIdx][gridline][cp];\r\n}\r\n\r\ndouble CongestionMap::getCrsnViaCost(const gr::PointOnLayer& via) const {\r\n    return crsnViaCostMap[via.layerIdx][via.x][via.y];\r\n}\r\n\r\nutils::BoxT<int> CongestionMap::getGrBox(const gr::PointOnLayer& u) const {  // get the gcell box in a coarsened cell\r\n    utils::BoxT<int> gcellBox;\r\n    gcellBox.x.Update(u[X] * xCrsnScale);\r\n    gcellBox.x.Update(min(u[X] * xCrsnScale + xCrsnScale, grDatabase.getNumGrPoint(X)) - 1);\r\n    gcellBox.y.Update(u[Y] * yCrsnScale);\r\n    gcellBox.y.Update(min(u[Y] * yCrsnScale + yCrsnScale, grDatabase.getNumGrPoint(Y)) - 1);\r\n    return gcellBox;\r\n}\r\n\r\ngr::PointOnLayer CongestionMap::grPointToPoint(const gr::GrPoint& point) const {\r\n    return {point.layerIdx, point[X] / xCrsnScale, point[Y] / yCrsnScale};\r\n}\r\n\r\nvoid CongestionMap::init(int x_crsn_scale, int y_crsn_scale) {\r\n    xCrsnScale = x_crsn_scale;\r\n    yCrsnScale = y_crsn_scale;\r\n\r\n    rsrcMap.assign(database.getLayerNum(),\r\n                   vector<vector<double>>(grDatabase.getNumGrPoint(X), vector<double>(grDatabase.getNumGrPoint(Y), 0)));\r\n\r\n    for (int l_idx = 0; l_idx < database.getLayerNum(); l_idx++)\r\n        for (int x_idx = 0; x_idx < grDatabase.getNumGrPoint(X); x_idx++)\r\n            for (int y_idx = 0; y_idx < grDatabase.getNumGrPoint(Y); y_idx++)\r\n                rsrcMap[l_idx][x_idx][y_idx] = grDatabase.getCellUsage({l_idx, x_idx, y_idx});\r\n\r\n    xNumCrsnCell = ceil(grDatabase.getNumGrPoint(X) / (double)xCrsnScale);\r\n    yNumCrsnCell = ceil(grDatabase.getNumGrPoint(Y) / (double)xCrsnScale);\r\n\r\n    crsnViaCostMap.clear();\r\n    crsnEdgeCostMap.clear();\r\n    crsnViaCostMap.resize(database.getLayerNum() - 1,\r\n                          vector<vector<double>>(xNumCrsnCell, vector<double>(yNumCrsnCell)));\r\n    crsnEdgeCostMap.resize(database.getLayerNum());\r\n    for (int l = 0; l < database.getLayerNum(); l++) {\r\n        if (database.getLayerDir(l) == X)\r\n            crsnEdgeCostMap[l].resize(xNumCrsnCell, vector<double>(yNumCrsnCell - 1));\r\n        else\r\n            crsnEdgeCostMap[l].resize(yNumCrsnCell, vector<double>(xNumCrsnCell - 1));\r\n    }\r\n    for (int l = 0; l < database.getLayerNum(); l++) {\r\n        if (database.getLayerDir(l) == X) {\r\n            for (int gridline = 0; gridline < xNumCrsnCell; gridline++)\r\n                for (int cp = 0; cp < yNumCrsnCell - 1; cp++)\r\n                    crsnEdgeCostMap[l][gridline][cp] = calcCrsnEdgeCost({l, gridline, cp}, {l, gridline, cp + 1});\r\n        } else {\r\n            for (int gridline = 0; gridline < yNumCrsnCell; gridline++)\r\n                for (int cp = 0; cp < xNumCrsnCell - 1; cp++)\r\n                    crsnEdgeCostMap[l][gridline][cp] = calcCrsnEdgeCost({l, cp, gridline}, {l, cp + 1, gridline});\r\n        }\r\n    }\r\n\r\n    for (int l = 0; l < database.getLayerNum() - 1; l++) {\r\n        for (int x = 0; x < xNumCrsnCell; x++)\r\n            for (int y = 0; y < yNumCrsnCell; y++) crsnViaCostMap[l][x][y] = calcCrsnViaCost({l, x, y});\r\n    }\r\n}\r\n\r\nvoid CongestionMap::update(const gr::GrNet& net) {\r\n    std::unordered_set<gr::PointOnLayer> pointSet;\r\n\r\n    auto updateBox = [&](const gr::GrBoxOnLayer& box) {\r\n        int l_idx = box.layerIdx;\r\n        for (int x_idx = box[X].low; x_idx <= box[X].high; x_idx++) {\r\n            for (int y_idx = box[Y].low; y_idx <= box[Y].high; y_idx++) {\r\n                rsrcMap[l_idx][x_idx][y_idx] = grDatabase.getCellUsage({l_idx, x_idx, y_idx});\r\n                pointSet.insert(grPointToPoint({l_idx, x_idx, y_idx}));\r\n            }\r\n        }\r\n    };\r\n\r\n    for (auto& guide : net.wireRouteGuides) {\r\n        // enlarge the updating box\r\n        auto box = guide;\r\n        if (database.getLayerDir(guide.layerIdx) == X) {\r\n            box[Y].Update(max(guide[Y].low - 1, 0));\r\n            box[Y].Update(min(guide[Y].high + 1, grDatabase.getNumGrPoint(Y) - 1));\r\n        } else {\r\n            box[X].Update(max(guide[X].low - 1, 0));\r\n            box[X].Update(min(guide[X].high + 1, grDatabase.getNumGrPoint(X) - 1));\r\n        }\r\n        updateBox(box);\r\n    }\r\n    for (auto& guide : net.viaRouteGuides) {\r\n        updateBox(guide);\r\n    }\r\n\r\n    for (auto& point : pointSet) {\r\n        updateViaCostMap(point);\r\n        updateWireCostMap(point);\r\n    }\r\n}\r\n\r\nvoid CongestionMap::updateViaCostMap(const gr::PointOnLayer& point) {\r\n    int layerIdx = point.layerIdx;\r\n\r\n    if (layerIdx < database.getLayerNum() - 1) crsnViaCostMap[layerIdx][point.x][point.y] = calcCrsnViaCost(point);\r\n    if (layerIdx > 0)\r\n        crsnViaCostMap[layerIdx - 1][point.x][point.y] = calcCrsnViaCost({layerIdx - 1, point.x, point.y});\r\n}\r\n\r\nvoid CongestionMap::updateWireCostMap(const gr::PointOnLayer& point) {\r\n    int layerIdx = point.layerIdx;\r\n    auto layerDir = database.getLayerDir(layerIdx);\r\n    int gridline = point[layerDir];\r\n    int cp = point[1 - layerDir];\r\n    int cpNum = (layerDir == X) ? yNumCrsnCell : xNumCrsnCell;\r\n\r\n    if (layerDir == X) {\r\n        if (cp > 0)\r\n            crsnEdgeCostMap[layerIdx][gridline][cp - 1] =\r\n                calcCrsnEdgeCost({layerIdx, point.x, point.y - 1}, {layerIdx, point.x, point.y});\r\n        if (cp < cpNum - 1)\r\n            crsnEdgeCostMap[layerIdx][gridline][cp] =\r\n                calcCrsnEdgeCost({layerIdx, point.x, point.y}, {layerIdx, point.x, point.y + 1});\r\n    } else {\r\n        if (cp > 0)\r\n            crsnEdgeCostMap[layerIdx][gridline][cp - 1] =\r\n                calcCrsnEdgeCost({layerIdx, point.x - 1, point.y}, {layerIdx, point.x, point.y});\r\n        if (cp < cpNum - 1)\r\n            crsnEdgeCostMap[layerIdx][gridline][cp] =\r\n                calcCrsnEdgeCost({layerIdx, point.x, point.y}, {layerIdx, point.x + 1, point.y});\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/multi_net/CongestionMap.h",
    "content": "#pragma once\r\n\r\n#include \"db/Database.h\"\r\n#include \"gr_db/GrDatabase.h\"\r\n\r\n// create remaining gcell resource map (for congestion overview)\r\nclass CongestionMap {\r\npublic:\r\n    double getCrsnEdgeCost(const gr::PointOnLayer& u, const gr::PointOnLayer& v) const;\r\n    double getCrsnViaCost(const gr::PointOnLayer& via) const;\r\n\r\n    int getCellWidth() const { return xCrsnScale; }\r\n    int getCellHeight() const { return yCrsnScale; }\r\n    gr::PointOnLayer grPointToPoint(const gr::GrPoint& point) const;\r\n    double getRsrcUsage(int l, int x, int y) const { return rsrcMap[l][x][y]; };\r\n\r\n    void init(int x_crsn_scale, int y_crsn_scale);\r\n    void update(const gr::GrNet& net);\r\n\r\nprivate:\r\n    bool getCrsnFixed(const gr::PointOnLayer& u) const;\r\n\r\n    utils::BoxT<int> getGrBox(const gr::PointOnLayer& u) const;  // get the gcell box in a coarsened cell\r\n\r\n    void updateViaCostMap(const gr::PointOnLayer& point);\r\n    void updateWireCostMap(const gr::PointOnLayer& point);\r\n    double calcCrsnEdgeCost(const gr::PointOnLayer& u, const gr::PointOnLayer& v);\r\n    double calcCrsnViaCost(const gr::PointOnLayer& via);\r\n\r\n    int xCrsnScale;\r\n    int yCrsnScale;\r\n    int xNumCrsnCell;\r\n    int yNumCrsnCell;\r\n\r\n    vector<vector<vector<double>>> rsrcMap;  // note that this is not coarsened\r\n    vector<vector<vector<double>>> crsnEdgeCostMap;\r\n    vector<vector<vector<double>>> crsnViaCostMap;\r\n};\r\n"
  },
  {
    "path": "src/multi_net/Router.cpp",
    "content": "#include \"Router.h\"\n#include \"flute/flute.h\"\n#include \"Scheduler.h\"\n#include \"single_net/InitRoute.h\"\n\nextern \"C\" {\nvoid readLUT();\n}\n\nconst MTStat& MTStat::operator+=(const MTStat& rhs) {\n    auto dur = rhs.durations;\n    std::sort(dur.begin(), dur.end());\n    if (durations.size() < dur.size()) {\n        durations.resize(dur.size(), 0.0);\n    }\n    for (int i = 0; i < dur.size(); ++i) {\n        durations[i] += dur[i];\n    }\n    return *this;\n}\n\nostream& operator<<(ostream& os, const MTStat mtStat) {\n    double minDur = std::numeric_limits<double>::max(), maxDur = 0.0, avgDur = 0.0;\n    for (double dur : mtStat.durations) {\n        minDur = min(minDur, dur);\n        maxDur = max(maxDur, dur);\n        avgDur += dur;\n    }\n    avgDur /= mtStat.durations.size();\n    os << \"#threads=\" << mtStat.durations.size() << \" (dur: min=\" << minDur << \", max=\" << maxDur << \", avg=\" << avgDur\n       << \")\";\n    return os;\n}\n\nvoid Router::run() {\n    allNetStatus.resize(database.nets.size(), db::RouteStatus::FAIL_UNPROCESSED);\n    for (iter = 0; iter < db::setting.rrrIterLimit; iter++) {\n        log() << std::endl;\n        log() << \"################################################################\" << std::endl;\n        log() << \"Start RRR iteration \" << iter << std::endl;\n        log() << std::endl;\n        db::routeStat.clear();\n        guideGenStat.reset();\n\n        vector<int> netsToRoute = getNetsToRoute();\n        if (netsToRoute.empty()) {\n            if (db::setting.multiNetVerbose >= +db::VerboseLevelT::MIDDLE) {\n                log() << \"No net is identified for this iteration of RRR.\" << std::endl;\n                log() << std::endl;\n            }\n            break;\n        }\n        sortNets(netsToRoute);  // Note: only effective when doing mazeroute sequentially\n\n        updateCost();\n        grDatabase.statHistCost();\n\n        if (iter > 0) {\n            ripup(netsToRoute);\n            congMap.init(cellWidth, cellHeight);\n        }\n\n        routeApprx(netsToRoute);\n\n        log() << std::endl;\n        log() << \"Finish RRR iteration \" << iter << std::endl;\n        log() << \"MEM: cur=\" << utils::mem_use::get_current() << \"MB, peak=\" << utils::mem_use::get_peak() << \"MB\"\n              << std::endl;\n        if (db::setting.multiNetVerbose >= +db::VerboseLevelT::MIDDLE) db::routeStat.print();\n    }\n    // postprocessing\n    for (auto& net : grDatabase.nets) {\n        GuideGenerator guideGen(net);\n        guideGen.genPatchGuides();\n    }\n    if (db::setting.multiNetVerbose >= +db::VerboseLevelT::MIDDLE) guideGenStat.print();\n\n    // congMap.printCrsnMap(1, {80, 1000}, {40, 70});\n    log() << std::endl;\n    log() << \"################################################################\" << std::endl;\n    database.setUnitVioCost(1);  // set the cost back to without discount\n    log() << \"Finish all RRR iterations and PostRoute\" << std::endl;\n    log() << \"MEM: cur=\" << utils::mem_use::get_current() << \"MB, peak=\" << utils::mem_use::get_peak() << \"MB\"\n          << std::endl;\n\n    printStat();\n}\n\nRouter::Router() {\n    readLUT();  // read flute LUT\n}\n\nvoid Router::ripup(const vector<int>& netsToRoute) {\n    for (auto id : netsToRoute) {\n        grDatabase.removeNet(grDatabase.nets[id]);\n        grDatabase.nets[id].gridTopo.clear();\n        allNetStatus[id] = db::RouteStatus::FAIL_UNPROCESSED;\n    }\n}\n\nvoid Router::updateCost() {\n    if (iter > 0) {\n        // apply in rrr stages\n        grDatabase.addHistCost();\n        grDatabase.fadeHistCost();\n\n        grDatabase.setUnitViaMultiplier(\n            max(100 / pow(5, iter - 1), 4.0));  // enlarge unit via cost to avoid extra use of vias\n        grDatabase.setLogisticSlope(db::setting.initLogisticSlope * pow(2, iter));\n    }\n\n    if (db::setting.rrrIterLimit > 1) {\n        double step = (1.0 - db::setting.rrrInitVioCostDiscount) / (db::setting.rrrIterLimit - 1);\n        database.setUnitVioCost(db::setting.rrrInitVioCostDiscount + step * iter);\n    }\n}\n\nvector<vector<int>> Router::getBatches(vector<SingleNetRouter>& routers, const vector<int>& netsToRoute, bool seqEq) {\n    vector<int> batch(netsToRoute.size());\n    for (int i = 0; i < netsToRoute.size(); i++) batch[i] = i;\n\n    runJobsMT(batch.size(), [&](int jobIdx) {\n        auto& router = routers[batch[jobIdx]];\n\n        const auto mergedPinAccessBoxes = grDatabase.nets[netsToRoute[jobIdx]].getMergedPinAccessBoxes(\n            [](const gr::GrPoint& point) { return gr::PointOnLayer(point.layerIdx, point[X], point[Y]); });\n        utils::IntervalT<int> xIntvl, yIntvl;\n        for (auto& points : mergedPinAccessBoxes) {\n            for (auto& point : points) {\n                xIntvl.Update(point[X]);\n                yIntvl.Update(point[Y]);\n            }\n        }\n        router.guides.emplace_back(0, xIntvl, yIntvl);\n    });\n\n    Scheduler scheduler(routers);\n    const vector<vector<int>>& batches = seqEq ? scheduler.scheduleOrderEq() : scheduler.schedule();\n\n    if (db::setting.multiNetVerbose >= +db::VerboseLevelT::MIDDLE) {\n        log() << \"Finish multi-thread scheduling\" << ((db::setting.numThreads == 0) ? \" using simple mode\" : \"\")\n              << \". There will be \" << batches.size() << \" batches for \" << netsToRoute.size() << \" nets.\" << std::endl;\n        log() << std::endl;\n    }\n\n    return batches;\n}\n\nvoid Router::routeApprx(const vector<int>& netsToRoute) {\n    if (iter == 0) {\n        fluteAllAndRoute(netsToRoute);\n    } else {\n        vector<SingleNetRouter> routers;\n        routers.reserve(netsToRoute.size());\n        for (auto id : netsToRoute) routers.emplace_back(grDatabase.nets[id]);\n\n        vector<vector<int>> batches = getBatches(routers, netsToRoute, false);\n\n        for (const vector<int>& batch : batches) {\n            runJobsMT(batch.size(), [&](int jobIdx) {\n                auto& router = routers[batch[jobIdx]];\n                router.planMazeRoute(congMap);\n            });\n\n            for (auto jobIdx : batch) {\n                auto& router = routers[jobIdx];\n                router.mazeRoute();\n                router.finish();\n\n                int netIdx = netsToRoute[jobIdx];\n                congMap.update(grDatabase.nets[netIdx]);\n                allNetStatus[netIdx] = router.status;\n            }\n        }\n    }\n}\n\nvoid Router::fluteAllAndRoute(const vector<int>& netsToRoute) {\n    vector<SingleNetRouter> routers;\n    vector<InitRoute> initRouters;\n    routers.reserve(netsToRoute.size());\n    initRouters.reserve(netsToRoute.size());\n    for (auto id : netsToRoute) routers.emplace_back(grDatabase.nets[id]);\n    for (auto id : netsToRoute) initRouters.emplace_back(grDatabase.nets[id]);\n\n    grDatabase.init2DMaps(grDatabase);\n\n    for (auto& router : initRouters)\n        if (router.grNet.needToRoute()) router.plan_fluteOnly();\n    printlog(\"finish planning\");\n\n    for (int i = 0; i < db::setting.edgeShiftingIter; i++) {\n        grDatabase.edge_shifted = 0;\n        for (auto& router : initRouters)\n            if (router.grNet.needToRoute()) router.edge_shift2d(router.getRouteNodes());\n        log() << \"Total Number of edges in Iter \" << i << \" : \" << grDatabase.tot_edge\n              << \". Edge Shifted: \" << grDatabase.edge_shifted << \"(\"\n              << 100.0 * grDatabase.edge_shifted / grDatabase.tot_edge << \"%)\" << std::endl;\n    }\n    for (auto& router : initRouters)\n        if (router.grNet.needToRoute()) router.getRoutingOrder();\n    printlog(\"finish edge shifting\");\n\n    vector<vector<int>> batches = getBatches(routers, netsToRoute, true);\n    for (const vector<int>& batch : batches) {\n            runJobsMT(batch.size(), [&](int jobIdx) {\n            int idx = batch[jobIdx];\n            auto& router = routers[idx];\n            router.initRoutePattern(initRouters[idx]);\n            router.finish();\n\n            allNetStatus[netsToRoute[idx]] = router.status;\n        });\n    }\n\n    printlog(\"finish pattern route\");\n}\n\nvoid Router::sortNets(vector<int>& netsToRoute) {\n    sort(netsToRoute.begin(), netsToRoute.end(), [&](int id1, int id2) {\n        return grDatabase.nets[id1].boundingBox.hp() < grDatabase.nets[id2].boundingBox.hp();\n    });\n}\n\nvector<int> Router::getNetsToRoute() {\n    vector<int> netsToRoute;\n    if (iter == 0) {\n        for (auto& net : grDatabase.nets) netsToRoute.push_back(net.dbNet.idx);\n    } else {\n        for (auto& net : grDatabase.nets)\n            if (grDatabase.hasVio(net)) netsToRoute.push_back(net.dbNet.idx);\n    }\n\n    return netsToRoute;\n}\n\nvoid Router::printStat() {\n    log() << std::endl;\n    log() << \"----------------------------------------------------------------\" << std::endl;\n    db::routeStat.print();\n    grDatabase.printAllUsageAndVio();\n    log() << \"----------------------------------------------------------------\" << std::endl;\n    log() << std::endl;\n}\n"
  },
  {
    "path": "src/multi_net/Router.h",
    "content": "#pragma once\n\n#include \"db/Database.h\"\n#include \"gr_db/GrDatabase.h\"\n#include \"single_net/SingleNetRouter.h\"\n#include \"CongestionMap.h\"\n\nclass Router {\npublic:\n    Router();\n    void run();\nprivate:\n    int iter;\n    \n    vector<db::RouteStatus> allNetStatus;\n    CongestionMap congMap;\n    int cellWidth = 5, cellHeight = 5;\n\n    vector<int> getNetsToRoute();\n    void sortNets(vector<int>& netsToRoute);\n    vector<vector<int>> getBatches(vector<SingleNetRouter>& routers, const vector<int>& netsToRoute, bool seqEq);\n\n    void routeApprx(const vector<int>& netsToRoute);\n    void fluteAllAndRoute(const vector<int>& netsToRoute);\n\n    void ripup(const vector<int>& netsToRoute);\n    void updateCost();\n\n    void printStat();\n};\n"
  },
  {
    "path": "src/multi_net/Scheduler.cpp",
    "content": "#include \"Scheduler.h\"\n\nvector<vector<int>> &Scheduler::schedule() {\n    //\n    vector<int> estimatedNumOfVertices(routers.size(), 0);\n    for (int id = 0; id < routers.size(); ++id)\n        for (auto &guide : routers[id].guides)\n            estimatedNumOfVertices[id] += (guide[X].range() + 1) * (guide[Y].range() + 1);\n\n    // init assigned table\n    vector<bool> assigned(routers.size(), false);\n\n    // sort by sizes\n    vector<int> routerIds;\n    for (int id = 0; id < routers.size(); ++id) routerIds.push_back(id);\n    if (db::setting.multiNetScheduleSortAll) {\n        std::sort(routerIds.begin(), routerIds.end(), [&](int lhs, int rhs) {\n            return estimatedNumOfVertices[lhs] > estimatedNumOfVertices[rhs];\n        });\n    }\n\n    if (db::setting.numThreads == 0) {\n        // simple case\n        for (int routerId : routerIds) batches.push_back({routerId});\n    } else {\n        // normal case\n        int lastUnroute = 0;\n        while (lastUnroute < routerIds.size()) {\n            // create a new batch from a seed\n            batches.emplace_back();\n            initSet({});\n            vector<int> &batch = batches.back();\n            for (int i = lastUnroute; i < routerIds.size(); ++i) {\n                int routerId = routerIds[i];\n\n                if (!assigned[routerId] && !hasConflict(routerId)) {\n                    batch.push_back(routerId);\n                    assigned[routerId] = true;\n                    updateSet(routerId);\n                }\n            }\n            // find the next seed\n            while (lastUnroute < routerIds.size() && assigned[routerIds[lastUnroute]]) {\n                ++lastUnroute;\n            }\n        }\n\n        // sort within batches by NumOfVertices\n        if (db::setting.multiNetScheduleSort) {\n            for (auto &batch : batches) {\n                std::sort(batch.begin(), batch.end(), [&](int lhs, int rhs) {\n                    return estimatedNumOfVertices[lhs] > estimatedNumOfVertices[rhs];\n                });\n            }\n        }\n    }\n\n    if (db::setting.multiNetScheduleReverse) {\n        reverse(batches.begin(), batches.end());\n    }\n\n    return batches;\n}\n\nvector<vector<int>> &Scheduler::scheduleOrderEq() {\n    vector<int> routerIds;\n    for (int id = 0; id < routers.size(); ++id) routerIds.push_back(id);\n\n    if (db::setting.numThreads == 0) {\n        // simple case\n        for (int routerId : routerIds) batches.push_back({routerId});\n    } else {\n        // normal case\n        vector<bool> assigned(routers.size(), false);\n        int lastUnroute = 0;\n\n        while (lastUnroute < routerIds.size()) {\n            // create a new batch from a seed\n            batches.emplace_back();\n            initSet({});\n            vector<int> &batch = batches.back();\n            int lastMetric = INT_MAX;  // Note: need to be change if sort metric changes\n\n            for (int i = lastUnroute; i < routerIds.size(); i++) {\n                int routerId = routerIds[i];\n\n                if (assigned[routerId]) continue;\n\n                int metric = routers[routerId].grNet.boundingBox.hp();\n                if (metric > lastMetric) break;\n\n                if (hasConflict(routerId)) {\n                    lastMetric = metric;\n                } else {\n                    batch.push_back(routerId);\n                    assigned[routerId] = true;\n                    updateSet(routerId);\n                }\n            }\n\n            // find the next seed\n            while (lastUnroute < routerIds.size() && assigned[routerIds[lastUnroute]]) {\n                ++lastUnroute;\n            }\n        }\n    }\n    return batches;\n}\n\nvoid Scheduler::initSet(vector<int> jobIdxes) {\n    rtrees = RTrees(database.getLayerNum());\n    for (int jobIdx : jobIdxes) {\n        updateSet(jobIdx);\n    }\n}\n\nvoid Scheduler::updateSet(int jobIdx) {\n    for (const auto &guide : routers[jobIdx].guides) {\n        boostBox box(boostPoint(guide[X].low, guide[Y].low), boostPoint(guide[X].high, guide[Y].high));\n        rtrees[guide.layerIdx].insert({box, jobIdx});\n    }\n}\n\nbool Scheduler::hasConflict(int jobIdx) {\n    for (const auto &guide : routers[jobIdx].guides) {\n        boostBox box(boostPoint(guide[X].low, guide[Y].low), boostPoint(guide[X].high, guide[Y].high));\n\n        std::vector<std::pair<boostBox, int>> results;\n        rtrees[guide.layerIdx].query(bgi::intersects(box), std::back_inserter(results));\n\n        for (const auto &result : results) {\n            if (result.second != jobIdx) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n"
  },
  {
    "path": "src/multi_net/Scheduler.h",
    "content": "#pragma once\n\n#include \"single_net/SingleNetRouter.h\"\n\nclass Scheduler {\npublic:\n    Scheduler(const vector<SingleNetRouter>& routersToExec) : routers(routersToExec){};\n    vector<vector<int>>& schedule();\n    vector<vector<int>>& scheduleOrderEq();\n\nprivate:\n    const vector<SingleNetRouter>& routers;\n    vector<vector<int>> batches;\n\n    // for conflict detect\n    RTrees rtrees;\n    void initSet(vector<int> jobIdxes);\n    void updateSet(int jobIdx);\n    bool hasConflict(int jobIdx);\n};\n"
  },
  {
    "path": "src/single_net/GenGuide.cpp",
    "content": "#include \"GenGuide.h\"\n\nGuideGeneratorStat guideGenStat;\n\nvoid GuideGenerator::sliceGuides(vector<gr::GrBoxOnLayer> &guides, bool mergeAdj) {\n    vector<vector<gr::GrBoxOnLayer>> tmpGuides(database.getLayerNum());  // route guides on different layers\n    for (auto &guide : guides) {\n        tmpGuides[guide.layerIdx].push_back(guide);\n    }\n    guides.clear();\n    for (int layerIdx = 0; layerIdx < database.getLayerNum(); ++layerIdx) {\n        gr::GrBoxOnLayer::sliceGrPolygons(tmpGuides[layerIdx], mergeAdj);\n        for (auto &guide : tmpGuides[layerIdx]) guides.push_back(guide);\n    }\n}\n\nvoid GuideGenerator::genConnGuides() {\n    // keep connectivity\n    for (auto &point : grNet.ovlpPoints) {\n        grNet.viaRouteGuides.emplace_back(\n            point.layerIdx, utils::IntervalT<int>(point[X], point[X]), utils::IntervalT<int>(point[Y], point[Y]));\n        if (point.layerIdx + 1 < database.getLayerNum())\n            grNet.viaRouteGuides.emplace_back(point.layerIdx + 1,\n                                              utils::IntervalT<int>(point[X], point[X]),\n                                              utils::IntervalT<int>(point[Y], point[Y]));\n        if (point.layerIdx - 1 >= 0)\n            grNet.viaRouteGuides.emplace_back(point.layerIdx - 1,\n                                              utils::IntervalT<int>(point[X], point[X]),\n                                              utils::IntervalT<int>(point[Y], point[Y]));\n    }\n}\n\nvoid GuideGenerator::patchPinRegions() {\n    double patchThresh = 2.0;\n    // check if the region allows patching\n    auto needPatch = [&](gr::GrPoint point) { return grDatabase.getCellUsage(point) < patchThresh; };\n    // get surrounding gcells of a point (normally 3 x 3, but will be different at boudary)\n    auto getSurrounding = [&](gr::GrPoint point) {\n        gr::GrBoxOnLayer box;\n        box.layerIdx = point.layerIdx;\n        box.x.low = max(point.x - 1, 0);\n        box.y.low = max(point.y - 1, 0);\n        box.x.high = min(point.x + 1, grDatabase.getNumGrPoint(X) - 1);\n        box.y.high = min(point.y + 1, grDatabase.getNumGrPoint(Y) - 1);\n        return box;\n    };\n\n    for (auto &pbxs : grNet.pinAccessBoxes) {\n        for (auto &pbx : pbxs) {\n            bool patched = false;\n            // patch upper two layers\n            if (pbx.layerIdx < database.getLayerNum() - 2) {\n                guideGenStat.pinRegionPatchCand++;\n                auto bxPlus1 = gr::GrPoint(pbx.layerIdx + 1, pbx.x, pbx.y);\n                auto bxPlus2 = gr::GrPoint(pbx.layerIdx + 2, pbx.x, pbx.y);\n                if (needPatch(bxPlus1) || needPatch(bxPlus2)) {\n                    patched = true;\n                    guideGenStat.pinRegionPatchNum++;\n                    grNet.patchRouteGuides.emplace_back(getSurrounding(bxPlus1));\n                    grNet.patchRouteGuides.emplace_back(getSurrounding(bxPlus2));\n                } else {\n                    grNet.patchRouteGuides.emplace_back(gr::GrBoxOnLayer(bxPlus1.layerIdx, {pbx.x}, {pbx.y}));\n                    grNet.patchRouteGuides.emplace_back(gr::GrBoxOnLayer(bxPlus2.layerIdx, {pbx.x}, {pbx.y}));\n                }\n            }\n            // patch lower two layers\n            if (pbx.layerIdx > 1) {\n                guideGenStat.pinRegionPatchCand++;\n                auto bxMinus1 = gr::GrPoint(pbx.layerIdx - 1, pbx.x, pbx.y);\n                auto bxMinus2 = gr::GrPoint(pbx.layerIdx - 2, pbx.x, pbx.y);\n                if (needPatch(bxMinus1) || needPatch(bxMinus2)) {\n                    patched = true;\n                    guideGenStat.pinRegionPatchNum++;\n                    grNet.patchRouteGuides.emplace_back(getSurrounding(bxMinus1));\n                    grNet.patchRouteGuides.emplace_back(getSurrounding(bxMinus2));\n                } else {\n                    grNet.patchRouteGuides.emplace_back(gr::GrBoxOnLayer(bxMinus1.layerIdx, {pbx.x}, {pbx.y}));\n                    grNet.patchRouteGuides.emplace_back(gr::GrBoxOnLayer(bxMinus2.layerIdx, {pbx.x}, {pbx.y}));\n                }\n            }\n            // patch original layer\n            if (patched) {\n                grNet.patchRouteGuides.emplace_back(getSurrounding(pbx));\n            } else {\n                grNet.patchRouteGuides.emplace_back(gr::GrBoxOnLayer(pbx.layerIdx, {pbx.x}, {pbx.y}));\n            }\n        }\n    }\n}\n\nvoid GuideGenerator::patchLongSegments() {\n    // Note: assuming all guides are single width\n    const int patchIntvl = 5;  // min patch interval\n    const double patchThresh = 1.0;\n    for (const auto &guide : grNet.wireRouteGuides) {\n        int layerIdx = guide.layerIdx;\n        auto dir = database.getLayerDir(layerIdx);\n        int offset = grNet.dbNet.idx % patchIntvl;\n        for (int cp = guide[1 - dir].low + offset; cp <= guide[1 - dir].high;) {\n            int x = dir == X ? guide[dir].low : cp;\n            int y = dir == X ? cp : guide[dir].low;\n            if (grDatabase.getCellUsage({layerIdx, x, y}) < patchThresh) {\n                bool patched = false;\n                for (int layer_delta = -1; layer_delta <= 1; layer_delta += 2) {\n                    int layer = layerIdx + layer_delta;\n                    if (layer < 1 || layer >= database.getLayerNum()) continue;\n                    if (grDatabase.getCellUsage({layer, x, y}) > patchThresh) {\n                        grNet.patchRouteGuides.emplace_back(gr::GrBoxOnLayer(layer, {x}, {y}));\n                        guideGenStat.longSegmentPatchNum++;\n                        patched = true;\n                    }\n                }\n                if (patched) {\n                    cp += patchIntvl;\n                } else {\n                    cp++;\n                }\n            } else {\n                cp++;\n            }\n        }\n    }\n}\n\nvoid GuideGenerator::patchVioCells() {\n    // Note: assuming all guides are single width\n    const int queryWidth = 1;\n\n    for (const auto &guide : grNet.wireRouteGuides) {\n        int layerIdx = guide.layerIdx;\n        auto dir = database.getLayerDir(layerIdx);\n        int gridline = guide[dir].low;\n\n        for (int cp = guide[1 - dir].low; cp <= guide[1 - dir].high; cp++) {\n            int x = dir == X ? gridline : cp;\n            int y = dir == X ? cp : gridline;\n\n            double cellUsage = grDatabase.getCellUsage({layerIdx, x, y});\n\n            if (cellUsage <= 0) {\n                guideGenStat.vioCellNum++;\n\n                gr::GrBoxOnLayer patch(layerIdx, utils::IntervalT<int>(x), utils::IntervalT<int>(y));\n\n                for (int g = gridline - queryWidth; g <= gridline + queryWidth; g++) {\n                    if (g < 0 || g >= grDatabase.getNumGrPoint(dir)) continue;\n\n                    double curCellUsage = dir == X ? grDatabase.getCellUsage({layerIdx, g, y})\n                                                   : grDatabase.getCellUsage({layerIdx, x, g});\n                    if (curCellUsage <= 0) continue;\n                    cellUsage += curCellUsage;\n                    patch[dir].Update(g);\n                }\n\n                if (cellUsage > 0) {\n                    const vector<int> layers = {layerIdx + 1, layerIdx - 1};\n                    for (auto l : layers) {\n                        if (l >= database.getLayerNum() || l <= 1) continue;\n\n                        bool vioFree = true;\n                        for (int x = patch.lx(); x <= patch.hx() && vioFree; x++)\n                            for (int y = patch.ly(); y <= patch.hy() && vioFree; y++)\n                                if (grDatabase.getCellUsage({l, x, y}) <= 0) vioFree = false;\n\n                        if (vioFree) {\n                            grNet.patchRouteGuides.push_back(patch);\n                            grNet.patchRouteGuides.emplace_back(l, patch[X], patch[Y]);\n                            guideGenStat.vioCellPatchNum++;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid GuideGenerator::genPatchGuides() {\n    grNet.patchRouteGuides.clear();\n    patchPinRegions();\n    patchLongSegments();\n    patchVioCells();\n}\n\nvoid GuideGenerator::genTopoGuides() {\n    grNet.wireRouteGuides.clear();\n    grNet.viaRouteGuides.clear();\n\n    genConnGuides();\n\n    // Note: generate guides by topology\n    grNet.postOrderVisitGridTopo([&](std::shared_ptr<gr::GrSteiner> node) {\n        auto parent = node;\n        for (auto child : parent->children) {\n            if (parent->layerIdx == child->layerIdx) {\n                std::shared_ptr<gr::GrSteiner> lower, upper;\n                if ((*parent)[X] < (*child)[X] || (*parent)[Y] < (*child)[Y]) {\n                    lower = parent;\n                    upper = child;\n                } else {\n                    lower = child;\n                    upper = parent;\n                }\n                grNet.wireRouteGuides.emplace_back(lower->layerIdx,\n                                                   utils::IntervalT<int>((*lower)[X], (*upper)[X]),\n                                                   utils::IntervalT<int>((*lower)[Y], (*upper)[Y]));\n            } else {\n                grNet.viaRouteGuides.emplace_back(parent->layerIdx,\n                                                  utils::IntervalT<int>((*parent)[X], (*parent)[X]),\n                                                  utils::IntervalT<int>((*parent)[Y], (*parent)[Y]));\n                grNet.viaRouteGuides.emplace_back(child->layerIdx,\n                                                  utils::IntervalT<int>((*child)[X], (*child)[X]),\n                                                  utils::IntervalT<int>((*child)[Y], (*child)[Y]));\n            }\n        }\n    });\n\n    sliceGuides(grNet.wireRouteGuides);\n    sliceGuides(grNet.viaRouteGuides);\n}\n"
  },
  {
    "path": "src/single_net/GenGuide.h",
    "content": "#pragma once\n#include \"gr_db/GrDatabase.h\"\n\nclass GuideGenerator {\npublic:\n    GuideGenerator(gr::GrNet& grNetData) : grNet(grNetData) {}\n    void genTopoGuides();\n    void genPatchGuides();\n    static void sliceGuides(vector<gr::GrBoxOnLayer>& guides, bool mergeAdj = false);\n\nprivate:\n    gr::GrNet& grNet;\n    void genConnGuides();\n\n    void patchPinRegions();\n    void patchLongSegments();\n    void patchVioCells();\n};\n\nclass GuideGeneratorStat {\npublic:\n    int longSegmentPatchNum;\n\n    int vioCellNum;\n    int vioCellPatchNum;\n\n    int pinRegionPatchCand;\n    int pinRegionPatchNum;\n\n    void reset() {\n        longSegmentPatchNum = 0;\n\n        vioCellNum = 0;\n        vioCellPatchNum = 0;\n    }\n\n    void print() {\n        log() << \"Add pin region patches. Totally \" << pinRegionPatchNum << \"/\" << pinRegionPatchCand\n              << \" patches are added.\" << std::endl;\n        log() << \"Add long segment patches. Totally \" << longSegmentPatchNum << \" patches are added.\" << std::endl;\n        printflog(\"Add cong cell patches. Totally %d/%d patches are added\\n\", vioCellPatchNum, vioCellNum);\n    }\n};\n\nextern GuideGeneratorStat guideGenStat;\n"
  },
  {
    "path": "src/single_net/GridGraph.cpp",
    "content": "#include \"GridGraph.h\"\n#include \"global.h\"\n#include \"GenGuide.h\"\n\nvoid GridGraph::init(int nNodes) {\n    conn.resize(nNodes, {-1, -1, -1, -1});\n    edgeCost.resize(nNodes, {-1, -1, -1, -1});\n\n    edgeCount = 0;\n}\n\nvoid GridGraph::addEdge(int u, int v, EdgeDirection dir, db::CostT w) {\n    if (hasEdge(u, dir)) return;\n\n    edgeCost[u][dir] = edgeCost[v][getOppDir(dir)] = w;\n    conn[u][dir] = v;\n    conn[v][oppDirections[dir]] = u;\n\n    edgeCount++;\n}\n\nvoid GridGraph::writeDebugFile(const std::string &fn) const {\n    std::ofstream debugFile(fn);\n    for (int i = 0; i < conn.size(); ++i) {\n        debugFile << i << \" \" << vertexToPoint[i] << \" edgeC=\" << edgeCost[i] << \" conn=\" << conn[i] << std::endl;\n    }\n}\n\nbool GridGraph::checkConn() const {\n    auto BFS = [&](int s, vector<bool> &visited) {\n        std::queue<int> q;\n        visited[s] = true;\n        q.push(s);\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            for (auto v : conn[u]) {\n                if (v != -1 && !visited[v]) {\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    };\n\n    vector<bool> visited(conn.size(), false);\n    BFS(0, visited);\n    for (int i = 0; i < visited.size(); i++)\n        if (!visited[i]) return false;\n    return true;\n}\n\nbool switchLayer(EdgeDirection direction) { return direction == UP || direction == DOWN; }\n\nEdgeDirection getOppDir(EdgeDirection direction) { return oppDirections[direction]; }\n\nvoid CoarseGridGraphBuilder::run(const vector<vector<gr::PointOnLayer>> &mergedPinAccessBoxes) {\n    numPointsX = ceil(grDatabase.getNumGrPoint(X) / (double)cellWidth);\n    numPointsY = ceil(grDatabase.getNumGrPoint(Y) / (double)cellHeight);\n    int numPoints = numPointsX * numPointsY * database.getLayerNum();\n\n    // 1. Give each grid point an index\n    graph.vertexToPoint.reserve(numPoints);\n    for (int l = 0; l < database.getLayerNum(); l++)\n        for (int x = 0; x < numPointsX; x++)\n            for (int y = 0; y < numPointsY; y++) graph.vertexToPoint.emplace_back(l, x, y);\n\n    // 2. Add vertex-pin connection\n    graph.pinToVertex.resize(mergedPinAccessBoxes.size());\n    for (unsigned p = 0; p < mergedPinAccessBoxes.size(); p++) {\n        for (const auto &point : mergedPinAccessBoxes[p]) {\n            int u = pointToVertex(point);\n            graph.pinToVertex[p].push_back(u);\n            graph.vertexToPin[u] = p;\n        }\n    }\n\n    graph.init(numPoints);\n\n    // 3. Add inter-layer connection\n    for (int l = 0; l < database.getLayerNum() - 1; l++) {\n        int lowerBias = numPointsX * numPointsY * l;\n        int upperBias = numPointsX * numPointsY * (l + 1);\n        for (int x = 0; x < numPointsX; x++) {\n            int bias = numPointsY * x;\n            for (int y = 0; y < numPointsY; y++) {\n                int u = lowerBias + bias + y;\n                int v = upperBias + bias + y;\n                graph.addEdge(u, v, UP, congMap.getCrsnViaCost({l, x, y}));\n            }\n        }\n    }\n\n    // 4. add intra-layer connection\n    for (int l = 0; l < database.getLayerNum(); l++) {\n        int layerBias = numPointsX * numPointsY * l;\n        if (database.getLayerDir(l) == X) {\n            for (int x = 0; x < numPointsX; x++) {\n                int bias = numPointsY * x;\n                for (int y = 0; y < numPointsY - 1; y++) {\n                    int u = layerBias + bias + y;\n                    int v = layerBias + bias + y + 1;\n                    graph.addEdge(u, v, FORWARD, congMap.getCrsnEdgeCost({l, x, y}, {l, x, y + 1}));\n                }\n            }\n        } else {\n            for (int x = 0; x < numPointsX - 1; x++) {\n                int bias = numPointsY * x;\n                for (int y = 0; y < numPointsY; y++) {\n                    int u = layerBias + bias + y;\n                    int v = layerBias + bias + y + numPointsY;\n                    graph.addEdge(u, v, FORWARD, congMap.getCrsnEdgeCost({l, x, y}, {l, x + 1, y}));\n                }\n            }\n        }\n    }\n}\n\nint CoarseGridGraphBuilder::pointToVertex(const gr::PointOnLayer &point) const {\n    return numPointsX * numPointsY * point.layerIdx + numPointsY * point[X] + point[Y];\n}\n\ngr::PointOnLayer CoarseGridGraphBuilder::grPointToPoint(const gr::GrPoint &point) const {\n    return congMap.grPointToPoint(point);\n}\n\ndouble CoarseGridGraphBuilder::getCost(int u, int v) { return 0; }\n\nvoid GuideGridGraphBuilder::run(const vector<vector<gr::PointOnLayer>> &mergedPinAccessBoxes) {\n    // 0. slice guides by their prefer direction\n    GuideGenerator::sliceGuides(guides);\n\n    // 1. Give each grid point an index\n    for (auto &box : guides) {\n        int begin = intervals.empty() ? 0 : intervals.back().second;\n        int end = begin + (box[X].range() + 1) * (box[Y].range() + 1);\n\n        intervals.emplace_back(begin, end);\n    }\n    graph.vertexToPoint.reserve(intervals.back().second);\n    for (auto &box : guides) {\n        auto dir = database.getLayerDir(box.layerIdx);\n        for (int gridline = box[dir].low; gridline <= box[dir].high; gridline++) {\n            for (int cp = box[1 - dir].low; cp <= box[1 - dir].high; cp++) {\n                if (dir == X)\n                    graph.vertexToPoint.emplace_back(box.layerIdx, gridline, cp);\n                else\n                    graph.vertexToPoint.emplace_back(box.layerIdx, cp, gridline);\n            }\n        }\n    }\n\n    // 2. Add guide-pin connection\n    graph.pinToVertex.resize(mergedPinAccessBoxes.size());\n    for (unsigned p = 0; p < mergedPinAccessBoxes.size(); p++) {\n        for (const auto &point : mergedPinAccessBoxes[p]) {\n            auto dir = database.getLayerDir(point.layerIdx);\n            for (unsigned g = 0; g < guides.size(); g++) {\n                if (guides[g].includePoint({point.layerIdx, point[X], point[Y]})) {\n                    int u = guideToVertex(g, point[dir], point[1 - dir]);\n                    graph.pinToVertex[p].push_back(u);\n                    graph.vertexToPin[u] = p;\n                }\n            }\n        }\n    }\n\n    graph.init(intervals.back().second);\n\n    // 3. Add inter-guide connection\n    for (unsigned b1 = 0; b1 < guides.size(); b1++) {\n        for (unsigned b2 = b1 + 1; b2 < guides.size(); b2++)\n            if (guides[b1][X].HasIntersectWith(guides[b2][X]) && guides[b1][Y].HasIntersectWith(guides[b2][Y]) &&\n                abs(guides[b1].layerIdx - guides[b2].layerIdx) <= 1)\n                connectTwoGuides(b1, b2);\n    }\n\n    // 4. add intra-guide connection\n    for (unsigned b = 0; b < guides.size(); b++) connectGuide(b);\n}\n\nvoid GuideGridGraphBuilder::connectGuide(int guideIdx) {\n    const auto &box = guides[guideIdx];\n\n    int layerIdx = box.layerIdx;\n    auto dir = database.getLayerDir(layerIdx);\n\n    const auto &gridlineRange = box[dir];\n    const auto &cpRange = box[1 - dir];\n    int netIdx = grNet.dbNet.idx;\n\n    auto setEdgeCost = [&](int gridline, int beginCP, int endCP) {\n        if (beginCP == endCP) return;\n\n        int u = guideToVertex(guideIdx, gridline, beginCP);\n        int v = guideToVertex(guideIdx, gridline, endCP);\n\n        gr::GrPoint point1(layerIdx, dir == X ? gridline : beginCP, dir == X ? beginCP : gridline);\n        gr::GrPoint point2(layerIdx, dir == X ? gridline : endCP, dir == X ? endCP : gridline);\n        db::CostT cost = grDatabase.getWireCost({point1, point2});\n\n        graph.addEdge(u, v, FORWARD, cost);\n    };\n\n    auto canRemove = [&](int gridline, int cp) {\n        int vertexIdx = guideToVertex(guideIdx, gridline, cp);\n        return !graph.hasEdge(vertexIdx, UP) && !graph.hasEdge(vertexIdx, DOWN) && graph.getPinIdx(vertexIdx) == -1 &&\n               cp != cpRange.low && cp != cpRange.high;\n    };\n\n    if (cpRange.range() == 0) return;\n\n    for (int g = gridlineRange.low; g <= gridlineRange.high; g++) {\n        // get the directIntervals\n        vector<utils::IntervalT<int>> directIntervals;\n        int begin = -1, end = -1;\n        for (int c = cpRange.low; c <= cpRange.high; c++) {\n            if (begin == -1) {\n                if (canRemove(g, c)) begin = c - 1;\n            } else {\n                if (!canRemove(g, c)) {\n                    end = c;\n                    directIntervals.emplace_back(begin, end);\n                    begin = -1;\n                    end = -1;\n                }\n            }\n        }\n\n        // get the indirectIntervals\n        vector<utils::IntervalT<int>> indirectIntervals;\n        if (directIntervals.empty()) {\n            indirectIntervals.push_back(cpRange);\n        } else {\n            indirectIntervals.emplace_back(cpRange.low, directIntervals.begin()->low);\n            for (int i = 0; i + 1 < directIntervals.size(); i++) {\n                indirectIntervals.emplace_back(directIntervals[i].high, directIntervals[i + 1].low);\n            }\n            indirectIntervals.emplace_back(directIntervals.rbegin()->high, cpRange.high);\n        }\n\n        // connect the intervals\n        for (auto &interval : directIntervals) setEdgeCost(g, interval.low, interval.high);\n\n        for (auto &interval : indirectIntervals)\n            for (int c = interval.low; c + 1 <= interval.high; c++) setEdgeCost(g, c, c + 1);\n    }\n}\n\nvoid GuideGridGraphBuilder::connectTwoGuides(int guideIdx1, int guideIdx2) {\n    const auto &box1 = guides[guideIdx1];\n    const auto &box2 = guides[guideIdx2];\n\n    int upperIdx = box1.layerIdx > box2.layerIdx ? guideIdx1 : guideIdx2;\n    int lowerIdx = box1.layerIdx < box2.layerIdx ? guideIdx1 : guideIdx2;\n\n    auto lowerDir = database.getLayerDir(guides[lowerIdx].layerIdx);\n\n    auto lowerGridLineIntvl = guides[lowerIdx][lowerDir].IntersectWith(guides[upperIdx][lowerDir]);\n    auto lowerCPIntvl = guides[lowerIdx][1 - lowerDir].IntersectWith(guides[upperIdx][1 - lowerDir]);\n\n    for (int lowerGridLine = lowerGridLineIntvl.low; lowerGridLine <= lowerGridLineIntvl.high; lowerGridLine++) {\n        for (int lowerCPIdx = lowerCPIntvl.low; lowerCPIdx <= lowerCPIntvl.high; lowerCPIdx++) {\n            int u = guideToVertex(upperIdx, lowerCPIdx, lowerGridLine);\n            int v = guideToVertex(lowerIdx, lowerGridLine, lowerCPIdx);\n\n            db::CostT cost = grDatabase.getViaCost({guides[lowerIdx].layerIdx,\n                                                    lowerDir == X ? lowerGridLine : lowerCPIdx,\n                                                    lowerDir == X ? lowerCPIdx : lowerGridLine});\n\n            graph.addEdge(u, v, DOWN, cost);\n        }\n    }\n}\n\nint GuideGridGraphBuilder::guideToVertex(int gIdx, int gridline, int cp) const {\n    const auto &box = guides[gIdx];\n    int pointBias = intervals[gIdx].first;\n\n    return boxToVertex(box, pointBias, gridline, cp);\n}\n\nint GuideGridGraphBuilder::boxToVertex(const gr::GrBoxOnLayer &box, int pointBias, int gridline, int cp) const {\n    auto dir = database.getLayerDir(box.layerIdx);\n    return pointBias + (gridline - box[dir].low) * (box[1 - dir].range() + 1) + (cp - box[1 - dir].low);\n}\n"
  },
  {
    "path": "src/single_net/GridGraph.h",
    "content": "#pragma once\n#include \"global.h\"\n#include \"db/Database.h\"\n#include \"gr_db/GrDatabase.h\"\n#include \"multi_net/CongestionMap.h\"\n\nenum EdgeDirection { BACKWARD = 0, FORWARD = 1, UP = 2, DOWN = 3 };\n\nconst vector<EdgeDirection> directions = {BACKWARD, FORWARD, UP, DOWN};\nconst vector<EdgeDirection> oppDirections = {FORWARD, BACKWARD, DOWN, UP};\n\nbool switchLayer(EdgeDirection direction);\nEdgeDirection getOppDir(EdgeDirection direction);\n\nclass GuideGridGraphBuilder;\nclass CoarseGridGraphBuilder;\n\n// Note: GridGraph will be across both GridGraphBuilder & MazeRoute\nclass GridGraph {\npublic:\n    friend GuideGridGraphBuilder;\n    friend CoarseGridGraphBuilder;\n\n    // getters\n    bool hasEdge(int u, EdgeDirection dir) const { return conn[u][dir] != -1; }\n    int getEdgeEndPoint(int u, EdgeDirection dir) const { return conn[u][dir]; }\n    db::CostT getEdgeCost(int u, EdgeDirection dir) const { return edgeCost[u][dir]; }\n    gr::PointOnLayer& getPoint(int u) { return vertexToPoint[u]; }\n    int getEdgeNum() const { return edgeCount; }\n    int getNodeNum() const { return conn.size(); }\n    int getPinIdx(int u) const {\n        auto it = vertexToPin.find(u);\n        return (it != vertexToPin.end()) ? it->second : -1;\n    }\n    vector<int>& getVertices(int pinIdx) { return pinToVertex[pinIdx]; }\n\n    void writeDebugFile(const std::string& fn) const;\n    bool checkConn() const;\n\nprivate:\n    int edgeCount;\n\n    // vertex properties\n    std::unordered_map<int, int> vertexToPin;  // vertexIdx to pinIdx\n    vector<vector<int>> pinToVertex;\n    vector<gr::PointOnLayer> vertexToPoint;\n\n    // adj lists\n    vector<std::array<int, 4>> conn;\n    vector<std::array<db::CostT, 4>> edgeCost;\n\n    // setters\n    void init(int nNodes);\n    void addEdge(int u, int v, EdgeDirection dir, db::CostT w);\n};\n\nclass GridGraphBuilderBase {\npublic:\n    GridGraphBuilderBase(gr::GrNet& grNetData, GridGraph& graphData) : grNet(grNetData), graph(graphData){};\n\n    virtual void run(const vector<vector<gr::PointOnLayer>>& mergedPinAccessBoxes) = 0;\n\nprotected:\n    gr::GrNet& grNet;\n    GridGraph& graph;\n};\n\nclass GuideGridGraphBuilder : public GridGraphBuilderBase {\npublic:\n    GuideGridGraphBuilder(gr::GrNet& grNetData, GridGraph& graphData, const vector<gr::GrBoxOnLayer>& guidesData)\n        : GridGraphBuilderBase(grNetData, graphData), guides(guidesData) {}\n\n    virtual void run(const vector<vector<gr::PointOnLayer>>& mergedPinAccessBoxes);\n\nprivate:\n    vector<gr::GrBoxOnLayer> guides;\n    vector<std::pair<int, int>> intervals;\n\n    void connectGuide(int guideIdx);\n    void connectTwoGuides(int guideIdx1, int guideIdx2);\n\n    int guideToVertex(int gIdx, int x, int y) const;\n    int boxToVertex(const gr::GrBoxOnLayer& box, int pointBias, int x, int y) const;\n};\n\nclass CoarseGridGraphBuilder : public GridGraphBuilderBase {\npublic:\n    CoarseGridGraphBuilder(gr::GrNet& grNetData, GridGraph& graphData, const CongestionMap& congMapData)\n        : GridGraphBuilderBase(grNetData, graphData),\n          congMap(congMapData),\n          cellWidth(congMap.getCellWidth()),\n          cellHeight(congMap.getCellHeight()) {}\n\n    virtual void run(const vector<vector<gr::PointOnLayer>>& mergedPinAccessBoxes);\n    gr::PointOnLayer grPointToPoint(const gr::GrPoint& point) const;\n\nprivate:\n    const CongestionMap& congMap;\n    int cellWidth;\n    int cellHeight;\n    int numPointsX;\n    int numPointsY;\n\n    int pointToVertex(const gr::PointOnLayer& point) const;\n    double getCost(int u, int v);\n};"
  },
  {
    "path": "src/single_net/InitRoute.cpp",
    "content": "#include \"InitRoute.h\"\n\nusing namespace std;\n\nmutex fluteMutex;\n\nstruct hash_tuple {  // hash binary tuple\n    template <class T>\n    size_t operator()(const tuple<T, T>& tup) const {\n        auto hash1 = hash<T>{}(get<0>(tup));\n        auto hash2 = hash<T>{}(get<1>(tup));\n        return hash1 ^ hash2;\n    }\n};\n\nvoid InitRoute::runFlute() {\n    // get net center\n    // float net_ctrz = 0;\n    float net_ctrx = 0;\n    float net_ctry = 0;\n    for (auto& pinBoxes : grNet.pinAccessBoxes) {\n        // float pin_ctrz = 0;\n        float pin_ctrx = 0;\n        float pin_ctry = 0;\n        for (auto& pinBox : pinBoxes) {\n            pin_ctrx += pinBox.x;\n            pin_ctry += pinBox.y;\n        }\n        pin_ctrx /= pinBoxes.size();\n        pin_ctry /= pinBoxes.size();\n\n        net_ctrx += pin_ctrx;\n        net_ctry += pin_ctry;\n    }\n    net_ctrx /= grNet.pinAccessBoxes.size();\n    net_ctry /= grNet.pinAccessBoxes.size();\n\n    // get pin center\n    vector<tuple<int, int>> pinCenters;\n\n    for (auto& pinBoxes : grNet.pinAccessBoxes) {\n        float xCenter = 0;\n        float yCenter = 0;\n        for (auto& pinBox : pinBoxes) {\n            xCenter += pinBox.x;\n            yCenter += pinBox.y;\n        }\n        xCenter /= pinBoxes.size();\n        yCenter /= pinBoxes.size();\n        // 3 kinds of accessibility (0) totally vio-free (1) one side vio-free (2) no side vio-free\n        float min_dist[3];\n        min_dist[0] = min_dist[1] = min_dist[2] = numeric_limits<float>::max();\n        int best_box[3] = {-1, -1, -1};\n\n        for (int pb = 0; pb < pinBoxes.size(); pb++) {\n            // check pin box's accessibility\n            auto& pb_x = pinBoxes[pb].x;\n            auto& pb_y = pinBoxes[pb].y;\n            int layer_idx = pinBoxes[pb].layerIdx;\n            int is_x = database.getLayerDir(layer_idx) == X ? 1 : 0;\n            auto low_edge =\n                gr::GrEdge({layer_idx, max(pb_x - (1 - is_x), 0), max(pb_y - is_x, 0)}, {layer_idx, pb_x, pb_y});\n            auto high_edge = gr::GrEdge({layer_idx, pb_x, pb_y},\n                                        {layer_idx,\n                                         min(pb_x + (1 - is_x), grDatabase.getNumGrPoint(X) - 1),\n                                         min(pb_y + is_x, grDatabase.getNumGrPoint(Y) - 1)});\n\n            int pb_access = 0;\n            pb_access += int(grDatabase.hasVio(low_edge, false));\n            pb_access += int(grDatabase.hasVio(high_edge, false));\n\n            float dist = abs(pinBoxes[pb].x - net_ctrx) + abs(pinBoxes[pb].y - net_ctrx);\n            if (dist < min_dist[pb_access]) {\n                min_dist[pb_access] = dist;\n                best_box[pb_access] = pb;\n            }\n        }\n        for (int ac = 0; ac < 3; ac++) {\n            if (best_box[ac] != -1) {\n                pinCenters.emplace_back(make_tuple(pinBoxes[best_box[ac]].x, pinBoxes[best_box[ac]].y));\n                break;\n            }\n        }\n    }\n\n    // location to pins\n    unordered_map<tuple<int, int>, vector<int>, hash_tuple> loc2Pins;\n    for (int i = 0; i < pinCenters.size(); i++) {\n        loc2Pins[pinCenters[i]].emplace_back(i);\n    }\n\n    // flute\n    int degree = loc2Pins.size();\n    int xs[100 * degree];\n    int ys[100 * degree];\n    int pt_cnt = 0;\n    int node_cnt = 0;\n    // if (loc2Pins.size() > MAX_DEGREE) {\n    //     log() << \"Warning: Net degree larger than MAXD(flute)\" << endl;\n    // }\n    for (auto& loc2pin : loc2Pins) {\n        const tuple<int, int>& loc = loc2pin.first;\n        xs[pt_cnt] = get<0>(loc);\n        ys[pt_cnt] = get<1>(loc);\n        pt_cnt++;\n    }\n    if (degree >= 2) {\n        fluteMutex.lock();\n        Tree flutetree = flute(degree, xs, ys, ACCURACY);\n        fluteMutex.unlock();\n        unordered_map<tuple<int, int>, int, hash_tuple> loc2Node;  // location -> RouteNode index\n        for (int i = 0; i < degree * 2 - 2; i++) {\n            Branch& branch1 = flutetree.branch[i];\n            Branch& branch2 = flutetree.branch[branch1.n];\n            tuple<int, int> fluteEdge[2];\n            fluteEdge[0] = make_tuple(branch1.x, branch1.y);\n            fluteEdge[1] = make_tuple(branch2.x, branch2.y);\n            // create route nodes\n            for (int j = 0; j < 2; j++) {\n                tuple<int, int>& nodeLoc = fluteEdge[j];\n                if (loc2Node.find(nodeLoc) == loc2Node.end()) {\n                    RouteNode node(fluteEdge[j]);\n                    // pin info\n                    if (loc2Pins.find(nodeLoc) != loc2Pins.end()) {\n                        node.pinIdxs = loc2Pins[nodeLoc];\n                        for (int pIdx : node.pinIdxs) {\n                            int layerIdx = grNet.pinAccessBoxes[pIdx][0].layerIdx;\n                            node.pinLayers.emplace_back(layerIdx);\n\n                            // for (auto& box: grNet.pinAccessBoxes[pIdx]) {\n                            //     if (box.layerIdx != layerIdx) {\n                            //         log() << \"Error: Pin across layers spotted\" << endl;\n                            //     }\n                            // }\n                        }\n                    }\n                    node.idx = node_cnt;\n                    routeNodes[node_cnt++] = node;\n                    loc2Node[nodeLoc] = routeNodes.size() - 1;\n                }\n            }\n            // add connectivity info\n            if (fluteEdge[0] != fluteEdge[1]) {\n                int nodeIdx1 = loc2Node[fluteEdge[0]];\n                int nodeIdx2 = loc2Node[fluteEdge[1]];\n                routeNodes[nodeIdx1].toConnect.insert(nodeIdx2);\n                routeNodes[nodeIdx2].toConnect.insert(nodeIdx1);\n            }\n        }\n    } else if (degree == 1) {\n        auto nodeLoc = make_tuple(xs[0], ys[0]);\n        RouteNode node(nodeLoc);\n        if (loc2Pins.find(nodeLoc) != loc2Pins.end()) {\n            node.pinIdxs = loc2Pins[nodeLoc];\n            for (int pIdx : node.pinIdxs) {\n                int layerIdx = grNet.pinAccessBoxes[pIdx][0].layerIdx;\n                node.pinLayers.emplace_back(layerIdx);\n            }\n        } else {\n            log() << \"Error: loc2Pins is empty.\" << std::endl;\n        }\n        node.idx = node_cnt;\n        routeNodes[node_cnt++] = node;\n        return;\n    } else {\n        log() << \"Error: degree = 0.\" << std::endl;\n    }\n}\n\nvoid InitRoute::patternRoute() {\n    int layer_cnt = database.getLayerNum();\n    for (auto& edge : routeEdges) {\n        auto& fromNode = routeNodes[edge.from];\n        auto& toNode = routeNodes[edge.to];\n        // Initialize fromNode's exitCosts\n        fromNode.exitCosts.resize(layer_cnt, numeric_limits<db::CostT>::max());\n        int lowest_pin = layer_cnt;\n        int highest_pin = -1;\n        for (int pin_layer : fromNode.pinLayers) {\n            lowest_pin = min(lowest_pin, pin_layer);\n            highest_pin = max(highest_pin, pin_layer);\n        }\n        if (fromNode.childIdxs.size() == 0) {  // no children nodes, only via costs\n            for (int layer_idx = 0; layer_idx < layer_cnt; layer_idx++) {\n                int lowest_layer = min(lowest_pin, layer_idx);\n                int highest_layer = max(highest_pin, layer_idx);\n                db::CostT exit_cost = grDatabase.getStackViaCost(gr::GrPoint(lowest_layer, fromNode.x, fromNode.y),\n                                                                 highest_layer - lowest_layer);\n                fromNode.exitCosts[layer_idx] = exit_cost;\n            }\n        } else {\n            // initialize exitEnterLayers map\n            for (int child_idx : fromNode.childIdxs) {\n                fromNode.exitEnterLayers[child_idx] = vector<int>(layer_cnt, -1);\n            }\n            // enumerate all children layer combinations\n            int num_children = fromNode.childIdxs.size();\n            for (int enum_idx = 0; enum_idx < pow(layer_cnt, num_children); enum_idx++) {\n                vector<int> enum_vec;\n                int e_idx = enum_idx;\n                for (int en = 0; en < num_children; en++) {\n                    enum_vec.emplace_back(e_idx % layer_cnt);\n                    e_idx /= layer_cnt;\n                }\n                db::CostT prev_cost = 0;\n                for (int c = 0; c < num_children; c++) {\n                    int child_idx = fromNode.childIdxs[c];\n                    prev_cost += fromNode.enterCosts[child_idx][enum_vec[c]];\n                }\n                int highest_layer = highest_pin;\n                int lowest_layer = lowest_pin;\n                for (int e_layer : enum_vec) {\n                    highest_layer = max(highest_layer, e_layer);\n                    lowest_layer = min(lowest_layer, e_layer);\n                }\n                for (int layer_idx = 0; layer_idx < layer_cnt; layer_idx++) {\n                    int via_bottom = min(lowest_layer, layer_idx);\n                    int via_height = max(highest_layer, layer_idx) - via_bottom;\n                    db::CostT via_cost =\n                        grDatabase.getStackViaCost(gr::GrPoint(via_bottom, fromNode.x, fromNode.y), via_height);\n                    db::CostT cost = prev_cost + via_cost;\n                    if (cost < fromNode.exitCosts[layer_idx]) {\n                        fromNode.exitCosts[layer_idx] = cost;\n                        for (int c = 0; c < num_children; c++) {\n                            fromNode.exitEnterLayers[fromNode.childIdxs[c]][layer_idx] = enum_vec[c];\n                        }\n                    }\n                }\n            }\n        }\n        // Patterns\n        LShape(edge);\n    }\n}\n\ndb::CostT InitRoute::getBufferedWireCost(gr::GrEdge edge) {\n    if (wireCostBuffer.find(edge) != wireCostBuffer.end()) {\n        return wireCostBuffer[edge];\n    } else {\n        auto wireCost = grDatabase.getWireCost(edge);\n        wireCostBuffer[edge] = wireCost;\n        return wireCost;\n    }\n}\n\nvoid InitRoute::LShape(const RouteEdge& edge) {\n    int layer_cnt = database.getLayerNum();\n\n    auto& fromNode = routeNodes[edge.from];\n    auto& toNode = routeNodes[edge.to];\n\n    vector<db::CostT> enter_cost(layer_cnt, numeric_limits<db::CostT>::max());\n    vector<vector<gr::GrPoint>> enter_edges(layer_cnt);\n\n    if (fromNode.x == toNode.x || fromNode.y == toNode.y) {  // has no bending point\n        bool dir = (fromNode.x == toNode.x ? X : Y);\n        for (int layer = 0; layer < layer_cnt; layer++) {\n            if (database.getLayerDir(layer) != dir) continue;\n            gr::GrEdge gr_edge(gr::GrPoint(layer, fromNode.x, fromNode.y), gr::GrPoint(layer, toNode.x, toNode.y));\n            db::CostT edge_cost = grDatabase.getWireCost(gr_edge);\n            db::CostT cost = fromNode.exitCosts[layer] + edge_cost;\n            if (cost < enter_cost[layer]) {\n                enter_cost[layer] = cost;\n                vector<gr::GrPoint> edge_vec;\n                edge_vec.emplace_back(gr::GrPoint(layer, fromNode.x, fromNode.y));\n                // edge_vec.emplace_back(gr::GrPoint(layer+1, fromNode.x, fromNode.y)); // additional\n                // edge_vec.emplace_back(gr::GrPoint(layer, fromNode.x, fromNode.y)); // additional\n                edge_vec.emplace_back(gr::GrPoint(layer, toNode.x, toNode.y));\n                // edge_vec.emplace_back(gr::GrPoint(layer, toNode.x, toNode.y)); // additional\n                // edge_vec.emplace_back(gr::GrPoint(layer, toNode.x, toNode.y)); // additional\n                enter_edges[layer] = move(edge_vec);\n            }\n        }\n    } else {  // has a bending point\n        for (int to_layer = 0; to_layer < layer_cnt; to_layer++) {\n            Dimension to_dir = database.getLayerDir(to_layer);\n            int bend_x = -1;  // bending point\n            int bend_y = -1;\n            if (to_dir == Y) {\n                bend_x = fromNode.x;\n                bend_y = toNode.y;\n            } else {\n                bend_x = toNode.x;\n                bend_y = fromNode.y;\n            }\n\n            // to_layer edge cost\n            gr::GrEdge to_gr_edge(gr::GrPoint(to_layer, bend_x, bend_y), gr::GrPoint(to_layer, toNode.x, toNode.y));\n            db::CostT to_edge_cost = grDatabase.getWireCost(to_gr_edge);\n\n            db::CostT min_cost = numeric_limits<db::CostT>::max();\n            int best_from_layer = -1;\n            for (int from_layer = 0; from_layer < layer_cnt; from_layer++) {\n                if (database.getLayerDir(from_layer) == to_dir) continue;  // same routing direction\n\n                // from_layer edge cost\n                gr::GrEdge from_gr_edge(gr::GrPoint(from_layer, fromNode.x, fromNode.y),\n                                        gr::GrPoint(from_layer, bend_x, bend_y));\n                db::CostT from_edge_cost = getBufferedWireCost(from_gr_edge);\n\n                db::CostT bend_via_cost = grDatabase.getStackViaCost(\n                    gr::GrPoint(min(from_layer, to_layer), bend_x, bend_y), abs(to_layer - from_layer));\n\n                db::CostT cost = fromNode.exitCosts[from_layer] + from_edge_cost + bend_via_cost + to_edge_cost;\n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_from_layer = from_layer;\n                }\n            }\n            enter_cost[to_layer] = min_cost;\n            vector<gr::GrPoint> edge_vec;\n            edge_vec.emplace_back(gr::GrPoint(best_from_layer, fromNode.x, fromNode.y));\n            bool go_up = (best_from_layer < to_layer);\n            for (int cur_layer = best_from_layer;;) {\n                edge_vec.emplace_back(gr::GrPoint(cur_layer, bend_x, bend_y));\n                if (cur_layer == to_layer) break;\n                cur_layer += (go_up ? 1 : -1);\n            }\n            // edge_vec.emplace_back(gr::GrPoint(best_from_layer, bend_x, bend_y));\n            // edge_vec.emplace_back(gr::GrPoint(to_layer, bend_x, bend_y));\n            edge_vec.emplace_back(gr::GrPoint(to_layer, toNode.x, toNode.y));\n            enter_edges[to_layer] = move(edge_vec);\n        }\n    }\n    toNode.enterCosts[edge.from] = move(enter_cost);\n    toNode.enterEdges[edge.from] = move(enter_edges);\n}\n\n\nvoid InitRoute::buildTopo() {\n    int layer_cnt = database.getLayerNum();\n    int rootIdx = -1;\n    int root_enter_layer = -1;\n    // build topo tree\n    if (routeEdges.size() > 0) {\n        rootIdx = routeEdges[routeEdges.size() - 1].to;\n        RouteNode& rootNode = routeNodes[rootIdx];\n\n        int highest_layer = -1;\n        int lowest_layer = layer_cnt;\n        for (int pin_layer : rootNode.pinLayers) {\n            lowest_layer = min(lowest_layer, pin_layer);\n            highest_layer = max(highest_layer, pin_layer);\n        }\n        // find min cost enter layer\n        assert(rootNode.enterCosts.size() == 1);\n        auto& enterCosts = rootNode.enterCosts.begin()->second;\n        db::CostT min_cost = numeric_limits<db::CostT>::max();\n        for (int layer_idx = 0; layer_idx < layer_cnt; layer_idx++) {\n            db::CostT cost = enterCosts[layer_idx];\n            int via_bottom = min(lowest_layer, layer_idx);\n            int via_height = max(highest_layer, layer_idx) - via_bottom;\n            db::CostT via_cost =\n                grDatabase.getStackViaCost(gr::GrPoint(via_bottom, rootNode.x, rootNode.y), via_height);\n            cost += via_cost;  // via cost\n            if (cost < min_cost) {\n                min_cost = cost;\n                root_enter_layer = layer_idx;\n            }\n        }\n    } else {  // local net\n        rootIdx = 0;\n        root_enter_layer = routeNodes[rootIdx].pinLayers[0];\n    }\n\n    // log() << \"cost \" << min_cost << endl;\n\n    function<shared_ptr<gr::GrSteiner>(int, int)> buildTopo = [&](int root_idx, int exit_layer) {\n        RouteNode& rNode = routeNodes[root_idx];\n        shared_ptr<gr::GrSteiner> topo_root = make_shared<gr::GrSteiner>(gr::GrPoint(exit_layer, rNode.x, rNode.y), -1);\n\n        // build layer topo\n        int low_layer = exit_layer;\n        int high_layer = exit_layer;\n\n        for (int child_idx : rNode.childIdxs) {\n            int child_enter_layer = exit_layer;  // root has no exit, thus no exitEnterLayers map, we use exit layer to\n                                                 // indicate its child's enter layer\n            if (rNode.exitEnterLayers.size() > 0) {\n                child_enter_layer = rNode.exitEnterLayers[child_idx][exit_layer];\n            }\n            low_layer = min(low_layer, child_enter_layer);\n            high_layer = max(high_layer, child_enter_layer);\n        }\n\n        for (int pin_layer : rNode.pinLayers) {\n            if (pin_layer != exit_layer) {\n                low_layer = min(low_layer, pin_layer);\n                high_layer = max(high_layer, pin_layer);\n            }\n        }\n\n        unordered_map<int, shared_ptr<gr::GrSteiner>> layer2layerTopo;\n        layer2layerTopo[exit_layer] = topo_root;\n        for (int cur_layer = exit_layer + 1; cur_layer <= high_layer; cur_layer++) {\n            layer2layerTopo[cur_layer] = make_shared<gr::GrSteiner>(gr::GrPoint(cur_layer, rNode.x, rNode.y), -1);\n            gr::GrSteiner::setParent(layer2layerTopo[cur_layer], layer2layerTopo[cur_layer - 1]);\n        }\n        for (int cur_layer = exit_layer - 1; cur_layer >= low_layer; cur_layer--) {\n            layer2layerTopo[cur_layer] = make_shared<gr::GrSteiner>(gr::GrPoint(cur_layer, rNode.x, rNode.y), -1);\n            gr::GrSteiner::setParent(layer2layerTopo[cur_layer], layer2layerTopo[cur_layer + 1]);\n        }\n\n        for (int child_idx : rNode.childIdxs) {  // build branches\n            int child_enter_layer = exit_layer;\n            if (rNode.exitEnterLayers.size() > 0) {\n                child_enter_layer = rNode.exitEnterLayers[child_idx][exit_layer];\n            }\n            auto& enter_edge = rNode.enterEdges[child_idx][child_enter_layer];\n            if (enter_edge.size() == 0) {\n                log() << \"Error: Enter edge missing\" << endl;\n            }\n\n            int child_exit_layer = enter_edge[0].layerIdx;\n            shared_ptr<gr::GrSteiner> child_topo = buildTopo(child_idx, child_exit_layer);\n            for (auto& point : enter_edge) {\n                shared_ptr<gr::GrSteiner> steiner = make_shared<gr::GrSteiner>(point, -1);\n                gr::GrSteiner::setParent(child_topo, steiner);\n                child_topo = steiner;\n            }\n            // if (gr::GrPoint(*child_topo) !=  gr::GrPoint(*topo_root)) {\n            gr::GrSteiner::setParent(child_topo, layer2layerTopo[child_enter_layer]);\n            // } else {\n            //     gr::GrSteiner::setParent(child_topo->children[0], topo_root);\n            // }\n        }\n\n        return topo_root;\n    };\n\n    // dumpTo grNet\n    grNet.gridTopo.emplace_back(buildTopo(rootIdx, root_enter_layer));\n    gr::GrSteiner::removeRedundancy(grNet.gridTopo[0]);\n\n    vector<gr::GrPoint> pin_locs;\n    for (auto& kv : routeNodes) {\n        auto& node = kv.second;\n        for (int pin_layer : node.pinLayers) {\n            // cout << \"(\" << pin_layer << \",\" << node.x << \",\" << node.y << \") \";\n            pin_locs.emplace_back(gr::GrPoint(pin_layer, node.x, node.y));\n        }\n    }\n\n    // debug\n\n    // cout << endl;\n    // log() << endl;\n    // grNet.preOrderVisitGridTopo([&](std::shared_ptr<gr::GrSteiner> topo) {\n    //     if (topo->children.size() == 0) return;\n    //     log() << gr::GrPoint(*topo) << \"->\";\n    //     for(auto& child: topo->children) {\n    //         cout << gr::GrPoint(*child) << \" \";\n    //     }\n    //     cout << endl;\n    // });\n    // log() << \"cost \" << min_cost << endl;\n    // log() << endl << \"+ + + + + + + + + + + + + + + + + + + + + +\" << endl;\n\n    // Check Connectivity and Mark Pins (0: no pin; 1: has pin)\n    if (!gr::GrSteiner::checkConnectivity(grNet.gridTopo[0], pin_locs)) {\n        log() << \"Error: Connectivity check failed\" << endl;\n    }\n}\n\nvoid InitRoute::plan_fluteOnly() {\n    runFlute();\n\n    int s = routeNodes.begin()->first;\n    queue<int> tmp_q;\n    tmp_q.push(s);\n    set<int> vis;\n    while (tmp_q.empty() == false) {\n        int u = tmp_q.front();\n        tmp_q.pop();\n        vis.insert(u);\n        RouteNode& node = routeNodes[u];\n        for (int nIdx : node.toConnect) {\n            if (vis.find(nIdx) != vis.end()) continue;\n            addUsage2D(node, routeNodes[nIdx], 1);  // update the usage\n            tmp_q.push(nIdx);\n        }\n    }\n}\nvoid InitRoute::edge_shift2d(std::map<int, RouteNode>& cur_routeNodes) {\n    if (cur_routeNodes.size() == 1) return;\n    vector<RouteEdge> edgeset;\n    map<pair<int, int>, set<int>> loc_nodes;  // will be used to merge overlapping nodes\n    int s = cur_routeNodes.begin()->first;\n    queue<int> tmp_q;\n    tmp_q.push(s);\n    set<int> vis;\n\n    while (tmp_q.empty() == false) {\n        int u = tmp_q.front();\n        tmp_q.pop();\n        vis.insert(u);\n        RouteNode& node = cur_routeNodes[u];\n        loc_nodes[make_pair(node.x, node.y)].insert(u);\n\n        for (int nIdx : node.toConnect) {\n            if (vis.find(nIdx) != vis.end()) continue;\n            RouteEdge edge;\n            edge.from = nIdx;\n            edge.to = u;\n            edgeset.emplace_back(edge);\n            removeUsage2D(node, cur_routeNodes[nIdx], 1);  // Remove this net\n            tmp_q.push(nIdx);\n        }\n    }\n\n    auto getStraightCost = [&](int dir, int gridline, utils::IntervalT<int> range) {\n        double cost = 0;\n        for (int cp = range.low; cp < range.high; cp++) {\n            cost += grDatabase.getCost2D(dir, gridline, cp);\n        }\n        return cost;\n    };\n\n    std::function<double(int, int, int, int)> getCost =\n        [&](int x1, int y1, int x2, int y2) {  // GR point (x1,y1) -> (x2,y2)\n            double ret = 0;\n            int layer_dir_count = 0;\n            if (x1 == x2 || y1 == y2) {  // straight line\n                int dir = (x1 == x2 ? X : Y);\n                if (dir == X) {\n                    utils::IntervalT<int> Range(min(y1, y2), max(y1, y2));\n                    ret = getStraightCost(X, x1, Range);\n                } else {\n                    utils::IntervalT<int> Range(min(x1, x2), max(x1, x2));\n                    ret = getStraightCost(Y, y1, Range);\n                }\n            } else {  // choose the L with lower cost\n                int x3 = x1;\n                int y3 = y2;\n                int x4 = x2;\n                int y4 = y1;\n                ret = min(getCost(x1, y1, x3, y3) + getCost(x2, y2, x3, y3),\n                          getCost(x1, y1, x4, y4) + getCost(x2, y2, x4, y4));\n            }\n            return ret;\n        };\n\n    auto shiftEdge = [&](bool& shifted) {\n        int find_edge = -1;\n        int dir = -1;\n        bool extendSafeRange = false;\n\n        for (int i = 0; i < edgeset.size(); i++) {\n            auto& edge = edgeset[i];\n            auto& fromNode = cur_routeNodes[edge.from];\n            auto& toNode = cur_routeNodes[edge.to];\n            if (fromNode.pinIdxs.size() == 0 && toNode.pinIdxs.size() == 0 && fromNode.degree() == 3 &&\n                toNode.degree() == 3) {  // two steiner points encountered,require the degree to be 3\n                if (fromNode.x == toNode.x || fromNode.y == toNode.y) {  // vertical or horizontal\n                    dir = (fromNode.x == toNode.x ? X : Y);\n                    vector<int> fromNeighbor;  // the two neighbors of fromNode\n                    vector<int> toNeighbor;    // the two neighbors of toNode\n                    for (auto& nei : fromNode.toConnect) {\n                        if (nei != edge.to) {\n                            fromNeighbor.push_back(nei);\n                        }\n                    }\n                    for (auto& nei : toNode.toConnect) {\n                        if (nei != edge.from) {\n                            toNeighbor.push_back(nei);\n                        }\n                    }\n                    assert(fromNeighbor.size() == 2);\n                    assert(toNeighbor.size() == 2);\n                    if (dir == X) {  // vertical edge\n\n                        if (cur_routeNodes[fromNeighbor[0]].x > cur_routeNodes[fromNeighbor[1]].x) {\n                            swap(fromNeighbor[0], fromNeighbor[1]);\n                        }\n                        if (cur_routeNodes[toNeighbor[0]].x > cur_routeNodes[toNeighbor[1]].x) {\n                            swap(toNeighbor[0], toNeighbor[1]);\n                        }\n\n                        utils::IntervalT<int> r1(cur_routeNodes[fromNeighbor[0]].x, cur_routeNodes[fromNeighbor[1]].x);\n                        utils::IntervalT<int> r2(cur_routeNodes[toNeighbor[0]].x, cur_routeNodes[toNeighbor[1]].x);\n                        utils::IntervalT<int> safeRange = r1.IntersectWith(r2);\n                        if (!safeRange.IsStrictValid()) {\n                            continue;\n                        }\n                        utils::IntervalT<int> yRange(min(fromNode.y, toNode.y), max(fromNode.y, toNode.y));\n\n                        int best_x = -1;\n                        double best_cost = std::numeric_limits<double>::infinity();\n\n                        for (int cur_x = safeRange.low; cur_x <= safeRange.high; cur_x++) {\n                            // try each candidate and choose the one with smallest cost\n                            double cur_cost = getStraightCost(X, cur_x, yRange);\n                            cur_cost += getCost(cur_x,\n                                                fromNode.y,\n                                                cur_routeNodes[fromNeighbor[0]].x,\n                                                cur_routeNodes[fromNeighbor[0]].y) +\n                                        getCost(cur_x,\n                                                fromNode.y,\n                                                cur_routeNodes[fromNeighbor[1]].x,\n                                                cur_routeNodes[fromNeighbor[1]].y);\n                            cur_cost +=\n                                getCost(\n                                    cur_x, toNode.y, cur_routeNodes[toNeighbor[0]].x, cur_routeNodes[toNeighbor[0]].y) +\n                                getCost(\n                                    cur_x, toNode.y, cur_routeNodes[toNeighbor[1]].x, cur_routeNodes[toNeighbor[1]].y);\n                            if (cur_cost < best_cost) {\n                                best_cost = cur_cost;\n                                best_x = cur_x;\n                            }\n                        }\n                        if (best_x != -1 && fromNode.x != best_x) {  // need to move, update the topology and locations\n\n                            loc_nodes[make_pair(fromNode.x, fromNode.y)].erase(fromNode.idx);\n                            loc_nodes[make_pair(toNode.x, toNode.y)].erase(toNode.idx);\n                            fromNode.x = best_x;\n                            toNode.x = best_x;\n                            loc_nodes[make_pair(fromNode.x, fromNode.y)].insert(fromNode.idx);\n                            loc_nodes[make_pair(toNode.x, toNode.y)].insert(toNode.idx);\n                            shifted = true;\n                            break;\n                        } else {  // check next candidate\n                            continue;\n                        }\n                    } else {\n                        if (cur_routeNodes[fromNeighbor[0]].y > cur_routeNodes[fromNeighbor[1]].y) {\n                            swap(fromNeighbor[0], fromNeighbor[1]);\n                        }\n                        if (cur_routeNodes[toNeighbor[0]].y > cur_routeNodes[toNeighbor[1]].y) {\n                            swap(toNeighbor[0], toNeighbor[1]);\n                        }\n                        utils::IntervalT<int> r1(cur_routeNodes[fromNeighbor[0]].y, cur_routeNodes[fromNeighbor[1]].y);\n                        utils::IntervalT<int> r2(cur_routeNodes[toNeighbor[0]].y, cur_routeNodes[toNeighbor[1]].y);\n                        utils::IntervalT<int> safeRange = r1.IntersectWith(r2);\n                        if (!safeRange.IsStrictValid()) {\n                            continue;\n                        }\n                        utils::IntervalT<int> xRange(min(fromNode.x, toNode.x), max(fromNode.x, toNode.x));\n                        int best_y = -1;\n                        double best_cost = std::numeric_limits<double>::infinity();\n\n                        for (int cur_y = safeRange.low; cur_y <= safeRange.high; cur_y++) {\n                            // try each candidate and choose the one with smallest cost\n                            double cur_cost = getStraightCost(Y, cur_y, xRange);\n                            cur_cost += getCost(fromNode.x,\n                                                cur_y,\n                                                cur_routeNodes[fromNeighbor[0]].x,\n                                                cur_routeNodes[fromNeighbor[0]].y) +\n                                        getCost(fromNode.x,\n                                                cur_y,\n                                                cur_routeNodes[fromNeighbor[1]].x,\n                                                cur_routeNodes[fromNeighbor[1]].y);\n                            cur_cost +=\n                                getCost(\n                                    toNode.x, cur_y, cur_routeNodes[toNeighbor[0]].x, cur_routeNodes[toNeighbor[0]].y) +\n                                getCost(\n                                    toNode.x, cur_y, cur_routeNodes[toNeighbor[1]].x, cur_routeNodes[toNeighbor[1]].y);\n                            if (cur_cost < best_cost) {\n                                best_cost = cur_cost;\n                                best_y = cur_y;\n                            }\n                        }\n                        if (best_y != -1 && fromNode.y != best_y) {  // need to move, update the topology and locations\n                            loc_nodes[make_pair(fromNode.x, fromNode.y)].erase(fromNode.idx);\n                            loc_nodes[make_pair(toNode.x, toNode.y)].erase(toNode.idx);\n                            fromNode.y = best_y;\n                            toNode.y = best_y;\n                            loc_nodes[make_pair(fromNode.x, fromNode.y)].insert(fromNode.idx);\n                            loc_nodes[make_pair(toNode.x, toNode.y)].insert(toNode.idx);\n                            shifted = true;\n                            break;\n                        } else {  // check next candidate\n                            continue;\n                        }\n                    }\n                }\n            }\n        }\n    };\n\n    auto mergeNode = [&]() {\n        while (1) {\n            bool found_to_merge = false;\n            pair<int, int> merge_loc;\n            for (auto it = loc_nodes.begin(); it != loc_nodes.end(); it++) {\n                if (it->second.size() > 1) {\n                    found_to_merge = true;\n                    merge_loc = it->first;\n                    break;\n                }\n            }\n            if (found_to_merge) {\n                set<int>& nodeset = loc_nodes[merge_loc];\n                int to_idx = -1;\n                int from_idx = -1;\n                assert(nodeset.size() == 2);  // only possibility: 1 steiner point + (another steiner point/pin point)\n                int two_steiner = -1;\n\n                for (auto idx : nodeset) {\n                    assert(idx != -1);\n                    if (cur_routeNodes[idx].pinIdxs.size() > 0) {\n                        two_steiner = idx;\n                    }\n                }\n                if (two_steiner != -1) {\n                    to_idx = two_steiner;\n                } else {\n                    to_idx = *nodeset.begin();\n                }\n                for (auto idx : nodeset) {\n                    if (idx != to_idx) {\n                        from_idx = idx;\n                        break;\n                    }\n                }\n\n                assert(to_idx != -1);\n                assert(from_idx != -1);\n                nodeset.erase(from_idx);\n\n                auto& fromNode = cur_routeNodes[from_idx];\n                auto& toNode = cur_routeNodes[to_idx];\n                if (toNode.toConnect.find(from_idx) != toNode.toConnect.end()) {  // two nodes are connected\n                    int del_edge = -1;\n                    for (int i = 0; i < edgeset.size(); i++) {\n                        if (edgeset[i].from == from_idx || edgeset[i].from == to_idx) {\n                            if (edgeset[i].to == from_idx || edgeset[i].to == to_idx) {\n                                del_edge = i;\n                                break;\n                            }\n                        }\n                    }\n                    edgeset.erase(edgeset.begin() + del_edge);\n                    toNode.toConnect.erase(from_idx);\n                }\n                for (int j = 0; j < edgeset.size(); j++) {\n                    if (edgeset[j].from == from_idx) {\n                        edgeset[j].from = to_idx;\n                        cur_routeNodes[edgeset[j].to].toConnect.erase(from_idx);\n                        cur_routeNodes[edgeset[j].to].toConnect.insert(to_idx);\n                        toNode.toConnect.insert(edgeset[j].to);\n                    } else if (edgeset[j].to == from_idx) {\n                        edgeset[j].to = to_idx;\n                        cur_routeNodes[edgeset[j].from].toConnect.erase(from_idx);\n                        cur_routeNodes[edgeset[j].from].toConnect.insert(to_idx);\n                        toNode.toConnect.insert(edgeset[j].from);\n                    }\n                }\n\n                cur_routeNodes.erase(from_idx);  // remove node\n                // remove redundant edge\n                set<int> toDelete;\n                for (int i = 0; i < edgeset.size(); i++) {\n                    for (int j = i + 1; j < edgeset.size(); j++) {\n                        if (edgeset[i].from == edgeset[j].from || edgeset[i].from == edgeset[j].to) {\n                            if (edgeset[i].to == edgeset[j].from || edgeset[i].to == edgeset[j].to) toDelete.insert(i);\n                        }\n                    }\n                }\n                for (auto idx : toDelete) {\n                    edgeset.erase(edgeset.begin() + idx);\n                }\n            } else {\n                break;\n            }\n        }\n    };\n    grDatabase.tot_edge += edgeset.size();\n    int while_limit = 10000;  // prevent possible(nearly impossible) infinite loop\n    int tmp_cnt = 0;\n    while (tmp_cnt < while_limit) {\n        bool edgeshift = false;\n        shiftEdge(edgeshift);\n        if (edgeshift == false) break;\n        mergeNode();\n        tmp_cnt += 1;\n    }\n    if (tmp_cnt == while_limit) log() << \"More Shifting is actually needed\" << std::endl;\n    grDatabase.edge_shifted += tmp_cnt;\n\n    s = cur_routeNodes.begin()->first;\n    queue<int> tmp_q_add;\n    tmp_q_add.push(s);\n    vis.clear();\n    while (tmp_q_add.empty() == false) {\n        int u = tmp_q_add.front();\n        tmp_q_add.pop();\n        vis.insert(u);\n        RouteNode& node = cur_routeNodes[u];\n        for (int nIdx : node.toConnect) {\n            if (vis.find(nIdx) != vis.end()) continue;\n            addUsage2D(node, cur_routeNodes[nIdx], 1);  // update the usage\n            tmp_q_add.push(nIdx);\n        }\n    }\n}\n\nvoid InitRoute::getRoutingOrder() {\n    // local net in one gcell\n    if (routeNodes.size() == 1) return;\n    // pick a degree 1 node as root\n    int root = -1;\n    for (auto it = routeNodes.begin(); it != routeNodes.end(); it++) {\n        if (it->second.degree() == 1) {\n            root = it->first;\n            break;\n        }\n    }\n\n    // dfs to decide routing order\n    set<int> visited;\n    function<void(int)> dfs = [&](int nodeIdx) {\n        visited.insert(nodeIdx);\n        RouteNode& node = routeNodes[nodeIdx];\n        for (int nIdx : node.toConnect) {\n            if (visited.find(nIdx) != visited.end()) continue;\n            RouteEdge edge;\n            edge.from = nIdx;\n            edge.to = nodeIdx;\n            routeEdges.emplace_back(edge);\n            routeNodes[edge.to].childIdxs.emplace_back(edge.from);\n            dfs(nIdx);\n        }\n    };\n    if (root != -1) {\n        dfs(root);\n        reverse(routeEdges.begin(), routeEdges.end());\n    } else {\n        log() << \"Error: Can't find a degree one node (2)\" << endl;\n    }\n}\n\nvoid InitRoute::addUsage2D(RouteNode& u, RouteNode& v, double usage) {\n    if (u.x == v.x) {  // straight edge dir = X\n        int gridline = u.x;\n        utils::IntervalT<int> Range(min(u.y, v.y), max(u.y, v.y));\n        for (int cp = Range.low; cp < Range.high; cp++) {\n            grDatabase.useWire2D(X, gridline, cp, usage);\n        }\n    } else if (u.y == v.y) {\n        int gridline = u.y;\n        utils::IntervalT<int> Range(min(u.x, v.x), max(u.x, v.x));\n        for (int cp = Range.low; cp < Range.high; cp++) {\n            grDatabase.useWire2D(Y, gridline, cp, usage);\n        }\n    } else {  // diagnal edge\n        RouteNode new1(u.x, v.y), new2(v.x, u.y);\n        addUsage2D(new1, u, usage / 2);\n        addUsage2D(new1, v, usage / 2);\n        addUsage2D(new2, u, usage / 2);\n        addUsage2D(new2, v, usage / 2);\n    }\n}\n\nvoid InitRoute::removeUsage2D(RouteNode& u, RouteNode& v, double usage) {\n    if (u.x == v.x) {  // straight edge dir = Y\n        int gridline = u.x;\n        utils::IntervalT<int> Range(min(u.y, v.y), max(u.y, v.y));\n        for (int cp = Range.low; cp < Range.high; cp++) {\n            grDatabase.removeUsage2D(X, gridline, cp, usage);\n        }\n    } else if (u.y == v.y) {\n        int gridline = u.y;\n        utils::IntervalT<int> Range(min(u.x, v.x), max(u.x, v.x));\n        for (int cp = Range.low; cp < Range.high; cp++) {\n            grDatabase.removeUsage2D(Y, gridline, cp, usage);\n        }\n    } else {  // diagnal edge\n        RouteNode new1(u.x, v.y), new2(v.x, u.y);\n        removeUsage2D(new1, u, usage / 2);\n        removeUsage2D(new1, v, usage / 2);\n        removeUsage2D(new2, u, usage / 2);\n        removeUsage2D(new2, v, usage / 2);\n    }\n}\n\nstd::map<int, RouteNode>& InitRoute::getRouteNodes() { return routeNodes; }\n"
  },
  {
    "path": "src/single_net/InitRoute.h",
    "content": "#pragma once\n\n#include \"global.h\"\n#include \"flute/flute.h\"\n#include \"gr_db/GrDatabase.h\"\n#include \"GenGuide.h\"\n#include <map>\n\nextern \"C\" {\nTree flute(int d, DTYPE x[], DTYPE y[], int acc);\n}\n\nclass RouteNode {\npublic:\n    int x;\n    int y;\n    int idx;\n    vector<int> pinLayers;    // pins' layers within the node\n    vector<int> pinIdxs;      // pins' indexes within the node\n    std::set<int> toConnect;  // nodes connecting to this one\n    vector<int> childIdxs;\n\n    // PatternRoute\n    vector<db::CostT> exitCosts;  // cost exiting the node from different layers\n    // cost of entering the node on different layers from different children\n    std::unordered_map<int, vector<db::CostT>> enterCosts;  // (childIdx->layerIdx->cost)\n    // topo of entering the node on different layers from different children\n    std::unordered_map<int, vector<vector<gr::GrPoint>>> enterEdges;  // (childIdx->layerIdx->edge)\n    // which layer should a child edge enter if exiting from a specific layer\n    std::unordered_map<int, vector<int>> exitEnterLayers;  // (childIdx->exit layer-> enter layer)\n\n    int degree() { return toConnect.size(); }\n\n    std::string str() {  // return string description\n        return std::to_string(idx) + \"(\" + std::to_string(x) + \", \" + std::to_string(y) + \")\" +\n               (pinIdxs.size() == 0 ? \"Steiner\" : \" \");\n    }\n\n    RouteNode() : x(-1), y(-1) {}\n    RouteNode(int nx, int ny) : x(nx), y(ny) {}\n    RouteNode(std::tuple<int, int> loc) : x(std::get<0>(loc)), y(std::get<1>(loc)) {}\n};\n\nstruct RouteEdge {\n    int from;\n    int to;\n};\n\nclass InitRoute {\npublic:\n    InitRoute(gr::GrNet &grNetData) : grNet(grNetData), guideGen(grNet), status(db::RouteStatus::SUCC_NORMAL) {\n        grNet.gridTopo.clear();\n    }\n\n    void patternRoute();  // pattern routing\n    void buildTopo();\n\n    void plan_fluteOnly();\n    void edge_shift2d(std::map<int, RouteNode> &routeNodes);\n    void getRoutingOrder();\n    void addUsage2D(RouteNode &u, RouteNode &v, double usage = 1);\n    void removeUsage2D(RouteNode &u, RouteNode &v, double usage = 1);\n\n    std::map<int, RouteNode> &getRouteNodes();\n\n    db::RouteStatus status;\n    gr::GrNet &grNet;\n\nprivate:\n    GuideGenerator guideGen;\n    std::map<int, RouteNode> routeNodes;\n    vector<RouteEdge> routeEdges;\n\n    db::CostT getBufferedWireCost(gr::GrEdge edge);\n    std::unordered_map<gr::GrEdge, db::CostT> wireCostBuffer;\n\n    void LShape(const RouteEdge &edge);\n\n    void runFlute();\n};\n"
  },
  {
    "path": "src/single_net/MazeRoute.cpp",
    "content": "#include \"MazeRoute.h\"\n\nostream &operator<<(ostream &os, const Solution &sol) {\n    os << \"cost=\" << sol.cost << \", vertex=\" << sol.vertex << \", prev=\" << (sol.prev ? sol.prev->vertex : -1);\n    return os;\n}\n\nvoid MazeRoute::constructGridGraph(const vector<gr::GrBoxOnLayer> &guides) {\n    GuideGridGraphBuilder graphBuilder(grNet, graph, guides);\n    mergedPinAccessBoxes = grNet.getMergedPinAccessBoxes(\n        [](const gr::GrPoint &point) { return gr::PointOnLayer(point.layerIdx, point[X], point[Y]); });\n    graphBuilder.run(mergedPinAccessBoxes);\n}\n\nvoid MazeRoute::constructGridGraph(const CongestionMap &congMap) {\n    CoarseGridGraphBuilder graphBuilder(grNet, graph, congMap);\n    mergedPinAccessBoxes =\n        grNet.getMergedPinAccessBoxes([&](const gr::GrPoint &point) { return graphBuilder.grPointToPoint(point); });\n    graphBuilder.run(mergedPinAccessBoxes);\n}\n\ndb::RouteStatus MazeRoute::run() {\n    vertexCosts.assign(graph.getNodeNum(), std::numeric_limits<db::CostT>::max());\n    pinSols.assign(mergedPinAccessBoxes.size(), nullptr);\n    const int startPin = 0;\n\n    auto status = route(startPin);\n    if (!db::isSucc(status)) {\n        return status;\n    }\n\n    getResult();\n\n    return status;\n}\n\ndb::RouteStatus MazeRoute::route(int startPin) {\n    // define std::priority_queue\n    auto solComp = [](const std::shared_ptr<Solution> &lhs, const std::shared_ptr<Solution> &rhs) {\n        return rhs->cost < lhs->cost;\n    };\n    std::priority_queue<std::shared_ptr<Solution>, vector<std::shared_ptr<Solution>>, decltype(solComp)> solQueue(\n        solComp);\n\n    auto updateSol = [&](const std::shared_ptr<Solution> &sol) {\n        solQueue.push(sol);\n        if (sol->cost < vertexCosts[sol->vertex]) vertexCosts[sol->vertex] = sol->cost;\n    };\n\n    // init from startPin\n    for (auto vertex : graph.getVertices(startPin)) updateSol(std::make_shared<Solution>(0, vertex, nullptr));\n\n    std::unordered_set<int> visitedPin = {startPin};\n    int nPinToConnect = mergedPinAccessBoxes.size() - 1;\n\n    while (nPinToConnect != 0) {\n        std::shared_ptr<Solution> dstVertex;\n        int dstPinIdx = -1;\n\n        // Dijkstra\n        while (!solQueue.empty()) {\n            auto newSol = solQueue.top();\n            int u = newSol->vertex;\n            solQueue.pop();\n\n            // reach a pin?\n            dstPinIdx = graph.getPinIdx(u);\n            if (dstPinIdx != -1 && visitedPin.find(dstPinIdx) == visitedPin.end()) {\n                dstVertex = newSol;\n                break;\n            }\n\n            // pruning by upper bound\n            if (vertexCosts[u] < newSol->cost) continue;\n\n            const db::MetalLayer &uLayer = database.getLayer(graph.getPoint(u).layerIdx);\n\n            for (auto direction : directions) {\n                if (!graph.hasEdge(u, direction) ||\n                    (newSol->prev && graph.getEdgeEndPoint(u, direction) == newSol->prev->vertex))\n                    continue;\n\n                // from u to v\n                int v = graph.getEdgeEndPoint(u, direction);\n\n                // edge cost\n                db::CostT w = graph.getEdgeCost(u, direction);\n\n                db::CostT newCost = w + newSol->cost;\n\n                if (newCost < vertexCosts[v]) updateSol(std::make_shared<Solution>(newCost, v, newSol));\n            }\n        }\n\n        if (!dstVertex) {\n            printWarnMsg(db::RouteStatus::FAIL_DISCONNECTED_GRID_GRAPH, grNet.dbNet);\n            printlog(visitedPin, nPinToConnect, mergedPinAccessBoxes.size(), mergedPinAccessBoxes);\n            printlog(graph.checkConn());\n            graph.writeDebugFile(grNet.getName() + \".graph\");\n            getchar();\n            return db::RouteStatus::FAIL_DISCONNECTED_GRID_GRAPH;\n        }\n\n        // update pinSols\n        pinSols[dstPinIdx] = dstVertex;\n\n        // mark the path to be zero\n        auto tmp = dstVertex;\n        while (tmp && tmp->cost != 0) {\n            updateSol(std::make_shared<Solution>(0, tmp->vertex, tmp->prev));\n            tmp = tmp->prev;\n        }\n\n        // mark all the accessbox of the pin to be almost zero\n        for (auto vertex : graph.getVertices(dstPinIdx)) {\n            if (vertex == dstVertex->vertex) continue;\n            updateSol(std::make_shared<Solution>(0, vertex, nullptr));\n        }\n\n        visitedPin.insert(dstPinIdx);\n        nPinToConnect--;\n    }\n\n    return db::RouteStatus::SUCC_NORMAL;\n}\n\nvoid MazeRoute::getResult() {\n    grNet.gridTopo.clear();\n\n    std::unordered_map<int, std::shared_ptr<gr::GrSteiner>> visited;\n\n    // back track from pin to source\n    for (unsigned p = 0; p < mergedPinAccessBoxes.size(); p++) {\n        std::unordered_map<int, std::shared_ptr<gr::GrSteiner>> curVisited;\n        auto cur = pinSols[p];\n        std::shared_ptr<gr::GrSteiner> prevS;\n        while (cur) {\n            auto it = visited.find(cur->vertex);\n            if (it != visited.end()) {\n                // graft to an existing node\n                if (prevS) {\n                    gr::GrSteiner::setParent(prevS, it->second);\n                }\n                break;\n            } else {\n                // get curS\n                auto point = graph.getPoint(cur->vertex);\n                auto curS = std::make_shared<gr::GrSteiner>(gr::GrPoint(point.layerIdx, point[X], point[Y]),\n                                                            graph.getPinIdx(cur->vertex));\n                if (prevS) {\n                    gr::GrSteiner::setParent(prevS, curS);\n                }\n                if (curVisited.find(cur->vertex) != curVisited.end()) {\n                    printlog(\"Warning: self loop found in a path for net\", grNet.getName(), \"for pin\", p);\n                }\n                curVisited.emplace(cur->vertex, curS);\n                // store tree root\n                if (!(cur->prev)) {\n                    grNet.gridTopo.push_back(curS);\n                    break;\n                }\n                // prep for the next loop\n                prevS = curS;\n                cur = cur->prev;\n            }\n        }\n        for (const auto &v : curVisited) visited.insert(v);\n    }\n\n    // remove redundant Steiner nodes\n    for (auto &tree : grNet.gridTopo) {\n        gr::GrSteiner::mergeNodes(tree);\n    }\n}\n"
  },
  {
    "path": "src/single_net/MazeRoute.h",
    "content": "#pragma once\n\n#include \"GridGraph.h\"\n#include \"multi_net/CongestionMap.h\"\n\nclass Solution {\npublic:\n    db::CostT cost;\n    int vertex;\n    std::shared_ptr<Solution> prev;\n\n    Solution(db::CostT c, int v, const std::shared_ptr<Solution> &p) : cost(c), vertex(v), prev(p) {}\n\n    friend ostream &operator<<(ostream &os, const Solution &sol);\n};\n\nclass MazeRoute {\npublic:\n    MazeRoute(gr::GrNet &grNetData) : grNet(grNetData) {}\n\n    void constructGridGraph(const vector<gr::GrBoxOnLayer> &guides);\n    void constructGridGraph(const CongestionMap& congMap);\n    db::RouteStatus run();\n\nprivate:\n    gr::GrNet &grNet;\n    GridGraph graph;\n\n    vector<db::CostT> vertexCosts;              // min cost upper bound for each vertex\n    vector<std::shared_ptr<Solution>> pinSols;  // best solution for each pin\n    vector<vector<gr::PointOnLayer>> mergedPinAccessBoxes;\n\n    db::RouteStatus route(int startPin);\n    void getResult();\n};\n"
  },
  {
    "path": "src/single_net/SingleNetRouter.cpp",
    "content": "#include \"SingleNetRouter.h\"\n#include \"InitRoute.h\"\n#include \"MazeRoute.h\"\n\nSingleNetRouter::SingleNetRouter(gr::GrNet& grDatabaseNet)\n    : grNet(grDatabaseNet), guideGen(grNet), status(db::RouteStatus::SUCC_NORMAL) {\n    grDatabase.removeNet(grNet);\n    grNet.gridTopo.clear();\n}\n\nvoid SingleNetRouter::finish() {\n    guideGen.genTopoGuides();\n    grDatabase.useNet(grNet);\n}\n\nvoid SingleNetRouter::mazeRoute() {\n    if (!grNet.needToRoute()) {\n        status = db::RouteStatus::SUCC_ONE_PIN;\n    } else {\n        MazeRoute mazeRouter(grNet);\n        mazeRouter.constructGridGraph(guides);\n        status = mazeRouter.run();\n    }\n\n    db::routeStat.increment(db::RouteStage::MAZE, status);\n}\n\nvoid SingleNetRouter::initRoutePattern(InitRoute& initRouter) {\n    if (!grNet.needToRoute()) {\n        status = db::RouteStatus::SUCC_ONE_PIN;\n    } else {\n        initRouter.patternRoute();\n        initRouter.buildTopo();\n        status = db::RouteStatus::SUCC_NORMAL;\n    }\n    db::routeStat.increment(db::RouteStage::INIT, status);\n}\n\nvoid SingleNetRouter::planMazeRoute(const CongestionMap& congMap) {\n    // run mazeroute on coarse grid\n    const int cellWidth = congMap.getCellWidth();\n    const int cellHeight = congMap.getCellHeight();\n\n    gr::GrNet tmpNet = grNet;\n    MazeRoute mazeRouter(tmpNet);\n    mazeRouter.constructGridGraph(congMap);\n    status = mazeRouter.run();\n\n    // generate guides\n    auto getLower = [&](int coor, Dimension dir) {\n        if (dir == X)\n            return coor * cellWidth;\n        else\n            return coor * cellHeight;\n    };\n    auto getUpper = [&](int coor, Dimension dir) {\n        if (dir == X)\n            return min((coor + 1) * cellWidth, grDatabase.getNumGrPoint(X)) - 1;\n        else\n            return min((coor + 1) * cellHeight, grDatabase.getNumGrPoint(Y)) - 1;\n    };\n\n    guides.clear();\n    tmpNet.postOrderVisitGridTopo([&](std::shared_ptr<gr::GrSteiner> node) {\n        auto parent = node;\n        for (auto child : parent->children) {\n            // if (tmpNet.getName() == \"net6700\") printlog(*parent, *child);\n            if (parent->layerIdx == child->layerIdx) {\n                std::shared_ptr<gr::GrSteiner> lower, upper;\n                if ((*parent)[X] < (*child)[X] || (*parent)[Y] < (*child)[Y]) {\n                    lower = parent;\n                    upper = child;\n                } else {\n                    lower = child;\n                    upper = parent;\n                }\n                guides.emplace_back(lower->layerIdx,\n                                    utils::IntervalT<int>(getLower((*lower)[X], X), getUpper((*upper)[X], X)),\n                                    utils::IntervalT<int>(getLower((*lower)[Y], Y), getUpper((*upper)[Y], Y)));\n            } else {\n                guides.emplace_back(parent->layerIdx,\n                                    utils::IntervalT<int>(getLower((*parent)[X], X), getUpper((*parent)[X], X)),\n                                    utils::IntervalT<int>(getLower((*parent)[Y], Y), getUpper((*parent)[Y], Y)));\n                guides.emplace_back(child->layerIdx,\n                                    utils::IntervalT<int>(getLower((*child)[X], X), getUpper((*child)[X], X)),\n                                    utils::IntervalT<int>(getLower((*child)[Y], Y), getUpper((*child)[Y], Y)));\n            }\n        }\n    });\n\n    // maintain connectivity\n    auto mergedPinAccessBoxes = grNet.getMergedPinAccessBoxes([&](const gr::GrPoint& point) {\n        return gr::PointOnLayer(point.layerIdx, point[X] / cellWidth, point[Y] / cellHeight);\n    });\n    const int neighLayers = 2;\n    for (auto& points : mergedPinAccessBoxes) {\n        for (auto& point : points) {\n            for (int l = point.layerIdx - neighLayers; l <= point.layerIdx + neighLayers; l++) {\n                if (l < database.getLayerNum() && l >= 0)\n                    guides.emplace_back(l,\n                                        utils::IntervalT<int>(getLower(point[X], X), getUpper(point[X], X)),\n                                        utils::IntervalT<int>(getLower(point[Y], Y), getUpper(point[Y], Y)));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/single_net/SingleNetRouter.h",
    "content": "#pragma once\n#include \"db/Database.h\"\n#include \"gr_db/GrDatabase.h\"\n#include \"multi_net/CongestionMap.h\"\n#include \"GenGuide.h\"\n\nclass InitRoute;\n\nclass SingleNetRouter {\npublic:\n    gr::GrNet& grNet;\n\n    db::RouteStatus status;\n\n    SingleNetRouter(gr::GrNet& grNet);\n\n    void planMazeRoute(const CongestionMap& congMap);\n    void mazeRoute();\n\n    void initRoutePattern(InitRoute& initRouter);\n\n    void finish();\n\n    vector<gr::GrBoxOnLayer> guides;\n\nprivate:\n    GuideGenerator guideGen;\n};\n"
  },
  {
    "path": "src/utils/enum.h",
    "content": "// This file is part of Better Enums, released under the BSD 2-clause license.\n// See doc/LICENSE for details, or visit http://github.com/aantron/better-enums.\n\n#pragma once\n\n#ifndef BETTER_ENUMS_ENUM_H\n#define BETTER_ENUMS_ENUM_H\n\n\n\n#include <cstddef>\n#include <cstring>\n#include <iosfwd>\n#include <stdexcept>\n\n\n\n// Feature detection.\n\n#ifdef __GNUC__\n#   ifdef __clang__\n#       if __has_feature(cxx_constexpr)\n#           define BETTER_ENUMS_HAVE_CONSTEXPR\n#       endif\n#       if !defined(__EXCEPTIONS) || !__has_feature(cxx_exceptions)\n#           define BETTER_ENUMS_NO_EXCEPTIONS\n#       endif\n#   else\n#       if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L\n#           if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))\n#               define BETTER_ENUMS_HAVE_CONSTEXPR\n#           endif\n#       endif\n#       ifndef __EXCEPTIONS\n#           define BETTER_ENUMS_NO_EXCEPTIONS\n#       endif\n#   endif\n#endif\n\n#ifdef _MSC_VER\n#   if _MSC_VER >= 1911\n#       define BETTER_ENUMS_HAVE_CONSTEXPR\n#   endif\n#   ifdef __clang__\n#       if __has_feature(cxx_constexpr)\n#           define BETTER_ENUMS_HAVE_CONSTEXPR\n#       endif\n#   endif\n#   ifndef _CPPUNWIND\n#       define BETTER_ENUMS_NO_EXCEPTIONS\n#   endif\n#   if _MSC_VER < 1600\n#       define BETTER_ENUMS_VC2008_WORKAROUNDS\n#   endif\n#endif\n\n#ifdef BETTER_ENUMS_CONSTEXPR\n#   define BETTER_ENUMS_HAVE_CONSTEXPR\n#endif\n\n#ifdef BETTER_ENUMS_NO_CONSTEXPR\n#   ifdef BETTER_ENUMS_HAVE_CONSTEXPR\n#       undef BETTER_ENUMS_HAVE_CONSTEXPR\n#   endif\n#endif\n\n// GCC (and maybe clang) can be made to warn about using 0 or NULL when nullptr\n// is available, so Better Enums tries to use nullptr. This passage uses\n// availability of constexpr as a proxy for availability of nullptr, i.e. it\n// assumes that nullptr is available when compiling on the right versions of gcc\n// and clang with the right -std flag. This is actually slightly wrong, because\n// nullptr is also available in Visual C++, but constexpr isn't. This\n// imprecision doesn't matter, however, because VC++ doesn't have the warnings\n// that make using nullptr necessary.\n#ifdef BETTER_ENUMS_HAVE_CONSTEXPR\n#   define BETTER_ENUMS_CONSTEXPR_     constexpr\n#   define BETTER_ENUMS_NULLPTR        nullptr\n#else\n#   define BETTER_ENUMS_CONSTEXPR_\n#   define BETTER_ENUMS_NULLPTR        NULL\n#endif\n\n#ifndef BETTER_ENUMS_NO_EXCEPTIONS\n#   define BETTER_ENUMS_IF_EXCEPTIONS(x) x\n#else\n#   define BETTER_ENUMS_IF_EXCEPTIONS(x)\n#endif\n\n#ifdef __GNUC__\n#   define BETTER_ENUMS_UNUSED __attribute__((__unused__))\n#else\n#   define BETTER_ENUMS_UNUSED\n#endif\n\n\n\n// Higher-order preprocessor macros.\n\n#ifdef BETTER_ENUMS_MACRO_FILE\n#   include BETTER_ENUMS_MACRO_FILE\n#else\n\n#define BETTER_ENUMS_PP_MAP(macro, data, ...) \\\n    BETTER_ENUMS_ID( \\\n        BETTER_ENUMS_APPLY( \\\n            BETTER_ENUMS_PP_MAP_VAR_COUNT, \\\n            BETTER_ENUMS_PP_COUNT(__VA_ARGS__)) \\\n        (macro, data, __VA_ARGS__))\n\n#define BETTER_ENUMS_PP_MAP_VAR_COUNT(count) BETTER_ENUMS_M ## count\n\n#define BETTER_ENUMS_APPLY(macro, ...) BETTER_ENUMS_ID(macro(__VA_ARGS__))\n\n#define BETTER_ENUMS_ID(x) x\n\n#define BETTER_ENUMS_M1(m, d, x) m(d,0,x)\n#define BETTER_ENUMS_M2(m,d,x,...) m(d,1,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M1(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M3(m,d,x,...) m(d,2,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M2(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M4(m,d,x,...) m(d,3,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M3(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M5(m,d,x,...) m(d,4,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M4(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M6(m,d,x,...) m(d,5,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M5(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M7(m,d,x,...) m(d,6,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M6(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M8(m,d,x,...) m(d,7,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M7(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M9(m,d,x,...) m(d,8,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M8(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M10(m,d,x,...) m(d,9,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M9(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M11(m,d,x,...) m(d,10,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M10(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M12(m,d,x,...) m(d,11,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M11(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M13(m,d,x,...) m(d,12,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M12(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M14(m,d,x,...) m(d,13,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M13(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M15(m,d,x,...) m(d,14,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M14(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M16(m,d,x,...) m(d,15,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M15(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M17(m,d,x,...) m(d,16,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M16(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M18(m,d,x,...) m(d,17,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M17(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M19(m,d,x,...) m(d,18,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M18(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M20(m,d,x,...) m(d,19,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M19(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M21(m,d,x,...) m(d,20,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M20(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M22(m,d,x,...) m(d,21,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M21(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M23(m,d,x,...) m(d,22,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M22(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M24(m,d,x,...) m(d,23,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M23(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M25(m,d,x,...) m(d,24,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M24(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M26(m,d,x,...) m(d,25,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M25(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M27(m,d,x,...) m(d,26,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M26(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M28(m,d,x,...) m(d,27,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M27(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M29(m,d,x,...) m(d,28,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M28(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M30(m,d,x,...) m(d,29,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M29(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M31(m,d,x,...) m(d,30,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M30(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M32(m,d,x,...) m(d,31,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M31(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M33(m,d,x,...) m(d,32,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M32(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M34(m,d,x,...) m(d,33,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M33(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M35(m,d,x,...) m(d,34,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M34(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M36(m,d,x,...) m(d,35,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M35(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M37(m,d,x,...) m(d,36,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M36(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M38(m,d,x,...) m(d,37,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M37(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M39(m,d,x,...) m(d,38,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M38(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M40(m,d,x,...) m(d,39,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M39(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M41(m,d,x,...) m(d,40,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M40(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M42(m,d,x,...) m(d,41,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M41(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M43(m,d,x,...) m(d,42,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M42(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M44(m,d,x,...) m(d,43,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M43(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M45(m,d,x,...) m(d,44,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M44(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M46(m,d,x,...) m(d,45,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M45(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M47(m,d,x,...) m(d,46,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M46(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M48(m,d,x,...) m(d,47,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M47(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M49(m,d,x,...) m(d,48,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M48(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M50(m,d,x,...) m(d,49,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M49(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M51(m,d,x,...) m(d,50,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M50(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M52(m,d,x,...) m(d,51,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M51(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M53(m,d,x,...) m(d,52,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M52(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M54(m,d,x,...) m(d,53,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M53(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M55(m,d,x,...) m(d,54,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M54(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M56(m,d,x,...) m(d,55,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M55(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M57(m,d,x,...) m(d,56,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M56(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M58(m,d,x,...) m(d,57,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M57(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M59(m,d,x,...) m(d,58,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M58(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M60(m,d,x,...) m(d,59,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M59(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M61(m,d,x,...) m(d,60,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M60(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M62(m,d,x,...) m(d,61,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M61(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M63(m,d,x,...) m(d,62,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M62(m,d,__VA_ARGS__))\n#define BETTER_ENUMS_M64(m,d,x,...) m(d,63,x) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_M63(m,d,__VA_ARGS__))\n\n#define BETTER_ENUMS_PP_COUNT_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10,    \\\n    _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \\\n    _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \\\n    _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, \\\n    _56, _57, _58, _59, _60, _61, _62, _63, _64, count, ...) count\n\n#define BETTER_ENUMS_PP_COUNT(...) \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60,\\\n        59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42,\\\n        41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24,\\\n        23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, \\\n        4, 3, 2, 1))\n\n#define BETTER_ENUMS_ITERATE(X, f, l) X(f, l, 0) X(f, l, 1) X(f, l, 2)         \\\n    X(f, l, 3) X(f, l, 4) X(f, l, 5) X(f, l, 6) X(f, l, 7) X(f, l, 8)          \\\n    X(f, l, 9) X(f, l, 10) X(f, l, 11) X(f, l, 12) X(f, l, 13) X(f, l, 14)     \\\n    X(f, l, 15) X(f, l, 16) X(f, l, 17) X(f, l, 18) X(f, l, 19) X(f, l, 20)    \\\n    X(f, l, 21) X(f, l, 22) X(f, l, 23)\n\n#endif // #ifdef BETTER_ENUMS_MACRO_FILE else case\n\n\n\nnamespace better_enums {\n\n\n// Optional type.\n\ntemplate <typename T>\nBETTER_ENUMS_CONSTEXPR_ inline T _default()\n{\n    return static_cast<typename T::_enumerated>(0);\n}\n\ntemplate <>\nBETTER_ENUMS_CONSTEXPR_ inline const char* _default<const char*>()\n{\n    return BETTER_ENUMS_NULLPTR;\n}\n\ntemplate <>\nBETTER_ENUMS_CONSTEXPR_ inline std::size_t _default<std::size_t>()\n{\n    return 0;\n}\n\ntemplate <typename T>\nstruct optional {\n    BETTER_ENUMS_CONSTEXPR_ optional() :\n        _valid(false), _value(_default<T>()) { }\n\n    BETTER_ENUMS_CONSTEXPR_ optional(T v) : _valid(true), _value(v) { }\n\n    BETTER_ENUMS_CONSTEXPR_ const T& operator *() const { return _value; }\n    BETTER_ENUMS_CONSTEXPR_ const T* operator ->() const { return &_value; }\n\n    BETTER_ENUMS_CONSTEXPR_ operator bool() const { return _valid; }\n\n    BETTER_ENUMS_CONSTEXPR_ const T& value() const { return _value; }\n\n  private:\n    bool    _valid;\n    T       _value;\n};\n\ntemplate <typename CastTo, typename Element>\nBETTER_ENUMS_CONSTEXPR_ static optional<CastTo>\n_map_index(const Element *array, optional<std::size_t> index)\n{\n    return index ? static_cast<CastTo>(array[*index]) : optional<CastTo>();\n}\n\n#ifdef BETTER_ENUMS_VC2008_WORKAROUNDS\n\n#define BETTER_ENUMS_OR_THROW                                                  \\\n    if (!maybe)                                                                \\\n        throw std::runtime_error(message);                                     \\\n                                                                               \\\n    return *maybe;\n\n#else\n\n#define BETTER_ENUMS_OR_THROW                                                  \\\n    return maybe ? *maybe : throw std::runtime_error(message);\n\n#endif\n\nBETTER_ENUMS_IF_EXCEPTIONS(\ntemplate <typename T>\nBETTER_ENUMS_CONSTEXPR_ static T _or_throw(optional<T> maybe,\n                                           const char *message)\n{\n    BETTER_ENUMS_OR_THROW\n}\n)\n\ntemplate <typename T>\nBETTER_ENUMS_CONSTEXPR_ static T* _or_null(optional<T*> maybe)\n{\n    return maybe ? *maybe : BETTER_ENUMS_NULLPTR;\n}\n\n\n\n// Functional sequencing. This is essentially a comma operator wrapped in a\n// constexpr function. g++ 4.7 doesn't \"accept\" integral constants in the second\n// position for the comma operator, and emits an external symbol, which then\n// causes a linking error.\n\ntemplate <typename T, typename U>\nBETTER_ENUMS_CONSTEXPR_ U\ncontinue_with(T, U value) { return value; }\n\n\n\n// Values array declaration helper.\n\ntemplate <typename EnumType>\nstruct _eat_assign {\n    explicit BETTER_ENUMS_CONSTEXPR_ _eat_assign(EnumType value) : _value(value)\n        { }\n\n    template <typename Any>\n    BETTER_ENUMS_CONSTEXPR_ const _eat_assign&\n    operator =(Any) const { return *this; }\n\n    BETTER_ENUMS_CONSTEXPR_ operator EnumType () const { return _value; }\n\n  private:\n    EnumType    _value;\n};\n\n\n\n// Iterables.\n\ntemplate <typename Element>\nstruct _Iterable {\n    typedef const Element*  iterator;\n\n    BETTER_ENUMS_CONSTEXPR_ iterator begin() const { return iterator(_array); }\n    BETTER_ENUMS_CONSTEXPR_ iterator end() const\n        { return iterator(_array + _size); }\n    BETTER_ENUMS_CONSTEXPR_ std::size_t size() const { return _size; }\n    BETTER_ENUMS_CONSTEXPR_ const Element& operator [](std::size_t index) const\n        { return _array[index]; }\n\n    BETTER_ENUMS_CONSTEXPR_ _Iterable(const Element *array, std::size_t s) :\n        _array(array), _size(s) { }\n\n  private:\n    const Element * const   _array;\n    const std::size_t       _size;\n};\n\n\n\n// String routines.\n\nBETTER_ENUMS_CONSTEXPR_ static const char       *_name_enders = \"= \\t\\n\";\n\nBETTER_ENUMS_CONSTEXPR_ inline bool _ends_name(char c, std::size_t index = 0)\n{\n    return\n        c == _name_enders[index] ? true  :\n        _name_enders[index] == '\\0' ? false :\n        _ends_name(c, index + 1);\n}\n\nBETTER_ENUMS_CONSTEXPR_ inline bool _has_initializer(const char *s,\n                                                     std::size_t index = 0)\n{\n    return\n        s[index] == '\\0' ? false :\n        s[index] == '=' ? true :\n        _has_initializer(s, index + 1);\n}\n\nBETTER_ENUMS_CONSTEXPR_ inline std::size_t\n_constant_length(const char *s, std::size_t index = 0)\n{\n    return _ends_name(s[index]) ? index : _constant_length(s, index + 1);\n}\n\nBETTER_ENUMS_CONSTEXPR_ inline char\n_select(const char *from, std::size_t from_length, std::size_t index)\n{\n    return index >= from_length ? '\\0' : from[index];\n}\n\nBETTER_ENUMS_CONSTEXPR_ inline char _to_lower_ascii(char c)\n{\n    return c >= 0x41 && c <= 0x5A ? static_cast<char>(c + 0x20) : c;\n}\n\nBETTER_ENUMS_CONSTEXPR_ inline bool _names_match(const char *stringizedName,\n                                                 const char *referenceName,\n                                                 std::size_t index = 0)\n{\n    return\n        _ends_name(stringizedName[index]) ? referenceName[index] == '\\0' :\n        referenceName[index] == '\\0' ? false :\n        stringizedName[index] != referenceName[index] ? false :\n        _names_match(stringizedName, referenceName, index + 1);\n}\n\nBETTER_ENUMS_CONSTEXPR_ inline bool\n_names_match_nocase(const char *stringizedName, const char *referenceName,\n                    std::size_t index = 0)\n{\n    return\n        _ends_name(stringizedName[index]) ? referenceName[index] == '\\0' :\n        referenceName[index] == '\\0' ? false :\n        _to_lower_ascii(stringizedName[index]) !=\n            _to_lower_ascii(referenceName[index]) ? false :\n        _names_match_nocase(stringizedName, referenceName, index + 1);\n}\n\ninline void _trim_names(const char * const *raw_names,\n                        const char **trimmed_names,\n                        char *storage, std::size_t count)\n{\n    std::size_t     offset = 0;\n\n    for (std::size_t index = 0; index < count; ++index) {\n        trimmed_names[index] = storage + offset;\n\n        std::size_t trimmed_length =\n            std::strcspn(raw_names[index], _name_enders);\n        storage[offset + trimmed_length] = '\\0';\n\n        std::size_t raw_length = std::strlen(raw_names[index]);\n        offset += raw_length + 1;\n    }\n}\n\n\n\n// Eager initialization.\ntemplate <typename Enum>\nstruct _initialize_at_program_start {\n    _initialize_at_program_start() { Enum::initialize(); }\n};\n\n} // namespace better_enums\n\n\n\n// Array generation macros.\n\n#define BETTER_ENUMS_EAT_ASSIGN_SINGLE(EnumType, index, expression)            \\\n    ((::better_enums::_eat_assign<EnumType>)EnumType::expression),\n\n#define BETTER_ENUMS_EAT_ASSIGN(EnumType, ...)                                 \\\n    BETTER_ENUMS_ID(                                                           \\\n        BETTER_ENUMS_PP_MAP(                                                   \\\n            BETTER_ENUMS_EAT_ASSIGN_SINGLE, EnumType, __VA_ARGS__))\n\n\n\n#ifdef BETTER_ENUMS_HAVE_CONSTEXPR\n\n\n\n#define BETTER_ENUMS_SELECT_SINGLE_CHARACTER(from, from_length, index)         \\\n    ::better_enums::_select(from, from_length, index),\n\n#define BETTER_ENUMS_SELECT_CHARACTERS(from, from_length)                      \\\n    BETTER_ENUMS_ITERATE(                                                      \\\n        BETTER_ENUMS_SELECT_SINGLE_CHARACTER, from, from_length)\n\n\n\n#define BETTER_ENUMS_TRIM_SINGLE_STRING(ignored, index, expression)            \\\nconstexpr std::size_t   _length_ ## index =                                    \\\n    ::better_enums::_constant_length(#expression);                             \\\nconstexpr const char    _trimmed_ ## index [] =                                \\\n    { BETTER_ENUMS_SELECT_CHARACTERS(#expression, _length_ ## index) };        \\\nconstexpr const char    *_final_ ## index =                                    \\\n    ::better_enums::_has_initializer(#expression) ?                            \\\n        _trimmed_ ## index : #expression;\n\n#define BETTER_ENUMS_TRIM_STRINGS(...)                                         \\\n    BETTER_ENUMS_ID(                                                           \\\n        BETTER_ENUMS_PP_MAP(                                                   \\\n            BETTER_ENUMS_TRIM_SINGLE_STRING, ignored, __VA_ARGS__))\n\n\n\n#define BETTER_ENUMS_REFER_TO_SINGLE_STRING(ignored, index, expression)        \\\n    _final_ ## index,\n\n#define BETTER_ENUMS_REFER_TO_STRINGS(...)                                     \\\n    BETTER_ENUMS_ID(                                                           \\\n        BETTER_ENUMS_PP_MAP(                                                   \\\n            BETTER_ENUMS_REFER_TO_SINGLE_STRING, ignored, __VA_ARGS__))\n\n\n\n#endif // #ifdef BETTER_ENUMS_HAVE_CONSTEXPR\n\n\n\n#define BETTER_ENUMS_STRINGIZE_SINGLE(ignored, index, expression)  #expression,\n\n#define BETTER_ENUMS_STRINGIZE(...)                                            \\\n    BETTER_ENUMS_ID(                                                           \\\n        BETTER_ENUMS_PP_MAP(                                                   \\\n            BETTER_ENUMS_STRINGIZE_SINGLE, ignored, __VA_ARGS__))\n\n#define BETTER_ENUMS_RESERVE_STORAGE_SINGLE(ignored, index, expression)        \\\n    #expression \",\"\n\n#define BETTER_ENUMS_RESERVE_STORAGE(...)                                      \\\n    BETTER_ENUMS_ID(                                                           \\\n        BETTER_ENUMS_PP_MAP(                                                   \\\n            BETTER_ENUMS_RESERVE_STORAGE_SINGLE, ignored, __VA_ARGS__))\n\n\n\n// The enums proper.\n\n#define BETTER_ENUMS_NS(EnumType)  better_enums_data_ ## EnumType\n\n#ifdef BETTER_ENUMS_VC2008_WORKAROUNDS\n\n#define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum)                                    \\\n        BETTER_ENUMS_CONSTEXPR_ Enum(const Enum &other) :                      \\\n            _value(other._value) { }\n\n#else\n\n#define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum)\n\n#endif\n\n#define BETTER_ENUMS_TYPE(SetUnderlyingType, SwitchType, GenerateSwitchType,   \\\n                          GenerateStrings, ToStringConstexpr,                  \\\n                          DeclareInitialize, DefineInitialize, CallInitialize, \\\n                          Enum, Underlying, ...)                               \\\n                                                                               \\\nnamespace better_enums_data_ ## Enum {                                         \\\n                                                                               \\\nBETTER_ENUMS_ID(GenerateSwitchType(Underlying, __VA_ARGS__))                   \\\n                                                                               \\\n}                                                                              \\\n                                                                               \\\nclass Enum {                                                                   \\\n  private:                                                                     \\\n    typedef ::better_enums::optional<Enum>                  _optional;         \\\n    typedef ::better_enums::optional<std::size_t>           _optional_index;   \\\n                                                                               \\\n  public:                                                                      \\\n    typedef Underlying                                      _integral;         \\\n                                                                               \\\n    enum _enumerated SetUnderlyingType(Underlying) { __VA_ARGS__ };            \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ Enum(_enumerated value) : _value(value) { }        \\\n                                                                               \\\n    BETTER_ENUMS_COPY_CONSTRUCTOR(Enum)                                        \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ operator SwitchType(Enum)() const                  \\\n    {                                                                          \\\n        return SwitchType(Enum)(_value);                                       \\\n    }                                                                          \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ _integral _to_integral() const;                    \\\n    BETTER_ENUMS_IF_EXCEPTIONS(                                                \\\n    BETTER_ENUMS_CONSTEXPR_ static Enum _from_integral(_integral value);       \\\n    )                                                                          \\\n    BETTER_ENUMS_CONSTEXPR_ static Enum                                        \\\n    _from_integral_unchecked(_integral value);                                 \\\n    BETTER_ENUMS_CONSTEXPR_ static _optional                                   \\\n    _from_integral_nothrow(_integral value);                                   \\\n                                                                               \\\n    ToStringConstexpr const char* _to_string() const;                          \\\n    BETTER_ENUMS_IF_EXCEPTIONS(                                                \\\n    BETTER_ENUMS_CONSTEXPR_ static Enum _from_string(const char *name);        \\\n    )                                                                          \\\n    BETTER_ENUMS_CONSTEXPR_ static _optional                                   \\\n    _from_string_nothrow(const char *name);                                    \\\n                                                                               \\\n    BETTER_ENUMS_IF_EXCEPTIONS(                                                \\\n    BETTER_ENUMS_CONSTEXPR_ static Enum _from_string_nocase(const char *name); \\\n    )                                                                          \\\n    BETTER_ENUMS_CONSTEXPR_ static _optional                                   \\\n    _from_string_nocase_nothrow(const char *name);                             \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(_integral value);            \\\n    BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(const char *name);           \\\n    BETTER_ENUMS_CONSTEXPR_ static bool _is_valid_nocase(const char *name);    \\\n                                                                               \\\n    typedef ::better_enums::_Iterable<Enum>             _value_iterable;       \\\n    typedef ::better_enums::_Iterable<const char*>      _name_iterable;        \\\n                                                                               \\\n    typedef _value_iterable::iterator                   _value_iterator;       \\\n    typedef _name_iterable::iterator                    _name_iterator;        \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ static const std::size_t _size_constant =          \\\n        BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT(__VA_ARGS__));                   \\\n    BETTER_ENUMS_CONSTEXPR_ static std::size_t _size()                         \\\n        { return _size_constant; }                                             \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ static const char* _name();                        \\\n    BETTER_ENUMS_CONSTEXPR_ static _value_iterable _values();                  \\\n    ToStringConstexpr static _name_iterable _names();                          \\\n                                                                               \\\n    _integral      _value;                                                     \\\n                                                                               \\\n    BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum)                                     \\\n                                                                               \\\n  private:                                                                     \\\n    explicit BETTER_ENUMS_CONSTEXPR_ Enum(const _integral &value) :            \\\n        _value(value) { }                                                      \\\n                                                                               \\\n    DeclareInitialize                                                          \\\n                                                                               \\\n    BETTER_ENUMS_CONSTEXPR_ static _optional_index                             \\\n    _from_value_loop(_integral value, std::size_t index = 0);                  \\\n    BETTER_ENUMS_CONSTEXPR_ static _optional_index                             \\\n    _from_string_loop(const char *name, std::size_t index = 0);                \\\n    BETTER_ENUMS_CONSTEXPR_ static _optional_index                             \\\n    _from_string_nocase_loop(const char *name, std::size_t index = 0);         \\\n                                                                               \\\n    friend struct ::better_enums::_initialize_at_program_start<Enum>;          \\\n};                                                                             \\\n                                                                               \\\nnamespace better_enums_data_ ## Enum {                                         \\\n                                                                               \\\nstatic ::better_enums::_initialize_at_program_start<Enum>                      \\\n                                                _force_initialization;         \\\n                                                                               \\\nenum _PutNamesInThisScopeAlso { __VA_ARGS__ };                                 \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ const Enum      _value_array[] =                       \\\n    { BETTER_ENUMS_ID(BETTER_ENUMS_EAT_ASSIGN(Enum, __VA_ARGS__)) };           \\\n                                                                               \\\nBETTER_ENUMS_ID(GenerateStrings(Enum, __VA_ARGS__))                            \\\n                                                                               \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline const Enum                                                              \\\noperator +(Enum::_enumerated enumerated)                                       \\\n{                                                                              \\\n    return static_cast<Enum>(enumerated);                                      \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index                           \\\nEnum::_from_value_loop(Enum::_integral value, std::size_t index)               \\\n{                                                                              \\\n    return                                                                     \\\n        index == _size() ?                                                     \\\n            _optional_index() :                                                \\\n            BETTER_ENUMS_NS(Enum)::_value_array[index]._value == value ?       \\\n                _optional_index(index) :                                       \\\n                _from_value_loop(value, index + 1);                            \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index                           \\\nEnum::_from_string_loop(const char *name, std::size_t index)                   \\\n{                                                                              \\\n    return                                                                     \\\n        index == _size() ? _optional_index() :                                 \\\n        ::better_enums::_names_match(                                          \\\n            BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ?                \\\n            _optional_index(index) :                                           \\\n            _from_string_loop(name, index + 1);                                \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index                           \\\nEnum::_from_string_nocase_loop(const char *name, std::size_t index)            \\\n{                                                                              \\\n    return                                                                     \\\n        index == _size() ? _optional_index() :                                 \\\n            ::better_enums::_names_match_nocase(                               \\\n                BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ?            \\\n                    _optional_index(index) :                                   \\\n                    _from_string_nocase_loop(name, index + 1);                 \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_integral Enum::_to_integral() const      \\\n{                                                                              \\\n    return _integral(_value);                                                  \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum                                            \\\nEnum::_from_integral_unchecked(_integral value)                                \\\n{                                                                              \\\n    return static_cast<_enumerated>(value);                                    \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_optional                                 \\\nEnum::_from_integral_nothrow(_integral value)                                  \\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array,  \\\n                                         _from_value_loop(value));             \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_IF_EXCEPTIONS(                                                    \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_integral(_integral value)      \\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_or_throw(_from_integral_nothrow(value),               \\\n                                  #Enum \"::_from_integral: invalid argument\"); \\\n}                                                                              \\\n)                                                                              \\\n                                                                               \\\nToStringConstexpr inline const char* Enum::_to_string() const                  \\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_or_null(                                              \\\n            ::better_enums::_map_index<const char*>(                           \\\n                BETTER_ENUMS_NS(Enum)::_name_array(),                          \\\n                _from_value_loop(CallInitialize(_value))));                    \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_optional                                 \\\nEnum::_from_string_nothrow(const char *name)                                   \\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_map_index<Enum>(                                      \\\n            BETTER_ENUMS_NS(Enum)::_value_array, _from_string_loop(name));     \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_IF_EXCEPTIONS(                                                    \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string(const char *name)       \\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_or_throw(_from_string_nothrow(name),                  \\\n                                  #Enum \"::_from_string: invalid argument\");   \\\n}                                                                              \\\n)                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_optional                                 \\\nEnum::_from_string_nocase_nothrow(const char *name)                            \\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array,  \\\n                                         _from_string_nocase_loop(name));      \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_IF_EXCEPTIONS(                                                    \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string_nocase(const char *name)\\\n{                                                                              \\\n    return                                                                     \\\n        ::better_enums::_or_throw(                                             \\\n            _from_string_nocase_nothrow(name),                                 \\\n            #Enum \"::_from_string_nocase: invalid argument\");                  \\\n}                                                                              \\\n)                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(_integral value)           \\\n{                                                                              \\\n    return _from_value_loop(value);                                            \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(const char *name)          \\\n{                                                                              \\\n    return _from_string_loop(name);                                            \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid_nocase(const char *name)   \\\n{                                                                              \\\n    return _from_string_nocase_loop(name);                                     \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline const char* Enum::_name()                       \\\n{                                                                              \\\n    return #Enum;                                                              \\\n}                                                                              \\\n                                                                               \\\nBETTER_ENUMS_CONSTEXPR_ inline Enum::_value_iterable Enum::_values()           \\\n{                                                                              \\\n    return _value_iterable(BETTER_ENUMS_NS(Enum)::_value_array, _size());      \\\n}                                                                              \\\n                                                                               \\\nToStringConstexpr inline Enum::_name_iterable Enum::_names()                   \\\n{                                                                              \\\n    return                                                                     \\\n        _name_iterable(BETTER_ENUMS_NS(Enum)::_name_array(),                   \\\n                       CallInitialize(_size()));                               \\\n}                                                                              \\\n                                                                               \\\nDefineInitialize(Enum)                                                         \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline bool operator ==(const Enum &a, const Enum &b)                          \\\n    { return a._to_integral() == b._to_integral(); }                           \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline bool operator !=(const Enum &a, const Enum &b)                          \\\n    { return a._to_integral() != b._to_integral(); }                           \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline bool operator <(const Enum &a, const Enum &b)                           \\\n    { return a._to_integral() < b._to_integral(); }                            \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline bool operator <=(const Enum &a, const Enum &b)                          \\\n    { return a._to_integral() <= b._to_integral(); }                           \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline bool operator >(const Enum &a, const Enum &b)                           \\\n    { return a._to_integral() > b._to_integral(); }                            \\\n                                                                               \\\nBETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_                                    \\\ninline bool operator >=(const Enum &a, const Enum &b)                          \\\n    { return a._to_integral() >= b._to_integral(); }                           \\\n                                                                               \\\n                                                                               \\\ntemplate <typename Char, typename Traits>                                      \\\nstd::basic_ostream<Char, Traits>&                                              \\\noperator <<(std::basic_ostream<Char, Traits>& stream, const Enum &value)       \\\n{                                                                              \\\n    return stream << value._to_string();                                       \\\n}                                                                              \\\n                                                                               \\\ntemplate <typename Char, typename Traits>                                      \\\nstd::basic_istream<Char, Traits>&                                              \\\noperator >>(std::basic_istream<Char, Traits>& stream, Enum &value)             \\\n{                                                                              \\\n    std::basic_string<Char, Traits>     buffer;                                \\\n                                                                               \\\n    stream >> buffer;                                                          \\\n    ::better_enums::optional<Enum>      converted =                            \\\n        Enum::_from_string_nothrow(buffer.c_str());                            \\\n                                                                               \\\n    if (converted)                                                             \\\n        value = *converted;                                                    \\\n    else                                                                       \\\n        stream.setstate(std::basic_istream<Char, Traits>::failbit);            \\\n                                                                               \\\n    return stream;                                                             \\\n}\n\n\n\n// Enum feature options.\n\n// C++98, C++11\n#define BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying)\n\n// C++11\n#define BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying)                         \\\n    : Underlying\n\n#if defined(_MSC_VER) && _MSC_VER >= 1700\n// VS 2012 and above fully support strongly typed enums and will warn about\n// incorrect usage.\n#   define BETTER_ENUMS_LEGACY_UNDERLYING_TYPE(Underlying) BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying)\n#else\n#   define BETTER_ENUMS_LEGACY_UNDERLYING_TYPE(Underlying) BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying)\n#endif\n\n// C++98, C++11\n#define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE(Type)                            \\\n    _enumerated\n\n// C++11\n#define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE(Type)                              \\\n    BETTER_ENUMS_NS(Type)::_EnumClassForSwitchStatements\n\n// C++98, C++11\n#define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE(Underlying, ...)\n\n// C++11\n#define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE(Underlying, ...)          \\\n    enum class _EnumClassForSwitchStatements : Underlying { __VA_ARGS__ };\n\n// C++98\n#define BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS(Enum, ...)                      \\\n    inline const char** _raw_names()                                           \\\n    {                                                                          \\\n        static const char   *value[] =                                         \\\n            { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) };          \\\n        return value;                                                          \\\n    }                                                                          \\\n                                                                               \\\n    inline char* _name_storage()                                               \\\n    {                                                                          \\\n        static char         storage[] =                                        \\\n            BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__));        \\\n        return storage;                                                        \\\n    }                                                                          \\\n                                                                               \\\n    inline const char** _name_array()                                          \\\n    {                                                                          \\\n        static const char   *value[Enum::_size_constant];                      \\\n        return value;                                                          \\\n    }                                                                          \\\n                                                                               \\\n    inline bool& _initialized()                                                \\\n    {                                                                          \\\n        static bool         value = false;                                     \\\n        return value;                                                          \\\n    }\n\n// C++11 fast version\n#define BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...)    \\\n    constexpr const char    *_the_raw_names[] =                                \\\n        { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) };              \\\n                                                                               \\\n    constexpr const char * const * _raw_names()                                \\\n    {                                                                          \\\n        return _the_raw_names;                                                 \\\n    }                                                                          \\\n                                                                               \\\n    inline char* _name_storage()                                               \\\n    {                                                                          \\\n        static char         storage[] =                                        \\\n            BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__));        \\\n        return storage;                                                        \\\n    }                                                                          \\\n                                                                               \\\n    inline const char** _name_array()                                          \\\n    {                                                                          \\\n        static const char   *value[Enum::_size_constant];                      \\\n        return value;                                                          \\\n    }                                                                          \\\n                                                                               \\\n    inline bool& _initialized()                                                \\\n    {                                                                          \\\n        static bool         value = false;                                     \\\n        return value;                                                          \\\n    }\n\n// C++11 slow all-constexpr version\n#define BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...)       \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_TRIM_STRINGS(__VA_ARGS__))                    \\\n                                                                               \\\n    constexpr const char * const    _the_name_array[] =                        \\\n        { BETTER_ENUMS_ID(BETTER_ENUMS_REFER_TO_STRINGS(__VA_ARGS__)) };       \\\n                                                                               \\\n    constexpr const char * const * _name_array()                               \\\n    {                                                                          \\\n        return _the_name_array;                                                \\\n    }                                                                          \\\n                                                                               \\\n    constexpr const char * const * _raw_names()                                \\\n    {                                                                          \\\n        return _the_name_array;                                                \\\n    }\n\n// C++98, C++11 fast version\n#define BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD\n\n// C++11 slow all-constexpr version\n#define BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD                               \\\n    constexpr\n\n// C++98, C++11 fast version\n#define BETTER_ENUMS_DO_DECLARE_INITIALIZE                                     \\\n    static int initialize();\n\n// C++11 slow all-constexpr version\n#define BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE                                  \\\n    static int initialize() { return 0; }\n\n// C++98, C++11 fast version\n#define BETTER_ENUMS_DO_DEFINE_INITIALIZE(Enum)                                \\\n    inline int Enum::initialize()                                              \\\n    {                                                                          \\\n        if (BETTER_ENUMS_NS(Enum)::_initialized())                             \\\n            return 0;                                                          \\\n                                                                               \\\n        ::better_enums::_trim_names(BETTER_ENUMS_NS(Enum)::_raw_names(),       \\\n                                    BETTER_ENUMS_NS(Enum)::_name_array(),      \\\n                                    BETTER_ENUMS_NS(Enum)::_name_storage(),    \\\n                                    _size());                                  \\\n                                                                               \\\n        BETTER_ENUMS_NS(Enum)::_initialized() = true;                          \\\n                                                                               \\\n        return 0;                                                              \\\n    }\n\n// C++11 slow all-constexpr version\n#define BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE(Enum)\n\n// C++98, C++11 fast version\n#define BETTER_ENUMS_DO_CALL_INITIALIZE(value)                                 \\\n    ::better_enums::continue_with(initialize(), value)\n\n// C++11 slow all-constexpr version\n#define BETTER_ENUMS_DO_NOT_CALL_INITIALIZE(value)                             \\\n    value\n\n\n\n// User feature selection.\n\n#ifdef BETTER_ENUMS_STRICT_CONVERSION\n#   define BETTER_ENUMS_DEFAULT_SWITCH_TYPE                                    \\\n        BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE\n#   define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE                           \\\n        BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE\n#else\n#   define BETTER_ENUMS_DEFAULT_SWITCH_TYPE                                    \\\n        BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE\n#   define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE                           \\\n        BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE\n#endif\n\n\n\n#ifndef BETTER_ENUMS_DEFAULT_CONSTRUCTOR\n#   define BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum)                              \\\n      private:                                                                 \\\n        Enum() : _value(0) { }\n#endif\n\n\n\n#ifdef BETTER_ENUMS_HAVE_CONSTEXPR\n\n#ifdef BETTER_ENUMS_CONSTEXPR_TO_STRING\n#   define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS                            \\\n        BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS\n#   define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD                              \\\n        BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD\n#   define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE                             \\\n        BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE\n#   define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE                              \\\n        BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE\n#   define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE                                \\\n        BETTER_ENUMS_DO_NOT_CALL_INITIALIZE\n#else\n#   define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS                            \\\n        BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS\n#   define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD                              \\\n        BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD\n#   define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE                             \\\n        BETTER_ENUMS_DO_DECLARE_INITIALIZE\n#   define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE                              \\\n        BETTER_ENUMS_DO_DEFINE_INITIALIZE\n#   define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE                                \\\n        BETTER_ENUMS_DO_CALL_INITIALIZE\n#endif\n\n\n\n// Top-level macros.\n\n#define BETTER_ENUM(Enum, Underlying, ...)                                     \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_TYPE(                                         \\\n        BETTER_ENUMS_CXX11_UNDERLYING_TYPE,                                    \\\n        BETTER_ENUMS_DEFAULT_SWITCH_TYPE,                                      \\\n        BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE,                             \\\n        BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS,                              \\\n        BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD,                                \\\n        BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE,                               \\\n        BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE,                                \\\n        BETTER_ENUMS_DEFAULT_CALL_INITIALIZE,                                  \\\n        Enum, Underlying, __VA_ARGS__))\n\n#define SLOW_ENUM(Enum, Underlying, ...)                                       \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_TYPE(                                         \\\n        BETTER_ENUMS_CXX11_UNDERLYING_TYPE,                                    \\\n        BETTER_ENUMS_DEFAULT_SWITCH_TYPE,                                      \\\n        BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE,                             \\\n        BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS,                 \\\n        BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD,                              \\\n        BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE,                                 \\\n        BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE,                                 \\\n        BETTER_ENUMS_DO_NOT_CALL_INITIALIZE,                                   \\\n        Enum, Underlying, __VA_ARGS__))\n\n#else\n\n#define BETTER_ENUM(Enum, Underlying, ...)                                     \\\n    BETTER_ENUMS_ID(BETTER_ENUMS_TYPE(                                         \\\n        BETTER_ENUMS_LEGACY_UNDERLYING_TYPE,                                   \\\n        BETTER_ENUMS_DEFAULT_SWITCH_TYPE,                                      \\\n        BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE,                             \\\n        BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS,                                \\\n        BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD,                           \\\n        BETTER_ENUMS_DO_DECLARE_INITIALIZE,                                    \\\n        BETTER_ENUMS_DO_DEFINE_INITIALIZE,                                     \\\n        BETTER_ENUMS_DO_CALL_INITIALIZE,                                       \\\n        Enum, Underlying, __VA_ARGS__))\n\n#endif\n\n\n\nnamespace better_enums {\n\n// Maps.\n\ntemplate <typename T>\nstruct map_compare {\n    BETTER_ENUMS_CONSTEXPR_ static bool less(const T& a, const T& b)\n        { return a < b; }\n};\n\ntemplate <>\nstruct map_compare<const char*> {\n    BETTER_ENUMS_CONSTEXPR_ static bool less(const char *a, const char *b)\n        { return less_loop(a, b); }\n\n  private:\n    BETTER_ENUMS_CONSTEXPR_ static bool\n    less_loop(const char *a, const char *b, size_t index = 0)\n    {\n        return\n            a[index] != b[index] ? a[index] < b[index] :\n            a[index] == '\\0' ? false :\n            less_loop(a, b, index + 1);\n    }\n};\n\n// chenyao add\ntemplate <>\nstruct map_compare<const wchar_t*> {\n    BETTER_ENUMS_CONSTEXPR_ static bool less(const wchar_t *a, const wchar_t *b)\n        { return less_loop(a, b); }\n\n  private:\n    BETTER_ENUMS_CONSTEXPR_ static bool\n    less_loop(const wchar_t *a, const wchar_t *b, size_t index = 0)\n    {\n        return\n            a[index] != b[index] ? a[index] < b[index] :\n            a[index] == L'\\0' ? false :\n            less_loop(a, b, index + 1);\n    }\n};\n\ntemplate <typename Enum, typename T, typename Compare = map_compare<T> >\nstruct map {\n    typedef T (*function)(Enum);\n\n    BETTER_ENUMS_CONSTEXPR_ explicit map(function f) : _f(f) { }\n\n    BETTER_ENUMS_CONSTEXPR_ T from_enum(Enum value) const { return _f(value); }\n    BETTER_ENUMS_CONSTEXPR_ T operator [](Enum value) const\n        { return _f(value); }\n\n    BETTER_ENUMS_CONSTEXPR_ Enum to_enum(T value) const\n    {\n        return\n            _or_throw(to_enum_nothrow(value), \"map::to_enum: invalid argument\");\n    }\n\n    BETTER_ENUMS_CONSTEXPR_ optional<Enum>\n    to_enum_nothrow(T value, size_t index = 0) const\n    {\n        return\n            index >= Enum::_size() ? optional<Enum>() :\n            Compare::less(_f(Enum::_values()[index]), value) ||\n            Compare::less(value, _f(Enum::_values()[index])) ?\n                to_enum_nothrow(value, index + 1) :\n            Enum::_values()[index];\n    }\n\n  private:\n    const function      _f;\n};\n\ntemplate <typename Enum, typename T>\nBETTER_ENUMS_CONSTEXPR_ map<Enum, T> make_map(T (*f)(Enum))\n{\n    return map<Enum, T>(f);\n}\n\n}\n\n#endif // #ifndef BETTER_ENUMS_ENUM_H\n"
  },
  {
    "path": "src/utils/geo.h",
    "content": "//\n// Some class templates for geometry primitives (point, interval, box)\n//\n\n#pragma once\n\n#include <cassert>\n#include <cmath>\n#include <iostream>\n#include <limits>\n#include <vector>\n#include <algorithm>\n\nnamespace utils {\n\n// Point template\ntemplate <typename T>\nclass PointT {\npublic:\n    T x, y;\n    PointT(T xx = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity()\n                                                       : std::numeric_limits<T>::max(),\n           T yy = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity()\n                                                       : std::numeric_limits<T>::max())\n        : x(xx), y(yy) {}\n    bool IsValid() { return *this != PointT(); }\n\n    // Operators\n    const T& operator[](const unsigned d) const {\n        assert(d == 0 || d == 1);\n        return (d == 0 ? x : y);\n    }\n    T& operator[](const unsigned d) {\n        assert(d == 0 || d == 1);\n        return (d == 0 ? x : y);\n    }\n    PointT operator+(const PointT& rhs) { return PointT(x + rhs.x, y + rhs.y); }\n    PointT operator/(T divisor) { return PointT(x / divisor, y / divisor); }\n    PointT& operator+=(const PointT& rhs) {\n        x += rhs.x;\n        y += rhs.y;\n        return *this;\n    }\n    PointT& operator-=(const PointT& rhs) {\n        x -= rhs.x;\n        y -= rhs.y;\n        return *this;\n    }\n    bool operator==(const PointT& rhs) const { return x == rhs.x && y == rhs.y; }\n    bool operator!=(const PointT& rhs) const { return !(*this == rhs); }\n\n    friend inline std::ostream& operator<<(std::ostream& os, const PointT& pt) {\n        os << \"(\" << pt.x << \", \" << pt.y << \")\";\n        return os;\n    }\n};\n\n// L-1 (Manhattan) distance between points\ntemplate <typename T>\ninline T Dist(const PointT<T>& pt1, const PointT<T>& pt2) {\n    return std::abs(pt1.x - pt2.x) + std::abs(pt1.y - pt2.y);\n}\n\n// L-2 (Euclidean) distance between points\ntemplate <typename T>\ninline double L2Dist(const PointT<T>& pt1, const PointT<T>& pt2) {\n    return std::sqrt(std::pow(pt1.x - pt2.x, 2) + std::pow(pt1.y - pt2.y, 2));\n}\n\n// L-inf distance between points\ntemplate <typename T>\ninline T LInfDist(const PointT<T>& pt1, const PointT<T>& pt2) {\n    return std::max(std::abs(pt1.x - pt2.x), std::abs(pt1.y - pt2.y));\n}\n\n// Interval template\ntemplate <typename T>\nclass IntervalT {\npublic:\n    T low, high;\n\n    template <typename... Args>\n    IntervalT(Args... params) {\n        Set(params...);\n    }\n\n    // Setters\n    void Set() {\n        low = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : std::numeric_limits<T>::max();\n        high = std::numeric_limits<T>::has_infinity ? -std::numeric_limits<T>::infinity()\n                                                    : std::numeric_limits<T>::lowest();\n    }\n    void Set(T val) {\n        low = val;\n        high = val;\n    }\n    void Set(T lo, T hi) {\n        low = lo;\n        high = hi;\n    }\n\n    // Getters\n    T center() const { return (high + low) / 2; }\n    T range() const { return high - low; }\n\n    // Update\n    // Update() is always safe, FastUpdate() assumes existing values\n    void Update(T newVal) {\n        if (newVal < low) low = newVal;\n        if (newVal > high) high = newVal;\n    }\n    void FastUpdate(T newVal) {\n        if (newVal < low)\n            low = newVal;\n        else if (newVal > high)\n            high = newVal;\n    }\n\n    // Two types of intervals: 1. normal, 2. degenerated (i.e., point)\n    // is valid interval (i.e., valid closed interval)\n    bool IsValid() const { return low <= high; }\n    // is strictly valid interval (excluding degenerated ones, i.e., valid open interval)\n    bool IsStrictValid() const { return low < high; }\n\n    // Geometric Query/Update\n    // interval/range of union (not union of intervals)\n    IntervalT UnionWith(const IntervalT& rhs) const {\n        if (!IsValid())\n            return rhs;\n        else if (!rhs.IsValid())\n            return *this;\n        else\n            return IntervalT(std::min(low, rhs.low), std::max(high, rhs.high));\n    }\n    // may return an invalid interval (as empty intersection)\n    IntervalT IntersectWith(const IntervalT& rhs) const {\n        return IntervalT(std::max(low, rhs.low), std::min(high, rhs.high));\n    }\n    bool HasIntersectWith(const IntervalT& rhs) const { return IntersectWith(rhs).IsValid(); }\n    bool HasStrictIntersectWith(const IntervalT& rhs) const { return IntersectWith(rhs).IsStrictValid(); }\n    //  Parallel run length between intervals\n    T ParaRunLength(const IntervalT& rhs) const { return IntersectWith(rhs).range(); }\n    // contain a val\n    bool Contain(int val) const { return val >= low && val <= high; }\n    bool StrictlyContain(int val) const { return val > low && val < high; }\n    // get nearest point(s) to val (assume valid intervals)\n    T GetNearestPointTo(T val) const {\n        if (val <= low) {\n            return low;\n        } else if (val >= high) {\n            return high;\n        } else {\n            return val;\n        }\n    }\n    IntervalT GetNearestPointsTo(IntervalT val) const {\n        if (val.high <= low) {\n            return {low};\n        } else if (val.low >= high) {\n            return {high};\n        } else {\n            return IntersectWith(val);\n        }\n    }\n\n    void ShiftBy(const T& rhs) {\n        low += rhs;\n        high += rhs;\n    }\n\n    // Operators\n    bool operator==(const IntervalT& rhs) const {\n        return (!IsValid() && !rhs.IsValid()) || (low == rhs.low && high == rhs.high);\n    }\n    bool operator!=(const IntervalT& rhs) const { return !(*this == rhs); }\n\n    friend inline std::ostream& operator<<(std::ostream& os, const IntervalT<T>& interval) {\n        os << \"(\" << interval.low << \", \" << interval.high << \")\";\n        return os;\n    }\n};\n\n// Distance between intervals/points (assume valid intervals)\ntemplate <typename T>\ninline T Dist(const IntervalT<T>& intvl, const T val) {\n    return std::abs(intvl.GetNearestPointTo(val) - val);\n}\n\ntemplate <typename T>\ninline T Dist(const IntervalT<T>& int1, const IntervalT<T>& int2) {\n    if (int1.high <= int2.low) {\n        return int2.low - int1.high;\n    } else if (int1.low >= int2.high) {\n        return int1.low - int2.high;\n    } else {\n        return 0;\n    }\n}\n\n// Box template\ntemplate <typename T>\nclass BoxT {\npublic:\n    IntervalT<T> x, y;\n\n    template <typename... Args>\n    BoxT(Args... params) {\n        Set(params...);\n    }\n\n    // Setters\n    T& lx() { return x.low; }\n    T& ly() { return y.low; }\n    T& hy() { return y.high; }\n    T& hx() { return x.high; }\n    IntervalT<T>& operator[](unsigned i) {\n        assert(i == 0 || i == 1);\n        return (i == 0) ? x : y;\n    }\n    void Set() {\n        x.Set();\n        y.Set();\n    }\n    void Set(T xVal, T yVal) {\n        x.Set(xVal);\n        y.Set(yVal);\n    }\n    void Set(const PointT<T>& pt) { Set(pt.x, pt.y); }\n    void Set(T lx, T ly, T hx, T hy) {\n        x.Set(lx, hx);\n        y.Set(ly, hy);\n    }\n    void Set(const IntervalT<T>& xRange, const IntervalT<T>& yRange) {\n        x = xRange;\n        y = yRange;\n    }\n    void Set(const PointT<T>& low, const PointT<T>& high) { Set(low.x, low.y, high.x, high.y); }\n    void Set(const BoxT<T>& box) { Set(box.x, box.y); }\n\n    // Two types of boxes: normal & degenerated (line or point)\n    // is valid box\n    bool IsValid() const { return x.IsValid() && y.IsValid(); }\n    // is strictly valid box (excluding degenerated ones)\n    bool IsStrictValid() const { return x.IsStrictValid() && y.IsStrictValid(); }  // tighter\n\n    // Getters\n    T lx() const { return x.low; }\n    T ly() const { return y.low; }\n    T hy() const { return y.high; }\n    T hx() const { return x.high; }\n    T cx() const { return x.center(); }\n    T cy() const { return y.center(); }\n    T width() const { return x.range(); }\n    T height() const { return y.range(); }\n    T hp() const { return width() + height(); }  // half perimeter\n    T area() const { return width() * height(); }\n    const IntervalT<T>& operator[](unsigned i) const {\n        assert(i == 0 || i == 1);\n        return (i == 0) ? x : y;\n    }\n\n    // Update() is always safe, FastUpdate() assumes existing values\n    void Update(T xVal, T yVal) {\n        x.Update(xVal);\n        y.Update(yVal);\n    }\n    void FastUpdate(T xVal, T yVal) {\n        x.FastUpdate(xVal);\n        y.FastUpdate(yVal);\n    }\n    void Update(const PointT<T>& pt) { Update(pt.x, pt.y); }\n    void FastUpdate(const PointT<T>& pt) { FastUpdate(pt.x, pt.y); }\n\n    // Geometric Query/Update\n    BoxT UnionWith(const BoxT& rhs) const { return {x.UnionWith(rhs.x), y.UnionWith(rhs.y)}; }\n    BoxT IntersectWith(const BoxT& rhs) const { return {x.IntersectWith(rhs.x), y.IntersectWith(rhs.y)}; }\n    bool HasIntersectWith(const BoxT& rhs) const { return IntersectWith(rhs).IsValid(); }\n    bool HasStrictIntersectWith(const BoxT& rhs) const { return IntersectWith(rhs).IsStrictValid(); }  // tighter\n    bool Contain(const PointT<T>& pt) const { return x.Contain(pt.x) && y.Contain(pt.y); }\n    bool StrictlyContain(const PointT<T>& pt) const { return x.StrictlyContain(pt.x) && y.StrictlyContain(pt.y); }\n    PointT<T> GetNearestPointTo(const PointT<T>& pt) { return {x.GetNearestPointTo(pt.x), y.GetNearestPointTo(pt.y)}; }\n    BoxT GetNearestPointsTo(BoxT val) const { return {x.GetNearestPointsTo(val.x), y.GetNearestPointsTo(val.y)}; }\n\n    void ShiftBy(const PointT<T>& rhs) {\n        x.ShiftBy(rhs.x);\n        y.ShiftBy(rhs.y);\n    }\n\n    bool operator==(const BoxT& rhs) const { return (x == rhs.x) && (y == rhs.y); }\n    bool operator!=(const BoxT& rhs) const { return !(*this == rhs); }\n\n    friend inline std::ostream& operator<<(std::ostream& os, const BoxT<T>& box) {\n        os << \"[x: \" << box.x << \", y: \" << box.y << \"]\";\n        return os;\n    }\n};\n\n// L-1 (Manhattan) distance between boxes/points (assume valid boxes)\ntemplate <typename T>\ninline T Dist(const BoxT<T>& box, const PointT<T>& point) {\n    return Dist(box.x, point.x) + Dist(box.y, point.y);\n}\ntemplate <typename T>\ninline T Dist(const BoxT<T>& box1, const BoxT<T>& box2) {\n    return Dist(box1.x, box2.x) + Dist(box1.y, box2.y);\n}\n\n// L-2 (Euclidean) distance between boxes\ntemplate <typename T>\ninline double L2Dist(const BoxT<T>& box1, const BoxT<T>& box2) {\n    return std::sqrt(std::pow(Dist(box1.x, box2.x), 2) + std::pow(Dist(box1.y, box2.y), 2));\n}\n\n// L-Inf (max) distance between boxes\ntemplate <typename T>\ninline T LInfDist(const BoxT<T>& box1, const BoxT<T>& box2) {\n    return std::max(Dist(box1.x, box2.x), Dist(box1.y, box2.y));\n}\n\n//  Parallel run length between boxes\ntemplate <typename T>\ninline T ParaRunLength(const BoxT<T>& box1, const BoxT<T>& box2) {\n    return std::max(box1.x.ParaRunLength(box2.x), box1.y.ParaRunLength(box2.y));\n}\n\n// Merge/stitch overlapped rectangles along mergeDir\n// mergeDir: 0 for x/vertical, 1 for y/horizontal\n// use BoxT instead of T & BoxT<T> to make it more general\ntemplate <typename BoxT>\nvoid MergeRects(std::vector<BoxT>& boxes, int mergeDir) {\n    int boundaryDir = 1 - mergeDir;\n    std::sort(boxes.begin(), boxes.end(), [&](const BoxT& lhs, const BoxT& rhs) {\n        return lhs[boundaryDir].low < rhs[boundaryDir].low ||\n               (lhs[boundaryDir].low == rhs[boundaryDir].low && lhs[mergeDir].low < rhs[mergeDir].low);\n    });\n    std::vector<BoxT> mergedBoxes;\n    mergedBoxes.push_back(boxes.front());\n    for (int i = 1; i < boxes.size(); ++i) {\n        auto& lastBox = mergedBoxes.back();\n        auto& slicedBox = boxes[i];\n        if (slicedBox[boundaryDir] == lastBox[boundaryDir] &&\n            slicedBox[mergeDir].low <= lastBox[mergeDir].high) {  // aligned and intersected\n            lastBox[mergeDir] = lastBox[mergeDir].UnionWith(slicedBox[mergeDir]);\n        } else {  // neither misaligned not seperated\n            mergedBoxes.push_back(slicedBox);\n        }\n    }\n    boxes = move(mergedBoxes);\n}\n\n// Slice polygons along sliceDir\n// sliceDir: 0 for x/vertical, 1 for y/horizontal\n// assume no degenerated case\ntemplate <typename T>\nvoid SlicePolygons(std::vector<BoxT<T>>& boxes, int sliceDir) {\n    // Line sweep in sweepDir = 1 - sliceDir\n    // Suppose sliceDir = y and sweepDir = x (sweep from left to right)\n    // Not scalable impl (brute force interval query) but fast for small case\n    if (boxes.size() <= 1) return;\n\n    // sort slice lines in sweepDir\n    int sweepDir = 1 - sliceDir;\n    std::vector<T> locs;\n    for (const auto& box : boxes) {\n        locs.push_back(box[sweepDir].low);\n        locs.push_back(box[sweepDir].high);\n    }\n    std::sort(locs.begin(), locs.end());\n    locs.erase(std::unique(locs.begin(), locs.end()), locs.end());\n\n    // slice each box\n    std::vector<BoxT<T>> slicedBoxes;\n    for (const auto& box : boxes) {\n        BoxT<T> slicedBox = box;\n        auto itLoc = std::lower_bound(locs.begin(), locs.end(), box[sweepDir].low);\n        auto itEnd = std::upper_bound(itLoc, locs.end(), box[sweepDir].high);\n        while ((itLoc + 1) != itEnd) {\n            slicedBox[sweepDir].Set(*itLoc, *(itLoc + 1));\n            slicedBoxes.push_back(slicedBox);\n            ++itLoc;\n        }\n    }\n    boxes = move(slicedBoxes);\n\n    // merge overlapped boxes along slice dir\n    MergeRects(boxes, sliceDir);\n\n    // stitch boxes along sweep dir\n    MergeRects(boxes, sweepDir);\n}\n\ntemplate <typename T>\nclass SegmentT : public BoxT<T> {\npublic:\n    using BoxT<T>::BoxT;\n    T length() const { return BoxT<T>::hp(); }\n    bool IsRectilinear() const { return BoxT<T>::x() == 0 || BoxT<T>::y() == 0; }\n};\n\n}  // namespace utils\n"
  },
  {
    "path": "src/utils/log.cpp",
    "content": "#include \"log.h\"\n\n#include <iomanip>\n#include <sstream>\n\n#if defined(__unix__)\n#include <sys/resource.h>\n#include <unistd.h>\n#elif defined(_WIN32)\n#include <windows.h>\n#include <psapi.h>\n#endif\n\nnamespace utils {\n\ntimer::timer() { start(); }\nvoid timer::start() { _start = clock::now(); }\ndouble timer::elapsed() const { return std::chrono::duration<double>(clock::now() - _start).count(); }\n\ntimer tstamp;\n\nstd::ostream& operator<<(std::ostream& os, const timer& t) {\n    std::ostringstream oss;  // seperate the impact of format\n    oss << \"[\" << std::setprecision(3) << std::setw(8) << std::fixed << t.elapsed() << \"] \";\n    os << oss.str();\n    return os;\n}\n\ndouble mem_use::get_current() {\n#if defined(__unix__)\n    long rss = 0L;\n    FILE* fp = NULL;\n    if ((fp = fopen(\"/proc/self/statm\", \"r\")) == NULL) {\n        return 0.0; /* Can't open? */\n    }\n    if (fscanf(fp, \"%*s%ld\", &rss) != 1) {\n        fclose(fp);\n        return 0.0; /* Can't read? */\n    }\n    fclose(fp);\n    return rss * sysconf(_SC_PAGESIZE) / 1048576.0;\n#elif defined(_WIN32)\n    PROCESS_MEMORY_COUNTERS info;\n    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));\n    return info.WorkingSetSize / 1048576.0;\n#else\n    return 0.0;  // unknown\n#endif\n}\n\ndouble mem_use::get_peak() {\n#if defined(__unix__)\n    struct rusage rusage;\n    getrusage(RUSAGE_SELF, &rusage);\n    return rusage.ru_maxrss / 1024.0;\n#elif defined(_WIN32)\n    PROCESS_MEMORY_COUNTERS info;\n    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));\n    return info.PeakWorkingSetSize / 1048576.0;\n#else\n    return 0.0;  // unknown\n#endif\n}\n\nstd::ostream& log(std::ostream& os) {\n    os << tstamp;\n    return os;\n}\n\n}  // namespace utils"
  },
  {
    "path": "src/utils/log.h",
    "content": "//\n// Some logging utilities\n// 1. \"log() << ...\" will show a time stamp first\n// 2. \"print(a, b, c)\" is python-like print for any a, b, c that has operator<< overloaded. For example,\n//      int a = 10;\n//      double b = 3.14;\n//      std::string c = \"Gengjie\";\n//      print(a, b, c);\n//     This code piece will show \"10 3.14 Gengjie\".\n//\n\n#pragma once\n\n#include <chrono>\n#include <iostream>\n#include <string>\n\nnamespace utils {\n\n// 1. Timer\n\nclass timer {\n    using clock = std::chrono::high_resolution_clock;\n\nprivate:\n    clock::time_point _start;\n\npublic:\n    timer();\n    void start();\n    double elapsed() const;  // seconds\n};\n\nstd::ostream& operator<<(std::ostream& os, const timer& t);\n\n// 2. Memory\n\nclass mem_use {\npublic:\n    static double get_current();  // MB\n    static double get_peak();     // MB\n};\n\n// 3. Easy print\n\n// print(a, b, c)\ninline void print() { std::cout << std::endl; }\ntemplate <typename T, typename... TAIL>\nvoid print(const T& t, TAIL... tail) {\n    std::cout << t << ' ';\n    print(tail...);\n}\n\n// \"log() << a << b << c\" puts a time stamp in beginning\nstd::ostream& log(std::ostream& os = std::cout);\n\n// \"printlog(a, b, c)\" puts a time stamp in beginning\ntemplate <typename... T>\nvoid printlog(T... t) {\n    log();\n    print(t...);\n}\n\ntemplate <typename... T>\nvoid printflog(T... t) {\n    log();\n    printf(t...);\n}\n\n}  // namespace utils"
  },
  {
    "path": "src/utils/prettyprint.h",
    "content": "//\n// Pretty printing for C++ STL containers\n//\n// Usage: operator<< will \"just work\" for most STL containers, for example,\n//      std::vector<int> nums = {1, 2, 10};\n//      std::cout << nums << std::endl;\n//     This code piece will show \"1 2 10\".\n//\n\n#pragma once\n\n#include <memory>\n#include <set>\n#include <unordered_set>\n#include <sstream>\n\nnamespace utils {\n\n// SFINAE has_begin_end\n\ntemplate <typename T, typename = void>\nstruct has_begin_end : std::false_type {};\ntemplate <typename T>\nstruct has_begin_end<T, decltype((void)std::begin(std::declval<T>()), (void)std::end(std::declval<T>()))>\n    : std::true_type {};\n\n// Holds the delimiter values for a specific character type\n\ntemplate <typename TChar>\nstruct delimiters_values {\n    using char_type = TChar;\n    const char_type *prefix;\n    const char_type *delimiter;\n    const char_type *postfix;\n};\n\n// Defines the delimiter values for a specific container and character type\n\ntemplate <typename T, typename TChar = char>\nstruct delimiters {\n    using type = delimiters_values<TChar>;\n    static const type values;\n};\n\n// Functor to print containers. You can use this directly if you want\n// to specificy a non-default delimiters type. The printing logic can\n// be customized by specializing the nested template.\n\ntemplate <typename T,\n          typename TChar = char,\n          typename TCharTraits = std::char_traits<TChar>,\n          typename TDelimiters = delimiters<T, TChar>>\nstruct print_container_helper {\n    using delimiters_type = TDelimiters;\n    using ostream_type = std::basic_ostream<TChar, TCharTraits>;\n\n    template <typename U>\n    struct printer {\n        static void print_body(const U &c, ostream_type &stream) {\n            auto it = std::begin(c);\n            const auto the_end = std::end(c);\n\n            if (it != the_end) {\n                for (;;) {\n                    stream << *it;\n\n                    if (++it == the_end) break;\n\n                    if (delimiters_type::values.delimiter != NULL) stream << delimiters_type::values.delimiter;\n                }\n            }\n        }\n    };\n\n    print_container_helper(const T &container) : container_(container) {}\n\n    inline void operator()(ostream_type &stream) const {\n        if (delimiters_type::values.prefix != NULL) stream << delimiters_type::values.prefix;\n\n        printer<T>::print_body(container_, stream);\n\n        if (delimiters_type::values.postfix != NULL) stream << delimiters_type::values.postfix;\n    }\n\nprivate:\n    const T &container_;\n};\n\n// Specialization for pairs\n\ntemplate <typename T, typename TChar, typename TCharTraits, typename TDelimiters>\ntemplate <typename T1, typename T2>\nstruct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>> {\n    using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;\n\n    static void print_body(const std::pair<T1, T2> &c, ostream_type &stream) {\n        stream << c.first;\n        if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)\n            stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;\n        stream << c.second;\n    }\n};\n\n// Specialization for tuples\n\ntemplate <typename T, typename TChar, typename TCharTraits, typename TDelimiters>\ntemplate <typename... Args>\nstruct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>> {\n    using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;\n    using element_type = std::tuple<Args...>;\n\n    template <std::size_t I>\n    struct Int {};\n\n    static void print_body(const element_type &c, ostream_type &stream) { tuple_print(c, stream, Int<0>()); }\n\n    static void tuple_print(const element_type &, ostream_type &, Int<sizeof...(Args)>) {}\n\n    static void tuple_print(const element_type &c,\n                            ostream_type &stream,\n                            typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type) {\n        stream << std::get<0>(c);\n        tuple_print(c, stream, Int<1>());\n    }\n\n    template <std::size_t N>\n    static void tuple_print(const element_type &c, ostream_type &stream, Int<N>) {\n        if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)\n            stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;\n\n        stream << std::get<N>(c);\n\n        tuple_print(c, stream, Int<N + 1>());\n    }\n};\n\n// Prints a print_container_helper to the specified stream.\n\ntemplate <typename T, typename TChar, typename TCharTraits, typename TDelimiters>\ninline std::basic_ostream<TChar, TCharTraits> &operator<<(\n    std::basic_ostream<TChar, TCharTraits> &stream,\n    const print_container_helper<T, TChar, TCharTraits, TDelimiters> &helper) {\n    helper(stream);\n    return stream;\n}\n\n// Basic is_container template; specialize to derive from std::true_type for all desired container types\n\ntemplate <typename T>\nstruct is_container : std::integral_constant<bool, has_begin_end<T>::value> {};\n\ntemplate <typename... T>\nstruct is_container<std::pair<T...>> : std::true_type {};\n\ntemplate <typename... T>\nstruct is_container<std::tuple<T...>> : std::true_type {};\n\n// Default delimiters\n\ntemplate <typename T>\nstruct delimiters<T, char> {\n    static constexpr delimiters_values<char> values = {\"[\", \", \", \"]\"};\n};\n\n// Delimiters for (unordered_)(multi)set\n\ntemplate <typename... T>\nstruct delimiters<std::set<T...>> {\n    static constexpr delimiters_values<char> values = {\"{\", \", \", \"}\"};\n};\n\ntemplate <typename... T>\nstruct delimiters<std::multiset<T...>> {\n    static constexpr delimiters_values<char> values = {\"{\", \", \", \"}\"};\n};\n\ntemplate <typename... T>\nstruct delimiters<std::unordered_set<T...>> {\n    static constexpr delimiters_values<char> values = {\"{\", \", \", \"}\"};\n};\n\ntemplate <typename... T>\nstruct delimiters<std::unordered_multiset<T...>> {\n    static constexpr delimiters_values<char> values = {\"{\", \", \", \"}\"};\n};\n\n// Delimiters for pair and tuple\n\ntemplate <typename... T>\nstruct delimiters<std::pair<T...>> {\n    static constexpr delimiters_values<char> values = {\"(\", \", \", \")\"};\n};\n\ntemplate <typename... T>\nstruct delimiters<std::tuple<T...>> {\n    static constexpr delimiters_values<char> values = {\"(\", \", \", \")\"};\n};\n\n// Type-erasing helper class for easy use of custom delimiters.\n// Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for\n// TChar. Usage: \"cout << pretty_print::custom_delims<MyDelims>(x)\".\n\nstruct custom_delims_base {\n    virtual ~custom_delims_base() {}\n    virtual std::ostream &stream(std::ostream &) = 0;\n};\n\ntemplate <typename T, typename Delims>\nstruct custom_delims_wrapper : custom_delims_base {\n    custom_delims_wrapper(const T &t_) : t(t_) {}\n\n    std::ostream &stream(std::ostream &s) {\n        return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);\n    }\n\nprivate:\n    const T &t;\n};\n\ntemplate <typename Delims>\nstruct custom_delims {\n    template <typename Container>\n    custom_delims(const Container &c) : base(new custom_delims_wrapper<Container, Delims>(c)) {}\n\n    std::unique_ptr<custom_delims_base> base;\n};\n\ntemplate <typename TChar, typename TCharTraits, typename Delims>\ninline std::basic_ostream<TChar, TCharTraits> &operator<<(std::basic_ostream<TChar, TCharTraits> &s,\n                                                          const custom_delims<Delims> &p) {\n    return p.base->stream(s);\n}\n\n}  // namespace utils\n\n// Main magic entry point: An overload snuck into namespace std.\n// Can we do better?\n\nnamespace std {\n// Prints a container to the stream using default delimiters\n\ntemplate <typename T, typename TChar, typename TCharTraits>\ninline typename enable_if<::utils::is_container<T>::value, basic_ostream<TChar, TCharTraits> &>::type operator<<(\n    basic_ostream<TChar, TCharTraits> &stream, const T &container) {\n    return stream << ::utils::print_container_helper<T, TChar, TCharTraits>(container);\n}\n\ntemplate <typename T>\nstring to_string_with_precision(const T a_value, const int n = 6) {\n    ostringstream out;\n    out.precision(n);\n    out << fixed << a_value;\n    return out.str();\n}\n\n}  // namespace std"
  },
  {
    "path": "src/utils/utils.h",
    "content": "#pragma once\n\n#include \"geo.h\"\n#include \"log.h\"\n#include \"prettyprint.h\"\n#include \"enum.h\""
  },
  {
    "path": "toys/iccad2019c/ispd18_sample/ispd18_sample.input.def",
    "content": "VERSION 5.8 ;\nDIVIDERCHAR \"/\" ;\nBUSBITCHARS \"[]\" ;\nDESIGN ispd18_sample ;\nUNITS DISTANCE MICRONS 2000 ;\n\nDIEAREA ( 83600 71820 ) ( 104400 91200 ) ;\n\nROW CORE_ROW_0 CoreSite 83600 71820 N DO 52 BY 1 STEP 400 0\n ;\nROW CORE_ROW_1 CoreSite 83600 75240 FS DO 52 BY 1 STEP 400 0\n ;\nROW CORE_ROW_2 CoreSite 83600 78660 N DO 52 BY 1 STEP 400 0\n ;\nROW CORE_ROW_3 CoreSite 83600 82080 FS DO 52 BY 1 STEP 400 0\n ;\nROW CORE_ROW_4 CoreSite 83600 85500 N DO 52 BY 1 STEP 400 0\n ;\n\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal9 ;\nTRACKS Y 72770 DO 25 STEP 760 LAYER Metal9 ;\nTRACKS Y 72580 DO 33 STEP 570 LAYER Metal8 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal8 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal7 ;\nTRACKS Y 72580 DO 33 STEP 570 LAYER Metal7 ;\nTRACKS Y 72010 DO 51 STEP 380 LAYER Metal6 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal6 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal5 ;\nTRACKS Y 72010 DO 51 STEP 380 LAYER Metal5 ;\nTRACKS Y 72010 DO 51 STEP 380 LAYER Metal4 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal4 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal3 ;\nTRACKS Y 72010 DO 51 STEP 380 LAYER Metal3 ;\nTRACKS Y 72010 DO 51 STEP 380 LAYER Metal2 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal2 ;\nTRACKS X 83800 DO 52 STEP 400 LAYER Metal1 ;\nTRACKS Y 72010 DO 51 STEP 380 LAYER Metal1 ;\n\nCOMPONENTS 22 ;\n- inst2015 NAND3X2 + PLACED ( 88000 78660 ) N ;\n- inst2591 NAND4X2 + PLACED ( 100000 71820 ) N ;\n- inst2908 OR4X1 + PLACED ( 85600 75240 ) FS ;\n- inst3428 BUFX3 + PLACED ( 86000 82080 ) FS ;\n- inst3502 NOR4X2 + PLACED ( 92800 75240 ) FS ;\n- inst3444 BUFX3 + PLACED ( 96800 82080 ) FS ;\n- inst4132 NAND4X1 + PLACED ( 102000 85500 ) N ;\n- inst4183 NOR4X4 + PLACED ( 96800 75240 ) FS ;\n- inst4062 AOI222X1 + PLACED ( 96000 85500 ) N ;\n- inst4678 NOR2X1 + PLACED ( 90800 82080 ) FS ;\n- inst4189 AOI22X2 + PLACED ( 85200 71820 ) N ;\n- inst4597 NAND4X1 + PLACED ( 94400 71820 ) N ;\n- inst4382 NAND4X1 + PLACED ( 84000 78660 ) N ;\n- inst5333 AOI221X1 + PLACED ( 89200 85500 ) N ;\n- inst5638 BUFX6 + PLACED ( 96000 78660 ) N ;\n- inst6286 AO22XL + PLACED ( 100000 78660 ) N ;\n- inst5275 AOI22X1 + PLACED ( 89600 75240 ) FS ;\n- inst5821 NAND3X1 + PLACED ( 84400 85500 ) N ;\n- inst6458 AOI221X2 + PLACED ( 99200 82080 ) FS ;\n- inst6050 NAND4X1 + PLACED ( 97200 71820 ) N ;\n- inst5195 AOI221X1 + PLACED ( 89600 71820 ) N ;\n- inst7234 AO22XL + PLACED ( 93200 82080 ) FS ;\nEND COMPONENTS\n\nPINS 0 ;\nEND PINS\n\nNETS 11 ;\n- net1237\n  ( inst5638 A ) ( inst4678 Y )\n ;\n- net1240\n  ( inst3502 A ) ( inst2015 Y )\n ;\n- net1233\n  ( inst6050 A ) ( inst4189 Y )\n ;\n- net1236\n  ( inst2908 D ) ( inst2591 Y )\n ;\n- net1234\n  ( inst6458 Y ) ( inst4597 B )\n ;\n- net1232\n  ( inst4382 C ) ( inst4062 Y )\n ;\n- net1231\n  ( inst5821 B ) ( inst5275 Y )\n ;\n- net1239\n  ( inst6286 Y ) ( inst5333 C0 )\n ;\n- net1235\n  ( inst4183 A ) ( inst4132 Y )\n ;\n- net1238\n  ( inst3444 Y ) ( inst3428 A )\n ;\n- net1230\n  ( inst7234 Y ) ( inst5195 C0 )\n ;\nEND NETS\n\nEND DESIGN\n"
  },
  {
    "path": "toys/iccad2019c/ispd18_sample/ispd18_sample.input.lef",
    "content": "VERSION 5.8 ;\n\nBUSBITCHARS \"[]\" ;\n\nDIVIDERCHAR \"/\" ;\n\nUNITS\n    DATABASE MICRONS 2000 ;\nEND UNITS\n\nMANUFACTURINGGRID 0.000500 ;\n\nCLEARANCEMEASURE EUCLIDEAN ;\nUSEMINSPACING OBS ON ;\n\nSITE CoreSite\n    CLASS CORE ;\n    SIZE 0.200000 BY 1.710000 ; \nEND CoreSite\n\nLAYER Metal1\n    TYPE ROUTING ;\n    DIRECTION HORIZONTAL ;\n    MINWIDTH 0.060000 ;\n    AREA 0.020000 ;\n    WIDTH 0.060000 ;\n    SPACING 0.060000 ;\n    SPACING 0.090000 ENDOFLINE 0.090000 WITHIN 0.025000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.060000\n      WIDTH  0.100000  0.100000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.190000 0.190000 ;\nEND Metal1\n\nLAYER Via1\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.06 ;\nEND Via1\n\nLAYER Metal2\n    TYPE ROUTING ;\n    DIRECTION VERTICAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal2\n\nLAYER Via2\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via2\n\nLAYER Metal3\n    TYPE ROUTING ;\n    DIRECTION HORIZONTAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal3\n\nLAYER Via3\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via3\n\nLAYER Metal4\n    TYPE ROUTING ;\n    DIRECTION VERTICAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal4\n\nLAYER Via4\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via4\n\nLAYER Metal5\n    TYPE ROUTING ;\n    DIRECTION HORIZONTAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal5\n\nLAYER Via5\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via5\n\nLAYER Metal6\n    TYPE ROUTING ;\n    DIRECTION VERTICAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal6\n\nLAYER Via6\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via6\n\nLAYER Metal7\n    TYPE ROUTING ;\n    DIRECTION HORIZONTAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal7\n\nLAYER Via7\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via7\n\nLAYER Metal8\n    TYPE ROUTING ;\n    DIRECTION VERTICAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.200000 0.200000 ;\nEND Metal8\n\nLAYER Via8\n    TYPE CUT ;\n    SPACING 0.070000 ;\n    WIDTH 0.07 ;\nEND Via8\n\nLAYER Metal9\n    TYPE ROUTING ;\n    DIRECTION HORIZONTAL ;\n    MINWIDTH 0.070000 ;\n    AREA 0.020000 ;\n    WIDTH 0.070000 ;\n    SPACING 0.070000 ;\n    SPACING 0.100000 ENDOFLINE 0.100000 WITHIN 0.035000 ;\n    SPACINGTABLE\n    PARALLELRUNLENGTH\n                       0.000000\n      WIDTH  0.000000  0.070000\n      WIDTH  0.100000  0.150000\n      WIDTH  0.750000  0.250000\n      WIDTH  1.500000  0.450000 ;\n    PITCH 0.330000 0.330000 ;\nEND Metal9\n\nLAYER OVERLAP\n    TYPE OVERLAP ;\nEND OVERLAP\n\nVIA VIA12_1C DEFAULT \n    LAYER Metal1 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\n    LAYER Via1 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal2 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA12_1C\n\nVIA VIA12_1C_H DEFAULT \n    LAYER Metal1 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\n    LAYER Via1 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal2 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA12_1C_H\n\nVIA VIA12_1C_V DEFAULT \n    LAYER Metal1 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via1 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal2 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA12_1C_V\n\nVIA VIA23_1C DEFAULT \n    LAYER Metal2 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via2 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA23_1C\n\nVIA VIA23_1C_H DEFAULT \n    LAYER Metal2 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\n    LAYER Via2 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA23_1C_H\n\nVIA VIA23_1C_V DEFAULT \n    LAYER Metal2 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via2 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal3 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA23_1C_V\n\nVIA VIA23_1ST_N DEFAULT \n    LAYER Metal2 ;\n        RECT -0.035000 -0.065000 0.035000 0.325000 ;\n    LAYER Via2 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA23_1ST_N\n\nVIA VIA23_1ST_S DEFAULT \n    LAYER Metal2 ;\n        RECT -0.035000 -0.325000 0.035000 0.065000 ;\n    LAYER Via2 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA23_1ST_S\n\nVIA VIA34_1C DEFAULT \n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\n    LAYER Via3 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA34_1C\n\nVIA VIA34_1C_H DEFAULT \n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\n    LAYER Via3 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal4 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA34_1C_H\n\nVIA VIA34_1C_V DEFAULT \n    LAYER Metal3 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via3 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA34_1C_V\n\nVIA VIA34_1ST_E DEFAULT \n    LAYER Metal3 ;\n        RECT -0.065000 -0.035000 0.325000 0.035000 ;\n    LAYER Via3 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA34_1ST_E\n\nVIA VIA34_1ST_W DEFAULT \n    LAYER Metal3 ;\n        RECT -0.325000 -0.035000 0.065000 0.035000 ;\n    LAYER Via3 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA34_1ST_W\n\nVIA VIA45_1C DEFAULT \n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via4 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal5 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA45_1C\n\nVIA VIA45_1C_H DEFAULT \n    LAYER Metal4 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\n    LAYER Via4 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal5 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA45_1C_H\n\nVIA VIA45_1C_V DEFAULT \n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via4 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal5 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\nEND VIA45_1C_V\n\nVIA VIA45_1ST_N DEFAULT \n    LAYER Metal4 ;\n        RECT -0.035000 -0.065000 0.035000 0.325000 ;\n    LAYER Via4 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal5 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA45_1ST_N\n\nVIA VIA45_1ST_S DEFAULT \n    LAYER Metal4 ;\n        RECT -0.035000 -0.325000 0.035000 0.065000 ;\n    LAYER Via4 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal5 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA45_1ST_S\n\nVIA VIA5_0_VH DEFAULT \n    LAYER Metal5 ;\n        RECT -0.035000 -0.065000 0.035000 0.065000 ;\n    LAYER Via5 ;\n        RECT -0.035000 -0.035000 0.035000 0.035000 ;\n    LAYER Metal6 ;\n        RECT -0.065000 -0.035000 0.065000 0.035000 ;\nEND VIA5_0_VH\n\nVIA VIA6_0_HV DEFAULT \n    LAYER Metal6 ;\n        RECT -0.260000 -0.200000 0.260000 0.200000 ;\n    LAYER Via6 ;\n        RECT -0.180000 -0.180000 0.180000 0.180000 ;\n    LAYER Metal7 ;\n        RECT -0.200000 -0.260000 0.200000 0.260000 ;\nEND VIA6_0_HV\n\nVIA VIA7_0_VH DEFAULT \n    LAYER Metal7 ;\n        RECT -0.200000 -0.260000 0.200000 0.260000 ;\n    LAYER Via7 ;\n        RECT -0.180000 -0.180000 0.180000 0.180000 ;\n    LAYER Metal8 ;\n        RECT -0.260000 -0.200000 0.260000 0.200000 ;\nEND VIA7_0_VH\n\nVIA VIA8_0_VH DEFAULT \n    LAYER Metal8 ;\n        RECT -0.200000 -0.260000 0.200000 0.260000 ;\n    LAYER Via8 ;\n        RECT -0.180000 -0.180000 0.180000 0.180000 ;\n    LAYER Metal9 ;\n        RECT -0.260000 -0.200000 0.260000 0.200000 ;\nEND VIA8_0_VH\n\n\nMACRO AOI221X2\n    CLASS CORE ;\n    FOREIGN AOI221X2 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 2.600000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.235000 0.625000 0.365000 0.715000 ;\n        RECT 0.285000 0.610000 0.960000 0.690000 ;\n        RECT 0.285000 0.610000 0.365000 0.715000 ;\n        RECT 0.235000 0.625000 0.960000 0.690000 ;\n        END\n    END A0\n    PIN A1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.765000 0.740000 1.065000 ;\n        END\n    END A1\n    PIN B0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.635000 0.625000 1.765000 0.715000 ;\n        RECT 1.240000 0.635000 1.935000 0.715000 ;\n        END\n    END B0\n    PIN B1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.435000 0.815000 1.935000 0.895000 ;\n        END\n    END B1\n    PIN C0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 2.065000 0.815000 2.565000 0.895000 ;\n        END\n    END C0\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 2.600000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 2.600000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.790000 1.140000 0.920000 ;\n        RECT 2.220000 0.995000 2.280000 1.135000 ;\n        RECT 1.080000 0.995000 2.280000 1.055000 ;\n        RECT 1.080000 0.450000 1.140000 1.055000 ;\n        RECT 0.605000 0.450000 2.170000 0.510000 ;\n        END\n    END Y\nEND AOI221X2\n\nMACRO NAND3X2\n    CLASS CORE ;\n    FOREIGN NAND3X2 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.600000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.600000 0.370000 0.735000 ;\n        RECT 1.240000 0.495000 1.300000 0.735000 ;\n        RECT 0.310000 0.495000 1.300000 0.555000 ;\n        RECT 0.310000 0.495000 0.370000 0.735000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.655000 1.140000 0.920000 ;\n        RECT 0.470000 0.655000 1.140000 0.715000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.520000 0.815000 0.765000 0.955000 ;\n        RECT 0.520000 0.815000 0.960000 0.895000 ;\n        END\n    END C\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.600000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.600000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.435000 1.005000 1.565000 1.115000 ;\n        RECT 0.360000 1.055000 0.430000 1.335000 ;\n        RECT 1.505000 0.335000 1.565000 1.115000 ;\n        RECT 1.190000 1.055000 1.250000 1.335000 ;\n        RECT 0.795000 0.335000 1.565000 0.395000 ;\n        RECT 0.780000 1.055000 0.840000 1.335000 ;\n        RECT 0.360000 1.055000 1.565000 1.115000 ;\n        END\n    END Y\nEND NAND3X2\n\nMACRO AOI222X1\n    CLASS CORE ;\n    FOREIGN AOI222X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.800000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.490000 0.340000 0.990000 ;\n        END\n    END A0\n    PIN A1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.220000 0.545000 0.715000 ;\n        END\n    END A1\n    PIN B0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.880000 0.860000 1.095000 1.100000 ;\n        RECT 0.860000 0.755000 0.940000 0.920000 ;\n        RECT 0.880000 0.755000 0.940000 1.100000 ;\n        RECT 0.860000 0.860000 1.095000 0.920000 ;\n        END\n    END B0\n    PIN B1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.620000 0.760000 0.920000 ;\n        RECT 0.680000 0.620000 0.760000 1.100000 ;\n        END\n    END B1\n    PIN C0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.195000 0.790000 1.340000 0.920000 ;\n        RECT 1.195000 0.790000 1.275000 1.225000 ;\n        END\n    END C0\n    PIN C1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.440000 0.620000 1.540000 1.100000 ;\n        END\n    END C1\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.800000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.800000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.450000 0.410000 1.720000 0.520000 ;\n        RECT 1.660000 0.980000 1.740000 1.260000 ;\n        RECT 1.660000 0.410000 1.720000 1.260000 ;\n        RECT 1.375000 1.200000 1.740000 1.260000 ;\n        RECT 1.375000 1.200000 1.435000 1.320000 ;\n        RECT 0.760000 0.460000 1.720000 0.520000 ;\n        RECT 0.760000 0.380000 0.820000 0.520000 ;\n        END\n    END Y\nEND AOI222X1\n\nMACRO NOR4X4\n    CLASS CORE ;\n    FOREIGN NOR4X4 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 3.800000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 0.755000 0.940000 0.950000 ;\n        RECT 0.350000 0.870000 0.940000 0.950000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.725000 0.755000 1.805000 0.895000 ;\n        RECT 1.240000 0.815000 1.805000 0.895000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 2.435000 0.775000 2.570000 0.895000 ;\n        RECT 2.110000 0.815000 2.570000 0.895000 ;\n        END\n    END C\n    PIN D\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 3.105000 0.775000 3.185000 0.895000 ;\n        RECT 2.835000 0.815000 3.420000 0.895000 ;\n        END\n    END D\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 3.800000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 3.800000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.790000 1.140000 0.920000 ;\n        RECT 3.460000 0.515000 3.520000 0.655000 ;\n        RECT 3.405000 0.995000 3.465000 1.135000 ;\n        RECT 3.050000 0.515000 3.110000 0.655000 ;\n        RECT 2.995000 0.995000 3.055000 1.135000 ;\n        RECT 2.640000 0.515000 2.700000 0.655000 ;\n        RECT 2.230000 0.515000 2.290000 0.655000 ;\n        RECT 1.820000 0.515000 1.880000 0.655000 ;\n        RECT 1.410000 0.515000 1.470000 0.655000 ;\n        RECT 1.080000 0.995000 3.465000 1.055000 ;\n        RECT 1.080000 0.595000 1.140000 1.055000 ;\n        RECT 1.000000 0.515000 1.060000 0.655000 ;\n        RECT 0.590000 0.595000 3.520000 0.655000 ;\n        RECT 0.590000 0.515000 0.650000 0.655000 ;\n        END\n    END Y\nEND NOR4X4\n\nMACRO NOR4X2\n    CLASS CORE ;\n    FOREIGN NOR4X2 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 2.000000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.660000 0.980000 1.740000 1.185000 ;\n        RECT 1.680000 0.820000 1.740000 1.185000 ;\n        RECT 0.260000 1.125000 1.740000 1.185000 ;\n        RECT 0.260000 0.820000 0.320000 1.185000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.790000 0.540000 0.920000 ;\n        RECT 1.435000 0.845000 1.495000 1.025000 ;\n        RECT 0.480000 0.965000 1.495000 1.025000 ;\n        RECT 0.480000 0.790000 0.540000 1.025000 ;\n        RECT 0.420000 0.835000 0.540000 0.895000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.275000 0.625000 1.565000 0.705000 ;\n        RECT 1.275000 0.625000 1.335000 0.865000 ;\n        RECT 0.640000 0.805000 1.335000 0.865000 ;\n        END\n    END C\n    PIN D\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.640000 0.625000 1.140000 0.705000 ;\n        END\n    END D\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 2.000000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 2.000000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.860000 1.170000 1.940000 1.345000 ;\n        RECT 1.595000 0.445000 1.715000 0.525000 ;\n        RECT 1.155000 0.445000 1.275000 0.525000 ;\n        RECT 0.715000 0.445000 0.835000 0.525000 ;\n        RECT 1.880000 0.465000 1.940000 1.345000 ;\n        RECT 1.010000 1.285000 1.940000 1.345000 ;\n        RECT 0.345000 0.465000 1.940000 0.525000 ;\n        RECT 0.275000 0.445000 0.395000 0.505000 ;\n        END\n    END Y\nEND NOR4X2\n\nMACRO NAND4X2\n    CLASS CORE ;\n    FOREIGN NAND4X2 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 2.200000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.860000 0.820000 1.940000 1.185000 ;\n        RECT 0.260000 1.125000 1.940000 1.185000 ;\n        RECT 0.260000 0.820000 0.320000 1.185000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.790000 0.540000 0.920000 ;\n        RECT 1.600000 0.845000 1.660000 1.025000 ;\n        RECT 0.480000 0.965000 1.660000 1.025000 ;\n        RECT 0.480000 0.790000 0.540000 1.025000 ;\n        RECT 0.420000 0.835000 0.540000 0.895000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.235000 0.625000 1.395000 0.705000 ;\n        RECT 1.335000 0.625000 1.395000 0.865000 ;\n        RECT 0.685000 0.805000 1.395000 0.865000 ;\n        END\n    END C\n    PIN D\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 0.625000 1.135000 0.705000 ;\n        RECT 0.860000 0.400000 0.940000 0.705000 ;\n        END\n    END D\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 2.200000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 2.200000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 2.060000 1.170000 2.140000 1.345000 ;\n        RECT 2.060000 0.465000 2.120000 1.345000 ;\n        RECT 1.730000 1.285000 1.790000 1.405000 ;\n        RECT 1.260000 1.285000 1.320000 1.405000 ;\n        RECT 1.185000 0.465000 2.120000 0.525000 ;\n        RECT 1.070000 0.445000 1.235000 0.505000 ;\n        RECT 0.790000 1.285000 0.850000 1.405000 ;\n        RECT 0.320000 1.285000 2.140000 1.345000 ;\n        RECT 0.320000 1.285000 0.380000 1.405000 ;\n        END\n    END Y\nEND NAND4X2\n\nMACRO BUFX3\n    CLASS CORE ;\n    FOREIGN BUFX3 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.200000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 0.720000 0.940000 1.220000 ;\n        END\n    END A\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.200000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.200000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.980000 0.340000 1.110000 ;\n        RECT 0.625000 1.050000 0.685000 1.440000 ;\n        RECT 0.585000 0.345000 0.645000 0.465000 ;\n        RECT 0.540000 0.405000 0.645000 0.465000 ;\n        RECT 0.540000 0.405000 0.600000 0.620000 ;\n        RECT 0.260000 0.560000 0.320000 1.110000 ;\n        RECT 0.215000 1.050000 0.685000 1.110000 ;\n        RECT 0.215000 1.050000 0.275000 1.440000 ;\n        RECT 0.175000 0.560000 0.600000 0.620000 ;\n        RECT 0.175000 0.480000 0.235000 0.620000 ;\n        END\n    END Y\nEND BUFX3\n\nMACRO AOI22X2\n    CLASS CORE ;\n    FOREIGN AOI22X2 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 2.200000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.840000 0.635000 1.065000 0.715000 ;\n        RECT 0.840000 0.575000 0.920000 0.715000 ;\n        RECT 0.480000 0.575000 0.920000 0.655000 ;\n        RECT 0.480000 0.575000 0.560000 0.705000 ;\n        RECT 0.235000 0.625000 0.560000 0.705000 ;\n        END\n    END A0\n    PIN A1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.655000 0.715000 0.745000 0.960000 ;\n        END\n    END A1\n    PIN B0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.840000 0.580000 1.960000 0.895000 ;\n        RECT 1.840000 0.815000 2.165000 0.895000 ;\n        RECT 1.500000 0.580000 1.960000 0.640000 ;\n        RECT 1.500000 0.580000 1.560000 0.715000 ;\n        RECT 1.325000 0.655000 1.560000 0.715000 ;\n        END\n    END B0\n    PIN B1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.660000 0.740000 1.740000 1.030000 ;\n        END\n    END B1\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 2.200000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 2.200000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.035000 0.815000 1.225000 0.895000 ;\n        RECT 1.840000 0.995000 1.900000 1.165000 ;\n        RECT 1.430000 1.105000 1.900000 1.165000 ;\n        RECT 1.430000 0.835000 1.490000 1.165000 ;\n        RECT 1.165000 0.415000 1.225000 0.895000 ;\n        RECT 1.035000 0.835000 1.490000 0.895000 ;\n        RECT 0.710000 0.415000 1.685000 0.475000 ;\n        END\n    END Y\nEND AOI22X2\n\nMACRO OR4X1\n    CLASS CORE ;\n    FOREIGN OR4X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.400000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.475000 1.140000 0.765000 ;\n        RECT 0.850000 0.685000 1.140000 0.765000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.980000 0.590000 1.070000 ;\n        RECT 0.510000 0.660000 0.590000 1.070000 ;\n        RECT 0.460000 0.980000 0.540000 1.110000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.330000 0.590000 0.410000 0.870000 ;\n        RECT 0.260000 0.790000 0.410000 0.870000 ;\n        RECT 0.260000 0.790000 0.340000 1.020000 ;\n        END\n    END C\n    PIN D\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.060000 0.590000 0.160000 0.795000 ;\n        RECT 0.030000 0.735000 0.120000 1.040000 ;\n        RECT 0.060000 0.590000 0.120000 1.040000 ;\n        RECT 0.030000 0.735000 0.160000 0.795000 ;\n        END\n    END D\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.400000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.400000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.240000 0.410000 1.340000 0.540000 ;\n        RECT 1.240000 0.395000 1.300000 1.385000 ;\n        END\n    END Y\nEND OR4X1\n\nMACRO NAND3X1\n    CLASS CORE ;\n    FOREIGN NAND3X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.000000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.600000 0.340000 1.100000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.480000 0.480000 0.560000 0.890000 ;\n        RECT 0.460000 0.410000 0.540000 0.540000 ;\n        RECT 0.480000 0.410000 0.540000 0.890000 ;\n        RECT 0.460000 0.480000 0.560000 0.540000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.600000 0.740000 1.100000 ;\n        END\n    END C\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.000000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.000000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 1.200000 0.940000 1.490000 ;\n        RECT 0.860000 0.440000 0.920000 1.490000 ;\n        RECT 0.745000 0.440000 0.920000 0.500000 ;\n        RECT 0.745000 0.380000 0.805000 0.500000 ;\n        RECT 0.425000 1.200000 0.940000 1.260000 ;\n        RECT 0.425000 1.200000 0.485000 1.480000 ;\n        END\n    END Y\nEND NAND3X1\n\nMACRO NOR2X1\n    CLASS CORE ;\n    FOREIGN NOR2X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 0.800000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.570000 0.340000 1.070000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.980000 0.560000 1.085000 ;\n        RECT 0.480000 0.730000 0.560000 1.085000 ;\n        RECT 0.460000 0.980000 0.540000 1.210000 ;\n        RECT 0.480000 0.730000 0.540000 1.210000 ;\n        END\n    END B\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 0.800000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 0.800000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.600000 0.740000 0.730000 ;\n        RECT 0.660000 0.570000 0.720000 1.290000 ;\n        RECT 0.460000 0.570000 0.720000 0.630000 ;\n        RECT 0.460000 0.490000 0.520000 0.630000 ;\n        END\n    END Y\nEND NOR2X1\n\nMACRO AOI221X1\n    CLASS CORE ;\n    FOREIGN AOI221X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.800000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.450000 0.340000 0.950000 ;\n        END\n    END A0\n    PIN A1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.220000 0.540000 0.720000 ;\n        END\n    END A1\n    PIN B0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.580000 1.140000 1.080000 ;\n        END\n    END B0\n    PIN B1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 0.580000 0.940000 1.080000 ;\n        END\n    END B1\n    PIN C0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.260000 0.650000 1.380000 0.730000 ;\n        RECT 1.260000 0.580000 1.340000 1.040000 ;\n        END\n    END C0\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.800000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.800000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.460000 0.220000 1.540000 0.480000 ;\n        RECT 1.480000 0.220000 1.540000 1.460000 ;\n        RECT 0.870000 0.420000 1.540000 0.480000 ;\n        RECT 0.800000 0.400000 0.920000 0.460000 ;\n        END\n    END Y\nEND AOI221X1\n\nMACRO NAND4X1\n    CLASS CORE ;\n    FOREIGN NAND4X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.200000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.230000 0.650000 0.340000 0.920000 ;\n        RECT 0.030000 0.840000 0.340000 0.920000 ;\n        END\n    END A\n    PIN B\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.480000 0.460000 0.560000 0.890000 ;\n        RECT 0.460000 0.460000 0.560000 0.540000 ;\n        RECT 0.460000 0.410000 0.540000 0.540000 ;\n        RECT 0.480000 0.410000 0.540000 0.890000 ;\n        END\n    END B\n    PIN C\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.220000 0.740000 0.830000 ;\n        END\n    END C\n    PIN D\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 0.410000 0.940000 0.910000 ;\n        END\n    END D\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.200000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.200000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.040000 0.790000 1.140000 1.080000 ;\n        RECT 1.040000 0.540000 1.100000 1.080000 ;\n        RECT 0.790000 1.020000 0.850000 1.300000 ;\n        RECT 0.370000 1.020000 1.140000 1.080000 ;\n        RECT 0.370000 1.020000 0.430000 1.300000 ;\n        END\n    END Y\nEND NAND4X1\n\nMACRO AOI22X1\n    CLASS CORE ;\n    FOREIGN AOI22X1 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.400000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.600000 0.340000 1.100000 ;\n        END\n    END A0\n    PIN A1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.480000 0.270000 0.560000 0.700000 ;\n        RECT 0.460000 0.270000 0.560000 0.350000 ;\n        RECT 0.460000 0.220000 0.540000 0.350000 ;\n        RECT 0.480000 0.220000 0.540000 0.700000 ;\n        END\n    END A1\n    PIN B0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.450000 1.140000 0.950000 ;\n        END\n    END B0\n    PIN B1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.860000 0.410000 0.940000 0.910000 ;\n        END\n    END B1\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.400000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.400000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.980000 0.740000 1.110000 ;\n        RECT 0.935000 1.050000 0.995000 1.190000 ;\n        RECT 0.680000 0.370000 0.740000 1.110000 ;\n        RECT 0.660000 1.050000 0.995000 1.110000 ;\n        END\n    END Y\nEND AOI22X1\n\nMACRO BUFX6\n    CLASS CORE ;\n    FOREIGN BUFX6 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.800000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.460000 0.570000 1.540000 1.070000 ;\n        END\n    END A\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.800000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.800000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.060000 0.790000 0.140000 0.975000 ;\n        RECT 0.060000 0.350000 0.130000 1.370000 ;\n        RECT 0.890000 0.915000 0.950000 1.370000 ;\n        RECT 0.890000 0.350000 0.950000 0.655000 ;\n        RECT 0.480000 0.915000 0.540000 1.370000 ;\n        RECT 0.480000 0.350000 0.540000 0.655000 ;\n        RECT 0.060000 0.915000 0.950000 0.975000 ;\n        RECT 0.060000 0.595000 0.950000 0.655000 ;\n        END\n    END Y\nEND BUFX6\n\nMACRO AO22XL\n    CLASS CORE ;\n    FOREIGN AO22XL 0.000000 0.000000 ;\n    ORIGIN 0.000000 0.000000 ;\n    SIZE 1.600000 BY 1.710000 ;\n    SYMMETRY X Y ;\n    SITE CoreSite ; \n    PIN A0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.260000 0.600000 0.340000 1.100000 ;\n        END\n    END A0\n    PIN A1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.460000 0.230000 0.540000 0.730000 ;\n        END\n    END A1\n    PIN B0\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.060000 0.790000 1.140000 1.230000 ;\n        RECT 1.000000 0.790000 1.140000 0.870000 ;\n        END\n    END B0\n    PIN B1\n        DIRECTION INPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.660000 0.595000 0.740000 1.095000 ;\n        END\n    END B1\n    PIN VDD\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE POWER ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 1.650000 1.600000 1.710000 ;\n        END\n    END VDD\n    PIN VSS\n        DIRECTION INOUT ;\n        SHAPE ABUTMENT ;\n        USE GROUND ;\n        PORT\n        LAYER Metal1 ;\n        RECT 0.000000 0.000000 1.600000 0.060000 ;\n        END\n    END VSS\n    PIN Y\n        DIRECTION OUTPUT ;\n        USE SIGNAL ;\n        PORT\n        LAYER Metal1 ;\n        RECT 1.260000 0.910000 1.510000 0.990000 ;\n        RECT 1.260000 0.600000 1.340000 0.990000 ;\n        RECT 1.250000 0.600000 1.340000 0.680000 ;\n        RECT 1.250000 0.405000 1.330000 0.680000 ;\n        RECT 1.260000 0.405000 1.330000 0.990000 ;\n        END\n    END Y\nEND AO22XL\n\nEND LIBRARY\n"
  }
]