Compare commits

..

No commits in common. "master" and "8.3.615" have entirely different histories.

183 changed files with 2626 additions and 9666 deletions

View File

@ -138,8 +138,6 @@ 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

View File

@ -1,12 +1,14 @@
# CI for native ARM64 Linux build. # This is a basic workflow to help you get started with Actions
name: CI-aarch64 name: CI-aarch64
# Controls when the workflow will run
on: on:
push: push:
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs: jobs:
simple_build_linux_arm: simple_build_linux_arm:
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
@ -21,3 +23,27 @@ jobs:
./configure ./configure
make database/database.h make database/database.h
make -j$(nproc) 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: Build
run: |
source ./emsdk/emsdk_env.sh
emconfigure ./configure --without-cairo --without-opengl --without-x --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

View File

@ -1,256 +0,0 @@
name: CI-wasm
# Builds the Magic WebAssembly target (both the non-TCL and TCL variants)
# on every push and pull request as a CI check. **Publishing** only happens
# when a release tag of the form <x.y.z>... (optionally v-prefixed) is
# pushed — the same tag that triggers the AppImage release workflows:
#
# # bump magic/VERSION, commit, push to default branch
# git tag 8.3.638
# git push origin 8.3.638
#
# The tag name (minus any leading "v") provides the base; the workflow appends
# the commit date and short SHA: 8.3.799 → 8.3.799020261231+git01234cde.
# Forks publish under their own namespace via the @<owner>/ scope.
on:
push:
pull_request:
workflow_dispatch:
inputs:
emsdk_version:
description: 'emsdk version to build with (default: latest; pin a version number to bisect)'
type: string
default: 'latest'
tcl_ref:
description: 'TCL ref to build against (default: auto-resolve latest stable tag). Use a tag like core-9-0-3, a branch, or a commit SHA to bisect a regression.'
type: string
default: ''
tcl_repo_url:
description: 'TCL repository URL (default: https://github.com/tcltk/tcl.git)'
type: string
default: ''
dry_run:
description: 'Dry run: pack only, do not publish even on tag pushes'
type: boolean
default: true
# actions/upload-artifact@v5 still runs on Node.js 20. Force Node 24 to
# silence the deprecation warning until upload-artifact ships a Node-24
# release. Drop this once upgraded.
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
packages: write
jobs:
build-wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 2
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: '22'
registry-url: 'https://npm.pkg.github.com'
- name: Install emsdk
env:
# Defaults to latest so CI tracks emsdk HEAD and catches breakage early.
# Override via workflow_dispatch to pin a specific version when needed
# (e.g. to bisect a regression or verify a post-build.sh patch still applies).
EMSDK_VERSION: ${{ github.event.inputs.emsdk_version || 'latest' }}
run: |
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install "$EMSDK_VERSION"
./emsdk activate "$EMSDK_VERSION"
# Dump native + emscripten preprocessor defines. Useful for diagnosing
# WASM-build differences after an emsdk bump.
- 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
# Determine which TCL ref to build against.
# Priority: workflow_dispatch input > auto-resolved latest stable tag.
# TCL stable releases follow the core-<major>-<even_minor>-<patch>
# naming convention; core-9-0-x is the current stable series.
# Falls back to main only if no release tags are found at all.
- name: Resolve TCL ref
id: resolve-tcl
env:
TCL_REPO_URL: ${{ github.event.inputs.tcl_repo_url || 'https://github.com/tcltk/tcl.git' }}
TCL_REF_INPUT: ${{ github.event.inputs.tcl_ref || '' }}
run: |
if [ -n "$TCL_REF_INPUT" ]; then
TCL_REF="$TCL_REF_INPUT"
echo "Using workflow_dispatch TCL_REF: $TCL_REF"
else
TCL_REF=$(git ls-remote --tags --sort=-version:refname "$TCL_REPO_URL" \
'refs/tags/core-9-0-*' \
| grep -v '\^{}' \
| head -1 \
| awk '{print $2}' \
| sed 's|refs/tags/||')
if [ -z "$TCL_REF" ]; then
TCL_REF=main
echo "Warning: no stable core-9-0-x tag found, falling back to main"
else
echo "Auto-resolved latest stable TCL tag: $TCL_REF"
fi
fi
echo "tcl_ref=$TCL_REF" >> "$GITHUB_OUTPUT"
echo "tcl_repo_url=$TCL_REPO_URL" >> "$GITHUB_OUTPUT"
# Clone tcltk/tcl into a sibling directory at the resolved ref.
# Done as an explicit step so the exact commit is visible in the job
# log. The source tree is read-only — the WASM build runs inside magic.
- name: Clone tcltk/tcl
env:
TCL_REPO_URL: ${{ steps.resolve-tcl.outputs.tcl_repo_url }}
TCL_REF: ${{ steps.resolve-tcl.outputs.tcl_ref }}
run: |
# autocrlf=false: ubuntu-latest is already LF, but make it explicit.
git -c core.autocrlf=false clone "$TCL_REPO_URL" ../tcl
cd ../tcl
git checkout --detach "$TCL_REF"
echo "=== TCL commit ==="
git log -n1 --format="commit %H%nauthor %an <%ae>%ndate %ci%nref %D%n%n %s"
- name: Build WASM — both variants (tcl + notcl)
env:
TCL_REF: ${{ steps.resolve-tcl.outputs.tcl_ref }}
TCL_REPO_URL: ${{ steps.resolve-tcl.outputs.tcl_repo_url }}
run: |
source ./emsdk/emsdk_env.sh
bash npm/build.sh --variant=both
- name: Run example tests (non-TCL variant)
run: cd npm && npm test
- name: Run full test suite (TCL variant)
run: cd npm && npm run test:tcl
# Dump generated text outputs (.ext, .spice, .cif, …) into the CI log
# so a regression in extraction / netlisting / cifoutput is visible
# without having to download artifacts. The .gds output is binary —
# skip it and just record its size.
- name: Display example outputs
run: |
shopt -s nullglob
for dir in npm/examples/output npm/examples/output-tcl; do
[ -d "$dir" ] || continue
echo "======== $dir ========"
for f in "$dir"/*; do
name=$(basename "$f")
case "$f" in
*.gds) echo "===== $name (binary, $(wc -c < "$f") bytes — skipped) =====" ;;
*) echo "===== $name ====="; cat "$f" ;;
esac
done
done
# The release gate. We publish a new npm version only when a tag of the
# shape <x.y.z>... (optionally v-prefixed) is pushed, matching the
# AppImage release workflows so one tag releases everything.
#
# Version scheme (per dmiles' recommendation):
# {MAJOR}.{MINOR}.{PATCH}0{YYYYMMDD}+git{SHORT_SHA}
# e.g. 8.3.799 pushed on 2026-12-31 → 8.3.799020261231+git01234cde
#
# The leading zero between PATCH and date keeps the number readable and
# ensures correct numeric ordering: 799020261231 < 800020261231.
# Build metadata (+git...) is ignored by npm for comparison but retained
# for traceability. Security patches for the 799 series can be inserted
# as later dates (799020270101, 799020270201, …) and are matched by the
# range <=8.3.799900000000 or <8.3.8000000000000.
- name: Determine release version (tag-driven only)
id: release
run: |
date=$(git show -s --format=%cs | tr -d '-')
hash=$(git show -s --format=%h)
if [ "${{ github.event_name }}" = "push" ] && \
echo "${{ github.ref }}" | grep -Eq '^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+'; then
tag="${GITHUB_REF#refs/tags/}"
base="${tag#v}"
echo "publish=true" >> "$GITHUB_OUTPUT"
echo "version=${base}0${date}+git${hash}" >> "$GITHUB_OUTPUT"
echo "Tag release: $tag → npm version ${base}0${date}+git${hash}"
else
base=$(cat VERSION)
echo "publish=false" >> "$GITHUB_OUTPUT"
echo "version=${base}0${date}+git${hash}" >> "$GITHUB_OUTPUT"
echo "Non-tag build: will not publish."
fi
- name: Set package version and scope
env:
VERSION: ${{ steps.release.outputs.version }}
run: |
# Scope the package to the repo owner so it lands in the right
# GitHub Packages namespace regardless of who hosts the repo.
SCOPED_NAME="@${{ github.repository_owner }}/magic-vlsi-wasm"
cd npm
npm pkg set name="$SCOPED_NAME"
npm pkg set publishConfig.registry="https://npm.pkg.github.com"
npm version "$VERSION" --no-git-tag-version --allow-same-version
- name: Pack
run: ./npm/pack.sh
- name: Upload tarball as artifact
uses: actions/upload-artifact@v5
with:
name: magic-vlsi-wasm-npm
path: npm/*.tgz
- name: Publish to GitHub Packages
if: steps.release.outputs.publish == 'true' && github.event.inputs.dry_run != 'true'
run: cd npm && npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Write a Markdown summary visible next to the artifacts on the Actions
# page. Captures the exact versions used so a future regression can be
# bisected without scrolling through raw logs.
- name: Build summary
if: always()
env:
TCL_REF: ${{ steps.resolve-tcl.outputs.tcl_ref }}
TCL_REPO_URL: ${{ steps.resolve-tcl.outputs.tcl_repo_url }}
run: |
source ./emsdk/emsdk_env.sh 2>/dev/null || true
EMCC_VER=$(emcc --version 2>/dev/null | head -1 || echo "unavailable")
GCC_VER=$(gcc --version 2>/dev/null | head -1 || echo "unavailable")
NODE_VER=$(node --version 2>/dev/null || echo "unavailable")
MAGIC_VER=$(cat VERSION 2>/dev/null || echo "unavailable")
if [ -d ../tcl/.git ]; then
TCL_SHA=$(cd ../tcl && git rev-parse HEAD)
TCL_DATE=$(cd ../tcl && git log -1 --format="%ci")
TCL_SUBJECT=$(cd ../tcl && git log -1 --format="%s")
else
TCL_SHA="(not cloned)"; TCL_DATE=""; TCL_SUBJECT=""
fi
printf '## Build info\n\n' >> "$GITHUB_STEP_SUMMARY"
printf '| Component | Details |\n' >> "$GITHUB_STEP_SUMMARY"
printf '|-----------|----------|\n' >> "$GITHUB_STEP_SUMMARY"
printf '| Magic | `%s` |\n' "$MAGIC_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| Emscripten | %s |\n' "$EMCC_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| GCC | %s |\n' "$GCC_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| Node.js | %s |\n' "$NODE_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL repo | %s |\n' "$TCL_REPO_URL" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL ref | `%s` |\n' "$TCL_REF" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL commit | `%s` |\n' "$TCL_SHA" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL date | %s |\n' "$TCL_DATE" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL subject | %s |\n' "$TCL_SUBJECT" >> "$GITHUB_STEP_SUMMARY"

View File

@ -1,21 +1,61 @@
# This is a basic workflow to help you get started with Actions
name: CI name: CI
# Controls when the workflow will run
on: on:
push: push:
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs: jobs:
simple_build_linux: vezzal:
# The type of runner that the job will run on
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps: steps:
- uses: actions/checkout@v5 - 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:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Get Dependencies - name: Get Dependencies
run: | run: |
sudo apt-get update
sudo apt-get install -y tcl-dev tk-dev libcairo-dev sudo apt-get install -y tcl-dev tk-dev libcairo-dev
- name: Build - name: Build
run: | run: |
./configure ./configure
make database/database.h make database/database.h
make -j$(nproc) make -j$(nproc)
simple_build_wasm:
runs-on: ubuntu-22.04
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: Build
run: |
source ./emsdk/emsdk_env.sh
emconfigure ./configure --without-cairo --without-opengl --without-x --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
path: |
${{ github.workspace }}/magic/magic.wasm

47
.gitignore vendored
View File

@ -1,33 +1,19 @@
# Autoconf / configure outputs
defs.mak defs.mak
!toolchains/emscripten/defs.mak */Depend
config.cache config.cache
config.log config.log
scripts/config.log scripts/config.log
scripts/config.status scripts/config.status
scripts/defs.mak scripts/defs.mak
install.log
make.log
reconfigure.sh
# Compiled objects / libraries
*.o
*.a
*.so
*/Depend
database/database.h
# Editor / OS cruft
.*.swp .*.swp
.*.swo *.o
*.so
*~ *~
.DS_Store
.vscode/
.idea/
# Magic runtime-generated files
magic/proto.magicrc
scmos/cif_template/objs/* scmos/cif_template/objs/*
database/database.h
install.log
magic/proto.magicrc
make.log
scmos/gdsquery.tech scmos/gdsquery.tech
scmos/minimum.tech scmos/minimum.tech
scmos/scmos-sub.tech scmos/scmos-sub.tech
@ -35,29 +21,14 @@ scmos/scmos-tm.tech
scmos/scmos.tech scmos/scmos.tech
scmos/scmosWR.tech scmos/scmosWR.tech
scmos/nmos.tech scmos/nmos.tech
# Native build artifacts
magic/magic
magic/tclmagic.dylib
tcltk/magic.sh tcltk/magic.sh
tcltk/magic.tcl tcltk/magic.tcl
tcltk/magicdnull tcltk/magicdnull
tcltk/magicexec tcltk/magicexec
tcltk/ext2spice.sh tcltk/ext2spice.sh
tcltk/ext2sim.sh tcltk/ext2sim.sh
magic/tclmagic.dylib
tcltk/magicdnull.dSYM/ tcltk/magicdnull.dSYM/
tcltk/magicexec.dSYM/ tcltk/magicexec.dSYM/
reconfigure.sh
pfx/ pfx/
# WASM build artifacts
magic/magic.js
magic/magic.js.symbols
magic/magic.symbols
magic/magic.wasm
build-tcl-wasm/
net2ir/net2ir
net2ir/net2ir.js
net2ir/net2ir.wasm
# Generated test output
npm/examples/output/

View File

@ -1 +1 @@
8.3.664 8.3.615

View File

@ -789,8 +789,8 @@ 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, angle; int xlo, ylo, xhi, yhi, xsep, ysep;
bool madeinst = FALSE, rotated = FALSE; bool madeinst = FALSE;
char *sname = NULL; char *sname = NULL;
bool isArray = FALSE; bool isArray = FALSE;
bool dolookahead = FALSE; bool dolookahead = FALSE;
@ -990,14 +990,6 @@ 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
@ -1008,7 +1000,6 @@ calmaElementSref(
* is problematic, and probably incorrect. * is problematic, and probably incorrect.
*/ */
for (n = 0; n < nref; n++) for (n = 0; n < nref; n++)
{ {
savescale = calmaReadScale1; savescale = calmaReadScale1;
@ -1020,17 +1011,17 @@ calmaElementSref(
* them as needed. * them as needed.
*/ */
if ((n > 0) && ((!rotated && (rows == 1)) || (rotated && (cols == 1)))) if ((n > 0) && (rows == 1))
{ {
calmaReadX(&refarray[n], 1); calmaReadX(&refarray[n], 1);
calmaSkipBytes(4); calmaSkipBytes(4);
refarray[n].p_y = refarray[0].p_y; refarray[n].p_y = 0;
} }
else if ((n > 0) && ((!rotated && (cols == 1)) || (rotated && (rows == 1)))) else if ((n > 0) && (cols == 1))
{ {
calmaSkipBytes(4); calmaSkipBytes(4);
calmaReadY(&refarray[n], 1); calmaReadY(&refarray[n], 1);
refarray[n].p_x = refarray[0].p_x; refarray[n].p_x = 0;
} }
else else
calmaReadPoint(&refarray[n], 1); calmaReadPoint(&refarray[n], 1);

View File

@ -537,6 +537,7 @@ calmaElementPath(void)
int layer, dt, width, pathtype, ciftype, savescale; int layer, dt, width, pathtype, ciftype, savescale;
int xmin, ymin, xmax, ymax, temp; int xmin, ymin, xmax, ymax, temp;
CIFPath *pathheadp, *pathp, *previousp; CIFPath *pathheadp, *pathp, *previousp;
Rect segment;
Plane *plane; Plane *plane;
int first,last; int first,last;
CellUse *use; CellUse *use;

View File

@ -112,7 +112,7 @@ bool CalmaUnique = FALSE; /* If TRUE, then if a cell exists in
extern bool CalmaDoLibrary; /* Also used by GDS write */ extern bool CalmaDoLibrary; /* Also used by GDS write */
extern void calmaUnexpected(int wanted, int got); extern void calmaUnexpected(int wanted, int got);
extern int calmaWriteInitFunc(CellDef *def, ClientData cdata); /* UNUSED */ extern int calmaWriteInitFunc(CellDef *def);
/* /*
* Scaling. * Scaling.

View File

@ -96,7 +96,7 @@ typedef struct {
} calmaOutputStruct; } calmaOutputStruct;
/* Forward declarations */ /* Forward declarations */
extern int calmaWriteInitFunc(CellDef *def, ClientData cdata); /* UNUSED */ extern int calmaWriteInitFunc(CellDef *def);
extern int calmaWritePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos); extern int calmaWritePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
extern int calmaMergePaintFunc(Tile *tile, TileType dinfo, 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);
@ -822,11 +822,9 @@ done:
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
calmaWriteInitFunc( calmaWriteInitFunc(
CellDef *def, CellDef *def)
ClientData cdata) /* UNUSED */
{ {
def->cd_client = (ClientData) 0; def->cd_client = (ClientData) 0;
return (0); return (0);

View File

@ -96,7 +96,7 @@ extern int calmaPaintLayerNumber;
extern int calmaPaintLayerType; extern int calmaPaintLayerType;
/* External functions from CalmaWrite.c */ /* External functions from CalmaWrite.c */
extern int calmaWriteInitFunc(CellDef *def, ClientData cdata); /* UNUSED */ extern int calmaWriteInitFunc(CellDef *def);
/* Structure used by calmaWritePaintFuncZ() and others */ /* Structure used by calmaWritePaintFuncZ() and others */

View File

@ -25,7 +25,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include <stdlib.h> /* for abs() */ #include <stdlib.h> /* for abs() */
#include <math.h> /* for ceil() and sqrt() */ #include <math.h> /* for ceil() and sqrt() */
#include <ctype.h> #include <ctype.h>
#include <string.h> /* for strcmp() */
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
@ -4117,7 +4116,7 @@ cifSrTiles(
* one or more times for the planes being used in processing * one or more times for the planes being used in processing
* where the CIF search should be conducted over "area" scaled * where the CIF search should be conducted over "area" scaled
* to CIF units, rather than the entire plane. Currently used * to CIF units, rather than the entire plane. Currently used
* only for operators CIFOP_INTERACT and CIFOP_TAGGED. * only for operator CIFOP_INTERACT.
* *
* Results: * Results:
* Returns the value returned by the function. * Returns the value returned by the function.
@ -4171,21 +4170,12 @@ cifSrTiles2(
} }
cifScale = 1; cifScale = 1;
if (TTMaskIsZero(&cifOp->co_cifMask) && TTMaskIsZero(&cifOp->co_paintMask))
{
/* Current CIF plane is in *temps */
if (DBSrPaintArea((Tile *)NULL, *temps, area,
&CIFSolidBits, func, (ClientData)cdArg))
return 1;
}
else
{
for (t = 0; t < TT_MAXTYPES; t++, temps++) for (t = 0; t < TT_MAXTYPES; t++, temps++)
if (TTMaskHasType(&cifOp->co_cifMask, t)) if (TTMaskHasType(&cifOp->co_cifMask, t))
if (DBSrPaintArea((Tile *)NULL, *temps, area, if (DBSrPaintArea((Tile *)NULL, *temps, area,
&CIFSolidBits, func, (ClientData)cdArg)) &CIFSolidBits, func, (ClientData)cdArg))
return 1; return 1;
}
return 0; return 0;
} }
@ -5054,47 +5044,6 @@ cifInteractingRegions(
} }
} }
/*
* ----------------------------------------------------------------------------
*
* cifCopyPropPlaneFunc --
*
* Copy the contents of a plane saved as a plane-type property into the
* current CIF plane. The property plane is in magic internal
* coordinates, so each tile needs to be scaled and redrawn into the
* current CIF plane.
*
* Results:
* Zero to keep the search going
*
* Side effects:
* Copies translated geometry into the target plane.
*
* ----------------------------------------------------------------------------
*/
int
cifCopyPropPlaneFunc(Tile *tile,
TileType dinfo,
Plane *curPlane)
{
Rect bbox;
TiToRect(tile, &bbox);
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
bbox.r_xbot *= cifScale;
bbox.r_ybot *= cifScale;
bbox.r_xtop *= cifScale;
bbox.r_ytop *= cifScale;
cifScale = 1;
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
CIFPaintTable, (PaintUndoInfo *)NULL);
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -5146,13 +5095,12 @@ CIFGenLayer(
CIFSquaresInfo csi; CIFSquaresInfo csi;
SearchContext scx; SearchContext scx;
TileType ttype; TileType ttype;
char *netname, *text; char *netname;
Label *label;
BloatStruct bls; BloatStruct bls;
BridgeStruct brs; BridgeStruct brs;
BridgeLimStruct brlims; BridgeLimStruct brlims;
BridgeData *bridge; BridgeData *bridge;
BloatData *bloats, locbloat; BloatData *bloats;
bool hstop = FALSE; bool hstop = FALSE;
PropertyRecord *proprec; PropertyRecord *proprec;
char *propvalue; char *propvalue;
@ -5463,6 +5411,7 @@ CIFGenLayer(
if (bloats->bl_plane < 0) /* Bloat types are CIF types */ if (bloats->bl_plane < 0) /* Bloat types are CIF types */
{ {
bls.temps = temps;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++) for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++)
if (bloats->bl_distance[ttype] > 0) if (bloats->bl_distance[ttype] > 0)
(void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect, (void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect,
@ -5470,12 +5419,9 @@ CIFGenLayer(
(ClientData)NULL); (ClientData)NULL);
} }
else else
{
TTMaskSetMask(&bls.connect, &op->co_paintMask);
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane], DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
&TiPlaneRect, &bls.connect, cifProcessResetFunc, &TiPlaneRect, &bls.connect, cifProcessResetFunc,
(ClientData)NULL); (ClientData)NULL);
}
break; break;
@ -5614,149 +5560,6 @@ CIFGenLayer(
} }
break; break;
case CIFOP_TAGGED:
if (hier)
{
hstop = TRUE; /* Stop hierarchical processing */
break;
}
/*
* Find all relevant labels by text matching and then continue
* like CIFOP_BLOATALL. CIFOP_BLOATALL uses a BloatData record
* which is not part of CIFOP_TAGGED. Create a BloatData record
* on the fly for each tagged area based on type, and swap it for
* the text, so that cifBloatAllFunc believes this is actually a
* CIFOP_BLOATALL operation. Note that we don't actually care
* what layer the label is attached to (lab_type). We are looking
* for labels whose lab_rect values overlap the types that are given
* in the rule.
*/
cifPlane = curPlane;
bls.op = op;
bls.def = cellDef;
bls.temps = temps;
text = (char *)op->co_client;
bloats = &locbloat;
if (!TTMaskIsZero(&op->co_cifMask))
{
bloats->bl_plane = -1;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
{
if (TTMaskHasType(&op->co_cifMask, ttype))
bloats->bl_distance[ttype] = 1;
else
bloats->bl_distance[ttype] = 0;
}
}
else if (!TTMaskIsZero(&op->co_paintMask))
{
int plane, pmask;
pmask = DBTechTypesToPlanes(&op->co_paintMask);
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
if (PlaneMaskHasPlane(pmask, plane))
break;
bloats->bl_plane = plane;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
{
if (TTMaskHasType(&op->co_paintMask, ttype))
bloats->bl_distance[ttype] = 1;
else
bloats->bl_distance[ttype] = 0;
}
}
else
{
/* Operate on the existing plane. */
bloats->bl_distance[0] = 1;
for (ttype = 1; ttype < TT_MAXTYPES; ttype++)
bloats->bl_distance[ttype] = 0;
bloats->bl_plane = -1;
bls.temps = &curPlane;
DBClearPaintPlane(nextPlane);
cifPlane = nextPlane;
}
/* Replace the client data with the bloat record */
op->co_client = (ClientData)bloats;
if (bloats->bl_plane < 0)
{
/* bl_plane == -1 indicates bloating into a CIF templayer, */
/* so the only connecting type should be CIF_SOLIDTYPE. */
TTMaskSetOnlyType(&bls.connect, CIF_SOLIDTYPE);
}
else
{
int i;
TTMaskZero(&bls.connect);
for (i = 0; i < TT_MAXTYPES; i++)
if (bloats->bl_distance[i] != 0)
TTMaskSetType(&bls.connect, i);
}
for (label = cellDef->cd_labels; label; label = label->lab_next)
{
if (!strcmp(label->lab_text, text))
{
Rect labr = label->lab_rect;
/* Since cifSrTiles2() searches over an area, the
* area must not be degenerate.
*/
if (labr.r_xbot == labr.r_xtop)
{
labr.r_xbot--;
labr.r_xtop++;
}
if (labr.r_ybot == labr.r_ytop)
{
labr.r_ybot--;
labr.r_ytop++;
}
cifSrTiles2(op, &labr, cellDef, bls.temps,
cifBloatAllFunc, (ClientData)&bls);
}
}
/* Reset marked tiles */
if (bloats->bl_plane < 0) /* Bloat types are CIF types */
{
for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++)
if (bloats->bl_distance[ttype] > 0)
(void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect,
&CIFSolidBits, cifProcessResetFunc,
(ClientData)NULL);
}
else
{
TTMaskSetMask(&bls.connect, &op->co_paintMask);
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
(ClientData)NULL);
}
/* Replace the client data */
op->co_client = (ClientData)text;
/* If operating on the current plane, swap the current
* and next planes.
*/
if (TTMaskIsZero(&op->co_cifMask) && TTMaskIsZero(&op->co_paintMask))
{
temp = curPlane;
curPlane = nextPlane;
nextPlane = temp;
}
break;
case CIFOP_BOUNDARY: case CIFOP_BOUNDARY:
if (hier) if (hier)
{ {
@ -5843,7 +5646,6 @@ CIFGenLayer(
int n; int n;
char propname[512]; char propname[512];
char *layername = (char *)op->co_client; char *layername = (char *)op->co_client;
Tile *t;
snprintf(propname, 512, "MASKHINTS_%s", layername); snprintf(propname, 512, "MASKHINTS_%s", layername);
@ -5851,11 +5653,30 @@ CIFGenLayer(
proprec = DBPropGet(cellDef, propname, &found); proprec = DBPropGet(cellDef, propname, &found);
if (!found) break; /* No mask hints available */ if (!found) break; /* No mask hints available */
ASSERT (proprec->prop_type == PROPERTY_TYPE_PLANE, "CIFGenLayer"); if (proprec->prop_type == PROPERTY_TYPE_DIMENSION)
t = PlaneGetHint(proprec->prop_value.prop_plane); {
DBSrPaintArea(t, proprec->prop_value.prop_plane, for (n = 0; n < proprec->prop_len; n += 4)
&TiPlaneRect, &CIFSolidBits, {
cifCopyPropPlaneFunc, (ClientData)curPlane); if ((n + 3) >= proprec->prop_len) break;
cifPlane = curPlane;
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
bbox.r_xbot = proprec->prop_value.prop_integer[n];
bbox.r_ybot = proprec->prop_value.prop_integer[n + 1];
bbox.r_xtop = proprec->prop_value.prop_integer[n + 2];
bbox.r_ytop = proprec->prop_value.prop_integer[n + 3];
bbox.r_xbot *= cifScale;
bbox.r_ybot *= cifScale;
bbox.r_xtop *= cifScale;
bbox.r_ytop *= cifScale;
cifScale = 1;
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
CIFPaintTable, (PaintUndoInfo *)NULL);
}
}
} }
break; break;

View File

@ -209,52 +209,16 @@ typedef struct _maskHintsData
{ {
Transform *mh_trans; Transform *mh_trans;
CellDef *mh_def; CellDef *mh_def;
Plane *mh_plane;
} MaskHintsData; } MaskHintsData;
/*
* ----------------------------------------------------------------------------
*
* cifCopyMaskHintFunc --
*
* Callback function used by cifFlatMaskHints. Transforms a tile
* from the original plane and paints it into the target plane,
* both of which are properties.
*
* Results:
* Zero to keep the search going.
*
* Side effects:
* Paints geometry into the target plane.
*
* ----------------------------------------------------------------------------
*/
int
cifCopyMaskHintFunc(Tile *tile,
TileType dinfo,
ClientData cdata)
{
MaskHintsData *mhd = (MaskHintsData *)cdata;
Rect r, newr;
TiToRect(tile, &r);
/* Transform tile area to coordinates of mhd->mh_plane and paint */
GeoTransRect(mhd->mh_trans, &r, &newr);
DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL);
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* 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 painting it into the * coordinate system of the flattened cell, and adding it to the
* property plane of the flattened cell. * property list of the flattened cell.
* *
* Returns: * Returns:
* 0 to keep the search going. * 0 to keep the search going.
@ -276,7 +240,6 @@ cifFlatMaskHints(
bool propfound; bool propfound;
int i, lastlen, numvals; int i, lastlen, numvals;
PropertyRecord *newproprec, *oldproprec; PropertyRecord *newproprec, *oldproprec;
Plane *plane;
if (!strncmp(name, "MASKHINTS_", 10)) if (!strncmp(name, "MASKHINTS_", 10))
{ {
@ -284,24 +247,53 @@ cifFlatMaskHints(
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound); oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
if (propfound) if (propfound)
{ {
ASSERT(oldproprec->prop_type == PROPERTY_TYPE_PLANE, newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
"cifFlatMaskHints"); (oldproprec->prop_len + proprec->prop_len - 2) * sizeof(int));
plane = oldproprec->prop_value.prop_plane; newproprec->prop_len = oldproprec->prop_len + proprec->prop_len;
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
} }
else else
{ {
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
newproprec->prop_len = 0; /* (unused) */ (proprec->prop_len - 2) * sizeof(int));
newproprec->prop_type = PROPERTY_TYPE_PLANE; newproprec->prop_len = proprec->prop_len;
plane = DBNewPlane((ClientData)TT_SPACE); newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
newproprec->prop_value.prop_plane = plane;
DBPropPut(mhd->mh_def, name, newproprec);
} }
mhd->mh_plane = plane; for (i = 0; i < proprec->prop_len; i += 4)
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane, {
&TiPlaneRect, &CIFSolidBits, /* There should be a multiple of 4 values but avoid an array overrun
cifCopyMaskHintFunc, (ClientData)mhd); * if not.
*/
if ((i + 3) >= proprec->prop_len)
{
TxError("MASKHINTS_%s: Expected 4 values, found only %d\n",
name + 10, numvals);
break;
}
r.r_xbot = proprec->prop_value.prop_integer[i];
r.r_ybot = proprec->prop_value.prop_integer[i + 1];
r.r_xtop = proprec->prop_value.prop_integer[i + 2];
r.r_ytop = proprec->prop_value.prop_integer[i + 3];
/* Transform rectangle to top level coordinates */
GeoTransRect(mhd->mh_trans, &r, &newr);
newproprec->prop_value.prop_integer[i] = newr.r_xbot;
newproprec->prop_value.prop_integer[i + 1] = newr.r_ybot;
newproprec->prop_value.prop_integer[i + 2] = newr.r_xtop;
newproprec->prop_value.prop_integer[i + 3] = newr.r_ytop;
}
/* If there were existing entries, copy them into the new property */
if (propfound)
{
for (i = 0; i < oldproprec->prop_len; i++)
newproprec->prop_value.prop_integer[i + proprec->prop_len] =
oldproprec->prop_value.prop_integer[i];
}
DBPropPut(mhd->mh_def, name, newproprec);
} }
return 0; return 0;
} }
@ -312,10 +304,9 @@ 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:
* Return 0 to keep the search going. * None.
* *
* Side effects: * Side effects:
* May modify properties in the target cell. * May modify properties in the target cell.
@ -323,7 +314,7 @@ cifFlatMaskHints(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
int void
CIFCopyMaskHints( CIFCopyMaskHints(
SearchContext *scx, SearchContext *scx,
CellDef *targetDef) CellDef *targetDef)
@ -333,9 +324,38 @@ 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;
} }
@ -460,7 +480,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, CIFCopyMaskHints, DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef); (ClientData)CIFComponentDef);
/* Set CIFErrorDef to NULL to ignore errors here... these will /* Set CIFErrorDef to NULL to ignore errors here... these will
@ -735,10 +755,8 @@ CIFGenSubcells(
/* This routine can take a long time, so use the display /* This routine can take a long time, so use the display
* timer to force a 5-second progress check (like is done * timer to force a 5-second progress check (like is done
* with extract). Save and restore GrDisplayStatus so that * with extract)
* a headless (DISPLAY_SUSPEND) build isn't left in DISPLAY_IDLE.
*/ */
unsigned char savedDisplayStatus = GrDisplayStatus;
GrDisplayStatus = DISPLAY_IN_PROGRESS; GrDisplayStatus = DISPLAY_IN_PROGRESS;
SigSetTimer(5); /* Print at 5-second intervals */ SigSetTimer(5); /* Print at 5-second intervals */
cuts = 0; cuts = 0;
@ -790,7 +808,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, CIFCopyMaskHints, DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFTotalDef); (ClientData)CIFTotalDef);
CIFErrorDef = def; CIFErrorDef = def;
@ -863,7 +881,7 @@ CIFGenSubcells(
CIFHierTileOps += CIFTileOps - oldTileOps; CIFHierTileOps += CIFTileOps - oldTileOps;
GrDisplayStatus = savedDisplayStatus; GrDisplayStatus = DISPLAY_IDLE;
SigRemoveTimer(); SigRemoveTimer();
UndoEnable(); UndoEnable();
@ -968,14 +986,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, CIFCopyMaskHints, DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(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, CIFCopyMaskHints, DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef); (ClientData)CIFComponentDef);
CIFErrorDef = (CellDef *) NULL; CIFErrorDef = (CellDef *) NULL;

