Merge branch 'StefanSchippers:master' into master

This commit is contained in:
Chayan Deb 2025-01-19 15:35:42 +05:30 committed by GitHub
commit eee26c9f3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 167 additions and 66 deletions

View File

@ -642,8 +642,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> copy_hierarchy to from</kbd></li><pre>
Copy hierarchy info from tab/window "from" to tab/window "to"
Example: xschem copy_hierarchy .drw .x1.drw </pre>
<li><kbd> copy_objects [deltax deltay [rot flip]]</kbd></li><pre>
if deltax and deltay (and optionally rot and flip) are given copy selection
<li><kbd> copy_objects [dx dy] [kissing] [stretch]</kbd></li><pre>
if kissing is given add nets to pins that touch other instances or nets
if stretch is given stretch connected nets to follow instace pins
if dx and dy are given copy selection
to specified offset, otherwise start a GUI copy operation </pre>
<li><kbd> count_items string separator quoting_chars</kbd></li><pre>
Debug command </pre>

View File

@ -1347,20 +1347,20 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
return 0;
}
/* del == 0 : delete and draw
* del == 1 : delete
* del == 2 : draw */
void draw_crosshair(int del)
/* what == 0 : delete and draw
* what == 1 : delete
* what == 2 : draw */
void draw_crosshair(int what)
{
int sdw, sdp;
dbg(1, "draw_crosshair(): del=%d\n", del);
dbg(1, "draw_crosshair(): what=%d\n", what);
sdw = xctx->draw_window;
sdp = xctx->draw_pixmap;
if(!xctx->mouse_inside) return;
xctx->draw_pixmap = 0;
xctx->draw_window = 1;
if(del != 2) {
if(what != 2) {
if(fix_broken_tiled_fill || !_unix) {
MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0],
0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw),
@ -1378,7 +1378,7 @@ void draw_crosshair(int del)
xctx->prev_crossx, Y_TO_XSCHEM(xctx->areay2));
}
}
if(del != 1) {
if(what != 1) {
drawline(xctx->crosshair_layer, NOW,X_TO_XSCHEM( xctx->areax1), xctx->mousey_snap,
X_TO_XSCHEM(xctx->areax2), xctx->mousey_snap, 3, NULL);
drawline(xctx->crosshair_layer, NOW, xctx->mousex_snap, Y_TO_XSCHEM(xctx->areay1),
@ -1475,7 +1475,7 @@ static int end_place_move_copy_zoom()
static int check_menu_start_commands(double c_snap)
{
dbg(1, "check_menu_start_commands(): ui_state=%d, ui_state2=%d last_command=%d\n",
dbg(1, "check_menu_start_commands(): ui_state=%x, ui_state2=%x last_command=%d\n",
xctx->ui_state, xctx->ui_state2, xctx->last_command);
if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTWIRECUT)) {
@ -1497,6 +1497,13 @@ static int check_menu_start_commands(double c_snap)
xctx->ui_state &=~MENUSTART;
return 1;
}
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTCOPY)) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
copy_objects(START);
xctx->ui_state &=~MENUSTART;
return 1;
}
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTWIRE)) {
int prev_state = xctx->ui_state;
if(xctx->semaphore >= 2) return 0;
@ -2184,6 +2191,24 @@ static int grabscreen(const char *winpath, int event, int mx, int my, KeySym key
}
#endif
static void snapped_wire(double c_snap)
{
double x, y;
if(!(xctx->ui_state & STARTWIRE)){
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
xctx->mx_double_save = my_round(x / c_snap) * c_snap;
xctx->my_double_save = my_round(y / c_snap) * c_snap;
new_wire(PLACE, x, y);
new_wire(RUBBER, xctx->mousex_snap,xctx->mousey_snap);
}
else {
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
new_wire(RUBBER, x, y);
new_wire(PLACE|END, x, y);
xctx->constr_mv=0;
tcleval("set constr_mv 0" );
}
}
/* main window callback */
/* mx and my are set to the mouse coord. relative to window */
@ -2728,21 +2753,8 @@ int rstate; /* (reduced state, without ShiftMask) */
break;
}
if(key== 'W' /* && !xctx->ui_state */ && rstate == 0) { /* create wire snapping to closest instance pin */
double x, y;
if(xctx->semaphore >= 2) break;
if(!(xctx->ui_state & STARTWIRE)){
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
xctx->mx_double_save = my_round(x / c_snap) * c_snap;
xctx->my_double_save = my_round(y / c_snap) * c_snap;
new_wire(PLACE, x, y);
}
else {
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
new_wire(RUBBER, x, y);
new_wire(PLACE|END, x, y);
xctx->constr_mv=0;
tcleval("set constr_mv 0" );
}
snapped_wire(c_snap);
break;
}
if(key == 'w' /* && !xctx->ui_state */ && rstate==0) /* place wire. */
@ -3625,64 +3637,93 @@ int rstate; /* (reduced state, without ShiftMask) */
}
break;
}
if(key=='m' && rstate==0 && !(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
/* Move selection */
if(key=='m' && rstate==0 && !(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
if(tclgetboolvar("enable_stretch"))
select_attached_nets(); /* stretch nets that land on selected instance pins */
move_objects(START,0,0,0);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
move_objects(START,0,0,0);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTMOVE;
}
break;
}
/* Move selection adding wires to moved pins */
if(((key == 'M' && rstate == 0) || (key == 'm' && EQUAL_MODMASK)) &&
!(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */
/* select_attached_nets(); */ /* stretch nets that land on selected instance pins */
move_objects(START,0,0,0);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
/* select_attached_nets(); */ /* stretch nets that land on selected instance pins */
move_objects(START,0,0,0);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTMOVE;
}
break;
}
/* move selection stretching attached nets */
if(key=='m' && rstate == ControlMask &&
!(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
if(!tclgetboolvar("enable_stretch"))
select_attached_nets(); /* stretch nets that land on selected instance pins */
move_objects(START,0,0,0);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
move_objects(START,0,0,0);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTMOVE;
}
break;
}
}
/* move selection, stretch attached nets, create new wires on pin-to-moved-pin connections */
if(key=='M' && state == (ControlMask | ShiftMask) &&
!(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
if(!tclgetboolvar("enable_stretch"))
select_attached_nets(); /* stretch nets that land on selected instance pins */
xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */
move_objects(START,0,0,0);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
move_objects(START,0,0,0);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTMOVE;
}
break;
}
if(key=='c' && EQUAL_MODMASK && /* duplicate selection */
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
if(xctx->semaphore >= 2) break;
xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
copy_objects(START);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
copy_objects(START);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTCOPY;
}
break;
}
@ -3690,9 +3731,14 @@ int rstate; /* (reduced state, without ShiftMask) */
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
if(xctx->semaphore >= 2) break;
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
copy_objects(START);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
copy_objects(START);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTCOPY;
}
break;
}
if(key=='n' && rstate == ControlMask) /* clear schematic */
@ -4000,6 +4046,11 @@ int rstate; /* (reduced state, without ShiftMask) */
/* Mouse wheel events */
else if(handle_mouse_wheel(event, mx, my, key, button, aux, state)) break;
/* terminate wire placement in snap mode */
else if(button==Button1 && (state & ShiftMask) && (xctx->ui_state & STARTWIRE) ) {
snapped_wire(c_snap);
}
/* Alt - Button1 click to unselect */
else if(button==Button1 && (SET_MODMASK) ) {
xctx->last_command = 0;
@ -4039,7 +4090,7 @@ int rstate; /* (reduced state, without ShiftMask) */
if(xctx->last_command == STARTWIRE) start_wire(xctx->mousex_snap, xctx->mousey_snap);
break;
}
/* handle all object insertions started from Tools menu */
/* handle all object insertions started from Tools/Edit menu */
if(check_menu_start_commands(c_snap)) break;
/* complete the STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */
if(end_place_move_copy_zoom()) break;

