From 6a4131699a4a37c95b771dc5342d220fdd45d62a Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Fri, 12 Apr 2024 00:06:36 +0200 Subject: [PATCH] improve `xschem add_symbol_pin` command, add create_symbol.tcl procedure --- src/Makefile.in | 1 + src/callback.c | 2 ++ src/create_symbol.tcl | 61 +++++++++++++++++++++++++++++++++++++++++++ src/move.c | 2 +- src/scheduler.c | 22 +++++++++++++--- 5 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 src/create_symbol.tcl diff --git a/src/Makefile.in b/src/Makefile.in index 28e66b22..1668c2ba 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -17,6 +17,7 @@ put /local/install_shares { add_custom_button.tcl change_index.tcl icon.xpm resources.tcl xschemrc ngspice_backannotate.tcl gschemtoxschem.awk traversal.tcl mouse_bindings.tcl place_sym_pins.tcl place_pins.tcl make_sch_from_spice.awk make_sym_from_spice.awk + create_symbol.tcl } # generate a list of objects from the list of source files diff --git a/src/callback.c b/src/callback.c index 3096635d..05119844 100644 --- a/src/callback.c +++ b/src/callback.c @@ -1820,6 +1820,7 @@ static int grabscreen(const char *winpath, int event, int mx, int my, KeySym key INT_RECTORDER(x1, y1, x2, y2); tclvareval("grab release ", xctx->top_path, ".drw", NULL); if(x2 - x1 > 10 && y2 -y1 > 10) { + xctx->push_undo(); grab_w = (x2 - x1 + 1); grab_h = (y2 - y1 + 1); dbg(1, "grabscreen(): grab area: %d %d - %d %d\n", x1, y1, x2, y2); @@ -2455,6 +2456,7 @@ int rstate; /* (reduced state, without ShiftMask) */ } if(key=='p' && EQUAL_MODMASK) /* add symbol pin */ { + xctx->push_undo(); unselect_all(1); storeobject(-1, xctx->mousex_snap-2.5, xctx->mousey_snap-2.5, xctx->mousex_snap+2.5, xctx->mousey_snap+2.5, xRECT, PINLAYER, SELECTED, "name=XXX\ndir=inout"); diff --git a/src/create_symbol.tcl b/src/create_symbol.tcl new file mode 100644 index 00000000..2668ea2c --- /dev/null +++ b/src/create_symbol.tcl @@ -0,0 +1,61 @@ +# +# File: create_symbol.tcl +# +# This file is part of XSCHEM, +# a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit +# simulation. +# Copyright (C) 1998-2023 Stefan Frederik Schippers +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Create an xschem symbol from a list of in, inout, out pins. +# Example: +# create_symbol test.sym {CLK RST D} {Q QB} {VCC VSS} +# +proc create_symbol {name {in {}} {out {}} {inout {}}} { + set symname [file rootname $name].sym + set res [catch {open $symname {WRONLY CREAT EXCL}} fd] + if {$res} {puts $fd; return 0} ;# Error. Print reason and exit. + puts $fd {v {xschem version=3.4.5 file_version=1.2}} + puts $fd {K {type=subcircuit format="@name @pinlist @symname" template="name=X1"}} + set x -150 + set y 0 + foreach pin $in { ;# create all input pins on the left + puts $fd "B 5 [expr {$x - 2.5}] [expr {$y - 2.5}] [expr {$x + 2.5}] [expr {$y + 2.5}] {name=$pin dir=in}" + puts $fd "T {$pin} [expr {$x + 25}] [expr {$y - 4}] 0 0 0.2 0.2 {}" + puts $fd "L 4 $x $y [expr {$x + 20}] $y {}" + incr y 20 + } + set x 150 + set y 0 + foreach pin $out { ;# create all out pins on the top right + puts $fd "B 5 [expr {$x - 2.5}] [expr {$y - 2.5}] [expr {$x + 2.5}] [expr {$y + 2.5}] {name=$pin dir=out}" + puts $fd "T {$pin} [expr {$x - 25}] [expr {$y - 4}] 0 1 0.2 0.2 {}" + puts $fd "L 4 [expr {$x - 20}] $y $x $y {}" + incr y 20 + } + foreach pin $inout { ;# create all inout pins on the bottom right + puts $fd "B 5 [expr {$x - 2.5}] [expr {$y - 2.5}] [expr {$x + 2.5}] [expr {$y + 2.5}] {name=$pin dir=inout}" + puts $fd "T {$pin} [expr {$x - 25}] [expr {$y - 4}] 0 1 0.2 0.2 {}" + puts $fd "L 7 [expr {$x - 20}] $y $x $y {}" + incr y 20 + } + puts $fd "B 4 -130 -10 130 [expr {$y - 10}] {fill=0}" ;# symbol box + puts $fd "T {@symname} 0 [expr {($y - 20) / 2}] 0 0 0.3 0.3 {hcenter=1 vcenter=1}" ;#symbol name + puts $fd "T {@name} 130 -10 2 1 0.2 0.2 {}" ;# instance name + close $fd + puts "Created symbol ${symname}" + return 1 +} diff --git a/src/move.c b/src/move.c index d21af1ba..f919d051 100644 --- a/src/move.c +++ b/src/move.c @@ -990,7 +990,7 @@ void move_objects(int what, int merge, double dx, double dy) /* no undo push for MERGE ad PLACE, already done before */ if(!xctx->kissing && - !(xctx->ui_state & (STARTMERGE | PLACE_SYMBOL | PLACE_TEXT)) ) { + !(xctx->ui_state & (START_SYMPIN | STARTMERGE | PLACE_SYMBOL | PLACE_TEXT)) ) { dbg(1, "move_objects(END): push undo state\n"); xctx->push_undo(); } diff --git a/src/scheduler.c b/src/scheduler.c index cb854ee6..417aed44 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -175,25 +175,42 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg * if no parameters given start a GUI placement of a symbol pin */ else if(!strcmp(argv[1], "add_symbol_pin")) { - int save, draw = 1; + int save, draw = 1, linecol = SYMLAYER; double x = xctx->mousex_snap; double y = xctx->mousey_snap; const char *name = NULL; const char *dir = NULL; if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} + xctx->push_undo(); if(argc > 6) draw = atoi(argv[6]); if(argc > 5) { char *prop = NULL; + int flip = 0; x = atof(argv[2]); y = atof(argv[3]); name = argv[4]; dir = argv[5]; + if(!strcmp(dir, "inout") || !strcmp(dir, "out") ) flip = 1; + if(!strcmp(dir, "inout")) linecol = 7; my_mstrcat(_ALLOC_ID_, &prop, "name=", name, " dir=", dir, NULL); storeobject(-1, x - 2.5, y - 2.5, x + 2.5, y + 2.5, xRECT, PINLAYER, 0, prop); + if(flip) { + create_text(draw, x - 25, y - 5, 0, 1, name, NULL, 0.2, 0.2); + storeobject(-1, x - 20, y, x, y, LINE, linecol, 0, NULL); + } else { + create_text(draw, x + 25, y - 5, 0, 0, name, NULL, 0.2, 0.2); + storeobject(-1, x, y, x + 20, y, LINE, linecol, 0, NULL); + } + if(draw) { save = xctx->draw_window; xctx->draw_window = 1; - drawrect(PINLAYER,NOW, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 0, -1, -1); + drawrect(PINLAYER, NOW, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 0, -1, -1); filledrect(PINLAYER,NOW, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 1, -1, -1); + if(flip) { + drawline(linecol, NOW, x -20, y, x, y, 0, NULL); + } else { + drawline(linecol, NOW, x, y, x + 20, y, 0, NULL); + } xctx->draw_window = save; } my_free(_ALLOC_ID_, &prop); @@ -204,7 +221,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg rebuild_selected_array(); move_objects(START,0,0,0); xctx->ui_state |= START_SYMPIN; - set_modify(1); } Tcl_ResetResult(interp); }