View File

@ -146,7 +146,6 @@ typedef struct cifop
* 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_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
@ -175,7 +174,6 @@ typedef struct cifop
#define CIFOP_BRIDGELIM 24 #define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25 #define CIFOP_MASKHINTS 25
#define CIFOP_NOTSQUARE 26 #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) */
@ -340,8 +338,9 @@ extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef
bool hier, ClientData clientdata); bool hier, ClientData clientdata);
extern void CIFInitCells(void); extern void CIFInitCells(void);
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, 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 int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef); extern void 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);

View File

@ -613,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, cifReadCellDef, cifReadCellDef, &TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
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
@ -718,9 +718,6 @@ CIFPaintCurrent(
&DBAllButSpaceBits, cifCheckPaintFunc, &DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1)) (ClientData)NULL) == 1))
{ {
/* (To do: remove the linked Rects and paint directly
* into the plane in cifMaskHintFunc())
*/
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMaskHintFunc, &CIFSolidBits, cifMaskHintFunc,
(ClientData)&lrec); (ClientData)&lrec);
@ -731,29 +728,30 @@ CIFPaintCurrent(
char *propname, *layername; char *propname, *layername;
int proplen, i, savescale; int proplen, i, savescale;
bool origfound = FALSE; bool origfound = FALSE;
Plane *plane;
layername = (char *)op->co_client; layername = (char *)op->co_client;
propname = (char *)mallocMagic(11 + strlen(layername)); propname = (char *)mallocMagic(11 + strlen(layername));
sprintf(propname, "MASKHINTS_%s", layername); sprintf(propname, "MASKHINTS_%s", layername);
/* If there is already a mask hint plane for this layer, /* Turn all linked Rects into a mask-hints property in the
* then add to it; otherwise, create a new plane. * target cell.
*/ */
proprec = DBPropGet(cifReadCellDef, layername, &origfound); proplen = 0;
if (origfound) for (lsrch = lrec; lsrch; lsrch = lsrch->r_next)
plane = proprec->prop_value.prop_plane; proplen += 4;
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);
}
/* If there is already a mask hint for this layer, then
* prepend to its data.
*/
proporig = DBPropGet(cifReadCellDef, layername, &origfound);
if (origfound) proplen += proporig->prop_len;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) *
(proplen - 2) * sizeof(int));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = proplen;
proplen = 0;
while (lrec != NULL) while (lrec != NULL)
{ {
lrec->r_r.r_xtop = lrec->r_r.r_xtop =
@ -789,14 +787,29 @@ CIFPaintCurrent(
(savescale / cifCurReadStyle->crs_scaleFactor); (savescale / cifCurReadStyle->crs_scaleFactor);
} }
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable, proprec->prop_value.prop_integer[proplen] =
(PaintUndoInfo *)NULL); lrec->r_r.r_xbot;
proprec->prop_value.prop_integer[proplen + 1] =
lrec->r_r.r_ybot;
proprec->prop_value.prop_integer[proplen + 2] =
lrec->r_r.r_xtop;
proprec->prop_value.prop_integer[proplen + 3] =
lrec->r_r.r_ytop;
free_magic1_t mm1 = freeMagic1_init(); free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec); freeMagic1(&mm1, lrec);
lrec = lrec->r_next; lrec = lrec->r_next;
freeMagic1_end(&mm1); freeMagic1_end(&mm1);
proplen += 4;
} }
if (origfound)
for (i = 0; i < proporig->prop_len; i++)
proprec->prop_value.prop_integer[proplen++] =
proporig->prop_value.prop_integer[i];
DBPropPut(cifReadCellDef, propname, proprec);
freeMagic(propname); freeMagic(propname);
} }
} }
@ -913,9 +926,7 @@ 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. (To do: Remove the linked Rects and paint * each shape found.
* 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);
@ -923,45 +934,44 @@ CIFPaintCurrent(
if (lrec != NULL) if (lrec != NULL)
{ {
PropertyRecord *proprec; PropertyRecord *proprec;
bool propfound;
char *propname; char *propname;
Plane *plane; int proplen;
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]);
/* Paint all linked Rects into a mask-hints property plane /* Turn all linked Rects into a mask-hints property in the
* in the target cell. * target cell.
*/ */
proplen = 0;
for (lsrch = lrec; lsrch; lsrch = lsrch->r_next)
proplen += 4;
proprec = DBPropGet(cifReadCellDef, propname, &propfound); proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) *
if (!propfound) (proplen - 2) * sizeof(int));
{ proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); proprec->prop_len = proplen;
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;
proplen = 0;
while (lrec != NULL) while (lrec != NULL)
{ {
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor; proprec->prop_value.prop_integer[proplen] =
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor; lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor; proprec->prop_value.prop_integer[proplen + 1] =
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor; lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor;
proprec->prop_value.prop_integer[proplen + 2] =
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable, lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor;
(PaintUndoInfo *)NULL); proprec->prop_value.prop_integer[proplen + 3] =
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor;
free_magic1_t mm1 = freeMagic1_init(); free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec); freeMagic1(&mm1, lrec);
lrec = lrec->r_next; lrec = lrec->r_next;
freeMagic1_end(&mm1); freeMagic1_end(&mm1);
proplen += 4;
} }
DBPropPut(cifReadCellDef, propname, proprec);
freeMagic(propname); freeMagic(propname);
} }
@ -1786,8 +1796,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,

View File

@ -462,22 +462,9 @@ CIFPaintWirePath(
/* Wire reverses direction. Break wire here, */ /* Wire reverses direction. Break wire here, */
/* draw, and start new polygon. */ /* draw, and start new polygon. */
/* Check first if last point and current point */
/* are the same, in which case a different */
/* message should be issued (and possibly */
/* should be handled differently?) */
if (previousp && previousp->cifp_x == pathp->cifp_x
&& previousp->cifp_y == pathp->cifp_y)
{
TxError("Warning: duplicate point in path at (%d, %d).\n",
pathp->cifp_x / 2, pathp->cifp_y / 2);
}
else
{
TxError("Warning: direction reversal in path at (%d, %d).\n", TxError("Warning: direction reversal in path at (%d, %d).\n",
pathp->cifp_x / 2, pathp->cifp_y / 2); pathp->cifp_x, pathp->cifp_y);
}
phi = theta; phi = theta;
if (endcap) if (endcap)
{ {

View File

@ -332,8 +332,7 @@ cifNewReadStyle(void)
free_magic1_t mm1 = freeMagic1_init(); 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)
{ {
if (op->co_opcode == CIFOP_MASKHINTS || if (op->co_opcode == CIFOP_MASKHINTS)
op->co_opcode == CIFOP_TAGGED)
freeMagic((char *)op->co_client); freeMagic((char *)op->co_client);
freeMagic1(&mm1, (char *)op); freeMagic1(&mm1, (char *)op);
} }
@ -999,8 +998,6 @@ CIFReadTechLine(
newOp->co_opcode = CIFOP_NOTSQUARE; newOp->co_opcode = CIFOP_NOTSQUARE;
else if (strcmp(argv[0], "mask-hints") == 0) else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS; 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]);
@ -1031,12 +1028,6 @@ CIFReadTechLine(
if (argc != 2) goto wrongNumArgs; if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]); newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
break; break;
case CIFOP_TAGGED:
if ((argc != 2) && (argc != 3)) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
if (argc == 3)
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
break;
} }
/* Link the new CIFOp onto the list. */ /* Link the new CIFOp onto the list. */

View File

@ -168,7 +168,7 @@ CIFPaintLayer(
(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, CIFCopyMaskHints, DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef); (ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount; oldCount = DBWFeedbackCount;
@ -289,7 +289,7 @@ CIFSeeLayer(
(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, CIFCopyMaskHints, DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef); (ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount; oldCount = DBWFeedbackCount;
@ -461,7 +461,7 @@ CIFCoverageLayer(
(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, CIFCopyMaskHints, DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef); (ClientData)CIFComponentDef);
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,

View File

@ -1107,8 +1107,6 @@ 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)
@ -1359,10 +1357,8 @@ bloatCheck:
bloatDone: break; bloatDone: break;
case CIFOP_NET: case CIFOP_NET:
case CIFOP_TAGGED: if (argc != 3) goto wrongNumArgs;
if ((argc != 2) && (argc != 3)) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]); newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
if (argc == 3)
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask, cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask, FALSE); &newOp->co_cifMask, FALSE);
break; break;
@ -1675,12 +1671,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, TAGGED, and MASKHINTS operators should never be */ /* BBOX, NET, and MASKHINTS operators should never be used */
/* used hierarchically so ignore any grow/shrink operators that */ /* 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_TAGGED || op->co_opcode == CIFOP_MASKHINTS) 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
@ -1992,8 +1988,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, CIFOP_MASKHINTS, and */ /* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
/* CIFOP_TAGGED use it for a string. */ /* uses it for a string. */
else else
{ {
switch (op->co_opcode) switch (op->co_opcode)
@ -2005,7 +2001,6 @@ 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:
@ -2541,7 +2536,6 @@ 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:
@ -2657,8 +2651,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, CIFOP_MASKHINTS, and */ /* and in CIFOP_NET and CIFOP_MASKHINTS is a */
/* CIFOP_TAGGED is a string. */ /* string. */
break; break;
} }
} }

View File

@ -44,7 +44,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "textio/textio.h" #include "textio/textio.h"
/* Forward declarations */ /* Forward declarations */
extern int cifWriteInitFunc(CellDef *def, ClientData cdata); /* UNUSED */ extern int cifWriteInitFunc(CellDef *def);
extern int cifWriteMarkFunc(CellUse *use); extern int cifWriteMarkFunc(CellUse *use);
extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f); extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f);
extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f); extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f);
@ -204,11 +204,9 @@ CIFWrite(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
cifWriteInitFunc( cifWriteInitFunc(
CellDef *def, CellDef *def)
ClientData cdata) /* UNUSED */
{ {
def->cd_client = (ClientData) 0; def->cd_client = (ClientData) 0;
return (0); return (0);

View File

@ -217,11 +217,10 @@ CMWdelete(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
void void
CMWreposition( CMWreposition(
MagWindow *window, MagWindow *window,
Rect *newScreenArea, /* UNUSED */ Rect *newScreenArea,
bool final) bool final)
{ {
if (final) if (final)

View File

@ -781,81 +781,38 @@ cmdEraseCellsFunc(
* Implement the "expand" command. * Implement the "expand" command.
* *
* Usage: * Usage:
* expand [selection|surround|overlap|all] [toggle] * expand
* * 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:
* Expansion state of cells is changed. May read cells in from * If "toggle" is specified, flips the expanded/unexpanded status
* disk, and update bounding boxes that have changed. * of all selected cells. Otherwise, aren't any unexpanded cells
* 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, option; int windowMask, boxMask, d;
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. */
static const char * const cmdExpandOption[] = { if (cmd->tx_argc > 2 || (cmd->tx_argc == 2
"selection expand cell instances in the selection", && (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0)))
"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)
{ {
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle", TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]);
strlen(cmd->tx_argv[cmd->tx_argc - 1]))) return;
{
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)
@ -887,95 +844,23 @@ 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 (doToggle) break; /* Don't toggle twice */ if (cmd->tx_argc == 2) break; /* Don't toggle twice */
} }
(void) ToolGetBoxWindow(&rootRect, &boxMask); (void) ToolGetBoxWindow(&rootRect, &boxMask);
if (option != EXPAND_SELECTION) if (cmd->tx_argc == 2)
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;
} }
}
switch (option)
{
case EXPAND_SELECTION:
SelectExpand(windowMask,
(doToggle) ? DB_EXPAND_TOGGLE : DB_EXPAND,
(Rect *)NULL);
break;
case EXPAND_OVERLAP:
if (doToggle)
{
DBExpandAll(rootBoxUse, &rootRect, windowMask, DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP, TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask);
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
&rootRect);
}
else
{
DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
&rootRect);
}
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);
}
else
{
DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND | DB_EXPAND_SURROUND,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_SURROUND,
&rootRect);
}
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);
}
else
{
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
(Rect *)NULL);
}
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.
@ -1096,7 +981,7 @@ CmdExtract(
"lumped estimate lumped 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 [notopports] ensure unique node names during extraction", "unique ensure unique node names during extraction",
"resistance extract resistance (same as \"do extresist\")", "resistance extract resistance (same as \"do extresist\")",
NULL NULL
}; };
@ -1403,7 +1288,6 @@ CmdExtract(
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 unique\n", OPTSET(EXT_DOUNIQUE));
TxPrintf("%s unique notopports\n", OPTSET(EXT_DOUNIQNOTOPPORTS));
TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST)); TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST));
return; return;
#undef OPTSET #undef OPTSET
@ -1434,19 +1318,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 DOEXTRESIST:
case DOEXTRESIST2: option = EXT_DOEXTRESIST; break; case DOEXTRESIST2: option = EXT_DOEXTRESIST; break;
case DOUNIQUE:
if (argc == 4)
{
if (!strncmp(argv[3], "notop", 5))
option = EXT_DOUNIQNOTOPPORTS | EXT_DOUNIQUE;
else
TxError("Usage: extract do unique [notopports]\n");
}
else
option = EXT_DOUNIQUE;
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

View File

@ -45,8 +45,9 @@ 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 */
@ -517,14 +518,14 @@ CmdLoad(
DBExpandAll(topuse, &(topuse->cu_bbox), DBExpandAll(topuse, &(topuse->cu_bbox),
((DBWclientRec *)w->w_clientData)->dbw_bitmask, ((DBWclientRec *)w->w_clientData)->dbw_bitmask,
DB_EXPAND, keepGoing, NULL); TRUE, keepGoing, NULL);
DBExpandAll(topuse, &(topuse->cu_bbox), DBExpandAll(topuse, &(topuse->cu_bbox),
((DBWclientRec *)w->w_clientData)->dbw_bitmask, ((DBWclientRec *)w->w_clientData)->dbw_bitmask,
DB_UNEXPAND, keepGoing, NULL); FALSE, keepGoing, NULL);
DBExpand(topuse, DBExpand(topuse,
((DBWclientRec *)w->w_clientData)->dbw_bitmask, ((DBWclientRec *)w->w_clientData)->dbw_bitmask,
DB_EXPAND); TRUE);
/* 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 */
@ -2324,9 +2325,9 @@ CmdDoProperty(
TxCommand *cmd, TxCommand *cmd,
int argstart) int argstart)
{ {
PropertyRecord *proprec = NULL; PropertyRecord *proprec;
char *value; char *value;
bool propfound, dolist; bool propfound;
int proptype, proplen, propvalue, i; int proptype, proplen, propvalue, i;
dlong dvalue; dlong dvalue;
int locargc = cmd->tx_argc - argstart + 1; int locargc = cmd->tx_argc - argstart + 1;
@ -2334,31 +2335,15 @@ CmdDoProperty(
Tcl_Obj *tobj; Tcl_Obj *tobj;
#endif #endif
/* Forward declarations */ int printPropertiesFunc(); /* Forward declaration */
int printPropertiesFunc();
int printPlanePropFunc();
/* These should match the property codes in database.h.in, except /* These should match the property codes in database.h.in, except
* for "compat" which must come at the end. * for "compat" which must come at the end.
*/ */
static const char * const cmdPropertyType[] = { static const char * const cmdPropertyType[] = {
"string", "integer", "dimension", "double", "plane", "compat", NULL "string", "integer", "dimension", "double", "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 /* If a property type is given, parse it and then strip it from
* the arguments list. * the arguments list.
*/ */
@ -2408,7 +2393,7 @@ CmdDoProperty(
return; return;
} }
/* Print the value of the indicated property */ /* print the value of the indicated property */
proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound); proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
if (propfound) if (propfound)
{ {
@ -2449,14 +2434,6 @@ CmdDoProperty(
Tcl_SetObjResult(magicinterp, tobj); Tcl_SetObjResult(magicinterp, tobj);
} }
break; 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: case PROPERTY_TYPE_DOUBLE:
if (proprec->prop_len == 1) if (proprec->prop_len == 1)
Tcl_SetObjResult(magicinterp, Tcl_SetObjResult(magicinterp,
@ -2488,17 +2465,10 @@ CmdDoProperty(
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%s ", DBWPrintValue( TxPrintf("%s ", DBWPrintValue(
proprec->prop_value.prop_integer[i], w, proprec->prop_value.prop_integer[i], w,
((i % 2) == 0) ? TRUE : FALSE)); ((i % 2) == 0) ? TRUE : FALSE);
TxPrintf("\n"); TxPrintf("\n");
break; 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: case PROPERTY_TYPE_DOUBLE:
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
TxPrintf( "%"DLONG_PREFIX"d", TxPrintf( "%"DLONG_PREFIX"d",
@ -2512,9 +2482,9 @@ CmdDoProperty(
#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 (!dolist) if (strcmp(cmd->tx_argv[1], "list"))
#endif #endif
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[argstart]); TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
} }
} }
else if (locargc >= 3) else if (locargc >= 3)
@ -2544,7 +2514,7 @@ CmdDoProperty(
* keyword functions work correctly. * keyword functions work correctly.
* *
* GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE * GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE
* MASKHINTS_*: PROPERTY_TYPE_PLANE * MASKHINTS_*: PROPERTY_TYPE_DIMENSION
* FIXED_BBOX: PROPERTY_TYPE_DIMENSION * FIXED_BBOX: PROPERTY_TYPE_DIMENSION
*/ */
if (!strcmp(cmd->tx_argv[argstart], "GDS_START")) if (!strcmp(cmd->tx_argv[argstart], "GDS_START"))
@ -2558,7 +2528,7 @@ CmdDoProperty(
else if (!strcmp(cmd->tx_argv[argstart], "OBS_BBOX")) else if (!strcmp(cmd->tx_argv[argstart], "OBS_BBOX"))
proptype = PROPERTY_TYPE_DIMENSION; proptype = PROPERTY_TYPE_DIMENSION;
else if (!strncmp(cmd->tx_argv[argstart], "MASKHINTS_", 10)) else if (!strncmp(cmd->tx_argv[argstart], "MASKHINTS_", 10))
proptype = PROPERTY_TYPE_PLANE; proptype = PROPERTY_TYPE_DIMENSION;
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);
@ -2573,11 +2543,8 @@ CmdDoProperty(
proprec->prop_len = proplen; proprec->prop_len = proplen;
strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]); strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]);
} }
else /* All non-string properties */ else /* PROPERTY_TYPE_INTEGER or PROPERTY_TYPE_DIMENSION */
{ {
Plane *plane;
Rect r;
/* Two choices: If locargc == 3 then all values are in one /* Two choices: If locargc == 3 then all values are in one
* argument. If locargc > 3, then parse each argument as a * argument. If locargc > 3, then parse each argument as a
* separate value. * separate value.
@ -2588,12 +2555,6 @@ CmdDoProperty(
if (proptype == PROPERTY_TYPE_DOUBLE) if (proptype == PROPERTY_TYPE_DOUBLE)
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proplen - 1)*sizeof(dlong)); (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 else
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proplen - 2)*sizeof(int)); (proplen - 2)*sizeof(int));
@ -2626,28 +2587,6 @@ CmdDoProperty(
proprec->prop_value.prop_double[i - 1] = 0; 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 */ else /* PROPERTY_TYPE_DIMENSION */
{ {
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i], propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
@ -2674,20 +2613,11 @@ CmdDoProperty(
} }
if (proplen > 0) if (proplen > 0)
{ {
if (proptype == PROPERTY_TYPE_PLANE) proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
{ (proplen - 2)*sizeof(int));
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_type = proptype;
proprec->prop_len = proplen; proprec->prop_len = proplen;
} }
/* Second pass */ /* Second pass */
value = cmd->tx_argv[argstart + 1]; value = cmd->tx_argv[argstart + 1];
for (proplen = 0; proplen < proprec->prop_len; proplen++) for (proplen = 0; proplen < proprec->prop_len; proplen++)
@ -2727,28 +2657,6 @@ CmdDoProperty(
} }
proprec->prop_value.prop_double[proplen] = dvalue; 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 */ else /* PROPERTY_TYPE_DIMENSION */
{ {
propvalue = cmdParseCoord(w, value, FALSE, propvalue = cmdParseCoord(w, value, FALSE,
@ -2819,59 +2727,6 @@ CmdProperty(
CmdDoProperty(def, w, 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
@ -2911,12 +2766,6 @@ printPropertiesFunc(
DBWPrintValue(proprec->prop_value.prop_integer[i], DBWPrintValue(proprec->prop_value.prop_integer[i],
w, ((i % 2) == 0) ? TRUE : FALSE), -1)); w, ((i % 2) == 0) ? TRUE : FALSE), -1));
break; 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: case PROPERTY_TYPE_DOUBLE:
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_ListObjAppendElement(magicinterp, lobj,
@ -2930,32 +2779,25 @@ printPropertiesFunc(
switch (proprec->prop_type) switch (proprec->prop_type)
{ {
case PROPERTY_TYPE_STRING: case PROPERTY_TYPE_STRING:
TxPrintf("%s = %s\n", name, (const char *)proprec->prop_value.prop_string); TxPrintf("%s = %s\n", name, (const char *)proprec->prop_string);
break; break;
case PROPERTY_TYPE_INTEGER: case PROPERTY_TYPE_INTEGER:
TxPrintf("%s = ", name); TxPrintf("%s = ", name);
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%d ", proprec->prop_value.prop_integer[i]); TxPrintf("%d ", proprec->prop_integer[i]);
TxPrintf("\n"); TxPrintf("\n");
break; break;
case PROPERTY_TYPE_DIMENSION: case PROPERTY_TYPE_DIMENSION:
TxPrintf("%s = ", name); TxPrintf("%s = ", name);
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%s ", DBWPrintValue(proprec->prop_value.prop_integer[i], TxPrintf("%s ", DBWPrintValue(proprec->prop_value.prop_integer[i],
w, ((i % 2) == 0) ? TRUE : FALSE)); 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"); TxPrintf("\n");
break; break;
case PROPERTY_TYPE_DOUBLE: case PROPERTY_TYPE_DOUBLE:
TxPrintf("%s = ", name); TxPrintf("%s = ", name);
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_value.prop_double[i]); TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_double[i]);
TxPrintf("\n"); TxPrintf("\n");
break; break;
} }

View File

@ -635,21 +635,10 @@ cmdSelectArea(
int i; int i;
for (i = 0; i < DBNumUserLayers; i++) for (i = 0; i < DBNumUserLayers; i++)
{ {
if ((TTMaskHasType(&mask, i)) && if((TTMaskHasType(&mask, i)) && !(TTMaskHasType(&crec->dbw_visibleLayers, i)))
!(TTMaskHasType(&crec->dbw_visibleLayers, i)))
TTMaskClearType(&mask, i); TTMaskClearType(&mask, i);
} }
/* Remove L_CELL and L_LABEL if crec->dbw_flags indicates that
* they are not visible in the layout window.
*/
if (!(crec->dbw_flags & DBW_SEELABELS)) TTMaskClearType(&mask, L_LABEL);
if (!(crec->dbw_flags & DBW_SEECELLS)) TTMaskClearType(&mask, L_CELL);
} }
else if (option == SEL_AREA)
TTMaskSetType(&mask, L_LABEL);
SelectArea(&scx, &mask, crec->dbw_bitmask, globmatch); SelectArea(&scx, &mask, crec->dbw_bitmask, globmatch);
} }
@ -1038,7 +1027,7 @@ CmdSelect(
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Select everything under the box, perhaps looking only at * Select everything under the box, perhaps looking only at
* particular layers, but only if it's visible. * particular layers, but only if its visible.
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
@ -1812,18 +1801,13 @@ 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_NewStringObj(labsize, -1)); Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewDoubleObj((double)label->lab_size / 8.0));
Tcl_SetObjResult(magicinterp, lobj); Tcl_SetObjResult(magicinterp, lobj);
#else #else
TxPrintf("%s\n", labsize); TxPrintf("%g\n", (double)label->lab_size / 8.0);
#endif #endif
} }
else if (label->lab_size != *value) else if (label->lab_size != *value)
@ -1968,22 +1952,18 @@ 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_NewStringObj(laboffx, -1)); Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffy, -1)); Tcl_NewDoubleObj((double)label->lab_offset.p_x / 8.0));
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("%s %s\n", laboffx, laboffy); TxPrintf("%g %g\n", (double)(label->lab_offset.p_x) / 8.0,
(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))
@ -2232,13 +2212,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelTextFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelTextFunc, cmdLabelTextFunc, (locargc == 3) ?
(ClientData)cmd->tx_argv[argstart + 1]); (ClientData)cmd->tx_argv[argstart + 1] : (ClientData)NULL);
} }
break; break;
@ -2304,12 +2280,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelFontFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelFontFunc, (ClientData)&font); cmdLabelFontFunc, (locargc == 3) ?
(ClientData)&font : (ClientData)NULL);
} }
} }
break; break;
@ -2337,12 +2310,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelJustFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelJustFunc, (ClientData)&pos); cmdLabelJustFunc, (locargc == 3) ?
(ClientData)&pos : (ClientData)NULL);
} }
break; break;
@ -2371,12 +2341,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelSizeFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelSizeFunc, (ClientData)&size); cmdLabelSizeFunc, (locargc == 3) ?
(ClientData)&size : (ClientData)NULL);
} }
break; break;
@ -2426,12 +2393,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelOffsetFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelOffsetFunc, (ClientData)&offset); cmdLabelOffsetFunc, (locargc != 2) ?
(ClientData)&offset : (ClientData)NULL);
} }
break; break;
@ -2495,12 +2459,10 @@ 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);
} }
if ((locargc == 3) || (locargc == 6))
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRectFunc, (ClientData)&rect); cmdLabelRectFunc,
else ((locargc == 6) || (locargc == 3)) ?
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, (ClientData)&rect : (ClientData)NULL);
cmdLabelRectFunc, (ClientData)NULL);
} }
break; break;
@ -2526,12 +2488,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRotateFunc, (ClientData)NULL);
else
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelRotateFunc, (ClientData)&rotate); cmdLabelRotateFunc, (locargc == 3) ?
(ClientData)&rotate : (ClientData)NULL);
} }
break; break;
@ -2563,12 +2522,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelStickyFunc, (ClientData)NULL); cmdLabelStickyFunc, (locargc == 3) ?
else (ClientData)&flags : (ClientData)NULL);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelStickyFunc, (ClientData)&flags);
} }
break; break;
@ -2607,12 +2563,9 @@ CmdSetLabel(
} }
else if (EditCellUse) else if (EditCellUse)
{ {
if (locargc == 2)
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelLayerFunc, (ClientData)NULL); cmdLabelLayerFunc, (locargc == 3) ?
else (ClientData)&ttype : (ClientData)NULL);
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
cmdLabelLayerFunc, (ClientData)&ttype);
} }
break; break;

View File

