this had two issues: (1) "getcell" was not being called with
"child 0 0", leading to child cells that are not placed where
expected in relation to a grid snap setting; and (2) "cursor"
was assuming internal units and needed that to be explicitly
stated using "cursor internal".
Add explicit length limit to sscanf in TclmagicRegisterCommands: %92s
instead of %s prevents a potential stack overwrite if a command name
were ever longer than the buffer. Matches the available space (keyword[100]
minus the 7-byte "magic::" prefix minus null).
Extend the CI output-display step to also iterate over output-tcl/ so
that TCL-variant test regressions are visible in the job log without
downloading artifacts.
tclmagic.c: remove stray /*-----*/ line left over from a previous edit
that left a duplicate comment opener before TclmagicRegisterCommands.
magicWasm.c: move TxSetPoint inside the #else (non-TCL) branch of
magic_wasm_source_file and restore its explanation comment. TxSetPoint
routes TxDispatch commands to the layout window; it is irrelevant and
misleading in the Tcl_EvalFile path.
magic/Makefile: guard the TCL linker flags in the magic.js link rule
with ifneq (${TCL_LIB_DIR},). When building the non-TCL WASM variant
TCL_LIB_DIR is empty, so the unconditional -L${TCL_LIB_DIR} -ltclstub
expanded to a bare -L flag and a missing library, breaking the notcl
build.
Rename *-magic.tcl scripts to *-tcl.tcl to match the -tcl.js test naming
convention. Delete the old bare-command pcell.tcl (used cellname create,
no magic:: prefix) and promote pcell-magic.tcl to pcell.tcl.
Fix misleading comment in magicWasm.c: Tclmagic_Init only bootstraps the
interpreter; magic:: commands are registered separately by
TclmagicRegisterCommands after magicMainInit. Align comment block
dashes in TclmagicRegisterCommands to match tclmagic.c style (62 dashes).
Replace intubun/tcl references in build scripts and CI with tcltk/tcl to
match the actual pinned repo in npm/tcl.ref. Also run both test suites
when build.sh is invoked with --test.
magic_wasm_init() called Tclmagic_Init() and magicMainInit() but never
ran the command-registration loop in _magic_initialize(), so magic::tech,
magic::load, magic::gds and all other Magic commands were missing from
the Tcl interpreter.
Add TclmagicRegisterCommands() in tclmagic.c containing the
WindNextClient/WindGetCommandTable loop and call it from magic_wasm_init()
after magicMainInit() succeeds.
Also change magic_wasm_source_file() to use Tcl_EvalFile in MAGIC_WRAPPER
mode so scripts with magic:: commands are evaluated through the Tcl
interpreter instead of the plain text dispatcher.
Bump VERSION to 8.3.645.
magic.wasm can now be built as two variants packaged in the same npm
release: notcl/ (legacy, magic's own parser) and tcl/ (intubun/tcl 9.x
statically linked, commands evaluated by Tcl_EvalEx). The TCL fork is
pinned via npm/tcl.ref and cloned/built by magic itself — the tcl/
checkout is treated as read-only and built out-of-source into
magic/build-tcl-wasm/.
Configure layer:
- New usingTk variable decoupled from usingTcl in scripts/configure.in
+ scripts/configure, so --with-tcl --without-tk is finally a valid
combination. Native Linux Tcl+Tk builds keep their previous behaviour
(both flags default to enabled).
- When usingTk is empty, configure passes -DMAGIC_NO_TK so the small
number of remaining Tk callsites in tcltk/tclmagic.{h,c} compile out,
and TKCOMMON_SRCS / USE_TK_STUBS are omitted from the link.
WASM build orchestration:
- toolchains/emscripten/build-tcl-wasm.sh builds libtcl9.x.a + libtclstub.a
+ tclConfig.sh out-of-source from a pristine intubun/tcl checkout.
- npm/build.sh grew a --variant=<tcl|notcl|both> flag and writes its
outputs into npm/tcl/ and npm/notcl/. It also clones intubun/tcl with
autocrlf=false at the SHA pinned by npm/tcl.ref.
- magic/Makefile (WASM block only): magicWasm.o is now compiled with
DFLAGS_NOSTUB so Tcl_CreateInterp resolves to libtcl9.x directly
before tclStubsPtr is set. magic.js link pulls in LIB_SPECS_NOSTUB
and -ltclstub. After rules.mak include, magic: is a phony alias for
magic.js so the generic ${MODULE} recipe doesn't fight it.
- toolchains/emscripten/defs.mak: add -sUSE_ZLIB=1 (libtcl9 references
zlib), replace -sSTACK_SIZE=N with -Wl,-z,stack-size=N (emcc >=5
rejects the setting form).
- magic/magicWasm.c bootstraps the embedded interp under MAGIC_WRAPPER
(Tcl_CreateInterp -> Tcl_Init -> Tclmagic_Init) and routes
run_command through Tcl_EvalEx.
- magic/magicTop.c: gate MagicVersion/Revision/CompileTime on
!MAGIC_WRAPPER so they don't collide with the copies in
tcltk/tclmagic.c when both objects land in the same wasm binary.
npm package:
- Subpath exports: ".", "./tcl", "./notcl". Default import keeps the
pre-existing non-TCL behaviour for backward compatibility.
- examples/smoke-tcl.mjs exercises the TCL variant.
CI:
- main-wasm.yml clones intubun/tcl at the pinned ref, builds both
variants via npm/build.sh --variant=both, runs the existing notcl
test suite and the new TCL smoke test, and publishes only on a
v<x.y.z>... git tag. Tag name (minus the leading v) becomes the
npm version.
This file exists in the magic directory, and is the one the build system uses, this file is a duplicate that has one different line "/ms { rectfill } bind def", and is not used anywhere
Keeping two duplicate files causes issues like them being out of sync, therefore it would be great if it was deleted
See github issue tracker issue #490. There were two cases: When
running without the Tk console, a NULL value was being passed to a
string comparison. When running with the Tk console, two variables
were not initialized. Both prolems have been fixed.
There is a bug where left-clicking a hidden layer in the toolbar successfully makes the layer visible in the layout but fails to update the toolbar icon to the "active" state.
The root cause is a positional argument mismatch in magic::toolupdate. When the Magic C-core issues a callback for a "see" command with two arguments, the third argument (layerlist) is passed as an empty string ("") rather than being omitted. This prevents the Tcl procedure from falling back to its hardcoded default of "none", causing the script to skip the logic that reassigns $yesno to "yes".
This patch changes the default value of $layerlist to "" and updates the conditional check to ensure the state and layer name are correctly reassigned regardless of how the C-core signals the update.
Added logic to ensure all cells are loaded into memory to prevent corruption when saving files. This is a fix for a minor edge case when generating "netlist_to_spice" for a file that already has a netlist, and which contains cells containing other cells. Followed by "writeall force". This causes unloaded files (that are still referenced) to be loaded during save with "ignoreTech" being true, and thus disregarding the scale, corrupting all coordinates if a scale is used.
This was caused by skipping regenerating cells that already had a .mag file
"magic::add_dependency" procedure. The "check" function should always
be called first, followed by the dependencies. Because otherwise, if
an incorrect value is entered for a device parameter, then it gets
used to calculate dependent values *before* it gets corrected by the
"check" procedure, resulting in an incorrect value being displayed
for the dependent value, even after the bad entry has been corrected.
"tool" command was changed to be overridden by a Tcl command. Due
to macro clients being registered with the tool name instead of
just "layout", the "macro" command with no arguments or with a
window client argument was just broken. In the process of fixing
this, I realized that there was a conflict between the use of
"netlist" as a window name and also as the name of a tool, so I
changed the tool name to "nettool", a change which should be
transparent to the end user. Otherwise, "macro netlist" returns
the key bindings for the window, and the only way to get the key
bindings for the tool is to make the tool active and then use
"macro" without arguments. One remaining issue is that there is
no syntax error that will cause the list of valid windows and
tools to be printed. Probably "macro help" should print usage
information instead of acting like "macro" with no arguments.
The main changes are:
(1) Changed the hash function used to generate the 6-character
suffix for generated device cell names. The original hash
function is not good for ensuring unique names, and can
cause cell name collisions (two different parameter sets
having the same cell name). The chance of name collisions
should now be diminishingly small.
(2) Modified the string passed to the hash:
(A) Ordered the parameter names alphabetically, since iterating
through dictionary keys is not guaranteed to be in any
specific order, leading to different strings for the same
parameter set
(B) Normalized numerical parameters, so that "2", "2.0", "2e0"
are all hashed the same, again to avoid having multiple
cell names for the same set of parameters.
(3) Fixed a problem in which when changing parameters for a cell
instance, the instance would become unselected and the instance
name would be lost and revert to magic's auto-generated name.
(4) Fixed the annoyance of having a pop-up dialog whenever magic
decides that a parameterized cell name is not being used anywhere,
and it can safely delete the cell.
(5) Fixed an issue where the check for whether a cell can be deleted
is not run consistently.
The result is, I hope, a much more pleasant experience with generated
cells.
(1) There was still one place that dimensional units were not being
printed, which was "setlabel", with both "setlabel size" and
"setlabel offset". This has been fixed.
(2) Fixing (1) surfaced an error in the text helper dialog, which was
not setting units properly when checking the size and offset entries.
(3) Fixed a very long-standing problem in which port labels were showing
up with the "pale" style of a subcell's label being drawn on top
when the parent and child had the same label in exactly the same
position. This was due to a parent-first search resulting in the
child cell being visited last, so its "pale" style label being drawn
last. Added a flag for label searches for display to reverse the
search order, visiting children first and then the parent, so that
the top cell's labels are the last to be drawn.
the issue of a device name in a netlist having different case than
the procedures defined for the device in the PDK. The difference
in case is transparent to SPICE, so it should also be transparent
to the PDK.
allow ideal devices in an input netlist to be mapped to
automatically generated cells. This works if the PDK toolkit
defines a device called either "capacitor" or "resistor". The
device must be defined such that it can determine sane parameters
for the drawn device from only a value given in the netlist
(capacitance in farads, or resistance in ohms).
actually works, and also can be called multiple times. The chaining
of commands and bindings had earlier been done for one of the widget
types (selection) but not the others (entry or checkbox).
otherwise, the existing code would produce results that vary
by units, with potentially incorrect label sizes and spacing
between instances when generating layout devices and subcells
from a netlist.
to force internal units to be used; this usage is now deprecated
and needed to be changed to the "units" command. Also: Fixed a
separate issue with getting both "view bbox" and "view get" to
return values in the currently selected units. Also: Fixed an
issue with "property" when setting a property to a list passed as
a single value (e.g., "property FIXED_BBOX [box values]"), which
needed to null the string after each value.
converted to the new PropertyRecord type. Since this was in the
CIFPropRecordPath() subroutine, which has always been problematic
and generally useless, I took the opportunity to make that function
dependent on an option set by "gds savepaths true", with the option
set to "false" by default, so "path" properties will no longer be
created from GDS input unless the option is manually set to "true".
Also: Found that the returned boolean from "box exists" is
sometimes getting overwritten with a NULL result, causing a spurious
Tcl error messages to pop up. I could not find where this
overwriting happens (probably in a tag callback), so I just took the
hack approach of converting a NULL result to "false", which is always
safe to do.
(Ctrl key + left mouse button) will start a wire at the current
cursor position with the wire values set by "wire type" and
reported by "wire values". So "wire type metal1 0.28um" will
always start a 0.28um wide wire of metal1 regardless of what is
present at the cursor location.
and area) so that they are consistent across commands. The default
behavior remains the same, for backwards compatibility. However, a
new "units" command has been added, so that "units microns" results
in measurements always being displayed in microns, with choice of
that or "internal", "lambda", or "grid". The units themselves may
be printed (for interactive use) or not (for scripted use). The
use of "units" is independent of "snap", after overriding the
default behavior, so that units parsed on the command line are
interpreted according to "units", not to "snap".
the dialog (and run limit checks) is installed by default on
checkboxes and selection menus, as it is already done for entry
boxes. Otherwise it is possible to make a selection (like changing
a device type) that invalidates the existing values, but if Apply
is hit immediately afterward, then no checks will be run and the
values may be used as-is even if invalid. This does not prohibit
the use of "add_dependency" to change the callback behavior.
the "tool" implementation. Previously, the "tool" implementation
would overwrite the button bindings for the mouse. The problem
with that is that if the user customizes one or more of the
bindings, such as using the mouse wheel for zooming instead of
panning, then the custom macro gets obliterated when the tool
changes. The reimplementation creates multiple macro sets which
are unique to each tool. The "enable_tools" function sets up
the initial unique default bindings for each tool. The user
can then customize the bindings for any tool, and the
implementation no longer requires the constant changing of key
bindings. Note that the new implementation is slightly less
efficient because the macro tables are found by string hash
based on the name of the tool or client type, not the integer
client ID. The reduction in efficiency is balanced by the
increased flexibility of the macros.
"replace" as the 2nd argument. This allows a simpler 'tag add
<command> <value>' than the existing awkward 'tag <command>
"[tag <command>]; <value>'. Using "add" also helps avoid
mistakes like one that was in the code for a long time which
overwrites one of the helper window callbacks. With this done,
added some additional callbacks to the "library manager" to
update when a new file is created by "select save" or "writeall".
Also added "Refresh" buttons to these windows, just in case.
Implemented a zoom function on the mouse scroll wheel when the
Control key is pressed. This is a stop-gap for a problem with
overriding button bindings that re-establish themselves when the
tool (box, wiring, etc.) changes. That needs to have a more
comprehensive solution (such as tool-specific bindings).
API docs indicate the original usage seems ok.
Calling Tcl_GetIndexFromObj() is allowed with a refcount == 0.
But in actual usage it leaks the Tcl_NewStringObj() memory across the
Tcl_EvalObjv() call like the object accounting system doesn't work on
that anymore (because the use of Tcl_EvalObjv() disrupted things).
Looking at the code nearby it increments refs (for all recently created
objs) and decrements around Tcl_EvalEx() for the actual data the 'eval'
needs pinned and is working on.
If we just repeat this same pattern but with 'objv0' the memory leak is
gone. The decrement must wake it up / make it remember what to do.
So this required covering all the exit paths to decrement as well.
This seems like it has 2 use cases.
Internal console management around reprinting command prompt, but many
modes of operation delegate the prompt processing to tkcon or readline.
Process termination to restore the termios.