diff --git a/macbuild/ReadMe.md b/macbuild/ReadMe.md index 9fea55364..79f408a12 100644 --- a/macbuild/ReadMe.md +++ b/macbuild/ReadMe.md @@ -1,12 +1,12 @@ -Relevant KLayout version: 0.29.11
+Relevant KLayout version: 0.30.2
Author: Kazzz-S
-Last modified: 2025-01-19
+Last modified: 2025-05-30
# 1. Introduction -This directory **`macbuild`** contains various files required for building KLayout (http://www.klayout.de/) version 0.29.11 or later for different 64-bit macOS, including: -* Sonoma (14.x) : the primary development environment -* Ventura (13.x) : experimental -* Sequoia (15.x) : -- ditto -- +This directory **`macbuild`** contains various files required for building KLayout (http://www.klayout.de/) version 0.30.2 or later for different 64-bit macOS, including: +* Sequoia (15.x) : the primary development environment +* Sonoma (14.x) : experimental +* Ventura (13.x) : -- ditto -- Building KLayout for the previous operating systems listed below has been discontinued.
Pre-built DMG packages are also not provided.
@@ -18,7 +18,7 @@ Pre-built DMG packages are also not provided.
* Sierra (10.12) * El Capitan (10.11) -Throughout this document, the primary target machine is **Intel x86_64** with **macOS Sonoma**.
+Throughout this document, the primary target machine is **Intel x86_64** with **macOS Sequoia**.
All Apple (M1|M2|M3|M4) chips are still untested, as the author does not own an (M1|M2|M3|M4) Mac.
However, some kind volunteers told me they successfully built on an Apple silicon machine.
@@ -43,7 +43,7 @@ If you have installed Anaconda3 under $HOME/opt/anaconda3/, make a symbolic link /Applications/anaconda3/ ---> $HOME/opt/anaconda3/ ``` -The migration work to "Qt6" is ongoing. You can try to use it; however, you might encounter some build and runtime errors.
+The migration work to "Qt6" is ongoing. You can try to use it; however, you might encounter some build or runtime errors.
If you use **Homebrew** to build KLayout >= 0.29.0, you need "Qt6" to address [the compilation issue](https://github.com/KLayout/klayout/issues/1599).
I have also tried migrating to "Python 3.12.x" (earlier, Python 3.11.x) in this version. @@ -70,7 +70,7 @@ The operating system type is detected automatically. ``` ----------------------------------------------------------------------------------------------------------- << Usage of 'build4mac.py' >> - for building KLayout 0.29.11 or later on different Apple macOS platforms. + for building KLayout 0.30.2 or later on different Apple macOS platforms. $ [python] ./build4mac.py option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details) | default value @@ -123,7 +123,7 @@ $ [python] ./build4mac.py ``` # 6. Use-cases -In this section, the actual file and directory names are those obtained on macOS Sonoma.
+In this section, the actual file and directory names are those obtained on macOS Sequoia.
On different OS, those names differ accordingly. ### 6A. Standard build using the OS-bundled Ruby and Python with MacPorts Qt5 @@ -141,7 +141,7 @@ Confirm that you have: ``` As of this writing, the provided Python version is `3.9.6`. -1. Invoke **`build4mac.py`** with the following options: **((Notes))** These options are the default values for Sonoma, Ventura, and Sequioa. +1. Invoke **`build4mac.py`** with the following options: **((Notes))** These options are the default values for Sequoia, Sonoma, and Ventura. ``` $ cd /where/'build.sh'/exists $ ./build4mac.py -q qt5macports -r sys -p sys @@ -154,7 +154,7 @@ $ ./build4mac.py -q qt5macports -r sys -p sys $ ./build4mac.py -q qt5macports -r sys -p sys -y ``` The application bundle **`klayout.app`** is located under:
- **`ST-qt5MP.pkg.macos-Sonoma-release-RsysPsys`** directory, where + **`ST-qt5MP.pkg.macos-Sequoia-release-RsysPsys`** directory, where * "ST-" means this is a standard package. * "qt5MP" means that Qt5 from MacPorts is used. * "RsysPsys" means that Ruby is 2.6 provided by OS; Python is 3.9 provided by OS. @@ -185,7 +185,7 @@ $ ./build4mac.py -q qt5macports -r mp33 -p mp312 $ ./build4mac.py -q qt5macports -r mp33 -p mp312 -Y ``` The application bundle **`klayout.app`** is located under:
- **`LW-qt5MP.pkg.macos-Sonoma-release-Rmp33Pmp312`** directory, where + **`LW-qt5MP.pkg.macos-Sequoia-release-Rmp33Pmp312`** directory, where * "LW-" means this is a lightweight package. * "qt5MP" means that Qt5 from MacPorts is used. * "Rmp33Pmp312" means that Ruby is 3.3 from MacPorts; Python is 3.12 from MacPorts. @@ -218,7 +218,7 @@ $ ./build4mac.py -q qt6brew -r hb34 -p hb312 $ ./build4mac.py -q qt6brew -r hb34 -p hb312 -Y ``` The application bundle **`klayout.app`** is located under:
- **`LW-qt6Brew.pkg.macos-Sonoma-release-Rhb34Phb312`** directory, where + **`LW-qt6Brew.pkg.macos-Sequoia-release-Rhb34Phb312`** directory, where * "LW-" means this is a lightweight package. * "qt6Brew" means that Qt6 from Homebrew is used. * "Rhb34Phb312" means that Ruby is 3.4 from Homebrew; Python is 3.12 from Homebrew. @@ -258,7 +258,7 @@ $ ./build4mac.py -q qt6brew -r sys -p hb311 $ ./build4mac.py -q qt6brew -r sys -p hb311 -y ``` The application bundle **`klayout.app`** is located under:
- **`HW-qt6Brew.pkg.macos-Sonoma-release-RsysPhb311`** directory, where + **`HW-qt6Brew.pkg.macos-Sequoia-release-RsysPhb311`** directory, where * "HW-" means this is a heavyweight package because both Qt6 and Python Frameworks are deployed. * "qt6Brew" means that Qt6 from Homebrew is used. * "RsysPhb311" means that Ruby is OS-bundled; Python is 3.11 from Homebrew. @@ -300,14 +300,14 @@ $ ./build4mac.py -q qt5macports -r sys -p hb311 $ ./build4mac.py -q qt5macports -r sys -p hb311 -y ``` The application bundle **`klayout.app`** is located under:
- **`HW-qt5MP.pkg.macos-Sonoma-release-RsysPhb311`** directory, where + **`HW-qt5MP.pkg.macos-Sequoia-release-RsysPhb311`** directory, where * "HW-" means this is a heavyweight package because both Qt5 and Python Frameworks are deployed. * "qt5MP" means that Qt5 from MacPorts is used. * "RsysPhb311" means that Ruby is OS-bundled; Python is 3.11 from Homebrew. 4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation. ### 6F. Fully Anaconda3-flavored build with Anaconda3 Ruby 3.2 and Anaconda3 Python 3.12 -0. Install Anaconda3 (Anaconda3-2024.06-1-MacOSX-x86_64.pkg), then install Ruby 3.2 and libgit2 by +0. Install Anaconda3 (Anaconda3-2024.10-1-MacOSX-x86_64.pkg), then install Ruby 3.2 and libgit2 by ``` $ conda install ruby=3.2.2 $ conda install libgit2=1.6.4 @@ -327,7 +327,7 @@ $ ./build4mac.py -q qt5ana3 -r ana3 -p ana3 $ ./build4mac.py -q qt5ana3 -r ana3 -p ana3 -Y ``` The application bundle **`klayout.app`** is located under:
- **`LW-qt5Ana3.pkg.macos-Sonoma-release-Rana3Pana3`** directory, where + **`LW-qt5Ana3.pkg.macos-Sequoia-release-Rana3Pana3`** directory, where * "LW-" means this is a lightweight package. * "qt5Ana3" means that Qt5 from Anaconda3 is used. * "Rana3Pana3" means that Ruby (3.2) is from Anaconda3; Python (3.12) is from Anaconda3. @@ -394,11 +394,11 @@ makeDMG4mac.py -> macbuild/makeDMG4mac.py 2. Invoke **`makeDMG4mac.py`** with -p and -m options, for example, ``` $ cd /where/'build.sh'/exists -$ ./makeDMG4mac.py -p LW-qt5MP.pkg.macos-Sonoma-release-Rmp33Pmp312 -m +$ ./makeDMG4mac.py -p LW-qt5MP.pkg.macos-Sequoia-release-Rmp33Pmp312 -m ``` This command will generate the two files below:
-* **`LW-klayout-0.29.11-macOS-Sonoma-1-qt5MP-Rmp33Pmp312.dmg`** ---(1) the main DMG file -* **`LW-klayout-0.29.11-macOS-Sonoma-1-qt5MP-Rmp33Pmp312.dmg.md5`** ---(2) MD5-value text file +* **`LW-klayout-0.30.2-macOS-Sequoia-1-qt5MP-Rmp33Pmp312.dmg`** ---(1) the main DMG file +* **`LW-klayout-0.30.2-macOS-Sequoia-1-qt5MP-Rmp33Pmp312.dmg.md5`** ---(2) MD5-value text file # Known issues Because we assume some specific versions of non-OS-standard Ruby and Python, updating Homebrew, MacPorts, or Anaconda3 may cause build- and link errors.
diff --git a/macbuild/Resources/script-bundle-A.zip b/macbuild/Resources/script-bundle-A.zip index 8fe31e938..1260f8645 100644 Binary files a/macbuild/Resources/script-bundle-A.zip and b/macbuild/Resources/script-bundle-A.zip differ diff --git a/macbuild/Resources/script-bundle-B.zip b/macbuild/Resources/script-bundle-B.zip index e48f71440..45ca4140b 100644 Binary files a/macbuild/Resources/script-bundle-B.zip and b/macbuild/Resources/script-bundle-B.zip differ diff --git a/macbuild/Resources/script-bundle-H.zip b/macbuild/Resources/script-bundle-H.zip index 40ecf395c..9cd7530f7 100644 Binary files a/macbuild/Resources/script-bundle-H.zip and b/macbuild/Resources/script-bundle-H.zip differ diff --git a/macbuild/Resources/script-bundle-P.zip b/macbuild/Resources/script-bundle-P.zip index a07c44ac9..4a29233d1 100644 Binary files a/macbuild/Resources/script-bundle-P.zip and b/macbuild/Resources/script-bundle-P.zip differ diff --git a/macbuild/Resources/script-bundle-S.zip b/macbuild/Resources/script-bundle-S.zip index 319b45b55..9addf53ae 100644 Binary files a/macbuild/Resources/script-bundle-S.zip and b/macbuild/Resources/script-bundle-S.zip differ diff --git a/macbuild/build4mac.py b/macbuild/build4mac.py index e5db7b1e6..b77691061 100755 --- a/macbuild/build4mac.py +++ b/macbuild/build4mac.py @@ -5,7 +5,7 @@ # File: "macbuild/build4mac.py" # # The top Python script for building KLayout (http://www.klayout.de/index.php) -# version 0.29.11 or later on different Apple Mac OSX platforms. +# version 0.30.2 or later on different Apple Mac OSX platforms. #=============================================================================== import sys import os @@ -45,7 +45,7 @@ def GenerateUsage(platform): usage = "\n" usage += "-----------------------------------------------------------------------------------------------------------\n" usage += "<< Usage of 'build4mac.py' >>\n" - usage += " for building KLayout 0.29.11 or later on different Apple macOS platforms.\n" + usage += " for building KLayout 0.30.2 or later on different Apple macOS platforms.\n" usage += "\n" usage += "$ [python] ./build4mac.py\n" usage += " option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details) | default value\n" @@ -847,29 +847,30 @@ def Build_pymod_wheel(parameters): cmd3_args = " \\\n" cmd4_args = " -m setup clean --all \\\n" - #-------------------------------------------------------------------- + #----------------------------------------------------------------------------------- # [4] Make the consolidated command lines - #-------------------------------------------------------------------- + # "caffeinate" makes the CPU run at full speed even when the screen is locked. + #----------------------------------------------------------------------------------- command1 = "time" - command1 += " \\\n %s \\\n" % parameters['python'] + command1 += " \\\n caffeinate -i %s \\\n" % parameters['python'] command1 += cmd1_args command1 += " 2>&1 | tee -a %s; \\\n" % parameters['logfile'] command1 += " test ${PIPESTATUS[0]} -eq 0" # tee always exits with 0 command2 = "time" - command2 += " \\\n %s \\\n" % parameters['python'] + command2 += " \\\n caffeinate -i %s \\\n" % parameters['python'] command2 += cmd2_args command2 += " 2>&1 | tee -a %s; \\\n" % parameters['logfile'] command2 += " test ${PIPESTATUS[0]} -eq 0" # tee always exits with 0 command3 = "time" - command3 += " \\\n %s \\\n" % deloc_cmd + command3 += " \\\n caffeinate -i %s \\\n" % deloc_cmd command3 += cmd3_args command3 += " 2>&1 | tee -a %s; \\\n" % parameters['logfile'] command3 += " test ${PIPESTATUS[0]} -eq 0" # tee always exits with 0 command4 = "time" - command4 += " \\\n %s \\\n" % parameters['python'] + command4 += " \\\n caffeinate -i %s \\\n" % parameters['python'] command4 += cmd4_args command4 += " 2>&1 | tee -a %s; \\\n" % parameters['logfile'] command4 += " test ${PIPESTATUS[0]} -eq 0" # tee always exits with 0 @@ -923,10 +924,10 @@ def Build_pymod_wheel(parameters): # Refer to: https://github.com/Kazzz-S/klayout/issues/49#issuecomment-1432154118 # https://pypi.org/project/delocate/ #--------------------------------------------------------------------------------------------------------- - cmd3_args = glob.glob( "dist/*.whl" ) # like ['dist/klayout-0.29.7-cp312-cp312-macosx_12_0_x86_64.whl'] + cmd3_args = glob.glob( "dist/*.whl" ) # like ['dist/klayout-0.30.2-cp312-cp312-macosx_10_15_x86_64.whl'] if len(cmd3_args) == 1: command3 = "time" - command3 += " \\\n %s \\\n" % deloc_cmd + command3 += " \\\n caffeinate -i %s \\\n" % deloc_cmd command3 += " %s \\\n" % cmd3_args[0] command3 += " 2>&1 | tee -a %s; \\\n" % parameters['logfile'] command3 += " test ${PIPESTATUS[0]} -eq 0" # tee always exits with 0 @@ -953,13 +954,13 @@ def Build_pymod_wheel(parameters): #------------------------------------------------------------------------ # [5-C] Forcibly change the wheel file name for anaconda3 # Ref. https://github.com/Kazzz-S/klayout/issues/53 - # original: klayout-0.29.7-cp312-cp312-macosx_12_0_x86_64.whl + # original: klayout-0.30.2-cp312-cp312-macosx_10_15_x86_64.whl # | # V - # new: klayout-0.29.7-cp312-cp312-macosx_10_9_x86_64.whl + # new: klayout-0.30.2-cp312-cp312-macosx_10_9_x86_64.whl #------------------------------------------------------------------------ if whlTarget == "ana3": - wheels = glob.glob( "dist/*.whl" ) # like ['dist/klayout-0.29.7-cp312-cp312-macosx_12_0_x86_64.whl'] + wheels = glob.glob( "dist/*.whl" ) # like ['dist/klayout-0.30.2-cp312-cp312-macosx_10_15_x86_64.whl'] if not len(wheels) == 1: print( "", file=sys.stderr ) print( "-------------------------------------------------------------", file=sys.stderr ) @@ -1114,11 +1115,12 @@ def Run_Build_Command(config, parameters): else: cmd_args += " \\\n -nopython" - #----------------------------------------------------- + #----------------------------------------------------------------------------------- # [4] Make the consolidated command line - #----------------------------------------------------- + # "caffeinate" makes the CPU run at full speed even when the screen is locked. + #----------------------------------------------------------------------------------- command = "time" - command += " \\\n %s" % parameters['build_cmd'] + command += " \\\n caffeinate -i %s" % parameters['build_cmd'] command += cmd_args command += " 2>&1 | tee %s; \\\n" % parameters['logfile'] command += "test ${PIPESTATUS[0]} -eq 0" # tee always exits with 0 @@ -1831,33 +1833,33 @@ def Deploy_Binaries_For_Bundle(config, parameters): #----------------------------------------------------------------------------------------------- # [9] Special deployment of Python3.11 from Homebrew - # To use Python3.1 from Homebrew on Sonoma... + # To use Python3.11 from Homebrew on Sequoia... # in "/usr/local/opt/python@3.11/lib/" # Python.framework -> ../Frameworks/Python.framework/ <=== this symbolic was needed # pkgconfig/ # # Use the "python3HB.py" tool to make different symbolic links [*] including the above one. - # Sonoma{kazzz-s} lib (1)% pwd + # Sequoia{kazzz-s} lib (1)% pwd # /usr/local/opt/python@3.11/lib - # Sonoma{kazzz-s} lib (2)% ll + # Sequoia{kazzz-s} lib (2)% ll # total 0 # drwxr-xr-x 4 kazzz-s admin 128 9 21 23:03 . # drwxr-xr-x 14 kazzz-s admin 448 9 21 18:33 .. # [*] lrwxr-xr-x 1 kazzz-s admin 31 9 21 23:03 Python.framework -> ../Frameworks/Python.framework/ # drwxr-xr-x 4 kazzz-s admin 128 9 7 10:03 pkgconfig # - # Sonoma{kazzz-s} Python.framework (3)% pwd + # Sequoia{kazzz-s} Python.framework (3)% pwd # /usr/local/opt/python@3.11/Frameworks/Python.framework/Versions - # Sonoma{kazzz-s} Versions (4)% ll + # Sequoia{kazzz-s} Versions (4)% ll # total 0 # drwxr-xr-x 4 kazzz-s admin 128 9 21 23:03 . # drwxr-xr-x 6 kazzz-s admin 192 9 21 23:03 .. # drwxr-xr-x 9 kazzz-s admin 288 9 7 10:03 3.11 # [*] lrwxr-xr-x 1 kazzz-s admin 5 9 21 23:03 Current -> 3.11/ # - # Sonoma{kazzz-s} Python.framework (5)% pwd + # Sequoia{kazzz-s} Python.framework (5)% pwd # /usr/local/opt/python@3.11/Frameworks/Python.framework - # Sonoma{kazzz-s} Python.framework (6)% ll + # Sequoia{kazzz-s} Python.framework (6)% ll # total 0 # drwxr-xr-x 6 kazzz-s admin 192 9 21 23:03 . # drwxr-xr-x 3 kazzz-s admin 96 9 7 10:03 .. diff --git a/macbuild/build4mac_env.py b/macbuild/build4mac_env.py index e3527edf6..cac9623de 100755 --- a/macbuild/build4mac_env.py +++ b/macbuild/build4mac_env.py @@ -6,7 +6,7 @@ # # Here are dictionaries of ... # different modules for building KLayout (http://www.klayout.de/index.php) -# version 0.29.11 or later on different Apple Mac OSX platforms. +# version 0.30.2 or later on different Apple Mac OSX platforms. # # This file is imported by 'build4mac.py' script. #=============================================================================== diff --git a/macbuild/build4mac_util.py b/macbuild/build4mac_util.py index 2fabd423b..7acc1fe47 100755 --- a/macbuild/build4mac_util.py +++ b/macbuild/build4mac_util.py @@ -6,7 +6,7 @@ # # Here are utility functions and classes ... # for building KLayout (http://www.klayout.de/index.php) -# version 0.29.7 or later on different Apple Mac OSX platforms. +# version 0.30.2 or later on different Apple Mac OSX platforms. # # This file is imported by 'build4mac.py' script. #======================================================================================== diff --git a/macbuild/macQAT.py b/macbuild/macQAT.py index 97ccd563a..e0a0ab90a 100755 --- a/macbuild/macQAT.py +++ b/macbuild/macQAT.py @@ -5,7 +5,7 @@ # File: "macbuild/macQAT.py" # # The top Python script to run "ut_runner" after building KLayout -# (http://www.klayout.de/index.php) version 0.29.7 or later on different +# (http://www.klayout.de/index.php) version 0.30.2 or later on different # Apple Mac OSX platforms. # # This script must be copied to a "*.macQAT/" directory to run. diff --git a/macbuild/macQAT.sh b/macbuild/macQAT.sh index 5f1e5eb90..162c3765c 100755 --- a/macbuild/macQAT.sh +++ b/macbuild/macQAT.sh @@ -4,7 +4,7 @@ # File: "macbuild/macQAT.sh" # # The top Bash script to run "ut_runner" after building KLayout -# (http://www.klayout.de/index.php) version 0.29.7 or later on different +# (http://www.klayout.de/index.php) version 0.30.2 or later on different # Apple Mac OSX platforms. # # This script must be copied to a "*.macQAT/" directory to run. diff --git a/macbuild/macQAT2.sh b/macbuild/macQAT2.sh index 42f0763fd..0736cc1b7 100755 --- a/macbuild/macQAT2.sh +++ b/macbuild/macQAT2.sh @@ -4,7 +4,7 @@ # File: "macbuild/macQAT2.sh" # # The top Bash script to run "ut_runner" after building KLayout -# (http://www.klayout.de/index.php) version 0.29.7 or later on different +# (http://www.klayout.de/index.php) version 0.30.2 or later on different # Apple Mac OSX platforms. # # This script must be copied to a directory that can be found in $PATH. diff --git a/macbuild/makeDMG4mac.py b/macbuild/makeDMG4mac.py index b7e7aa9da..7c62caab3 100755 --- a/macbuild/makeDMG4mac.py +++ b/macbuild/makeDMG4mac.py @@ -78,13 +78,13 @@ def SetGlobals(): Usage = "\n" Usage += "---------------------------------------------------------------------------------------------------------\n" Usage += "<< Usage of 'makeDMG4mac.py' >>\n" - Usage += " for making a DMG file of KLayout 0.29.11 or later on different Apple macOS platforms.\n" + Usage += " for making a DMG file of KLayout 0.30.2 or later on different Apple macOS platforms.\n" Usage += "\n" Usage += "$ [python] ./makeDMG4mac.py\n" Usage += " option & argument : descriptions | default value\n" Usage += " ----------------------------------------------------------------------------------+-----------------\n" Usage += " <-p|--pkg > : package directory created by `build4mac.py` with [-y|-Y] | ``\n" - Usage += " : like 'LW-qt5MP.pkg.macos-Monterey-release-Rmp33Pmp311' | \n" + Usage += " : like 'LW-qt5MP.pkg.macos-Sequoia-release-Rmp33Pmp312' | \n" Usage += " <-c|--clean> : clean the work directory | disabled\n" Usage += " <-m|--make> : make a compressed DMG file | disabled\n" Usage += " : <-c|--clean> and <-m|--make> are mutually exclusive | \n" @@ -218,17 +218,17 @@ def SetGlobals(): ## To check the contents of the package directory # # The package directory name should look like: -# * ST-qt5MP.pkg.macos-Sonoma-release-RsysPsys -# * LW-qt5Ana3.pkg.macos-Sonoma-release-Rana3Pana3 -# * LW-qt6Brew.pkg.macos-Sonoma-release-Rhb34Phb312 --- (1) -# * LW-qt5MP.pkg.macos-Sonoma-release-Rmp33Pmp312 -# * HW-qt6Brew.pkg.macos-Sonoma-release-RsysPhb311 +# * ST-qt5MP.pkg.macos-Sequoia-release-RsysPsys +# * LW-qt5Ana3.pkg.macos-Sequoia-release-Rana3Pana3 +# * LW-qt6Brew.pkg.macos-Sequoia-release-Rhb34Phb312 --- (1) +# * LW-qt5MP.pkg.macos-Sequoia-release-Rmp33Pmp312 +# * HW-qt6Brew.pkg.macos-Sequoia-release-RsysPhb311 # -# * ST-qt6MP.pkg.macos-Sonoma-release-RsysPsys -# * LW-qt6MP.pkg.macos-Sonoma-release-Rmp33Pmp312 +# * ST-qt6MP.pkg.macos-Sequoia-release-RsysPsys +# * LW-qt6MP.pkg.macos-Sequoia-release-Rmp33Pmp312 # # Generated DMG will be, for example, -# (1) ---> LW-klayout-0.29.7-macOS-Sonoma-1-qt6Brew-Rhb34Phb312.dmg +# (1) ---> LW-klayout-0.30.2-macOS-Sequoia-1-qt6Brew-Rhb34Phb312.dmg # # @return on success, positive integer in [MB] that tells approx. occupied disc space; # on failure, -1 @@ -268,15 +268,15 @@ def CheckPkgDirectory(): #----------------------------------------------------------------------------------------------- # [2] Identify (Qt, Ruby, Python) from PkgDir - # * ST-qt5MP.pkg.macos-Sonoma-release-RsysPsys - # * LW-qt5Ana3.pkg.macos-Sonoma-release-Rana3Pana3 - # * LW-qt6Brew.pkg.macos-Sonoma-release-Rhb34Phb312 - # * LW-qt5MP.pkg.macos-Sonoma-release-Rmp33Pmp312 - # * HW-qt6Brew.pkg.macos-Sonoma-release-RsysPhb311 - # * EX-qt5MP.pkg.macos-Sonoma-release-Rhb34Pmp312 + # * ST-qt5MP.pkg.macos-Sequoia-release-RsysPsys + # * LW-qt5Ana3.pkg.macos-Sequoia-release-Rana3Pana3 + # * LW-qt6Brew.pkg.macos-Sequoia-release-Rhb34Phb312 + # * LW-qt5MP.pkg.macos-Sequoia-release-Rmp33Pmp312 + # * HW-qt6Brew.pkg.macos-Sequoia-release-RsysPhb311 + # * EX-qt5MP.pkg.macos-Sequoia-release-Rhb34Pmp312 # - # * ST-qt6MP.pkg.macos-Sonoma-release-RsysPsys - # * LW-qt6MP.pkg.macos-Sonoma-release-Rmp33Pmp312 + # * ST-qt6MP.pkg.macos-Sequoia-release-RsysPsys + # * LW-qt6MP.pkg.macos-Sequoia-release-Rmp33Pmp312 #----------------------------------------------------------------------------------------------- # 0 1 2 3 4 5 6 7 patQRP = r'(ST|LW|HW|EX)([-])([qt5|qt6][0-9A-Za-z]+)([.]pkg[.])([A-Za-z]+[-][A-Za-z]+[-])(release|debug)([-])([0-9A-Za-z]+)' diff --git a/macbuild/nightlyBuild.py b/macbuild/nightlyBuild.py index 0cd27822a..8c3d51e27 100755 --- a/macbuild/nightlyBuild.py +++ b/macbuild/nightlyBuild.py @@ -339,7 +339,7 @@ def Parse_CommandLine_Arguments(): Usage += " (3) $ ./nightlyBuild.py --test |\n" Usage += " (4) $ ./nightlyBuild.py --check (confirm the QA Test results) |\n" Usage += " (5) $ ./nightlyBuild.py --makedmg 1 |\n" - Usage += " (6) $ ./nightlyBuild.py --upload '0.29.7' |\n" + Usage += " (6) $ ./nightlyBuild.py --upload '0.30.2' |\n" Usage += " (7) $ ./nightlyBuild.py --cleandmg 1 |\n" Usage += "-----------------------------------------------------------------------------+----------------------------\n" diff --git a/macbuild/nightlyBuild.sample.csv b/macbuild/nightlyBuild.sample.csv index 30ba786a3..bea222f3a 100644 --- a/macbuild/nightlyBuild.sample.csv +++ b/macbuild/nightlyBuild.sample.csv @@ -18,7 +18,7 @@ qtVer,target,bdType 5,0,r 5,1,r 6,2,r -6,13,r +5,13,r 5,4,r #6,0,r #6,1,r diff --git a/macbuild/python3HB.py b/macbuild/python3HB.py index 82046c09b..7015618b4 100755 --- a/macbuild/python3HB.py +++ b/macbuild/python3HB.py @@ -33,8 +33,7 @@ def SetGlobals(): Usage += "\n" Usage += " option & argument : descriptions | default value\n" Usage += " -------------------------------------------------------------------+---------------\n" - Usage += " <-v|--version >: in ['3.8', '3.9', '3.10', '3.11', '3.12', | ''\n" - Usage += " '3.13'] |\n" + Usage += " <-v|--version >: in ['3.11', '3.12','3.13'] | ''\n" Usage += " [-u|-unlink] : unlink only | disabled\n" Usage += " [-?|--?] : print this usage and exit | disabled\n" Usage += "----------------------------------------------------------------------+-----------------\n" @@ -50,7 +49,7 @@ def Parse_CLI_Args(): p.add_option( '-v', '--version', dest='version', - help="python3 version=['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']" ) + help="python3 version=['3.11', '3.12', '3.13']" ) p.add_option( '-u', '--unlink', action='store_true', @@ -75,7 +74,7 @@ def Parse_CLI_Args(): Version = opt.version UnlinkOnly = opt.unlink - if not Version in [ '3.8', '3.9', '3.10', '3.11', '3.12', '3.13' ]: + if not Version in [ '3.11', '3.12', '3.13' ]: print( "! Unsupported Python 3 version <%s>" % Version ) print(Usage) sys.exit(0) diff --git a/src/buddies/src/bd/bdConverterMain.cc b/src/buddies/src/bd/bdConverterMain.cc index d3f418b06..6c247445a 100644 --- a/src/buddies/src/bd/bdConverterMain.cc +++ b/src/buddies/src/bd/bdConverterMain.cc @@ -43,8 +43,13 @@ int converter_main (int argc, char *argv[], const std::string &format) generic_reader_options.add_options (cmd); cmd << tl::arg ("input", &infile, "The input file (any format, may be gzip compressed)", - "You can use '+' or ',' to supply multiple files which will be read after each other into the same layout. " - "This provides some cheap, but risky way of merging files. Beware of cell name conflicts.") + "Multiple files can be combined using '+' or ','. '+' will combine the files in 'blending' mode. " + "In this mode it is possible to combine identically named cells into one cell for example. This mode " + "needs to be used with care and there some constraints - e.g. the database unit of the involved " + "layouts needs to be the same. When using ',' as a separator, blending is not used, but the layouts " + "are merged by first creating two layouts and then combining them into one. This mode is more robust " + "but does not allow cell merging. '+' combination has higher priority than ',' - i.e. 'a+b,c' is " + "understood as '(a+b),c'.") << tl::arg ("output", &outfile, tl::sprintf ("The output file (%s format)", format)) ; diff --git a/src/buddies/src/bd/bdReaderOptions.cc b/src/buddies/src/bd/bdReaderOptions.cc index 958bdb723..1cab8c0c3 100644 --- a/src/buddies/src/bd/bdReaderOptions.cc +++ b/src/buddies/src/bd/bdReaderOptions.cc @@ -22,6 +22,8 @@ #include "bdReaderOptions.h" #include "dbLoadLayoutOptions.h" +#include "dbLayerMapping.h" +#include "dbCellMapping.h" #include "tlCommandLineParser.h" #include "tlStream.h" @@ -831,15 +833,28 @@ static std::string::size_type find_file_sep (const std::string &s, std::string:: } } -static std::vector split_file_list (const std::string &infile) +static std::vector > split_file_list (const std::string &infile) { - std::vector files; + std::vector > files; + files.push_back (std::vector ()); size_t p = 0; - for (size_t pp = 0; (pp = find_file_sep (infile, p)) != std::string::npos; p = pp + 1) { - files.push_back (std::string (infile, p, pp - p)); + while (true) { + + size_t sep = find_file_sep (infile, p); + if (sep == std::string::npos) { + files.back ().push_back (std::string (infile, p)); + return files; + } + + files.back ().push_back (std::string (infile, p, sep - p)); + if (infile [sep] == ',') { + files.push_back (std::vector ()); + } + + p = sep + 1; + } - files.push_back (std::string (infile, p)); return files; } @@ -850,16 +865,73 @@ void read_files (db::Layout &layout, const std::string &infile, const db::LoadLa // db::LayoutLocker locker (&layout); // but there are yet unknown side effects - // enter a LEF caching context for chaining multiple DEF with the same LEF - db::LoadLayoutOptions local_options (options); - local_options.set_option_by_name ("lefdef_config.lef_context_enabled", true); + std::vector > files = split_file_list (infile); - std::vector files = split_file_list (infile); + for (auto ff = files.begin (); ff != files.end (); ++ff) { + + // enter a LEF caching context for chaining multiple DEF with the same LEF + db::LoadLayoutOptions local_options (options); + local_options.set_option_by_name ("lefdef_config.lef_context_enabled", true); + + db::Layout tmp; + db::Layout *ly = (ff == files.begin () ? &layout : &tmp); + + for (auto f = ff->begin (); f != ff->end (); ++f) { + tl::InputStream stream (*f); + db::Reader reader (stream); + if (f != ff->begin ()) { + reader.set_expected_dbu (ly->dbu ()); + } + reader.read (*ly, local_options); + } + + if (ly != &layout) { + + // Move over cells from read layout to destination ("," separated blocks). + // This path does not imply limitations in terms of DBU compatibility etc. + + std::vector cells_target; + std::vector cells_source; + + for (auto c = tmp.begin_top_down (); c != tmp.end_top_cells (); ++c) { + + cells_source.push_back (*c); + + // as a special rule, join ghost cells if the source top cell fits into + // a ghost cell of the target. + auto cell_target = layout.cell_by_name (tmp.cell_name (*c)); + if (cell_target.first && layout.cell (cell_target.second).is_ghost_cell ()) { + cells_target.push_back (cell_target.second); + } else { + cells_target.push_back (layout.add_cell (tmp.cell_name (*c))); + } + + } + + // ghost cell joining also works the other way around: a top cell of destination + // can match a ghost cell of the source + for (auto c = tmp.end_top_cells (); c != tmp.end_top_down (); ++c) { + + const db::Cell &cell_source = tmp.cell (*c); + auto cell_target = layout.cell_by_name (tmp.cell_name (*c)); + + if (cell_source.is_ghost_cell () && cell_target.first) { + cells_source.push_back (*c); + cells_target.push_back (cell_target.second); + } + + } + + db::CellMapping cm; + cm.create_multi_mapping_full (layout, cells_target, tmp, cells_source); + + db::LayerMapping lm; + lm.create_full (layout, tmp); + + layout.move_tree_shapes (tmp, cm, lm); + + } - for (std::vector::const_iterator f = files.begin (); f != files.end (); ++f) { - tl::InputStream stream (*f); - db::Reader reader (stream); - reader.read (layout, local_options); } } diff --git a/src/buddies/unit_tests/bdConverterTests.cc b/src/buddies/unit_tests/bdConverterTests.cc index 03ebc7155..cfbd51e03 100644 --- a/src/buddies/unit_tests/bdConverterTests.cc +++ b/src/buddies/unit_tests/bdConverterTests.cc @@ -483,7 +483,7 @@ TEST(10) std::string input; for (size_t i = 0; i < sizeof (def_files) / sizeof (def_files[0]); ++i) { if (i > 0) { - input += ","; + input += "+"; } input += def_dir + "/" + def_files[i]; } @@ -510,3 +510,201 @@ TEST(10) db::compare_layouts (this, layout, input_au, db::WriteOAS); } + +// Merging with + +TEST(11_1) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_1.oas"; + std::string input = input_dir + "/strm2oas_1.oas+" + input_dir + "/strm2oas_2.oas"; + + std::string output = this->tmp_file ("strm2oas_1.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0); + + db::Layout layout; + { + tl::InputStream stream (output); + db::LoadLayoutOptions options; + db::Reader reader (stream); + reader.read (layout, options); + } + + db::compare_layouts (this, layout, input_au, db::WriteOAS); +} + +// Merging with + not allowed on different DBUs +TEST(11_2) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_1.oas"; + std::string input = input_dir + "/strm2oas_1.oas+" + input_dir + "/strm2oas_2_10nm.oas"; + + std::string output = this->tmp_file ("strm2oas_1.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + try { + bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name); + EXPECT_EQ (1, 0); + } catch (tl::Exception &ex) { + EXPECT_EQ (ex.msg (), "Former and present database units are not compatible: 0.001 (former) vs. 0.01 (present)"); + } +} + +// Merging with + not allowed on different DBUs +TEST(11_3) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_3.oas"; + std::string input = input_dir + "/strm2oas_1.oas," + input_dir + "/strm2oas_2_10nm.oas"; + + std::string output = this->tmp_file ("strm2oas_3.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0); + + db::Layout layout; + { + tl::InputStream stream (output); + db::LoadLayoutOptions options; + db::Reader reader (stream); + reader.read (layout, options); + } + + db::compare_layouts (this, layout, input_au, db::WriteOAS); +} + +// Merging with + and , under the presence of ghost cells: test+test,top->(test) +TEST(12_1) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_12_1.oas"; + std::string input = input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas," + input_dir + "/strm2oas_c.oas"; + + std::string output = this->tmp_file ("strm2oas_12_1.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0); + + db::Layout layout; + { + tl::InputStream stream (output); + db::LoadLayoutOptions options; + db::Reader reader (stream); + reader.read (layout, options); + } + + db::compare_layouts (this, layout, input_au, db::WriteOAS); +} + +// Merging with + and , under the presence of ghost cells: top->(test),test+test +TEST(12_2) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_12_2.oas"; + std::string input = input_dir + "/strm2oas_c.oas," + input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas"; + + std::string output = this->tmp_file ("strm2oas_12_2.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0); + + db::Layout layout; + { + tl::InputStream stream (output); + db::LoadLayoutOptions options; + db::Reader reader (stream); + reader.read (layout, options); + } + + db::compare_layouts (this, layout, input_au, db::WriteOAS); +} + +// Merging with + and , under the presence of ghost cells: test+test,toptop->top->(test) +TEST(12_3) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_12_3.oas"; + std::string input = input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas," + input_dir + "/strm2oas_cc.oas"; + + std::string output = this->tmp_file ("strm2oas_12_3.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0); + + db::Layout layout; + { + tl::InputStream stream (output); + db::LoadLayoutOptions options; + db::Reader reader (stream); + reader.read (layout, options); + } + + db::compare_layouts (this, layout, input_au, db::WriteOAS); +} + +// Merging with + and , under the presence of ghost cells: toptop->top->(test),test+test +TEST(12_4) +{ + std::string input_dir = tl::testdata (); + input_dir += "/bd"; + + std::string input_au = input_dir + "/strm2oas_au_12_4.oas"; + std::string input = input_dir + "/strm2oas_cc.oas," + input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas"; + + std::string output = this->tmp_file ("strm2oas_12_4.oas"); + const char *argv[] = { "x", + "--blend-mode=0", + input.c_str (), + output.c_str () + }; + + EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0); + + db::Layout layout; + { + tl::InputStream stream (output); + db::LoadLayoutOptions options; + db::Reader reader (stream); + reader.read (layout, options); + } + + db::compare_layouts (this, layout, input_au, db::WriteOAS); +} diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc index b1becdcfb..7cf6de737 100644 --- a/src/db/db/dbCommonReader.cc +++ b/src/db/db/dbCommonReader.cc @@ -146,8 +146,6 @@ CommonReaderBase::name_for_id (size_t id) const void CommonReaderBase::rename_cell (db::Layout &layout, size_t id, const std::string &cn) { - m_name_for_id.insert (std::make_pair (id, cn)); - std::map >::iterator iid = m_id_map.find (id); std::map >::iterator iname = m_name_map.find (cn); @@ -156,9 +154,22 @@ CommonReaderBase::rename_cell (db::Layout &layout, size_t id, const std::string } if (iname != m_name_map.end () && iname->second.first != null_id && iname->second.first != id) { - common_reader_error (tl::sprintf (tl::to_string (tr ("Same cell name %s, but different IDs: %ld and %ld")), cn, id, iname->second.first)); + + // picking a different name on name clash (issue #2088) + std::string cn_new = cn + "_id$" + tl::to_string (id); + for (size_t i = 0; m_name_map.find (cn_new) != m_name_map.end (); ++i) { + cn_new = cn + "_id$" + tl::to_string (id) + "$" + tl::to_string (i); + } + + common_reader_warn (tl::sprintf (tl::to_string (tr ("Same cell name %s, but different IDs: %ld and %ld, renaming first to %s")), cn, id, iname->second.first, cn_new)); + rename_cell (layout, id, cn_new); + + return; + } + m_name_for_id.insert (std::make_pair (id, cn)); + if (iid != m_id_map.end () && iname != m_name_map.end ()) { if (iname->second.second != iid->second.second) { @@ -240,7 +251,7 @@ CommonReaderBase::cell_for_instance (db::Layout &layout, const std::string &cn) } void -CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta, bool no_duplicate_instances) const +CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta, bool no_duplicate_instances) { const db::Cell &src_cell = layout.cell (src_cell_index); db::Cell &target_cell = layout.cell (target_cell_index); @@ -284,7 +295,7 @@ CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cel } void -CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const +CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) { const db::Cell &src_cell = layout.cell (src_cell_index); db::Cell &target_cell = layout.cell (target_cell_index); @@ -297,20 +308,21 @@ CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_ind } // replace all instances of the new cell with the original one - layout.replace_instances_of (src_cell.cell_index (), target_cell.cell_index ()); + layout.replace_instances_of (src_cell_index, target_cell_index); // merge meta info if (with_meta) { - auto ib = layout.begin_meta (src_cell.cell_index ()); - auto ie = layout.end_meta (src_cell.cell_index ()); + auto ib = layout.begin_meta (src_cell_index); + auto ie = layout.end_meta (src_cell_index); for (auto i = ib; i != ie; ++i) { - layout.add_meta_info (target_cell.cell_index (), i->first, i->second); + layout.add_meta_info (target_cell_index, i->first, i->second); } } - layout.clear_meta (src_cell.cell_index ()); + layout.clear_meta (src_cell_index); // finally delete the new cell - layout.delete_cell (src_cell.cell_index ()); + m_temp_cells.erase (src_cell_index); + layout.delete_cell (src_cell_index); } void diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h index 1a7dafcdf..065c5eb6c 100644 --- a/src/db/db/dbCommonReader.h +++ b/src/db/db/dbCommonReader.h @@ -242,12 +242,12 @@ protected: /** * @brief Merge (and delete) the src_cell into target_cell */ - void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta, bool no_duplicate_instances) const; + void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta, bool no_duplicate_instances); /** * @brief Merge (and delete) the src_cell into target_cell without instances */ - void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const; + void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta); /** * @brief Gets the layer name map diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index 0dd69de06..04358f6e1 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -77,14 +77,16 @@ public: } // because the rasterizer can't handle overlapping cells we need to multiply the row and columns steps - // with an integer until the effective rasterizer pitch get big enough. + // with an integer until the effective rasterizer pitch gets big enough. m_row_steps *= (m_dim.x () - 1) / (m_row_steps * m_row_step.x ()) + 1; m_column_steps *= (m_dim.y () - 1) / (m_column_steps * m_column_step.y ()) + 1; db::Box fp_bbox = fp.box (); // compensate for distortion by sheared kernel - fp_bbox.enlarge (db::Vector (db::coord_traits::rounded (double (fp_bbox.height ()) * std::abs (m_column_step.x ()) / dy), db::coord_traits::rounded (double (fp_bbox.width ()) * std::abs (m_row_step.y ()) / dx))); + db::Coord ex = std::max (std::abs (db::Coord (m_column_step.x () * m_column_steps)), std::abs (db::Coord (m_row_step.x () * m_row_steps))); + db::Coord ey = std::max (std::abs (db::Coord (m_column_step.y () * m_column_steps)), std::abs (db::Coord (m_row_step.y () * m_row_steps))); + fp_bbox.enlarge (db::Vector (ex, ey)); int columns_per_rows = (int (m_row_steps) * m_row_step.y ()) / dy; int rows_per_columns = (int (m_column_steps) * m_column_step.x ()) / dx; @@ -167,6 +169,11 @@ public: return m_area_maps [i]; } + db::AreaMap &area_map (unsigned int i) + { + return m_area_maps [i]; + } + private: std::vector m_area_maps; db::Vector m_row_step, m_column_step; @@ -246,7 +253,7 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f for (unsigned int i = 0; i < am.area_maps (); ++i) { - const db::AreaMap &am1 = am.area_map (i); + db::AreaMap &am1 = am.area_map (i); size_t nx = am1.nx (); size_t ny = am1.ny (); @@ -263,31 +270,54 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f ++jj; } - ninsts += (jj - j); - db::Vector p0 = (am1.p0 () - db::Point ()) - kernel_origin; p0 += db::Vector (i * am1.d ().x (), j * am1.d ().y ()); db::CellInstArray array; - if (jj > j + 1) { - array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), db::Vector (0, am1.d ().y ()), db::Vector (), (unsigned long) (jj - j), 1); + // try to expand the array in x direction + size_t ii = i + 1; + for ( ; ii < nx; ++ii) { + bool all = true; + for (size_t k = j; k < jj && all; ++k) { + all = am1.get (ii, k) == am1.pixel_area (); + } + if (all) { + for (size_t k = j; k < jj; ++k) { + // disable pixel, so we do not see it again in the following columns + am1.get (ii, k) = 0; + } + } else { + break; + } + } + + ninsts += (jj - j) * (ii - i); + + if (jj > j + 1 || ii > i + 1) { + array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), db::Vector (0, am1.d ().y ()), db::Vector (am1.d ().x (), 0), (unsigned long) (jj - j), (unsigned long) (ii - i)); } else { array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0)); } { // In case we run this from a tiling processor we need to lock against multithread races - tl::MutexLocker locker (&db::TilingProcessor::output_lock ()); + tl_assert (cell->layout () != 0); + tl::MutexLocker locker (&cell->layout ()->lock ()); cell->insert (array); } if (remaining_parts) { - if (am1.d ().y () == am1.p ().y ()) { - filled_regions.push_back (db::Polygon (db::Box (db::Point (), db::Point (am1.p ().x (), am1.p ().y () * db::Coord (jj - j))).moved (kernel_origin + p0))); + if (am1.d ().y () == am1.p ().y () && am1.d ().x () == am1.p ().x ()) { + db::Box fill_box (db::Point (), db::Point (am1.p ().x () * db::Coord (ii - i), am1.p ().y () * db::Coord (jj - j))); + filled_regions.push_back (db::Polygon (fill_box.enlarged (fill_margin).moved (kernel_origin + p0))); } else { + db::Box fill_box (db::Point (), db::Point () + am1.p ()); + fill_box.enlarge (fill_margin); for (size_t k = 0; k < jj - j; ++k) { - filled_regions.push_back (db::Polygon (db::Box (db::Point (), db::Point () + am1.p ()).moved (kernel_origin + p0 + db::Vector (0, am1.d ().y () * db::Coord (k))))); + for (size_t l = 0; l < ii - i; ++l) { + filled_regions.push_back (db::Polygon (fill_box.moved (kernel_origin + p0 + db::Vector (am1.d ().x () * db::Coord (l), am1.d ().y () * db::Coord (k))))); + } } } } @@ -314,19 +344,9 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f if (any_fill) { if (remaining_parts) { - std::vector fp1; - - if (fill_margin != db::Vector ()) { - ep.size (filled_regions, fill_margin.x (), fill_margin.y (), fp1, 3 /*mode*/, false /*=don't resolve holes*/); - filled_regions.swap (fp1); - fp1.clear (); - } - fp1.push_back (fp0); ep.boolean (fp1, filled_regions, *remaining_parts, db::BooleanOp::ANotB, false /*=don't resolve holes*/); - - } return true; diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc index 9c306aa21..f709df749 100644 --- a/src/db/db/dbPolygonTools.cc +++ b/src/db/db/dbPolygonTools.cc @@ -1918,7 +1918,7 @@ rasterize_impl (const db::polygon &polygon, db::area_map &am) area_type aa = a; - if (dx == py) { + if (dx == px) { box_type cell (x, y, xx, yy); diff --git a/src/db/db/dbReader.cc b/src/db/db/dbReader.cc index 6561c6d9a..5f5177e4d 100644 --- a/src/db/db/dbReader.cc +++ b/src/db/db/dbReader.cc @@ -61,7 +61,7 @@ join_layer_names (std::string &s, const std::string &n) // ReaderBase implementation ReaderBase::ReaderBase () - : m_warnings_as_errors (false), m_warn_level (1), m_warn_count_for_same_message (0), m_first_warning (true) + : m_warnings_as_errors (false), m_warn_level (1), m_warn_count_for_same_message (0), m_first_warning (true), m_expected_dbu (0.0) { } @@ -114,6 +114,20 @@ ReaderBase::compress_warning (const std::string &msg) } } +void +ReaderBase::set_expected_dbu (double dbu) +{ + m_expected_dbu = dbu; +} + +void +ReaderBase::check_dbu (double dbu) const +{ + if (m_expected_dbu > db::epsilon && fabs (dbu - m_expected_dbu) > db::epsilon) { + throw ReaderException (tl::sprintf (tl::to_string (tr ("Former and present database units are not compatible: %.12g (former) vs. %.12g (present)")), m_expected_dbu, dbu)); + } +} + // --------------------------------------------------------------- // Reader implementation diff --git a/src/db/db/dbReader.h b/src/db/db/dbReader.h index b13025a56..e9a2c23c6 100644 --- a/src/db/db/dbReader.h +++ b/src/db/db/dbReader.h @@ -138,6 +138,33 @@ public: */ int compress_warning (const std::string &msg); + /** + * @brief Sets the expected database unit + * + * With this value set, the reader can check if the present database unit is + * compatible with the expected one and either take actions to scale the layouts + * or to reject the file. + * + * Setting the value to 0 resets the expected DBU and will disable all checks + * or scaling. + */ + void set_expected_dbu (double dbu); + + /** + * @brief Gets the expected database unit + */ + double expected_dbu () const + { + return m_expected_dbu; + } + + /** + * @brief Checks the given DBU against the expected one + * + * This method will raise an exception if the database units do not match. + */ + void check_dbu (double dbu) const; + protected: virtual void init (const db::LoadLayoutOptions &options); @@ -147,6 +174,7 @@ private: std::string m_last_warning; int m_warn_count_for_same_message; bool m_first_warning; + double m_expected_dbu; }; /** @@ -231,6 +259,22 @@ public: return mp_actual_reader->warnings_as_errors (); } + /** + * @brief Sets the expected database unit (see ReaderBase) + */ + void set_expected_dbu (double dbu) + { + return mp_actual_reader->set_expected_dbu (dbu); + } + + /** + * @brief Gets the expected database unit + */ + double expected_dbu () const + { + return mp_actual_reader->expected_dbu (); + } + private: ReaderBase *mp_actual_reader; tl::InputStream &m_stream; diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index b3965f9ce..1f8758bd1 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -500,15 +500,21 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const } if (mp_shapes) { + // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) // TODO: get rid of that const cast (const_cast (mp_shapes))->update (); + start_shapes (); + } else if (mp_layout && (! m_has_layers || m_current_layer < m_layers.size ())) { + // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) mp_layout->update (); + new_cell (receiver); next_shape (receiver); + } if (mp_layout && ! at_end ()) { diff --git a/src/db/db/dbShapes.cc b/src/db/db/dbShapes.cc index 2c5e90f46..5774973b9 100644 --- a/src/db/db/dbShapes.cc +++ b/src/db/db/dbShapes.cc @@ -1127,10 +1127,20 @@ void Shapes::reset_bbox_dirty () void Shapes::update () { + std::unique_ptr locker; + + // If not in a layout context, we should lock here against multiple calls from different threads. + // In a layout context, the Layout object will do that for us. + if (layout () == 0) { + static tl::Mutex lock; + locker.reset (new tl::MutexLocker (&lock)); + } + for (tl::vector::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { (*l)->sort (); (*l)->update_bbox (); } + set_dirty (false); } diff --git a/src/db/db/dbTextWriter.cc b/src/db/db/dbTextWriter.cc index 87148793a..8ac82ad39 100644 --- a/src/db/db/dbTextWriter.cc +++ b/src/db/db/dbTextWriter.cc @@ -149,7 +149,7 @@ TextWriter::write_props (const db::Layout & /*layout*/, size_t prop_id) const tl::Variant &name = p->first; const tl::Variant &value = p->second; - if (name.is_long () || name.is_ulong ()) { + if (name.can_convert_to_long ()) { *this << " {" << int (name.to_long ()) << " {" << value.to_string () << "}}" << endl_str (); } else if (name.is_a_string ()) { *this << " {{" << name.to_string () << "} {" << value.to_string () << "}}" << endl_str (); diff --git a/src/db/db/gsiDeclDbShapes.cc b/src/db/db/gsiDeclDbShapes.cc index cd7fbefbb..85115261d 100644 --- a/src/db/db/gsiDeclDbShapes.cc +++ b/src/db/db/gsiDeclDbShapes.cc @@ -223,213 +223,305 @@ static db::Shape insert_shape_with_dcplx_trans (db::Shapes *s, const db::Shape & return s->insert (shape, dbu_trans.inverted () * trans * dbu_trans, pm); } +namespace { + +/** + * @brief Provides protection against inserting shapes into a target that is also source + * + * The strategy is to use an temporary Shapes container if needed. + */ +class ProtectedShapes +{ +public: + ProtectedShapes (db::Shapes *target, const db::RecursiveShapeIterator &src) + : mp_target (target), mp_tmp_shapes () + { + if (target == src.shapes () || target->layout () == src.layout ()) { + mp_tmp_shapes.reset (new db::Shapes ()); + } + } + + ProtectedShapes (db::Shapes *target, const db::Shapes &src) + : mp_target (target), mp_tmp_shapes () + { + if (target == &src || target->layout () == src.layout ()) { + mp_tmp_shapes.reset (new db::Shapes ()); + } + } + + ProtectedShapes (db::Shapes *target, const db::Region &src) + : mp_target (target), mp_tmp_shapes () + { + auto iter = src.begin_iter (); + if (target == iter.first.shapes () || target->layout () == iter.first.layout ()) { + mp_tmp_shapes.reset (new db::Shapes ()); + } + } + + ProtectedShapes (db::Shapes *target, const db::Texts &src) + : mp_target (target), mp_tmp_shapes () + { + auto iter = src.begin_iter (); + if (target == iter.first.shapes () || target->layout () == iter.first.layout ()) { + mp_tmp_shapes.reset (new db::Shapes ()); + } + } + + ProtectedShapes (db::Shapes *target, const db::Edges &src) + : mp_target (target), mp_tmp_shapes () + { + auto iter = src.begin_iter (); + if (target == iter.first.shapes () || target->layout () == iter.first.layout ()) { + mp_tmp_shapes.reset (new db::Shapes ()); + } + } + + ProtectedShapes (db::Shapes *target, const db::EdgePairs &src) + : mp_target (target), mp_tmp_shapes () + { + auto iter = src.begin_iter (); + if (target == iter.first.shapes () || target->layout () == iter.first.layout ()) { + mp_tmp_shapes.reset (new db::Shapes ()); + } + } + + ~ProtectedShapes () + { + if (mp_tmp_shapes.get ()) { + mp_target->insert (*mp_tmp_shapes.get ()); + } + } + + db::Shapes *operator-> () const + { + if (mp_tmp_shapes.get ()) { + return mp_tmp_shapes.get (); + } else { + return mp_target; + } + } + +private: + db::Shapes *mp_target; + std::unique_ptr mp_tmp_shapes; +}; + +} + static void insert_iter (db::Shapes *sh, const db::RecursiveShapeIterator &r) { - // NOTE: if the source (r) is from the same layout than the shapes live in, we better - // lock the layout against updates while inserting - db::LayoutLocker locker (sh->layout ()); + ProtectedShapes ps (sh, r); for (db::RecursiveShapeIterator i = r; !i.at_end (); ++i) { tl::ident_map pm; - sh->insert (*i, i.trans (), pm); + ps->insert (*i, i.trans (), pm); } } static void insert_iter_with_trans (db::Shapes *sh, const db::RecursiveShapeIterator &r, const db::ICplxTrans &trans) { - // NOTE: if the source (r) is from the same layout than the shapes live in, we better - // lock the layout against updates while inserting - db::LayoutLocker locker (sh->layout ()); + ProtectedShapes ps (sh, r); for (db::RecursiveShapeIterator i = r; !i.at_end (); ++i) { tl::ident_map pm; - sh->insert (*i, trans * i.trans (), pm); + ps->insert (*i, trans * i.trans (), pm); } } static void insert_shapes (db::Shapes *sh, const db::Shapes &s) { - sh->insert (s); + ProtectedShapes ps (sh, s); + ps->insert (s); } static void insert_shapes_with_flags (db::Shapes *sh, const db::Shapes &s, unsigned int flags) { - sh->insert (s, flags); + ProtectedShapes ps (sh, s); + ps->insert (s, flags); } static void insert_shapes_with_trans (db::Shapes *sh, const db::Shapes &s, const db::ICplxTrans &trans) { - // NOTE: if the source (r) is from the same layout than the shapes live in, we better - // lock the layout against updates while inserting - db::LayoutLocker locker (sh->layout ()); + ProtectedShapes ps (sh, s); for (db::Shapes::shape_iterator i = s.begin (db::ShapeIterator::All); !i.at_end(); ++i) { tl::ident_map pm; - sh->insert (*i, trans, pm); + ps->insert (*i, trans, pm); } } static void insert_shapes_with_flag_and_trans (db::Shapes *sh, const db::Shapes &s, unsigned int flags, const db::ICplxTrans &trans) { - // NOTE: if the source (r) is from the same layout than the shapes live in, we better - // lock the layout against updates while inserting - db::LayoutLocker locker (sh->layout ()); + ProtectedShapes ps (sh, s); for (db::Shapes::shape_iterator i = s.begin (flags); !i.at_end(); ++i) { tl::ident_map pm; - sh->insert (*i, trans, pm); + ps->insert (*i, trans, pm); } } static void insert_region (db::Shapes *sh, const db::Region &r) { - // NOTE: if the source (r) is from the same layout than the shapes live in, we better - // lock the layout against updates while inserting - db::LayoutLocker locker (sh->layout ()); + ProtectedShapes ps (sh, r); for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (*s); + ps->insert (*s); } } static void insert_region_with_trans (db::Shapes *sh, const db::Region &r, const db::ICplxTrans &trans) { - // NOTE: if the source (r) is from the same layout than the shapes live in, we better - // lock the layout against updates while inserting - db::LayoutLocker locker (sh->layout ()); + ProtectedShapes ps (sh, r); for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (trans)); + ps->insert (s->transformed (trans)); } } static void insert_region_with_dtrans (db::Shapes *sh, const db::Region &r, const db::DCplxTrans &trans) { + ProtectedShapes ps (sh, r); db::CplxTrans dbu_trans (shapes_dbu (sh)); db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans; for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (itrans)); + ps->insert (s->transformed (itrans)); } } static void insert_edges (db::Shapes *sh, const db::Edges &r) { + ProtectedShapes ps (sh, r); for (db::Edges::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (*s); + ps->insert (*s); } } static void insert_edges_with_trans (db::Shapes *sh, const db::Edges &r, const db::ICplxTrans &trans) { + ProtectedShapes ps (sh, r); for (db::Edges::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (trans)); + ps->insert (s->transformed (trans)); } } static void insert_edges_with_dtrans (db::Shapes *sh, const db::Edges &r, const db::DCplxTrans &trans) { + ProtectedShapes ps (sh, r); db::CplxTrans dbu_trans (shapes_dbu (sh)); db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans; for (db::Edges::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (itrans)); + ps->insert (s->transformed (itrans)); } } static void insert_edge_pairs_as_polygons (db::Shapes *sh, const db::EdgePairs &r, db::Coord e) { + ProtectedShapes ps (sh, r); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->normalized ().to_simple_polygon (e)); + ps->insert (s->normalized ().to_simple_polygon (e)); } } static void insert_edge_pairs_as_polygons_d (db::Shapes *sh, const db::EdgePairs &r, db::DCoord de) { + ProtectedShapes ps (sh, r); db::Coord e = db::coord_traits::rounded (de / shapes_dbu (sh)); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->normalized ().to_simple_polygon (e)); + ps->insert (s->normalized ().to_simple_polygon (e)); } } static void insert_edge_pairs_as_polygons_with_trans (db::Shapes *sh, const db::EdgePairs &r, const db::ICplxTrans &trans, db::Coord e) { + ProtectedShapes ps (sh, r); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->normalized ().to_simple_polygon (e).transformed (trans)); + ps->insert (s->normalized ().to_simple_polygon (e).transformed (trans)); } } static void insert_edge_pairs_as_polygons_with_dtrans (db::Shapes *sh, const db::EdgePairs &r, const db::DCplxTrans &trans, db::DCoord de) { + ProtectedShapes ps (sh, r); db::Coord e = db::coord_traits::rounded (de / shapes_dbu (sh)); db::CplxTrans dbu_trans (shapes_dbu (sh)); db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans; for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->normalized ().to_simple_polygon (e).transformed (itrans)); + ps->insert (s->normalized ().to_simple_polygon (e).transformed (itrans)); } } static void insert_edge_pairs_as_edges (db::Shapes *sh, const db::EdgePairs &r) { + ProtectedShapes ps (sh, r); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->first ()); - sh->insert (s->second ()); + ps->insert (s->first ()); + ps->insert (s->second ()); } } static void insert_edge_pairs_as_edges_with_trans (db::Shapes *sh, const db::EdgePairs &r, const db::ICplxTrans &trans) { + ProtectedShapes ps (sh, r); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->first ().transformed (trans)); - sh->insert (s->second ().transformed (trans)); + ps->insert (s->first ().transformed (trans)); + ps->insert (s->second ().transformed (trans)); } } static void insert_edge_pairs_as_edges_with_dtrans (db::Shapes *sh, const db::EdgePairs &r, const db::DCplxTrans &trans) { + ProtectedShapes ps (sh, r); db::CplxTrans dbu_trans (shapes_dbu (sh)); db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans; for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->first ().transformed (itrans)); - sh->insert (s->second ().transformed (itrans)); + ps->insert (s->first ().transformed (itrans)); + ps->insert (s->second ().transformed (itrans)); } } static void insert_edge_pairs (db::Shapes *sh, const db::EdgePairs &r) { + ProtectedShapes ps (sh, r); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (*s); + ps->insert (*s); } } static void insert_edge_pairs_with_trans (db::Shapes *sh, const db::EdgePairs &r, const db::ICplxTrans &trans) { + ProtectedShapes ps (sh, r); for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (trans)); + ps->insert (s->transformed (trans)); } } static void insert_edge_pairs_with_dtrans (db::Shapes *sh, const db::EdgePairs &r, const db::DCplxTrans &trans) { + ProtectedShapes ps (sh, r); db::CplxTrans dbu_trans (shapes_dbu (sh)); db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans; for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (itrans)); + ps->insert (s->transformed (itrans)); } } static void insert_texts (db::Shapes *sh, const db::Texts &r) { + ProtectedShapes ps (sh, r); for (db::Texts::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (*s); + ps->insert (*s); } } static void insert_texts_with_trans (db::Shapes *sh, const db::Texts &r, const db::ICplxTrans &trans) { + ProtectedShapes ps (sh, r); for (db::Texts::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (trans)); + ps->insert (s->transformed (trans)); } } static void insert_texts_with_dtrans (db::Shapes *sh, const db::Texts &r, const db::DCplxTrans &trans) { + ProtectedShapes ps (sh, r); db::CplxTrans dbu_trans (shapes_dbu (sh)); db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans; for (db::Texts::const_iterator s = r.begin (); ! s.at_end (); ++s) { - sh->insert (s->transformed (itrans)); + ps->insert (s->transformed (itrans)); } } diff --git a/src/db/unit_tests/dbFillToolTests.cc b/src/db/unit_tests/dbFillToolTests.cc index 97ebbfefb..4ce7b53bb 100644 --- a/src/db/unit_tests/dbFillToolTests.cc +++ b/src/db/unit_tests/dbFillToolTests.cc @@ -345,3 +345,35 @@ TEST(5) CHECKPOINT(); db::compare_layouts (_this, ly, tl::testdata () + "/algo/fill_tool_au5.oas", db::WriteOAS); } + +// issue #2087 +TEST(6) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/fill_tool6.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type fill_cell = ly.cell_by_name ("FILL_CELL").second; + db::cell_index_type top_cell = ly.cell_by_name ("TOP").second; + unsigned int fill_layer = ly.get_layer (db::LayerProperties (1, 0)); + + db::Region fill_region (db::RecursiveShapeIterator (ly, ly.cell (top_cell), fill_layer)); + + db::Region remaining_polygons; + + db::Vector rs (2500, 0); + db::Vector cs (650, 2500); + db::Box fc_box = ly.cell (fill_cell).bbox (); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), false, &remaining_polygons); + + unsigned int l100 = ly.insert_layer (db::LayerProperties (100, 0)); + remaining_polygons.insert_into (&ly, top_cell, l100); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testdata () + "/algo/fill_tool_au6.oas", db::WriteOAS); +} diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 25f47c22d..5e37dd784 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -5460,8 +5460,17 @@ CODE # as the reference point. The reference point will also defined the footprint of the fill cell - more precisely # the lower left corner. When step vectors are given, the fill cell's footprint is taken to be a rectangle # having the horizontal and vertical step pitch for width and height respectively. This way the fill cells - # will be arrange seamlessly. However, the cell's dimensions can be changed, so that the fill cells + # will be arrange seamlessly. + # + # However, the cell's dimensions can be changed, so that the fill cells # can overlap or there is a space between the cells. To change the dimensions use the "dim" method. + # This example will use a fill cell footprint of 1x1 micrometers, regardless of the step pitch: + # + # @code + # p = fill_pattern("FILL_CELL") + # p.shape(1, 0, box(0.0, 0.0, 1.0, 1.0)) + # p.dim(1.0, 1.0) + # @/code # # The following example specifies a fill cell with an active area of -0.5 .. 1.5 in both directions # (2 micron width and height). With these dimensions the fill cell's footprint is independent of the @@ -5474,6 +5483,18 @@ CODE # p.dim(2.0, 2.0) # @/code # + # Finally, the fill cell can be given a margin: this is a space around the fill cell which needs + # to be inside the fill region. Hence, the margin can be used to implement a distance, the fill + # cells (more precisely: their footprints) will maintain to the outside border of the fill region. + # The following example implements a margin of 200 nm in horizontal and 250 nm in vertical direction: + # + # @code + # p = fill_pattern("FILL_CELL") + # p.shape(1, 0, box(0.0, 0.0, 1.0, 1.0)) + # p.dim(1.0, 1.0) + # p.margin(0.2, 0.25) + # @/code + # # With these ingredients will can use the fill function. The first example fills the polygons # of "to_fill" with an orthogonal pattern of 1x1 micron rectangles with a pitch of 2 microns: # @@ -5574,6 +5595,7 @@ CODE fill_cell = pattern.create_cell(@engine._output_layout, @engine) top_cell = @engine._output_cell fc_box = dbu_trans * pattern.cell_box(row_step.x, column_step.y) + fill_margin = dbu_trans * pattern.fill_margin rs = dbu_trans * row_step cs = dbu_trans * column_step origin = origin ? dbu_trans * origin : nil @@ -5604,6 +5626,7 @@ CODE tp.var("rs", rs) tp.var("cs", cs) tp.var("origin", origin) + tp.var("fill_margin", fill_margin) tp.var("fc_index", fc_index) tp.var("repeat", repeat) tp.var("with_left", with_left) @@ -5616,8 +5639,8 @@ CODE tile_box = tile_box & tc_box; var left = with_left ? Region.new : nil; repeat ? - (region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, Vector.new, left, _tile.bbox) : - (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, Vector.new, left, _tile.bbox); + (region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, left, _tile.bbox) : + (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, fill_margin, left, _tile.bbox); with_left && _output(#{result_arg}, left) ) END @@ -5639,9 +5662,9 @@ END @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do if repeat - self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, RBA::Vector::new, result) + self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, result) else - self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result) + self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, fill_margin, result) end end diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index 56cf18023..710626f53 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -335,6 +335,7 @@ module DRC @shapes = [] @origin = nil @dim = nil + @margin = RBA::DVector::new end def create_cell(layout, engine) @@ -350,7 +351,11 @@ module DRC def cell_box(def_w, def_h) o = @origin || self._computed_origin d = @dim || RBA::DVector::new(def_w, def_h) - RBA::DBox::new(o, o + d) + RBA::DBox::new(o, o + d).enlarged(@margin) + end + + def fill_margin + -@margin end def default_xpitch @@ -454,6 +459,20 @@ module DRC end + def margin(w, h) + + if !w.is_a?(1.class) && !w.is_a?(1.0.class) + raise("w argument not numeric FillCell#dim") + end + if !h.is_a?(1.class) && !h.is_a?(1.0.class) + raise("h argument not numeric FillCell#dim") + end + @margin = RBA::DVector::new(w, h) + + self + + end + end # A wrapper for the fill step definition diff --git a/src/drc/unit_tests/drcFullTests.cc b/src/drc/unit_tests/drcFullTests.cc new file mode 100644 index 000000000..36aecd8a7 --- /dev/null +++ b/src/drc/unit_tests/drcFullTests.cc @@ -0,0 +1,70 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2025 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tlUnitTest.h" +#include "dbReader.h" +#include "dbTestSupport.h" +#include "lymMacro.h" + +TEST(1_IHPMetal1Fill) +{ + test_is_long_runner (); + + std::string rs = tl::testdata (); + rs += "/drc/drcFullTest_1.drc"; + + std::string input = tl::testdata (); + input += "/drc/drcFullTest_1.oas"; + + std::string au = tl::testdata (); + au += "/drc/drcFullTest_au1.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + { + // Set some variables + lym::Macro config; + config.set_text (tl::sprintf ( + "$drc_force_gc = true\n" + "$drc_test_source = '%s'\n" + "$drc_test_target = '%s'\n" + , input, output) + ); + config.set_interpreter (lym::Macro::Ruby); + EXPECT_EQ (config.run (), 0); + } + + lym::Macro drc; + drc.load_from (rs); + EXPECT_EQ (drc.run (), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (_this, layout, au, db::NoNormalization); +} + diff --git a/src/drc/unit_tests/unit_tests.pro b/src/drc/unit_tests/unit_tests.pro index 30b2d3db0..b65797945 100644 --- a/src/drc/unit_tests/unit_tests.pro +++ b/src/drc/unit_tests/unit_tests.pro @@ -10,6 +10,7 @@ SOURCES = \ drcBasicTests.cc \ drcGenericTests.cc \ drcSimpleTests.cc \ + drcFullTests.cc \ drcSuiteTests.cc \ INCLUDEPATH += $$DRC_INC $$TL_INC $$RDB_INC $$DB_INC $$GSI_INC $$LYM_INC diff --git a/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc b/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc index 1d101f041..9b338c833 100644 --- a/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc +++ b/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc @@ -836,6 +836,7 @@ CIFReader::do_read (db::Layout &layout) db::LayoutLocker locker (&layout); double sf = 0.01 / m_dbu; + check_dbu (m_dbu); layout.dbu (m_dbu); m_cellname = "{CIF top level}"; diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc index 3abe3501f..cf7a00912 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc @@ -350,6 +350,7 @@ DXFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) db::cell_index_type top = layout.add_cell("TOP"); // TODO: make variable .. + check_dbu (m_dbu); layout.dbu (m_dbu); do_read (layout, top); cleanup (layout, top); diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc index dad91a563..f6a9f8889 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc @@ -236,6 +236,7 @@ GDS2ReaderBase::do_read (db::Layout &layout) m_dbuu = dbuu; m_dbu = dbum * 1e6; /*in micron*/ + check_dbu (m_dbu); layout.dbu (m_dbu); } else { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index ed3856e6e..78c08e706 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -30,6 +30,8 @@ namespace db { +static const std::pair ext_not_set = std::make_pair (std::numeric_limits::min (), std::numeric_limits::min ()); + struct DEFImporterGroup { DEFImporterGroup (const std::string &n, const std::string &rn, const std::vector &m) @@ -133,7 +135,7 @@ DEFImporter::get_def_ext (const std::string & /*ln*/, const std::pair::const_iterator pt = pts.begin (); + std::vector >::const_iterator ex = ext.begin (); + while (pt != pts.end ()) { - std::vector::const_iterator pt0 = pt; + auto pt0 = pt; + auto ex0 = ex; ++pt; + ++ex; if (pt == pts.end ()) { break; } bool multipart = false; if (is_isotropic) { - while (pt != pts.end () && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())) { + while (pt != pts.end ()) { + if (! (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())) { + // non-orthogonal segments are treated otherwise, not by paths + break; + } + if (pt + 1 != pts.end () && ex[0] != ext_not_set) { + // connection points feature non-default extensions and should not be represented by paths + break; + } ++pt; + ++ex; multipart = true; } if (multipart) { --pt; + --ex; } } - // The next part is the interval [pt0..pt] (pt inclusive) + // The next part is the interval [pt0..pt] (including pt) - if (multipart || (pt0->x () == pt0[1].x () || pt0->y () == pt0[1].y())) { + if (! multipart && (pt0->x () == pt0[1].x () && pt0->y () == pt0[1].y())) { + + // ignore single-point paths + + } else if (multipart || (pt0->x () == pt0[1].x () || pt0->y () == pt0[1].y())) { db::Coord wxy, wxy_perp; @@ -388,33 +408,27 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u wxy_perp = w.second; } - // compute begin extension + // compute begin and end extensions db::Coord be = 0; - if (pt0 == pts.begin ()) { - if (pt0->x () == pt0 [1].x ()) { - be = ext.front ().second; - } else { - be = ext.front ().first; - } + if (*ex0 != ext_not_set) { + be = (pt0->x () == pt0 [1].x ()) ? ex0->second : ex0->first; } else if (was_path_before) { // provides the overlap to the previous segment be = wxy_perp / 2; } - // compute end extension db::Coord ee = 0; - if (pt + 1 == pts.end ()) { - if (pt [-1].x () == pt->x ()) { - ee = ext.back ().second; - } else { - ee = ext.back ().first; - } + if (*ex != ext_not_set) { + ee = (pt [-1].x () == pt->x ()) ? ex->second : ex->first; } auto pt_from = pt0; auto pt_to = pt + 1; - // do not split away end segments if they are shorter than half the width + // Pplit paths if "joined_paths" is off. Sorry for spending the effort before to + // compute multipath chains. + // But now we can keep end segments joined if they are shorter than half the width + // to establish a proper path end in that case. auto pt_from_split = pt_from; auto pt_to_split = pt_to; @@ -553,10 +567,6 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C const std::string *rulename = 0; std::pair w (0, 0); - if (specialnets) { - db::Coord n = db::coord_traits::rounded (get_double () * scale); - w = std::make_pair (n, n); - } const db::Polygon *style = 0; @@ -564,6 +574,9 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C if (specialnets) { + db::Coord n = db::coord_traits::rounded (get_double () * scale); + w = std::make_pair (n, n); + while (test ("+")) { if (test ("STYLE")) { @@ -598,11 +611,17 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C rulename = &nondefaultrule; } - std::pair def_ext (0, 0); - if (! specialnets) { w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + // default extension for first and last point + std::pair def_ext (0, 0); + std::pair def_ext_conn = get_def_ext (ln, w, layout.dbu ()); + + if (! specialnets) { + // first and last extensions are half width by default for routed nets + def_ext = def_ext_conn; } std::map::const_iterator s = m_styles.find (sn); @@ -694,7 +713,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C y = get_double (); } pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); - std::pair ee = def_ext; + std::pair ee = ext_not_set; if (! peek (")")) { db::Coord e = db::coord_traits::rounded (get_double () * scale); ee.first = ee.second = e; @@ -706,10 +725,20 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C } if (pts.size () > 1) { + + // replace the default extensions + if (ext.front () == ext_not_set) { + ext.front () = def_ext; + } + if (ext.back () == ext_not_set) { + ext.back () = def_ext; + } + std::set dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask); for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { produce_routing_geometry (design, style, *l, prop_id, pts, ext, w); } + } // continue a segment with the current point and the new mask diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index e4e7dfb80..253b7b6db 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -119,6 +119,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti effective_options = *lefdef_options; } + check_dbu (effective_options.dbu ()); layout.dbu (effective_options.dbu ()); std::string base_path; diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 8f27111a6..32898adcf 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -432,7 +432,7 @@ TEST(def16) // (complete example) db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); - run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au_4b.oas.gz", opt); + run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au_4c.oas.gz", opt); } TEST(100) @@ -1153,3 +1153,10 @@ TEST(215_multiDEF) db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS); } + +// issue-2075 +TEST(216_line_extensions) +{ + run_test (_this, "issue-2075", "map:test.map+lef:test.lef+def:test.def", "au.oas", default_options (), false); +} + diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc index 78e6420c4..56abcf8d3 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc +++ b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc @@ -98,6 +98,7 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) top_cell = layout.add_cell (top_cellname.c_str ()); } + check_dbu (m_dbu); layout.dbu (m_dbu); m_cells_to_read.clear (); diff --git a/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc b/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc index a474874a7..07c0e1de4 100644 --- a/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc +++ b/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc @@ -51,7 +51,6 @@ namespace db MALYReader::MALYReader (tl::InputStream &s) : m_stream (s), m_progress (tl::to_string (tr ("Reading MALY file")), 1000), - m_dbu (0.001), m_last_record_line (0) { m_progress.set_format (tl::to_string (tr ("%.0fk lines"))); @@ -89,7 +88,10 @@ MALYReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) init (options); const db::MALYReaderOptions &specific_options = options.get_options (); - m_dbu = specific_options.dbu; + double dbu = specific_options.dbu; + + check_dbu (dbu); + layout.dbu (dbu); set_layer_map (specific_options.layer_map); set_create_layers (specific_options.create_other_layers); diff --git a/src/plugins/streamers/maly/db_plugin/dbMALYReader.h b/src/plugins/streamers/maly/db_plugin/dbMALYReader.h index ea4feabbb..be63c9ccd 100644 --- a/src/plugins/streamers/maly/db_plugin/dbMALYReader.h +++ b/src/plugins/streamers/maly/db_plugin/dbMALYReader.h @@ -223,7 +223,6 @@ private: tl::TextInputStream m_stream; tl::AbsoluteProgress m_progress; - double m_dbu; unsigned int m_last_record_line; std::string m_record; std::string m_record_returned; diff --git a/src/plugins/streamers/maly/unit_tests/dbMALYReaderTests.cc b/src/plugins/streamers/maly/unit_tests/dbMALYReaderTests.cc index 95a6ff447..6068c082f 100644 --- a/src/plugins/streamers/maly/unit_tests/dbMALYReaderTests.cc +++ b/src/plugins/streamers/maly/unit_tests/dbMALYReaderTests.cc @@ -135,6 +135,7 @@ TEST(10_BasicLayout) { run_test (_this, tl::testdata (), "MALY_test10.maly", "maly_test10_au.oas"); run_test (_this, tl::testdata (), "MALY_test10.maly", "maly_test10_lm_au.oas", "A: 10, B: 11, C: 12, D: 13"); + run_test (_this, tl::testdata (), "MALY_test10.maly", "maly_test10_dbu10nm_au.oas", 0, 0.01); } TEST(11_Titles) diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc index 74fc56034..2ea867b15 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc @@ -110,22 +110,22 @@ OASISReader::init (const db::LoadLayoutOptions &options) m_expect_strict_mode = oasis_options.expect_strict_mode; } -inline long long -OASISReader::get_long_long () +inline int64_t +OASISReader::get_int64 () { - unsigned long long u = get_ulong_long (); + uint64_t u = get_uint64 (); if ((u & 1) != 0) { - return -(long long) (u >> 1); + return -(int64_t) (u >> 1); } else { - return (long long) (u >> 1); + return (int64_t) (u >> 1); } } -inline unsigned long long -OASISReader::get_ulong_long () +inline uint64_t +OASISReader::get_uint64 () { - unsigned long long v = 0; - unsigned long long vm = 1; + uint64_t v = 0; + uint64_t vm = 1; char c; do { @@ -135,79 +135,43 @@ OASISReader::get_ulong_long () return 0; } c = *b; - if (vm > std::numeric_limits ::max () / 128 && - (unsigned long long) (c & 0x7f) > (std::numeric_limits ::max () / vm)) { - error (tl::to_string (tr ("Unsigned long value overflow"))); + if (vm > std::numeric_limits ::max () / 128 && + (uint64_t) (c & 0x7f) > (std::numeric_limits ::max () / vm)) { + error (tl::to_string (tr ("uint64 value overflow"))); } - v += (unsigned long long) (c & 0x7f) * vm; + v += (uint64_t) (c & 0x7f) * vm; vm <<= 7; } while ((c & 0x80) != 0); return v; } -inline long -OASISReader::get_long () +inline uint64_t +OASISReader::get_uint64_for_divider () { - unsigned long u = get_ulong (); - if ((u & 1) != 0) { - return -long (u >> 1); - } else { - return long (u >> 1); - } -} - -inline unsigned long -OASISReader::get_ulong_for_divider () -{ - unsigned long l = get_ulong (); + uint64_t l = get_uint64 (); if (l == 0) { error (tl::to_string (tr ("Divider must not be zero"))); } return l; } -inline unsigned long -OASISReader::get_ulong () +inline int32_t +OASISReader::get_int32 () { - unsigned long v = 0; - unsigned long vm = 1; - char c; - - do { - unsigned char *b = (unsigned char *) m_stream.get (1); - if (! b) { - error (tl::to_string (tr ("Unexpected end-of-file"))); - return 0; - } - c = *b; - if (vm > std::numeric_limits ::max () / 128 && - (unsigned long) (c & 0x7f) > (std::numeric_limits ::max () / vm)) { - error (tl::to_string (tr ("Unsigned long value overflow"))); - } - v += (unsigned long) (c & 0x7f) * vm; - vm <<= 7; - } while ((c & 0x80) != 0); - - return v; -} - -inline int -OASISReader::get_int () -{ - unsigned int u = get_uint (); + uint32_t u = get_uint32 (); if ((u & 1) != 0) { - return -int (u >> 1); + return -int32_t (u >> 1); } else { - return int (u >> 1); + return int32_t (u >> 1); } } -inline unsigned int -OASISReader::get_uint () +inline uint32_t +OASISReader::get_uint32 () { - unsigned int v = 0; - unsigned int vm = 1; + uint32_t v = 0; + uint32_t vm = 1; char c; do { @@ -217,11 +181,11 @@ OASISReader::get_uint () return 0; } c = *b; - if (vm > std::numeric_limits ::max () / 128 && - (unsigned int) (c & 0x7f) > (std::numeric_limits ::max () / vm)) { - error (tl::to_string (tr ("Unsigned integer value overflow"))); + if (vm > std::numeric_limits ::max () / 128 && + (uint32_t) (c & 0x7f) > (std::numeric_limits ::max () / vm)) { + error (tl::to_string (tr ("uin32 value overflow"))); } - v += (unsigned int) (c & 0x7f) * vm; + v += (uint32_t) (c & 0x7f) * vm; vm <<= 7; } while ((c & 0x80) != 0); @@ -240,7 +204,7 @@ void OASISReader::get_str (std::string &s) { size_t l = 0; - get (l); + get_size (l); char *b = (char *) m_stream.get (l); if (b) { @@ -253,33 +217,33 @@ OASISReader::get_str (std::string &s) double OASISReader::get_real () { - unsigned int t = get_uint (); + unsigned int t = get_uint32 (); if (t == 0) { - return double (get_ulong ()); + return double (get_uint64 ()); } else if (t == 1) { - return -double (get_ulong ()); + return -double (get_uint64 ()); } else if (t == 2) { - return 1.0 / double (get_ulong_for_divider ()); + return 1.0 / double (get_uint64_for_divider ()); } else if (t == 3) { - return -1.0 / double (get_ulong_for_divider ()); + return -1.0 / double (get_uint64_for_divider ()); } else if (t == 4) { - double d = double (get_ulong ()); - return d / double (get_ulong_for_divider ()); + double d = double (get_uint64 ()); + return d / double (get_uint64_for_divider ()); } else if (t == 5) { - double d = double (get_ulong ()); - return -d / double (get_ulong_for_divider ()); + double d = double (get_uint64 ()); + return -d / double (get_uint64_for_divider ()); } else if (t == 6) { @@ -326,51 +290,51 @@ OASISReader::get_real () } db::Coord -OASISReader::get_ucoord (unsigned long grid) +OASISReader::get_ucoord (uint64_t grid) { - unsigned long long lx = 0; + uint64_t lx = 0; get (lx); lx *= grid; - if (lx > (unsigned long long) (std::numeric_limits ::max ())) { + if (lx > (uint64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } return db::Coord (lx); } OASISReader::distance_type -OASISReader::get_ucoord_as_distance (unsigned long grid) +OASISReader::get_ucoord_as_distance (uint64_t grid) { - unsigned long long lx = 0; + uint64_t lx = 0; get (lx); lx *= grid; - if (lx > (unsigned long long) (std::numeric_limits ::max ())) { + if (lx > (uint64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } return distance_type (lx); } db::Coord -OASISReader::get_coord (long grid) +OASISReader::get_coord (int64_t grid) { - long long lx = 0; + int64_t lx = 0; get (lx); lx *= grid; - if (lx < (long long) (std::numeric_limits ::min ()) || - lx > (long long) (std::numeric_limits ::max ())) { + if (lx < (int64_t) (std::numeric_limits ::min ()) || + lx > (int64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } return db::Coord (lx); } db::Vector -OASISReader::get_2delta (long grid) +OASISReader::get_2delta (int64_t grid) { - unsigned long long l1 = 0; + uint64_t l1 = 0; get (l1); - long long lx = l1 >> 2; + int64_t lx = l1 >> 2; lx *= grid; - if (lx > (long long) (std::numeric_limits ::max ())) { + if (lx > (int64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } db::Coord x = lx; @@ -389,14 +353,14 @@ OASISReader::get_2delta (long grid) } db::Vector -OASISReader::get_3delta (long grid) +OASISReader::get_3delta (int64_t grid) { - unsigned long long l1 = 0; + uint64_t l1 = 0; get (l1); - long long lx = l1 >> 3; + int64_t lx = l1 >> 3; lx *= grid; - if (lx > (long long) (std::numeric_limits ::max ())) { + if (lx > (int64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } db::Coord x = lx; @@ -423,25 +387,25 @@ OASISReader::get_3delta (long grid) } db::Vector -OASISReader::get_gdelta (long grid) +OASISReader::get_gdelta (int64_t grid) { - unsigned long long l1 = 0; + uint64_t l1 = 0; get (l1); if ((l1 & 1) != 0) { - long long lx = ((l1 & 2) == 0 ? (long long) (l1 >> 2) : -(long long) (l1 >> 2)); + int64_t lx = ((l1 & 2) == 0 ? (int64_t) (l1 >> 2) : -(int64_t) (l1 >> 2)); lx *= grid; - if (lx < (long long) (std::numeric_limits ::min ()) || - lx > (long long) (std::numeric_limits ::max ())) { + if (lx < (int64_t) (std::numeric_limits ::min ()) || + lx > (int64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } - long long ly; + int64_t ly; get (ly); ly *= grid; - if (ly < (long long) (std::numeric_limits ::min ()) || - ly > (long long) (std::numeric_limits ::max ())) { + if (ly < (int64_t) (std::numeric_limits ::min ()) || + ly > (int64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } @@ -449,9 +413,9 @@ OASISReader::get_gdelta (long grid) } else { - long long lx = l1 >> 4; + int64_t lx = l1 >> 4; lx *= grid; - if (lx > (long long) (std::numeric_limits ::max ())) { + if (lx > (int64_t) (std::numeric_limits ::max ())) { error (tl::to_string (tr ("Coordinate value overflow"))); } db::Coord x = lx; @@ -568,42 +532,42 @@ OASISReader::mark_start_table () void OASISReader::read_offset_table () { - unsigned int of = 0; + uint64_t of = 0; - of = get_uint (); - get (m_table_cellname); + of = get_uint64 (); + get_size (m_table_cellname); if (m_table_cellname != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("CELLNAME offset table has unexpected strict mode"))); } - of = get_uint (); - get (m_table_textstring); + of = get_uint64 (); + get_size (m_table_textstring); if (m_table_textstring != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("TEXTSTRING offset table has unexpected strict mode"))); } - of = get_uint (); - get (m_table_propname); + of = get_uint64 (); + get_size (m_table_propname); if (m_table_propname != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("PROPNAME offset table has unexpected strict mode"))); } - of = get_uint (); - get (m_table_propstring); + of = get_uint64 (); + get_size (m_table_propstring); if (m_table_propstring != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("PROPSTRING offset table has unexpected strict mode"))); } - of = get_uint (); - get (m_table_layername); + of = get_uint64 (); + get_size (m_table_layername); if (m_table_layername != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("LAYERNAME offset table has unexpected strict mode"))); } // XNAME table ignored currently - get_uint (); + get_uint64 (); size_t dummy = 0; - get (dummy); + get_size (dummy); } static const char magic_bytes[] = { "%SEMI-OASIS\015\012" }; @@ -659,10 +623,12 @@ OASISReader::do_read (db::Layout &layout) } // compute database unit in pixel per meter - layout.dbu (1.0 / res); + double dbu = 1.0 / res; + check_dbu (dbu); + layout.dbu (dbu); // read over table offsets if required - bool table_offsets_at_end = get_uint (); + bool table_offsets_at_end = get_uint64 () != 0; if (! table_offsets_at_end) { read_offset_table (); } @@ -681,10 +647,10 @@ OASISReader::do_read (db::Layout &layout) m_table_layername = 0; // define the name id counters - unsigned long cellname_id = 0; - unsigned long textstring_id = 0; - unsigned long propstring_id = 0; - unsigned long propname_id = 0; + uint64_t cellname_id = 0; + uint64_t textstring_id = 0; + uint64_t propstring_id = 0; + uint64_t propname_id = 0; // id mode (explicit or implicit) enum id_mode { any, expl, impl }; @@ -744,7 +710,7 @@ OASISReader::do_read (db::Layout &layout) std::string name = get_str (); // and the associated id - unsigned long id = cellname_id; + uint64_t id = cellname_id; if (r == 3) { if (cellname_id_mode == expl) { error (tl::to_string (tr ("Explicit and implicit CELLNAME modes cannot be mixed"))); @@ -782,7 +748,7 @@ OASISReader::do_read (db::Layout &layout) std::string name = get_str (); // and the associated id - unsigned long id = textstring_id; + uint64_t id = textstring_id; if (r == 5) { if (textstring_id_mode == expl) { error (tl::to_string (tr ("Explicit and implicit TEXTSTRING modes cannot be mixed"))); @@ -819,7 +785,7 @@ OASISReader::do_read (db::Layout &layout) std::string name = get_str (); // and the associated id - unsigned long id = propname_id; + uint64_t id = propname_id; if (r == 7) { if (propname_id_mode == expl) { error (tl::to_string (tr ("Explicit and implicit PROPNAME modes cannot be mixed"))); @@ -861,7 +827,7 @@ OASISReader::do_read (db::Layout &layout) std::string name = get_str (); // and the associated id - unsigned long id = propstring_id; + uint64_t id = propstring_id; if (r == 9) { if (propstring_id_mode == expl) { error (tl::to_string (tr ("Explicit and implicit PROPSTRING modes cannot be mixed"))); @@ -880,7 +846,7 @@ OASISReader::do_read (db::Layout &layout) error (tl::sprintf (tl::to_string (tr ("A PROPSTRING with id %ld is present already")), id)); } - std::map::iterator fw = m_propvalue_forward_references.find (id); + std::map::iterator fw = m_propvalue_forward_references.find (id); if (fw != m_propvalue_forward_references.end ()) { fw->second = name; } @@ -904,38 +870,38 @@ OASISReader::do_read (db::Layout &layout) db::ld_type dt1 = 0, dt2 = std::numeric_limits::max () - 1; db::ld_type l1 = 0, l2 = std::numeric_limits::max () - 1; - unsigned int it; + uint32_t it; - it = get_uint (); + it = get_uint32 (); if (it == 0) { // keep limits } else if (it == 1) { - l2 = get_uint (); + l2 = get_uint32 (); } else if (it == 2) { - l1 = get_uint (); + l1 = get_uint32 (); } else if (it == 3) { - l1 = get_uint (); + l1 = get_uint32 (); l2 = l1; } else if (it == 4) { - l1 = get_uint (); - l2 = get_uint (); + l1 = get_uint32 (); + l2 = get_uint32 (); } else { error (tl::to_string (tr ("Invalid LAYERNAME interval mode (layer)"))); } - it = get_uint (); + it = get_uint32 (); if (it == 0) { // keep limits } else if (it == 1) { - dt2 = get_uint (); + dt2 = get_uint32 (); } else if (it == 2) { - dt1 = get_uint (); + dt1 = get_uint32 (); } else if (it == 3) { - dt1 = get_uint (); + dt1 = get_uint32 (); dt2 = dt1; } else if (it == 4) { - dt1 = get_uint (); - dt2 = get_uint (); + dt1 = get_uint32 (); + dt2 = get_uint32 (); } else { error (tl::to_string (tr ("Invalid LAYERNAME interval mode (datatype)"))); } @@ -973,10 +939,10 @@ OASISReader::do_read (db::Layout &layout) } else if (r == 30 || r == 31 /*XNAME*/) { // read a XNAME: it is simply ignored - get_ulong (); + get_uint64 (); get_str (); if (r == 31) { - get_ulong (); + get_uint64 (); } reset_modal_variables (); @@ -993,7 +959,7 @@ OASISReader::do_read (db::Layout &layout) // read a cell if (r == 13) { - unsigned long id = 0; + uint64_t id = 0; get (id); std::pair cc = cell_by_id (id); @@ -1034,12 +1000,12 @@ OASISReader::do_read (db::Layout &layout) } else if (r == 34 /*CBLOCK*/) { - unsigned int type = get_uint (); + uint32_t type = get_uint32 (); if (type != 0) { error (tl::sprintf (tl::to_string (tr ("Invalid CBLOCK compression type %d")), type)); } - size_t dummy = 0; + uint64_t dummy = 0; get (dummy); // uncomp-byte-count - not needed get (dummy); // comp-byte-count - not needed @@ -1070,7 +1036,7 @@ OASISReader::do_read (db::Layout &layout) error (tl::to_string (tr ("Format error (too many bytes after END record)"))); } - for (std::map ::const_iterator fw = m_text_forward_references.begin (); fw != m_text_forward_references.end (); ++fw) { + for (std::map ::const_iterator fw = m_text_forward_references.begin (); fw != m_text_forward_references.end (); ++fw) { auto ts = m_textstrings.find (fw->first); if (ts == m_textstrings.end ()) { error (tl::sprintf (tl::to_string (tr ("No text string defined for text string id %ld")), fw->first)); @@ -1080,7 +1046,7 @@ OASISReader::do_read (db::Layout &layout) } // all forward references to property names must be resolved - for (std::map ::const_iterator fw = m_propname_forward_references.begin (); fw != m_propname_forward_references.end (); ++fw) { + for (std::map ::const_iterator fw = m_propname_forward_references.begin (); fw != m_propname_forward_references.end (); ++fw) { if (fw->second == 0) { error (tl::sprintf (tl::to_string (tr ("No property name defined for property name id %ld")), fw->first)); } @@ -1181,7 +1147,7 @@ OASISReader::do_read (db::Layout &layout) } // attach the properties found in CELLNAME to the cells (which may have other properties) - for (std::map::const_iterator p = m_cellname_properties.begin (); p != m_cellname_properties.end (); ++p) { + for (std::map::const_iterator p = m_cellname_properties.begin (); p != m_cellname_properties.end (); ++p) { // The cellname properties ID may be a forward properties ID, resolve it first @@ -1356,7 +1322,7 @@ OASISReader::resolve_forward_references (db::PropertiesSet &properties) const tl::Variant &name = db::property_name (p->first); if (name.is_id ()) { - std::map ::iterator pf = m_propname_forward_references.find (name.to_id ()); + std::map ::iterator pf = m_propname_forward_references.find (name.to_id ()); if (pf != m_propname_forward_references.end ()) { if (pf->second == m_s_gds_property_name_id) { @@ -1388,8 +1354,8 @@ OASISReader::replace_forward_references_in_variant (tl::Variant &v) { if (v.is_id ()) { - unsigned long id = (unsigned long) v.to_id (); - std::map ::const_iterator fw = m_propvalue_forward_references.find (id); + uint64_t id = (uint64_t) v.to_id (); + std::map ::const_iterator fw = m_propvalue_forward_references.find (id); if (fw != m_propvalue_forward_references.end ()) { v = tl::Variant (fw->second); } else { @@ -1412,8 +1378,8 @@ OASISReader::replace_forward_references_in_variant (tl::Variant &v) std::vector new_list (l); for (std::vector::iterator ll = new_list.begin (); ll != new_list.end (); ++ll) { if (ll->is_id ()) { - unsigned long id = (unsigned long) ll->to_id (); - std::map ::const_iterator fw = m_propvalue_forward_references.find (id); + uint64_t id = (uint64_t) ll->to_id (); + std::map ::const_iterator fw = m_propvalue_forward_references.find (id); if (fw != m_propvalue_forward_references.end ()) { *ll = tl::Variant (fw->second); } else { @@ -1483,12 +1449,12 @@ OASISReader::read_element_properties (bool ignore_special) } else if (m == 34 /*CBLOCK*/) { - unsigned int type = get_uint (); + uint32_t type = get_uint32 (); if (type != 0) { error (tl::sprintf (tl::to_string (tr ("Invalid CBLOCK compression type %d")), type)); } - size_t dummy = 0; + uint64_t dummy = 0; get (dummy); // uncomp-byte-count - not needed get (dummy); // comp-byte-count - not needed @@ -1539,10 +1505,10 @@ OASISReader::read_properties () if (m & 0x04) { if (m & 0x02) { - unsigned long id; + uint64_t id; get (id); - std::map ::const_iterator cid = m_propnames.find (id); + std::map ::const_iterator cid = m_propnames.find (id); if (cid == m_propnames.end ()) { mm_last_property_name = db::property_names_id (tl::Variant (id, true /*dummy for id type*/)); m_propname_forward_references.insert (std::make_pair (id, db::property_names_id_type (0))); @@ -1563,7 +1529,7 @@ OASISReader::read_properties () if (! (m & 0x08)) { - unsigned long n = ((unsigned long) (m >> 4)) & 0x0f; + uint64_t n = ((uint64_t) (m >> 4)) & 0x0f; if (n == 15) { get (n); } @@ -1584,15 +1550,15 @@ OASISReader::read_properties () } else if (t == 8) { - unsigned long l; + uint64_t l; get (l); if (m_read_properties) { - mm_last_value_list.get_non_const ().push_back (tl::Variant (long (l))); + mm_last_value_list.get_non_const ().push_back (tl::Variant (int64_t (l))); } } else if (t == 9) { - long l; + int64_t l; get (l); if (m_read_properties) { mm_last_value_list.get_non_const ().push_back (tl::Variant (l)); @@ -1612,10 +1578,10 @@ OASISReader::read_properties () } else if (t == 13 || t == 14 || t == 15) { - unsigned long id; + uint64_t id; get (id); if (m_read_properties) { - std::map ::const_iterator sid = m_propstrings.find (id); + std::map ::const_iterator sid = m_propstrings.find (id); if (sid == m_propstrings.end ()) { m_propvalue_forward_references.insert (std::make_pair (id, std::string ())); mm_last_value_list.get_non_const ().push_back (tl::Variant (id, true /*dummy for id type*/)); @@ -1642,9 +1608,9 @@ OASISReader::read_properties () void OASISReader::read_pointlist (modal_variable > &pointlist, bool for_polygon) { - unsigned int type = get_uint (); + uint32_t type = get_uint32 (); - unsigned long n = 0; + uint64_t n = 0; get (n); if (n == 0) { error (tl::to_string (tr ("Invalid point list: length is zero")).c_str ()); @@ -1665,7 +1631,7 @@ OASISReader::read_pointlist (modal_variable > &pointlis bool h = (type == 0); db::Point pos; - for (unsigned long i = 0; i < n; ++i) { + for (uint64_t i = 0; i < n; ++i) { db::Coord d = get_coord (); if (h) { pos += db::Vector (d, 0); @@ -1691,7 +1657,7 @@ OASISReader::read_pointlist (modal_variable > &pointlis } else if (type == 2) { db::Point pos; - for (unsigned long i = 0; i < n; ++i) { + for (uint64_t i = 0; i < n; ++i) { pos += get_2delta (); pointlist.get_non_const ().push_back (pos); } @@ -1699,7 +1665,7 @@ OASISReader::read_pointlist (modal_variable > &pointlis } else if (type == 3) { db::Point pos; - for (unsigned long i = 0; i < n; ++i) { + for (uint64_t i = 0; i < n; ++i) { pos += get_3delta (); pointlist.get_non_const ().push_back (pos); } @@ -1707,7 +1673,7 @@ OASISReader::read_pointlist (modal_variable > &pointlis } else if (type == 4) { db::Point pos; - for (unsigned long i = 0; i < n; ++i) { + for (uint64_t i = 0; i < n; ++i) { pos += get_gdelta (); pointlist.get_non_const ().push_back (pos); } @@ -1716,7 +1682,7 @@ OASISReader::read_pointlist (modal_variable > &pointlis db::Point pos; db::Vector delta; - for (unsigned long i = 0; i < n; ++i) { + for (uint64_t i = 0; i < n; ++i) { delta += get_gdelta (); pos += delta; pointlist.get_non_const ().push_back (pos); @@ -1732,14 +1698,14 @@ OASISReader::read_pointlist (modal_variable > &pointlis bool OASISReader::read_repetition () { - unsigned int type = get_uint (); + uint32_t type = get_uint32 (); if (type == 0) { // reuse modal variable } else if (type == 1) { - unsigned long nx = 0, ny = 0; + uint64_t nx = 0, ny = 0; get (nx); get (ny); @@ -1750,7 +1716,7 @@ OASISReader::read_repetition () } else if (type == 2) { - unsigned long nx = 0; + uint64_t nx = 0; get (nx); db::Coord dx = get_ucoord (); @@ -1759,7 +1725,7 @@ OASISReader::read_repetition () } else if (type == 3) { - unsigned long ny = 0; + uint64_t ny = 0; get (ny); db::Coord dy = get_ucoord (); @@ -1771,10 +1737,10 @@ OASISReader::read_repetition () IrregularRepetition *rep = new IrregularRepetition (); mm_repetition = rep; - unsigned long n = 0; + uint64_t n = 0; get (n); - unsigned long lgrid = 1; + uint64_t lgrid = 1; if (type == 5) { get (lgrid); } @@ -1782,7 +1748,7 @@ OASISReader::read_repetition () rep->reserve (n + 1); db::Coord x = 0; - for (unsigned long i = 0; i <= n; ++i) { + for (uint64_t i = 0; i <= n; ++i) { m_progress.set (m_stream.pos ()); db::Coord d = get_ucoord (lgrid); if (d != 0) { @@ -1796,10 +1762,10 @@ OASISReader::read_repetition () IrregularRepetition *rep = new IrregularRepetition (); mm_repetition = rep; - unsigned long n = 0; + uint64_t n = 0; get (n); - unsigned long lgrid = 1; + uint64_t lgrid = 1; if (type == 7) { get (lgrid); } @@ -1807,7 +1773,7 @@ OASISReader::read_repetition () rep->reserve (n + 1); db::Coord y = 0; - for (unsigned long i = 0; i <= n; ++i) { + for (uint64_t i = 0; i <= n; ++i) { m_progress.set (m_stream.pos ()); db::Coord d = get_ucoord (lgrid); if (d != 0) { @@ -1818,7 +1784,7 @@ OASISReader::read_repetition () } else if (type == 8) { - unsigned long n = 0, m = 0; + uint64_t n = 0, m = 0; get (n); get (m); @@ -1829,7 +1795,7 @@ OASISReader::read_repetition () } else if (type == 9) { - unsigned long n = 0; + uint64_t n = 0; get (n); db::Vector dn = get_gdelta (); @@ -1840,10 +1806,10 @@ OASISReader::read_repetition () IrregularRepetition *rep = new IrregularRepetition (); mm_repetition = rep; - unsigned long n = 0; + uint64_t n = 0; get (n); - unsigned long grid = 1; + uint64_t grid = 1; if (type == 11) { get (grid); } @@ -1851,7 +1817,7 @@ OASISReader::read_repetition () rep->reserve (n + 1); db::Vector p; - for (unsigned long i = 0; i <= n; ++i) { + for (uint64_t i = 0; i <= n; ++i) { m_progress.set (m_stream.pos ()); db::Vector d = get_gdelta (grid); if (d != db::Vector ()) { @@ -1882,7 +1848,7 @@ OASISReader::do_read_placement (unsigned char r, if (m & 0x40) { // cell by id - unsigned long id; + uint64_t id; get (id); mm_placement_cell = cell_for_instance (layout, id); @@ -1974,10 +1940,10 @@ OASISReader::do_read_placement (unsigned char r, if (mag_set || angle < 0) { inst = db::CellInstArray (db::CellInst (mm_placement_cell.get ()), - db::ICplxTrans (mag, angle_deg, mirror, pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb); + db::ICplxTrans (mag, angle_deg, mirror, pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb); } else { inst = db::CellInstArray (db::CellInst (mm_placement_cell.get ()), - db::Trans (angle, mirror, pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb); + db::Trans (angle, mirror, pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb); } if (pp.first) { @@ -2078,7 +2044,7 @@ OASISReader::do_read_text (bool xy_absolute, if (m & 0x40) { if (m & 0x20) { - unsigned long id; + uint64_t id; get (id); if (m_text_forward_references.find (id) != m_text_forward_references.end ()) { @@ -2088,7 +2054,7 @@ OASISReader::do_read_text (bool xy_absolute, } else { - std::map ::const_iterator tid = m_textstrings.find (id); + std::map ::const_iterator tid = m_textstrings.find (id); if (tid == m_textstrings.end ()) { mm_text_string.reset (); @@ -2117,11 +2083,11 @@ OASISReader::do_read_text (bool xy_absolute, } if (m & 0x1) { - mm_textlayer = get_uint (); + mm_textlayer = get_uint32 (); } if (m & 0x2) { - mm_texttype = get_uint (); + mm_texttype = get_uint32 (); } if (m & 0x10) { @@ -2178,12 +2144,12 @@ OASISReader::do_read_text (bool xy_absolute, db::TextPtr text_ptr (text, layout.shape_repository ()); if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties (db::Shape::text_ptr_array_type (text_ptr, db::Disp (pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties (db::Shape::text_ptr_array_type (text_ptr, db::Disp (pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::Shape::text_ptr_array_type (text_ptr, db::Disp (pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::Shape::text_ptr_array_type (text_ptr, db::Disp (pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -2261,11 +2227,11 @@ OASISReader::do_read_rectangle (bool xy_absolute, unsigned char m = get_byte (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } if (m & 0x40) { @@ -2322,12 +2288,12 @@ OASISReader::do_read_rectangle (bool xy_absolute, // Create a box array if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties (db::Shape::box_array_type (box, db::UnitTrans (), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties (db::Shape::box_array_type (box, db::UnitTrans (), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::Shape::box_array_type (box, db::UnitTrans (), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::Shape::box_array_type (box, db::UnitTrans (), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -2395,11 +2361,11 @@ OASISReader::do_read_polygon (bool xy_absolute, db::cell_index_type cell_index, unsigned char m = get_byte (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } if (m & 0x20) { @@ -2460,12 +2426,12 @@ OASISReader::do_read_polygon (bool xy_absolute, db::cell_index_type cell_index, db::SimplePolygonPtr poly_ptr (poly, layout.shape_repository ()); if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -2550,11 +2516,11 @@ OASISReader::do_read_path (bool xy_absolute, db::cell_index_type cell_index, db: unsigned char m = get_byte (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } if (m & 0x40) { @@ -2563,7 +2529,7 @@ OASISReader::do_read_path (bool xy_absolute, db::cell_index_type cell_index, db: if (m & 0x80) { - unsigned int e = get_uint (); + uint32_t e = get_uint32 (); if ((e & 0x0c) == 0x0c) { mm_path_start_extension = get_coord (); } else if ((e & 0x0c) == 0x04) { @@ -2641,12 +2607,12 @@ OASISReader::do_read_path (bool xy_absolute, db::cell_index_type cell_index, db: db::PathPtr path_ptr (path, layout.shape_repository ()); if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (path_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (path_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::array (path_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::array (path_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -2733,11 +2699,11 @@ OASISReader::do_read_trapezoid (unsigned char r, bool xy_absolute,db::cell_index unsigned char m = get_byte (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } if (m & 0x40) { @@ -2822,12 +2788,12 @@ OASISReader::do_read_trapezoid (unsigned char r, bool xy_absolute,db::cell_index db::SimplePolygonPtr poly_ptr (poly, layout.shape_repository ()); if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -2904,15 +2870,15 @@ OASISReader::do_read_ctrapezoid (bool xy_absolute,db::cell_index_type cell_index unsigned char m = get_byte (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } if (m & 0x80) { - mm_ctrapezoid_type = get_uint (); + mm_ctrapezoid_type = get_uint32 (); } if (m & 0x40) { @@ -3193,12 +3159,12 @@ OASISReader::do_read_ctrapezoid (bool xy_absolute,db::cell_index_type cell_index db::SimplePolygonPtr poly_ptr (poly, layout.shape_repository ()); if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::array (poly_ptr, db::Disp (d + pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -3275,11 +3241,11 @@ OASISReader::do_read_circle (bool xy_absolute, db::cell_index_type cell_index, d unsigned char m = get_byte (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } if (m & 0x20) { @@ -3343,12 +3309,12 @@ OASISReader::do_read_circle (bool xy_absolute, db::cell_index_type cell_index, d db::PathPtr path_ptr (path, layout.shape_repository ()); if (pp.first) { - auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (path_ptr, db::Disp (pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb), pp.second)); + auto shape = cell.shapes (ll.second).insert (db::object_with_properties > (db::array (path_ptr, db::Disp (pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb), pp.second)); if (is_forward_properties_id (pp.second)) { register_forward_property_for_shape (shape); } } else { - cell.shapes (ll.second).insert (db::array (path_ptr, db::Disp (pos), layout.array_repository (), a, b, (unsigned long) na, (unsigned long) nb)); + cell.shapes (ll.second).insert (db::array (path_ptr, db::Disp (pos), layout.array_repository (), a, b, (uint64_t) na, (uint64_t) nb)); } } else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) { @@ -3537,7 +3503,7 @@ OASISReader::do_read_cell (db::cell_index_type cell_index, db::Layout &layout) } else if (r == 32 /*XELEMENT*/) { // read over - get_ulong (); + get_uint64 (); get_str (); read_element_properties (true); @@ -3547,14 +3513,14 @@ OASISReader::do_read_cell (db::cell_index_type cell_index, db::Layout &layout) // read over. unsigned char m = get_byte (); - get_ulong (); + get_uint64 (); if (m & 0x1) { - mm_layer = get_uint (); + mm_layer = get_uint32 (); } if (m & 0x2) { - mm_datatype = get_uint (); + mm_datatype = get_uint32 (); } // data payload: @@ -3588,12 +3554,12 @@ OASISReader::do_read_cell (db::cell_index_type cell_index, db::Layout &layout) } else if (r == 34 /*CBLOCK*/) { - unsigned int type = get_uint (); + uint32_t type = get_uint32 (); if (type != 0) { error (tl::sprintf (tl::to_string (tr ("Invalid CBLOCK compression type %d")), type)); } - size_t dummy = 0; + uint64_t dummy = 0; get (dummy); // uncomp-byte-count - not needed get (dummy); // comp-byte-count - not needed diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h index 7d64666bd..28df204fc 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h @@ -140,14 +140,14 @@ private: modal_variable mm_placement_cell; modal_variable mm_placement_x; modal_variable mm_placement_y; - modal_variable mm_layer; - modal_variable mm_datatype; - modal_variable mm_textlayer; - modal_variable mm_texttype; + modal_variable mm_layer; + modal_variable mm_datatype; + modal_variable mm_textlayer; + modal_variable mm_texttype; modal_variable mm_text_x; modal_variable mm_text_y; modal_variable mm_text_string; - modal_variable mm_text_string_id; + modal_variable mm_text_string_id; modal_variable mm_geometry_x; modal_variable mm_geometry_y; modal_variable mm_geometry_w; @@ -157,17 +157,17 @@ private: modal_variable mm_path_start_extension; modal_variable mm_path_end_extension; modal_variable< std::vector > mm_path_point_list; - modal_variable mm_ctrapezoid_type; + modal_variable mm_ctrapezoid_type; modal_variable mm_circle_radius; modal_variable mm_last_property_name; modal_variable mm_last_property_is_sprop; modal_variable mm_last_value_list; - std::map m_cellname_properties; - std::map m_textstrings; - std::map m_text_forward_references; - std::map m_propstrings; - std::map m_propnames; + std::map m_cellname_properties; + std::map m_textstrings; + std::map m_text_forward_references; + std::map m_propstrings; + std::map m_propnames; std::map > m_context_strings_per_cell; @@ -178,8 +178,8 @@ private: bool m_read_properties; bool m_read_all_properties; - std::map m_propname_forward_references; - std::map m_propvalue_forward_references; + std::map m_propname_forward_references; + std::map m_propvalue_forward_references; std::map > m_forward_properties_for_shapes; std::map > m_forward_properties_for_instances; std::map m_future_cell_properties; @@ -234,42 +234,35 @@ private: } } - long long get_long_long (); - unsigned long long get_ulong_long (); - long get_long (); - unsigned long get_ulong (); - unsigned long get_ulong_for_divider (); - int get_int (); - unsigned int get_uint (); + int64_t get_int64 (); + uint64_t get_uint64 (); + uint64_t get_uint64_for_divider (); + int32_t get_int32 (); + uint32_t get_uint32 (); - void get (long long &l) + void get (int64_t &l) { - l = get_long_long (); + l = get_int64 (); } - void get (unsigned long long &l) + void get_size (size_t &l) { - l = get_ulong_long (); + l = get_uint64 (); } - void get (long &l) + void get (uint64_t &l) { - l = get_long (); + l = get_uint64 (); } - void get (unsigned long &l) + void get (int32_t &l) { - l = get_ulong (); + l = get_int32 (); } - void get (int &l) + void get (uint32_t &l) { - l = get_int (); - } - - void get (unsigned int &l) - { - l = get_uint (); + l = get_uint32 (); } void get (double &d) @@ -280,12 +273,12 @@ private: std::string get_str (); void get_str (std::string &s); double get_real (); - db::Vector get_gdelta (long grid = 1); - db::Vector get_3delta (long grid = 1); - db::Vector get_2delta (long grid = 1); - db::Coord get_coord (long grid = 1); - db::Coord get_ucoord (unsigned long grid = 1); - distance_type get_ucoord_as_distance (unsigned long grid = 1); + db::Vector get_gdelta (int64_t grid = 1); + db::Vector get_3delta (int64_t grid = 1); + db::Vector get_2delta (int64_t grid = 1); + db::Coord get_coord (int64_t grid = 1); + db::Coord get_ucoord (uint64_t grid = 1); + distance_type get_ucoord_as_distance (uint64_t grid = 1); }; } diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc index 548a4e447..292326925 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc @@ -26,6 +26,7 @@ #include "tlDeflate.h" #include "tlMath.h" +#include "tlUniqueName.h" #include @@ -411,7 +412,7 @@ Compressor::flush (db::OASISWriter *writer) if (dd != displacements.end ()) { dxy = xrep ? db::Vector (safe_diff (dd->x (), d->x ()), 0) : db::Vector (0, safe_diff (dd->y (), d->y ())); - while (dd != displacements.end () && *dd == dd[-1] + dxy) { + while (dd != displacements.end () && *dd == dd[-1] + dxy && nxy < std::numeric_limits::max ()) { ++dd; ++nxy; } @@ -453,7 +454,7 @@ Compressor::flush (db::OASISWriter *writer) db::Vector dxy = xrep ? db::Vector (safe_diff (dd->x (), d->x ()), 0) : db::Vector (0, safe_diff (dd->y (), d->y ())); int nxy = 2; - while (dd != dwindow) { + while (dd != dwindow && nxy < std::numeric_limits::max ()) { disp_vector::iterator df = std::lower_bound (dd + 1, dwindow, *dd + dxy); if (df == dwindow || *df != *dd + dxy) { break; @@ -717,45 +718,17 @@ OASISWriter::write_bytes (const char *b, size_t n) } void -OASISWriter::write (long long n) +OASISWriter::write (int64_t n) { if (n < 0) { - write (((unsigned long long) (-n) << 1) | 1); + write (((uint64_t) (-n) << 1) | 1); } else { - write ((unsigned long long) n << 1); + write ((uint64_t) n << 1); } } void -OASISWriter::write (unsigned long long n) -{ - char buffer [50]; - char *bptr = buffer; - - do { - unsigned char b = n & 0x7f; - n >>= 7; - if (n > 0) { - b |= 0x80; - } - *bptr++ = (char) b; - } while (n > 0); - - write_bytes (buffer, bptr - buffer); -} - -void -OASISWriter::write (long n) -{ - if (n < 0) { - write (((unsigned long) (-n) << 1) | 1); - } else { - write ((unsigned long) n << 1); - } -} - -void -OASISWriter::write (unsigned long n) +OASISWriter::write (uint64_t n) { char buffer [50]; char *bptr = buffer; @@ -775,15 +748,15 @@ OASISWriter::write (unsigned long n) void OASISWriter::write (float d) { - if (fabs (d) >= 0.5 && fabs (floor (d + 0.5) - d) < 1e-6 && fabs (d) < double (std::numeric_limits::max ())) { + if (fabs (d) >= 0.5 && fabs (floor (d + 0.5) - d) < 1e-6 && fabs (d) < double (std::numeric_limits::max ())) { // whole number (negative or positive) if (d < 0.0) { write_byte (1); - write ((unsigned long) floor (-d + 0.5)); + write ((uint64_t) floor (-d + 0.5)); } else { write_byte (0); - write ((unsigned long) floor (d + 0.5)); + write ((uint64_t) floor (d + 0.5)); } } else { @@ -799,7 +772,7 @@ OASISWriter::write (float d) f2i.d = d; uint32_t i = f2i.i; char b[sizeof (f2i.i)]; - for (unsigned int n = 0; n < sizeof (f2i.i); n++) { + for (size_t n = 0; n < sizeof (f2i.i); n++) { b[n] = char (i & 0xff); i >>= 8; } @@ -811,15 +784,15 @@ OASISWriter::write (float d) void OASISWriter::write (double d) { - if (fabs (d) >= 0.5 && fabs (floor (d + 0.5) - d) < 1e-10 && fabs (d) < double (std::numeric_limits::max ())) { + if (fabs (d) >= 0.5 && fabs (floor (d + 0.5) - d) < 1e-10 && fabs (d) < double (std::numeric_limits::max ())) { // whole number (negative or positive) if (d < 0.0) { write_byte (1); - write ((unsigned long) floor (-d + 0.5)); + write ((uint64_t) floor (-d + 0.5)); } else { write_byte (0); - write ((unsigned long) floor (d + 0.5)); + write ((uint64_t) floor (d + 0.5)); } } else { @@ -848,7 +821,7 @@ void OASISWriter::write_bstring (const char *s) { size_t l = strlen (s); - write (l); + write ((uint64_t) l); write_bytes (s, l); } @@ -867,7 +840,7 @@ void OASISWriter::write_astring (const char *s) { std::string nstr = make_astring (s); - write (nstr.size ()); + write ((uint64_t) nstr.size ()); write_bytes (nstr.c_str (), nstr.size ()); } @@ -886,7 +859,7 @@ void OASISWriter::write_nstring (const char *s) { std::string nstr = make_nstring (s); - write (nstr.size ()); + write ((uint64_t) nstr.size ()); write_bytes (nstr.c_str (), nstr.size ()); } @@ -903,8 +876,8 @@ OASISWriter::write_gdelta (const db::Vector &p, double sf) if (x == -y || x == y || x == 0 || y == 0) { - unsigned long long dir = 0; - unsigned long long l = 0; + uint64_t dir = 0; + uint64_t l = 0; if (x > 0) { l = x; @@ -938,11 +911,11 @@ OASISWriter::write_gdelta (const db::Vector &p, double sf) } else { - unsigned long long d; + uint64_t d; if (x < 0) { - d = ((unsigned long long) -x << 2) | 3; + d = ((uint64_t) -x << 2) | 3; } else { - d = ((unsigned long long) x << 2) | 1; + d = ((uint64_t) x << 2) | 1; } write (d); write (y); @@ -1090,8 +1063,8 @@ OASISWriter::end_cblock () // RFC1951 compression: write_byte (0); - write (m_cblock_buffer.size ()); - write (m_cblock_compressed.size ()); + write ((uint64_t) m_cblock_buffer.size ()); + write ((uint64_t) m_cblock_compressed.size ()); write_bytes (m_cblock_compressed.data (), m_cblock_compressed.size ()); @@ -1158,7 +1131,7 @@ OASISWriter::write_propname_table (size_t &propnames_table_pos, const std::vecto { // write the property names collected so far in the order of the ID's. - std::vector > rev_pn; + std::vector > rev_pn; rev_pn.reserve (m_propnames.size ()); for (auto p = m_propnames.begin (); p != m_propnames.end (); ++p) { rev_pn.push_back (std::make_pair (p->second, p->first)); @@ -1166,7 +1139,7 @@ OASISWriter::write_propname_table (size_t &propnames_table_pos, const std::vecto std::sort (rev_pn.begin (), rev_pn.end ()); for (auto p = rev_pn.begin (); p != rev_pn.end (); ++p) { - tl_assert (p->first == (unsigned long)(p - rev_pn.begin ())); + tl_assert (p->first == (uint64_t)(p - rev_pn.begin ())); begin_table (propnames_table_pos); write_record_id (7); write_nstring (p->second.c_str ()); @@ -1236,7 +1209,7 @@ OASISWriter::write_propstring_table (size_t &propstrings_table_pos, const std::v { // write the property strings collected so far in the order of the ID's. - std::vector > rev_ps; + std::vector > rev_ps; rev_ps.reserve (m_propstrings.size ()); for (auto p = m_propstrings.begin (); p != m_propstrings.end (); ++p) { rev_ps.push_back (std::make_pair (p->second, &p->first)); @@ -1246,7 +1219,7 @@ OASISWriter::write_propstring_table (size_t &propstrings_table_pos, const std::v tl_assert (rev_ps.size () == size_t (m_propstring_id)); for (auto p = rev_ps.begin (); p != rev_ps.end (); ++p) { - tl_assert (p->first == (unsigned long)(p - rev_ps.begin ())); + tl_assert (p->first == (uint64_t)(p - rev_ps.begin ())); begin_table (propstrings_table_pos); write_record_id (9); write_bstring (p->second->c_str ()); @@ -1334,9 +1307,9 @@ OASISWriter::write_cellname_table (size_t &cellnames_table_pos, const std::vecto begin_table (cellnames_table_pos); write_record_id (sequential ? 3 : 4); - write_nstring (layout.cell_name (*cell)); + write_nstring (cell_nstring (*cell)); if (! sequential) { - write ((unsigned long) *cell); + write ((uint64_t) *cell); } if (m_options.write_std_properties >= 1) { @@ -1391,7 +1364,7 @@ OASISWriter::write_textstring_table (size_t &textstrings_table_pos, const std::v // write present text strings // collect present strings by ID - std::vector > rev_ts; + std::vector > rev_ts; rev_ts.reserve (m_textstrings.size ()); for (auto p = m_textstrings.begin (); p != m_textstrings.end (); ++p) { rev_ts.push_back (std::make_pair (p->second, &p->first)); @@ -1401,7 +1374,7 @@ OASISWriter::write_textstring_table (size_t &textstrings_table_pos, const std::v tl_assert (rev_ts.size () == size_t (m_textstring_id)); for (auto t = rev_ts.begin (); t != rev_ts.end (); ++t) { - tl_assert (t->first == (unsigned long)(t - rev_ts.begin ())); + tl_assert (t->first == (uint64_t)(t - rev_ts.begin ())); begin_table (textstrings_table_pos); write_record_id (5); write_nstring (t->second->c_str ()); @@ -1444,16 +1417,16 @@ OASISWriter::write_layername_table (size_t &layernames_table_pos, const std::vec write_record_id (11); write_nstring (l->second.name.c_str ()); write_byte (3); - write ((unsigned long) l->second.layer); + write ((uint64_t) l->second.layer); write_byte (3); - write ((unsigned long) l->second.datatype); + write ((uint64_t) l->second.datatype); write_record_id (12); write_nstring (l->second.name.c_str ()); write_byte (3); - write ((unsigned long) l->second.layer); + write ((uint64_t) l->second.layer); write_byte (3); - write ((unsigned long) l->second.datatype); + write ((uint64_t) l->second.datatype); m_progress.set (mp_stream->pos ()); @@ -1476,6 +1449,31 @@ static bool skip_cell_body (const db::Cell &cref) return cref.is_ghost_cell () && cref.empty (); } +void +OASISWriter::create_cell_nstrings (const db::Layout &layout, const std::set &cell_set) +{ + m_cell_nstrings.clear (); + + std::set names; + + for (auto c = cell_set.begin (); c != cell_set.end (); ++c) { + + std::string cn = make_nstring (layout.cell_name (*c)); + cn = tl::unique_name (cn, names); + + m_cell_nstrings.insert (std::make_pair (*c, cn)); + names.insert (cn); + + } +} + +const char * +OASISWriter::cell_nstring (db::cell_index_type cell_index) +{ + auto n = m_cell_nstrings.find (cell_index); + tl_assert (n != m_cell_nstrings.end ()); + return n->second.c_str (); +} void OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLayoutOptions &options) @@ -1510,6 +1508,8 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save std::set cell_set; options.get_cells (layout, cell_set, layers); + create_cell_nstrings (layout, cell_set); + // create a cell index vector sorted bottom-up std::vector cells, cells_by_index; @@ -1602,7 +1602,7 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save is_top = (cell_set.find (*p) == cell_set.end ()); } if (is_top) { - write_property_def (s_top_cell_name, tl::Variant (make_nstring (layout.cell_name (*cell))), true); + write_property_def (s_top_cell_name, tl::Variant (cell_nstring (*cell)), true); } } @@ -1679,7 +1679,7 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save cell_positions.insert (std::make_pair (*cell, mp_stream->pos ())); write_record_id (13); // CELL - write ((unsigned long) *cell); + write ((uint64_t) *cell); reset_modal_variables (); @@ -1696,8 +1696,8 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save write_record_id (28); write_byte (char (0xf6)); - unsigned long pnid = 0; - std::map ::const_iterator pni = m_propnames.find (klayout_context_name); + uint64_t pnid = 0; + std::map ::const_iterator pni = m_propnames.find (klayout_context_name); if (pni == m_propnames.end ()) { pnid = m_propname_id++; m_propnames.insert (std::make_pair (klayout_context_name, pnid)); @@ -1706,12 +1706,12 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save } write (pnid); - write ((unsigned long) context_prop_strings.size ()); + write ((uint64_t) context_prop_strings.size ()); for (std::vector ::const_iterator c = context_prop_strings.begin (); c != context_prop_strings.end (); ++c) { write_byte (14); // b-string by reference number - unsigned long psid = 0; - std::map ::const_iterator psi = m_propstrings.find (*c); + uint64_t psid = 0; + std::map ::const_iterator psi = m_propstrings.find (*c); if (psi == m_propstrings.end ()) { psid = m_propstring_id++; m_propstrings.insert (std::make_pair (*c, psid)).second; @@ -1795,23 +1795,23 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save // cellnames write_byte (1); - write (cellnames_table_pos); + write ((uint64_t) cellnames_table_pos); // textstrings write_byte (1); - write (textstrings_table_pos); + write ((uint64_t) textstrings_table_pos); // propnames write_byte (1); - write (propnames_table_pos); + write ((uint64_t) propnames_table_pos); // propstrings write_byte (1); - write (propstrings_table_pos); + write ((uint64_t) propstrings_table_pos); // layernames write_byte (1); - write (layernames_table_pos); + write ((uint64_t) layernames_table_pos); // xnames (not used) write_byte (1); @@ -1875,11 +1875,11 @@ OASISWriter::write (const Repetition &rep) if (g <= 1) { write_byte (10); - write (iterated->size () - 1); + write ((uint64_t) iterated->size () - 1); g = 1; } else { write_byte (11); - write (iterated->size () - 1); + write ((uint64_t) iterated->size () - 1); write_ucoord (g, 1.0); } @@ -1909,39 +1909,39 @@ OASISWriter::write (const Repetition &rep) if (b.x () == 0 && b.y () >= 0) { write_byte (3); - write (bmax - 2); + write ((uint64_t) bmax - 2); write_ucoord (b.y ()); } else if (b.y () == 0 && b.x () >= 0) { write_byte (2); - write (bmax - 2); + write ((uint64_t) bmax - 2); write_ucoord (b.x ()); } else { write_byte (9); - write (bmax - 2); + write ((uint64_t) bmax - 2); write_gdelta (b); } } else if (b.x () == 0 && b.y () >= 0 && a.y () == 0 && a.x () >= 0) { write_byte (1); - write (amax - 2); - write (bmax - 2); + write ((uint64_t) amax - 2); + write ((uint64_t) bmax - 2); write_ucoord (a.x ()); write_ucoord (b.y ()); } else if (b.y () == 0 && b.x () >= 0 && a.x () == 0 && a.y () >= 0) { write_byte (1); - write (bmax - 2); - write (amax - 2); + write ((uint64_t) bmax - 2); + write ((uint64_t) amax - 2); write_ucoord (b.x ()); write_ucoord (a.y ()); } else { write_byte (8); - write (amax - 2); - write (bmax - 2); + write ((uint64_t) amax - 2); + write ((uint64_t) bmax - 2); write_gdelta (a); write_gdelta (b); @@ -1985,7 +1985,7 @@ OASISWriter::write_inst_with_rep (const db::CellInstArray &inst, db::properties_ if (info & 0x80) { mm_placement_cell = inst.object ().cell_index (); - write ((unsigned long) mm_placement_cell.get ()); + write ((uint64_t) mm_placement_cell.get ()); } if (inst.is_complex ()) { @@ -2191,7 +2191,7 @@ OASISWriter::write_property_def (const char *name_str, const std::vector::const_iterator pni = m_propnames.find (name_str); + std::map ::const_iterator pni = m_propnames.find (name_str); // In strict mode always write property ID's: before we have issued the table we can // create new ID's. @@ -2219,11 +2219,11 @@ OASISWriter::write_property_def (const char *name_str, const std::vector= 15) { - write ((unsigned long) pvl.size ()); + write ((uint64_t) pvl.size ()); } // write property values - for (unsigned long i = 0; i < pvl.size (); ++i) { + for (uint64_t i = 0; i < pvl.size (); ++i) { const tl::Variant &v = pvl[i]; @@ -2234,27 +2234,27 @@ OASISWriter::write_property_def (const char *name_str, const std::vector::const_iterator pvi = m_propstrings.find (pvs); + std::map ::const_iterator pvi = m_propstrings.find (pvs); // In strict mode always write property string ID's: before we have issued the table we can // create new ID's. @@ -2335,7 +2335,7 @@ OASISWriter::write_pointlist (const std::vector &pointlist, bool for // manhattan pointlist write_byte (type); size_t implicit = for_polygons ? 1 : 0; - write ((unsigned long) (pointlist.size () - implicit)); + write ((uint64_t) (pointlist.size () - implicit)); db::Vector plast (0, 0); for (std::vector::const_iterator p = pointlist.begin (); p != pointlist.end () - implicit; ++p) { @@ -2353,7 +2353,7 @@ OASISWriter::write_pointlist (const std::vector &pointlist, bool for // generic pointlist write_byte (4); - write ((unsigned long) pointlist.size ()); + write ((uint64_t) pointlist.size ()); db::Vector plast (0, 0); if (m_sf == 1.0) { for (std::vector::const_iterator p = pointlist.begin (); p != pointlist.end (); ++p) { @@ -2378,8 +2378,8 @@ OASISWriter::write (const db::Text &text, db::properties_id_type prop_id, const db::Trans trans = text.trans (); - unsigned long text_id = 0; - std::map ::const_iterator ts = m_textstrings.find (text.string ()); + uint64_t text_id = 0; + std::map ::const_iterator ts = m_textstrings.find (text.string ()); if (ts == m_textstrings.end ()) { text_id = m_textstring_id++; m_textstrings.insert (std::make_pair (text.string (), text_id)); @@ -2412,15 +2412,15 @@ OASISWriter::write (const db::Text &text, db::properties_id_type prop_id, const write_byte (info); if (info & 0x40) { mm_text_string = text.string (); - write ((unsigned long) text_id); + write ((uint64_t) text_id); } if (info & 0x01) { mm_textlayer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_texttype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } if (info & 0x10) { mm_text_x = trans.disp ().x (); @@ -2496,11 +2496,11 @@ OASISWriter::write (const db::SimplePolygon &polygon, db::properties_id_type pro if (info & 0x01) { mm_layer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_datatype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } if (info & 0x20) { mm_polygon_point_list.swap (m_pointlist); @@ -2597,11 +2597,11 @@ OASISWriter::write (const db::Polygon &polygon, db::properties_id_type prop_id, if (info & 0x01) { mm_layer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_datatype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } if (info & 0x20) { mm_polygon_point_list.swap (m_pointlist); @@ -2667,11 +2667,11 @@ OASISWriter::write (const db::Box &box, db::properties_id_type prop_id, const db if (info & 0x01) { mm_layer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_datatype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } mm_geometry_w = box.width (); @@ -2772,11 +2772,11 @@ OASISWriter::write (const db::Path &path, db::properties_id_type prop_id, const if (info & 0x01) { mm_layer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_datatype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } if (info & 0x20) { mm_circle_radius = hw; @@ -2853,11 +2853,11 @@ OASISWriter::write (const db::Path &path, db::properties_id_type prop_id, const if (info & 0x01) { mm_layer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_datatype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } if (info & 0x40) { mm_path_halfwidth = hw; @@ -3046,11 +3046,11 @@ OASISWriter::write (const db::Edge &edge, db::properties_id_type prop_id, const if (info & 0x01) { mm_layer = m_layer; - write ((unsigned long) m_layer); + write ((uint64_t) m_layer); } if (info & 0x02) { mm_datatype = m_datatype; - write ((unsigned long) m_datatype); + write ((uint64_t) m_datatype); } if (info & 0x40) { mm_path_halfwidth = 0; diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h index 9c7fbf491..8570fee5d 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h @@ -208,14 +208,15 @@ private: tl::OutputMemoryStream m_cblock_buffer; tl::OutputMemoryStream m_cblock_compressed; bool m_in_cblock; - unsigned long m_propname_id; - unsigned long m_propstring_id; - unsigned long m_textstring_id; + uint64_t m_propname_id; + uint64_t m_propstring_id; + uint64_t m_textstring_id; bool m_proptables_written; - std::map m_textstrings; - std::map m_propnames; - std::map m_propstrings; + std::map m_textstrings; + std::map m_propnames; + std::map m_propstrings; + std::map m_cell_nstrings; typedef std::vector property_value_list; @@ -223,23 +224,23 @@ private: modal_variable mm_placement_cell; modal_variable mm_placement_x; modal_variable mm_placement_y; - modal_variable mm_layer; - modal_variable mm_datatype; - modal_variable mm_textlayer; - modal_variable mm_texttype; + modal_variable mm_layer; + modal_variable mm_datatype; + modal_variable mm_textlayer; + modal_variable mm_texttype; modal_variable mm_text_x; modal_variable mm_text_y; modal_variable mm_text_string; modal_variable mm_geometry_x; modal_variable mm_geometry_y; - modal_variable mm_geometry_w; - modal_variable mm_geometry_h; + modal_variable::distance_type> mm_geometry_w; + modal_variable::distance_type> mm_geometry_h; modal_variable< std::vector > mm_polygon_point_list; modal_variable mm_path_halfwidth; modal_variable mm_path_start_extension; modal_variable mm_path_end_extension; modal_variable< std::vector > mm_path_point_list; - modal_variable mm_ctrapezoid_type; + modal_variable mm_ctrapezoid_type; modal_variable mm_circle_radius; modal_variable mm_last_property_name; modal_variable mm_last_property_is_sprop; @@ -248,6 +249,9 @@ private: OASISWriterOptions m_options; tl::AbsoluteProgress m_progress; + void create_cell_nstrings (const db::Layout &layout, const std::set &cell_set); + const char *cell_nstring(db::cell_index_type cell_index); + void write_record_id (char b); void write_byte (char b); void write_bytes (const char *b, size_t n); @@ -273,19 +277,17 @@ private: void write (double d); void write (float d); - void write (long n); - void write (unsigned long n); - void write (long long n); - void write (unsigned long long n); + void write (int64_t n); + void write (uint64_t n); - void write (int n) + void write (int32_t n) { - write (long (n)); + write (int64_t (n)); } - void write (unsigned int n) + void write (uint32_t n) { - write ((unsigned long) (n)); + write ((uint64_t) (n)); } void write (const Repetition &rep); diff --git a/src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc b/src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc index 02d1f8a3c..59176b5a5 100644 --- a/src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc +++ b/src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc @@ -662,20 +662,37 @@ TEST(Bug_1799) EXPECT_EQ (ps2.value (pn).to_string (), "hello, world!"); } +// Modified in #2088 to give a warning TEST(DuplicateCellname) { db::Manager m (false); db::Layout layout (&m); - try { - tl::InputStream file (tl::testdata () + "/oasis/duplicate_cellname.oas"); + tl::InputStream file (tl::testdata () + "/oasis/duplicate_cellname.oas"); + db::OASISReader reader (file); + reader.read (layout); + + std::string fn_au (tl::testdata () + "/oasis/duplicate_cellname_au.oas"); + db::compare_layouts (_this, layout, fn_au, db::NoNormalization, 1); +} + +TEST(BlendCrash) +{ + db::Manager m (false); + db::Layout layout (&m); + + { + tl::InputStream file (tl::testdata () + "/oasis/blend_crash1.oas"); db::OASISReader reader (file); reader.read (layout); - EXPECT_EQ (false, true); - } catch (tl::CancelException &ex) { - // Seen when private test data is not installed - throw; - } catch (tl::Exception &ex) { - EXPECT_EQ (ex.msg ().find ("Same cell name TOP, but different IDs: 3 and 0 (position=1070, cell=)"), size_t (0)); } + + { + tl::InputStream file (tl::testdata () + "/oasis/blend_crash2.oas"); + db::OASISReader reader (file); + reader.read (layout); + } + + std::string fn_au (tl::testdata () + "/oasis/blend_crash_au.gds.gz"); + db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1); } diff --git a/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc b/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc index 3332e6e87..1621dddb0 100644 --- a/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc +++ b/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc @@ -2072,3 +2072,31 @@ TEST(130d) run_test130 (_this, true, true); } +// Issue #2088 (name duplication) +TEST(140) +{ + db::Layout layout_org; + + layout_org.add_cell ("X X"); + layout_org.add_cell ("X*X"); + + std::string tmp_file = tl::TestBase::tmp_file (tl::sprintf ("tmp_dbOASISWriter140.oas")); + + { + tl::OutputStream out (tmp_file); + db::SaveLayoutOptions options; + options.set_format ("OASIS"); + db::Writer writer (options); + writer.write (layout_org, out); + } + + { + tl::InputStream in (tmp_file); + db::Reader reader (in); + db::Layout gg; + reader.set_warnings_as_errors (true); + reader.read (gg); + + db::compare_layouts (_this, gg, tl::testdata () + "/oasis/dbOASISWriter40_au.gds", db::NoNormalization); + } +} diff --git a/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc b/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc index 0472b9a34..85c29c90f 100644 --- a/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc +++ b/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc @@ -1142,6 +1142,8 @@ public: db::GerberImporter importer (warn_level ()); data.setup_importer (&importer); + check_dbu (data.dbu); + importer.read (layout); std::string lyr_file = data.get_layer_properties_file (); diff --git a/testdata/algo/fill_tool6.gds b/testdata/algo/fill_tool6.gds new file mode 100644 index 000000000..708e35256 Binary files /dev/null and b/testdata/algo/fill_tool6.gds differ diff --git a/testdata/algo/fill_tool_au5.oas b/testdata/algo/fill_tool_au5.oas index f4040eedc..1a190bc74 100644 Binary files a/testdata/algo/fill_tool_au5.oas and b/testdata/algo/fill_tool_au5.oas differ diff --git a/testdata/algo/fill_tool_au6.oas b/testdata/algo/fill_tool_au6.oas new file mode 100644 index 000000000..8d679848d Binary files /dev/null and b/testdata/algo/fill_tool_au6.oas differ diff --git a/testdata/bd/strm2oas_1.oas b/testdata/bd/strm2oas_1.oas new file mode 100644 index 000000000..ea1ce8c00 Binary files /dev/null and b/testdata/bd/strm2oas_1.oas differ diff --git a/testdata/bd/strm2oas_2.oas b/testdata/bd/strm2oas_2.oas new file mode 100644 index 000000000..4d4efd59f Binary files /dev/null and b/testdata/bd/strm2oas_2.oas differ diff --git a/testdata/bd/strm2oas_2_10nm.oas b/testdata/bd/strm2oas_2_10nm.oas new file mode 100644 index 000000000..22f07fb36 Binary files /dev/null and b/testdata/bd/strm2oas_2_10nm.oas differ diff --git a/testdata/bd/strm2oas_a.oas b/testdata/bd/strm2oas_a.oas new file mode 100644 index 000000000..7d970af98 Binary files /dev/null and b/testdata/bd/strm2oas_a.oas differ diff --git a/testdata/bd/strm2oas_au_1.oas b/testdata/bd/strm2oas_au_1.oas new file mode 100644 index 000000000..9cd21228b Binary files /dev/null and b/testdata/bd/strm2oas_au_1.oas differ diff --git a/testdata/bd/strm2oas_au_12_1.oas b/testdata/bd/strm2oas_au_12_1.oas new file mode 100644 index 000000000..b75507708 Binary files /dev/null and b/testdata/bd/strm2oas_au_12_1.oas differ diff --git a/testdata/bd/strm2oas_au_12_2.oas b/testdata/bd/strm2oas_au_12_2.oas new file mode 100644 index 000000000..1eb221765 Binary files /dev/null and b/testdata/bd/strm2oas_au_12_2.oas differ diff --git a/testdata/bd/strm2oas_au_12_3.oas b/testdata/bd/strm2oas_au_12_3.oas new file mode 100644 index 000000000..3610b571e Binary files /dev/null and b/testdata/bd/strm2oas_au_12_3.oas differ diff --git a/testdata/bd/strm2oas_au_12_4.oas b/testdata/bd/strm2oas_au_12_4.oas new file mode 100644 index 000000000..0900f1f3f Binary files /dev/null and b/testdata/bd/strm2oas_au_12_4.oas differ diff --git a/testdata/bd/strm2oas_au_3.oas b/testdata/bd/strm2oas_au_3.oas new file mode 100644 index 000000000..7977695c1 Binary files /dev/null and b/testdata/bd/strm2oas_au_3.oas differ diff --git a/testdata/bd/strm2oas_b.oas b/testdata/bd/strm2oas_b.oas new file mode 100644 index 000000000..04da0a598 Binary files /dev/null and b/testdata/bd/strm2oas_b.oas differ diff --git a/testdata/bd/strm2oas_c.oas b/testdata/bd/strm2oas_c.oas new file mode 100644 index 000000000..737e49599 Binary files /dev/null and b/testdata/bd/strm2oas_c.oas differ diff --git a/testdata/bd/strm2oas_cc.oas b/testdata/bd/strm2oas_cc.oas new file mode 100644 index 000000000..ddf4638d7 Binary files /dev/null and b/testdata/bd/strm2oas_cc.oas differ diff --git a/testdata/drc/drcFullTest_1.drc b/testdata/drc/drcFullTest_1.drc new file mode 100644 index 000000000..8c77cc4f9 --- /dev/null +++ b/testdata/drc/drcFullTest_1.drc @@ -0,0 +1,58 @@ + +source($drc_test_source) +target($drc_test_target) + +verbose + +ncpu = 4 + +chip = input(189, 4) +chip.output(189, 4) + +# NOTE: this must not happen in tiled mode as the sealring +# is only visible as a whole in flat mode +sealring = source.cell("sealring") + +metal1_seal = sealring.input(8, 0) +metal1_seal_inner = metal1_seal.holes +# NOTE: metal1_seal_outer is empty if there is no sealring -> +# the full chip will be filled +metal1_seal_outer = chip.interacting(metal1_seal_inner) - metal1_seal_inner + +# Everything else can be done in tiled mode + +tiles(500) +tile_borders(2.0) +threads(ncpu) + +metal1 = input(8, 0) +metal1.output(8, 0) +metal1_fill = input(8, 22) +metal1_nofill = input(8, 23) + metal1_seal_outer + +metal1_dist = 0.42 +min_space_to_fill = 1.0 + +pattern = fill_pattern("METAL1_FILL1") +pattern.shape(8, 22, box(0.0, 0.0, 5.0, 5.0)) +pattern.dim(5.0, 5.0) +pattern.margin(metal1_dist, metal1_dist) + +to_fill = chip - metal1_nofill - metal1 + +to_fill = to_fill.fill_with_left(pattern, hstep(7.0, 0), vstep(1.5, 7.0), multi_origin) + +pattern = fill_pattern("METAL1_FILL2") +pattern.shape(8, 22, box(0.0, 0.0, 2.0, 2.0)) +pattern.dim(2.0, 2.0) +pattern.margin(metal1_dist, metal1_dist) + +to_fill = to_fill.fill_with_left(pattern, hstep(2.42, 0), vstep(0.65, 2.42), multi_origin) + +pattern = fill_pattern("METAL1_FILL3") +pattern.shape(8, 22, box(0.0, 0.0, 1.2, 1.2)) +pattern.dim(1.2, 1.2) +pattern.margin(metal1_dist, metal1_dist) + +to_fill = to_fill.fill_with_left(pattern, hstep(1.62, 0), vstep(0.3, 1.62), multi_origin) + diff --git a/testdata/drc/drcFullTest_1.oas b/testdata/drc/drcFullTest_1.oas new file mode 100644 index 000000000..57116b1d2 Binary files /dev/null and b/testdata/drc/drcFullTest_1.oas differ diff --git a/testdata/drc/drcFullTest_au1.oas b/testdata/drc/drcFullTest_au1.oas new file mode 100644 index 000000000..437274197 Binary files /dev/null and b/testdata/drc/drcFullTest_au1.oas differ diff --git a/testdata/drc/drcSimpleTests_40.drc b/testdata/drc/drcSimpleTests_40.drc index de7f810f1..2a20e4798 100644 --- a/testdata/drc/drcSimpleTests_40.drc +++ b/testdata/drc/drcSimpleTests_40.drc @@ -14,18 +14,22 @@ f2 = extent - l1.sized(1.0) p1 = fill_pattern("PAT1").shape(100, 0, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p2 = fill_pattern("PAT2").shape(100, 1, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p3 = fill_pattern("PAT3").shape(100, 2, box(0, 0, 1.um, 1.um)).shape(1000, 0, box(-0.5.um, -0.5.um, 1.5.um, 1.5.um)) +p4 = fill_pattern("PAT4").shape(100, 3, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um).margin(2.um, 4.um) p11 = fill_pattern("PAT11").shape(101, 0, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p12 = fill_pattern("PAT12").shape(101, 1, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p13 = fill_pattern("PAT13").shape(101, 2, box(0, 0, 1.um, 1.um)).shape(1000, 0, box(-0.5.um, -0.5.um, 1.5.um, 1.5.um)) +p14 = fill_pattern("PAT14").shape(101, 3, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um).margin(2.um, 4.um) f1.fill(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)) f1.fill(p2, hstep(2.0, 1.0), vstep(-1.0, 2.0), auto_origin) f1.fill(p3) +f1.fill(p4, hstep(2.0, 0), vstep(0, 2.0)) f2.fill(p11, hstep(2.0, 1.0), vstep(-1.0, 2.0)) f2.fill(p12, hstep(2.0, 1.0), vstep(-1.0, 2.0), auto_origin) f2.fill(p13) +f2.fill(p14, hstep(2.0, 0), vstep(0, 2.0)) l1.output(1, 0) f1.output(10, 0) diff --git a/testdata/drc/drcSimpleTests_42.drc b/testdata/drc/drcSimpleTests_42.drc index fa9bce1fb..2cc27c21e 100644 --- a/testdata/drc/drcSimpleTests_42.drc +++ b/testdata/drc/drcSimpleTests_42.drc @@ -11,8 +11,12 @@ l1 = input(1, 0) f1 = l1 p1 = fill_pattern("PAT1").shape(100, 0, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) +p2 = fill_pattern("PAT1").shape(100, 1, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um) +p3 = fill_pattern("PAT1").shape(100, 2, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um).margin(1.um, 2.um) -f1.fill_with_left(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(100, 0) +f1.fill_with_left(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(101, 0) +f1.fill_with_left(p2, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(101, 1) +f1.fill_with_left(p3, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(101, 2) l1.output(1, 0) f1.output(10, 0) diff --git a/testdata/drc/drcSimpleTests_au40.gds b/testdata/drc/drcSimpleTests_au40.gds index 04a9f564c..862f21aa3 100644 Binary files a/testdata/drc/drcSimpleTests_au40.gds and b/testdata/drc/drcSimpleTests_au40.gds differ diff --git a/testdata/drc/drcSimpleTests_au42.gds b/testdata/drc/drcSimpleTests_au42.gds index 01f2a2f5a..0325c8c07 100644 Binary files a/testdata/drc/drcSimpleTests_au42.gds and b/testdata/drc/drcSimpleTests_au42.gds differ diff --git a/testdata/lefdef/issue-2075/au.oas b/testdata/lefdef/issue-2075/au.oas new file mode 100644 index 000000000..08bcd3660 Binary files /dev/null and b/testdata/lefdef/issue-2075/au.oas differ diff --git a/testdata/lefdef/issue-2075/test.def b/testdata/lefdef/issue-2075/test.def new file mode 100644 index 000000000..c25e27049 --- /dev/null +++ b/testdata/lefdef/issue-2075/test.def @@ -0,0 +1,16 @@ +VERSION 5.8 ; + +DESIGN test ; + +UNITS DISTANCE MICRONS 2000 ; + +DIEAREA ( 0 0 ) ( 6000 3000 ) ; + +VIAS 1 ; +END VIAS + +NETS 1 ; + - dummy + ROUTED M2 ( 1670 830 ) ( * * 300 ) ( 4950 * 300 ) ( * 2000 300 ) ; +END NETS + +END DESIGN diff --git a/testdata/lefdef/issue-2075/test.lef b/testdata/lefdef/issue-2075/test.lef new file mode 100644 index 000000000..5892d8ee9 --- /dev/null +++ b/testdata/lefdef/issue-2075/test.lef @@ -0,0 +1,12 @@ +VERSION 5.8 ; + +UNITS + DATABASE MICRONS 2000 ; +END UNITS + +LAYER M2 + TYPE ROUTING ; + WIDTH 0.2 ; +END M2 + +END LIBRARY diff --git a/testdata/lefdef/issue-2075/test.map b/testdata/lefdef/issue-2075/test.map new file mode 100644 index 000000000..c3954ceee --- /dev/null +++ b/testdata/lefdef/issue-2075/test.map @@ -0,0 +1,2 @@ +DIEAREA ALL 108 0 +M2 NET 32 0 diff --git a/testdata/maly/maly_test10_dbu10nm_au.oas b/testdata/maly/maly_test10_dbu10nm_au.oas new file mode 100644 index 000000000..f8193382b Binary files /dev/null and b/testdata/maly/maly_test10_dbu10nm_au.oas differ diff --git a/testdata/oasis/blend_crash1.oas b/testdata/oasis/blend_crash1.oas new file mode 100644 index 000000000..1d86e551f Binary files /dev/null and b/testdata/oasis/blend_crash1.oas differ diff --git a/testdata/oasis/blend_crash2.oas b/testdata/oasis/blend_crash2.oas new file mode 100644 index 000000000..ccd436483 Binary files /dev/null and b/testdata/oasis/blend_crash2.oas differ diff --git a/testdata/oasis/blend_crash_au.gds.gz b/testdata/oasis/blend_crash_au.gds.gz new file mode 100644 index 000000000..5118f4399 Binary files /dev/null and b/testdata/oasis/blend_crash_au.gds.gz differ diff --git a/testdata/oasis/dbOASISWriter40_au.gds b/testdata/oasis/dbOASISWriter40_au.gds new file mode 100644 index 000000000..e7cceb60f Binary files /dev/null and b/testdata/oasis/dbOASISWriter40_au.gds differ diff --git a/testdata/oasis/duplicate_cellname_au.oas b/testdata/oasis/duplicate_cellname_au.oas new file mode 100644 index 000000000..e3a32581f Binary files /dev/null and b/testdata/oasis/duplicate_cellname_au.oas differ diff --git a/testdata/ruby/dbShapesTest.rb b/testdata/ruby/dbShapesTest.rb index b29e11726..6981eb1cd 100644 --- a/testdata/ruby/dbShapesTest.rb +++ b/testdata/ruby/dbShapesTest.rb @@ -1728,6 +1728,181 @@ class DBShapes_TestClass < TestBase end + def test_15 + + # Various container insert methods + + ly = RBA::Layout::new + l1 = ly.layer(1, 0) + top = ly.create_cell("TOP") + top.shapes(l1).insert(RBA::Box::new(2000)) + + shapes2 = RBA::Shapes::new + shapes2.insert(RBA::Box::new(4000)) + + shapes = RBA::Shapes::new + shapes.insert(shapes2) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-2000,-2000;2000,2000)") + + # self-insert + shapes.insert(shapes) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-2000,-2000;2000,2000);box (-2000,-2000;2000,2000)") + + shapes.clear + + shapes.insert(shapes2, RBA::Shapes::SBoxes) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-2000,-2000;2000,2000)") + + shapes.clear + + shapes.insert(shapes2, RBA::Shapes::SPolygons) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "") + + shapes.clear + + shapes.insert(shapes2, RBA::ICplxTrans::new(RBA::Vector::new(100, 200))) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-1900,-1800;2100,2200)") + + shapes.clear + + shapes.insert(shapes2, RBA::Shapes::SBoxes, RBA::ICplxTrans::new(RBA::Vector::new(100, 200))) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-1900,-1800;2100,2200)") + + shapes.clear + + shapes.insert(shapes2, RBA::Shapes::SPolygons, RBA::ICplxTrans::new(RBA::Vector::new(100, 200))) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "") + + shapes.clear + + shapes.insert(top.begin_shapes_rec(l1)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-1000,-1000;1000,1000)") + + shapes.clear + + shapes.insert(top.begin_shapes_rec(l1), RBA::ICplxTrans::new(100, 200)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "box (-900,-800;1100,1200)") + + top.shapes(l1).insert(top.begin_shapes_rec(l1)) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "box (-1000,-1000;1000,1000);box (-1000,-1000;1000,1000)") + + shapes.clear + + r = RBA::Region::new(RBA::Box::new(2000)) + shapes.insert(r) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "polygon (-1000,-1000;-1000,1000;1000,1000;1000,-1000)") + + shapes.clear + + r = RBA::Region::new(RBA::Box::new(2000)) + shapes.insert(r, RBA::ICplxTrans::new(100, 200)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "polygon (-900,-800;-900,1200;1100,1200;1100,-800)") + + top.shapes(l1).clear + top.shapes(l1).insert(r, RBA::DCplxTrans::new(0.1, 0.2)) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "polygon (-900,-800;-900,1200;1100,1200;1100,-800)") + + shapes.clear + + r = RBA::Edges::new(RBA::Edge::new(0, 0, 1000, 2000)) + shapes.insert(r) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "edge (0,0;1000,2000)") + + shapes.clear + + r = RBA::Edges::new(RBA::Edge::new(0, 0, 1000, 2000)) + shapes.insert(r, RBA::ICplxTrans::new(100, 200)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "edge (100,200;1100,2200)") + + top.shapes(l1).clear + top.shapes(l1).insert(r, RBA::DCplxTrans::new(0.1, 0.2)) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "edge (100,200;1100,2200)") + + shapes.clear + + r = RBA::EdgePairs::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 2000), RBA::Edge::new(100, 0, 100, 2000))) + shapes.insert_as_polygons(r, 10) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "simple_polygon (-10,-10;-10,2010;110,2010;110,-10)") + + shapes.clear + + r = RBA::EdgePairs::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 2000), RBA::Edge::new(100, 0, 100, 2000))) + shapes.insert_as_polygons(r, RBA::ICplxTrans::new(100, 200), 10) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "simple_polygon (90,190;90,2210;210,2210;210,190)") + + top.shapes(l1).clear + top.shapes(l1).insert_as_polygons(r, RBA::DCplxTrans::new(0.1, 0.2), 0.01) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "simple_polygon (90,190;90,2210;210,2210;210,190)") + + shapes.clear + + r = RBA::EdgePairs::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 2000), RBA::Edge::new(100, 0, 100, 2000))) + shapes.insert_as_edges(r) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "edge (0,0;0,2000);edge (100,0;100,2000)") + + shapes.clear + + r = RBA::EdgePairs::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 2000), RBA::Edge::new(100, 0, 100, 2000))) + shapes.insert_as_edges(r, RBA::ICplxTrans::new(100, 200)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "edge (100,200;100,2200);edge (200,200;200,2200)") + + top.shapes(l1).clear + top.shapes(l1).insert_as_edges(r, RBA::DCplxTrans::new(0.1, 0.2)) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "edge (100,200;100,2200);edge (200,200;200,2200)") + + shapes.clear + + r = RBA::EdgePairs::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 2000), RBA::Edge::new(100, 0, 100, 2000))) + shapes.insert(r) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "edge_pair (0,0;0,2000)/(100,0;100,2000)") + + shapes.clear + + r = RBA::EdgePairs::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 2000), RBA::Edge::new(100, 0, 100, 2000))) + shapes.insert(r, RBA::ICplxTrans::new(100, 200)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "edge_pair (100,200;100,2200)/(200,200;200,2200)") + + top.shapes(l1).clear + top.shapes(l1).insert(r, RBA::DCplxTrans::new(0.1, 0.2)) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "edge_pair (100,200;100,2200)/(200,200;200,2200)") + + shapes.clear + + r = RBA::Texts::new(RBA::Text::new("Text", RBA::Trans::new(100, 200))) + shapes.insert(r) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "text ('Text',r0 100,200)") + + shapes.clear + + r = RBA::Texts::new(RBA::Text::new("Text", RBA::Trans::new(100, 200))) + shapes.insert(r, RBA::ICplxTrans::new(100, 200)) + assert_equal(shapes.each.collect { |s| s.to_s }.join(";"), "text ('Text',r0 200,400)") + + top.shapes(l1).clear + top.shapes(l1).insert(r, RBA::DCplxTrans::new(0.1, 0.2)) + assert_equal(top.shapes(l1).each.collect { |s| s.to_s }.join(";"), "text ('Text',r0 200,400)") + + end + + def test_16 + + # issue #2094 + # speedy insert -> should not take more than a few seconds + + ly = RBA::Layout::new + l1 = ly.layer(1, 0) + main = ly.create_cell("MAIN") + + box = RBA::Region::new(RBA::Box::new(4000)) + + 100000.times do + main.shapes(l1).insert(box) + end + + assert_equal(main.shapes(l1).size, 100000) + + end + end load("test_epilogue.rb")