@ -1019,7 +1019,7 @@ CmdSetWindCaption(
* edit cell was selected. * edit cell was selected.
*/ */
{ {
int cmdWindSet(MagWindow *window, ClientData clientData); /* UNUSED */ int cmdWindSet(MagWindow *window);
newEditDef = (newEditUse) ? newEditUse->cu_def : NULL; newEditDef = (newEditUse) ? newEditUse->cu_def : NULL;
newRootDef = rootDef; newRootDef = rootDef;
@ -1053,11 +1053,9 @@ CmdSetWindCaption(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
cmdWindSet( cmdWindSet(
MagWindow *window, MagWindow *window)
ClientData clientData) /* UNUSED */
{ {
char caption[200]; char caption[200];
CellDef *wDef; CellDef *wDef;
@ -1241,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 ? DB_EXPAND : DB_UNEXPAND); DBExpand(cu, bitmask, expand);
/* now, unexpand its direct children (ONE LEVEL ONLY) */ /* now, unexpand its direct children (ONE LEVEL ONLY) */
if (expand) if (expand)
@ -1253,7 +1251,7 @@ cmdExpand1func(
CellUse *cu, CellUse *cu,
ClientData bitmask) ClientData bitmask)
{ {
DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND); DBExpand(cu, (int)CD2INT(bitmask), FALSE);
return 0; return 0;
} }

View File

@ -702,62 +702,32 @@ CmdTool(
* Implement the "unexpand" command. * Implement the "unexpand" command.
* *
* Usage: * Usage:
* unexpand [selection|surround|overlap|all] * unexpand
*
* "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:
* Changes the expansion state of cells. * Unexpands all cells under the box that don't completely
* 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, option; int windowMask, boxMask;
const char * const *msg;
Rect rootRect; Rect rootRect;
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */ int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
static const char * const cmdUnexpandOption[] = { if (cmd->tx_argc != 1)
"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)
{ {
option = Lookup(cmd->tx_argv[1], cmdUnexpandOption); TxError("Usage: %s\n", cmd->tx_argv[0]);
if (option < 0) option = UNEXPAND_HELP; return;
} }
else
option = UNEXPAND_SURROUND;
if (option == UNEXPAND_HELP) goto badusage;
windCheckOnlyWindow(&w, DBWclientID); windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL) if (w == (MagWindow *) NULL)
@ -773,42 +743,8 @@ 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,
switch (option) FALSE, cmdUnexpandFunc, (ClientData)(pointertype) windowMask);
{
case UNEXPAND_SELECTION:
SelectExpand(windowMask, DB_UNEXPAND, (Rect *)NULL);
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);
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);
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.

View File

@ -53,10 +53,10 @@ typedef struct dbcellboundstruct
*/ */
int int
DBBoundCellPlane( DBBoundCellPlane(def, extended, rect)
CellDef *def, CellDef *def;
Rect *extended, Rect *extended;
Rect *rect) Rect *rect;
{ {
TreeFilter filter; TreeFilter filter;
DBCellBoundStruct cbs; DBCellBoundStruct cbs;
@ -79,9 +79,9 @@ DBBoundCellPlane(
} }
int int
dbCellBoundFunc( dbCellBoundFunc(use, fp)
CellUse *use, CellUse *use;
TreeFilter *fp) TreeFilter *fp;
{ {
DBCellBoundStruct *cbs; DBCellBoundStruct *cbs;
@ -124,9 +124,9 @@ dbCellBoundFunc(
*/ */
bool bool
DBBoundPlane( DBBoundPlane(plane, rect)
Plane *plane, Plane *plane;
Rect *rect) Rect *rect;
{ {
Tile *left, *right, *top, *bottom, *tp; Tile *left, *right, *top, *bottom, *tp;
@ -205,9 +205,9 @@ DBBoundPlane(
*/ */
bool bool
DBBoundPlaneVert( DBBoundPlaneVert(plane, rect)
Plane *plane, Plane *plane;
Rect *rect) Rect *rect;
{ {
Tile *left, *right, *top, *bottom, *tp; Tile *left, *right, *top, *bottom, *tp;

View File

@ -37,8 +37,9 @@ 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
@ -356,43 +357,9 @@ 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;
}
/* /*
*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------
* *
@ -420,45 +387,62 @@ dbCopyMaskHintsFunc(key, proprec, puds)
{ {
CellDef *dest = puds->puds_dest; CellDef *dest = puds->puds_dest;
Transform *trans = puds->puds_trans; Transform *trans = puds->puds_trans;
Rect *clip = puds->puds_area;
PropertyRecord *parentproprec, *newproprec; PropertyRecord *parentproprec, *newproprec;
char *parentprop, *newvalue, *vptr; char *parentprop, *newvalue, *vptr;
Rect r, rnew; Rect r, rnew;
bool propfound; bool propfound;
int i, j; int i;
if (!strncmp(key, "MASKHINTS_", 10)) if (!strncmp(key, "MASKHINTS_", 10))
{ {
char *vptr, *lastval; char *vptr, *lastval;
int lastlen; int lastlen;
Plane *plane;
ASSERT(proprec->prop_type == PROPERTY_TYPE_PLANE, "dbCopyMaskHintsFunc"); /* Append to existing mask hint (if any) */
/* Get the existing mask hint plane in the parent cell, and
* create it if it does not already exist.
*/
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound); parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
if (propfound) if (propfound)
plane = parentproprec->prop_value.prop_plane; {
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
(proprec->prop_len + parentproprec->prop_len - 2) *
sizeof(int));
newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
newproprec->prop_len = proprec->prop_len + parentproprec->prop_len;
}
else else
{ {
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
newproprec->prop_type = PROPERTY_TYPE_PLANE; (proprec->prop_len - 2) * sizeof(int));
newproprec->prop_len = 0; newproprec->prop_type = PROPERTY_TYPE_DIMENSION;
plane = DBNewPlane((ClientData)TT_SPACE); newproprec->prop_len = proprec->prop_len;
newproprec->prop_value.prop_plane = plane; }
for (i = 0; i < proprec->prop_len; i += 4)
{
r.r_xbot = proprec->prop_value.prop_integer[i];
r.r_ybot = proprec->prop_value.prop_integer[i + 1];
r.r_xtop = proprec->prop_value.prop_integer[i + 2];
r.r_ytop = proprec->prop_value.prop_integer[i + 3];
GeoTransRect(trans, &r, &rnew);
newproprec->prop_value.prop_integer[i] = rnew.r_xbot;
newproprec->prop_value.prop_integer[i + 1] = rnew.r_ybot;
newproprec->prop_value.prop_integer[i + 2] = rnew.r_xtop;
newproprec->prop_value.prop_integer[i + 3] = rnew.r_ytop;
}
if (propfound)
{
/* Append the original values to the end of the list */
for (i = 0; i < parentproprec->prop_len; i++)
newproprec->prop_value.prop_integer[i + proprec->prop_len] =
parentproprec->prop_value.prop_integer[i];
}
DBPropPut(dest, key, newproprec); DBPropPut(dest, key, newproprec);
} }
puds->puds_plane = plane;
/* 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;
} }
@ -490,7 +474,6 @@ 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);
} }
@ -524,7 +507,6 @@ 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);

View File

@ -588,25 +588,6 @@ 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;
@ -659,8 +640,6 @@ 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;
@ -732,16 +711,6 @@ 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;
@ -763,9 +732,7 @@ dbCellLabelSrFunc(scx, fp)
} }
} }
/* Now visit each child use recursively, if not doing a reverse search */ /* Now visit each child use recursively */
if (!(fp->tf_flags & TF_LABEL_REVERSE_SEARCH))
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp)) if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
result = 1; result = 1;
@ -1746,7 +1713,7 @@ dbTileMoveFunc(tile, dinfo, mvvals)
if (IsSplit(tile)) if (IsSplit(tile))
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect, DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum), DBStdPaintTbl(type, mvvals->pnum),
(PaintUndoInfo *)NULL); (PaintUndoInfo *)NULL);
return 0; return 0;
} }
@ -1847,22 +1814,7 @@ int dbScaleProp(name, proprec, cps)
int i, scalen, scaled; int i, scalen, scaled;
Point p; Point p;
/* Only "dimension" and "plane" type properties get scaled */ /* Only "dimension" type properties get scaled */
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
{
Plane *newplane;
newplane = DBNewPlane((ClientData)TT_SPACE);
DBClearPaintPlane(newplane);
/* Plane index is unused; arbitrarily substitute -1 */
dbScalePlane(proprec->prop_value.prop_plane, newplane, -1,
scalen, scaled, TRUE);
DBFreePaintPlane(proprec->prop_value.prop_plane);
TiFreePlane(proprec->prop_value.prop_plane);
proprec->prop_value.prop_plane = newplane;
return 0;
}
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0; if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
/* Scale numerator held in point X value, */ /* Scale numerator held in point X value, */
@ -1905,22 +1857,7 @@ int dbMoveProp(name, proprec, cps)
char *newvalue; char *newvalue;
Point p; Point p;
/* Only "dimension" and "plane" type properties get scaled */ /* Only "dimension" type properties get scaled */
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
{
Plane *newplane;
newplane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(newplane);
/* Use plane index -1 to indicate use of CIFPaintTable */
dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy);
DBFreePaintPlane(proprec->prop_value.prop_plane);
TiFreePlane(proprec->prop_value.prop_plane);
proprec->prop_value.prop_plane = newplane;
return 0;
}
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0; if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
origx = cps->cps_point.p_x; origx = cps->cps_point.p_x;

View File

@ -1037,13 +1037,7 @@ dbcConnectFunc(tile, dinfo, cx)
if (++csa2->csa2_top == CSA2_LIST_SIZE) if (++csa2->csa2_top == CSA2_LIST_SIZE)
{ {
/* Reached list size limit---need to push the list and */ /* Reached list size limit---need to push the list and */
/* start a new one. NOTE: Setting lasttop to -1 means */ /* start a new one. */
/* that some entries may be duplicated between the */
/* stacks, which is a small inefficiency. In theory, */
/* lasttop could be left as is, then if lasttop > top */
/* when searching the last 5 entries, pop the stack, do */
/* the search, and then push the stack again. But it's */
/* a lot easier just to be slightly inefficient. */
conSrArea *newlist; conSrArea *newlist;
@ -1051,7 +1045,6 @@ dbcConnectFunc(tile, dinfo, cx)
StackPush((ClientData)csa2->csa2_list, csa2->csa2_stack); StackPush((ClientData)csa2->csa2_list, csa2->csa2_stack);
csa2->csa2_list = newlist; csa2->csa2_list = newlist;
csa2->csa2_top = 0; csa2->csa2_top = 0;
csa2->csa2_lasttop = -1;
} }
csa2->csa2_list[csa2->csa2_top].area = newarea; csa2->csa2_list[csa2->csa2_top].area = newarea;

View File

@ -39,7 +39,6 @@ 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.
*/ */
@ -68,22 +67,15 @@ struct expandArg
*/ */
void void
DBExpand(cellUse, expandMask, expandType) DBExpand(cellUse, expandMask, expandFlag)
CellUse *cellUse; CellUse *cellUse;
int expandMask; int expandMask;
int expandType; bool expandFlag;
{ {
CellDef *def; CellDef *def;
bool expandFlag, expandTest;
expandTest = DBDescendSubcell(cellUse, expandMask); if (DBDescendSubcell(cellUse, expandMask) == expandFlag)
if ((expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE) return;
expandFlag = expandTest;
else
{
expandFlag = ((expandType & DB_EXPAND_MASK) == DB_EXPAND) ? TRUE : FALSE;
if (expandFlag == expandTest) return;
}
if (expandFlag) if (expandFlag)
{ {
@ -138,17 +130,17 @@ DBExpand(cellUse, expandMask, expandType)
*/ */
void void
DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg) DBExpandAll(rootUse, rootRect, expandMask, expandFlag, 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 */
int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */ bool expandFlag; /* TRUE => expand, FALSE => unexpand */
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(); int dbExpandFunc(), dbUnexpandFunc();
SearchContext scontext; SearchContext scontext;
struct expandArg arg; struct expandArg arg;
@ -156,26 +148,29 @@ DBExpandAll(rootUse, rootRect, expandMask, expandType, 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 appropriately. * Walk through the area and set the expansion state
* 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, unexpanded, or toggled. * when cells are being expanded.
*/ */
int int
@ -189,23 +184,13 @@ 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 (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE))) if (!DBDescendSubcell(childUse, arg->ea_xmask))
{
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
{ {
/* If the cell is unavailable, then don't expand it. /* If the cell is unavailable, then don't expand it.
*/ */
@ -213,7 +198,7 @@ dbExpandFunc(scx, arg)
{ {
/* If the parent is dereferenced, then the child should be, too */ /* If the parent is dereferenced, then the child should be, too */
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE; if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
if (!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL)) if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
{ {
TxError("Cell %s is unavailable. It could not be expanded.\n", TxError("Cell %s is unavailable. It could not be expanded.\n",
childUse->cu_def->cd_name); childUse->cu_def->cd_name);
@ -222,22 +207,45 @@ dbExpandFunc(scx, arg)
} }
childUse->cu_expandMask |= arg->ea_xmask; childUse->cu_expandMask |= arg->ea_xmask;
expandTest = TRUE;
if (arg->ea_func != NULL) if (arg->ea_func != NULL)
{ {
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1; 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))
{ {
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area) if (!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. */
@ -248,7 +256,11 @@ dbExpandFunc(scx, arg)
} }
} }
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg)) /* Don't recursively search things that aren't already expanded. */
else return 2;
if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg))
return 1; return 1;
return 2; return 2;
} }

View File

@ -73,9 +73,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/undo.h" #include "utils/undo.h"
#include "utils/malloc.h" #include "utils/malloc.h"
#include "utils/signals.h" #include "utils/signals.h"
/* C99 compat */
#include "dbwind/dbwtech.h" #include "dbwind/dbwtech.h"
#include "cif/cif.h" #include "cif/cif.h"
#include "cif/CIFint.h"
#include "lef/lef.h" #include "lef/lef.h"
#include "commands/commands.h" #include "commands/commands.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"
@ -2016,8 +2017,8 @@ badTransform:
if ((cellDef->cd_file != NULL) && (cellDef->cd_file[0] == '/')) if ((cellDef->cd_file != NULL) && (cellDef->cd_file[0] == '/'))
{ {
char *homedir = getenv("HOME"); char *homedir = getenv("HOME");
if (homedir && (strncmp(cellDef->cd_file, homedir, strlen(homedir)) || if (strncmp(cellDef->cd_file, homedir, strlen(homedir)) ||
*(cellDef->cd_file + strlen(homedir)) != '/')) *(cellDef->cd_file + strlen(homedir)) != '/')
{ {
char *homeroot = strrchr(homedir, '/'); char *homeroot = strrchr(homedir, '/');
int rootlen = (int)(homeroot - homedir) + 1; int rootlen = (int)(homeroot - homedir) + 1;
@ -2060,10 +2061,9 @@ badTransform:
if (*pathptr == '~') if (*pathptr == '~')
{ {
char *homedir = getenv("HOME"); char *homedir = getenv("HOME");
if (homedir && (!strncmp(subCellDef->cd_file, homedir, if (!strncmp(subCellDef->cd_file, homedir, strlen(homedir))
strlen(homedir)) && && (!strcmp(subCellDef->cd_file + strlen(homedir),
(!strcmp(subCellDef->cd_file + strlen(homedir), pathptr + 1)))
pathptr + 1))))
pathOK = TRUE; pathOK = TRUE;
} }
else if (!strcmp(cwddir, pathptr)) pathOK = TRUE; else if (!strcmp(cwddir, pathptr)) pathOK = TRUE;
@ -2255,9 +2255,9 @@ badTransform:
/* Check if the path is the same as the current directory */ /* Check if the path is the same as the current directory */
char *homedir = getenv("HOME"); char *homedir = getenv("HOME");
if (homedir && (!strncmp(cwddir, homedir, strlen(homedir)) if (!strncmp(cwddir, homedir, strlen(homedir))
&& (!strcmp(cwddir + strlen(homedir), && (!strcmp(cwddir + strlen(homedir),
pathptr + 1)))) pathptr + 1)))
pathOK = TRUE; pathOK = TRUE;
} }
else if (!strcmp(cwddir, pathptr)) pathOK = TRUE; else if (!strcmp(cwddir, pathptr)) pathOK = TRUE;
@ -2492,24 +2492,10 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
* (2) "integer" (a fixed integer or list of integers) * (2) "integer" (a fixed integer or list of integers)
* (3) "dimension" (an integer that scales with internal units) * (3) "dimension" (an integer that scales with internal units)
* (4) "double" (a fixed double-wide integer or list thereof) * (4) "double" (a fixed double-wide integer or list thereof)
* (5) "plane" (a tile plane structure)
*/ */
switch (option) switch (option)
{ {
case PROPERTY_TYPE_PLANE:
/* Treat this like "string" but make sure property is a
* mask hint. There is currently no method to specify
* a plane property other than to write out the bounding
* box coordinates of all the tiles in a list.
*/
if (strncmp(propertyname, "MASKHINTS_", 10))
{
TxError("Plane type specified for property \"%s\" but "
"property is not a mask hint!\n", propertyname);
break;
}
/* Else drop through */
case PROPERTY_TYPE_STRING: case PROPERTY_TYPE_STRING:
/* Go ahead and process the vendor GDS property */ /* Go ahead and process the vendor GDS property */
if (!strcmp(propertyname, "GDS_FILE")) if (!strcmp(propertyname, "GDS_FILE"))
@ -2579,64 +2565,69 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
else if (!strncmp(propertyname, "MASKHINTS_", 10)) else if (!strncmp(propertyname, "MASKHINTS_", 10))
{ {
pptr = pvalueptr; pptr = pvalueptr;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
proprec->prop_type = PROPERTY_TYPE_PLANE;
proprec->prop_len = 0;
proprec->prop_value.prop_plane = DBNewPlane((ClientData)TT_SPACE); /* Do one pass through the string to count the number of
* values and make sure they all parse as integers.
/* Parse the string and convert sets of four values
* to coordinates and paint into the plane.
*/ */
numvals = 0; numvals = 0;
while (*pptr != '\0') while (*pptr != '\0')
{ {
Rect r;
while (isspace(*pptr) && (*pptr != '\0')) pptr++; while (isspace(*pptr) && (*pptr != '\0')) pptr++;
if (!isspace(*pptr)) if (!isspace(*pptr))
{ {
if (sscanf(pptr, "%d", &ival) != 1) char *endptr;
long result;
/* Check that the value is an integer */
result = strtol(pptr, &endptr, 0);
if (endptr == pptr)
{ {
TxError("Mask-hint \"%s\" has non-integer values!", /* Unable to parse correctly. Save as a string value */
pptr); proplen = strlen(pvalueptr);
DBFreePaintPlane(proprec->prop_value.prop_plane); proprec = (PropertyRecord *)mallocMagic(
TiFreePlane(proprec->prop_value.prop_plane); sizeof(PropertyRecord) - 7 + proplen);
freeMagic((char *)proprec); proprec->prop_type = PROPERTY_TYPE_STRING;
proprec = (PropertyRecord *)NULL; proprec->prop_len = proplen;
break; strcpy(proprec->prop_value.prop_string, pvalueptr);
} (void) DBPropPut(cellDef, propertyname, proprec);
if (scalen > 1) ival *= scalen;
if (scaled > 1) ival /= scaled;
switch (numvals)
{
case 0:
r.r_xbot = ival;
numvals++;
break;
case 1:
r.r_ybot = ival;
numvals++;
break;
case 2:
r.r_xtop = ival;
numvals++;
break;
case 3:
r.r_ytop = ival;
numvals = 0;
/* Paint this into the plane */
DBPaintPlane(proprec->prop_value.prop_plane,
&r, CIFPaintTable,
(PaintUndoInfo *)NULL);
break; break;
} }
while (!isspace(*pptr) && (*pptr != '\0')) pptr++; while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
numvals++;
} }
} }
if (numvals != 0) if (numvals % 4 != 0)
{ {
TxError("Mask-hint property number of values is not" TxError("Cannot read bounding box values in %s property",
" divisible by four. Truncated.\n"); propertyname);
/* This does not need to be a fatal error. Extra
* values will be unused.
*/
}
pptr = pvalueptr;
proprec = (PropertyRecord *)mallocMagic(
sizeof(PropertyRecord) + ((numvals - 2) * sizeof(int)));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = numvals;
/* Do a second pass through the string to convert the values
* to dimensions and save as an integer array.
*/
numvals = 0;
while (*pptr != '\0')
{
while (isspace(*pptr) && (*pptr != '\0')) pptr++;
if (!isspace(*pptr))
{
sscanf(pptr, "%d", &ival);
if (scalen > 1) ival *= scalen;
if (scaled > 1) ival /= scaled;
proprec->prop_value.prop_integer[numvals] = ival;
while (!isspace(*pptr) && (*pptr != '\0')) pptr++;
numvals++;
}
} }
(void) DBPropPut(cellDef, propertyname, proprec); (void) DBPropPut(cellDef, propertyname, proprec);
} }
@ -3490,23 +3481,6 @@ DBCellFindScale(cellDef)
return ggcf; return ggcf;
} }
/*
* ----------------------------------------------------------------------------
*
* dbFindGCFFunc ---
*
* Find the greatest common factor between the current GCF and each point
* in a tile.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* May modify the GCF passed as client data to the function.
*
* ----------------------------------------------------------------------------
*/
int int
dbFindGCFFunc(tile, dinfo, ggcf) dbFindGCFFunc(tile, dinfo, ggcf)
Tile *tile; Tile *tile;
@ -3529,24 +3503,6 @@ dbFindGCFFunc(tile, dinfo, ggcf)
return (*ggcf == 1) ? 1 : 0; return (*ggcf == 1) ? 1 : 0;
} }
/*
* ----------------------------------------------------------------------------
*
* dbFindCellGCFFunc ---
*
* Find the greatest common factor between the current GCF and each point
* of a uses bounding box, each component of the use's transform , and
* for arrays, the array pitch.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* May modify the GCF passed as client data to the function.
*
* ----------------------------------------------------------------------------
*/
int int
dbFindCellGCFFunc(cellUse, ggcf) dbFindCellGCFFunc(cellUse, ggcf)
CellUse *cellUse; /* Cell use whose "call" is to be written to a file */ CellUse *cellUse; /* Cell use whose "call" is to be written to a file */
@ -3587,23 +3543,6 @@ dbFindCellGCFFunc(cellUse, ggcf)
return (*ggcf == 1) ? 1 : 0; return (*ggcf == 1) ? 1 : 0;
} }
/*
* ----------------------------------------------------------------------------
*
* dbFindPropGCFFunc ---
*
* Find the greatest common factor between the current GCF and each point
* of a dimension property, or each point of each tile in a plane property.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* May modify the GCF passed as client data to the function.
*
* ----------------------------------------------------------------------------
*/
int int
dbFindPropGCFFunc(key, proprec, ggcf) dbFindPropGCFFunc(key, proprec, ggcf)
char *key; char *key;
@ -3612,28 +3551,20 @@ dbFindPropGCFFunc(key, proprec, ggcf)
{ {
int value, n; int value, n;
if (proprec->prop_type == PROPERTY_TYPE_PLANE) /* Only PROPERTY_TYPE_DIMENSION properties get handled */
{ if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, dbFindGCFFunc, (ClientData)ggcf))
return (*ggcf == 1) ? 1 : 0;
}
else if (proprec->prop_type == PROPERTY_TYPE_DIMENSION)
{
for (n = 0; n < proprec->prop_len; n++) for (n = 0; n < proprec->prop_len; n++)
{ {
value = proprec->prop_value.prop_integer[n]; value = proprec->prop_value.prop_integer[n];
if (value % (*ggcf) != 0) if (value % (*ggcf) != 0)
*ggcf = FindGCF(value, *ggcf); *ggcf = FindGCF(value, *ggcf);
} }
return (*ggcf == 1) ? 1 : 0; return (*ggcf == 1) ? 1 : 0;
}
else
/* Only PROPERTY_TYPE_PLANE and PROPERTY_TYPE_DIMENSION get handled */
return 0;
} }
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -3642,12 +3573,6 @@ dbFindPropGCFFunc(key, proprec, ggcf)
* String comparison of two instance names, for the purpose of sorting * String comparison of two instance names, for the purpose of sorting
* the instances in a .mag file output in a repeatable way. * the instances in a .mag file output in a repeatable way.
* *
* Results:
* The string comparison, equivalent to the return value of strcmp().
*
* Side effects:
* None.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -3685,9 +3610,6 @@ struct cellUseList {
* Return value: * Return value:
* Return 0 to keep the search going. * Return 0 to keep the search going.
* *
* Side effects:
* Adds to the list of cell uses passed as client data.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -3713,9 +3635,6 @@ dbGetUseFunc(cellUse, useRec)
* Return value: * Return value:
* Return 0 to keep the search going. * Return 0 to keep the search going.
* *
* Side effects:
* Increments the count passed as client data.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -3744,12 +3663,6 @@ struct keyValuePair {
* String comparison of two property keys, for the purpose of sorting * String comparison of two property keys, for the purpose of sorting
* the properties in a .mag file output in a repeatable way. * the properties in a .mag file output in a repeatable way.
* *
* Results:
* The string comparison, equivalent to the result of strcmp().
*
* Side effects:
* None.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -3785,9 +3698,6 @@ struct cellPropList {
* Return value: * Return value:
* Return 0 to keep the search going. * Return 0 to keep the search going.
* *
* Side Effects:
* Adds to the list of property records passed as client data.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -3817,9 +3727,6 @@ dbGetPropFunc(key, proprec, propRec)
* Return value: * Return value:
* Return 0 to keep the search going. * Return 0 to keep the search going.
* *
* Side Effects:
* Increments the count passed as client data.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -4157,52 +4064,6 @@ ioerror:
return (TRUE); return (TRUE);
} }
/*
* ----------------------------------------------------------------------------
*
* dbWritePropPaintFunc --
*
* Transform tiles in a plane into a set of four coordinate values and output
* them to the file. This turns plane data into a PROP_TYPE_DIMENSION array,
* which is not a very efficient form and may be revisited. For relatively
* simple plane data, it suffices. The property planes are single-bit types.
* Note that there is no support for non-Manhattan geometry in the property
* plane at this time.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
int
dbWritePropPaintFunc(Tile *tile,
TileType dinfo,
ClientData cdata)
{
pwfrec *pwf = (pwfrec *)cdata;
FILE *f = pwf->pwf_file;
int reducer = pwf->pwf_reducer;
Rect r;
char newvalue[20];
TiToRect(tile, &r);
snprintf(newvalue, 20, " %d", r.r_xbot / reducer);
FPUTSR(f, newvalue);
snprintf(newvalue, 20, " %d", r.r_ybot / reducer);
FPUTSR(f, newvalue);
snprintf(newvalue, 20, " %d", r.r_xtop / reducer);
FPUTSR(f, newvalue);
snprintf(newvalue, 20, " %d", r.r_ytop / reducer);
FPUTSR(f, newvalue);
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -4250,12 +4111,6 @@ dbWritePropFunc(key, proprec, cdata)
case PROPERTY_TYPE_INTEGER: case PROPERTY_TYPE_INTEGER:
FPUTSR(f, "integer "); FPUTSR(f, "integer ");
break; break;
case PROPERTY_TYPE_PLANE:
/* A mask hint is a plane type property; declare it
* as a dimension, but it's arbitrary anyway since
* the prefix "MASKHINTS_" is detected on read-in and
* the property is parsed as plane data.
*/
case PROPERTY_TYPE_DIMENSION: case PROPERTY_TYPE_DIMENSION:
FPUTSR(f, "dimension "); FPUTSR(f, "dimension ");
break; break;
@ -4288,13 +4143,6 @@ dbWritePropFunc(key, proprec, cdata)
FPUTSR(f, newvalue); FPUTSR(f, newvalue);
} }
break; break;
case PROPERTY_TYPE_PLANE:
/* Scan the plane and output each non-space tile as four values */
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, dbWritePropPaintFunc,
(ClientData)cdata);
break;
case PROPERTY_TYPE_DOUBLE: case PROPERTY_TYPE_DOUBLE:
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
{ {
@ -4419,7 +4267,7 @@ DBCellWriteCommandFile(cellDef, f)
} }
else else
{ {
fprintf(f, "label %s %s %d %d %d %d %s %s%s\n", fprintf(f, "label %s %s %d %d %d %d %s %s\n",
lab->lab_text, lab->lab_text,
DBFontList[lab->lab_font]->mf_name, DBFontList[lab->lab_font]->mf_name,
lab->lab_size >> 3, lab->lab_size >> 3,
@ -4427,10 +4275,15 @@ DBCellWriteCommandFile(cellDef, f)
lab->lab_offset.p_x, lab->lab_offset.p_x,
lab->lab_offset.p_y, lab->lab_offset.p_y,
directionNames[lab->lab_just], directionNames[lab->lab_just],
(lab->lab_flags & LABEL_STICKY) ? "-" : "",
DBTypeLongName(lab->lab_type)); DBTypeLongName(lab->lab_type));
} }
if (lab->lab_flags & LABEL_STICKY)
{
fprintf(f, "select area label\n");
fprintf(f, "setlabel sticky true\n");
}
if (lab->lab_flags & PORT_DIR_MASK) if (lab->lab_flags & PORT_DIR_MASK)
{ {
if (!(lab->lab_flags & LABEL_STICKY)) if (!(lab->lab_flags & LABEL_STICKY))
@ -4542,12 +4395,6 @@ ioerror:
* Callback function used by DBCellWriteCommandFile() to output * Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to cell layout geometry. * commands corresponding to cell layout geometry.
* *
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -4613,12 +4460,6 @@ dbWritePaintCommandsFunc(tile, dinfo, cdarg)
* Callback function used by DBCellWriteCommandFile() to output * Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to cell uses in the layout. * commands corresponding to cell uses in the layout.
* *
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -4638,45 +4479,6 @@ dbWriteUseCommandsFunc(cellUse, cdarg)
return 0; return 0;
} }
/*
* ----------------------------------------------------------------------------
*
* dbWritePropCommandPaintFunc --
*
* Transform tiles in a plane into a set of four coordinate values and output
* them to the file. This turns plane data into a PROP_TYPE_DIMENSION array,
* which is not a very efficient form and may be revisited. For relatively
* simple plane data, it suffices. The property planes are single-bit types.
* Note that there is no support for non-Manhattan geometry in the property
* plane at this time.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ----------------------------------------------------------------------------
*/
int
dbWritePropCommandPaintFunc(Tile *tile,
TileType dinfo,
FILE *f)
{
Rect r;
MagWindow *w;
TiToRect(tile, &r);
windCheckOnlyWindow(&w, DBWclientID);
fprintf(f, "%s ", DBWPrintValue(r.r_xbot, w, TRUE));
fprintf(f, "%s ", DBWPrintValue(r.r_ybot, w, FALSE));
fprintf(f, "%s ", DBWPrintValue(r.r_xtop, w, TRUE));
fprintf(f, "%s ", DBWPrintValue(r.r_ytop, w, FALSE));
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -4685,12 +4487,6 @@ dbWritePropCommandPaintFunc(Tile *tile,
* Callback function used by DBCellWriteCommandFile() to output * Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to properties in the layout. * commands corresponding to properties in the layout.
* *
* Results:
* 0 to keep the search going.
*
* Side effects:
* Writes output to a file.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -4744,19 +4540,6 @@ dbWritePropCommandsFunc(key, proprec, cdarg)
fprintf(f, "\n"); fprintf(f, "\n");
break; break;
case PROPERTY_TYPE_PLANE:
/* Plane properties are automatically handled as plane data,
* so the property type does not need to be declared.
* Only mask hints can be plane properties.
*/
fprintf(f, "property %s ", key);
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
proprec->prop_value.prop_plane,
&TiPlaneRect, &CIFSolidBits, dbWritePropCommandPaintFunc,
(ClientData)f);
fprintf(f, "\n");
break;
case PROPERTY_TYPE_DOUBLE: case PROPERTY_TYPE_DOUBLE:
fprintf(f, "property double %s ", key); fprintf(f, "property double %s ", key);
for (i = 0; i < proprec->prop_len; i++) for (i = 0; i < proprec->prop_len; i++)
@ -4790,6 +4573,7 @@ dbWritePropCommandsFunc(key, proprec, cdarg)
* the file. If successful, rewind the now-expanded file and * the file. If successful, rewind the now-expanded file and
* overwrite the beginning of the file, then truncate it. * overwrite the beginning of the file, then truncate it.
* *
*
* Results: * Results:
* TRUE if the cell could be written successfully, FALSE otherwise. * TRUE if the cell could be written successfully, FALSE otherwise.
* *

View File

@ -574,8 +574,7 @@ DBReOrientLabel(cellDef, area, newPos)
* dbGetLabelArea --- * dbGetLabelArea ---
* *
* Callback function used by DBAdjustLabels. Find all material under a label * Callback function used by DBAdjustLabels. Find all material under a label
* that is *not* the label type, and return the label area adjusted to leave * that is *not* the label type, and return the
* out that amount.
* *
* Note: This clips in a regular order, and does not consider what is the * Note: This clips in a regular order, and does not consider what is the
* largest rectangular area outside the area that has been clipped out. * largest rectangular area outside the area that has been clipped out.
@ -605,26 +604,6 @@ dbGetLabelArea(tile, dinfo, area)
return 0; return 0;
} }
/*
* ----------------------------------------------------------------------------
*
* dbLabelNotEmpty ---
*
* Callback function used by DBAdjustLabels. Finds any material under a
* label that is the label type, and returns 1 to stop the search.
*
* ----------------------------------------------------------------------------
*/
int
dbLabelNotEmpty(tile, dinfo, clientData)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information (unused) */
ClientData clientData; /* (unused) */
{
return 1;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -682,13 +661,6 @@ DBAdjustLabels(def, area)
TTMaskSetOnlyType(&lmask, lab->lab_type); TTMaskSetOnlyType(&lmask, lab->lab_type);
/* To do: Add compatible types (contact, residue) */ /* To do: Add compatible types (contact, residue) */
/* If there is no material left inside the label area, then
* the label gets reassigned to space.
*/
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)],
&lab->lab_rect, &lmask, dbLabelNotEmpty, (ClientData)NULL) == 1)
{
TTMaskCom(&lmask); TTMaskCom(&lmask);
r = lab->lab_rect; r = lab->lab_rect;
@ -697,8 +669,7 @@ DBAdjustLabels(def, area)
if (!GEO_RECTNULL(&r)) if (!GEO_RECTNULL(&r))
{ {
if ((DBVerbose >= DB_VERBOSE_ALL) && if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
((def->cd_flags & CDINTERNAL) == 0))
{ {
TxPrintf("Adjusting size of label \"%s\" in cell %s.\n", TxPrintf("Adjusting size of label \"%s\" in cell %s.\n",
lab->lab_text, def->cd_name); lab->lab_text, def->cd_name);
@ -714,7 +685,6 @@ DBAdjustLabels(def, area)
adjusted = TRUE; adjusted = TRUE;
} }
} }
}
if (!adjusted) if (!adjusted)
{ {

View File

@ -106,18 +106,7 @@ DBPropPut(cellDef, name, value)
entry = HashFind(htab, name); entry = HashFind(htab, name);
oldvalue = (PropertyRecord *)HashGetValue(entry); oldvalue = (PropertyRecord *)HashGetValue(entry);
/* All properties are allocated as a single block and can just be freed, if (oldvalue != NULL) freeMagic((char *)oldvalue);
* 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) if (value == (PropertyRecord *)NULL)
HashRemove(htab, name); HashRemove(htab, name);
else else

View File

@ -238,11 +238,9 @@ DBUpdateStamps(def)
} }
} }
/*ARGSUSED*/
int int
dbStampFunc(cellDef, cdata) dbStampFunc(cellDef)
CellDef *cellDef; CellDef *cellDef;
ClientData cdata; /* UNUSED */
{ {
CellUse *cu; CellUse *cu;
CellDef *cd; CellDef *cd;

View File

@ -578,20 +578,6 @@ typedef struct extRectList
struct extRectList *r_next; struct extRectList *r_next;
} ExtRectList; } ExtRectList;
/* Structure similar to the above, but adding a pointer to a cell use ID
* and a client data record which can be used to hold a region pointer.
*/
typedef struct extConnList
{
char *r_useid; /* Cell Use being connected to */
TileType r_type; /* Connecting tile type in the parent */
Rect r_r; /* Area of connection */
ClientData r_upnode; /* Parent node making the connection */
ClientData r_downnode; /* Child node making the connection */
struct extConnList *r_next; /* Next item in the linked list */
} ExtConnList;
/* -------------------- Search context information -------------------- */ /* -------------------- Search context information -------------------- */
/* Search contexts are used in hierarchical searches */ /* Search contexts are used in hierarchical searches */
@ -665,7 +651,6 @@ 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 */
@ -734,7 +719,6 @@ typedef struct
char prop_string[8]; /* For PROPERTY_TYPE_STRING */ char prop_string[8]; /* For PROPERTY_TYPE_STRING */
int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */ int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */
dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */ dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */
Plane *prop_plane; /* For PROPERTY_TYPE_PLANE */
} prop_value; } prop_value;
} PropertyRecord; } PropertyRecord;
@ -776,7 +760,6 @@ typedef struct
#define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */ #define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */
#define PROPERTY_TYPE_DIMENSION 2 /* Integer property that scales with units */ #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_DOUBLE 3 /* Double-long integer (for file positions) */
#define PROPERTY_TYPE_PLANE 4 /* A tile plane structure */
/* -------------------- Exported procedure headers -------------------- */ /* -------------------- Exported procedure headers -------------------- */
@ -1076,19 +1059,6 @@ 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 ------------------- */
/*** /***

View File

@ -131,11 +131,8 @@ DBWAddButtonHandler(
for (i = 0; i < MAXBUTTONHANDLERS; i++) for (i = 0; i < MAXBUTTONHANDLERS; i++)
{ {
if (dbwButtonHandlers[i] != NULL) continue; if (dbwButtonHandlers[i] != NULL) continue;
StrDup(&dbwButtonHandlers[i], name); (void) StrDup(&dbwButtonHandlers[i], name);
if (doc != NULL) (void) StrDup(&dbwButtonDoc[i], doc);
StrDup(&dbwButtonDoc[i], doc);
else
dbwButtonDoc[i] = (char *)NULL;
dbwButtonProcs[i] = proc; dbwButtonProcs[i] = proc;
dbwButtonCursors[i] = cursor; dbwButtonCursors[i] = cursor;
return; return;
@ -276,37 +273,6 @@ DBWGetButtonHandler()
return dbwButtonHandlers[dbwButtonCurrentIndex]; 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;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -328,10 +294,7 @@ DBWButtonHandlerIndex(char *toolName)
void void
DBWPrintButtonDoc() DBWPrintButtonDoc()
{ {
if (dbwButtonDoc[dbwButtonCurrentIndex])
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]); TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
else
TxPrintf("(no usage information)\n");
} }

View File

@ -149,9 +149,6 @@ extern void CmdAutoExtToSpice();
#else #else
extern void CmdExtToSpice(); extern void CmdExtToSpice();
#endif #endif
#else /* !MAGIC_WRAPPER */
extern void CmdExtToSim();
extern void CmdExtToSpice();
#endif #endif
/* /*
@ -572,24 +569,6 @@ DBWInitCommands()
" type\n\t\t\t\"ext2spice help\" for information on options", " type\n\t\t\t\"ext2spice help\" for information on options",
CmdExtToSpice, FALSE); CmdExtToSpice, FALSE);
#endif /* EXT2SPICE_AUTO */ #endif /* EXT2SPICE_AUTO */
#else /* !MAGIC_WRAPPER */
/* In non-Tcl builds (e.g. WASM), register the C implementations directly */
WindAddCommand(DBWclientID,
"exttosim [args] convert extracted file(s) to a sim format file;"
" type\n\t\t\t\"exttosim help\" for information on options",
CmdExtToSim, FALSE);
WindAddCommand(DBWclientID,
"ext2sim [args] convert extracted file(s) to a sim format file;"
" type\n\t\t\t\"ext2sim help\" for information on options",
CmdExtToSim, FALSE);
WindAddCommand(DBWclientID,
"exttospice [args] convert extracted file(s) to a SPICE format file;"
" type\n\t\t\t\"exttospice help\" for information on options",
CmdExtToSpice, FALSE);
WindAddCommand(DBWclientID,
"ext2spice [args] convert extracted file(s) to a SPICE format file;"
" type\n\t\t\t\"ext2spice help\" for information on options",
CmdExtToSpice, FALSE);
#endif /* MAGIC_WRAPPER */ #endif /* MAGIC_WRAPPER */

