Compare commits
222 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
d0e38df6bf | |
|
|
d157eea7f3 | |
|
|
67c6ed9395 | |
|
|
f15f0dabbb | |
|
|
ae6d26578e | |
|
|
cb1653b157 | |
|
|
a3f5e665d1 | |
|
|
2eea849c06 | |
|
|
6e295d030e | |
|
|
ceba050a21 | |
|
|
f7cceed5e3 | |
|
|
5d35ae38b5 | |
|
|
05561b90f3 | |
|
|
06eab7feb6 | |
|
|
9ade4c931e | |
|
|
1bb5316d8d | |
|
|
2f26237b8b | |
|
|
003506ba62 | |
|
|
d659b5e1df | |
|
|
a0afe242c8 | |
|
|
88ca77f6a4 | |
|
|
9d967bdf64 | |
|
|
7fd2ef8100 | |
|
|
e789f18523 | |
|
|
460a357730 | |
|
|
7ceeccef56 | |
|
|
66faf1d907 | |
|
|
37db9e453b | |
|
|
2d5c4be6dd | |
|
|
a9673e45ae | |
|
|
8f95efc257 | |
|
|
fd12c39c37 | |
|
|
7d9167257a | |
|
|
058b320c3f | |
|
|
fee4b887c0 | |
|
|
04e91d640d | |
|
|
7d9210a3f1 | |
|
|
03bbc544b2 | |
|
|
ee79bba5e4 | |
|
|
15943d0cb1 | |
|
|
7bdd9e1d4f | |
|
|
725c8e9235 | |
|
|
73ffad3802 | |
|
|
037daf1121 | |
|
|
d0ef32de0f | |
|
|
0d9b862c0e | |
|
|
71dc472797 | |
|
|
2929ef583e | |
|
|
ecd6ec56ae | |
|
|
f3478cba7b | |
|
|
ba5154698d | |
|
|
1023461ca5 | |
|
|
197763e46e | |
|
|
cb7855235a | |
|
|
8f684ad5be | |
|
|
f3404f67b7 | |
|
|
cedd64adcb | |
|
|
afca58f162 | |
|
|
95baea1c22 | |
|
|
751757a02c | |
|
|
c32bae1a24 | |
|
|
0c913eca59 | |
|
|
2f00f6d8f1 | |
|
|
9ab7b77dc4 | |
|
|
00c0208f18 | |
|
|
cb30ac369b | |
|
|
7e9b6fb61e | |
|
|
3b1de8ff40 | |
|
|
10a6c8635f | |
|
|
e2292f5d70 | |
|
|
736c507fe8 | |
|
|
c20a267a2b | |
|
|
bad0b67ce8 | |
|
|
727649b308 | |
|
|
4dde62b206 | |
|
|
94edc2a23d | |
|
|
b248f186ec | |
|
|
1656866f41 | |
|
|
99297e33ec | |
|
|
727833fcd3 | |
|
|
feb5d61294 | |
|
|
4b120eb417 | |
|
|
55eadcfb90 | |
|
|
b4f62abb40 | |
|
|
deefe0e3a3 | |
|
|
57c33c48c7 | |
|
|
76f97c90e5 | |
|
|
297a05c4ed | |
|
|
b768fcc3f9 | |
|
|
4943da5ce4 | |
|
|
512400e39f | |
|
|
0cbed6078a | |
|
|
9760ef6d1d | |
|
|
bd13febb72 | |
|
|
81436b75ed | |
|
|
8822f8dce2 | |
|
|
f03003b79f | |
|
|
802c31d16a | |
|
|
308224109f | |
|
|
4d9c7fd7d7 | |
|
|
a55ec49434 | |
|
|
c0dbb2067b | |
|
|
b59708e27a | |
|
|
c0c5e1b5bf | |
|
|
3de9ed9cbf | |
|
|
846c8e0f65 | |
|
|
8bd01f5597 | |
|
|
1cb58e973a | |
|
|
516c9d7635 | |
|
|
d24d52e403 | |
|
|
a93d248a5a | |
|
|
4ccd5a78d1 | |
|
|
f998f8ee6f | |
|
|
662e21a2d1 | |
|
|
949ec7672c | |
|
|
bd417aa54b | |
|
|
73e08e0c88 | |
|
|
893a36cae7 | |
|
|
3b4d66e7d7 | |
|
|
5e8a3f038a | |
|
|
9850c5586e | |
|
|
27df5f9c5f | |
|
|
e9202c1d29 | |
|
|
ea1a89b19c | |
|
|
9489b23985 | |
|
|
c74215ad55 | |
|
|
4201f56048 | |
|
|
26372f5d50 | |
|
|
ef419258ab | |
|
|
97134848ab | |
|
|
00c692b140 | |
|
|
203ece1a16 | |
|
|
22a230edc9 | |
|
|
7f1217596e | |
|
|
ff718c3ecf | |
|
|
98aa2f760a | |
|
|
441d933148 | |
|
|
9d3fb61cf3 | |
|
|
a1fb779314 | |
|
|
abd3975997 | |
|
|
227f264838 | |
|
|
c87e5baff4 | |
|
|
957d7edd64 | |
|
|
969137d1e2 | |
|
|
f3adea8c65 | |
|
|
246c0ea7a4 | |
|
|
47778971ee | |
|
|
cccd79ab0d | |
|
|
51b9846120 | |
|
|
1afd48e840 | |
|
|
99a5a28a3e | |
|
|
0ac4d3a465 | |
|
|
42aa06f8f5 | |
|
|
4d2912a406 | |
|
|
b668b02a1f | |
|
|
6b8f5d1d67 | |
|
|
c977e4cf76 | |
|
|
9327e319da | |
|
|
0e84616af8 | |
|
|
c42db8e71b | |
|
|
27c423c2ed | |
|
|
53e7dfe04c | |
|
|
9ca81f8ea6 | |
|
|
d822353e85 | |
|
|
4951f013d5 | |
|
|
d3a0228958 | |
|
|
656d27b17a | |
|
|
3631892cfa | |
|
|
8c323803b7 | |
|
|
acdfb256a1 | |
|
|
5e74ecf9fa | |
|
|
d6d8620a7c | |
|
|
a2390167e6 | |
|
|
3cfc24f4b9 | |
|
|
7e12bec49d | |
|
|
5f1f92f30d | |
|
|
15faa19346 | |
|
|
af7b6bf119 | |
|
|
8b0616eaf5 | |
|
|
2b62123459 | |
|
|
2259ef626d | |
|
|
3c9987f460 | |
|
|
f4212d8e0e | |
|
|
a16c667290 | |
|
|
6e2babd141 | |
|
|
b80279c6db | |
|
|
722209b1ae | |
|
|
692c0f2339 | |
|
|
dbdec3aa17 | |
|
|
f7d2debb98 | |
|
|
0f047b89ce | |
|
|
3b57ae1179 | |
|
|
dc45242d46 | |
|
|
6d8c3eee1a | |
|
|
c8fe30398b | |
|
|
5093182f4a | |
|
|
4864a80179 | |
|
|
70054ccde2 | |
|
|
c007d8077c | |
|
|
da216195b3 | |
|
|
5fe586100b | |
|
|
c7ef7d743a | |
|
|
df7b9079bd | |
|
|
cfd1d567bd | |
|
|
b1424bfaf3 | |
|
|
aef23fd5f3 | |
|
|
1dfe1ed645 | |
|
|
9c5cf1a567 | |
|
|
55931e8811 | |
|
|
bb131f14d0 | |
|
|
78f7d22796 | |
|
|
b1c7b52ed2 | |
|
|
5de118b762 | |
|
|
00e3bbd12a | |
|
|
0022c502c8 | |
|
|
741216d6f3 | |
|
|
6195c20d3d | |
|
|
59a1953f3c | |
|
|
b1095b323c | |
|
|
e9f2628f41 | |
|
|
e04307c085 | |
|
|
d2acdac901 |
|
|
@ -14,35 +14,33 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04, ubuntu-22.04]
|
os: [ubuntu-24.04, ubuntu-22.04]
|
||||||
# Configure Options
|
# Configure Options
|
||||||
pkgs: [all, none, no_tk_tcl_rl, no_rl, no_zlib, no_gc_gl_gu, no_gc_gu]
|
# X11 OGL CAIRO
|
||||||
|
pkgs: [all, none, no_tk_tcl_rl, no_tk_tcl_brl, no_zlib, no_gc_gl_gu, no_gc, no_gl_gu]
|
||||||
# Toolchain
|
# Toolchain
|
||||||
# ubuntu-20.04 [gcc-9] gcc-10
|
# ubuntu-20.04 [gcc-9, clang-10]
|
||||||
# ubuntu-22.04 [gcc-11] gcc-12
|
# ubuntu-22.04 [gcc-11, clang-14]
|
||||||
# ubuntu-24.04 [gcc-13] gcc-14
|
# ubuntu-24.04 [gcc-13, clang-18]
|
||||||
tc: [default, gcc-10, gcc-12, gcc-14, clang-17, clang-18]
|
tc: [default, gcc-10, gcc-11, gcc-12, gcc-13, gcc-14, clang-14, clang-15, clang-17, clang-18, clang-19]
|
||||||
exclude:
|
exclude:
|
||||||
- os: ubuntu-20.04
|
|
||||||
tc: gcc-12
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
tc: gcc-14
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
tc: clang-17
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
tc: clang-18
|
|
||||||
|
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
tc: gcc-10
|
tc: gcc-13
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
tc: gcc-14
|
tc: gcc-14
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
tc: clang-17
|
tc: clang-17
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04 # some sources show this as present but not found
|
||||||
tc: clang-18
|
tc: clang-18
|
||||||
|
- os: ubuntu-22.04
|
||||||
|
tc: clang-19
|
||||||
|
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
tc: gcc-10
|
tc: gcc-10
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
tc: gcc-12
|
tc: gcc-11
|
||||||
|
- os: ubuntu-24.04
|
||||||
|
tc: clang-14
|
||||||
|
- os: ubuntu-24.04
|
||||||
|
tc: clang-15
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -69,16 +67,19 @@ jobs:
|
||||||
# z no.*_zl zlib1g-dev
|
# z no.*_zl zlib1g-dev
|
||||||
# n no.*_nc libncurses-dev
|
# n no.*_nc libncurses-dev
|
||||||
# r no.*_rl libreadline-dev
|
# r no.*_rl libreadline-dev
|
||||||
|
# R no.*_brl --enable-readline-bundled
|
||||||
# c no.*_tcl tcl-dev
|
# c no.*_tcl tcl-dev
|
||||||
# k no.*_tk tk-dev
|
# k no.*_tk tk-dev
|
||||||
# C no.*_gc libcairo-dev
|
# C no.*_gc libcairo-dev
|
||||||
# L no.*_gl libgl-dev
|
# L no.*_gl libgl-dev
|
||||||
# U no.*_gu libglu1-mesa-dev
|
# U no.*_gu libglu1-mesa-dev # GLU requires GL
|
||||||
# X no.*_gx libx11-dev
|
# X no.*_gx libx11-dev
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_zl"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_zl"; then
|
||||||
pkgs=$(echo -n "$pkgs" | sed -e 's#z##'); fi
|
pkgs=$(echo -n "$pkgs" | sed -e 's#z##'); fi
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_nc"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_nc"; then
|
||||||
pkgs=$(echo -n "$pkgs" | sed -e 's#n##'); fi
|
pkgs=$(echo -n "$pkgs" | sed -e 's#n##'); fi
|
||||||
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_brl"; then
|
||||||
|
pkgs=$(echo -n "$pkgs" | sed -e 's#r#R#'); fi # replace
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_rl"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_rl"; then
|
||||||
pkgs=$(echo -n "$pkgs" | sed -e 's#r##'); fi
|
pkgs=$(echo -n "$pkgs" | sed -e 's#r##'); fi
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tcl"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tcl"; then
|
||||||
|
|
@ -111,6 +112,8 @@ jobs:
|
||||||
_configure_args=()
|
_configure_args=()
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_zl"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_zl"; then
|
||||||
_configure_args+=(--disable-compression); fi
|
_configure_args+=(--disable-compression); fi
|
||||||
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_brl"; then
|
||||||
|
_configure_args+=(--enable-readline-bundled); fi
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_rl"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_rl"; then
|
||||||
_configure_args+=(--disable-readline); fi
|
_configure_args+=(--disable-readline); fi
|
||||||
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tcl"; then
|
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tcl"; then
|
||||||
|
|
@ -135,6 +138,8 @@ jobs:
|
||||||
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
|
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
|
||||||
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
|
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
if [ -n "$BUILD_GCC_VERSION" ]
|
if [ -n "$BUILD_GCC_VERSION" ]
|
||||||
then
|
then
|
||||||
GCCV=$BUILD_GCC_VERSION
|
GCCV=$BUILD_GCC_VERSION
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# This is a basic workflow to help you get started with Actions
|
||||||
|
|
||||||
|
name: CI-aarch64
|
||||||
|
|
||||||
|
# Controls when the workflow will run
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
|
jobs:
|
||||||
|
simple_build_linux_arm:
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Get Dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y tcl-dev tk-dev libcairo-dev
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
./configure
|
||||||
|
make database/database.h
|
||||||
|
make -j$(nproc)
|
||||||
|
simple_build_wasm_arm:
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Get Dependencies
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/emscripten-core/emsdk.git
|
||||||
|
cd emsdk
|
||||||
|
./emsdk install latest
|
||||||
|
./emsdk activate latest
|
||||||
|
- name: Emscripten Diagnostic
|
||||||
|
run: |
|
||||||
|
source ./emsdk/emsdk_env.sh
|
||||||
|
echo "===== gcc -dM -E - ====="
|
||||||
|
echo | gcc -dM -E - | sort
|
||||||
|
echo "===== g++ -dM -E - ====="
|
||||||
|
echo | g++ -dM -E - | sort
|
||||||
|
echo "===== emcc -dM -E - ====="
|
||||||
|
echo | emcc -dM -E - | sort
|
||||||
|
echo "===== em++ -dM -E - ====="
|
||||||
|
echo | em++ -dM -E - | sort
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
source ./emsdk/emsdk_env.sh
|
||||||
|
# The --without and --disable in these build options is due to no WASM library being available for that feature
|
||||||
|
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 -g" emconfigure ./configure --without-cairo --without-opengl --without-x --without-tk --without-tcl --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||||
|
echo "===== defs.mak ====="
|
||||||
|
cat defs.mak
|
||||||
|
echo "===== defs.mak ====="
|
||||||
|
emmake make
|
||||||
|
- name: archive wasm bundle
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: magic-wasm-bundle-arm
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}/magic/magic.wasm
|
||||||
|
|
@ -10,8 +10,8 @@ on:
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
jobs:
|
jobs:
|
||||||
simple_build_macos13:
|
simple_build_macos15:
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel # only and last supported intel MacOS
|
||||||
timeout-minutes: 45 # x86_64 seems non-SSD based (slower)
|
timeout-minutes: 45 # x86_64 seems non-SSD based (slower)
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
@ -235,10 +235,10 @@ jobs:
|
||||||
cp *.mak dist/BUILD-INFO/
|
cp *.mak dist/BUILD-INFO/
|
||||||
cp *.LOG dist/BUILD-INFO/
|
cp *.LOG dist/BUILD-INFO/
|
||||||
|
|
||||||
- name: Upload archive magic-macos13
|
- name: Upload archive magic-macos15
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: magic-macos13
|
name: magic-macos15
|
||||||
path: |
|
path: |
|
||||||
${{ github.workspace }}/dist
|
${{ github.workspace }}/dist
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,6 @@ on:
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
jobs:
|
jobs:
|
||||||
vezzal:
|
|
||||||
# The type of runner that the job will run on
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
|
||||||
steps:
|
|
||||||
- name: Pulling the docker image
|
|
||||||
run: docker pull vezzal/vezzal:v1
|
|
||||||
|
|
||||||
- name: Start the container with the docker image
|
|
||||||
run: docker run -id --name test_magic vezzal/vezzal:v1 bash | exit
|
|
||||||
|
|
||||||
- name: Run the testing on the container and send the mail
|
|
||||||
run: docker exec test_magic /vezzal/test_magic.sh "lankasaicharan123@gmail.com,tim@opencircuitdesign.com" ${{secrets.MAILING_KEY}}
|
|
||||||
simple_build_linux:
|
simple_build_linux:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -45,10 +32,22 @@ jobs:
|
||||||
cd emsdk
|
cd emsdk
|
||||||
./emsdk install latest
|
./emsdk install latest
|
||||||
./emsdk activate latest
|
./emsdk activate latest
|
||||||
|
- name: Emscripten Diagnostic
|
||||||
|
run: |
|
||||||
|
source ./emsdk/emsdk_env.sh
|
||||||
|
echo "===== gcc -dM -E - ====="
|
||||||
|
echo | gcc -dM -E - | sort
|
||||||
|
echo "===== g++ -dM -E - ====="
|
||||||
|
echo | g++ -dM -E - | sort
|
||||||
|
echo "===== emcc -dM -E - ====="
|
||||||
|
echo | emcc -dM -E - | sort
|
||||||
|
echo "===== em++ -dM -E - ====="
|
||||||
|
echo | em++ -dM -E - | sort
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
source ./emsdk/emsdk_env.sh
|
source ./emsdk/emsdk_env.sh
|
||||||
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
# The --without and --disable in these build options is due to no WASM library being available for that feature
|
||||||
|
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 -g" emconfigure ./configure --without-cairo --without-opengl --without-x --without-tk --without-tcl --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||||
echo "===== defs.mak ====="
|
echo "===== defs.mak ====="
|
||||||
cat defs.mak
|
cat defs.mak
|
||||||
echo "===== defs.mak ====="
|
echo "===== defs.mak ====="
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -58,13 +58,15 @@ LIBS_SUBDIR := $(shell for i in ${MODULES}; do echo "$${i}/lib$${i}.a"; done)
|
||||||
${MODULES_SUBDIR}: FORCE
|
${MODULES_SUBDIR}: FORCE
|
||||||
@${MAKE} -C $(dir $@) module
|
@${MAKE} -C $(dir $@) module
|
||||||
|
|
||||||
|
.PHONY: modules
|
||||||
modules: database/database.h depend ${MODULES_SUBDIR}
|
modules: database/database.h depend ${MODULES_SUBDIR}
|
||||||
|
|
||||||
${LIBS_SUBDIR}: FORCE
|
${LIBS_SUBDIR}: FORCE
|
||||||
@${MAKE} -C $(dir $@) lib
|
@${MAKE} -C $(dir $@) lib
|
||||||
|
|
||||||
# Force the tiles/utils modules to exist first for libdatabase.a
|
# Force the tiles/utils modules to exist first for libdatabase.a
|
||||||
libs: database/database.h tiles/libtiles.o utils/libutils.o depend ${LIBS_SUBDIR}
|
.PHONY: libs
|
||||||
|
libs: database/database.h depend tiles/libtiles.o utils/libutils.o ${LIBS_SUBDIR}
|
||||||
|
|
||||||
#
|
#
|
||||||
# extcheck - utility tool
|
# extcheck - utility tool
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
export CURDIR=$(dirname $(readlink -f "${0}"))
|
export CURDIR=$(dirname $(readlink -f "${0}"))
|
||||||
|
|
||||||
export PATH="${CURDIR}/bin":$PATH
|
export PATH="${CURDIR}/bin":$PATH
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ static BinArray *bpBinArrayNew(int dx, /* x diameter of bins */
|
||||||
|
|
||||||
/* allocate array */
|
/* allocate array */
|
||||||
size = sizeof(BinArray) + numBins*(sizeof(void *));
|
size = sizeof(BinArray) + numBins*(sizeof(void *));
|
||||||
new = (BinArray *)callocMagic(size);
|
new = (BinArray *)callocMagic(1, size);
|
||||||
|
|
||||||
/* initial */
|
/* initial */
|
||||||
new->ba_bbox = *bbox;
|
new->ba_bbox = *bbox;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ int calmaNonManhattan;
|
||||||
int CalmaFlattenLimit = 10;
|
int CalmaFlattenLimit = 10;
|
||||||
int NameConvertErrors = 0;
|
int NameConvertErrors = 0;
|
||||||
bool CalmaRewound = FALSE;
|
bool CalmaRewound = FALSE;
|
||||||
|
bool CalmaRecordPaths = FALSE;
|
||||||
TileTypeBitMask *CalmaMaskHints = NULL;
|
TileTypeBitMask *CalmaMaskHints = NULL;
|
||||||
|
|
||||||
extern HashTable calmaDefInitHash;
|
extern HashTable calmaDefInitHash;
|
||||||
|
|
@ -245,7 +246,9 @@ calmaExact(void)
|
||||||
int pNum;
|
int pNum;
|
||||||
Plane *newplane;
|
Plane *newplane;
|
||||||
Plane **parray;
|
Plane **parray;
|
||||||
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
|
|
||||||
|
/* Forward reference */
|
||||||
|
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
|
||||||
|
|
||||||
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
|
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
|
||||||
|
|
||||||
|
|
@ -387,6 +390,15 @@ calmaParseStructure(
|
||||||
he = HashFind(&calmaDefInitHash, strname);
|
he = HashFind(&calmaDefInitHash, strname);
|
||||||
if ((def = (CellDef *)HashGetValue(he)) != NULL)
|
if ((def = (CellDef *)HashGetValue(he)) != NULL)
|
||||||
{
|
{
|
||||||
|
if (def->cd_flags & CDPRELOADED)
|
||||||
|
{
|
||||||
|
/* Cell definition was read ahead due to option "flatten" */
|
||||||
|
/* or "flatglob". Do not complain about seeing it again. */
|
||||||
|
def->cd_flags &= ~CDPRELOADED;
|
||||||
|
calmaNextCell();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (def->cd_flags & CDPROCESSEDGDS)
|
if (def->cd_flags & CDPROCESSEDGDS)
|
||||||
{
|
{
|
||||||
/* If cell definition was marked as processed, then skip */
|
/* If cell definition was marked as processed, then skip */
|
||||||
|
|
@ -396,6 +408,7 @@ calmaParseStructure(
|
||||||
|
|
||||||
if (!CalmaPostOrder && !CalmaRewound)
|
if (!CalmaPostOrder && !CalmaRewound)
|
||||||
{
|
{
|
||||||
|
cifReadCellDef = def;
|
||||||
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
|
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
|
||||||
strname);
|
strname);
|
||||||
CalmaReadError("Ignoring duplicate definition\n");
|
CalmaReadError("Ignoring duplicate definition\n");
|
||||||
|
|
@ -407,6 +420,7 @@ calmaParseStructure(
|
||||||
{
|
{
|
||||||
char *newname;
|
char *newname;
|
||||||
|
|
||||||
|
cifReadCellDef = def;
|
||||||
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
|
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
|
||||||
strname);
|
strname);
|
||||||
newname = (char *)mallocMagic(strlen(strname) + 20);
|
newname = (char *)mallocMagic(strlen(strname) + 20);
|
||||||
|
|
@ -492,28 +506,33 @@ calmaParseStructure(
|
||||||
|
|
||||||
if (CalmaReadOnly || predefined)
|
if (CalmaReadOnly || predefined)
|
||||||
{
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
char cstring[1024];
|
char cstring[1024];
|
||||||
|
|
||||||
/* Writing the file position into a string is slow, but */
|
|
||||||
/* it prevents requiring special handling when printing */
|
|
||||||
/* out the properties. */
|
|
||||||
|
|
||||||
char *fpcopy = (char *)mallocMagic(20);
|
|
||||||
char *fncopy;
|
|
||||||
|
|
||||||
/* Substitute variable for PDK path or ~ for home directory */
|
/* Substitute variable for PDK path or ~ for home directory */
|
||||||
/* the same way that cell references are handled in .mag files. */
|
/* the same way that cell references are handled in .mag files. */
|
||||||
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
||||||
fncopy = StrDup(NULL, cstring);
|
|
||||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
|
|
||||||
|
|
||||||
fpcopy = (char *)mallocMagic(20);
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||||
|
proprec->prop_len = 1;
|
||||||
|
proprec->prop_value.prop_double[0] = filepos;
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)proprec);
|
||||||
|
|
||||||
filepos = FTELL(calmaInputFile);
|
filepos = FTELL(calmaInputFile);
|
||||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy);
|
|
||||||
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy);
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||||
|
proprec->prop_len = 1;
|
||||||
|
proprec->prop_value.prop_double[0] = filepos;
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)proprec);
|
||||||
|
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) - 7 +
|
||||||
|
strlen(cstring));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||||
|
proprec->prop_len = 1;
|
||||||
|
strcpy(proprec->prop_value.prop_string, cstring);
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)proprec);
|
||||||
|
|
||||||
if (predefined)
|
if (predefined)
|
||||||
{
|
{
|
||||||
|
|
@ -740,6 +759,7 @@ calmaParseElement(
|
||||||
int
|
int
|
||||||
calmaEnumFunc(
|
calmaEnumFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
int *plane)
|
int *plane)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -769,20 +789,22 @@ calmaElementSref(
|
||||||
char *filename)
|
char *filename)
|
||||||
{
|
{
|
||||||
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
||||||
int xlo, ylo, xhi, yhi, xsep, ysep;
|
int xlo, ylo, xhi, yhi, xsep, ysep, angle;
|
||||||
bool madeinst = FALSE;
|
bool madeinst = FALSE, rotated = FALSE;
|
||||||
char *sname = NULL;
|
char *sname = NULL;
|
||||||
bool isArray = FALSE;
|
bool isArray = FALSE;
|
||||||
|
bool dolookahead = FALSE;
|
||||||
Transform trans, tinv;
|
Transform trans, tinv;
|
||||||
Point refarray[3], refunscaled[3], p;
|
Point refarray[3], refunscaled[3], p;
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
|
|
||||||
int gdsHasUses(CellUse *use, ClientData clientdata); /* Forward reference */
|
|
||||||
/* Added by NP */
|
|
||||||
char *useid = NULL, *arraystr = NULL;
|
char *useid = NULL, *arraystr = NULL;
|
||||||
int propAttrType;
|
int propAttrType;
|
||||||
|
|
||||||
|
/* Forward reference */
|
||||||
|
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
|
||||||
|
int gdsHasUses(CellUse *use, ClientData clientdata);
|
||||||
|
|
||||||
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
|
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
|
||||||
calmaSkipSet(calmaElementIgnore);
|
calmaSkipSet(calmaElementIgnore);
|
||||||
|
|
||||||
|
|
@ -798,7 +820,38 @@ calmaElementSref(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
def = calmaLookCell(sname);
|
def = calmaLookCell(sname);
|
||||||
if (!def && (CalmaPostOrder || CalmaFlattenUses || (CalmaFlattenUsesByName != NULL)))
|
|
||||||
|
/*
|
||||||
|
* If the "flatten" option is set, then we always have to seek
|
||||||
|
* ahead and read the structure in order to determine if it
|
||||||
|
* meets the requirement of being flattened or not. If the
|
||||||
|
* "flatglob" option is set, then we need to read ahead and
|
||||||
|
* read the cell definition so that it can be flatten. This
|
||||||
|
* requires pattern-matching the cell def.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dolookahead = (CalmaPostOrder || CalmaFlattenUses) ? TRUE : FALSE;
|
||||||
|
if ((!dolookahead) && (CalmaFlattenUsesByName != NULL))
|
||||||
|
{
|
||||||
|
char *pattern;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
pattern = CalmaFlattenUsesByName[i];
|
||||||
|
if (pattern == NULL) break;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/* Check pattern against strname */
|
||||||
|
if (Match(pattern, sname))
|
||||||
|
{
|
||||||
|
dolookahead = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!def && dolookahead)
|
||||||
{
|
{
|
||||||
/* Force the GDS parser to read the cell definition in
|
/* Force the GDS parser to read the cell definition in
|
||||||
* post-order. If cellname "sname" is not defined before
|
* post-order. If cellname "sname" is not defined before
|
||||||
|
|
@ -832,6 +885,7 @@ calmaElementSref(
|
||||||
FSEEK(calmaInputFile, originalFilePos, SEEK_SET);
|
FSEEK(calmaInputFile, originalFilePos, SEEK_SET);
|
||||||
cifReadCellDef = calmaLookCell(currentSname);
|
cifReadCellDef = calmaLookCell(currentSname);
|
||||||
def = calmaLookCell(sname);
|
def = calmaLookCell(sname);
|
||||||
|
def->cd_flags |= CDPRELOADED;
|
||||||
cifCurReadPlanes = savePlanes;
|
cifCurReadPlanes = savePlanes;
|
||||||
calmaLayerHash = OrigCalmaLayerHash;
|
calmaLayerHash = OrigCalmaLayerHash;
|
||||||
if (crsMultiplier != cifCurReadStyle->crs_multiplier)
|
if (crsMultiplier != cifCurReadStyle->crs_multiplier)
|
||||||
|
|
@ -936,17 +990,73 @@ calmaElementSref(
|
||||||
refarray[2].p_x = refarray[2].p_y = 0;
|
refarray[2].p_x = refarray[2].p_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the array is given an angle, then the meaning of rows and
|
||||||
|
* columns needs to be swapped for the purpose of ignoring
|
||||||
|
* X or Y values in the case of a 1-row or 1-column entry.
|
||||||
|
*/
|
||||||
|
angle = GeoTransAngle(&trans, 0);
|
||||||
|
if ((angle == 90) || (angle == 270) || (angle == -90) || (angle == -270))
|
||||||
|
rotated = TRUE;
|
||||||
|
|
||||||
/* If this is a cell reference, then we scale to magic coordinates
|
/* If this is a cell reference, then we scale to magic coordinates
|
||||||
* and place the cell in the magic database. However, if this is
|
* and place the cell in the magic database. However, if this is
|
||||||
* a cell to be flattened a la "gds flatten", then we keep the GDS
|
* a cell to be flattened a la "gds flatten", then we keep the GDS
|
||||||
* coordinates, and don't scale to the magic database.
|
* coordinates, and don't scale to the magic database.
|
||||||
|
*
|
||||||
|
* NOTE: Scaling everything in the middle or reading array data
|
||||||
|
* and then retroactively adjusting the array data read earlier
|
||||||
|
* is problematic, and probably incorrect.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
for (n = 0; n < nref; n++)
|
||||||
|
{
|
||||||
|
savescale = calmaReadScale1;
|
||||||
|
|
||||||
|
/* If there is only one column, then X data in the 2nd or 3rd
|
||||||
|
* entry is irrelevant. If there is only one row, then Y data
|
||||||
|
* in the 2nd or 3rd entry is irrelevant. Prevent issues caused
|
||||||
|
* by incorrect/uninitialized data in these positions by ignoring
|
||||||
|
* them as needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((n > 0) && ((!rotated && (rows == 1)) || (rotated && (cols == 1))))
|
||||||
|
{
|
||||||
|
calmaReadX(&refarray[n], 1);
|
||||||
|
calmaSkipBytes(4);
|
||||||
|
refarray[n].p_y = refarray[0].p_y;
|
||||||
|
}
|
||||||
|
else if ((n > 0) && ((!rotated && (cols == 1)) || (rotated && (rows == 1))))
|
||||||
|
{
|
||||||
|
calmaSkipBytes(4);
|
||||||
|
calmaReadY(&refarray[n], 1);
|
||||||
|
refarray[n].p_x = refarray[0].p_x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
calmaReadPoint(&refarray[n], 1);
|
||||||
|
|
||||||
|
if (savescale != calmaReadScale1)
|
||||||
|
{
|
||||||
|
/* Scale changed, so update previous points read */
|
||||||
|
int newscale = calmaReadScale1 / savescale;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
refarray[i].p_x *= newscale;
|
||||||
|
refarray[i].p_y *= newscale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FEOF(calmaInputFile))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < nref; n++)
|
||||||
|
refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells
|
||||||
|
|
||||||
for (n = 0; n < nref; n++)
|
for (n = 0; n < nref; n++)
|
||||||
{
|
{
|
||||||
savescale = cifCurReadStyle->crs_scaleFactor;
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
calmaReadPoint(&refarray[n], 1);
|
|
||||||
refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells
|
|
||||||
refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT);
|
refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT);
|
||||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
{
|
{
|
||||||
|
|
@ -967,9 +1077,6 @@ calmaElementSref(
|
||||||
}
|
}
|
||||||
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FEOF(calmaInputFile))
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip remainder */
|
/* Skip remainder */
|
||||||
|
|
@ -1245,27 +1352,28 @@ gdsHasUses(
|
||||||
int
|
int
|
||||||
gdsCopyPaintFunc(
|
gdsCopyPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
GDSCopyRec *gdsCopyRec)
|
GDSCopyRec *gdsCopyRec)
|
||||||
{
|
{
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo;
|
TileType newdinfo;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
Transform *trans = gdsCopyRec->trans;
|
Transform *trans = gdsCopyRec->trans;
|
||||||
Plane *plane = gdsCopyRec->plane;
|
Plane *plane = gdsCopyRec->plane;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile);
|
newdinfo = TiGetTypeExact(tile) | dinfo;
|
||||||
|
|
||||||
if (trans)
|
if (trans)
|
||||||
{
|
{
|
||||||
TiToRect(tile, &sourceRect);
|
TiToRect(tile, &sourceRect);
|
||||||
GeoTransRect(trans, &sourceRect, &targetRect);
|
GeoTransRect(trans, &sourceRect, &targetRect);
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TiToRect(tile, &targetRect);
|
TiToRect(tile, &targetRect);
|
||||||
|
|
||||||
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1384,13 +1492,18 @@ calmaFindCell(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxPrintf("Warning: cell %s already existed before reading GDS!\n",
|
|
||||||
name);
|
|
||||||
if (CalmaNoDuplicates)
|
if (CalmaNoDuplicates)
|
||||||
{
|
{
|
||||||
|
TxPrintf("Note: cell %s already existed before reading GDS.\n",
|
||||||
|
name);
|
||||||
if (predefined) *predefined = TRUE;
|
if (predefined) *predefined = TRUE;
|
||||||
TxPrintf("Using pre-existing cell definition\n");
|
TxPrintf("Using pre-existing cell definition\n");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxPrintf("Warning: cell %s already existed before reading GDS!\n",
|
||||||
|
name);
|
||||||
|
}
|
||||||
if (was_called) *was_called = TRUE;
|
if (was_called) *was_called = TRUE;
|
||||||
}
|
}
|
||||||
HashSetValue(h, def);
|
HashSetValue(h, def);
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ calmaInputRescale(
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
* calmaReadX ---
|
||||||
|
* calmaReadY ---
|
||||||
* calmaReadPoint ---
|
* calmaReadPoint ---
|
||||||
*
|
*
|
||||||
* Read a point from the input.
|
* Read a point from the input.
|
||||||
|
|
@ -132,11 +134,17 @@ calmaInputRescale(
|
||||||
* encountered, then everything in the GDS planes is rescaled
|
* encountered, then everything in the GDS planes is rescaled
|
||||||
* to match.
|
* to match.
|
||||||
*
|
*
|
||||||
|
* Notes:
|
||||||
|
* This routine has been split into individual X and Y reads so that
|
||||||
|
* array data can be read while ignoring offset information when there
|
||||||
|
* is only one row or column; otherwise, bad or uninitialized data
|
||||||
|
* in the record can cause unnecessary and incorrect scaling.
|
||||||
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
calmaReadPoint(
|
calmaReadX(
|
||||||
Point *p,
|
Point *p,
|
||||||
int iscale)
|
int iscale)
|
||||||
{
|
{
|
||||||
|
|
@ -163,6 +171,15 @@ calmaReadPoint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->p_x /= calmaReadScale2;
|
p->p_x /= calmaReadScale2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
calmaReadY(
|
||||||
|
Point *p,
|
||||||
|
int iscale)
|
||||||
|
{
|
||||||
|
int rescale;
|
||||||
|
|
||||||
READI4((p)->p_y);
|
READI4((p)->p_y);
|
||||||
p->p_y *= (calmaReadScale1 * iscale);
|
p->p_y *= (calmaReadScale1 * iscale);
|
||||||
|
|
@ -188,6 +205,15 @@ calmaReadPoint(
|
||||||
p->p_y /= calmaReadScale2;
|
p->p_y /= calmaReadScale2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
calmaReadPoint(
|
||||||
|
Point *p,
|
||||||
|
int iscale)
|
||||||
|
{
|
||||||
|
calmaReadX(p, iscale);
|
||||||
|
calmaReadY(p, iscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -360,12 +386,14 @@ calmaElementBoundary(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Paint the rectangles (if any) */
|
/* Paint the rectangles (if any) */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (; rp != NULL ; rp = rp->r_next)
|
for (; rp != NULL ; rp = rp->r_next)
|
||||||
{
|
{
|
||||||
if (plane)
|
if (plane)
|
||||||
DBPaintPlane(plane, &rp->r_r, CIFPaintTable, (PaintUndoInfo *)NULL);
|
DBPaintPlane(plane, &rp->r_r, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
freeMagic((char *) rp);
|
freeMagic1(&mm1, (char *) rp);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
if (cifCurReadPlanes == cifEditCellPlanes)
|
if (cifCurReadPlanes == cifEditCellPlanes)
|
||||||
{
|
{
|
||||||
|
|
@ -690,7 +718,12 @@ calmaElementPath(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path");
|
/* If requested by command option, record the path centerline as a
|
||||||
|
* property of the cell def.
|
||||||
|
*/
|
||||||
|
if (CalmaRecordPaths)
|
||||||
|
CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path");
|
||||||
|
|
||||||
CIFPaintWirePath(pathheadp, width,
|
CIFPaintWirePath(pathheadp, width,
|
||||||
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
|
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
|
||||||
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
|
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
|
|
|
||||||
|
|
@ -613,20 +613,23 @@ CalmaTechInit(void)
|
||||||
ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
|
ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
|
||||||
ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h");
|
ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h");
|
||||||
|
|
||||||
/* NOTE: Enable the code below when CalmaContactArrays */
|
/* NOTE: Add "$$*$$" to the default "flatglob" value */
|
||||||
/* behaves like the non-arrayed function and can be enabled */
|
/* when CalmaContactArrays behaves like the non-arrayed */
|
||||||
/* by default. */
|
/* function and can be enabled by default. */
|
||||||
#if 0
|
|
||||||
/* Initialize CalmaFlattenByName to have one entry for */
|
/* Initialize CalmaFlattenByName to have one entry for */
|
||||||
/* "$$*$$" to match the name style used by the contact */
|
/* "*_CDNS_*" to match the name style used by many foundry */
|
||||||
/* array cell generation. This can be overridden by the */
|
/* cells and which corresponds to pcells that often split */
|
||||||
/* "gds flatglob none" command option. */
|
/* layers between cells in ways that magic can't cope with; */
|
||||||
|
/* and whose original parameterized functions cannot be */
|
||||||
|
/* recovered by magic anyway. When necessary, this default */
|
||||||
|
/* can be overridden by the "gds flatglob none" command */
|
||||||
|
/* option. */
|
||||||
|
|
||||||
if (CalmaFlattenUsesByName == (char **)NULL)
|
if (CalmaFlattenUsesByName == (char **)NULL)
|
||||||
{
|
{
|
||||||
CalmaFlattenUsesByName = (char **)mallocMagic(2 * sizeof(char *));
|
CalmaFlattenUsesByName = (char **)mallocMagic(2 * sizeof(char *));
|
||||||
*CalmaFlattenUsesByName = StrDup((char **)NULL, "$$*$$");
|
*CalmaFlattenUsesByName = StrDup((char **)NULL, "*_CDNS_*");
|
||||||
*(CalmaFlattenUsesByName + 1) = NULL;
|
*(CalmaFlattenUsesByName + 1) = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,10 @@ typedef struct {
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
extern int calmaWriteInitFunc(CellDef *def);
|
extern int calmaWriteInitFunc(CellDef *def);
|
||||||
extern int calmaWritePaintFunc(Tile *tile, calmaOutputStruct *cos);
|
extern int calmaWritePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||||
extern int calmaMergePaintFunc(Tile *tile, calmaOutputStruct *cos);
|
extern int calmaMergePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||||
extern int calmaWriteUseFunc(CellUse *use, FILE *f);
|
extern int calmaWriteUseFunc(CellUse *use, FILE *f);
|
||||||
extern int calmaPaintLabelFunc(Tile *tile, calmaOutputStruct *cos);
|
extern int calmaPaintLabelFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||||
extern void calmaWriteContacts(FILE *f);
|
extern void calmaWriteContacts(FILE *f);
|
||||||
extern void calmaDelContacts(void);
|
extern void calmaDelContacts(void);
|
||||||
extern void calmaOutFunc(CellDef *def, FILE *f, const Rect *cliprect);
|
extern void calmaOutFunc(CellDef *def, FILE *f, const Rect *cliprect);
|
||||||
|
|
@ -528,7 +528,7 @@ calmaDumpStructure(
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
if (isAbstract && isReadOnly)
|
if (isAbstract && isReadOnly)
|
||||||
{
|
{
|
||||||
|
|
@ -738,7 +738,7 @@ calmaFullDump(
|
||||||
* names in the GDS file do not shadow any names in the database.
|
* names in the GDS file do not shadow any names in the database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||||
{
|
{
|
||||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||||
|
|
@ -918,7 +918,7 @@ calmaProcessDef(
|
||||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||||
DBPropGet(def, "CIFhier", &needHier);
|
DBPropGet(def, "CIFhier", &needHier);
|
||||||
|
|
||||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
/* When used with "calma addendum true", don't output the read-only */
|
/* When used with "calma addendum true", don't output the read-only */
|
||||||
/* cells. This makes the library incomplete and dependent on the */
|
/* cells. This makes the library incomplete and dependent on the */
|
||||||
|
|
@ -1033,13 +1033,12 @@ calmaProcessDef(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellend = (off_t)cval;
|
cellend = (off_t)cval;
|
||||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||||
if (!oldStyle)
|
if (!oldStyle)
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||||
|
|
||||||
/* Write our own header and string name, to ensure */
|
/* Write our own header and string name, to ensure */
|
||||||
/* that the magic cell name and GDS name match. */
|
/* that the magic cell name and GDS name match. */
|
||||||
|
|
@ -1056,7 +1055,6 @@ calmaProcessDef(
|
||||||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellstart = (off_t)cval;
|
cellstart = (off_t)cval;
|
||||||
|
|
||||||
/* GDS_START has been defined as the start of data after the cell */
|
/* GDS_START has been defined as the start of data after the cell */
|
||||||
|
|
@ -1263,7 +1261,7 @@ calmaOutFunc(
|
||||||
int dbunits;
|
int dbunits;
|
||||||
calmaOutputStruct cos;
|
calmaOutputStruct cos;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
char *propvalue;
|
PropertyRecord *proprec;
|
||||||
|
|
||||||
cos.f = f;
|
cos.f = f;
|
||||||
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
||||||
|
|
@ -1323,14 +1321,20 @@ calmaOutFunc(
|
||||||
|
|
||||||
/* Include any fixed bounding box as part of the area to process, */
|
/* Include any fixed bounding box as part of the area to process, */
|
||||||
/* in case the fixed bounding box is larger than the geometry. */
|
/* in case the fixed bounding box is larger than the geometry. */
|
||||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
(proprec->prop_len == 4))
|
||||||
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
GeoInclude(&bbox, &bigArea);
|
GeoInclude(&bbox, &bigArea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
|
|
@ -1400,8 +1404,10 @@ calmaOutFunc(
|
||||||
{
|
{
|
||||||
pllist[i].pl_label = ll->ll_label;
|
pllist[i].pl_label = ll->ll_label;
|
||||||
pllist[i].pl_port = (unsigned int)ll->ll_attr;
|
pllist[i].pl_port = (unsigned int)ll->ll_attr;
|
||||||
freeMagic(ll);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, ll);
|
||||||
ll = ll->ll_next;
|
ll = ll->ll_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2422,19 +2428,27 @@ calmaProcessBoundary(
|
||||||
|
|
||||||
/* Free the LinkedBoundary list */
|
/* Free the LinkedBoundary list */
|
||||||
|
|
||||||
lbref = listtop;
|
|
||||||
while (lbref->lb_next != listtop)
|
|
||||||
{
|
{
|
||||||
freeMagic(lbref);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lbref = lbref->lb_next;
|
lbref = listtop;
|
||||||
|
while (lbref->lb_next != listtop)
|
||||||
|
{
|
||||||
|
freeMagic1(&mm1, lbref);
|
||||||
|
lbref = lbref->lb_next;
|
||||||
|
}
|
||||||
|
freeMagic1(&mm1, lbref);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
freeMagic(lbref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the BoundaryTop list */
|
/* Free the BoundaryTop list */
|
||||||
|
|
||||||
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
|
{
|
||||||
freeMagic(bounds);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
|
||||||
|
freeMagic1(&mm1, bounds);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2454,6 +2468,7 @@ calmaProcessBoundary(
|
||||||
int
|
int
|
||||||
calmaMergePaintFunc(
|
calmaMergePaintFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStruct *cos) /* Information needed by algorithm */
|
calmaOutputStruct *cos) /* Information needed by algorithm */
|
||||||
{
|
{
|
||||||
FILE *f = cos->f;
|
FILE *f = cos->f;
|
||||||
|
|
@ -2484,11 +2499,10 @@ calmaMergePaintFunc(
|
||||||
split_type = -1;
|
split_type = -1;
|
||||||
if (IsSplit(t))
|
if (IsSplit(t))
|
||||||
{
|
{
|
||||||
/* If we use SplitSide, then we need to set it when the */
|
/* If we use TT_SIDE, then we need to set it when the */
|
||||||
/* tile is pushed. Since these are one-or-zero mask layers */
|
/* tile is pushed. Since these are one-or-zero mask layers */
|
||||||
/* I assume it is okay to just check which side is TT_SPACE */
|
/* I assume it is okay to just check which side is TT_SPACE */
|
||||||
|
|
||||||
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
|
|
||||||
split_type = SplitDirection(t);
|
split_type = SplitDirection(t);
|
||||||
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
||||||
num_points = 2;
|
num_points = 2;
|
||||||
|
|
@ -2500,8 +2514,10 @@ calmaMergePaintFunc(
|
||||||
lb = edge;
|
lb = edge;
|
||||||
while (lb->lb_next != edge) lb = lb->lb_next;
|
while (lb->lb_next != edge) lb = lb->lb_next;
|
||||||
lb->lb_next = edge->lb_next;
|
lb->lb_next = edge->lb_next;
|
||||||
freeMagic(edge);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, edge);
|
||||||
edge = edge->lb_next;
|
edge = edge->lb_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2709,7 +2725,9 @@ right_search:
|
||||||
done_searches:
|
done_searches:
|
||||||
if (intedges == 0)
|
if (intedges == 0)
|
||||||
{
|
{
|
||||||
calmaWritePaintFunc(t, cos);
|
calmaWritePaintFunc(t,
|
||||||
|
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
|
||||||
|
cos);
|
||||||
|
|
||||||
/* Although calmaWritePaintFunc is called only on isolated */
|
/* Although calmaWritePaintFunc is called only on isolated */
|
||||||
/* tiles, we may have expanded it. This could use a LOT of */
|
/* tiles, we may have expanded it. This could use a LOT of */
|
||||||
|
|
@ -2720,11 +2738,13 @@ done_searches:
|
||||||
|
|
||||||
if (num_points != 4)
|
if (num_points != 4)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (i = 0; i < num_points; i++)
|
for (i = 0; i < num_points; i++)
|
||||||
{
|
{
|
||||||
freeMagic(edge);
|
freeMagic1(&mm1, edge);
|
||||||
edge = edge->lb_next;
|
edge = edge->lb_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
edge = NULL;
|
edge = NULL;
|
||||||
}
|
}
|
||||||
if (!StackEmpty(SegStack))
|
if (!StackEmpty(SegStack))
|
||||||
|
|
@ -2777,6 +2797,7 @@ done_searches:
|
||||||
int
|
int
|
||||||
calmaWritePaintFunc(
|
calmaWritePaintFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
calmaOutputStruct *cos) /* File for output and clipping area */
|
calmaOutputStruct *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
FILE *f = cos->f;
|
FILE *f = cos->f;
|
||||||
|
|
@ -2812,7 +2833,7 @@ calmaWritePaintFunc(
|
||||||
/* Coordinates */
|
/* Coordinates */
|
||||||
calmaOutRH(36, CALMA_XY, CALMA_I4, f);
|
calmaOutRH(36, CALMA_XY, CALMA_I4, f);
|
||||||
|
|
||||||
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
|
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f);
|
calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f);
|
||||||
|
|
@ -3053,6 +3074,7 @@ calmaWriteLabelFunc(
|
||||||
int
|
int
|
||||||
calmaPaintLabelFunc(
|
calmaPaintLabelFunc(
|
||||||
Tile *tile, /* Tile contains area for label. */
|
Tile *tile, /* Tile contains area for label. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStruct *cos) /* File for output and clipping area */
|
calmaOutputStruct *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
FILE *f = cos->f;
|
FILE *f = cos->f;
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,10 @@ typedef struct {
|
||||||
} calmaOutputStructZ;
|
} calmaOutputStructZ;
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
extern int calmaWritePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
extern int calmaWritePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||||
extern int calmaMergePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
extern int calmaMergePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||||
extern int calmaWriteUseFuncZ(CellUse *use, gzFile f);
|
extern int calmaWriteUseFuncZ(CellUse *use, gzFile f);
|
||||||
extern int calmaPaintLabelFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
extern int calmaPaintLabelFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||||
extern void calmaWriteContactsZ(gzFile f);
|
extern void calmaWriteContactsZ(gzFile f);
|
||||||
extern void calmaOutFuncZ(CellDef *def, gzFile f, const Rect *cliprect);
|
extern void calmaOutFuncZ(CellDef *def, gzFile f, const Rect *cliprect);
|
||||||
extern void calmaOutStructNameZ(int type, CellDef *def, gzFile f);
|
extern void calmaOutStructNameZ(int type, CellDef *def, gzFile f);
|
||||||
|
|
@ -508,7 +508,7 @@ calmaDumpStructureZ(
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
if (isAbstract && isReadOnly)
|
if (isAbstract && isReadOnly)
|
||||||
{
|
{
|
||||||
|
|
@ -716,7 +716,7 @@ calmaFullDumpZ(
|
||||||
* names in the GDS file do not shadow any names in the database.
|
* names in the GDS file do not shadow any names in the database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||||
{
|
{
|
||||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||||
|
|
@ -870,7 +870,7 @@ calmaProcessDefZ(
|
||||||
DBPropGet(def, "GDS_START", &hasContent);
|
DBPropGet(def, "GDS_START", &hasContent);
|
||||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||||
DBPropGet(def, "CIFhier", &needHier);
|
DBPropGet(def, "CIFhier", &needHier);
|
||||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
/* When used with "calma addendum true", don't output the read-only */
|
/* When used with "calma addendum true", don't output the read-only */
|
||||||
/* cells. This makes the library incomplete and dependent on the */
|
/* cells. This makes the library incomplete and dependent on the */
|
||||||
|
|
@ -985,13 +985,12 @@ calmaProcessDefZ(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellend = (z_off_t)cval;
|
cellend = (z_off_t)cval;
|
||||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||||
if (!oldStyle)
|
if (!oldStyle)
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||||
|
|
||||||
/* Write our own header and string name, to ensure */
|
/* Write our own header and string name, to ensure */
|
||||||
/* that the magic cell name and GDS name match. */
|
/* that the magic cell name and GDS name match. */
|
||||||
|
|
@ -1008,7 +1007,6 @@ calmaProcessDefZ(
|
||||||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellstart = (z_off_t)cval;
|
cellstart = (z_off_t)cval;
|
||||||
|
|
||||||
/* GDS_START has been defined as the start of data after the cell */
|
/* GDS_START has been defined as the start of data after the cell */
|
||||||
|
|
@ -1186,6 +1184,7 @@ calmaOutFuncZ(
|
||||||
int dbunits;
|
int dbunits;
|
||||||
calmaOutputStructZ cos;
|
calmaOutputStructZ cos;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
|
PropertyRecord *proprec;
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
extern int compport(const void *one, const void *two); /* Forward declaration */
|
extern int compport(const void *one, const void *two); /* Forward declaration */
|
||||||
|
|
||||||
|
|
@ -1247,14 +1246,20 @@ calmaOutFuncZ(
|
||||||
|
|
||||||
/* Include any fixed bounding box as part of the area to process, */
|
/* Include any fixed bounding box as part of the area to process, */
|
||||||
/* in case the fixed bounding box is larger than the geometry. */
|
/* in case the fixed bounding box is larger than the geometry. */
|
||||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
(proprec->prop_len == 4))
|
||||||
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
GeoInclude(&bbox, &bigArea);
|
GeoInclude(&bbox, &bigArea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
|
|
@ -1324,8 +1329,10 @@ calmaOutFuncZ(
|
||||||
{
|
{
|
||||||
pllist[i].pl_label = ll->ll_label;
|
pllist[i].pl_label = ll->ll_label;
|
||||||
pllist[i].pl_port = (unsigned int)ll->ll_attr;
|
pllist[i].pl_port = (unsigned int)ll->ll_attr;
|
||||||
freeMagic(ll);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, ll);
|
||||||
ll = ll->ll_next;
|
ll = ll->ll_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1857,19 +1864,27 @@ calmaProcessBoundaryZ(
|
||||||
|
|
||||||
/* Free the LinkedBoundary list */
|
/* Free the LinkedBoundary list */
|
||||||
|
|
||||||
lbref = listtop;
|
|
||||||
while (lbref->lb_next != listtop)
|
|
||||||
{
|
{
|
||||||
freeMagic(lbref);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lbref = lbref->lb_next;
|
lbref = listtop;
|
||||||
|
while (lbref->lb_next != listtop)
|
||||||
|
{
|
||||||
|
freeMagic1(&mm1, lbref);
|
||||||
|
lbref = lbref->lb_next;
|
||||||
|
}
|
||||||
|
freeMagic1(&mm1, lbref);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
freeMagic(lbref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the BoundaryTop list */
|
/* Free the BoundaryTop list */
|
||||||
|
|
||||||
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
|
{
|
||||||
freeMagic(bounds);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
|
||||||
|
freeMagic1(&mm1, bounds);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1889,6 +1904,7 @@ calmaProcessBoundaryZ(
|
||||||
int
|
int
|
||||||
calmaMergePaintFuncZ(
|
calmaMergePaintFuncZ(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStructZ *cos) /* Information needed by algorithm */
|
calmaOutputStructZ *cos) /* Information needed by algorithm */
|
||||||
{
|
{
|
||||||
gzFile f = cos->f;
|
gzFile f = cos->f;
|
||||||
|
|
@ -1919,11 +1935,10 @@ calmaMergePaintFuncZ(
|
||||||
split_type = -1;
|
split_type = -1;
|
||||||
if (IsSplit(t))
|
if (IsSplit(t))
|
||||||
{
|
{
|
||||||
/* If we use SplitSide, then we need to set it when the */
|
/* If we use TT_SIDE, then we need to set it when the */
|
||||||
/* tile is pushed. Since these are one-or-zero mask layers */
|
/* tile is pushed. Since these are one-or-zero mask layers */
|
||||||
/* I assume it is okay to just check which side is TT_SPACE */
|
/* I assume it is okay to just check which side is TT_SPACE */
|
||||||
|
|
||||||
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
|
|
||||||
split_type = SplitDirection(t);
|
split_type = SplitDirection(t);
|
||||||
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
||||||
num_points = 2;
|
num_points = 2;
|
||||||
|
|
@ -1935,8 +1950,10 @@ calmaMergePaintFuncZ(
|
||||||
lb = edge;
|
lb = edge;
|
||||||
while (lb->lb_next != edge) lb = lb->lb_next;
|
while (lb->lb_next != edge) lb = lb->lb_next;
|
||||||
lb->lb_next = edge->lb_next;
|
lb->lb_next = edge->lb_next;
|
||||||
freeMagic(edge);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, edge);
|
||||||
edge = edge->lb_next;
|
edge = edge->lb_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2144,7 +2161,9 @@ right_search:
|
||||||
done_searches:
|
done_searches:
|
||||||
if (intedges == 0)
|
if (intedges == 0)
|
||||||
{
|
{
|
||||||
calmaWritePaintFuncZ(t, cos);
|
calmaWritePaintFuncZ(t,
|
||||||
|
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
|
||||||
|
cos);
|
||||||
|
|
||||||
/* Although calmaWritePaintFunc is called only on isolated */
|
/* Although calmaWritePaintFunc is called only on isolated */
|
||||||
/* tiles, we may have expanded it. This could use a LOT of */
|
/* tiles, we may have expanded it. This could use a LOT of */
|
||||||
|
|
@ -2155,11 +2174,13 @@ done_searches:
|
||||||
|
|
||||||
if (num_points != 4)
|
if (num_points != 4)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (i = 0; i < num_points; i++)
|
for (i = 0; i < num_points; i++)
|
||||||
{
|
{
|
||||||
freeMagic(edge);
|
freeMagic1(&mm1, edge);
|
||||||
edge = edge->lb_next;
|
edge = edge->lb_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
edge = NULL;
|
edge = NULL;
|
||||||
}
|
}
|
||||||
if (!StackEmpty(SegStack))
|
if (!StackEmpty(SegStack))
|
||||||
|
|
@ -2212,6 +2233,7 @@ done_searches:
|
||||||
int
|
int
|
||||||
calmaWritePaintFuncZ(
|
calmaWritePaintFuncZ(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
calmaOutputStructZ *cos) /* File for output and clipping area */
|
calmaOutputStructZ *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
gzFile f = cos->f;
|
gzFile f = cos->f;
|
||||||
|
|
@ -2247,7 +2269,7 @@ calmaWritePaintFuncZ(
|
||||||
/* Coordinates */
|
/* Coordinates */
|
||||||
calmaOutRHZ(36, CALMA_XY, CALMA_I4, f);
|
calmaOutRHZ(36, CALMA_XY, CALMA_I4, f);
|
||||||
|
|
||||||
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
|
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
calmaOutI4Z(r.r_xbot, f); calmaOutI4Z(r.r_ybot, f);
|
calmaOutI4Z(r.r_xbot, f); calmaOutI4Z(r.r_ybot, f);
|
||||||
|
|
@ -2488,6 +2510,7 @@ calmaWriteLabelFuncZ(
|
||||||
int
|
int
|
||||||
calmaPaintLabelFuncZ(
|
calmaPaintLabelFuncZ(
|
||||||
Tile *tile, /* Tile contains area for label. */
|
Tile *tile, /* Tile contains area for label. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStructZ *cos) /* File for output and clipping area */
|
calmaOutputStructZ *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
gzFile f = cos->f;
|
gzFile f = cos->f;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ extern TileTypeBitMask *CalmaMaskHints;
|
||||||
extern bool CalmaMergeTiles;
|
extern bool CalmaMergeTiles;
|
||||||
extern bool CalmaFlattenArrays;
|
extern bool CalmaFlattenArrays;
|
||||||
extern bool CalmaNoDRCCheck;
|
extern bool CalmaNoDRCCheck;
|
||||||
|
extern bool CalmaRecordPaths;
|
||||||
extern bool CalmaFlattenUses;
|
extern bool CalmaFlattenUses;
|
||||||
extern int CalmaFlattenLimit;
|
extern int CalmaFlattenLimit;
|
||||||
extern float CalmaMagScale;
|
extern float CalmaMagScale;
|
||||||
|
|
@ -81,6 +82,8 @@ extern int calmaProcessDefZ(CellDef *def, gzFile outf, bool do_library);
|
||||||
#endif
|
#endif
|
||||||
extern bool calmaReadI2Record(int type, int *pvalue);
|
extern bool calmaReadI2Record(int type, int *pvalue);
|
||||||
extern bool calmaReadI4Record(int type, int *pvalue);
|
extern bool calmaReadI4Record(int type, int *pvalue);
|
||||||
|
extern void calmaReadX(Point *p, int iscale);
|
||||||
|
extern void calmaReadY(Point *p, int iscale);
|
||||||
extern void calmaReadPoint(Point *p, int iscale);
|
extern void calmaReadPoint(Point *p, int iscale);
|
||||||
extern bool calmaReadR8(double *pd);
|
extern bool calmaReadR8(double *pd);
|
||||||
extern bool calmaReadStampRecord(int type, int *stampptr);
|
extern bool calmaReadStampRecord(int type, int *stampptr);
|
||||||
|
|
|
||||||
677
cif/CIFgen.c
677
cif/CIFgen.c
File diff suppressed because it is too large
Load Diff
211
cif/CIFhier.c
211
cif/CIFhier.c
|
|
@ -209,52 +209,41 @@ typedef struct _maskHintsData
|
||||||
{
|
{
|
||||||
Transform *mh_trans;
|
Transform *mh_trans;
|
||||||
CellDef *mh_def;
|
CellDef *mh_def;
|
||||||
|
Plane *mh_plane;
|
||||||
} MaskHintsData;
|
} MaskHintsData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* cifMaskHints --
|
* cifCopyMaskHintFunc --
|
||||||
*
|
*
|
||||||
* Copy a mask hint into a target cell by adding it to the
|
* Callback function used by cifFlatMaskHints. Transforms a tile
|
||||||
* property list of the target cell. If the target cell already
|
* from the original plane and paints it into the target plane,
|
||||||
* has the same mask hint key, then the mask hint value is
|
* both of which are properties.
|
||||||
* appended to the property in the target cell def.
|
|
||||||
*
|
*
|
||||||
* Returns:
|
* Results:
|
||||||
* 0 to keep the search going.
|
* Zero to keep the search going.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Modifies properties of the target cell def.
|
* Paints geometry into the target plane.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* DEPRECATED */
|
|
||||||
int
|
int
|
||||||
cifMaskHints(
|
cifCopyMaskHintFunc(Tile *tile,
|
||||||
char *name,
|
TileType dinfo,
|
||||||
char *value,
|
ClientData cdata)
|
||||||
CellDef *targetDef)
|
|
||||||
{
|
{
|
||||||
char *propvalue, *newval;
|
MaskHintsData *mhd = (MaskHintsData *)cdata;
|
||||||
bool propfound;
|
Rect r, newr;
|
||||||
|
|
||||||
if (!strncmp(name, "MASKHINTS_", 10))
|
TiToRect(tile, &r);
|
||||||
{
|
|
||||||
/* Check if name exists already in the flattened cell */
|
/* Transform tile area to coordinates of mhd->mh_plane and paint */
|
||||||
propvalue = (char *)DBPropGet(targetDef, name, &propfound);
|
GeoTransRect(mhd->mh_trans, &r, &newr);
|
||||||
if (propfound)
|
DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
{
|
|
||||||
/* Append value to the property */
|
|
||||||
newval = mallocMagic(strlen(value) + strlen(propvalue) + 2);
|
|
||||||
sprintf(newval, "%s %s", propvalue, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newval = StrDup((char **)NULL, value);
|
|
||||||
|
|
||||||
DBPropPut(targetDef, name, newval);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,8 +253,8 @@ cifMaskHints(
|
||||||
* cifFlatMaskHints --
|
* cifFlatMaskHints --
|
||||||
*
|
*
|
||||||
* Copy a mask hint into a flattened cell by transforming it into the
|
* Copy a mask hint into a flattened cell by transforming it into the
|
||||||
* coordinate system of the flattened cell, and adding it to the
|
* coordinate system of the flattened cell, and painting it into the
|
||||||
* property list of the flattened cell.
|
* property plane of the flattened cell.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* 0 to keep the search going.
|
* 0 to keep the search going.
|
||||||
|
|
@ -279,67 +268,40 @@ cifMaskHints(
|
||||||
int
|
int
|
||||||
cifFlatMaskHints(
|
cifFlatMaskHints(
|
||||||
char *name,
|
char *name,
|
||||||
char *value,
|
PropertyRecord *proprec,
|
||||||
MaskHintsData *mhd)
|
MaskHintsData *mhd)
|
||||||
{
|
{
|
||||||
Rect r, newr;
|
Rect r, newr;
|
||||||
char *vptr, *newval, *lastval, *propvalue;
|
char *vptr, *newval, *lastval, *propvalue;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
int lastlen, numvals;
|
int i, lastlen, numvals;
|
||||||
|
PropertyRecord *newproprec, *oldproprec;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
if (!strncmp(name, "MASKHINTS_", 10))
|
if (!strncmp(name, "MASKHINTS_", 10))
|
||||||
{
|
{
|
||||||
newval = (char *)NULL;
|
|
||||||
vptr = value;
|
|
||||||
while (*vptr != '\0')
|
|
||||||
{
|
|
||||||
numvals = sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
|
||||||
&r.r_xtop, &r.r_ytop);
|
|
||||||
if (numvals == 4)
|
|
||||||
{
|
|
||||||
/* Transform rectangle to top level coordinates */
|
|
||||||
GeoTransRect(mhd->mh_trans, &r, &newr);
|
|
||||||
lastval = newval;
|
|
||||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
|
||||||
newval = mallocMagic(40 + lastlen);
|
|
||||||
if (lastval)
|
|
||||||
strcpy(newval, lastval);
|
|
||||||
else
|
|
||||||
*newval = '\0';
|
|
||||||
sprintf(newval + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
|
||||||
newr.r_xbot, newr.r_ybot, newr.r_xtop, newr.r_ytop);
|
|
||||||
if (lastval) freeMagic(lastval);
|
|
||||||
|
|
||||||
/* Parse through the four values and check if there's more */
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TxError("MASKHINTS_%s: Expected 4 values, found only %d\n",
|
|
||||||
name + 10, numvals);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if name exists already in the flattened cell */
|
/* Check if name exists already in the flattened cell */
|
||||||
propvalue = (char *)DBPropGet(mhd->mh_def, name, &propfound);
|
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
/* Append newval to the property */
|
ASSERT(oldproprec->prop_value.prop_type == PROPERTY_TYPE_PLANE,
|
||||||
lastval = newval;
|
"cifFlatMaskHints");
|
||||||
newval = mallocMagic(strlen(lastval) + strlen(propvalue) + 2);
|
plane = oldproprec->prop_value.prop_plane;
|
||||||
sprintf(newval, "%s %s", propvalue, lastval);
|
|
||||||
freeMagic(lastval);
|
|
||||||
}
|
}
|
||||||
DBPropPut(mhd->mh_def, name, newval);
|
else
|
||||||
|
{
|
||||||
|
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
newproprec->prop_len = 0; /* (unused) */
|
||||||
|
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
newproprec->prop_value.prop_plane = plane;
|
||||||
|
DBPropPut(mhd->mh_def, name, newproprec);
|
||||||
|
}
|
||||||
|
|
||||||
|
mhd->mh_plane = plane;
|
||||||
|
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits,
|
||||||
|
cifCopyMaskHintFunc, (ClientData)mhd);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -350,9 +312,10 @@ cifFlatMaskHints(
|
||||||
* CIFCopyMaskHints --
|
* CIFCopyMaskHints --
|
||||||
*
|
*
|
||||||
* Callback function to copy mask hints from one cell into another.
|
* Callback function to copy mask hints from one cell into another.
|
||||||
|
* (Occasionally called as a standalone function, not as a callback.)
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* Return 0 to keep the search going.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* May modify properties in the target cell.
|
* May modify properties in the target cell.
|
||||||
|
|
@ -360,7 +323,7 @@ cifFlatMaskHints(
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
int
|
||||||
CIFCopyMaskHints(
|
CIFCopyMaskHints(
|
||||||
SearchContext *scx,
|
SearchContext *scx,
|
||||||
CellDef *targetDef)
|
CellDef *targetDef)
|
||||||
|
|
@ -370,38 +333,9 @@ CIFCopyMaskHints(
|
||||||
CellDef *sourceDef = scx->scx_use->cu_def;
|
CellDef *sourceDef = scx->scx_use->cu_def;
|
||||||
mhd.mh_trans = &scx->scx_trans;
|
mhd.mh_trans = &scx->scx_trans;
|
||||||
mhd.mh_def = targetDef;
|
mhd.mh_def = targetDef;
|
||||||
|
mhd.mh_plane = (Plane *)NULL;
|
||||||
|
|
||||||
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
|
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* cifHierCopyMaskHints --
|
|
||||||
*
|
|
||||||
* Callback function to copy mask hints from a subcell into a flattened
|
|
||||||
* cell, which is passed in the clientData record.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Always returns 0 to keep the search alive.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* May modify properties in the flattened cell.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
cifHierCopyMaskHints(
|
|
||||||
SearchContext *scx,
|
|
||||||
ClientData clientData)
|
|
||||||
{
|
|
||||||
MaskHintsData mhd;
|
|
||||||
|
|
||||||
mhd.mh_trans = &scx->scx_trans;
|
|
||||||
mhd.mh_def = (CellDef *)clientData;
|
|
||||||
|
|
||||||
DBPropEnum(scx->scx_use->cu_def, cifFlatMaskHints, &mhd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,15 +367,16 @@ cifHierCopyMaskHints(
|
||||||
int
|
int
|
||||||
cifHierCopyFunc(
|
cifHierCopyFunc(
|
||||||
Tile *tile, /* Pointer to tile to copy. */
|
Tile *tile, /* Pointer to tile to copy. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
TreeContext *cxp) /* Describes context of search, including
|
TreeContext *cxp) /* Describes context of search, including
|
||||||
* transform and client data.
|
* transform and client data.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
TileType type = TiGetTypeExact(tile);
|
TileType type = TiGetTypeExact(tile) | dinfo;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
int pNum;
|
int pNum;
|
||||||
CellDef *def = (CellDef *) cxp->tc_filter->tf_arg;
|
CellDef *def = (CellDef *) cxp->tc_filter->tf_arg;
|
||||||
int dinfo = 0;
|
TileType newdinfo = 0;
|
||||||
|
|
||||||
/* Ignore tiles in vendor GDS, unless this is specifically */
|
/* Ignore tiles in vendor GDS, unless this is specifically */
|
||||||
/* overridden by the "see-vendor" option. */
|
/* overridden by the "see-vendor" option. */
|
||||||
|
|
@ -457,8 +392,8 @@ cifHierCopyFunc(
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
dinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
|
newdinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) :
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -473,7 +408,7 @@ cifHierCopyFunc(
|
||||||
{
|
{
|
||||||
if (DBPaintOnPlane(type, pNum))
|
if (DBPaintOnPlane(type, pNum))
|
||||||
{
|
{
|
||||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo, &targetRect,
|
DBNMPaintPlane(def->cd_planes[pNum], newdinfo, &targetRect,
|
||||||
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -525,7 +460,7 @@ cifHierCellFunc(
|
||||||
|
|
||||||
/* Flatten mask hints in the area of interest */
|
/* Flatten mask hints in the area of interest */
|
||||||
CIFCopyMaskHints(scx, CIFComponentDef);
|
CIFCopyMaskHints(scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&newscx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
||||||
|
|
@ -562,9 +497,11 @@ cifHierCellFunc(
|
||||||
int
|
int
|
||||||
cifHierErrorFunc(
|
cifHierErrorFunc(
|
||||||
Tile *tile, /* Tile that covers area it shouldn't. */
|
Tile *tile, /* Tile that covers area it shouldn't. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
Rect *checkArea) /* Intersection of this and tile is error. */
|
Rect *checkArea) /* Intersection of this and tile is error. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
bool side = (dinfo & TT_SIDE) ? TRUE : FALSE;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
||||||
|
|
@ -572,8 +509,8 @@ cifHierErrorFunc(
|
||||||
* space bounds the checkArea.
|
* space bounds the checkArea.
|
||||||
*/
|
*/
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
if (((area.r_xbot == checkArea->r_xbot) && !SplitSide(tile)) ||
|
if (((area.r_xbot == checkArea->r_xbot) && !side) ||
|
||||||
((area.r_xtop == checkArea->r_xtop) && SplitSide(tile)))
|
((area.r_xtop == checkArea->r_xtop) && side))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GeoClip(&area, checkArea);
|
GeoClip(&area, checkArea);
|
||||||
|
|
@ -604,6 +541,7 @@ cifHierErrorFunc(
|
||||||
int
|
int
|
||||||
cifHierCheckFunc(
|
cifHierCheckFunc(
|
||||||
Tile *tile, /* Tile containing CIF. */
|
Tile *tile, /* Tile containing CIF. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
Plane *plane) /* Plane to check against and modify. */
|
Plane *plane) /* Plane to check against and modify. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -612,10 +550,10 @@ cifHierCheckFunc(
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile),
|
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile) | dinfo,
|
||||||
&area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area);
|
&area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area);
|
||||||
|
|
||||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
|
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -651,6 +589,7 @@ cifHierCheckFunc(
|
||||||
int
|
int
|
||||||
cifHierTempCheckFunc(
|
cifHierTempCheckFunc(
|
||||||
Tile *tile, /* Tile containing CIF. */
|
Tile *tile, /* Tile containing CIF. */
|
||||||
|
TileType dinfo, /* Information about split tiles */
|
||||||
Plane *plane) /* Plane to check against and modify. */
|
Plane *plane) /* Plane to check against and modify. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -658,7 +597,7 @@ cifHierTempCheckFunc(
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
|
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
else
|
else
|
||||||
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
|
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
|
||||||
|
|
@ -686,6 +625,7 @@ cifHierTempCheckFunc(
|
||||||
int
|
int
|
||||||
cifHierPaintFunc(
|
cifHierPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* Information about split tiles */
|
||||||
Plane *plane) /* Plane in which to paint CIF over tile's
|
Plane *plane) /* Plane in which to paint CIF over tile's
|
||||||
* area.
|
* area.
|
||||||
*/
|
*/
|
||||||
|
|
@ -693,9 +633,9 @@ cifHierPaintFunc(
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
|
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFPaintTable,
|
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFPaintTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
else
|
else
|
||||||
DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||||
|
|
@ -848,7 +788,7 @@ CIFGenSubcells(
|
||||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||||
/* Flatten mask hints in the area of interest */
|
/* Flatten mask hints in the area of interest */
|
||||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFTotalDef);
|
(ClientData)CIFTotalDef);
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
|
|
@ -1026,14 +966,14 @@ cifHierElementFunc(
|
||||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFTotalDef);
|
(ClientData)CIFTotalDef);
|
||||||
|
|
||||||
DBCellClearDef(CIFComponentDef);
|
DBCellClearDef(CIFComponentDef);
|
||||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
CIFErrorDef = (CellDef *) NULL;
|
CIFErrorDef = (CellDef *) NULL;
|
||||||
|
|
@ -1067,6 +1007,7 @@ cifHierElementFunc(
|
||||||
int
|
int
|
||||||
cifGrowSliver(
|
cifGrowSliver(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* Split tile information, needs to be handled */
|
||||||
Rect *area)
|
Rect *area)
|
||||||
{
|
{
|
||||||
int height, width, expand_up, expand_side;
|
int height, width, expand_up, expand_side;
|
||||||
|
|
@ -1127,22 +1068,24 @@ cifGrowSliver(
|
||||||
|
|
||||||
int
|
int
|
||||||
cifHierPaintArrayFunc(
|
cifHierPaintArrayFunc(
|
||||||
Tile *tile)
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
int i, j, xbot, xtop;
|
int i, j, xbot, xtop;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
|
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
|
||||||
xbot = area.r_xbot;
|
xbot = area.r_xbot;
|
||||||
xtop = area.r_xtop;
|
xtop = area.r_xtop;
|
||||||
for (i=0; i<cifHierYCount; i++)
|
for (i=0; i<cifHierYCount; i++)
|
||||||
{
|
{
|
||||||
for (j=0; j<cifHierXCount; j++)
|
for (j = 0; j < cifHierXCount; j++)
|
||||||
{
|
{
|
||||||
DBPaintPlane(cifHierCurPlane, &area, CIFPaintTable,
|
DBNMPaintPlane(cifHierCurPlane, TiGetTypeExact(tile) | dinfo,
|
||||||
(PaintUndoInfo *) NULL);
|
&area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||||
CIFTileOps += 1;
|
CIFTileOps++;
|
||||||
area.r_xbot += cifHierXSpacing;
|
area.r_xbot += cifHierXSpacing;
|
||||||
area.r_xtop += cifHierXSpacing;
|
area.r_xtop += cifHierXSpacing;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
cif/CIFint.h
14
cif/CIFint.h
|
|
@ -145,6 +145,8 @@ typedef struct cifop
|
||||||
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
|
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
|
||||||
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
|
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
|
||||||
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
|
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
|
||||||
|
* CIFOP_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
|
||||||
|
* CIFOP_TAGGED - Added 3/11/26---Find geometry attached to the given text label
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CIFOP_AND 1
|
#define CIFOP_AND 1
|
||||||
|
|
@ -172,6 +174,8 @@ typedef struct cifop
|
||||||
#define CIFOP_BRIDGE 23
|
#define CIFOP_BRIDGE 23
|
||||||
#define CIFOP_BRIDGELIM 24
|
#define CIFOP_BRIDGELIM 24
|
||||||
#define CIFOP_MASKHINTS 25
|
#define CIFOP_MASKHINTS 25
|
||||||
|
#define CIFOP_NOTSQUARE 26
|
||||||
|
#define CIFOP_TAGGED 27
|
||||||
|
|
||||||
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
|
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
|
||||||
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
||||||
|
|
@ -335,10 +339,9 @@ extern void CIFClearPlanes(Plane **planes);
|
||||||
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[],
|
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[],
|
||||||
bool hier, ClientData clientdata);
|
bool hier, ClientData clientdata);
|
||||||
extern void CIFInitCells(void);
|
extern void CIFInitCells(void);
|
||||||
extern int cifHierCopyFunc(Tile *tile, TreeContext *cxp);
|
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
|
|
||||||
extern void CIFLoadStyle(char *stylename);
|
extern void CIFLoadStyle(char *stylename);
|
||||||
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
||||||
|
|
@ -346,7 +349,7 @@ extern bool CIFWriteFlat(CellDef *rootDef, FILE *f);
|
||||||
extern void CIFScalePlanes(int scalen, int scaled, Plane **planearray);
|
extern void CIFScalePlanes(int scalen, int scaled, Plane **planearray);
|
||||||
extern void CIFInputRescale(int n, int d);
|
extern void CIFInputRescale(int n, int d);
|
||||||
extern int CIFScaleCoord(int cifCoord, int snap_type);
|
extern int CIFScaleCoord(int cifCoord, int snap_type);
|
||||||
extern int cifGrowSliver(Tile *tile, Rect *area);
|
extern int cifGrowSliver(Tile *tile, TileType dinfo, Rect *area);
|
||||||
extern int cifHierElementFunc(CellUse *use, Transform *transform, int x, int y, Rect *checkArea);
|
extern int cifHierElementFunc(CellUse *use, Transform *transform, int x, int y, Rect *checkArea);
|
||||||
extern int cifSquareFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
extern int cifSquareFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
||||||
extern int cifSquareGridFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
extern int cifSquareGridFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
||||||
|
|
@ -367,6 +370,9 @@ extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a
|
||||||
* def.
|
* def.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern Plane *CIFTotalPlanes[]; /* Exported for diagnostics */
|
||||||
|
extern Plane *CIFComponentPlanes[]; /* Exported for diagnostics */
|
||||||
|
|
||||||
/* Valid values of CIFWarningLevel (see cif.h) */
|
/* Valid values of CIFWarningLevel (see cif.h) */
|
||||||
|
|
||||||
typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN,
|
typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN,
|
||||||
|
|
|
||||||
217
cif/CIFrdcl.c
217
cif/CIFrdcl.c
|
|
@ -505,6 +505,7 @@ CIFParseStart(void)
|
||||||
|
|
||||||
int cifCheckPaintFunc(
|
int cifCheckPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
ClientData clientData)
|
ClientData clientData)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -515,27 +516,28 @@ int cifCheckPaintFunc(
|
||||||
int
|
int
|
||||||
cifCopyPaintFunc(
|
cifCopyPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
CIFCopyRec *cifCopyRec)
|
CIFCopyRec *cifCopyRec)
|
||||||
{
|
{
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo;
|
TileType newdinfo;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
Transform *trans = cifCopyRec->trans;
|
Transform *trans = cifCopyRec->trans;
|
||||||
Plane *plane = cifCopyRec->plane;
|
Plane *plane = cifCopyRec->plane;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile);
|
newdinfo = TiGetTypeExact(tile) | dinfo;
|
||||||
|
|
||||||
if (trans)
|
if (trans)
|
||||||
{
|
{
|
||||||
TiToRect(tile, &sourceRect);
|
TiToRect(tile, &sourceRect);
|
||||||
GeoTransRect(trans, &sourceRect, &targetRect);
|
GeoTransRect(trans, &sourceRect, &targetRect);
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TiToRect(tile, &targetRect);
|
TiToRect(tile, &targetRect);
|
||||||
|
|
||||||
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -561,6 +563,7 @@ cifCopyPaintFunc(
|
||||||
int
|
int
|
||||||
cifMaskHintFunc(
|
cifMaskHintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* Unused, do not support non-manhattan hints */
|
||||||
LinkedRect **lrecp)
|
LinkedRect **lrecp)
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -597,8 +600,9 @@ int
|
||||||
CIFPaintCurrent(
|
CIFPaintCurrent(
|
||||||
int filetype)
|
int filetype)
|
||||||
{
|
{
|
||||||
extern int cifMakeBoundaryFunc(Tile *tile, ClientData clientdata); /* Forward declaration. */
|
/* Forward declarations. */
|
||||||
extern int cifPaintCurrentFunc(Tile *tile, TileType type); /* Forward declaration. */
|
extern int cifMakeBoundaryFunc(Tile *tile, TileType dinfo, ClientData clientdata);
|
||||||
|
extern int cifPaintCurrentFunc(Tile *tile, TileType dinfo, TileType type);
|
||||||
|
|
||||||
Plane *plane, *swapplane;
|
Plane *plane, *swapplane;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -609,7 +613,7 @@ CIFPaintCurrent(
|
||||||
CIFOp *op;
|
CIFOp *op;
|
||||||
|
|
||||||
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
||||||
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
|
&TiPlaneRect, cifReadCellDef, cifReadCellDef,
|
||||||
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
||||||
|
|
||||||
/* Generate a paint/erase table, then paint from the CIF
|
/* Generate a paint/erase table, then paint from the CIF
|
||||||
|
|
@ -684,6 +688,8 @@ CIFPaintCurrent(
|
||||||
}
|
}
|
||||||
else if (op == NULL)
|
else if (op == NULL)
|
||||||
{
|
{
|
||||||
|
LinkedRect *lrec = NULL, *lsrch;
|
||||||
|
|
||||||
/* Handle boundary layer */
|
/* Handle boundary layer */
|
||||||
|
|
||||||
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
||||||
|
|
@ -698,6 +704,102 @@ CIFPaintCurrent(
|
||||||
(ClientData)NULL) == 1))
|
(ClientData)NULL) == 1))
|
||||||
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
||||||
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
||||||
|
|
||||||
|
/* Handle mask-hints input operator */
|
||||||
|
|
||||||
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
||||||
|
while (op)
|
||||||
|
{
|
||||||
|
if (op->co_opcode == CIFOP_MASKHINTS) break;
|
||||||
|
op = op->co_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
||||||
|
&DBAllButSpaceBits, cifCheckPaintFunc,
|
||||||
|
(ClientData)NULL) == 1))
|
||||||
|
{
|
||||||
|
/* (To do: remove the linked Rects and paint directly
|
||||||
|
* into the plane in cifMaskHintFunc())
|
||||||
|
*/
|
||||||
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
||||||
|
&CIFSolidBits, cifMaskHintFunc,
|
||||||
|
(ClientData)&lrec);
|
||||||
|
|
||||||
|
if (lrec != NULL)
|
||||||
|
{
|
||||||
|
PropertyRecord *proprec, *proporig;
|
||||||
|
char *propname, *layername;
|
||||||
|
int proplen, i, savescale;
|
||||||
|
bool origfound = FALSE;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
|
layername = (char *)op->co_client;
|
||||||
|
propname = (char *)mallocMagic(11 + strlen(layername));
|
||||||
|
sprintf(propname, "MASKHINTS_%s", layername);
|
||||||
|
|
||||||
|
/* If there is already a mask hint plane for this layer,
|
||||||
|
* then add to it; otherwise, create a new plane.
|
||||||
|
*/
|
||||||
|
proprec = DBPropGet(cifReadCellDef, layername, &origfound);
|
||||||
|
if (origfound)
|
||||||
|
plane = proprec->prop_value.prop_plane;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(
|
||||||
|
sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
|
proprec->prop_len = 0; /* (unused) */
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
DBPropPut(cifReadCellDef, propname, proprec);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lrec != NULL)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_xtop, COORD_EXACT);
|
||||||
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
lrec->r_r.r_ytop =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_ytop, COORD_EXACT);
|
||||||
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
}
|
||||||
|
lrec->r_r.r_xbot =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_xbot, COORD_EXACT);
|
||||||
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
lrec->r_r.r_ytop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
}
|
||||||
|
lrec->r_r.r_ybot =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_ybot, COORD_EXACT);
|
||||||
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
lrec->r_r.r_ytop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
lrec->r_r.r_xbot *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, lrec);
|
||||||
|
lrec = lrec->r_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
|
freeMagic(propname);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap planes */
|
/* Swap planes */
|
||||||
|
|
@ -786,9 +888,7 @@ CIFPaintCurrent(
|
||||||
|
|
||||||
for (i = 0; i < cifNReadLayers; i++)
|
for (i = 0; i < cifNReadLayers; i++)
|
||||||
{
|
{
|
||||||
LinkedRect *lrec = NULL;
|
LinkedRect *lrec = NULL, *lsrch;
|
||||||
char *propstr = NULL;
|
|
||||||
char locstr[512];
|
|
||||||
Plane *tempp;
|
Plane *tempp;
|
||||||
|
|
||||||
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
||||||
|
|
@ -813,51 +913,55 @@ CIFPaintCurrent(
|
||||||
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
||||||
|
|
||||||
/* Scan the resulting plane and generate linked Rect structures for
|
/* Scan the resulting plane and generate linked Rect structures for
|
||||||
* each shape found.
|
* each shape found. (To do: Remove the linked Rects and paint
|
||||||
|
* directly into the plane in cifMaskHintFunc(), which is more
|
||||||
|
* efficient but not hugely so.)
|
||||||
*/
|
*/
|
||||||
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
||||||
cifMaskHintFunc, (ClientData)&lrec);
|
cifMaskHintFunc, (ClientData)&lrec);
|
||||||
|
|
||||||
if (lrec != NULL)
|
if (lrec != NULL)
|
||||||
{
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool propfound;
|
||||||
char *propname;
|
char *propname;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
||||||
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
||||||
|
|
||||||
propstr = (char *)NULL;
|
/* Paint all linked Rects into a mask-hints property plane
|
||||||
|
* in the target cell.
|
||||||
/* Turn all linked Rects into a mask-hints property in the
|
|
||||||
* target cell.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
proprec = DBPropGet(cifReadCellDef, propname, &propfound);
|
||||||
|
if (!propfound)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
|
proprec->prop_len = 0; /* (unused) */
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
DBPropPut(cifReadCellDef, propname, proprec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
plane = proprec->prop_value.prop_plane;
|
||||||
|
|
||||||
while (lrec != NULL)
|
while (lrec != NULL)
|
||||||
{
|
{
|
||||||
char *newstr;
|
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor;
|
||||||
sprintf(locstr, "%d %d %d %d",
|
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor;
|
||||||
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor,
|
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor;
|
||||||
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor,
|
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor;
|
||||||
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor,
|
|
||||||
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor);
|
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
||||||
if (propstr == NULL)
|
(PaintUndoInfo *)NULL);
|
||||||
{
|
|
||||||
newstr = (char *)mallocMagic(strlen(locstr) + 1);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
sprintf(newstr, "%s", locstr);
|
freeMagic1(&mm1, lrec);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newstr = (char *)mallocMagic(strlen(locstr)
|
|
||||||
+ strlen(propstr) + 2);
|
|
||||||
sprintf(newstr, "%s %s", propstr, locstr);
|
|
||||||
freeMagic(propstr);
|
|
||||||
}
|
|
||||||
propstr = newstr;
|
|
||||||
freeMagic(lrec);
|
|
||||||
lrec = lrec->r_next;
|
lrec = lrec->r_next;
|
||||||
}
|
freeMagic1_end(&mm1);
|
||||||
/* NOTE: propstr is transferred to the CellDef and should
|
}
|
||||||
* not be free'd here.
|
|
||||||
*/
|
|
||||||
DBPropPut(cifReadCellDef, propname, propstr);
|
|
||||||
freeMagic(propname);
|
freeMagic(propname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -889,12 +993,14 @@ CIFPaintCurrent(
|
||||||
int
|
int
|
||||||
cifMakeBoundaryFunc(
|
cifMakeBoundaryFunc(
|
||||||
Tile *tile, /* Tile of CIF information. */
|
Tile *tile, /* Tile of CIF information. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
|
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
|
||||||
{
|
{
|
||||||
/* It is assumed that there is one rectangle for the boundary. */
|
/* It is assumed that there is one rectangle for the boundary. */
|
||||||
/* If there are multiple rectangles defined with the boundary */
|
/* If there are multiple rectangles defined with the boundary */
|
||||||
/* layer, then the last one defines the FIXED_BBOX property. */
|
/* layer, then the last one defines the FIXED_BBOX property. */
|
||||||
|
|
||||||
|
PropertyRecord *proprec;
|
||||||
Rect area;
|
Rect area;
|
||||||
char propertyvalue[128], *storedvalue;
|
char propertyvalue[128], *storedvalue;
|
||||||
int savescale;
|
int savescale;
|
||||||
|
|
@ -926,19 +1032,24 @@ cifMakeBoundaryFunc(
|
||||||
|
|
||||||
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
char *propvalue;
|
PropertyRecord *proprec;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
/* Only flag a warning if the redefined boundary was */
|
/* Only flag a warning if the redefined boundary was */
|
||||||
/* different from the original. */
|
/* different from the original. */
|
||||||
|
|
||||||
propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
proprec = DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
(proprec->prop_len == 4))
|
||||||
{
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
|
|
||||||
if ((bbox.r_xbot != area.r_xbot) ||
|
if ((bbox.r_xbot != area.r_xbot) ||
|
||||||
(bbox.r_ybot != area.r_ybot) ||
|
(bbox.r_ybot != area.r_ybot) ||
|
||||||
(bbox.r_xtop != area.r_xtop) ||
|
(bbox.r_xtop != area.r_xtop) ||
|
||||||
|
|
@ -955,10 +1066,15 @@ cifMakeBoundaryFunc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(propertyvalue, "%d %d %d %d",
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + 2 * sizeof(int));
|
||||||
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
|
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||||
storedvalue = StrDup((char **)NULL, propertyvalue);
|
proprec->prop_len = 4;
|
||||||
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
|
proprec->prop_value.prop_integer[0] = area.r_xbot;
|
||||||
|
proprec->prop_value.prop_integer[1] = area.r_ybot;
|
||||||
|
proprec->prop_value.prop_integer[2] = area.r_xtop;
|
||||||
|
proprec->prop_value.prop_integer[3] = area.r_ytop;
|
||||||
|
|
||||||
|
DBPropPut(cifReadCellDef, "FIXED_BBOX", proprec);
|
||||||
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -968,6 +1084,7 @@ cifMakeBoundaryFunc(
|
||||||
int
|
int
|
||||||
cifPaintCurrentFunc(
|
cifPaintCurrentFunc(
|
||||||
Tile *tile, /* Tile of CIF information. */
|
Tile *tile, /* Tile of CIF information. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
TileType type) /* Magic type to be painted. */
|
TileType type) /* Magic type to be painted. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -1017,7 +1134,7 @@ cifPaintCurrentFunc(
|
||||||
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
||||||
if (DBPaintOnPlane(type, pNum))
|
if (DBPaintOnPlane(type, pNum))
|
||||||
{
|
{
|
||||||
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile),
|
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
|
||||||
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1669,8 +1786,8 @@ CIFReadCellCleanup(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do geometrical processing on the top-level cell. */
|
/* Do geometrical processing on the top-level cell. */
|
||||||
|
if (filetype == FILE_CIF) CIFPaintCurrent(filetype);
|
||||||
|
|
||||||
CIFPaintCurrent(FILE_CIF);
|
|
||||||
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
|
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
|
||||||
DBReComputeBbox(EditCellUse->cu_def);
|
DBReComputeBbox(EditCellUse->cu_def);
|
||||||
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
|
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
|
||||||
|
|
|
||||||
|
|
@ -244,40 +244,61 @@ CIFPropRecordPath(
|
||||||
{
|
{
|
||||||
extern float CIFGetOutputScale(int convert);
|
extern float CIFGetOutputScale(int convert);
|
||||||
CIFPath *pathp;
|
CIFPath *pathp;
|
||||||
char *pathstr, *sptr;
|
char *namestr = NULL;
|
||||||
int components;
|
int components, i, x, y, mult, pathnum;
|
||||||
float x, y, oscale, mult;
|
PropertyRecord *proprec;
|
||||||
|
bool propfound;
|
||||||
|
|
||||||
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
/* If "name" is a property, then append a suffix to it to ensure uniqueness */
|
||||||
if (oscale == 0.0) oscale = 1.0;
|
DBPropGet(def, propname, &propfound);
|
||||||
mult = (iswire == TRUE) ? 0.5 : 1.0;
|
if (propfound)
|
||||||
|
{
|
||||||
|
pathnum = 0;
|
||||||
|
namestr = mallocMagic(strlen(propname) + 10);
|
||||||
|
while (propfound)
|
||||||
|
{
|
||||||
|
sprintf(namestr, "%s_%d", propname, pathnum);
|
||||||
|
DBPropGet(def, namestr, &propfound);
|
||||||
|
pathnum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pathp = pathheadp;
|
mult = (iswire == TRUE) ? 1 : 0;
|
||||||
components = 0;
|
|
||||||
|
|
||||||
/* Count the number of components in the path */
|
/* Count the number of components in the path */
|
||||||
|
pathp = pathheadp;
|
||||||
|
components = 0;
|
||||||
while (pathp != NULL)
|
while (pathp != NULL)
|
||||||
{
|
{
|
||||||
pathp = pathp->cifp_next;
|
|
||||||
components++;
|
components++;
|
||||||
|
pathp = pathp->cifp_next;
|
||||||
}
|
}
|
||||||
/* Allocate enough space to hold 2 * N points at "infinity" */
|
/* Allocate enough space to hold 2 * N points. */
|
||||||
pathstr = (char *)mallocMagic(components * 40);
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||||
|
((components - 1) * 2) * sizeof(int));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||||
|
proprec->prop_len = components * 2;
|
||||||
|
|
||||||
pathp = pathheadp;
|
pathp = pathheadp;
|
||||||
sptr = pathstr;
|
i = 0;
|
||||||
while (pathp != NULL)
|
while (pathp != NULL)
|
||||||
{
|
{
|
||||||
x = (float)pathp->cifp_x * oscale * mult;
|
x = pathp->cifp_x >> mult;
|
||||||
y = (float)pathp->cifp_y * oscale * mult;
|
y = pathp->cifp_y >> mult;
|
||||||
sprintf(sptr, "%.3f %.3f ", x, y);
|
|
||||||
sptr = sptr + strlen(sptr);
|
proprec->prop_value.prop_integer[i] = x;
|
||||||
|
proprec->prop_value.prop_integer[i + 1] = y;
|
||||||
|
|
||||||
|
i += 2;
|
||||||
pathp = pathp->cifp_next;
|
pathp = pathp->cifp_next;
|
||||||
}
|
}
|
||||||
|
if (namestr)
|
||||||
/* Reallocate pathstr to be no larger than needed to hold the path contents */
|
{
|
||||||
StrDup(&pathstr, pathstr);
|
DBPropPut(def, namestr, proprec);
|
||||||
DBPropPut(def, propname, (ClientData)pathstr);
|
freeMagic(namestr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DBPropPut(def, propname, proprec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -338,18 +359,20 @@ CIFPaintWirePath(
|
||||||
pathp = pathheadp->cifp_next;
|
pathp = pathheadp->cifp_next;
|
||||||
if (pathp != NULL)
|
if (pathp != NULL)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (pathp->cifp_next != NULL)
|
while (pathp->cifp_next != NULL)
|
||||||
{
|
{
|
||||||
if (pathp->cifp_next->cifp_x == pathp->cifp_x &&
|
if (pathp->cifp_next->cifp_x == pathp->cifp_x &&
|
||||||
pathp->cifp_next->cifp_y == pathp->cifp_y)
|
pathp->cifp_next->cifp_y == pathp->cifp_y)
|
||||||
{
|
{
|
||||||
previousp->cifp_next = pathp->cifp_next;
|
previousp->cifp_next = pathp->cifp_next;
|
||||||
freeMagic(pathp);
|
freeMagic1(&mm1, pathp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
previousp = pathp;
|
previousp = pathp;
|
||||||
pathp = pathp->cifp_next;
|
pathp = pathp->cifp_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
previousp = pathheadp;
|
previousp = pathheadp;
|
||||||
|
|
@ -439,7 +462,8 @@ CIFPaintWirePath(
|
||||||
/* Wire reverses direction. Break wire here, */
|
/* Wire reverses direction. Break wire here, */
|
||||||
/* draw, and start new polygon. */
|
/* draw, and start new polygon. */
|
||||||
|
|
||||||
TxError("Warning: direction reversal in path.\n");
|
TxError("Warning: direction reversal in path at (%d, %d).\n",
|
||||||
|
pathp->cifp_x, pathp->cifp_y);
|
||||||
|
|
||||||
phi = theta;
|
phi = theta;
|
||||||
if (endcap)
|
if (endcap)
|
||||||
|
|
@ -451,7 +475,8 @@ CIFPaintWirePath(
|
||||||
firstpoint = TRUE;
|
firstpoint = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TxError("Error: mitre limit exceeded at wire junction.\n");
|
TxError("Error: mitre limit exceeded at wire junction at (%d, %d).\n",
|
||||||
|
pathp->cifp_x, pathp->cifp_y);
|
||||||
TxError("Route has been truncated.\n");
|
TxError("Route has been truncated.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -484,11 +509,13 @@ CIFPaintWirePath(
|
||||||
rectp = CIFPolyToRects(polypath, plane, ptable, ui, FALSE);
|
rectp = CIFPolyToRects(polypath, plane, ptable, ui, FALSE);
|
||||||
CIFFreePath(polypath);
|
CIFFreePath(polypath);
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (; rectp != NULL ; rectp = rectp->r_next)
|
for (; rectp != NULL ; rectp = rectp->r_next)
|
||||||
{
|
{
|
||||||
DBPaintPlane(plane, &rectp->r_r, ptable, ui);
|
DBPaintPlane(plane, &rectp->r_r, ptable, ui);
|
||||||
freeMagic((char *) rectp);
|
freeMagic1(&mm1, (char *) rectp);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
polypath = NULL;
|
polypath = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -586,11 +613,13 @@ PaintPolygon(
|
||||||
rectlist = CIFPolyToRects(cifpath, plane, ptable, ui, FALSE);
|
rectlist = CIFPolyToRects(cifpath, plane, ptable, ui, FALSE);
|
||||||
CIFFreePath(cifpath);
|
CIFFreePath(cifpath);
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next)
|
for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next)
|
||||||
{
|
{
|
||||||
DBPaintPlane(plane, &rectp->r_r, ptable, ui);
|
DBPaintPlane(plane, &rectp->r_r, ptable, ui);
|
||||||
if (!keep) freeMagic((char *) rectp);
|
if (!keep) freeMagic1(&mm1, (char *) rectp);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
return (keep) ? rectlist : (LinkedRect *)NULL;
|
return (keep) ? rectlist : (LinkedRect *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -819,11 +848,13 @@ CIFParsePoly(void)
|
||||||
CIFSkipToSemi();
|
CIFSkipToSemi();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (; rectp != NULL ; rectp = rectp->r_next)
|
for (; rectp != NULL ; rectp = rectp->r_next)
|
||||||
{
|
{
|
||||||
DBPaintPlane(cifReadPlane, &rectp->r_r, CIFPaintTable,
|
DBPaintPlane(cifReadPlane, &rectp->r_r, CIFPaintTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
freeMagic((char *) rectp);
|
freeMagic1(&mm1, (char *) rectp);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -324,13 +324,20 @@ cifNewReadStyle(void)
|
||||||
{
|
{
|
||||||
/* Destroy old style and free all memory allocated to it */
|
/* Destroy old style and free all memory allocated to it */
|
||||||
|
|
||||||
for (i=0; i<MAXCIFRLAYERS; i+=1)
|
for (i = 0; i < MAXCIFRLAYERS; i++)
|
||||||
{
|
{
|
||||||
layer = cifCurReadStyle->crs_layers[i];
|
layer = cifCurReadStyle->crs_layers[i];
|
||||||
if (layer != NULL)
|
if (layer != NULL)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (op = layer->crl_ops; op != NULL; op = op->co_next)
|
for (op = layer->crl_ops; op != NULL; op = op->co_next)
|
||||||
freeMagic((char *)op);
|
{
|
||||||
|
if (op->co_opcode == CIFOP_MASKHINTS ||
|
||||||
|
op->co_opcode == CIFOP_TAGGED)
|
||||||
|
freeMagic((char *)op->co_client);
|
||||||
|
freeMagic1(&mm1, (char *)op);
|
||||||
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
freeMagic((char *)layer);
|
freeMagic((char *)layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -408,11 +415,13 @@ CIFReadTechInit(void)
|
||||||
|
|
||||||
/* forget the list of styles */
|
/* forget the list of styles */
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (style = cifReadStyleList; style != NULL; style = style->crs_next)
|
for (style = cifReadStyleList; style != NULL; style = style->crs_next)
|
||||||
{
|
{
|
||||||
freeMagic(style->crs_name);
|
freeMagic(style->crs_name);
|
||||||
freeMagic(style);
|
freeMagic1(&mm1, style);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
cifReadStyleList = NULL;
|
cifReadStyleList = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -986,6 +995,12 @@ CIFReadTechLine(
|
||||||
newOp->co_opcode = CIFOP_COPYUP;
|
newOp->co_opcode = CIFOP_COPYUP;
|
||||||
else if (strcmp(argv[0], "boundary") == 0)
|
else if (strcmp(argv[0], "boundary") == 0)
|
||||||
newOp->co_opcode = CIFOP_BOUNDARY;
|
newOp->co_opcode = CIFOP_BOUNDARY;
|
||||||
|
else if (strcmp(argv[0], "not-square") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_NOTSQUARE;
|
||||||
|
else if (strcmp(argv[0], "mask-hints") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_MASKHINTS;
|
||||||
|
else if (strcmp(argv[0], "tagged") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_TAGGED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TechError("Unknown statement \"%s\".\n", argv[0]);
|
TechError("Unknown statement \"%s\".\n", argv[0]);
|
||||||
|
|
@ -1012,6 +1027,15 @@ CIFReadTechLine(
|
||||||
goto errorReturn;
|
goto errorReturn;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CIFOP_MASKHINTS:
|
||||||
|
if (argc != 2) goto wrongNumArgs;
|
||||||
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
|
break;
|
||||||
|
case CIFOP_TAGGED:
|
||||||
|
if (argc != 3) goto wrongNumArgs;
|
||||||
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
|
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link the new CIFOp onto the list. */
|
/* Link the new CIFOp onto the list. */
|
||||||
|
|
@ -1095,6 +1119,7 @@ CIFReadTechFinal(void)
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
CIFReadLoadStyle(
|
CIFReadLoadStyle(
|
||||||
char *stylename)
|
char *stylename)
|
||||||
|
|
|
||||||
|
|
@ -1338,11 +1338,13 @@ void
|
||||||
CIFFreePath(
|
CIFFreePath(
|
||||||
CIFPath *path) /* Path to be freed. */
|
CIFPath *path) /* Path to be freed. */
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (path != NULL)
|
while (path != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *) path);
|
freeMagic1(&mm1, (char *) path);
|
||||||
path = path->cifp_next;
|
path = path->cifp_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
33
cif/CIFsee.c
33
cif/CIFsee.c
|
|
@ -78,6 +78,7 @@ typedef struct {
|
||||||
int
|
int
|
||||||
cifPaintDBFunc(
|
cifPaintDBFunc(
|
||||||
Tile *tile, /* Tile of CIF information. */
|
Tile *tile, /* Tile of CIF information. */
|
||||||
|
TileType dinfo,
|
||||||
PaintLayerData *pld)
|
PaintLayerData *pld)
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -106,7 +107,7 @@ cifPaintDBFunc(
|
||||||
if (DBPaintOnPlane(type, pNum))
|
if (DBPaintOnPlane(type, pNum))
|
||||||
{
|
{
|
||||||
ui.pu_pNum = pNum;
|
ui.pu_pNum = pNum;
|
||||||
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
|
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
|
||||||
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
|
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,9 +166,9 @@ CIFPaintLayer(
|
||||||
scx.scx_use = CIFDummyUse;
|
scx.scx_use = CIFDummyUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
oldCount = DBWFeedbackCount;
|
oldCount = DBWFeedbackCount;
|
||||||
|
|
@ -219,6 +220,7 @@ CIFPaintLayer(
|
||||||
int
|
int
|
||||||
cifSeeFunc(
|
cifSeeFunc(
|
||||||
Tile *tile, /* Tile to be entered as feedback. */
|
Tile *tile, /* Tile to be entered as feedback. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
SeeLayerData *sld) /* Layer and explanation for the feedback. */
|
SeeLayerData *sld) /* Layer and explanation for the feedback. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -233,10 +235,10 @@ cifSeeFunc(
|
||||||
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
|
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
|
||||||
DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
|
DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
|
||||||
sld->style |
|
sld->style | ((TiGetTypeExact(tile) | dinfo) &
|
||||||
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||||
/* (preserve information about the geometry of a diagonal tile) */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,9 +287,9 @@ CIFSeeLayer(
|
||||||
scx.scx_use = CIFDummyUse;
|
scx.scx_use = CIFDummyUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
oldCount = DBWFeedbackCount;
|
oldCount = DBWFeedbackCount;
|
||||||
|
|
@ -438,9 +440,11 @@ CIFCoverageLayer(
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
TileTypeBitMask mask, depend;
|
TileTypeBitMask mask, depend;
|
||||||
float fcover;
|
float fcover;
|
||||||
int cifCoverageFunc(Tile *tile, ClientData *arg);
|
|
||||||
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
|
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int cifCoverageFunc(Tile *tile, TileType dinfo, ClientData *arg);
|
||||||
|
|
||||||
/* Check out the CIF layer name. */
|
/* Check out the CIF layer name. */
|
||||||
|
|
||||||
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
||||||
|
|
@ -455,9 +459,9 @@ CIFCoverageLayer(
|
||||||
scx.scx_use = CIFDummyUse;
|
scx.scx_use = CIFDummyUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
||||||
|
|
@ -500,10 +504,10 @@ CIFCoverageLayer(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
|
TxPrintf("%s Area = %"DLONG_PREFIX"d CIF units^2\n", doBox ? "Cursor Box" :
|
||||||
"Cell", btotal);
|
"Cell", btotal);
|
||||||
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
|
TxPrintf("Layer Bounding Area = %"DLONG_PREFIX"d CIF units^2\n", atotal);
|
||||||
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
|
TxPrintf("Layer Total Area = %"DLONG_PREFIX"d CIF units^2\n", cstats.coverage);
|
||||||
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
||||||
"cell", 100.0 * fcover);
|
"cell", 100.0 * fcover);
|
||||||
}
|
}
|
||||||
|
|
@ -512,6 +516,7 @@ CIFCoverageLayer(
|
||||||
int
|
int
|
||||||
cifCoverageFunc(
|
cifCoverageFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
ClientData *arg)
|
ClientData *arg)
|
||||||
{
|
{
|
||||||
coverstats *cstats = (coverstats *)arg;
|
coverstats *cstats = (coverstats *)arg;
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ cifTechFreeStyle(void)
|
||||||
layer = CIFCurStyle->cs_layers[i];
|
layer = CIFCurStyle->cs_layers[i];
|
||||||
if (layer != NULL)
|
if (layer != NULL)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
||||||
{
|
{
|
||||||
if (op->co_client != (ClientData)NULL)
|
if (op->co_client != (ClientData)NULL)
|
||||||
|
|
@ -120,8 +121,9 @@ cifTechFreeStyle(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
freeMagic((char *)op);
|
freeMagic1(&mm1, (char *)op);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
freeMagic((char *)layer);
|
freeMagic((char *)layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +236,7 @@ cifParseLayers(
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
TileTypeBitMask curCifMask, curPaintMask;
|
TileTypeBitMask curCifMask, curPaintMask;
|
||||||
char curLayer[40], *p, *cp;
|
char curLayer[512], *p, *cp;
|
||||||
TileType paintType;
|
TileType paintType;
|
||||||
int i;
|
int i;
|
||||||
bool allResidues;
|
bool allResidues;
|
||||||
|
|
@ -246,6 +248,10 @@ cifParseLayers(
|
||||||
{
|
{
|
||||||
p = curLayer;
|
p = curLayer;
|
||||||
|
|
||||||
|
if (*string == '(')
|
||||||
|
while ((*string != ')') && (*string != 0))
|
||||||
|
*p++ = *string++;
|
||||||
|
|
||||||
if (*string == '*')
|
if (*string == '*')
|
||||||
{
|
{
|
||||||
allResidues = TRUE;
|
allResidues = TRUE;
|
||||||
|
|
@ -263,7 +269,22 @@ cifParseLayers(
|
||||||
|
|
||||||
if (paintMask != NULL)
|
if (paintMask != NULL)
|
||||||
{
|
{
|
||||||
paintType = DBTechNameTypes(curLayer, &curPaintMask);
|
if (*curLayer == '(')
|
||||||
|
{
|
||||||
|
TileType t;
|
||||||
|
|
||||||
|
/* Layer groups with parentheses can only be paint types,
|
||||||
|
* and will be parsed accordingly. Residues will be
|
||||||
|
* handled within the group. Set paintType to -3, which
|
||||||
|
* is flagged and handled below.
|
||||||
|
*/
|
||||||
|
DBTechNoisyNameMask(curLayer, &curPaintMask);
|
||||||
|
paintType = -3;
|
||||||
|
allResidues = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
paintType = DBTechNameTypes(curLayer, &curPaintMask);
|
||||||
|
|
||||||
if (paintType >= 0) goto okpaint;
|
if (paintType >= 0) goto okpaint;
|
||||||
}
|
}
|
||||||
else paintType = -2;
|
else paintType = -2;
|
||||||
|
|
@ -299,7 +320,7 @@ okpaint:
|
||||||
TechError("Ambiguous layer (type) \"%s\".\n", curLayer);
|
TechError("Ambiguous layer (type) \"%s\".\n", curLayer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (paintType >= 0)
|
if ((paintType >= 0) || (paintType == -3))
|
||||||
{
|
{
|
||||||
if (paintType == TT_SPACE && spaceOK ==0)
|
if (paintType == TT_SPACE && spaceOK ==0)
|
||||||
TechError("\"Space\" layer not permitted in CIF rules.\n");
|
TechError("\"Space\" layer not permitted in CIF rules.\n");
|
||||||
|
|
@ -369,11 +390,13 @@ CIFTechInit(void)
|
||||||
|
|
||||||
/* forget the list of styles */
|
/* forget the list of styles */
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (style = CIFStyleList; style != NULL; style = style->cs_next)
|
for (style = CIFStyleList; style != NULL; style = style->cs_next)
|
||||||
{
|
{
|
||||||
freeMagic(style->cs_name);
|
freeMagic(style->cs_name);
|
||||||
freeMagic(style);
|
freeMagic1(&mm1, style);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
CIFStyleList = NULL;
|
CIFStyleList = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -794,7 +817,7 @@ CIFTechLine(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
|
l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
|
||||||
if (!strcmp(tptr, CIFCurStyle->cs_name + l))
|
if ((l > 0) && !strcmp(tptr, CIFCurStyle->cs_name + l))
|
||||||
{
|
{
|
||||||
CIFCurStyle->cs_status = TECH_PENDING;
|
CIFCurStyle->cs_status = TECH_PENDING;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -1084,6 +1107,8 @@ CIFTechLine(
|
||||||
newOp->co_opcode = CIFOP_BBOX;
|
newOp->co_opcode = CIFOP_BBOX;
|
||||||
else if (strcmp(argv[0], "net") == 0)
|
else if (strcmp(argv[0], "net") == 0)
|
||||||
newOp->co_opcode = CIFOP_NET;
|
newOp->co_opcode = CIFOP_NET;
|
||||||
|
else if (strcmp(argv[0], "tagged") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_TAGGED;
|
||||||
else if (strcmp(argv[0], "maxrect") == 0)
|
else if (strcmp(argv[0], "maxrect") == 0)
|
||||||
newOp->co_opcode = CIFOP_MAXRECT;
|
newOp->co_opcode = CIFOP_MAXRECT;
|
||||||
else if (strcmp(argv[0], "boundary") == 0)
|
else if (strcmp(argv[0], "boundary") == 0)
|
||||||
|
|
@ -1094,6 +1119,8 @@ CIFTechLine(
|
||||||
newOp->co_opcode = CIFOP_CLOSE;
|
newOp->co_opcode = CIFOP_CLOSE;
|
||||||
else if (strcmp(argv[0], "orthogonal") == 0)
|
else if (strcmp(argv[0], "orthogonal") == 0)
|
||||||
newOp->co_opcode = CIFOP_MANHATTAN;
|
newOp->co_opcode = CIFOP_MANHATTAN;
|
||||||
|
else if (strcmp(argv[0], "not-square") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_NOTSQUARE;
|
||||||
else if (strcmp(argv[0], "bridge") == 0)
|
else if (strcmp(argv[0], "bridge") == 0)
|
||||||
newOp->co_opcode = CIFOP_BRIDGE;
|
newOp->co_opcode = CIFOP_BRIDGE;
|
||||||
else if (strcmp(argv[0], "bridge-lim") == 0)
|
else if (strcmp(argv[0], "bridge-lim") == 0)
|
||||||
|
|
@ -1332,6 +1359,7 @@ bloatCheck:
|
||||||
bloatDone: break;
|
bloatDone: break;
|
||||||
|
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
|
case CIFOP_TAGGED:
|
||||||
if (argc != 3) goto wrongNumArgs;
|
if (argc != 3) goto wrongNumArgs;
|
||||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
||||||
|
|
@ -1646,12 +1674,12 @@ cifComputeRadii(
|
||||||
|
|
||||||
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
||||||
{
|
{
|
||||||
/* BBOX, NET, and MASKHINTS operators should never be used */
|
/* BBOX, NET, TAGGED, and MASKHINTS operators should never be */
|
||||||
/* hierarchically so ignore any grow/shrink operators that */
|
/* used hierarchically so ignore any grow/shrink operators that */
|
||||||
/* come after them. */
|
/* come after them. */
|
||||||
|
|
||||||
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
||||||
op->co_opcode == CIFOP_MASKHINTS)
|
op->co_opcode == CIFOP_TAGGED || op->co_opcode == CIFOP_MASKHINTS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* If CIF layers are used, switch to the max of current
|
/* If CIF layers are used, switch to the max of current
|
||||||
|
|
@ -1758,7 +1786,8 @@ cifComputeHalo(
|
||||||
if (maxGrow > maxShrink)
|
if (maxGrow > maxShrink)
|
||||||
style->cs_radius = 2*maxGrow;
|
style->cs_radius = 2*maxGrow;
|
||||||
else style->cs_radius = 2*maxShrink;
|
else style->cs_radius = 2*maxShrink;
|
||||||
style->cs_radius /= style->cs_scaleFactor;
|
if (style->cs_scaleFactor > 0)
|
||||||
|
style->cs_radius /= style->cs_scaleFactor;
|
||||||
style->cs_radius++;
|
style->cs_radius++;
|
||||||
|
|
||||||
/* TxPrintf("Radius for %s CIF is %d.\n",
|
/* TxPrintf("Radius for %s CIF is %d.\n",
|
||||||
|
|
@ -1962,8 +1991,8 @@ CIFTechFinal(void)
|
||||||
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
||||||
/* of the SquaresData pointer from a following operator. */
|
/* of the SquaresData pointer from a following operator. */
|
||||||
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
||||||
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
|
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */
|
||||||
/* uses it for a string. */
|
/* CIFOP_TAGGED use it for a string. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (op->co_opcode)
|
switch (op->co_opcode)
|
||||||
|
|
@ -1975,6 +2004,7 @@ CIFTechFinal(void)
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
case CIFOP_MANHATTAN:
|
case CIFOP_MANHATTAN:
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
|
case CIFOP_TAGGED:
|
||||||
break;
|
break;
|
||||||
case CIFOP_BRIDGELIM:
|
case CIFOP_BRIDGELIM:
|
||||||
case CIFOP_BRIDGE:
|
case CIFOP_BRIDGE:
|
||||||
|
|
@ -2510,6 +2540,7 @@ CIFTechOutputScale(
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
case CIFOP_MANHATTAN:
|
case CIFOP_MANHATTAN:
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
|
case CIFOP_TAGGED:
|
||||||
case CIFOP_INTERACT:
|
case CIFOP_INTERACT:
|
||||||
break;
|
break;
|
||||||
case CIFOP_BRIDGELIM:
|
case CIFOP_BRIDGELIM:
|
||||||
|
|
@ -2625,8 +2656,8 @@ CIFTechOutputScale(
|
||||||
default:
|
default:
|
||||||
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
||||||
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
||||||
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
|
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */
|
||||||
/* string. */
|
/* CIFOP_TAGGED is a string. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
extern int cifWriteInitFunc(CellDef *def);
|
extern int cifWriteInitFunc(CellDef *def);
|
||||||
extern int cifWriteMarkFunc(CellUse *use);
|
extern int cifWriteMarkFunc(CellUse *use);
|
||||||
extern int cifWritePaintFunc(Tile *tile, FILE *f);
|
extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f);
|
||||||
extern int cifWriteLabelFunc(Tile *tile, FILE *f);
|
extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f);
|
||||||
extern int cifWriteUseFunc(CellUse *use, FILE *f);
|
extern int cifWriteUseFunc(CellUse *use, FILE *f);
|
||||||
extern void cifOutPreamble(FILE *outf, CellDef *cell);
|
extern void cifOutPreamble(FILE *outf, CellDef *cell);
|
||||||
extern void cifOut(FILE *outf);
|
extern void cifOut(FILE *outf);
|
||||||
|
|
@ -584,6 +584,7 @@ cifWriteUseFunc(
|
||||||
int
|
int
|
||||||
cifWriteLabelFunc(
|
cifWriteLabelFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
FILE *f) /* File in which to write. */
|
FILE *f) /* File in which to write. */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -643,7 +644,8 @@ cifWriteLabelFunc(
|
||||||
int
|
int
|
||||||
cifWritePaintFunc(
|
cifWritePaintFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
FILE *f) /* File in which to write. */
|
TileType dinfo, /* Split tile information */
|
||||||
|
FILE *f) /* File in which to write. */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
||||||
|
|
@ -662,7 +664,7 @@ cifWritePaintFunc(
|
||||||
Point points[5];
|
Point points[5];
|
||||||
int i, np;
|
int i, np;
|
||||||
|
|
||||||
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile), points, &np);
|
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile) | dinfo, points, &np);
|
||||||
|
|
||||||
/* Write triangle as a CIF polygon */
|
/* Write triangle as a CIF polygon */
|
||||||
|
|
||||||
|
|
|
||||||
226
commands/CmdAB.c
226
commands/CmdAB.c
|
|
@ -81,6 +81,70 @@ CmdAddPath(
|
||||||
PaAppend(&Path, cmd->tx_argv[1]);
|
PaAppend(&Path, cmd->tx_argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* CmdArchive --
|
||||||
|
*
|
||||||
|
* Save an entire database to a "crash recovery"-type archive file, or
|
||||||
|
* load a database from a "crash recovery"-type archive file. Option
|
||||||
|
* "writeall" writes everything, including read-only PDK cells, while
|
||||||
|
* "readref" does not dereference and will prefer files found in the
|
||||||
|
* search path over content in the archive.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* archive write|writeall|read|readref file
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Writes a single file with the contents of the entire database,
|
||||||
|
* or loads the database with multiple cells from the file.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
CmdArchive(
|
||||||
|
MagWindow *w,
|
||||||
|
TxCommand *cmd)
|
||||||
|
{
|
||||||
|
int option = -1;
|
||||||
|
char *filename = NULL;
|
||||||
|
static const char * const cmdArchiveOpt[] = {"write", "writeall",
|
||||||
|
"read", "readref", 0};
|
||||||
|
|
||||||
|
if (cmd->tx_argc != 3)
|
||||||
|
TxError("Usage: %s write|writeall|read|readref filename\n", cmd->tx_argv[0]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
option = Lookup(cmd->tx_argv[1], cmdArchiveOpt);
|
||||||
|
if (option < 0)
|
||||||
|
{
|
||||||
|
TxError("Usage: %s write|writeall|read|readref filename\n", cmd->tx_argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filename = cmd->tx_argv[2];
|
||||||
|
|
||||||
|
switch(option) {
|
||||||
|
case 0: /* write */
|
||||||
|
DBWriteBackup(filename, TRUE, FALSE);
|
||||||
|
break;
|
||||||
|
case 1: /* writeall */
|
||||||
|
DBWriteBackup(filename, TRUE, TRUE);
|
||||||
|
break;
|
||||||
|
case 2: /* read */
|
||||||
|
DBReadBackup(filename, TRUE, TRUE);
|
||||||
|
break;
|
||||||
|
case 3: /* readref */
|
||||||
|
DBReadBackup(filename, TRUE, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Linked-list structure for returning information about arrayed cells */
|
/* Linked-list structure for returning information about arrayed cells */
|
||||||
|
|
||||||
|
|
@ -274,14 +338,17 @@ CmdArray(
|
||||||
case ARRAY_WIDTH:
|
case ARRAY_WIDTH:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *xsepvalue;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
xsepvalue = DBWPrintValue(la->arrayInfo.ar_xsep,
|
||||||
|
w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
Tcl_NewStringObj(xsepvalue, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -291,7 +358,7 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
|
TxPrintf("x separation %s\n", xsepvalue);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -310,14 +377,17 @@ CmdArray(
|
||||||
case ARRAY_HEIGHT:
|
case ARRAY_HEIGHT:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *ysepvalue;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
ysepvalue = DBWPrintValue(la->arrayInfo.ar_ysep,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
Tcl_NewStringObj(ysepvalue, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -327,7 +397,7 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
TxPrintf("y separation %s\n", ysepvalue);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -346,16 +416,21 @@ CmdArray(
|
||||||
case ARRAY_PITCH:
|
case ARRAY_PITCH:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *xpitch, *ypitch;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
xpitch = DBWPrintValue(la->arrayInfo.ar_xsep,
|
||||||
|
w, TRUE);
|
||||||
|
ypitch = DBWPrintValue(la->arrayInfo.ar_ysep,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
Tcl_NewStringObj(xpitch, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
Tcl_NewStringObj(ypitch, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -365,8 +440,8 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
|
TxPrintf("x separation %s ", xpitch);
|
||||||
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
TxPrintf("y separation %s\n", ypitch);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -386,16 +461,21 @@ CmdArray(
|
||||||
case ARRAY_POSITION:
|
case ARRAY_POSITION:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *xpos, *ypos;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
xpos = DBWPrintValue(la->cellUse->cu_bbox.r_xbot,
|
||||||
|
w, TRUE);
|
||||||
|
ypos = DBWPrintValue(la->cellUse->cu_bbox.r_ybot,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
|
Tcl_NewStringObj(xpos, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
|
Tcl_NewStringObj(ypos, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -405,8 +485,8 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
|
TxPrintf("x=%s ", xpos);
|
||||||
TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
|
TxPrintf("y=%s\n", ypos);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -466,11 +546,15 @@ badusage:
|
||||||
}
|
}
|
||||||
|
|
||||||
freelist:
|
freelist:
|
||||||
la = lahead;
|
|
||||||
while (la != NULL)
|
|
||||||
{
|
{
|
||||||
freeMagic((char *)la);
|
la = lahead;
|
||||||
la = la->ar_next;
|
while (la != NULL)
|
||||||
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, (char *)la);
|
||||||
|
la = la->ar_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -695,8 +779,8 @@ CmdBox(
|
||||||
break;
|
break;
|
||||||
case BOX_EXISTS:
|
case BOX_EXISTS:
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0",
|
Tcl_SetObjResult(magicinterp,
|
||||||
NULL);
|
Tcl_NewBooleanObj(ToolGetBox(NULL, NULL) ? TRUE : FALSE));
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -806,13 +890,16 @@ CmdBox(
|
||||||
TxRebuildCommand(cmd);
|
TxRebuildCommand(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (DBWSnapToGrid != DBW_SNAP_USER)
|
else if (DBWUnits != DBW_UNITS_USER)
|
||||||
{
|
{
|
||||||
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
||||||
distancey = distancex;
|
distancey = distancex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* For user units, the distance may be different in the X and Y
|
||||||
|
* directions for a given value.
|
||||||
|
*/
|
||||||
switch (direction)
|
switch (direction)
|
||||||
{
|
{
|
||||||
case GEO_EAST: case GEO_WEST:
|
case GEO_EAST: case GEO_WEST:
|
||||||
|
|
@ -840,15 +927,14 @@ CmdBox(
|
||||||
case BOX_WIDTH:
|
case BOX_WIDTH:
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *boxvalues;
|
||||||
|
boxvalues = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
|
||||||
|
w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
|
||||||
sprintf(boxvalues, "%d",
|
|
||||||
boxptr->r_xtop - boxptr->r_xbot);
|
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box width is %d\n",
|
TxPrintf("%s box width is %s\n", (refEdit) ? "Edit" : "Root",
|
||||||
(refEdit) ? "Edit" : "Root",
|
boxvalues);
|
||||||
boxptr->r_xtop - boxptr->r_xbot);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -860,15 +946,14 @@ CmdBox(
|
||||||
case BOX_HEIGHT:
|
case BOX_HEIGHT:
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *boxvalues;
|
||||||
|
boxvalues = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
|
||||||
sprintf(boxvalues, "%d",
|
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box height is %d\n",
|
TxPrintf("%s box height is %s\n", (refEdit) ? "Edit" : "Root",
|
||||||
(refEdit) ? "Edit" : "Root",
|
boxvalues);
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -881,16 +966,24 @@ CmdBox(
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_Obj *tobj;
|
||||||
sprintf(boxvalues, "%d %d",
|
#endif
|
||||||
boxptr->r_xtop - boxptr->r_xbot,
|
char *boxvaluex, *boxvaluey;
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
boxvaluex = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
w, TRUE);
|
||||||
|
boxvaluey = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
|
||||||
|
w, FALSE);
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluex, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluey, -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box size is %d x %d\n",
|
TxPrintf("%s box size is %s x %s\n",
|
||||||
(refEdit) ? "Edit" : "Root",
|
(refEdit) ? "Edit" : "Root",
|
||||||
boxptr->r_xtop - boxptr->r_xbot,
|
boxvaluex, boxvaluey);
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -905,14 +998,22 @@ CmdBox(
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_Obj *tobj;
|
||||||
sprintf(boxvalues, "%d %d",
|
#endif
|
||||||
boxptr->r_xbot, boxptr->r_ybot);
|
char *boxvaluex, *boxvaluey;
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
boxvaluex = DBWPrintValue(boxptr->r_xbot, w, TRUE);
|
||||||
|
boxvaluey = DBWPrintValue(boxptr->r_ybot, w, FALSE);
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluex, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluey, -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box lower-left corner at (%d, %d)\n",
|
TxPrintf("%s box lower-left corner at (%s, %s)\n",
|
||||||
(refEdit) ? "Edit" : "Root",
|
(refEdit) ? "Edit" : "Root",
|
||||||
boxptr->r_xbot, boxptr->r_ybot);
|
boxvaluex, boxvaluey);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -944,16 +1045,31 @@ CmdBox(
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_Obj *tobj;
|
||||||
sprintf(boxvalues, "%d %d %d %d",
|
#endif
|
||||||
boxptr->r_xbot, boxptr->r_ybot,
|
char *boxvaluellx, *boxvaluelly;
|
||||||
boxptr->r_xtop, boxptr->r_ytop);
|
char *boxvalueurx, *boxvalueury;
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
||||||
|
boxvaluellx = DBWPrintValue(boxptr->r_xbot, w, TRUE);
|
||||||
|
boxvaluelly = DBWPrintValue(boxptr->r_ybot, w, FALSE);
|
||||||
|
boxvalueurx = DBWPrintValue(boxptr->r_xtop, w, TRUE);
|
||||||
|
boxvalueury = DBWPrintValue(boxptr->r_ytop, w, FALSE);
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluellx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluelly, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvalueurx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvalueury, -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
|
TxPrintf("%s box coordinates (%s, %s) to (%s, %s)\n",
|
||||||
(refEdit) ? "Edit" : "Root",
|
(refEdit) ? "Edit" : "Root",
|
||||||
boxptr->r_xbot, boxptr->r_ybot,
|
boxvaluellx, boxvaluelly, boxvalueurx, boxvalueury);
|
||||||
boxptr->r_xtop, boxptr->r_ytop);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
152
commands/CmdCD.c
152
commands/CmdCD.c
|
|
@ -117,12 +117,13 @@ bool cmdDumpParseArgs(char *cmdName, MagWindow *w, TxCommand *cmd, CellUse *dumm
|
||||||
#define CALMA_READ 19
|
#define CALMA_READ 19
|
||||||
#define CALMA_READONLY 20
|
#define CALMA_READONLY 20
|
||||||
#define CALMA_RESCALE 21
|
#define CALMA_RESCALE 21
|
||||||
#define CALMA_WARNING 22
|
#define CALMA_SAVEPATHS 22
|
||||||
#define CALMA_WRITE 23
|
#define CALMA_WARNING 23
|
||||||
#define CALMA_POLYS 24
|
#define CALMA_WRITE 24
|
||||||
#define CALMA_PATHS 25
|
#define CALMA_POLYS 25
|
||||||
#define CALMA_UNDEFINED 26
|
#define CALMA_PATHS 26
|
||||||
#define CALMA_UNIQUE 27
|
#define CALMA_UNDEFINED 27
|
||||||
|
#define CALMA_UNIQUE 28
|
||||||
|
|
||||||
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
||||||
|
|
||||||
|
|
@ -175,6 +176,7 @@ CmdCalma(
|
||||||
" into edit cell",
|
" into edit cell",
|
||||||
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
||||||
"rescale [yes|no] allow or disallow internal grid subdivision",
|
"rescale [yes|no] allow or disallow internal grid subdivision",
|
||||||
|
"savepaths [yes|no] save path centerlines as cell properties",
|
||||||
"warning [option] set warning information level",
|
"warning [option] set warning information level",
|
||||||
"write file output Calma GDS-II format to \"file\"\n"
|
"write file output Calma GDS-II format to \"file\"\n"
|
||||||
" for the window's root cell",
|
" for the window's root cell",
|
||||||
|
|
@ -431,7 +433,7 @@ CmdCalma(
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)CalmaMagScale));
|
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)CalmaMagScale));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Text magnification 1.0 = %g microns.\n");
|
TxPrintf("Text magnification 1.0 = %g microns.\n", (double)CalmaMagScale);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -738,13 +740,34 @@ CmdCalma(
|
||||||
CalmaSubcellPolygons = (unsigned char)option;
|
CalmaSubcellPolygons = (unsigned char)option;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case CALMA_SAVEPATHS:
|
||||||
|
if (cmd->tx_argc == 2)
|
||||||
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaRecordPaths));
|
||||||
|
#else
|
||||||
|
TxPrintf("Paths in GDS cells read from input file are%s recorded"
|
||||||
|
" as cell properties.\n",
|
||||||
|
(CalmaRecordPaths) ? " " : " not");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cmd->tx_argc != 3)
|
||||||
|
goto wrongNumArgs;
|
||||||
|
|
||||||
|
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
|
||||||
|
if (option < 0)
|
||||||
|
goto wrongNumArgs;
|
||||||
|
CalmaRecordPaths = (option < 4) ? FALSE : TRUE;
|
||||||
|
return;
|
||||||
|
|
||||||
case CALMA_NO_DUP:
|
case CALMA_NO_DUP:
|
||||||
if (cmd->tx_argc == 2)
|
if (cmd->tx_argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaNoDuplicates));
|
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaNoDuplicates));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Cell defs that exist before reading GDS will not be paresd.\n",
|
TxPrintf("Cell defs that exist before reading GDS will %sbe parsed.\n",
|
||||||
(CalmaNoDuplicates) ? "not " : "");
|
(CalmaNoDuplicates) ? "not " : "");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
@ -764,7 +787,7 @@ CmdCalma(
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaUnique));
|
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaUnique));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Cell defs that exist before reading GDS will be renamed.\n",
|
TxPrintf("Cell defs that exist before reading GDS will %sbe renamed.\n",
|
||||||
(CalmaUnique) ? "not " : "");
|
(CalmaUnique) ? "not " : "");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
@ -1300,7 +1323,7 @@ CmdCellname(
|
||||||
if (cellDef == (CellDef *) NULL)
|
if (cellDef == (CellDef *) NULL)
|
||||||
TxError("Unknown cell %s\n", cellname);
|
TxError("Unknown cell %s\n", cellname);
|
||||||
else
|
else
|
||||||
CmdDoProperty(cellDef, cmd, 3 + ((dolist) ? 1 : 0));
|
CmdDoProperty(cellDef, w, cmd, 3 + ((dolist) ? 1 : 0));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDX_DELETE:
|
case IDX_DELETE:
|
||||||
|
|
@ -2396,8 +2419,10 @@ CmdContact(
|
||||||
CCStruct ccs;
|
CCStruct ccs;
|
||||||
Rect area;
|
Rect area;
|
||||||
LinkedRect *lr = NULL;
|
LinkedRect *lr = NULL;
|
||||||
int cmdContactFunc(Tile *tile, CCStruct *ccs); /* Forward declaration */
|
|
||||||
int cmdContactEraseFunc(Tile *tile, LinkedRect **lr); /* Forward declaration */
|
/* Forward declarations */
|
||||||
|
int cmdContactFunc(Tile *tile, TileType dinfo, CCStruct *ccs);
|
||||||
|
int cmdContactEraseFunc(Tile *tile, TileType dinfo, LinkedRect **lr);
|
||||||
|
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
|
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
|
||||||
|
|
@ -2455,6 +2480,7 @@ CmdContact(
|
||||||
|
|
||||||
rmask = DBResidueMask(type);
|
rmask = DBResidueMask(type);
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (lr != NULL)
|
while (lr != NULL)
|
||||||
{
|
{
|
||||||
GeoClip(&lr->r_r, &area);
|
GeoClip(&lr->r_r, &area);
|
||||||
|
|
@ -2465,9 +2491,10 @@ CmdContact(
|
||||||
if (TTMaskHasType(rmask, rtype))
|
if (TTMaskHasType(rmask, rtype))
|
||||||
DBPaint(EditCellUse->cu_def, &lr->r_r, rtype);
|
DBPaint(EditCellUse->cu_def, &lr->r_r, rtype);
|
||||||
|
|
||||||
freeMagic(lr);
|
freeMagic1(&mm1, lr);
|
||||||
lr = lr->r_next;
|
lr = lr->r_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
/* Refresh the layout drawing */
|
/* Refresh the layout drawing */
|
||||||
DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &smask);
|
DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &smask);
|
||||||
|
|
@ -2504,14 +2531,16 @@ CmdContact(
|
||||||
DBSrPaintArea((Tile *) NULL, EditCellUse->cu_def->cd_planes[DBPlane(rtype)],
|
DBSrPaintArea((Tile *) NULL, EditCellUse->cu_def->cd_planes[DBPlane(rtype)],
|
||||||
&area, &smask, cmdContactFunc, (ClientData) &ccs);
|
&area, &smask, cmdContactFunc, (ClientData) &ccs);
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (ccs.lhead != NULL)
|
while (ccs.lhead != NULL)
|
||||||
{
|
{
|
||||||
TTMaskSetOnlyType(&smask, type);
|
TTMaskSetOnlyType(&smask, type);
|
||||||
TTMaskAndMask(&smask, &DBActiveLayerBits);
|
TTMaskAndMask(&smask, &DBActiveLayerBits);
|
||||||
DBPaintMask(EditCellUse->cu_def, &ccs.lhead->r_r, &smask);
|
DBPaintMask(EditCellUse->cu_def, &ccs.lhead->r_r, &smask);
|
||||||
freeMagic(ccs.lhead);
|
freeMagic1(&mm1, ccs.lhead);
|
||||||
ccs.lhead = ccs.lhead->r_next;
|
ccs.lhead = ccs.lhead->r_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
/* Refresh the layout drawing */
|
/* Refresh the layout drawing */
|
||||||
DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &smask);
|
DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &smask);
|
||||||
|
|
@ -2527,11 +2556,14 @@ CmdContact(
|
||||||
int
|
int
|
||||||
cmdContactFunc(
|
cmdContactFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
CCStruct *ccs)
|
CCStruct *ccs)
|
||||||
{
|
{
|
||||||
TileType stype;
|
TileType stype;
|
||||||
TileTypeBitMask smask;
|
TileTypeBitMask smask;
|
||||||
int cmdContactFunc2(Tile *tile, CCStruct *ccs); /* Forward declaration */
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int cmdContactFunc2(Tile *tile, TileType dinfo, CCStruct *ccs);
|
||||||
|
|
||||||
TiToRect(tile, &ccs->area);
|
TiToRect(tile, &ccs->area);
|
||||||
GeoClip(&ccs->area, &ccs->clip);
|
GeoClip(&ccs->area, &ccs->clip);
|
||||||
|
|
@ -2541,14 +2573,16 @@ cmdContactFunc(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
TTMaskSetOnlyType(&smask, stype);
|
TTMaskSetOnlyType(&smask, stype);
|
||||||
DBSrPaintArea((Tile *) NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
|
DBSrPaintNMArea((Tile *)NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
|
||||||
&ccs->area, &smask, cmdContactFunc2, (ClientData)ccs);
|
TiGetTypeExact(tile) | dinfo, &ccs->area, &smask,
|
||||||
|
cmdContactFunc2, (ClientData)ccs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdContactFunc2(
|
cmdContactFunc2(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
CCStruct *ccs)
|
CCStruct *ccs)
|
||||||
{
|
{
|
||||||
LinkedRect *newlr;
|
LinkedRect *newlr;
|
||||||
|
|
@ -2571,6 +2605,7 @@ cmdContactFunc2(
|
||||||
int
|
int
|
||||||
cmdContactEraseFunc(
|
cmdContactEraseFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
LinkedRect **lr)
|
LinkedRect **lr)
|
||||||
{
|
{
|
||||||
LinkedRect *newlr;
|
LinkedRect *newlr;
|
||||||
|
|
@ -2824,14 +2859,15 @@ CmdCorner(
|
||||||
TileTypeBitMask maskBits;
|
TileTypeBitMask maskBits;
|
||||||
Rect editBox;
|
Rect editBox;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
extern int cmdCornerFunc(Tile *tile, TreeContext *cxp);
|
|
||||||
bool hasErr = FALSE;
|
bool hasErr = FALSE;
|
||||||
int locargc = cmd->tx_argc;
|
int locargc = cmd->tx_argc;
|
||||||
|
|
||||||
extern int cmdBevelFunc(Tile *tile, TreeContext *cxp);
|
|
||||||
bool dobevel = FALSE;
|
bool dobevel = FALSE;
|
||||||
NMCornerPath cmdPathList;
|
NMCornerPath cmdPathList;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
extern int cmdCornerFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
extern int cmdBevelFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
|
||||||
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s direction1 direction2 [layers]\n",
|
TxError("Usage: %s direction1 direction2 [layers]\n",
|
||||||
|
|
@ -2952,14 +2988,22 @@ CmdCorner(
|
||||||
|
|
||||||
rectp = CIFPolyToRects(cmdPathList.pathlist->pathhead, plane,
|
rectp = CIFPolyToRects(cmdPathList.pathlist->pathhead, plane,
|
||||||
resultTbl, &ui, FALSE);
|
resultTbl, &ui, FALSE);
|
||||||
for (; rectp != NULL; rectp = rectp->r_next)
|
|
||||||
{
|
{
|
||||||
DBPaintPlane(plane, &rectp->r_r, resultTbl, &ui);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
freeMagic((char *)rectp);
|
for (; rectp != NULL; rectp = rectp->r_next)
|
||||||
|
{
|
||||||
|
DBPaintPlane(plane, &rectp->r_r, resultTbl, &ui);
|
||||||
|
freeMagic1(&mm1, (char *)rectp);
|
||||||
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
CIFFreePath(cmdPathList.pathlist->pathhead);
|
CIFFreePath(cmdPathList.pathlist->pathhead);
|
||||||
freeMagic((char *)cmdPathList.pathlist);
|
{
|
||||||
cmdPathList.pathlist = cmdPathList.pathlist->cpl_next;
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, (char *)cmdPathList.pathlist);
|
||||||
|
cmdPathList.pathlist = cmdPathList.pathlist->cpl_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2977,14 +3021,16 @@ CmdCorner(
|
||||||
/* Now that we've got all the material, scan over the list
|
/* Now that we've got all the material, scan over the list
|
||||||
* painting the material and freeing up the entries on the list.
|
* painting the material and freeing up the entries on the list.
|
||||||
*/
|
*/
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (cmdCornerList != NULL)
|
while (cmdCornerList != NULL)
|
||||||
{
|
{
|
||||||
DBPaint(EditCellUse->cu_def, &cmdCornerList->cca_area,
|
DBPaint(EditCellUse->cu_def, &cmdCornerList->cca_area,
|
||||||
cmdCornerList->cca_type);
|
cmdCornerList->cca_type);
|
||||||
freeMagic((char *) cmdCornerList);
|
freeMagic1(&mm1, (char *) cmdCornerList);
|
||||||
cmdCornerList = cmdCornerList->cca_next;
|
cmdCornerList = cmdCornerList->cca_next;
|
||||||
}
|
}
|
||||||
}
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
|
|
||||||
SelectClear();
|
SelectClear();
|
||||||
DBAdjustLabels(EditCellUse->cu_def, &editBox);
|
DBAdjustLabels(EditCellUse->cu_def, &editBox);
|
||||||
|
|
@ -3016,6 +3062,7 @@ CmdCorner(
|
||||||
int
|
int
|
||||||
cmdCornerFunc(
|
cmdCornerFunc(
|
||||||
Tile *tile, /* Tile to fill with. */
|
Tile *tile, /* Tile to fill with. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
TreeContext *cxp) /* Describes state of search. */
|
TreeContext *cxp) /* Describes state of search. */
|
||||||
{
|
{
|
||||||
Rect r1, r2, r3;
|
Rect r1, r2, r3;
|
||||||
|
|
@ -3182,6 +3229,7 @@ AddNewPoint(
|
||||||
int
|
int
|
||||||
cmdBevelFunc(
|
cmdBevelFunc(
|
||||||
Tile *tile, /* Tile to fill with. */
|
Tile *tile, /* Tile to fill with. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
TreeContext *cxp) /* Describes state of search. */
|
TreeContext *cxp) /* Describes state of search. */
|
||||||
{
|
{
|
||||||
Rect r1, r2, r3;
|
Rect r1, r2, r3;
|
||||||
|
|
@ -3643,8 +3691,10 @@ cmdBevelFunc(
|
||||||
GeoClip(&r3, &cmdCornerRootBox);
|
GeoClip(&r3, &cmdCornerRootBox);
|
||||||
if (GEO_RECTNULL(&r2) || GEO_RECTNULL(&r3))
|
if (GEO_RECTNULL(&r2) || GEO_RECTNULL(&r3))
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (pptr = pathhead; pptr != NULL; pptr = pptr->cifp_next)
|
for (pptr = pathhead; pptr != NULL; pptr = pptr->cifp_next)
|
||||||
freeMagic((char *)pptr);
|
freeMagic1(&mm1, (char *)pptr);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3678,7 +3728,7 @@ cmdBevelFunc(
|
||||||
* Save cells to or recover cells from a crash backup file
|
* Save cells to or recover cells from a crash backup file
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* crash save|recover [file]
|
* crash save|recover|archive|read [file]
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -3713,7 +3763,7 @@ CmdCrash(
|
||||||
|
|
||||||
switch(option) {
|
switch(option) {
|
||||||
case 0: /* save */
|
case 0: /* save */
|
||||||
DBWriteBackup(filename);
|
DBWriteBackup(filename, FALSE, FALSE);
|
||||||
break;
|
break;
|
||||||
case 1: /* recover */
|
case 1: /* recover */
|
||||||
DBFileRecovery(filename);
|
DBFileRecovery(filename);
|
||||||
|
|
@ -4154,6 +4204,7 @@ CmdDrc(
|
||||||
|
|
||||||
rootUse = (CellUse *) window->w_surfaceID;
|
rootUse = (CellUse *) window->w_surfaceID;
|
||||||
dcl = DRCCount(rootUse, &rootArea, doforall);
|
dcl = DRCCount(rootUse, &rootArea, doforall);
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (dcl != NULL)
|
while (dcl != NULL)
|
||||||
{
|
{
|
||||||
if (count_total >= 0)
|
if (count_total >= 0)
|
||||||
|
|
@ -4183,9 +4234,10 @@ CmdDrc(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
freeMagic((char *)dcl);
|
freeMagic1(&mm1, (char *)dcl);
|
||||||
dcl = dcl->dcl_next;
|
dcl = dcl->dcl_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if ((count_total >= 0) || (!dolist))
|
if ((count_total >= 0) || (!dolist))
|
||||||
|
|
@ -4308,6 +4360,8 @@ CmdDrc(
|
||||||
#endif
|
#endif
|
||||||
TxPrintf("Error area #%d:\n", result);
|
TxPrintf("Error area #%d:\n", result);
|
||||||
if (DRCWhy(dolist, rootUse, &area, findonly)) break;
|
if (DRCWhy(dolist, rootUse, &area, findonly)) break;
|
||||||
|
/* Check for interrupt or this will go into an infinite loop */
|
||||||
|
else if (SigInterruptPending) break;
|
||||||
drc_nth++;
|
drc_nth++;
|
||||||
}
|
}
|
||||||
else if (result < 0)
|
else if (result < 0)
|
||||||
|
|
@ -4334,12 +4388,14 @@ CmdDrc(
|
||||||
}
|
}
|
||||||
if (findonly)
|
if (findonly)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
/* Delete temporary rules */
|
/* Delete temporary rules */
|
||||||
while (DRCIgnoreRules != NULL)
|
while (DRCIgnoreRules != NULL)
|
||||||
{
|
{
|
||||||
freeMagic(DRCIgnoreRules);
|
freeMagic1(&mm1, DRCIgnoreRules);
|
||||||
DRCIgnoreRules = DRCIgnoreRules->li_next;
|
DRCIgnoreRules = DRCIgnoreRules->li_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
/* Replace temporary set of rules */
|
/* Replace temporary set of rules */
|
||||||
DRCIgnoreRules = DRCSaveRules;
|
DRCIgnoreRules = DRCSaveRules;
|
||||||
}
|
}
|
||||||
|
|
@ -4422,8 +4478,10 @@ CmdDrc(
|
||||||
{
|
{
|
||||||
while (DRCIgnoreRules != NULL)
|
while (DRCIgnoreRules != NULL)
|
||||||
{
|
{
|
||||||
freeMagic(DRCIgnoreRules);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, DRCIgnoreRules);
|
||||||
DRCIgnoreRules = DRCIgnoreRules->li_next;
|
DRCIgnoreRules = DRCIgnoreRules->li_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -4561,6 +4619,7 @@ CmdDrc(
|
||||||
int
|
int
|
||||||
cmdDropPaintCell(
|
cmdDropPaintCell(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
TreeContext *cxp)
|
TreeContext *cxp)
|
||||||
{
|
{
|
||||||
CellDef *cellDef = cxp->tc_scx->scx_use->cu_def;
|
CellDef *cellDef = cxp->tc_scx->scx_use->cu_def;
|
||||||
|
|
@ -4569,7 +4628,7 @@ cmdDropPaintCell(
|
||||||
TileType type;
|
TileType type;
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
type = SplitRightType(tile);
|
type = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
type = SplitLeftType(tile);
|
type = SplitLeftType(tile);
|
||||||
|
|
@ -4602,6 +4661,7 @@ cmdDropPaintCell(
|
||||||
int
|
int
|
||||||
cmdDropFunc(
|
cmdDropFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
ClientData clientData)
|
ClientData clientData)
|
||||||
{
|
{
|
||||||
TileTypeBitMask tMask, *lMask = (TileTypeBitMask *)clientData;
|
TileTypeBitMask tMask, *lMask = (TileTypeBitMask *)clientData;
|
||||||
|
|
@ -4612,7 +4672,7 @@ cmdDropFunc(
|
||||||
scx.scx_use = EditCellUse;
|
scx.scx_use = EditCellUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
type = SplitRightType(tile);
|
type = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
type = SplitLeftType(tile);
|
type = SplitLeftType(tile);
|
||||||
|
|
@ -4954,15 +5014,20 @@ cmdDumpParseArgs(
|
||||||
bbox = def->cd_bbox;
|
bbox = def->cd_bbox;
|
||||||
if (def->cd_flags & CDFIXEDBBOX)
|
if (def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
char *propvalue;
|
PropertyRecord *proprec;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
(proprec->prop_len == 4))
|
||||||
bbox = def->cd_bbox;
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5239,11 +5304,12 @@ default_action:
|
||||||
}
|
}
|
||||||
av += 2;
|
av += 2;
|
||||||
ac -= 2;
|
ac -= 2;
|
||||||
}
|
|
||||||
GeoTransPoint(tx_cell, &editPoint, &locp);
|
GeoTransPoint(tx_cell, &editPoint, &locp);
|
||||||
GeoTranslateTrans(tx_cell, editPoint.p_x - locp.p_x,
|
GeoTranslateTrans(tx_cell, editPoint.p_x - locp.p_x,
|
||||||
editPoint.p_y - locp.p_y,
|
editPoint.p_y - locp.p_y,
|
||||||
&trans_cell);
|
&trans_cell);
|
||||||
|
}
|
||||||
hasTrans = TRUE;
|
hasTrans = TRUE;
|
||||||
break;
|
break;
|
||||||
case IDX_90: /* "90" */
|
case IDX_90: /* "90" */
|
||||||
|
|
|
||||||
191
commands/CmdE.c
191
commands/CmdE.c
|
|
@ -781,39 +781,82 @@ cmdEraseCellsFunc(
|
||||||
* Implement the "expand" command.
|
* Implement the "expand" command.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* expand
|
* expand [selection|surround|overlap|all] [toggle]
|
||||||
* expand toggle
|
*
|
||||||
|
* "selection" expands cells in the selection. All other options
|
||||||
|
* expand cells in the layout. "all" expands all cells in the
|
||||||
|
* layout. "surround" expands cells which the cursor box
|
||||||
|
* surrounds completely, and "overlap" expands cells which the
|
||||||
|
* cursor box overlaps.
|
||||||
|
*
|
||||||
|
* If "toggle" is specified, flips the expanded/unexpanded status.
|
||||||
|
* Cells which were expanded are unexpanded, and cells which were
|
||||||
|
* unexpanded are expanded.
|
||||||
|
*
|
||||||
|
* For backwards compatibility:
|
||||||
|
* "expand" alone implements "expand overlap".
|
||||||
|
* "expand toggle" implements "expand selection toggle".
|
||||||
|
*
|
||||||
|
* Also see: CmdUnexpand
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* If "toggle" is specified, flips the expanded/unexpanded status
|
* Expansion state of cells is changed. May read cells in from
|
||||||
* of all selected cells. Otherwise, aren't any unexpanded cells
|
* disk, and update bounding boxes that have changed.
|
||||||
* left under the box. May read cells in from disk, and updates
|
|
||||||
* bounding boxes that have changed.
|
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define EXPAND_SELECTION 0
|
||||||
|
#define EXPAND_SURROUND 1
|
||||||
|
#define EXPAND_OVERLAP 2
|
||||||
|
#define EXPAND_ALL 3
|
||||||
|
#define EXPAND_HELP 4
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdExpand(
|
CmdExpand(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
int windowMask, boxMask, d;
|
int windowMask, boxMask, d, option;
|
||||||
|
bool doToggle = FALSE;
|
||||||
|
const char * const *msg;
|
||||||
Rect rootRect;
|
Rect rootRect;
|
||||||
CellUse *rootBoxUse;
|
CellUse *rootBoxUse;
|
||||||
CellDef *rootBoxDef;
|
CellDef *rootBoxDef;
|
||||||
|
|
||||||
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
||||||
|
|
||||||
if (cmd->tx_argc > 2 || (cmd->tx_argc == 2
|
static const char * const cmdExpandOption[] = {
|
||||||
&& (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0)))
|
"selection expand cell instances in the selection",
|
||||||
|
"surround expand cell instances which the cursor box surrounds",
|
||||||
|
"overlap expand cell instances which the cursor box overlaps",
|
||||||
|
"all expand all cell instances",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 1)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]);
|
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle",
|
||||||
return;
|
strlen(cmd->tx_argv[cmd->tx_argc - 1])))
|
||||||
|
{
|
||||||
|
doToggle = TRUE;
|
||||||
|
cmd->tx_argc--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 1)
|
||||||
|
{
|
||||||
|
option = Lookup(cmd->tx_argv[1], cmdExpandOption);
|
||||||
|
if (option < 0) option = EXPAND_HELP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
option = EXPAND_OVERLAP;
|
||||||
|
|
||||||
|
if (option == EXPAND_HELP) goto badusage;
|
||||||
|
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if (w == (MagWindow *) NULL)
|
if (w == (MagWindow *) NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -844,23 +887,95 @@ CmdExpand(
|
||||||
WindScale(d, 1);
|
WindScale(d, 1);
|
||||||
TxPrintf("expand: rescaled by %d\n", d);
|
TxPrintf("expand: rescaled by %d\n", d);
|
||||||
d = DBLambda[1];
|
d = DBLambda[1];
|
||||||
if (cmd->tx_argc == 2) break; /* Don't toggle twice */
|
if (doToggle) break; /* Don't toggle twice */
|
||||||
}
|
}
|
||||||
(void) ToolGetBoxWindow(&rootRect, &boxMask);
|
(void) ToolGetBoxWindow(&rootRect, &boxMask);
|
||||||
|
|
||||||
if (cmd->tx_argc == 2)
|
if (option != EXPAND_SELECTION)
|
||||||
SelectExpand(windowMask);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if ((boxMask & windowMask) != windowMask)
|
if ((boxMask & windowMask) != windowMask)
|
||||||
{
|
{
|
||||||
TxError("The box isn't in the same window as the cursor.\n");
|
TxError("The box isn't in the same window as the cursor.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
}
|
||||||
TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask);
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case EXPAND_SELECTION:
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
(doToggle) ? DB_EXPAND_TOGGLE : DB_EXPAND,
|
||||||
|
(Rect *)NULL, FALSE);
|
||||||
|
break;
|
||||||
|
case EXPAND_OVERLAP:
|
||||||
|
if (doToggle)
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
|
||||||
|
&rootRect, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
&rootRect, FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXPAND_SURROUND:
|
||||||
|
if (doToggle)
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
|
||||||
|
&rootRect, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_SURROUND,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_SURROUND,
|
||||||
|
&rootRect, TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXPAND_ALL:
|
||||||
|
if (doToggle)
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
(Rect *)NULL, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
(Rect *)NULL, FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while (d != DBLambda[1]);
|
} while (d != DBLambda[1]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
badusage:
|
||||||
|
for (msg = &(cmdExpandOption[0]); *msg != NULL; msg++)
|
||||||
|
TxPrintf(" %s\n", *msg);
|
||||||
|
TxPrintf(" toggle Toggle the visibility of cell instances.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called for each cell whose expansion status changed.
|
/* This function is called for each cell whose expansion status changed.
|
||||||
|
|
@ -925,11 +1040,14 @@ cmdExpandFunc(
|
||||||
#define DOALL 1
|
#define DOALL 1
|
||||||
#define DOCAPACITANCE 2
|
#define DOCAPACITANCE 2
|
||||||
#define DOCOUPLING 3
|
#define DOCOUPLING 3
|
||||||
#define DOLENGTH 4
|
#define DOEXTRESIST 4
|
||||||
#define DOLOCAL 5
|
#define DOLENGTH 5
|
||||||
#define DORESISTANCE 6
|
#define DOLOCAL 6
|
||||||
#define DOLABELCHECK 7
|
#define DORESISTANCE 7
|
||||||
#define DOALIASES 8
|
#define DOLABELCHECK 8
|
||||||
|
#define DOALIASES 9
|
||||||
|
#define DOUNIQUE 10
|
||||||
|
#define DOEXTRESIST2 11
|
||||||
|
|
||||||
#define LENCLEAR 0
|
#define LENCLEAR 0
|
||||||
#define LENDRIVER 1
|
#define LENDRIVER 1
|
||||||
|
|
@ -972,11 +1090,14 @@ CmdExtract(
|
||||||
"all all options",
|
"all all options",
|
||||||
"capacitance extract substrate capacitance",
|
"capacitance extract substrate capacitance",
|
||||||
"coupling extract coupling capacitance",
|
"coupling extract coupling capacitance",
|
||||||
|
"extresist extract resistance",
|
||||||
"length compute driver-receiver pathlengths",
|
"length compute driver-receiver pathlengths",
|
||||||
"local put all generated files in the current directory",
|
"local put all generated files in the current directory",
|
||||||
"resistance estimate resistance",
|
"lumped estimate lumped resistance",
|
||||||
"labelcheck check for connections through sticky labels",
|
"labelcheck check for connections through sticky labels",
|
||||||
"aliases output all net name aliases",
|
"aliases output all net name aliases",
|
||||||
|
"unique ensure unique node names during extraction",
|
||||||
|
"resistance extract resistance (same as \"do extresist\")",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static const char * const cmdExtLength[] =
|
static const char * const cmdExtLength[] =
|
||||||
|
|
@ -1120,12 +1241,13 @@ CmdExtract(
|
||||||
}
|
}
|
||||||
else if (argc == 2)
|
else if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *halodisp;
|
||||||
|
halodisp = DBWPrintValue(ExtCurStyle->exts_sideCoupleHalo,
|
||||||
|
w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_Obj *tobj;
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(halodisp, -1));
|
||||||
tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo);
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo);
|
TxPrintf("Side overlap halo is %s\n", halodisp);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1150,12 +1272,12 @@ CmdExtract(
|
||||||
}
|
}
|
||||||
else if (argc == 2)
|
else if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *stepdisp;
|
||||||
|
stepdisp = DBWPrintValue(ExtCurStyle->exts_stepSize, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_Obj *tobj;
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(stepdisp, -1));
|
||||||
tobj = Tcl_NewIntObj(ExtCurStyle->exts_stepSize);
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("Extraction step size is %d\n", ExtCurStyle->exts_stepSize);
|
TxPrintf("Extraction step size is %s\n", stepdisp);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1277,9 +1399,11 @@ CmdExtract(
|
||||||
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
|
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
|
||||||
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
|
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
|
||||||
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
|
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
|
||||||
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
|
TxPrintf("%s lumped R\n", OPTSET(EXT_DORESISTANCE));
|
||||||
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
||||||
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
||||||
|
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
|
||||||
|
TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST));
|
||||||
return;
|
return;
|
||||||
#undef OPTSET
|
#undef OPTSET
|
||||||
}
|
}
|
||||||
|
|
@ -1309,6 +1433,9 @@ CmdExtract(
|
||||||
case DORESISTANCE: option = EXT_DORESISTANCE; break;
|
case DORESISTANCE: option = EXT_DORESISTANCE; break;
|
||||||
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
||||||
case DOALIASES: option = EXT_DOALIASES; break;
|
case DOALIASES: option = EXT_DOALIASES; break;
|
||||||
|
case DOUNIQUE: option = EXT_DOUNIQUE; break;
|
||||||
|
case DOEXTRESIST:
|
||||||
|
case DOEXTRESIST2: option = EXT_DOEXTRESIST; break;
|
||||||
case DOLOCAL:
|
case DOLOCAL:
|
||||||
/* "extract do local" and "extract no local" are kept for
|
/* "extract do local" and "extract no local" are kept for
|
||||||
* backwards compatibility, but now effectively implement
|
* backwards compatibility, but now effectively implement
|
||||||
|
|
|
||||||
|
|
@ -102,15 +102,17 @@ struct cmdFPArg
|
||||||
int
|
int
|
||||||
feedPolyFunc(
|
feedPolyFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
struct cmdFPArg *arg)
|
struct cmdFPArg *arg)
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
||||||
|
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
|
||||||
DBWFeedbackAdd(&area, arg->text, arg->def, FEEDMAGNIFY,
|
DBWFeedbackAdd(&area, arg->text, arg->def, FEEDMAGNIFY,
|
||||||
arg->style |
|
arg->style |
|
||||||
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
((TiGetTypeExact(tile) | dinfo) &
|
||||||
/* (preserve information about the geometry of a diagonal tile) */
|
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,13 +509,15 @@ struct cmdFillArea *cmdFillList; /* List of areas to fill. */
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdFill(
|
CmdFill(
|
||||||
MagWindow *w, /* Window in which command was invoked. */
|
MagWindow *w, /* Window in which command was invoked. */
|
||||||
TxCommand *cmd) /* Describes the command that was invoked. */
|
TxCommand *cmd) /* Describes the command that was invoked. */
|
||||||
{
|
{
|
||||||
TileTypeBitMask maskBits;
|
TileTypeBitMask maskBits;
|
||||||
Rect editBox;
|
Rect editBox;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
extern int cmdFillFunc(Tile *tile, TreeContext *cxp);
|
|
||||||
|
/* Forward declaration */
|
||||||
|
extern int cmdFillFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
|
||||||
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
|
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
|
||||||
{
|
{
|
||||||
|
|
@ -581,13 +585,15 @@ CmdFill(
|
||||||
/* Now that we've got all the material, scan over the list
|
/* Now that we've got all the material, scan over the list
|
||||||
* painting the material and freeing up the entries on the list.
|
* painting the material and freeing up the entries on the list.
|
||||||
*/
|
*/
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (cmdFillList != NULL)
|
while (cmdFillList != NULL)
|
||||||
{
|
{
|
||||||
DBPaint(EditCellUse->cu_def, &cmdFillList->cfa_area,
|
DBPaint(EditCellUse->cu_def, &cmdFillList->cfa_area,
|
||||||
cmdFillList->cfa_type);
|
cmdFillList->cfa_type);
|
||||||
freeMagic((char *) cmdFillList);
|
freeMagic1(&mm1, (char *) cmdFillList);
|
||||||
cmdFillList = cmdFillList->cfa_next;
|
cmdFillList = cmdFillList->cfa_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
SelectClear();
|
SelectClear();
|
||||||
DBAdjustLabels(EditCellUse->cu_def, &editBox);
|
DBAdjustLabels(EditCellUse->cu_def, &editBox);
|
||||||
|
|
@ -601,11 +607,16 @@ CmdFill(
|
||||||
* paint here it may mess up the search. Instead, the procedures
|
* paint here it may mess up the search. Instead, the procedures
|
||||||
* save areas on a list. The list is post-processed to paint the
|
* save areas on a list. The list is post-processed to paint the
|
||||||
* areas once the search is finished.
|
* areas once the search is finished.
|
||||||
|
*
|
||||||
|
* Split tile information is unused because there is no obvious
|
||||||
|
* meaning to "filling" from a split tile, although probably reasonable
|
||||||
|
* methods could be worked out.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdFillFunc(
|
cmdFillFunc(
|
||||||
Tile *tile, /* Tile to fill with. */
|
Tile *tile, /* Tile to fill with. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
TreeContext *cxp) /* Describes state of search. */
|
TreeContext *cxp) /* Describes state of search. */
|
||||||
{
|
{
|
||||||
Rect r1, r2;
|
Rect r1, r2;
|
||||||
|
|
@ -841,7 +852,7 @@ CmdFindLabel(
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
labname = cmd->tx_argv[1 + (doglob) ? 1 : 0];
|
labname = cmd->tx_argv[1 + ((doglob) ? 1 : 0)];
|
||||||
labUse = EditCellUse;
|
labUse = EditCellUse;
|
||||||
if (labUse == NULL) labUse = (CellUse *)w->w_surfaceID;
|
if (labUse == NULL) labUse = (CellUse *)w->w_surfaceID;
|
||||||
|
|
||||||
|
|
@ -1208,7 +1219,7 @@ CmdGetnode(
|
||||||
TxError("Put the cursor in a layout window\n");
|
TxError("Put the cursor in a layout window\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( is_fast == TRUE )
|
if (is_fast == TRUE)
|
||||||
{
|
{
|
||||||
SimRecomputeSel = TRUE;
|
SimRecomputeSel = TRUE;
|
||||||
SimGetsnode();
|
SimGetsnode();
|
||||||
|
|
@ -1216,7 +1227,8 @@ CmdGetnode(
|
||||||
else
|
else
|
||||||
SimGetnode();
|
SimGetnode();
|
||||||
|
|
||||||
if (SimGetnodeAlias) { /* "erase" the hash table */
|
if (SimGetnodeAlias) /* "erase" the hash table */
|
||||||
|
{
|
||||||
HashKill(&SimGNAliasTbl);
|
HashKill(&SimGNAliasTbl);
|
||||||
HashInit(&SimGNAliasTbl, 120, STRINGS);
|
HashInit(&SimGNAliasTbl, 120, STRINGS);
|
||||||
}
|
}
|
||||||
|
|
@ -1602,7 +1614,7 @@ CmdFindNetProc(
|
||||||
int pnum, xpos, ypos;
|
int pnum, xpos, ypos;
|
||||||
char *xstr, *ystr;
|
char *xstr, *ystr;
|
||||||
bool locvalid = FALSE, usefound = TRUE;
|
bool locvalid = FALSE, usefound = TRUE;
|
||||||
TileType ttype;
|
TileType ttype, dinfo = (TileType)0;
|
||||||
|
|
||||||
scx.scx_use = use;
|
scx.scx_use = use;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
@ -1640,6 +1652,7 @@ CmdFindNetProc(
|
||||||
|
|
||||||
if ((xstr = strchr(s, '_')) != NULL)
|
if ((xstr = strchr(s, '_')) != NULL)
|
||||||
{
|
{
|
||||||
|
char *hashpos;
|
||||||
bool isNeg = FALSE;
|
bool isNeg = FALSE;
|
||||||
|
|
||||||
/* The characters up to the leading '_' should match one of the */
|
/* The characters up to the leading '_' should match one of the */
|
||||||
|
|
@ -1683,6 +1696,17 @@ CmdFindNetProc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Format variant used for node regions where a split tile
|
||||||
|
* occupies the root position of the node but the tile type
|
||||||
|
* belonging to the node is on the right side of the tile,
|
||||||
|
* not at the location encoded into the name. An 'x' is
|
||||||
|
* added before the final hash sign.
|
||||||
|
*/
|
||||||
|
hashpos = strrchr(s, '#');
|
||||||
|
if (hashpos != NULL)
|
||||||
|
if (*(hashpos - 1) == 'r')
|
||||||
|
dinfo = TT_DIAGONAL | TT_SIDE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1705,17 +1729,23 @@ checklocal:
|
||||||
|
|
||||||
if (locvalid == TRUE)
|
if (locvalid == TRUE)
|
||||||
{
|
{
|
||||||
int findTile(Tile *tile, TileType *rtype);
|
int findTile(Tile *tile, TileType dinfo, TileAndDinfo *tad);
|
||||||
CellDef *targetdef = use->cu_def;
|
CellDef *targetdef = use->cu_def;
|
||||||
Plane *plane = targetdef->cd_planes[pnum];
|
Plane *plane = targetdef->cd_planes[pnum];
|
||||||
|
TileAndDinfo tad;
|
||||||
ttype = TT_SPACE; /* revert to space in case of failure */
|
|
||||||
|
|
||||||
/* Find the tile type of the tile at the specified point which */
|
/* Find the tile type of the tile at the specified point which */
|
||||||
/* exists on the plane pnum. */
|
/* exists on the plane pnum. Note that in the case of a split */
|
||||||
|
/* tile region marked with "x" in the name, it does not work to */
|
||||||
|
/* call DBSrPainNMArea() because the diagonal position is not */
|
||||||
|
/* known. findTile() determines the proper type and leaves it */
|
||||||
|
/* in the tad.tad_dinfo record. */
|
||||||
|
|
||||||
|
tad.tad_tile = (Tile *)NULL;
|
||||||
|
tad.tad_dinfo = dinfo;
|
||||||
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
|
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
|
||||||
(ClientData) &ttype);
|
(ClientData) &tad);
|
||||||
|
ttype = tad.tad_dinfo & TT_LEFTMASK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1783,7 +1813,7 @@ CmdGoto(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
char *s, *nodename = cmd->tx_argv[1];
|
char *nodename = cmd->tx_argv[1];
|
||||||
Rect rect;
|
Rect rect;
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
int locargc;
|
int locargc;
|
||||||
|
|
@ -1824,9 +1854,9 @@ CmdGoto(
|
||||||
/* are multiple layers drawn at the indicated point. */
|
/* are multiple layers drawn at the indicated point. */
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp, DBTypeLongName(ttype), NULL);
|
Tcl_SetResult(magicinterp, (char*)DBTypeLongName(ttype), NULL); /* Tcl treats as const */
|
||||||
#else
|
#else
|
||||||
TxPrintf("node %s is type %s\n", s, DBTypeLongName(ttype));
|
TxPrintf("node %s is type %s\n", nodename, DBTypeLongName(ttype));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1839,20 +1869,31 @@ CmdGoto(
|
||||||
int
|
int
|
||||||
findTile(
|
findTile(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
TileType *rtype)
|
TileType dinfo, /* (unused) */
|
||||||
|
TileAndDinfo *tad)
|
||||||
{
|
{
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
|
|
||||||
|
/* Note that since all types are being searched, a split
|
||||||
|
* tile would cause the callback to be called twice. But
|
||||||
|
* this routine will pick the indicated side from the
|
||||||
|
* "tad" structure and return 1 so it does not get called
|
||||||
|
* a second time. The "dinfo" value passed is irrelevant.
|
||||||
|
*/
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
if (SplitSide(tile))
|
if (tad->tad_dinfo & TT_SIDE)
|
||||||
ttype = SplitRightType(tile);
|
ttype = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
ttype = SplitLeftType(tile);
|
ttype = SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ttype = TiGetTypeExact(tile);
|
ttype = TiGetTypeExact(tile);
|
||||||
*rtype = ttype;
|
|
||||||
|
/* Leave the tile type in tad_dinfo before returning */
|
||||||
|
tad->tad_dinfo = ttype;
|
||||||
|
|
||||||
return 1; /* stop search */
|
return 1; /* stop search */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
604
commands/CmdLQ.c
604
commands/CmdLQ.c
|
|
@ -45,9 +45,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
#include "select/select.h"
|
#include "select/select.h"
|
||||||
#include "netmenu/netmenu.h"
|
#include "netmenu/netmenu.h"
|
||||||
|
|
||||||
/* C99 compat */
|
|
||||||
#include "cif/cif.h"
|
#include "cif/cif.h"
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
|
|
||||||
|
|
@ -518,14 +517,14 @@ CmdLoad(
|
||||||
|
|
||||||
DBExpandAll(topuse, &(topuse->cu_bbox),
|
DBExpandAll(topuse, &(topuse->cu_bbox),
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||||
TRUE, keepGoing, NULL);
|
DB_EXPAND, keepGoing, NULL);
|
||||||
|
|
||||||
DBExpandAll(topuse, &(topuse->cu_bbox),
|
DBExpandAll(topuse, &(topuse->cu_bbox),
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||||
FALSE, keepGoing, NULL);
|
DB_UNEXPAND, keepGoing, NULL);
|
||||||
DBExpand(topuse,
|
DBExpand(topuse,
|
||||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||||
TRUE);
|
DB_EXPAND);
|
||||||
|
|
||||||
/* We don't want to save and restore DBLambda, because */
|
/* We don't want to save and restore DBLambda, because */
|
||||||
/* loading the file may change their values. Instead, we */
|
/* loading the file may change their values. Instead, we */
|
||||||
|
|
@ -2176,11 +2175,15 @@ parseindex:
|
||||||
{
|
{
|
||||||
if ((int)sl->lab_port == idx)
|
if ((int)sl->lab_port == idx)
|
||||||
{
|
{
|
||||||
TxError("Port index %d is already used by port %s.\n"
|
/* This is only an error if port name doesn't match */
|
||||||
"Use command \"port index %d\" to force "
|
if (strcmp(sl->lab_text, lab->lab_text))
|
||||||
"equivalence after defining the port.\n",
|
{
|
||||||
idx, sl->lab_text, idx);
|
TxError("Port index %d is already used by port %s.\n"
|
||||||
return;
|
"Use command \"port index %d\" to force "
|
||||||
|
"equivalence after defining the port.\n",
|
||||||
|
idx, sl->lab_text, idx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2292,6 +2295,8 @@ parsepositions:
|
||||||
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PROPERTY_TYPE_COMPAT 4 /* Last entry in cmdPropertyType */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -2315,47 +2320,448 @@ parsepositions:
|
||||||
void
|
void
|
||||||
CmdDoProperty(
|
CmdDoProperty(
|
||||||
CellDef *def,
|
CellDef *def,
|
||||||
|
MagWindow *w,
|
||||||
TxCommand *cmd,
|
TxCommand *cmd,
|
||||||
int argstart)
|
int argstart)
|
||||||
{
|
{
|
||||||
int printPropertiesFunc();
|
PropertyRecord *proprec;
|
||||||
char *value;
|
char *value;
|
||||||
bool propfound;
|
bool propfound, dolist;
|
||||||
|
int proptype, proplen, propvalue, i;
|
||||||
|
dlong dvalue;
|
||||||
int locargc = cmd->tx_argc - argstart + 1;
|
int locargc = cmd->tx_argc - argstart + 1;
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
int printPropertiesFunc();
|
||||||
|
int printPlanePropFunc();
|
||||||
|
|
||||||
|
/* These should match the property codes in database.h.in, except
|
||||||
|
* for "compat" which must come at the end.
|
||||||
|
*/
|
||||||
|
static const char * const cmdPropertyType[] = {
|
||||||
|
"string", "integer", "dimension", "double", "plane", "compat", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* If the first keyword is "list", then set dolist and increment
|
||||||
|
* the starting argument position.
|
||||||
|
*/
|
||||||
|
dolist = FALSE;
|
||||||
|
if (locargc > 1)
|
||||||
|
{
|
||||||
|
if (!strcmp(cmd->tx_argv[argstart], "list"))
|
||||||
|
{
|
||||||
|
dolist = TRUE;
|
||||||
|
locargc--;
|
||||||
|
argstart++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a property type is given, parse it and then strip it from
|
||||||
|
* the arguments list.
|
||||||
|
*/
|
||||||
|
if (locargc > 1)
|
||||||
|
{
|
||||||
|
proptype = Lookup(cmd->tx_argv[argstart], cmdPropertyType);
|
||||||
|
if (proptype >= 0)
|
||||||
|
{
|
||||||
|
if (proptype != PROPERTY_TYPE_COMPAT)
|
||||||
|
{
|
||||||
|
locargc--;
|
||||||
|
argstart++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
proptype = PROPERTY_TYPE_STRING; /* default */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
proptype = PROPERTY_TYPE_STRING; /* default */
|
||||||
|
|
||||||
if (locargc == 1)
|
if (locargc == 1)
|
||||||
{
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj;
|
||||||
|
/* Create an empty list for the interpreter result; the
|
||||||
|
* printPropertiesFunc() function will append values to it.
|
||||||
|
*/
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
#endif
|
||||||
/* print all properties and their values */
|
/* print all properties and their values */
|
||||||
DBPropEnum(def, printPropertiesFunc, NULL);
|
DBPropEnum(def, printPropertiesFunc, (ClientData)w);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (locargc == 2)
|
else if (locargc == 2)
|
||||||
{
|
{
|
||||||
/* print the value of the indicated property */
|
/* If the property type was "compat", then give the state of the
|
||||||
value = (char *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
* compatibility flag and return.
|
||||||
if (propfound)
|
*/
|
||||||
|
if (proptype == PROPERTY_TYPE_COMPAT)
|
||||||
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp, value, NULL);
|
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(DBPropCompat));
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s", value);
|
TxPrintf("%s\n", (DBPropCompat == TRUE) ? "True" : "False");
|
||||||
#endif
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the value of the indicated property */
|
||||||
|
proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
||||||
|
if (propfound)
|
||||||
|
{
|
||||||
|
proptype = proprec->prop_type;
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
switch (proptype)
|
||||||
|
{
|
||||||
|
case PROPERTY_TYPE_STRING:
|
||||||
|
Tcl_SetResult(magicinterp, proprec->prop_value.prop_string, NULL);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
if (proprec->prop_len == 1)
|
||||||
|
Tcl_SetObjResult(magicinterp,
|
||||||
|
Tcl_NewIntObj(proprec->prop_value.prop_integer[0]));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewIntObj(
|
||||||
|
proprec->prop_value.prop_integer[i]));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
if (proprec->prop_len == 1)
|
||||||
|
Tcl_SetResult(magicinterp,
|
||||||
|
DBWPrintValue(proprec->prop_value.prop_integer[0],
|
||||||
|
w, TRUE), NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(
|
||||||
|
proprec->prop_value.prop_integer[i], w,
|
||||||
|
((i % 2) == 0) ? TRUE : FALSE), -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)tobj);
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
if (proprec->prop_len == 1)
|
||||||
|
Tcl_SetObjResult(magicinterp,
|
||||||
|
Tcl_NewWideIntObj((Tcl_WideInt)
|
||||||
|
proprec->prop_value.prop_double[0]));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewWideIntObj((Tcl_WideInt)
|
||||||
|
proprec->prop_value.prop_double[i]));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
switch (proptype)
|
||||||
|
{
|
||||||
|
case PROPERTY_TYPE_STRING:
|
||||||
|
TxPrintf("%s\n", proprec->prop_value.prop_string);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%d ", proprec->prop_value.prop_integer[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%s ", DBWPrintValue(
|
||||||
|
proprec->prop_value.prop_integer[i], w,
|
||||||
|
((i % 2) == 0) ? TRUE : FALSE));
|
||||||
|
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)NULL);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf( "%"DLONG_PREFIX"d",
|
||||||
|
proprec->prop_value.prop_double[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
/* If the command was "cellname list property ...", then */
|
/* If the command was "cellname list property ...", then */
|
||||||
/* just return NULL if the property was not found. */
|
/* just return NULL if the property was not found. */
|
||||||
if (strcmp(cmd->tx_argv[1], "list"))
|
if (!dolist)
|
||||||
#endif
|
#endif
|
||||||
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
|
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[argstart]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (locargc == 3)
|
else if (locargc >= 3)
|
||||||
{
|
{
|
||||||
|
/* If the property type was "compat", then set the state of the
|
||||||
|
* compatibility flag and return.
|
||||||
|
*/
|
||||||
|
if (proptype == PROPERTY_TYPE_COMPAT)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
static const char * const cmdPropYesNo[] = {
|
||||||
|
"disable", "no", "false", "off", "0",
|
||||||
|
"enable", "yes", "true", "on", "1", 0 };
|
||||||
|
idx = Lookup(cmd->tx_argv[2], cmdPropYesNo);
|
||||||
|
if (idx < 0)
|
||||||
|
{
|
||||||
|
TxError("Unknown property compat option \"%s\"\n", cmd->tx_argv[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DBPropCompat = (idx <= 4) ? FALSE : TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Catch the following known reserved keywords and cast them to the
|
||||||
|
* expected property type. If any property type was already given
|
||||||
|
* to the command, it is overridden. This ensures that the reserved
|
||||||
|
* keyword functions work correctly.
|
||||||
|
*
|
||||||
|
* GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE
|
||||||
|
* MASKHINTS_*: PROPERTY_TYPE_PLANE
|
||||||
|
* FIXED_BBOX: PROPERTY_TYPE_DIMENSION
|
||||||
|
*/
|
||||||
|
if (!strcmp(cmd->tx_argv[argstart], "GDS_START"))
|
||||||
|
proptype = PROPERTY_TYPE_DOUBLE;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "GDS_END"))
|
||||||
|
proptype = PROPERTY_TYPE_DOUBLE;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "GDS_FILE"))
|
||||||
|
proptype = PROPERTY_TYPE_STRING;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "FIXED_BBOX"))
|
||||||
|
proptype = PROPERTY_TYPE_DIMENSION;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "OBS_BBOX"))
|
||||||
|
proptype = PROPERTY_TYPE_DIMENSION;
|
||||||
|
else if (!strncmp(cmd->tx_argv[argstart], "MASKHINTS_", 10))
|
||||||
|
proptype = PROPERTY_TYPE_PLANE;
|
||||||
|
|
||||||
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
|
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
|
||||||
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = StrDup((char **)NULL, cmd->tx_argv[argstart + 1]);
|
if (proptype == PROPERTY_TYPE_STRING)
|
||||||
DBPropPut(def, cmd->tx_argv[argstart], value);
|
{
|
||||||
|
proplen = strlen(cmd->tx_argv[argstart + 1]);
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) -
|
||||||
|
7 + proplen);
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]);
|
||||||
|
}
|
||||||
|
else /* All non-string properties */
|
||||||
|
{
|
||||||
|
Plane *plane;
|
||||||
|
Rect r;
|
||||||
|
|
||||||
|
/* Two choices: If locargc == 3 then all values are in one
|
||||||
|
* argument. If locargc > 3, then parse each argument as a
|
||||||
|
* separate value.
|
||||||
|
*/
|
||||||
|
if (locargc > 3)
|
||||||
|
{
|
||||||
|
proplen = locargc - 2;
|
||||||
|
if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||||
|
(proplen - 1)*sizeof(dlong));
|
||||||
|
else if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||||
|
(proplen - 2)*sizeof(int));
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
|
||||||
|
for (i = 1; i < locargc - 1; i++)
|
||||||
|
{
|
||||||
|
if (proptype == PROPERTY_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
if (sscanf(cmd->tx_argv[argstart + i], "%d",
|
||||||
|
&propvalue) == 1)
|
||||||
|
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxError("Unable to parse value \"%s\" as an integer\n",
|
||||||
|
cmd->tx_argv[argstart + i]);
|
||||||
|
proprec->prop_value.prop_integer[i - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||||
|
{
|
||||||
|
if (sscanf(cmd->tx_argv[argstart + i], "%"DLONG_PREFIX"d",
|
||||||
|
&dvalue) == 1)
|
||||||
|
proprec->prop_value.prop_double[i - 1] = dvalue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxError("Unable to parse value \"%s\" as an integer\n",
|
||||||
|
cmd->tx_argv[argstart + i]);
|
||||||
|
proprec->prop_value.prop_double[i - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
||||||
|
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
||||||
|
switch ((i - 1) % 4)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
r.r_xbot = propvalue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r.r_ybot = propvalue;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r.r_xtop = propvalue;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r.r_ytop = propvalue;
|
||||||
|
DBPaintPlane(plane, &r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* PROPERTY_TYPE_DIMENSION */
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
||||||
|
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
||||||
|
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Make two passes through the argument string, once to get
|
||||||
|
* the valid number of arguments, then again to parse the
|
||||||
|
* values, once the property record has been allocated
|
||||||
|
*/
|
||||||
|
if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = cmd->tx_argv[argstart + 1];
|
||||||
|
for (proplen = 0; *value != '\0'; )
|
||||||
|
{
|
||||||
|
if (isspace(*value) && (*value != '\0')) value++;
|
||||||
|
if (!isspace(*value))
|
||||||
|
{
|
||||||
|
proplen++;
|
||||||
|
while (!isspace(*value) && (*value != '\0')) value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proplen > 0)
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(
|
||||||
|
sizeof(PropertyRecord) +
|
||||||
|
(proplen - 2) * sizeof(int));
|
||||||
|
}
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
|
||||||
|
/* Second pass */
|
||||||
|
value = cmd->tx_argv[argstart + 1];
|
||||||
|
for (proplen = 0; proplen < proprec->prop_len; proplen++)
|
||||||
|
{
|
||||||
|
if (isspace(*value) && (*value != '\0')) value++;
|
||||||
|
if (!isspace(*value))
|
||||||
|
{
|
||||||
|
char *spptr, spchar;
|
||||||
|
/* cmdParseCoord() can only handle one value at a
|
||||||
|
* time, so look ahead and null out the next space
|
||||||
|
* character if there is one.
|
||||||
|
*/
|
||||||
|
spptr = value + 1;
|
||||||
|
while (!isspace(*spptr) && (*spptr != '\0')) spptr++;
|
||||||
|
spchar = *spptr;
|
||||||
|
*spptr = '\0';
|
||||||
|
|
||||||
|
if (proptype == PROPERTY_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
if (sscanf(value, "%d", &propvalue) != 1)
|
||||||
|
{
|
||||||
|
TxError("Unable to parse integer "
|
||||||
|
"value from \"%s\"\n",
|
||||||
|
value);
|
||||||
|
propvalue = 0;
|
||||||
|
}
|
||||||
|
proprec->prop_value.prop_integer[proplen] = propvalue;
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||||
|
{
|
||||||
|
if (sscanf(value, "%"DLONG_PREFIX"d", &dvalue) != 1)
|
||||||
|
{
|
||||||
|
TxError("Unable to parse integer "
|
||||||
|
"value from \"%s\"\n",
|
||||||
|
value);
|
||||||
|
propvalue = 0;
|
||||||
|
}
|
||||||
|
proprec->prop_value.prop_double[proplen] = dvalue;
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, value, FALSE,
|
||||||
|
((proplen % 2) == 0) ? TRUE : FALSE);
|
||||||
|
switch (proplen % 4)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
r.r_xbot = propvalue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r.r_ybot = propvalue;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r.r_xtop = propvalue;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r.r_ytop = propvalue;
|
||||||
|
DBPaintPlane(plane, &r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* PROPERTY_TYPE_DIMENSION */
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, value, FALSE,
|
||||||
|
((proplen % 2) == 0) ? TRUE : FALSE);
|
||||||
|
proprec->prop_value.prop_integer[proplen] = propvalue;
|
||||||
|
}
|
||||||
|
*spptr = spchar;
|
||||||
|
while (!isspace(*value) && (*value != '\0')) value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBPropPut(def, cmd->tx_argv[argstart], proprec);
|
||||||
}
|
}
|
||||||
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||||
}
|
}
|
||||||
|
|
@ -2376,10 +2782,14 @@ CmdDoProperty(
|
||||||
* defined in database/DBprop.c.
|
* defined in database/DBprop.c.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* property [name] [value]
|
* property [string|integer|dimension] [name] [value]
|
||||||
*
|
*
|
||||||
* "name" is a unique string tag for the property, and "value" is its
|
* If the first argument is present, it must be one of the known
|
||||||
* string value.
|
* keywords, and determines the form in which "value" is interpreted and
|
||||||
|
* stored. "name" is a unique string tag for the property. "value" is
|
||||||
|
* the value of the property, which is either a string, integer, or a
|
||||||
|
* list of integers. The difference between an "integer" and a "dimension"
|
||||||
|
* is that all values which are dimensions are scaled with internal units.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -2406,9 +2816,62 @@ CmdProperty(
|
||||||
else
|
else
|
||||||
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
||||||
|
|
||||||
CmdDoProperty(def, cmd, 1);
|
CmdDoProperty(def, w, cmd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* Callback function for printing values from a Plane property
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
int
|
||||||
|
printPlanePropFunc(
|
||||||
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
Tcl_Obj *lobj)
|
||||||
|
{
|
||||||
|
Rect r;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
TiToRect(tile, &r);
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_xbot, w, TRUE), -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_ybot, w, FALSE), -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_xtop, w, TRUE), -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_ytop, w, FALSE), -1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int
|
||||||
|
printPlanePropFunc(
|
||||||
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData cdata) /* (unused) */
|
||||||
|
{
|
||||||
|
Rect r;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
TiToRect(tile, &r);
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_xbot, w, TRUE));
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_ybot, w, FALSE));
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_xtop, w, TRUE));
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_ytop, w, FALSE));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
* Callback function for printing a single property key:value pair
|
* Callback function for printing a single property key:value pair
|
||||||
|
|
@ -2418,27 +2881,84 @@ CmdProperty(
|
||||||
int
|
int
|
||||||
printPropertiesFunc(
|
printPropertiesFunc(
|
||||||
const char *name,
|
const char *name,
|
||||||
ClientData value,
|
PropertyRecord *proprec,
|
||||||
ClientData cdata) /* not used */
|
MagWindow *w)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
int i;
|
||||||
char *keyvalue;
|
|
||||||
|
|
||||||
if (value == NULL)
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj, *lobj;
|
||||||
|
|
||||||
|
tobj = Tcl_GetObjResult(magicinterp);
|
||||||
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(name, -1));
|
||||||
|
|
||||||
|
switch (proprec->prop_type)
|
||||||
{
|
{
|
||||||
keyvalue = (char *)mallocMagic(strlen(name) + 4);
|
case PROPERTY_TYPE_STRING:
|
||||||
sprintf(keyvalue, "%s {}", name);
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(proprec->prop_value.prop_string, -1));
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewIntObj(proprec->prop_value.prop_integer[i]));
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(
|
||||||
|
DBWPrintValue(proprec->prop_value.prop_integer[i],
|
||||||
|
w, ((i % 2) == 0) ? TRUE : FALSE), -1));
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)lobj);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewWideIntObj(proprec->prop_value.prop_double[i]));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
Tcl_ListObjAppendElement(magicinterp, tobj, lobj);
|
||||||
{
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2);
|
|
||||||
sprintf(keyvalue, "%s %s", name, (char *)value);
|
|
||||||
}
|
|
||||||
Tcl_AppendElement(magicinterp, keyvalue);
|
|
||||||
freeMagic(keyvalue);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s = %s\n", name, value);
|
switch (proprec->prop_type)
|
||||||
|
{
|
||||||
|
case PROPERTY_TYPE_STRING:
|
||||||
|
TxPrintf("%s = %s\n", name, (const char *)proprec->prop_value.prop_string);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%d ", proprec->prop_value.prop_integer[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%s ", DBWPrintValue(proprec->prop_value.prop_integer[i],
|
||||||
|
w, ((i % 2) == 0) ? TRUE : FALSE));
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)NULL);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_value.prop_double[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0; /* keep the search alive */
|
return 0; /* keep the search alive */
|
||||||
|
|
|
||||||
259
commands/CmdRS.c
259
commands/CmdRS.c
|
|
@ -99,7 +99,7 @@ CmdRandom(
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(random()));
|
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(random()));
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d", random());
|
TxPrintf("%ld", random());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if ((cmd->tx_argc >= 2) && (!strcmp(cmd->tx_argv[1], "seed")))
|
else if ((cmd->tx_argc >= 2) && (!strcmp(cmd->tx_argv[1], "seed")))
|
||||||
|
|
@ -220,8 +220,6 @@ CmdSave(
|
||||||
DBUpdateStamps(locDef);
|
DBUpdateStamps(locDef);
|
||||||
if (cmd->tx_argc == 2)
|
if (cmd->tx_argc == 2)
|
||||||
{
|
{
|
||||||
char *fileName;
|
|
||||||
|
|
||||||
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
|
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -1086,25 +1084,33 @@ CmdSelect(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case SEL_BBOX:
|
case SEL_BBOX:
|
||||||
|
{
|
||||||
|
char *selllx, *sellly, *selurx, *selury;
|
||||||
|
|
||||||
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
||||||
|
|
||||||
|
selllx = DBWPrintValue(selarea.r_xbot, w, TRUE);
|
||||||
|
sellly = DBWPrintValue(selarea.r_ybot, w, FALSE);
|
||||||
|
selurx = DBWPrintValue(selarea.r_xtop, w, TRUE);
|
||||||
|
selury = DBWPrintValue(selarea.r_ytop, w, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_xbot));
|
Tcl_NewStringObj(selllx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_ybot));
|
Tcl_NewStringObj(sellly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_xtop));
|
Tcl_NewStringObj(selurx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_ytop));
|
Tcl_NewStringObj(selury, -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("Select bounding box: %d %d %d %d\n",
|
TxPrintf("Select bounding box: %s %s %s %s\n",
|
||||||
selarea.r_xbot, selarea.r_ybot,
|
selllx, sellly, selurx, selury);
|
||||||
selarea.r_xtop, selarea.r_ytop);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------
|
/*--------------------------------------------------------------------
|
||||||
* Make a copy of the selection at its present loction but do not
|
* Make a copy of the selection at its present loction but do not
|
||||||
|
|
@ -1121,14 +1127,36 @@ CmdSelect(
|
||||||
|
|
||||||
/*--------------------------------------------------------------------
|
/*--------------------------------------------------------------------
|
||||||
* Move the selection relative to the cell def
|
* Move the selection relative to the cell def
|
||||||
|
* With two additional arguments: Arguments are X and Y position
|
||||||
|
* With no additional arugments: X and Y position taken from pointer.
|
||||||
*--------------------------------------------------------------------
|
*--------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case SEL_MOVE:
|
case SEL_MOVE:
|
||||||
if ((more) || (less) || (primargs != 4)) goto usageError;
|
if ((more) || (less) || ((primargs != 4) && (primargs != 2)))
|
||||||
|
goto usageError;
|
||||||
|
|
||||||
p.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
|
if (primargs == 2)
|
||||||
p.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
|
{
|
||||||
|
MagWindow *window;
|
||||||
|
Rect rootBox;
|
||||||
|
|
||||||
|
window = ToolGetPoint(&p, (Rect *)NULL);
|
||||||
|
if ((window == NULL) ||
|
||||||
|
!ToolGetBox(&SelectRootDef, &rootBox) ||
|
||||||
|
(EditRootDef != ((CellUse *) window->w_surfaceID)->cu_def))
|
||||||
|
{
|
||||||
|
TxError("Error: Pointer is not in the edit cell.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.p_x -= rootBox.r_xbot;
|
||||||
|
p.p_y -= rootBox.r_ybot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
|
||||||
|
p.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Erase first, then recompute the transform */
|
/* Erase first, then recompute the transform */
|
||||||
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
||||||
|
|
@ -1236,15 +1264,17 @@ CmdSelect(
|
||||||
/* of rlist) */
|
/* of rlist) */
|
||||||
SelectClear();
|
SelectClear();
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (rlist != NULL)
|
while (rlist != NULL)
|
||||||
{
|
{
|
||||||
/* Paint rlist back into SelectDef */
|
/* Paint rlist back into SelectDef */
|
||||||
DBPaint(SelectDef, &rlist->r_r, rlist->r_type);
|
DBPaint(SelectDef, &rlist->r_r, rlist->r_type);
|
||||||
|
|
||||||
/* cleanup as we go */
|
/* cleanup as we go */
|
||||||
freeMagic(rlist);
|
freeMagic1(&mm1, rlist);
|
||||||
rlist = rlist->r_next;
|
rlist = rlist->r_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
/* Force erase and redraw of the selection */
|
/* Force erase and redraw of the selection */
|
||||||
DBReComputeBbox(SelectDef);
|
DBReComputeBbox(SelectDef);
|
||||||
|
|
@ -1771,13 +1801,18 @@ cmdLabelSizeFunc(
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
{
|
{
|
||||||
|
char *labsize;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
labsize = DBWPrintValue(label->lab_size / 8, w, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(labsize, -1));
|
||||||
Tcl_NewDoubleObj((double)label->lab_size / 8.0));
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%g\n", (double)label->lab_size / 8.0);
|
TxPrintf("%s\n", labsize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (label->lab_size != *value)
|
else if (label->lab_size != *value)
|
||||||
|
|
@ -1922,18 +1957,22 @@ cmdLabelOffsetFunc(
|
||||||
|
|
||||||
if (point == NULL)
|
if (point == NULL)
|
||||||
{
|
{
|
||||||
|
char *laboffx, *laboffy;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
laboffx = DBWPrintValue(label->lab_offset.p_x / 8, w, TRUE);
|
||||||
|
laboffy = DBWPrintValue(label->lab_offset.p_x / 8, w, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffx, -1));
|
||||||
Tcl_NewDoubleObj((double)label->lab_offset.p_x / 8.0));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffy, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewDoubleObj((double)label->lab_offset.p_y / 8.0));
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%g %g\n", (double)(label->lab_offset.p_x) / 8.0,
|
TxPrintf("%s %s\n", laboffx, laboffy);
|
||||||
(double)(label->lab_offset.p_y) / 8.0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!GEO_SAMEPOINT(label->lab_offset, *point))
|
else if (!GEO_SAMEPOINT(label->lab_offset, *point))
|
||||||
|
|
@ -1963,23 +2002,25 @@ cmdLabelRectFunc(
|
||||||
|
|
||||||
if (rect == NULL)
|
if (rect == NULL)
|
||||||
{
|
{
|
||||||
|
char *labllx, *lablly, *laburx, *labury;
|
||||||
|
|
||||||
|
/* Note: Ideally, the MagWindow pointer should be passed to this function */
|
||||||
|
labllx = DBWPrintValue(label->lab_rect.r_xbot, (MagWindow *)NULL, TRUE);
|
||||||
|
lablly = DBWPrintValue(label->lab_rect.r_ybot, (MagWindow *)NULL, FALSE);
|
||||||
|
laburx = DBWPrintValue(label->lab_rect.r_xtop, (MagWindow *)NULL, TRUE);
|
||||||
|
labury = DBWPrintValue(label->lab_rect.r_ytop, (MagWindow *)NULL, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labllx, -1));
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_xbot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(lablly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laburx, -1));
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_ybot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labury, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_xtop));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_ytop));
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d %d %d %d\n",
|
TxPrintf("%s %s %s %s\n", labllx, lablly, laburx,labury);
|
||||||
label->lab_rect.r_xbot, label->lab_rect.r_ybot,
|
|
||||||
label->lab_rect.r_xtop, label->lab_rect.r_ytop);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!GEO_SAMERECT(label->lab_rect, *rect))
|
else if (!GEO_SAMERECT(label->lab_rect, *rect))
|
||||||
|
|
@ -2180,9 +2221,13 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelTextFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)cmd->tx_argv[argstart + 1] : (ClientData)NULL);
|
cmdLabelTextFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelTextFunc,
|
||||||
|
(ClientData)cmd->tx_argv[argstart + 1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2248,9 +2293,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelFontFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&font : (ClientData)NULL);
|
cmdLabelFontFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelFontFunc, (ClientData)&font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -2278,9 +2326,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelJustFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&pos : (ClientData)NULL);
|
cmdLabelJustFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelJustFunc, (ClientData)&pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2295,11 +2346,13 @@ CmdSetLabel(
|
||||||
{
|
{
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *labsize;
|
||||||
|
|
||||||
|
labsize = DBWPrintValue(DefaultLabel->lab_size, w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp,
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(labsize, -1));
|
||||||
Tcl_NewIntObj(DefaultLabel->lab_size));
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d\n", DefaultLabel->lab_size);
|
TxPrintf("%s\n", labsize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2307,9 +2360,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelSizeFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&size : (ClientData)NULL);
|
cmdLabelSizeFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelSizeFunc, (ClientData)&size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2338,16 +2394,20 @@ CmdSetLabel(
|
||||||
{
|
{
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *laboffx, *laboffy;
|
||||||
|
laboffx = DBWPrintValue(DefaultLabel->lab_offset.p_x, w,
|
||||||
|
TRUE);
|
||||||
|
laboffy = DBWPrintValue(DefaultLabel->lab_offset.p_y, w,
|
||||||
|
FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(DefaultLabel->lab_offset.p_x));
|
Tcl_NewStringObj(laboffx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(DefaultLabel->lab_offset.p_y));
|
Tcl_NewStringObj(laboffy, -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d %d\n", DefaultLabel->lab_offset.p_x,
|
TxPrintf("%s %s\n", laboffx, laboffy);
|
||||||
DefaultLabel->lab_offset.p_y);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2355,9 +2415,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelOffsetFunc, (locargc != 2) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&offset : (ClientData)NULL);
|
cmdLabelOffsetFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelOffsetFunc, (ClientData)&offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2421,10 +2484,12 @@ CmdSetLabel(
|
||||||
rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4],
|
rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4],
|
||||||
TRUE, FALSE, 1);
|
TRUE, FALSE, 1);
|
||||||
}
|
}
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if ((locargc == 3) || (locargc == 6))
|
||||||
cmdLabelRectFunc,
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
((locargc == 6) || (locargc == 3)) ?
|
cmdLabelRectFunc, (ClientData)&rect);
|
||||||
(ClientData)&rect : (ClientData)NULL);
|
else
|
||||||
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelRectFunc, (ClientData)NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2450,9 +2515,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelRotateFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&rotate : (ClientData)NULL);
|
cmdLabelRotateFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelRotateFunc, (ClientData)&rotate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2484,9 +2552,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelStickyFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&flags : (ClientData)NULL);
|
cmdLabelStickyFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelStickyFunc, (ClientData)&flags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2514,7 +2585,7 @@ CmdSetLabel(
|
||||||
else
|
else
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp,
|
Tcl_SetResult(magicinterp,
|
||||||
DBTypeLongNameTbl[DefaultLabel->lab_type],
|
(char*)DBTypeLongNameTbl[DefaultLabel->lab_type], /* Tcl treats as const */
|
||||||
TCL_VOLATILE);
|
TCL_VOLATILE);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s\n", DBTypeLongNameTbl[DefaultLabel->lab_type]);
|
TxPrintf("%s\n", DBTypeLongNameTbl[DefaultLabel->lab_type]);
|
||||||
|
|
@ -2525,9 +2596,12 @@ CmdSetLabel(
|
||||||
}
|
}
|
||||||
else if (EditCellUse)
|
else if (EditCellUse)
|
||||||
{
|
{
|
||||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
if (locargc == 2)
|
||||||
cmdLabelLayerFunc, (locargc == 3) ?
|
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
(ClientData)&ttype : (ClientData)NULL);
|
cmdLabelLayerFunc, (ClientData)NULL);
|
||||||
|
else
|
||||||
|
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||||
|
cmdLabelLayerFunc, (ClientData)&ttype);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2764,7 +2838,7 @@ CmdSimCmd(
|
||||||
{
|
{
|
||||||
static char cmdbuf[200];
|
static char cmdbuf[200];
|
||||||
char *strptr;
|
char *strptr;
|
||||||
char *nodeCmd;
|
const char *nodeCmd;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!SimRsimRunning) {
|
if (!SimRsimRunning) {
|
||||||
|
|
@ -2862,16 +2936,39 @@ CmdSnap(
|
||||||
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Backwards compatibility: Use of "snap" to set units display and
|
||||||
|
* parsing has been deprecated as of February 2026. However, as this
|
||||||
|
* is rather disruptive to existing scripts which use "snap" to change
|
||||||
|
* the parsing of units, then the following measure is being taken
|
||||||
|
* (for now, anyway): If DBWUnits is set to DBW_UNITS_DEFAULT, then
|
||||||
|
* "snap internal" will set DBWUnits as well as DBWSnapToGrid. If
|
||||||
|
* DBWUnits is changed first (e.g., "units internal"), then "snap" will
|
||||||
|
* affect only the snap grid. The older usage will be accompanied by a
|
||||||
|
* warning message. Note that backwards compatibility is being kept
|
||||||
|
* only in the case of "snap internal", which was commonly used in
|
||||||
|
* scripts to make sure that all units were interpreted as internal
|
||||||
|
* units.
|
||||||
|
*/
|
||||||
|
if ((DBWUnits == DBW_UNITS_DEFAULT) && (n == SNAP_INTERNAL))
|
||||||
|
{
|
||||||
|
DBWUnits = DBW_UNITS_INTERNAL;
|
||||||
|
TxError("Warning: snap setting is also changing units. This usage "
|
||||||
|
"is deprecated\nand may be removed in the future. Use "
|
||||||
|
"\"units\" to change units, and\nchange units before "
|
||||||
|
"setting snap to keep this message from appearing.\n");
|
||||||
|
}
|
||||||
|
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
case SNAP_OFF: case SNAP_INTERNAL:
|
case SNAP_OFF: case SNAP_INTERNAL:
|
||||||
DBWSnapToGrid = DBW_SNAP_INTERNAL;
|
DBWSnapToGrid = DBW_UNITS_INTERNAL;
|
||||||
return;
|
return;
|
||||||
case SNAP_LAMBDA:
|
case SNAP_LAMBDA:
|
||||||
DBWSnapToGrid = DBW_SNAP_LAMBDA;
|
DBWSnapToGrid = DBW_UNITS_LAMBDA;
|
||||||
return;
|
return;
|
||||||
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
|
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
|
||||||
DBWSnapToGrid = DBW_SNAP_USER;
|
DBWSnapToGrid = DBW_UNITS_USER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2879,21 +2976,19 @@ printit:
|
||||||
if (n == SNAP_LIST) /* list */
|
if (n == SNAP_LIST) /* list */
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp,
|
Tcl_SetResult(magicinterp,
|
||||||
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"),
|
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"),
|
||||||
TCL_VOLATILE);
|
TCL_VOLATILE);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s\n", (DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
TxPrintf("%s\n", (DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
|
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
TxPrintf("Box is aligned to %s grid\n",
|
TxPrintf("Box is aligned to %s grid\n",
|
||||||
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
|
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,22 @@ TileTypeBitMask CmdYMAllButSpace;
|
||||||
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric
|
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric
|
||||||
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
|
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
|
||||||
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
|
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
|
||||||
* Units without any suffix are assumed to be in lambda if "snap"
|
* Traditional (backwards-compatible) behavior: Units without any suffix
|
||||||
* (DBWSnapToGrid) is set to lambda, grid units if "snap" is set to the
|
* are assumed to be in lambda if "snap" (DBWSnapToGrid) is set to lambda,
|
||||||
* user grid, and internal units otherwise.
|
* grid units if "snap" is set to the user grid, and internal units otherwise.
|
||||||
|
* Current behavior: Use of the "units" command to set the units to
|
||||||
|
* any value other than "default" causes cmdScaleCoord() to parse any
|
||||||
|
* units provided without an identifying suffix as the units indicted by
|
||||||
|
* the "units" command. Once the "units" command has been issued, the
|
||||||
|
* values are dependent on DBWUnits and not on DBWSnapToGrid.
|
||||||
|
*
|
||||||
|
* Additional behavior from magic version 8.3.596: A single command
|
||||||
|
* option can use simple expressions using '+', '-', '*', and '/'. These
|
||||||
|
* can be passed as a single token, without spaces, or within a string
|
||||||
|
* token deliniated by quotes or braces, per usual Tcl syntax. Unlike
|
||||||
|
* the Tcl "expr" command, this can solve arithmetic expressions of
|
||||||
|
* suffixed values, evaluated independently such that different suffixes
|
||||||
|
* may be used (e.g., "1g + 3um" meaning 1 grid pitch plus 3 microns).
|
||||||
*
|
*
|
||||||
* MagWindow argument w is used only with grid-based snapping, to find
|
* MagWindow argument w is used only with grid-based snapping, to find
|
||||||
* the value of the grid for the given window. In this case, because the
|
* the value of the grid for the given window. In this case, because the
|
||||||
|
|
@ -99,6 +112,13 @@ TileTypeBitMask CmdYMAllButSpace;
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define PARSEOP_NONE 0
|
||||||
|
#define PARSEOP_ADD 1
|
||||||
|
#define PARSEOP_SUB 2
|
||||||
|
#define PARSEOP_MUL 3
|
||||||
|
#define PARSEOP_DIV 4
|
||||||
|
#define PARSEOP_END 5
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdScaleCoord(
|
cmdScaleCoord(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
|
|
@ -109,107 +129,195 @@ cmdScaleCoord(
|
||||||
{
|
{
|
||||||
char *endptr;
|
char *endptr;
|
||||||
double dval = 0;
|
double dval = 0;
|
||||||
int mscale = 1;
|
int mscale = 1, curunits;
|
||||||
|
int retval, curval, parseop;
|
||||||
DBWclientRec *crec;
|
DBWclientRec *crec;
|
||||||
|
|
||||||
if (*arg == '{') arg++;
|
if (*arg == '{' || *arg == '"') arg++;
|
||||||
while (isspace(*arg)) arg++;
|
while (isspace(*arg) && (*arg != '\0')) arg++;
|
||||||
|
|
||||||
dval = strtod(arg, &endptr);
|
parseop = PARSEOP_NONE;
|
||||||
dval *= (double)scale;
|
retval = 0;
|
||||||
|
while (*arg != '\0')
|
||||||
|
{
|
||||||
|
dval = strtod(arg, &endptr);
|
||||||
|
dval *= (double)scale;
|
||||||
|
mscale = -1;
|
||||||
|
|
||||||
if (endptr == arg)
|
if (endptr == arg)
|
||||||
{
|
|
||||||
/* strtod() error condition */
|
|
||||||
TxError("Coordinate value cannot be parsed: assuming 0\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((*endptr == 'l')
|
|
||||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_LAMBDA)))
|
|
||||||
{
|
|
||||||
/* lambda or default units */
|
|
||||||
dval *= (double)DBLambda[1];
|
|
||||||
dval /= (double)DBLambda[0];
|
|
||||||
return round(dval);
|
|
||||||
}
|
|
||||||
else if ((*endptr == 'i')
|
|
||||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_INTERNAL)))
|
|
||||||
{
|
|
||||||
/* internal units */
|
|
||||||
return round(dval);
|
|
||||||
}
|
|
||||||
else if ((*endptr == 'g')
|
|
||||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_USER)))
|
|
||||||
{
|
|
||||||
/* grid units */
|
|
||||||
if (w == (MagWindow *)NULL)
|
|
||||||
{
|
{
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
/* strtod() error condition */
|
||||||
if (w == (MagWindow *)NULL)
|
TxError("Coordinate value cannot be parsed: assuming 0\n");
|
||||||
return round(dval); /* Default, if window is unknown */
|
curval = 0;
|
||||||
}
|
break;
|
||||||
crec = (DBWclientRec *) w->w_clientData;
|
|
||||||
if (is_x)
|
|
||||||
{
|
|
||||||
dval *= (double)(crec->dbw_gridRect.r_xtop
|
|
||||||
- crec->dbw_gridRect.r_xbot);
|
|
||||||
if (!is_relative)
|
|
||||||
dval += (double)crec->dbw_gridRect.r_xbot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Original behavior was to accept un-suffixed values according to the
|
||||||
|
* "snap" setting. This behavior remains in effect until the "units"
|
||||||
|
* command is used, in which case units follow the selected units
|
||||||
|
* value indepedendently of the snap setting.
|
||||||
|
*
|
||||||
|
* Updated 12/24/2026 to handle space-separated values (in which
|
||||||
|
* *endptr may be a space as well as NULL).
|
||||||
|
*/
|
||||||
|
if (DBWUnits == DBW_UNITS_DEFAULT)
|
||||||
|
curunits = DBWSnapToGrid;
|
||||||
else
|
else
|
||||||
|
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
|
||||||
|
|
||||||
|
if ((*endptr == 'l')
|
||||||
|
|| (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_LAMBDA)))
|
||||||
{
|
{
|
||||||
dval *= (double)(crec->dbw_gridRect.r_ytop
|
/* lambda or default units */
|
||||||
- crec->dbw_gridRect.r_ybot);
|
dval *= (double)DBLambda[1];
|
||||||
if (!is_relative)
|
dval /= (double)DBLambda[0];
|
||||||
dval += (double)crec->dbw_gridRect.r_ybot;
|
|
||||||
}
|
}
|
||||||
return round(dval);
|
else if ((*endptr == 'i')
|
||||||
}
|
|| (((*endptr == '\0') || isspace(*endptr))
|
||||||
else
|
&& (curunits == DBW_UNITS_INTERNAL)))
|
||||||
{
|
{
|
||||||
/* natural units referred to the current cifoutput style */
|
/* internal units */
|
||||||
if (*(endptr + 1) == 'm')
|
}
|
||||||
|
else if ((*endptr == 'g')
|
||||||
|
|| (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_USER)))
|
||||||
|
{
|
||||||
|
/* grid units */
|
||||||
|
if (w == (MagWindow *)NULL)
|
||||||
|
{
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
if (w == (MagWindow *)NULL)
|
||||||
|
{
|
||||||
|
curval = round(dval); /* Default, if window is unknown */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crec = (DBWclientRec *) w->w_clientData;
|
||||||
|
if (is_x)
|
||||||
|
{
|
||||||
|
dval *= (double)(crec->dbw_gridRect.r_xtop
|
||||||
|
- crec->dbw_gridRect.r_xbot);
|
||||||
|
if (!is_relative)
|
||||||
|
dval += (double)crec->dbw_gridRect.r_xbot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dval *= (double)(crec->dbw_gridRect.r_ytop
|
||||||
|
- crec->dbw_gridRect.r_ybot);
|
||||||
|
if (!is_relative)
|
||||||
|
dval += (double)crec->dbw_gridRect.r_ybot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_MICRONS))
|
||||||
|
{
|
||||||
|
mscale = 1000;
|
||||||
|
}
|
||||||
|
else if (*endptr != '\0')
|
||||||
|
{
|
||||||
|
/* natural units referred to the current cifoutput style */
|
||||||
|
if (*(endptr + 1) == 'm')
|
||||||
|
{
|
||||||
|
switch (*endptr)
|
||||||
|
{
|
||||||
|
case 'n':
|
||||||
|
mscale = 1;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
mscale = 1000;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mscale = 1000000;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
mscale = 10000000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TxError("Unknown metric prefix \"%cm\"; assuming "
|
||||||
|
"internal units\n", *endptr);
|
||||||
|
mscale = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((*endptr == 'u') && !isalnum(*(endptr + 1)))
|
||||||
|
/* Maybe "u" is too ambiguous but it is very commonly used as
|
||||||
|
* an abbreviation for "micron".
|
||||||
|
*/
|
||||||
|
mscale = 1000;
|
||||||
|
else if (!strncmp(endptr, "micron", 6))
|
||||||
|
mscale = 1000;
|
||||||
|
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
|
||||||
|
mscale = 10;
|
||||||
|
else if (!isspace(*endptr) && (*endptr != '+') && (*endptr != '-') &&
|
||||||
|
(*endptr != '*') && (*endptr != '/'))
|
||||||
|
{
|
||||||
|
TxError("Unknown coordinate type at \"%s\"; assuming internal units\n",
|
||||||
|
endptr);
|
||||||
|
mscale = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mscale != -1)
|
||||||
|
dval /= CIFGetOutputScale(mscale);
|
||||||
|
curval = round(dval);
|
||||||
|
|
||||||
|
switch (parseop)
|
||||||
|
{
|
||||||
|
case PARSEOP_NONE:
|
||||||
|
retval = curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_ADD:
|
||||||
|
retval += curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_SUB:
|
||||||
|
retval -= curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_MUL:
|
||||||
|
retval *= curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_DIV:
|
||||||
|
retval /= curval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseop = PARSEOP_NONE;
|
||||||
|
while (*endptr != '\0')
|
||||||
{
|
{
|
||||||
switch (*endptr)
|
switch (*endptr)
|
||||||
{
|
{
|
||||||
case 'n':
|
case '}':
|
||||||
mscale = 1;
|
case '"':
|
||||||
|
parseop = PARSEOP_END;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case '+':
|
||||||
mscale = 1000;
|
parseop = PARSEOP_ADD;
|
||||||
|
endptr++;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case '-':
|
||||||
mscale = 1000000;
|
parseop = PARSEOP_SUB;
|
||||||
|
endptr++;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case '*':
|
||||||
mscale = 10000000;
|
parseop = PARSEOP_MUL;
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
parseop = PARSEOP_DIV;
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
endptr++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TxError("Unknown metric prefix \"%cm\"; assuming internal units\n",
|
/* Should this flag an error? */
|
||||||
*endptr);
|
return retval;
|
||||||
return round(dval);
|
|
||||||
}
|
}
|
||||||
|
if (parseop != PARSEOP_NONE) break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(endptr, "u"))
|
arg = endptr;
|
||||||
/* Maybe "u" is too ambiguous but it is very commonly used as
|
while (isspace(*arg) && (*arg != '\0')) arg++;
|
||||||
* an abbreviation for "micron".
|
|
||||||
*/
|
|
||||||
mscale = 1000;
|
|
||||||
else if (!strncmp(endptr, "micron", 6))
|
|
||||||
mscale = 1000;
|
|
||||||
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
|
|
||||||
mscale = 10;
|
|
||||||
else if (!isspace(*endptr))
|
|
||||||
{
|
|
||||||
TxError("Unknown coordinate type \"%s\"; assuming internal units\n",
|
|
||||||
endptr);
|
|
||||||
return round(dval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!isspace(*endptr))
|
return retval;
|
||||||
dval /= CIFGetOutputScale(mscale);
|
|
||||||
return round(dval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -653,13 +761,16 @@ cmdSaveCell(
|
||||||
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Rename the cell */
|
/* Rename the cell, unless fileName is a .tcl file (scripted output) */
|
||||||
if (!DBCellRenameDef(cellDef, fileName))
|
if ((strlen(fileName) <= 4) || strcmp(fileName + strlen(fileName) - 4, ".tcl"))
|
||||||
{
|
{
|
||||||
/* This should never happen */
|
if (!DBCellRenameDef(cellDef, fileName))
|
||||||
TxError("Magic error: there is already a cell named \"%s\"\n",
|
{
|
||||||
|
/* This should never happen */
|
||||||
|
TxError("Magic error: there is already a cell named \"%s\"\n",
|
||||||
fileName);
|
fileName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
||||||
|
|
@ -1128,7 +1239,7 @@ cmdExpandOneLevel(
|
||||||
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
|
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
|
||||||
|
|
||||||
/* first, expand this cell use */
|
/* first, expand this cell use */
|
||||||
DBExpand(cu, bitmask, expand);
|
DBExpand(cu, bitmask, expand ? DB_EXPAND : DB_UNEXPAND);
|
||||||
|
|
||||||
/* now, unexpand its direct children (ONE LEVEL ONLY) */
|
/* now, unexpand its direct children (ONE LEVEL ONLY) */
|
||||||
if (expand)
|
if (expand)
|
||||||
|
|
@ -1140,7 +1251,7 @@ cmdExpand1func(
|
||||||
CellUse *cu,
|
CellUse *cu,
|
||||||
ClientData bitmask)
|
ClientData bitmask)
|
||||||
{
|
{
|
||||||
DBExpand(cu, (int)CD2INT(bitmask), FALSE);
|
DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
328
commands/CmdTZ.c
328
commands/CmdTZ.c
|
|
@ -61,7 +61,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
|
|
||||||
int
|
int
|
||||||
existFunc(
|
existFunc(
|
||||||
Tile *tile)
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -453,15 +455,18 @@ CmdTech(
|
||||||
}
|
}
|
||||||
if (!strncmp(cmd->tx_argv[2], "width", 5))
|
if (!strncmp(cmd->tx_argv[2], "width", 5))
|
||||||
{
|
{
|
||||||
|
char *techwidth;
|
||||||
tresult = DRCGetDefaultLayerWidth(t1);
|
tresult = DRCGetDefaultLayerWidth(t1);
|
||||||
|
techwidth = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techwidth, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum width is %d\n", tresult);
|
TxPrintf("Minimum width is %s\n", techwidth);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
|
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
|
||||||
{
|
{
|
||||||
|
char *techspace;
|
||||||
if (cmd->tx_argc >= 5)
|
if (cmd->tx_argc >= 5)
|
||||||
{
|
{
|
||||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||||
|
|
@ -473,14 +478,16 @@ CmdTech(
|
||||||
else
|
else
|
||||||
t2 = t1;
|
t2 = t1;
|
||||||
tresult = DRCGetDefaultLayerSpacing(t1, t2);
|
tresult = DRCGetDefaultLayerSpacing(t1, t2);
|
||||||
|
techspace = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techspace, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum spacing is %d\n", tresult);
|
TxPrintf("Minimum spacing is %s\n", techspace);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
|
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
|
||||||
{
|
{
|
||||||
|
char *techsurround;
|
||||||
if (cmd->tx_argc >= 5)
|
if (cmd->tx_argc >= 5)
|
||||||
{
|
{
|
||||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||||
|
|
@ -496,14 +503,17 @@ CmdTech(
|
||||||
}
|
}
|
||||||
|
|
||||||
tresult = DRCGetDefaultLayerSurround(t1, t2);
|
tresult = DRCGetDefaultLayerSurround(t1, t2);
|
||||||
|
techsurround = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techsurround, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum surround is %d\n", tresult);
|
TxPrintf("Minimum surround is %s\n", techsurround);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
|
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
|
||||||
{
|
{
|
||||||
|
char *techdirec;
|
||||||
|
|
||||||
if (cmd->tx_argc >= 5)
|
if (cmd->tx_argc >= 5)
|
||||||
{
|
{
|
||||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||||
|
|
@ -519,10 +529,11 @@ CmdTech(
|
||||||
}
|
}
|
||||||
|
|
||||||
tresult = DRCGetDirectionalLayerSurround(t1, t2);
|
tresult = DRCGetDirectionalLayerSurround(t1, t2);
|
||||||
|
techdirec = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techdirec, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum surround (in one orientation) is %d\n", tresult);
|
TxPrintf("Minimum surround (in one orientation) is %s\n", techdirec);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -671,6 +682,15 @@ CmdTool(
|
||||||
|
|
||||||
if (strcmp(cmd->tx_argv[1], "info") == 0)
|
if (strcmp(cmd->tx_argv[1], "info") == 0)
|
||||||
DBWPrintButtonDoc();
|
DBWPrintButtonDoc();
|
||||||
|
else if (strcmp(cmd->tx_argv[1], "type") == 0)
|
||||||
|
{
|
||||||
|
char *toolType = DBWGetButtonHandler();
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(toolType, -1));
|
||||||
|
#else
|
||||||
|
TxPrintf("Current tool is \"%s\".\n", toolType);
|
||||||
|
#endif /* MAGIC_WRAPPER */
|
||||||
|
}
|
||||||
else (void) DBWChangeButtonHandler(cmd->tx_argv[1]);
|
else (void) DBWChangeButtonHandler(cmd->tx_argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -682,32 +702,62 @@ CmdTool(
|
||||||
* Implement the "unexpand" command.
|
* Implement the "unexpand" command.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* unexpand
|
* unexpand [selection|surround|overlap|all]
|
||||||
|
*
|
||||||
|
* "selection" unexpands (hides) cells in the selection. All
|
||||||
|
* other options unexpand cells in the layout. "all" unexpands
|
||||||
|
* all cells in the layout. "surround" unexpannds cells which
|
||||||
|
* the cursor box surrounds completely, and "overlap" unexpands
|
||||||
|
* cells which the cursor box overlaps.
|
||||||
|
*
|
||||||
|
* For backwards compatibility:
|
||||||
|
* "unexpand" alone implements "unexpand surround".
|
||||||
|
*
|
||||||
|
* Also see: CmdExpand
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Unexpands all cells under the box that don't completely
|
* Changes the expansion state of cells.
|
||||||
* contain the box.
|
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define UNEXPAND_SELECTION 0
|
||||||
|
#define UNEXPAND_SURROUND 1
|
||||||
|
#define UNEXPAND_OVERLAP 2
|
||||||
|
#define UNEXPAND_ALL 3
|
||||||
|
#define UNEXPAND_HELP 4
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdUnexpand(
|
CmdUnexpand(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
int windowMask, boxMask;
|
int windowMask, boxMask, option;
|
||||||
|
const char * const *msg;
|
||||||
Rect rootRect;
|
Rect rootRect;
|
||||||
|
|
||||||
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
||||||
|
|
||||||
if (cmd->tx_argc != 1)
|
static const char * const cmdUnexpandOption[] = {
|
||||||
|
"selection expand cell instances in the selection",
|
||||||
|
"surround expand cell instances which the cursor box surrounds",
|
||||||
|
"overlap expand cell instances which the cursor box overlaps",
|
||||||
|
"all expand all cell instances",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 1)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s\n", cmd->tx_argv[0]);
|
option = Lookup(cmd->tx_argv[1], cmdUnexpandOption);
|
||||||
return;
|
if (option < 0) option = UNEXPAND_HELP;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
option = UNEXPAND_SURROUND;
|
||||||
|
|
||||||
|
if (option == UNEXPAND_HELP) goto badusage;
|
||||||
|
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if (w == (MagWindow *) NULL)
|
if (w == (MagWindow *) NULL)
|
||||||
|
|
@ -723,8 +773,42 @@ CmdUnexpand(
|
||||||
TxError("The box isn't in the same window as the cursor.\n");
|
TxError("The box isn't in the same window as the cursor.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DBExpandAll(((CellUse *) w->w_surfaceID), &rootRect, windowMask,
|
|
||||||
FALSE, cmdUnexpandFunc, (ClientData)(pointertype) windowMask);
|
switch (option)
|
||||||
|
{
|
||||||
|
case UNEXPAND_SELECTION:
|
||||||
|
SelectExpand(windowMask, DB_UNEXPAND, (Rect *)NULL, FALSE);
|
||||||
|
break;
|
||||||
|
case UNEXPAND_OVERLAP:
|
||||||
|
DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
&rootRect, FALSE);
|
||||||
|
break;
|
||||||
|
case UNEXPAND_SURROUND:
|
||||||
|
DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_SURROUND,
|
||||||
|
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_SURROUND,
|
||||||
|
&rootRect, TRUE);
|
||||||
|
break;
|
||||||
|
case UNEXPAND_ALL:
|
||||||
|
DBExpandAll(((CellUse *)w->w_surfaceID), &TiPlaneRect, windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||||
|
SelectExpand(windowMask,
|
||||||
|
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||||
|
(Rect *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
badusage:
|
||||||
|
for (msg = &(cmdUnexpandOption[0]); *msg != NULL; msg++)
|
||||||
|
TxPrintf(" %s\n", *msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called for each cell whose expansion status changed.
|
/* This function is called for each cell whose expansion status changed.
|
||||||
|
|
@ -743,6 +827,182 @@ cmdUnexpandFunc(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* CmdUnits --
|
||||||
|
*
|
||||||
|
* Implement the "units" command.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* units [value] [print|noprint]
|
||||||
|
*
|
||||||
|
* where "value" may be one of "default", "internal", "lambda",
|
||||||
|
* "user" (equivalently "grid"), or "microns".
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The global variable DBWUnits may be changed, which changes the
|
||||||
|
* behavior of magic when interpreting un-suffixed values or
|
||||||
|
* displaying values.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* The units behavior was previously dependent on what command was
|
||||||
|
* issued, with results usually being given in internal units, and
|
||||||
|
* with un-suffixed values following the snap behavior. Backwards-
|
||||||
|
* compatible behavior is used on startup or at any time by setting
|
||||||
|
* the units to "default". Otherwise, unit display follows the
|
||||||
|
* given "units" setting.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UNITS_DEFAULT 0
|
||||||
|
#define UNITS_INTERNAL 1
|
||||||
|
#define UNITS_LAMBDA 2
|
||||||
|
#define UNITS_GRID 3
|
||||||
|
#define UNITS_USER 4
|
||||||
|
#define UNITS_MICRONS 5
|
||||||
|
#define UNITS_LIST 6
|
||||||
|
#define UNITS_PRINT 7
|
||||||
|
#define UNITS_NOPRINT 8
|
||||||
|
|
||||||
|
void
|
||||||
|
CmdUnits(
|
||||||
|
MagWindow *w,
|
||||||
|
TxCommand *cmd)
|
||||||
|
{
|
||||||
|
static const char * const names[] = { "default", "internal", "lambda",
|
||||||
|
"grid", "user", "microns", "list", "print", "noprint", 0 };
|
||||||
|
int idx, n = UNITS_LIST, n2, saveflag;
|
||||||
|
DBWclientRec *crec;
|
||||||
|
|
||||||
|
if (cmd->tx_argc >= 2)
|
||||||
|
{
|
||||||
|
n = Lookup(cmd->tx_argv[1], names);
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
TxPrintf("Usage: units [default | internal | lambda | microns"
|
||||||
|
" | user] [print]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DBWUnits != DBW_UNITS_DEFAULT)
|
||||||
|
saveflag = DBWUnits & DBW_UNITS_PRINT_FLAG;
|
||||||
|
else
|
||||||
|
saveflag = -1;
|
||||||
|
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case UNITS_DEFAULT:
|
||||||
|
DBWUnits = DBW_UNITS_DEFAULT;
|
||||||
|
break;
|
||||||
|
case UNITS_INTERNAL:
|
||||||
|
DBWUnits = DBW_UNITS_INTERNAL;
|
||||||
|
break;
|
||||||
|
case UNITS_LAMBDA:
|
||||||
|
DBWUnits = DBW_UNITS_LAMBDA;
|
||||||
|
break;
|
||||||
|
case UNITS_USER:
|
||||||
|
case UNITS_GRID:
|
||||||
|
DBWUnits = DBW_UNITS_USER;
|
||||||
|
break;
|
||||||
|
case UNITS_MICRONS:
|
||||||
|
DBWUnits = DBW_UNITS_MICRONS;
|
||||||
|
break;
|
||||||
|
case UNITS_PRINT:
|
||||||
|
saveflag = DBW_UNITS_PRINT_FLAG;
|
||||||
|
break;
|
||||||
|
case UNITS_NOPRINT:
|
||||||
|
saveflag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
TxError("Unrecognized units option %s\n.", cmd->tx_argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (n != UNITS_LIST)
|
||||||
|
{
|
||||||
|
if ((cmd->tx_argc == 3) && (n != UNITS_DEFAULT))
|
||||||
|
{
|
||||||
|
n2 = Lookup(cmd->tx_argv[2], names);
|
||||||
|
switch (n2)
|
||||||
|
{
|
||||||
|
case UNITS_PRINT:
|
||||||
|
DBWUnits |= DBW_UNITS_PRINT_FLAG;
|
||||||
|
break;
|
||||||
|
case UNITS_NOPRINT:
|
||||||
|
DBWUnits &= DBW_UNITS_TYPE_MASK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TxError("Unrecognized units option %s\n.", cmd->tx_argv[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((n != UNITS_DEFAULT) && (saveflag != -1))
|
||||||
|
{
|
||||||
|
/* Preserve the previous value of the print/noprint flag */
|
||||||
|
DBWUnits &= DBW_UNITS_TYPE_MASK;
|
||||||
|
DBWUnits |= saveflag;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DBWUnits == DBW_UNITS_DEFAULT)
|
||||||
|
idx = UNITS_DEFAULT;
|
||||||
|
else
|
||||||
|
switch (DBWUnits & DBW_UNITS_TYPE_MASK)
|
||||||
|
{
|
||||||
|
case DBW_UNITS_INTERNAL:
|
||||||
|
idx = UNITS_INTERNAL;
|
||||||
|
break;
|
||||||
|
case DBW_UNITS_LAMBDA:
|
||||||
|
idx = UNITS_LAMBDA;
|
||||||
|
break;
|
||||||
|
case DBW_UNITS_USER:
|
||||||
|
idx = UNITS_USER;
|
||||||
|
break;
|
||||||
|
case DBW_UNITS_MICRONS:
|
||||||
|
idx = UNITS_MICRONS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == UNITS_LIST) /* list */
|
||||||
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj;
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj((char *)names[idx], -1));
|
||||||
|
if (idx != UNITS_DEFAULT)
|
||||||
|
{
|
||||||
|
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj("print", 5));
|
||||||
|
else
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj("noprint", 7));
|
||||||
|
}
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
#else
|
||||||
|
TxPrintf("%s", names[idx]);
|
||||||
|
if (idx != UNITS_DEFAULT)
|
||||||
|
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
|
||||||
|
TxPrintf(" print");
|
||||||
|
TxPrintf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (idx == UNITS_DEFAULT)
|
||||||
|
TxPrintf("Reported units follow the snap setting.\n");
|
||||||
|
else if (DBWUnits & DBW_UNITS_PRINT_FLAG)
|
||||||
|
TxPrintf("Values are reported as %s, along with the units.\n", names[idx]);
|
||||||
|
else
|
||||||
|
TxPrintf("Values are reported as %s\n", names[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -830,7 +1090,8 @@ struct linked_id {
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdWhatPrintCell(
|
cmdWhatPrintCell(
|
||||||
Tile *tile,
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
TreeContext *cxp)
|
TreeContext *cxp)
|
||||||
{
|
{
|
||||||
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
|
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
|
||||||
|
|
@ -885,6 +1146,7 @@ static LabelStore *labelBlockTop, *labelEntry;
|
||||||
int
|
int
|
||||||
cmdFindWhatTileFunc(
|
cmdFindWhatTileFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
ClientData clientData)
|
ClientData clientData)
|
||||||
{
|
{
|
||||||
struct linked_id **lid = (struct linked_id **)clientData;
|
struct linked_id **lid = (struct linked_id **)clientData;
|
||||||
|
|
@ -896,7 +1158,7 @@ cmdFindWhatTileFunc(
|
||||||
scx.scx_use = EditCellUse;
|
scx.scx_use = EditCellUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
type = SplitRightType(tile);
|
type = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
type = SplitLeftType(tile);
|
type = SplitLeftType(tile);
|
||||||
|
|
@ -1094,11 +1356,13 @@ CmdWhat(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (lid != NULL)
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
{
|
while (lid != NULL)
|
||||||
freeMagic(lid);
|
{
|
||||||
|
freeMagic1(&mm1, lid);
|
||||||
lid = lid->lid_next;
|
lid = lid->lid_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doListAll)
|
if (doListAll)
|
||||||
Tcl_ListObjAppendElement(magicinterp, paintobj,
|
Tcl_ListObjAppendElement(magicinterp, paintobj,
|
||||||
|
|
@ -1681,18 +1945,20 @@ CmdWire(
|
||||||
case VALUES:
|
case VALUES:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *wdisp;
|
||||||
width = WireGetWidth();
|
width = WireGetWidth();
|
||||||
type = WireGetType();
|
type = WireGetType();
|
||||||
|
wdisp = DBWPrintValue(width, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
|
||||||
Tcl_NewIntObj(width));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
|
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(wdisp, -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("Wire layer %s, width %d\n",
|
TxPrintf("Wire layer %s, width %s\n",
|
||||||
DBTypeLongNameTbl[type], width);
|
DBTypeLongNameTbl[type], wdisp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1717,12 +1983,14 @@ CmdWire(
|
||||||
case WIDTH:
|
case WIDTH:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *wdisp;
|
||||||
width = WireGetWidth();
|
width = WireGetWidth();
|
||||||
|
wdisp = DBWPrintValue(width, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewIntObj(width);
|
lobj = Tcl_NewStringObj(wdisp, -1);
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("Wire width is %d\n", width);
|
TxPrintf("Wire width is %s\n", wdisp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (locargc != 3)
|
else if (locargc != 3)
|
||||||
|
|
@ -1945,7 +2213,7 @@ CmdWriteall(
|
||||||
option = Lookup(cmd->tx_argv[1], writeallOpts);
|
option = Lookup(cmd->tx_argv[1], writeallOpts);
|
||||||
if (option < 0)
|
if (option < 0)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s [force|modified|noupdate [cellname ...]]\n",
|
TxError("Usage: %s [force|modified [cellname ...]]\n",
|
||||||
cmd->tx_argv[0]);
|
cmd->tx_argv[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,10 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
|
|
||||||
|
/* For diagnostics */
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
#include "database/databaseInt.h"
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
|
|
||||||
|
|
@ -189,6 +193,234 @@ CmdExtractTest(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* tileCountProc --
|
||||||
|
*
|
||||||
|
* Routine to count tiles.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* 0 to keep the search going
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Keeps count in clientData
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
tileCountProc(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
int *tcount)
|
||||||
|
{
|
||||||
|
(*tcount)++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* showMem --
|
||||||
|
* CmdShowmem --
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* showmem [outfile]
|
||||||
|
*
|
||||||
|
* Display all the (principle) internal memory usage for tiles, including
|
||||||
|
* all cell defs, and all CIF generated planes.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* May write to a disk file.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
showMem(
|
||||||
|
FILE *outf, /* File to which information is to be output */
|
||||||
|
bool verbose) /* If TRUE, output detailed erase table */
|
||||||
|
{
|
||||||
|
int ttotal, ttotal1, ttotal2;
|
||||||
|
int i;
|
||||||
|
Plane *plane;
|
||||||
|
CellDef *def;
|
||||||
|
int pNum;
|
||||||
|
HashSearch hs;
|
||||||
|
HashEntry *entry;
|
||||||
|
|
||||||
|
fprintf(outf, "Tile memory usage summary\n");
|
||||||
|
fprintf(outf, "Technology %s\n", DBTechName);
|
||||||
|
|
||||||
|
/* Search every cell def (including internal ones), count tiles,
|
||||||
|
* and add up the tile memory usage on every plane.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Search the CIFPlanes and count tiles. */
|
||||||
|
/* CIFPlanes, CIFTotalPlanes, CIFComponentPlanes */
|
||||||
|
|
||||||
|
ttotal2 = 0;
|
||||||
|
if (CIFCurStyle != NULL)
|
||||||
|
{
|
||||||
|
fprintf(outf, "\nCIFPlanes:\n");
|
||||||
|
ttotal1 = 0;
|
||||||
|
for (i = 0; i < MAXCIFLAYERS; i++)
|
||||||
|
{
|
||||||
|
plane = CIFPlanes[i];
|
||||||
|
if (plane != NULL)
|
||||||
|
{
|
||||||
|
ttotal = 0;
|
||||||
|
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
||||||
|
&DBAllTypeBits, tileCountProc, &ttotal);
|
||||||
|
ttotal1 += ttotal;
|
||||||
|
|
||||||
|
if (CIFCurStyle->cs_layers[i])
|
||||||
|
fprintf(outf, " layer %s: %ld\n",
|
||||||
|
CIFCurStyle->cs_layers[i]->cl_name,
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
else
|
||||||
|
fprintf(outf, " layer %d: %d\n", i,
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(outf, " Subtotal: %ld bytes\n",
|
||||||
|
(long)ttotal1 * (long)sizeof(Tile));
|
||||||
|
ttotal2 += ttotal1;
|
||||||
|
|
||||||
|
fprintf(outf, "\nCIFTotalPlanes\n");
|
||||||
|
ttotal1 = 0;
|
||||||
|
for (i = 0; i < MAXCIFLAYERS; i++)
|
||||||
|
{
|
||||||
|
plane = CIFTotalPlanes[i];
|
||||||
|
if (plane != NULL)
|
||||||
|
{
|
||||||
|
ttotal = 0;
|
||||||
|
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
||||||
|
&DBAllTypeBits, tileCountProc, &ttotal);
|
||||||
|
ttotal1 += ttotal;
|
||||||
|
|
||||||
|
if (CIFCurStyle->cs_layers[i])
|
||||||
|
fprintf(outf, " layer %s: %ld\n",
|
||||||
|
CIFCurStyle->cs_layers[i]->cl_name,
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
else
|
||||||
|
fprintf(outf, " layer %d: %d\n", i,
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(outf, " Subtotal: %ld bytes\n",
|
||||||
|
(long)ttotal1 * (long)sizeof(Tile));
|
||||||
|
ttotal2 += ttotal1;
|
||||||
|
|
||||||
|
fprintf(outf, "\nCIFComponentPlanes\n");
|
||||||
|
ttotal1 = 0;
|
||||||
|
for (i = 0; i < MAXCIFLAYERS; i++)
|
||||||
|
{
|
||||||
|
plane = CIFComponentPlanes[i];
|
||||||
|
if (plane != NULL)
|
||||||
|
{
|
||||||
|
ttotal = 0;
|
||||||
|
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
||||||
|
&DBAllTypeBits, tileCountProc, &ttotal);
|
||||||
|
ttotal1 += ttotal;
|
||||||
|
|
||||||
|
if (CIFCurStyle->cs_layers[i])
|
||||||
|
fprintf(outf, " layer %s: %ld bytes\n",
|
||||||
|
CIFCurStyle->cs_layers[i]->cl_name,
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
else
|
||||||
|
fprintf(outf, " layer %d: %ld bytes\n", i,
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(outf, " Subtotal: %ld bytes\n",
|
||||||
|
(long)ttotal1 * (long)sizeof(Tile));
|
||||||
|
ttotal2 += ttotal1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(outf, "CIF planes: No memory usage\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while ((entry = HashNext(&dbCellDefTable, &hs)) != NULL)
|
||||||
|
{
|
||||||
|
def = (CellDef *)HashGetValue(entry);
|
||||||
|
if (def != (CellDef *)NULL)
|
||||||
|
{
|
||||||
|
fprintf(outf, "\nCell def %s\n", def->cd_name);
|
||||||
|
ttotal1 = 0;
|
||||||
|
for (pNum = 0; pNum < DBNumPlanes; pNum++)
|
||||||
|
{
|
||||||
|
plane = def->cd_planes[pNum];
|
||||||
|
if (plane != NULL)
|
||||||
|
{
|
||||||
|
ttotal = 0;
|
||||||
|
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
||||||
|
&DBAllTypeBits, tileCountProc, &ttotal);
|
||||||
|
|
||||||
|
fprintf(outf, " plane %s: %ld bytes\n",
|
||||||
|
DBPlaneLongNameTbl[pNum],
|
||||||
|
(long)ttotal * (long)sizeof(Tile));
|
||||||
|
ttotal1 += ttotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(outf, " Subtotal: %ld bytes\n",
|
||||||
|
(long)ttotal1 * (long)sizeof(Tile));
|
||||||
|
ttotal2 += ttotal1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(outf, " Grand total: %ld bytes\n",
|
||||||
|
(long)ttotal2 * (long)sizeof(Tile));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CmdShowmem(
|
||||||
|
MagWindow *w,
|
||||||
|
TxCommand *cmd)
|
||||||
|
{
|
||||||
|
FILE *outf;
|
||||||
|
bool verbose;
|
||||||
|
char **av;
|
||||||
|
int ac;
|
||||||
|
|
||||||
|
if (cmd->tx_argc > 3)
|
||||||
|
{
|
||||||
|
TxError("Usage: showmem [-v] [file]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose = FALSE;
|
||||||
|
av = &cmd->tx_argv[1];
|
||||||
|
ac = cmd->tx_argc - 1;
|
||||||
|
|
||||||
|
outf = stdout;
|
||||||
|
if (ac > 0 && strcmp(av[0], "-v") == 0)
|
||||||
|
{
|
||||||
|
verbose = TRUE;
|
||||||
|
av++, ac--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ac > 0)
|
||||||
|
{
|
||||||
|
outf = fopen(av[0], "w");
|
||||||
|
if (outf == (FILE *) NULL)
|
||||||
|
{
|
||||||
|
perror(av[0]);
|
||||||
|
TxError("Nothing written\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showMem(outf, verbose);
|
||||||
|
if (outf != stdout)
|
||||||
|
(void) fclose(outf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -232,7 +464,7 @@ showTech(
|
||||||
fprintf(outf, "\n");
|
fprintf(outf, "\n");
|
||||||
fprintf(outf, "Types:\n");
|
fprintf(outf, "Types:\n");
|
||||||
for (i = 0; i < DBNumTypes; i++) {
|
for (i = 0; i < DBNumTypes; i++) {
|
||||||
int pl ; char *spl ;
|
int pl ; const char *spl ;
|
||||||
|
|
||||||
pl = DBPlane(i);
|
pl = DBPlane(i);
|
||||||
spl = ( pl <= 0 || pl > DBNumPlanes ) ? "??" : DBPlaneLongName(pl);
|
spl = ( pl <= 0 || pl > DBNumPlanes ) ? "??" : DBPlaneLongName(pl);
|
||||||
|
|
@ -569,11 +801,13 @@ cmdStatsCount(
|
||||||
CellDef *def,
|
CellDef *def,
|
||||||
struct countClient *cc)
|
struct countClient *cc)
|
||||||
{
|
{
|
||||||
int cmdStatsCountTile(Tile *tile, struct cellInfo *ci);
|
|
||||||
int pNum;
|
int pNum;
|
||||||
struct cellInfo *ci;
|
struct cellInfo *ci;
|
||||||
TileType t;
|
TileType t;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int cmdStatsCountTile(Tile *tile, TileType dinfo, struct cellInfo *ci);
|
||||||
|
|
||||||
if (def->cd_client)
|
if (def->cd_client)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
|
|
@ -598,6 +832,7 @@ cmdStatsCount(
|
||||||
int
|
int
|
||||||
cmdStatsCountTile(
|
cmdStatsCountTile(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
struct cellInfo *ci)
|
struct cellInfo *ci)
|
||||||
{
|
{
|
||||||
TileType type = TiGetType(tile);
|
TileType type = TiGetType(tile);
|
||||||
|
|
@ -868,17 +1103,18 @@ CmdTsearch(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
int cmdTsrFunc(Tile *tp);
|
|
||||||
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
|
|
||||||
char *rstatp;
|
char *rstatp;
|
||||||
static TileTypeBitMask mask;
|
static TileTypeBitMask mask;
|
||||||
static struct tms tlast, tdelta;
|
static struct tms tlast, tdelta;
|
||||||
Rect rtool, rsearch;
|
Rect rtool, rsearch;
|
||||||
/**** Rect *ebox; ****/
|
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
int i, pNum, count;
|
int i, pNum, count;
|
||||||
int usPerSearch, usPerTile, usPerL2, us, boxarea;
|
int usPerSearch, usPerTile, usPerL2, us, boxarea;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
int cmdTsrFunc(Tile *tp, TileType dinfo, ClientData clientdata);
|
||||||
|
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
|
||||||
|
|
||||||
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
||||||
{
|
{
|
||||||
TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
|
TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
|
||||||
|
|
@ -978,10 +1214,12 @@ CmdTsearch(
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdTsrFunc(
|
cmdTsrFunc(
|
||||||
Tile *tp)
|
Tile *tp,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
if (cmdTsearchDebug)
|
if (cmdTsearchDebug)
|
||||||
TxPrintf("%lx\n", (intmax_t) tp);
|
TxPrintf("%lx\n", (intptr_t) tp);
|
||||||
numTilesFound++;
|
numTilesFound++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1047,7 +1285,7 @@ CmdWatch(
|
||||||
pNum = DBTechNamePlane(cmd->tx_argv[1]);
|
pNum = DBTechNamePlane(cmd->tx_argv[1]);
|
||||||
if (pNum < 0)
|
if (pNum < 0)
|
||||||
{
|
{
|
||||||
char *cp;
|
const char *cp;
|
||||||
TxError("Unrecognized plane: %s. Legal names are:\n",
|
TxError("Unrecognized plane: %s. Legal names are:\n",
|
||||||
cmd->tx_argv[1]);
|
cmd->tx_argv[1]);
|
||||||
for(pNum=0; pNum < PL_MAXTYPES; pNum++) {
|
for(pNum=0; pNum < PL_MAXTYPES; pNum++) {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ extern int cmdParseCoord(MagWindow *w, char *arg, bool is_relative, bool is_x);
|
||||||
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
||||||
extern void CmdInit(void);
|
extern void CmdInit(void);
|
||||||
|
|
||||||
extern void CmdDoProperty(CellDef *def, TxCommand *cmd, int argstart);
|
extern void CmdDoProperty(CellDef *def, MagWindow *w, TxCommand *cmd, int argstart);
|
||||||
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
||||||
|
|
||||||
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
||||||
|
|
|
||||||
|
|
@ -30,19 +30,32 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
typedef struct dbcellboundstruct
|
typedef struct dbcellboundstruct
|
||||||
{
|
{
|
||||||
Rect *area;
|
Rect *area;
|
||||||
bool extended;
|
Rect *extended;
|
||||||
bool found;
|
bool found;
|
||||||
} DBCellBoundStruct;
|
} DBCellBoundStruct;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
|
* DBBoundCellPlane ---
|
||||||
|
*
|
||||||
|
* Find the extents of all subcells of the cell "def", both the
|
||||||
|
* extent of geometry (rect) and the extent of geometry plus any
|
||||||
|
* labels extending outside the extent of geometry (extended).
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* TRUE if subcells were found and measured; FALSE if no subcells
|
||||||
|
* were found (in which case "extended" and "rect" may not be
|
||||||
|
* valid).
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Values may be recorded in "extended" and "rect".
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
DBBoundCellPlane(def, extended, rect)
|
DBBoundCellPlane(def, extended, rect)
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
bool extended;
|
Rect *extended;
|
||||||
Rect *rect;
|
Rect *rect;
|
||||||
{
|
{
|
||||||
TreeFilter filter;
|
TreeFilter filter;
|
||||||
|
|
@ -70,25 +83,19 @@ dbCellBoundFunc(use, fp)
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
TreeFilter *fp;
|
TreeFilter *fp;
|
||||||
{
|
{
|
||||||
Rect *bbox;
|
|
||||||
DBCellBoundStruct *cbs;
|
DBCellBoundStruct *cbs;
|
||||||
|
|
||||||
cbs = (DBCellBoundStruct *)fp->tf_arg;
|
cbs = (DBCellBoundStruct *)fp->tf_arg;
|
||||||
|
|
||||||
bbox = &use->cu_bbox;
|
|
||||||
if (cbs->found)
|
if (cbs->found)
|
||||||
{
|
{
|
||||||
if (cbs->extended)
|
GeoInclude(&use->cu_extended, cbs->extended);
|
||||||
GeoInclude(&use->cu_extended, cbs->area);
|
GeoInclude(&use->cu_bbox, cbs->area);
|
||||||
else
|
|
||||||
GeoInclude(&use->cu_bbox, cbs->area);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cbs->extended)
|
*cbs->extended = use->cu_extended;
|
||||||
*cbs->area = use->cu_extended;
|
*cbs->area = use->cu_bbox;
|
||||||
else
|
|
||||||
*cbs->area = use->cu_bbox;
|
|
||||||
cbs->found = TRUE;
|
cbs->found = TRUE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -108,16 +108,55 @@ DBCellFindDup(use, parent)
|
||||||
"DBCellFindDup");
|
"DBCellFindDup");
|
||||||
while ((dupUse = BPEnumNext(&bpe)))
|
while ((dupUse = BPEnumNext(&bpe)))
|
||||||
if (dupUse->cu_def == use->cu_def)
|
if (dupUse->cu_def == use->cu_def)
|
||||||
|
{
|
||||||
|
bool transMatch, arrayMatch, notXarray, notYarray;
|
||||||
|
|
||||||
/* Transforms must be equal---Aligned bounding boxes are
|
/* Transforms must be equal---Aligned bounding boxes are
|
||||||
* an insufficient measure of exact overlap.
|
* an insufficient measure of exact overlap. Also, array
|
||||||
|
* counts and separation must match for arrayed devices
|
||||||
*/
|
*/
|
||||||
if ((dupUse->cu_transform.t_a == use->cu_transform.t_a) &&
|
transMatch = ((dupUse->cu_transform.t_a == use->cu_transform.t_a) &&
|
||||||
(dupUse->cu_transform.t_b == use->cu_transform.t_b) &&
|
(dupUse->cu_transform.t_b == use->cu_transform.t_b) &&
|
||||||
(dupUse->cu_transform.t_c == use->cu_transform.t_c) &&
|
(dupUse->cu_transform.t_c == use->cu_transform.t_c) &&
|
||||||
(dupUse->cu_transform.t_d == use->cu_transform.t_d) &&
|
(dupUse->cu_transform.t_d == use->cu_transform.t_d) &&
|
||||||
(dupUse->cu_transform.t_e == use->cu_transform.t_e) &&
|
(dupUse->cu_transform.t_e == use->cu_transform.t_e) &&
|
||||||
(dupUse->cu_transform.t_f == use->cu_transform.t_f))
|
(dupUse->cu_transform.t_f == use->cu_transform.t_f));
|
||||||
|
|
||||||
|
/* First check if both use and dupUse are not arrays. */
|
||||||
|
notXarray = (dupUse->cu_xhi == dupUse->cu_xlo) &&
|
||||||
|
(use->cu_xhi == use->cu_xlo);
|
||||||
|
|
||||||
|
notYarray = (dupUse->cu_yhi == dupUse->cu_ylo) &&
|
||||||
|
(use->cu_yhi == use->cu_ylo);
|
||||||
|
|
||||||
|
arrayMatch = (notXarray && notYarray);
|
||||||
|
|
||||||
|
/* If they are arrays, then the array parameters must match. */
|
||||||
|
|
||||||
|
if (!notXarray && notYarray)
|
||||||
|
{
|
||||||
|
arrayMatch = ((dupUse->cu_xhi - dupUse->cu_xlo) ==
|
||||||
|
(use->cu_xhi - use->cu_xlo)) &&
|
||||||
|
(dupUse->cu_xsep == use->cu_xsep);
|
||||||
|
}
|
||||||
|
else if (!notYarray && notXarray)
|
||||||
|
{
|
||||||
|
arrayMatch = ((dupUse->cu_yhi - dupUse->cu_ylo) ==
|
||||||
|
(use->cu_yhi - use->cu_ylo)) &&
|
||||||
|
(dupUse->cu_ysep == use->cu_ysep);
|
||||||
|
}
|
||||||
|
else if (!notYarray && !notXarray)
|
||||||
|
{
|
||||||
|
arrayMatch = (((dupUse->cu_xhi - dupUse->cu_xlo) ==
|
||||||
|
(use->cu_xhi - use->cu_xlo)) &&
|
||||||
|
(dupUse->cu_xsep == use->cu_xsep)) &&
|
||||||
|
(((dupUse->cu_yhi - dupUse->cu_ylo) ==
|
||||||
|
(use->cu_yhi - use->cu_ylo)) &&
|
||||||
|
(dupUse->cu_ysep == use->cu_ysep));
|
||||||
|
}
|
||||||
|
if (transMatch && arrayMatch)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
BPEnumTerm(&bpe);
|
BPEnumTerm(&bpe);
|
||||||
return dupUse;
|
return dupUse;
|
||||||
|
|
|
||||||
|
|
@ -619,8 +619,9 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
|
||||||
/*
|
/*
|
||||||
* Include area of subcells separately
|
* Include area of subcells separately
|
||||||
*/
|
*/
|
||||||
if ((foundAny = DBBoundCellPlane(cellDef, TRUE, &rect)) > 0)
|
if (!((foundAny = DBBoundCellPlane(cellDef, &extended, &rect)) > 0))
|
||||||
area = rect;
|
extended = GeoNullRect;
|
||||||
|
area = rect;
|
||||||
|
|
||||||
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
||||||
if (pNum != PL_DRC_CHECK)
|
if (pNum != PL_DRC_CHECK)
|
||||||
|
|
@ -634,7 +635,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Include the area of labels, too.
|
* Include the area of label anchors, too.
|
||||||
*/
|
*/
|
||||||
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
|
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
|
||||||
{
|
{
|
||||||
|
|
@ -656,7 +657,11 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extended = area;
|
/* Make sure the extended bounding box includes the area of all
|
||||||
|
* paint material just found, then include the area of all text
|
||||||
|
* in the current cell.
|
||||||
|
*/
|
||||||
|
GeoInclude(&area, &extended);
|
||||||
if (foundAny)
|
if (foundAny)
|
||||||
{
|
{
|
||||||
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
|
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
|
||||||
|
|
@ -673,6 +678,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
|
||||||
degenerate = TRUE;
|
degenerate = TRUE;
|
||||||
area.r_xbot = area.r_ybot = 0;
|
area.r_xbot = area.r_ybot = 0;
|
||||||
area.r_xtop = area.r_ytop = 1;
|
area.r_xtop = area.r_ytop = 1;
|
||||||
|
extended = area;
|
||||||
}
|
}
|
||||||
else degenerate = FALSE;
|
else degenerate = FALSE;
|
||||||
|
|
||||||
|
|
@ -687,7 +693,11 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
|
||||||
if (area.r_ybot == area.r_ytop)
|
if (area.r_ybot == area.r_ytop)
|
||||||
area.r_ytop = area.r_ybot + 1;
|
area.r_ytop = area.r_ybot + 1;
|
||||||
|
|
||||||
if (degenerate) extended = area;
|
if (extended.r_xbot == extended.r_xtop)
|
||||||
|
extended.r_xtop = extended.r_xbot + 1;
|
||||||
|
|
||||||
|
if (extended.r_ybot == extended.r_ytop)
|
||||||
|
extended.r_ytop = extended.r_ybot + 1;
|
||||||
|
|
||||||
/* Did the bounding box change? If not then there's no need to
|
/* Did the bounding box change? If not then there's no need to
|
||||||
* recompute the parents. If the cell has no material, then
|
* recompute the parents. If the cell has no material, then
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
|
|
||||||
/* C99 compat */
|
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following variable points to the tables currently used for
|
* The following variable points to the tables currently used for
|
||||||
|
|
@ -357,9 +356,43 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
|
||||||
struct propUseDefStruct {
|
struct propUseDefStruct {
|
||||||
CellDef *puds_source;
|
CellDef *puds_source;
|
||||||
CellDef *puds_dest;
|
CellDef *puds_dest;
|
||||||
|
Plane *puds_plane; /* Mask hint plane in dest */
|
||||||
Transform *puds_trans; /* Transform from source use to dest */
|
Transform *puds_trans; /* Transform from source use to dest */
|
||||||
|
Rect *puds_area; /* Clip area in source coordinates */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbCopyMaskHintPlaneFunc --
|
||||||
|
*
|
||||||
|
* Translate tiles from a child mask-hint property plane into the
|
||||||
|
* coordinate system of the parent, and paint the mask-hint area
|
||||||
|
* into the mask-hint property plane of the parent.
|
||||||
|
*
|
||||||
|
*-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
dbCopyMaskHintPlaneFunc(Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
struct propUseDefStruct *puds)
|
||||||
|
{
|
||||||
|
Transform *trans = puds->puds_trans;
|
||||||
|
Rect *clip = puds->puds_area;
|
||||||
|
Rect r, rnew;
|
||||||
|
Plane *plane = puds->puds_plane;
|
||||||
|
|
||||||
|
TiToRect(tile, &r);
|
||||||
|
GeoClip(&r, clip);
|
||||||
|
if (!GEO_RECTNULL(&r))
|
||||||
|
{
|
||||||
|
GeoTransRect(trans, &r, &rnew);
|
||||||
|
DBPaintPlane(plane, &rnew, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -380,63 +413,52 @@ struct propUseDefStruct {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyMaskHintsFunc(key, value, puds)
|
dbCopyMaskHintsFunc(key, proprec, puds)
|
||||||
char *key;
|
char *key;
|
||||||
ClientData value;
|
PropertyRecord *proprec;
|
||||||
struct propUseDefStruct *puds;
|
struct propUseDefStruct *puds;
|
||||||
{
|
{
|
||||||
CellDef *dest = puds->puds_dest;
|
CellDef *dest = puds->puds_dest;
|
||||||
Transform *trans = puds->puds_trans;
|
Transform *trans = puds->puds_trans;
|
||||||
char *propstr = (char *)value;
|
Rect *clip = puds->puds_area;
|
||||||
|
PropertyRecord *parentproprec, *newproprec;
|
||||||
char *parentprop, *newvalue, *vptr;
|
char *parentprop, *newvalue, *vptr;
|
||||||
Rect r, rnew;
|
Rect r, rnew;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
if (!strncmp(key, "MASKHINTS_", 10))
|
if (!strncmp(key, "MASKHINTS_", 10))
|
||||||
{
|
{
|
||||||
char *vptr, *lastval;
|
char *vptr, *lastval;
|
||||||
int lastlen;
|
int lastlen;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
/* Append to existing mask hint (if any) */
|
ASSERT(proprec->prop_type == PROPERTY_TYPE_PLANE, "dbCopyMaskHintsFunc");
|
||||||
parentprop = (char *)DBPropGet(dest, key, &propfound);
|
|
||||||
newvalue = (propfound) ? StrDup((char **)NULL, parentprop) : (char *)NULL;
|
|
||||||
|
|
||||||
vptr = propstr;
|
/* Get the existing mask hint plane in the parent cell, and
|
||||||
while (*vptr != '\0')
|
* create it if it does not already exist.
|
||||||
|
*/
|
||||||
|
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
|
||||||
|
|
||||||
|
if (propfound)
|
||||||
|
plane = parentproprec->prop_value.prop_plane;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
{
|
newproprec->prop_len = 0;
|
||||||
GeoTransRect(trans, &r, &rnew);
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
newproprec->prop_value.prop_plane = plane;
|
||||||
lastval = newvalue;
|
DBPropPut(dest, key, newproprec);
|
||||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
|
||||||
newvalue = mallocMagic(40 + lastlen);
|
|
||||||
|
|
||||||
if (lastval)
|
|
||||||
strcpy(newvalue, lastval);
|
|
||||||
else
|
|
||||||
*newvalue = '\0';
|
|
||||||
|
|
||||||
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
|
||||||
rnew.r_xbot, rnew.r_ybot, rnew.r_xtop, rnew.r_ytop);
|
|
||||||
if (lastval) freeMagic(lastval);
|
|
||||||
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
if (newvalue)
|
puds->puds_plane = plane;
|
||||||
DBPropPut(dest, key, newvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Copy the properties from child to parent */
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
clip, &CIFSolidBits, dbCopyMaskHintPlaneFunc,
|
||||||
|
(ClientData)puds);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,6 +490,7 @@ DBCellCopyMaskHints(child, parent, transform)
|
||||||
puds.puds_source = child->cu_def;
|
puds.puds_source = child->cu_def;
|
||||||
puds.puds_dest = parent;
|
puds.puds_dest = parent;
|
||||||
puds.puds_trans = transform;
|
puds.puds_trans = transform;
|
||||||
|
puds.puds_area = (Rect *)&TiPlaneRect;
|
||||||
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,6 +524,7 @@ dbFlatCopyMaskHintsFunc(scx, def)
|
||||||
puds.puds_source = scx->scx_use->cu_def;
|
puds.puds_source = scx->scx_use->cu_def;
|
||||||
puds.puds_dest = def;
|
puds.puds_dest = def;
|
||||||
puds.puds_trans = &scx->scx_trans;
|
puds.puds_trans = &scx->scx_trans;
|
||||||
|
puds.puds_area = &scx->scx_area;
|
||||||
|
|
||||||
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||||
|
|
||||||
|
|
@ -967,14 +991,15 @@ DBCellGenerateSimpleSubstrate(scx, subType, notSubMask, targetDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbEraseSubFunc(tile, cxp)
|
dbEraseSubFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to source tile with shield type */
|
Tile *tile; /* Pointer to source tile with shield type */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo, loctype, subType;
|
TileType newdinfo, loctype, subType;
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
struct dbCopySubData *csd; /* Client data */
|
struct dbCopySubData *csd; /* Client data */
|
||||||
|
|
||||||
|
|
@ -983,13 +1008,14 @@ dbEraseSubFunc(tile, cxp)
|
||||||
plane = csd->csd_plane;
|
plane = csd->csd_plane;
|
||||||
pNum = csd->csd_pNum;
|
pNum = csd->csd_pNum;
|
||||||
subType = csd->csd_subtype;
|
subType = csd->csd_subtype;
|
||||||
dinfo = TiGetTypeExact(tile);
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
newdinfo = (TileType)0;
|
||||||
|
|
||||||
/* Construct the rect for the tile */
|
/* Construct the rect for the tile */
|
||||||
TITORECT(tile, &sourceRect);
|
TITORECT(tile, &sourceRect);
|
||||||
|
|
@ -999,7 +1025,7 @@ dbEraseSubFunc(tile, cxp)
|
||||||
|
|
||||||
csd->csd_modified = TRUE;
|
csd->csd_modified = TRUE;
|
||||||
|
|
||||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1011,14 +1037,15 @@ dbEraseSubFunc(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbPaintSubFunc(tile, cxp)
|
dbPaintSubFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to source tile with shield type */
|
Tile *tile; /* Pointer to source tile with shield type */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo, loctype, subType;
|
TileType newdinfo, loctype, subType;
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
struct dbCopySubData *csd; /* Client data */
|
struct dbCopySubData *csd; /* Client data */
|
||||||
|
|
||||||
|
|
@ -1027,13 +1054,14 @@ dbPaintSubFunc(tile, cxp)
|
||||||
plane = csd->csd_plane;
|
plane = csd->csd_plane;
|
||||||
pNum = csd->csd_pNum;
|
pNum = csd->csd_pNum;
|
||||||
subType = csd->csd_subtype;
|
subType = csd->csd_subtype;
|
||||||
dinfo = TiGetTypeExact(tile);
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
newdinfo = (TileType)0;
|
||||||
|
|
||||||
/* Construct the rect for the tile */
|
/* Construct the rect for the tile */
|
||||||
TITORECT(tile, &sourceRect);
|
TITORECT(tile, &sourceRect);
|
||||||
|
|
@ -1043,7 +1071,7 @@ dbPaintSubFunc(tile, cxp)
|
||||||
|
|
||||||
csd->csd_modified = TRUE;
|
csd->csd_modified = TRUE;
|
||||||
|
|
||||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdPaintTbl(subType, pNum),
|
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdPaintTbl(subType, pNum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,14 +1084,15 @@ dbPaintSubFunc(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbEraseNonSub(tile, cxp)
|
dbEraseNonSub(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to tile to erase from target */
|
Tile *tile; /* Pointer to tile to erase from target */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
Plane *plane; /* Plane of target data */
|
Plane *plane; /* Plane of target data */
|
||||||
TileType dinfo, loctype, subType;
|
TileType newdinfo, loctype, subType;
|
||||||
struct dbCopySubData *csd;
|
struct dbCopySubData *csd;
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
|
|
@ -1074,13 +1103,14 @@ dbEraseNonSub(tile, cxp)
|
||||||
|
|
||||||
scx = cxp->tc_scx;
|
scx = cxp->tc_scx;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile);
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
newdinfo = (TileType)0;
|
||||||
|
|
||||||
/* Construct the rect for the tile */
|
/* Construct the rect for the tile */
|
||||||
TITORECT(tile, &sourceRect);
|
TITORECT(tile, &sourceRect);
|
||||||
|
|
@ -1089,7 +1119,7 @@ dbEraseNonSub(tile, cxp)
|
||||||
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
|
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
|
||||||
|
|
||||||
/* Erase the substrate type from the area of this tile in the target plane. */
|
/* Erase the substrate type from the area of this tile in the target plane. */
|
||||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1101,8 +1131,9 @@ dbEraseNonSub(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopySubFunc(tile, csd)
|
dbCopySubFunc(tile, dinfo, csd)
|
||||||
Tile *tile; /* Pointer to tile to erase from target */
|
Tile *tile; /* Pointer to tile to erase from target */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
struct dbCopySubData *csd; /* Client data */
|
struct dbCopySubData *csd; /* Client data */
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -1112,10 +1143,10 @@ dbCopySubFunc(tile, csd)
|
||||||
|
|
||||||
plane = csd->csd_plane;
|
plane = csd->csd_plane;
|
||||||
pNum = csd->csd_pNum;
|
pNum = csd->csd_pNum;
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile) | dinfo;
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1436,8 +1467,9 @@ DBCellCopyLabels(scx, mask, xMask, targetUse, pArea)
|
||||||
***/
|
***/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyManhattanPaint(tile, cxp)
|
dbCopyManhattanPaint(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to tile to copy */
|
Tile *tile; /* Pointer to tile to copy */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -1483,8 +1515,9 @@ dbCopyManhattanPaint(tile, cxp)
|
||||||
***/
|
***/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyAllPaint(tile, cxp)
|
dbCopyAllPaint(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to tile to copy */
|
Tile *tile; /* Pointer to tile to copy */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -1492,7 +1525,7 @@ dbCopyAllPaint(tile, cxp)
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
PaintUndoInfo ui;
|
PaintUndoInfo ui;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
TileType type = TiGetTypeExact(tile);
|
TileType type = TiGetTypeExact(tile) | dinfo;
|
||||||
int pNum = cxp->tc_plane;
|
int pNum = cxp->tc_plane;
|
||||||
int result;
|
int result;
|
||||||
TileTypeBitMask *typeMask;
|
TileTypeBitMask *typeMask;
|
||||||
|
|
@ -1505,13 +1538,13 @@ dbCopyAllPaint(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool splittile = FALSE;
|
bool splittile = FALSE;
|
||||||
TileType dinfo = 0;
|
TileType newdinfo = 0;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
splittile = TRUE;
|
splittile = TRUE;
|
||||||
dinfo = DBTransformDiagonal(type, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(type, &scx->scx_trans);
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) :
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1571,7 +1604,7 @@ dbCopyAllPaint(tile, cxp)
|
||||||
Rect rrect, orect;
|
Rect rrect, orect;
|
||||||
int np, i, j;
|
int np, i, j;
|
||||||
|
|
||||||
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, dinfo, points, &np);
|
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, newdinfo, points, &np);
|
||||||
|
|
||||||
if (np == 0)
|
if (np == 0)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
@ -1600,7 +1633,7 @@ dbCopyAllPaint(tile, cxp)
|
||||||
rrect.r_ybot = points[0].p_y;
|
rrect.r_ybot = points[0].p_y;
|
||||||
rrect.r_ytop = points[2].p_y;
|
rrect.r_ytop = points[2].p_y;
|
||||||
GeoCanonicalRect(&rrect, &targetRect);
|
GeoCanonicalRect(&rrect, &targetRect);
|
||||||
dinfo = 0;
|
newdinfo = 0;
|
||||||
}
|
}
|
||||||
else if (np >= 4) /* Process extra rectangles in the area */
|
else if (np >= 4) /* Process extra rectangles in the area */
|
||||||
{
|
{
|
||||||
|
|
@ -1657,7 +1690,7 @@ topbottom:
|
||||||
|
|
||||||
splitdone:
|
splitdone:
|
||||||
|
|
||||||
result = (*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
|
result = (*dbCurPaintPlane)(def, pNum, newdinfo | type, &targetRect, &ui);
|
||||||
if ((result != 0) && (arg->caa_func != NULL))
|
if ((result != 0) && (arg->caa_func != NULL))
|
||||||
{
|
{
|
||||||
/* result == 1 used exclusively for DRC off-grid error flagging */
|
/* result == 1 used exclusively for DRC off-grid error flagging */
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,14 @@ DBCellRename(cellname, newname, doforce)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cannot rename a cell with the name of an existing cell */
|
||||||
|
entry = HashLookOnly(&dbCellDefTable, newname);
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
TxError("Cannot rename; cell \"%s\" already exists!\n", newname);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Disallow renaming if the cell has the READONLY flag set, */
|
/* Disallow renaming if the cell has the READONLY flag set, */
|
||||||
/* because the cellname must match the name in the GDS */
|
/* because the cellname must match the name in the GDS */
|
||||||
/* file referenced. */
|
/* file referenced. */
|
||||||
|
|
@ -144,10 +152,9 @@ DBCellRename(cellname, newname, doforce)
|
||||||
|
|
||||||
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
||||||
{
|
{
|
||||||
char *chkgdsfile;
|
|
||||||
bool isReadOnly;
|
bool isReadOnly;
|
||||||
|
|
||||||
chkgdsfile = (char *)DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||||
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
||||||
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
||||||
|
|
||||||
|
|
@ -312,6 +319,7 @@ DBCellDelete(cellname, force)
|
||||||
/* use. If so, load the window with (UNNAMED). */
|
/* use. If so, load the window with (UNNAMED). */
|
||||||
|
|
||||||
UndoDisable();
|
UndoDisable();
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (celluse = celldef->cd_parents; celluse != (CellUse *) NULL;
|
for (celluse = celldef->cd_parents; celluse != (CellUse *) NULL;
|
||||||
celluse = celluse->cu_nextuse)
|
celluse = celluse->cu_nextuse)
|
||||||
{
|
{
|
||||||
|
|
@ -320,8 +328,9 @@ DBCellDelete(cellname, force)
|
||||||
WindUnload(celluse);
|
WindUnload(celluse);
|
||||||
freeMagic(celluse->cu_id);
|
freeMagic(celluse->cu_id);
|
||||||
}
|
}
|
||||||
freeMagic((char *)celluse);
|
freeMagic1(&mm1, (char *)celluse);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
celldef->cd_parents = (CellUse *)NULL;
|
celldef->cd_parents = (CellUse *)NULL;
|
||||||
|
|
||||||
DBWResetBox(celldef);
|
DBWResetBox(celldef);
|
||||||
|
|
@ -1610,7 +1619,9 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
||||||
{
|
{
|
||||||
Rect bbox, refbox;
|
Rect bbox, refbox;
|
||||||
Transform *trans;
|
Transform *trans;
|
||||||
|
PropertyRecord *proprec;
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
|
char *refllx, *reflly, *refurx, *refury;
|
||||||
bool found;
|
bool found;
|
||||||
bool *dolist = (bool *)data;
|
bool *dolist = (bool *)data;
|
||||||
|
|
||||||
|
|
@ -1632,32 +1643,47 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
trans = &use->cu_transform;
|
trans = &use->cu_transform;
|
||||||
propvalue = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||||
if (!found)
|
if (!found)
|
||||||
bbox = use->cu_def->cd_bbox;
|
bbox = use->cu_def->cd_bbox;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
(proprec->prop_len == 4))
|
||||||
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxError("Unable to parse the cell's FIXED_BBOX property; using "
|
||||||
|
"the instance bounding box instead.\n");
|
||||||
bbox = use->cu_def->cd_bbox;
|
bbox = use->cu_def->cd_bbox;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GeoTransRect(trans, &bbox, &refbox);
|
GeoTransRect(trans, &bbox, &refbox);
|
||||||
|
|
||||||
|
/* NOTE: Ideally, the MagWindow pointer should get passed to this routine */
|
||||||
|
refllx = DBWPrintValue(refbox.r_xbot, (MagWindow *)NULL, TRUE);
|
||||||
|
reflly = DBWPrintValue(refbox.r_ybot, (MagWindow *)NULL, FALSE);
|
||||||
|
refurx = DBWPrintValue(refbox.r_xtop, (MagWindow *)NULL, TRUE);
|
||||||
|
refury = DBWPrintValue(refbox.r_ytop, (MagWindow *)NULL, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (*dolist)
|
if (*dolist)
|
||||||
{
|
{
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xbot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refllx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ybot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(reflly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xtop));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refurx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ytop));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refury, -1));
|
||||||
Tcl_SetObjResult(magicinterp, pobj);
|
Tcl_SetObjResult(magicinterp, pobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
TxPrintf("Abutment box: %d %d %d %d\n", refbox.r_xbot, refbox.r_ybot,
|
TxPrintf("Abutment box: %s %s %s %s\n", refllx, reflly, refurx, refury);
|
||||||
refbox.r_xtop, refbox.r_ytop);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1936,6 +1962,7 @@ DBCellDeleteDef(cellDef)
|
||||||
entry = HashFind(&dbCellDefTable, cellDef->cd_name);
|
entry = HashFind(&dbCellDefTable, cellDef->cd_name);
|
||||||
ASSERT(HashGetValue(entry) == (ClientData) cellDef, "DBCellDeleteDef");
|
ASSERT(HashGetValue(entry) == (ClientData) cellDef, "DBCellDeleteDef");
|
||||||
HashSetValue(entry, (ClientData) NULL);
|
HashSetValue(entry, (ClientData) NULL);
|
||||||
|
HashRemove(&dbCellDefTable, cellDef->cd_name);
|
||||||
if (cellDef->cd_props)
|
if (cellDef->cd_props)
|
||||||
DBPropClearAll(cellDef);
|
DBPropClearAll(cellDef);
|
||||||
|
|
||||||
|
|
@ -1997,8 +2024,10 @@ DBCellDefFree(cellDef)
|
||||||
cellDef->cd_planes[pNum] = (Plane *) NULL;
|
cellDef->cd_planes[pNum] = (Plane *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
|
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
|
||||||
freeMagic((char *) lab);
|
freeMagic1(&mm1, (char *) lab);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
HashKill(&cellDef->cd_idHash);
|
HashKill(&cellDef->cd_idHash);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,13 @@ struct seeTypesArg
|
||||||
int
|
int
|
||||||
DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg)
|
DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg)
|
||||||
{
|
{
|
||||||
|
BPEnum sbpe;
|
||||||
BPEnum *bpe;
|
BPEnum *bpe;
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
|
|
||||||
bpe = (BPEnum *)mallocMagic(sizeof(BPEnum));
|
/* bpe = (BPEnum *)mallocMagic(sizeof(BPEnum)); */
|
||||||
|
bpe = &sbpe;
|
||||||
BPEnumInit(bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
|
BPEnumInit(bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
|
||||||
|
|
||||||
while ((use = BPEnumNext(bpe)))
|
while ((use = BPEnumNext(bpe)))
|
||||||
|
|
@ -102,7 +104,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
|
||||||
}
|
}
|
||||||
|
|
||||||
BPEnumTerm(bpe);
|
BPEnumTerm(bpe);
|
||||||
freeMagic(bpe);
|
/* freeMagic(bpe); */
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +120,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
|
||||||
* int
|
* int
|
||||||
* func(tile, cxp)
|
* func(tile, cxp)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* TreeContext *cxp;
|
* TreeContext *cxp;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -414,6 +417,7 @@ dbCellUniqueTileSrFunc(scx, fp)
|
||||||
* int
|
* int
|
||||||
* func(tile, cxp)
|
* func(tile, cxp)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* TreeContext *cxp;
|
* TreeContext *cxp;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -584,6 +588,25 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
||||||
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (flags & TF_LABEL_REVERSE_SEARCH)
|
||||||
|
{
|
||||||
|
/* Search children first */
|
||||||
|
filter.tf_func = func;
|
||||||
|
filter.tf_arg = cdarg;
|
||||||
|
filter.tf_mask = mask;
|
||||||
|
filter.tf_xmask = xMask;
|
||||||
|
filter.tf_tpath = tpath;
|
||||||
|
filter.tf_flags = flags;
|
||||||
|
|
||||||
|
scx2 = *scx;
|
||||||
|
if (scx2.scx_area.r_xbot > TiPlaneRect.r_xbot) scx2.scx_area.r_xbot -= 1;
|
||||||
|
if (scx2.scx_area.r_ybot > TiPlaneRect.r_ybot) scx2.scx_area.r_ybot -= 1;
|
||||||
|
if (scx2.scx_area.r_xtop < TiPlaneRect.r_xtop) scx2.scx_area.r_xtop += 1;
|
||||||
|
if (scx2.scx_area.r_ytop < TiPlaneRect.r_ytop) scx2.scx_area.r_ytop += 1;
|
||||||
|
if (DBCellSrArea(&scx2, dbCellLabelSrFunc, (ClientData) &filter))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||||
{
|
{
|
||||||
if (SigInterruptPending) break;
|
if (SigInterruptPending) break;
|
||||||
|
|
@ -636,6 +659,8 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & TF_LABEL_REVERSE_SEARCH) return 0; /* children already searched */
|
||||||
|
|
||||||
filter.tf_func = func;
|
filter.tf_func = func;
|
||||||
filter.tf_arg = cdarg;
|
filter.tf_arg = cdarg;
|
||||||
filter.tf_mask = mask;
|
filter.tf_mask = mask;
|
||||||
|
|
@ -707,6 +732,16 @@ dbCellLabelSrFunc(scx, fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If fp->tf_flags has TF_LABEL_REVERSE_SEARCH, then search child
|
||||||
|
* uses first, then the parent. This is for display, so that if
|
||||||
|
* a child cell and parent cell have overlapping labels, the parent
|
||||||
|
* label is the one on top.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (fp->tf_flags & TF_LABEL_REVERSE_SEARCH)
|
||||||
|
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||||
|
result = 1;
|
||||||
|
|
||||||
/* Apply the function first to any of the labels in this def. */
|
/* Apply the function first to any of the labels in this def. */
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
@ -728,9 +763,11 @@ dbCellLabelSrFunc(scx, fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now visit each child use recursively */
|
/* Now visit each child use recursively, if not doing a reverse search */
|
||||||
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
|
||||||
result = 1;
|
if (!(fp->tf_flags & TF_LABEL_REVERSE_SEARCH))
|
||||||
|
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||||
|
result = 1;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
/* Remove the trailing pathname component from the TerminalPath */
|
/* Remove the trailing pathname component from the TerminalPath */
|
||||||
|
|
@ -912,8 +949,9 @@ DBSeeTypesAll(rootUse, rootRect, xMask, mask)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbSeeTypesAllSrFunc(tile, cxp)
|
dbSeeTypesAllSrFunc(tile, dinfo, cxp)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
Rect tileRect;
|
Rect tileRect;
|
||||||
|
|
@ -924,7 +962,7 @@ dbSeeTypesAllSrFunc(tile, cxp)
|
||||||
if (GEO_OVERLAP((&tileRect), area))
|
if (GEO_OVERLAP((&tileRect), area))
|
||||||
{
|
{
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
TTMaskSetType(mask, SplitSide(tile) ?
|
TTMaskSetType(mask, (dinfo & TT_SIDE) ?
|
||||||
SplitRightType(tile) : SplitLeftType(tile));
|
SplitRightType(tile) : SplitLeftType(tile));
|
||||||
else
|
else
|
||||||
TTMaskSetType(mask, TiGetType(tile));
|
TTMaskSetType(mask, TiGetType(tile));
|
||||||
|
|
@ -1514,13 +1552,14 @@ DBScaleEverything(scalen, scaled)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the linked CellDef list */
|
/* Free the linked CellDef list */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lcd = lhead;
|
lcd = lhead;
|
||||||
while (lcd != NULL)
|
while (lcd != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)lcd);
|
freeMagic1(&mm1, (char *)lcd);
|
||||||
lcd = lcd->cd_next;
|
lcd = lcd->cd_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
/* Scale all elements */
|
/* Scale all elements */
|
||||||
DBWScaleElements(scalen, scaled);
|
DBWScaleElements(scalen, scaled);
|
||||||
|
|
@ -1604,8 +1643,9 @@ dbScalePlane(oldplane, newplane, pnum, scalen, scaled, doCIF)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbTileScaleFunc(tile, scvals)
|
dbTileScaleFunc(tile, dinfo, scvals)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct scaleArg *scvals;
|
struct scaleArg *scvals;
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
|
|
@ -1628,10 +1668,10 @@ dbTileScaleFunc(tile, scvals)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile) | dinfo;
|
||||||
exact = type;
|
exact = type;
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
|
DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
|
||||||
(
|
(
|
||||||
#ifdef CIF_MODULE
|
#ifdef CIF_MODULE
|
||||||
|
|
@ -1686,8 +1726,9 @@ dbMovePlane(oldplane, newplane, pnum, origx, origy)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbTileMoveFunc(tile, mvvals)
|
dbTileMoveFunc(tile, dinfo, mvvals)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct moveArg *mvvals;
|
struct moveArg *mvvals;
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
|
|
@ -1700,12 +1741,12 @@ dbTileMoveFunc(tile, mvvals)
|
||||||
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
|
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
|
||||||
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
|
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
|
||||||
|
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile) | dinfo;
|
||||||
exact = type;
|
exact = type;
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
||||||
DBStdPaintTbl(type, mvvals->pnum),
|
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1767,12 +1808,14 @@ DBSrCellUses(cellDef, func, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free this linked cellUse structure */
|
/* Free this linked cellUse structure */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lu = luhead;
|
lu = luhead;
|
||||||
while (lu != NULL)
|
while (lu != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)lu);
|
freeMagic1(&mm1, (char *)lu);
|
||||||
lu = lu->cu_next;
|
lu = lu->cu_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1796,84 +1839,48 @@ typedef struct _cellpropstruct {
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dbScaleProp(name, value, cps)
|
int dbScaleProp(name, proprec, cps)
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
PropertyRecord *proprec;
|
||||||
CellPropStruct *cps;
|
CellPropStruct *cps;
|
||||||
{
|
{
|
||||||
int scalen, scaled;
|
int i, scalen, scaled;
|
||||||
char *newvalue, *vptr;
|
Point p;
|
||||||
Rect r;
|
|
||||||
|
|
||||||
if ((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
/* Only "dimension" and "plane" type properties get scaled */
|
||||||
|
|
||||||
|
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
||||||
{
|
{
|
||||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
Plane *newplane;
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
newplane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
{
|
DBClearPaintPlane(newplane);
|
||||||
/* Scale numerator held in point X value, */
|
/* Plane index is unused; arbitrarily substitute -1 */
|
||||||
/* scale denominator held in point Y value */
|
dbScalePlane(proprec->prop_value.prop_plane, newplane, -1,
|
||||||
|
scalen, scaled, TRUE);
|
||||||
scalen = cps->cps_point.p_x;
|
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
||||||
scaled = cps->cps_point.p_y;
|
TiFreePlane(proprec->prop_value.prop_plane);
|
||||||
|
proprec->prop_value.prop_plane = newplane;
|
||||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
return 0;
|
||||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
|
||||||
|
|
||||||
newvalue = (char *)mallocMagic(40);
|
|
||||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
|
||||||
r.r_xtop, r.r_ytop);
|
|
||||||
DBPropPut(cps->cps_def, name, newvalue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!strncmp(name, "MASKHINTS_", 10))
|
|
||||||
|
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||||
|
|
||||||
|
/* Scale numerator held in point X value, */
|
||||||
|
/* scale denominator held in point Y value */
|
||||||
|
scalen = cps->cps_point.p_x;
|
||||||
|
scaled = cps->cps_point.p_y;
|
||||||
|
|
||||||
|
for (i = 0; i < proprec->prop_len; i += 2)
|
||||||
{
|
{
|
||||||
char *vptr, *lastval;
|
if ((i + 1) >= proprec->prop_len) break;
|
||||||
int lastlen;
|
|
||||||
|
|
||||||
newvalue = (char *)NULL;
|
p.p_x = proprec->prop_value.prop_integer[i];
|
||||||
vptr = value;
|
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||||
while (*vptr != '\0')
|
DBScalePoint(&p, scalen, scaled);
|
||||||
{
|
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
|
||||||
{
|
|
||||||
/* Scale numerator held in point X value, */
|
|
||||||
/* scale denominator held in point Y value */
|
|
||||||
|
|
||||||
scalen = cps->cps_point.p_x;
|
|
||||||
scaled = cps->cps_point.p_y;
|
|
||||||
|
|
||||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
|
||||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
|
||||||
|
|
||||||
lastval = newvalue;
|
|
||||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
|
||||||
newvalue = mallocMagic(40 + lastlen);
|
|
||||||
|
|
||||||
if (lastval)
|
|
||||||
strcpy(newvalue, lastval);
|
|
||||||
else
|
|
||||||
*newvalue = '\0';
|
|
||||||
|
|
||||||
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
|
||||||
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
|
|
||||||
if (lastval) freeMagic(lastval);
|
|
||||||
|
|
||||||
/* Parse through the four values and check if there's more */
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
if (newvalue)
|
|
||||||
DBPropPut(cps->cps_def, name, newvalue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* Keep enumerating through properties */
|
return 0; /* Keep enumerating through properties */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1889,33 +1896,47 @@ int dbScaleProp(name, value, cps)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dbMoveProp(name, value, cps)
|
int dbMoveProp(name, proprec, cps)
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
PropertyRecord *proprec;
|
||||||
CellPropStruct *cps;
|
CellPropStruct *cps;
|
||||||
{
|
{
|
||||||
int origx, origy;
|
int i, origx, origy;
|
||||||
char *newvalue;
|
char *newvalue;
|
||||||
Rect r;
|
Point p;
|
||||||
|
|
||||||
if (((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
/* Only "dimension" and "plane" type properties get scaled */
|
||||||
|| !strncmp(name, "MASKHINTS_", 10))
|
|
||||||
|
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
||||||
{
|
{
|
||||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
Plane *newplane;
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
|
||||||
{
|
|
||||||
origx = cps->cps_point.p_x;
|
|
||||||
origy = cps->cps_point.p_y;
|
|
||||||
|
|
||||||
DBMovePoint(&r.r_ll, origx, origy);
|
newplane = DBNewPlane((ClientData) TT_SPACE);
|
||||||
DBMovePoint(&r.r_ur, origx, origy);
|
DBClearPaintPlane(newplane);
|
||||||
|
/* Use plane index -1 to indicate use of CIFPaintTable */
|
||||||
newvalue = (char *)mallocMagic(40);
|
dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy);
|
||||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
||||||
r.r_xtop, r.r_ytop);
|
TiFreePlane(proprec->prop_value.prop_plane);
|
||||||
DBPropPut(cps->cps_def, name, newvalue);
|
proprec->prop_value.prop_plane = newplane;
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||||
|
|
||||||
|
origx = cps->cps_point.p_x;
|
||||||
|
origy = cps->cps_point.p_y;
|
||||||
|
|
||||||
|
for (i = 0; i < proprec->prop_len; i += 2)
|
||||||
|
{
|
||||||
|
if ((i + 1) >= proprec->prop_len) break;
|
||||||
|
|
||||||
|
p.p_x = proprec->prop_value.prop_integer[i];
|
||||||
|
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||||
|
DBMovePoint(&p, origx, origy);
|
||||||
|
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||||
|
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||||
|
}
|
||||||
|
|
||||||
return 0; /* Keep enumerating through properties */
|
return 0; /* Keep enumerating through properties */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2000,12 +2021,14 @@ dbScaleCell(cellDef, scalen, scaled)
|
||||||
BPFree(cellPlaneOrig);
|
BPFree(cellPlaneOrig);
|
||||||
|
|
||||||
/* Free this linked cellUse structure */
|
/* Free this linked cellUse structure */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lu = luhead;
|
lu = luhead;
|
||||||
while (lu != NULL)
|
while (lu != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)lu);
|
freeMagic1(&mm1, (char *)lu);
|
||||||
lu = lu->cu_next;
|
lu = lu->cu_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
/* Scale all of the paint tiles in this cell by creating a new plane */
|
/* Scale all of the paint tiles in this cell by creating a new plane */
|
||||||
/* and copying all tiles into the new plane at scaled dimensions. */
|
/* and copying all tiles into the new plane at scaled dimensions. */
|
||||||
|
|
@ -2208,12 +2231,14 @@ DBMoveCell(cellDef, origx, origy)
|
||||||
BPFree(cellPlaneOrig);
|
BPFree(cellPlaneOrig);
|
||||||
|
|
||||||
/* Free this linked cellUse structure */
|
/* Free this linked cellUse structure */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lu = luhead;
|
lu = luhead;
|
||||||
while (lu != NULL)
|
while (lu != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)lu);
|
freeMagic1(&mm1, (char *)lu);
|
||||||
lu = lu->cu_next;
|
lu = lu->cu_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
/* Move all of the paint tiles in this cell by creating a new plane */
|
/* Move all of the paint tiles in this cell by creating a new plane */
|
||||||
/* and copying all tiles into the new plane at the new position. */
|
/* and copying all tiles into the new plane at the new position. */
|
||||||
|
|
|
||||||
|
|
@ -218,8 +218,10 @@ DBCellClearDef(cellDef)
|
||||||
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_ytop = 1;
|
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_ytop = 1;
|
||||||
cellDef->cd_extended.r_xbot = cellDef->cd_extended.r_ybot = 0;
|
cellDef->cd_extended.r_xbot = cellDef->cd_extended.r_ybot = 0;
|
||||||
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_ytop = 1;
|
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_ytop = 1;
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
|
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
|
||||||
freeMagic((char *) lab);
|
freeMagic1(&mm1, (char *) lab);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
cellDef->cd_labels = (Label *) NULL;
|
cellDef->cd_labels = (Label *) NULL;
|
||||||
cellDef->cd_lastLabel = (Label *) NULL;
|
cellDef->cd_lastLabel = (Label *) NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,85 +128,6 @@ DBInvTransformDiagonal(oldtype, trans)
|
||||||
return dinfo;
|
return dinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* DBSrConnectOnePlane --
|
|
||||||
*
|
|
||||||
* Search from a starting tile to find all paint that is electrically
|
|
||||||
* connected to that tile in the same plane.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* 0 is returned if the search finished normally. 1 is returned
|
|
||||||
* if the search was aborted.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* For every paint tile that is electrically connected to the initial
|
|
||||||
* tile, func is called. Func should have the following form:
|
|
||||||
*
|
|
||||||
* int
|
|
||||||
* func(tile, clientData)
|
|
||||||
* Tile *tile;
|
|
||||||
* ClientData clientData;
|
|
||||||
* {
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* The clientData passed to func is the same one that was passed
|
|
||||||
* to us. Func returns 0 under normal conditions; if it returns
|
|
||||||
* 1 then the search is aborted.
|
|
||||||
*
|
|
||||||
* *** WARNING ***
|
|
||||||
*
|
|
||||||
* Func should not modify any paint during the search, since this
|
|
||||||
* will mess up pointers kept by these procedures and likely cause
|
|
||||||
* a core-dump.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
DBSrConnectOnePlane(startTile, connect, func, clientData)
|
|
||||||
Tile *startTile; /* Starting tile for search */
|
|
||||||
TileTypeBitMask *connect; /* Pointer to a table indicating what tile
|
|
||||||
* types connect to what other tile types.
|
|
||||||
* Each entry gives a mask of types that
|
|
||||||
* connect to tiles of a given type.
|
|
||||||
*/
|
|
||||||
int (*func)(); /* Function to apply at each connected tile. */
|
|
||||||
ClientData clientData; /* Client data for above function. */
|
|
||||||
|
|
||||||
{
|
|
||||||
struct conSrArg csa;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
csa.csa_def = (CellDef *)NULL;
|
|
||||||
csa.csa_bounds = TiPlaneRect;
|
|
||||||
|
|
||||||
/* Pass 1. During this pass the client function gets called. */
|
|
||||||
|
|
||||||
csa.csa_clientFunc = func;
|
|
||||||
csa.csa_clientData = clientData;
|
|
||||||
csa.csa_clientDefault = startTile->ti_client;
|
|
||||||
csa.csa_clear = FALSE;
|
|
||||||
csa.csa_connect = connect;
|
|
||||||
csa.csa_pNum = -1;
|
|
||||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
|
||||||
|
|
||||||
/* Pass 2. Don't call any client function, just clear the marks.
|
|
||||||
* Don't allow any interruptions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SigDisableInterrupts();
|
|
||||||
csa.csa_clientFunc = NULL;
|
|
||||||
csa.csa_clear = TRUE;
|
|
||||||
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
|
|
||||||
SigEnableInterrupts();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -276,7 +197,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
{
|
{
|
||||||
struct conSrArg csa;
|
struct conSrArg csa;
|
||||||
int startPlane, result;
|
int startPlane, result;
|
||||||
Tile *startTile; /* Starting tile for search. */
|
TileAndDinfo start_tad; /* Starting tile and split information */
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
csa.csa_def = def;
|
csa.csa_def = def;
|
||||||
|
|
@ -287,17 +208,18 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
* the tile address and returns.
|
* the tile address and returns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
startTile = NULL;
|
start_tad.tad_tile = NULL;
|
||||||
|
start_tad.tad_next = NULL; /* unused */
|
||||||
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
||||||
{
|
{
|
||||||
csa.csa_pNum = startPlane;
|
csa.csa_pNum = startPlane;
|
||||||
if (DBSrPaintArea((Tile *) NULL,
|
if (DBSrPaintArea((Tile *) NULL,
|
||||||
def->cd_planes[startPlane], startArea, mask,
|
def->cd_planes[startPlane], startArea, mask,
|
||||||
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
|
dbSrConnectStartFunc, PTR2CD(&start_tad)) != 0) break;
|
||||||
}
|
}
|
||||||
if (startTile == NULL) return 0;
|
if (start_tad.tad_tile == NULL) return 0;
|
||||||
/* The following lets us call DBSrConnect recursively */
|
/* The following lets us call DBSrConnect recursively */
|
||||||
else if (startTile->ti_client == (ClientData)1) return 0;
|
else if (start_tad.tad_tile->ti_client == (ClientData)1) return 0;
|
||||||
|
|
||||||
/* Pass 1. During this pass the client function gets called. */
|
/* Pass 1. During this pass the client function gets called. */
|
||||||
|
|
||||||
|
|
@ -306,7 +228,8 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
csa.csa_clientDefault = CLIENTDEFAULT;
|
csa.csa_clientDefault = CLIENTDEFAULT;
|
||||||
csa.csa_clear = FALSE;
|
csa.csa_clear = FALSE;
|
||||||
csa.csa_connect = connect;
|
csa.csa_connect = connect;
|
||||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
if (dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo,
|
||||||
|
PTR2CD(&csa)) != 0) result = 1;
|
||||||
|
|
||||||
/* Pass 2. Don't call any client function, just clear the marks.
|
/* Pass 2. Don't call any client function, just clear the marks.
|
||||||
* Don't allow any interruptions.
|
* Don't allow any interruptions.
|
||||||
|
|
@ -315,7 +238,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
csa.csa_clientFunc = NULL;
|
csa.csa_clientFunc = NULL;
|
||||||
csa.csa_clear = TRUE;
|
csa.csa_clear = TRUE;
|
||||||
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
|
(void) dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo, PTR2CD(&csa));
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -325,11 +248,12 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
int
|
int
|
||||||
dbSrConnectStartFunc(
|
dbSrConnectStartFunc(
|
||||||
Tile *tile, /* This will be the starting tile. */
|
Tile *tile, /* This will be the starting tile. */
|
||||||
ClientData cdata) /* We store tile's address here. */
|
TileType dinfo, /* (unused) */
|
||||||
/* (Tile **pTile) */
|
ClientData cdata) /* We store tile and split info here. */
|
||||||
{
|
{
|
||||||
Tile **pTile = (Tile **)CD2PTR(cdata);
|
TileAndDinfo *tad = (TileAndDinfo *)CD2PTR(cdata);
|
||||||
*pTile = tile;
|
tad->tad_tile = tile;
|
||||||
|
tad->tad_dinfo = dinfo;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,7 +291,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
{
|
{
|
||||||
struct conSrArg csa;
|
struct conSrArg csa;
|
||||||
int startPlane, result;
|
int startPlane, result;
|
||||||
Tile *startTile; /* Starting tile for search. */
|
TileAndDinfo tad;
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
csa.csa_def = def;
|
csa.csa_def = def;
|
||||||
|
|
@ -378,17 +302,18 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
* the tile address and returns.
|
* the tile address and returns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
startTile = NULL;
|
tad.tad_tile = NULL;
|
||||||
|
tad.tad_next = NULL; /* unused */
|
||||||
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
||||||
{
|
{
|
||||||
csa.csa_pNum = startPlane;
|
csa.csa_pNum = startPlane;
|
||||||
if (DBSrPaintArea((Tile *) NULL,
|
if (DBSrPaintArea((Tile *) NULL,
|
||||||
def->cd_planes[startPlane], startArea, mask,
|
def->cd_planes[startPlane], startArea, mask,
|
||||||
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
|
dbSrConnectStartFunc, PTR2CD(&tad)) != 0) break;
|
||||||
}
|
}
|
||||||
if (startTile == NULL) return 0;
|
if (tad.tad_tile == NULL) return 0;
|
||||||
/* The following lets us call DBSrConnect recursively */
|
/* The following lets us call DBSrConnect recursively */
|
||||||
else if (startTile->ti_client == (ClientData)1) return 0;
|
else if (tad.tad_tile->ti_client == (ClientData)1) return 0;
|
||||||
|
|
||||||
/* Pass 1. During this pass the client function gets called. */
|
/* Pass 1. During this pass the client function gets called. */
|
||||||
|
|
||||||
|
|
@ -397,7 +322,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
csa.csa_clientDefault = CLIENTDEFAULT;
|
csa.csa_clientDefault = CLIENTDEFAULT;
|
||||||
csa.csa_clear = FALSE;
|
csa.csa_clear = FALSE;
|
||||||
csa.csa_connect = connect;
|
csa.csa_connect = connect;
|
||||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
if (dbSrConnectFunc(tad.tad_tile, tad.tad_dinfo, PTR2CD(&csa)) != 0) result = 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -420,12 +345,15 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbcFindTileFunc(tile, arg)
|
dbcFindTileFunc(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
ClientData arg;
|
ClientData arg;
|
||||||
{
|
{
|
||||||
Tile **tptr = (Tile **)arg;
|
TileAndDinfo *tad = (TileAndDinfo *)arg;
|
||||||
*tptr = tile;
|
|
||||||
|
tad->tad_tile = tile;
|
||||||
|
tad->tad_dinfo = dinfo;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,6 +393,7 @@ dbcFindTileFunc(tile, arg)
|
||||||
int
|
int
|
||||||
dbSrConnectFunc(
|
dbSrConnectFunc(
|
||||||
Tile *tile, /* Tile that is connected. */
|
Tile *tile, /* Tile that is connected. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
ClientData cdata) /* Contains information about the search. */
|
ClientData cdata) /* Contains information about the search. */
|
||||||
/* (struct conSrArg *csa) */
|
/* (struct conSrArg *csa) */
|
||||||
{
|
{
|
||||||
|
|
@ -484,11 +413,13 @@ dbSrConnectFunc(
|
||||||
/* Drop the first entry on the stack */
|
/* Drop the first entry on the stack */
|
||||||
pNum = csa->csa_pNum;
|
pNum = csa->csa_pNum;
|
||||||
STACKPUSH(INT2CD(tile), dbConnectStack);
|
STACKPUSH(INT2CD(tile), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(dinfo), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
|
|
||||||
while (!StackEmpty(dbConnectStack))
|
while (!StackEmpty(dbConnectStack))
|
||||||
{
|
{
|
||||||
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
|
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
|
||||||
|
dinfo = (int)CD2INT(STACKPOP(dbConnectStack));
|
||||||
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
|
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
|
||||||
if (result == 1) continue;
|
if (result == 1) continue;
|
||||||
|
|
||||||
|
|
@ -522,7 +453,7 @@ dbSrConnectFunc(
|
||||||
|
|
||||||
if (callClient && (csa->csa_clientFunc != NULL))
|
if (callClient && (csa->csa_clientFunc != NULL))
|
||||||
{
|
{
|
||||||
if ((*csa->csa_clientFunc)(tile, pNum, csa->csa_clientData) != 0)
|
if ((*csa->csa_clientFunc)(tile, dinfo, pNum, csa->csa_clientData) != 0)
|
||||||
{
|
{
|
||||||
result = 1;
|
result = 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -536,7 +467,7 @@ dbSrConnectFunc(
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
loctype = SplitRightType(tile);
|
loctype = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
loctype = SplitLeftType(tile);
|
loctype = SplitLeftType(tile);
|
||||||
|
|
@ -547,7 +478,7 @@ dbSrConnectFunc(
|
||||||
|
|
||||||
/* Left side: */
|
/* Left side: */
|
||||||
|
|
||||||
if (IsSplit(tile) && SplitSide(tile)) goto bottomside;
|
if (IsSplit(tile) && (dinfo & TT_SIDE)) goto bottomside;
|
||||||
|
|
||||||
for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
|
for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
|
||||||
{
|
{
|
||||||
|
|
@ -564,9 +495,11 @@ dbSrConnectFunc(
|
||||||
if (t2->ti_client == csa->csa_clientDefault) continue;
|
if (t2->ti_client == csa->csa_clientDefault) continue;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) continue;
|
else if (t2->ti_client == (ClientData) 1) continue;
|
||||||
if (IsSplit(t2))
|
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE)); /* bit set */
|
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
|
if (IsSplit(t2))
|
||||||
|
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||||
|
else
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -574,7 +507,7 @@ dbSrConnectFunc(
|
||||||
/* Bottom side: */
|
/* Bottom side: */
|
||||||
|
|
||||||
bottomside:
|
bottomside:
|
||||||
if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile))))
|
if (IsSplit(tile) && ((!((dinfo & TT_SIDE) ? 1 : 0)) ^ SplitDirection(tile)))
|
||||||
goto rightside;
|
goto rightside;
|
||||||
|
|
||||||
for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
|
for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
|
||||||
|
|
@ -592,16 +525,17 @@ bottomside:
|
||||||
if (t2->ti_client == csa->csa_clientDefault) continue;
|
if (t2->ti_client == csa->csa_clientDefault) continue;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) continue;
|
else if (t2->ti_client == (ClientData) 1) continue;
|
||||||
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
if (IsSplit(t2))
|
if (IsSplit(t2))
|
||||||
{
|
{
|
||||||
if (SplitDirection(t2))
|
if (SplitDirection(t2))
|
||||||
/* bit set */
|
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
|
|
||||||
else
|
else
|
||||||
/* bit clear */
|
/* bit clear */
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
}
|
}
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
else
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -609,7 +543,7 @@ bottomside:
|
||||||
/* Right side: */
|
/* Right side: */
|
||||||
|
|
||||||
rightside:
|
rightside:
|
||||||
if (IsSplit(tile) && !SplitSide(tile)) goto topside;
|
if (IsSplit(tile) && !(dinfo & TT_SIDE)) goto topside;
|
||||||
|
|
||||||
for (t2 = TR(tile); ; t2 = LB(t2))
|
for (t2 = TR(tile); ; t2 = LB(t2))
|
||||||
{
|
{
|
||||||
|
|
@ -626,9 +560,8 @@ rightside:
|
||||||
if (t2->ti_client == csa->csa_clientDefault) goto nextRight;
|
if (t2->ti_client == csa->csa_clientDefault) goto nextRight;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) goto nextRight;
|
else if (t2->ti_client == (ClientData) 1) goto nextRight;
|
||||||
if (IsSplit(t2))
|
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE)); /* bit clear */
|
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
|
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
|
||||||
|
|
@ -637,7 +570,8 @@ rightside:
|
||||||
/* Top side: */
|
/* Top side: */
|
||||||
topside:
|
topside:
|
||||||
|
|
||||||
if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto donesides;
|
if (IsSplit(tile) && (((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile)))
|
||||||
|
goto donesides;
|
||||||
|
|
||||||
for (t2 = RT(tile); ; t2 = BL(t2))
|
for (t2 = RT(tile); ; t2 = BL(t2))
|
||||||
{
|
{
|
||||||
|
|
@ -654,16 +588,18 @@ topside:
|
||||||
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
|
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) goto nextTop;
|
else if (t2->ti_client == (ClientData) 1) goto nextTop;
|
||||||
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
if (IsSplit(t2))
|
if (IsSplit(t2))
|
||||||
{
|
{
|
||||||
if (SplitDirection(t2))
|
if (SplitDirection(t2))
|
||||||
/* bit clear */
|
/* bit clear */
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
else
|
else
|
||||||
/* bit set */
|
/* bit set */
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
|
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||||
}
|
}
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
else
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
|
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
|
||||||
|
|
@ -682,6 +618,7 @@ donesides:
|
||||||
{
|
{
|
||||||
Rect newArea;
|
Rect newArea;
|
||||||
GEO_EXPAND(&tileArea, 1, &newArea);
|
GEO_EXPAND(&tileArea, 1, &newArea);
|
||||||
|
TileAndDinfo tad;
|
||||||
|
|
||||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -689,18 +626,20 @@ donesides:
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
||||||
TiGetTypeExact(tile), &newArea, connectMask,
|
TiGetTypeExact(tile) | dinfo, &newArea, connectMask,
|
||||||
dbcFindTileFunc, (ClientData)&t2) != 0)
|
dbcFindTileFunc, (ClientData)&tad) != 0)
|
||||||
{
|
{
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(i), dbConnectStack);
|
STACKPUSH(INT2CD(i), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
||||||
&newArea, connectMask, dbcFindTileFunc,
|
&newArea, connectMask, dbcFindTileFunc,
|
||||||
(ClientData)&t2) != 0)
|
(ClientData)&tad) != 0)
|
||||||
{
|
{
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(i), dbConnectStack);
|
STACKPUSH(INT2CD(i), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -734,9 +673,10 @@ donesides:
|
||||||
/** @typedef cb_database_srpaintnmarea_t */
|
/** @typedef cb_database_srpaintnmarea_t */
|
||||||
/** @typedef cb_database_srpaintarea_t */
|
/** @typedef cb_database_srpaintarea_t */
|
||||||
int
|
int
|
||||||
dbcUnconnectFunc(tile, clientData)
|
dbcUnconnectFunc(tile, dinfo, clientData)
|
||||||
Tile *tile; /* Current tile */
|
Tile *tile; /* Current tile */
|
||||||
ClientData clientData; /* Unused. */
|
TileType dinfo; /* Split tile information, unused */
|
||||||
|
ClientData clientData; /* Unused. */
|
||||||
|
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -828,6 +768,7 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
CellDef *orig_def = scx->scx_use->cu_def;
|
CellDef *orig_def = scx->scx_use->cu_def;
|
||||||
Label *slab;
|
Label *slab;
|
||||||
int lidx = lab->lab_port;
|
int lidx = lab->lab_port;
|
||||||
|
bool foundOne;
|
||||||
const TileTypeBitMask *connectMask;
|
const TileTypeBitMask *connectMask;
|
||||||
|
|
||||||
/* Check for equivalent ports. For any found, call */
|
/* Check for equivalent ports. For any found, call */
|
||||||
|
|
@ -839,6 +780,7 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
/* are more equivalent ports, they will be found when */
|
/* are more equivalent ports, they will be found when */
|
||||||
/* processing this label's area. */
|
/* processing this label's area. */
|
||||||
|
|
||||||
|
foundOne = FALSE;
|
||||||
for (slab = orig_def->cd_labels; slab != NULL; slab = slab->lab_next)
|
for (slab = orig_def->cd_labels; slab != NULL; slab = slab->lab_next)
|
||||||
if ((slab->lab_flags & PORT_DIR_MASK) && (slab != lab))
|
if ((slab->lab_flags & PORT_DIR_MASK) && (slab != lab))
|
||||||
if (slab->lab_port == lidx)
|
if (slab->lab_port == lidx)
|
||||||
|
|
@ -899,6 +841,20 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
||||||
csa2->csa2_list[csa2->csa2_top].dinfo = 0;
|
csa2->csa2_list[csa2->csa2_top].dinfo = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* This warning is useful but currently is generating
|
||||||
|
* multiple messages per instance and so its more of
|
||||||
|
* an annoyance than an aid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (foundOne == FALSE)
|
||||||
|
TxError("Warning: Port %s at location (%d %d) connects"
|
||||||
|
" a net across multiple disconnected areas!\n",
|
||||||
|
lab->lab_text, lab->lab_rect.r_xbot,
|
||||||
|
lab->lab_rect.r_ybot);
|
||||||
|
#endif
|
||||||
|
foundOne = TRUE;
|
||||||
|
|
||||||
/* See above: Process only one equivalent port at a time */
|
/* See above: Process only one equivalent port at a time */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -933,8 +889,9 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbcConnectFunc(tile, cx)
|
dbcConnectFunc(tile, dinfo, cx)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cx; /* Describes context of search. The client
|
TreeContext *cx; /* Describes context of search. The client
|
||||||
* data is a pointer to a conSrArg2 record
|
* data is a pointer to a conSrArg2 record
|
||||||
* containing various required information.
|
* containing various required information.
|
||||||
|
|
@ -947,8 +904,8 @@ dbcConnectFunc(tile, cx)
|
||||||
Rect *srArea;
|
Rect *srArea;
|
||||||
SearchContext *scx = cx->tc_scx;
|
SearchContext *scx = cx->tc_scx;
|
||||||
SearchContext scx2;
|
SearchContext scx2;
|
||||||
TileType loctype = TiGetTypeExact(tile);
|
TileType loctype = TiGetTypeExact(tile) | dinfo;
|
||||||
TileType dinfo = 0;
|
TileType newdinfo = 0;
|
||||||
int retval, i, pNum = cx->tc_plane;
|
int retval, i, pNum = cx->tc_plane;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
|
||||||
|
|
@ -980,8 +937,8 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
dinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = ((dinfo & TT_SIDE)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if the destination cell contains stuff over the whole
|
/* See if the destination cell contains stuff over the whole
|
||||||
|
|
@ -1019,7 +976,7 @@ dbcConnectFunc(tile, cx)
|
||||||
def = csa2->csa2_use->cu_def;
|
def = csa2->csa2_use->cu_def;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
|
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
|
||||||
dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
newdinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
||||||
(ClientData) NULL) == 0)
|
(ClientData) NULL) == 0)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
|
|
@ -1028,7 +985,7 @@ dbcConnectFunc(tile, cx)
|
||||||
* the storage for the current list element.
|
* the storage for the current list element.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo,
|
DBNMPaintPlane(def->cd_planes[pNum], newdinfo,
|
||||||
&newarea, DBStdPaintTbl(loctype, pNum),
|
&newarea, DBStdPaintTbl(loctype, pNum),
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
|
|
||||||
|
|
@ -1045,14 +1002,14 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
/* Only extend those sides bordering the diagonal tile */
|
/* Only extend those sides bordering the diagonal tile */
|
||||||
|
|
||||||
if (dinfo & TT_DIAGONAL)
|
if (newdinfo & TT_DIAGONAL)
|
||||||
{
|
{
|
||||||
if (dinfo & TT_SIDE) /* right */
|
if (newdinfo & TT_SIDE) /* right */
|
||||||
newarea.r_xtop += 1;
|
newarea.r_xtop += 1;
|
||||||
else /* left */
|
else /* left */
|
||||||
newarea.r_xbot -= 1;
|
newarea.r_xbot -= 1;
|
||||||
if (((dinfo & TT_SIDE) >> 1)
|
if (((newdinfo & TT_SIDE) >> 1)
|
||||||
== (dinfo & TT_DIRECTION)) /* top */
|
== (newdinfo & TT_DIRECTION)) /* top */
|
||||||
newarea.r_ytop += 1;
|
newarea.r_ytop += 1;
|
||||||
else /* bottom */
|
else /* bottom */
|
||||||
newarea.r_ybot -= 1;
|
newarea.r_ybot -= 1;
|
||||||
|
|
@ -1092,7 +1049,7 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
csa2->csa2_list[csa2->csa2_top].area = newarea;
|
csa2->csa2_list[csa2->csa2_top].area = newarea;
|
||||||
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
||||||
csa2->csa2_list[csa2->csa2_top].dinfo = dinfo;
|
csa2->csa2_list[csa2->csa2_top].dinfo = newdinfo;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1247,7 +1204,8 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, doLabels, destUse)
|
||||||
if (DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype,
|
if (DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype,
|
||||||
dbcConnectLabelFunc, (ClientData) &csa2) != 0)
|
dbcConnectLabelFunc, (ClientData) &csa2) != 0)
|
||||||
{
|
{
|
||||||
TxError("Connection search hit memory limit and stopped.\n");
|
TxError("Connection search was interrupted or hit "
|
||||||
|
"memory limit and stopped.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ struct expandArg
|
||||||
{
|
{
|
||||||
bool ea_deref; /* TRUE if root def dereference flag is set */
|
bool ea_deref; /* TRUE if root def dereference flag is set */
|
||||||
int ea_xmask; /* Expand mask. */
|
int ea_xmask; /* Expand mask. */
|
||||||
|
int ea_type; /* Expand, unexpand, or toggle */
|
||||||
int (*ea_func)(); /* Function to call for each cell whose
|
int (*ea_func)(); /* Function to call for each cell whose
|
||||||
* status is changed.
|
* status is changed.
|
||||||
*/
|
*/
|
||||||
|
|
@ -67,15 +68,22 @@ struct expandArg
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBExpand(cellUse, expandMask, expandFlag)
|
DBExpand(cellUse, expandMask, expandType)
|
||||||
CellUse *cellUse;
|
CellUse *cellUse;
|
||||||
int expandMask;
|
int expandMask;
|
||||||
bool expandFlag;
|
int expandType;
|
||||||
{
|
{
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
bool expandFlag, expandTest;
|
||||||
|
|
||||||
if (DBDescendSubcell(cellUse, expandMask) == expandFlag)
|
expandTest = DBDescendSubcell(cellUse, expandMask);
|
||||||
return;
|
if ((expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE)
|
||||||
|
expandFlag = expandTest;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expandFlag = ((expandType & DB_EXPAND_MASK) == DB_EXPAND) ? TRUE : FALSE;
|
||||||
|
if (expandFlag == expandTest) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (expandFlag)
|
if (expandFlag)
|
||||||
{
|
{
|
||||||
|
|
@ -130,17 +138,17 @@ DBExpand(cellUse, expandMask, expandFlag)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
|
DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg)
|
||||||
CellUse *rootUse; /* Root cell use from which search begins */
|
CellUse *rootUse; /* Root cell use from which search begins */
|
||||||
Rect *rootRect; /* Area to be expanded, in root coordinates */
|
Rect *rootRect; /* Area to be expanded, in root coordinates */
|
||||||
int expandMask; /* Window mask in which cell is to be expanded */
|
int expandMask; /* Window mask in which cell is to be expanded */
|
||||||
bool expandFlag; /* TRUE => expand, FALSE => unexpand */
|
int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */
|
||||||
int (*func)(); /* Function to call for each cell whose expansion
|
int (*func)(); /* Function to call for each cell whose expansion
|
||||||
* status is modified. NULL means don't call anyone.
|
* status is modified. NULL means don't call anyone.
|
||||||
*/
|
*/
|
||||||
ClientData cdarg; /* Argument to pass to func. */
|
ClientData cdarg; /* Argument to pass to func. */
|
||||||
{
|
{
|
||||||
int dbExpandFunc(), dbUnexpandFunc();
|
int dbExpandFunc();
|
||||||
SearchContext scontext;
|
SearchContext scontext;
|
||||||
struct expandArg arg;
|
struct expandArg arg;
|
||||||
|
|
||||||
|
|
@ -148,29 +156,26 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
|
||||||
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
|
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Walk through the area and set the expansion state
|
* Walk through the area and set the expansion state appropriately.
|
||||||
* appropriately.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
arg.ea_xmask = expandMask;
|
arg.ea_xmask = expandMask;
|
||||||
arg.ea_func = func;
|
arg.ea_func = func;
|
||||||
arg.ea_arg = cdarg;
|
arg.ea_arg = cdarg;
|
||||||
|
arg.ea_type = expandType;
|
||||||
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
|
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
|
||||||
|
|
||||||
scontext.scx_use = rootUse;
|
scontext.scx_use = rootUse;
|
||||||
scontext.scx_trans = GeoIdentityTransform;
|
scontext.scx_trans = GeoIdentityTransform;
|
||||||
scontext.scx_area = *rootRect;
|
scontext.scx_area = *rootRect;
|
||||||
if (expandFlag)
|
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
|
||||||
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
|
|
||||||
else
|
|
||||||
DBCellSrArea(&scontext, dbUnexpandFunc, (ClientData) &arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dbExpandFunc --
|
* dbExpandFunc --
|
||||||
*
|
*
|
||||||
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
||||||
* when cells are being expanded.
|
* when cells are being expanded, unexpanded, or toggled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -184,68 +189,55 @@ dbExpandFunc(scx, arg)
|
||||||
{
|
{
|
||||||
CellUse *childUse = scx->scx_use;
|
CellUse *childUse = scx->scx_use;
|
||||||
int n = DBLambda[1];
|
int n = DBLambda[1];
|
||||||
|
int expandTest;
|
||||||
|
int expandType = (arg->ea_type & DB_EXPAND_MASK);
|
||||||
|
int expandSurround = (arg->ea_type & DB_EXPAND_SURROUND_MASK);
|
||||||
|
bool surround;
|
||||||
|
|
||||||
|
expandTest = DBDescendSubcell(childUse, arg->ea_xmask);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change the expansion status of this cell if necessary. Call the
|
* Change the expansion status of this cell if necessary. Call the
|
||||||
* client's function if the expansion status has changed.
|
* client's function if the expansion status has changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!DBDescendSubcell(childUse, arg->ea_xmask))
|
if (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE)))
|
||||||
{
|
{
|
||||||
/* If the cell is unavailable, then don't expand it.
|
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||||
*/
|
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
|
||||||
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
|
||||||
{
|
{
|
||||||
/* If the parent is dereferenced, then the child should be, too */
|
/* If the cell is unavailable, then don't expand it.
|
||||||
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
|
*/
|
||||||
if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
|
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
||||||
{
|
{
|
||||||
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
/* If the parent is dereferenced, then the child should be, too */
|
||||||
childUse->cu_def->cd_name);
|
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
|
||||||
return 2;
|
if (!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
|
||||||
|
{
|
||||||
|
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
||||||
|
childUse->cu_def->cd_name);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
childUse->cu_expandMask |= arg->ea_xmask;
|
||||||
|
expandTest = TRUE;
|
||||||
|
if (arg->ea_func != NULL)
|
||||||
|
{
|
||||||
|
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
childUse->cu_expandMask |= arg->ea_xmask;
|
|
||||||
if (arg->ea_func != NULL)
|
|
||||||
{
|
|
||||||
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (expandTest && ((expandType == DB_UNEXPAND) ||
|
||||||
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
|
(expandType == DB_EXPAND_TOGGLE)))
|
||||||
return 1;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dbUnexpandFunc --
|
|
||||||
*
|
|
||||||
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
|
||||||
* when cells are being unexpanded.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
dbUnexpandFunc(scx, arg)
|
|
||||||
SearchContext *scx; /* Pointer to search context containing
|
|
||||||
* child use, search area in coor-
|
|
||||||
* dinates of the child use, and
|
|
||||||
* transform back to "root".
|
|
||||||
*/
|
|
||||||
struct expandArg *arg; /* Client data from caller */
|
|
||||||
{
|
|
||||||
CellUse *childUse = scx->scx_use;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Change the expansion status of this cell if necessary.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (DBDescendSubcell(childUse, arg->ea_xmask))
|
|
||||||
{
|
{
|
||||||
if (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||||
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox))
|
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
|
||||||
|
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
|
||||||
{
|
{
|
||||||
childUse->cu_expandMask &= ~arg->ea_xmask;
|
childUse->cu_expandMask &= ~arg->ea_xmask;
|
||||||
|
expandTest = FALSE;
|
||||||
|
|
||||||
/* Call the client's function, if there is one. */
|
/* Call the client's function, if there is one. */
|
||||||
|
|
||||||
|
|
@ -256,11 +248,7 @@ dbUnexpandFunc(scx, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't recursively search things that aren't already expanded. */
|
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
|
||||||
|
|
||||||
else return 2;
|
|
||||||
|
|
||||||
if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg))
|
|
||||||
return 1;
|
return 1;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1510
database/DBio.c
1510
database/DBio.c
File diff suppressed because it is too large
Load Diff
|
|
@ -280,6 +280,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
|
||||||
bool erasedAny = FALSE;
|
bool erasedAny = FALSE;
|
||||||
TileType newType;
|
TileType newType;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
labPrev = NULL;
|
labPrev = NULL;
|
||||||
lab = cellDef->cd_labels;
|
lab = cellDef->cd_labels;
|
||||||
while (lab != NULL)
|
while (lab != NULL)
|
||||||
|
|
@ -313,7 +314,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
|
||||||
if ((lab->lab_font >= 0) && areaReturn)
|
if ((lab->lab_font >= 0) && areaReturn)
|
||||||
GeoInclude(&lab->lab_bbox, areaReturn);
|
GeoInclude(&lab->lab_bbox, areaReturn);
|
||||||
|
|
||||||
freeMagic((char *) lab);
|
freeMagic1(&mm1, (char *) lab);
|
||||||
lab = lab->lab_next;
|
lab = lab->lab_next;
|
||||||
erasedAny = TRUE;
|
erasedAny = TRUE;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -321,6 +322,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
|
||||||
nextLab: labPrev = lab;
|
nextLab: labPrev = lab;
|
||||||
lab = lab->lab_next;
|
lab = lab->lab_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
if (erasedAny)
|
if (erasedAny)
|
||||||
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
||||||
|
|
@ -442,6 +444,7 @@ DBEraseLabelsByContent(def, rect, type, text)
|
||||||
{
|
{
|
||||||
Label *lab, *labPrev;
|
Label *lab, *labPrev;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (labPrev = NULL, lab = def->cd_labels;
|
for (labPrev = NULL, lab = def->cd_labels;
|
||||||
lab != NULL;
|
lab != NULL;
|
||||||
labPrev = lab, lab = lab->lab_next)
|
labPrev = lab, lab = lab->lab_next)
|
||||||
|
|
@ -457,7 +460,7 @@ DBEraseLabelsByContent(def, rect, type, text)
|
||||||
else labPrev->lab_next = lab->lab_next;
|
else labPrev->lab_next = lab->lab_next;
|
||||||
if (def->cd_lastLabel == lab)
|
if (def->cd_lastLabel == lab)
|
||||||
def->cd_lastLabel = labPrev;
|
def->cd_lastLabel = labPrev;
|
||||||
freeMagic((char *) lab);
|
freeMagic1(&mm1, (char *) lab);
|
||||||
|
|
||||||
/* Don't iterate through loop, since this will skip a label:
|
/* Don't iterate through loop, since this will skip a label:
|
||||||
* just go back to top. This is tricky!
|
* just go back to top. This is tricky!
|
||||||
|
|
@ -467,6 +470,7 @@ DBEraseLabelsByContent(def, rect, type, text)
|
||||||
if (lab == NULL) break;
|
if (lab == NULL) break;
|
||||||
else goto nextCheck;
|
else goto nextCheck;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -495,6 +499,7 @@ DBRemoveLabel(def, refLab)
|
||||||
{
|
{
|
||||||
Label *lab, *labPrev;
|
Label *lab, *labPrev;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (labPrev = NULL, lab = def->cd_labels;
|
for (labPrev = NULL, lab = def->cd_labels;
|
||||||
lab != NULL;
|
lab != NULL;
|
||||||
labPrev = lab, lab = lab->lab_next)
|
labPrev = lab, lab = lab->lab_next)
|
||||||
|
|
@ -508,7 +513,7 @@ DBRemoveLabel(def, refLab)
|
||||||
else labPrev->lab_next = lab->lab_next;
|
else labPrev->lab_next = lab->lab_next;
|
||||||
if (def->cd_lastLabel == lab)
|
if (def->cd_lastLabel == lab)
|
||||||
def->cd_lastLabel = labPrev;
|
def->cd_lastLabel = labPrev;
|
||||||
freeMagic((char *) lab);
|
freeMagic1(&mm1, (char *) lab);
|
||||||
|
|
||||||
/* Don't iterate through loop, since this will skip a label:
|
/* Don't iterate through loop, since this will skip a label:
|
||||||
* just go back to top. This is tricky!
|
* just go back to top. This is tricky!
|
||||||
|
|
@ -518,6 +523,7 @@ DBRemoveLabel(def, refLab)
|
||||||
if (lab == NULL) break;
|
if (lab == NULL) break;
|
||||||
else goto nextCheck;
|
else goto nextCheck;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -577,8 +583,9 @@ DBReOrientLabel(cellDef, area, newPos)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbGetLabelArea(tile, area)
|
dbGetLabelArea(tile, dinfo, area)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
Rect *area; /* Area to be modified. */
|
Rect *area; /* Area to be modified. */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -760,8 +767,10 @@ DBAdjustLabelsNew(def, area)
|
||||||
def->cd_lastLabel = labPrev;
|
def->cd_lastLabel = labPrev;
|
||||||
DBUndoEraseLabel(def, lab);
|
DBUndoEraseLabel(def, lab);
|
||||||
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
|
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
|
||||||
freeMagic((char *) lab);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, (char *) lab);
|
||||||
lab = lab->lab_next;
|
lab = lab->lab_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
modified = TRUE;
|
modified = TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1077,14 +1086,15 @@ DBPickLabelLayer(def, lab, doCalma)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbPickFunc1(tile, mask)
|
dbPickFunc1(tile, dinfo, mask)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TileTypeBitMask *mask; /* Mask to be modified. */
|
TileTypeBitMask *mask; /* Mask to be modified. */
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
|
|
||||||
|
|
@ -1103,15 +1113,16 @@ dbPickFunc1(tile, mask)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbPickFunc2(tile, mask)
|
dbPickFunc2(tile, dinfo, mask)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TileTypeBitMask *mask; /* Mask to be modified. */
|
TileTypeBitMask *mask; /* Mask to be modified. */
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
TileTypeBitMask tmp, *rMask;
|
TileTypeBitMask tmp, *rMask;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
|
|
||||||
|
|
@ -1744,8 +1755,10 @@ DBLoadFont(fontfile, scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the pointlist */
|
/* Remove the pointlist */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (newPath = pathStart; newPath != NULL; newPath = newPath->fp_next)
|
for (newPath = pathStart; newPath != NULL; newPath = newPath->fp_next)
|
||||||
freeMagic(newPath);
|
freeMagic1(&mm1, newPath);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
pathStart = NULL;
|
pathStart = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -487,8 +487,6 @@ enumerate:
|
||||||
newType = (method == (unsigned char)PAINT_XOR) ?
|
newType = (method == (unsigned char)PAINT_XOR) ?
|
||||||
*resultTbl : resultTbl[oldType];
|
*resultTbl : resultTbl[oldType];
|
||||||
|
|
||||||
if (mergeFlags & MRG_RIGHT)
|
|
||||||
tile = TiNMMergeRight(tile, plane); // was commented out?
|
|
||||||
if (mergeFlags & MRG_LEFT)
|
if (mergeFlags & MRG_LEFT)
|
||||||
TiNMMergeLeft(LB(newtile), plane);
|
TiNMMergeLeft(LB(newtile), plane);
|
||||||
}
|
}
|
||||||
|
|
@ -496,8 +494,6 @@ enumerate:
|
||||||
{
|
{
|
||||||
if (mergeFlags & MRG_LEFT)
|
if (mergeFlags & MRG_LEFT)
|
||||||
TiNMMergeLeft(newtile, plane);
|
TiNMMergeLeft(newtile, plane);
|
||||||
if (mergeFlags & MRG_RIGHT)
|
|
||||||
TiNMMergeRight(LB(tile), plane); // was commented out?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1439,10 +1435,6 @@ DBDiagonalProc(oldtype, dinfo)
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* For purposes of "undo" recording, record which side we just painted */
|
|
||||||
if (dinfo->side)
|
|
||||||
newtype |= TT_SIDE;
|
|
||||||
|
|
||||||
return newtype;
|
return newtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1796,12 +1788,14 @@ nextrect:
|
||||||
lr = lr->r_next;
|
lr = lr->r_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
lr = lhead;
|
lr = lhead;
|
||||||
while (lr != NULL)
|
while (lr != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *) lr);
|
freeMagic1(&mm1, (char *) lr);
|
||||||
lr = lr->r_next;
|
lr = lr->r_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ?
|
result = DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ?
|
||||||
|
|
@ -1822,14 +1816,15 @@ nextrect:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbNMEnumFunc(tile, arg)
|
dbNMEnumFunc(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
LinkedRect **arg;
|
LinkedRect **arg;
|
||||||
{
|
{
|
||||||
LinkedRect *lr;
|
LinkedRect *lr;
|
||||||
|
|
||||||
/* Ignore the second call to any diagonal---only count once! */
|
/* Ignore the second call to any diagonal---only count once! */
|
||||||
if (IsSplit(tile) && SplitSide(tile)) return 0;
|
if (IsSplit(tile) && (dinfo & TT_SIDE)) return 0;
|
||||||
|
|
||||||
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
|
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
|
||||||
TiToRect(tile, &lr->r_r);
|
TiToRect(tile, &lr->r_r);
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,9 @@ DBPaint (cellDef, rect, type)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbResolveImages(tile, cellDef)
|
dbResolveImages(tile, dinfo, cellDef)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
CellDef *cellDef;
|
CellDef *cellDef;
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -130,7 +131,7 @@ dbResolveImages(tile, cellDef)
|
||||||
/* Recursive call back to DBPaint---this will ensure that */
|
/* Recursive call back to DBPaint---this will ensure that */
|
||||||
/* all of the planes of the image type are painted. */
|
/* all of the planes of the image type are painted. */
|
||||||
|
|
||||||
DBPaint(cellDef, &rect, TiGetTypeExact(tile));
|
DBPaint(cellDef, &rect, TiGetTypeExact(tile) | dinfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
|
||||||
|
/* Global variable */
|
||||||
|
|
||||||
|
bool DBPropCompat = TRUE; /* If TRUE, then always save properties to
|
||||||
|
* .mag files as type "string" for backwards
|
||||||
|
* compatibility. If FALSE, then properties
|
||||||
|
* are saved to the .mag file along with their
|
||||||
|
* type. Regardless of the setting, properties
|
||||||
|
* which are reserved keywords are converted
|
||||||
|
* to the best internal representation on input.
|
||||||
|
*/
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -47,16 +57,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBPropPut(cellDef, name, value)
|
DBPropPut(cellDef, name, value)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
char *name; /* The name of the property desired. */
|
char *name; /* The name of the property desired. */
|
||||||
ClientData value; /* MUST point to a malloc'ed structure, or NULL.
|
PropertyRecord *value; /* MUST point to a malloc'ed structure, or NULL.
|
||||||
* This will be freed when the CellDef is freed.
|
* This will be freed when the CellDef is freed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
HashTable *htab;
|
HashTable *htab;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
char *oldvalue;
|
PropertyRecord *oldvalue;
|
||||||
|
|
||||||
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
||||||
/* the value would be saved in the hash table, so if it is not */
|
/* the value would be saved in the hash table, so if it is not */
|
||||||
|
|
@ -95,12 +105,23 @@ DBPropPut(cellDef, name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = HashFind(htab, name);
|
entry = HashFind(htab, name);
|
||||||
oldvalue = (char *)HashGetValue(entry);
|
oldvalue = (PropertyRecord *)HashGetValue(entry);
|
||||||
if (oldvalue != NULL) freeMagic(oldvalue);
|
/* All properties are allocated as a single block and can just be freed,
|
||||||
if (value == (ClientData)NULL)
|
* except for plane properties, which require freeing the plane.
|
||||||
|
*/
|
||||||
|
if (oldvalue != NULL)
|
||||||
|
{
|
||||||
|
if (oldvalue->prop_type == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
DBFreePaintPlane(oldvalue->prop_value.prop_plane);
|
||||||
|
TiFreePlane(oldvalue->prop_value.prop_plane);
|
||||||
|
}
|
||||||
|
freeMagic((char *)oldvalue);
|
||||||
|
}
|
||||||
|
if (value == (PropertyRecord *)NULL)
|
||||||
HashRemove(htab, name);
|
HashRemove(htab, name);
|
||||||
else
|
else
|
||||||
HashSetValue(entry, value);
|
HashSetValue(entry, PTR2CD(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
@ -110,13 +131,13 @@ DBPropPut(cellDef, name, value)
|
||||||
* Get a property from a celldef.
|
* Get a property from a celldef.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* NULL if the property didn't exist, or if the property value was NULL.
|
* NULL if the property didn't exist, or if the property record was NULL.
|
||||||
* Otherwise, ClientData that represents the property.
|
* Otherwise, returns a pointer to the property record.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ClientData
|
PropertyRecord *
|
||||||
DBPropGet(cellDef, name, found)
|
DBPropGet(cellDef, name, found)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
char *name; /* The name of the property desired. */
|
char *name; /* The name of the property desired. */
|
||||||
|
|
@ -124,12 +145,12 @@ DBPropGet(cellDef, name, found)
|
||||||
* exists.
|
* exists.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ClientData result;
|
PropertyRecord *result;
|
||||||
bool haveit;
|
bool haveit;
|
||||||
HashTable *htab;
|
HashTable *htab;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
|
|
||||||
result = (ClientData) NULL;
|
result = (PropertyRecord *)NULL;
|
||||||
haveit = FALSE;
|
haveit = FALSE;
|
||||||
htab = (HashTable *) cellDef->cd_props;
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
if (htab == (HashTable *) NULL) goto done;
|
if (htab == (HashTable *) NULL) goto done;
|
||||||
|
|
@ -138,7 +159,7 @@ DBPropGet(cellDef, name, found)
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
{
|
{
|
||||||
haveit = TRUE;
|
haveit = TRUE;
|
||||||
result = (ClientData) HashGetValue(entry);
|
result = (PropertyRecord *)HashGetValue(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
@ -146,6 +167,109 @@ done:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBPropGetString --
|
||||||
|
*
|
||||||
|
* Get a string property from a celldef.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* NULL if the property didn't exist, or if the property record was NULL.
|
||||||
|
* Otherwise, returns a pointer to the property's string record.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* This is basically the original DBPropGet(), when properties were only
|
||||||
|
* allowed to be strings.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBPropGetString(cellDef, name, found)
|
||||||
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
|
char *name; /* The name of the property desired. */
|
||||||
|
bool *found; /* If not NULL, filled in with TRUE iff the property
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool haveit;
|
||||||
|
HashTable *htab;
|
||||||
|
HashEntry *entry;
|
||||||
|
|
||||||
|
haveit = FALSE;
|
||||||
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
|
if (htab == (HashTable *) NULL) goto pdone;
|
||||||
|
|
||||||
|
entry = HashLookOnly(htab, name);
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)HashGetValue(entry);
|
||||||
|
if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
||||||
|
{
|
||||||
|
haveit = TRUE;
|
||||||
|
result = proprec->prop_value.prop_string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdone:
|
||||||
|
if (found != (bool *) NULL) *found = haveit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBPropGetDouble --
|
||||||
|
*
|
||||||
|
* Get a single double-long integer property from a celldef.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* NULL if the property didn't exist, or if the property record was NULL.
|
||||||
|
* Otherwise, returns a pointer to the property's value record.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
dlong
|
||||||
|
DBPropGetDouble(cellDef, name, found)
|
||||||
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
|
char *name; /* The name of the property desired. */
|
||||||
|
bool *found; /* If not NULL, filled in with TRUE iff the property
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
dlong result = 0;
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool haveit;
|
||||||
|
HashTable *htab;
|
||||||
|
HashEntry *entry;
|
||||||
|
|
||||||
|
haveit = FALSE;
|
||||||
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
|
if (htab == (HashTable *) NULL) goto ddone;
|
||||||
|
|
||||||
|
entry = HashLookOnly(htab, name);
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)HashGetValue(entry);
|
||||||
|
if (proprec->prop_type == PROPERTY_TYPE_DOUBLE)
|
||||||
|
{
|
||||||
|
haveit = TRUE;
|
||||||
|
result = proprec->prop_value.prop_double[0];
|
||||||
|
}
|
||||||
|
else if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
||||||
|
{
|
||||||
|
haveit = TRUE;
|
||||||
|
sscanf(proprec->prop_value.prop_string, "%"DLONG_PREFIX"d", &result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ddone:
|
||||||
|
if (found != (bool *) NULL) *found = haveit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* DBPropEnum --
|
* DBPropEnum --
|
||||||
|
|
@ -168,7 +292,7 @@ DBPropEnum(cellDef, func, cdata)
|
||||||
*
|
*
|
||||||
* int foo(name, value, cdata)
|
* int foo(name, value, cdata)
|
||||||
* char *name;
|
* char *name;
|
||||||
* ClientData value;
|
* PropertyRecord *value;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* -- return 0 to continue,
|
* -- return 0 to continue,
|
||||||
|
|
@ -189,7 +313,7 @@ DBPropEnum(cellDef, func, cdata)
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((entry = HashNext(htab, &hs)) != NULL)
|
while ((entry = HashNext(htab, &hs)) != NULL)
|
||||||
{
|
{
|
||||||
res = (*func)(entry->h_key.h_name, (ClientData) entry->h_pointer, cdata);
|
res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata);
|
||||||
if (res != 0) return res;
|
if (res != 0) return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -327,11 +327,11 @@ DBTechNoisyNamePlane(planename)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
const char *
|
||||||
DBTypeShortName(type)
|
DBTypeShortName(
|
||||||
TileType type;
|
TileType type)
|
||||||
{
|
{
|
||||||
NameList *tbl;
|
const NameList *tbl;
|
||||||
|
|
||||||
for (tbl = dbTypeNameLists.sn_next;
|
for (tbl = dbTypeNameLists.sn_next;
|
||||||
tbl != &dbTypeNameLists;
|
tbl != &dbTypeNameLists;
|
||||||
|
|
@ -347,11 +347,11 @@ DBTypeShortName(type)
|
||||||
return ("???");
|
return ("???");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
const char *
|
||||||
DBPlaneShortName(pNum)
|
DBPlaneShortName(
|
||||||
int pNum;
|
int pNum)
|
||||||
{
|
{
|
||||||
NameList *tbl;
|
const NameList *tbl;
|
||||||
|
|
||||||
for (tbl = dbPlaneNameLists.sn_next;
|
for (tbl = dbPlaneNameLists.sn_next;
|
||||||
tbl != &dbPlaneNameLists;
|
tbl != &dbPlaneNameLists;
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
/* Types and their names */
|
/* Types and their names */
|
||||||
int DBNumTypes;
|
int DBNumTypes;
|
||||||
char *DBTypeLongNameTbl[NT];
|
const char *DBTypeLongNameTbl[NT];
|
||||||
int DBTypePlaneTbl[NT]; /* Normally accessed as macro "DBPlane(x)" */
|
int DBTypePlaneTbl[NT]; /* Normally accessed as macro "DBPlane(x)" */
|
||||||
NameList dbTypeNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
|
NameList dbTypeNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
|
||||||
HashTable DBTypeAliasTable;
|
HashTable DBTypeAliasTable;
|
||||||
|
|
||||||
/* Planes and their names */
|
/* Planes and their names */
|
||||||
int DBNumPlanes;
|
int DBNumPlanes;
|
||||||
char *DBPlaneLongNameTbl[PL_MAXTYPES];
|
const char *DBPlaneLongNameTbl[PL_MAXTYPES];
|
||||||
NameList dbPlaneNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
|
NameList dbPlaneNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -116,22 +116,24 @@ NameList *dbTechNameAddOne();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBTechInitPlane()
|
DBTechInitPlane(void)
|
||||||
{
|
{
|
||||||
DefaultPlane *dpp;
|
DefaultPlane *dpp;
|
||||||
char *cp;
|
const char *cp;
|
||||||
|
|
||||||
/* Clear out any old information */
|
/* Clear out any old information */
|
||||||
if (dbPlaneNameLists.sn_next != NULL)
|
if (dbPlaneNameLists.sn_next != NULL)
|
||||||
{
|
{
|
||||||
NameList *tbl;
|
NameList *tbl;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (tbl = dbPlaneNameLists.sn_next; tbl != &dbPlaneNameLists;
|
for (tbl = dbPlaneNameLists.sn_next; tbl != &dbPlaneNameLists;
|
||||||
tbl = tbl->sn_next)
|
tbl = tbl->sn_next)
|
||||||
{
|
{
|
||||||
freeMagic(tbl->sn_name);
|
freeMagic(tbl->sn_name);
|
||||||
freeMagic(tbl);
|
freeMagic1(&mm1, tbl);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tables of short names */
|
/* Tables of short names */
|
||||||
|
|
@ -205,12 +207,14 @@ DBTechInitType()
|
||||||
{
|
{
|
||||||
NameList *tbl;
|
NameList *tbl;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (tbl = dbTypeNameLists.sn_next; tbl != &dbTypeNameLists;
|
for (tbl = dbTypeNameLists.sn_next; tbl != &dbTypeNameLists;
|
||||||
tbl = tbl->sn_next)
|
tbl = tbl->sn_next)
|
||||||
{
|
{
|
||||||
freeMagic(tbl->sn_name);
|
freeMagic(tbl->sn_name);
|
||||||
freeMagic(tbl);
|
freeMagic1(&mm1, tbl);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tables of short names */
|
/* Tables of short names */
|
||||||
|
|
@ -264,12 +268,12 @@ DBTechInitType()
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
bool
|
bool
|
||||||
DBTechAddPlane(sectionName, argc, argv)
|
DBTechAddPlane(
|
||||||
char *sectionName;
|
const char *sectionName,
|
||||||
int argc;
|
int argc,
|
||||||
char *argv[];
|
char *argv[])
|
||||||
{
|
{
|
||||||
char *cp;
|
const char *cp;
|
||||||
|
|
||||||
if (DBNumPlanes >= PL_MAXTYPES)
|
if (DBNumPlanes >= PL_MAXTYPES)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,296 @@ struct dbCheck
|
||||||
|
|
||||||
int dbCheckMaxHFunc(), dbCheckMaxVFunc();
|
int dbCheckMaxHFunc(), dbCheckMaxVFunc();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbEvalCorner --
|
||||||
|
*
|
||||||
|
* Used by DBTestNMInteract() to determine whether two non-
|
||||||
|
* Manhattan areas have crossing diagonals by evaluating the
|
||||||
|
* corner points of the area of intersection between the two
|
||||||
|
* tiles. This routine finds the distance from a point in
|
||||||
|
* the second triangle to the diagonal of the first, in both
|
||||||
|
* x and y. If the point is below or to the left, the
|
||||||
|
* distance is negative; otherwise the distance is positive.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* 1 for a positive result, -1 for a negative result, and 0
|
||||||
|
* for the same result (point touches the diagonal).
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
dbEvalCorner(Point *p, // Point to evaluate
|
||||||
|
Rect *rect, // Triangular area bounding rectangle
|
||||||
|
TileType di) // Diagonal information for split rect
|
||||||
|
{
|
||||||
|
dlong D;
|
||||||
|
|
||||||
|
/* D is the distance from a point to the diagonal of the rectangle.
|
||||||
|
* The magnitude is not important. It only matters what the sign
|
||||||
|
* is, so return 1 for positive, -1 for negative, or 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (di & TT_DIRECTION)
|
||||||
|
D = (p->p_y - rect->r_ybot) * (rect->r_xtop - rect->r_xbot) -
|
||||||
|
(rect->r_xtop - p->p_x) * (rect->r_ytop - rect->r_ybot);
|
||||||
|
else
|
||||||
|
D = (p->p_y - rect->r_ybot) * (rect->r_xtop - rect->r_xbot) -
|
||||||
|
(p->p_x - rect->r_xbot) * (rect->r_ytop - rect->r_ybot);
|
||||||
|
|
||||||
|
if (D > 0) return 1;
|
||||||
|
if (D < 0) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBTestNMInteract --
|
||||||
|
*
|
||||||
|
* Determine if a tile (t2) interacts with (touches or overlaps)
|
||||||
|
* a triangular area (rect1, with diagonal split information in
|
||||||
|
* di1). Tile t2 may or may not be a split tile. If t2 is
|
||||||
|
* split, then diagonal split information is in di2.
|
||||||
|
*
|
||||||
|
* There are two distinct cases: DBSrPaintNMArea() looks for
|
||||||
|
* tiles that overlap the area of rect1, but extTestNMInteract()
|
||||||
|
* looks for tiles that both overlap or touch (indicating
|
||||||
|
* electrical connectivity between the two). "overlap_only"
|
||||||
|
* distinguishes between the two use cases. Set "overlap_only"
|
||||||
|
* to TRUE for overlap searches, and FALSE for interaction
|
||||||
|
* searches.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
*
|
||||||
|
* If overlap_only is TRUE:
|
||||||
|
* Return TRUE if the indicated areas overlap, FALSE if not.
|
||||||
|
* If overlap_only is FALSE:
|
||||||
|
* Return TRUE if the indicated areas touch or overlap, FALSE if not.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
DBTestNMInteract(Rect *rect1,
|
||||||
|
TileType tt1,
|
||||||
|
Tile *t2,
|
||||||
|
TileType di2,
|
||||||
|
bool overlap_only)
|
||||||
|
{
|
||||||
|
Rect rect2, r;
|
||||||
|
Point p;
|
||||||
|
int rheight, rwidth, rmax;
|
||||||
|
dlong f1, f2, f3, f4;
|
||||||
|
TileType tt2;
|
||||||
|
int pos, neg, touch, sign;
|
||||||
|
|
||||||
|
TiToRect(t2, &rect2);
|
||||||
|
|
||||||
|
/* Assuming that rect1 is a split area, then check if any part of t2
|
||||||
|
* overlaps the split side of interest in rect1, regardless of whether
|
||||||
|
* t2 is split or not. If there is no overlap, then return FALSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
rheight = rect1->r_ytop - rect1->r_ybot;
|
||||||
|
rwidth = rect1->r_xtop - rect1->r_xbot;
|
||||||
|
rmax = MAX(rheight, rwidth);
|
||||||
|
|
||||||
|
f1 = (rect2.r_ybot > MINFINITY + 2) ?
|
||||||
|
((dlong)(rect1->r_ytop - rect2.r_ybot) * rwidth) : DLONG_MAX;
|
||||||
|
f2 = (rect2.r_ytop < INFINITY - 2) ?
|
||||||
|
((dlong)(rect2.r_ytop - rect1->r_ybot) * rwidth) : DLONG_MAX;
|
||||||
|
|
||||||
|
if (tt1 & TT_SIDE)
|
||||||
|
{
|
||||||
|
/* Outside-of-triangle check---ignore sub-integer slivers */
|
||||||
|
if (rect2.r_xtop < INFINITY - 2)
|
||||||
|
{
|
||||||
|
f3 = (dlong)(rect1->r_xtop - rect2.r_xtop) * rheight;
|
||||||
|
f3 += rmax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f3 = DLONG_MIN;
|
||||||
|
if ((tt1 & TT_DIRECTION) ? (f2 < f3) : (f1 < f3))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Outside-of-triangle check---ignore sub-integer slivers */
|
||||||
|
if (rect2.r_xbot > MINFINITY + 2)
|
||||||
|
{
|
||||||
|
f4 = (dlong)(rect2.r_xbot - rect1->r_xbot) * rheight;
|
||||||
|
f4 += rmax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f4 = DLONG_MIN;
|
||||||
|
if ((tt1 & TT_DIRECTION) ? (f1 < f4) : (f2 < f4))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If t2 is not split, or its diagonal is the opposite of t1,
|
||||||
|
* or its side is the same as that of t1, then they overlap.
|
||||||
|
*/
|
||||||
|
if (!IsSplit(t2)) return TRUE;
|
||||||
|
|
||||||
|
tt2 = TiGetTypeExact(t2) | di2;
|
||||||
|
|
||||||
|
if ((tt1 & TT_DIRECTION) != (tt2 & TT_DIRECTION)) return TRUE;
|
||||||
|
// if ((tt1 & TT_SIDE) == (tt2 & TT_SIDE)) return TRUE;
|
||||||
|
|
||||||
|
/* Hard case: Same diagonal direction, opposite sides. To determine
|
||||||
|
* overlap, count which of the three points of triangle t2 land on
|
||||||
|
* one side or the other of the rect1 split diagonal. From those
|
||||||
|
* counts, determine if the triangles are overlapping, touching,
|
||||||
|
* or disjoint.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Evaluate the three corners of the rect2 triangle */
|
||||||
|
|
||||||
|
pos = neg = touch = 0;
|
||||||
|
if (!(tt2 & TT_DIRECTION) || !(tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the lower left corner */
|
||||||
|
sign = dbEvalCorner(&rect2.r_ll, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tt2 & TT_DIRECTION) || (tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the upper right corner */
|
||||||
|
sign = dbEvalCorner(&rect2.r_ur, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tt2 & TT_DIRECTION) || !(tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the upper left corner */
|
||||||
|
p.p_x = rect2.r_xbot;
|
||||||
|
p.p_y = rect2.r_ytop;
|
||||||
|
sign = dbEvalCorner(&p, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tt2 & TT_DIRECTION) || (tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the lower right corner */
|
||||||
|
p.p_x = rect2.r_xtop;
|
||||||
|
p.p_y = rect2.r_ybot;
|
||||||
|
sign = dbEvalCorner(&p, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If side and direction match, then pos and neg need to be swapped */
|
||||||
|
if (((tt1 & TT_SIDE) && (tt1 & TT_DIRECTION)) ||
|
||||||
|
(!(tt1 & TT_SIDE) && !(tt1 & TT_DIRECTION)))
|
||||||
|
{
|
||||||
|
int temp = neg;
|
||||||
|
neg = pos;
|
||||||
|
pos = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return TRUE or FALSE depending on the values of pos, neg, and
|
||||||
|
* touch, and depending on whether overlap_only is set or not.
|
||||||
|
*/
|
||||||
|
if (pos == 3)
|
||||||
|
return FALSE; /* Fully disjoint */
|
||||||
|
else if (neg == 3)
|
||||||
|
{
|
||||||
|
if ((tt1 & TT_SIDE) != (tt2 & TT_SIDE))
|
||||||
|
return TRUE; /* Fully enclosed */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is a trickier situation. Both triangles have
|
||||||
|
* the same TT_SIDE bit, but the triangular area of t2
|
||||||
|
* could still be outside of rect1. Need to check where
|
||||||
|
* the inside corner of rect1 lands with respect to the
|
||||||
|
* t2 diagonal.
|
||||||
|
*/
|
||||||
|
if (((tt1 & TT_SIDE) == 0) && ((tt1 & TT_DIRECTION) != 0))
|
||||||
|
{
|
||||||
|
sign = dbEvalCorner(&rect1->r_ll, &rect2, tt2);
|
||||||
|
}
|
||||||
|
else if (((tt1 & TT_SIDE) == 0) && ((tt1 & TT_DIRECTION) == 0))
|
||||||
|
{
|
||||||
|
p.p_x = rect1->r_ll.p_x;
|
||||||
|
p.p_y = rect1->r_ur.p_y;
|
||||||
|
sign = dbEvalCorner(&p, &rect2, tt2);
|
||||||
|
}
|
||||||
|
else if (((tt1 & TT_SIDE) != 0) && ((tt1 & TT_DIRECTION) == 0))
|
||||||
|
{
|
||||||
|
p.p_x = rect1->r_ur.p_x;
|
||||||
|
p.p_y = rect1->r_ll.p_y;
|
||||||
|
sign = dbEvalCorner(&p, &rect2, tt2);
|
||||||
|
}
|
||||||
|
else /* if (((tt1 & TT_SIDE) != 0) && ((tt1 & TT_DIRECTION) != 0)) */
|
||||||
|
{
|
||||||
|
sign = dbEvalCorner(&rect1->r_ur, &rect2, tt2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Again, if side and direction match, then sign is backwards
|
||||||
|
*/
|
||||||
|
if (((tt2 & TT_SIDE) && (tt2 & TT_DIRECTION)) ||
|
||||||
|
(!(tt2 & TT_SIDE) && !(tt2 & TT_DIRECTION)))
|
||||||
|
sign = -sign;
|
||||||
|
|
||||||
|
if (sign == 1)
|
||||||
|
return FALSE; /* Fully disjoint */
|
||||||
|
else if (sign == -1)
|
||||||
|
return TRUE; /* Fully overlapping */
|
||||||
|
else if (overlap_only)
|
||||||
|
return FALSE; /* Touching but not overlapping */
|
||||||
|
else
|
||||||
|
return TRUE; /* Touching but not overlapping */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (overlap_only)
|
||||||
|
{
|
||||||
|
if ((touch > 0) && (neg + touch == 3))
|
||||||
|
return TRUE; /* Enclosed and touching */
|
||||||
|
else if ((touch > 0) && (pos + touch == 3))
|
||||||
|
return FALSE; /* Unenclosed but touching */
|
||||||
|
else
|
||||||
|
return TRUE; /* Partially overlapping */
|
||||||
|
}
|
||||||
|
else /* overlap_only == FALSE */
|
||||||
|
{
|
||||||
|
if ((touch > 0) && (neg + touch == 3))
|
||||||
|
return TRUE; /* Enclosed and touching */
|
||||||
|
else if ((touch > 0) && (pos + touch == 3))
|
||||||
|
return TRUE; /* Unenclosed but touching */
|
||||||
|
else
|
||||||
|
return TRUE; /* Partially overlapping */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -56,6 +346,7 @@ int dbCheckMaxHFunc(), dbCheckMaxVFunc();
|
||||||
* int
|
* int
|
||||||
* func(tile, cdata)
|
* func(tile, cdata)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -92,7 +383,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
|
||||||
* provide a hint tile in case hintTile == NULL.
|
* provide a hint tile in case hintTile == NULL.
|
||||||
* The hint tile in the plane is updated to be
|
* The hint tile in the plane is updated to be
|
||||||
* the last tile visited in the area
|
* the last tile visited in the area
|
||||||
* enumeration.
|
* enumeration, if plane is non-NULL.
|
||||||
*/
|
*/
|
||||||
TileType ttype; /* Information about the non-manhattan area to
|
TileType ttype; /* Information about the non-manhattan area to
|
||||||
* search; zero if area is manhattan.
|
* search; zero if area is manhattan.
|
||||||
|
|
@ -129,7 +420,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
|
||||||
{
|
{
|
||||||
/* Each iteration enumerates another tile */
|
/* Each iteration enumerates another tile */
|
||||||
nm_enum:
|
nm_enum:
|
||||||
PlaneSetHint(plane, tp);
|
if (plane != (Plane *)NULL) PlaneSetHint(plane, tp);
|
||||||
if (SigInterruptPending)
|
if (SigInterruptPending)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
|
|
@ -137,147 +428,26 @@ nm_enum:
|
||||||
/* the tile enumeration if it is not. */
|
/* the tile enumeration if it is not. */
|
||||||
/* Watch for calculations involving (M)INFINITY in tile (tp)! */
|
/* Watch for calculations involving (M)INFINITY in tile (tp)! */
|
||||||
|
|
||||||
rheight = rect->r_ytop - rect->r_ybot;
|
|
||||||
rwidth = rect->r_xtop - rect->r_xbot;
|
|
||||||
rmax = MAX(rheight, rwidth);
|
|
||||||
f1 = (BOTTOM(tp) > MINFINITY + 2) ?
|
|
||||||
((dlong)(rect->r_ytop - BOTTOM(tp)) * rwidth) : DLONG_MAX;
|
|
||||||
f2 = (TOP(tp) < INFINITY - 2) ?
|
|
||||||
((dlong)(TOP(tp) - rect->r_ybot) * rwidth) : DLONG_MAX;
|
|
||||||
|
|
||||||
if (ttype & TT_SIDE)
|
|
||||||
{
|
|
||||||
/* Outside-of-triangle check---ignore sub-integer slivers */
|
|
||||||
if (RIGHT(tp) < INFINITY - 2)
|
|
||||||
{
|
|
||||||
f3 = (dlong)(rect->r_xtop - RIGHT(tp)) * rheight;
|
|
||||||
f3 += rmax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
f3 = DLONG_MIN;
|
|
||||||
if ((ttype & TT_DIRECTION) ? (f2 < f3) : (f1 < f3))
|
|
||||||
goto enum_next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Outside-of-triangle check---ignore sub-integer slivers */
|
|
||||||
if (LEFT(tp) > MINFINITY + 2)
|
|
||||||
{
|
|
||||||
f4 = (dlong)(LEFT(tp) - rect->r_xbot) * rheight;
|
|
||||||
f4 += rmax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
f4 = DLONG_MIN;
|
|
||||||
if ((ttype & TT_DIRECTION) ? (f1 < f4) : (f2 < f4))
|
|
||||||
goto enum_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Secondary checks---if tile is also non-Manhattan, is */
|
|
||||||
/* either side of it outside the area? If so, restrict it. */
|
|
||||||
/* This check is only necessary if the split directions are */
|
|
||||||
/* the same, so we have to see if either of the neighboring */
|
|
||||||
/* points is also inside the search triangle. */
|
|
||||||
|
|
||||||
ignore_sides = 0;
|
|
||||||
|
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
if (!TTMaskHasType(mask, SplitLeftType(tp)))
|
TileType tpdi = TiGetTypeExact(tp);
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
if (!TTMaskHasType(mask, SplitRightType(tp)))
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
|
|
||||||
tpt = TiGetTypeExact(tp);
|
if (TTMaskHasType(mask, SplitLeftType(tp)))
|
||||||
if ((tpt & TT_DIRECTION) == (ttype & TT_DIRECTION))
|
if (DBTestNMInteract(rect, ttype, tp, tpdi, TRUE))
|
||||||
{
|
if ((*func)(tp, (TileType)TT_DIAGONAL, arg))
|
||||||
f3 = (LEFT(tp) > MINFINITY + 2) ?
|
return 1;
|
||||||
((dlong)(rect->r_xtop - LEFT(tp)) * rheight) : DLONG_MAX;
|
if (TTMaskHasType(mask, SplitRightType(tp)))
|
||||||
f4 = (RIGHT(tp) < INFINITY - 2) ?
|
if (DBTestNMInteract(rect, ttype, tp, tpdi | TT_SIDE, TRUE))
|
||||||
((dlong)(RIGHT(tp) - rect->r_xbot) * rheight) : DLONG_MAX;
|
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg))
|
||||||
|
return 1;
|
||||||
if (ttype & TT_SIDE)
|
}
|
||||||
{
|
|
||||||
/* Ignore sub-integer slivers */
|
|
||||||
if (f4 != DLONG_MAX) f4 -= rmax;
|
|
||||||
if (f3 != DLONG_MAX) f3 += rmax;
|
|
||||||
|
|
||||||
if (ttype & TT_DIRECTION)
|
|
||||||
{
|
|
||||||
if ((f2 < f3) && (f1 > f4))
|
|
||||||
/* Tile bottom left is outside search area */
|
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((f1 < f3) && (f2 > f4))
|
|
||||||
/* Tile top left is outside search area */
|
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Ignore sub-integer slivers */
|
|
||||||
if (f4 != DLONG_MAX) f4 += rmax;
|
|
||||||
if (f3 != DLONG_MAX) f3 -= rmax;
|
|
||||||
|
|
||||||
if (ttype & TT_DIRECTION)
|
|
||||||
{
|
|
||||||
if ((f2 > f3) && (f1 < f4))
|
|
||||||
/* Tile top right is outside search area */
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((f1 > f3) && (f2 < f4))
|
|
||||||
/* Tile bottom right is outside search area */
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the tile is larger than the search area or overlaps */
|
|
||||||
/* the search area, we need to check if one of the sides */
|
|
||||||
/* of the tile is disjoint from the search area. */
|
|
||||||
|
|
||||||
rheight = TOP(tp) - BOTTOM(tp);
|
|
||||||
rwidth = RIGHT(tp) - LEFT(tp);
|
|
||||||
rmax = MAX(rheight, rwidth);
|
|
||||||
f1 = (TOP(tp) < INFINITY - 2) ?
|
|
||||||
((dlong)(TOP(tp) - rect->r_ybot) * rwidth) : DLONG_MAX;
|
|
||||||
f2 = (BOTTOM(tp) > MINFINITY + 2) ?
|
|
||||||
((dlong)(rect->r_ytop - BOTTOM(tp)) * rwidth) : DLONG_MAX;
|
|
||||||
f3 = (RIGHT(tp) < INFINITY - 2) ?
|
|
||||||
((dlong)(RIGHT(tp) - rect->r_xtop) * rheight) : DLONG_MAX;
|
|
||||||
f4 = (LEFT(tp) > MINFINITY + 2) ?
|
|
||||||
((dlong)(rect->r_xbot - LEFT(tp)) * rheight) : DLONG_MAX;
|
|
||||||
|
|
||||||
/* ignore sub-integer slivers */
|
|
||||||
if (f4 < DLONG_MAX) f4 += rmax;
|
|
||||||
if (f3 < DLONG_MAX) f3 += rmax;
|
|
||||||
|
|
||||||
if (SplitDirection(tp) ? (f1 < f4) : (f2 < f4))
|
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
|
|
||||||
if (SplitDirection(tp) ? (f2 < f3) : (f1 < f3))
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
|
|
||||||
/* May call function twice to paint both sides of */
|
|
||||||
/* the split tile, if necessary. */
|
|
||||||
|
|
||||||
if (!(ignore_sides & IGNORE_LEFT))
|
|
||||||
{
|
|
||||||
TiSetBody(tp, INT2CD(tpt & ~TT_SIDE)); /* bit clear */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
|
||||||
if (!(ignore_sides & IGNORE_RIGHT))
|
|
||||||
{
|
|
||||||
TiSetBody(tp, INT2CD(tpt | TT_SIDE)); /* bit set */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
|
{
|
||||||
return (1);
|
if (TTMaskHasType(mask, TiGetType(tp)))
|
||||||
|
if (DBTestNMInteract(rect, ttype, tp, (TileType)0, TRUE))
|
||||||
|
if ((*func)(tp, (TileType)0, arg))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
enum_next:
|
enum_next:
|
||||||
tpnew = TR(tp);
|
tpnew = TR(tp);
|
||||||
|
|
@ -325,6 +495,7 @@ enum_next:
|
||||||
* int
|
* int
|
||||||
* func(tile, cdata)
|
* func(tile, cdata)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -416,9 +587,7 @@ enumerate:
|
||||||
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
|
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((*func)(tp, (TileType)TT_DIAGONAL, arg)) return (1);
|
||||||
& ~TT_SIDE)); /* bit clear */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,14 +598,12 @@ enumerate:
|
||||||
(dlong)(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
|
(dlong)(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg)) return (1);
|
||||||
| TT_SIDE)); /* bit set */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
|
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, (TileType)0, arg))
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
tpnew = TR(tp);
|
tpnew = TR(tp);
|
||||||
|
|
@ -485,6 +652,7 @@ enumerate:
|
||||||
* int
|
* int
|
||||||
* func(tile, cdata)
|
* func(tile, cdata)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -576,9 +744,7 @@ enumerate:
|
||||||
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
|
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL, arg))
|
||||||
& ~TT_SIDE)); /* bit clear */
|
|
||||||
if ((tp->ti_client == client) && (*func)(tp, arg))
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -590,16 +756,15 @@ enumerate:
|
||||||
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
|
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL
|
||||||
| TT_SIDE)); /* bit set */
|
| TT_SIDE, arg))
|
||||||
if ((tp->ti_client == client) && (*func)(tp, arg))
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (TTMaskHasType(mask, TiGetType(tp)) && tp->ti_client == client
|
if (TTMaskHasType(mask, TiGetType(tp)) && tp->ti_client == client
|
||||||
&& (*func)(tp, arg))
|
&& (*func)(tp, (TileType)0, arg))
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
tpnew = TR(tp);
|
tpnew = TR(tp);
|
||||||
|
|
@ -665,7 +830,7 @@ DBResetTilePlane(plane, cdata)
|
||||||
/* Each iteration visits another tile on the LHS of the search area */
|
/* Each iteration visits another tile on the LHS of the search area */
|
||||||
while (TOP(tp) > rect->r_ybot)
|
while (TOP(tp) > rect->r_ybot)
|
||||||
{
|
{
|
||||||
/* Each iteration frees another tile */
|
/* Each iteration resets another tile */
|
||||||
enumerate:
|
enumerate:
|
||||||
tp->ti_client = cdata;
|
tp->ti_client = cdata;
|
||||||
|
|
||||||
|
|
@ -701,6 +866,88 @@ enumerate:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBResetTilePlaneSpecial --
|
||||||
|
*
|
||||||
|
* This routine works like DBResetTilePlane(), but is designed
|
||||||
|
* specifically to be run after extFindNodes() or ExtFindRegions()
|
||||||
|
* to check for split tiles that have an allocated ExtSplitRegion
|
||||||
|
* structure in the ClientData; this needs to be freed before
|
||||||
|
* resetting the ClientData value to "cdata". It is not necessary
|
||||||
|
* to know anything about the ExtSplitRegion structure other than
|
||||||
|
* the condition under which it can be expected to be present,
|
||||||
|
* which is a split tile with neither side having type TT_SPACE.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Resets the ti_client fields of all tiles.
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
DBResetTilePlaneSpecial(plane, cdata)
|
||||||
|
Plane *plane; /* Plane whose tiles are to be reset */
|
||||||
|
ClientData cdata;
|
||||||
|
{
|
||||||
|
Tile *tp, *tpnew;
|
||||||
|
const Rect *rect = &TiPlaneRect;
|
||||||
|
|
||||||
|
/* Start with the leftmost non-infinity tile in the plane */
|
||||||
|
tp = TR(plane->pl_left);
|
||||||
|
|
||||||
|
/* Each iteration visits another tile on the LHS of the search area */
|
||||||
|
while (TOP(tp) > rect->r_ybot)
|
||||||
|
{
|
||||||
|
/* Each iteration resets another tile */
|
||||||
|
enumerate:
|
||||||
|
if (IsSplit(tp))
|
||||||
|
if ((TiGetLeftType(tp) != TT_SPACE) && (TiGetRightType(tp) != TT_SPACE))
|
||||||
|
if (tp->ti_client != cdata)
|
||||||
|
{
|
||||||
|
ASSERT(TiGetBody((Tile *)tp->ti_client) == CLIENTDEFAULT,
|
||||||
|
"DBResetTilePlaneSpecial");
|
||||||
|
freeMagic(tp->ti_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
tp->ti_client = cdata;
|
||||||
|
|
||||||
|
/* Move along to the next tile */
|
||||||
|
tpnew = TR(tp);
|
||||||
|
if (LEFT(tpnew) < rect->r_xtop)
|
||||||
|
{
|
||||||
|
while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew);
|
||||||
|
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
|
||||||
|
{
|
||||||
|
tp = tpnew;
|
||||||
|
goto enumerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Each iteration returns one tile further to the left */
|
||||||
|
while (LEFT(tp) > rect->r_xbot)
|
||||||
|
{
|
||||||
|
if (BOTTOM(tp) <= rect->r_ybot)
|
||||||
|
return;
|
||||||
|
tpnew = LB(tp);
|
||||||
|
tp = BL(tp);
|
||||||
|
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
|
||||||
|
{
|
||||||
|
tp = tpnew;
|
||||||
|
goto enumerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At left edge -- walk down to next tile along the left edge */
|
||||||
|
for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp))
|
||||||
|
/* Nothing */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -918,8 +1165,9 @@ DBCheckMaxHStrips(plane, area, proc, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCheckMaxHFunc(tile, dbc)
|
dbCheckMaxHFunc(tile, dinfo, dbc)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct dbCheck *dbc;
|
struct dbCheck *dbc;
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
@ -1010,8 +1258,9 @@ DBCheckMaxVStrips(plane, area, proc, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCheckMaxVFunc(tile, dbc)
|
dbCheckMaxVFunc(tile, dinfo, dbc)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct dbCheck *dbc;
|
struct dbCheck *dbc;
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
|
||||||
|
|
@ -137,8 +137,10 @@ DBFixMismatch()
|
||||||
|
|
||||||
cellDef = mismatch->mm_cellDef;
|
cellDef = mismatch->mm_cellDef;
|
||||||
oldArea = mismatch->mm_oldArea;
|
oldArea = mismatch->mm_oldArea;
|
||||||
freeMagic((char *) mismatch);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, (char *) mismatch);
|
||||||
mismatch = mismatch->mm_next;
|
mismatch = mismatch->mm_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
if (cellDef->cd_flags & CDPROCESSED) continue;
|
if (cellDef->cd_flags & CDPROCESSED) continue;
|
||||||
|
|
||||||
(void) DBCellRead(cellDef, TRUE, TRUE, NULL);
|
(void) DBCellRead(cellDef, TRUE, TRUE, NULL);
|
||||||
|
|
@ -182,13 +184,15 @@ DBFixMismatch()
|
||||||
}
|
}
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
TxPrintf("Timestamp mismatches found in these cells: ");
|
TxPrintf("Timestamp mismatches found in these cells: ");
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (cl != NULL)
|
while (cl != NULL)
|
||||||
{
|
{
|
||||||
TxPrintf("%s", cl->cl_cell->cd_name);
|
TxPrintf("%s", cl->cl_cell->cd_name);
|
||||||
if (cl->cl_next != NULL) TxPrintf(", ");
|
if (cl->cl_next != NULL) TxPrintf(", ");
|
||||||
freeMagic(cl);
|
freeMagic1(&mm1, cl);
|
||||||
cl = cl->cl_next;
|
cl = cl->cl_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
TxPrintf(".\n");
|
TxPrintf(".\n");
|
||||||
TxFlush();
|
TxFlush();
|
||||||
if (redisplay) WindAreaChanged((MagWindow *) NULL, (Rect *) NULL);
|
if (redisplay) WindAreaChanged((MagWindow *) NULL, (Rect *) NULL);
|
||||||
|
|
@ -227,7 +231,7 @@ DBUpdateStamps(def)
|
||||||
|
|
||||||
else if (def->cd_flags & CDGETNEWSTAMP)
|
else if (def->cd_flags & CDGETNEWSTAMP)
|
||||||
{
|
{
|
||||||
if (def->cd_flags & CDFIXEDSTAMP)
|
if (def->cd_flags & (CDNOEDIT | CDFIXEDSTAMP))
|
||||||
def->cd_flags &= ~CDGETNEWSTAMP;
|
def->cd_flags &= ~CDGETNEWSTAMP;
|
||||||
else
|
else
|
||||||
dbStampFunc(def);
|
dbStampFunc(def);
|
||||||
|
|
@ -247,6 +251,26 @@ dbStampFunc(cellDef)
|
||||||
|
|
||||||
if (cellDef->cd_timestamp == timestamp) return 0;
|
if (cellDef->cd_timestamp == timestamp) return 0;
|
||||||
|
|
||||||
|
/* Non-editable cells should not try to update timestamps, as the
|
||||||
|
* new timestamp cannot be written back to the file. This is
|
||||||
|
* basically a hack solution for the problem that running DRC on
|
||||||
|
* all cells causes all cells, including non-editable ones, to be
|
||||||
|
* marked as modified, even if there were no DRC changes in the
|
||||||
|
* cell. It is possible to get into trouble this way by modifying
|
||||||
|
* a cell and then marking it as non-editable
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (cellDef->cd_flags & CDNOEDIT)
|
||||||
|
{
|
||||||
|
cellDef->cd_flags &= ~CDGETNEWSTAMP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not force a non-edit cell or a cell with a fixed timestamp
|
||||||
|
* to update its timestamp, as it cannot or should not. Just clear
|
||||||
|
* any flag suggesting that it needs a new timestamp.
|
||||||
|
*/
|
||||||
if (!(cellDef->cd_flags & CDFIXEDSTAMP))
|
if (!(cellDef->cd_flags & CDFIXEDSTAMP))
|
||||||
cellDef->cd_timestamp = timestamp;
|
cellDef->cd_timestamp = timestamp;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -303,9 +303,14 @@ typedef struct label
|
||||||
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
|
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
|
||||||
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
|
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
|
||||||
|
|
||||||
#define PORT_VISITED 0x2000 /* Bit for checking if a port */
|
#define LABEL_STICKY 0x2000 /* Label does not change layers */
|
||||||
|
#define LABEL_UNIQUE 0x4000 /* Temporary unique label */
|
||||||
|
|
||||||
|
/* The last two flags are never used at the same time and so can share
|
||||||
|
* a flag bit.
|
||||||
|
*/
|
||||||
|
#define PORT_VISITED 0x8000 /* Bit for checking if a port */
|
||||||
/* has been previously visited. */
|
/* has been previously visited. */
|
||||||
#define LABEL_STICKY 0x4000 /* Label does not change layers */
|
|
||||||
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
|
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -403,6 +408,9 @@ typedef struct celldef
|
||||||
* is added to the magic database. The flag is used to identify
|
* is added to the magic database. The flag is used to identify
|
||||||
* whether the cell has been processed when forcing the GDS
|
* whether the cell has been processed when forcing the GDS
|
||||||
* stream data to be read in post-order.
|
* stream data to be read in post-order.
|
||||||
|
* CDPRELOADED is similar to CDPROCESSEDGDS but is used in cases
|
||||||
|
* other than forced post-order reading, such as flattening
|
||||||
|
* or flatten-by-name.
|
||||||
* CDVENDORGDS indicates that the cell was read from a GDS stream
|
* CDVENDORGDS indicates that the cell was read from a GDS stream
|
||||||
* with the option "gds readonly true".
|
* with the option "gds readonly true".
|
||||||
* CDVISITED indicates that at least one instance of the cell was
|
* CDVISITED indicates that at least one instance of the cell was
|
||||||
|
|
@ -434,12 +442,13 @@ typedef struct celldef
|
||||||
#define CDFLATGDS 0x00400
|
#define CDFLATGDS 0x00400
|
||||||
#define CDFLATTENED 0x00800
|
#define CDFLATTENED 0x00800
|
||||||
#define CDPROCESSEDGDS 0x01000
|
#define CDPROCESSEDGDS 0x01000
|
||||||
#define CDVENDORGDS 0x02000
|
#define CDPRELOADED 0x02000
|
||||||
#define CDVISITED 0x04000
|
#define CDVENDORGDS 0x04000
|
||||||
#define CDDEREFERENCE 0x08000
|
#define CDVISITED 0x08000
|
||||||
#define CDFIXEDSTAMP 0x10000
|
#define CDDEREFERENCE 0x10000
|
||||||
#define CDNOEXTRACT 0x20000
|
#define CDFIXEDSTAMP 0x20000
|
||||||
#define CDDONTUSE 0x40000
|
#define CDNOEXTRACT 0x40000
|
||||||
|
#define CDDONTUSE 0x80000
|
||||||
|
|
||||||
#include "database/arrayinfo.h" /* ArrayInfo */
|
#include "database/arrayinfo.h" /* ArrayInfo */
|
||||||
|
|
||||||
|
|
@ -547,6 +556,18 @@ typedef struct diag_info
|
||||||
bool side;
|
bool side;
|
||||||
} DiagInfo;
|
} DiagInfo;
|
||||||
|
|
||||||
|
/* Where search functions need to return a Tile pointer and tile split */
|
||||||
|
/* information, use this structure. Contains a pointer to its own */
|
||||||
|
/* structure type so that it may also be used to create a linked list */
|
||||||
|
/* of tiles including split side information. */
|
||||||
|
|
||||||
|
typedef struct tile_and_dinfo
|
||||||
|
{
|
||||||
|
struct tile_and_dinfo *tad_next;
|
||||||
|
Tile *tad_tile;
|
||||||
|
TileType tad_dinfo;
|
||||||
|
} TileAndDinfo;
|
||||||
|
|
||||||
/* This would normally go in geometry.h except that it uses TileType. */
|
/* This would normally go in geometry.h except that it uses TileType. */
|
||||||
/* Used in selOps.c but also passed back to CmdRS.c for select command. */
|
/* Used in selOps.c but also passed back to CmdRS.c for select command. */
|
||||||
|
|
||||||
|
|
@ -630,6 +651,7 @@ typedef struct treeFilter
|
||||||
#define TF_LABEL_ATTACH_NOT_SE 0x10 /* Same as above, ignore tile SE corner */
|
#define TF_LABEL_ATTACH_NOT_SE 0x10 /* Same as above, ignore tile SE corner */
|
||||||
#define TF_LABEL_ATTACH_NOT_SW 0x20 /* Same as above, ignore tile SW corner */
|
#define TF_LABEL_ATTACH_NOT_SW 0x20 /* Same as above, ignore tile SW corner */
|
||||||
#define TF_LABEL_ATTACH_CORNER 0x3C /* Mask of the four types above */
|
#define TF_LABEL_ATTACH_CORNER 0x3C /* Mask of the four types above */
|
||||||
|
#define TF_LABEL_REVERSE_SEARCH 0x40 /* Search children before parent */
|
||||||
|
|
||||||
/* To do: Make the tpath entries dynamically allocated */
|
/* To do: Make the tpath entries dynamically allocated */
|
||||||
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
|
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
|
||||||
|
|
@ -683,6 +705,25 @@ struct conSrArg2
|
||||||
|
|
||||||
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
||||||
|
|
||||||
|
/* ------------------------ Properties ------------------------------ */
|
||||||
|
|
||||||
|
/* Note that the property record is a single allocated block large enough
|
||||||
|
* to hold the string or integer list, and can be freed as a single block.
|
||||||
|
* The array bounds, like those of lab_text for labels, are placeholders.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int prop_type; /* See codes below; e.g., PROPERTY_TYPE_STRING */
|
||||||
|
int prop_len; /* String length or number of values */
|
||||||
|
union {
|
||||||
|
char prop_string[8]; /* For PROPERTY_TYPE_STRING */
|
||||||
|
int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */
|
||||||
|
dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */
|
||||||
|
Plane *prop_plane; /* For PROPERTY_TYPE_PLANE */
|
||||||
|
} prop_value;
|
||||||
|
} PropertyRecord;
|
||||||
|
|
||||||
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
@ -715,6 +756,14 @@ typedef struct
|
||||||
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
||||||
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
||||||
|
|
||||||
|
/* ---------------------- Codes for properties -------------------------*/
|
||||||
|
|
||||||
|
#define PROPERTY_TYPE_STRING 0 /* ASCII string property */
|
||||||
|
#define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */
|
||||||
|
#define PROPERTY_TYPE_DIMENSION 2 /* Integer property that scales with units */
|
||||||
|
#define PROPERTY_TYPE_DOUBLE 3 /* Double-long integer (for file positions) */
|
||||||
|
#define PROPERTY_TYPE_PLANE 4 /* A tile plane structure */
|
||||||
|
|
||||||
/* -------------------- Exported procedure headers -------------------- */
|
/* -------------------- Exported procedure headers -------------------- */
|
||||||
|
|
||||||
/* Painting/erasing */
|
/* Painting/erasing */
|
||||||
|
|
@ -769,7 +818,7 @@ extern void DBTechInit();
|
||||||
extern bool DBTechSetTech();
|
extern bool DBTechSetTech();
|
||||||
extern void DBTechInitVersion();
|
extern void DBTechInitVersion();
|
||||||
extern bool DBTechSetVersion();
|
extern bool DBTechSetVersion();
|
||||||
extern bool DBTechAddPlane();
|
extern bool DBTechAddPlane(const char *sectionName, int argc, char *argv[]);
|
||||||
extern bool DBTechAddType();
|
extern bool DBTechAddType();
|
||||||
extern bool DBTechAddAlias();
|
extern bool DBTechAddAlias();
|
||||||
extern void DBTechFinalType();
|
extern void DBTechFinalType();
|
||||||
|
|
@ -781,7 +830,7 @@ extern int DBTechNamePlane(), DBTechNoisyNamePlane();
|
||||||
extern PlaneMask DBTechNameMask(), DBTechNoisyNameMask();
|
extern PlaneMask DBTechNameMask(), DBTechNoisyNameMask();
|
||||||
extern PlaneMask DBTechTypesToPlanes();
|
extern PlaneMask DBTechTypesToPlanes();
|
||||||
extern bool DBTechTypesOnPlane();
|
extern bool DBTechTypesOnPlane();
|
||||||
extern void DBTechInitPlane();
|
extern void DBTechInitPlane(void);
|
||||||
extern void DBTypeInit();
|
extern void DBTypeInit();
|
||||||
extern void DBTechInitType();
|
extern void DBTechInitType();
|
||||||
extern void DBTechInitCompose();
|
extern void DBTechInitCompose();
|
||||||
|
|
@ -900,7 +949,9 @@ extern void DBFreePaintPlane();
|
||||||
|
|
||||||
/* Cell properties */
|
/* Cell properties */
|
||||||
extern void DBPropPut();
|
extern void DBPropPut();
|
||||||
extern ClientData DBPropGet();
|
extern PropertyRecord *DBPropGet();
|
||||||
|
extern char *DBPropGetString();
|
||||||
|
extern dlong DBPropGetDouble();
|
||||||
extern int DBPropEnum();
|
extern int DBPropEnum();
|
||||||
extern void DBPropClearAll();
|
extern void DBPropClearAll();
|
||||||
|
|
||||||
|
|
@ -916,9 +967,10 @@ extern int DBArraySr();
|
||||||
extern bool DBNearestLabel();
|
extern bool DBNearestLabel();
|
||||||
extern int DBSrLabelLoc();
|
extern int DBSrLabelLoc();
|
||||||
extern TileType DBTransformDiagonal();
|
extern TileType DBTransformDiagonal();
|
||||||
extern int dbcUnconnectFunc(Tile *tile, ClientData clientData); /* (notused) */
|
extern bool DBTestNMInteract(Rect *rect1, TileType tt1, Tile *t2, TileType di2, bool overlap_only);
|
||||||
extern int dbSrConnectFunc(Tile *tile, ClientData clientData); /* (struct conSrArg *csa) */
|
extern int dbcUnconnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (notused) */
|
||||||
extern int dbSrConnectStartFunc(Tile *tile, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
|
extern int dbSrConnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (struct conSrArg *csa) */
|
||||||
|
extern int dbSrConnectStartFunc(Tile *tile, TileType dinfo, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void DBEraseValid();
|
extern void DBEraseValid();
|
||||||
|
|
@ -965,10 +1017,10 @@ extern int dbIsPrimary();
|
||||||
extern void dbTechMatchResidues();
|
extern void dbTechMatchResidues();
|
||||||
extern void DBUndoInit();
|
extern void DBUndoInit();
|
||||||
extern void DBResetTilePlane();
|
extern void DBResetTilePlane();
|
||||||
|
extern void DBResetTilePlaneSpecial();
|
||||||
extern void DBNewYank();
|
extern void DBNewYank();
|
||||||
extern int DBSrPaintClient();
|
extern int DBSrPaintClient();
|
||||||
extern int DBSrConnect();
|
extern int DBSrConnect();
|
||||||
extern int DBSrConnectOnePlane();
|
|
||||||
extern char *dbFgets();
|
extern char *dbFgets();
|
||||||
extern void DBAdjustLabelsNew();
|
extern void DBAdjustLabelsNew();
|
||||||
extern bool DBScaleValue();
|
extern bool DBScaleValue();
|
||||||
|
|
@ -997,6 +1049,7 @@ extern int DBLambda[2];
|
||||||
/* -------------------- Exported magic file suffix -------------------- */
|
/* -------------------- Exported magic file suffix -------------------- */
|
||||||
|
|
||||||
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
||||||
|
extern bool DBPropCompat; /* Backwards-compatible properties */
|
||||||
|
|
||||||
/* -------------------- User Interface Stuff -------------------------- */
|
/* -------------------- User Interface Stuff -------------------------- */
|
||||||
|
|
||||||
|
|
@ -1009,6 +1062,19 @@ extern unsigned char DBVerbose; /* If 0, don't print any messages */
|
||||||
#define DB_VERBOSE_WARN 2
|
#define DB_VERBOSE_WARN 2
|
||||||
#define DB_VERBOSE_ALL 3
|
#define DB_VERBOSE_ALL 3
|
||||||
|
|
||||||
|
/* ---------- Definitions for expanding/unexpanding cells --------------*/
|
||||||
|
|
||||||
|
/* Selection expansion flags */
|
||||||
|
#define DB_EXPAND_MASK 3 /* 1 = expand, 0 = unexpand, 2 = toggle */
|
||||||
|
#define DB_EXPAND_SURROUND_MASK 4 /* 1 = surround, 0 = touch */
|
||||||
|
|
||||||
|
/* Selection expansion values */
|
||||||
|
#define DB_EXPAND 0
|
||||||
|
#define DB_UNEXPAND 1
|
||||||
|
#define DB_EXPAND_TOGGLE 2
|
||||||
|
#define DB_EXPAND_SURROUND 4
|
||||||
|
#define DB_EXPAND_OVERLAP 0
|
||||||
|
|
||||||
/* ------------------ Exported technology variables ------------------- */
|
/* ------------------ Exported technology variables ------------------- */
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|
@ -1055,10 +1121,10 @@ extern int DBNumPlanes;
|
||||||
extern HashTable DBTypeAliasTable;
|
extern HashTable DBTypeAliasTable;
|
||||||
|
|
||||||
/* Gives the official long name of each plane: */
|
/* Gives the official long name of each plane: */
|
||||||
extern char *DBPlaneLongNameTbl[NP];
|
extern const char *DBPlaneLongNameTbl[NP];
|
||||||
|
|
||||||
/* Gives a short name for each plane: */
|
/* Gives a short name for each plane: */
|
||||||
extern char *DBPlaneShortName();
|
extern const char *DBPlaneShortName();
|
||||||
|
|
||||||
/* Gives for each plane a mask of all tile types stored in that plane: */
|
/* Gives for each plane a mask of all tile types stored in that plane: */
|
||||||
extern TileTypeBitMask DBPlaneTypes[NP];
|
extern TileTypeBitMask DBPlaneTypes[NP];
|
||||||
|
|
@ -1117,10 +1183,10 @@ extern int DBTypePlaneTbl[TT_MAXTYPES];
|
||||||
extern PlaneMask DBTypePlaneMaskTbl[TT_MAXTYPES];
|
extern PlaneMask DBTypePlaneMaskTbl[TT_MAXTYPES];
|
||||||
|
|
||||||
/* Gives the long name for each tile type: */
|
/* Gives the long name for each tile type: */
|
||||||
extern char *DBTypeLongNameTbl[TT_MAXTYPES];
|
extern const char *DBTypeLongNameTbl[TT_MAXTYPES];
|
||||||
|
|
||||||
/* Gives a short name for a tile type: */
|
/* Gives a short name for a tile type: */
|
||||||
extern char *DBTypeShortName();
|
extern const char *DBTypeShortName(TileType type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following give masks of all planes that may be affected
|
* The following give masks of all planes that may be affected
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,8 @@ typedef struct
|
||||||
extern int dbNumSavedRules;
|
extern int dbNumSavedRules;
|
||||||
extern Rule dbSavedRules[];
|
extern Rule dbSavedRules[];
|
||||||
|
|
||||||
|
extern HashTable dbCellDefTable; /* Exported for diagnostics */
|
||||||
|
|
||||||
/* -------------------- Internal procedure headers -------------------- */
|
/* -------------------- Internal procedure headers -------------------- */
|
||||||
|
|
||||||
extern void DBUndoPutLabel();
|
extern void DBUndoPutLabel();
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
|
|
@ -130,8 +131,11 @@ DBWAddButtonHandler(
|
||||||
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
||||||
{
|
{
|
||||||
if (dbwButtonHandlers[i] != NULL) continue;
|
if (dbwButtonHandlers[i] != NULL) continue;
|
||||||
(void) StrDup(&dbwButtonHandlers[i], name);
|
StrDup(&dbwButtonHandlers[i], name);
|
||||||
(void) StrDup(&dbwButtonDoc[i], doc);
|
if (doc != NULL)
|
||||||
|
StrDup(&dbwButtonDoc[i], doc);
|
||||||
|
else
|
||||||
|
dbwButtonDoc[i] = (char *)NULL;
|
||||||
dbwButtonProcs[i] = proc;
|
dbwButtonProcs[i] = proc;
|
||||||
dbwButtonCursors[i] = cursor;
|
dbwButtonCursors[i] = cursor;
|
||||||
return;
|
return;
|
||||||
|
|
@ -240,6 +244,69 @@ DBWChangeButtonHandler(name)
|
||||||
return oldName;
|
return oldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBWGetButtonHandler --
|
||||||
|
*
|
||||||
|
* Return the name of the current button handler. This does the same
|
||||||
|
* thing as DBWChangeButtonHandler(name) with an invalid name, but
|
||||||
|
* without printing the error messages. However, if magic is running
|
||||||
|
* with the Tcl interpreter wrapper, then return the string value of
|
||||||
|
* $Opts(tool), if it exists.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* A pointer to the name of the current button handler.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWGetButtonHandler()
|
||||||
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
char *toolName;
|
||||||
|
toolName = (char *)Tcl_GetVar2(magicinterp, "Opts", "tool", TCL_GLOBAL_ONLY);
|
||||||
|
if (toolName != NULL) return toolName;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return dbwButtonHandlers[dbwButtonCurrentIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBWButtonHandlerIndex()
|
||||||
|
*
|
||||||
|
* Given a string, return the index of the button handler. If the
|
||||||
|
* string does not correspond to any button handler name, then
|
||||||
|
* return -1.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Index of button handler, if it exists; -1 otherwise.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
DBWButtonHandlerIndex(char *toolName)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXBUTTONHANDLERS; i++)
|
||||||
|
{
|
||||||
|
if (dbwButtonHandlers[i] == NULL) return -1;
|
||||||
|
else if (!strcmp(toolName, dbwButtonHandlers[i])) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -261,7 +328,10 @@ DBWChangeButtonHandler(name)
|
||||||
void
|
void
|
||||||
DBWPrintButtonDoc()
|
DBWPrintButtonDoc()
|
||||||
{
|
{
|
||||||
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
|
if (dbwButtonDoc[dbwButtonCurrentIndex])
|
||||||
|
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
|
||||||
|
else
|
||||||
|
TxPrintf("(no usage information)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* Standard DBWind command set
|
* Standard DBWind command set
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void CmdAddPath(), CmdAntennaCheck(), CmdArray();
|
extern void CmdAddPath(), CmdAntennaCheck(), CmdArchive(), CmdArray();
|
||||||
extern void CmdBox(), CmdCellname(), CmdClockwise();
|
extern void CmdBox(), CmdCellname(), CmdClockwise();
|
||||||
extern void CmdContact(), CmdCopy(), CmdCorner();
|
extern void CmdContact(), CmdCopy(), CmdCorner();
|
||||||
extern void CmdCrash(), CmdCrosshair();
|
extern void CmdCrash(), CmdCrosshair();
|
||||||
|
|
@ -54,7 +54,7 @@ extern void CmdRandom(), CmdSave(), CmdScaleGrid(), CmdSee();
|
||||||
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
|
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
|
||||||
extern void CmdShell(), CmdSnap();
|
extern void CmdShell(), CmdSnap();
|
||||||
extern void CmdStretch(), CmdStraighten();
|
extern void CmdStretch(), CmdStraighten();
|
||||||
extern void CmdTech(), CmdTool(), CmdUnexpand();
|
extern void CmdTech(), CmdTool(), CmdUnexpand(), CmdUnits();
|
||||||
extern void CmdUpsidedown(), CmdWhat(), CmdWire(), CmdWriteall();
|
extern void CmdUpsidedown(), CmdWhat(), CmdWire(), CmdWriteall();
|
||||||
extern void CmdGoto(), CmdFlatten(), CmdXload(), CmdXor();
|
extern void CmdGoto(), CmdFlatten(), CmdXload(), CmdXor();
|
||||||
|
|
||||||
|
|
@ -75,6 +75,7 @@ extern void CmdExtResis();
|
||||||
extern void CmdPsearch();
|
extern void CmdPsearch();
|
||||||
extern void CmdPlowTest();
|
extern void CmdPlowTest();
|
||||||
extern void CmdShowtech();
|
extern void CmdShowtech();
|
||||||
|
extern void CmdShowmem();
|
||||||
extern void CmdTilestats();
|
extern void CmdTilestats();
|
||||||
extern void CmdTsearch();
|
extern void CmdTsearch();
|
||||||
extern void CmdWatch();
|
extern void CmdWatch();
|
||||||
|
|
@ -208,6 +209,9 @@ DBWInitCommands()
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"*psearch plane count invoke point search over box area",
|
"*psearch plane count invoke point search over box area",
|
||||||
CmdPsearch, FALSE);
|
CmdPsearch, FALSE);
|
||||||
|
WindAddCommand(DBWclientID,
|
||||||
|
"*showmem [file] print internal memory usage",
|
||||||
|
CmdShowmem, FALSE);
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"*showtech [file] print internal technology tables",
|
"*showtech [file] print internal technology tables",
|
||||||
CmdShowtech, FALSE);
|
CmdShowtech, FALSE);
|
||||||
|
|
@ -228,6 +232,10 @@ DBWInitCommands()
|
||||||
"antennacheck [path] check for antenna violations",
|
"antennacheck [path] check for antenna violations",
|
||||||
CmdAntennaCheck, FALSE);
|
CmdAntennaCheck, FALSE);
|
||||||
#endif
|
#endif
|
||||||
|
WindAddCommand(DBWclientID,
|
||||||
|
"archive write|read file\n"
|
||||||
|
" write or read the archive file \"file\".",
|
||||||
|
CmdArchive, FALSE);
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"array xsize ysize OR\n"
|
"array xsize ysize OR\n"
|
||||||
"array xlo xhi ylo yhi\n"
|
"array xlo xhi ylo yhi\n"
|
||||||
|
|
@ -466,6 +474,9 @@ DBWInitCommands()
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"unexpand unexpand subcells under box",
|
"unexpand unexpand subcells under box",
|
||||||
CmdUnexpand, FALSE);
|
CmdUnexpand, FALSE);
|
||||||
|
WindAddCommand(DBWclientID,
|
||||||
|
"units [type] set type of units parsed and displayed",
|
||||||
|
CmdUnits, FALSE);
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"upsidedown flip selection and box upside down",
|
"upsidedown flip selection and box upside down",
|
||||||
CmdUpsidedown, FALSE);
|
CmdUpsidedown, FALSE);
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,8 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
/* Set style information beforehand */
|
/* Set style information beforehand */
|
||||||
GrSetStuff(STYLE_LABEL);
|
GrSetStuff(STYLE_LABEL);
|
||||||
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
||||||
(TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
|
(TerminalPath *) NULL,
|
||||||
|
TF_LABEL_DISPLAY | TF_LABEL_ATTACH | TF_LABEL_REVERSE_SEARCH,
|
||||||
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
|
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
|
||||||
GrClipTo(&rootClip);
|
GrClipTo(&rootClip);
|
||||||
}
|
}
|
||||||
|
|
@ -571,8 +572,9 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwPaintFunc(tile, cxp)
|
dbwPaintFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Tile to be redisplayed. */
|
Tile *tile; /* Tile to be redisplayed. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* From DBTreeSrTiles */
|
TreeContext *cxp; /* From DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -652,7 +654,7 @@ dbwPaintFunc(tile, cxp)
|
||||||
/* whether to render the outline with a fast rectangle- */
|
/* whether to render the outline with a fast rectangle- */
|
||||||
/* drawing routine or to render it segment by segment. */
|
/* drawing routine or to render it segment by segment. */
|
||||||
|
|
||||||
GrBox(dbwWindow, &scx->scx_trans, tile);
|
GrBox(dbwWindow, &scx->scx_trans, tile, dinfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1075,8 +1077,10 @@ dbwBBoxFunc(scx)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwTileFunc(tile)
|
dbwTileFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile; /* A tile to be redisplayed. */
|
Tile *tile; /* A tile to be redisplayed. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
Rect r, r2;
|
Rect r, r2;
|
||||||
int xoffset, yoffset;
|
int xoffset, yoffset;
|
||||||
|
|
@ -1113,7 +1117,7 @@ dbwTileFunc(tile)
|
||||||
|
|
||||||
if (dbwSeeTypes)
|
if (dbwSeeTypes)
|
||||||
{
|
{
|
||||||
(void) sprintf(string, "%s",DBTypeShortName(TiGetType(tile)));
|
(void) sprintf(string, "%s", DBTypeShortName(TiGetType(tile)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1129,7 +1133,7 @@ dbwTileFunc(tile)
|
||||||
|
|
||||||
#define XYOFFSET 12
|
#define XYOFFSET 12
|
||||||
|
|
||||||
for (i=0; i<4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
xoffset = 0;
|
xoffset = 0;
|
||||||
yoffset = 0;
|
yoffset = 0;
|
||||||
|
|
@ -1172,13 +1176,13 @@ dbwTileFunc(tile)
|
||||||
yoffset = temp;
|
yoffset = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0) )
|
if ((dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0))
|
||||||
{
|
{
|
||||||
/* mirror in x */
|
/* mirror in x */
|
||||||
xoffset = -xoffset;
|
xoffset = -xoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0) )
|
if ((dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0))
|
||||||
{
|
{
|
||||||
/* mirror in y */
|
/* mirror in y */
|
||||||
yoffset = -yoffset;
|
yoffset = -yoffset;
|
||||||
|
|
|
||||||
|
|
@ -588,10 +588,12 @@ DBWElementDelete(MagWindow *w, char *name)
|
||||||
if (elem->flags & DBW_ELEMENT_PERSISTENT)
|
if (elem->flags & DBW_ELEMENT_PERSISTENT)
|
||||||
elem->rootDef->cd_flags |= CDMODIFIED;
|
elem->rootDef->cd_flags |= CDMODIFIED;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
|
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
|
||||||
{
|
{
|
||||||
freeMagic(stylePtr);
|
freeMagic1(&mm1, stylePtr);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
if (elem->type == ELEMENT_TEXT)
|
if (elem->type == ELEMENT_TEXT)
|
||||||
freeMagic(elem->text);
|
freeMagic(elem->text);
|
||||||
|
|
||||||
|
|
@ -1156,8 +1158,10 @@ DBWElementStyle(MagWindow *w, char *ename, int style, bool add)
|
||||||
(elem->stylelist->style == style))
|
(elem->stylelist->style == style))
|
||||||
{
|
{
|
||||||
dbwElementUndraw(w, elem);
|
dbwElementUndraw(w, elem);
|
||||||
freeMagic(elem->stylelist);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, elem->stylelist);
|
||||||
elem->stylelist = elem->stylelist->next;
|
elem->stylelist = elem->stylelist->next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
if (elem->stylelist == NULL)
|
if (elem->stylelist == NULL)
|
||||||
TxPrintf("Warning: Element %s has no styles!\n", ename);
|
TxPrintf("Warning: Element %s has no styles!\n", ename);
|
||||||
}
|
}
|
||||||
|
|
@ -1169,8 +1173,10 @@ DBWElementStyle(MagWindow *w, char *ename, int style, bool add)
|
||||||
else if (sptr->next != NULL)
|
else if (sptr->next != NULL)
|
||||||
{
|
{
|
||||||
dbwElementUndraw(w, elem);
|
dbwElementUndraw(w, elem);
|
||||||
freeMagic(sptr->next);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, sptr->next);
|
||||||
sptr->next = sptr->next->next;
|
sptr->next = sptr->next->next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* mark element's cell as having been modified */
|
/* mark element's cell as having been modified */
|
||||||
|
|
@ -1279,8 +1285,10 @@ DBWElementClearDef(cellDef)
|
||||||
if (!elem) continue;
|
if (!elem) continue;
|
||||||
if (elem->rootDef != cellDef) continue;
|
if (elem->rootDef != cellDef) continue;
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
|
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
|
||||||
freeMagic(stylePtr);
|
freeMagic1(&mm1, stylePtr);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
if (elem->type == ELEMENT_TEXT)
|
if (elem->type == ELEMENT_TEXT)
|
||||||
freeMagic(elem->text);
|
freeMagic(elem->text);
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,10 @@ DBWFeedbackRedraw(window, plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwFeedbackAlways1()
|
dbwFeedbackAlways1(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -392,8 +392,9 @@ DBWHLRedrawWind(window)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwhlEraseFunc(tile, window)
|
dbwhlEraseFunc(tile, dinfo, window)
|
||||||
Tile *tile; /* Tile describing area to be erased. */
|
Tile *tile; /* Tile describing area to be erased. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
MagWindow *window; /* Window that is being altered. */
|
MagWindow *window; /* Window that is being altered. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
@ -33,6 +34,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
|
#include "cif/cif.h"
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
@ -544,12 +546,12 @@ DBWloadWindow(window, name, flags)
|
||||||
newEditUse = DBCellNewUse(newEditDef, (char *) NULL);
|
newEditUse = DBCellNewUse(newEditDef, (char *) NULL);
|
||||||
(void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window");
|
(void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window");
|
||||||
DBExpand(newEditUse,
|
DBExpand(newEditUse,
|
||||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask, TRUE);
|
((DBWclientRec *)window->w_clientData)->dbw_bitmask, DB_EXPAND);
|
||||||
|
|
||||||
if (expand)
|
if (expand)
|
||||||
DBExpandAll(newEditUse, &(newEditUse->cu_bbox),
|
DBExpandAll(newEditUse, &(newEditUse->cu_bbox),
|
||||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask,
|
((DBWclientRec *)window->w_clientData)->dbw_bitmask,
|
||||||
FALSE, UnexpandFunc,
|
DB_UNEXPAND, UnexpandFunc,
|
||||||
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
|
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
|
||||||
|
|
||||||
if (newEdit)
|
if (newEdit)
|
||||||
|
|
@ -653,6 +655,311 @@ DBWexit()
|
||||||
return (CmdWarnWrite() == 1);
|
return (CmdWarnWrite() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbwValueFormat ---
|
||||||
|
*
|
||||||
|
* Remove unnecessary trailing zeros and decimal from a floating-point
|
||||||
|
* value formatted with "%.Nf" where N is the expected maximum number
|
||||||
|
* of places after the decimal, matching the argument "places".
|
||||||
|
* This makes the "%f" formatting work like "%g" formatting, but
|
||||||
|
* works around the limitation of "%.Ng" that it operates on the number
|
||||||
|
* of significant digits, not the number of decimal places.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The string "buf" may be altered with a new terminating null character.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dbwValueFormat(char *buf,
|
||||||
|
int places)
|
||||||
|
{
|
||||||
|
char *p = buf + strlen(buf) - 1;
|
||||||
|
while (p > buf && *p == '0') *p-- = '\0';
|
||||||
|
if (p > buf && *p == '.') *p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbwPrintValue0 --
|
||||||
|
*
|
||||||
|
* Convert a value in internal database units to a string based on
|
||||||
|
* the chosen display units as defined by DBWUnits (which is set
|
||||||
|
* with the "units" command). If DBWUnits has not been changed
|
||||||
|
* since startup, then the behavior is to print the internal units
|
||||||
|
* in string form. If DBWUnits has been set, then the units type
|
||||||
|
* determines how the output is displayed.
|
||||||
|
*
|
||||||
|
* If "is_square" is TRUE, then the value is in units squared, and
|
||||||
|
* scaling is done accordingly. In the case of DBW_UNITS_USER,
|
||||||
|
* where values are in grid multiples, the units for X and Y may
|
||||||
|
* differ, and "is_x" = TRUE indicates a measurement in the X direction,
|
||||||
|
* while false indicase a measurements in the Y direction. Naturally,
|
||||||
|
* if "is_square" is TRUE then "is_x" is ignored. "is_x" is also ignored
|
||||||
|
* for any output units other than user/grid units.
|
||||||
|
*
|
||||||
|
* If "is_cif" is true, then "value" is in CIF database units
|
||||||
|
* (centimicrons, nanometers, or angstroms, according to the
|
||||||
|
* scalefactor line in the tech file), rather than internal units.
|
||||||
|
*
|
||||||
|
* This routine is generally meant to be called as one of the three
|
||||||
|
* variants defined below it: DBWPrintValue(), DBWPrintSqValue(),
|
||||||
|
* or DBWPrintCIFValue().
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* A pointer to a string. To facilitate printing up to four values
|
||||||
|
* (e.g., rectangle coordinates, such as from "box values"), a static
|
||||||
|
* string partitioned into four parts is created in this subroutine,
|
||||||
|
* and the result points to one position in the string, which is cycled
|
||||||
|
* through every four calls to the subroutine. The caller does not
|
||||||
|
* free the returned string.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* NOTE: Prior to the introduction of the "units" command, magic had the
|
||||||
|
* inconsistent behavior that parsed input values on the command line
|
||||||
|
* would be interpreted per the "snap" setting, but output values were
|
||||||
|
* (almost) always given in internal units. This routine keeps the
|
||||||
|
* original behavior backwards-compatible, as inconsistent as it is.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
dbwPrintValue0(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w, /* current window, for use with grid */
|
||||||
|
bool is_x, /* TRUE if value is an X dimension */
|
||||||
|
bool is_square, /* TRUE if value is a dimension squared */
|
||||||
|
bool is_cif) /* TRUE if value is in centimicrons */
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
float oscale, dscale, fvalue;
|
||||||
|
DBWclientRec *crec;
|
||||||
|
int locunits;
|
||||||
|
|
||||||
|
/* This routine is called often, so avoid constant use of malloc and
|
||||||
|
* free by keeping up to four printed results in static memory.
|
||||||
|
*/
|
||||||
|
static char resultstr[128];
|
||||||
|
static unsigned char resultpos = 0;
|
||||||
|
|
||||||
|
result = &resultstr[resultpos];
|
||||||
|
resultpos += 32;
|
||||||
|
resultpos &= 127; /* At 128, cycle back to zero */
|
||||||
|
|
||||||
|
/* CIF database units are centimicrons/nanometers/angstroms as
|
||||||
|
* set by the "scalefactor" line in the tech file. When "is_cif"
|
||||||
|
* is TRUE, then "value" is in these units. Find the conversion
|
||||||
|
* factor to convert "value" to internal units, and then it can
|
||||||
|
* be subsequently converted to lambda, microns, etc.
|
||||||
|
*/
|
||||||
|
if (is_cif == TRUE)
|
||||||
|
dscale = CIFGetScale(100) / CIFGetOutputScale(1000);
|
||||||
|
else
|
||||||
|
dscale = 1.0;
|
||||||
|
|
||||||
|
/* When printing user/grid units, check for a valid window */
|
||||||
|
|
||||||
|
locunits = DBWUnits;
|
||||||
|
if (locunits != DBW_UNITS_DEFAULT) locunits &= DBW_UNITS_TYPE_MASK;
|
||||||
|
|
||||||
|
/* The MagWindow argument is only needed for user units, since the
|
||||||
|
* user grid values are found there. Setting MagWindow to NULL
|
||||||
|
* effectively disables printing values in user grid units, which
|
||||||
|
* then default to internal units.
|
||||||
|
*/
|
||||||
|
if (locunits == DBW_UNITS_USER)
|
||||||
|
{
|
||||||
|
if (w == (MagWindow *)NULL)
|
||||||
|
{
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
if (w == (MagWindow *)NULL)
|
||||||
|
locunits = DBW_UNITS_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (locunits)
|
||||||
|
{
|
||||||
|
case DBW_UNITS_DEFAULT:
|
||||||
|
snprintf(result, 32, "%d", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_INTERNAL:
|
||||||
|
if (is_cif)
|
||||||
|
{
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
snprintf(result, 32, "%.6f", value * dscale * dscale);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(result, 32, "%.3f", value * dscale);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
snprintf(result, 32, "%d", value);
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 29))
|
||||||
|
strcat(result, "i^2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 31))
|
||||||
|
strcat(result, "i");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_LAMBDA:
|
||||||
|
|
||||||
|
oscale = (float)DBLambda[0];
|
||||||
|
oscale /= (float)DBLambda[1];
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * oscale * dscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.6f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 29))
|
||||||
|
strcat(result, "l^2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.3f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 31))
|
||||||
|
strcat(result, "l");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_MICRONS:
|
||||||
|
oscale = CIFGetOutputScale(1000);
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * oscale * dscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.6f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 28))
|
||||||
|
strcat(result, "um^2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.3f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
|
||||||
|
strcat(result, "um");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_USER:
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
oscale = (float)((crec->dbw_gridRect.r_xtop -
|
||||||
|
crec->dbw_gridRect.r_xbot) *
|
||||||
|
(crec->dbw_gridRect.r_ytop -
|
||||||
|
crec->dbw_gridRect.r_ybot));
|
||||||
|
}
|
||||||
|
else if (is_x)
|
||||||
|
{
|
||||||
|
oscale = (float)(crec->dbw_gridRect.r_xtop -
|
||||||
|
crec->dbw_gridRect.r_xbot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oscale = (float)(crec->dbw_gridRect.r_ytop -
|
||||||
|
crec->dbw_gridRect.r_ybot);
|
||||||
|
}
|
||||||
|
fvalue = (float)value * oscale * dscale;
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
fvalue *= dscale;
|
||||||
|
snprintf(result, 32, "%0.6f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 27))
|
||||||
|
strcat(result, "gx*gy");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(result, 32, "%0.3f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
if (is_x)
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
|
||||||
|
strcat(result, "gx");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
|
||||||
|
strcat(result, "gy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBWPrintValue --
|
||||||
|
* DBWPrintSqValue --
|
||||||
|
* DBWPrintCIFValue --
|
||||||
|
* DBWPrintCIFSqValue --
|
||||||
|
*
|
||||||
|
* Convenience functions which call dbwPrintValue0() with specific
|
||||||
|
* fixed arguments, so that the calls are not full of boolean values.
|
||||||
|
* The "is_x" boolean is retained because it is used often.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w, /* current window, for use with grid */
|
||||||
|
bool is_x) /* TRUE if value is an X dimension */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = FALSE and is_cif = FALSE */
|
||||||
|
return dbwPrintValue0(value, w, is_x, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintSqValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w) /* current window, for use with grid */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = TRUE and is_cif = FALSE */
|
||||||
|
/* is_x is set to TRUE although it is unused. */
|
||||||
|
return dbwPrintValue0(value, w, TRUE, TRUE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintCIFValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w, /* current window, for use with grid */
|
||||||
|
bool is_x) /* TRUE if value is an X dimension */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = FALSE and is_cif = TRUE */
|
||||||
|
return dbwPrintValue0(value, w, is_x, FALSE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintCIFSqValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w) /* current window, for use with grid */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = TRUE and is_cif = TRUE */
|
||||||
|
/* is_x is set to TRUE although it is unused. */
|
||||||
|
return dbwPrintValue0(value, w, TRUE, TRUE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,21 @@ typedef struct _crosshairRec {
|
||||||
static CrosshairRec curCrosshair; /* Crosshair position */
|
static CrosshairRec curCrosshair; /* Crosshair position */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the following is DBW_SNAP_USER, the box gets snapped to the user's
|
* If the following is DBW_UNITS_USER, the box gets snapped to the user's
|
||||||
* grid always, instead of snapping to the usual 1x1 grid. If the value
|
* grid always, instead of snapping to the usual 1x1 grid. If the value
|
||||||
* is DBW_SNAP_INTERNAL, the box gets snapped to the internal grid.
|
* is DBW_UNITS_INTERNAL, the box gets snapped to the internal grid.
|
||||||
*/
|
*/
|
||||||
int DBWSnapToGrid = DBW_SNAP_LAMBDA;
|
int DBWSnapToGrid = DBW_UNITS_LAMBDA;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The original behavior with respect to units was that un-suffixed
|
||||||
|
* values follow whatever the snap setting is (DBWSnapToGrid, above).
|
||||||
|
* Current behavior is that the original behavior is followed while
|
||||||
|
* DBWUnits is set to DBW_UNITS_DEFAULT. However, if the "units"
|
||||||
|
* command is given, then displayed and entered units follow that
|
||||||
|
* value independently of the snap setting.
|
||||||
|
*/
|
||||||
|
int DBWUnits = DBW_UNITS_DEFAULT;
|
||||||
|
|
||||||
/* Forward reference: */
|
/* Forward reference: */
|
||||||
|
|
||||||
|
|
@ -82,8 +92,8 @@ extern int DBWToolDraw();
|
||||||
* toolFindPoint --
|
* toolFindPoint --
|
||||||
*
|
*
|
||||||
* Returns the point in root coordinates.
|
* Returns the point in root coordinates.
|
||||||
* If DBWSnapToGrid is DBW_SNAP_USER, pick the nearest point that is
|
* If DBWSnapToGrid is DBW_UNITS_USER, pick the nearest point that is
|
||||||
* aligned with the window's grid. If DBWSnapToGrid is DBW_SNAP_LAMBDA,
|
* aligned with the window's grid. If DBWSnapToGrid is DBW_UNITS_LAMBDA,
|
||||||
* pick the nearest point that is an integer lambda value.
|
* pick the nearest point that is an integer lambda value.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -120,7 +130,7 @@ toolFindPoint(p, rootPoint, rootArea)
|
||||||
if (!GEO_ENCLOSE(p, &WindCurrentWindow->w_screenArea)) return NULL;
|
if (!GEO_ENCLOSE(p, &WindCurrentWindow->w_screenArea)) return NULL;
|
||||||
|
|
||||||
WindPointToSurface(WindCurrentWindow, p, rootPoint, rootArea);
|
WindPointToSurface(WindCurrentWindow, p, rootPoint, rootArea);
|
||||||
if (DBWSnapToGrid != DBW_SNAP_INTERNAL)
|
if (DBWSnapToGrid != DBW_UNITS_INTERNAL)
|
||||||
ToolSnapToGrid(WindCurrentWindow, rootPoint, rootArea);
|
ToolSnapToGrid(WindCurrentWindow, rootPoint, rootArea);
|
||||||
return WindCurrentWindow;
|
return WindCurrentWindow;
|
||||||
|
|
||||||
|
|
@ -764,7 +774,10 @@ DBWDrawBox(window, plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwBoxAlways1()
|
dbwBoxAlways1(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -841,8 +854,8 @@ DBWResetBox(CellDef *def)
|
||||||
* Repositions the box by one of its corners.
|
* Repositions the box by one of its corners.
|
||||||
* If the point given to reposition the box is in screen coordinates,
|
* If the point given to reposition the box is in screen coordinates,
|
||||||
* the box corner is snapped to the user's grid (set with the :grid
|
* the box corner is snapped to the user's grid (set with the :grid
|
||||||
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
|
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
|
||||||
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
|
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
|
||||||
* lambda value.
|
* lambda value.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -945,8 +958,8 @@ ToolMoveBox(corner, point, screenCoords, rootDef)
|
||||||
*
|
*
|
||||||
* If the point given to reposition the box is in screen coordinates,
|
* If the point given to reposition the box is in screen coordinates,
|
||||||
* the box corner is snapped to the user's grid (set with the :grid
|
* the box corner is snapped to the user's grid (set with the :grid
|
||||||
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
|
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
|
||||||
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
|
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
|
||||||
* lambda value.
|
* lambda value.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -1089,7 +1102,7 @@ ToolSnapToGrid(w, p, rEnclose)
|
||||||
if (crec == NULL || p == NULL)
|
if (crec == NULL || p == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (DBWSnapToGrid == DBW_SNAP_LAMBDA)
|
if (DBWSnapToGrid == DBW_UNITS_LAMBDA)
|
||||||
{
|
{
|
||||||
lr.r_xbot = lr.r_ybot = 0;
|
lr.r_xbot = lr.r_ybot = 0;
|
||||||
lr.r_xtop = DBLambda[1] / DBLambda[0];
|
lr.r_xtop = DBLambda[1] / DBLambda[0];
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ typedef struct DBW1 {
|
||||||
|
|
||||||
extern WindClient DBWclientID;
|
extern WindClient DBWclientID;
|
||||||
extern int DBWSnapToGrid;
|
extern int DBWSnapToGrid;
|
||||||
|
extern int DBWUnits;
|
||||||
|
|
||||||
extern int DBWMaxTechStyles;
|
extern int DBWMaxTechStyles;
|
||||||
extern int DBWMaxTileStyles;
|
extern int DBWMaxTileStyles;
|
||||||
|
|
@ -121,13 +122,17 @@ extern int DBWNumStyles;
|
||||||
extern int RtrPolyWidth, RtrMetalWidth, RtrContactWidth;
|
extern int RtrPolyWidth, RtrMetalWidth, RtrContactWidth;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported procedure headers for redisplay
|
* Exported procedure headers for redisplay and output
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int DBWWatchTiles();
|
extern int DBWWatchTiles();
|
||||||
extern void DBWAreaChanged();
|
extern void DBWAreaChanged();
|
||||||
extern void DBWLabelChanged();
|
extern void DBWLabelChanged();
|
||||||
extern void DBWDrawLabel();
|
extern void DBWDrawLabel();
|
||||||
|
extern char *DBWPrintValue(int value, MagWindow *w, bool is_x);
|
||||||
|
extern char *DBWPrintSqValue(int value, MagWindow *w);
|
||||||
|
extern char *DBWPrintCIFValue(int value, MagWindow *w, bool is_x);
|
||||||
|
extern char *DBWPrintCIFSqValue(int value, MagWindow *w);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported procedures and variables related to the technology file
|
* Exported procedures and variables related to the technology file
|
||||||
|
|
@ -145,7 +150,9 @@ extern void (*DBWButtonCurrentProc)();
|
||||||
typedef void (*cb_database_buttonhandler_t)(MagWindow *w, TxCommand *cmd);
|
typedef void (*cb_database_buttonhandler_t)(MagWindow *w, TxCommand *cmd);
|
||||||
extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandler_t proc,
|
extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandler_t proc,
|
||||||
int cursor, const char *doc);
|
int cursor, const char *doc);
|
||||||
|
extern char *DBWGetButtonHandler();
|
||||||
extern char *DBWChangeButtonHandler();
|
extern char *DBWChangeButtonHandler();
|
||||||
|
extern int DBWButtonHandlerIndex();
|
||||||
extern void DBWPrintButtonDoc();
|
extern void DBWPrintButtonDoc();
|
||||||
extern void DBWBoxHandler();
|
extern void DBWBoxHandler();
|
||||||
|
|
||||||
|
|
@ -168,14 +175,36 @@ extern void DBWBoxHandler();
|
||||||
#define TOOL_ILG -1
|
#define TOOL_ILG -1
|
||||||
|
|
||||||
/* The following defines are used to indicate which coordinate system
|
/* The following defines are used to indicate which coordinate system
|
||||||
* the cursor box snaps to when moved with mouse clicks (values for
|
* is used when displaying or returning values. By default this is
|
||||||
* DBWSnapToGrid).
|
* set to DBW_UNITS_INTERNAL. From magic version 8.3.595, this is
|
||||||
|
* independently set from "snap". For backwards compatibility,
|
||||||
|
* the value starts as DBW_UNITS_DEFAULT which implements the original
|
||||||
|
* behavior in which the "snap" setting dictates the dispaly units.
|
||||||
|
* Only if set to a non-negative value do the display units operate
|
||||||
|
* independently of the snap setting.
|
||||||
|
*
|
||||||
|
* NOTES:
|
||||||
|
* Lambda units are fixed by the tech file.
|
||||||
|
* Internal units are scalable.
|
||||||
|
* User units are scalable; this can be used, for example, to
|
||||||
|
* set a box position according to multiples of a track
|
||||||
|
* pitch, but is most often used manually with the "g"
|
||||||
|
* (for "grid") suffix; e.g., "move box e 1g"
|
||||||
|
* Micron units are dependent on the specified cifoutput style
|
||||||
|
* and how the tech file defines the scalefactor for it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DBW_SNAP_INTERNAL 0 /* internal units (fine grid) */
|
#define DBW_UNITS_DEFAULT -1 /* backwards-compatible behavior */
|
||||||
#define DBW_SNAP_LAMBDA 1 /* lambda units (coarse grid) */
|
#define DBW_UNITS_INTERNAL 0 /* internal units */
|
||||||
#define DBW_SNAP_USER 2 /* user grid units (user grid) */
|
#define DBW_UNITS_LAMBDA 1 /* lambda units */
|
||||||
#define DBW_SNAP_MICRONS 3 /* micron units */
|
#define DBW_UNITS_USER 2 /* user grid units */
|
||||||
|
#define DBW_UNITS_MICRONS 3 /* micron units */
|
||||||
|
#define DBW_UNITS_TYPE_MASK 3 /* everything but the flag field(s) */
|
||||||
|
#define DBW_UNITS_PRINT_FLAG 4 /* flag used to indicate that
|
||||||
|
* the units should be printed
|
||||||
|
* with the value; e.g.,
|
||||||
|
* "10um" instead of "10".
|
||||||
|
*/
|
||||||
|
|
||||||
/* The following window mask can be used to select all database windows
|
/* The following window mask can be used to select all database windows
|
||||||
* for things like the mask parameter to DBWAreaChanged.
|
* for things like the mask parameter to DBWAreaChanged.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<STYLE type="text/css">
|
||||||
|
H1 {color: black }
|
||||||
|
H2 {color: maroon }
|
||||||
|
H3 {color: #007090 }
|
||||||
|
A.head:link {color: #0060a0 }
|
||||||
|
A.head:visited {color: #3040c0 }
|
||||||
|
A.head:active {color: white }
|
||||||
|
A.head:hover {color: yellow }
|
||||||
|
A.red:link {color: red }
|
||||||
|
A.red:visited {color: maroon }
|
||||||
|
A.red:active {color: yellow }
|
||||||
|
</STYLE>
|
||||||
|
</HEAD>
|
||||||
|
<TITLE>Magic-8.3 Command Reference</TITLE>
|
||||||
|
<BODY BACKGROUND=graphics/blpaper.gif>
|
||||||
|
<H1> <IMG SRC=graphics/magic_title8_3.png ALT="Magic VLSI Layout Tool Version 8.3">
|
||||||
|
<IMG SRC=graphics/magic_OGL_sm.gif ALIGN="top" ALT="*"> </H1>
|
||||||
|
|
||||||
|
<H2>archive</H2>
|
||||||
|
<HR>
|
||||||
|
Handle archive files
|
||||||
|
<HR>
|
||||||
|
|
||||||
|
<H3>Usage:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>archive write</B> | <B>read</B> <I>filename</I> <BR><BR>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Summary:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
The <B>archive</B> command handles archive files. The exact
|
||||||
|
operation depends on the option, and are outlined below:
|
||||||
|
<DL>
|
||||||
|
<DT> <B>archive write</B> <I>filename</I>
|
||||||
|
<DD> creates and writes to the file <I>filename</I> a copy of
|
||||||
|
the contents of all database cells. <P>
|
||||||
|
<DT> <B>archive read</B> <I>filename</I>
|
||||||
|
<DD> recovers the database from the contents of the saved archive
|
||||||
|
file <I>filename</I>. <P>
|
||||||
|
</DL>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
Archive files use the same format as crash recovery files, which is a
|
||||||
|
single file containing all database files with additional metadata
|
||||||
|
about the original location of each file.
|
||||||
|
|
||||||
|
<H3>Implementation Notes:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>archive</B> is implemented as a built-in command in <B>magic</B>.
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>See Also:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=crash.html><B>crash</B></A> <BR>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
<TABLE BORDER=0>
|
||||||
|
<TR>
|
||||||
|
<TD> <A HREF=commands.html>Return to command index</A>
|
||||||
|
</TR>
|
||||||
|
</TABLE>
|
||||||
|
<P><I>Last updated:</I> January 12, 2021 at 10:10am <P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
|
|
@ -71,12 +71,15 @@ Operations on cell definitions.
|
||||||
<DT> <B>rename</B> <I>name newname</I>
|
<DT> <B>rename</B> <I>name newname</I>
|
||||||
<DD> Change the name of the cell definition <I>name</I> to
|
<DD> Change the name of the cell definition <I>name</I> to
|
||||||
<I>newname</I>.
|
<I>newname</I>.
|
||||||
<DT> <B>delete</B> <I>name</I>
|
<DT> <B>delete</B> <I>name</I> [<B>-noprompt</B>]
|
||||||
<DD> Delete the cell definition with name <I>name</I>. If cell
|
<DD> Delete the cell definition with name <I>name</I>. If cell
|
||||||
<I>name</I> is a descendent of another cell, the command
|
<I>name</I> is a descendent of another cell, the command
|
||||||
will be prohibited. If the cell <I>name</I> is currently
|
will be prohibited. If the cell <I>name</I> is currently
|
||||||
the topmost cell in the window, the window will be loaded
|
the topmost cell in the window, the window will be loaded
|
||||||
with default cell "(UNNAMED)".
|
with default cell "(UNNAMED)". If option <B>-noprompt</B>
|
||||||
|
is specified, then the actions specified above happen
|
||||||
|
immediately. Otherwise, a dialog box will be raised
|
||||||
|
asking for confirmation to delete the cell.
|
||||||
<DT> <B>dereference</B> <I>name</I>
|
<DT> <B>dereference</B> <I>name</I>
|
||||||
<DD> Perform a flush of the cell (per the "<B>flush</B>" command),
|
<DD> Perform a flush of the cell (per the "<B>flush</B>" command),
|
||||||
first removing any file path associated with the cell, so
|
first removing any file path associated with the cell, so
|
||||||
|
|
|
||||||
|
|
@ -362,184 +362,194 @@
|
||||||
cellpadding="5" bgcolor="#ccccff">
|
cellpadding="5" bgcolor="#ccccff">
|
||||||
<TBODY>
|
<TBODY>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=addcommandentry.html><B>addcommandentry</B></A><TD>
|
<TD> <A HREF=addcommandentry.html><B>addcommandentry</B></A></TD>
|
||||||
<TD> <A HREF=addpath.html> <B>addpath</B></A><TD>
|
<TD> <A HREF=addpath.html> <B>addpath</B></A></TD>
|
||||||
<TD> <A HREF=antennacheck.html> <B>antennacheck</B></A><TD>
|
<TD> <A HREF=antennacheck.html> <B>antennacheck</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=array.html> <B>array</B></A><TD>
|
<TD> <A HREF=archive.html> <B>archive</B></A></TD>
|
||||||
<TD> <A HREF=box.html> <B>box</B></A><TD>
|
<TD> <A HREF=array.html> <B>array</B></A></TD>
|
||||||
<TD> <A HREF=calma.html> <B>calma</B></A><TD>
|
<TD> <A HREF=box.html> <B>box</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=caption.html> <B>caption</B></A><TD>
|
<TD> <A HREF=calma.html> <B>calma</B></A></TD>
|
||||||
<TD> <A HREF=cellmanager.html> <B>cellmanager</B></A><TD>
|
<TD> <A HREF=caption.html> <B>caption</B></A></TD>
|
||||||
<TD> <A HREF=cellname.html> <B>cellname</B></A><TD>
|
<TD> <A HREF=cellmanager.html> <B>cellmanager</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=cellsearch.html> <B>cellsearch</B></A><TD>
|
<TD> <A HREF=cellname.html> <B>cellname</B></A></TD>
|
||||||
<TD> <A HREF=channels.html> <B>channels</B></A><TD>
|
<TD> <A HREF=cellsearch.html> <B>cellsearch</B></A></TD>
|
||||||
<TD> <A HREF=cif.html> <B>cif</B></A><TD>
|
<TD> <A HREF=channels.html> <B>channels</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=clockwise.html> <B>clockwise</B></A><TD>
|
<TD> <A HREF=cif.html> <B>cif</B></A></TD>
|
||||||
<TD> <A HREF=closewrapper.html> <B>closewrapper</B></A><TD>
|
<TD> <A HREF=clockwise.html> <B>clockwise</B></A></TD>
|
||||||
<TD> <A HREF=contact.html> <B>contact</B></A><TD>
|
<TD> <A HREF=closewrapper.html> <B>closewrapper</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=copy.html> <B>copy</B></A><TD>
|
<TD> <A HREF=contact.html> <B>contact</B></A></TD>
|
||||||
<TD> <A HREF=corner.html> <B>corner</B></A><TD>
|
<TD> <A HREF=copy.html> <B>copy</B></A></TD>
|
||||||
<TD> <A HREF=crash.html> <B>crash</B></A><TD>
|
<TD> <A HREF=corner.html> <B>corner</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=crashbackups.html> <B>crashbackups</B></A><TD>
|
<TD> <A HREF=crash.html> <B>crash</B></A></TD>
|
||||||
<TD> <A HREF=crosshair.html> <B>crosshair</B></A><TD>
|
<TD> <A HREF=crashbackups.html> <B>crashbackups</B></A></TD>
|
||||||
<TD> <A HREF=def.html> <B>def</B></A><TD>
|
<TD> <A HREF=crosshair.html> <B>crosshair</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=delete.html> <B>delete</B></A><TD>
|
<TD> <A HREF=def.html> <B>def</B></A></TD>
|
||||||
<TD> <A HREF=deletecommandentry.html> <B>deletecommandentry</B></A><TD>
|
<TD> <A HREF=delete.html> <B>delete</B></A></TD>
|
||||||
<TD> <A HREF=down.html> <B>down</B></A><TD>
|
<TD> <A HREF=deletecommandentry.html> <B>deletecommandentry</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=drc.html> <B>drc</B></A><TD>
|
<TD> <A HREF=display.html> <B>display</B></A></TD>
|
||||||
<TD> <A HREF=dump.html> <B>dump</B></A><TD>
|
<TD> <A HREF=down.html> <B>down</B></A></TD>
|
||||||
<TD> <A HREF=edit.html> <B>edit</B></A><TD>
|
<TD> <A HREF=drc.html> <B>drc</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=element.html> <B>element</B></A><TD>
|
<TD> <A HREF=drop.html> <B>drop</B></A></TD>
|
||||||
<TD> <A HREF=erase.html> <B>erase</B></A><TD>
|
<TD> <A HREF=dump.html> <B>dump</B></A></TD>
|
||||||
<TD> <A HREF=expand.html> <B>expand</B></A><TD>
|
<TD> <A HREF=edit.html> <B>edit</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=ext.html> <B>ext</B></A><TD>
|
<TD> <A HREF=element.html> <B>element</B></A></TD>
|
||||||
<TD> <A HREF=ext2sim.html> <B>ext2sim</B></A><TD>
|
<TD> <A HREF=erase.html> <B>erase</B></A></TD>
|
||||||
<TD> <A HREF=ext2spice.html> <B>ext2spice</B></A><TD>
|
<TD> <A HREF=expand.html> <B>expand</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=extract.html> <B>extract</B></A><TD>
|
<TD> <A HREF=ext.html> <B>ext</B></A></TD>
|
||||||
<TD> <A HREF=extresist.html> <B>extresist</B></A><TD>
|
<TD> <A HREF=ext2sim.html> <B>ext2sim</B></A></TD>
|
||||||
<TD> <A HREF=ext2sim.html> <B>exttosim</B></A><TD>
|
<TD> <A HREF=ext2spice.html> <B>ext2spice</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=ext2spice.html> <B>exttospice</B></A><TD>
|
<TD> <A HREF=extract.html> <B>extract</B></A></TD>
|
||||||
<TD> <A HREF=feedback.html> <B>feedback</B></A><TD>
|
<TD> <A HREF=extresist.html> <B>extresist</B></A></TD>
|
||||||
<TD> <A HREF=fill.html> <B>fill</B></A><TD>
|
<TD> <A HREF=feedback.html> <B>feedback</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=findbox.html> <B>findbox</B></A><TD>
|
<TD> <A HREF=fill.html> <B>fill</B></A></TD>
|
||||||
<TD> <A HREF=findlabel.html> <B>findlabel</B></A><TD>
|
<TD> <A HREF=findbox.html> <B>findbox</B></A></TD>
|
||||||
<TD> <A HREF=flatten.html> <B>flatten</B></A><TD>
|
<TD> <A HREF=findlabel.html> <B>findlabel</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=flush.html> <B>flush</B></A><TD>
|
<TD> <A HREF=flatten.html> <B>flatten</B></A></TD>
|
||||||
<TD> <A HREF=garoute.html> <B>garoute</B></A><TD>
|
<TD> <A HREF=flush.html> <B>flush</B></A></TD>
|
||||||
<TD> <A HREF=gds.html> <B>gds</B></A><TD>
|
<TD> <A HREF=garoute.html> <B>garoute</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=get.html> <B>get</B></A><TD>
|
<TD> <A HREF=gds.html> <B>gds</B></A></TD>
|
||||||
<TD> <A HREF=getcell.html> <B>getcell</B></A><TD>
|
<TD> <A HREF=get.html> <B>get</B></A></TD>
|
||||||
<TD> <A HREF=getnode.html> <B>getnode</B></A><TD>
|
<TD> <A HREF=getcell.html> <B>getcell</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=goto.html> <B>goto</B></A><TD>
|
<TD> <A HREF=getnode.html> <B>getnode</B></A></TD>
|
||||||
<TD> <A HREF=grid.html> <B>grid</B></A><TD>
|
<TD> <A HREF=goto.html> <B>goto</B></A></TD>
|
||||||
<TD> <A HREF=help.html> <B>help</B></A><TD>
|
<TD> <A HREF=grid.html> <B>grid</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=identify.html> <B>identify</B></A><TD>
|
<TD> <A HREF=help.html> <B>help</B></A></TD>
|
||||||
<TD> <A HREF=initialize.html> <B>initialize</B></A><TD>
|
<TD> <A HREF=identify.html> <B>identify</B></A></TD>
|
||||||
<TD> <A HREF=instance.html> <B>instance</B></A><TD>
|
<TD> <A HREF=initialize.html> <B>initialize</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=iroute.html> <B>iroute</B></A><TD>
|
<TD> <A HREF=instance.html> <B>instance</B></A></TD>
|
||||||
<TD> <A HREF=irsim.html> <B>irsim</B></A><TD>
|
<TD> <A HREF=iroute.html> <B>iroute</B></A></TD>
|
||||||
<TD> <A HREF=label.html> <B>label</B></A><TD>
|
<TD> <A HREF=irsim.html> <B>irsim</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=lef.html> <B>lef</B></A><TD>
|
<TD> <A HREF=label.html> <B>label</B></A></TD>
|
||||||
<TD> <A HREF=load.html> <B>load</B></A><TD>
|
<TD> <A HREF=lef.html> <B>lef</B></A></TD>
|
||||||
<TD> <A HREF=maketoolbar.html> <B>maketoolbar</B></A><TD>
|
<TD> <A HREF=load.html> <B>load</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=move.html> <B>move</B></A><TD>
|
<TD> <A HREF=locking.html> <B>locking</B></A></TD>
|
||||||
<TD> <A HREF=measure.html> <B>measure</B></A><TD>
|
<TD> <A HREF=maketoolbar.html> <B>maketoolbar</B></A></TD>
|
||||||
<TD> <A HREF=openwrapper.html> <B>openwrapper</B></A><TD>
|
<TD> <A HREF=measure.html> <B>measure</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=paint.html> <B>paint</B></A><TD>
|
<TD> <A HREF=move.html> <B>move</B></A></TD>
|
||||||
<TD> <A HREF=path.html> <B>path</B></A><TD>
|
<TD> <A HREF=openwrapper.html> <B>openwrapper</B></A></TD>
|
||||||
<TD> <A HREF=peekbox.html> <B>peekbox</B></A><TD>
|
<TD> <A HREF=paint.html> <B>paint</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=plot.html> <B>plot</B></A><TD>
|
<TD> <A HREF=path.html> <B>path</B></A></TD>
|
||||||
<TD> <A HREF=plow.html> <B>plow</B></A><TD>
|
<TD> <A HREF=peekbox.html> <B>peekbox</B></A></TD>
|
||||||
<TD> <A HREF=polygon.html> <B>polygon</B></A><TD>
|
<TD> <A HREF=plot.html> <B>plot</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=popbox.html> <B>popbox</B></A><TD>
|
<TD> <A HREF=plow.html> <B>plow</B></A></TD>
|
||||||
<TD> <A HREF=popstack.html> <B>popstack</B></A><TD>
|
<TD> <A HREF=polygon.html> <B>polygon</B></A></TD>
|
||||||
<TD> <A HREF=port.html> <B>port</B></A><TD>
|
<TD> <A HREF=popbox.html> <B>popbox</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=promptload.html> <B>promptload</B></A><TD>
|
<TD> <A HREF=popstack.html> <B>popstack</B></A></TD>
|
||||||
<TD> <A HREF=promptsave.html> <B>promptsave</B></A><TD>
|
<TD> <A HREF=port.html> <B>port</B></A></TD>
|
||||||
<TD> <A HREF=property.html> <B>property</B></A><TD>
|
<TD> <A HREF=promptload.html> <B>promptload</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=pushbox.html> <B>pushbox</B></A><TD>
|
<TD> <A HREF=promptsave.html> <B>promptsave</B></A></TD>
|
||||||
<TD> <A HREF=pushstack.html> <B>pushstack</B></A><TD>
|
<TD> <A HREF=property.html> <B>property</B></A></TD>
|
||||||
<TD> <A HREF=render3d.html> <B>render3d</B></A><TD>
|
<TD> <A HREF=pushbox.html> <B>pushbox</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=resumeall.html> <B>resumeall</B></A><TD>
|
<TD> <A HREF=pushstack.html> <B>pushstack</B></A></TD>
|
||||||
<TD> <A HREF=rotate.html> <B>rotate</B></A><TD>
|
<TD> <A HREF=readspice.html> <B>readspice</B></A></TD>
|
||||||
<TD> <A HREF=route.html> <B>route</B></A><TD>
|
<TD> <A HREF=render3d.html> <B>render3d</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=save.html> <B>save</B></A><TD>
|
<TD> <A HREF=resumeall.html> <B>resumeall</B></A></TD>
|
||||||
<TD> <A HREF=scalegrid.html> <B>scalegrid</B></A><TD>
|
<TD> <A HREF=rotate.html> <B>rotate</B></A></TD>
|
||||||
<TD> <A HREF=search.html> <B>search</B></A><TD>
|
<TD> <A HREF=route.html> <B>route</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=see.html> <B>see</B></A><TD>
|
<TD> <A HREF=save.html> <B>save</B></A></TD>
|
||||||
<TD> <A HREF=select.html> <B>select</B></A><TD>
|
<TD> <A HREF=scalegrid.html> <B>scalegrid</B></A></TD>
|
||||||
<TD> <A HREF=setlabel.html> <B>setlabel</B> <I>(version 8.0)</I></A><TD>
|
<TD> <A HREF=search.html> <B>search</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=shell.html> <B>shell</B></A><TD>
|
<TD> <A HREF=see.html> <B>see</B></A></TD>
|
||||||
<TD> <A HREF=sideways.html> <B>sideways</B></A><TD>
|
<TD> <A HREF=select.html> <B>select</B></A></TD>
|
||||||
<TD> <A HREF=snap.html> <B>snap</B></A><TD>
|
<TD> <A HREF=setlabel.html> <B>setlabel</B> <I>(version 8.0)</I></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=spliterase.html> <B>spliterase</B></A><TD>
|
<TD> <A HREF=shell.html> <B>shell</B></A></TD>
|
||||||
<TD> <A HREF=splitpaint.html> <B>splitpaint</B></A><TD>
|
<TD> <A HREF=sideways.html> <B>sideways</B></A></TD>
|
||||||
<TD> <A HREF=startup.html> <B>startup</B></A><TD>
|
<TD> <A HREF=snap.html> <B>snap</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=straighten.html> <B>straighten</B></A><TD>
|
<TD> <A HREF=spliterase.html> <B>spliterase</B></A></TD>
|
||||||
<TD> <A HREF=stretch.html> <B>stretch</B></A><TD>
|
<TD> <A HREF=splitpaint.html> <B>splitpaint</B></A></TD>
|
||||||
<TD> <A HREF=suspendall.html> <B>suspendall</B></A><TD>
|
<TD> <A HREF=startup.html> <B>startup</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=tag.html> <B>tag</B></A><TD>
|
<TD> <A HREF=straighten.html> <B>straighten</B></A></TD>
|
||||||
<TD> <A HREF=tech.html> <B>tech</B></A><TD>
|
<TD> <A HREF=stretch.html> <B>stretch</B></A></TD>
|
||||||
<TD> <A HREF=techmanager.html> <B>techmanager</B></A><TD>
|
<TD> <A HREF=suspendall.html> <B>suspendall</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=tool.html> <B>tool</B> <I>(non-Tcl version)</I></A><TD>
|
<TD> <A HREF=tag.html> <B>tag</B></A></TD>
|
||||||
<TD> <A HREF=changetool.html> <B>tool</B> <I>(Tcl version)</I></A><TD>
|
<TD> <A HREF=tech.html> <B>tech</B></A></TD>
|
||||||
<TD> <A HREF=unexpand.html> <B>unexpand</B></A><TD>
|
<TD> <A HREF=techmanager.html> <B>techmanager</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=unmeasure.html> <B>unmeasure</B></A><TD>
|
<TD> <A HREF=tool.html> <B>tool</B> <I>(non-Tcl version)</I></A></TD>
|
||||||
<TD> <A HREF=upsidedown.html> <B>upsidedown</B></A><TD>
|
<TD> <A HREF=changetool.html> <B>tool</B> <I>(Tcl version)</I></A></TD>
|
||||||
<TD> <A HREF=what.html> <B>what</B></A><TD>
|
<TD> <A HREF=unexpand.html> <B>unexpand</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wire.html> <B>wire</B></A><TD>
|
<TD> <A HREF=units.html> <B>units</B></A> </TD>
|
||||||
<TD> <A HREF=writeall.html> <B>writeall</B></A><TD>
|
<TD> <A HREF=unmeasure.html> <B>unmeasure</B></A></TD>
|
||||||
<TD> <A HREF=xload.html> <B>xload</B></A><TD>
|
<TD> <A HREF=upsidedown.html> <B>upsidedown</B></A></TD>
|
||||||
|
</TR>
|
||||||
|
<TR>
|
||||||
|
<TD> <A HREF=what.html> <B>what</B></A></TD>
|
||||||
|
<TD> <A HREF=wire.html> <B>wire</B></A></TD>
|
||||||
|
<TD> <A HREF=writeall.html> <B>writeall</B></A></TD>
|
||||||
|
</TR>
|
||||||
|
<TR>
|
||||||
|
<TD> <A HREF=xload.html> <B>xload</B></A></TD>
|
||||||
|
<TD> <A HREF=xor.html> <B>xor</B></A></TD>
|
||||||
|
<TD> </TD>
|
||||||
</TR>
|
</TR>
|
||||||
</TBODY>
|
</TBODY>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
|
|
@ -551,38 +561,38 @@
|
||||||
cellpadding="5" bgcolor="#ffcccc">
|
cellpadding="5" bgcolor="#ffcccc">
|
||||||
<TBODY>
|
<TBODY>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/add.html><B>add</B></A><TD>
|
<TD> <A HREF=netlist/add.html><B>add</B></A></TD>
|
||||||
<TD> <A HREF=netlist/cleanup.html><B>cleanup</B></A><TD>
|
<TD> <A HREF=netlist/cleanup.html><B>cleanup</B></A></TD>
|
||||||
<TD> <A HREF=netlist/cull.html><B>cull</B></A><TD>
|
<TD> <A HREF=netlist/cull.html><B>cull</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/dnet.html><B>dnet</B></A><TD>
|
<TD> <A HREF=netlist/dnet.html><B>dnet</B></A></TD>
|
||||||
<TD> <A HREF=netlist/dterm.html><B>dterm</B></A><TD>
|
<TD> <A HREF=netlist/dterm.html><B>dterm</B></A></TD>
|
||||||
<TD> <A HREF=netlist/extract.html><B>extract</B></A><TD>
|
<TD> <A HREF=netlist/extract.html><B>extract</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/find.html><B>find</B></A><TD>
|
<TD> <A HREF=netlist/find.html><B>find</B></A></TD>
|
||||||
<TD> <A HREF=netlist/flush.html><B>flush</B></A><TD>
|
<TD> <A HREF=netlist/flush.html><B>flush</B></A></TD>
|
||||||
<TD> <A HREF=netlist/join.html><B>join</B></A><TD>
|
<TD> <A HREF=netlist/join.html><B>join</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/netlist.html><B>netlist</B></A><TD>
|
<TD> <A HREF=netlist/netlist.html><B>netlist</B></A></TD>
|
||||||
<TD> <A HREF=netlist/orient.html><B>orient</B></A><TD>
|
<TD> <A HREF=netlist/orient.html><B>orient</B></A></TD>
|
||||||
<TD> <A HREF=netlist/pushbutton.html><B>pushbutton</B></A><TD>
|
<TD> <A HREF=netlist/pushbutton.html><B>pushbutton</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/print.html><B>print</B></A><TD>
|
<TD> <A HREF=netlist/print.html><B>print</B></A></TD>
|
||||||
<TD> <A HREF=netlist/ripup.html><B>ripup</B></A><TD>
|
<TD> <A HREF=netlist/ripup.html><B>ripup</B></A></TD>
|
||||||
<TD> <A HREF=netlist/savenetlist.html><B>savenetlist</B></A><TD>
|
<TD> <A HREF=netlist/savenetlist.html><B>savenetlist</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/shownet.html><B>shownet</B></A><TD>
|
<TD> <A HREF=netlist/shownet.html><B>shownet</B></A></TD>
|
||||||
<TD> <A HREF=netlist/showterms.html><B>showterms</B></A><TD>
|
<TD> <A HREF=netlist/showterms.html><B>showterms</B></A></TD>
|
||||||
<TD> <A HREF=netlist/trace.html><B>trace</B></A><TD>
|
<TD> <A HREF=netlist/trace.html><B>trace</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=netlist/verify.html><B>verify</B></A><TD>
|
<TD> <A HREF=netlist/verify.html><B>verify</B></A></TD>
|
||||||
<TD> <A HREF=netlist/writeall.html><B>writeall</B></A><TD>
|
<TD> <A HREF=netlist/writeall.html><B>writeall</B></A></TD>
|
||||||
<TD></TD>
|
<TD></TD>
|
||||||
</TR>
|
</TR>
|
||||||
</TBODY>
|
</TBODY>
|
||||||
|
|
@ -595,24 +605,24 @@
|
||||||
cellpadding="5" bgcolor="#ccffcc">
|
cellpadding="5" bgcolor="#ccffcc">
|
||||||
<TBODY>
|
<TBODY>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wind3d/cif.html><B>cif</B></A><TD>
|
<TD> <A HREF=wind3d/cif.html><B>cif</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/closewindow.html><B>closewindow</B></A><TD>
|
<TD> <A HREF=wind3d/closewindow.html><B>closewindow</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/cutbox.html><B>cutbox</B></A><TD>
|
<TD> <A HREF=wind3d/cutbox.html><B>cutbox</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wind3d/defaults.html><B>defaults</B></A><TD>
|
<TD> <A HREF=wind3d/defaults.html><B>defaults</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/help.html><B>help</B></A><TD>
|
<TD> <A HREF=wind3d/help.html><B>help</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/level.html><B>level</B></A><TD>
|
<TD> <A HREF=wind3d/level.html><B>level</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wind3d/refresh.html><B>refresh</B></A><TD>
|
<TD> <A HREF=wind3d/refresh.html><B>refresh</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/render.html><B>render</B></A><TD>
|
<TD> <A HREF=wind3d/render.html><B>render</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/scroll.html><B>scroll</B></A><TD>
|
<TD> <A HREF=wind3d/scroll.html><B>scroll</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wind3d/see.html><B>see</B></A><TD>
|
<TD> <A HREF=wind3d/see.html><B>see</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/view.html><B>view</B></A><TD>
|
<TD> <A HREF=wind3d/view.html><B>view</B></A></TD>
|
||||||
<TD> <A HREF=wind3d/zoom.html><B>zoom</B></A><TD>
|
<TD> <A HREF=wind3d/zoom.html><B>zoom</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
</TBODY>
|
</TBODY>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
|
|
@ -624,12 +634,12 @@
|
||||||
cellpadding="5" bgcolor="#ffccff">
|
cellpadding="5" bgcolor="#ffccff">
|
||||||
<TBODY>
|
<TBODY>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=color/pushbutton.html><B>pushbutton</B></A><TD>
|
<TD> <A HREF=color/pushbutton.html><B>pushbutton</B></A></TD>
|
||||||
<TD> <A HREF=color/color.html><B>color</B></A><TD>
|
<TD> <A HREF=color/color.html><B>color</B></A></TD>
|
||||||
<TD> <A HREF=color/load.html><B>load</B></A><TD>
|
<TD> <A HREF=color/load.html><B>load</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=color/save.html><B>save</B></A><TD>
|
<TD> <A HREF=color/save.html><B>save</B></A></TD>
|
||||||
<TD></TD>
|
<TD></TD>
|
||||||
<TD></TD>
|
<TD></TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
|
@ -643,19 +653,19 @@
|
||||||
cellpadding="5" bgcolor="#ffffcc">
|
cellpadding="5" bgcolor="#ffffcc">
|
||||||
<TBODY>
|
<TBODY>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wizard/bypass.html><B>*bypass</B></A><TD>
|
<TD> <A HREF=wizard/bypass.html><B>*bypass</B></A></TD>
|
||||||
<TD> <A HREF=wizard/coord.html><B>*coord</B></A><TD>
|
<TD> <A HREF=wizard/coord.html><B>*coord</B></A></TD>
|
||||||
<TD> <A HREF=wizard/extract.html><B>*extract</B></A><TD>
|
<TD> <A HREF=wizard/extract.html><B>*extract</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wizard/plow.html><B>*plow</B></A><TD>
|
<TD> <A HREF=wizard/plow.html><B>*plow</B></A></TD>
|
||||||
<TD> <A HREF=wizard/psearch.html><B>*psearch</B></A><TD>
|
<TD> <A HREF=wizard/psearch.html><B>*psearch</B></A></TD>
|
||||||
<TD> <A HREF=wizard/showtech.html><B>*showtech</B></A><TD>
|
<TD> <A HREF=wizard/showtech.html><B>*showtech</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wizard/tilestats.html><B>*tilestats</B></A><TD>
|
<TD> <A HREF=wizard/tilestats.html><B>*tilestats</B></A></TD>
|
||||||
<TD> <A HREF=wizard/tsearch.html><B>*tsearch</B></A><TD>
|
<TD> <A HREF=wizard/tsearch.html><B>*tsearch</B></A></TD>
|
||||||
<TD> <A HREF=wizard/watch.html><B>*watch</B></A><TD>
|
<TD> <A HREF=wizard/watch.html><B>*watch</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
</TBODY>
|
</TBODY>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
|
|
@ -667,14 +677,14 @@
|
||||||
cellpadding="5" bgcolor="#cccccc">
|
cellpadding="5" bgcolor="#cccccc">
|
||||||
<TBODY>
|
<TBODY>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wizard/crash.html><B>*crash</B></A><TD>
|
<TD> <A HREF=wizard/crash.html><B>*crash</B></A></TD>
|
||||||
<TD> <A HREF=wizard/files.html><B>*files</B></A><TD>
|
<TD> <A HREF=wizard/files.html><B>*files</B></A></TD>
|
||||||
<TD> <A HREF=wizard/grstats.html><B>*grstats</B></A><TD>
|
<TD> <A HREF=wizard/grstats.html><B>*grstats</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=wizard/pause.html><B>*pause</B></A><TD>
|
<TD> <A HREF=wizard/pause.html><B>*pause</B></A></TD>
|
||||||
<TD> <A HREF=wizard/winddebug.html><B>*winddebug</B></A><TD>
|
<TD> <A HREF=wizard/winddebug.html><B>*winddebug</B></A></TD>
|
||||||
<TD> <A HREF=wizard/winddump.html><B>*winddump</B></A><TD>
|
<TD> <A HREF=wizard/winddump.html><B>*winddump</B></A></TD>
|
||||||
</TR>
|
</TR>
|
||||||
</TBODY>
|
</TBODY>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
addcommandentry
|
addcommandentry
|
||||||
addpath
|
addpath
|
||||||
antennacheck
|
antennacheck
|
||||||
|
archive
|
||||||
array
|
array
|
||||||
box
|
box
|
||||||
calma
|
calma
|
||||||
|
|
@ -116,6 +117,7 @@ techmanager
|
||||||
tool
|
tool
|
||||||
undo
|
undo
|
||||||
unexpand
|
unexpand
|
||||||
|
units
|
||||||
updatedisplay
|
updatedisplay
|
||||||
upsidedown
|
upsidedown
|
||||||
version
|
version
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ expanded/unexpanded cells in the current selection.
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>expand</B> [<B>toggle</B>] <BR><BR>
|
<B>expand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
|
||||||
|
[<B>toggle</B>] <BR><BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Shortcuts:</H3>
|
<H3>Shortcuts:</H3>
|
||||||
|
|
@ -38,14 +39,32 @@ expanded/unexpanded cells in the current selection.
|
||||||
<H3>Summary:</H3>
|
<H3>Summary:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
The <B>expand</B> command expands the view of subcells to
|
The <B>expand</B> command expands the view of subcells to
|
||||||
display the contents of the subcells. Without arguments,
|
display the contents of the subcells.
|
||||||
the <B>expand</B> command expands all unexpanded subcells that
|
|
||||||
touch or intersect the cursor box in the layout window. <P>
|
Option <B>overlap</B> expands all unexpanded subcells that
|
||||||
|
overlap with the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>surround</B> expands all unexpanded subcells that
|
||||||
|
are completely surrounded by the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>all</B> expands all subcells in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>selection</B> operates on the current selection, not
|
||||||
|
relative to the cursor box, expanding all selected cells. <P>
|
||||||
|
|
||||||
|
Option <B>toggle</B> will expand a selected cell that is
|
||||||
|
unexpanded, or unexpand a cell that is already expanded.
|
||||||
|
<B>toggle</B> may be given as an additional option to any
|
||||||
|
of the other options above; however, the <B>toggle</B> option
|
||||||
|
must be the last option given to the command.<P>
|
||||||
|
|
||||||
|
With no arguments, the <B>expand</B> command behaves like
|
||||||
|
<B>expand overlap</B>, and the <B>expand toggle</B> command
|
||||||
|
with no additonal arguments behaves like
|
||||||
|
<B>expand selection toggle</B>, for backwards-compatible
|
||||||
|
behavior with earlier versions of magic which offered only
|
||||||
|
the <B>toggle</B> option.
|
||||||
|
|
||||||
Option <B>expand toggle</B> operates on the current selection,
|
|
||||||
not relative to the cursor box, and will expand a selected
|
|
||||||
cell that is unexpanded, or unexpand a cell that is already
|
|
||||||
expanded.
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,15 @@ Convert extracted file(s) to a SPICE format file.
|
||||||
(see Summary, below).
|
(see Summary, below).
|
||||||
<DT> <B>default</B>
|
<DT> <B>default</B>
|
||||||
<DD> Reset to default values
|
<DD> Reset to default values
|
||||||
<DT> <B>format hspice</B>|<B>spice2</B>|<B>spice3</B>|<B>ngspice</B>
|
<DT> <B>format hspice</B>|<B>spice2</B>|<B>spice3</B>|<B>ngspice</B>|<B>cdl</B>
|
||||||
<DD> Set output format. <B>spice3</B> is the default,
|
<DD> Set output format. <B>spice3</B> is the default,
|
||||||
for compatibility with <B>tclspice</B>. This is a
|
for compatibility with <B>tclspice</B>. This is a
|
||||||
change from previous versions of magic, where the
|
change from previous versions of magic, where the
|
||||||
default was <B>hspice</B>.
|
default was <B>hspice</B>. <B>ngspice</B> is set as
|
||||||
|
default by the <B>ext2spice lvs</B> option. <B>cdl</B>
|
||||||
|
format incorporates some common syntax used by CDL format
|
||||||
|
files, including placing a slash between a subcircuit's
|
||||||
|
pins and the subcircuit name.
|
||||||
<DT> <B>rthresh</B> [<I>value</I>]
|
<DT> <B>rthresh</B> [<I>value</I>]
|
||||||
<DD> Set resistance threshold value. Lumped resistances
|
<DD> Set resistance threshold value. Lumped resistances
|
||||||
below this value will not be written to the output. The
|
below this value will not be written to the output. The
|
||||||
|
|
@ -46,7 +50,6 @@ Convert extracted file(s) to a SPICE format file.
|
||||||
to prohibit writing any lumped resistances to the output.
|
to prohibit writing any lumped resistances to the output.
|
||||||
<DT> <B>cthresh</B> [<I>value</I>]
|
<DT> <B>cthresh</B> [<I>value</I>]
|
||||||
<DD> Set capacitance threshold value. The value is in femtofarads,
|
<DD> Set capacitance threshold value. The value is in femtofarads,
|
||||||
or may be the keyword <B>infinite</B> to prohibit writing
|
|
||||||
any parasitic capacitances to the output.
|
any parasitic capacitances to the output.
|
||||||
<DT> <B>merge</B> [<I>merge_option</I>]
|
<DT> <B>merge</B> [<I>merge_option</I>]
|
||||||
<DD> Merge parallel devices/transistors. The valid merge options are:
|
<DD> Merge parallel devices/transistors. The valid merge options are:
|
||||||
|
|
@ -95,13 +98,18 @@ Convert extracted file(s) to a SPICE format file.
|
||||||
<B>subcircuit</B> is set to <B>off</B>, the top-level
|
<B>subcircuit</B> is set to <B>off</B>, the top-level
|
||||||
circuit will be the top level of the netlist, and it
|
circuit will be the top level of the netlist, and it
|
||||||
will have no associated subcircuit definition.
|
will have no associated subcircuit definition.
|
||||||
<DT> <B>subcircuit top</B> [<B>on</B>|<B>off</B>]
|
<DT> <B>subcircuit top</B> [<B>on</B>|<B>off</B>|<B>auto</B>]
|
||||||
<DD> This variant of the <B>subcircuit</B> option controls
|
<DD> This variant of the <B>subcircuit</B> option controls
|
||||||
whether or not ext2spice generates a .subckt wrapper
|
whether or not ext2spice generates a .subckt wrapper
|
||||||
around the top-level circuit. If the top-level circuit
|
around the top-level circuit. If <B>on</B> is specified,
|
||||||
does not have defined ports, then no .subckt wrapper
|
a ".subckt" wrapper will always be output, regardless of
|
||||||
will ever be generated, because ext2spice will not
|
whether or not ports are defined in the layout. If
|
||||||
be able to know which nets are the ports.
|
<B>off</B>, no ".subckt" wrapper will be output, and
|
||||||
|
ports will be ignored (They will be regular nets in the
|
||||||
|
output netlist). If set to <B>auto</B>, magic will
|
||||||
|
check whether or not ports are defined in the layout,
|
||||||
|
and generate a ".subckt" wrapper only if ports have
|
||||||
|
been defined.
|
||||||
<DT> <B>subcircuit descend</B> [<B>on</B>|<B>off</B>]
|
<DT> <B>subcircuit descend</B> [<B>on</B>|<B>off</B>]
|
||||||
<DD> When set to <B>off</B>, the <B>subcircuit descend</B>
|
<DD> When set to <B>off</B>, the <B>subcircuit descend</B>
|
||||||
option will not descend into any subcells below the
|
option will not descend into any subcells below the
|
||||||
|
|
@ -230,7 +238,7 @@ Convert extracted file(s) to a SPICE format file.
|
||||||
class, and substrate node name for device type <I>device</I>.
|
class, and substrate node name for device type <I>device</I>.
|
||||||
Resistance classes are indexed by number and must match the
|
Resistance classes are indexed by number and must match the
|
||||||
definition in the technology file's extract section.
|
definition in the technology file's extract section.
|
||||||
<DT> <B>-f spice2</B>|<B>spice3</B>|<B>hspice</B>|<B>ngspice</B>
|
<DT> <B>-f spice2</B>|<B>spice3</B>|<B>hspice</B>|<B>ngspice</B>|<B>cdl</B>
|
||||||
<DD> Choose the output SPICE format for compatibility with
|
<DD> Choose the output SPICE format for compatibility with
|
||||||
different versions of SPICE.
|
different versions of SPICE.
|
||||||
<DT> <B>-d</B>
|
<DT> <B>-d</B>
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,11 @@ Circuit netlist extractor
|
||||||
<DL>
|
<DL>
|
||||||
<DT> <B>capacitance</B>
|
<DT> <B>capacitance</B>
|
||||||
<DD> Extract local parasitic capacitance values to substrate
|
<DD> Extract local parasitic capacitance values to substrate
|
||||||
<DT> <B>resistance</B>
|
<DT> <B>coupling</B>
|
||||||
<DD> Extract lumped resistance values. Note that this
|
<DD> Extract the parasitic coupling capacitance between
|
||||||
is <I>not</I> the same as full parasitic resistance.
|
nodes.
|
||||||
|
<DT> <B>lumped</B>
|
||||||
|
<DD> Extract lumped resistance values.
|
||||||
The values extracted are "lumped" resistance and
|
The values extracted are "lumped" resistance and
|
||||||
indicate the value for which the delay through the
|
indicate the value for which the delay through the
|
||||||
net can be computed with R times C, where R is the
|
net can be computed with R times C, where R is the
|
||||||
|
|
@ -55,9 +57,10 @@ Circuit netlist extractor
|
||||||
command. Lumped resistances have no meaning in
|
command. Lumped resistances have no meaning in
|
||||||
SPICE netlists and will only be used when running
|
SPICE netlists and will only be used when running
|
||||||
<B>ext2sim</B> to generate a .sim netlist.
|
<B>ext2sim</B> to generate a .sim netlist.
|
||||||
<DT> <B>coupling</B>
|
Prior to magic version 8.3.597, this option was
|
||||||
<DD> Extract the parasitic coupling capacitance between
|
<B>resistance</B>, but as that was often confused
|
||||||
nodes.
|
with full parasitic resistance extraction, it has
|
||||||
|
been changed.
|
||||||
<DT> <B>length</B>
|
<DT> <B>length</B>
|
||||||
<DD> Extract the length of the shortest path from a driver
|
<DD> Extract the length of the shortest path from a driver
|
||||||
to a receiver, for computing more accurate parasitic
|
to a receiver, for computing more accurate parasitic
|
||||||
|
|
@ -73,7 +76,7 @@ Circuit netlist extractor
|
||||||
array instances, is guaranteed to be strictly positive.
|
array instances, is guaranteed to be strictly positive.
|
||||||
<DT> <B>all</B>
|
<DT> <B>all</B>
|
||||||
<DD> Apply all standard options (does not include options
|
<DD> Apply all standard options (does not include options
|
||||||
"local", "labelcheck", or "aliases").
|
"local", "labelcheck", "aliases", or "resistance").
|
||||||
<DT> <B>local</B>
|
<DT> <B>local</B>
|
||||||
<DD> Write all .ext files to the current working directory.
|
<DD> Write all .ext files to the current working directory.
|
||||||
If not specified, each .ext file will be placed in the
|
If not specified, each .ext file will be placed in the
|
||||||
|
|
@ -99,6 +102,28 @@ Circuit netlist extractor
|
||||||
but will usually just slow down processing by commands
|
but will usually just slow down processing by commands
|
||||||
like "ext2spice" that use the .ext file contents, so it
|
like "ext2spice" that use the .ext file contents, so it
|
||||||
is disabled by default.
|
is disabled by default.
|
||||||
|
<DT> <B>unique</B>
|
||||||
|
<DD> (Added in magic version 8.3.594) This setting replaces
|
||||||
|
the use of the command option "extract unique". Instead
|
||||||
|
of changing labels in the design, unique labels are
|
||||||
|
generated for the duration of the extraction, and then
|
||||||
|
reverted back to the original text. The "extract unique"
|
||||||
|
command option is maintained for backwards compatibility.
|
||||||
|
Note the difference: "extract unique" is a command that
|
||||||
|
runs immediately, and cannot be undone;
|
||||||
|
"extract do unique" is an option setting for "extract".
|
||||||
|
<DT> <B>resistance</B>
|
||||||
|
<DD> (Added in magic version 8.3.597) This setting replaces
|
||||||
|
the use of the standalone command "extresist". The
|
||||||
|
effect is the same: Magic performs full R-C extraction,
|
||||||
|
generating a <TT>.res.ext</TT> file that annotates the
|
||||||
|
existing <TT>.ext</TT> file (see the "extresist" command
|
||||||
|
documentation). The "extresist" command options can
|
||||||
|
still be used to set options such as tolerance for the
|
||||||
|
R-C extraction.
|
||||||
|
Note that prior to magic version 8.3.597, this option
|
||||||
|
name would produce the lumped resistance approximation
|
||||||
|
(see <B>lumped</B>, above).
|
||||||
</DL>
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
These options (except for "local") determine how much
|
These options (except for "local") determine how much
|
||||||
|
|
@ -213,7 +238,9 @@ Circuit netlist extractor
|
||||||
<I>Warning:</I> This operation immediately modifies the
|
<I>Warning:</I> This operation immediately modifies the
|
||||||
existing layout in preparation for extraction. Label
|
existing layout in preparation for extraction. Label
|
||||||
modifications are permanent, and cannot be undone. All
|
modifications are permanent, and cannot be undone. All
|
||||||
cells in the hierarchy may potentially be modified. <BR>
|
cells in the hierarchy may potentially be modified. To avoid
|
||||||
|
this issue, use the "extract do unique" option instead (see
|
||||||
|
above). <BR>
|
||||||
<DT> <B>warn</B> [[<B>no</B>] <I>option</I>]
|
<DT> <B>warn</B> [[<B>no</B>] <I>option</I>]
|
||||||
<DD> Enable/disable reporting of non-fatal errors, where <I>option</I>
|
<DD> Enable/disable reporting of non-fatal errors, where <I>option</I>
|
||||||
may be one of the following:
|
may be one of the following:
|
||||||
|
|
|
||||||
|
|
@ -92,17 +92,25 @@ information.
|
||||||
The <B>extresist</B> command provides a method for generating
|
The <B>extresist</B> command provides a method for generating
|
||||||
a more detailed model of resistance, in which long network
|
a more detailed model of resistance, in which long network
|
||||||
routes and branching routes are replaced with resistor devices
|
routes and branching routes are replaced with resistor devices
|
||||||
and device networks. <P>
|
and device networks. This is known as "full R-C extraction". <P>
|
||||||
|
|
||||||
Using <B>extresist</B> is a multi-step process. It is first
|
Using <B>extresist</B> as a standalone command is a multi-step
|
||||||
necessary to run both <B>extract</B> and <B>ext2sim</B> to get
|
process. It is first necessary to run <B>extract</B> to get
|
||||||
the initial netlist (with lumped, not detailed, resistances).
|
the initial netlist.
|
||||||
After a <TT>.sim</TT> file has been generated, the
|
After a <TT>.ext</TT> file has been generated, the
|
||||||
<B>extresist all</B> command may be run. The output is
|
<B>extresist</B> command may be run. The output is
|
||||||
a file <TT>.res.ext</TT> for each cell in the hierarchy.
|
a file <TT>.res.ext</TT> for each cell in the hierarchy.
|
||||||
Finally, with the option <B>extresist on</B> set,
|
Finally, with the option <B>extresist on</B> set, <B>ext2spice</B>
|
||||||
<B>ext2sim</B> or <B>ext2spice</B> will generate the final,
|
will generate the final, detailed simulation file. <P>
|
||||||
detailed simulation file. <P>
|
|
||||||
|
Prior to magic version 8.3.597, it was also necessary to run
|
||||||
|
<B>ext2sim labels on</B> and <B>ext2sim</B> to write out a
|
||||||
|
<TT>.sim</TT> and a <TT>.node</TT> file before running
|
||||||
|
<B>extresist</B>. This is no longer necessary. There is since
|
||||||
|
magic version 8.3.597 an option <B>extract do resistance</B>
|
||||||
|
that runs the resistance extraction in sequence with the regular
|
||||||
|
extraction, producing both the <TT>.ext</TT> and <TT>.res.ext</TT>
|
||||||
|
files.
|
||||||
|
|
||||||
More details on using <B>extresist</B> can be found in
|
More details on using <B>extresist</B> can be found in
|
||||||
<B>magic</B> Tutorial number 8.
|
<B>magic</B> Tutorial number 8.
|
||||||
|
|
@ -117,6 +125,7 @@ information.
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<A HREF=extract.html><B>extract</B></A> <BR>
|
<A HREF=extract.html><B>extract</B></A> <BR>
|
||||||
<A HREF=ext2sim.html><B>ext2sim</B></A> <BR>
|
<A HREF=ext2sim.html><B>ext2sim</B></A> <BR>
|
||||||
|
<A HREF=ext2spice.html><B>ext2spice</B></A> <BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<STYLE type="text/css">
|
|
||||||
H1 {color: black }
|
|
||||||
H2 {color: maroon }
|
|
||||||
H3 {color: #007090 }
|
|
||||||
A.head:link {color: #0060a0 }
|
|
||||||
A.head:visited {color: #3040c0 }
|
|
||||||
A.head:active {color: white }
|
|
||||||
A.head:hover {color: yellow }
|
|
||||||
A.red:link {color: red }
|
|
||||||
A.red:visited {color: maroon }
|
|
||||||
A.red:active {color: yellow }
|
|
||||||
</STYLE>
|
|
||||||
</HEAD>
|
|
||||||
<TITLE>Magic-8.3 Command Reference</TITLE>
|
|
||||||
<BODY BACKGROUND=graphics/blpaper.gif>
|
|
||||||
<H1> <IMG SRC=graphics/magic_title8_3.gif ALT="Magic VLSI Layout Tool Version 8.3">
|
|
||||||
<IMG SRC=graphics/magic_OGL_sm.gif ALIGN="top" ALT="*"> </H1>
|
|
||||||
|
|
||||||
<H2>ext2sim, exttosim</H2>
|
|
||||||
<HR>
|
|
||||||
Convert extracted file(s) to a ".sim" format file.
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<B>ext2sim</B> [<I>option</I>] <BR><BR>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
where <I>option</I> is one of the following:
|
|
||||||
<DL>
|
|
||||||
<DT> [<B>run</B>] [<I>runtime_options</I>]
|
|
||||||
<DD> Run exttosim on current cell, with command-line options
|
|
||||||
(see Summary, below).
|
|
||||||
<DT> <B>alias on</B>|<B>off</B>
|
|
||||||
<DD> Enable/disable alias (.al) file
|
|
||||||
<DT> <B>labels on</B>|<B>off</B>
|
|
||||||
<DD> Enable/disable labels (.nodes) file
|
|
||||||
<DT> <B>default</B>
|
|
||||||
<DD> Reset to default values
|
|
||||||
<DT> <B>format MIT</B>|<B>SU</B>|<B>LBL</B>
|
|
||||||
<DD> Set output format
|
|
||||||
<DT> <B>rthresh</B> [<I>value</I>]
|
|
||||||
<DD> Set resistance threshold value. Lumped resistances
|
|
||||||
below this value will not be written to the output. The
|
|
||||||
value is in ohms, or may be the keyword <B>infinite</B>
|
|
||||||
to prohibit writing any lumped resistances to the output.
|
|
||||||
<DT> <B>cthresh</B> [<I>value</I>]
|
|
||||||
<DD> Set capacitance threshold value. The value is in femtofarads,
|
|
||||||
or may be the keyword <B>infinite</B> to prohibit writing
|
|
||||||
any parasitic capacitances to the output.
|
|
||||||
<DT> <B>merge</B> [<I>merge_option</I>]
|
|
||||||
<DD> Merge parallel devices/transistors. The valid merge options are:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<DL>
|
|
||||||
<DT><B>conservative</B>
|
|
||||||
<DD> Merge transistors and capacitors having the same device
|
|
||||||
type and node connections and having the same width and
|
|
||||||
length. Widths are summed in the final output for
|
|
||||||
transistors. Capacitor values are summed in the final
|
|
||||||
output.
|
|
||||||
<DT><B>aggressive</B>
|
|
||||||
<DD> Merge transistors having the same node
|
|
||||||
connections and having the same length. Widths
|
|
||||||
are summed in the final output. Merge any capacitors
|
|
||||||
having the same device type and node connections.
|
|
||||||
Capacitance is summed in the final output.
|
|
||||||
<DT><B>none</B>
|
|
||||||
<DD> Do not merge any devices.
|
|
||||||
</DL>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
<DT> <B>extresist on</B>|<B>off</B>
|
|
||||||
<DD> Incorporate output from the command <B>extresist</B> into
|
|
||||||
the final <TT>.sim</TT> file.
|
|
||||||
<DT> <B>help</B>
|
|
||||||
<DD> Print help information
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>Summary:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Without options, or with the option <B>run</B>,
|
|
||||||
the <B>ext2sim</B> command converts the hierarchical extracted
|
|
||||||
netlist information produced by the <B>extract</B> command in
|
|
||||||
a series of <TT>.ext</TT> files into a flattened representation
|
|
||||||
in the <TT>.sim</TT> format, used for switch-level simulation. <P>
|
|
||||||
|
|
||||||
<I>runtime_options</I> may be passed on the command line, and
|
|
||||||
represent the original command-line options passed to the
|
|
||||||
standalone version of ext2sim. A number of the original
|
|
||||||
command-line options have been deprecated in the Tcl-based
|
|
||||||
version, and some are duplicated by other <B>ext2sim</B> options.
|
|
||||||
Valid <I>runtime_options</I> are:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<DL>
|
|
||||||
<DT> <B>-B</B>
|
|
||||||
<DD> Don't output transistor or node attributes in the .sim file.
|
|
||||||
This option will also disable the output of information such
|
|
||||||
as the area and perimeter of source and drain diffusion and
|
|
||||||
the FET substrate.
|
|
||||||
<DT> <B>-F</B>
|
|
||||||
<DD> Don't output nodes that aren't connected to devices (floating
|
|
||||||
nodes).
|
|
||||||
<DT> <B>-t</B><I>char</I>
|
|
||||||
<DD> Trim characters from node names when writing the output file.
|
|
||||||
<I>char</I> should be either "<B>#</B>" or "<B>!</B>". The
|
|
||||||
option may be used twice if both characters require trimming.
|
|
||||||
<DT> <B>-y</B> <I>num</I>
|
|
||||||
<DD> Select the precision for outputting capacitors. The default is
|
|
||||||
1 which means that the capacitors will be printed to a precision
|
|
||||||
of 0.1 fF.
|
|
||||||
<DT> <B>-J</B> <B>hier</B>|<B>flat</B>
|
|
||||||
<DD> Select the source/drain area and perimeter extraction algorithm.
|
|
||||||
If <B>hier</B> is selected then the areas and perimeters are
|
|
||||||
extracted only within each subcell. For each device in a
|
|
||||||
subcell the area and perimeter of its source and drain within
|
|
||||||
this subcell are output. If two or more devices share a
|
|
||||||
source/drain node then the total area and perimeter will be
|
|
||||||
output in only one of them and the other will have 0. If
|
|
||||||
<B>flat</B> is selected the same rules apply, only the scope
|
|
||||||
of search for area and perimeter is the whole netlist. In
|
|
||||||
general, <B>flat</B> (which is the default) will give accurate
|
|
||||||
results (it will take into account shared sources/drains).
|
|
||||||
</DL>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
With options, the command sets various parameters affecting the
|
|
||||||
output format and content. <P>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<B>ext2sim</B> is implemented as a separate loadable Tcl package,
|
|
||||||
but one which depends on the presence of the standard "tclmagic"
|
|
||||||
package. <B>magic</B> is set up with a placeholder command for
|
|
||||||
<B>ext2sim</B>, and will automatically load the Tcl package when
|
|
||||||
this command is invoked. <P>
|
|
||||||
|
|
||||||
<B>exttosim</B> is an alias for <B>ext2sim</B>, to satisfy the
|
|
||||||
grammatically anal retentive.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>See Also:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<A HREF=extract.html><B>extract</B></A> <BR>
|
|
||||||
<A HREF=extresist.html><B>extresist</B></A> <BR>
|
|
||||||
<A HREF=ext2spice.html><B>ext2spice</B></A> <BR>
|
|
||||||
<A HREF=irsim.html><B>irsim</B></A> <BR>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
|
||||||
<TABLE BORDER=0>
|
|
||||||
<TR>
|
|
||||||
<TD> <A HREF=commands.html>Return to command index</A>
|
|
||||||
</TR>
|
|
||||||
</TABLE>
|
|
||||||
<P><I>Last updated:</I> October 12, 2005 at 9:40pm <P>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<STYLE type="text/css">
|
|
||||||
H1 {color: black }
|
|
||||||
H2 {color: maroon }
|
|
||||||
H3 {color: #007090 }
|
|
||||||
A.head:link {color: #0060a0 }
|
|
||||||
A.head:visited {color: #3040c0 }
|
|
||||||
A.head:active {color: white }
|
|
||||||
A.head:hover {color: yellow }
|
|
||||||
A.red:link {color: red }
|
|
||||||
A.red:visited {color: maroon }
|
|
||||||
A.red:active {color: yellow }
|
|
||||||
</STYLE>
|
|
||||||
</HEAD>
|
|
||||||
<TITLE>Magic-8.3 Command Reference</TITLE>
|
|
||||||
<BODY BACKGROUND=graphics/blpaper.gif>
|
|
||||||
<H1> <IMG SRC=graphics/magic_title8_3.gif ALT="Magic VLSI Layout Tool Version 8.3">
|
|
||||||
<IMG SRC=graphics/magic_OGL_sm.gif ALIGN="top" ALT="*"> </H1>
|
|
||||||
|
|
||||||
<H2>ext2spice, exttospice</H2>
|
|
||||||
<HR>
|
|
||||||
Convert extracted file(s) to a SPICE format file.
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<B>ext2spice</B> [<I>option</I>] <BR><BR>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
where <I>option</I> is one of the following:
|
|
||||||
<DL>
|
|
||||||
<DT> [<B>run</B>] [<I>runtime_options</I>]
|
|
||||||
<DD> Run <B>ext2spice</B> on current cell, with command-line options
|
|
||||||
(see Summary, below).
|
|
||||||
<DT> <B>default</B>
|
|
||||||
<DD> Reset to default values
|
|
||||||
<DT> <B>format hspice</B>|<B>spice2</B>|<B>spice3</B>
|
|
||||||
<DD> Set output format. <B>spice3</B> is the default,
|
|
||||||
for compatibility with <B>tclspice</B>. This is a
|
|
||||||
change from previous versions of magic, where the
|
|
||||||
default was <B>hspice</B>.
|
|
||||||
<DT> <B>rthresh</B> [<I>value</I>]
|
|
||||||
<DD> Set resistance threshold value. Lumped resistances
|
|
||||||
below this value will not be written to the output. The
|
|
||||||
value is in ohms, or may be the keyword <B>infinite</B>
|
|
||||||
to prohibit writing any lumped resistances to the output.
|
|
||||||
<DT> <B>cthresh</B> [<I>value</I>]
|
|
||||||
<DD> Set capacitance threshold value. The value is in femtofarads,
|
|
||||||
or may be the keyword <B>infinite</B> to prohibit writing
|
|
||||||
any parasitic capacitances to the output.
|
|
||||||
<DT> <B>merge</B> [<I>merge_option</I>]
|
|
||||||
<DD> Merge parallel devices/transistors. The valid merge options are:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<DL>
|
|
||||||
<DT><B>conservative</B>
|
|
||||||
<DD> Merge transistors and capacitors having the same device
|
|
||||||
type and node connections and having the same width and
|
|
||||||
length. Widths are summed in the final output for
|
|
||||||
transistors. Capacitor values are summed in the final
|
|
||||||
output.
|
|
||||||
<DT><B>aggressive</B>
|
|
||||||
<DD> Merge transistors having the same node
|
|
||||||
connections and having the same length. Widths
|
|
||||||
are summed in the final output. Merge any capacitors
|
|
||||||
having the same device type and node connections.
|
|
||||||
Capacitance is summed in the final output.
|
|
||||||
<DT><B>none</B>
|
|
||||||
<DD> Do not merge any devices.
|
|
||||||
</DL>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
<DT> <B>extresist on</B>|<B>off</B>
|
|
||||||
<DD> Incorporate output from the command <B>extresist</B> into
|
|
||||||
the final SPICE file.
|
|
||||||
<DT> <B>resistor tee</B> [<B>on</B>|<B>off</B>]
|
|
||||||
<DD> Model resistor capacitance as a T-network. Each resistor
|
|
||||||
device is split into two, with all substrate and overlap
|
|
||||||
capacitance placed on the node between the two half-length
|
|
||||||
devices. Without this option, resistor devices lose all
|
|
||||||
parasitic capacitance information, and <B>ext2spice</B>
|
|
||||||
may produce warnings about unknown nodes. However, use of
|
|
||||||
this option may conflict with LVS (layout-vs.-schematic),
|
|
||||||
when only one resistor is expected per drawn device.
|
|
||||||
<DT> <B>subcircuits</B> [<B>on</B>|<B>off</B>]
|
|
||||||
<DD> When set to <B>on</B> (the default), standard cells become
|
|
||||||
subcircuit calls ("X") in the SPICE output. The contents
|
|
||||||
of the standard cells are not output, and it is assumed
|
|
||||||
that a pre-characterized SPICE deck exists modeling the
|
|
||||||
behavior of each standard cell definition. Standard cells
|
|
||||||
are defined by the use of the <B>port</B> method for
|
|
||||||
labeling input and output ports. When set to <B>off</B>,
|
|
||||||
ports are ignored, and the entire circuit hierarchy is
|
|
||||||
flattened down to the device level.
|
|
||||||
<DT> <B>help</B>
|
|
||||||
<DD> Print help information.
|
|
||||||
</DL>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>Summary:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Without options, or with the option <B>run</B>,
|
|
||||||
the <B>ext2spice</B> command converts the hierarchical extracted
|
|
||||||
netlist information produced by the <B>extract</B> command in
|
|
||||||
a series of <TT>.ext</TT> files into a flattened representation
|
|
||||||
in SPICE format, used for detailed analog simulation. <P>
|
|
||||||
|
|
||||||
<I>runtime_options</I> may be passed on the command line, and
|
|
||||||
represent the original command-line options passed to the
|
|
||||||
standalone version of ext2spice. A number of the original
|
|
||||||
command-line options have been deprecated in the Tcl-based
|
|
||||||
version, and some are duplicated by other <B>ext2spice</B> options.
|
|
||||||
Valid <I>runtime_options</I> are:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<DL>
|
|
||||||
<DT> <B>-B</B>
|
|
||||||
<DD> Don't output transistor or node attributes in the SPICE file.
|
|
||||||
This option will also disable the output of information such
|
|
||||||
as the area and perimeter of source and drain diffusion and
|
|
||||||
the FET substrate.
|
|
||||||
<DT> <B>-F</B>
|
|
||||||
<DD> Don't output nodes that aren't connected to devices (floating
|
|
||||||
nodes).
|
|
||||||
<DT> <B>-t</B><I>char</I>
|
|
||||||
<DD> Trim characters from node names when writing the output file.
|
|
||||||
<I>char</I> should be either "<B>#</B>" or "<B>!</B>". The
|
|
||||||
option may be used twice if both characters require trimming.
|
|
||||||
<DT> <B>-y</B> <I>num</I>
|
|
||||||
<DD> Select the precision for outputting capacitors. The default is
|
|
||||||
1 which means that the capacitors will be printed to a precision
|
|
||||||
of 0.1 fF.
|
|
||||||
<DT> <B>-J</B> <B>hier</B>|<B>flat</B>
|
|
||||||
<DD> Select the source/drain area and perimeter extraction algorithm.
|
|
||||||
If <B>hier</B> is selected then the areas and perimeters are
|
|
||||||
extracted only within each subcell. For each device in a
|
|
||||||
subcell the area and perimeter of its source and drain within
|
|
||||||
this subcell are output. If two or more devices share a
|
|
||||||
source/drain node then the total area and perimeter will be
|
|
||||||
output in only one of them and the other will have 0. If
|
|
||||||
<B>flat</B> is selected the same rules apply, only the scope
|
|
||||||
of search for area and perimeter is the whole netlist. In
|
|
||||||
general, <B>flat</B> (which is the default) will give accurate
|
|
||||||
results (it will take into account shared sources/drains).
|
|
||||||
</DL>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
With options, the command sets various parameters affecting the
|
|
||||||
output format and content. <P>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<B>ext2spice</B> is implemented as a separate loadable Tcl package,
|
|
||||||
but one which depends on the presence of the standard "tclmagic"
|
|
||||||
package. <B>magic</B> is set up with a placeholder command for
|
|
||||||
<B>ext2spice</B>, and will automatically load the Tcl package when
|
|
||||||
this command is invoked. <P>
|
|
||||||
|
|
||||||
<B>exttospice</B> is an alias for <B>ext2spice</B>, to satisfy the
|
|
||||||
grammatically anal retentive.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>See Also:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<A HREF=extract.html><B>extract</B></A> <BR>
|
|
||||||
<A HREF=ext2sim.html><B>ext2sim</B></A> <BR>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
|
||||||
<TABLE BORDER=0>
|
|
||||||
<TR>
|
|
||||||
<TD> <A HREF=commands.html>Return to command index</A>
|
|
||||||
</TR>
|
|
||||||
</TABLE>
|
|
||||||
<P><I>Last updated:</I> October 12, 2005 at 9:40pm <P>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
|
|
@ -182,6 +182,13 @@ Read GDSII input or generate GDSII output.
|
||||||
than to subsplit the internal grid to such a fine value.
|
than to subsplit the internal grid to such a fine value.
|
||||||
The "<B>cif limit</B>" function may also be used to limit
|
The "<B>cif limit</B>" function may also be used to limit
|
||||||
grid subdivision to a minimum value.
|
grid subdivision to a minimum value.
|
||||||
|
<DT> <B>savepaths</B> [<B>yes</B>|<B>no</B>]
|
||||||
|
<DD> When reading paths from a GDS file, record the centerline of
|
||||||
|
the path as a property in the cell. The default behavior is
|
||||||
|
<B>no</B>. If no argument is given, then return the status
|
||||||
|
of the <B>savepaths</B> option. The first path property is
|
||||||
|
named "<TT>path</TT>", followed by "<TT>path_0</TT>" and
|
||||||
|
increasing the suffix index for each individual path read.
|
||||||
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
|
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
|
||||||
<DD> When reading a GDS file, this option forces magic to rename
|
<DD> When reading a GDS file, this option forces magic to rename
|
||||||
cell definitions in the database when a cell of the same name
|
cell definitions in the database when a cell of the same name
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 991 B |
|
|
@ -87,6 +87,50 @@ Place a label in the layout
|
||||||
to another layer. <P>
|
to another layer. <P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>Attribute labels:</B> <P>
|
||||||
|
A handful of labels are referred to as "attribute" labels. These
|
||||||
|
label types are placed on devices and affect how the device is
|
||||||
|
extracted. <P>
|
||||||
|
|
||||||
|
A label that is placed inside a device (e.g., a MOSFET gate) which
|
||||||
|
ends with the character "<B>^</B>" is a <I>gate attribute</I>. A
|
||||||
|
gate attribute in the form of "<I>name</I><B>=</B><I>value</I><B>^</B>"
|
||||||
|
specifies an extra parameter to be passed to the device in addition
|
||||||
|
to the standard parameters calculated for that device. This is used
|
||||||
|
to capture parameters which cannot easily be inferred from the layout.
|
||||||
|
For example, an RF device model might be distinguished from a non-RF
|
||||||
|
device model by a parameter such as <B>rfmode=1</B>. Whether or not
|
||||||
|
a device is intended for RF use is not easily guessed from the layout,
|
||||||
|
and so "tagging" the gate with the parameter allows the correct model
|
||||||
|
parameters to be used for the device. <P>
|
||||||
|
|
||||||
|
A gate attribute that is not in the form of a parameter will be used
|
||||||
|
as the device's instance index in the netlist; e.g., a label of
|
||||||
|
"<B>1^</B>" on a MOSFET gate extracted as a MOSFET device would be an
|
||||||
|
entry "<B>M1</B>" in the netlist. This can be used to better track
|
||||||
|
device indexes between a schematic and layout. <P>
|
||||||
|
|
||||||
|
A label that is placed on the <I>edge</I> a device, specificlly a
|
||||||
|
MOSFET gate, and which ends with the character "<B>$</B>", is a
|
||||||
|
<I>terminal attribute</I>. The only terminal attributes recognized
|
||||||
|
by magic are <B>S$</B> and <B>D$</B>, which specify which side of the
|
||||||
|
gate is to be considered the source and which is to be considered the
|
||||||
|
drain. Generally, MOSFET devices are symmetric, and their use in a
|
||||||
|
simulation does not depend on which side is in the position of the
|
||||||
|
"source" and which is in the position of the "drain". To the extent
|
||||||
|
that it matters, the terminal attributes can be used to ensure that
|
||||||
|
the source and drain connections appear in the netlist in their
|
||||||
|
intended orientation. <P>
|
||||||
|
|
||||||
|
Labels ending with "<B>@</B>" are <I>node attributes</I>. There is
|
||||||
|
currently no functional application for node attributes. When one
|
||||||
|
is applied, it will appear in the output netlist in a SPICE comment
|
||||||
|
line indicating the node and attribute. This could be used, say,
|
||||||
|
by a post-processing script, but as it is in a comment line, it has
|
||||||
|
no impact on simulation or LVS.
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@ LEF-format input and output
|
||||||
<DT> <B>read</B> [<I>filename</I>] <B>-annotate</B>
|
<DT> <B>read</B> [<I>filename</I>] <B>-annotate</B>
|
||||||
<DD> Read a LEF file. Use any macros defined in the LEF file
|
<DD> Read a LEF file. Use any macros defined in the LEF file
|
||||||
to annotate existing layouts, and ignore all other macros.
|
to annotate existing layouts, and ignore all other macros.
|
||||||
<DT> <B>write</B> [<I>cell</I>] [<B>-tech</B>]
|
<DT> <B>write</B> [<I>filename</I>] [<B>-tech</B>]
|
||||||
[<B>-hide</B> [<I>distance</I>]] [<B>-toplayer</B>]
|
[<B>-hide</B> [<I>distance</I>]] [<B>-toplayer</B>]
|
||||||
[<B>-pinonly</B> [<I>distance</I>]] [<B>-nomaster</B>]
|
[<B>-pinonly</B> [<I>distance</I>]] [<B>-nomaster</B>]
|
||||||
<DD> Write LEF for the current or indicated cell.<BR>
|
<DD> Write LEF for the current cell to the file <I>filename</I>.<BR>
|
||||||
Option <B>-tech</B> writes the technology information (layer
|
Option <B>-tech</B> writes the technology information (layer
|
||||||
mapping and rules) to the same file as the cell macro. <BR>
|
mapping and rules) to the same file as the cell macro. <BR>
|
||||||
Option <B>-hide</B> generates an abstract view that has all
|
Option <B>-hide</B> generates an abstract view that has all
|
||||||
|
|
|
||||||
|
|
@ -20,22 +20,64 @@
|
||||||
|
|
||||||
<H2>macro</H2>
|
<H2>macro</H2>
|
||||||
<HR>
|
<HR>
|
||||||
Define or print a macro called char
|
Define or print a key or button macro binding.
|
||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>macro</B> [<I>window_type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
|
<B>macro</B> [<I>window_type</I>] [<I>option</I>] [<I>key</I> [<I>value</I>]]
|
||||||
|
<BR><BR>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>key</I> is the name of a valid key (see below), and
|
where <I>key</I> is the name of a valid key (see below), and
|
||||||
<I>value</I> is a <B>magic</B> command-line command. If
|
<I>value</I> is a <B>magic</B> command-line command. If
|
||||||
present, <I>window_type</I> must be one of the four window
|
present, <I>window_type</I> must be one of the known valid window
|
||||||
types accepted by the <B>specialopen</B> command: <B>layout</B>,
|
types accepted by the <B>specialopen</B> command (<B>color</B>,
|
||||||
<B>color</B>, <B>netlist</B>, and <B>wind3d</B>. If omitted,
|
<B>netlist</B>, and <B>wind3d</B>), or a known layout tool
|
||||||
the layout window is assumed by default, unless the command has
|
(<B>box</B>, <B>wiring</B>, <B>nettool</B>, or <B>pick</B>). If
|
||||||
been called from inside a window (using the colon or semicolon
|
omitted, the layout window is assumed by default, unless the command
|
||||||
|
has been called from inside a window (using the colon or semicolon
|
||||||
escape to the command-line), in which case that window type is
|
escape to the command-line), in which case that window type is
|
||||||
assumed.
|
assumed. <P>
|
||||||
|
|
||||||
|
In the non-Tcl version of magic, the <I>window_type</I> must be
|
||||||
|
one of the three valid window types listed above, or <B>layout</B>.
|
||||||
|
Tool button bindings are hard-coded, fixed, and unknown to the
|
||||||
|
macro handler. <P>
|
||||||
|
|
||||||
|
In the Tcl version of magic, tool types are generated by
|
||||||
|
procedure and can be modified or overridden. The four tools
|
||||||
|
listed above are the default tools known to magic. If no window
|
||||||
|
or tool type is given, then the current tool in the current
|
||||||
|
active layout window is assumed.<P>
|
||||||
|
|
||||||
|
<I>option</I> may be one of the following:
|
||||||
|
<DL>
|
||||||
|
<DT> <B>list</B> [<B>-reverse</B>]
|
||||||
|
<DD> The key bindings are returned in the form of a Tcl list
|
||||||
|
(Tcl version of magic only). The returned value is a
|
||||||
|
single list with alternating entries of the macro key and
|
||||||
|
the macro binding. In Tcl, this list can be treated as a
|
||||||
|
dictionary type of key:value pairs. With the <B>-reverse</B>
|
||||||
|
option, the keys and values are reversed, resulting in a
|
||||||
|
dictionary that can be searched or listed by function.
|
||||||
|
<DT> <B>help</B>
|
||||||
|
<DD> Curently, <B>macro help</B> is equivalent to <B>macro</B>
|
||||||
|
without arguments, and returns a full list of macro names
|
||||||
|
and their bindings.
|
||||||
|
<DT> <B>search</B> <I>text</I>
|
||||||
|
<DD> Return only results which match (all or in part) the string
|
||||||
|
<I>text</I>. For example, <B>macro search grid</B> will
|
||||||
|
return all key bindings that include the command <B>grid</B>.
|
||||||
|
<DT> <B>copy</B> <I>tool_name</I>
|
||||||
|
<DD> This is a method introduced to allow the interactive creation
|
||||||
|
of new tools, in the Tcl version of magic. Each tool is defined
|
||||||
|
specifically by its unique button and key bindings. Because
|
||||||
|
tools generally keep most of the same default bindings, the
|
||||||
|
<B>copy</B> option will copy all the existing bindings to the
|
||||||
|
new tool from the current tool. This can be followed by
|
||||||
|
switching to the new tool and replacing macros with ones
|
||||||
|
unique to the tool.
|
||||||
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -72,7 +114,6 @@ Define or print a macro called char
|
||||||
etc., the <B>macro</B> command accepts the abbreviated
|
etc., the <B>macro</B> command accepts the abbreviated
|
||||||
forms <B>Button1</B>, and so forth. <P>
|
forms <B>Button1</B>, and so forth. <P>
|
||||||
|
|
||||||
|
|
||||||
Finally, key modifiers may be prepended to the key name.
|
Finally, key modifiers may be prepended to the key name.
|
||||||
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
|
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
|
||||||
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
|
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
|
||||||
|
|
@ -89,6 +130,7 @@ Define or print a macro called char
|
||||||
<H3>See Also:</H3>
|
<H3>See Also:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<A HREF=imacro.html><B>imacro</B></A> <BR>
|
<A HREF=imacro.html><B>imacro</B></A> <BR>
|
||||||
|
<A HREF=toolchange.html><B>tool</B></A> (Tcl version) <BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,13 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>property</B> [<I>key</I> [<I>value</I>]] <BR><BR>
|
<B>property</B> [<I>list</I>] [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR>
|
||||||
|
or
|
||||||
|
<B>property</B> [<B>compat</B>] [<B>true</B>|<B>false</B>] <BR><BR>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>key</I> and <I>value</I> are any text strings.
|
where <I>key</I> and <I>value</I> are any text strings. <BR>
|
||||||
|
<I>type</I> may be one of <B>string</B>, <B>integer</B>,
|
||||||
|
<B>dimension</B>, or <B>double</B>.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -45,11 +49,64 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
with the key is returned. With both arguments, the string
|
with the key is returned. With both arguments, the string
|
||||||
<I>value</I> is associated with the string <I>key</I> as a
|
<I>value</I> is associated with the string <I>key</I> as a
|
||||||
property of the cell. If <I>key</I> is an existing key, then
|
property of the cell. If <I>key</I> is an existing key, then
|
||||||
its original value will be overwritten.
|
its original value will be overwritten. <P>
|
||||||
|
|
||||||
|
By default, properties are interpreted as verbatim string values,
|
||||||
|
with exceptions for the reserved types (see below). To force the
|
||||||
|
values of the property to be interpreted as a specific type, use
|
||||||
|
the <I>type</I> option. <P>
|
||||||
|
|
||||||
|
The <B>property compat</B> setting determines how properties are
|
||||||
|
written out to a .mag file. The default setting is <B>true</B>
|
||||||
|
(backwards compatibility mode), which writes all properties as
|
||||||
|
type "<TT>string</TT>". Properties which are reserved names
|
||||||
|
(see below) will be converted to the best type when reading the
|
||||||
|
.mag file. However, if the user wants to create a property that
|
||||||
|
is handled differently than a string (namely, to be a dimensional
|
||||||
|
value that scales), then comptability mode should be turned off. <P>
|
||||||
|
|
||||||
|
If the argument <I>list</I> is given as the first argument, and
|
||||||
|
<I>value</I> is not present, then if the property <I>key</I>
|
||||||
|
does not exist, then the command will return a NULL object to the
|
||||||
|
interpreter instead of printing an error message. This is the
|
||||||
|
"quiet" version of the command preferred for scripts that want to
|
||||||
|
query whether or not a specific property exists.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
Property names reserved by and used by magic:
|
Types are interpreted as follows:
|
||||||
|
<DL>
|
||||||
|
<DT> <B>string</B> type:
|
||||||
|
<DD> The property value is a character string. Character strings
|
||||||
|
may contain spaces, but if so, then the string should be quoted
|
||||||
|
or in braces, per Tcl syntax.
|
||||||
|
<DT> <B>integer</I> type:
|
||||||
|
<DD> The property value is an integer value or a list of integer
|
||||||
|
values. The values are not considered to be measurements and
|
||||||
|
do not scale. Multiple values may be passed on the command
|
||||||
|
line as additional arguments, or the set of values may be
|
||||||
|
given as a list.
|
||||||
|
<DT> <B>dimension</I> type:
|
||||||
|
<DD> The property value is an integer value or a list of integer
|
||||||
|
values. The values are considered to be (linear) dimensional
|
||||||
|
measurements and therefore scale with the database internal
|
||||||
|
units. They are interpreted as having the values currently
|
||||||
|
specified for <B>units</B>, and display back in the same
|
||||||
|
units. Multiple values may be passed on the command line as
|
||||||
|
additional arguments, or the set of values may be given as a
|
||||||
|
list.
|
||||||
|
<DT> <B>double</I> type:
|
||||||
|
<DD> The property value is a double-wide (64-bit) integer value or
|
||||||
|
a list of double-wide integer values. The values are not
|
||||||
|
considered to be measurements and do not scale. Multiple
|
||||||
|
values may be passed on the command line as additional arguments,
|
||||||
|
or the set of values may be given as a list.
|
||||||
|
</DL>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
Property names reserved by and used by magic (types are <B>string</B>
|
||||||
|
unless otherwise noted):
|
||||||
<DL>
|
<DL>
|
||||||
<DT> <B>GDS_FILE</B>
|
<DT> <B>GDS_FILE</B>
|
||||||
<DD> The value is the name of a GDS file which contains the mask
|
<DD> The value is the name of a GDS file which contains the mask
|
||||||
|
|
@ -60,12 +117,14 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||||
byte position of the start of mask data for this cell definition
|
byte position of the start of mask data for this cell definition
|
||||||
in the file. If set to value <B>0</B>, then the file will be
|
in the file. If set to value <B>0</B>, then the file will be
|
||||||
searched for the data bounds.
|
searched for the data bounds. This property is always of type
|
||||||
|
<B>double</B>.
|
||||||
<DT> <B>GDS_END</B>
|
<DT> <B>GDS_END</B>
|
||||||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||||
byte position of the end of mask data for this cell definition
|
byte position of the end of mask data for this cell definition
|
||||||
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
||||||
property may be omitted.
|
property may be omitted. This property is always of type
|
||||||
|
<B>double</B>.
|
||||||
<DT> <B>LEFview</B>
|
<DT> <B>LEFview</B>
|
||||||
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
||||||
obtained from a LEF macro, and should not be used for extraction
|
obtained from a LEF macro, and should not be used for extraction
|
||||||
|
|
@ -97,6 +156,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
corresponding to the abutment box of the cell, in magic's internal
|
corresponding to the abutment box of the cell, in magic's internal
|
||||||
units. The abutment box is automatically read from LEF files, but
|
units. The abutment box is automatically read from LEF files, but
|
||||||
may be defined for any file and can be used for placement alignment.
|
may be defined for any file and can be used for placement alignment.
|
||||||
|
This property is always of type <B>dimension</B> and must contain
|
||||||
|
exactly four values.
|
||||||
<DT> <B>OBS_BBOX</B>
|
<DT> <B>OBS_BBOX</B>
|
||||||
<DD> This property value is a space-sparated list of four integer values
|
<DD> This property value is a space-sparated list of four integer values
|
||||||
corresponding to a bounding box to be used when generating a LEF
|
corresponding to a bounding box to be used when generating a LEF
|
||||||
|
|
@ -104,7 +165,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
will be entirely covered in obstruction layers (unless cut-outs
|
will be entirely covered in obstruction layers (unless cut-outs
|
||||||
are required to accommodate pins). Any set-back applied by the
|
are required to accommodate pins). Any set-back applied by the
|
||||||
"lef write -hide <value>" option will be applied to this obstruction
|
"lef write -hide <value>" option will be applied to this obstruction
|
||||||
box.
|
box. This property is always of type <B>dimension</B> and must
|
||||||
|
contain exactly four values.
|
||||||
<DT> <B>flatten</B>
|
<DT> <B>flatten</B>
|
||||||
<DD> This property is used in conjunction with the "flatten -doproperty"
|
<DD> This property is used in conjunction with the "flatten -doproperty"
|
||||||
command option and marks the cell for flattening. Cells without
|
command option and marks the cell for flattening. Cells without
|
||||||
|
|
@ -146,7 +208,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
always generate mask layer <I>type</I> in the specified rectangle
|
always generate mask layer <I>type</I> in the specified rectangle
|
||||||
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
||||||
such that <I>type</I> could be defined as the absence of a mask layer,
|
such that <I>type</I> could be defined as the absence of a mask layer,
|
||||||
for example.
|
for example. This property is always of type <B>dimension</B> and
|
||||||
|
must have a multiple of four values.
|
||||||
</DL>
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -157,6 +220,11 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
the cell definition structure.
|
the cell definition structure.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>See Also:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=units.html><B>units</B></A> <BR>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
<TABLE BORDER=0>
|
<TABLE BORDER=0>
|
||||||
<TR>
|
<TR>
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,15 @@ Save edit cell on disk
|
||||||
|
|
||||||
The <B>save</B> command differs from <B>writeall</B> in several
|
The <B>save</B> command differs from <B>writeall</B> in several
|
||||||
ways: <B>save</B> does not descend the hierarchy, and does not
|
ways: <B>save</B> does not descend the hierarchy, and does not
|
||||||
prompt the user for an action.
|
prompt the user for an action. <P>
|
||||||
|
|
||||||
|
As of magic version 8.3.549, if <I>filename</I> ends with
|
||||||
|
"<B>.tcl</B>", then magic will save a script file containing
|
||||||
|
a sequence of magic command-line commands that completely
|
||||||
|
reproduces the file layout. The cell can then be regenerated
|
||||||
|
by sourcing the script. This is not a substitution for a
|
||||||
|
database (<B>.mag</B>) file, and magic will not normally
|
||||||
|
search for or source these type of script files itself. <P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
|
|
|
||||||
|
|
@ -99,9 +99,12 @@ create a new cell definition from a selection.
|
||||||
<DD> Copy the selection from the layout into the selection
|
<DD> Copy the selection from the layout into the selection
|
||||||
buffer, and keep the selection buffer for interactive
|
buffer, and keep the selection buffer for interactive
|
||||||
processing.
|
processing.
|
||||||
<DT> <B>move</B> <I>x y</I>
|
<DT> <B>move</B> [ <I>x y</I> ]
|
||||||
<DD> Move the selection buffer to position <I>x y</I>,
|
<DD> Move the selection buffer to position <I>x y</I>,
|
||||||
relative to the cell definition origin.
|
relative to the cell definition origin. If <I>x</I> and
|
||||||
|
<I>y</I> are not given, the move the selection buffer so
|
||||||
|
that its lower left corner is at the current pointer
|
||||||
|
position.
|
||||||
<DT> <B>bbox</B>
|
<DT> <B>bbox</B>
|
||||||
<DD> Return the bounding box of the selection.
|
<DD> Return the bounding box of the selection.
|
||||||
<DT> <B>feedback</B> [ <I>style</I> [ <I>text</I> ]]
|
<DT> <B>feedback</B> [ <I>style</I> [ <I>text</I> ]]
|
||||||
|
|
|
||||||
|
|
@ -39,21 +39,15 @@ in the selected grid.
|
||||||
feature size, and <B>user</B>, based on the value given by the
|
feature size, and <B>user</B>, based on the value given by the
|
||||||
user to the <B>grid</B> command. <P>
|
user to the <B>grid</B> command. <P>
|
||||||
|
|
||||||
In addition to changing the behavior of the box to mouse
|
Historically, in addition to changing the behavior of the box
|
||||||
button events, the <B>snap</B> command also changes the way
|
to mouse button events, the <B>snap</B> command also changed
|
||||||
that <A HREF=distance.html>distance measurements</A> are
|
the way that <A HREF=distance.html>distance measurements</A>
|
||||||
interpreted in commands that take distance arguments, such
|
are interpreted in commands that take distance arguments.
|
||||||
as <B>move</B>, <B>copy</B>, and <B>stretch</B>. An integer
|
This behavior remains the default for backwards compatibility.
|
||||||
number with no other identifying units is interpreted as a
|
The <B>units</B> command overrides this behavior and allows
|
||||||
measurement in the current snap grid. All other measurements
|
<B>snap</B> to control only the box positioning behavior,
|
||||||
must have an identifying unit: <B>i</B> for internal units,
|
independently of how unsuffixed values are parsed by the
|
||||||
<B>l</B> for lambda units, and <B>g</B> for user grid units
|
interpreter. <P>
|
||||||
(as well as the usual metric units). Even when <B>snap</B>
|
|
||||||
is set to the larger lambda or user grids, it is possible to
|
|
||||||
move the cursor box to finer grid positions from the command
|
|
||||||
line. See the reference page on
|
|
||||||
<A HREF=distance.html>distance measures</A> for a complete
|
|
||||||
description of distance values. <P>
|
|
||||||
|
|
||||||
<B>snap</B> with no arguments returns the current snap grid
|
<B>snap</B> with no arguments returns the current snap grid
|
||||||
type. <P>
|
type. <P>
|
||||||
|
|
@ -80,6 +74,7 @@ in the selected grid.
|
||||||
|
|
||||||
<H3>See Also:</H3>
|
<H3>See Also:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=units.html><B>units</B></A> <BR>
|
||||||
<A HREF=grid.html><B>grid</B></A> <BR>
|
<A HREF=grid.html><B>grid</B></A> <BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ Unexpand everything inside or touching the cursor box.
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>unexpand</B> <BR><BR>
|
<B>unexpand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
|
||||||
|
<BR><BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Shortcuts:</H3>
|
<H3>Shortcuts:</H3>
|
||||||
|
|
@ -37,8 +38,23 @@ Unexpand everything inside or touching the cursor box.
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
The <B>unexpand</B> command unexpands the view of subcells to
|
The <B>unexpand</B> command unexpands the view of subcells to
|
||||||
hide the contents of the subcells and show the bounding box
|
hide the contents of the subcells and show the bounding box
|
||||||
outline only. The <B>unexpand</B> command unexpands all subcells
|
outline only.
|
||||||
that touch or intersect the cursor box in the layout window. <P>
|
|
||||||
|
Option <B>overlap</B> unexpands all expanded subcells that
|
||||||
|
overlap with the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>surround</B> unexpands all expanded subcells that
|
||||||
|
are completely surrounded by the cursor box in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>all</B> unexpands all subcells in the layout window. <P>
|
||||||
|
|
||||||
|
Option <B>selection</B> operates on the current selection, not
|
||||||
|
relative to the cursor box, unexpanding all selected cells. <P>
|
||||||
|
|
||||||
|
With no arguments, the <B>unexpand</B> command behaves like
|
||||||
|
<B>unexpand surround</B>, for backwards-compatible behavior with
|
||||||
|
earlier versions of magic which did not offer the options.
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<STYLE type="text/css">
|
||||||
|
H1 {color: black }
|
||||||
|
H2 {color: maroon }
|
||||||
|
H3 {color: #007090 }
|
||||||
|
A.head:link {color: #0060a0 }
|
||||||
|
A.head:visited {color: #3040c0 }
|
||||||
|
A.head:active {color: white }
|
||||||
|
A.head:hover {color: yellow }
|
||||||
|
A.red:link {color: red }
|
||||||
|
A.red:visited {color: maroon }
|
||||||
|
A.red:active {color: yellow }
|
||||||
|
</STYLE>
|
||||||
|
</HEAD>
|
||||||
|
<TITLE>Magic-8.3 Command Reference</TITLE>
|
||||||
|
<BODY BACKGROUND=graphics/blpaper.gif>
|
||||||
|
<H1> <IMG SRC=graphics/magic_title8_3.png ALT="Magic VLSI Layout Tool Version 8.3">
|
||||||
|
<IMG SRC=graphics/magic_OGL_sm.gif ALIGN="top" ALT="*"> </H1>
|
||||||
|
|
||||||
|
<H2>units</H2>
|
||||||
|
<HR>
|
||||||
|
Cause distance measurements to be interpreted by default (with no
|
||||||
|
suffix provied) as measurments of the selected units, and also cause
|
||||||
|
distance measurements to be printed in the selected units.
|
||||||
|
<HR>
|
||||||
|
|
||||||
|
<H3>Usage:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>units</B> [<B>internal</B>|<B>lambda</B>|<B>user</B>|<B>grid</B>|<B>microns</B>|<B>default</B>] [<B>print</B>|</B>noprint</B>] <BR>
|
||||||
|
or <BR>
|
||||||
|
<B>units</B> [<B>list</B>] <BR><BR>
|
||||||
|
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Summary:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
The <B>units</B> command causes printed measurements to be
|
||||||
|
given in the selected units. The possible unit types are
|
||||||
|
<B>internal</B>, the size of the internal database units,
|
||||||
|
<B>lambda</B>, the lambda grid based on the technology minimum
|
||||||
|
feature size, <B>user</B> (or <B>grid</B>), based on the
|
||||||
|
value given by the user to the <B>grid</B> command, or
|
||||||
|
<B>microns</B>, which are physical units dependent on the
|
||||||
|
CIF or GDS output scaling as defined in the technology file. <P>
|
||||||
|
|
||||||
|
The <B>units</B> command also changes the way
|
||||||
|
that <A HREF=distance.html>distance measurements</A> are
|
||||||
|
interpreted in commands that take distance arguments, such
|
||||||
|
as <B>move</B>, <B>copy</B>, and <B>stretch</B>. An integer
|
||||||
|
number with no other identifying units is interpreted as a
|
||||||
|
measurement in the current units type. All other measurements
|
||||||
|
must have an identifying unit: <B>i</B> for internal units,
|
||||||
|
<B>l</B> for lambda units, and <B>g</B> for user grid units,
|
||||||
|
as well as the usual metric units such as <B>um</B> for
|
||||||
|
microns, <B>nm</B> for nanometers, and so forth. See the
|
||||||
|
reference page on <A HREF=distance.html>distance measures</A>
|
||||||
|
for a complete description of distance values. <P>
|
||||||
|
|
||||||
|
For printed units, the additional argument <B>print</B>
|
||||||
|
causes the units to be printed along with the value; e.g.,
|
||||||
|
"<B>1.0um</B>." This is the usual setting for interactive
|
||||||
|
use. The argument <B>noprint</B> suppresses the unit name,
|
||||||
|
which is appropriate for scripted use, when the value may
|
||||||
|
be passed to arithmetic expressions to be evaluated by the
|
||||||
|
interpreter. <P>
|
||||||
|
|
||||||
|
<B>units</B> with no arguments returns the current units type.
|
||||||
|
<B>units list</B> returns the current units type as a Tcl list
|
||||||
|
of two items; the first item is the units type, and the second
|
||||||
|
item is <B>print</B> or <B>noprint</B>, indicating whether units
|
||||||
|
suffixes are printed with the values. <P>
|
||||||
|
|
||||||
|
Historically, values parsed from the command line were interpreted
|
||||||
|
according to the <B>snap</B> setting. On startup, this behavior
|
||||||
|
remains in effect for backwards compatibility until overridden
|
||||||
|
with a <B>units</B> command. The command <B>units default</B>
|
||||||
|
reverts back to the original behavior. Once the <B>units</B>
|
||||||
|
default type is overridden, the <B>snap</B> behavior is controlled
|
||||||
|
independently of <B>units</B>. <P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Implementation Notes:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>units</B> is implemented as a built-in command in <B>magic</B>.
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>See Also:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=grid.html><B>grid</B></A> <BR>
|
||||||
|
<A HREF=snap.html><B>snap</B></A> <BR>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
<TABLE BORDER=0>
|
||||||
|
<TR>
|
||||||
|
<TD> <A HREF=commands.html>Return to command index</A>
|
||||||
|
</TR>
|
||||||
|
</TABLE>
|
||||||
|
<P><I>Last updated:</I> March 7, 2020 at 1:06pm <P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
|
|
@ -45,10 +45,12 @@ view [get|bbox|llx lly urx ury]
|
||||||
center and scale the screen view of the layout window to fit the layout. <P>
|
center and scale the screen view of the layout window to fit the layout. <P>
|
||||||
|
|
||||||
<B>view bbox</B> returns the bounding box dimensions of the layout,
|
<B>view bbox</B> returns the bounding box dimensions of the layout,
|
||||||
in the coordinate system of the layout. <P>
|
in the coordinate system of the layout (according to the units
|
||||||
|
set by the "units" command). <P>
|
||||||
|
|
||||||
<B>view get</B> returns the coordinates of the screen limits in
|
<B>view get</B> returns the coordinates of the screen limits in
|
||||||
the coordinate system of the layout (internal database units). <P>
|
the coordinate system of the layout (according to the units set
|
||||||
|
by the "units" command). <P>
|
||||||
|
|
||||||
<B>view</B> <I>llx lly urx ury</I> sets the view so that the
|
<B>view</B> <I>llx lly urx ury</I> sets the view so that the
|
||||||
corners of the screen are at the indicated positions in the
|
corners of the screen are at the indicated positions in the
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ extern int drcArrayYankFunc(), drcArrayOverlapFunc();
|
||||||
static DRCCookie drcArrayCookie = {
|
static DRCCookie drcArrayCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_ARRAY_OVERLAP_TAG,
|
DRC_ARRAY_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
|
||||||
307
drc/DRCbasic.c
307
drc/DRCbasic.c
|
|
@ -27,6 +27,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h> // for memcpy()
|
#include <string.h> // for memcpy()
|
||||||
#include <math.h> // for sqrt() for diagonal check
|
#include <math.h> // for sqrt() for diagonal check
|
||||||
|
|
||||||
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
|
|
@ -36,6 +38,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
#include "utils/maxrect.h"
|
#include "utils/maxrect.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/undo.h"
|
||||||
|
#include "textio/textio.h"
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
|
||||||
int dbDRCDebug = 0;
|
int dbDRCDebug = 0;
|
||||||
|
|
||||||
|
|
@ -47,7 +52,7 @@ int dbDRCDebug = 0;
|
||||||
static DRCCookie drcOverlapCookie = {
|
static DRCCookie drcOverlapCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_OVERLAP_TAG,
|
DRC_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -61,7 +66,33 @@ extern MaxRectsData *drcCanonicalMaxwidth();
|
||||||
/*
|
/*
|
||||||
*-----------------------------------------------------------------------
|
*-----------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* drcCifPointToSegment
|
* drcFoundOneFunc --
|
||||||
|
*
|
||||||
|
* Simple callback for a plane search on a mask-hint plane inside
|
||||||
|
* a DRC check area.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Return 1 always, indicating that a tile has been found in the
|
||||||
|
* DRC search area, and the search can end.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
*-----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
drcFoundOneFunc(Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData cdata)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-----------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* drcCifPointToSegment --
|
||||||
*
|
*
|
||||||
* Euclidean-distance point-to-segment distance (squared)
|
* Euclidean-distance point-to-segment distance (squared)
|
||||||
* calculation (borrowed from XCircuit)
|
* calculation (borrowed from XCircuit)
|
||||||
|
|
@ -139,8 +170,9 @@ drcCifPointToSegment(px, py, s1x, s1y, s2x, s2y)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaCheck(tile, arg)
|
areaCheck(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
Rect rect; /* Area where error is to be recorded. */
|
Rect rect; /* Area where error is to be recorded. */
|
||||||
|
|
@ -194,7 +226,7 @@ areaCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -209,7 +241,7 @@ areaCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -225,7 +257,7 @@ areaCheck(tile, arg)
|
||||||
+ sdist - rect.r_ytop) >= 0)
|
+ sdist - rect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
@ -241,7 +273,7 @@ areaCheck(tile, arg)
|
||||||
+ sdist - rect.r_ytop) >= 0)
|
+ sdist - rect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
@ -287,16 +319,59 @@ areaCheck(tile, arg)
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* areaNMCheck ---
|
* areaNMReject ---
|
||||||
*
|
*
|
||||||
* Check for errors in triangular area of a tile
|
* Trivial callback function used by areaNMCheck to see if a tile
|
||||||
|
* found in the error area of a reverse non-manhattan check exists
|
||||||
|
* only on the other side of the original check boundary. If it
|
||||||
|
* is found in this search, return 1 to immediately stop the search.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Returns 1 if the tile indicated in the ClientData argument was
|
||||||
|
* found in the check area, otherwise return 0 to keep looking.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaNMCheck(tile, arg)
|
areaNMReject(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
|
ClientData *arg;
|
||||||
|
{
|
||||||
|
Tile *checktile = (Tile *)arg;
|
||||||
|
|
||||||
|
if (tile == checktile)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* areaNMCheck ---
|
||||||
|
*
|
||||||
|
* Check for errors in triangular area of a tile.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Return 0 always to keep the search going.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* If the tile is not rejected due to being outside of the various
|
||||||
|
* clip areas, then call the function specified in the drcClientData
|
||||||
|
* argument.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
areaNMCheck(tile, dinfo, arg)
|
||||||
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
Rect rect; /* Area where error is to be recorded. */
|
Rect rect; /* Area where error is to be recorded. */
|
||||||
|
|
@ -320,6 +395,25 @@ areaNMCheck(tile, arg)
|
||||||
if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop))
|
if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (arg->dCD_entries & TT_DIAGONAL)
|
||||||
|
{
|
||||||
|
TileTypeBitMask mask;
|
||||||
|
int dinfo = arg->dCD_entries;
|
||||||
|
|
||||||
|
/* In the DRC_REVERSE case, the area being searched extends
|
||||||
|
* behind the edge that triggered the DRC check, but any
|
||||||
|
* tile that is outside that edge should be ignored. This
|
||||||
|
* requires a separate check.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TTMaskSetOnlyType(&mask, TiGetLeftType(tile));
|
||||||
|
TTMaskSetType(&mask, TiGetRightType(tile));
|
||||||
|
if (DBSrPaintNMArea((Tile *)tile, (Plane *)NULL,
|
||||||
|
TiGetTypeExact(tile) | dinfo, arg->dCD_rlist,
|
||||||
|
&mask, areaNMReject, (ClientData)tile) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
(*(arg->dCD_function))(arg->dCD_celldef, &rect, arg->dCD_cptr,
|
(*(arg->dCD_function))(arg->dCD_celldef, &rect, arg->dCD_cptr,
|
||||||
arg->dCD_clientData);
|
arg->dCD_clientData);
|
||||||
(*(arg->dCD_errors))++;
|
(*(arg->dCD_errors))++;
|
||||||
|
|
@ -404,12 +498,39 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
||||||
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
||||||
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
||||||
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
||||||
|
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
/* Execute pending Tcl events, so the DRC process doesn't block. */
|
||||||
|
|
||||||
|
/* WARNING: This code cannot be enabled until some method is
|
||||||
|
* worked out to determine if any event resulted in a change
|
||||||
|
* to the DRC check plane which would invalidate the current
|
||||||
|
* search. If so, the search must end immediately and the
|
||||||
|
* area being checked must be reinstated. The code was added
|
||||||
|
* to see how it speeds up the response time of magic when
|
||||||
|
* some of the DRC rules are compute-intensive. It speeds up
|
||||||
|
* performance enough that it is worthwhile to implement the
|
||||||
|
* method just mentioned.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
UndoEnable();
|
||||||
|
while (Tcl_DoOneEvent(TCL_DONT_WAIT));
|
||||||
|
UndoDisable();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
drcCifCheck(&arg);
|
drcCifCheck(&arg);
|
||||||
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
||||||
return (errors);
|
return (errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Expect that keeping around 3 MaxRectsData records should be sufficient
|
||||||
|
* to avoid recomputing drcCanonicalMaxwidth() multiple times. Note that
|
||||||
|
* if a PDK sets up multiple rules on an edge which all require running
|
||||||
|
* drcCanonicalMaxwidth(), then this cache size may need to be revisited.
|
||||||
|
*/
|
||||||
|
#define MAXRECTSCACHE 3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -432,8 +553,9 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcTile (tile, arg)
|
drcTile (tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile being examined */
|
Tile *tile; /* Tile being examined */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
DRCCookie *cptr; /* Current design rule on list */
|
DRCCookie *cptr; /* Current design rule on list */
|
||||||
|
|
@ -446,6 +568,19 @@ drcTile (tile, arg)
|
||||||
int triggered;
|
int triggered;
|
||||||
int cdist, dist, ccdist, result;
|
int cdist, dist, ccdist, result;
|
||||||
|
|
||||||
|
/* Keep up to three MaxRectsData records to avoid doing the same
|
||||||
|
* expensive computation more than once.
|
||||||
|
*
|
||||||
|
* mrdcache[0] will be used for the tpleft tile, since it will never
|
||||||
|
* be reused. mrdcache[1] and mrdcache[2] will be used for the tile
|
||||||
|
* itself. Note that if more than 2 DRCCookie entries for the same
|
||||||
|
* edge require drcCanonicalMaxwidth(), then mrdcache[2] will be
|
||||||
|
* re-used so that at least mrdcache[1] is always a cache hit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static MaxRectsData *mrdcache[MAXRECTSCACHE] = {NULL, NULL, NULL};
|
||||||
|
DRCCookie *cptrcache;
|
||||||
|
|
||||||
arg->dCD_constraint = &errRect;
|
arg->dCD_constraint = &errRect;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -473,7 +608,7 @@ drcTile (tile, arg)
|
||||||
/* DRC searches only one direction on regular tiles, the split */
|
/* DRC searches only one direction on regular tiles, the split */
|
||||||
/* tiles are only processed for one of the two cases. */
|
/* tiles are only processed for one of the two cases. */
|
||||||
|
|
||||||
if (IsSplit(tile) && !SplitSide(tile))
|
if (IsSplit(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
int deltax, deltay;
|
int deltax, deltay;
|
||||||
TileType tt, to;
|
TileType tt, to;
|
||||||
|
|
@ -495,7 +630,7 @@ drcTile (tile, arg)
|
||||||
{
|
{
|
||||||
int deltax, deltay, w, h;
|
int deltax, deltay, w, h;
|
||||||
double r;
|
double r;
|
||||||
TileType dinfo, dsplit;
|
TileType newdinfo, dsplit;
|
||||||
|
|
||||||
/* Work to be done: Handle triggering rules for non-Manhattan */
|
/* Work to be done: Handle triggering rules for non-Manhattan */
|
||||||
/* edges; especially important for the wide-spacing rule. */
|
/* edges; especially important for the wide-spacing rule. */
|
||||||
|
|
@ -545,7 +680,7 @@ drcTile (tile, arg)
|
||||||
|
|
||||||
if (SplitDirection(tile) == 0) deltay = -deltay;
|
if (SplitDirection(tile) == 0) deltay = -deltay;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION);
|
newdinfo = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION);
|
||||||
if (!(cptr->drcc_flags & DRC_REVERSE))
|
if (!(cptr->drcc_flags & DRC_REVERSE))
|
||||||
{
|
{
|
||||||
/* Forward case is behind the triangle */
|
/* Forward case is behind the triangle */
|
||||||
|
|
@ -553,9 +688,23 @@ drcTile (tile, arg)
|
||||||
deltay = -deltay;
|
deltay = -deltay;
|
||||||
|
|
||||||
/* Split side changes in the reverse case */
|
/* Split side changes in the reverse case */
|
||||||
dinfo |= TT_SIDE;
|
newdinfo |= TT_SIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The area to check is bounded between the diagonals of
|
||||||
|
* tile and errRect (which is the tile area, offset).
|
||||||
|
* Pass errRect and newdinfo to areaNMCheck using the
|
||||||
|
* ClientData structure arg->dCD_rlist and arg->dCD_entries,
|
||||||
|
* which are not used by areaNMCheck.
|
||||||
|
*/
|
||||||
|
arg->dCD_rlist = (Rect *)mallocMagic(sizeof(Rect));
|
||||||
|
*(arg->dCD_rlist) = errRect;
|
||||||
|
arg->dCD_entries = newdinfo;
|
||||||
|
if (newdinfo & TT_SIDE)
|
||||||
|
arg->dCD_entries &= ~TT_SIDE;
|
||||||
|
else
|
||||||
|
arg->dCD_entries |= TT_SIDE;
|
||||||
|
|
||||||
/* errRect is the tile area offset by (deltax, deltay) */
|
/* errRect is the tile area offset by (deltax, deltay) */
|
||||||
errRect.r_xbot += deltax;
|
errRect.r_xbot += deltax;
|
||||||
errRect.r_ybot += deltay;
|
errRect.r_ybot += deltay;
|
||||||
|
|
@ -563,12 +712,18 @@ drcTile (tile, arg)
|
||||||
errRect.r_ytop += deltay;
|
errRect.r_ytop += deltay;
|
||||||
|
|
||||||
DBSrPaintNMArea((Tile *) NULL,
|
DBSrPaintNMArea((Tile *) NULL,
|
||||||
arg->dCD_celldef->cd_planes[cptr->drcc_plane], dinfo,
|
arg->dCD_celldef->cd_planes[cptr->drcc_plane], newdinfo,
|
||||||
&errRect, &tmpMask, areaNMCheck, (ClientData) arg);
|
&errRect, &tmpMask, areaNMCheck, (ClientData) arg);
|
||||||
|
|
||||||
|
arg->dCD_entries = 0;
|
||||||
|
freeMagic(arg->dCD_rlist);
|
||||||
|
arg->dCD_rlist = (Rect *)NULL;
|
||||||
}
|
}
|
||||||
DRCstatEdges++;
|
DRCstatEdges++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cptrcache = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check design rules along a vertical boundary between two tiles.
|
* Check design rules along a vertical boundary between two tiles.
|
||||||
*
|
*
|
||||||
|
|
@ -613,7 +768,6 @@ drcTile (tile, arg)
|
||||||
int edgeX = LEFT(tile);
|
int edgeX = LEFT(tile);
|
||||||
|
|
||||||
firsttile = TRUE;
|
firsttile = TRUE;
|
||||||
mrd = NULL;
|
|
||||||
for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft))
|
for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft))
|
||||||
{
|
{
|
||||||
/* Get the tile types to the left and right of the edge */
|
/* Get the tile types to the left and right of the edge */
|
||||||
|
|
@ -644,6 +798,44 @@ drcTile (tile, arg)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
|
/* Handle rule exceptions and exemptions */
|
||||||
|
if (cptr->drcc_exception != DRC_EXCEPTION_NONE)
|
||||||
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool propfound, isinside = FALSE;
|
||||||
|
char *name;
|
||||||
|
int idx = cptr->drcc_exception & ~DRC_EXCEPTION_MASK;
|
||||||
|
name = DRCCurStyle->DRCExceptionList[idx];
|
||||||
|
|
||||||
|
/* Is there any exception area defined? */
|
||||||
|
proprec = DBPropGet(arg->dCD_celldef, name, &propfound);
|
||||||
|
|
||||||
|
/* If an exception area exists, is the error edge inside? */
|
||||||
|
if (propfound)
|
||||||
|
{
|
||||||
|
Rect redge;
|
||||||
|
|
||||||
|
redge.r_xbot = redge.r_xtop = edgeX;
|
||||||
|
redge.r_ybot = edgeBot;
|
||||||
|
redge.r_ytop = edgeTop;
|
||||||
|
|
||||||
|
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&redge, &CIFSolidBits, drcFoundOneFunc,
|
||||||
|
(ClientData)NULL) == 1)
|
||||||
|
isinside = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exemption rules are ignored if the edge is inside
|
||||||
|
* an exception area. Exception rules are ignored if
|
||||||
|
* the edge is outside an exception area.
|
||||||
|
*/
|
||||||
|
if (!isinside && (!(cptr->drcc_exception & DRC_EXCEPTION_MASK) == 0))
|
||||||
|
continue;
|
||||||
|
if (isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) != 0))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||||
/* the code above for non-Manhattan shapes and do not */
|
/* the code above for non-Manhattan shapes and do not */
|
||||||
/* need to be processed again. */
|
/* need to be processed again. */
|
||||||
|
|
@ -665,6 +857,7 @@ drcTile (tile, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
DRCstatRules++;
|
DRCstatRules++;
|
||||||
|
if (!triggered) mrd = NULL;
|
||||||
|
|
||||||
if (cptr->drcc_flags & DRC_AREA)
|
if (cptr->drcc_flags & DRC_AREA)
|
||||||
{
|
{
|
||||||
|
|
@ -686,12 +879,23 @@ drcTile (tile, arg)
|
||||||
|
|
||||||
if (cptr->drcc_flags & DRC_REVERSE)
|
if (cptr->drcc_flags & DRC_REVERSE)
|
||||||
{
|
{
|
||||||
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr);
|
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr,
|
||||||
|
&mrdcache[0]);
|
||||||
triggered = 0;
|
triggered = 0;
|
||||||
}
|
}
|
||||||
else if (firsttile)
|
else
|
||||||
{
|
{
|
||||||
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
|
if (cptrcache == NULL)
|
||||||
|
{
|
||||||
|
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr,
|
||||||
|
&mrdcache[1]);
|
||||||
|
cptrcache = cptr;
|
||||||
|
}
|
||||||
|
else if (cptrcache != cptr)
|
||||||
|
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr,
|
||||||
|
&mrdcache[2]);
|
||||||
|
else
|
||||||
|
mrd = (mrdcache[1]->entries == 0) ? NULL : mrdcache[1];
|
||||||
triggered = 0;
|
triggered = 0;
|
||||||
}
|
}
|
||||||
if (!trigpending || (DRCCurStyle->DRCFlags
|
if (!trigpending || (DRCCurStyle->DRCFlags
|
||||||
|
|
@ -982,6 +1186,8 @@ drcTile (tile, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cptrcache = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check design rules along a horizontal boundary between two tiles.
|
* Check design rules along a horizontal boundary between two tiles.
|
||||||
*
|
*
|
||||||
|
|
@ -1021,7 +1227,6 @@ drcTile (tile, arg)
|
||||||
|
|
||||||
/* Go right across bottom of tile */
|
/* Go right across bottom of tile */
|
||||||
firsttile = TRUE;
|
firsttile = TRUE;
|
||||||
mrd = NULL;
|
|
||||||
for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot))
|
for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot))
|
||||||
{
|
{
|
||||||
/* Get the tile types to the top and bottom of the edge */
|
/* Get the tile types to the top and bottom of the edge */
|
||||||
|
|
@ -1053,6 +1258,44 @@ drcTile (tile, arg)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
|
/* Handle rule exceptions and exemptions */
|
||||||
|
if (cptr->drcc_exception != DRC_EXCEPTION_NONE)
|
||||||
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool propfound, isinside = FALSE;
|
||||||
|
char *name;
|
||||||
|
int idx = cptr->drcc_exception & ~DRC_EXCEPTION_MASK;
|
||||||
|
name = DRCCurStyle->DRCExceptionList[idx];
|
||||||
|
|
||||||
|
/* Is there any exception area defined? */
|
||||||
|
proprec = DBPropGet(arg->dCD_celldef, name, &propfound);
|
||||||
|
|
||||||
|
/* If an exception area exists, is the error edge inside? */
|
||||||
|
if (propfound)
|
||||||
|
{
|
||||||
|
Rect redge;
|
||||||
|
|
||||||
|
redge.r_ybot = redge.r_ytop = edgeY;
|
||||||
|
redge.r_xbot = edgeLeft;
|
||||||
|
redge.r_xtop = edgeRight;
|
||||||
|
|
||||||
|
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&redge, &CIFSolidBits, drcFoundOneFunc,
|
||||||
|
(ClientData)NULL) == 1)
|
||||||
|
isinside = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exemption rules are ignored if the edge is inside
|
||||||
|
* an exception area. Exception rules are ignored if
|
||||||
|
* the edge is outside an exception area.
|
||||||
|
*/
|
||||||
|
if (!isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) == 0))
|
||||||
|
continue;
|
||||||
|
if (isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) != 0))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||||
/* the code above for non-Manhattan shapes and do not */
|
/* the code above for non-Manhattan shapes and do not */
|
||||||
/* need to be processed again. */
|
/* need to be processed again. */
|
||||||
|
|
@ -1074,6 +1317,7 @@ drcTile (tile, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
DRCstatRules++;
|
DRCstatRules++;
|
||||||
|
if (!triggered) mrd = NULL;
|
||||||
|
|
||||||
/* top to bottom */
|
/* top to bottom */
|
||||||
|
|
||||||
|
|
@ -1090,12 +1334,23 @@ drcTile (tile, arg)
|
||||||
|
|
||||||
if (cptr->drcc_flags & DRC_REVERSE)
|
if (cptr->drcc_flags & DRC_REVERSE)
|
||||||
{
|
{
|
||||||
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr);
|
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr,
|
||||||
|
&mrdcache[0]);
|
||||||
triggered = 0;
|
triggered = 0;
|
||||||
}
|
}
|
||||||
else if (firsttile)
|
else
|
||||||
{
|
{
|
||||||
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
|
if (cptrcache == NULL)
|
||||||
|
{
|
||||||
|
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr,
|
||||||
|
&mrdcache[1]);
|
||||||
|
cptrcache = cptr;
|
||||||
|
}
|
||||||
|
else if (cptrcache != cptr)
|
||||||
|
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr,
|
||||||
|
&mrdcache[2]);
|
||||||
|
else
|
||||||
|
mrd = (mrdcache[1]->entries == 0) ? NULL : mrdcache[1];
|
||||||
triggered = 0;
|
triggered = 0;
|
||||||
}
|
}
|
||||||
if (!trigpending || (DRCCurStyle->DRCFlags
|
if (!trigpending || (DRCCurStyle->DRCFlags
|
||||||
|
|
@ -1135,7 +1390,7 @@ drcTile (tile, arg)
|
||||||
lr = &mrd->rlist[i];
|
lr = &mrd->rlist[i];
|
||||||
GeoClip(lr, arg->dCD_clip);
|
GeoClip(lr, arg->dCD_clip);
|
||||||
if (!GEO_RECTNULL(lr))
|
if (!GEO_RECTNULL(lr))
|
||||||
{
|
{
|
||||||
(*(arg->dCD_function)) (arg->dCD_celldef,
|
(*(arg->dCD_function)) (arg->dCD_celldef,
|
||||||
lr, cptr, arg->dCD_clientData);
|
lr, cptr, arg->dCD_clientData);
|
||||||
(*(arg->dCD_errors))++;
|
(*(arg->dCD_errors))++;
|
||||||
|
|
|
||||||
20
drc/DRCcif.c
20
drc/DRCcif.c
|
|
@ -603,8 +603,9 @@ drcCifCheck(arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCifTile (tile, arg)
|
drcCifTile (tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile being examined */
|
Tile *tile; /* Tile being examined */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
DRCCookie *cptr; /* Current design rule on list */
|
DRCCookie *cptr; /* Current design rule on list */
|
||||||
|
|
@ -628,7 +629,7 @@ drcCifTile (tile, arg)
|
||||||
/* check. */
|
/* check. */
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
goto tbcheck;
|
goto tbcheck;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -826,7 +827,7 @@ tbcheck:
|
||||||
/* bottom check. */
|
/* bottom check. */
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
if (SplitSide(tile) == SplitDirection(tile))
|
if (((dinfo & TT_SIDE) ? 1 : 0) == SplitDirection(tile))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1031,8 +1032,9 @@ tbcheck:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaCifCheck(tile, arg)
|
areaCifCheck(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
Rect rect; /* Area where error is to be recorded. */
|
Rect rect; /* Area where error is to be recorded. */
|
||||||
|
|
@ -1085,7 +1087,7 @@ areaCifCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -1100,7 +1102,7 @@ areaCifCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -1116,7 +1118,7 @@ areaCifCheck(tile, arg)
|
||||||
+ sdist - cifrect.r_ytop) >= 0)
|
+ sdist - cifrect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
@ -1132,7 +1134,7 @@ areaCifCheck(tile, arg)
|
||||||
+ sdist - cifrect.r_ytop) >= 0)
|
+ sdist - cifrect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
|
||||||
|
|
@ -203,13 +203,12 @@ DRCCheckThis (celldef, operation, area)
|
||||||
/* Insert celldef into list of Defs waiting to be checked, unless */
|
/* Insert celldef into list of Defs waiting to be checked, unless */
|
||||||
/* it is already there. */
|
/* it is already there. */
|
||||||
|
|
||||||
#if (0)
|
|
||||||
|
|
||||||
/* The switch to copying up DRC errors from non-interacting */
|
/* The switch to copying up DRC errors from non-interacting */
|
||||||
/* child cells means that the child cells must be processed */
|
/* child cells means that the child cells must be processed */
|
||||||
/* first. So this routine changes from prepending the cell */
|
/* first. So this routine changes from prepending the cell */
|
||||||
/* to the list to appending it. */
|
/* to the list to appending it. */
|
||||||
|
|
||||||
|
#if (0)
|
||||||
pback = &DRCPendingRoot;
|
pback = &DRCPendingRoot;
|
||||||
p = DRCPendingRoot;
|
p = DRCPendingRoot;
|
||||||
|
|
||||||
|
|
@ -230,8 +229,8 @@ DRCCheckThis (celldef, operation, area)
|
||||||
}
|
}
|
||||||
p->dpc_next = DRCPendingRoot;
|
p->dpc_next = DRCPendingRoot;
|
||||||
DRCPendingRoot = p;
|
DRCPendingRoot = p;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Append new cell to check to the pending list */
|
/* Append new cell to check to the pending list */
|
||||||
if (DRCPendingRoot == NULL)
|
if (DRCPendingRoot == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -548,8 +547,10 @@ DRCContinuous()
|
||||||
|
|
||||||
if (DRCPendingRoot != (DRCPendingCookie *)NULL) {
|
if (DRCPendingRoot != (DRCPendingCookie *)NULL) {
|
||||||
DBReComputeBbox(DRCPendingRoot->dpc_def);
|
DBReComputeBbox(DRCPendingRoot->dpc_def);
|
||||||
freeMagic((char *) DRCPendingRoot);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, (char *) DRCPendingRoot);
|
||||||
DRCPendingRoot = DRCPendingRoot->dpc_next;
|
DRCPendingRoot = DRCPendingRoot->dpc_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give the timestamp manager a chance to update any mismatches. */
|
/* Give the timestamp manager a chance to update any mismatches. */
|
||||||
|
|
@ -638,9 +639,10 @@ checkDone:
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
drcCheckTile(tile, arg)
|
drcCheckTile(tile, dinfo, arg)
|
||||||
Tile * tile; /* tile in DRC_CHECK plane */
|
Tile *tile; /* Tile in DRC_CHECK plane */
|
||||||
ClientData arg; /* Not used. */
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
|
ClientData arg; /* Not used. */
|
||||||
{
|
{
|
||||||
Rect square; /* Square area of the checkerboard
|
Rect square; /* Square area of the checkerboard
|
||||||
* being processed right now.
|
* being processed right now.
|
||||||
|
|
@ -766,13 +768,15 @@ drcCheckTile(tile, arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcXorFunc(tile)
|
drcXorFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
|
ClientData clientdata;
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
DBPaintPlane(drcDisplayPlane, &area, drcXorTable, (PaintUndoInfo *) NULL);
|
DBNMPaintPlane(drcDisplayPlane, dinfo, &area, drcXorTable, (PaintUndoInfo *) NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -781,14 +785,15 @@ drcXorFunc(tile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcPutBackFunc(tile, cellDef)
|
drcPutBackFunc(tile, dinfo, cellDef)
|
||||||
Tile *tile; /* Error tile, from drcTempPlane. */
|
Tile *tile; /* Error tile, from drcTempPlane. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
CellDef *cellDef; /* Celldef in which to paint error. */
|
CellDef *cellDef; /* Celldef in which to paint error. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
DBPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], &area,
|
DBNMPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], dinfo, &area,
|
||||||
DBStdPaintTbl(TiGetType(tile), PL_DRC_ERROR),
|
DBStdPaintTbl(TiGetType(tile), PL_DRC_ERROR),
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -815,8 +820,9 @@ drcPutBackFunc(tile, cellDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcIncludeArea(tile, rect)
|
drcIncludeArea(tile, dinfo, rect)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
Rect *rect; /* Rectangle in which to record total area. */
|
Rect *rect; /* Rectangle in which to record total area. */
|
||||||
{
|
{
|
||||||
Rect dum;
|
Rect dum;
|
||||||
|
|
|
||||||
|
|
@ -449,6 +449,32 @@ drcCheckRectSize(starttile, arg, cptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* MaxRectsExclude ---
|
||||||
|
*
|
||||||
|
* Trivial callback function which detects if a type is found
|
||||||
|
* overlapping a Maxrects area.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Always return 1 to immediately halt the search.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
MaxRectsExclude(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -484,16 +510,17 @@ drcCheckRectSize(starttile, arg, cptr)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MaxRectsData *
|
MaxRectsData *
|
||||||
drcCanonicalMaxwidth(starttile, dir, arg, cptr)
|
drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr)
|
||||||
Tile *starttile;
|
Tile *starttile;
|
||||||
int dir; /* direction of rule */
|
int dir; /* direction of rule */
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
DRCCookie *cptr;
|
DRCCookie *cptr;
|
||||||
|
MaxRectsData **mrdptr;
|
||||||
{
|
{
|
||||||
int s, edgelimit;
|
int s, edgelimit;
|
||||||
Tile *tile,*tp;
|
Tile *tile,*tp;
|
||||||
TileTypeBitMask wrongtypes;
|
TileTypeBitMask wrongtypes;
|
||||||
static MaxRectsData *mrd = (MaxRectsData *)NULL;
|
MaxRectsData *mrd = *mrdptr;
|
||||||
Rect *boundrect, boundorig;
|
Rect *boundrect, boundorig;
|
||||||
|
|
||||||
/* Generate an initial array size of 8 for rlist and swap. */
|
/* Generate an initial array size of 8 for rlist and swap. */
|
||||||
|
|
@ -503,6 +530,7 @@ drcCanonicalMaxwidth(starttile, dir, arg, cptr)
|
||||||
mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect));
|
mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect));
|
||||||
mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect));
|
mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect));
|
||||||
mrd->listdepth = 8;
|
mrd->listdepth = 8;
|
||||||
|
*mrdptr = mrd;
|
||||||
}
|
}
|
||||||
if (starttile == NULL) return mrd;
|
if (starttile == NULL) return mrd;
|
||||||
|
|
||||||
|
|
@ -563,10 +591,31 @@ drcCanonicalMaxwidth(starttile, dir, arg, cptr)
|
||||||
mrd->maxdist = edgelimit;
|
mrd->maxdist = edgelimit;
|
||||||
TTMaskCom2(&wrongtypes, &cptr->drcc_mask);
|
TTMaskCom2(&wrongtypes, &cptr->drcc_mask);
|
||||||
boundorig = *boundrect;
|
boundorig = *boundrect;
|
||||||
DBSrPaintArea(starttile, arg->dCD_celldef->cd_planes[cptr->drcc_plane],
|
DBSrPaintArea(starttile, arg->dCD_celldef->cd_planes[cptr->drcc_edgeplane],
|
||||||
&boundorig, &wrongtypes, FindMaxRects, mrd);
|
&boundorig, &wrongtypes, FindMaxRects, mrd);
|
||||||
if (mrd->entries == 0)
|
if (mrd->entries == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
else if (cptr->drcc_plane != cptr->drcc_edgeplane)
|
||||||
|
{
|
||||||
|
/* If the "exclude" option is used, then the maxrect rule will be
|
||||||
|
* ignored for any metal area partially or totally covered by any
|
||||||
|
* type in cptr->drcc_corner on plane cptr->drcc_plane (!=
|
||||||
|
* cptr->drcc_edgeplane).
|
||||||
|
*/
|
||||||
|
for (s = 0; s < mrd->entries; s++)
|
||||||
|
{
|
||||||
|
Rect *r = &(mrd->rlist[s]);
|
||||||
|
if (DBSrPaintArea((Tile *)NULL,
|
||||||
|
arg->dCD_celldef->cd_planes[cptr->drcc_plane],
|
||||||
|
r, &cptr->drcc_corner, MaxRectsExclude, NULL) != 0)
|
||||||
|
{
|
||||||
|
/* Take this area out of consideration */
|
||||||
|
r->r_xtop = r->r_xbot;
|
||||||
|
r->r_ytop = r->r_ybot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (MaxRectsData *)mrd;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return (MaxRectsData *)mrd;
|
return (MaxRectsData *)mrd;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
199
drc/DRCmain.c
199
drc/DRCmain.c
|
|
@ -184,9 +184,9 @@ drcSubstitute (cptr)
|
||||||
DRCCookie * cptr; /* Design rule violated */
|
DRCCookie * cptr; /* Design rule violated */
|
||||||
{
|
{
|
||||||
static char *why_out = NULL;
|
static char *why_out = NULL;
|
||||||
char *whyptr, *sptr, *wptr;
|
char *whyptr, *sptr, *wptr, *vptr;
|
||||||
int subscnt = 0, whylen;
|
int subscnt = 0, whylen, saveunits;
|
||||||
float oscale, value;
|
float value;
|
||||||
extern float CIFGetOutputScale();
|
extern float CIFGetOutputScale();
|
||||||
|
|
||||||
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
||||||
|
|
@ -203,10 +203,14 @@ drcSubstitute (cptr)
|
||||||
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
||||||
strcpy(why_out, whyptr);
|
strcpy(why_out, whyptr);
|
||||||
|
|
||||||
if (cptr->drcc_flags & DRC_CIFRULE)
|
/* For backwards compatibility: If the units are set to "default",
|
||||||
oscale = CIFGetScale(100); /* 100 = microns to centimicrons */
|
* then print the DRC value in microns, with units, which is how
|
||||||
else
|
* the output was previously presented.
|
||||||
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
*/
|
||||||
|
saveunits = DBWUnits;
|
||||||
|
if (saveunits == DBW_UNITS_DEFAULT)
|
||||||
|
DBWUnits = DBW_UNITS_MICRONS | DBW_UNITS_PRINT_FLAG;
|
||||||
|
|
||||||
wptr = why_out;
|
wptr = why_out;
|
||||||
|
|
||||||
while ((sptr = strchr(whyptr, '%')) != NULL)
|
while ((sptr = strchr(whyptr, '%')) != NULL)
|
||||||
|
|
@ -218,21 +222,29 @@ drcSubstitute (cptr)
|
||||||
switch (*(sptr + 1))
|
switch (*(sptr + 1))
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
/* Replace with "dist" value in microns */
|
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||||
value = (float)cptr->drcc_dist * oscale;
|
vptr = DBWPrintCIFValue(cptr->drcc_dist, (MagWindow *)NULL, TRUE);
|
||||||
snprintf(wptr, 20, "%01.3gum", value);
|
else
|
||||||
|
vptr = DBWPrintValue(cptr->drcc_dist, (MagWindow *)NULL, TRUE);
|
||||||
|
snprintf(wptr, 20, "%s", vptr);
|
||||||
wptr += strlen(wptr);
|
wptr += strlen(wptr);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Replace with "cdist" value in microns */
|
/* Replace with "cdist" value in microns */
|
||||||
value = (float)cptr->drcc_cdist * oscale;
|
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||||
snprintf(wptr, 20, "%01.3gum", value);
|
vptr = DBWPrintCIFValue(cptr->drcc_cdist, (MagWindow *)NULL, TRUE);
|
||||||
|
else
|
||||||
|
vptr = DBWPrintValue(cptr->drcc_cdist, (MagWindow *)NULL, TRUE);
|
||||||
|
snprintf(wptr, 20, "%s", vptr);
|
||||||
wptr += strlen(wptr);
|
wptr += strlen(wptr);
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
/* Replace with "cdist" value in microns squared */
|
/* Replace with "cdist" value in microns squared */
|
||||||
value = (float)cptr->drcc_cdist * oscale * oscale;
|
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||||
snprintf(wptr, 20, "%01.4gum^2", value);
|
vptr = DBWPrintCIFSqValue(cptr->drcc_cdist, (MagWindow *)NULL);
|
||||||
|
else
|
||||||
|
vptr = DBWPrintSqValue(cptr->drcc_cdist, (MagWindow *)NULL);
|
||||||
|
snprintf(wptr, 20, "%s", vptr);
|
||||||
wptr += strlen(wptr);
|
wptr += strlen(wptr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -245,6 +257,7 @@ drcSubstitute (cptr)
|
||||||
/* copy remainder of string (including trailing null) */
|
/* copy remainder of string (including trailing null) */
|
||||||
strncpy(wptr, whyptr, strlen(whyptr) + 1);
|
strncpy(wptr, whyptr, strlen(whyptr) + 1);
|
||||||
|
|
||||||
|
DBWUnits = saveunits;
|
||||||
return why_out;
|
return why_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,20 +290,50 @@ drcPrintError (celldef, rect, cptr, scx)
|
||||||
{
|
{
|
||||||
HashEntry *h;
|
HashEntry *h;
|
||||||
int i;
|
int i;
|
||||||
Rect *area, r;
|
Rect *area;
|
||||||
|
int drcsave = DRCErrorCount;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
void drcWhyFunc(SearchContext *scx, ClientData cdarg);
|
||||||
|
|
||||||
ASSERT (cptr != (DRCCookie *) NULL, "drcPrintError");
|
ASSERT (cptr != (DRCCookie *) NULL, "drcPrintError");
|
||||||
|
|
||||||
area = &scx->scx_area;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
|
|
||||||
i = DRCErrorList[cptr->drcc_tag];
|
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
|
||||||
if (i == 0)
|
|
||||||
TxPrintf("%s\n", drcSubstitute(cptr));
|
|
||||||
if (i >= 0)
|
|
||||||
{
|
{
|
||||||
DRCErrorCount += 1;
|
SearchContext newscx;
|
||||||
DRCErrorList[cptr->drcc_tag] = i + 1;
|
|
||||||
|
/* Recurse into subcells to find the error being flagged */
|
||||||
|
/* recursive call is drcWhyFunc, clientdata is FALSE */
|
||||||
|
|
||||||
|
newscx.scx_area = *rect;
|
||||||
|
newscx.scx_use = scx->scx_use;
|
||||||
|
newscx.scx_x = scx->scx_use->cu_xlo;
|
||||||
|
newscx.scx_y = scx->scx_use->cu_ylo;
|
||||||
|
newscx.scx_trans = scx->scx_trans;
|
||||||
|
|
||||||
|
DBTreeSrCells(&newscx, 0, drcWhyFunc, (ClientData)FALSE);
|
||||||
|
}
|
||||||
|
/* Hack to avoid printing "no errors found" when recursing on
|
||||||
|
* drcWhyFunc() above. In some cases like run-length rules,
|
||||||
|
* changing the search area can make the error disappear. If
|
||||||
|
* that happens, "See error definition in subcell" will be
|
||||||
|
* printed. The underlying error needs to be fixed, but this
|
||||||
|
* method provides the information the user needs to find the
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
if (drcsave == DRCErrorCount)
|
||||||
|
{
|
||||||
|
i = DRCErrorList[cptr->drcc_tag];
|
||||||
|
if (i == 0)
|
||||||
|
TxPrintf("%s\n", drcSubstitute(cptr));
|
||||||
|
if (i >= 0)
|
||||||
|
{
|
||||||
|
DRCErrorCount += 1;
|
||||||
|
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,24 +352,47 @@ drcListError (celldef, rect, cptr, scx)
|
||||||
HashEntry *h;
|
HashEntry *h;
|
||||||
int i;
|
int i;
|
||||||
Rect *area;
|
Rect *area;
|
||||||
|
int drcsave = DRCErrorCount;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
void drcWhyFunc(SearchContext *scx, ClientData cdarg);
|
||||||
|
|
||||||
ASSERT (cptr != (DRCCookie *) NULL, "drcListError");
|
ASSERT (cptr != (DRCCookie *) NULL, "drcListError");
|
||||||
|
|
||||||
area = &scx->scx_area;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
i = DRCErrorList[cptr->drcc_tag];
|
|
||||||
if (i == 0)
|
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
|
||||||
{
|
{
|
||||||
Tcl_Obj *lobj;
|
SearchContext newscx;
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
/* Recurse into subcells to find the error being flagged */
|
||||||
Tcl_NewStringObj(drcSubstitute(cptr), -1));
|
/* recursive call is drcWhyFunc, clientdata is TRUE */
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
|
||||||
|
newscx.scx_area = *rect;
|
||||||
|
newscx.scx_use = scx->scx_use;
|
||||||
|
newscx.scx_x = scx->scx_use->cu_xlo;
|
||||||
|
newscx.scx_y = scx->scx_use->cu_ylo;
|
||||||
|
newscx.scx_trans = scx->scx_trans;
|
||||||
|
|
||||||
|
DBTreeSrCells(&newscx, 0, drcWhyFunc, (ClientData)TRUE);
|
||||||
}
|
}
|
||||||
if (i >= 0)
|
if (drcsave == DRCErrorCount)
|
||||||
{
|
{
|
||||||
DRCErrorCount += 1;
|
i = DRCErrorList[cptr->drcc_tag];
|
||||||
DRCErrorList[cptr->drcc_tag] = i + 1;
|
if (i == 0)
|
||||||
|
{
|
||||||
|
Tcl_Obj *lobj;
|
||||||
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(drcSubstitute(cptr), -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
|
}
|
||||||
|
if (i >= 0)
|
||||||
|
{
|
||||||
|
DRCErrorCount += 1;
|
||||||
|
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,6 +409,10 @@ drcListallError (celldef, rect, cptr, scx)
|
||||||
Tcl_Obj *lobj, *pobj;
|
Tcl_Obj *lobj, *pobj;
|
||||||
HashEntry *h;
|
HashEntry *h;
|
||||||
Rect *area, r;
|
Rect *area, r;
|
||||||
|
int drcsave = DRCErrorCount;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int drcWhyAllFunc(SearchContext *scx, ClientData cdarg);
|
||||||
|
|
||||||
ASSERT (cptr != (DRCCookie *) NULL, "drcListallError");
|
ASSERT (cptr != (DRCCookie *) NULL, "drcListallError");
|
||||||
|
|
||||||
|
|
@ -350,21 +420,47 @@ drcListallError (celldef, rect, cptr, scx)
|
||||||
GeoTransRect(&scx->scx_trans, rect, &r);
|
GeoTransRect(&scx->scx_trans, rect, &r);
|
||||||
area = &scx->scx_area;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
DRCErrorCount += 1;
|
|
||||||
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
|
||||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
|
||||||
if (lobj == NULL)
|
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
|
||||||
|
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
|
||||||
|
{
|
||||||
|
SearchContext newscx;
|
||||||
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xbot));
|
/* Recurse into subcells to find the error being flagged */
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ybot));
|
/* recursive call is drcWhyAllFunc, clientdata is NULL */
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xtop));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ytop));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
|
||||||
|
|
||||||
HashSetValue(h, lobj);
|
newscx.scx_area = *rect;
|
||||||
|
newscx.scx_use = scx->scx_use;
|
||||||
|
newscx.scx_x = scx->scx_use->cu_xlo;
|
||||||
|
newscx.scx_y = scx->scx_use->cu_ylo;
|
||||||
|
newscx.scx_trans = scx->scx_trans;
|
||||||
|
|
||||||
|
DBTreeSrCells(&newscx, 0, drcWhyAllFunc, (ClientData)NULL);
|
||||||
|
}
|
||||||
|
if (drcsave == DRCErrorCount)
|
||||||
|
{
|
||||||
|
char *rllx, *rlly, *rurx, *rury;
|
||||||
|
|
||||||
|
DRCErrorCount += 1;
|
||||||
|
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||||
|
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||||
|
if (lobj == NULL)
|
||||||
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
|
|
||||||
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
|
|
||||||
|
rllx = DBWPrintValue(r.r_xbot, (MagWindow *)NULL, TRUE);
|
||||||
|
rlly = DBWPrintValue(r.r_ybot, (MagWindow *)NULL, FALSE);
|
||||||
|
rurx = DBWPrintValue(r.r_xtop, (MagWindow *)NULL, TRUE);
|
||||||
|
rury = DBWPrintValue(r.r_ytop, (MagWindow *)NULL, FALSE);
|
||||||
|
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rllx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rlly, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rurx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rury, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||||
|
|
||||||
|
HashSetValue(h, lobj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
@ -737,11 +833,12 @@ drcCheckFunc(scx, cdarg)
|
||||||
DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK),
|
DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK),
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
|
|
||||||
DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL);
|
/* Search children and apply recursively */
|
||||||
|
|
||||||
/* Search children */
|
|
||||||
(void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL);
|
(void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL);
|
||||||
|
|
||||||
|
/* Then do self */
|
||||||
|
DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL);
|
||||||
|
|
||||||
/* As a special performance hack, if the complete cell area is
|
/* As a special performance hack, if the complete cell area is
|
||||||
* handled here, don't bother to look at any more array elements.
|
* handled here, don't bother to look at any more array elements.
|
||||||
*/
|
*/
|
||||||
|
|
@ -880,9 +977,10 @@ drcCountFunc(scx, dupTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCountFunc2(tile, countptr)
|
drcCountFunc2(tile, dinfo, countptr)
|
||||||
Tile *tile; /* Tile found in error plane. */
|
Tile *tile; /* Tile found in error plane. */
|
||||||
int *countptr; /* Address of count word. */
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
|
int *countptr; /* Address of count word. */
|
||||||
{
|
{
|
||||||
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1029,8 +1127,9 @@ drcFindFunc(scx, finddata)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcFindFunc2(tile, finddata)
|
drcFindFunc2(tile, dinfo, finddata)
|
||||||
Tile *tile; /* Tile in error plane. */
|
Tile *tile; /* Tile in error plane. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
Sindx *finddata; /* Information about error to find */
|
Sindx *finddata; /* Information about error to find */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "drc/drc.h"
|
#include "drc/drc.h"
|
||||||
|
|
||||||
extern char *maskToPrint();
|
extern char *maskToPrint();
|
||||||
extern char *DBTypeShortName();
|
extern const char *DBTypeShortName(TileType type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
231
drc/DRCsubcell.c
231
drc/DRCsubcell.c
|
|
@ -27,6 +27,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/signals.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
|
|
@ -36,18 +38,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
|
|
||||||
/* The variables below are made owns so that they can be used to
|
/* The variables below are made global so that they can be used to
|
||||||
* pass information to the various search functions.
|
* pass information to the various search functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static Rect drcSubIntArea; /* Accumulates area of interactions. */
|
static void (*drcSubFunc)(); /* Error function. */
|
||||||
static CellDef *drcSubDef; /* Cell definition we're checking. */
|
static ClientData drcSubClientData; /* To be passed to error function. */
|
||||||
static int drcSubRadius; /* Interaction radius. */
|
|
||||||
static CellUse *drcCurSub; /* Holds current use while searching for interactions */
|
|
||||||
static Rect drcSubLookArea; /* Area where we're looking for interactions */
|
|
||||||
static void (*drcSubFunc)(); /* Error function. */
|
|
||||||
static ClientData drcSubClientData;
|
|
||||||
/* To be passed to error function. */
|
|
||||||
|
|
||||||
/* The cookie below is dummied up to provide an error message for
|
/* The cookie below is dummied up to provide an error message for
|
||||||
* errors that occur because of inexact overlaps between subcells.
|
* errors that occur because of inexact overlaps between subcells.
|
||||||
|
|
@ -56,7 +52,7 @@ static ClientData drcSubClientData;
|
||||||
static DRCCookie drcSubcellCookie = {
|
static DRCCookie drcSubcellCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_SUBCELL_OVERLAP_TAG,
|
DRC_SUBCELL_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -69,7 +65,7 @@ static DRCCookie drcSubcellCookie = {
|
||||||
static DRCCookie drcInSubCookie = {
|
static DRCCookie drcInSubCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_IN_SUBCELL_TAG,
|
DRC_IN_SUBCELL_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -83,7 +79,7 @@ static DRCCookie drcInSubCookie = {
|
||||||
static DRCCookie drcOffGridCookie = {
|
static DRCCookie drcOffGridCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_OFFGRID_TAG,
|
DRC_OFFGRID_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -91,6 +87,28 @@ static DRCCookie drcOffGridCookie = {
|
||||||
extern int DRCErrorType;
|
extern int DRCErrorType;
|
||||||
extern CellDef *DRCErrorDef;
|
extern CellDef *DRCErrorDef;
|
||||||
|
|
||||||
|
/* Structure used to hold information about child uses found in the
|
||||||
|
* search area during DRCFindInteractions(), so these can be
|
||||||
|
* subsequently searched for sibling interactions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct drcLinkedUse {
|
||||||
|
CellUse *dlu_use; // Use being checked
|
||||||
|
Rect dlu_area; // Area of use to check (w/halo)
|
||||||
|
struct drcLinkedUse *dlu_next; // For linked list
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Structure used to pass information to and from drcSubcellFunc() */
|
||||||
|
|
||||||
|
struct drcSubcellArg {
|
||||||
|
CellDef *dsa_def; /* Cell use being checked */
|
||||||
|
int dsa_radius; /* Halo radius around area to check */
|
||||||
|
Rect *dsa_searchArea; /* Area of cell use being searched */
|
||||||
|
Rect *dsa_intArea; /* Total interaction area */
|
||||||
|
bool dsa_found; /* At least one interacting cell was found */
|
||||||
|
struct drcLinkedUse *dsa_dlu;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -112,12 +130,12 @@ extern CellDef *DRCErrorDef;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcFindOtherCells(use, area)
|
drcFindOtherCells(use, dlu)
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
Rect *area;
|
struct drcLinkedUse *dlu;
|
||||||
{
|
{
|
||||||
if (use != drcCurSub)
|
if (use != dlu->dlu_use)
|
||||||
GeoInclude(&use->cu_bbox, area);
|
GeoInclude(&use->cu_bbox, &dlu->dlu_area);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -134,14 +152,15 @@ drcFindOtherCells(use, area)
|
||||||
* different for "drc why" commands than for "drc check".
|
* different for "drc why" commands than for "drc check".
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* 0 to keep the search going.
|
* 0 to keep the search going. In case of an interrupt, return 1.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcSubCopyErrors(tile, cxp)
|
drcSubCopyErrors(tile, dinfo, cxp)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -156,6 +175,9 @@ drcSubCopyErrors(tile, cxp)
|
||||||
arg->dCD_clientData);
|
arg->dCD_clientData);
|
||||||
(*(arg->dCD_errors))++;
|
(*(arg->dCD_errors))++;
|
||||||
|
|
||||||
|
/* Allow a break here */
|
||||||
|
if (SigInterruptPending) return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,68 +246,56 @@ drcSubCopyFunc(scx, cdarg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcSubcellFunc(subUse, flags)
|
drcSubcellFunc(subUse, dsa)
|
||||||
CellUse *subUse; /* Subcell instance. */
|
CellUse *subUse; /* Subcell instance found in area. */
|
||||||
int *flags; /* Information to propagate up */
|
struct drcSubcellArg *dsa; /* Information needed for funtion and to pass
|
||||||
|
* back to the caller.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
Rect area, haloArea, intArea, subIntArea, locIntArea;
|
Rect area, haloArea, intArea;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* A subcell has been seen, so set the "cell found" flag */
|
/* Record that a subcell has been seen in the search area. */
|
||||||
*flags |= CELLFOUND_FLAG;
|
dsa->dsa_found = TRUE;
|
||||||
|
|
||||||
/* To determine interactions, find the bounding box of
|
/* To determine interactions, find the bounding box of
|
||||||
* all paint and other subcells within one halo of this
|
* all paint and other subcells within one halo of this
|
||||||
* subcell (and also within the original area where
|
* subcell (and also within the original area where
|
||||||
* we're recomputing errors).
|
* we're recomputing errors).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
area = subUse->cu_bbox;
|
area = subUse->cu_bbox;
|
||||||
|
|
||||||
GEO_EXPAND(&area, drcSubRadius, &haloArea);
|
GEO_EXPAND(&area, dsa->dsa_radius, &haloArea);
|
||||||
GeoClip(&haloArea, &drcSubLookArea);
|
GeoClip(&haloArea, dsa->dsa_searchArea);
|
||||||
|
|
||||||
intArea = GeoNullRect;
|
intArea = GeoNullRect;
|
||||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||||
{
|
{
|
||||||
(void) DBSrPaintArea((Tile *) NULL, drcSubDef->cd_planes[i],
|
(void) DBSrPaintArea((Tile *) NULL, dsa->dsa_def->cd_planes[i],
|
||||||
&haloArea, &DBAllButSpaceBits, drcIncludeArea,
|
&haloArea, &DBAllButSpaceBits, drcIncludeArea,
|
||||||
(ClientData) &intArea);
|
(ClientData) &intArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DRC error tiles in a subcell are automatically pulled into the */
|
/* To check sibling interactions, DBSrCellPlaneArea() must not be
|
||||||
/* interaction area of the parent. Ultimately this is recursive as */
|
* called from within itself, so save the information about this
|
||||||
/* all cells are checked and errors propagate to the top level. */
|
* cell and its area in a linked list. If haloArea is already
|
||||||
|
* inside intArea, then do nothing.
|
||||||
|
*/
|
||||||
|
|
||||||
subIntArea = GeoNullRect;
|
if (!GEO_SURROUND(&intArea, &haloArea))
|
||||||
|
{
|
||||||
#if (0)
|
struct drcLinkedUse *newdlu;
|
||||||
/* NOTE: DRC errors inside a subcell should be ignored for */
|
newdlu = (struct drcLinkedUse *)mallocMagic(sizeof(struct drcLinkedUse));
|
||||||
/* the purpose of finding interactions. Errors should only */
|
newdlu->dlu_use = subUse;
|
||||||
/* be copied up into the parent when in a non-interaction */
|
newdlu->dlu_area = haloArea;
|
||||||
/* area. This is done below in DRCFindInteractions(). */
|
newdlu->dlu_next = dsa->dsa_dlu;
|
||||||
/* (Method added by Tim, 10/15/2020) */
|
dsa->dsa_dlu = newdlu;
|
||||||
|
}
|
||||||
/* Maybe S and PS errors should be pulled here? */
|
|
||||||
|
|
||||||
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
|
|
||||||
&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
|
|
||||||
(ClientData) &subIntArea);
|
|
||||||
|
|
||||||
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
|
|
||||||
GeoInclude(&locIntArea, &intArea);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!GEO_RECTNULL(&subIntArea)) *flags |= PROPAGATE_FLAG;
|
|
||||||
|
|
||||||
drcCurSub = subUse;
|
|
||||||
(void) DBSrCellPlaneArea(drcSubDef->cd_cellPlane, &haloArea,
|
|
||||||
drcFindOtherCells, (ClientData)(&intArea));
|
|
||||||
if (GEO_RECTNULL(&intArea)) return 0;
|
if (GEO_RECTNULL(&intArea)) return 0;
|
||||||
|
|
||||||
GEO_EXPAND(&intArea, drcSubRadius, &intArea);
|
GEO_EXPAND(&intArea, dsa->dsa_radius, &intArea);
|
||||||
GeoClip(&intArea, &haloArea);
|
GeoClip(&intArea, &haloArea);
|
||||||
(void) GeoInclude(&intArea, &drcSubIntArea);
|
(void) GeoInclude(&intArea, dsa->dsa_intArea);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,7 +318,9 @@ drcSubcellFunc(subUse, flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcAlwaysOne()
|
drcAlwaysOne(Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData clientdata)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -409,10 +421,10 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
int i;
|
int i;
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
int flags;
|
Rect searchArea, intArea;
|
||||||
|
struct drcSubcellArg dsa;
|
||||||
|
struct drcLinkedUse *curDLU;
|
||||||
|
|
||||||
drcSubDef = def;
|
|
||||||
drcSubRadius = radius;
|
|
||||||
DRCDummyUse->cu_def = def;
|
DRCDummyUse->cu_def = def;
|
||||||
|
|
||||||
/* Find all the interactions in the area and compute the
|
/* Find all the interactions in the area and compute the
|
||||||
|
|
@ -422,11 +434,53 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
* each cell has material everywhere within its bounding box.
|
* each cell has material everywhere within its bounding box.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
drcSubIntArea = GeoNullRect;
|
GEO_EXPAND(area, radius, &searchArea);
|
||||||
GEO_EXPAND(area, radius, &drcSubLookArea);
|
intArea = GeoNullRect;
|
||||||
flags = 0;
|
|
||||||
(void) DBSrCellPlaneArea(def->cd_cellPlane, &drcSubLookArea,
|
/* Copy drcSubLookArea to a local Rect structure because it
|
||||||
drcSubcellFunc, (ClientData)(&flags));
|
* gets modified by drcSubcellFunc().
|
||||||
|
*/
|
||||||
|
|
||||||
|
dsa.dsa_def = def;
|
||||||
|
dsa.dsa_radius = radius;
|
||||||
|
dsa.dsa_searchArea = &searchArea;
|
||||||
|
dsa.dsa_intArea = &intArea;
|
||||||
|
dsa.dsa_found = FALSE;
|
||||||
|
dsa.dsa_dlu = (struct drcLinkedUse *)NULL;
|
||||||
|
|
||||||
|
(void) DBSrCellPlaneArea(def->cd_cellPlane, &searchArea,
|
||||||
|
drcSubcellFunc, (ClientData)&dsa);
|
||||||
|
|
||||||
|
/* If no subcells were in the search area, there is nothing
|
||||||
|
* more to do.
|
||||||
|
*/
|
||||||
|
if (dsa.dsa_found == FALSE) return -1;
|
||||||
|
|
||||||
|
/* If drcSubcellFunc() returned a list of uses, then check
|
||||||
|
* the area of each use for interacting sibling uses, and
|
||||||
|
* add the overlap to the potential interaction area.
|
||||||
|
*/
|
||||||
|
curDLU = dsa.dsa_dlu;
|
||||||
|
while (curDLU != NULL)
|
||||||
|
{
|
||||||
|
Rect subIntArea, subSearchArea;
|
||||||
|
struct drcLinkedUse *nextdlu = curDLU->dlu_next;
|
||||||
|
|
||||||
|
subSearchArea = curDLU->dlu_area;
|
||||||
|
curDLU->dlu_area = GeoNullRect;
|
||||||
|
|
||||||
|
(void) DBSrCellPlaneArea(def->cd_cellPlane, &subSearchArea,
|
||||||
|
drcFindOtherCells, (ClientData)curDLU);
|
||||||
|
|
||||||
|
/* Re-clip interaction area to subcell halo area */
|
||||||
|
GEO_EXPAND(&curDLU->dlu_area, radius, &curDLU->dlu_area);
|
||||||
|
GeoClip(&curDLU->dlu_area, &subSearchArea);
|
||||||
|
(void) GeoInclude(&curDLU->dlu_area, &intArea);
|
||||||
|
|
||||||
|
/* Free entry and move to next entry in linked list */
|
||||||
|
freeMagic((char *)curDLU);
|
||||||
|
curDLU = nextdlu;
|
||||||
|
}
|
||||||
|
|
||||||
/* If there seems to be an interaction area, make a second pass
|
/* If there seems to be an interaction area, make a second pass
|
||||||
* to make sure there's more than one cell with paint in the
|
* to make sure there's more than one cell with paint in the
|
||||||
|
|
@ -434,35 +488,31 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
* have overlapping bounding boxes without overlapping paint.
|
* have overlapping bounding boxes without overlapping paint.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(flags & CELLFOUND_FLAG)) return -1;
|
if (GEO_RECTNULL(&intArea)) return 0;
|
||||||
if (GEO_RECTNULL(&drcSubIntArea)) return 0;
|
|
||||||
use = NULL;
|
use = NULL;
|
||||||
|
|
||||||
/* If errors are being propagated up from child to parent, */
|
/* If errors are being propagated up from child to parent, */
|
||||||
/* then the interaction area is always valid. */
|
/* then the interaction area is always valid. */
|
||||||
|
|
||||||
if (!(flags & PROPAGATE_FLAG))
|
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||||
{
|
{
|
||||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
|
||||||
|
&intArea, &DBAllButSpaceBits, drcAlwaysOne,
|
||||||
|
(ClientData) NULL) != 0)
|
||||||
{
|
{
|
||||||
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
|
use = (CellUse *) -1;
|
||||||
&drcSubIntArea, &DBAllButSpaceBits, drcAlwaysOne,
|
break;
|
||||||
(ClientData) NULL) != 0)
|
|
||||||
{
|
|
||||||
use = (CellUse *) -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
scx.scx_use = DRCDummyUse;
|
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
|
||||||
scx.scx_area = drcSubIntArea;
|
|
||||||
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
scx.scx_use = DRCDummyUse;
|
||||||
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
scx.scx_area = intArea;
|
||||||
|
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* OK, no more excuses, there's really an interaction area here. */
|
/* OK, no more excuses, there's really an interaction area here. */
|
||||||
|
|
||||||
*interaction = drcSubIntArea;
|
*interaction = intArea;
|
||||||
GeoClip(interaction, area);
|
GeoClip(interaction, area);
|
||||||
if (GEO_RECTNULL(interaction)) return 0;
|
if (GEO_RECTNULL(interaction)) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -489,8 +539,9 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcExactOverlapCheck(tile, arg)
|
drcExactOverlapCheck(tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile to check. */
|
Tile *tile; /* Tile to check. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
struct drcClientData *arg; /* How to detect and process errors. */
|
struct drcClientData *arg; /* How to detect and process errors. */
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -528,8 +579,9 @@ drcExactOverlapCheck(tile, arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcExactOverlapTile(tile, cxp)
|
drcExactOverlapTile(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Tile that must overlap exactly. */
|
Tile *tile; /* Tile that must overlap exactly. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
TreeContext *cxp; /* Tells how to translate out of subcell.
|
TreeContext *cxp; /* Tells how to translate out of subcell.
|
||||||
* The client data must be a drcClientData
|
* The client data must be a drcClientData
|
||||||
* record, and the caller must have filled
|
* record, and the caller must have filled
|
||||||
|
|
@ -734,9 +786,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
|
||||||
* square separately.
|
* square separately.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
x = (area->r_xbot/DRCStepSize) * DRCStepSize;
|
x = (area->r_xbot/DRCStepSize) * DRCStepSize - (DRCStepSize / 2);
|
||||||
if (x > area->r_xbot) x -= DRCStepSize;
|
if (x > area->r_xbot) x -= DRCStepSize;
|
||||||
y = (area->r_ybot/DRCStepSize) * DRCStepSize;
|
y = (area->r_ybot/DRCStepSize) * DRCStepSize - (DRCStepSize / 2);
|
||||||
if (y > area->r_ybot) y -= DRCStepSize;
|
if (y > area->r_ybot) y -= DRCStepSize;
|
||||||
for (square.r_xbot = x; square.r_xbot < area->r_xtop;
|
for (square.r_xbot = x; square.r_xbot < area->r_xtop;
|
||||||
square.r_xbot += DRCStepSize)
|
square.r_xbot += DRCStepSize)
|
||||||
|
|
@ -774,6 +826,7 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
|
||||||
*/
|
*/
|
||||||
subArea = *erasebox;
|
subArea = *erasebox;
|
||||||
GeoClip(&subArea, &cliparea);
|
GeoClip(&subArea, &cliparea);
|
||||||
|
if (GEO_RECTNULL(&subArea)) continue;
|
||||||
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
||||||
|
|
||||||
errorSaveType = DRCErrorType;
|
errorSaveType = DRCErrorType;
|
||||||
|
|
|
||||||
259
drc/DRCtech.c
259
drc/DRCtech.c
|
|
@ -72,6 +72,12 @@ static int drcRulesOptimized = 0;
|
||||||
|
|
||||||
static int DRCtag = 0;
|
static int DRCtag = 0;
|
||||||
|
|
||||||
|
/* Keep track of what rule exemption or exception is in effect
|
||||||
|
* while reading the DRC tech file section.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned char drcCurException = DRC_EXCEPTION_NONE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declarations.
|
* Forward declarations.
|
||||||
*/
|
*/
|
||||||
|
|
@ -79,6 +85,7 @@ int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap();
|
||||||
int drcExactOverlap(), drcExtend();
|
int drcExactOverlap(), drcExtend();
|
||||||
int drcSurround(), drcRectOnly(), drcOverhang();
|
int drcSurround(), drcRectOnly(), drcOverhang();
|
||||||
int drcStepSize(), drcOption(), drcOffGrid();
|
int drcStepSize(), drcOption(), drcOffGrid();
|
||||||
|
int drcException(), drcExemption();
|
||||||
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
||||||
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
||||||
int drcCifMaxwidth(), drcCifArea();
|
int drcCifMaxwidth(), drcCifArea();
|
||||||
|
|
@ -301,6 +308,12 @@ drcTechFreeStyle()
|
||||||
/* Clear the Why string list */
|
/* Clear the Why string list */
|
||||||
freeMagic(DRCCurStyle->DRCWhyList);
|
freeMagic(DRCCurStyle->DRCWhyList);
|
||||||
|
|
||||||
|
/* Clear the exception list */
|
||||||
|
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
||||||
|
freeMagic(DRCCurStyle->DRCExceptionList[i]);
|
||||||
|
if (DRCCurStyle->DRCExceptionList != (char **)NULL)
|
||||||
|
freeMagic(DRCCurStyle->DRCExceptionList);
|
||||||
|
|
||||||
freeMagic(DRCCurStyle);
|
freeMagic(DRCCurStyle);
|
||||||
DRCCurStyle = NULL;
|
DRCCurStyle = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -384,6 +397,63 @@ drcWhyCreate(whystring)
|
||||||
return DRCCurStyle->DRCWhySize;
|
return DRCCurStyle->DRCWhySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* drcExceptionCreate --
|
||||||
|
*
|
||||||
|
* Create an entry for a DRC rule exception/exemption type, if it does
|
||||||
|
* not already exist.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* The index of the exception (which is an unsigned character containing
|
||||||
|
* the index in the lower 7 bits and a high bit indicating if the rule
|
||||||
|
* is an exception (0) or an exemption (1)).
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Adds to the DRCExceptionList if "name" has not been used before.
|
||||||
|
* Calls StrDup() and increments DRCExceptionSize.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char
|
||||||
|
drcExceptionCreate(name)
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char **newlist;
|
||||||
|
|
||||||
|
/* NOTE: DRCExceptionList has "MASKHINTS_" prepended to the names */
|
||||||
|
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
||||||
|
if (!strcmp(name, DRCCurStyle->DRCExceptionList[i] + 10))
|
||||||
|
return (unsigned char)i;
|
||||||
|
|
||||||
|
/* Note that i cannot be 127 as this is reserved for DRC_EXCEPTION_NONE */
|
||||||
|
if (i > 126)
|
||||||
|
{
|
||||||
|
/* I would be shocked if this code ever got executed. */
|
||||||
|
TxError("Error: Too many rule exceptions! Limit is 126.\n");
|
||||||
|
return DRC_EXCEPTION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new list that is one entry longer than the old list.
|
||||||
|
* This is not elegant but there will never be more than a handful
|
||||||
|
* of exceptions in a rule deck.
|
||||||
|
*/
|
||||||
|
newlist = (char **)mallocMagic((i + 1) * sizeof(char *));
|
||||||
|
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
||||||
|
newlist[i] = DRCCurStyle->DRCExceptionList[i];
|
||||||
|
|
||||||
|
/* The rule deck does not have the "MASKHINTS_" prefix on the name */
|
||||||
|
newlist[i] = (char *)mallocMagic(strlen(name) + 11);
|
||||||
|
sprintf(newlist[i], "MASKHINTS_%s", name);
|
||||||
|
DRCCurStyle->DRCExceptionSize++;
|
||||||
|
if (DRCCurStyle->DRCExceptionList != (char **)NULL)
|
||||||
|
freeMagic(DRCCurStyle->DRCExceptionList);
|
||||||
|
DRCCurStyle->DRCExceptionList = newlist;
|
||||||
|
return (unsigned char)i;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -522,11 +592,13 @@ DRCTechInit()
|
||||||
|
|
||||||
drcTechFreeStyle();
|
drcTechFreeStyle();
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (style = DRCStyleList; style != NULL; style = style->ds_next)
|
for (style = DRCStyleList; style != NULL; style = style->ds_next)
|
||||||
{
|
{
|
||||||
freeMagic(style->ds_name);
|
freeMagic(style->ds_name);
|
||||||
freeMagic(style);
|
freeMagic1(&mm1, style);
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
DRCStyleList = NULL;
|
DRCStyleList = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -569,6 +641,8 @@ DRCTechStyleInit()
|
||||||
DRCCurStyle->DRCStepSize = 0;
|
DRCCurStyle->DRCStepSize = 0;
|
||||||
DRCCurStyle->DRCFlags = (char)0;
|
DRCCurStyle->DRCFlags = (char)0;
|
||||||
DRCCurStyle->DRCWhySize = 0;
|
DRCCurStyle->DRCWhySize = 0;
|
||||||
|
DRCCurStyle->DRCExceptionList = (char **)NULL;
|
||||||
|
DRCCurStyle->DRCExceptionSize = 0;
|
||||||
|
|
||||||
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
||||||
|
|
||||||
|
|
@ -661,6 +735,7 @@ DRCTechStyleInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
drcCifInit();
|
drcCifInit();
|
||||||
|
drcCurException = DRC_EXCEPTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -953,6 +1028,7 @@ drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, plane
|
||||||
(cookie)->drcc_plane = planeto;
|
(cookie)->drcc_plane = planeto;
|
||||||
(cookie)->drcc_mod = 0;
|
(cookie)->drcc_mod = 0;
|
||||||
(cookie)->drcc_cmod = 0;
|
(cookie)->drcc_cmod = 0;
|
||||||
|
(cookie)->drcc_exception = drcCurException;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
||||||
|
|
@ -1029,50 +1105,37 @@ DRCTechAddRule(sectionName, argc, argv)
|
||||||
int (*rk_proc)(); /* Procedure implementing this keyword */
|
int (*rk_proc)(); /* Procedure implementing this keyword */
|
||||||
const char *rk_err; /* Error message */
|
const char *rk_err; /* Error message */
|
||||||
} ruleKeys[] = {
|
} ruleKeys[] = {
|
||||||
{"angles", 4, 4, drcAngles,
|
{"angles", 4, 4, drcAngles, "layers 45|90 why"},
|
||||||
"layers 45|90 why"},
|
|
||||||
{"edge", 8, 10, drcEdge,
|
{"edge", 8, 10, drcEdge,
|
||||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||||
{"edge4way", 8, 10, drcEdge,
|
{"edge4way", 8, 10, drcEdge,
|
||||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||||
{"exact_overlap", 2, 2, drcExactOverlap,
|
{"exact_overlap", 2, 2, drcExactOverlap, "layers"},
|
||||||
"layers"},
|
{"exception", 2, 2, drcException, "name"},
|
||||||
|
{"exemption", 2, 2, drcExemption, "name"},
|
||||||
{"extend", 5, 6, drcExtend,
|
{"extend", 5, 6, drcExtend,
|
||||||
"layers1 layers2 distance [option] why"},
|
"layers1 layers2 distance [option] why"},
|
||||||
{"no_overlap", 3, 3, drcNoOverlap,
|
{"no_overlap", 3, 3, drcNoOverlap, "layers1 layers2"},
|
||||||
"layers1 layers2"},
|
{"option", 2, 2, drcOption, "option_name option_value"},
|
||||||
{"option", 2, 2, drcOption,
|
{"overhang", 5, 5, drcOverhang, "layers1 layers2 distance why"},
|
||||||
"option_name option_value"},
|
{"rect_only", 3, 3, drcRectOnly, "layers why"},
|
||||||
{"overhang", 5, 5, drcOverhang,
|
|
||||||
"layers1 layers2 distance why"},
|
|
||||||
{"rect_only", 3, 3, drcRectOnly,
|
|
||||||
"layers why"},
|
|
||||||
{"spacing", 6, 7, drcSpacing,
|
{"spacing", 6, 7, drcSpacing,
|
||||||
"layers1 layers2 separation [layers3] adjacency why"},
|
"layers1 layers2 separation [layers3] adjacency why"},
|
||||||
{"stepsize", 2, 2, drcStepSize,
|
{"stepsize", 2, 2, drcStepSize, "step_size"},
|
||||||
"step_size"},
|
|
||||||
{"surround", 6, 7, drcSurround,
|
{"surround", 6, 7, drcSurround,
|
||||||
"layers1 layers2 distance presence why"},
|
"layers1 layers2 distance presence why"},
|
||||||
{"width", 4, 5, drcWidth,
|
{"width", 4, 5, drcWidth, "layers width why"},
|
||||||
"layers width why"},
|
|
||||||
{"widespacing", 7, 8, drcSpacing,
|
{"widespacing", 7, 8, drcSpacing,
|
||||||
"layers1 width layers2 separation adjacency why"},
|
"layers1 width layers2 separation adjacency why"},
|
||||||
{"area", 5, 5, drcArea,
|
{"area", 5, 5, drcArea, "layers area horizon why"},
|
||||||
"layers area horizon why"},
|
{"off_grid", 4, 4, drcOffGrid, "layers pitch why"},
|
||||||
{"off_grid", 4, 4, drcOffGrid,
|
{"maxwidth", 4, 6, drcMaxwidth, "layers maxwidth bends why"},
|
||||||
"layers pitch why"},
|
{"cifstyle", 2, 2, drcCifSetStyle, "cif_style"},
|
||||||
{"maxwidth", 4, 5, drcMaxwidth,
|
{"cifwidth", 4, 4, drcCifWidth, "layers width why"},
|
||||||
"layers maxwidth bends why"},
|
|
||||||
{"cifstyle", 2, 2, drcCifSetStyle,
|
|
||||||
"cif_style"},
|
|
||||||
{"cifwidth", 4, 4, drcCifWidth,
|
|
||||||
"layers width why"},
|
|
||||||
{"cifspacing", 6, 6, drcCifSpacing,
|
{"cifspacing", 6, 6, drcCifSpacing,
|
||||||
"layers1 layers2 separation adjacency why"},
|
"layers1 layers2 separation adjacency why"},
|
||||||
{"cifarea", 5, 5, drcCifArea,
|
{"cifarea", 5, 5, drcCifArea, "layers area horizon why"},
|
||||||
"layers area horizon why"},
|
{"cifmaxwidth", 5, 5, drcCifMaxwidth, "layers maxwidth bends why"},
|
||||||
{"cifmaxwidth", 5, 5, drcCifMaxwidth,
|
|
||||||
"layers maxwidth bends why"},
|
|
||||||
{"rectangle", 5, 5, drcRectangle,
|
{"rectangle", 5, 5, drcRectangle,
|
||||||
"layers maxwidth [even|odd|any] why"},
|
"layers maxwidth [even|odd|any] why"},
|
||||||
{0}
|
{0}
|
||||||
|
|
@ -1582,7 +1645,7 @@ drcOffGrid(argc, argv)
|
||||||
* Process a maxwidth rule.
|
* Process a maxwidth rule.
|
||||||
* This is of the form:
|
* This is of the form:
|
||||||
*
|
*
|
||||||
* maxwidth layers distance [bends] why
|
* maxwidth layers distance [bends] [exclude_layers] why
|
||||||
*
|
*
|
||||||
* This routine was updated 3/6/05 to match the "canonical" definition of
|
* This routine was updated 3/6/05 to match the "canonical" definition of
|
||||||
* a maxwidth region, which is any rectangle containing <layers> that is
|
* a maxwidth region, which is any rectangle containing <layers> that is
|
||||||
|
|
@ -1591,6 +1654,11 @@ drcOffGrid(argc, argv)
|
||||||
* (see below) for backwards-compatibility. Otherwise ("bend_ok" or
|
* (see below) for backwards-compatibility. Otherwise ("bend_ok" or
|
||||||
* nothing), the new routine is used.
|
* nothing), the new routine is used.
|
||||||
*
|
*
|
||||||
|
* exclude_layers is optional and indicates a type or types (which if more
|
||||||
|
* than one must all be on the same plane) that prevent "maxwidth" from
|
||||||
|
* being checked. A common use case is using "glass" (passivation cut) to
|
||||||
|
* exclude top metal on a pad from being checked for maximum metal width.
|
||||||
|
*
|
||||||
* maxwidth metal1 389 "metal1 width > 35um must be slotted"
|
* maxwidth metal1 389 "metal1 width > 35um must be slotted"
|
||||||
* maxwidth pmc 4 bend_illegal "poly contact area must be no wider than 4"
|
* maxwidth pmc 4 bend_illegal "poly contact area must be no wider than 4"
|
||||||
* maxwidth trench 4 bend_ok "trench width must be exactly 4"
|
* maxwidth trench 4 bend_ok "trench width must be exactly 4"
|
||||||
|
|
@ -1629,11 +1697,11 @@ drcMaxwidth(argc, argv)
|
||||||
int distance = atoi(argv[2]);
|
int distance = atoi(argv[2]);
|
||||||
char *bends = argv[3];
|
char *bends = argv[3];
|
||||||
int why;
|
int why;
|
||||||
TileTypeBitMask set, setC;
|
TileTypeBitMask set, setC, setE;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
PlaneMask pmask, ptest, pset;
|
PlaneMask pmask, pmask2, ptest, pset;
|
||||||
int plane;
|
int plane, plane2;
|
||||||
int bend;
|
int bend;
|
||||||
|
|
||||||
ptest = DBTechNoisyNameMask(layers, &set);
|
ptest = DBTechNoisyNameMask(layers, &set);
|
||||||
|
|
@ -1667,8 +1735,34 @@ drcMaxwidth(argc, argv)
|
||||||
TechError("unknown bend option %s\n",bends);
|
TechError("unknown bend option %s\n",bends);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
why = drcWhyCreate(argv[4]);
|
if (argc == 6)
|
||||||
|
why = drcWhyCreate(argv[5]);
|
||||||
|
else
|
||||||
|
why = drcWhyCreate(argv[4]);
|
||||||
}
|
}
|
||||||
|
if (argc == 6)
|
||||||
|
{
|
||||||
|
ptest = DBTechNoisyNameMask(argv[4], &setE);
|
||||||
|
pmask2 = CoincidentPlanes(&setE, ptest);
|
||||||
|
if (pmask2 == 0)
|
||||||
|
{
|
||||||
|
TechError("All layers for \"maxwidth\" exclude types must "
|
||||||
|
"be on same plane.\n");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (plane2 = PL_TECHDEPBASE; plane2 < DBNumPlanes; plane2++)
|
||||||
|
if (PlaneMaskHasPlane(pmask2, plane2))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (PlaneMaskHasPlane(pmask, plane2))
|
||||||
|
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
||||||
|
"same plane and so cannot be checked.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
plane2 = -1;
|
||||||
|
|
||||||
for (i = 0; i < DBNumTypes; i++)
|
for (i = 0; i < DBNumTypes; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -1689,8 +1783,12 @@ drcMaxwidth(argc, argv)
|
||||||
/* find bucket preceding the new one we wish to insert */
|
/* find bucket preceding the new one we wish to insert */
|
||||||
dp = drcFindBucket(i, j, distance);
|
dp = drcFindBucket(i, j, distance);
|
||||||
dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie));
|
dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie));
|
||||||
drcAssign(dpnew, distance, dp->drcc_next, &set, &set, why,
|
if (plane2 == -1)
|
||||||
|
drcAssign(dpnew, distance, dp->drcc_next, &set, &set, why,
|
||||||
distance, DRC_MAXWIDTH | bend, plane, plane);
|
distance, DRC_MAXWIDTH | bend, plane, plane);
|
||||||
|
else
|
||||||
|
drcAssign(dpnew, distance, dp->drcc_next, &set, &setE, why,
|
||||||
|
distance, DRC_MAXWIDTH | bend, plane2, plane);
|
||||||
|
|
||||||
dp->drcc_next = dpnew;
|
dp->drcc_next = dpnew;
|
||||||
}
|
}
|
||||||
|
|
@ -3597,6 +3695,84 @@ drcRectangle(argc, argv)
|
||||||
return maxwidth;
|
return maxwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* drcException, drcExemption --
|
||||||
|
*
|
||||||
|
* Process a DRC exception declaration
|
||||||
|
* This is of the form:
|
||||||
|
*
|
||||||
|
* exception exception_name|none
|
||||||
|
* or
|
||||||
|
* exemption exemption_name|none
|
||||||
|
*
|
||||||
|
* e.g,
|
||||||
|
*
|
||||||
|
* exception SRAM
|
||||||
|
* exemption SRAM
|
||||||
|
*
|
||||||
|
* The exception_name or exemption_name is the suffix part of a MASKHINTS_*
|
||||||
|
* property name; e.g., the name SRAM corresponds to a property called
|
||||||
|
* MASKHINTS_SRAM. This declaration is followed by a block of DRC rules
|
||||||
|
* that are subject to the exception or the exemption. An exception is the
|
||||||
|
* opposite of an exemption: If a rule is excepted, then the rule applies
|
||||||
|
* within areas delineated by bounding boxes defined by the
|
||||||
|
* MASKHINTS_<exception_name> property. If a rule is exempted, then the
|
||||||
|
* rule applies only outside of areas delineated by bounding boxes defined
|
||||||
|
* by the MASKHINTS_<exemption_name> property. The block of rules subject
|
||||||
|
* to the exemption or exception ends with another exception or exemption
|
||||||
|
* declaration. If the following rules are not to be excepted or exempted
|
||||||
|
* at all, then use "exception none" or "exemption none".
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Returns 0.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Updates drcCurException. drcCurException contains the index in
|
||||||
|
* the lower 7 bits, and a flag in the upper bit (0 = exception rule,
|
||||||
|
* 1 = exemption rule). The index can be recovered by masking off
|
||||||
|
* the upper bit.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
drcException(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (DRCCurStyle == NULL) return 0;
|
||||||
|
|
||||||
|
/* Assume that argc must be 2 because the parser insists upon it */
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "none"))
|
||||||
|
drcCurException = DRC_EXCEPTION_NONE;
|
||||||
|
else
|
||||||
|
drcCurException = drcExceptionCreate(argv[1]);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
drcExemption(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (DRCCurStyle == NULL) return 0;
|
||||||
|
|
||||||
|
/* Assume that argc must be 2 because the parser insists upon it */
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "none"))
|
||||||
|
drcCurException = DRC_EXCEPTION_NONE;
|
||||||
|
else
|
||||||
|
drcCurException = drcExceptionCreate(argv[1]) | DRC_EXCEPTION_MASK;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -4044,6 +4220,7 @@ drcTechFinalStyle(style)
|
||||||
{
|
{
|
||||||
for (j = 0; j < DBNumTypes; j++)
|
for (j = 0; j < DBNumTypes; j++)
|
||||||
{
|
{
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (dp = style->DRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next)
|
for (dp = style->DRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next)
|
||||||
{
|
{
|
||||||
/* Don't optimize on trigger rules; optimize on the */
|
/* Don't optimize on trigger rules; optimize on the */
|
||||||
|
|
@ -4081,6 +4258,7 @@ drcTechFinalStyle(style)
|
||||||
if (dp->drcc_dist > next->drcc_dist) continue;
|
if (dp->drcc_dist > next->drcc_dist) continue;
|
||||||
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
||||||
if (dp->drcc_plane != next->drcc_plane) continue;
|
if (dp->drcc_plane != next->drcc_plane) continue;
|
||||||
|
if (dp->drcc_exception != next->drcc_exception) continue;
|
||||||
if (dp->drcc_flags & DRC_REVERSE)
|
if (dp->drcc_flags & DRC_REVERSE)
|
||||||
{
|
{
|
||||||
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
||||||
|
|
@ -4126,7 +4304,8 @@ drcTechFinalStyle(style)
|
||||||
if (dptrig != NULL)
|
if (dptrig != NULL)
|
||||||
{
|
{
|
||||||
dptrig = dp->drcc_next;
|
dptrig = dp->drcc_next;
|
||||||
freeMagic((char *)dp->drcc_next);
|
free_magic1_t mm1_ = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1_, (char *)dp->drcc_next);
|
||||||
*dp2back = dp->drcc_next->drcc_next;
|
*dp2back = dp->drcc_next->drcc_next;
|
||||||
|
|
||||||
/* Replace this entry so on the next cycle */
|
/* Replace this entry so on the next cycle */
|
||||||
|
|
@ -4134,13 +4313,15 @@ drcTechFinalStyle(style)
|
||||||
/* even though dp is free'd (below), due to */
|
/* even though dp is free'd (below), due to */
|
||||||
/* the one-delayed free mechanism. */
|
/* the one-delayed free mechanism. */
|
||||||
dp->drcc_next = *dp2back;
|
dp->drcc_next = *dp2back;
|
||||||
|
freeMagic1_end(&mm1_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*dp2back = dp->drcc_next;
|
*dp2back = dp->drcc_next;
|
||||||
|
|
||||||
freeMagic((char *) dp);
|
freeMagic1(&mm1, (char *) dp);
|
||||||
drcRulesOptimized += 1;
|
drcRulesOptimized += 1;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ typedef struct drccookie
|
||||||
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
||||||
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
||||||
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
||||||
|
unsigned char drcc_exception; /* Index to list of exceptions */
|
||||||
int drcc_edgeplane; /* Plane of edge */
|
int drcc_edgeplane; /* Plane of edge */
|
||||||
int drcc_plane; /* Index of plane on which to check
|
int drcc_plane; /* Index of plane on which to check
|
||||||
* legal types. */
|
* legal types. */
|
||||||
|
|
@ -91,6 +92,11 @@ typedef struct drccookie
|
||||||
#define DRC_UNPROCESSED CLIENTDEFAULT
|
#define DRC_UNPROCESSED CLIENTDEFAULT
|
||||||
#define DRC_PROCESSED 1
|
#define DRC_PROCESSED 1
|
||||||
|
|
||||||
|
/* drcc_exception defaults to 255 meaning no exceptions/exemptions */
|
||||||
|
#define DRC_EXCEPTION_NONE ((unsigned char)0xff)
|
||||||
|
/* The high bit of the value determines if this is an exception or an exemption. */
|
||||||
|
#define DRC_EXCEPTION_MASK ((unsigned char)0x80)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Background DRC (DRC Idle proc) for Tcl-based Magic
|
* Background DRC (DRC Idle proc) for Tcl-based Magic
|
||||||
*/
|
*/
|
||||||
|
|
@ -177,6 +183,8 @@ typedef struct drcstyle
|
||||||
unsigned short DRCFlags; /* Option flags */
|
unsigned short DRCFlags; /* Option flags */
|
||||||
char **DRCWhyList; /* Indexed list of "why" text strings */
|
char **DRCWhyList; /* Indexed list of "why" text strings */
|
||||||
int DRCWhySize; /* Length of DRCWhyList */
|
int DRCWhySize; /* Length of DRCWhyList */
|
||||||
|
char **DRCExceptionList; /* Indexed list of DRC exceptions */
|
||||||
|
int DRCExceptionSize; /* Length of DRCExceptionList */
|
||||||
PaintResultType DRCPaintTable[NP][NT][NT];
|
PaintResultType DRCPaintTable[NP][NT][NT];
|
||||||
} DRCStyle;
|
} DRCStyle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||||
#include "commands/commands.h" /* for module auto-load */
|
#include "commands/commands.h" /* for module auto-load */
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
|
#include "extract/extract.h" /* for extDevTable */
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h" /* for extDevTable */
|
|
||||||
#include "utils/runstats.h"
|
#include "utils/runstats.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
|
||||||
|
|
@ -683,8 +683,10 @@ runexttosim:
|
||||||
EFVisitDevs(simmergeVisit, PTR2CD(NULL));
|
EFVisitDevs(simmergeVisit, PTR2CD(NULL));
|
||||||
TxPrintf("Devices merged: %d\n", esDevsMerged);
|
TxPrintf("Devices merged: %d\n", esDevsMerged);
|
||||||
esFMIndex = 0;
|
esFMIndex = 0;
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (p = devMergeList; p != NULL; p = p->next)
|
for (p = devMergeList; p != NULL; p = p->next)
|
||||||
freeMagic((char *)p);
|
freeMagic1(&mm1, (char *)p);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
devMergeList = NULL;
|
devMergeList = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -812,7 +814,10 @@ main(
|
||||||
EFVisitDevs(simmergeVisit, PTR2CD(NULL));
|
EFVisitDevs(simmergeVisit, PTR2CD(NULL));
|
||||||
TxPrintf("Devices merged: %d\n", esDevsMerged);
|
TxPrintf("Devices merged: %d\n", esDevsMerged);
|
||||||
esFMIndex = 0;
|
esFMIndex = 0;
|
||||||
for (p = devMergeList; p != NULL; p = p->next) freeMagic((char *)p);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
for (p = devMergeList; p != NULL; p = p->next)
|
||||||
|
freeMagic1(&mm1, (char *)p);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EFVisitDevs(simdevVisit, PTR2CD(NULL));
|
EFVisitDevs(simdevVisit, PTR2CD(NULL));
|
||||||
|
|
@ -1116,6 +1121,7 @@ simdevVisit(
|
||||||
break;
|
break;
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_SUBCKT:
|
case DEV_SUBCKT:
|
||||||
/* Use the 'x' type in .sim format. This is implemented in the */
|
/* Use the 'x' type in .sim format. This is implemented in the */
|
||||||
|
|
|
||||||
|
|
@ -41,14 +41,11 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "commands/commands.h" /* for module auto-load */
|
#include "commands/commands.h" /* for module auto-load */
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
|
||||||
#include "extract/extract.h" /* for extDevTable */
|
#include "extract/extract.h" /* for extDevTable */
|
||||||
|
#include "extflat/EFint.h"
|
||||||
#include "utils/runstats.h"
|
#include "utils/runstats.h"
|
||||||
#include "ext2spice/ext2spice.h"
|
#include "ext2spice/ext2spice.h"
|
||||||
|
|
||||||
/* C99 compat */
|
|
||||||
#include "extflat/extflat.h"
|
|
||||||
|
|
||||||
/* These global values are defined in ext2spice.c */
|
/* These global values are defined in ext2spice.c */
|
||||||
extern HashTable subcktNameTable;
|
extern HashTable subcktNameTable;
|
||||||
extern DQueue subcktNameQueue;
|
extern DQueue subcktNameQueue;
|
||||||
|
|
@ -126,6 +123,94 @@ GetHierNode(
|
||||||
return(nn->efnn_node);
|
return(nn->efnn_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* spcHierWriteValue ---
|
||||||
|
*
|
||||||
|
* Special case of spcHierWriteParams() below. Only check for 'r' or 'c'
|
||||||
|
* parameters which have no parameter name. Write out the given value,
|
||||||
|
* which in the case of CDL format is written out after the pins but before
|
||||||
|
* everything else, arbitrarily.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
spcHierWriteValue(
|
||||||
|
HierContext *hc,
|
||||||
|
Dev *dev) /* Dev being output */
|
||||||
|
{
|
||||||
|
DevParam *plist;
|
||||||
|
|
||||||
|
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
|
||||||
|
while (plist != NULL)
|
||||||
|
{
|
||||||
|
switch (plist->parm_type[0])
|
||||||
|
{
|
||||||
|
case 'r':
|
||||||
|
if (*(plist->parm_name) == '\0')
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
|
esSIvalue(esSpiceF, (double)(dev->dev_res));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (*(plist->parm_name) == '\0')
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
|
esSIvalue(esSpiceF, (double)(dev->dev_cap));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
plist = plist->parm_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* spcHierWriteSubParam ---
|
||||||
|
*
|
||||||
|
* Special case of spcHierWriteParams() below. Only check for the substrate
|
||||||
|
* parameter, which in the case of CDL format is written out before the
|
||||||
|
* device model, for whatever reason. Return TRUE if the substrate parameter
|
||||||
|
* was output; otherwise return FALSE.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
spcHierWriteSubParam(
|
||||||
|
HierContext *hc,
|
||||||
|
Dev *dev) /* Dev being output */
|
||||||
|
{
|
||||||
|
DevParam *plist;
|
||||||
|
bool retvalue = FALSE;
|
||||||
|
|
||||||
|
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
|
||||||
|
while (plist != NULL)
|
||||||
|
{
|
||||||
|
switch (plist->parm_type[0])
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
if (dev->dev_subsnode == NULL)
|
||||||
|
TxError("Error: Device %s missing substrate node!\n",
|
||||||
|
EFDevTypes[dev->dev_type]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
spcdevSubstrate(hc->hc_hierName,
|
||||||
|
dev->dev_subsnode->efnode_name->efnn_hier,
|
||||||
|
dev->dev_type, esSpiceF);
|
||||||
|
retvalue = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
plist = plist->parm_next;
|
||||||
|
}
|
||||||
|
return retvalue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -145,7 +230,8 @@ spcHierWriteParams(
|
||||||
float scale, /* Scale transform for output */
|
float scale, /* Scale transform for output */
|
||||||
int l, /* Device length, in internal units */
|
int l, /* Device length, in internal units */
|
||||||
int w, /* Device width, in internal units */
|
int w, /* Device width, in internal units */
|
||||||
float sdM) /* Device multiplier */
|
float sdM, /* Device multiplier */
|
||||||
|
bool subdone) /* If TRUE, then substrate parameter was already output */
|
||||||
{
|
{
|
||||||
DevParam *plist, *dparam;
|
DevParam *plist, *dparam;
|
||||||
int parmval;
|
int parmval;
|
||||||
|
|
@ -289,6 +375,7 @@ spcHierWriteParams(
|
||||||
else
|
else
|
||||||
esSIvalue(esSpiceF, (dval + plist->parm_offset)
|
esSIvalue(esSpiceF, (dval + plist->parm_offset)
|
||||||
* scale * esScale * 1.0E-6);
|
* scale * esScale * 1.0E-6);
|
||||||
|
/* Why is this here? */
|
||||||
dparam->parm_name[0] = '\0';
|
dparam->parm_name[0] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -342,10 +429,19 @@ spcHierWriteParams(
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
if (!subdone)
|
||||||
/*EFNode *subnodeFlat =*/ spcdevSubstrate(hc->hc_hierName,
|
{
|
||||||
dev->dev_subsnode->efnode_name->efnn_hier,
|
if (dev->dev_subsnode == NULL)
|
||||||
dev->dev_type, esSpiceF);
|
TxError("Error: Device %s missing substrate node!\n",
|
||||||
|
EFDevTypes[dev->dev_type]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
spcdevSubstrate(hc->hc_hierName,
|
||||||
|
dev->dev_subsnode->efnode_name->efnn_hier,
|
||||||
|
dev->dev_type, esSpiceF);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
|
@ -370,12 +466,18 @@ spcHierWriteParams(
|
||||||
* scale * esScale * 1.0E-6);
|
* scale * esScale * 1.0E-6);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
if (*(plist->parm_name) != '\0')
|
||||||
fprintf(esSpiceF, "%f", (double)(dev->dev_res));
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
esSIvalue(esSpiceF, (double)(dev->dev_res));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
if (*(plist->parm_name) != '\0')
|
||||||
fprintf(esSpiceF, "%ff", (double)(dev->dev_cap));
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
esSIvalue(esSpiceF, (double)(dev->dev_cap));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
plist = plist->parm_next;
|
plist = plist->parm_next;
|
||||||
|
|
@ -449,10 +551,16 @@ esOutputHierResistor(
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, " %f", ((double)(dev->dev_res)
|
fprintf(esSpiceF, " %f", ((double)(dev->dev_res)
|
||||||
/ (double)(dscale)) / (double)sdM);
|
/ (double)(dscale)) / (double)sdM);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool subdone = FALSE;
|
||||||
|
|
||||||
|
spcHierWriteValue(hc, dev);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcHierWriteSubParam(hc, dev);
|
||||||
|
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
|
|
@ -467,7 +575,7 @@ esOutputHierResistor(
|
||||||
fprintf(esSpiceF, " l=");
|
fprintf(esSpiceF, " l=");
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * (float)((l * scale * esScale) / dscale));
|
esSIvalue(esSpiceF, 1.0E-6 * (float)((l * scale * esScale) / dscale));
|
||||||
}
|
}
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
}
|
}
|
||||||
|
|
@ -526,7 +634,7 @@ subcktHierVisit(
|
||||||
|
|
||||||
if (hasports || is_top)
|
if (hasports || is_top)
|
||||||
return subcktVisit(use, hierName, is_top);
|
return subcktVisit(use, hierName, is_top);
|
||||||
else if (def->def_flags & DEF_NODEVICES)
|
else if ((def->def_flags & DEF_NODEVICES) && (!isStub))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return subcktVisit(use, hierName, is_top);
|
return subcktVisit(use, hierName, is_top);
|
||||||
|
|
@ -584,6 +692,7 @@ spcdevHierVisit(
|
||||||
float sdM;
|
float sdM;
|
||||||
char devchar;
|
char devchar;
|
||||||
bool has_model = TRUE;
|
bool has_model = TRUE;
|
||||||
|
bool subdone = FALSE;
|
||||||
|
|
||||||
/* If no terminals, or only a gate, can't do much of anything */
|
/* If no terminals, or only a gate, can't do much of anything */
|
||||||
if (dev->dev_nterm <= 1 )
|
if (dev->dev_nterm <= 1 )
|
||||||
|
|
@ -694,6 +803,7 @@ spcdevHierVisit(
|
||||||
case DEV_SUBCKT:
|
case DEV_SUBCKT:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
devchar = 'X';
|
devchar = 'X';
|
||||||
break;
|
break;
|
||||||
|
|
@ -731,6 +841,7 @@ spcdevHierVisit(
|
||||||
case DEV_VERILOGA:
|
case DEV_VERILOGA:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
fprintf(esSpiceF, "%d", esSbckNum++);
|
fprintf(esSpiceF, "%d", esSbckNum++);
|
||||||
break;
|
break;
|
||||||
|
|
@ -765,12 +876,15 @@ spcdevHierVisit(
|
||||||
source->dterm_node->efnode_name->efnn_hier,
|
source->dterm_node->efnode_name->efnn_hier,
|
||||||
"base", esSpiceF);
|
"base", esSpiceF);
|
||||||
|
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcHierWriteSubParam(hc, dev);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
/* msubcircuit is "Xnnn drain gate [source [sub]]]" */
|
/* msubcircuit is "Xnnn drain gate [source [sub]]]" */
|
||||||
/* to more conveniently handle situations where MOSFETs */
|
/* to more conveniently handle situations where MOSFETs */
|
||||||
/* are modeled by subcircuits with the same pin ordering. */
|
/* are modeled by subcircuits with the same pin ordering. */
|
||||||
|
|
@ -799,7 +913,11 @@ spcdevHierVisit(
|
||||||
/* except that the "gate" node is treated as an identifier */
|
/* except that the "gate" node is treated as an identifier */
|
||||||
/* only and is not output. */
|
/* only and is not output. */
|
||||||
|
|
||||||
if (dev->dev_class != DEV_MSUBCKT)
|
if (dev->dev_class == DEV_DSUBCKT)
|
||||||
|
{
|
||||||
|
/* Do nothing; both terminals have already been output */
|
||||||
|
}
|
||||||
|
else if (dev->dev_class != DEV_MSUBCKT)
|
||||||
{
|
{
|
||||||
if (dev->dev_nterm > 1)
|
if (dev->dev_nterm > 1)
|
||||||
spcdevOutNode(hc->hc_hierName, source->dterm_node->efnode_name->efnn_hier,
|
spcdevOutNode(hc->hc_hierName, source->dterm_node->efnode_name->efnn_hier,
|
||||||
|
|
@ -840,11 +958,13 @@ spcdevHierVisit(
|
||||||
subnode->efnode_name->efnn_hier,
|
subnode->efnode_name->efnn_hier,
|
||||||
dev->dev_type, esSpiceF);
|
dev->dev_type, esSpiceF);
|
||||||
}
|
}
|
||||||
|
/* Support for CDL format */
|
||||||
|
if (esFormat == CDL) fprintf(esSpiceF, " /");
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
/* Write all requested parameters to the subcircuit call. */
|
/* Write all requested parameters to the subcircuit call. */
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
break;
|
break;
|
||||||
|
|
@ -915,9 +1035,11 @@ spcdevHierVisit(
|
||||||
spcdevOutNode(hc->hc_hierName,
|
spcdevOutNode(hc->hc_hierName,
|
||||||
subnode->efnode_name->efnn_hier,
|
subnode->efnode_name->efnn_hier,
|
||||||
"diode_bot", esSpiceF);
|
"diode_bot", esSpiceF);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcHierWriteSubParam(hc, dev);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_NDIODE:
|
case DEV_NDIODE:
|
||||||
|
|
@ -936,9 +1058,11 @@ spcdevHierVisit(
|
||||||
spcdevOutNode(hc->hc_hierName,
|
spcdevOutNode(hc->hc_hierName,
|
||||||
gate->dterm_node->efnode_name->efnn_hier,
|
gate->dterm_node->efnode_name->efnn_hier,
|
||||||
"diode_top", esSpiceF);
|
"diode_top", esSpiceF);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcHierWriteSubParam(hc, dev);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
|
|
@ -964,11 +1088,15 @@ spcdevHierVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
spcHierWriteValue(hc, dev);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcHierWriteSubParam(hc, dev);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
|
|
@ -982,7 +1110,7 @@ spcdevHierVisit(
|
||||||
fprintf(esSpiceF, " l=");
|
fprintf(esSpiceF, " l=");
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
||||||
}
|
}
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
}
|
}
|
||||||
|
|
@ -1011,11 +1139,15 @@ spcdevHierVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
spcHierWriteValue(hc, dev);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcHierWriteSubParam(hc, dev);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
|
|
@ -1029,7 +1161,7 @@ spcdevHierVisit(
|
||||||
fprintf(esSpiceF, " l=");
|
fprintf(esSpiceF, " l=");
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
||||||
}
|
}
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, subdone);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
}
|
}
|
||||||
|
|
@ -1073,7 +1205,7 @@ spcdevHierVisit(
|
||||||
fprintf(esSpiceF, " l=");
|
fprintf(esSpiceF, " l=");
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
||||||
}
|
}
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
|
|
||||||
|
|
@ -2069,11 +2201,13 @@ esMakePorts(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free table data */
|
/* Free table data */
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
while (flagtop != NULL)
|
while (flagtop != NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)flagtop);
|
freeMagic1(&mm1, (char *)flagtop);
|
||||||
flagtop = flagtop->fdr_next;
|
flagtop = flagtop->fdr_next;
|
||||||
}
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
HashKill(&flagHashTable);
|
HashKill(&flagHashTable);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -2205,8 +2339,10 @@ esHierVisit(
|
||||||
EFHierVisitDevs(hcf, spcdevHierMergeVisit, (ClientData)NULL);
|
EFHierVisitDevs(hcf, spcdevHierMergeVisit, (ClientData)NULL);
|
||||||
TxPrintf("Devs merged: %d\n", esSpiceDevsMerged);
|
TxPrintf("Devs merged: %d\n", esSpiceDevsMerged);
|
||||||
esFMIndex = 0;
|
esFMIndex = 0;
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (p = devMergeList; p != NULL; p = p->next)
|
for (p = devMergeList; p != NULL; p = p->next)
|
||||||
freeMagic((char *)p);
|
freeMagic1(&mm1, (char *)p);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
devMergeList = NULL;
|
devMergeList = NULL;
|
||||||
}
|
}
|
||||||
else if (esDistrJunct)
|
else if (esDistrJunct)
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||||
#include "commands/commands.h" /* for module auto-load */
|
#include "commands/commands.h" /* for module auto-load */
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
|
#include "extract/extract.h" /* for extDevTable */
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h" /* for extDevTable */
|
|
||||||
#include "utils/runstats.h"
|
#include "utils/runstats.h"
|
||||||
|
|
||||||
#include "ext2spice/ext2spice.h"
|
#include "ext2spice/ext2spice.h"
|
||||||
|
|
@ -284,7 +284,7 @@ CmdExtToSpice(
|
||||||
static int LocResistThreshold = INFINITE_THRESHOLD;
|
static int LocResistThreshold = INFINITE_THRESHOLD;
|
||||||
|
|
||||||
static const char * const spiceFormats[] = {
|
static const char * const spiceFormats[] = {
|
||||||
"SPICE2", "SPICE3", "HSPICE", "NGSPICE", NULL
|
"SPICE2", "SPICE3", "HSPICE", "NGSPICE", "CDL", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const cmdExtToSpcOption[] = {
|
static const char * const cmdExtToSpcOption[] = {
|
||||||
|
|
@ -330,6 +330,7 @@ CmdExtToSpice(
|
||||||
"spice3",
|
"spice3",
|
||||||
"hspice",
|
"hspice",
|
||||||
"ngspice",
|
"ngspice",
|
||||||
|
"cdl",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -663,10 +664,10 @@ CmdExtToSpice(
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp, "Bad format type. Formats are:"
|
Tcl_SetResult(magicinterp, "Bad format type. Formats are:"
|
||||||
"spice2, spice3, hspice, and ngspice.", NULL);
|
"spice2, spice3, hspice, ngspice, and cdl.", NULL);
|
||||||
#else
|
#else
|
||||||
TxError("Bad format type. Formats are:"
|
TxError("Bad format type. Formats are:"
|
||||||
"spice2, spice3, hspice, and ngspice.");
|
"spice2, spice3, hspice, ngspice, and cdl.");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -876,7 +877,12 @@ runexttospice:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (spcesOutName == spcesDefaultOut)
|
if (spcesOutName == spcesDefaultOut)
|
||||||
sprintf(spcesDefaultOut, "%s.spice", inName);
|
{
|
||||||
|
if (esFormat == CDL)
|
||||||
|
sprintf(spcesDefaultOut, "%s.cdl", inName);
|
||||||
|
else
|
||||||
|
sprintf(spcesDefaultOut, "%s.spice", inName);
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the hierarchical description of the input circuit */
|
/* Read the hierarchical description of the input circuit */
|
||||||
if (EFReadFile(inName, esDoHierarchy, esDoExtResis, FALSE, TRUE)
|
if (EFReadFile(inName, esDoHierarchy, esDoExtResis, FALSE, TRUE)
|
||||||
|
|
@ -963,8 +969,11 @@ runexttospice:
|
||||||
|
|
||||||
locsubname = StrDup(NULL, subname);
|
locsubname = StrDup(NULL, subname);
|
||||||
|
|
||||||
bangptr = locsubname + strlen(locsubname) - 1;
|
if (esFormat != CDL)
|
||||||
if (*bangptr == '!') *bangptr = '\0';
|
{
|
||||||
|
bangptr = locsubname + strlen(locsubname) - 1;
|
||||||
|
if (*bangptr == '!') *bangptr = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
// Ad-hoc check: Global names with "Error", "err", etc.
|
// Ad-hoc check: Global names with "Error", "err", etc.
|
||||||
// should be rejected from the list. Also node name
|
// should be rejected from the list. Also node name
|
||||||
|
|
@ -994,6 +1003,42 @@ runexttospice:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
|
if (esFormat == CDL)
|
||||||
|
{
|
||||||
|
/* In CDL format, if the global substrate ends with "!" then
|
||||||
|
* add it to the list of globals; likewise for VDD and GND.
|
||||||
|
*/
|
||||||
|
char *glbstr;
|
||||||
|
globalList *glptr;
|
||||||
|
|
||||||
|
glbstr = (char *)Tcl_GetVar(magicinterp, "SUB", TCL_GLOBAL_ONLY);
|
||||||
|
if ((glbstr != NULL) && (*(glbstr + strlen(glbstr) - 1) == '!'))
|
||||||
|
{
|
||||||
|
glptr = (globalList *)mallocMagic(sizeof(globalList));
|
||||||
|
glptr->gll_name = StrDup((char **)NULL, glbstr);
|
||||||
|
glptr->gll_next = glist;
|
||||||
|
glist = glptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
glbstr = (char *)Tcl_GetVar(magicinterp, "VDD", TCL_GLOBAL_ONLY);
|
||||||
|
if ((glbstr != NULL) && (*(glbstr + strlen(glbstr) - 1) == '!'))
|
||||||
|
{
|
||||||
|
glptr = (globalList *)mallocMagic(sizeof(globalList));
|
||||||
|
glptr->gll_name = StrDup((char **)NULL, glbstr);
|
||||||
|
glptr->gll_next = glist;
|
||||||
|
glist = glptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
glbstr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY);
|
||||||
|
if ((glbstr != NULL) && (*(glbstr + strlen(glbstr) - 1) == '!'))
|
||||||
|
{
|
||||||
|
glptr = (globalList *)mallocMagic(sizeof(globalList));
|
||||||
|
glptr->gll_name = StrDup((char **)NULL, glbstr);
|
||||||
|
glptr->gll_next = glist;
|
||||||
|
glist = glptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (EFCompat == TRUE)
|
if (EFCompat == TRUE)
|
||||||
{
|
{
|
||||||
/* Keep a pointer to the "GND" variable, if it exists. */
|
/* Keep a pointer to the "GND" variable, if it exists. */
|
||||||
|
|
@ -1027,6 +1072,8 @@ runexttospice:
|
||||||
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
|
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
|
||||||
if (esFormat == HSPICE)
|
if (esFormat == HSPICE)
|
||||||
EFOutputFlags |= EF_TRIMLOCAL;
|
EFOutputFlags |= EF_TRIMLOCAL;
|
||||||
|
if (esFormat == CDL)
|
||||||
|
EFOutputFlags &= ~EF_TRIMGLOB;
|
||||||
|
|
||||||
/* Write globals under a ".global" card */
|
/* Write globals under a ".global" card */
|
||||||
|
|
||||||
|
|
@ -1057,8 +1104,10 @@ runexttospice:
|
||||||
|
|
||||||
fprintf(esSpiceF, " ");
|
fprintf(esSpiceF, " ");
|
||||||
freeMagic(glist->gll_name);
|
freeMagic(glist->gll_name);
|
||||||
freeMagic(glist);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, glist);
|
||||||
glist = glist->gll_next;
|
glist = glist->gll_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
fprintf(esSpiceF, "\n\n");
|
fprintf(esSpiceF, "\n\n");
|
||||||
}
|
}
|
||||||
|
|
@ -1112,8 +1161,10 @@ runexttospice:
|
||||||
EFVisitDevs(devMergeVisit, (ClientData) NULL);
|
EFVisitDevs(devMergeVisit, (ClientData) NULL);
|
||||||
TxPrintf("Devs merged: %d\n", esSpiceDevsMerged);
|
TxPrintf("Devs merged: %d\n", esSpiceDevsMerged);
|
||||||
esFMIndex = 0;
|
esFMIndex = 0;
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (p = devMergeList; p != NULL; p = p->next)
|
for (p = devMergeList; p != NULL; p = p->next)
|
||||||
freeMagic((char *) p);
|
freeMagic1(&mm1, (char *) p);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
devMergeList = NULL;
|
devMergeList = NULL;
|
||||||
}
|
}
|
||||||
else if (esDistrJunct)
|
else if (esDistrJunct)
|
||||||
|
|
@ -1226,7 +1277,13 @@ main(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (spcesOutName == spcesDefaultOut)
|
if (spcesOutName == spcesDefaultOut)
|
||||||
sprintf(spcesDefaultOut, "%s.spice", inName);
|
{
|
||||||
|
if (esFormat == CDL)
|
||||||
|
sprintf(spcesDefaultOut, "%s.cdl", inName);
|
||||||
|
else
|
||||||
|
sprintf(spcesDefaultOut, "%s.spice", inName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((esSpiceF = fopen(spcesOutName, "w")) == NULL)
|
if ((esSpiceF = fopen(spcesOutName, "w")) == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1288,9 +1345,12 @@ main(
|
||||||
TxPrintf("Devs merged: %d\n", esSpiceDevsMerged);
|
TxPrintf("Devs merged: %d\n", esSpiceDevsMerged);
|
||||||
esFMIndex = 0 ;
|
esFMIndex = 0 ;
|
||||||
{
|
{
|
||||||
const devMerge *p;
|
const devMerge *p;
|
||||||
|
|
||||||
for ( p = devMergeList ; p != NULL ; p=p->next ) freeMagic((char *)p);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
for (p = devMergeList; p != NULL; p = p->next)
|
||||||
|
freeMagic1(&mm1, (char *)p);
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
} else if ( esDistrJunct )
|
} else if ( esDistrJunct )
|
||||||
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
||||||
|
|
@ -1363,7 +1423,7 @@ spcParseArgs(
|
||||||
|
|
||||||
const char usage_text[] = "Usage: ext2spice "
|
const char usage_text[] = "Usage: ext2spice "
|
||||||
"[-B] [-o spicefile] [-M|-m] [-J flat|hier]\n"
|
"[-B] [-o spicefile] [-M|-m] [-J flat|hier]\n"
|
||||||
"[-f spice2|spice3|hspice|ngspice] [-M] [-m] "
|
"[-f spice2|spice3|hspice|ngspice|cdl] [-M] [-m] "
|
||||||
"[file]\n";
|
"[file]\n";
|
||||||
|
|
||||||
switch (argv[0][1])
|
switch (argv[0][1])
|
||||||
|
|
@ -1407,6 +1467,8 @@ spcParseArgs(
|
||||||
}
|
}
|
||||||
else if (strcasecmp(ftmp, "NGSPICE") == 0)
|
else if (strcasecmp(ftmp, "NGSPICE") == 0)
|
||||||
esFormat = NGSPICE;
|
esFormat = NGSPICE;
|
||||||
|
else if (strcasecmp(ftmp, "CDL") == 0)
|
||||||
|
esFormat = CDL;
|
||||||
else goto usage;
|
else goto usage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1627,23 +1689,43 @@ subcktVisit(
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((he = HashNext(&def->def_nodes, &hs)))
|
while ((he = HashNext(&def->def_nodes, &hs)))
|
||||||
{
|
{
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
sname = (EFNodeName *) HashGetValue(he);
|
sname = (EFNodeName *) HashGetValue(he);
|
||||||
if (sname == NULL) continue;
|
if (sname == NULL) continue;
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
|
|
||||||
if ((snode == NULL) || !(snode->efnode_flags & EF_PORT)) continue;
|
if ((snode == NULL) || !(snode->efnode_flags & EF_PORT)) continue;
|
||||||
|
|
||||||
|
portidx = snode->efnode_name->efnn_port;
|
||||||
|
|
||||||
|
if (portidx >= 0)
|
||||||
|
{
|
||||||
|
if (nodeList[portidx] == NULL)
|
||||||
|
{
|
||||||
|
nodeList[portidx] = snode->efnode_name;
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normally there should be a port associated with snode, but
|
||||||
|
* if not, go looking for one in the node name aliases.
|
||||||
|
*/
|
||||||
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
||||||
{
|
{
|
||||||
|
if (found == TRUE) break;
|
||||||
|
|
||||||
portidx = nodeName->efnn_port;
|
portidx = nodeName->efnn_port;
|
||||||
if (portidx < 0) continue;
|
if (portidx < 0) continue;
|
||||||
if (nodeList[portidx] == NULL)
|
if (nodeList[portidx] == NULL)
|
||||||
{
|
{
|
||||||
nodeList[portidx] = nodeName;
|
nodeList[portidx] = nodeName;
|
||||||
|
found = TRUE;
|
||||||
}
|
}
|
||||||
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
||||||
{
|
{
|
||||||
nodeList[portidx] = nodeName;
|
nodeList[portidx] = nodeName;
|
||||||
|
found = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1677,6 +1759,7 @@ subcktVisit(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tchars > 80) fprintf(esSpiceF, "\n+");
|
if (tchars > 80) fprintf(esSpiceF, "\n+");
|
||||||
|
if (esFormat == CDL) fprintf(esSpiceF, " /");
|
||||||
fprintf(esSpiceF, " %s", subcktname); /* subcircuit model name */
|
fprintf(esSpiceF, " %s", subcktname); /* subcircuit model name */
|
||||||
|
|
||||||
// Check for a "device parameter" defined with the name of the cell.
|
// Check for a "device parameter" defined with the name of the cell.
|
||||||
|
|
@ -1849,8 +1932,10 @@ topVisit(
|
||||||
sname = lnn->lnn_nodeName;
|
sname = lnn->lnn_nodeName;
|
||||||
if (esDoBlackBox == FALSE || !(def->def_flags & DEF_ABSTRACT))
|
if (esDoBlackBox == FALSE || !(def->def_flags & DEF_ABSTRACT))
|
||||||
sname->efnn_port = ++portmax;
|
sname->efnn_port = ++portmax;
|
||||||
freeMagic(lnn);
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, lnn);
|
||||||
lnn = lnn->lnn_next;
|
lnn = lnn->lnn_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Port numbers need not start at zero or be contiguous. They will be */
|
/* Port numbers need not start at zero or be contiguous. They will be */
|
||||||
|
|
@ -1867,6 +1952,7 @@ topVisit(
|
||||||
{
|
{
|
||||||
char stmp[MAX_STR_SIZE];
|
char stmp[MAX_STR_SIZE];
|
||||||
int portidx;
|
int portidx;
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
sname = (EFNodeName *) HashGetValue(he);
|
sname = (EFNodeName *) HashGetValue(he);
|
||||||
if (sname == NULL) continue; /* Should not happen */
|
if (sname == NULL) continue; /* Should not happen */
|
||||||
|
|
@ -1874,33 +1960,68 @@ topVisit(
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
|
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
|
||||||
|
|
||||||
|
/* Found a node which is also a port */
|
||||||
|
|
||||||
|
portidx = snode->efnode_name->efnn_port;
|
||||||
|
if (portidx >= 0)
|
||||||
|
{
|
||||||
|
if (sorted_ports[portidx] == NULL)
|
||||||
|
{
|
||||||
|
if ((def->def_flags & DEF_ABSTRACT))
|
||||||
|
{
|
||||||
|
EFHNSprintf(stmp, sname->efnn_hier);
|
||||||
|
pname = stmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
||||||
|
|
||||||
|
hep = HashLookOnly(&portNameTable, pname);
|
||||||
|
if (hep == (HashEntry *)NULL)
|
||||||
|
{
|
||||||
|
hep = HashFind(&portNameTable, pname);
|
||||||
|
HashSetValue(hep, (ClientData)(pointertype)portidx);
|
||||||
|
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Node that was unassigned has been found to be
|
||||||
|
* a repeat (see NOTE at top), so make sure its
|
||||||
|
* port number is set correctly.
|
||||||
|
*/
|
||||||
|
snode->efnode_name->efnn_port = (int)(pointertype)HashGetValue(hep);
|
||||||
|
}
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(def->def_flags & DEF_ABSTRACT))
|
||||||
|
heh = HashLookOnly(&efNodeHashTable, (char *)snode->efnode_name->efnn_hier);
|
||||||
|
|
||||||
|
/* Might need to check here for a port that was optimized out? */
|
||||||
|
|
||||||
|
/* If snode is flagged as a port but no port number was found, then
|
||||||
|
* check the all of the node's name entries to see if any of them has
|
||||||
|
* a port number.
|
||||||
|
*/
|
||||||
|
|
||||||
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
||||||
{
|
{
|
||||||
|
if (found == TRUE) break;
|
||||||
portidx = nodeName->efnn_port;
|
portidx = nodeName->efnn_port;
|
||||||
if (portidx < 0) continue;
|
if (portidx < 0) continue;
|
||||||
|
|
||||||
/* Check if the same hierName is recorded in the flattened/optimized
|
|
||||||
* def's efNodeHashTable. If not, then it has been optimized out
|
|
||||||
* and should be removed from the port list.
|
|
||||||
*/
|
|
||||||
if (def->def_flags & DEF_ABSTRACT)
|
|
||||||
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
|
||||||
else
|
|
||||||
heh = HashLookOnly(&efNodeHashTable,
|
|
||||||
(char *)snode->efnode_name->efnn_hier);
|
|
||||||
|
|
||||||
/* If view is abstract, rely on the given port name, not
|
|
||||||
* the node. Otherwise, artifacts of the abstract view
|
|
||||||
* may cause nodes to be merged and the names lost.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (def->def_flags & DEF_ABSTRACT)
|
if (def->def_flags & DEF_ABSTRACT)
|
||||||
{
|
{
|
||||||
|
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
||||||
|
|
||||||
|
/* If view is abstract, rely on the given port name, not
|
||||||
|
* the node. Otherwise, artifacts of the abstract view
|
||||||
|
* may cause nodes to be merged and the names lost.
|
||||||
|
*/
|
||||||
EFHNSprintf(stmp, nodeName->efnn_hier);
|
EFHNSprintf(stmp, nodeName->efnn_hier);
|
||||||
pname = stmp;
|
pname = stmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
|
||||||
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
||||||
|
|
||||||
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
||||||
|
|
@ -1918,7 +2039,10 @@ topVisit(
|
||||||
hep = HashFind(&portNameTable, pname);
|
hep = HashFind(&portNameTable, pname);
|
||||||
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
||||||
if (sorted_ports[portidx] == NULL)
|
if (sorted_ports[portidx] == NULL)
|
||||||
|
{
|
||||||
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1974,6 +2098,92 @@ topVisit(
|
||||||
fprintf(esSpiceF, "\n");
|
fprintf(esSpiceF, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* spcWriteValue ---
|
||||||
|
*
|
||||||
|
* Special handling for CDL format: Output any resistor or capacitor value,
|
||||||
|
* value only, no parameter name.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
spcWriteValue(
|
||||||
|
Dev *dev, /* Dev being output */
|
||||||
|
HierName *hierName) /* Hierarchical path down to this dev */
|
||||||
|
{
|
||||||
|
DevParam *plist;
|
||||||
|
|
||||||
|
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
|
||||||
|
while (plist != NULL)
|
||||||
|
{
|
||||||
|
switch (plist->parm_type[0])
|
||||||
|
{
|
||||||
|
case 'r':
|
||||||
|
if (*(plist->parm_name) == '\0')
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
|
esSIvalue(esSpiceF, (double)dev->dev_res);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (*(plist->parm_name) == '\0')
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
|
esSIvalue(esSpiceF, (double)dev->dev_res);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
plist = plist->parm_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* spcWriteSubParam ---
|
||||||
|
*
|
||||||
|
* Special handling for CDL format: Output any substrate parameter before
|
||||||
|
* the device model. Why this makes sense, I have no idea.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
spcWriteSubParam(
|
||||||
|
Dev *dev, /* Dev being output */
|
||||||
|
HierName *hierName) /* Hierarchical path down to this dev */
|
||||||
|
{
|
||||||
|
bool retval; /* True if substrate parameter was output */
|
||||||
|
DevParam *plist;
|
||||||
|
|
||||||
|
retval = FALSE;
|
||||||
|
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
|
||||||
|
while (plist != NULL)
|
||||||
|
{
|
||||||
|
switch (plist->parm_type[0])
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
if (dev->dev_subsnode == NULL)
|
||||||
|
TxError("Error: No substrate definition for device %s\n",
|
||||||
|
EFDevTypes[dev->dev_type]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
spcdevSubstrate(hierName,
|
||||||
|
dev->dev_subsnode->efnode_name->efnn_hier,
|
||||||
|
dev->dev_type, esSpiceF);
|
||||||
|
retval = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
plist = plist->parm_next;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -1993,7 +2203,8 @@ spcWriteParams(
|
||||||
float scale, /* Scale transform for output */
|
float scale, /* Scale transform for output */
|
||||||
int l, /* Device length, in internal units */
|
int l, /* Device length, in internal units */
|
||||||
int w, /* Device width, in internal units */
|
int w, /* Device width, in internal units */
|
||||||
float sdM) /* Device multiplier */
|
float sdM, /* Device multiplier */
|
||||||
|
bool subdone) /* If TRUE, substrate parameter was already output */
|
||||||
{
|
{
|
||||||
bool hierD;
|
bool hierD;
|
||||||
DevParam *plist, *dparam;
|
DevParam *plist, *dparam;
|
||||||
|
|
@ -2227,10 +2438,19 @@ spcWriteParams(
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
if (!subdone)
|
||||||
/*EFNode *subnodeFlat =*/ spcdevSubstrate(hierName,
|
{
|
||||||
dev->dev_subsnode->efnode_name->efnn_hier,
|
if (dev->dev_subsnode == NULL)
|
||||||
dev->dev_type, esSpiceF);
|
TxError("Error: No substrate definition for device %s\n",
|
||||||
|
EFDevTypes[dev->dev_type]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
spcdevSubstrate(hierName,
|
||||||
|
dev->dev_subsnode->efnode_name->efnn_hier,
|
||||||
|
dev->dev_type, esSpiceF);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
|
@ -2255,12 +2475,18 @@ spcWriteParams(
|
||||||
* scale * esScale * 1.0E-6);
|
* scale * esScale * 1.0E-6);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
if (*(plist->parm_name) != '\0')
|
||||||
fprintf(esSpiceF, "%f", (double)(dev->dev_res));
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
esSIvalue(esSpiceF, (double)dev->dev_res);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
if (*(plist->parm_name) != '\0')
|
||||||
fprintf(esSpiceF, "%ff", (double)(dev->dev_cap));
|
{
|
||||||
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
|
esSIvalue(esSpiceF, (double)dev->dev_cap);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
plist = plist->parm_next;
|
plist = plist->parm_next;
|
||||||
|
|
@ -2326,10 +2552,14 @@ esOutputResistor(
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, " %f", ((double)(dev->dev_res)
|
fprintf(esSpiceF, " %f", ((double)(dev->dev_res)
|
||||||
/ (double)(dscale)) / (double)sdM);
|
/ (double)(dscale)) / (double)sdM);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool subdone = FALSE;
|
||||||
|
spcWriteValue(dev, hierName);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcWriteSubParam(dev, hierName);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
|
|
@ -2342,7 +2572,7 @@ esOutputResistor(
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * (l * scale * esScale) / dscale);
|
esSIvalue(esSpiceF, 1.0E-6 * (l * scale * esScale) / dscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
}
|
}
|
||||||
|
|
@ -2489,6 +2719,7 @@ spcdevVisit(
|
||||||
float sdM;
|
float sdM;
|
||||||
char name[12], devchar;
|
char name[12], devchar;
|
||||||
bool has_model = TRUE;
|
bool has_model = TRUE;
|
||||||
|
bool subdone = FALSE;
|
||||||
HierName *hierName = hc->hc_hierName;
|
HierName *hierName = hc->hc_hierName;
|
||||||
|
|
||||||
sprintf(name, "output");
|
sprintf(name, "output");
|
||||||
|
|
@ -2534,6 +2765,7 @@ spcdevVisit(
|
||||||
case DEV_VERILOGA:
|
case DEV_VERILOGA:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
break;
|
break;
|
||||||
case DEV_DIODE:
|
case DEV_DIODE:
|
||||||
|
|
@ -2631,6 +2863,7 @@ spcdevVisit(
|
||||||
case DEV_SUBCKT:
|
case DEV_SUBCKT:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
devchar = 'X';
|
devchar = 'X';
|
||||||
break;
|
break;
|
||||||
|
|
@ -2672,6 +2905,7 @@ spcdevVisit(
|
||||||
case DEV_VERILOGA:
|
case DEV_VERILOGA:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
fprintf(esSpiceF, "%d", esSbckNum++);
|
fprintf(esSpiceF, "%d", esSbckNum++);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2703,12 +2937,15 @@ spcdevVisit(
|
||||||
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
|
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
|
||||||
name, esSpiceF);
|
name, esSpiceF);
|
||||||
|
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcWriteSubParam(dev, hierName);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_MSUBCKT:
|
case DEV_MSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
|
|
||||||
/* MOS-like subcircuit is "Xnnn drain gate [source [sub]]" */
|
/* MOS-like subcircuit is "Xnnn drain gate [source [sub]]" */
|
||||||
/* to more conveniently handle cases where MOS devices are */
|
/* to more conveniently handle cases where MOS devices are */
|
||||||
|
|
@ -2736,7 +2973,11 @@ spcdevVisit(
|
||||||
/* except that the "gate" node is treated as an identifier */
|
/* except that the "gate" node is treated as an identifier */
|
||||||
/* only and is not output. */
|
/* only and is not output. */
|
||||||
|
|
||||||
if (dev->dev_class != DEV_MSUBCKT)
|
if (dev->dev_class == DEV_DSUBCKT)
|
||||||
|
{
|
||||||
|
/* Do nothing: Both terminals have already been output */
|
||||||
|
}
|
||||||
|
else if (dev->dev_class != DEV_MSUBCKT)
|
||||||
{
|
{
|
||||||
if (dev->dev_nterm > 1)
|
if (dev->dev_nterm > 1)
|
||||||
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
|
spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier,
|
||||||
|
|
@ -2777,12 +3018,15 @@ spcdevVisit(
|
||||||
subnode->efnode_name->efnn_hier,
|
subnode->efnode_name->efnn_hier,
|
||||||
dev->dev_type, esSpiceF);
|
dev->dev_type, esSpiceF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CDL format support: Output a slash followed by a space. */
|
||||||
|
if (esFormat == CDL) fprintf(esSpiceF, " /");
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
/* Write all requested parameters to the subcircuit call. */
|
/* Write all requested parameters to the subcircuit call. */
|
||||||
|
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2848,9 +3092,12 @@ spcdevVisit(
|
||||||
spcdevOutNode(hierName, subnode->efnode_name->efnn_hier,
|
spcdevOutNode(hierName, subnode->efnode_name->efnn_hier,
|
||||||
name, esSpiceF);
|
name, esSpiceF);
|
||||||
|
|
||||||
|
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcWriteSubParam(dev, hierName);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_NDIODE:
|
case DEV_NDIODE:
|
||||||
|
|
@ -2866,9 +3113,11 @@ spcdevVisit(
|
||||||
spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier,
|
spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier,
|
||||||
name, esSpiceF);
|
name, esSpiceF);
|
||||||
|
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcWriteSubParam(dev, hierName);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
sdM = getCurDevMult();
|
sdM = getCurDevMult();
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
|
|
@ -2891,11 +3140,15 @@ spcdevVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
spcWriteValue(dev, hierName);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcWriteSubParam(dev, hierName);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
|
|
@ -2908,7 +3161,7 @@ spcdevVisit(
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
}
|
}
|
||||||
|
|
@ -2934,11 +3187,15 @@ spcdevVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
spcWriteValue(dev, hierName);
|
||||||
|
if (esFormat == CDL)
|
||||||
|
subdone = spcWriteSubParam(dev, hierName);
|
||||||
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
|
||||||
|
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
|
|
@ -2951,7 +3208,7 @@ spcdevVisit(
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, subdone);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
}
|
}
|
||||||
|
|
@ -2999,7 +3256,7 @@ spcdevVisit(
|
||||||
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
esSIvalue(esSpiceF, 1.0E-6 * l * scale * esScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
if (sdM != 1.0)
|
if (sdM != 1.0)
|
||||||
fprintf(esSpiceF, " M=%g", sdM);
|
fprintf(esSpiceF, " M=%g", sdM);
|
||||||
|
|
||||||
|
|
@ -3118,12 +3375,15 @@ spcdevSubstrate(
|
||||||
/* Canonical name */
|
/* Canonical name */
|
||||||
nn = (EFNodeName *) HashGetValue(he);
|
nn = (EFNodeName *) HashGetValue(he);
|
||||||
if (outf)
|
if (outf)
|
||||||
fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier,
|
{
|
||||||
NULL));
|
const char *spicename;
|
||||||
|
spicename = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL);
|
||||||
|
fprintf(outf, "%s", spicename);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create node client if it doesn't exist */
|
/* Create node client if it doesn't exist */
|
||||||
if ((nodeClient *)nn->efnn_node->efnode_client == (nodeClient *)NULL)
|
if ((nodeClient *)nn->efnn_node->efnode_client == (nodeClient *)NULL)
|
||||||
initNodeClientHier(nn->efnn_node);
|
initNodeClient(nn->efnn_node);
|
||||||
|
|
||||||
/* Mark node as visited (set bit one higher than number of resist classes) */
|
/* Mark node as visited (set bit one higher than number of resist classes) */
|
||||||
if (esDistrJunct)
|
if (esDistrJunct)
|
||||||
|
|
@ -4260,6 +4520,7 @@ parallelDevs(
|
||||||
case DEV_VERILOGA:
|
case DEV_VERILOGA:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
case DEV_DSUBCKT:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_VOLT:
|
case DEV_VOLT:
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ typedef struct {
|
||||||
#define SPICE3 1
|
#define SPICE3 1
|
||||||
#define HSPICE 2
|
#define HSPICE 2
|
||||||
#define NGSPICE 3
|
#define NGSPICE 3
|
||||||
|
#define CDL 4
|
||||||
|
|
||||||
#define AUTO 2 /* TRUE | FALSE | AUTO for esDoSubckt */
|
#define AUTO 2 /* TRUE | FALSE | AUTO for esDoSubckt */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -754,8 +754,9 @@ antennacheckVisit(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaMarkFunc(tile, ams)
|
areaMarkFunc(tile, dinfo, ams)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
AntennaMarkStruct *ams;
|
AntennaMarkStruct *ams;
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -778,8 +779,9 @@ areaMarkFunc(tile, ams)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaAccumFunc(tile, gdas)
|
areaAccumFunc(tile, dinfo, gdas)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
GateDiffAccumStruct *gdas;
|
GateDiffAccumStruct *gdas;
|
||||||
{
|
{
|
||||||
Rect *rect = &(gdas->r);
|
Rect *rect = &(gdas->r);
|
||||||
|
|
@ -788,7 +790,7 @@ areaAccumFunc(tile, gdas)
|
||||||
|
|
||||||
/* Avoid double-counting the area of contacts */
|
/* Avoid double-counting the area of contacts */
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
|
|
||||||
|
|
@ -798,6 +800,7 @@ areaAccumFunc(tile, gdas)
|
||||||
|
|
||||||
TiToRect(tile, rect);
|
TiToRect(tile, rect);
|
||||||
area = (dlong)(rect->r_xtop - rect->r_xbot) * (dlong)(rect->r_ytop - rect->r_ybot);
|
area = (dlong)(rect->r_xtop - rect->r_xbot) * (dlong)(rect->r_ytop - rect->r_ybot);
|
||||||
|
if (IsSplit(tile)) area /= 2;
|
||||||
gdas->accum += area;
|
gdas->accum += area;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -816,8 +819,9 @@ areaAccumFunc(tile, gdas)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
antennaAccumFunc(tile, aaptr)
|
antennaAccumFunc(tile, dinfo, aaptr)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* Not used, but should be handled */
|
||||||
AntennaAccumStruct *aaptr;
|
AntennaAccumStruct *aaptr;
|
||||||
{
|
{
|
||||||
Rect *rect = &(aaptr->r);
|
Rect *rect = &(aaptr->r);
|
||||||
|
|
@ -1003,6 +1007,7 @@ antennaAccumFunc(tile, aaptr)
|
||||||
TiToRect(tile, rect);
|
TiToRect(tile, rect);
|
||||||
area = (dlong)(rect->r_xtop - rect->r_xbot)
|
area = (dlong)(rect->r_xtop - rect->r_xbot)
|
||||||
* (dlong)(rect->r_ytop - rect->r_ybot);
|
* (dlong)(rect->r_ytop - rect->r_ybot);
|
||||||
|
if (IsSplit(tile)) area /= 2;
|
||||||
|
|
||||||
typeareas[type] += area;
|
typeareas[type] += area;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue