From df4ec3ab32a0cc0dc7b370e956d77a21a5c1e356 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Wed, 6 May 2026 10:21:35 -0400 Subject: [PATCH 1/5] Corrects an error that can cause "extresist" to segfault. This is due to moving away from using the node "location" in favor of a drivepoint specified by a port or other connection point. The "location" record can end up at the default value of "infinity", and should not be used to set the area for searches. This fix is in response to issue #502 on the github issue tracker, submitted by Julian Schwarz. --- VERSION | 2 +- resis/ResMain.c | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index ee16f1e6..d15f068e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.638 +8.3.639 diff --git a/resis/ResMain.c b/resis/ResMain.c index 96719df6..6b8af42f 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -1054,11 +1054,24 @@ ResExtractNet(node, resisdata, cellname) /* Copy Paint */ - scx.scx_area.r_ll.p_x = node->location.p_x - 2; - scx.scx_area.r_ll.p_y = node->location.p_y - 2; - scx.scx_area.r_ur.p_x = node->location.p_x + 2; - scx.scx_area.r_ur.p_y = node->location.p_y + 2; - startpoint = node->location; + /* If the node location is INFINITY, then use the rs_bbox */ + + if ((node->location.p_x == INFINITY) || (node->location.p_y == INFINITY)) + { + scx.scx_area.r_ll.p_x = node->rs_bbox.r_xbot; + scx.scx_area.r_ll.p_y = node->rs_bbox.r_ybot; + scx.scx_area.r_ur.p_x = node->rs_bbox.r_xtop; + scx.scx_area.r_ur.p_y = node->rs_bbox.r_ytop; + startpoint = node->drivepoint; + } + else + { + scx.scx_area.r_ll.p_x = node->location.p_x - 2; + scx.scx_area.r_ll.p_y = node->location.p_y - 2; + scx.scx_area.r_ur.p_x = node->location.p_x + 2; + scx.scx_area.r_ur.p_y = node->location.p_y + 2; + startpoint = node->location; + } /* Because node->type might come from a label with a sticky type * that does not correspond exactly to the layer underneath, include From 97fd047aabf5fe9e7151aa9d63009a3853e743db Mon Sep 17 00:00:00 2001 From: Ahmed Nematallah Date: Fri, 1 May 2026 22:54:33 +0200 Subject: [PATCH 2/5] Implement existing cell check for layout generation Added logic to check if subcircuits are already loaded and generate layouts accordingly. --- tcltk/toolkit.tcl | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index 5d3f06ad..346f93aa 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -525,11 +525,25 @@ proc magic::netlist_to_layout {netfile library} { # Pre-generate placeholders for all subcircuits. set curtop [cellname list self] + array set existing_cells {} foreach subckt $allsubs { - # Diagnostic output - puts stdout "Pre-generating subcircuit $subckt placeholder" - load $subckt -silent + if {$subckt == $curtop || $subckt == $topname} { + set existing_cells($subckt) "false" + load $subckt -silent + continue + } + + if {[catch {load $subckt -fail -silent}] == 0} { + puts stdout "Subcircuit $subckt successfully loaded." + set existing_cells($subckt) "true" + } else { + puts stdout "Subcircuit $subckt not found. Will generate." + set existing_cells($subckt) "false" + # Now we load it normally to create the placeholder for the generator + load $subckt -silent + } } + load $curtop # Parse the file and process all lines @@ -561,7 +575,14 @@ proc magic::netlist_to_layout {netfile library} { } else { if {[regexp -nocase {^[ \t]*\.ends} $line]} { set insub false - magic::generate_layout_add $subname $subpins $complist $library + + if {[info exists existing_cells($subname)] && $existing_cells($subname) == "false"} { + puts stdout "Cell $subname is empty. Generating initial layout..." + magic::generate_layout_add $subname $subpins $complist $library + } else { + puts stdout "Cell $subname already contains layout. Skipping generation." + } + set subname "" set subpins "" set complist {} From 900f6d7b0faefa9899d5a72c4667a101416c7437 Mon Sep 17 00:00:00 2001 From: Ahmed Nematallah Date: Sun, 3 May 2026 05:12:21 +0200 Subject: [PATCH 3/5] Ensure all cells are loaded into memory in netlist_to_spice to avoid file corruption during save 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 --- tcltk/toolkit.tcl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index 346f93aa..77442a3f 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -536,6 +536,12 @@ proc magic::netlist_to_layout {netfile library} { if {[catch {load $subckt -fail -silent}] == 0} { puts stdout "Subcircuit $subckt successfully loaded." set existing_cells($subckt) "true" + + # Make sure to load all cells into memory to avoid + # corruption when saving all files (files get loaded + # without taking the scale into account) + select top cell + expand } else { puts stdout "Subcircuit $subckt not found. Will generate." set existing_cells($subckt) "false" From c3ee33e9a1cbd19b6a9a80db93b13c3170f20cd3 Mon Sep 17 00:00:00 2001 From: Ahmed Nematallah Date: Sat, 2 May 2026 18:09:18 +0200 Subject: [PATCH 4/5] tcl/tk: Fix layer toolbar icon synchronization on left-click 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. --- tcltk/wrapper.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index d3e30318..1cae6d5b 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -706,7 +706,7 @@ proc magic::cursorview {win} { *bypass logcommands resume } -proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} { +proc magic::toolupdate {win {yesno "yes"} {layerlist ""}} { global Winopts if {[magic::display] == "NULL"} {return} @@ -728,7 +728,7 @@ proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} { # Don't do anything if toolbar is not present if { $Winopts(${topname},toolbar) == 0 } { return } - if {$layerlist == "none"} { + if {$layerlist == ""} { set layerlist $yesno set yesno "yes" } From fa80458d800d2059844e4095a882cd4358e7fc5c Mon Sep 17 00:00:00 2001 From: Ahmed Nematallah Date: Sat, 2 May 2026 22:50:25 +0200 Subject: [PATCH 5/5] Ensure layer name compatibility in wrapper.tcl Added check for 'none' layer name to ensure backwards compatibility. --- tcltk/wrapper.tcl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 1cae6d5b..7ee3ec98 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -728,7 +728,9 @@ proc magic::toolupdate {win {yesno "yes"} {layerlist ""}} { # Don't do anything if toolbar is not present if { $Winopts(${topname},toolbar) == 0 } { return } - if {$layerlist == ""} { + # To ensure backwards compatibility, we check if the + # layer is called none, so avoid naming a layer none. + if {$layerlist == "" || $layerlist == "none"} { set layerlist $yesno set yesno "yes" }