View File

@ -421,8 +421,7 @@ 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, (TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
TF_LABEL_DISPLAY | TF_LABEL_ATTACH | TF_LABEL_REVERSE_SEARCH,
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers)); dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
GrClipTo(&rootClip); GrClipTo(&rootClip);
} }

View File

@ -867,11 +867,8 @@ dbwelemGetTransform(use, transform, cdarg)
return 1; return 1;
} }
/*ARGSUSED*/
int int
dbwElementAlways1(w, clientData) dbwElementAlways1()
MagWindow *w; /* UNUSED */
ClientData clientData; /* UNUSED */
{ {
return 1; return 1;
} }

View File

@ -531,11 +531,8 @@ dbwfbGetTransform(use, transform, cdarg)
* cell. * cell.
*/ */
/*ARGSUSED*/
int int
dbwfbWindFunc(w, clientData) dbwfbWindFunc()
MagWindow *w; /* UNUSED */
ClientData clientData; /* UNUSED */
{ {
return 1; return 1;
} }

View File

@ -357,11 +357,9 @@ DBWHLRedrawPrepWindow(MagWindow *window, Rect *area)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
DBWHLRedrawWind(window, clientData) DBWHLRedrawWind(window)
MagWindow *window; /* Window in which to redraw highlights. */ MagWindow *window; /* Window in which to redraw highlights. */
ClientData clientData; /* UNUSED */
{ {
int i; int i;
DBWclientRec *crec; DBWclientRec *crec;

View File

@ -546,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, DB_EXPAND); ((DBWclientRec *)window->w_clientData)->dbw_bitmask, TRUE);
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,
DB_UNEXPAND, UnexpandFunc, FALSE, UnexpandFunc,
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask)); INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
if (newEdit) if (newEdit)

View File

@ -152,7 +152,6 @@ extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandle
int cursor, const char *doc); int cursor, const char *doc);
extern char *DBWGetButtonHandler(); extern char *DBWGetButtonHandler();
extern char *DBWChangeButtonHandler(); extern char *DBWChangeButtonHandler();
extern int DBWButtonHandlerIndex();
extern void DBWPrintButtonDoc(); extern void DBWPrintButtonDoc();
extern void DBWBoxHandler(); extern void DBWBoxHandler();

View File

@ -71,15 +71,12 @@ 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> [<B>-noprompt</B>] <DT> <B>delete</B> <I>name</I>
<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)". If option <B>-noprompt</B> with default cell "(UNNAMED)".
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

View File

@ -334,23 +334,23 @@
</TR> </TR>
<TR> <TR>
<TD> <A HREF=undo.html> <B>undo</B></A> </TD> <TD> <A HREF=undo.html> <B>undo</B></A> </TD>
<TD> <A HREF=units.html> <B>units</B></A> </TD>
<TD> <A HREF=updatedisplay.html> <B>updatedisplay</B></A> </TD> <TD> <A HREF=updatedisplay.html> <B>updatedisplay</B></A> </TD>
<TD> <A HREF=version.html> <B>version</B></A> </TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=version.html> <B>version</B></A> </TD>
<TD> <A HREF=view.html> <B>view</B></A> </TD> <TD> <A HREF=view.html> <B>view</B></A> </TD>
<TD> <A HREF=windowborder.html> <B>windowborder</B></A> </TD> <TD> <A HREF=windowborder.html> <B>windowborder</B></A> </TD>
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
<TD> <A HREF=windownames.html> <B>windownames</B></A> </TD> <TD> <A HREF=windownames.html> <B>windownames</B></A> </TD>
<TD> <A HREF=windowscrollbars.html> <B>windowscrollbars</B></A> </TD> <TD> <A HREF=windowscrollbars.html> <B>windowscrollbars</B></A> </TD>
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
<TD> <A HREF=zoom.html> <B>zoom</B></A> </TD> <TD> <A HREF=zoom.html> <B>zoom</B></A> </TD>
<TD> <A HREF=tk_path_name.html> <I>tk_path_name</I></A> </TD> <TD> <A HREF=tk_path_name.html> <I>tk_path_name</I></A> </TD>
<TD> </TD>
</TR> </TR>
</TBODY> </TBODY>
</TABLE> </TABLE>
@ -367,7 +367,7 @@
<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=archive.html> <B>archive</B></A></TD> <TD> <A HREF=archive.html> <B>array</B></A></TD>
<TD> <A HREF=array.html> <B>array</B></A></TD> <TD> <A HREF=array.html> <B>array</B></A></TD>
<TD> <A HREF=box.html> <B>box</B></A></TD> <TD> <A HREF=box.html> <B>box</B></A></TD>
</TR> </TR>
@ -402,28 +402,28 @@
<TD> <A HREF=deletecommandentry.html> <B>deletecommandentry</B></A></TD> <TD> <A HREF=deletecommandentry.html> <B>deletecommandentry</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=display.html> <B>display</B></A></TD>
<TD> <A HREF=down.html> <B>down</B></A></TD> <TD> <A HREF=down.html> <B>down</B></A></TD>
<TD> <A HREF=drc.html> <B>drc</B></A></TD> <TD> <A HREF=drc.html> <B>drc</B></A></TD>
</TR>
<TR>
<TD> <A HREF=drop.html> <B>drop</B></A></TD>
<TD> <A HREF=dump.html> <B>dump</B></A></TD> <TD> <A HREF=dump.html> <B>dump</B></A></TD>
<TD> <A HREF=edit.html> <B>edit</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=edit.html> <B>edit</B></A></TD>
<TD> <A HREF=element.html> <B>element</B></A></TD> <TD> <A HREF=element.html> <B>element</B></A></TD>
<TD> <A HREF=erase.html> <B>erase</B></A></TD> <TD> <A HREF=erase.html> <B>erase</B></A></TD>
<TD> <A HREF=expand.html> <B>expand</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=expand.html> <B>expand</B></A></TD>
<TD> <A HREF=ext.html> <B>ext</B></A></TD> <TD> <A HREF=ext.html> <B>ext</B></A></TD>
<TD> <A HREF=ext2sim.html> <B>ext2sim</B></A></TD> <TD> <A HREF=ext2sim.html> <B>ext2sim</B></A></TD>
<TD> <A HREF=ext2spice.html> <B>ext2spice</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=ext2spice.html> <B>ext2spice</B></A></TD>
<TD> <A HREF=extract.html> <B>extract</B></A></TD> <TD> <A HREF=extract.html> <B>extract</B></A></TD>
<TD> <A HREF=extresist.html> <B>extresist</B></A></TD> <TD> <A HREF=extresist.html> <B>extresist</B></A></TD>
</TR>
<TR>
<TD> <A HREF=ext2sim.html> <B>exttosim</B></A></TD>
<TD> <A HREF=ext2spice.html> <B>exttospice</B></A></TD>
<TD> <A HREF=feedback.html> <B>feedback</B></A></TD> <TD> <A HREF=feedback.html> <B>feedback</B></A></TD>
</TR> </TR>
<TR> <TR>
@ -462,82 +462,77 @@
<TD> <A HREF=load.html> <B>load</B></A></TD> <TD> <A HREF=load.html> <B>load</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=locking.html> <B>locking</B></A></TD>
<TD> <A HREF=maketoolbar.html> <B>maketoolbar</B></A></TD> <TD> <A HREF=maketoolbar.html> <B>maketoolbar</B></A></TD>
<TD> <A HREF=move.html> <B>move</B></A></TD>
<TD> <A HREF=measure.html> <B>measure</B></A></TD> <TD> <A HREF=measure.html> <B>measure</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=move.html> <B>move</B></A></TD>
<TD> <A HREF=openwrapper.html> <B>openwrapper</B></A></TD> <TD> <A HREF=openwrapper.html> <B>openwrapper</B></A></TD>
<TD> <A HREF=paint.html> <B>paint</B></A></TD> <TD> <A HREF=paint.html> <B>paint</B></A></TD>
<TD> <A HREF=path.html> <B>path</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=path.html> <B>path</B></A></TD>
<TD> <A HREF=peekbox.html> <B>peekbox</B></A></TD> <TD> <A HREF=peekbox.html> <B>peekbox</B></A></TD>
<TD> <A HREF=plot.html> <B>plot</B></A></TD> <TD> <A HREF=plot.html> <B>plot</B></A></TD>
<TD> <A HREF=plow.html> <B>plow</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=plow.html> <B>plow</B></A></TD>
<TD> <A HREF=polygon.html> <B>polygon</B></A></TD> <TD> <A HREF=polygon.html> <B>polygon</B></A></TD>
<TD> <A HREF=popbox.html> <B>popbox</B></A></TD> <TD> <A HREF=popbox.html> <B>popbox</B></A></TD>
<TD> <A HREF=popstack.html> <B>popstack</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=popstack.html> <B>popstack</B></A></TD>
<TD> <A HREF=port.html> <B>port</B></A></TD> <TD> <A HREF=port.html> <B>port</B></A></TD>
<TD> <A HREF=promptload.html> <B>promptload</B></A></TD> <TD> <A HREF=promptload.html> <B>promptload</B></A></TD>
<TD> <A HREF=promptsave.html> <B>promptsave</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=promptsave.html> <B>promptsave</B></A></TD>
<TD> <A HREF=property.html> <B>property</B></A></TD> <TD> <A HREF=property.html> <B>property</B></A></TD>
<TD> <A HREF=pushbox.html> <B>pushbox</B></A></TD> <TD> <A HREF=pushbox.html> <B>pushbox</B></A></TD>
</TR>
<TR>
<TD> <A HREF=pushstack.html> <B>pushstack</B></A></TD> <TD> <A HREF=pushstack.html> <B>pushstack</B></A></TD>
<TD> <A HREF=readspice.html> <B>readspice</B></A></TD>
<TD> <A HREF=render3d.html> <B>render3d</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=render3d.html> <B>render3d</B></A></TD>
<TD> <A HREF=resumeall.html> <B>resumeall</B></A></TD> <TD> <A HREF=resumeall.html> <B>resumeall</B></A></TD>
<TD> <A HREF=rotate.html> <B>rotate</B></A></TD> <TD> <A HREF=rotate.html> <B>rotate</B></A></TD>
<TD> <A HREF=route.html> <B>route</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=route.html> <B>route</B></A></TD>
<TD> <A HREF=save.html> <B>save</B></A></TD> <TD> <A HREF=save.html> <B>save</B></A></TD>
<TD> <A HREF=scalegrid.html> <B>scalegrid</B></A></TD> <TD> <A HREF=scalegrid.html> <B>scalegrid</B></A></TD>
<TD> <A HREF=search.html> <B>search</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=search.html> <B>search</B></A></TD>
<TD> <A HREF=see.html> <B>see</B></A></TD> <TD> <A HREF=see.html> <B>see</B></A></TD>
<TD> <A HREF=select.html> <B>select</B></A></TD> <TD> <A HREF=select.html> <B>select</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=setlabel.html> <B>setlabel</B> <I>(version 8.0)</I></A></TD>
<TD> <A HREF=shell.html> <B>shell</B></A></TD> <TD> <A HREF=shell.html> <B>shell</B></A></TD>
<TD> <A HREF=sideways.html> <B>sideways</B></A></TD> <TD> <A HREF=sideways.html> <B>sideways</B></A></TD>
<TD> <A HREF=snap.html> <B>snap</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=snap.html> <B>snap</B></A></TD>
<TD> <A HREF=spliterase.html> <B>spliterase</B></A></TD> <TD> <A HREF=spliterase.html> <B>spliterase</B></A></TD>
<TD> <A HREF=splitpaint.html> <B>splitpaint</B></A></TD> <TD> <A HREF=splitpaint.html> <B>splitpaint</B></A></TD>
<TD> <A HREF=startup.html> <B>startup</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=startup.html> <B>startup</B></A></TD>
<TD> <A HREF=straighten.html> <B>straighten</B></A></TD> <TD> <A HREF=straighten.html> <B>straighten</B></A></TD>
<TD> <A HREF=stretch.html> <B>stretch</B></A></TD> <TD> <A HREF=stretch.html> <B>stretch</B></A></TD>
<TD> <A HREF=suspendall.html> <B>suspendall</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=suspendall.html> <B>suspendall</B></A></TD>
<TD> <A HREF=tag.html> <B>tag</B></A></TD> <TD> <A HREF=tag.html> <B>tag</B></A></TD>
<TD> <A HREF=tech.html> <B>tech</B></A></TD> <TD> <A HREF=tech.html> <B>tech</B></A></TD>
<TD> <A HREF=techmanager.html> <B>techmanager</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=techmanager.html> <B>techmanager</B></A></TD>
<TD> <A HREF=tool.html> <B>tool</B> <I>(non-Tcl version)</I></A></TD> <TD> <A HREF=tool.html> <B>tool</B> <I>(non-Tcl version)</I></A></TD>
<TD> <A HREF=changetool.html> <B>tool</B> <I>(Tcl version)</I></A></TD> <TD> <A HREF=changetool.html> <B>tool</B> <I>(Tcl version)</I></A></TD>
<TD> <A HREF=unexpand.html> <B>unexpand</B></A></TD>
</TR> </TR>
<TR> <TR>
<TD> <A HREF=units.html> <B>units</B></A> </TD> <TD> <A HREF=unexpand.html> <B>unexpand</B></A></TD>
<TD> <A HREF=unmeasure.html> <B>unmeasure</B></A></TD> <TD> <A HREF=unmeasure.html> <B>unmeasure</B></A></TD>
<TD> <A HREF=upsidedown.html> <B>upsidedown</B></A></TD> <TD> <A HREF=upsidedown.html> <B>upsidedown</B></A></TD>
</TR> </TR>
@ -548,7 +543,7 @@
</TR> </TR>
<TR> <TR>
<TD> <A HREF=xload.html> <B>xload</B></A></TD> <TD> <A HREF=xload.html> <B>xload</B></A></TD>
<TD> <A HREF=xor.html> <B>xor</B></A></TD> <TD> </TD>
<TD> </TD> <TD> </TD>
</TR> </TR>
</TBODY> </TBODY>

View File

@ -26,8 +26,7 @@ expanded/unexpanded cells in the current selection.
<H3>Usage:</H3> <H3>Usage:</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<B>expand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>] <B>expand</B> [<B>toggle</B>] <BR><BR>
[<B>toggle</B>] <BR><BR>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3>Shortcuts:</H3> <H3>Shortcuts:</H3>
@ -39,32 +38,14 @@ 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. display the contents of the subcells. Without arguments,
the <B>expand</B> command expands all unexpanded subcells that
Option <B>overlap</B> expands all unexpanded subcells that touch or intersect the cursor box in the layout window. <P>
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>

View File

@ -102,17 +102,16 @@ 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> [<B>notopports</B>] <DT> <B>unique</B>
<DD> (Added in magic version 8.3.594) This setting replaces <DD> (Added in magic version 8.3.594) This setting replaces
the use of the command option "extract unique" (and the use of the command option "extract unique". Instead
"extract unique notopports"). Instead of changing labels of changing labels in the design, unique labels are
in the design, unique labels are generated for the duration generated for the duration of the extraction, and then
of the extraction, and then reverted back to the original reverted back to the original text. The "extract unique"
text. The "extract unique" command option is maintained command option is maintained for backwards compatibility.
for backwards compatibility. Note the difference: Note the difference: "extract unique" is a command that
"extract unique" is a command that runs immediately, and runs immediately, and cannot be undone;
cannot be undone; "extract do unique" is an option setting "extract do unique" is an option setting for "extract".
for "extract".
<DT> <B>resistance</B> <DT> <B>resistance</B>
<DD> (Added in magic version 8.3.597) This setting replaces <DD> (Added in magic version 8.3.597) This setting replaces
the use of the standalone command "extresist". The the use of the standalone command "extresist". The

View File

@ -30,30 +30,11 @@ information.
<BLOCKQUOTE> <BLOCKQUOTE>
where <I>option</I> may be one of the following: where <I>option</I> may be one of the following:
<DL> <DL>
<DT> <B>tolerance</B> <I>value</I>
<DD> Set the ratio between resistor and transistor tolerance
for determining when to insert resistance into a network route.
<DT> <B>all</B> <DT> <B>all</B>
<DD> Extract all the nets. <DD> Extract all the nets.
<DT> <B>threshold</B> [<I>value</I>]
<DD> With no value given, returns the current lumped resistance
threshold used to determine if a network will or will not be
analyzed for resistance extraction, in milliohms. The default
<B>threshold</B> value is 10000 milliohms (10 ohms). If
<I>value</I> is given, then set the lumped resistance threshold
to <I>value</I> milliohms.
<DT> <B>mindelay</B> [<I>value</I>]
<DD> With no value given, returns the current delay time threshold
used to determine if a network will or will not be analyzed for
resistance extraction, in picoseconds. The default
<B>mindelay</B> value is 1ps. If <I>value</I> is given,
then set the delay threshold to <I>value</I> picoseconds.
<DT> <B>minres</B> [<I>value</I>]
<DD> With no value given, returns the current absolute resistance
threshold used to prune small resistances from a network when
simplifying, in milliohms. The default <B>minres</B> value
is 1000 milliohms (1 ohm). If <I>value</I> is given, then set
the absolute resistance threshold to <I>value</I> milliohms.
Note that resistances smaller than <I>value</I> may still
appear in the output netlist if the algorithm is unable to
simplify the network around the resistor.
<DT> <B>simplify</B> [<B>on</B>|<B>off</B>] <DT> <B>simplify</B> [<B>on</B>|<B>off</B>]
<DD> Turn on/off simplification of resistor nets. <DD> Turn on/off simplification of resistor nets.
<DT> <B>extout</B> [<B>on</B>|<B>off</B>] <DT> <B>extout</B> [<B>on</B>|<B>off</B>]
@ -61,9 +42,7 @@ information.
<DT> <B>lumped</B> [<B>on</B>|<B>off</B>] <DT> <B>lumped</B> [<B>on</B>|<B>off</B>]
<DD> Turn on/off writing of updated lumped resistances. <DD> Turn on/off writing of updated lumped resistances.
<DT> <B>silent</B> [<B>on</B>|<B>off</B>] <DT> <B>silent</B> [<B>on</B>|<B>off</B>]
<DD> Turn off/on printing of nets being processed. <DD> Turn off/on printing of net statistics.
<DT> <B>debug</B> [<B>on</B>|<B>off</B>]
<DD> Turn off/on additional diagnostic information.
<DT> <B>skip</B> <I>mask</I> <DT> <B>skip</B> <I>mask</I>
<DD> Don't extract types indicated in the comma-separated list <I>mask</I> <DD> Don't extract types indicated in the comma-separated list <I>mask</I>
<DT> <B>ignore</B> [<I>netname</I>|<B>none</B>] <DT> <B>ignore</B> [<I>netname</I>|<B>none</B>]
@ -90,8 +69,6 @@ information.
<TT>.fh</TT> file. If <I>freq</I> is specified, the file will <TT>.fh</TT> file. If <I>freq</I> is specified, the file will
be customized for <B>fasthenry</B> analysis at the indicated be customized for <B>fasthenry</B> analysis at the indicated
frequency (in Hz). frequency (in Hz).
<DT> <B>tolerance</B> <I>value</I>
<DD> <I>Deprecated!</I> This option is no longer used by extresist.
<DT> <B>help</B> <DT> <B>help</B>
<DD> Print help information <DD> Print help information
</DL> </DL>
@ -102,9 +79,9 @@ information.
<BLOCKQUOTE> <BLOCKQUOTE>
The normal flow through layout extraction into a simulation file The normal flow through layout extraction into a simulation file
treats routes as nonphysical entities, that is, with infinitesimal treats routes as nonphysical entities, that is, with infinitesimal
impedence through the wires. Standard extraction generates "lumped impedence through the wires. Extraction for digital simulation
resistance" values, a single resistance per network node that, along using <B>irsim</B> generates "lumped resistances", a single
with the node capacitance resistance per network node that, along with the node capacitance
to substrate, provides an <I>RC</I> time constant to approximately to substrate, provides an <I>RC</I> time constant to approximately
model the delay from point to point in the network node. The model the delay from point to point in the network node. The
lumped resistance model is inappropriate for analog (i.e., SPICE) lumped resistance model is inappropriate for analog (i.e., SPICE)
@ -119,9 +96,10 @@ information.
Using <B>extresist</B> as a standalone command is a multi-step Using <B>extresist</B> as a standalone command is a multi-step
process. It is first necessary to run <B>extract</B> to get process. It is first necessary to run <B>extract</B> to get
the initial netlist. After a <TT>.ext</TT> file has been generated, the initial netlist.
the <B>extresist</B> command may be run. The output is a file After a <TT>.ext</TT> file has been generated, the
<TT>.res.ext</TT> for each cell in the hierarchy. <B>extresist</B> command may be run. The output is
a file <TT>.res.ext</TT> for each cell in the hierarchy.
Finally, with the option <B>extresist on</B> set, <B>ext2spice</B> Finally, with the option <B>extresist on</B> set, <B>ext2spice</B>
will generate the final, detailed simulation file. <P> will generate the final, detailed simulation file. <P>
@ -132,42 +110,7 @@ information.
magic version 8.3.597 an option <B>extract do resistance</B> magic version 8.3.597 an option <B>extract do resistance</B>
that runs the resistance extraction in sequence with the regular that runs the resistance extraction in sequence with the regular
extraction, producing both the <TT>.ext</TT> and <TT>.res.ext</TT> extraction, producing both the <TT>.ext</TT> and <TT>.res.ext</TT>
files. When <B>extract do resistance</B> is used, there is no need files.
to run <B>extresist</B> as a separate command. However,
<B>extresist</B> may be run prior to <B>extract</B> to set the
options that affect resistance network extraction, such as
<B>extresist threshold</B>, <B>extresist minres</B>, etc. <P>
As of magic version 8.3.653, the <B>extresist tolerance</B> option
is deprecated and has no effect on network resistance extraction.
Instead, extraction is controlled by three main options: <P>
<B>extresist threshold</B> (value in milliohms) sets a cutoff for
considering a network for detailed resistance extraction based on
the lumped resistance estimate (see above). For point-to-point
wires, the lumped resistance is approximately equal to the actual
wire resistance. For branching networks, it will generally be an
over-estimate. The default <B>threshold</B> value is set to
10 ohms. <P>
<B>extresist minres</B> (value in milliohms) sets a cutoff for
individual resistors in the detailed resistor network. Resistors
below this threshold will get pruned out of the network if the
simplification algorithm is able to remove them. The default
<B>minres</B> value is set to 1 ohm. <P>
<B>extresist mindelay</B> (value in picoseconds) sets a cutoff for
considering a network for detailed resistance extraction based on
the end-to-end delay calculated from the lumped resistance
estimate. Once the network has been extracted, the <B>mindelay</B>
value is again evaluated against a revised calculation of the
delay to determine if the extracted detailed network should be
output. The default <B>mindelay<B> value is set to 0, indicating
that only the lumped resistance threshold should be used for
determining when to extract a detailed resistance network.
<B>mindelay</B> may be used in place of <B>threshold</B>, or both
may be used together, in which case a network is only extracted
if both <B>threshold</B> and <B>mindelay</B> are exceeded. <P>
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.
@ -191,6 +134,6 @@ information.
<TD> <A HREF=commands.html>Return to command index</A> <TD> <A HREF=commands.html>Return to command index</A>
</TR> </TR>
</TABLE> </TABLE>
<P><I>Last updated:</I> May 29, 2026 at 11:33am <P> <P><I>Last updated:</I> October 4, 2021 at 3:32pm <P>
</BODY> </BODY>
</HTML> </HTML>