View File

@ -683,29 +683,37 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
}
/* copy_objects [deltax deltay [rot flip]]
* if deltax and deltay (and optionally rot and flip) are given copy selection
/* copy_objects [dx dy] [kissing] [stretch]
* if kissing is given add nets to pins that touch other instances or nets
* if stretch is given stretch connected nets to follow instace pins
* if dx and dy are given copy selection
* to specified offset, otherwise start a GUI copy operation */
else if(!strcmp(argv[1], "copy_objects"))
{
int nparam = 0;
int kissing= 0;
int stretch = 0;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 3) {
if(argc > 2) {
int i;
for(i = 2; i < argc; i++) {
if(!strcmp(argv[i], "kissing")) {kissing = 1; nparam++;}
if(!strcmp(argv[i], "stretch")) {stretch = 1; nparam++;}
}
}
if(stretch) select_attached_nets();
if(kissing) xctx->connect_by_kissing = 2;
if(argc > 3 + nparam) {
copy_objects(START);
xctx->deltax = atof(argv[2]);
xctx->deltay = atof(argv[3]);
if(argc > 4) {
xctx->move_rot = (short int)atoi(argv[4]);
}
if(argc > 5) {
xctx->move_flip = (short int)atoi(argv[5]);
}
copy_objects(END);
} else {
copy_objects(START);
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTCOPY;
}
Tcl_ResetResult(interp);
}
/* count_items string separator quoting_chars
Debug command */
else if(!strcmp(argv[1], "count_items"))

