diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index 3f3d14a7..d7287a29 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -642,8 +642,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
  • copy_hierarchy to from
  •     Copy hierarchy info from tab/window "from" to tab/window "to"
        Example: xschem copy_hierarchy .drw .x1.drw 
    -
  • 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 
  • count_items string separator quoting_chars
  •     Debug command 
    diff --git a/src/callback.c b/src/callback.c index 7a21213c..218f93c0 100644 --- a/src/callback.c +++ b/src/callback.c @@ -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; diff --git a/src/scheduler.c b/src/scheduler.c index dac6cc38..c00f0c47 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -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")) diff --git a/src/token.c b/src/token.c index 145c8e63..19968d29 100644 --- a/src/token.c +++ b/src/token.c @@ -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 : ""); 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; diff --git a/src/xschem.h b/src/xschem.h index a51b4ee9..93082e58 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -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); diff --git a/xschem_library/devices/bsource.sym b/xschem_library/devices/bsource.sym index 89929bfa..7e642017 100644 --- a/xschem_library/devices/bsource.sym +++ b/xschem_library/devices/bsource.sym @@ -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 {} diff --git a/xschem_library/devices/stop.sym b/xschem_library/devices/stop.sym new file mode 100644 index 00000000..24195862 --- /dev/null +++ b/xschem_library/devices/stop.sym @@ -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 {}