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