View File

@ -87,50 +87,6 @@ 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>.

View File

@ -20,64 +20,22 @@
<H2>macro</H2> <H2>macro</H2>
<HR> <HR>
Define or print a key or button macro binding. Define or print a macro called char
<HR> <HR>
<H3>Usage:</H3> <H3>Usage:</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<B>macro</B> [<I>window_type</I>] [<I>option</I>] [<I>key</I> [<I>value</I>]] <B>macro</B> [<I>window_type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
<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 known valid window present, <I>window_type</I> must be one of the four window
types accepted by the <B>specialopen</B> command (<B>color</B>, types accepted by the <B>specialopen</B> command: <B>layout</B>,
<B>netlist</B>, and <B>wind3d</B>), or a known layout tool <B>color</B>, <B>netlist</B>, and <B>wind3d</B>. If omitted,
(<B>box</B>, <B>wiring</B>, <B>nettool</B>, or <B>pick</B>). If the layout window is assumed by default, unless the command has
omitted, the layout window is assumed by default, unless the command been called from inside a window (using the colon or semicolon
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. <P> assumed.
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>
@ -114,6 +72,7 @@ Define or print a key or button macro binding.
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
@ -130,7 +89,6 @@ Define or print a key or button macro binding.
<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>

View File

@ -25,7 +25,7 @@ Attach a "property" (string key and value pair) to the edit cell
<H3>Usage:</H3> <H3>Usage:</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<B>property</B> [<I>list</I>] [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR> <B>property</B> [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR>
or or
<B>property</B> [<B>compat</B>] [<B>true</B>|<B>false</B>] <BR><BR> <B>property</B> [<B>compat</B>] [<B>true</B>|<B>false</B>] <BR><BR>
<BLOCKQUOTE> <BLOCKQUOTE>
@ -64,13 +64,6 @@ Attach a "property" (string key and value pair) to the edit cell
.mag file. However, if the user wants to create a property that .mag file. However, if the user wants to create a property that
is handled differently than a string (namely, to be a dimensional is handled differently than a string (namely, to be a dimensional
value that scales), then comptability mode should be turned off. <P> 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>

View File

@ -25,8 +25,7 @@ Unexpand everything inside or touching the cursor box.
<H3>Usage:</H3> <H3>Usage:</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<B>unexpand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>] <B>unexpand</B> <BR><BR>
<BR><BR>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3>Shortcuts:</H3> <H3>Shortcuts:</H3>
@ -38,23 +37,8 @@ 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. outline only. The <B>unexpand</B> command unexpands all subcells
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>

View File

@ -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, DRC_EXCEPTION_NONE, 0, 0, 0, 0, 0,
DRC_ARRAY_OVERLAP_TAG, DRC_ARRAY_OVERLAP_TAG,
(DRCCookie *) NULL (DRCCookie *) NULL
}; };

View File

@ -27,8 +27,6 @@ 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"
@ -38,9 +36,7 @@ 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 "textio/textio.h"
#include "cif/CIFint.h"
int dbDRCDebug = 0; int dbDRCDebug = 0;
@ -52,7 +48,7 @@ int dbDRCDebug = 0;
static DRCCookie drcOverlapCookie = { static DRCCookie drcOverlapCookie = {
0, 0, 0, 0, 0, 0, 0, 0,
{ {0} }, { {0} }, { {0} }, { {0} },
0, DRC_EXCEPTION_NONE, 0, 0, 0, 0, 0,
DRC_OVERLAP_TAG, DRC_OVERLAP_TAG,
(DRCCookie *) NULL (DRCCookie *) NULL
}; };
@ -66,33 +62,7 @@ extern MaxRectsData *drcCanonicalMaxwidth();
/* /*
*----------------------------------------------------------------------- *-----------------------------------------------------------------------
* *
* drcFoundOneFunc -- * drcCifPointToSegment
*
* 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)
@ -498,39 +468,12 @@ 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
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -568,19 +511,6 @@ drcTile (tile, dinfo, 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;
/* /*
@ -722,8 +652,6 @@ drcTile (tile, dinfo, arg)
DRCstatEdges++; DRCstatEdges++;
} }
cptrcache = NULL;
/* /*
* Check design rules along a vertical boundary between two tiles. * Check design rules along a vertical boundary between two tiles.
* *
@ -768,6 +696,7 @@ drcTile (tile, dinfo, 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 */
@ -798,44 +727,6 @@ drcTile (tile, dinfo, 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. */
@ -857,7 +748,6 @@ drcTile (tile, dinfo, arg)
} }
DRCstatRules++; DRCstatRules++;
if (!triggered) mrd = NULL;
if (cptr->drcc_flags & DRC_AREA) if (cptr->drcc_flags & DRC_AREA)
{ {
@ -879,23 +769,12 @@ drcTile (tile, dinfo, 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 else if (firsttile)
{ {
if (cptrcache == NULL) mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
{
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
@ -1186,8 +1065,6 @@ drcTile (tile, dinfo, arg)
} }
} }
cptrcache = NULL;
/* /*
* Check design rules along a horizontal boundary between two tiles. * Check design rules along a horizontal boundary between two tiles.
* *
@ -1227,6 +1104,7 @@ drcTile (tile, dinfo, 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 */
@ -1258,44 +1136,6 @@ drcTile (tile, dinfo, 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. */
@ -1317,7 +1157,6 @@ drcTile (tile, dinfo, arg)
} }
DRCstatRules++; DRCstatRules++;
if (!triggered) mrd = NULL;
/* top to bottom */ /* top to bottom */
@ -1334,23 +1173,12 @@ drcTile (tile, dinfo, 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 else if (firsttile)
{ {
if (cptrcache == NULL) mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
{
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

View File

@ -510,17 +510,16 @@ MaxRectsExclude(
*/ */
MaxRectsData * MaxRectsData *
drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr) drcCanonicalMaxwidth(starttile, dir, arg, cptr)
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;
MaxRectsData *mrd = *mrdptr; static MaxRectsData *mrd = (MaxRectsData *)NULL;
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. */
@ -530,7 +529,6 @@ drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr)
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;

View File

@ -52,7 +52,7 @@ static ClientData drcSubClientData; /* To be passed to error function. */
static DRCCookie drcSubcellCookie = { static DRCCookie drcSubcellCookie = {
0, 0, 0, 0, 0, 0, 0, 0,
{ {0} }, { {0} }, { {0} }, { {0} },
0, DRC_EXCEPTION_NONE, 0, 0, 0, 0, 0,
DRC_SUBCELL_OVERLAP_TAG, DRC_SUBCELL_OVERLAP_TAG,
(DRCCookie *) NULL (DRCCookie *) NULL
}; };
@ -65,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, DRC_EXCEPTION_NONE, 0, 0, 0, 0, 0,
DRC_IN_SUBCELL_TAG, DRC_IN_SUBCELL_TAG,
(DRCCookie *) NULL (DRCCookie *) NULL
}; };
@ -79,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, DRC_EXCEPTION_NONE, 0, 0, 0, 0, 0,
DRC_OFFGRID_TAG, DRC_OFFGRID_TAG,
(DRCCookie *) NULL (DRCCookie *) NULL
}; };

View File

@ -72,12 +72,6 @@ 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.
*/ */
@ -85,7 +79,6 @@ 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();
@ -308,12 +301,6 @@ 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;
} }
@ -397,63 +384,6 @@ 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;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -641,8 +571,6 @@ 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);
@ -735,7 +663,6 @@ DRCTechStyleInit()
} }
drcCifInit(); drcCifInit();
drcCurException = DRC_EXCEPTION_NONE;
} }
/* /*
@ -1028,7 +955,6 @@ 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
@ -1105,37 +1031,50 @@ 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, "layers 45|90 why"}, {"angles", 4, 4, drcAngles,
"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, "layers"}, {"exact_overlap", 2, 2, drcExactOverlap,
{"exception", 2, 2, drcException, "name"}, "layers"},
{"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, "layers1 layers2"}, {"no_overlap", 3, 3, drcNoOverlap,
{"option", 2, 2, drcOption, "option_name option_value"}, "layers1 layers2"},
{"overhang", 5, 5, drcOverhang, "layers1 layers2 distance why"}, {"option", 2, 2, drcOption,
{"rect_only", 3, 3, drcRectOnly, "layers why"}, "option_name option_value"},
{"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, "step_size"}, {"stepsize", 2, 2, drcStepSize,
"step_size"},
{"surround", 6, 7, drcSurround, {"surround", 6, 7, drcSurround,
"layers1 layers2 distance presence why"}, "layers1 layers2 distance presence why"},
{"width", 4, 5, drcWidth, "layers width why"}, {"width", 4, 5, drcWidth,
"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, "layers area horizon why"}, {"area", 5, 5, drcArea,
{"off_grid", 4, 4, drcOffGrid, "layers pitch why"}, "layers area horizon why"},
{"maxwidth", 4, 6, drcMaxwidth, "layers maxwidth bends why"}, {"off_grid", 4, 4, drcOffGrid,
{"cifstyle", 2, 2, drcCifSetStyle, "cif_style"}, "layers pitch why"},
{"cifwidth", 4, 4, drcCifWidth, "layers width why"}, {"maxwidth", 4, 6, drcMaxwidth,
"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, "layers area horizon why"}, {"cifarea", 5, 5, drcCifArea,
{"cifmaxwidth", 5, 5, drcCifMaxwidth, "layers maxwidth bends why"}, "layers area horizon 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}
@ -1756,7 +1695,7 @@ drcMaxwidth(argc, argv)
if (PlaneMaskHasPlane(pmask2, plane2)) if (PlaneMaskHasPlane(pmask2, plane2))
break; break;
if (PlaneMaskHasPlane(pmask, plane2)) if (plane2 == plane)
TechError("Warning: Exclude types for \"maxwidth\" are on the " TechError("Warning: Exclude types for \"maxwidth\" are on the "
"same plane and so cannot be checked.\n"); "same plane and so cannot be checked.\n");
} }
@ -3695,84 +3634,6 @@ 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);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -4258,7 +4119,6 @@ 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;

View File

@ -36,7 +36,6 @@ 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. */
@ -92,11 +91,6 @@ 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
*/ */
@ -183,8 +177,6 @@ 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;

View File

@ -757,7 +757,7 @@ spcdevHierVisit(
case DEV_FET: case DEV_FET:
if (source == drain) if (source == drain)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); if (esFormat == NGSPICE) fprintf(esSpiceF, "$ ");
fprintf(esSpiceF, "** SOURCE/DRAIN TIED\n"); fprintf(esSpiceF, "** SOURCE/DRAIN TIED\n");
} }
break; break;
@ -765,7 +765,7 @@ spcdevHierVisit(
default: default:
if (gate == source) if (gate == source)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); if (esFormat == NGSPICE) fprintf(esSpiceF, "$ ");
fprintf(esSpiceF, "** SHORTED DEVICE\n"); fprintf(esSpiceF, "** SHORTED DEVICE\n");
} }
break; break;
@ -844,8 +844,6 @@ spcdevHierVisit(
case DEV_DSUBCKT: case DEV_DSUBCKT:
case DEV_MSUBCKT: case DEV_MSUBCKT:
fprintf(esSpiceF, "%d", esSbckNum++); fprintf(esSpiceF, "%d", esSbckNum++);
if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee)
fprintf(esSpiceF, "A");
break; break;
default: default:
fprintf(esSpiceF, "%d", esDevNum++); fprintf(esSpiceF, "%d", esDevNum++);
@ -922,27 +920,16 @@ spcdevHierVisit(
else if (dev->dev_class != DEV_MSUBCKT) else if (dev->dev_class != DEV_MSUBCKT)
{ {
if (dev->dev_nterm > 1) if (dev->dev_nterm > 1)
spcdevOutNode(hc->hc_hierName, spcdevOutNode(hc->hc_hierName, source->dterm_node->efnode_name->efnn_hier,
source->dterm_node->efnode_name->efnn_hier,
"subckt", esSpiceF); "subckt", esSpiceF);
if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) if (dev->dev_nterm > 2)
{ spcdevOutNode(hc->hc_hierName, drain->dterm_node->efnode_name->efnn_hier,
/* Handle resistor "tee" model */
spcdevOutNode(hc->hc_hierName,
gate->dterm_node->efnode_name->efnn_hier,
"subckt", esSpiceF);
l /= 2; /* Halve the resistor length for each side */
}
else if (dev->dev_nterm > 2)
spcdevOutNode(hc->hc_hierName,
drain->dterm_node->efnode_name->efnn_hier,
"subckt", esSpiceF); "subckt", esSpiceF);
} }
else /* class DEV_MSUBCKT */ else /* class DEV_MSUBCKT */
{ {
if (dev->dev_nterm > 2) if (dev->dev_nterm > 2)
spcdevOutNode(hc->hc_hierName, spcdevOutNode(hc->hc_hierName, source->dterm_node->efnode_name->efnn_hier,
source->dterm_node->efnode_name->efnn_hier,
"subckt", esSpiceF); "subckt", esSpiceF);
} }
/* The following only applies to DEV_SUBCKT and DEV_VERILOGA, which */ /* The following only applies to DEV_SUBCKT and DEV_VERILOGA, which */
@ -980,54 +967,6 @@ spcdevHierVisit(
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE); 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);
if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee)
{
/* Repeat everything above for the second half of the "tee" resistor */
fprintf(esSpiceF, "\n%c%dB", devchar, esSbckNum - 1);
spcdevOutNode(hc->hc_hierName,
gate->dterm_node->efnode_name->efnn_hier,
"subckt", esSpiceF);
spcdevOutNode(hc->hc_hierName,
drain->dterm_node->efnode_name->efnn_hier,
"subckt", esSpiceF);
/* Get the device parameters now, and check if the substrate is */
/* passed as a parameter rather than as a node. */
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
for (pptr = plist; pptr != NULL; pptr = pptr->parm_next)
if (pptr->parm_type[0] == 's')
break;
if ((pptr == NULL) && subnode)
{
EFNode *dnode;
fprintf(esSpiceF, " ");
subnodeFlat = spcdevSubstrate(hc->hc_hierName,
subnode->efnode_name->efnn_hier,
dev->dev_type, esSpiceF);
/* If a tee resistor subcircuit has a substrate pin, then the
* parasitic capacitance to substrate should be assumed to be
* part of the resistor subcircuit model, and so the parasitic
* to substrate on the "gate" node should be forced to zero.
*/
dnode = GetHierNode(hc, gate->dterm_node->efnode_name->efnn_hier);
dnode->efnode_cap = 0;
}
/* Support for CDL format */
if (esFormat == CDL) fprintf(esSpiceF, " /");
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
/* Write all requested parameters to the subcircuit call. */
sdM = getCurDevMult();
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM);
}
break; break;
case DEV_RES: case DEV_RES:
@ -1149,7 +1088,6 @@ 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, FALSE); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
} }
@ -1200,7 +1138,6 @@ 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, FALSE); spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
} }
@ -1624,14 +1561,12 @@ spcsubHierVisit(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
spcnodeHierVisit( spcnodeHierVisit(
HierContext *hc, HierContext *hc,
EFNode *node, EFNode *node,
int res, int res,
double cap, double cap)
ClientData cdata) /* UNUSED */
{ {
HierName *hierName; HierName *hierName;
bool isConnected = FALSE; bool isConnected = FALSE;
@ -1658,7 +1593,7 @@ spcnodeHierVisit(
static char ntmp[MAX_STR_SIZE]; static char ntmp[MAX_STR_SIZE];
EFHNSprintf(ntmp, hierName); EFHNSprintf(ntmp, hierName);
if (esFormat == NGSPICE) fprintf(esSpiceF, " ; "); if (esFormat == NGSPICE) fprintf(esSpiceF, " $ ");
fprintf(esSpiceF, "** %s == %s\n", ntmp, nsn); fprintf(esSpiceF, "** %s == %s\n", ntmp, nsn);
} }
cap = cap / 1000; cap = cap / 1000;
@ -1668,14 +1603,14 @@ spcnodeHierVisit(
esSIvalue(esSpiceF, 1.0E-15 * cap); esSIvalue(esSpiceF, 1.0E-15 * cap);
if (!isConnected) if (!isConnected)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, " ;"); if (esFormat == NGSPICE) fprintf(esSpiceF, " $");
fprintf(esSpiceF, " **FLOATING"); fprintf(esSpiceF, " **FLOATING");
} }
fprintf(esSpiceF, "\n"); fprintf(esSpiceF, "\n");
} }
if (node->efnode_attrs && !esNoAttrs) if (node->efnode_attrs && !esNoAttrs)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, " ; "); if (esFormat == NGSPICE) fprintf(esSpiceF, " $ ");
fprintf(esSpiceF, "**nodeattr %s :",nsn ); fprintf(esSpiceF, "**nodeattr %s :",nsn );
for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next) for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next)
{ {

View File

@ -2817,7 +2817,7 @@ spcdevVisit(
case DEV_FET: case DEV_FET:
if (source == drain) if (source == drain)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); if (esFormat == NGSPICE) fprintf(esSpiceF, "$ ");
fprintf(esSpiceF, "** SOURCE/DRAIN TIED\n"); fprintf(esSpiceF, "** SOURCE/DRAIN TIED\n");
} }
break; break;
@ -2825,7 +2825,7 @@ spcdevVisit(
default: default:
if (gate == source) if (gate == source)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); if (esFormat == NGSPICE) fprintf(esSpiceF, "$ ");
fprintf(esSpiceF, "** SHORTED DEVICE\n"); fprintf(esSpiceF, "** SHORTED DEVICE\n");
} }
break; break;
@ -2901,17 +2901,13 @@ spcdevVisit(
case DEV_VOLT: case DEV_VOLT:
fprintf(esSpiceF, "%d", esVoltNum++); fprintf(esSpiceF, "%d", esVoltNum++);
break; break;
case DEV_RSUBCKT:
case DEV_SUBCKT: case DEV_SUBCKT:
case DEV_VERILOGA: case DEV_VERILOGA:
case DEV_RSUBCKT:
case DEV_CSUBCKT: case DEV_CSUBCKT:
case DEV_DSUBCKT: case DEV_DSUBCKT:
case DEV_MSUBCKT: case DEV_MSUBCKT:
fprintf(esSpiceF, "%d", esSbckNum++); fprintf(esSpiceF, "%d", esSbckNum++);
if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee)
/* For resistor tee networks, use, e.g., */
/* "X1A" and "X1B", for clarity */
fprintf(esSpiceF, "A");
break; break;
default: default:
fprintf(esSpiceF, "%d", esDevNum++); fprintf(esSpiceF, "%d", esDevNum++);
@ -2986,15 +2982,7 @@ spcdevVisit(
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,
name, esSpiceF); name, esSpiceF);
if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) if (dev->dev_nterm > 2)
{
l /= 2; /* Halve the resistor. Note that this may introduce
* error if l is an odd value.
*/
spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
}
else if (dev->dev_nterm > 2)
spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier,
name, esSpiceF); name, esSpiceF);
} }
@ -3043,53 +3031,6 @@ spcdevVisit(
fprintf(esSpiceF, " M=%g", sdM); fprintf(esSpiceF, " M=%g", sdM);
break; break;
if (dev->dev_class == DEV_RSUBCKT && esDoResistorTee)
{
/* Write the second half of the "Tee" resistor when
* the resistor is type DEV_RSUBCKT and not DEV_RES.
*/
fprintf(esSpiceF, "\n%c%dB", devchar, esSbckNum - 1);
spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier,
name, esSpiceF);
/* Get the device parameters now, and check if the substrate is */
/* passed as a parameter rather than as a node. */
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
for (pptr = plist; pptr != NULL; pptr = pptr->parm_next)
if (pptr->parm_type[0] == 's')
break;
if ((pptr == NULL) && subnode)
{
fprintf(esSpiceF, " ");
subnodeFlat = spcdevSubstrate(hierName,
subnode->efnode_name->efnn_hier,
dev->dev_type, esSpiceF);
/* There is a substrate pin on the resistor subcircuit, so assume
* that the substrate cap is part of the subcircuit model, and
* zero it.
*/
gate->dterm_node->efnode_cap = 0;
}
/* CDL format support: Output a slash followed by a space. */
if (esFormat == CDL) fprintf(esSpiceF, " /");
fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]);
/* Write all requested parameters to the subcircuit call. */
sdM = getCurDevMult();
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
if (sdM != 1.0)
fprintf(esSpiceF, " M=%g", sdM);
}
break;
case DEV_RES: case DEV_RES:
if (esDoResistorTee) if (esDoResistorTee)
{ {
@ -3199,7 +3140,6 @@ 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, FALSE); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
} }
@ -3246,7 +3186,6 @@ 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, FALSE); spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
} }
@ -4111,7 +4050,7 @@ spcnodeVisit(
static char ntmp[MAX_STR_SIZE]; static char ntmp[MAX_STR_SIZE];
EFHNSprintf(ntmp, hierName); EFHNSprintf(ntmp, hierName);
if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); if (esFormat == NGSPICE) fprintf(esSpiceF, "$ ");
fprintf(esSpiceF, "** %s == %s\n", ntmp, nsn); fprintf(esSpiceF, "** %s == %s\n", ntmp, nsn);
} }
cap = cap / 1000; cap = cap / 1000;
@ -4121,14 +4060,14 @@ spcnodeVisit(
esSIvalue(esSpiceF, 1.0E-15 * cap); esSIvalue(esSpiceF, 1.0E-15 * cap);
if (!isConnected) if (!isConnected)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, " ;"); if (esFormat == NGSPICE) fprintf(esSpiceF, " $");
fprintf(esSpiceF, " **FLOATING"); fprintf(esSpiceF, " **FLOATING");
} }
fprintf(esSpiceF, "\n"); fprintf(esSpiceF, "\n");
} }
if (node->efnode_attrs && !esNoAttrs) if (node->efnode_attrs && !esNoAttrs)
{ {
if (esFormat == NGSPICE) fprintf(esSpiceF, " ; "); if (esFormat == NGSPICE) fprintf(esSpiceF, " $ ");
fprintf(esSpiceF, "**nodeattr %s :",nsn ); fprintf(esSpiceF, "**nodeattr %s :",nsn );
for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next) for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next)
{ {

View File

@ -307,12 +307,6 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
if (inname == NULL) if (inname == NULL)
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
return NULL; return NULL;
#elif defined(EMSCRIPTEN)
{
/* Headless WASM: signal error via err_result, no goto usage path */
if (err_result != NULL) *err_result = TRUE;
return NULL;
}
#else #else
goto usage; goto usage;
#endif #endif
@ -373,7 +367,7 @@ efLoadSearchPath(path)
PaVisitFiles(DOT_MAGIC_PATH, ".magicrc", pv); PaVisitFiles(DOT_MAGIC_PATH, ".magicrc", pv);
PaVisitFree(pv); PaVisitFree(pv);
if (*path == NULL) if (*path == NULL)
StrDup(path, "."); *path = ".";
} }
int int

View File