View File

@ -3633,6 +3633,7 @@ static char *get_pin_attr(const char *token, int inst, int engineering)
const char *str_ptr=NULL;
int multip;
size_t tmp;
prepare_netlist_structs(0);
str_ptr = net_name(inst,n, &multip, 0, 1);
tmp = strlen(str_ptr) +100 ; /* always make room for some extra chars
* so 1-char writes to result do not need reallocs */
@ -4295,13 +4296,14 @@ const char *translate(int inst, const char* s)
if(!error) {
char *iprefix = modelparam == 0 ? "i(" : modelparam == 1 ? "" : "v(";
char *ipostfix = modelparam == 1 ? "" : ")";
int prefix;
my_strdup2(_ALLOC_ID_, &dev, instname);
strtolower(dev);
prefix=dev[0];
len = strlen(path) + strlen(dev) + 40; /* some extra chars for i(..) wrapper */
dbg(1, "token=%s, dev=%s param=%s\n", token, dev, param ? param : "<NULL>");
fqdev = my_malloc(_ALLOC_ID_, len);
if(!sim_is_xyce) {
int prefix=dev[0];
int vsource = (prefix == 'v') || (prefix == 'e');
if(path[0]) {
if(vsource) {
@ -4340,6 +4342,21 @@ const char *translate(int inst, const char* s)
if(idx >= 0) {
val = xctx->raw->cursor_b_val[idx];
}
/* special handling for resistors that are converted to b sources:
* i(@r.x4.r1[i]) --> i(@b.x4.br1[i])
*/
if(idx < 0 && !strncmp(fqdev, "i(@r", 4)) {
if(path[0]) {
my_snprintf(fqdev, len, "i(@b.%sb%s[i])", path, dev);
} else {
my_snprintf(fqdev, len, "i(@b%s[i])", dev);
}
dbg(1, "fqdev=%s\n", fqdev);
idx = get_raw_index(fqdev, NULL);
if(idx >= 0) {
val = xctx->raw->cursor_b_val[idx];
}
}
if(idx < 0) {
valstr = "-";
xctx->tok_size = 1;

View File

@ -249,6 +249,7 @@ extern char win_temp_dir[PATH_MAX];
#define MENUSTARTMOVE 256U
#define MENUSTARTWIRECUT 512U
#define MENUSTARTWIRECUT2 1024U /* do not align cut point to snap */
#define MENUSTARTCOPY 2048U
#define WIRE 1 /* types of defined objects */
#define xRECT 2
@ -1394,7 +1395,7 @@ extern int select_dangling_nets(void);
extern void tclmainloop(void);
extern int Tcl_AppInit(Tcl_Interp *interp);
extern void abort_operation(void);
extern void draw_crosshair(int del);
extern void draw_crosshair(int what);
extern void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr);
extern int callback(const char *winpath, int event, int mx, int my, KeySym key,
int button, int aux, int state);

View File

@ -34,9 +34,9 @@ L 4 -15 -25 -15 -15 {}
B 5 -2.5 -32.5 2.5 -27.5 {name=p dir=inout}
B 5 -2.5 27.5 2.5 32.5 {name=m dir=inout}
A 4 0 0 15 270 360 {}
T {@name} 20 -17.5 0 0 0.2 0.2 {}
T {@VAR
@FUNC} 20 0 0 0 0.2 0.2 {}
T {@#0:net_name} 5 -42.5 0 0 0.15 0.15 {layer=15 hide=instance}
T {@#1:net_name} 5 32.5 0 0 0.15 0.15 {layer=15 hide=instance}
T {@spice_get_current} -12.5 7.5 0 1 0.2 0.2 {layer=17}
T {@name} 20 -27.5 0 0 0.2 0.2 {}
T {@VAR = @FUNC
m=@m} 20 -10 0 0 0.2 0.2 {}

View File

@ -0,0 +1,22 @@
v {xschem version=3.4.6 file_version=1.2}
G {}
K {type=stop
format="
.control
stop when time @timecond when @@node @nodecond
.endc"
template="name=s1 timecond=\\"> 1u\\" nodecond=\\"< 3\\""}
V {}
S {}
E {}
L 4 -80 0 -60 0 {}
L 4 -60 -20 -60 20 {}
L 4 -60 -20 60 -20 {}
L 4 60 -20 60 20 {}
L 4 -60 20 60 20 {}
B 5 -82.5 -2.5 -77.5 2.5 {name=node
dir=in}
T {STOP} -60 -35 0 0 0.2 0.2 {}
T {@@node @nodecond} -57.5 -15 0 0 0.2 0.2 {}
T {time @timecond} -47.5 5 0 0 0.2 0.2 {}
T {@name} 60 -35 0 1 0.2 0.2 {}