@ -706,11 +706,6 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
dev->dev_terms[n].dterm_node = dev->dev_terms[n].dterm_node =
(nn1->efnn_node == NULL) ? (nn1->efnn_node == NULL) ?
nn2->efnn_node : nn1->efnn_node; nn2->efnn_node : nn1->efnn_node;
/* Also check the substrate terminal */
if (dev->dev_subsnode == lostnode)
dev->dev_subsnode = (nn1->efnn_node == NULL) ?
nn2->efnn_node : nn1->efnn_node;
} }
/* If a node has been merged away, make sure that its name */ /* If a node has been merged away, make sure that its name */
@ -1623,128 +1618,12 @@ efConnectionFreeLinkedList(Connection *conn)
} }
} }
/*
* ----------------------------------------------------------------------------
*
* efConnPointFreeLinkedList --
*
* Release memory for linked-list of ConnectionPoint* based on internal
* list at ConnectionPoint->conn_next. 'connpt' argument must be non-NULL.
*
* Results:
* Deallocates linked-list of ConnectionPoint* starting at 'connpt'
*
* Side effects:
* Deallocates one or more connection point record(s).
*
* ----------------------------------------------------------------------------
*/
void
efConnPointFreeLinkedList(ConnectionPoint *connpt)
{
while (connpt)
{
ConnectionPoint *next = connpt->conn_next;
if (connpt->conn_name != NULL)
freeMagic(connpt->conn_name);
freeMagic(connpt);
connpt = next;
}
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* efBuildConnect -- * efBuildConnect --
* *
* Process a "connect" line from a .ext file. * Process a "connect" line from a .ext file.
* Creates a record of the area and type of the connection. Since the
* extraction at the point of finding connections no longer knows what
* net in the celldef (if any) is part of the connection, only the
* location and type is preserved, and the cell being connected has to
* be recovered by a search on the celldef's layout. These records are
* used only by "extresist".
*
* Results:
* None.
*
* Side effects:
* Allocates a new connection port record for extresist, and prepends
* it to the list for def.
*
* ----------------------------------------------------------------------------
*/
void
efBuildConnect(def, llx, lly, urx, ury, layerName, upnodeName, downnodeName)
Def *def;
int llx, lly, urx, ury;
char *layerName;
char *upnodeName;
char *downnodeName;
{
int tnew;
ConnectionPoint *connpt;
HashEntry *he;
Use *subuse;
char *hierptr, *qptr, *useid;
/* Can't do anything without a node name to connect to */
if (!strcmp(downnodeName, "\"None\"")) return;
/* "downnodeName" should be hierarchical; stop at the first hierarchical
* divider and use the prefix to find the use being connected to.
* NOTE: This will require dealing with connections that are more than
* one hierarchical level deep (to be done).
*/
useid = downnodeName;
if (*useid == '"') useid++;
hierptr = strchr(useid, '/');
if (hierptr != NULL) *hierptr = '\0';
qptr = strrchr(useid, '"');
if (qptr != NULL) *qptr = '\0';
if (layerName)
tnew = efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
else
tnew = 0;
connpt = (ConnectionPoint *)mallocMagic(sizeof(ConnectionPoint));
he = HashFind(&def->def_uses, useid);
subuse = (Use *)HashGetValue(he);
connpt->conn_use = subuse;
connpt->conn_r.r_xbot = llx;
connpt->conn_r.r_ybot = lly;
connpt->conn_r.r_xtop = urx;
connpt->conn_r.r_ytop = ury;
connpt->conn_type = tnew;
if (!strcmp(upnodeName, "\"None\""))
connpt->conn_name = (char *)NULL;
else
{
if (*upnodeName == '"') upnodeName++;
connpt->conn_name = StrDup((char **)NULL, upnodeName);
if ((qptr = strrchr(connpt->conn_name, '"')) != NULL) *qptr = '\0';
}
/* To do: Add "downnodeName" to the ConnectionPoint structure. This
* may not be necessary, as it is only being used by "extresist" which
* is not using the extflat parser.
*/
connpt->conn_next = def->def_connpts;
def->def_connpts = connpt;
}
/*
* ----------------------------------------------------------------------------
*
* efBuildMerge --
*
* Process a "merge" line from a .ext file.
* Creates a connection record for the names 'nodeName1' and * Creates a connection record for the names 'nodeName1' and
* 'nodeName2'. * 'nodeName2'.
* *
@ -1759,7 +1638,7 @@ efBuildConnect(def, llx, lly, urx, ury, layerName, upnodeName, downnodeName)
*/ */
void void
efBuildMerge(def, nodeName1, nodeName2, deltaC, av, ac) efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
Def *def; /* Def to which this connection is to be added */ Def *def; /* Def to which this connection is to be added */
char *nodeName1; /* Name of first node in connection */ char *nodeName1; /* Name of first node in connection */
char *nodeName2; /* Name of other node in connection */ char *nodeName2; /* Name of other node in connection */

View File

@ -122,7 +122,6 @@ EFDone(func)
efConnectionFreeLinkedList(def->def_conns); efConnectionFreeLinkedList(def->def_conns);
efConnectionFreeLinkedList(def->def_caps); efConnectionFreeLinkedList(def->def_caps);
efConnectionFreeLinkedList(def->def_resistors); efConnectionFreeLinkedList(def->def_resistors);
efConnPointFreeLinkedList(def->def_connpts);
free_magic1_t mm1 = freeMagic1_init(); free_magic1_t mm1 = freeMagic1_init();
for (kill = def->def_kills; kill; kill = kill->kill_next) for (kill = def->def_kills; kill; kill = kill->kill_next)
@ -249,7 +248,6 @@ efDefNew(name)
newdef->def_conns = (Connection *) NULL; newdef->def_conns = (Connection *) NULL;
newdef->def_caps = (Connection *) NULL; newdef->def_caps = (Connection *) NULL;
newdef->def_resistors = (Connection *) NULL; newdef->def_resistors = (Connection *) NULL;
newdef->def_connpts = (ConnectionPoint *) NULL;
newdef->def_kills = (Kill *) NULL; newdef->def_kills = (Kill *) NULL;
/* Initialize circular list of nodes */ /* Initialize circular list of nodes */

View File

@ -32,7 +32,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/utils.h" #include "utils/utils.h"
#include "extflat/extflat.h" #include "extflat/extflat.h"
#include "extflat/EFint.h" #include "extflat/EFint.h"
#include "textio/textio.h"
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -492,13 +491,7 @@ efHierVisitDevs(hc, ca)
{ {
dev = (Dev *)HashGetValue(he); dev = (Dev *)HashGetValue(he);
if (efHierDevKilled(hc, dev, hc->hc_hierName)) if (efHierDevKilled(hc, dev, hc->hc_hierName))
{ continue;
TxError("Error: Device at (%d %d) is connected to one or more"
" eliminated nodes.\n",
dev->dev_rect.r_xbot, dev->dev_rect.r_ybot);
/* Output the device anyway, but something needs fixing */
// continue;
}
const cb_extflat_hiervisitdevs_t ca_hiervisitdevs_proc = (cb_extflat_hiervisitdevs_t) ca->ca_proc; /* FIXME temporary */ const cb_extflat_hiervisitdevs_t ca_hiervisitdevs_proc = (cb_extflat_hiervisitdevs_t) ca->ca_proc; /* FIXME temporary */
if ((*ca_hiervisitdevs_proc)(hc, dev, scale, ca->ca_cdata)) /* @invoke cb_extflat_hiervisitdevs_t */ if ((*ca_hiervisitdevs_proc)(hc, dev, scale, ca->ca_cdata)) /* @invoke cb_extflat_hiervisitdevs_t */

View File

@ -145,8 +145,6 @@ typedef struct conn
#define conn_res conn_value.conn_val_res #define conn_res conn_value.conn_val_res
#define conn_cap conn_value.conn_val_cap #define conn_cap conn_value.conn_val_cap
typedef struct connpoint ConnectionPoint;
/* -------------------------- Defs and uses --------------------------- */ /* -------------------------- Defs and uses --------------------------- */
/* A Def exists for each .ext file */ /* A Def exists for each .ext file */
@ -164,7 +162,6 @@ typedef struct def
/* The following are all NULL-terminated lists */ /* The following are all NULL-terminated lists */
Connection *def_conns; /* Hierarchical connections/adjustments */ Connection *def_conns; /* Hierarchical connections/adjustments */
ConnectionPoint *def_connpts; /* Position of hierarchical connections */
Connection *def_caps; /* Two-terminal capacitors */ Connection *def_caps; /* Two-terminal capacitors */
Connection *def_resistors; /* Two-terminal resistors */ Connection *def_resistors; /* Two-terminal resistors */
Kill *def_kills; /* Used to modify hierarchical structure Kill *def_kills; /* Used to modify hierarchical structure
@ -209,17 +206,6 @@ typedef struct use
#define IsArray(u) ((u)->use_xlo!=(u)->use_xhi || (u)->use_ylo!=(u)->use_yhi) #define IsArray(u) ((u)->use_xlo!=(u)->use_xhi || (u)->use_ylo!=(u)->use_yhi)
/* Connection point structure (used by "extresist") */
typedef struct connpoint
{
Use *conn_use; /* Use being connected to */
Rect conn_r; /* Area, edge, or point of connection */
int conn_type; /* A tile type at the connection */
char *conn_name; /* Top level name of node, or NULL */
struct connpoint *conn_next; /* Next connection point in list */
} ConnectionPoint;
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Structure passed down during hierarchical searching */ /* Structure passed down during hierarchical searching */
@ -321,9 +307,7 @@ extern void CapHashSetValue();
extern DevParam *efGetDeviceParams(); extern DevParam *efGetDeviceParams();
extern void efBuildNode(); extern void efBuildNode();
extern void efConnectionFreeLinkedList(Connection *conn); extern void efConnectionFreeLinkedList(Connection *conn);
extern void efConnPointFreeLinkedList(ConnectionPoint *conn);
extern void efBuildConnect(); extern void efBuildConnect();
extern void efBuildMerge();
extern void efBuildResistor(); extern void efBuildResistor();
extern void efBuildCap(); extern void efBuildCap();
extern HierContext *EFFlatBuildOneLevel(); extern HierContext *EFFlatBuildOneLevel();

View File

@ -275,11 +275,15 @@ readfile:
efBuildCap(def, argv[1], argv[2], (double) cap); efBuildCap(def, argv[1], argv[2], (double) cap);
break; break;
/* connect useid llx lly urx ury type "node" ... */ /* subcap node capacitance */
case CONNECT: case SUBCAP:
efBuildConnect(def, atoi(argv[1]), atoi(argv[2]), cap = cscale*atoCap(argv[2]);
atoi(argv[3]), atoi(argv[4]), argv[5], efAdjustSubCap(def, argv[1], cap);
argv[6], argv[7]); break;
/* equiv node1 node2 */
case EQUIV:
efBuildEquiv(def, argv[1], argv[2], resist, isspice);
break; break;
/* replaces "fet" (below) */ /* replaces "fet" (below) */
@ -333,41 +337,6 @@ readfile:
r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale); r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale); r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale);
if (!strcmp(argv[2], "Short"))
{
/* Device name "Short" is a reserved name indicating
* that the device does not get output but acts as a
* short between the first two terminals. Consequently,
* it acts like an "equiv" statement. However, unlike
* regular "equiv" statements, it should always merge
* the nodes, so do not pass "resist" to efBuildEquiv().
*/
int argstart = 7;
/* "Short" devices should not have parameters, but just in
* case, skip over any that are found.
*/
while (strchr(argv[argstart], '=') != NULL) argstart++;
/* Tricky---Since "Short" devices are treated like "equiv"
* statements, then when doing full R-C extraction, it's
* important *not* to merge the nodes when reading the
* .ext file, but only when reading the .res.ext file.
* Otherwise the wrong nodes may get merged. "resist" is
* TRUE when "ext2spice extresist on" is selected, and
* DoResist is set to FALSE when the .res.ext file is
* opened for reading.
*/
if (argstart + 4 >= argc)
efReadError("Bad terminal description for Short device\n");
else if ((!resist) || (resist && (!(DoResist))))
{
efBuildEquiv(def, argv[argstart + 1], argv[argstart + 4],
FALSE, isspice);
}
break;
}
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0) if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0)
{ {
efReadError("Incomplete terminal description for device\n"); efReadError("Incomplete terminal description for device\n");
@ -375,11 +344,6 @@ readfile:
} }
break; break;
/* equiv node1 node2 */
case EQUIV:
efBuildEquiv(def, argv[1], argv[2], resist, isspice);
break;
/* for backwards compatibility */ /* for backwards compatibility */
/* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */ /* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */
case FET: case FET:
@ -409,7 +373,7 @@ readfile:
*/ */
cap = (argc > 3) ? atoCap(argv[3]) * cscale : 0; cap = (argc > 3) ? atoCap(argv[3]) * cscale : 0;
efBuildMerge(def, argv[1], argv[2], (double)cap, &argv[4], argc - 4); efBuildConnect(def, argv[1], argv[2], (double)cap, &argv[4], argc - 4);
break; break;
/* node name R C x y layer a1 p1 a2 p2 ... [ attrs ] */ /* node name R C x y layer a1 p1 a2 p2 ... [ attrs ] */
@ -485,12 +449,6 @@ resistChanged:
} }
break; break;
/* subcap node capacitance */
case SUBCAP:
cap = cscale*atoCap(argv[2]);
efAdjustSubCap(def, argv[1], cap);
break;
/* use def use-id T0 .. T5 */ /* use def use-id T0 .. T5 */
case USE: case USE:
efBuildUse(def, argv[1], argv[2], efBuildUse(def, argv[1], argv[2],

View File

@ -25,9 +25,9 @@
*/ */
typedef enum typedef enum
{ {
ABSTRACT, ADJUST, ATTR, CAP, CONNECT, DEVICE, DIST, EQUIV, FET, KILLNODE, ABSTRACT, ADJUST, ATTR, CAP, DEVICE, DIST, EQUIV, FET, KILLNODE, MERGE,
MERGE, NODE, PARAMETERS, PORT, PRIMITIVE, RESISTOR, RESISTCLASS, RNODE, NODE, PARAMETERS, PORT, PRIMITIVE, RESISTOR, RESISTCLASS, RNODE, SCALE,
SCALE, SUBCAP, SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE SUBCAP, SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE
} Key; } Key;
static const struct static const struct
@ -42,7 +42,6 @@ keyTable[] =
{"adjust", ADJUST, 4}, {"adjust", ADJUST, 4},
{"attr", ATTR, 8}, {"attr", ATTR, 8},
{"cap", CAP, 4}, {"cap", CAP, 4},
{"connect", CONNECT, 7},
{"device", DEVICE, 11}, /* effectively replaces "fet" */ {"device", DEVICE, 11}, /* effectively replaces "fet" */
{"distance", DIST, 4}, {"distance", DIST, 4},
{"equiv", EQUIV, 3}, {"equiv", EQUIV, 3},

View File

@ -147,13 +147,13 @@ NodeRegion *temp_subsnode = NULL; /* Last subsnode found */
/* Forward declarations */ /* Forward declarations */
void extOutputNodes(); void extOutputNodes();
int extTransTileFunc(); int extTransTileFunc();
int extTransPerimFunc(Boundary *, ClientData); /* UNUSED */ int extTransPerimFunc();
int extTransFindSubs(); int extTransFindSubs();
int extTransFindId(); int extTransFindId();
void extTermAPFunc(); void extTermAPFunc();
int extAnnularTileFunc(Tile *, TileType, int, FindRegion *); /* UNUSED */ int extAnnularTileFunc();
int extResistorTileFunc(Tile *, TileType, int, FindRegion *); /* UNUSED */ int extResistorTileFunc();
int extSpecialPerimFunc(); int extSpecialPerimFunc();
void extFindDuplicateLabels(); void extFindDuplicateLabels();
@ -629,8 +629,6 @@ extSetResist(reg)
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
{ {
ResValue resnew, restot;
reg->nreg_pa[n].pa_area = area = extResistArea[n]; reg->nreg_pa[n].pa_area = area = extResistArea[n];
reg->nreg_pa[n].pa_perim = perim = extResistPerim[n]; reg->nreg_pa[n].pa_perim = perim = extResistPerim[n];
if (area > 0 && perim > 0) if (area > 0 && perim > 0)
@ -641,15 +639,8 @@ extSetResist(reg)
if (v < 0) s = 0; else s = sqrt(v); if (v < 0) s = 0; else s = sqrt(v);
fperim = (float) perim; fperim = (float) perim;
resnew = (fperim + s) / (fperim - s) * reg->nreg_resist += (fperim + s) / (fperim - s)
ExtCurStyle->exts_resistByResistClass[n]; * ExtCurStyle->exts_resistByResistClass[n];
restot = reg->nreg_resist + resnew;
/* Check for integer overflow. There is no point in trying
* to accommodate huge resistance values for an estimate.
* The value just saturates at the maximum integer value.
*/
if (restot > 0) reg->nreg_resist = restot;
} }
/* Reset for the next pass */ /* Reset for the next pass */
@ -731,8 +722,7 @@ extOutputNodes(nodeList, outFile)
/* Check if this node is the substrate */ /* Check if this node is the substrate */
if (reg == glob_subsnode) if (reg == glob_subsnode)
{ {
intR = (reg->nreg_resist + rround) / ExtCurStyle->exts_resistScale; fprintf(outFile, "substrate \"%s\" 0 0", text);
fprintf(outFile, "substrate \"%s\" %d 0", text, intR);
} }
else else
{ {
@ -821,14 +811,8 @@ extOutputNodes(nodeList, outFile)
* For a net to be shorted to itself is not an error. * For a net to be shorted to itself is not an error.
* NOTE: Potentially the unique name could be removed * NOTE: Potentially the unique name could be removed
* here and save ext2spice the trouble. * here and save ext2spice the trouble.
*
* Also: If "extresist" is being run in the same
* pass, then don't print an error, because
* electrical shorts are meaningless in an R-C
* extraction.
*/ */
if ((portname != NULL) && if ((portname != NULL) &&
(!(ExtOptions & EXT_DORESISTANCE)) &&
(ll->ll_attr == LL_PORTATTR) && (ll->ll_attr == LL_PORTATTR) &&
(strcmp(ll->ll_label->lab_text, portname))) (strcmp(ll->ll_label->lab_text, portname)))
{ {
@ -1126,7 +1110,7 @@ ExtSortTerminals(tran, ll)
do do
{ {
changed = 0; changed = 0;
for (nsd = 0; nsd < tran->tr_nterm-1; nsd++) for( nsd = 0; nsd < tran->tr_nterm-1; nsd++ )
{ {
p1 = &(tran->tr_termpos[nsd]); p1 = &(tran->tr_termpos[nsd]);
p2 = &(tran->tr_termpos[nsd+1]); p2 = &(tran->tr_termpos[nsd+1]);
@ -1171,17 +1155,14 @@ ExtSortTerminals(tran, ll)
* but S,D attributes are not that common so it should not matter * but S,D attributes are not that common so it should not matter
* that much -- Stefanos 5/96 */ * that much -- Stefanos 5/96 */
for (lp = ll; lp; lp = lp->ll_next) for ( lp = ll ; lp ; lp = lp->ll_next )
if (lp->ll_attr == nsd) if ( lp->ll_attr == nsd ) lp->ll_attr = LL_SORTATTR ;
lp->ll_attr = LL_SORTATTR; else if ( lp->ll_attr == nsd+1 ) lp->ll_attr = nsd ;
else if (lp->ll_attr == nsd + 1) for ( lp = ll ; lp ; lp = lp->ll_next )
lp->ll_attr = nsd; if ( lp->ll_attr == LL_SORTATTR ) lp->ll_attr = nsd+1;
for (lp = ll; lp; lp = lp->ll_next)
if (lp->ll_attr == LL_SORTATTR)
lp->ll_attr = nsd + 1;
} }
} }
while (changed); while( changed );
} }
/* /*
@ -1854,8 +1835,6 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec)
ParamList *chkParam; ParamList *chkParam;
HashEntry *he; HashEntry *he;
ResValue resvalue; ResValue resvalue;
LabRegion *node; /* Node connected to gate terminal */
LabelList *ll; /* Gate's label list */
for (chkParam = devptr->exts_deviceParams; chkParam for (chkParam = devptr->exts_deviceParams; chkParam
!= NULL; chkParam = chkParam->pl_next) != NULL; chkParam = chkParam->pl_next)
@ -1987,34 +1966,6 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec)
break; break;
} }
} }
/* If there are device attribute labels (labels attached to the device
* type ending with "^") with "=" in them, then treat them as extra
* parameters. Output each one and remove the gate attribute property
* from the label.
*/
node = (LabRegion *)ExtGetRegion(reg->treg_tile, reg->treg_dinfo);
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
{
if (ll->ll_attr == LL_GATEATTR)
{
char cs, *ct, *cp = ll->ll_label->lab_text;
if (strchr(cp, '=') != NULL)
{
/* Since this is an attribute label, it has a special character
* at the end, which needs to be stripped off while printing
* and then put back again.
*/
ct = ll->ll_label->lab_text + strlen(ll->ll_label->lab_text) - 1;
cs = *ct;
*ct = '\0';
fprintf(outFile, " %s", ll->ll_label->lab_text);
ll->ll_attr = LL_NOATTR;
*ct = cs;
}
}
}
} }
/* Structures used by extTermAPFunc() for storing area and perimeter data */ /* Structures used by extTermAPFunc() for storing area and perimeter data */
@ -2204,13 +2155,11 @@ extDevFindParamMatch(devptr, length, width)
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
extSDTileFunc(tile, dinfo, pNum, arg) extSDTileFunc(tile, dinfo, pNum)
Tile *tile; Tile *tile;
TileType dinfo; /* UNUSED */ TileType dinfo; /* (unused) */
int pNum; int pNum;
FindRegion *arg; /* UNUSED */
{ {
LinkedTile *newdevtile; LinkedTile *newdevtile;
@ -2671,6 +2620,30 @@ extOutputDevices(def, transList, outFile)
if (!strcmp(devptr->exts_deviceName, "Ignore")) if (!strcmp(devptr->exts_deviceName, "Ignore"))
continue; continue;
/* Model type "Short" in the techfile indicates a device */
/* to short across the first two nodes (the gate and the */
/* source). This solves the specific issue of a transistor */
/* extended drain where the drain is a resistor but the */
/* resistor is part of the model and should not be output. */
if (!strcmp(devptr->exts_deviceName, "Short"))
{
fprintf(outFile, "equiv ");
/* To do: Use parameters to specify which terminals */
/* are shorted. */
/* gate */
node = (NodeRegion *)ExtGetRegion(reg->treg_tile, reg->treg_dinfo);
fprintf(outFile, "\"%s\" ", extNodeName((LabRegion *)node));
/* First non-gate terminal */
node = (NodeRegion *)extTransRec.tr_termnode[0];
fprintf(outFile, "\"%s\"\n", extNodeName((LabRegion *)node));
continue;
}
/* Original-style FET record backward compatibility */ /* Original-style FET record backward compatibility */
if (devptr->exts_deviceClass != DEV_FET) if (devptr->exts_deviceClass != DEV_FET)
fprintf(outFile, "device "); fprintf(outFile, "device ");
@ -2752,56 +2725,6 @@ extOutputDevices(def, transList, outFile)
/* get corrected by extComputeEffectiveLW(). */ /* get corrected by extComputeEffectiveLW(). */
length = (extTransRec.tr_gatelen - width) / 2; length = (extTransRec.tr_gatelen - width) / 2;
} }
if ((n == 1) && (length == 0) && (extTransRec.tr_gatelen == 0))
{
/* If a one-terminal device has not recorded any
* gate length, then get W and L from the bounding
* box of the device. This routine could be much
* better optimized but it is probably not worth
* the effort. Just reusing the code from above
* for creating extSpecialDevice, a list of device
* tiles. Note that W and L are not distinguishable
* and hopefully the PDK defines the device by area
* and perimeter.
*/
LinkedTile *lt;
Rect devbbox, ltbox;
extSpecialDevice = (LinkedTile *)NULL;
arg.fra_uninit = (ClientData)extTransRec.tr_gatenode;
arg.fra_region = (ExtRegion *)reg;
arg.fra_each = extSDTileFunc;
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
arg.fra_pNum, &arg);
arg.fra_uninit = (ClientData) reg;
arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode;
arg.fra_each = (int (*)()) NULL;
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
arg.fra_pNum, &arg);
lt = extSpecialDevice;
if (lt)
{
TiToRect(lt->t, &devbbox);
for (; lt; lt = lt->t_next)
{
TiToRect(lt->t, &ltbox);
GeoInclude(&ltbox, &devbbox);
}
free_magic1_t mm1 = freeMagic1_init();
for (lt = extSpecialDevice; lt; lt = lt->t_next)
freeMagic1(&mm1, (char *)lt);
freeMagic1_end(&mm1);
}
length = devbbox.r_xtop - devbbox.r_xbot;
/* Width was likely a perimeter value and will
* be recalculated as the actual device width.
*/
width = devbbox.r_ytop - devbbox.r_ybot;
}
} }
/*------------------------------------------------------*/ /*------------------------------------------------------*/
@ -3944,11 +3867,9 @@ extTermAPFunc(tile, dinfo, eapd)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
extTransPerimFunc(bp, cdata) extTransPerimFunc(bp)
Boundary *bp; Boundary *bp;
ClientData cdata; /* UNUSED */
{ {
TileType tinside, toutside, dinfo; TileType tinside, toutside, dinfo;
Tile *tile; Tile *tile;
@ -4224,13 +4145,11 @@ extTransPerimFunc(bp, cdata)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
extAnnularTileFunc(tile, dinfo, pNum, arg) extAnnularTileFunc(tile, dinfo, pNum)
Tile *tile; Tile *tile;
TileType dinfo; TileType dinfo;
int pNum; int pNum;
FindRegion *arg; /* UNUSED */
{ {
TileTypeBitMask mask; TileTypeBitMask mask;
TileType loctype; TileType loctype;
@ -4276,13 +4195,11 @@ extAnnularTileFunc(tile, dinfo, pNum, arg)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
extResistorTileFunc(tile, dinfo, pNum, arg) extResistorTileFunc(tile, dinfo, pNum)
Tile *tile; Tile *tile;
TileType dinfo; TileType dinfo;
int pNum; int pNum;
FindRegion *arg; /* UNUSED */
{ {
TileTypeBitMask mask; TileTypeBitMask mask;
TileType loctype; TileType loctype;
@ -5130,7 +5047,7 @@ extFindNodes(def, clipArea, subonly)
pNum = ExtCurStyle->exts_globSubstratePlane; pNum = ExtCurStyle->exts_globSubstratePlane;
/* Does the type set of this plane intersect the substrate types? */ /* Does the type set of this plane intersect the substrate types? */
if ((pNum != -1) && TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace)) if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
{ {
arg.fra_pNum = pNum; arg.fra_pNum = pNum;
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],

View File

@ -76,19 +76,18 @@ void extHeader();
*/ */
Plane * Plane *
ExtCell(def, outName, isTop) ExtCell(def, outName, doLength)
CellDef *def; /* Cell being extracted */ CellDef *def; /* Cell being extracted */
char *outName; /* Name of output file; if NULL, derive from def name */ char *outName; /* Name of output file; if NULL, derive from def name */
bool isTop; /* If TRUE, cell is the top level cell */ bool doLength; /* If TRUE, extract pathlengths from drivers to
* receivers (the names are stored in ExtLength.c).
* Should only be TRUE for the root cell in a
* hierarchy.
*/
{ {
char *filename; char *filename;
FILE *f = NULL; FILE *f = NULL;
Plane *savePlane; Plane *savePlane;
bool noextract;
/* If marked abstract, then don't extract the cell */
DBPropGet(def, "noextract", &noextract);
if (noextract) return extPrepSubstrate(def);
/* Incremental extraction: If the cell is marked for no extraction, /* Incremental extraction: If the cell is marked for no extraction,
* then just prepare the substrate plane and return it to the caller. * then just prepare the substrate plane and return it to the caller.
@ -112,7 +111,7 @@ ExtCell(def, outName, isTop)
} }
extNumErrors = extNumWarnings = 0; extNumErrors = extNumWarnings = 0;
savePlane = extCellFile(def, f, isTop); savePlane = extCellFile(def, f, doLength);
if (f != NULL) fclose(f); if (f != NULL) fclose(f);
if (extNumErrors > 0 || extNumWarnings > 0) if (extNumErrors > 0 || extNumWarnings > 0)
@ -472,10 +471,13 @@ ExtRevertSubstrate(def, savePlane)
*/ */
Plane * Plane *
extCellFile(def, f, isTop) extCellFile(def, f, doLength)
CellDef *def; /* Def to be extracted */ CellDef *def; /* Def to be extracted */
FILE *f; /* Output to this file */ FILE *f; /* Output to this file */
bool isTop; /* TRUE if the cell is the top level cell */ bool doLength; /* TRUE if we should extract driver-receiver path
* length information for this cell (see ExtCell
* for more details).
*/
{ {
NodeRegion *reg; NodeRegion *reg;
Plane *saveSub; Plane *saveSub;
@ -486,19 +488,8 @@ extCellFile(def, f, isTop)
/* If "extract do unique" was specified, then make labels in the /* If "extract do unique" was specified, then make labels in the
* cell unique. * cell unique.
*/ */
if (ExtOptions & EXT_DOUNIQUE) if (ExtOptions & EXT_DOUNIQUE)
{
if (ExtOptions & EXT_DOUNIQNOTOPPORTS)
{
if (isTop)
extUniqueCell(def, EXT_UNIQ_TEMP_NOPORTS);
else
extUniqueCell(def, EXT_UNIQ_TEMP); extUniqueCell(def, EXT_UNIQ_TEMP);
}
else
extUniqueCell(def, EXT_UNIQ_TEMP);
}
/* Prep any isolated substrate areas */ /* Prep any isolated substrate areas */
if (ExtOptions & EXT_DOEXTRESIST) if (ExtOptions & EXT_DOEXTRESIST)
@ -528,7 +519,7 @@ extCellFile(def, f, isTop)
ExtResetTiles(def, CLIENTDEFAULT); ExtResetTiles(def, CLIENTDEFAULT);
/* Final pass: extract length information if desired */ /* Final pass: extract length information if desired */
if (!SigInterruptPending && isTop && (ExtOptions & EXT_DOLENGTH)) if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH))
extLength(extParentUse, f); extLength(extParentUse, f);
UndoEnable(); UndoEnable();

View File

@ -113,91 +113,23 @@ bool extTestNMInteract(Tile *t1, TileType di1, Tile *t2, TileType di2)
return DBTestNMInteract(&rect1, tt1, t2, di2, FALSE); return DBTestNMInteract(&rect1, tt1, t2, di2, FALSE);
} }
/*
*----------------------------------------------------------------------
* extHierSubInteractFunc --
*
* Simple callback function for extHierSubShielfFunc() that halts
* the search if any type connecting to substrate is found in
* the area.
*
* Results: 1 to stop the search.
*
* Side effects: None.
*
*----------------------------------------------------------------------
*/
int
extHierSubInteractFunc(tile, dinfo, clientdata)
Tile *tile; /* unused */
TileType dinfo; /* unused */
ClientData clientdata; /* unused */
{
return 1;
}
/* /*
*---------------------------------------------------------------------- *----------------------------------------------------------------------
* extHierSubShieldFunc -- * extHierSubShieldFunc --
* *
* Callback function for extHierSubstrate() that halts the search * Simple callback function for extHierSubstrate() that halts the
* if any substrate shield type is found in the search area. To * search if any substrate shield type is found in the search area
* avoid flagging substrate shields that overlap the search area
* but do not interact with the cell, check the area of the
* substrate shield for device types that connect to substrate
* (ExtCurStyle->exts_subsDevTypes). If something is found, then
* return 1 immediately to stop the search.
*
* Results: 1 if an interacting substrate shield is found, 0 otherwise.
*
* Side effects: None.
* *
*---------------------------------------------------------------------- *----------------------------------------------------------------------
*/ */
int int
extHierSubShieldFunc(tile, dinfo, use) extHierSubShieldFunc(tile, dinfo, clientdata)
Tile *tile; Tile *tile; /* (unused) */
TileType dinfo; TileType dinfo; /* (unused) */
CellUse *use; ClientData clientdata; /* (unused) */
{ {
Rect r, rsub;
int pNum;
TileType ttype;
CellDef *subdef;
Transform t;
if (IsSplit(tile))
{
ttype = TiGetLeftType(tile);
if (!TTMaskHasType(&ExtCurStyle->exts_globSubstrateShieldTypes, ttype))
ttype = TiGetRightType(tile);
}
else
ttype = TiGetTypeExact(tile);
TiToRect(tile, &r);
/* Convert area of tile to the coordinates of the cell "subdef", which is
* a child of the cell containing "tile".
*/
subdef = use->cu_def;
GeoInvertTrans(&use->cu_transform, &t);
GeoTransRect(&t, &r, &rsub);
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (TTMaskIntersect(&DBPlaneTypes[pNum], &ExtCurStyle->exts_subsDevTypes))
{
if (DBSrPaintNMArea((Tile *)NULL,
subdef->cd_planes[pNum], dinfo, &rsub,
&ExtCurStyle->exts_subsDevTypes,
extHierSubInteractFunc, (ClientData)NULL) == 1)
return 1; return 1;
}
}
return 0;
} }
/* /*
@ -297,7 +229,7 @@ extHierSubstrate(ha, use, x, y)
if (DBSrPaintArea((Tile *) NULL, if (DBSrPaintArea((Tile *) NULL,
def->cd_planes[pNum], &subArea, def->cd_planes[pNum], &subArea,
&ExtCurStyle->exts_globSubstrateShieldTypes, &ExtCurStyle->exts_globSubstrateShieldTypes,
extHierSubShieldFunc, PTR2CD(use)) != 0) extHierSubShieldFunc, (ClientData)NULL) != 0)
{ {
freeMagic(nodeList); freeMagic(nodeList);
ExtResetTiles(use->cu_def, CLIENTDEFAULT); ExtResetTiles(use->cu_def, CLIENTDEFAULT);
@ -349,13 +281,6 @@ extHierSubstrate(ha, use, x, y)
nn->nn_next = node2->node_names->nn_next; nn->nn_next = node2->node_names->nn_next;
node2->node_names->nn_next = node1->node_names; node2->node_names->nn_next = node1->node_names;
node2->node_len += node1->node_len; node2->node_len += node1->node_len;
if (node2->node_ports)
{
ExtConnList *nport;
for (nport = node2->node_ports; nport && nport->r_next;
nport = nport->r_next);
if (nport) nport->r_next = node1->node_ports;
}
freeMagic((char *)node1); freeMagic((char *)node1);
} }
else else
@ -369,13 +294,6 @@ extHierSubstrate(ha, use, x, y)
nn->nn_next = node1->node_names; nn->nn_next = node1->node_names;
node1->node_names = node2->node_names; node1->node_names = node2->node_names;
node1->node_len += node2->node_len; node1->node_len += node2->node_len;
if (node1->node_ports)
{
ExtConnList *nport;
for (nport = node1->node_ports; nport && nport->r_next;
nport = nport->r_next);
if (nport) nport->r_next = node2->node_ports;
}
freeMagic((char *)node2); freeMagic((char *)node2);
} }
} }
@ -436,8 +354,8 @@ extHierConnections(ha, cumFlat, oneFlat)
if (!(lab->lab_flags & LABEL_STICKY)) continue; if (!(lab->lab_flags & LABEL_STICKY)) continue;
r = lab->lab_rect; r = lab->lab_rect;
if (!GEO_TOUCH(&r, &ha->ha_subArea)) continue;
GEOCLIP(&r, &ha->ha_subArea); GEOCLIP(&r, &ha->ha_subArea);
if (GEO_RECTNULL(&r)) continue;
cumDef = cumFlat->et_use->cu_def; cumDef = cumFlat->et_use->cu_def;
connected = &DBConnectTbl[lab->lab_type]; connected = &DBConnectTbl[lab->lab_type];
@ -581,13 +499,6 @@ extHierConnectFunc1(oneTile, dinfo, ha)
nn->nn_next = node2->node_names->nn_next; nn->nn_next = node2->node_names->nn_next;
node2->node_names->nn_next = node1->node_names; node2->node_names->nn_next = node1->node_names;
node2->node_len += node1->node_len; node2->node_len += node1->node_len;
if (node2->node_ports)
{
ExtConnList *nport;
for (nport = node2->node_ports; nport && nport->r_next;
nport = nport->r_next);
if (nport) nport->r_next = node1->node_ports;
}
freeMagic((char *) node1); freeMagic((char *) node1);
} }
else else
@ -603,13 +514,6 @@ extHierConnectFunc1(oneTile, dinfo, ha)
nn->nn_next = node1->node_names; nn->nn_next = node1->node_names;
node1->node_names = node2->node_names; node1->node_names = node2->node_names;
node1->node_len += node2->node_len; node1->node_len += node2->node_len;
if (node1->node_ports)
{
ExtConnList *nport;
for (nport = node1->node_ports; nport && nport->r_next;
nport = nport->r_next);
if (nport) nport->r_next = node2->node_ports;
}
freeMagic((char *) node2); freeMagic((char *) node2);
} }
} }
@ -619,48 +523,6 @@ extHierConnectFunc1(oneTile, dinfo, ha)
} }
/* /*
*------------------------------------------------------------------------
*
* extHierFindTopNode --
*
* Simple callback function used in extHierConnectFunc2() to retrieve
* the node name of a node in the CellDef being extracted at a specific
* point. If there is no node at that point (indicating that there is
* paint in a subcell at that location but no paint in the top level
* cell) then return NULL.
*
* Returns:
* 1 if a node is found, otherwise 0 to keep the search going.
*
* Side effects:
* A pointer to the node is returned in the clientData field.
*
*------------------------------------------------------------------------
*/
int
extHierFindTopNode(Tile *tile,
TileType dinfo,
ExtRegion **nreg)
{
ExtRegion *tireg;
tireg = (ExtRegion *)ExtGetRegion(tile, dinfo);
if ((ClientData)tireg == CLIENTDEFAULT)
{
*nreg = (ExtRegion *)0;
return 0;
}
else
{
*nreg = tireg;
return 1;
}
}
/*
*------------------------------------------------------------------------
*
* extHierConnectFunc2 -- * extHierConnectFunc2 --
* *
* Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def * Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def
@ -676,8 +538,6 @@ extHierFindTopNode(Tile *tile,
* if the types of ha->hierOneTile and 'cum' connect. * if the types of ha->hierOneTile and 'cum' connect.
* Otherwise, if the tiles actually overlap (as opposed * Otherwise, if the tiles actually overlap (as opposed
* to merely abut), mark it with feedback as an error. * to merely abut), mark it with feedback as an error.
*
*------------------------------------------------------------------------
*/ */
int int
@ -748,53 +608,6 @@ extHierConnectFunc2(cum, dinfo, ha)
if (node1 != node2) if (node1 != node2)
{ {
ExtConnList *newport;
int pNum;
if (ExtOptions & EXT_DOEXTRESIST)
{
NodeRegion *topnode = NULL;
/* Record the area of connection for both nodes in their
* respective coordinate systems, and the name of the
* cell use to which the connection is made.
*/
newport = (ExtConnList *)mallocMagic(sizeof(ExtConnList));
newport->r_r = r;
newport->r_type = ttype;
newport->r_useid = ha->ha_subUse->cu_id;
/* Find a node at the given location in et_lookNames (the
* original CellDef being extracted). If there is no node
* in the def itself then the entry is NULL.
*/
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (TTMaskHasType(&DBPlaneTypes[pNum], ttype))
{
/* Make sure that the rect is not zero area */
if (r.r_xtop == r.r_xbot)
{
r.r_xtop++;
r.r_xbot--;
}
if (r.r_ytop == r.r_ybot)
{
r.r_ytop++;
r.r_ybot--;
}
DBSrPaintArea((Tile *)NULL,
ha->ha_cumFlat.et_lookNames->cd_planes[pNum],
&r, &DBConnectTbl[ttype], extHierFindTopNode,
(ClientData)PTR2CD(&topnode));
newport->r_upnode = PTR2CD(topnode);
newport->r_downnode = PTR2CD(node2->node_names);
}
}
}
if (node1->node_len < node2->node_len) if (node1->node_len < node2->node_len)
{ {
/* /*
@ -809,12 +622,6 @@ extHierConnectFunc2(cum, dinfo, ha)
node2->node_names->nn_next = node1->node_names; node2->node_names->nn_next = node1->node_names;
node2->node_len += node1->node_len; node2->node_len += node1->node_len;
freeMagic((char *) node1); freeMagic((char *) node1);
if (ExtOptions & EXT_DOEXTRESIST)
{
newport->r_next = node2->node_ports;
node2->node_ports = newport;
}
} }
else else
{ {
@ -830,12 +637,6 @@ extHierConnectFunc2(cum, dinfo, ha)
node1->node_names = node2->node_names; node1->node_names = node2->node_names;
node1->node_len += node2->node_len; node1->node_len += node2->node_len;
freeMagic((char *) node2); freeMagic((char *) node2);
if (ExtOptions & EXT_DOEXTRESIST)
{
newport->r_next = node1->node_ports;
node1->node_ports = newport;
}
} }
} }
} }
@ -932,13 +733,6 @@ extHierConnectFunc3(cum, dinfo, ha)
nn->nn_next = node2->node_names->nn_next; nn->nn_next = node2->node_names->nn_next;
node2->node_names->nn_next = node1->node_names; node2->node_names->nn_next = node1->node_names;
node2->node_len += node1->node_len; node2->node_len += node1->node_len;
if (node2->node_ports)
{
ExtConnList *nport;
for (nport = node2->node_ports; nport && nport->r_next;
nport = nport->r_next);
if (nport) nport->r_next = node1->node_ports;
}
freeMagic((char *) node1); freeMagic((char *) node1);
} }
else else
@ -954,13 +748,6 @@ extHierConnectFunc3(cum, dinfo, ha)
nn->nn_next = node1->node_names; nn->nn_next = node1->node_names;
node1->node_names = node2->node_names; node1->node_names = node2->node_names;
node1->node_len += node2->node_len; node1->node_len += node2->node_len;
if (node1->node_ports)
{
ExtConnList *nport;
for (nport = node1->node_ports; nport && nport->r_next;
nport = nport->r_next);
if (nport) nport->r_next = node2->node_ports;
}
freeMagic((char *) node2); freeMagic((char *) node2);
} }
} }
@ -1129,7 +916,6 @@ extOutputConns(table, outf)
NodeName *nfirst; NodeName *nfirst;
HashSearch hs; HashSearch hs;
HashEntry *he; HashEntry *he;
ExtConnList *nport, *npnext;
HashStartSearch(&hs); HashStartSearch(&hs);
while ((he = HashNext(table, &hs))) while ((he = HashNext(table, &hs)))
@ -1162,6 +948,7 @@ extOutputConns(table, outf)
node->node_pa[n].pa_area, node->node_pa[n].pa_area,
node->node_pa[n].pa_perim); node->node_pa[n].pa_perim);
fprintf(outf, "\n"); fprintf(outf, "\n");
nn->nn_node = (Node *) NULL; /* Processed */ nn->nn_node = (Node *) NULL; /* Processed */
/* Subsequent merges */ /* Subsequent merges */
@ -1173,23 +960,6 @@ extOutputConns(table, outf)
} }
} }
nn->nn_node = (Node *) NULL; nn->nn_node = (Node *) NULL;
for (nport = node->node_ports; nport;)
{
LabRegion *lreg = (LabRegion *)CD2PTR(nport->r_upnode);
NodeName *nn2 = (NodeName *)CD2PTR(nport->r_downnode);
npnext = nport->r_next;
/* Output port positions */
fprintf(outf, "connect %d %d %d %d %s \"%s\" \"%s\"\n",
nport->r_r.r_xbot, nport->r_r.r_ybot,
nport->r_r.r_xtop, nport->r_r.r_ytop,
DBTypeShortName(nport->r_type),
(lreg == (LabRegion *)NULL) ? "None" :
extNodeName(lreg),
(nn2) ? nn2->nn_name : "None");
freeMagic((char *)nport);
nport = npnext;
}
freeMagic((char *) node); freeMagic((char *) node);
} }
freeMagic((char *) nfirst); freeMagic((char *) nfirst);
@ -1235,7 +1005,6 @@ extHierNewNode(he)
node->node_names = nn; node->node_names = nn;
node->node_cap = (CapValue) 0; node->node_cap = (CapValue) 0;
node->node_len = 1; node->node_len = 1;
node->node_ports = (ExtConnList *)NULL;
for (n = 0; n < nclasses; n++) for (n = 0; n < nclasses; n++)
node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0; node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0;
HashSetValue(he, (char *) nn); HashSetValue(he, (char *) nn);

View File

@ -272,7 +272,7 @@ extInterSubtreeElement(use, trans, x, y, r)
int int
extInterSubtreeTile(tile, dinfo, cxp) extInterSubtreeTile(tile, dinfo, cxp)
Tile *tile; Tile *tile;
TileType dinfo; /* (unused) */ TileType dinfo;
TreeContext *cxp; TreeContext *cxp;
{ {
SearchContext newscx; SearchContext newscx;
@ -343,9 +343,8 @@ extInterOverlapSubtree(scx)
*/ */
int int
extInterOverlapTile(tile, dinfo, cxp) extInterOverlapTile(tile, cxp)
Tile *tile; Tile *tile;
TileType dinfo; /* (unused) */
TreeContext *cxp; TreeContext *cxp;
{ {
SearchContext *scx = cxp->tc_scx; SearchContext *scx = cxp->tc_scx;

View File

@ -85,7 +85,7 @@ typedef struct _linkedDef {
Stack *extDefStack; Stack *extDefStack;
/* Forward declarations */ /* Forward declarations */
int extDefInitFunc(CellDef *, ClientData); /* UNUSED */ int extDefInitFunc();
void extDefPush(); void extDefPush();
void extDefIncremental(); void extDefIncremental();
void extParents(); void extParents();
@ -395,11 +395,9 @@ ExtAll(rootUse)
* cell defs, in preparation for extracting a subtree * cell defs, in preparation for extracting a subtree
* rooted at a particular def. * rooted at a particular def.
*/ */
/*ARGSUSED*/
int int
extDefInitFunc(def, cdata) extDefInitFunc(def)
CellDef *def; CellDef *def;
ClientData cdata; /* UNUSED */
{ {
def->cd_client = (ClientData) 0; def->cd_client = (ClientData) 0;
return (0); return (0);
@ -473,19 +471,6 @@ ExtUnique(rootUse, option)
/* Fix up bounding boxes if they've changed */ /* Fix up bounding boxes if they've changed */
DBFixMismatch(); DBFixMismatch();
/* Because the "extract unique" does the same thing as "extract do unique"
* but the options may be different, disable "extract do unique" when
* "extract unique" is run, on the assumption that no user would
* intentionally use both methods. If "do unique" was set and got
* disabled, then flag a warning.
*/
if (ExtOptions & EXT_DOUNIQUE)
{
ExtOptions &= ~EXT_DOUNIQUE;
TxPrintf("Warning: Extract option \"do unique\" disabled because "
"\"extract unique\" was run.\n");
}
/* Mark all defs as being unvisited */ /* Mark all defs as being unvisited */
(void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0);

View File

@ -614,7 +614,6 @@ termtop:
termdone: termdone:
/* (continue) */ /* (continue) */
(void)0; /* older compilers need a statement after the label to prevent a compile error */
} }
/* Clean up---Put the ClientData entries in the tiles back to /* Clean up---Put the ClientData entries in the tiles back to

View File

@ -54,14 +54,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* C99 compat */ /* C99 compat */
#include "drc/drc.h" #include "drc/drc.h"
/*
* If "exactinteractions" is defined, use an experimental algorithm
* for finding exact interaction areas. Currently it doesn't work
* too well, so it is disabled.
*/
/* #define exactinteractions */
#ifdef exactinteractions #ifdef exactinteractions
/*
* If "exactinteractions" is defined, we use an experimental algorithm
* for finding exact interaction areas. Currently it doesn't work too
* well, so we leave it turned off.
*/
int ExtInterBloat = 10; int ExtInterBloat = 10;
#endif /* exactinteractions */ #endif /* exactinteractions */
@ -176,10 +174,8 @@ extSubtree(parentUse, reg, f)
int cuts, totcuts; int cuts, totcuts;
float pdone, plast; float pdone, plast;
SearchContext scx; SearchContext scx;
int savedDisplayStatus;
/* Use the display timer to force a 5-second progress check */ /* Use the display timer to force a 5-second progress check */
savedDisplayStatus = GrDisplayStatus;
GrDisplayStatus = DISPLAY_IN_PROGRESS; GrDisplayStatus = DISPLAY_IN_PROGRESS;
SigSetTimer(5); /* Print at 5-second intervals */ SigSetTimer(5); /* Print at 5-second intervals */
@ -255,17 +251,6 @@ extSubtree(parentUse, reg, f)
if (result == 0) { if (result == 0) {
/* If result == FALSE then ha.ha_interArea is invalid. */ /* If result == FALSE then ha.ha_interArea is invalid. */
ha.ha_interArea = rlab; ha.ha_interArea = rlab;
/* Ensure that the interaction area is not zero */
if (ha.ha_interArea.r_xtop - ha.ha_interArea.r_xbot == 0)
{
ha.ha_interArea.r_xtop++;
ha.ha_interArea.r_xbot--;
}
if (ha.ha_interArea.r_ytop - ha.ha_interArea.r_ybot == 0)
{
ha.ha_interArea.r_ytop++;
ha.ha_interArea.r_ybot--;
}
result = 1; result = 1;
} }
else else
@ -352,7 +337,7 @@ done:
/* Output connections and node adjustments */ /* Output connections and node adjustments */
extOutputConns(&ha.ha_connHash, f); extOutputConns(&ha.ha_connHash, f);
HashKill(&ha.ha_connHash); HashKill(&ha.ha_connHash);
GrDisplayStatus = savedDisplayStatus; GrDisplayStatus = DISPLAY_IDLE;
SigRemoveTimer(); SigRemoveTimer();
/* Clear the CU_SUB_EXTRACTED flag from all children instances */ /* Clear the CU_SUB_EXTRACTED flag from all children instances */
@ -794,7 +779,6 @@ extSubtreeFunc(scx, ha)
*/ */
ha->ha_subArea = use->cu_bbox; ha->ha_subArea = use->cu_bbox;
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea); GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
hy.hy_area = &ha->ha_subArea; hy.hy_area = &ha->ha_subArea;
hy.hy_target = oneFlat->et_use; hy.hy_target = oneFlat->et_use;
hy.hy_prefix = TRUE; hy.hy_prefix = TRUE;

View File

@ -836,7 +836,6 @@ extTechStyleInit(style)
style->exts_sidePlanes = style->exts_overlapPlanes = 0; style->exts_sidePlanes = style->exts_overlapPlanes = 0;
TTMaskZero(&style->exts_deviceMask); TTMaskZero(&style->exts_deviceMask);
TTMaskZero(&style->exts_subsDevTypes);
style->exts_activeTypes = DBAllButSpaceAndDRCBits; style->exts_activeTypes = DBAllButSpaceAndDRCBits;
for (r = 0; r < NP; r++) for (r = 0; r < NP; r++)
@ -2356,9 +2355,6 @@ ExtTechLine(sectionName, argc, argv)
} }
TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1);
if (!TTMaskIsZero(&subsTypes))
TTMaskSetMask(&ExtCurStyle->exts_subsDevTypes, &types1);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (TTMaskHasType(&types1, t)) if (TTMaskHasType(&types1, t))
{ {
@ -2384,7 +2380,6 @@ ExtTechLine(sectionName, argc, argv)
devptr->exts_next = ExtCurStyle->exts_device[t]; devptr->exts_next = ExtCurStyle->exts_device[t];
ExtCurStyle->exts_device[t] = devptr; ExtCurStyle->exts_device[t] = devptr;
#ifdef ARIEL #ifdef ARIEL
{ {
int z; int z;
@ -2872,8 +2867,6 @@ ExtTechLine(sectionName, argc, argv)
} }
TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1);
if (!TTMaskIsZero(&subsTypes))
TTMaskSetMask(&ExtCurStyle->exts_subsDevTypes, &types1);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
{ {

View File

@ -288,11 +288,9 @@ ExtTimes(rootUse, f)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
extTimesInitFunc(use, cdata) extTimesInitFunc(use)
CellUse *use; CellUse *use;
ClientData cdata; /* UNUSED */
{ {
CellDef *def = use->cu_def; CellDef *def = use->cu_def;
struct cellStats *cs; struct cellStats *cs;

View File

@ -66,8 +66,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
* label. This way, the unique label form can be used by the * label. This way, the unique label form can be used by the
* extraction code but labels (and port indexes) can be reverted * extraction code but labels (and port indexes) can be reverted
* afterward, and no permanent change is made to the circuit. * afterward, and no permanent change is made to the circuit.
* Option EXT_UNIQ_TEMP_NOPORTS is a combination of EXT_UNIQ_TEMP and
* EXT_UNIQ_NOPORTS.
* *
* Results: * Results:
* Returns the number of warnings generated. * Returns the number of warnings generated.
@ -228,9 +226,8 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
text = ll->ll_label->lab_text; text = ll->ll_label->lab_text;
if (option == EXT_UNIQ_ALL || option == EXT_UNIQ_TEMP) if (option == EXT_UNIQ_ALL || option == EXT_UNIQ_TEMP)
goto makeUnique; goto makeUnique;
else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS || else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS)
option == EXT_UNIQ_TEMP_NOPORTS) && && !(ll->ll_label->lab_flags & PORT_DIR_MASK))
!(ll->ll_label->lab_flags & PORT_DIR_MASK))
goto makeUnique; goto makeUnique;
cpend = strchr(text, '\0'); cpend = strchr(text, '\0');
@ -329,8 +326,7 @@ makeUnique:
saveLab = *lab; saveLab = *lab;
/* Flag this label as having been modified */ /* Flag this label as having been modified */
if ((option == EXT_UNIQ_TEMP) || (option == EXT_UNIQ_TEMP_NOPORTS)) if (option == EXT_UNIQ_TEMP) flags |= LABEL_UNIQUE;
flags |= LABEL_UNIQUE;
DBRemoveLabel(def, lab); DBRemoveLabel(def, lab);
DBPutFontLabel(def, &saveLab.lab_rect, DBPutFontLabel(def, &saveLab.lab_rect,

View File

@ -71,12 +71,11 @@ extern const char * const extDevTable[];
#define EXT_DORESISTANCE 0x008 /* Extract lumped resistance */ #define EXT_DORESISTANCE 0x008 /* Extract lumped resistance */
#define EXT_DOLENGTH 0x010 /* Extract pathlengths */ #define EXT_DOLENGTH 0x010 /* Extract pathlengths */
#define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */ #define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */
#define EXT_DOUNIQUE 0x100 /* Force unique nodes during extraction */ #define EXT_DOALL 0x03f /* ALL OF THE ABOVE */
#define EXT_DOALL 0x13f /* ALL OF THE ABOVE */
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */ #define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
#define EXT_DOALIASES 0x080 /* Output all node aliases */ #define EXT_DOALIASES 0x080 /* Output all node aliases */
#define EXT_DOUNIQUE 0x100 /* Force unique nodes during extraction */
#define EXT_DOEXTRESIST 0x200 /* Do full R-C extraction */ #define EXT_DOEXTRESIST 0x200 /* Do full R-C extraction */
#define EXT_DOUNIQNOTOPPORTS 0x400 /* Ignore top cell ports w/EXT_DOUNIQUE */
extern int ExtOptions; /* Bitmask of above */ extern int ExtOptions; /* Bitmask of above */
extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
@ -87,7 +86,6 @@ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
#define EXT_UNIQ_NOPORTS 2 #define EXT_UNIQ_NOPORTS 2
#define EXT_UNIQ_NOTOPPORTS 3 #define EXT_UNIQ_NOTOPPORTS 3
#define EXT_UNIQ_TEMP 4 /* Used only with "EXT_DOUNIQUE" */ #define EXT_UNIQ_TEMP 4 /* Used only with "EXT_DOUNIQUE" */
#define EXT_UNIQ_TEMP_NOPORTS 5 /* Used only with "EXT_DOUNIQUE" */
extern bool ExtTechLine(); extern bool ExtTechLine();
extern void ExtTechInit(); extern void ExtTechInit();

View File

@ -626,13 +626,6 @@ typedef struct extstyle
*/ */
TileTypeBitMask exts_deviceConn[NT]; TileTypeBitMask exts_deviceConn[NT];
/*
* List of device types which connect to a substrate type. This
* distinguishes between devices that make a connection to substrate
* (e.g., FETs) and those that don't (e.g., MiM caps, metal resistors).
*/
TileTypeBitMask exts_subsDevTypes;
/* /*
* Set of types to be considered for extraction. Types not in * Set of types to be considered for extraction. Types not in
* this list cannot be nodes (e.g., implant layers) * this list cannot be nodes (e.g., implant layers)
@ -988,7 +981,6 @@ typedef struct node
* in the list is the "official" node name. * in the list is the "official" node name.
*/ */
int node_len; /* Number of entries in node_names */ int node_len; /* Number of entries in node_names */
ExtConnList *node_ports; /* List of areas that connect to other cells */
CapValue node_cap; /* Capacitance to substrate */ CapValue node_cap; /* Capacitance to substrate */
PerimArea node_pa[1]; /* Dummy; each node actually has PerimArea node_pa[1]; /* Dummy; each node actually has
* ExtCurStyle->exts_numResistClasses * ExtCurStyle->exts_numResistClasses

View File

@ -63,6 +63,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <unistd.h> #include <unistd.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "utils/hash.h" #include "utils/hash.h"

View File

@ -20,6 +20,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "utils/magsgtty.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"
@ -61,74 +62,6 @@ nullDoNothing()
{ {
} }
/*
* Typed no-op stubs for WASM call_indirect type compatibility.
* WASM enforces exact type signatures at indirect call sites; assigning
* a 0-arg nullDoNothing to a pointer called with arguments causes a
* "null function or function signature mismatch" trap. These stubs
* have the correct arity so the WASM type check passes.
*/
/* 1-argument stub (int or pointer) */
static void
nullDoNothingI(int a)
{
(void) a;
}
/* 2-argument stub */
static void
nullDoNothingII(int a, int b)
{
(void) a; (void) b;
}
/* 4-argument stub */
static void
nullDoNothingIIII(int a, int b, int c, int d)
{
(void) a; (void) b; (void) c; (void) d;
}
/* 7-argument stub (for grFontTextPtr) */
static void
nullDoNothingIIIIIII(int a, int b, int c, int d, int e, int f, int g)
{
(void) a; (void) b; (void) c; (void) d; (void) e; (void) f; (void) g;
}
/* bool-returning stubs — return FALSE so callers treat backing store / window
* creation as unavailable, which is correct for the headless null driver. */
static bool
nullReturnFalseI(int a)
{
(void) a;
return FALSE;
}
static bool
nullReturnFalseII(int a, int b)
{
(void) a; (void) b;
return FALSE;
}
/* 3-argument bool-returning stub (for grDrawGridPtr) */
static bool
nullReturnFalseIII(int a, int b, int c)
{
(void) a; (void) b; (void) c;
return FALSE;
}
/* 1-argument int-returning stub (for GrWindowIdPtr) */
static int
nullReturnZeroI(int a)
{
(void) a;
return 0;
}
/* /*
*--------------------------------------------------------- *---------------------------------------------------------
* *
@ -314,10 +247,8 @@ nullSetDisplay(dispType, outFileName, mouseFileName)
{ {
TxPrintf("Using NULL graphics device.\n"); TxPrintf("Using NULL graphics device.\n");
#ifndef __EMSCRIPTEN__
TxAdd1InputDevice(fileno(stdin), nullStdin, (ClientData) NULL); TxAdd1InputDevice(fileno(stdin), nullStdin, (ClientData) NULL);
if (TxStdinIsatty) SigWatchFile(fileno(stdin), "stdin"); if (TxStdinIsatty) SigWatchFile(fileno(stdin), "stdin");
#endif
/* Set up the procedure values in the indirection table. */ /* Set up the procedure values in the indirection table. */
@ -329,49 +260,25 @@ nullSetDisplay(dispType, outFileName, mouseFileName)
GrEnableTabletPtr = nullDoNothing; GrEnableTabletPtr = nullDoNothing;
GrDisableTabletPtr = nullDoNothing; GrDisableTabletPtr = nullDoNothing;
GrSetCursorPtr = (void (*)()) nullDoNothingI; GrSetCursorPtr = nullDoNothing;
GrTextSizePtr = NullTextSize; GrTextSizePtr = NullTextSize;
GrDrawGlyphPtr = (void (*)()) nullDoNothingII; GrDrawGlyphPtr = nullDoNothing;
GrBitBltPtr = NullBitBlt; GrBitBltPtr = NullBitBlt;
GrReadPixelPtr = nullReturnZero; GrReadPixelPtr = nullReturnZero;
GrFlushPtr = nullDoNothing; GrFlushPtr = nullDoNothing;
/* Window management — null driver has no real windows; return FALSE so
* callers know the operation wasn't performed. */
GrCreateWindowPtr = NULL; /* headless: skip OS window creation, WindCreate stays OK */
GrDeleteWindowPtr = (void (*)()) nullDoNothingI;
GrConfigureWindowPtr = (void (*)()) nullDoNothingI;
GrOverWindowPtr = (void (*)()) nullDoNothingI;
GrUnderWindowPtr = (void (*)()) nullDoNothingI;
GrDamagedPtr = nullDoNothing;
GrUpdateIconPtr = (void (*)()) nullDoNothingII;
GrEventPendingPtr = (bool (*)()) nullReturnFalse;
GrWindowIdPtr = (int (*)()) nullReturnZeroI;
GrWindowNamePtr = NULL; /* protected by callers */
GrGetCursorPosPtr = (bool (*)()) nullReturnFalseII;
GrGetCursorRootPosPtr = (bool (*)()) nullReturnFalseII;
/* Backing store — not available in headless mode */
GrGetBackingStorePtr = (bool (*)()) nullReturnFalseII;
GrScrollBackingStorePtr = (bool (*)()) nullReturnFalseII;
GrPutBackingStorePtr = (void (*)()) nullDoNothingII;
GrFreeBackingStorePtr = (void (*)()) nullDoNothingI;
GrCreateBackingStorePtr = (void (*)()) nullDoNothingI;
/* local indirections */ /* local indirections */
grSetSPatternPtr = (void (*)()) nullDoNothingII; grSetSPatternPtr = nullDoNothing;
grPutTextPtr = (void (*)()) nullDoNothingIIII; grPutTextPtr = nullDoNothing;
grFontTextPtr = (void (*)()) nullDoNothingIIIIIII; grFontTextPtr = nullDoNothing;
grDefineCursorPtr = (void (*)()) nullDoNothingI; grDefineCursorPtr = nullDoNothing;
grFreeCursorPtr = (void (*)()) nullDoNothingI; grDrawGridPtr = nullReturnFalse;
grDrawGridPtr = (bool (*)()) nullReturnFalseIII; grDrawLinePtr = nullDoNothing;
grDrawLinePtr = (void (*)()) nullDoNothingIIII; grSetWMandCPtr = nullDoNothing;
grSetWMandCPtr = (void (*)()) nullDoNothingII; grFillRectPtr = nullDoNothing;
grFillRectPtr = (void (*)()) nullDoNothingI; grSetStipplePtr = nullDoNothing;
grFillPolygonPtr = (void (*)()) nullDoNothingII; grSetLineStylePtr = nullDoNothing;
grSetStipplePtr = (void (*)()) nullDoNothingI; grSetCharSizePtr = nullDoNothing;
grSetLineStylePtr = (void (*)()) nullDoNothingI;
grSetCharSizePtr = (void (*)()) nullDoNothingI;
GrScreenRect.r_xtop = 511; GrScreenRect.r_xtop = 511;
GrScreenRect.r_ytop = 483; GrScreenRect.r_ytop = 483;

View File

@ -17,6 +17,7 @@
#include <signal.h> #include <signal.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"
#include "windows/windows.h" #include "windows/windows.h"

View File

@ -22,6 +22,7 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"

View File

@ -28,6 +28,7 @@
#include "utils/main.h" #include "utils/main.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/malloc.h" #include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"

View File

@ -15,6 +15,7 @@
#include "tcltk/tclmagic.h" #include "tcltk/tclmagic.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"

View File

@ -26,6 +26,7 @@
#include "utils/main.h" #include "utils/main.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/malloc.h" #include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"

View File

@ -13,6 +13,7 @@
#include "tcltk/tclmagic.h" #include "tcltk/tclmagic.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"

View File

@ -23,6 +23,7 @@
#include "utils/main.h" #include "utils/main.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/malloc.h" #include "utils/malloc.h"
#include "utils/magsgtty.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"

View File

@ -13,6 +13,7 @@
#include "tcltk/tclmagic.h" #include "tcltk/tclmagic.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "windows/windows.h" #include "windows/windows.h"

View File

@ -31,6 +31,7 @@
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "textio/txcommands.h" #include "textio/txcommands.h"

View File

@ -22,6 +22,7 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "graphics/graphics.h" #include "graphics/graphics.h"

View File

@ -4,14 +4,10 @@
MODULE = magic MODULE = magic
MAGICDIR = .. MAGICDIR = ..
SRCS = magicTop.c
include ${MAGICDIR}/defs.mak include ${MAGICDIR}/defs.mak
SRCS = magicTop.c
ifeq (${MAKE_WASM},1)
SRCS += magicWasm.c
endif
EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \ EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \
${MAGICDIR}/cmwind/libcmwind.o \ ${MAGICDIR}/cmwind/libcmwind.o \
${MAGICDIR}/commands/libcommands.o \ ${MAGICDIR}/commands/libcommands.o \
@ -41,35 +37,7 @@ LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \
${OA_LIBS} ${ZLIB_FLAG} ${TOP_EXTRA_LIBS} ${OA_LIBS} ${ZLIB_FLAG} ${TOP_EXTRA_LIBS}
CLEANS += tclmagic${SHDLIB_EXT} libtclmagic${SHDLIB_EXT}.a proto.magicrc CLEANS += tclmagic${SHDLIB_EXT} libtclmagic${SHDLIB_EXT}.a proto.magicrc
ifeq (${MAKE_WASM},1)
# magicWasm.c bootstraps the embedded Tcl interp by calling Tcl_CreateInterp /
# Tcl_Init before tclStubsPtr is initialised. With -DUSE_TCL_STUBS those calls
# expand to (*tclStubsPtr->...)() and dereference a NULL stubs pointer; so
# this one file must be compiled with DFLAGS_NOSTUB (= DFLAGS without
# -DUSE_TCL_STUBS). All other files keep using stubs.
magicWasm.o: magicWasm.c
@echo --- compiling magic/magicWasm.o '(no Tcl stubs)'
${RM} magicWasm.o
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS_NOSTUB} -c magicWasm.c
magic.js: lib${MODULE}.o ${EXTRA_LIBS}
@echo --- building main magic WASM
${RM} magic.js magic.wasm
ifneq (${TCL_LIB_DIR},)
# TCL variant: pull in the main TCL archive (LIB_SPECS_NOSTUB → -ltcl9.x) and
# the stub-bootstrap archive (-ltclstub). Both are required: magic's objects
# use USE_TCL_STUBS macros (resolved by tclStubsPtr from libtclstub.a), and
# tclStubsPtr itself must point into the real TCL implementation (libtcl9.x.a).
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} lib${MODULE}.o ${EXTRA_LIBS} -o magic.js ${LIBS} ${LIB_SPECS_NOSTUB} -L${TCL_LIB_DIR} -ltclstub
else
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} lib${MODULE}.o ${EXTRA_LIBS} -o magic.js ${LIBS}
endif
endif
main: magic proto.magicrc main: magic proto.magicrc
ifeq (${MAKE_WASM},1)
@bash ${MAGICDIR}/toolchains/emscripten/post-build.sh magic.js magic.wasm
endif
tcl-main: tclmagic${SHDLIB_EXT} proto.magicrc tcl-main: tclmagic${SHDLIB_EXT} proto.magicrc
@ -110,14 +78,3 @@ $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro: magicps.pro
${CP} magicps.pro $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro ${CP} magicps.pro $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
include ${MAGICDIR}/rules.mak include ${MAGICDIR}/rules.mak
ifeq (${MAKE_WASM},1)
# rules.mak defines `${MODULE}` (= `magic`) with a recipe that links a native
# executable without the TCL libraries. For the WASM build the real artifact
# is `magic.js` (+ `magic.wasm`), so override the target to be a phony alias
# that just rebuilds magic.js. Must come after the include so make uses this
# recipe instead of rules.mak's.
.PHONY: magic
magic: magic.js
@:
endif

View File

@ -59,14 +59,8 @@ main(int argc, char *argv[])
* here, nor its format. It is updated by the Makefile in this directory. * here, nor its format. It is updated by the Makefile in this directory.
* *
* The version string originates at the top of scripts/config. * The version string originates at the top of scripts/config.
*
* Under MAGIC_WRAPPER (Tcl-embedded builds), tclmagic.c owns these globals;
* defining them here as well would produce duplicate-symbol errors when both
* objects end up in the same binary (as in the WASM build).
*/ */
#ifndef MAGIC_WRAPPER
char *MagicVersion = MAGIC_VERSION; char *MagicVersion = MAGIC_VERSION;
char *MagicRevision = MAGIC_REVISION; char *MagicRevision = MAGIC_REVISION;
char *MagicCompileTime = MAGIC_BUILDDATE; char *MagicCompileTime = MAGIC_BUILDDATE;
#endif

View File

@ -1,194 +0,0 @@
/*
* magicWasm.c --
*
* Headless Emscripten entry points for running Magic without a
* terminal-driven event loop.
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef MAGIC_WRAPPER
#include "tcltk/tclmagic.h"
#endif
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/paths.h"
#include "textio/textio.h"
#include "textio/txcommands.h"
#include "utils/utils.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#else
#define EMSCRIPTEN_KEEPALIVE
#endif
static int
magicWasmEnsureCadRoot(void)
{
if (getenv("CAD_ROOT") == NULL)
{
if (setenv("CAD_ROOT", "/", 0) != 0)
{
TxError("Failed to set CAD_ROOT for the WASM runtime.\n");
return -1;
}
}
return 0;
}
#ifdef MAGIC_WRAPPER
/* Forward decl — Tclmagic_Init bootstraps the Tcl interpreter (registers
* the magic::initialize command and calls Tcl_InitStubs(), which sets
* tclStubsPtr). Without this, any Tcl_X macro dereferences a NULL stubs
* pointer at runtime (crashes the wasm). The actual magic:: commands
* (magic::load, magic::gds, etc.) are registered separately by
* TclmagicRegisterCommands() after magicMainInit() populates the clients. */
extern int Tclmagic_Init(Tcl_Interp *interp);
#endif
EMSCRIPTEN_KEEPALIVE int
magic_wasm_init(void)
{
static char *argv[] = {
"magic",
"-d",
"null",
"-T",
"minimum",
NULL
};
if (magicWasmEnsureCadRoot() != 0)
return -1;
#ifdef MAGIC_WRAPPER
/* In wrapper mode, magic's code (and our PaExpand path expansion) reaches
* for `magicinterp` to resolve $env vars via Tcl_GetVar. In the normal
* Linux flow Tclmagic_Init() is called by tclsh after dlopen(); here we
* embed the interp directly, so we have to bootstrap it before
* magicMainInit() runs anything that might touch Tcl.
*
* Note: we deliberately avoid TxError here in MAGIC_WRAPPER mode
* TxError flushes via Tcl_EvalEx through tclStubsPtr, which only becomes
* non-NULL after Tclmagic_Init -> Tcl_InitStubs. So early errors go
* straight to stderr. */
if (magicinterp == NULL)
{
Tcl_Interp *interp = Tcl_CreateInterp();
if (interp == NULL)
{
fprintf(stderr, "magic_wasm_init: Tcl_CreateInterp returned NULL\n");
return -1;
}
/* Tcl_Init loads /init.tcl from the Tcl library directory; in our
* embedded VFS that script isn't shipped, so failure here is expected
* and non-fatal the interpreter itself is still usable for embedded
* evaluation, which is all we need. */
(void)Tcl_Init(interp);
consoleinterp = interp;
if (Tclmagic_Init(interp) != TCL_OK)
{
fprintf(stderr, "magic_wasm_init: Tclmagic_Init failed: %s\n",
Tcl_GetStringResult(interp));
return -1;
}
}
#endif
{
static int commandsRegistered = FALSE;
int rc = magicMainInit(5, argv);
#ifdef MAGIC_WRAPPER
if (rc == 0 && !commandsRegistered)
{
TclmagicRegisterCommands(magicinterp);
commandsRegistered = TRUE;
}
#endif
return rc;
}
}
EMSCRIPTEN_KEEPALIVE int
magic_wasm_run_command(const char *command)
{
int status;
status = magic_wasm_init();
if (status != 0)
return status;
if ((command == NULL) || (*command == '\0'))
return 0;
/* Set the current point to the center of the screen so that
* WindSendCommand routes the command to the layout window client
* (not the window-management border client which handles point 0,0).
*/
TxSetPoint(GrScreenRect.r_xtop / 2, GrScreenRect.r_ytop / 2,
WIND_UNKNOWN_WINDOW);
#ifdef MAGIC_WRAPPER
/* In wrapper mode the command is Tcl. Evaluate it via the magic interp;
* the magic backend is reachable through ::magic:: ensemble commands. */
if (magicinterp == NULL)
return -1;
return Tcl_EvalEx(magicinterp, command, -1, 0);
#else
return TxDispatchString(command, FALSE);
#endif
}
EMSCRIPTEN_KEEPALIVE int
magic_wasm_source_file(const char *path)
{
int status;
status = magic_wasm_init();
if (status != 0)
return status;
if ((path == NULL) || (*path == '\0'))
return -1;
#ifdef MAGIC_WRAPPER
/* In wrapper mode the file contains Tcl; evaluate it through the
* Tcl interpreter so that magic:: commands are dispatched via
* _tcl_dispatch just like magic_wasm_run_command does for strings. */
if (magicinterp == NULL)
return -1;
return Tcl_EvalFile(magicinterp, path);
#else
{
FILE *f = PaOpen((char *)path, "r", (char *)NULL, ".", (char *)NULL,
(char **)NULL);
if (f == NULL)
{
TxError("Unable to open command file \"%s\".\n", path);
return -1;
}
/* Set the current point to the center of the screen so that
* WindSendCommand routes all commands from the file to the layout
* window client. Without this, commands arrive with point (0,0)
* and end up in the border/windClient context where most are unknown. */
TxSetPoint(GrScreenRect.r_xtop / 2, GrScreenRect.r_ytop / 2,
WIND_UNKNOWN_WINDOW);
TxDispatch(f);
fclose(f);
return 0;
}
#endif
}
EMSCRIPTEN_KEEPALIVE void
magic_wasm_update(void)
{
if (magic_wasm_init() == 0)
WindUpdate();
}

View File

@ -26,19 +26,17 @@ StipplePattern begin
/FontMatrix [1 0 0 1 0 0] def /FontMatrix [1 0 0 1 0 0] def
/FontBBox [0 0 1 1] def /FontBBox [0 0 1 1] def
/Encoding 256 array def /Encoding 256 array def
/PattName (P000) def /PattName (P0) def
/tmpStr 3 string def /tmpStr 1 string def
/NoPatt {<00>} def /NoPatt {<00>} def
0 1 255 { Encoding exch /NoPatt put } for 0 1 255 { Encoding exch /NoPatt put } for
/BuildChar { /BuildChar {
1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load
64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end } def 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end } def
end end
/dp { StipplePattern begin /dp { StipplePattern begin dup 30 tmpStr cvrs PattName exch 1 exch
dup 10 tmpStr cvrs /num exch def putinterval PattName cvn dup Encoding exch 4 -1 roll exch put exch
PattName 1 num putinterval store end } def
PattName 0 num length 1 add getinterval cvn
dup Encoding exch 4 -1 roll exch put exch store end } def
/sf { findfont exch scalefont setfont } bind def /sf { findfont exch scalefont setfont } bind def
/sp { patterns setfont 2 setlinewidth } def /sp { patterns setfont 2 setlinewidth } def
/lb { gsave translate 0 0 moveto /just exch def gsave dup true charpath /lb { gsave translate 0 0 moveto /just exch def gsave dup true charpath
@ -70,3 +68,4 @@ end
x y moveto w y lineto w h lineto x h lineto closepath clip bx } def x y moveto w y lineto w h lineto x h lineto closepath clip bx } def
/tb {1 sub 3 1 roll gsave newpath moveto {lineto} repeat closepath clip pathbbox /tb {1 sub 3 1 roll gsave newpath moveto {lineto} repeat closepath clip pathbbox
/h exch def /w exch def /y exch def /x exch def bx } def /h exch def /w exch def /y exch def /x exch def bx } def

14
npm/.gitignore vendored
View File

@ -1,14 +0,0 @@
# Variant build outputs (regenerable via npm/build.sh).
tcl/magic.js
tcl/magic.wasm
notcl/magic.js
notcl/magic.wasm
# Pre-restructure artifacts (just in case anyone still has them locally).
magic.js
magic.wasm
*.tgz
node_modules/
package-lock.json
examples/output/

View File

@ -1,10 +0,0 @@
Copyright (C) 1985, 1990 Regents of the University of California.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies. The University of California
makes no representations about the suitability of this
software for any purpose. It is provided "as is" without
express or implied warranty. Export of this software outside
of the United States of America may require an export license.

View File

@ -1,235 +0,0 @@
# magic-vlsi-wasm
[Magic VLSI](http://opencircuitdesign.com/magic/) layout tool, compiled to
WebAssembly as a headless library. Runs in Node.js, browsers, and Web Workers
— no X11, no Tk, no native dependencies.
Use it to programmatically read and write `.mag`, `.gds`, `.cif`, `.ext`, and
SPICE netlists; run DRC; extract parasitics — anywhere JavaScript runs.
The package ships two variants:
| Variant | Entry point | Description |
|---------|-------------|-------------|
| **notcl** (default) | `magic-vlsi-wasm` | Standalone — no Tcl interpreter. Commands are plain Magic command strings. |
| **tcl** | `magic-vlsi-wasm/tcl` | Embeds a full Tcl 9 interpreter. Commands are evaluated as Tcl; Magic commands are available as the `::magic::` ensemble. |
## Install
The package is published to GitHub Packages. Add the following to your
project's `.npmrc` so npm knows where to find it:
```
@rtimothyedwards:registry=https://npm.pkg.github.com
```
Then install:
```bash
npm install @rtimothyedwards/magic-vlsi-wasm
```
If the package is private or you hit a 401, authenticate with a GitHub
[personal access token](https://github.com/settings/tokens) that has the
`read:packages` scope:
```
//npm.pkg.github.com/:_authToken=YOUR_TOKEN
@rtimothyedwards:registry=https://npm.pkg.github.com
```
Requires Node.js 18 or newer.
## Quick start
### Default variant (no Tcl)
```js
import createMagic from 'magic-vlsi-wasm';
const { runCommand, FS } = await createMagic();
// Drop a layout into Magic's virtual filesystem
FS.mkdirTree('/work');
FS.writeFile('/work/inv.mag', layoutBytes);
// Run Magic commands — scmos is built into the WASM binary, no tech file needed
runCommand('tech load scmos');
runCommand('load /work/inv');
runCommand('gds write /work/inv');
// Read the result back out
const gdsBytes = FS.readFile('/work/inv.gds');
```
### TCL variant
```js
import createMagic from 'magic-vlsi-wasm/tcl';
const { runCommand, FS } = await createMagic();
// Pure Tcl works directly
runCommand('set x 42');
runCommand('puts $tcl_version');
// Magic commands are available as the ::magic:: ensemble
runCommand('magic::tech load scmos');
runCommand('magic::load /work/inv');
runCommand('magic::gds write /work/inv');
```
The `scmos` technology family (`scmos`, `minimum`, `nmos`, ...) is embedded in
the WASM binary and available out of the box — those names work without
writing any tech file. To use a custom technology, write its `.tech` file into
the VFS at `/magic/sys/current/<name>.tech` before calling `tech load <name>`.
## API
```ts
createMagic(options?): Promise<MagicInstance>
```
`options` is forwarded to the underlying Emscripten module. Useful keys:
| Key | Default | Purpose |
|--------------|------------------|---------|
| `wasmBinary` | fetched lazily | Pre-fetched ArrayBuffer of `magic.wasm` (skips a network round-trip in browsers) |
| `print` | `console.log` | Callback for each stdout line |
| `printErr` | `console.error` | Callback for each stderr line |
The returned `MagicInstance` exposes:
| Method | Description |
|---------------------------|-------------|
| `runCommand(cmd: string)` | Dispatch a single Magic command. Returns 0 on success. |
| `sourceFile(path: string)` | Execute a script from the virtual filesystem. Returns 0 on success, -1 if the file could not be opened. |
| `init()` | Force initialization. Idempotent — `runCommand` and `sourceFile` call it for you. |
| `update()` | Drive a display-update cycle. No-op in this headless build. |
| `FS` | Emscripten virtual filesystem. See the [Emscripten docs](https://emscripten.org/docs/api_reference/Filesystem-API.html). |
Full TypeScript types ship in [`index.d.ts`](index.d.ts).
### Low-level access
`createMagic()` is a thin convenience wrapper over the underlying Emscripten
module. If you need direct access — for example to call `cwrap` yourself or
to drive `magic_wasm_init` manually — import the module factory directly:
```js
import createMagicModule from 'magic-vlsi-wasm/magic.js';
const module = await createMagicModule({ wasmBinary, print, printErr });
module._magic_wasm_init();
const run = module.cwrap('magic_wasm_run_command', 'number', ['string']);
run('tech load scmos');
```
The bundled examples use this lower-level path together with a small helper
class ([`examples/helpers.js`](examples/helpers.js)) that adds a
`runScript(text)` convenience method — it splits a multi-line Tcl block,
strips comments, and dispatches each line via `runCommand`. Useful when you
have a script as a string rather than as a file in the VFS.
## Examples
The package ships runnable examples for the most common workflows. After
installing, run one directly:
```bash
node node_modules/magic-vlsi-wasm/examples/extract.js
node node_modules/magic-vlsi-wasm/examples/gds.js
node node_modules/magic-vlsi-wasm/examples/drc.js
node node_modules/magic-vlsi-wasm/examples/cif.js
```
Or, when developing inside this repo:
```bash
npm test # full suite (extract, gds, drc, cif)
npm run example # extract.js — RC extraction + SPICE netlist
npm run test:gds # GDS write only
npm run test:drc # DRC check only
npm run test:cif # CIF write only
```
Each example loads the bundled [`min.mag`](examples/min.mag) (a small NPN
transistor cell from Magic's own scmos test suite) under the built-in `scmos`
technology — no external tech file required. See [`examples/`](examples/) for
the source; [`example.js`](examples/example.js) is the simplest entry point
(GDS → CIF conversion in ~40 lines).
## Build from source
If you want to rebuild the WASM module yourself, see
[`toolchains/emscripten/README.md`](../toolchains/emscripten/README.md).
The short version:
```bash
bash npm/build.sh # both variants, debug build
bash npm/build.sh --variant=notcl # default variant only (faster)
bash npm/build.sh --variant=tcl # TCL variant only
bash npm/build.sh --release # optimized (-O2, no debug symbols)
bash npm/build.sh --test # build + run tests
bash npm/build.sh --pack # build + produce magic-vlsi-wasm-<version>.tgz
```
You will need an activated [emsdk](https://emscripten.org/docs/getting_started/downloads.html)
on your PATH. If you pass `EMSDK_DIR=/path/to/emsdk`, `build.sh` sources
`emsdk_env.sh` for you.
### TCL variant: cloning the TCL source tree
The TCL variant links against a static WASM build of
[tcltk/tcl](https://github.com/tcltk/tcl). `build.sh` clones the source tree
automatically into `build-tcl-wasm/tcl` on the first run and builds it
out-of-source in the same directory — everything stays under `build-tcl-wasm/`
(which is gitignored), so nothing outside it is touched. Subsequent runs reuse
the existing clone and build.
```bash
# Override the TCL version or source repository
TCL_REF=core-9-0-3 bash npm/build.sh --variant=tcl
TCL_REPO_URL=https://github.com/tcltk/tcl.git bash npm/build.sh --variant=tcl
```
CI always resolves the latest stable `core-9-0-x` tag automatically. To build
against a specific version, set `TCL_REF` in the environment.
## Versioning
Published versions follow the scheme `{MAJOR}.{MINOR}.{PATCH}0{YYYYMMDD}+git{SHA}`,
for example `8.3.799020261231+git01234cde`.
The date is embedded directly into the patch number (separated by a leading
zero for readability). This means:
- Versions are orderable numerically — a later build date is always a higher
version number within the same patch series.
- Security or bugfix releases for `8.3.799` can be inserted as later dates
(`8.3.799020270101`, `8.3.799020270201`, …) without bumping the patch number.
- Users who want to lock to the `8.3.799` series and receive only those patches
can use the range `<=8.3.799900000000` or `<8.3.8000000000000`.
- `~8.3.799` matches all `8.3.*` versions (broader than the 799 series alone).
The `+git…` suffix is build metadata — it is ignored by npm for version
comparison and range matching. It exists purely for traceability.
## Limitations
- Headless only. There is no display driver, so commands that draw to a
window (`view`, `findbox`, interactive macros) are no-ops.
- Single-threaded. WASM modules are not thread-safe — create one instance
per worker.
## License
[HPND](LICENSE) — Copyright (C) 1985, 1990 Regents of the University of California.
### Bundled test layout
The example layout [`examples/min.mag`](examples/min.mag) is taken from
Magic's own scmos test suite ([`scmos/examples/bipolar/min.mag`](../scmos/examples/bipolar/min.mag))
and is included here as a runnable smoke test for the WASM build. The `scmos`
technology it targets is compiled into the WASM binary, so no external tech
file is shipped.

View File

@ -1,215 +0,0 @@
#!/usr/bin/env bash
# Build Magic WASM and copy artifacts into this npm/ directory.
#
# Usage:
# npm/build.sh [--variant=<tcl|notcl|both>] [--release] [--test] [--pack]
#
# --variant=tcl Build only the TCL-embedded variant → npm/tcl/
# --variant=notcl Build only the plain (no Tcl/Tk) variant → npm/notcl/
# --variant=both Build both (default)
#
# --release Omit debug symbols (-g) and build with -O2.
# --test Run `npm run test` after copying artifacts.
# --pack Run `npm pack` after copying artifacts (and tests, if given).
#
# Requirements (must be on PATH or set via env vars before running):
# emcc / emmake / emconfigure — Emscripten compiler tools
# make, gcc — standard build tools
# node, npm — only required for --test / --pack
#
# Environment:
# EMSDK_DIR Path to an activated emsdk checkout.
# If set, emsdk_env.sh is sourced from there.
# If unset, emcc must already be on PATH (e.g. sourced externally).
# TCL_REF git ref (tag/branch/SHA) of tcltk/tcl to build for the TCL
# variant. Default: main. (CI pins the latest stable tag.)
# TCL_REPO_URL git URL to clone tcltk/tcl from. Default: the upstream repo.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
# The TCL variant builds a static WASM Tcl from a pristine clone of tcltk/tcl.
# Both the clone (tcl/) and the out-of-source build artifacts live entirely
# under build-tcl-wasm/ (gitignored), so nothing outside it is ever touched.
TCL_BUILD_DIR="${TCL_BUILD_DIR:-$REPO_ROOT/build-tcl-wasm}"
TCL_SRC_DIR="$TCL_BUILD_DIR/tcl"
TCL_WASM_PREFIX="$TCL_BUILD_DIR/install"
OPT_RELEASE=0
OPT_TEST=0
OPT_PACK=0
OPT_VARIANT=both
for arg in "$@"; do
case "$arg" in
--release) OPT_RELEASE=1 ;;
--test) OPT_TEST=1 ;;
--pack) OPT_PACK=1 ;;
--variant=tcl) OPT_VARIANT=tcl ;;
--variant=notcl) OPT_VARIANT=notcl ;;
--variant=both) OPT_VARIANT=both ;;
*) echo "Unknown option: $arg" >&2; exit 1 ;;
esac
done
# --- locate emscripten -------------------------------------------------------
if [ -n "${EMSDK_DIR:-}" ]; then
if [ ! -f "$EMSDK_DIR/emsdk_env.sh" ]; then
echo "Error: EMSDK_DIR is set to '$EMSDK_DIR' but emsdk_env.sh was not found there." >&2
exit 1
fi
# shellcheck source=/dev/null
source "$EMSDK_DIR/emsdk_env.sh"
else
if ! command -v emcc &>/dev/null; then
echo "Error: emcc not found on PATH and EMSDK_DIR is not set." >&2
echo " Either source emsdk_env.sh before running this script," >&2
echo " or set EMSDK_DIR to your emsdk checkout directory." >&2
exit 1
fi
fi
echo "Using emcc: $(command -v emcc)"
emcc --version | head -1
# --- portability helpers -----------------------------------------------------
# CPU count: Linux has nproc, macOS has sysctl, fall back to getconf.
ncpu() {
if command -v nproc &>/dev/null; then
nproc
elif [ "$(uname)" = "Darwin" ]; then
sysctl -n hw.ncpu
else
getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1
fi
}
# Portable in-place sed (BSD sed on macOS disagrees with GNU on -i).
# Uses redirect-back instead of mv so the file's mode bits are preserved
# (configure must stay executable across build.sh invocations).
sed_strip_cr() {
local file=$1 tmp
tmp=$(mktemp)
sed 's/\r//' "$file" > "$tmp" && cat "$tmp" > "$file" && rm "$tmp"
}
if [ $OPT_RELEASE -eq 1 ]; then
EXTRA_CFLAGS="-O2"
else
EXTRA_CFLAGS="-g"
fi
# --- TCL fork: clone and prebuild (TCL variant only) ------------------------
# Uses TCL_REPO_URL and TCL_REF from the environment (both have defaults).
# The source is cloned into build-tcl-wasm/tcl on the first run and checked
# out at the requested ref. Because this clone is private to the build dir,
# we manage its HEAD freely — no user-supplied tree is ever mutated.
#
# The actual WASM build runs out-of-source in $TCL_BUILD_DIR, driven by
# toolchains/emscripten/build-tcl-wasm.sh.
ensure_tcl_built() {
: "${TCL_REPO_URL:=https://github.com/tcltk/tcl.git}"
: "${TCL_REF:=main}"
if [ ! -d "$TCL_SRC_DIR/.git" ]; then
echo "=== cloning $TCL_REPO_URL into $TCL_SRC_DIR ==="
mkdir -p "$TCL_BUILD_DIR"
git -c core.autocrlf=false clone "$TCL_REPO_URL" "$TCL_SRC_DIR"
fi
( cd "$TCL_SRC_DIR"
current_sha=$(git rev-parse HEAD 2>/dev/null || echo "")
if [ "$current_sha" != "$TCL_REF" ]; then
git fetch --quiet origin
git checkout --quiet --detach "$TCL_REF"
fi
echo "Using TCL at $(git rev-parse HEAD) ($TCL_REPO_URL)"
)
# Build TCL for WASM if it hasn't been built yet. The presence of
# tclConfig.sh in the install prefix is the canonical "TCL is built" marker.
if [ ! -f "$TCL_WASM_PREFIX/lib/tclConfig.sh" ]; then
echo "=== building TCL for WASM into $TCL_BUILD_DIR (one-time) ==="
bash "$REPO_ROOT/toolchains/emscripten/build-tcl-wasm.sh" \
--src="$TCL_SRC_DIR" --out="$TCL_BUILD_DIR"
fi
}
# --- build a single variant --------------------------------------------------
# Each variant gets a fresh configure run because the two configurations
# select different code paths (MAGIC_WRAPPER on/off, MAGIC_NO_TK, link flags),
# so the object cache from one variant is not compatible with the other.
build_variant() {
local variant=$1
local out_dir="$SCRIPT_DIR/$variant"
echo
echo "==============================================================="
echo "=== building variant: $variant"
echo "==============================================================="
cd "$REPO_ROOT"
# Full clean — distclean removes the generated defs.mak and module objects.
if [ -f defs.mak ]; then
emmake make distclean || true
fi
rm -f defs.mak database/database.h
# Strip Windows CRLF line endings (no-op on Linux-native files).
sed_strip_cr configure
find scripts/ -type f -print0 | while IFS= read -r -d '' f; do sed_strip_cr "$f"; done
if [ "$variant" = "tcl" ]; then
ensure_tcl_built
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 ${EXTRA_CFLAGS}" \
emconfigure ./configure \
--without-cairo --without-opengl --without-x --without-tk \
--with-tcl="$TCL_WASM_PREFIX/lib" \
--with-tclincls="$TCL_WASM_PREFIX/include" \
--with-tcllibs="$TCL_WASM_PREFIX/lib" \
--disable-readline --disable-compression \
--host=asmjs-unknown-emscripten \
--target=asmjs-unknown-emscripten
else
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 ${EXTRA_CFLAGS}" \
emconfigure ./configure \
--without-cairo --without-opengl --without-x \
--without-tk --without-tcl \
--disable-readline --disable-compression \
--host=asmjs-unknown-emscripten \
--target=asmjs-unknown-emscripten
fi
cat toolchains/emscripten/defs.mak >> defs.mak
emmake make depend
emmake make -j"$(ncpu)" modules libs
emmake make techs
emmake make mains
mkdir -p "$out_dir"
cp magic/magic.js "$out_dir/"
cp magic/magic.wasm "$out_dir/"
echo "Copied magic.js + magic.wasm into npm/$variant/"
}
case "$OPT_VARIANT" in
tcl|notcl) build_variant "$OPT_VARIANT" ;;
both) build_variant notcl
build_variant tcl ;;
esac
# --- optional test -----------------------------------------------------------
# Runs the same smoke test that CI runs (see .github/workflows/main-wasm.yml).
# Run in a subshell so the cd does not leak into the --pack step below, which
# relies on the script's working directory being unchanged.
if [ $OPT_TEST -eq 1 ]; then
( cd "$SCRIPT_DIR" && npm run test && npm run test:tcl )
fi
# --- optional pack -----------------------------------------------------------
if [ $OPT_PACK -eq 1 ]; then
"$SCRIPT_DIR/pack.sh"
echo "npm package tarball created in npm/"
fi

Some files were not shown because too many files have changed in this diff Show More