Merge remote-tracking branch 'supercd/master' into SuperChayan

This commit is contained in:
stefan schippers 2025-03-14 12:02:29 +01:00
commit dafb0c870d
32 changed files with 3506 additions and 2348 deletions

3
.gitignore vendored
View File

@ -23,6 +23,9 @@ src/eval_expr.c
src/parselabel.c
src/parselabel.h
# Config file for C/C++ code formatter (clang-format)
.clang-format
# Executables
*.exe
src/rawtovcd

View File

@ -229,6 +229,7 @@ ctrl+alt 's' Save-as symbol
- 't' Place text
shift 'T' Toggle *_ignore flag on selected instances
alt 'u' Align to current grid selected objects
ctrl 'u' Unselect attached floater objects
shift 'U' Redo
- 'u' Undo
- 'v' Constrained vertical move/copy of objects

View File

@ -138,6 +138,11 @@ name="mchanged_name" model=\"nmos\" w="20u" l="3u" m="10"
<li><kbd>text_layer_&lt;n&gt;</kbd></li>
<p> This attribute sets the layer of symbol text item number <kbd>n</kbd>. This allows
instance based symbol text color customization.</p>
<li><kbd>attach</kbd></li>
<p> An attribute <kbd>attach="x1 g3 p4"</kbd> will "attach" specified objects that have a matching <kbd>name=...</kbd>
attribute. These objects can be any xschem objects, like other elements, wires, rectangles, polygons, texts etc.<br>
Attached objects will be selected when selecting the component with this attribute set.
This allows to create "object groups"</p>
<li><kbd>highlight</kbd></li>
<p>If set to <kbd>true</kbd> the symbol will be highlighted when one of the nets attached to its pins are highlighted.</p>
<li><kbd>net_name</kbd></li>

View File

@ -551,7 +551,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> abort_operation</kbd></li><pre>
@ -814,6 +813,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> textlayer </kbd> layer number for texts </li>
<li><kbd> top_path </kbd> get top hier path of current window (always "" for tabbed if) </li>
<li><kbd> topwindow </kbd> same as top_path but main window returned as "." </li>
<li><kbd> ui_state </kbd> return UI state </li>
<li><kbd> version </kbd> return xschem version </li>
<li><kbd> wirelayer </kbd> layer used for wires </li>
<li><kbd> wires </kbd> number of wires </li>
@ -828,6 +828,15 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
return result of get_cell function </pre>
<li><kbd> get_cell_w_ext cell n_dirs</kbd></li><pre>
return result of get_cell_w_ext function </pre>
<li><kbd> get_fqdevice instname param modelparam</kbd></li><pre>
get the full pathname of "instname" device
modelparam:
0: current, 1: modelparam, 2: modelvoltage
param: device parameter, like ib, gm, vth
set param to {} (empty str) for just branch current of 2 terminal device
for parameters like "vth" modelparam must be 2
for parameters like "ib" modelparam must be 0
for parameters like "gm" modelparam must be 1</pre>
<li><kbd> getprop instance|instance_pin|symbol|text ref</kbd></li><pre>
getprop instance inst
@ -981,13 +990,17 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> is_generator symbol</kbd></li><pre>
tell if 'symbol' is a generator (symbol(param1,param2,...) </pre>
<li><kbd> line [x1 y1 x2 y2] [pos] [propstring] [draw]</kbd></li><pre>
line
line gui
if 'x1 y1 x2 y2'is given place line on current
layer (rectcolor) at indicated coordinates.
if 'pos' is given insert at given position in rectangle array.
if 'pos' is given insert at given position in line array.
if 'pos' set to -1 append to last element in line array.
'propstring' is the attribute string. Set to empty if not given.
if 'draw' is set to 1 (default) draw the new object, else don't
If no coordinates are given start a GUI operation of line placement </pre>
If no coordinates are given start a GUI operation of line placement
if `gui` argument is given start a line GUI placement with 1st point
set to current mouse coordinates </pre>
<li><kbd> line_width n</kbd></li><pre>
set line width to floating point number 'n' </pre>
<li><kbd> list_hierarchy</kbd></li><pre>
@ -1153,8 +1166,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
If not given take from symbol template attribute.</pre>
<li><kbd> place_text</kbd></li><pre>
Start a GUI placement of a text object </pre>
<li><kbd> polygon</kbd></li><pre>
Start a GUI placement of a polygon </pre>
<li><kbd> polygon [gui]</kbd></li><pre>
Start a GUI placement of a polygon
if `gui` argument is given start a polygon GUI placement with 1st point
set to current mouse coordinates </pre>
<li><kbd> preview_window create|draw|destroy|close [win_path] [file]</kbd></li><pre>
destroy: will delete preview schematic data and destroy container window
close: same as destroy but leave the container window.
@ -1192,8 +1207,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> push_undo</kbd></li><pre>
Push current state on undo stack </pre>
<li><kbd> raw what ...</kbd></li><pre>
what = add | clear | datasets | index | info | loaded | list | new | points | rawfile | del |
read | set | sim_type | switch | switch_back | table_read | value | values | pos_at | vars |
what = add | clear | datasets | index | info | loaded | list |
new | points | rawfile | del | read | set | rename |
sim_type | switch | switch_back | table_read | value | values | pos_at | vars |
xschem raw read filename [type [sweep1 sweep2]]
if sweep1, sweep2 interval is given in 'read' subcommand load only the interval
@ -1208,6 +1224,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
xschem raw del name
delete named vector from current raw file
xschem raw rename old_name new_name
rename a node in the loaded raw file.
xschem raw info
print information about loaded raw files and show the currently active one.
@ -1284,7 +1303,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
new dataset do not start with a header row.
Lines beginning with '#' are comments and ignored
time var_a var_b var_c
time var_a var_b var_cnode in the loaded raw file.
# this is a comment, ignored
0.0 0.0 1.8 0.3
&lt;single empty line: ignored&gt;
@ -1325,14 +1344,19 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Rebuild selection list</pre>
<li><kbd> record_global_node n node</kbd></li><pre>
call the record_global_node function (list of netlist global nodes) </pre>
<li><kbd> rect [x1 y1 x2 y2] [pos] [propstring] [draw]</kbd></li><pre>
if 'x1 y1 x2 y2'is given place recangle on current
layer (rectcolor) at indicated coordinates.
if 'pos' is given insert at given position in rectangle array.
if 'pos' set to -1 append rectangle to last element in rectangle array.
'propstring' is the attribute string. Set to empty if not given.
if 'draw' is set to 1 (default) draw the new object, else don't
If no coordinates are given start a GUI operation of rectangle placement </pre>
<li><kbd> rect ...</kbd></li><pre>
rect [x1 y1 x2 y2] [pos] [propstring] [draw]
if 'x1 y1 x2 y2'is given place recangle on current
layer (rectcolor) at indicated coordinates.
if 'pos' is given insert at given position in rectangle array.
if 'pos' set to -1 append rectangle to last element in rectangle array.
'propstring' is the attribute string. Set to empty if not given.
if 'draw' is set to 1 (default) draw the new object, else don't
rect
If no coordinates are given start a GUI operation of rectangle placement
rect gui
if `gui` argument is given start a GUI placement of a rectangle with 1st
point starting from current mouse coordinates </pre>
<li><kbd> redo</kbd></li><pre>
Redo last undone action </pre>
<li><kbd> redraw</kbd></li><pre>
@ -1634,6 +1658,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Unhighlight selected nets/pins </pre>
<li><kbd> unselect_all [draw]</kbd></li><pre>
Unselect everything. If draw is given and set to '0' no drawing is done </pre>
<li><kbd> unselect_attached_floaters</kbd></li><pre>
Unselect objects (not symbol instances) attached to some instance with a
non empty name=... attribute </pre>
<li><kbd> update_all_sym_bboxes</kbd></li><pre>
Update all symbol bounding boxes </pre>
<li><kbd> update_op</kbd></li><pre>
@ -1649,8 +1676,12 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> wire_coord n</kbd></li><pre>
return 4 coordinates of wire[n] </pre>
<li><kbd> wire [x1 y1 x2 y2] [pos] [prop] [sel]</kbd></li><pre>
wire
wire gui
Place a new wire
if no coordinates are given start a GUI wire placement </pre>
if no coordinates are given start a GUI wire placement
if `gui` argument is given start a GUI placement of a wire with 1st point
starting from current mouse coordinates </pre>
<li><kbd> wire_cut [x y] [noalign]</kbd></li><pre>
start a wire cut operation. Point the mouse in the middle of a wire and
Alt-click right button.
@ -1732,6 +1763,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
</ul>

View File

@ -551,6 +551,19 @@ verilog_format="xnor #(@risedel , @falldel ) @name ( @@Z , @@A , @@B );"
</ul>
<h3>PREDEFINED SYMBOL VALUES</h3>
<ul>
<li><kbd>@name</kbd></li>
<p> This expands to the instance name of the symbol (like C1, R2, X3, ...)
It is replaced with the value of the <kbd>name=...</kbd> attribute given when placing an instance of the symbol
in a schematic.</p>
<li><kbd>#pattern#@name</kbd></li>
<p> This is a variation of the above where <kbd>pattern</kbd> is prefixed to all substituted <kbd>@name</kbd>
patterns. The difference with <kbd>pattern@name</kbd> is that in case of vector instances (this means
a placement of an instance with <kbd>name=R2[3:0]</kbd>, for example) the <kbd>pattern</kbd> string
is added to all single instances when expanding the name. see below examples.<br>
<kbd>pattern@name</kbd> where <kbd>name=R2[2:0]</kbd> is given in the instance placement,
expands to <kbd>patternR2[2],R2[1],R2[0]</kbd><br>
<kbd>#pattern#@name</kbd> where <kbd>name=R2[2:0]</kbd> is given in the instance placement,
expands to <kbd>patternR2[2],patternR2[1],patternR2[0]</kbd><br>
<li><kbd>@symname</kbd></li>
<p> This expands to the name of the symbol</p>
<li><kbd>@symref</kbd></li>

View File

@ -1066,7 +1066,7 @@ void clear_partial_selected_wires(void)
rebuild_selected_array();
for(j=0; j < xctx->lastsel; ++j) if(xctx->sel_array[j].type == WIRE) {
int wire = xctx->sel_array[j].n;
select_wire(wire, 0, 1);
select_wire(wire, 0, 1, 1);
}
xctx->need_reb_sel_arr = 1;
rebuild_selected_array();
@ -1229,7 +1229,7 @@ int unselect_partial_sel_wires(void)
while(wptr) {
xWire *w = &xctx->wire[wptr->n];
if(touch(w->x1, w->y1, w->x2, w->y2, pinx0, piny0) && w->sel && w->sel != SELECTED) {
select_wire(wptr->n, 0, 1);
select_wire(wptr->n, 0, 1, 1);
changed = 1;
}
wptr = wptr->next;
@ -1258,7 +1258,7 @@ int unselect_partial_sel_wires(void)
}
if(touch(w->x1, w->y1, w->x2, w->y2, x0, y0) && w->sel && w->sel != SELECTED) {
xctx->wire[wptr->n].sel = 0;
select_wire(wptr->n, 0, 1);
select_wire(wptr->n, 0, 1, 1);
changed = 1;
}
wptr = wptr->next;
@ -1295,8 +1295,8 @@ void attach_labels_to_inst(int interactive) /* offloaded from callback.c 201710
int use_label_prefix;
int found=0;
my_strdup(_ALLOC_ID_, &symname_pin, tcleval("rel_sym_path [find_file_first lab_pin.sym]"));
my_strdup(_ALLOC_ID_, &symname_wire, tcleval("rel_sym_path [find_file_first lab_wire.sym]"));
my_strdup(_ALLOC_ID_, &symname_pin, tcleval("find_file_first lab_pin.sym"));
my_strdup(_ALLOC_ID_, &symname_wire, tcleval("find_file_first lab_wire.sym"));
if(symname_pin && symname_wire) {
rebuild_selected_array();
k = xctx->lastsel;
@ -1450,12 +1450,11 @@ void delete_files(void)
void place_net_label(int type)
{
unselect_all(1);
if(type == 1) {
const char *lab = tcleval("rel_sym_path [find_file_first lab_pin.sym]");
const char *lab = tcleval("find_file_first lab_pin.sym");
place_symbol(-1, lab, xctx->mousex_snap, xctx->mousey_snap, 0, 0, NULL, 4, 1, 1/*to_push_undo*/);
} else {
const char *lab = tcleval("rel_sym_path [find_file_first lab_wire.sym]");
const char *lab = tcleval("find_file_first lab_wire.sym");
place_symbol(-1, lab, xctx->mousex_snap, xctx->mousey_snap, 0, 0, NULL, 4, 1, 1/*to_push_undo*/);
}
move_objects(START,0,0,0);
@ -1478,13 +1477,14 @@ int place_symbol(int pos, const char *symbol_name, double x, double y, short rot
char name[PATH_MAX];
char name1[PATH_MAX];
char tclev = 0;
if(symbol_name==NULL) {
tcleval("load_file_dialog {Choose symbol} *.\\{sym,tcl\\} INITIALINSTDIR");
my_strncpy(name1, tclresult(), S(name1));
} else {
my_strncpy(name1, trim_chars(symbol_name, " \t\n"), S(name1));
my_strncpy(name1, abs_sym_path(trim_chars(symbol_name, " \t\n"), ""), S(name1));
}
if(!name1[0]) return 0;
dbg(1, "place_symbol(): 1: name1=%s first_call=%d\n",name1, first_call);
/* remove tcleval( given in file selector, if any ... */
if(strstr(name1, "tcleval(")) {
@ -1562,7 +1562,11 @@ int place_symbol(int pos, const char *symbol_name, double x, double y, short rot
/* After having assigned prop_ptr to new instance translate symbol reference
* to resolve @params --> res.tcl(@value\) --> res.tcl(100) */
my_strncpy(name, translate(n, name), S(name));
i = match_symbol(name);
/* parameters like res.tcl(@value\) have been resolved, so reload symbol removing previous */
if(strcmp(name, name1)) {
remove_symbol(i);
i = match_symbol(name);
}
xctx->inst[n].ptr = i;
set_inst_flags(&xctx->inst[n]);
hash_names(n, XINSERT);
@ -1576,6 +1580,50 @@ int place_symbol(int pos, const char *symbol_name, double x, double y, short rot
if(xctx->prep_hash_inst) hash_inst(XINSERT, n); /* no need to rehash, add item */
/* xctx->prep_hash_inst=0; */
/* embed a (locked) graph object floater inside the symbol */
if(xctx->sym[i].type && !strcmp(xctx->sym[i].type, "scope")) {
char *prop = NULL;
my_strdup(_ALLOC_ID_, &xctx->inst[n].prop_ptr,
subst_token(xctx->inst[n].prop_ptr, "attach", xctx->inst[n].instname));
my_mstrcat(_ALLOC_ID_, &prop, "name=", xctx->inst[n].instname, "\n", NULL);
my_mstrcat(_ALLOC_ID_, &prop, "flags=graph,unlocked\n", NULL);
my_mstrcat(_ALLOC_ID_, &prop, "lock=1\n", NULL);
my_mstrcat(_ALLOC_ID_, &prop, "color=8\n", NULL);
if(xctx->sym[i].rects[PINLAYER] == 0) {
if(xctx->lastsel == 1 && xctx->sel_array[0].type==ELEMENT) {
my_mstrcat(_ALLOC_ID_, &prop, "node=\"tcleval([xschem get_fqdevice [xschem translate ",
xctx->inst[n].instname, " @device]])\"\n", NULL);
my_strdup(_ALLOC_ID_, &xctx->inst[n].prop_ptr,
subst_token(xctx->inst[n].prop_ptr, "device", xctx->inst[xctx->sel_array[0].n].instname));
} else {
const char msg[]="scope_ammeter is being inserted but no selected ammeter device/vsource to link to\n";
dbg(0, "%s", msg);
if(has_x) tclvareval("alert_ {", msg, "} {}", NULL);
if(xctx->inst[n].instname) my_free(_ALLOC_ID_, &xctx->inst[n].instname);
if(xctx->inst[n].name) my_free(_ALLOC_ID_, &xctx->inst[n].name);
if(xctx->inst[n].prop_ptr) my_free(_ALLOC_ID_, &xctx->inst[n].prop_ptr);
if(xctx->inst[n].lab) my_free(_ALLOC_ID_, &xctx->inst[n].lab);
if(prop) my_free(_ALLOC_ID_, &prop);
xctx->instances--;
return 0;
}
} else if(xctx->sym[i].rects[PINLAYER] == 1) {
my_mstrcat(_ALLOC_ID_, &prop,
"node=\"tcleval(",
"[xschem translate ", xctx->inst[n].instname, " @#0:net_name]",
")\"\n", NULL);
} else {
my_mstrcat(_ALLOC_ID_, &prop,
"node=\"tcleval(",
"[xschem translate ", xctx->inst[n].instname, " @#0:net_name] ",
"[xschem translate ", xctx->inst[n].instname, " @#1:net_name] -",
")\"\n", NULL);
}
storeobject(-1, x + 20, y-125, x + 130 , y - 25, xRECT, 2, SELECTED, prop);
my_free(_ALLOC_ID_, &prop);
}
if(draw_sym & 3) {
bbox(ADD, xctx->inst[n].x1, xctx->inst[n].y1, xctx->inst[n].x2, xctx->inst[n].y2);
}
@ -1587,6 +1635,7 @@ int place_symbol(int pos, const char *symbol_name, double x, double y, short rot
/* hilight new element 24122002 */
if(draw_sym & 4 ) {
unselect_all(1);
select_element(n, SELECTED,0, 1);
drawtemparc(xctx->gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0, 0.0);
drawtemprect(xctx->gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0);
@ -2214,7 +2263,7 @@ int change_sch_path(int instnumber, int dr)
char *ptr;
size_t pathlen;
int res = 0;
if(level <= 0 ) return 0;
if(level < 0 ) return 0;
my_strdup2(_ALLOC_ID_, &instname, get_tok_value(xctx->hier_attr[level].prop_ptr, "name", 0));
my_strdup2(_ALLOC_ID_, &expanded_instname, expandlabel(instname, &inst_mult));
my_strdup2(_ALLOC_ID_, &path, xctx->sch_path[xctx->currsch]);
@ -2261,6 +2310,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
int inst_mult, inst_number;
int save_ok = 0;
int i, n = 0;
int descend_ok = 1;
if(xctx->currsch + 1 >= CADMAXHIER) {
dbg(0, "descend_schematic(): max hierarchy depth reached: %d", CADMAXHIER);
@ -2416,24 +2466,25 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
dbg(1, "descend_schematic(): filename=%s\n", filename);
/* we are descending from a parent schematic downloaded from the web */
if(!tclgetboolvar("keep_symbols")) remove_symbols();
load_schematic(1, filename, (set_title & 1), alert);
if(xctx->hilight_nets) {
prepare_netlist_structs(0);
propagate_hilights(1, 0, XINSERT_NOREPLACE);
}
dbg(1, "descend_schematic(): before zoom(): prep_hash_inst=%d\n", xctx->prep_hash_inst);
if(xctx->rects[GRIDLAYER] > 0 && tcleval("info exists ngspice::ngspice_data")[0] == '0') {
Graph_ctx *gr = &xctx->graph_struct;
xRect *r = &xctx->rect[GRIDLAYER][0];
if(r->flags & 1) {
backannotate_at_cursor_b_pos(r, gr);
descend_ok = load_schematic(1, filename, (set_title & 1), alert);
if(descend_ok) {
if(xctx->hilight_nets) {
prepare_netlist_structs(0);
propagate_hilights(1, 0, XINSERT_NOREPLACE);
}
dbg(1, "descend_schematic(): before zoom(): prep_hash_inst=%d\n", xctx->prep_hash_inst);
if(xctx->rects[GRIDLAYER] > 0 && tcleval("info exists ngspice::ngspice_data")[0] == '0') {
Graph_ctx *gr = &xctx->graph_struct;
xRect *r = &xctx->rect[GRIDLAYER][0];
if(r->flags & 1) {
backannotate_at_cursor_b_pos(r, gr);
}
}
}
zoom_full(1, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
}
return 1;
return descend_ok;
}
/*
@ -2449,7 +2500,7 @@ void go_back(int what)
char filename[PATH_MAX];
int prev_sch_type;
int confirm = what & 1;
int set_title = !(confirm & 2);
int set_title = !(what & 2);
save_ok=1;
dbg(1,"go_back(): sch[xctx->currsch]=%s\n", xctx->sch[xctx->currsch]);
@ -3132,61 +3183,11 @@ void new_wire(int what, double mx_snap, double my_snap)
xctx->ui_state &= ~STARTWIRE;
}
if( (what & RUBBER) ) {
if(xctx->manhattan_lines & 1) {
xctx->nl_xx1=xctx->nl_x1;xctx->nl_yy1=xctx->nl_y1;
xctx->nl_xx2=xctx->nl_x2;xctx->nl_yy2=xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1);
drawtempline(xctx->gctiled, NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1);
xctx->nl_xx1=xctx->nl_x1;xctx->nl_yy1=xctx->nl_y1;
xctx->nl_xx2=xctx->nl_x2;xctx->nl_yy2=xctx->nl_y2;
ORDER(xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(xctx->gctiled, NOW, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
restore_selection(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
xctx->nl_x2 = mx_snap; xctx->nl_y2 = my_snap;
if(!(what & CLEAR)) {
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1);
drawtempline(xctx->gc[WIRELAYER], NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1);
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(xctx->gc[WIRELAYER], NOW, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
}
} else if(xctx->manhattan_lines & 2) {
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2);
drawtempline(xctx->gctiled, NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2);
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(xctx->gctiled, NOW, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2);
restore_selection(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
xctx->nl_x2 = mx_snap; xctx->nl_y2 = my_snap;
if(!(what & CLEAR)) {
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2);
drawtempline(xctx->gc[WIRELAYER], NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2);
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(xctx->gc[WIRELAYER], NOW, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2);
}
} else {
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(xctx->gctiled, NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
restore_selection(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
xctx->nl_x2 = mx_snap; xctx->nl_y2 = my_snap;
if(!(what & CLEAR)) {
xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1;
xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(xctx->gc[WIRELAYER], NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
}
drawtemp_manhattanline(xctx->gctiled, NOW, xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
restore_selection(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
xctx->nl_x2 = mx_snap; xctx->nl_y2 = my_snap;
if(!(what & CLEAR)) {
drawtemp_manhattanline(xctx->gc[WIRELAYER], NOW, xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
}
}
}
@ -3830,7 +3831,7 @@ int place_text(int draw_text, double mx, double my)
dbg(1,"props=%s, txt=%s\n", props, txt);
create_text(draw_text, mx, my, 0, 0, txt, props, atof(hsize), atof(vsize));
select_text(xctx->texts - 1, SELECTED, 0);
select_text(xctx->texts - 1, SELECTED, 0, 1);
rebuild_selected_array(); /* sets xctx->ui_state |= SELECTION */
drawtemprect(xctx->gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0);
drawtempline(xctx->gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0);

File diff suppressed because it is too large Load Diff

View File

@ -930,10 +930,14 @@ static void drawgrid()
double mult;
#if DRAW_ALL_CAIRO==0
int i=0;
const char *psize_ptr;
int big_gr = tclgetboolvar("big_grid_points");
int grid_point_size = -1;
char dash_arr[2];
int axes = tclgetboolvar("draw_grid_axes");
psize_ptr = tclgetvar("grid_point_size");
if(psize_ptr[0]) grid_point_size = atoi(psize_ptr);
if(axes) {
dash_arr[0] = dash_arr[1] = (char) 3;
XSetDashes(display, xctx->gc[GRIDLAYER], 0, dash_arr, 1);
@ -959,9 +963,8 @@ static void drawgrid()
delta = delta * pow(CADGRIDMULTIPLY, mult);
}
/* while(delta < CADGRIDTHRESHOLD) delta *= CADGRIDMULTIPLY; */ /* <-- to be improved,but works */
/* ************************ Draw axes ****************** */
#if DRAW_ALL_CAIRO==1
xax =floor(xctx->xorigin*xctx->mooz) + 0.5; yax = floor(xctx->yorigin*xctx->mooz) + 0.5;
#else
@ -1007,26 +1010,36 @@ static void drawgrid()
#endif
}
}
/* ************************ /Draw axes ****************** */
#if DRAW_ALL_CAIRO==0
if(axes) {
if(grid_point_size != -1) {
XSetLineAttributes (display, xctx->gc[GRIDLAYER],
grid_point_size, LineSolid, CapProjecting, LINEJOIN);
} else if(!big_gr) {
XSetLineAttributes (display, xctx->gc[GRIDLAYER],
0, LineSolid, LINECAP, LINEJOIN);
} else {
XSetLineAttributes (display, xctx->gc[GRIDLAYER],
XLINEWIDTH(xctx->lw), LineSolid, LINECAP, LINEJOIN);
}
#endif
if(grid_point_size >= 0) big_gr = 1;
tmp = floor((xctx->areay1+1)/delta)*delta-fmod(-xctx->yorigin*xctx->mooz, delta);
for(x=floor((xctx->areax1+1)/delta)*delta-fmod(-xctx->xorigin*xctx->mooz, delta); x < xctx->areax2; x += delta) {
xx = x;
#if DRAW_ALL_CAIRO==1
xx = floor(x) + 0.5;
#endif
if((int)xx == (int)xax) continue;
if(axes && (int)xx == (int)xax) continue;
for(y=tmp; y < xctx->areay2; y += delta) {
yy = y;
#if DRAW_ALL_CAIRO==1
yy = floor(y) + 0.5;
#endif
if((int)yy == (int)yax) continue;
if(axes && (int)yy == (int)yax) continue;
#if DRAW_ALL_CAIRO==1
if(xctx->draw_window) {
cairo_move_to(xctx->cairo_ctx, xx, yy) ;
@ -1087,6 +1100,12 @@ static void drawgrid()
if(xctx->draw_pixmap) cairo_stroke(xctx->cairo_save_ctx);
if(xctx->draw_window) cairo_stroke(xctx->cairo_ctx);
#endif
#if DRAW_ALL_CAIRO==0
XSetLineAttributes (display, xctx->gc[GRIDLAYER],
XLINEWIDTH(xctx->lw), LineSolid, LINECAP, LINEJOIN);
#endif
}
#if !defined(__unix__) && HAS_CAIRO==1
@ -1356,6 +1375,45 @@ void drawtempline(GC gc, int what, double linex1,double liney1,double linex2,dou
}
}
void drawtemp_manhattanline(GC gc, int what, double x1, double y1, double x2, double y2)
{
double origin_shifted_x2, origin_shifted_y2;
if(tclgetboolvar("orthogonal_wiring")) {
/* Origin shift the cartesian coordinate p2(x2,y2) w.r.t. p1(x1,y1) */
origin_shifted_x2 = x2 - x1;
origin_shifted_y2 = y2 - y1;
/* Draw whichever component of the resulting orthogonal-wire is bigger (either horizontal or vertical), first */
if(origin_shifted_x2*origin_shifted_x2 > origin_shifted_y2*origin_shifted_y2)
xctx->manhattan_lines = 1;
else
xctx->manhattan_lines = 2;
}
if(xctx->manhattan_lines & 1) {
xctx->nl_xx1 = x1; xctx->nl_yy1 = y1;
xctx->nl_xx2 = x2; xctx->nl_yy2 = y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1);
drawtempline(gc, what, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1);
xctx->nl_xx1 = x1; xctx->nl_yy1 = y1;
xctx->nl_xx2 = x2; xctx->nl_yy2 = y2;
ORDER(xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(gc, what, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
} else if(xctx->manhattan_lines & 2) {
xctx->nl_xx1 = x1; xctx->nl_yy1 = y1;
xctx->nl_xx2 = x2; xctx->nl_yy2 = y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2);
drawtempline(gc, what, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2);
xctx->nl_xx1 = x1; xctx->nl_yy1 = y1;
xctx->nl_xx2 = x2; xctx->nl_yy2 = y2;
ORDER(xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(gc, what, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2);
} else {
xctx->nl_xx1 = x1; xctx->nl_yy1 = y1;
xctx->nl_xx2 = x2; xctx->nl_yy2 = y2;
ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtempline(gc, what, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
}
}
void drawtemparc(GC gc, int what, double x, double y, double r, double a, double b)
{
static int i=0;
@ -2838,7 +2896,7 @@ static void draw_graph_grid(Graph_ctx *gr, void *ct)
/* background */
filledrect(0, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 2, -1, -1);
/* graph bounding box */
drawrect(GRIDLAYER, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 0, -1, -1);
drawrect(GRIDLAYER, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 2, -1, -1);
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD, gr->rx1, gr->ry1, gr->rx2, gr->ry2);
@ -3055,10 +3113,9 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->gh = gr->gy2 - gr->gy1;
/* set margins */
tmp = gr->rw * 0.14;
gr->marginx = tmp < 50 ? 50 : tmp;
gr->marginx = tmp;
tmp = gr->rh * 0.14;
gr->marginy = tmp < 40 ? 40 : tmp;
gr->marginy = tmp;
/* calculate graph bounding box (container - margin)
* This is the box where plot is done */
gr->x1 = gr->rx1 + gr->marginx;
@ -3083,14 +3140,15 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
/* x axis, y axis text sizes */
gr->txtsizey = gr->h / gr->divy * 0.0095;
tmp = gr->marginx * 0.003;
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
tmp = gr->marginy * 0.02;
tmp = gr->marginx * 0.004;
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
/* tmp = gr->marginy * 0.02;
* if(tmp < gr->txtsizey) gr->txtsizey = tmp;
*/
gr->txtsizey *= gr->magy;
gr->txtsizex = gr->w / gr->divx * 0.0033;
tmp = gr->marginy * 0.0063;
gr->txtsizex = gr->w / gr->divx * 0.0070;
tmp = gr->marginy * 0.0065;
if(tmp < gr->txtsizex) gr->txtsizex = tmp;
gr->txtsizex *= gr->magx;
@ -3258,7 +3316,7 @@ static void draw_graph_variables(int wcnt, int wave_color, int n_nodes, int swee
if(gr->unitx != 1.0) my_snprintf(tmpstr, S(tmpstr), "%s[%c]", stok ? stok : "" , gr->unitx_suffix);
else my_snprintf(tmpstr, S(tmpstr), "%s", stok ? stok : "");
draw_string(wave_color, NOW, tmpstr, 2, 1, 0, 0,
gr->rx1 + 2 + gr->rw / n_nodes * wcnt, gr->ry2-5, gr->txtsizelab, gr->txtsizelab);
gr->rx1 + 2 + gr->rw / n_nodes * wcnt, gr->ry2-2, gr->txtsizelab, gr->txtsizelab);
}
if(gr->legend || gr->digital) {
@ -3782,7 +3840,7 @@ int find_closest_wave(int i, Graph_ctx *gr)
* 8: all drawing, if not set do only XCopyArea / x-cursor if specified
* ct is a pointer used in windows for cairo
*/
void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
void draw_graph(int i, int flags, Graph_ctx *gr, void *ct)
{
int wc = 4, wave_color = 4;
char *node = NULL, *color = NULL, *sweep = NULL;
@ -3804,7 +3862,6 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
int save_extra_idx = -1;
double cursor1, cursor2;
if(xctx->only_probes) return;
if(RECT_OUTSIDE( gr->sx1, gr->sy1, gr->sx2, gr->sy2,
xctx->areax1, xctx->areay1, xctx->areax2, xctx->areay2)) return;
@ -4089,7 +4146,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
if((gr->mode == 2) || (xxfollowing >= start && xxprevious <= end)) {
if(first == -1) first = p;
/* Build poly x array. Translate from graph coordinates to screen coords */
point[poly_npoints].x = (short)S_X(xx);
point[poly_npoints].x = (short)CLIP(S_X(xx), -30000, 30000);
if(dataset == -1 || dataset == sweepvar_wrap) {
/* cursor1: show measurements on nodes in graph */
if(flags & 2 && measure_p == -1 && cnt) {
@ -4770,8 +4827,11 @@ static void draw_images_all(void)
#endif
}
void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2, double ry2)
void svg_embedded_graph(FILE *fd, int i, double rx1, double ry1, double rx2, double ry2)
{
#ifndef __unix__
xRect *r = &xctx->rect[GRIDLAYER][i];
#endif
#if HAS_CAIRO==1
Zoom_info zi;
char *ptr = NULL;
@ -4821,7 +4881,9 @@ void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2,
xctx->draw_pixmap=1;
save = xctx->do_copy_area;
xctx->do_copy_area=0;
draw();
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, NULL);
#ifdef __unix__
png_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual,
xctx->xrect[0].width, xctx->xrect[0].height);
@ -4834,12 +4896,9 @@ void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2,
cairo_set_source_surface(ct, xctx->cairo_save_sfc, 0, 0);
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
cairo_paint(ct);
for(int i = 0; i < xctx->rects[GRIDLAYER]; ++i) {
xRect *r = &xctx->rect[GRIDLAYER][i];
if(r->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
if(r->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
#endif
closure.buffer = NULL;

View File

@ -594,7 +594,11 @@ FILE *my_fopen(const char *f, const char *m)
st = stat(f, &buf);
if(st) return NULL; /* not existing or error */
#ifdef __unix__
if(!S_ISREG(buf.st_mode)) return NULL; /* not a regular file/symlink to a regular file */
#else
/* TBD */
#endif
fd = fopen(f, m);
return fd;
}
@ -1637,6 +1641,7 @@ static int update_symbol(const char *result, int x, int selected_inst)
/* preserve backslashes in name ---------0---------------------------------->. */
my_strdup(_ALLOC_ID_, &name, get_tok_value(xctx->inst[*ii].prop_ptr, "name", 1));
if(name && name[0] ) {
char *old_name = NULL;
dbg(1, "update_symbol(): prefix!='\\0', name=%s\n", name);
/* change prefix if changing symbol type; */
if(prefix && old_prefix && old_prefix != prefix) {
@ -1650,10 +1655,13 @@ static int update_symbol(const char *result, int x, int selected_inst)
if(!k) hash_names(-1, XINSERT);
hash_names(*ii, XDELETE);
dbg(1, "update_symbol(): delete %s\n", xctx->inst[*ii].instname);
my_strdup2(_ALLOC_ID_, &old_name, xctx->inst[*ii].instname);
new_prop_string(*ii, ptr, /* sets also inst[].instname */
tclgetboolvar("disable_unique_names")); /* set new prop_ptr */
hash_names(*ii, XINSERT);
update_attached_floaters(old_name, *ii, 1);
dbg(1, "update_symbol(): insert %s\n", xctx->inst[*ii].instname);
my_free(_ALLOC_ID_, &old_name);
}
set_inst_flags(&xctx->inst[*ii]);
} /* end for(k=0;k<xctx->lastsel; ++k) */

View File

@ -274,10 +274,11 @@ static int kklex()
while (c != 0 && isalnum(c) && i < length);
str--;
symbuf[i] = '\0';
s = getsym (symbuf);
s = getsym(symbuf);
kklval.tptr = s;
dbg(dbglev, "ylex: FNCT=%s\n", symbuf);
return FNCT;
if(s) return FNCT;
return 0; /* error : undefined identifier */
}
/* Any other character is a token by itself. */
return c;

View File

@ -25,7 +25,7 @@
static double distance; /* safe to keep even with multiple schematics */
static Selected sel; /* safe to keep even with multiple schematics */
static void find_closest_wire(double mx, double my)
static void find_closest_wire(double mx, double my, int override_lock)
/* returns the net that is closest to the mouse pointer */
/* if there are nets and distance < CADWIREMINDIST */
{
@ -42,14 +42,15 @@ static void find_closest_wire(double mx, double my)
w = i; d = tmp;
}
}
if( d <= threshold && w!=-1)
if( w != -1 && d <= threshold &&
(override_lock || strboolcmp(get_tok_value(xctx->wire[w].prop_ptr, "lock", 0), "true")) )
{
sel.n = w; sel.type = WIRE;
distance = d;
}
}
static void find_closest_bezier(double mx, double my, int c, int i, int *l, int *col)
static double find_closest_bezier(double mx, double my, double d, int c, int i, int *l, int *col)
{
const double bez_steps = 1.0/8.0; /* divide the t = [0,1] interval into 8 steps */
int b;
@ -97,16 +98,17 @@ static void find_closest_bezier(double mx, double my, int c, int i, int *l, int
xp1 = (1 - t1) * (1 - t1) * x0 + 2 * (1 - t1) * t1 * x1 + t1 * t1 * x2;
yp1 = (1 - t1) * (1 - t1) * y0 + 2 * (1 - t1) * t1 * y1 + t1 * t1 * y2;
ORDER(xp, yp, xp1, yp1);
if( (tmp = dist(xp, yp, xp1, yp1, mx, my)) < distance )
if( (tmp = dist(xp, yp, xp1, yp1, mx, my)) < d )
{
*l = i; distance = tmp; *col = c;
dbg(1, "find_closest_bezier(): distance=%.16g n=%d\n", distance, i);
*l = i; d = tmp; *col = c;
}
}
}
dbg(1, "find_closest_bezier(): d=%.16g n=%d\n", d, i);
return d;
}
static void find_closest_polygon(double mx, double my)
static void find_closest_polygon(double mx, double my, int override_lock)
/* returns the polygon that is closest to the mouse pointer */
/* if there are lines and distance < CADWIREMINDIST */
{
@ -126,15 +128,7 @@ static void find_closest_polygon(double mx, double my)
bezier = bezier && (p->points > 2);
if(bezier) {
double ds = xctx->cadhalfdotsize;
find_closest_bezier(mx, my, c, i, &l, &col);
for(j = 0; j < p->points; j++) {
if( POINTINSIDE(mx, my, p->x[j] - ds, p->y[j] - ds, p->x[j] + ds, p->y[j] + ds)) {
l = i; d = 0.0;col = c;
break;
}
}
d = find_closest_bezier(mx, my, d, c, i, &l, &col);
} else {
for(j=0; j<xctx->poly[c][i].points-1; ++j) {
x1 = p->x[j];
@ -145,13 +139,14 @@ static void find_closest_polygon(double mx, double my)
if( (tmp = dist(x1, y1, x2, y2, mx, my)) < d )
{
l = i; d = tmp;col = c;
dbg(1, "find_closest_polygon(): d=%.16g n=%d\n", d, i);
}
}
dbg(1, "find_closest_polygon(): d=%.16g n=%d\n", d, i);
}
} /* end for i */
} /* end for c */
if( d <= threshold && l!=-1)
if( d <= threshold && l!=-1 &&
(override_lock || strboolcmp(get_tok_value(xctx->poly[col][l].prop_ptr, "lock", 0), "true")))
{
sel.n = l; sel.type = POLYGON; sel.col = col;
distance = d;
@ -159,7 +154,7 @@ static void find_closest_polygon(double mx, double my)
}
static void find_closest_line(double mx, double my)
static void find_closest_line(double mx, double my, int override_lock)
/* returns the line that is closest to the mouse pointer */
/* if there are lines and distance < CADWIREMINDIST */
{
@ -181,7 +176,8 @@ static void find_closest_line(double mx, double my)
}
} /* end for i */
} /* end for c */
if( d <= threshold && l!=-1)
if( d <= threshold && l!=-1 &&
(override_lock || strboolcmp(get_tok_value(xctx->line[col][l].prop_ptr, "lock", 0), "true")))
{
sel.n = l; sel.type = LINE; sel.col = col;
distance = d;
@ -326,7 +322,7 @@ void xfind_closest_net_or_symbol_pin(double mx, double my, double *x, double *y)
}
#endif
static void find_closest_arc(double mx, double my)
static void find_closest_arc(double mx, double my, int override_lock)
{
double dist, angle, angle1, angle2;
int i, c, r=-1, col;
@ -371,7 +367,8 @@ static void find_closest_arc(double mx, double my)
}
} /* end for i */
} /* end for c */
if( r!=-1 && d <= threshold ) /* * pow(xctx->arc[col][r].r, 2)) */
if(r!=-1 && d <= threshold &&
strboolcmp(get_tok_value(xctx->arc[col][r].prop_ptr, "lock", 0), "true"))
{
sel.n = r; sel.type = ARC; sel.col = col;
distance = d;
@ -439,7 +436,7 @@ static void find_closest_element(double mx, double my, int override_lock)
}
}
static void find_closest_text(double mx, double my)
static void find_closest_text(double mx, double my, int override_lock)
{
short rot, flip;
double xx1, xx2, yy1, yy2;
@ -476,7 +473,9 @@ static void find_closest_text(double mx, double my)
dbg(2, "find_closest_text(): finding closest text, texts=%d, dist=%.16g\n", i, d);
}
} /* end for i */
if( d <= threshold && r!=-1)
if( r != -1 && d <= threshold &&
(override_lock || strboolcmp(get_tok_value(xctx->text[r].prop_ptr, "lock", 0), "true")) )
{
sel.n = r; sel.type = xTEXT;
distance = d;
@ -487,14 +486,14 @@ Selected find_closest_obj(double mx, double my, int override_lock)
{
sel.n = 0L; sel.col = 0; sel.type = 0;
distance = DBL_MAX;
find_closest_line(mx, my);
find_closest_polygon(mx, my);
find_closest_line(mx, my, override_lock);
find_closest_polygon(mx, my, override_lock);
/* dbg(1, "1 find_closest_obj(): sel.n=%d, sel.col=%d, sel.type=%d\n", sel.n, sel.col, sel.type); */
find_closest_box(mx, my, override_lock);
find_closest_arc(mx, my);
find_closest_arc(mx, my, override_lock);
/* dbg(1, "2 find_closest_obj(): sel.n=%d, sel.col=%d, sel.type=%d\n", sel.n, sel.col, sel.type); */
find_closest_text(mx, my);
find_closest_wire(mx, my);
find_closest_text(mx, my, override_lock);
find_closest_wire(mx, my, override_lock);
find_closest_element(mx, my, override_lock);
return sel; /*sel.type = 0 if nothing found */
}

View File

@ -169,6 +169,7 @@ ctrl+alt 's' Save-as symbol
- 't' Place text
shift 'T' Toggle *_ignore flag on selected instances
alt 'u' Align to current grid selected objects
ctrl 'u' Unselect attached floater objects
shift 'U' Redo
- 'u' Undo
- 'v' Constrained vertical move/copy of objects

View File

@ -378,25 +378,25 @@ void draw_selection(GC g, int interruptable)
if(xctx->wire[n].sel==SELECTED)
{
if(xctx->wire[n].bus)
drawtempline(g, THICK, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay,
drawtemp_manhattanline(g, THICK, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay,
xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay);
else
drawtempline(g, ADD, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay,
drawtemp_manhattanline(g, ADD, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay,
xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay);
}
else if(xctx->wire[n].sel==SELECTED1)
{
if(xctx->wire[n].bus)
drawtempline(g, THICK, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay, xctx->rx2, xctx->ry2);
drawtemp_manhattanline(g, THICK, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay, xctx->rx2, xctx->ry2);
else
drawtempline(g, ADD, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay, xctx->rx2, xctx->ry2);
drawtemp_manhattanline(g, ADD, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay, xctx->rx2, xctx->ry2);
}
else if(xctx->wire[n].sel==SELECTED2)
{
if(xctx->wire[n].bus)
drawtempline(g, THICK, xctx->rx1, xctx->ry1, xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay);
drawtemp_manhattanline(g, THICK, xctx->rx1, xctx->ry1, xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay);
else
drawtempline(g, ADD, xctx->rx1, xctx->ry1, xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay);
drawtemp_manhattanline(g, ADD, xctx->rx1, xctx->ry1, xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay);
}
break;
case LINE:
@ -513,6 +513,82 @@ void draw_selection(GC g, int interruptable)
xctx->movelastsel = i;
}
/* sel: if set to 1 change references only on selected items, like in a copy operation.
* If set to 0 operate on all objects with matching name=... attribute */
void update_attached_floaters(const char *from_name, int inst, int sel)
{
int i, c;
char *to_name = xctx->inst[inst].instname;
const char *attach = get_tok_value(xctx->inst[inst].prop_ptr, "attach", 0);
char *new_attach;
if(!from_name || !from_name[0]) return;
if(!to_name || !to_name[0]) return;
if(!attach[0]) return;
new_attach = str_replace(attach, from_name, to_name, 1, 1);
my_strdup(_ALLOC_ID_, &xctx->inst[inst].prop_ptr,
subst_token(xctx->inst[inst].prop_ptr, "attach", new_attach) );
for(c = 0; c < cadlayers; c++) {
for(i = 0; i < xctx->rects[c]; i++) {
if(!sel || xctx->rect[c][i].sel == SELECTED) {
if( !strcmp(from_name, get_tok_value(xctx->rect[c][i].prop_ptr, "name", 0))) {
my_strdup(_ALLOC_ID_, &xctx->rect[c][i].prop_ptr,
subst_token(xctx->rect[c][i].prop_ptr, "name", to_name) );
}
if(c == GRIDLAYER) {
const char *node = get_tok_value(xctx->rect[c][i].prop_ptr, "node", 2);
if(node && node[0]) {
const char *new_node = str_replace(node, from_name, to_name, 1, -1);
my_strdup(_ALLOC_ID_, &xctx->rect[c][i].prop_ptr,
subst_token(xctx->rect[c][i].prop_ptr, "node", new_node));
}
}
}
}
for(i = 0; i < xctx->lines[c]; i++) {
if((!sel || xctx->line[c][i].sel == SELECTED) &&
!strcmp(from_name, get_tok_value(xctx->line[c][i].prop_ptr, "name", 0))) {
my_strdup(_ALLOC_ID_, &xctx->line[c][i].prop_ptr,
subst_token(xctx->line[c][i].prop_ptr, "name", to_name) );
}
}
for(i = 0; i < xctx->polygons[c]; i++) {
if((!sel || xctx->poly[c][i].sel == SELECTED) &&
!strcmp(from_name, get_tok_value(xctx->poly[c][i].prop_ptr, "name", 0))) {
my_strdup(_ALLOC_ID_, &xctx->poly[c][i].prop_ptr,
subst_token(xctx->poly[c][i].prop_ptr, "name", to_name) );
}
}
for(i = 0; i < xctx->arcs[c]; i++) {
if((!sel || xctx->arc[c][i].sel == SELECTED) &&
!strcmp(from_name, get_tok_value(xctx->arc[c][i].prop_ptr, "name", 0))) {
my_strdup(_ALLOC_ID_, &xctx->arc[c][i].prop_ptr,
subst_token(xctx->arc[c][i].prop_ptr, "name", to_name) );
}
}
}
for(i = 0; i < xctx->wires; i++) {
if((!sel || xctx->wire[i].sel == SELECTED) &&
!strcmp(from_name, get_tok_value(xctx->wire[i].prop_ptr, "name", 0))) {
my_strdup(_ALLOC_ID_, &xctx->wire[i].prop_ptr,
subst_token(xctx->wire[i].prop_ptr, "name", to_name) );
}
}
for(i = 0; i < xctx->texts; i++) {
if((!sel || xctx->text[i].sel == SELECTED) &&
!strcmp(from_name, get_tok_value(xctx->text[i].prop_ptr, "name", 0))) {
my_strdup(_ALLOC_ID_, &xctx->text[i].prop_ptr,
subst_token(xctx->text[i].prop_ptr, "name", to_name) );
set_text_flags(&xctx->text[i]);
}
}
}
void copy_objects(int what)
{
int tmpi, c, i, n, k /*, tmp */ ;
@ -881,6 +957,9 @@ void copy_objects(int what)
newpropcnt++;
new_prop_string(xctx->instances, xctx->inst[n].prop_ptr, /* sets also inst[].instname */
tclgetboolvar("disable_unique_names"));
update_attached_floaters(xctx->inst[n].instname, xctx->instances, 1);
hash_names(xctx->instances, XINSERT);
xctx->instances++; /* symbol_bbox calls translate and translate must have updated xctx->instances */
symbol_bbox(xctx->instances-1,
@ -1056,10 +1135,36 @@ void move_objects(int what, int merge, double dx, double dy)
if(wire[n].sel == SELECTED1) wire[n].sel = SELECTED2;
else if(wire[n].sel == SELECTED2) wire[n].sel = SELECTED1;
}
wire[n].x1=xctx->rx1;
wire[n].y1=xctx->ry1;
wire[n].x2=xctx->rx2;
wire[n].y2=xctx->ry2;
if(wire[n].sel & (SELECTED|SELECTED1))
{
if(xctx->manhattan_lines & 1) xctx->manhattan_lines=2;
else if(xctx->manhattan_lines & 2) xctx->manhattan_lines=1;
}
wire[n].x1 = xctx->rx1;
wire[n].y1 = xctx->ry1;
if(xctx->manhattan_lines&1)
{
wire[n].x2 = xctx->rx2;
wire[n].y2 = xctx->ry1;
storeobject(-1, xctx->rx2,xctx->ry1,xctx->rx2,xctx->ry2,WIRE,0,0,NULL);
hash_wire(XINSERT, xctx->wires-1, 1);
drawline(WIRELAYER,ADD, xctx->rx2,xctx->ry1,xctx->rx2,xctx->ry2, 0, NULL);
}
else if(xctx->manhattan_lines&2)
{
wire[n].x2 = xctx->rx1;
wire[n].y2 = xctx->ry2;
storeobject(-1, xctx->rx1,xctx->ry2,xctx->rx2,xctx->ry2,WIRE,0,0,NULL);
hash_wire(XINSERT, xctx->wires-1, 1);
drawline(WIRELAYER,ADD, xctx->rx1,xctx->ry2,xctx->rx2,xctx->ry2, 0, NULL);
}
else
{
wire[n].x2 = xctx->rx2;
wire[n].y2 = xctx->ry2;
}
}
break;

View File

@ -678,7 +678,7 @@ static void print_wires(void)
ptr=xctx->wire_spatial_table[0][1];
while(ptr)
{
select_wire(ptr->n,SELECTED, 1);
select_wire(ptr->n,SELECTED, 1, 1);
rebuild_selected_array();
ptr=ptr->next;
}

View File

@ -48,7 +48,7 @@ static void merge_text(FILE *fd)
xctx->text[i].sel=0;
load_ascii_string(&xctx->text[i].prop_ptr,fd);
set_text_flags(&xctx->text[i]);
select_text(i,SELECTED, 1);
select_text(i,SELECTED, 1, 1);
xctx->texts++;
}
@ -66,7 +66,7 @@ static void merge_wire(FILE *fd)
load_ascii_string( &ptr, fd);
storeobject(-1, x1,y1,x2,y2,WIRE,0,SELECTED,ptr);
my_free(_ALLOC_ID_, &ptr);
select_wire(i, SELECTED, 1);
select_wire(i, SELECTED, 1, 1);
}
static void merge_box(FILE *fd)
@ -172,7 +172,7 @@ static void merge_arc(FILE *fd)
ptr[i].dash = 0;
}
select_arc(c,i, SELECTED, 1);
select_arc(c,i, SELECTED, 1, 1);
xctx->arcs[c]++;
}
@ -232,7 +232,7 @@ static void merge_polygon(FILE *fd)
ptr[i].dash = 0;
}
select_polygon(c,i, SELECTED, 1);
select_polygon(c,i, SELECTED, 1, 1);
xctx->polygons[c]++;
}
@ -271,7 +271,7 @@ static void merge_line(FILE *fd)
ptr[i].bus = 1;
else
ptr[i].bus = 0;
select_line(c,i, SELECTED, 1);
select_line(c,i, SELECTED, 1, 1);
xctx->lines[c]++;
}

View File

@ -250,8 +250,9 @@ static int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y
return 1;
}
static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
static int ps_embedded_graph(int i, double rx1, double ry1, double rx2, double ry2)
{
xRect *r = &xctx->rect[GRIDLAYER][i];
#if defined(HAS_LIBJPEG) && HAS_CAIRO==1
Zoom_info zi;
double rw, rh, scale;
@ -269,7 +270,7 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
int quality=40;
const char *quality_attr;
size_t oLength;
int i;
int j;
double sx1, sy1, sx2, sy2;
/* screen position */
@ -323,7 +324,9 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
d_c = tclgetboolvar("dark_colorscheme");
tclsetboolvar("dark_colorscheme", 0);
build_colors(0, 0);
draw();
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, NULL);
dbg(1, "width=%d, rwi=%d height=%d rhi=%d\n", xctx->xrect[0].width, rwi, xctx->xrect[0].height, rhi);
#ifdef __unix__
png_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual,
@ -337,13 +340,8 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
cairo_set_source_surface(ct, xctx->cairo_save_sfc, 0, 0);
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
cairo_paint(ct);
for (i = 0; i < xctx->rects[GRIDLAYER]; ++i) {
xRect* r2 = &xctx->rect[GRIDLAYER][i];
if (r2->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
}
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
#endif
cairo_image_surface_write_to_jpeg_mem(png_sfc, &jpgData, &fileSize, quality);
@ -382,10 +380,10 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
fprintf(fd, "} exec\n");
#if 1 /* break lines */
for (i = 0; i < oLength; ++i)
for (j = 0; j < oLength; ++j)
{
fputc(ascii85EncodedJpeg[i],fd);
if(i > 0 && (i % 64) == 0)
fputc(ascii85EncodedJpeg[j],fd);
if(j > 0 && (j % 64) == 0)
{
fputc('\n',fd);
/* if (ascii85Encode[i+1]=='%') idx=63; imageMagic does this for some reason?!
@ -1449,8 +1447,8 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
continue;
}
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1)) { /* graph */
xRect* r = &xctx->rect[c][i];
ps_embedded_graph(r, r->x1, r->y1, r->x2, r->y2);
xRect *r = &xctx->rect[c][i];
ps_embedded_graph(i, r->x1, r->y1, r->x2, r->y2);
}
if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
ps_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1,

View File

@ -1014,17 +1014,16 @@ int raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, doub
return res;
}
dbg(1, "raw_read(): type=%s\n", type ? type : "<NULL>");
*rawptr = my_calloc(_ALLOC_ID_, 1, sizeof(Raw));
raw = *rawptr;
raw->level = -1;
raw->annot_p = -1;
raw->sweep1 = sweep1;
raw->sweep2 = sweep2;
raw->annot_sweep_idx = -1;
int_hash_init(&raw->table, HASHSIZE);
fd = my_fopen(f, fopen_read_mode);
if(fd) {
*rawptr = my_calloc(_ALLOC_ID_, 1, sizeof(Raw));
raw = *rawptr;
raw->level = -1;
raw->annot_p = -1;
raw->sweep1 = sweep1;
raw->sweep2 = sweep2;
raw->annot_sweep_idx = -1;
int_hash_init(&raw->table, HASHSIZE);
if((res = read_dataset(fd, rawptr, type, no_warning)) == 1) {
int i;
set_modify(-2); /* clear text floater caches */
@ -1044,12 +1043,13 @@ int raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, doub
xRect *r;
r = &xctx->rect[GRIDLAYER][0];
if(r->flags & 1) {
setup_graph_data(0, 0, &xctx->graph_struct);
backannotate_at_cursor_b_pos(r, &xctx->graph_struct);
/* don't overwrite xctx->graph_struct, being used in draw_graph() which calls raw_read() */
Graph_ctx gr_ctx;
setup_graph_data(0, 0, &gr_ctx);
backannotate_at_cursor_b_pos(r, &gr_ctx);
}
}
}
} else {
/* free_rawfile(rawptr, 0, 0); */ /* do not free: already done in read_dataset()->extra_rawfile() */
if(!no_warning) {
@ -1074,6 +1074,22 @@ int raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, doub
return 0;
}
int raw_renamevar(const char *old_name, const char *new_name)
{
int n, ret = 0;
Raw *raw = xctx->raw;
Int_hashentry *entry;
n = get_raw_index(old_name, &entry);
if(n < 0) return ret;
dbg(1, "n=%d, %s \n", n, entry->token);
int_hash_lookup(&raw->table, entry->token, 0, XDELETE);
my_strdup2(_ALLOC_ID_, &raw->names[n], new_name);
int_hash_lookup(&raw->table, raw->names[n], n, XINSERT); /* update hash table */
ret = 1;
return ret;
}
int raw_deletevar(const char *name)
{
int ret = 0;
@ -1206,6 +1222,7 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
if(what == 0) return 0;
/* if not already done insert base raw file (if there is one) into xctx->extra_raw_arr[0] */
if(xctx->raw && xctx->extra_raw_n == 0) {
dbg(1, "insert extra_raw_arr[0]\n");
xctx->extra_raw_arr[xctx->extra_raw_n] = xctx->raw;
xctx->extra_raw_n++;
}
@ -1277,7 +1294,8 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
if(!no_warning) {
dbg(0, "extra_rawfile() read: %s not found or no \"%s\" analysis\n", f, type ? type : "<unspecified>");
}
if(xctx->extra_raw_n) { /* only restore if raw wiles were not deleted due to a failure in read_raw() */
if(xctx->extra_raw_n) { /* only restore if raw files were not deleted due to a failure in read_raw() */
dbg(1, "extra_rawfile(): read: restore previous, extra_idx=%d\n", xctx->extra_idx);
xctx->raw = save; /* restore */
xctx->extra_prev_idx = xctx->extra_idx;
}
@ -2783,7 +2801,8 @@ static void load_inst(int k, FILE *fd)
if(name[0] == '/') my_strdup2(_ALLOC_ID_, &xctx->inst[i].name, rel_sym_path(name));
else my_strdup2(_ALLOC_ID_, &xctx->inst[i].name, name);
#else
my_strdup2(_ALLOC_ID_, &xctx->inst[i].name, rel_sym_path(name));
if(isupper(name[0]) && name[1] == ':' && name[1] == '/') my_strdup2(_ALLOC_ID_, &xctx->inst[i].name, rel_sym_path(name));
else my_strdup2(_ALLOC_ID_, &xctx->inst[i].name, name);
#endif
my_free(_ALLOC_ID_, &tmp);
if(fscanf(fd, "%lf %lf %hd %hd", &xctx->inst[i].x0, &xctx->inst[i].y0,

View File

@ -1725,6 +1725,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, top_path,TCL_VOLATILE);
}
break;
case 'u':
if(!strcmp(argv[2], "ui_state")) { /* return UI state */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, my_itoa(xctx->ui_state), TCL_VOLATILE);
}
break;
case 'v':
if(!strcmp(argv[2], "version")) { /* return xschem version */
Tcl_SetResult(interp, XSCHEM_VERSION, TCL_VOLATILE);
@ -1798,8 +1804,34 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, (char *)get_cell_w_ext(argv[2], atoi(argv[3])), TCL_VOLATILE);
}
}
/************ end xschem get subcommands *************/
/* get_fqdevice instname param modelparam
* get the full pathname of "instname" device
* modelparam:
* 0: current, 1: modelparam, 2: modelvoltage
* param: device parameter, like ib, gm, vth
* set param to {} (empty str) for just branch current of 2 terminal device
* for parameters like "vth" modelparam must be 2
* for parameters like "ib" modelparam must be 0
* for parameters like "gm" modelparam must be 1
*/
else if(!strcmp(argv[1], "get_fqdevice"))
{
char *fqdev;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 4) {
fqdev = get_fqdevice(argv[3], atoi(argv[4]), argv[2]);
Tcl_SetResult(interp, fqdev, TCL_VOLATILE);
my_free(_ALLOC_ID_, &fqdev);
} else if(argc > 2) {
fqdev = get_fqdevice("", 0, argv[2]);
Tcl_SetResult(interp, fqdev, TCL_VOLATILE);
my_free(_ALLOC_ID_, &fqdev);
}
}
/* getprop instance|instance_pin|symbol|text ref
*
* getprop instance inst
@ -2103,6 +2135,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
my_snprintf(res, S(res), "semaphore=%d\n", xctx->semaphore); Tcl_AppendResult(interp, res, NULL);
my_snprintf(res, S(res), "ui_state=%d\n", xctx->ui_state); Tcl_AppendResult(interp, res, NULL);
my_snprintf(res, S(res), "ui_state2=%d\n", xctx->ui_state2); Tcl_AppendResult(interp, res, NULL);
my_snprintf(res, S(res), "drag_elements=%d\n", xctx->drag_elements); Tcl_AppendResult(interp, res, NULL);
my_snprintf(res, S(res), "last_command=%d\n", xctx->last_command); Tcl_AppendResult(interp, res, NULL);
my_snprintf(res, S(res), "prep_net_structs=%d\n", xctx->prep_net_structs); Tcl_AppendResult(interp, res, NULL);
my_snprintf(res, S(res), "prep_hi_structs=%d\n", xctx->prep_hi_structs); Tcl_AppendResult(interp, res, NULL);
@ -2760,13 +2793,17 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
break;
case 'l': /*----------------------------------------------*/
/* line [x1 y1 x2 y2] [pos] [propstring] [draw]
* line
* line gui
* if 'x1 y1 x2 y2'is given place line on current
* layer (rectcolor) at indicated coordinates.
* if 'pos' is given insert at given position in rectangle array.
* if 'pos' is given insert at given position in line array.
* if 'pos' set to -1 append to last element in line array.
* 'propstring' is the attribute string. Set to empty if not given.
* if 'draw' is set to 1 (default) draw the new object, else don't
* If no coordinates are given start a GUI operation of line placement */
* If no coordinates are given start a GUI operation of line placement
* if `gui` argument is given start a line GUI placement with 1st point
* set to current mouse coordinates */
if(!strcmp(argv[1], "line"))
{
double x1,y1,x2,y2;
@ -2792,6 +2829,21 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
set_modify(1);
}
else if(argc == 3 && !strcmp(argv[2], "gui")) {
int prev_state = xctx->ui_state;
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
start_line(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTLINE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTLINE;
}
}
else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
@ -2888,11 +2940,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1], "load") )
{
int load_symbols = 1, force = 1, undo_reset = 1, nofullzoom = 0, nodraw = 0;
int keep_symbols = 0;
size_t i;
int keep_symbols = 0, first;
int i;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
for(i = 2; i < argc; i++) {
if(argv[i][0] == '-') {
if(!strcmp(argv[i], "-nosymbols")) {
@ -2912,8 +2963,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
break;
}
}
if(argc>i) {
first = i;
if(argc==2) {
ask_new_file();
tcleval("load_additional_files");
} else
for(i = first; i < argc; i++) {
char f[PATH_MAX + 100];
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[i], home_dir);
tcleval(f);
@ -2940,34 +2995,41 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
unselect_all(1);
/* no implicit undo: if needed do it before loading */
/* if(!undo_reset) xctx->push_undo(); */
if(undo_reset) xctx->currsch = 0;
if(!keep_symbols) remove_symbols();
if(!nofullzoom) {
xctx->zoom=CADINITIALZOOM;
xctx->mooz=1/CADINITIALZOOM;
xctx->xorigin=CADINITIALX;
xctx->yorigin=CADINITIALY;
if(i == first) {
if(undo_reset) xctx->currsch = 0;
if(!keep_symbols) remove_symbols();
if(!nofullzoom) {
xctx->zoom=CADINITIALZOOM;
xctx->mooz=1/CADINITIALZOOM;
xctx->xorigin=CADINITIALX;
xctx->yorigin=CADINITIALY;
}
}
dbg(1, "scheduler: undo_reset=%d\n", undo_reset);
ret = load_schematic(load_symbols, f, undo_reset, !force);
dbg(1, "xschem load: ret=%d\n", ret);
if(undo_reset) {
tclvareval("update_recent_file {", f, "}", NULL);
my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch], ".");
if(xctx->portmap[xctx->currsch].table) str_hash_free(&xctx->portmap[xctx->currsch]);
str_hash_init(&xctx->portmap[xctx->currsch], HASHSIZE);
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
if(i > first) {
ret = new_schematic("create", "noconfirm", f, 1);
if(undo_reset) {
tclvareval("update_recent_file {", f, "}", NULL);
}
} else {
ret = load_schematic(load_symbols, f, undo_reset, !force);
dbg(1, "xschem load: f=%s, ret=%d\n", f, ret);
if(undo_reset) {
tclvareval("update_recent_file {", f, "}", NULL);
my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch], ".");
if(xctx->portmap[xctx->currsch].table) str_hash_free(&xctx->portmap[xctx->currsch]);
str_hash_init(&xctx->portmap[xctx->currsch], HASHSIZE);
xctx->sch_path_hash[xctx->currsch] = 0;
xctx->sch_inst_number[xctx->currsch] = 1;
}
if(nofullzoom) {
if(!nodraw) draw();
} else zoom_full(1, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
}
if(nofullzoom) {
if(!nodraw) draw();
} else zoom_full(1, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
}
}
}
else if(argc==2) {
ask_new_file();
}
Tcl_SetResult(interp, xctx->sch[xctx->currsch], TCL_STATIC);
}
@ -2980,13 +3042,32 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int cancel = 0;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
if(!is_from_web(argv[2])) {
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir);
tcleval(f);
/* tclvareval("file normalize {", tclresult(), "}", NULL); */
my_strncpy(f, abs_sym_path(tclresult(), ""), S(f));
} else {
my_strncpy(f, argv[2], S(f));
int i;
for(i = 2; i < argc; i++) {
if(!is_from_web(argv[i])) {
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[i], home_dir);
tcleval(f);
/* tclvareval("file normalize {", tclresult(), "}", NULL); */
my_strncpy(f, abs_sym_path(tclresult(), ""), S(f));
} else {
my_strncpy(f, argv[i], S(f));
}
if(f[0]) {
char win_path[WINDOW_PATH_SIZE];
dbg(1, "f=%s\n", f);
if(check_loaded(f, win_path)) {
char msg[PATH_MAX + 100];
my_snprintf(msg, S(msg),
"tk_messageBox -type okcancel -icon warning -parent [xschem get topwindow] "
"-message {Warning: %s already open.}", f);
tcleval(msg);
if(strcmp(tclresult(), "ok")) continue;
}
new_schematic("create", "noconfirm", f, 1);
tclvareval("update_recent_file {", f, "}", NULL);
} else {
new_schematic("create", NULL, NULL, 1);
}
}
} else {
tcleval("load_file_dialog {Load file} *.\\{sch,sym,tcl\\} INITIALLOADDIR");
@ -2995,14 +3076,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
} else {
cancel = 1;
}
}
if(!cancel) {
if(f[0]) {
dbg(1, "f=%s\n", f);
new_schematic("create", "noconfirm", f, 1);
tclvareval("update_recent_file {", f, "}", NULL);
} else {
new_schematic("create", NULL, NULL, 1);
if(!cancel) {
if(f[0]) {
dbg(1, "f=%s\n", f);
new_schematic("create", "noconfirm", f, 1);
tclvareval("update_recent_file {", f, "}", NULL);
} else {
new_schematic("create", NULL, NULL, 1);
}
}
}
Tcl_ResetResult(interp);
@ -3604,7 +3685,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
tclvareval("set INITIALINSTDIR [file dirname {",
abs_sym_path(tcl_hook2(xctx->inst[xctx->sel_array[0].n].name), ""), "}]", NULL);
}
unselect_all(1);
xctx->mx_double_save = xctx->mousex_snap;
xctx->my_double_save = xctx->mousey_snap;
if(argc > 3) {
@ -3646,13 +3726,28 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* polygon
* Start a GUI placement of a polygon */
/* polygon [gui]
* Start a GUI placement of a polygon
* if `gui` argument is given start a polygon GUI placement with 1st point
* set to current mouse coordinates */
else if(!strcmp(argv[1], "polygon"))
{
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
if(argc > 2 && !strcmp(argv[2], "gui")) {
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
}
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
}
}
/* preview_window create|draw|destroy|close [win_path] [file]
@ -3969,8 +4064,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
case 'r': /*----------------------------------------------*/
/* raw what ...
* what = add | clear | datasets | index | info | loaded | list | new | points | rawfile | del |
* read | set | sim_type | switch | switch_back | table_read | value | values | pos_at | vars |
* what = add | clear | datasets | index | info | loaded | list |
* new | points | rawfile | del | read | set | rename |
* sim_type | switch | switch_back | table_read | value | values | pos_at | vars |
*
* xschem raw read filename [type [sweep1 sweep2]]
* if sweep1, sweep2 interval is given in 'read' subcommand load only the interval
@ -3985,6 +4081,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* xschem raw del name
* delete named vector from current raw file
*
* xschem raw rename old_name new_name
* rename a node in the loaded raw file.
*
* xschem raw info
* print information about loaded raw files and show the currently active one.
*
@ -4061,7 +4160,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* new dataset do not start with a header row.
* Lines beginning with '#' are comments and ignored
*
* time var_a var_b var_c
* time var_a var_b var_cnode in the loaded raw file.
* # this is a comment, ignored
* 0.0 0.0 1.8 0.3
* <single empty line: ignored>
@ -4129,9 +4228,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
update_op();
}
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
} else if(argc > 3 && !strcmp(argv[2], "del")) {
ret = raw_deletevar(argv[3]);
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
} else if(argc > 2 && !strcmp(argv[2], "clear")) {
if(argc > 4) {
ret = extra_rawfile(3, argv[3], argv[4], -1.0, -1.0);
@ -4164,6 +4260,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, dtoa(val), TCL_VOLATILE);
}
}
} else if(argc > 3 && !strcmp(argv[2], "del")) {
ret = raw_deletevar(argv[3]);
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
} else if(argc > 4 && !strcmp(argv[2], "rename")) {
ret = raw_renamevar(argv[3], argv[4]);
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
} else if(argc > 3 && !strcmp(argv[2], "index")) {
/* xschem raw index v(ldcp) */
int idx;
@ -4372,7 +4474,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
/* rebuild_connectivity
Rebuild logical connectivity abstraction of schematic */
* Rebuild logical connectivity abstraction of schematic */
else if(!strcmp(argv[1], "rebuild_connectivity"))
{
int err = 0;
@ -4411,14 +4513,19 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
}
/* rect [x1 y1 x2 y2] [pos] [propstring] [draw]
* if 'x1 y1 x2 y2'is given place recangle on current
* layer (rectcolor) at indicated coordinates.
* if 'pos' is given insert at given position in rectangle array.
* if 'pos' set to -1 append rectangle to last element in rectangle array.
* 'propstring' is the attribute string. Set to empty if not given.
* if 'draw' is set to 1 (default) draw the new object, else don't
* If no coordinates are given start a GUI operation of rectangle placement */
/* rect ...
* rect [x1 y1 x2 y2] [pos] [propstring] [draw]
* if 'x1 y1 x2 y2'is given place recangle on current
* layer (rectcolor) at indicated coordinates.
* if 'pos' is given insert at given position in rectangle array.
* if 'pos' set to -1 append rectangle to last element in rectangle array.
* 'propstring' is the attribute string. Set to empty if not given.
* if 'draw' is set to 1 (default) draw the new object, else don't
* rect
* If no coordinates are given start a GUI operation of rectangle placement
* rect gui
* if `gui` argument is given start a GUI placement of a rectangle with 1st
* point starting from current mouse coordinates */
else if(!strcmp(argv[1], "rect"))
{
double x1,y1,x2,y2;
@ -4448,8 +4555,18 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
xctx->draw_window = save;
}
set_modify(1);
}
else {
} else if(argc > 2 && !strcmp(argv[2], "gui")) {
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTRECT;
}
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTRECT;
}
@ -4960,7 +5077,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int n=atoi(argv[3]);
int valid = n < xctx->wires && n >= 0;
if(valid) {
select_wire(n, sel, fast);
select_wire(n, sel, fast, 1);
xctx->ui_state |= SELECTION;
}
Tcl_SetResult(interp, valid ? "1" : "0" , TCL_STATIC);
@ -4970,7 +5087,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int n=atoi(argv[4]);
int valid = n < xctx->lines[c] && n >= 0 && c < cadlayers && c >= 0;
if(valid) {
select_line(c, n, sel, fast);
select_line(c, n, sel, fast, 0);
xctx->ui_state |= SELECTION;
}
Tcl_SetResult(interp, valid ? "1" : "0" , TCL_STATIC);
@ -4990,7 +5107,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int n=atoi(argv[4]);
int valid = n < xctx->arcs[c] && n >= 0 && c < cadlayers && c >= 0;
if(valid) {
select_arc(c, n, sel, fast);
select_arc(c, n, sel, fast, 0);
xctx->ui_state |= SELECTION;
}
Tcl_SetResult(interp, valid ? "1" : "0" , TCL_STATIC);
@ -5000,7 +5117,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int n=atoi(argv[4]);
int valid = n < xctx->polygons[c] && n >= 0 && c < cadlayers && c >= 0;
if(valid) {
select_polygon(c, n, sel, fast);
select_polygon(c, n, sel, fast, 0);
xctx->ui_state |= SELECTION;
}
Tcl_SetResult(interp, valid ? "1" : "0" , TCL_STATIC);
@ -5009,7 +5126,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int n=atoi(argv[3]);
int valid = n < xctx->texts && n >= 0;
if(valid) {
select_text(n, sel, fast);
select_text(n, sel, fast, 0);
xctx->ui_state |= SELECTION;
}
Tcl_SetResult(interp, valid ? "1" : "0" , TCL_STATIC);
@ -5461,7 +5578,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
} else {
char *translated_sym = NULL;
int sym_number = -1;
char *subst = NULL;
char *subst = NULL, *old_name = NULL;;
if(!fast) {
symbol_bbox(inst, &xctx->inst[inst].x1, &xctx->inst[inst].y1, &xctx->inst[inst].x2, &xctx->inst[inst].y2);
xctx->push_undo();
@ -5469,7 +5587,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
xctx->prep_hash_inst=0;
xctx->prep_net_structs=0;
xctx->prep_hi_structs=0;
if(argc > 4 && !strcmp(argv[4], "name") && fast == 0) hash_names(-1, XINSERT);
if(argc > 4 && !strcmp(argv[4], "name")) {
if(fast == 0) {
hash_names(-1, XINSERT);
}
my_strdup2(_ALLOC_ID_, &old_name, xctx->inst[inst].instname);
}
if(argc > 5) {
if(!strcmp(argv[4], "allprops")) {
hash_names(-1, XINSERT);
@ -5486,7 +5609,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
hash_names(inst, XDELETE);
new_prop_string(inst, subst, tclgetboolvar("disable_unique_names"));
if(old_name) {
update_attached_floaters(old_name, inst, 0);
}
my_strdup2(_ALLOC_ID_, &translated_sym, translate(inst, xctx->inst[inst].name));
sym_number=match_symbol(translated_sym);
@ -5495,6 +5620,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
xctx->inst[inst].ptr=sym_number;
}
if(subst) my_free(_ALLOC_ID_, &subst);
if(old_name) my_free(_ALLOC_ID_, &old_name);
set_inst_flags(&xctx->inst[inst]);
hash_names(inst, XINSERT);
if(!fast) {
@ -5927,22 +6053,22 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
select_element(n, SELECTED, 1, 1);
break;
case WIRE:
select_wire(n, SELECTED, 1);
select_wire(n, SELECTED, 1, 1);
break;
case xTEXT:
select_text(n, SELECTED, 1);
select_text(n, SELECTED, 1, 1);
break;
case xRECT:
select_box(c, n, SELECTED, 1, 0);
select_box(c, n, SELECTED, 1, 1);
break;
case LINE:
select_line(c, n, SELECTED, 1);
select_line(c, n, SELECTED, 1, 1);
break;
case POLYGON:
select_polygon(c, n, SELECTED, 1);
select_polygon(c, n, SELECTED, 1, 1);
break;
case ARC:
select_arc(c, n, SELECTED, 1);
select_arc(c, n, SELECTED, 1, 1);
break;
}
}
@ -6215,6 +6341,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* unselect_attached_floaters
* Unselect objects (not symbol instances) attached to some instance with a
* non empty name=... attribute */
else if(!strcmp(argv[1], "unselect_attached_floaters"))
{
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
unselect_attached_floaters();
}
/* update_all_sym_bboxes
* Update all symbol bounding boxes */
else if(!strcmp(argv[1], "update_all_sym_bboxes"))
@ -6295,8 +6429,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
/* wire [x1 y1 x2 y2] [pos] [prop] [sel]
* wire
* wire gui
* Place a new wire
* if no coordinates are given start a GUI wire placement */
* if no coordinates are given start a GUI wire placement
* if `gui` argument is given start a GUI placement of a wire with 1st point
* starting from current mouse coordinates */
else if(!strcmp(argv[1], "wire"))
{
double x1,y1,x2,y2;
@ -6324,7 +6462,21 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(tclgetboolvar("autotrim_wires")) trim_wires();
set_modify(1);
}
else {
else if(argc > 2 && !strcmp(argv[2], "gui")) {
int prev_state = xctx->ui_state;
int infix_interface = tclgetboolvar("infix_interface");
if(infix_interface) {
start_wire(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTWIRE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTWIRE;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTWIRE;

View File

@ -735,7 +735,7 @@ void bbox(int what,double x1,double y1, double x2, double y2)
/* n = -1 : clear first selected info
* n = -2 : return first selected element if still selected, or get first from
* selected list. Id no elements selected return first selected item (j = 0)
* selected list. If no elements selected return first selected item (j = 0)
* n >= 0 : store indicated element as first selected
*/
int set_first_sel(unsigned short type, int n, unsigned int col)
@ -896,10 +896,12 @@ void unselect_all(int dr)
}
}
void select_wire(int i,unsigned short select_mode, int fast)
void select_wire(int i,unsigned short select_mode, int fast, int override_lock)
{
char str[1024]; /* overflow safe */
/*my_strncpy(s,xctx->wire[i].prop_ptr!=NULL?xctx->wire[i].prop_ptr:"<NULL>",256); */
if(!strboolcmp(get_tok_value(xctx->wire[i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return;
if( !fast )
{
my_snprintf(str, S(str), "Info: selected wire: n=%d end1=%d end2=%d\nnode=%s",i,
@ -937,6 +939,68 @@ void select_wire(int i,unsigned short select_mode, int fast)
xctx->need_reb_sel_arr=1;
}
static int select_attached_floaters(int inst, const char *name)
{
int i, c;
int found = 0;
char *attach = NULL;
char *att_save, *att_ptr;
if(!name || !name[0]) return found;
my_strdup2(_ALLOC_ID_, &attach, name);
att_ptr = attach;
while( (name = my_strtok_r(att_ptr, " \n", "\"", 0, &att_save)) ) {
att_ptr = NULL;
for(c = 0; c < cadlayers; c++) {
for(i = 0; i < xctx->rects[c]; i++) {
if(!strcmp(name, get_tok_value(xctx->rect[c][i].prop_ptr, "name", 0))) {
found = 1;
select_box(c, i, SELECTED, 1, 1);
}
}
for(i = 0; i < xctx->lines[c]; i++) {
if(!strcmp(name, get_tok_value(xctx->line[c][i].prop_ptr, "name", 0))) {
found = 1;
select_line(c, i, SELECTED, 1, 1);
}
}
for(i = 0; i < xctx->polygons[c]; i++) {
if(!strcmp(name, get_tok_value(xctx->poly[c][i].prop_ptr, "name", 0))) {
found = 1;
select_polygon(c, i, SELECTED, 1, 1);
}
}
for(i = 0; i < xctx->arcs[c]; i++) {
if(!strcmp(name, get_tok_value(xctx->arc[c][i].prop_ptr, "name", 0))) {
found = 1;
select_arc(c, i, SELECTED, 1, 1);
}
}
}
for(i = 0; i < xctx->wires; i++) {
if(!strcmp(name, get_tok_value(xctx->wire[i].prop_ptr, "name", 0))) {
found = 1;
select_wire(i, SELECTED, 1, 1);
}
}
for(i = 0; i < xctx->texts; i++) {
if(!strcmp(name, get_tok_value(xctx->text[i].prop_ptr, "name", 0))) {
found = 1;
select_text(i, SELECTED, 1, 1);
}
}
for(i = 0; i < xctx->instances; i++) {
if(i != inst && !strcmp(name, xctx->inst[i].instname)) {
found = 1;
select_element(i, SELECTED, 1, 0);
}
}
}
my_free(_ALLOC_ID_, &attach);
return found;
}
/* fast == 1: do not update status line
* fast == 2: do not draw / undraw selected elements
* fast == 3: 1 + 2
@ -991,16 +1055,21 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
}
}
}
if(!fast && select_mode == SELECTED) {
select_attached_floaters(i, get_tok_value(xctx->inst[i].prop_ptr, "attach", 0));
}
xctx->need_reb_sel_arr=1;
}
void select_text(int i,unsigned short select_mode, int fast)
void select_text(int i, unsigned short select_mode, int fast, int override_lock)
{
char str[1024]; /* overflow safe */
char s[256]; /* overflow safe */
#if HAS_CAIRO==1
int customfont;
#endif
if(!strboolcmp(get_tok_value(xctx->text[i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return;
if(!fast) {
my_strncpy(s,xctx->text[i].prop_ptr!=NULL?xctx->text[i].prop_ptr:"<NULL>",S(s));
my_snprintf(str, S(str), "Info: selected text %d: properties: %s", i,s);
@ -1075,7 +1144,7 @@ void select_box(int c, int i, unsigned short select_mode, int fast, int override
void select_arc(int c, int i, unsigned short select_mode, int fast)
void select_arc(int c, int i, unsigned short select_mode, int fast, int override_lock)
{
char str[1024]; /* overflow safe */
char s[256]; /* overflow safe */
@ -1105,11 +1174,14 @@ void select_arc(int c, int i, unsigned short select_mode, int fast)
xctx->need_reb_sel_arr=1;
}
void select_polygon(int c, int i, unsigned short select_mode, int fast )
void select_polygon(int c, int i, unsigned short select_mode, int fast, int override_lock )
{
char str[1024]; /* overflow safe */
char s[256]; /* overflow safe */
int bezier;
if(!strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return;
if(!fast)
{
my_strncpy(s,xctx->poly[c][i].prop_ptr!=NULL?xctx->poly[c][i].prop_ptr:"<NULL>",S(s));
@ -1134,10 +1206,13 @@ void select_polygon(int c, int i, unsigned short select_mode, int fast )
xctx->need_reb_sel_arr=1;
}
void select_line(int c, int i, unsigned short select_mode, int fast )
void select_line(int c, int i, unsigned short select_mode, int fast, int override_lock )
{
char str[1024]; /* overflow safe */
char s[256]; /* overflow safe */
if(!strboolcmp(get_tok_value(xctx->line[c][i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return;
if(!fast)
{
my_strncpy(s,xctx->line[c][i].prop_ptr!=NULL?xctx->line[c][i].prop_ptr:"<NULL>",S(s));
@ -1193,19 +1268,19 @@ Selected select_object(double mx,double my, unsigned short select_mode,
{
case WIRE:
if(xctx->wire[sel.n].sel) xctx->already_selected = 1;
select_wire(sel.n, select_mode, 0);
select_wire(sel.n, select_mode, 0, override_lock);
break;
case xTEXT:
if(xctx->text[sel.n].sel) xctx->already_selected = 1;
select_text(sel.n, select_mode, 0);
select_text(sel.n, select_mode, 0, override_lock);
break;
case LINE:
if(xctx->line[sel.col][sel.n].sel) xctx->already_selected = 1;
select_line(sel.col, sel.n, select_mode,0);
select_line(sel.col, sel.n, select_mode,0, override_lock);
break;
case POLYGON:
if(xctx->poly[sel.col][sel.n].sel) xctx->already_selected = 1;
select_polygon(sel.col, sel.n, select_mode,0);
select_polygon(sel.col, sel.n, select_mode,0, override_lock);
break;
case xRECT:
if(xctx->rect[sel.col][sel.n].sel) xctx->already_selected = 1;
@ -1213,11 +1288,11 @@ Selected select_object(double mx,double my, unsigned short select_mode,
break;
case ARC:
if(xctx->arc[sel.col][sel.n].sel) xctx->already_selected = 1;
select_arc(sel.col,sel.n, select_mode,0);
select_arc(sel.col,sel.n, select_mode,0, override_lock);
break;
case ELEMENT:
if(xctx->inst[sel.n].sel) xctx->already_selected = 1;
select_element(sel.n,select_mode,0, override_lock);
select_element(sel.n, select_mode,0, override_lock);
break;
default:
break;
@ -1260,10 +1335,10 @@ void select_attached_nets(void)
for(wptr=xctx->wire_spatial_table[sqx][sqy]; wptr; wptr=wptr->next) {
i = wptr->n;
if(xctx->wire[i].x1 == x0 && xctx->wire[i].y1 == y0) {
select_wire(i,SELECTED1, 1);
select_wire(i,SELECTED1, 1, 0);
}
if(xctx->wire[i].x2 == x0 && xctx->wire[i].y2 == y0) {
select_wire(i,SELECTED2, 1);
select_wire(i,SELECTED2, 1, 0);
}
}
}
@ -1286,10 +1361,10 @@ void select_attached_nets(void)
i = wptr->n;
if(i == wire) continue;
if(xctx->wire[i].x1 == x0 && xctx->wire[i].y1 == y0) {
select_wire(i,SELECTED1, 1);
select_wire(i,SELECTED1, 1, 0);
}
if(xctx->wire[i].x2 == x0 && xctx->wire[i].y2 == y0) {
select_wire(i,SELECTED2, 1);
select_wire(i,SELECTED2, 1, 0);
}
}
}
@ -1316,23 +1391,23 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
if(RECT_INSIDE(xctx->wire[i].x1,xctx->wire[i].y1,xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2))
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
select_wire(i, SELECTED, 1);
select_wire(i, SELECTED, 1, 0);
}
else if(stretch && POINTINSIDE(xctx->wire[i].x1,xctx->wire[i].y1, x1,y1,x2,y2) )
{
xctx->ui_state |= SELECTION;
select_wire(i, SELECTED1, 1);
select_wire(i, SELECTED1, 1, 0);
}
else if(stretch && POINTINSIDE(xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2) )
{
xctx->ui_state |= SELECTION;
select_wire(i, SELECTED2, 1);
select_wire(i, SELECTED2, 1, 0);
}
} else {
if(RECT_INSIDE(xctx->wire[i].x1,xctx->wire[i].y1,xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2))
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
select_wire(i, 0, 1);
select_wire(i, 0, 1, 0);
}
}
}
@ -1358,7 +1433,7 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
if(RECT_INSIDE(xx1,yy1, xx2, yy2,x1,y1,x2,y2))
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
sel ? select_text(i, SELECTED, 1): select_text(i, 0, 1);
sel ? select_text(i, SELECTED, 1, 0): select_text(i, 0, 1, 0);
}
}
for(i=0;i<xctx->instances; ++i)
@ -1367,9 +1442,7 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
if(sel) {
if(strboolcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true")) {
select_element(i, SELECTED, 1, 1);
}
select_element(i, SELECTED, 1, 0);
} else {
select_element(i, 0, 1, 0);
}
@ -1403,14 +1476,14 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
}
if(flag) {
if(selected_points==0) {
select_polygon(c, i, 0, 1);
select_polygon(c, i, 0, 1, 0);
}
if(selected_points==xctx->poly[c][i].points) {
xctx->ui_state |= SELECTION;
select_polygon(c, i, SELECTED, 1);
select_polygon(c, i, SELECTED, 1, 0);
} else if(selected_points) {
/* for polygon, SELECTED1 means partial sel */
if(sel && stretch) select_polygon(c, i, SELECTED1,1);
if(sel && stretch) select_polygon(c, i, SELECTED1, 1, 0);
}
}
@ -1421,23 +1494,23 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
if(RECT_INSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1,xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2))
{
xctx->ui_state |= SELECTION;
select_line(c,i,SELECTED,1);
select_line(c, i, SELECTED, 1, 0);
}
else if(stretch && POINTINSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1, x1,y1,x2,y2) )
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
select_line(c, i,SELECTED1,1);
select_line(c, i, SELECTED1, 1, 0);
}
else if(stretch && POINTINSIDE(xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2) )
{
xctx->ui_state |= SELECTION;
select_line(c, i,SELECTED2,1);
select_line(c, i, SELECTED2, 1, 0);
}
} else {
if(RECT_INSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1,xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2))
{
xctx->ui_state |= SELECTION;
select_line(c,i,0,1);
select_line(c, i, 0, 1, 0);
}
}
}
@ -1454,22 +1527,22 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
arc_bbox(x, y, r, a, b, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2);
if(RECT_INSIDE(tmp.x1, tmp.y1, tmp.x2, tmp.y2, x1,y1,x2,y2)) {
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
sel? select_arc(c, i, SELECTED,1): select_arc(c, i, 0,1);
sel? select_arc(c, i, SELECTED,1, 0): select_arc(c, i, 0,1, 0);
}
else if( sel && stretch && POINTINSIDE(x, y, x1, y1, x2, y2) )
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
select_arc(c, i,SELECTED1,1);
select_arc(c, i,SELECTED1,1, 0);
}
else if( sel && stretch && POINTINSIDE(xb, yb, x1, y1, x2, y2) )
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
select_arc(c, i,SELECTED3,1);
select_arc(c, i,SELECTED3,1, 0);
}
else if( sel && stretch && POINTINSIDE(xa, ya, x1, y1, x2, y2) )
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
select_arc(c, i,SELECTED2,1);
select_arc(c, i,SELECTED2,1, 0);
}
}
for(i=0;i<xctx->rects[c]; ++i)
@ -1480,9 +1553,7 @@ void select_inside(int stretch, double x1,double y1, double x2, double y2, int s
if(sel) {
if(strboolcmp(get_tok_value(xctx->rect[c][i].prop_ptr, "lock", 0), "true")) {
select_box(c,i, SELECTED, 1, 1);
}
select_box(c,i, SELECTED, 1, 0);
} else {
select_box(c,i, 0, 1, 0);
}
@ -1544,7 +1615,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
ly2 = xctx->wire[i].y2;
if(lineclip(&lx1, &ly1, &lx2, &ly2, x1,y1,x2,y2)) {
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
sel ? select_wire(i,SELECTED, 1): select_wire(i,0, 1);
sel ? select_wire(i,SELECTED, 1, 0): select_wire(i,0, 1, 0);
}
}
for(i=0;i<xctx->texts; ++i)
@ -1570,7 +1641,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
if(RECT_TOUCH(xx1, yy1, xx2, yy2,x1,y1,x2,y2))
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
sel ? select_text(i, SELECTED, 1): select_text(i, 0, 1);
sel ? select_text(i, SELECTED, 1, 0): select_text(i, 0, 1, 0);
}
}
for(i=0;i<xctx->instances; ++i)
@ -1579,9 +1650,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
if(sel) {
if(strboolcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true")) {
select_element(i, SELECTED, 1, 1);
}
select_element(i, SELECTED, 1, 0);
} else {
select_element(i, 0, 1, 0);
}
@ -1605,7 +1674,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
}
}
if(flag) {
sel ? select_polygon(c, i, SELECTED, 1): select_polygon(c, i, 0, 1);
sel ? select_polygon(c, i, SELECTED, 1, 0): select_polygon(c, i, 0, 1, 0);
}
}
for(i=0;i<xctx->lines[c]; ++i)
@ -1617,7 +1686,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
ly2 = xctx->line[c][i].y2;
if(lineclip(&lx1, &ly1, &lx2, &ly2, x1,y1,x2,y2)) {
xctx->ui_state |= SELECTION;
sel? select_line(c,i,SELECTED,1): select_line(c,i,0,1);
sel? select_line(c, i, SELECTED, 1, 0): select_line(c, i, 0, 1, 0);
}
}
for(i=0;i<xctx->arcs[c]; ++i) {
@ -1633,7 +1702,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
arc_bbox(x, y, r, a, b, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2);
if(RECT_TOUCH(tmp.x1, tmp.y1, tmp.x2, tmp.y2, x1,y1,x2,y2)) {
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
sel? select_arc(c, i, SELECTED,1): select_arc(c, i, 0,1);
sel? select_arc(c, i, SELECTED,1, 0): select_arc(c, i, 0,1, 0);
}
}
for(i=0;i<xctx->rects[c]; ++i)
@ -1642,9 +1711,7 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
{
xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */
if(sel) {
if(strboolcmp(get_tok_value(xctx->rect[c][i].prop_ptr, "lock", 0), "true")) {
select_box(c,i, SELECTED, 1, 1);
}
select_box(c,i, SELECTED, 1, 0);
} else {
select_box(c,i, 0, 1, 0);
}
@ -1688,6 +1755,8 @@ int floaters_from_selected_inst()
}
my_strdup2(_ALLOC_ID_, &xctx->inst[i].prop_ptr,
subst_token(xctx->inst[i].prop_ptr, "hide_texts", "true"));
my_strdup2(_ALLOC_ID_, &xctx->inst[i].prop_ptr,
subst_token(xctx->inst[i].prop_ptr, "attach", xctx->inst[i].instname));
set_inst_flags(&xctx->inst[i]);
for(t = 0; t < sym->texts; t++) {
double txtx0, txty0;
@ -1730,33 +1799,35 @@ void select_all(void)
for(i=0;i<xctx->wires; ++i)
{
select_wire(i,SELECTED, 1);
select_wire(i,SELECTED, 1, 0);
}
for(i=0;i<xctx->texts; ++i)
{
select_text(i, SELECTED, 1);
select_text(i, SELECTED, 1, 0);
}
for(i=0;i<xctx->instances; ++i)
{
select_element(i,SELECTED,1, 0);
select_element(i, SELECTED, 1, 0);
/* following not done in select_element() due to fast=1 argument */
select_attached_floaters(i, get_tok_value(xctx->inst[i].prop_ptr, "attach", 0));
}
for(c=0;c<cadlayers; ++c)
{
for(i=0;i<xctx->polygons[c]; ++i)
{
select_polygon(c,i,SELECTED,1);
select_polygon(c, i, SELECTED, 1, 0);
}
for(i=0;i<xctx->lines[c]; ++i)
{
select_line(c,i,SELECTED,1);
select_line(c, i, SELECTED, 1, 0);
}
for(i=0;i<xctx->arcs[c]; ++i)
{
select_arc(c,i, SELECTED, 1);
select_arc(c, i, SELECTED, 1, 0);
}
for(i=0;i<xctx->rects[c]; ++i)
{
select_box(c,i, SELECTED, 1, 0);
select_box(c, i, SELECTED, 1, 0);
}
} /* end for c */
drawtemparc(xctx->gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0, 0.0);

View File

@ -275,7 +275,7 @@ function process( i,j, iprefix, saveinstr, savetype, saveanalysis)
} else if( $1 ~ /^\*\.(ipin|opin|iopin)/ ) {
num=split($2,name,",")
for(i=1;i<=num;i++) print $1 " " name[i]
} else if( $1 ~ /\.subckt/) {
} else if( tolower($1) ~ /\.subckt/) {
# remove m=.. from subcircuit definition since m= is a multiplier not a param
sub(/ m=[0-9]+/," ",$0)
gsub(","," ",$0)

View File

@ -173,10 +173,9 @@ static int spice_netlist(FILE *fd, int spice_stop )
int err = 0;
int i, flag = 0;
const char *type;
int top_sub;
int top_sub = tclgetboolvar("lvs_netlist") || tclgetboolvar("top_is_subckt");
int lvs_ignore = tclgetboolvar("lvs_ignore");
top_sub = tclgetboolvar("lvs_netlist") || tclgetboolvar("top_is_subckt");
if(!spice_stop) {
dbg(1, "spice_netlist(): invoke prepare_netlist_structs for %s\n", xctx->current_name);
xctx->prep_net_structs = 0;
@ -278,6 +277,7 @@ int global_spice_netlist(int global, int alert) /* netlister driver */
int found_top_symbol = 0;
int npins = 0; /* top schematic number of i/o ports */
Sch_pin_record *pinnumber_list = NULL; /* list of top sch i/o ports ordered wrt sim_pinnumber attr */
int uppercase_subckt = tclgetboolvar("uppercase_subckt");
exit_code = 0; /* reset exit code */
split_f = tclgetboolvar("split_files");
@ -341,7 +341,10 @@ int global_spice_netlist(int global, int alert) /* netlister driver */
}
top_sub = tclgetboolvar("lvs_netlist") || tclgetboolvar("top_is_subckt");
if(!top_sub) fprintf(fd,"**");
fprintf(fd,".subckt %s", get_cell(xctx->sch[xctx->currsch], 0));
if(uppercase_subckt)
fprintf(fd,".SUBCKT %s", get_cell(xctx->sch[xctx->currsch], 0));
else
fprintf(fd,".subckt %s", get_cell(xctx->sch[xctx->currsch], 0));
pinnumber_list = sort_schematic_pins(&npins); /* sort pins according to sim_pinnumber attr */
/* print top subckt ipin/opins */
@ -405,7 +408,10 @@ int global_spice_netlist(int global, int alert) /* netlister driver */
/* /20100217 */
if(!top_sub) fprintf(fd,"**");
fprintf(fd, ".ends\n");
if(uppercase_subckt)
fprintf(fd, ".ENDS\n");
else
fprintf(fd, ".ends\n");
if(split_f) {
@ -572,7 +578,7 @@ int global_spice_netlist(int global, int alert) /* netlister driver */
/* 20150922 added split_files check */
if(!split_f) fprintf(fd, ".end\n");
if( !top_sub && !split_f) fprintf(fd, ".end\n");
dbg(1, "global_spice_netlist(): starting awk on netlist!\n");
@ -612,7 +618,8 @@ int spice_block_netlist(FILE *fd, int i, int alert)
char *sym_def = NULL;
char *name = NULL;
const char *default_schematic;
int uppercase_subckt = tclgetboolvar("uppercase_subckt");
split_f = tclgetboolvar("split_files");
if(!strboolcmp( get_tok_value(xctx->sym[i].prop_ptr,"spice_stop",0),"true") )
@ -657,7 +664,10 @@ int spice_block_netlist(FILE *fd, int i, int alert)
} else {
const char *s = get_cell(sanitize(name), 0);
fprintf(fd, "** sch_path: %s\n", sanitized_abs_sym_path(filename, ""));
fprintf(fd, ".subckt %s ", s);
if(uppercase_subckt)
fprintf(fd, ".SUBCKT %s ", s);
else
fprintf(fd, ".subckt %s ", s);
print_spice_subckt_nodes(fd, i);
my_strdup(_ALLOC_ID_, &extra, get_tok_value(xctx->sym[i].prop_ptr,"extra",0) );
@ -680,7 +690,10 @@ int spice_block_netlist(FILE *fd, int i, int alert)
fprintf(fd, "%s\n", xctx->schprop);
fprintf(fd,"**** end user architecture code\n");
}
fprintf(fd, ".ends\n\n");
if(uppercase_subckt)
fprintf(fd, ".ENDS\n\n");
else
fprintf(fd, ".ends\n\n");
}
if(split_f) {
int save;

View File

@ -1035,7 +1035,7 @@ void svg_draw(void)
{
if(xctx->rect[c][i].flags & 1) { /* graph */
xRect *r = &xctx->rect[c][i];
svg_embedded_graph(fd, r, r->x1, r->y1, r->x2, r->y2);
svg_embedded_graph(fd, i, r->x1, r->y1, r->x2, r->y2);
}
}
}

View File

@ -184,6 +184,7 @@ int match_symbol(const char *name) /* never returns -1, if symbol not found loa
int i,found;
found=0;
dbg(1, "match_symbol(): name=%s\n", name);
for(i=0;i<xctx->symbols; ++i) {
/* dbg(1, "match_symbol(): name=%s, sym[i].name=%s\n",name, xctx->sym[i].name);*/
if(xctx->x_strcmp(name, xctx->sym[i].name) == 0)
@ -1198,8 +1199,8 @@ static void print_vhdl_primitive(FILE *fd, int inst) /* netlist primitives, 200
}
}
my_strdup2(_ALLOC_ID_, &result, tcl_hook2(result)); /* tcl evaluation if tcleval(....) */
if(strstr(result, "expr(") ) {
result = eval_expr(result);
if(strstr(result, "expr(")) {
my_strdup2(_ALLOC_ID_, &result, eval_expr(result));
}
dbg(1, "print_vhdl_primitive(): after translate3() result=%s\n", result);
}
@ -2152,7 +2153,8 @@ int print_spice_element(FILE *fd, int inst)
const char *str_ptr=NULL;
register int c, state=TOK_BEGIN, space;
char *template=NULL,*format=NULL, *s, *name=NULL, *token=NULL;
const char *lab, *value = NULL;
const char *lab;
const char *value = NULL;
/* char *translatedvalue = NULL; */
size_t sizetok=0;
size_t token_pos=0;
@ -2462,8 +2464,8 @@ int print_spice_element(FILE *fd, int inst)
value = spiceprefixtag;
}
if(strstr(value, "expr(") ) {
value = eval_expr(value);
if(strstr(value, "expr(")) {
value = eval_expr(value);
}
/* token=%xxxx and xxxx is not defined in prop_ptr or template: return xxxx */
if(!token_exists && token[0] =='%') {
@ -2517,8 +2519,8 @@ int print_spice_element(FILE *fd, int inst)
if(result) {
my_strdup(_ALLOC_ID_, &result, tcl_hook2(result));
}
if(strstr(result, "expr(") ) {
result = eval_expr(result);
if(strstr(result, "expr(")) {
my_strdup2(_ALLOC_ID_, &result, eval_expr(result));
}
if(result) fprintf(fd, "%s", result);
dbg(1, "print_spice_element(): returning |%s|\n", result);
@ -3154,8 +3156,8 @@ static void print_verilog_primitive(FILE *fd, int inst) /* netlist switch level
}
}
my_strdup2(_ALLOC_ID_, &result, tcl_hook2(result)); /* tcl evaluation if tcleval(....) */
if(strstr(result, "expr(") ) {
result = eval_expr(result);
if(strstr(result, "expr(")) {
my_strdup2(_ALLOC_ID_, &result, eval_expr(result));
}
dbg(1, "print_verilog_primitive(): after translate3() result=%s\n", result);
}
@ -3779,6 +3781,99 @@ const char *spice_get_node(const char *token)
}
/* caller must free returned value
* get the full pathname of "instname" device
* modelparam:
* 0: current, 1: modelparam, 2: modelvoltage
* param: device parameter, like "ib", "gm", "vth"
* set param to {} (empty str) for just branch current of 2 terminal device
* for parameters like "vth" modelparam must be 2
* for parameters like "ib" modelparam must be 0
* for parameters like "gm" modelparam must be 1
*/
char *get_fqdevice(const char *param, int modelparam, const char *instname)
{
int start_level; /* hierarchy level where waves were loaded */
char *fqdev = NULL;
const char *path = xctx->sch_path[xctx->currsch] + 1;
char *dev = NULL;
size_t len;
int idx;
int sim_is_xyce = tcleval("sim_is_xyce")[0] == '1' ? 1 : 0;
int skip = 0;
char *iprefix = modelparam == 0 ? "i(" : modelparam == 1 ? "" : "v(";
char *ipostfix = modelparam == 1 ? "" : ")";
int prefix;
start_level = sch_waves_loaded();
/* skip path components that are above the level where raw file was loaded */
while(*path && skip < start_level) {
if(*path == '.') skip++;
++path;
}
my_strdup2(_ALLOC_ID_, &dev, instname);
strtolower(dev);
prefix=dev[0];
len = strlen(path) + strlen(dev) + 40; /* some extra chars for i(..) wrapper */
fqdev = my_malloc(_ALLOC_ID_, len);
if(!sim_is_xyce) {
int vsource = (prefix == 'v') || (prefix == 'e');
if(path[0]) {
if(vsource) {
my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev);
} else if(prefix=='q') {
my_snprintf(fqdev, len, "%s@%c.%s%s[%s]%s",
iprefix, prefix, path, dev, param ? param : "ic", ipostfix);
} else if(prefix=='d' || prefix == 'm') {
my_snprintf(fqdev, len, "%s@%c.%s%s[%s]%s",
iprefix, prefix, path, dev, param ? param : "id", ipostfix);
} else if(prefix=='i') {
my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev);
} else {
my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev);
}
} else {
if(vsource) {
my_snprintf(fqdev, len, "i(%s)", dev);
} else if(prefix == 'q') {
my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "ic", ipostfix);
} else if(prefix == 'd' || prefix == 'm') {
my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "id", ipostfix);
} else if(prefix == 'i') {
my_snprintf(fqdev, len, "i(@%s[current])", dev);
} else {
my_snprintf(fqdev, len, "i(@%s[i])", dev);
}
}
} else {
my_snprintf(fqdev, len, "i(%s%s)", path, dev);
}
dbg(1, "fqdev=%s\n", fqdev);
strtolower(fqdev);
idx = get_raw_index(fqdev, NULL);
/* 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);
}
my_free(_ALLOC_ID_, &dev);
return fqdev;
}
/* substitute given tokens in a string with their corresponding values */
/* ex.: name=@name w=@w l=@l ---> name=m112 w=3e-6 l=0.8e-6 */
/* if s==NULL return emty string */

View File

@ -1179,7 +1179,7 @@ static int source_tcl_file(char *s)
fprintf(errfp, "Tcl_AppInit() error: can not execute %s, please fix:\n", s);
fprintf(errfp, "%s", tclresult());
#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >=6
fprintf(errfp, "Line No: %d\n", Tcl_GetErrorLine(interp));
fprintf(errfp, "\nLine No: %d\n", Tcl_GetErrorLine(interp));
#endif
fprintf(errfp, "\n");
#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >=6
@ -1666,6 +1666,7 @@ static void create_new_window(int *window_count, const char *noconfirm, const ch
tclvareval("set_bindings ", window_path[n], NULL);
tclvareval("set_replace_key_binding ", window_path[n], NULL);
tclvareval("save_ctx ", window_path[n], NULL);
tcleval("eval_user_startup_commands");
/* restore previous context,
* because the Expose event after new window creation does a context switch prev win -> new win
*
@ -2060,6 +2061,7 @@ void change_linewidth(double w)
double cs = tclgetdoublevar("cadsnap");
if(tclgetboolvar("change_lw")) {
xctx->lw=xctx->mooz * 0.09 * cs;
if(xctx->lw > 100.) xctx->lw = 100.;
xctx->cadhalfdotsize = CADHALFDOTSIZE * (cs < 20. ? cs : 20.) / 10.;
}
/* explicitly set line width */
@ -2891,6 +2893,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
if(has_x) {
tclsetintvar("tctx::max_new_windows", MAX_NEW_WINDOWS);
tcleval("pack_widgets; set_bindings .drw");
tcleval("eval_user_startup_commands");
}
fs=tclgetintvar("fullscreen");

View File

@ -163,8 +163,8 @@ extern char win_temp_dir[PATH_MAX];
#define CADINITIALY -870
#define CADZOOMSTEP 1.2
#define CADMOVESTEP 200
#define CADMAXZOOM 1000000.0
#define CADMINZOOM 0.000001
#define CADMAXZOOM 10000.0
#define CADMINZOOM 0.005
#define CADHALFDOTSIZE 3.7
#define CADNULLNODE -1 /* no valid node number */
#define CADWIREMINDIST 8.0
@ -375,7 +375,7 @@ extern char win_temp_dir[PATH_MAX];
* show_label also used on metal option type symbols (pass-through symbols)
* to optionally short two nets (using *_ignore=[true|false] attribute) */
#define IS_LABEL_SH_OR_PIN(type) (!(strcmp(type,"label") && strcmp(type,"ipin") && strcmp(type,"opin") && \
strcmp(type,"show_label") && strcmp(type,"iopin") && strcmp(type,"bus_tap")))
strcmp(type,"scope") && strcmp(type,"show_label") && strcmp(type,"iopin") && strcmp(type,"bus_tap")))
#define IS_LABEL_OR_PIN(type) (!(strcmp(type,"label") && strcmp(type,"ipin") && \
strcmp(type,"opin") && strcmp(type,"iopin")))
#define IS_PIN(type) (!(strcmp(type,"ipin") && strcmp(type,"opin") && strcmp(type,"iopin")))
@ -954,7 +954,7 @@ typedef struct {
int lastsel;
int maxsel;
Selected *sel_array;
Selected first_sel; /* first selected instance (used as master when editing multile pbjects) */
Selected first_sel; /* first selected instance (used as master when editing multiple objects) */
int prep_net_structs;
int prep_hi_structs;
int prep_hash_inst;
@ -1259,6 +1259,7 @@ extern int embed_rawfile(const char *rawfile);
extern int read_rawfile_from_attr(const char *b64s, size_t length, const char *type);
extern int raw_read_from_attr(Raw **rawptr, const char *type, double sweep1, double sweep2);
extern int raw_add_vector(const char *varname, const char *expr, int sweep_idx);
extern int raw_renamevar(const char *old_name, const char *new_name);
extern int raw_deletevar(const char *name);
extern int new_rawfile(const char *name, const char *type, const char *sweepvar,
double start, double end, double step);
@ -1329,7 +1330,7 @@ extern int process_options(int argc, char **argv);
extern void calc_drawing_bbox(xRect *boundbox, int selected);
extern int ps_draw(int what, int fullzoom, int eps);
extern void svg_draw(void);
extern void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2, double ry2);
extern void svg_embedded_graph(FILE *fd, int i, double rx1, double ry1, double rx2, double ry2);
extern void set_viewport_size(int w, int h, double lw);
extern void print_image();
extern const char *get_trailing_path(const char *str, int no_of_dir, int skip_ext);
@ -1400,9 +1401,11 @@ extern void tclmainloop(void);
extern int Tcl_AppInit(Tcl_Interp *interp);
extern void abort_operation(void);
extern void draw_crosshair(int what, int state);
extern void draw_snap_cursor(int what);
extern void start_line(double mx, double my);
extern void start_wire(double mx, double my);
extern void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr);
/* extern void snapped_wire(double c_snap); */
extern void unselect_attached_floaters(void);
extern int callback(const char *win_path, int event, int mx, int my, KeySym key,
int button, int aux, int state);
extern void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h);
@ -1425,6 +1428,7 @@ extern void filledrect(int c, int what, double rectx1,double recty1,
extern void drawtempline(GC gc, int what, double x1,double y1,double x2,double y2);
extern void drawtemp_manhattanline(GC gc, int what, double x1,double y1,double x2,double y2);
/* instead of doing a drawtemprect(xctx->gctiled, NOW, ....) do 4
* XCopy Area operations. Used if fix_broken_tiled_fill is set */
@ -1547,6 +1551,8 @@ extern void new_line(int what, double mx_snap, double my_snap);
extern void new_arc(int what, double sweep, double mousex_snap, double mousey_snap);
extern void arc_3_points(double x1, double y1, double x2, double y2, double x3, double y3,
double *x, double *y, double *r, double *a, double *b);
/* sel: if set to 1 change references only on selected items, like in a copy operation */
extern void update_attached_floaters(const char *from_name, int inst, int sel);
extern void move_objects(int what,int merge, double dx, double dy);
extern void check_collapsing_objects();
extern void redraw_w_a_l_r_p_z_rubbers(int force); /* redraw wire, arcs, line, polygon rubbers */
@ -1611,6 +1617,7 @@ extern char *trim_chars(const char *str, const char *sep);
extern char *find_nth(const char *str, const char *sep, const char *quote, int keep_quote, int n);
extern int isonlydigit(const char *s);
extern const char *spice_get_node(const char *token);
extern char *get_fqdevice(const char *param, int modelparam, const char *instname);
extern const char *translate(int inst, const char* s);
extern const char* translate2(Lcc *lcc, int level, char* s);
extern const char *translate3(const char* s, int eat_escapes, const char *s1,
@ -1688,13 +1695,13 @@ extern const char *expandlabel(const char *s, int *m);
extern void parse(const char *s);
extern void clear_expandlabel_data(void);
extern void merge_file(int selection_load, const char ext[]);
extern void select_wire(int i, unsigned short select_mode, int fast);
extern void select_wire(int i, unsigned short select_mode, int fast, int override_lock);
extern void select_element(int i, unsigned short select_mode, int fast, int override_lock);
extern void select_text(int i, unsigned short select_mode, int fast);
extern void select_text(int i, unsigned short select_mode, int fast, int override_lock);
extern void select_box(int c, int i, unsigned short select_mode, int fast, int override_lock);
extern void select_arc(int c, int i, unsigned short select_mode, int fast);
extern void select_line(int c, int i, unsigned short select_mode, int fast);
extern void select_polygon(int c, int i, unsigned short select_mode, int fast );
extern void select_arc(int c, int i, unsigned short select_mode, int fast, int override_lock);
extern void select_line(int c, int i, unsigned short select_mode, int fast, int override_lock);
extern void select_polygon(int c, int i, unsigned short select_mode, int fast, int override_lock );
extern const char *net_name(int i, int j, int *mult, int hash_prefix_unnamed_net, int erc);
extern int record_global_node(int what, FILE *fp, const char *node);
extern int count_items(const char *s, const char *sep, const char *quote);

View File

@ -628,6 +628,10 @@ proc from_eng {i} {
## convert number to engineering form
proc to_eng {args} {
set suffix {}
if {[ catch {uplevel #0 expr [join $args]} i]} {
return [join $args]
}
set i [uplevel #0 expr [join $args]]
set absi [expr {abs($i)}]
@ -1836,6 +1840,7 @@ proc simconf_add {tool} {
############ cellview
# proc cellview prints symbol bindings (default binding or "schematic" attr in symbol)
# of all symbols used in current and sub schematics.
# the derived_symbols parameter of cellview should be either empty or 'derived_symbols'
proc cellview_setlabels {w symbol derived_symbol} {
global dark_gui_colorscheme netlist_type
if {$dark_gui_colorscheme} {
@ -1937,6 +1942,8 @@ proc cellview_edit_sym {w} {
xschem load_new_window $sym
}
# derived_symbols: empty or 'derived_symbols'
# upd: never set by caller (used iinternally to update)
proc cellview { {derived_symbols {}} {upd 0}} {
global keep_symbols nolist_libs dark_gui_colorscheme netlist_type
@ -2095,10 +2102,9 @@ proc traversal_setlabels {w parent_sch instname inst_sch sym_sch default_sch
set save_netlist_type [xschem get netlist_type]
# puts "traversal_setlabels: $w parent: |$parent_sch| inst: $instname def: $sym_sch $inst_sch --> [$w get]"
# update schematic
if {$parent_sch ne {}} {
if {$parent_sch ne {} && $sym_spice_sym_def eq {} && $inst_spice_sym_def eq {} } {
set current [xschem get current_name]
if { $inst_sch ne [$w get] } {
puts "update attr"
xschem load -undoreset -nodraw $parent_sch
if { [$w get] eq $sym_sch} {
xschem setprop -fast instance $instname schematic ;# remove schematic attr on instance
@ -2224,6 +2230,7 @@ proc hier_traversal {{level 0} {only_subckts 0} {all_hierarchy 1}} {
set instances [xschem get instances]
set current_level [xschem get currsch]
for {set i 0} { $i < $instances} { incr i} {
# puts "hier_traversal: i=$i, current_level=$current_level, parent_sch=$parent_sch"
set instname [xschem getprop instance $i name]
set symbol [xschem getprop instance $i cell::name]
set default_sch [add_ext $symbol .sch]
@ -2301,8 +2308,10 @@ proc hier_traversal {{level 0} {only_subckts 0} {all_hierarchy 1}} {
if {$descended} {
incr level
set dp [hier_traversal $level $only_subckts 1]
xschem go_back 1
xschem go_back 2
incr level -1
} else { ;# descended into a blank schematic. Go back.
xschem go_back 2
}
}
}
@ -3973,6 +3982,7 @@ proc open_sub_schematic {{inst {}} {inst_number 0}} {
proc is_xschem_file {f} {
# puts "is_xschem_file $f"
regsub {\(.*} $f {} f ;# remove trailing generator args (gen.tcl(....)) if any
if { ![file exists $f] } { return 0
} elseif { [file isdirectory $f] } { return 0 }
@ -3987,6 +3997,13 @@ proc is_xschem_file {f} {
} else {
fconfigure $fd -translation binary
while { [gets $fd line] >=0 } {
#### Can not use this. schematics may containg 8 bit extended characters
# if {[regexp {[^[:print:][:space:]]} $line]} { ;# line contains non ascii chars
# close $fd
# return 0
# }
# this is a script. not an xschem file
if { $nline == 0 && [regexp {^#!} $line] } {
#### too dangerous executing an arbitrary script...
@ -4365,8 +4382,10 @@ proc file_dialog_display_preview {f} {
proc file_dialog_right_listboxselect {dirselect} {
global file_dialog_yview file_dialog_dir1 file_dialog_dir2 file_dialog_retval file_dialog_sel
global OS file_dialog_loadfile file_dialog_index1 file_dialog_files1 file_dialog_globfilter
global file_dialog_others
set file_dialog_yview [.load.l.paneright.f.list yview]
set file_dialog_sel [.load.l.paneright.f.list curselection]
set file_dialog_sel [lindex [.load.l.paneright.f.list curselection] 0]
if { $file_dialog_sel ne {} } {
set curr_dir [abs_sym_path [lindex $file_dialog_files1 $file_dialog_index1]]
set curr_item [.load.l.paneright.f.list get $file_dialog_sel]
@ -4399,6 +4418,17 @@ proc file_dialog_right_listboxselect {dirselect} {
set file_dialog_dir1 $curr_dir
set file_dialog_dir2 $curr_item
set file_dialog_others {}
if {$file_dialog_loadfile == 1} {
foreach i [lrange [.load.l.paneright.f.list curselection] 1 end] {
set file_dialog_retval [.load.l.paneright.f.list get $i]
lappend file_dialog_others [file_dialog_getresult 1 0]
}
}
set file_dialog_retval {} ;# we used this variable above to communicate with file_dialog_getresult
if { [file isdirectory $file_dialog_d]} {
bind .load.l.paneright.draw <Expose> {}
bind .load.l.paneright.draw <Configure> {}
@ -4421,6 +4451,16 @@ proc file_dialog_right_listboxselect {dirselect} {
}
}
proc load_additional_files {} {
global file_dialog_others
if {$file_dialog_others ne {} } {
foreach i $file_dialog_others {
xschem load_new_window $i
}
}
}
# global_initdir: name of global variable containing the initial directory
# loadfile: set to 0 if calling for saving instead of loading a file
# set to 2 for non blocking operation (symbol insertion)
@ -4458,7 +4498,8 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
set_ne file_dialog_files2 {}
panedwindow .load.l -orient horizontal -height 8c
if { $loadfile == 2} {frame .load.l.recent -takefocus 0}
frame .load.l.paneleft -takefocus 0 -highlightcolor red -highlightthickness 2 -bg {grey90}
frame .load.l.paneleft -takefocus 0 -highlightcolor red -highlightthickness 2 -bg {grey90} \
-highlightbackground [option get . background {}]
eval [subst {listbox .load.l.paneleft.list -listvariable file_dialog_names1 -width 40 -height 12 \
-fg black -background {grey90} -highlightthickness 0 -relief flat -borderwidth 0 \
-yscrollcommand ".load.l.paneleft.yscroll set" -selectmode browse \
@ -4469,9 +4510,6 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
file_dialog_set_colors1
scrollbar .load.l.paneleft.yscroll -command ".load.l.paneleft.list yview" -takefocus 0
scrollbar .load.l.paneleft.xscroll -command ".load.l.paneleft.list xview" -orient horiz -takefocus 0
pack .load.l.paneleft.yscroll -side right -fill y
pack .load.l.paneleft.xscroll -side bottom -fill x
pack .load.l.paneleft.list -fill both -expand true -padx 12
bind .load.l.paneleft.list <<ListboxSelect>> {
set file_dialog_sel [.load.l.paneleft.list curselection]
if { $file_dialog_sel ne {} } {
@ -4486,14 +4524,12 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
}
}
panedwindow .load.l.paneright -orient vertical
frame .load.l.paneright.f -takefocus 0
frame .load.l.paneright.draw -background white -height 3.8c -takefocus 0
.load.l.paneright add .load.l.paneright.f
.load.l.paneright add .load.l.paneright.draw -minsize 150
if { ![catch {.load.l.paneright panecget .load.l.paneright.f -stretch}]} {
set optnever {-stretch never}
set optalways {-stretch always}
@ -4506,17 +4542,19 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
eval .load.l.paneright paneconfigure .load.l.paneright.f $optnever
eval .load.l.paneright paneconfigure .load.l.paneright.draw $optalways
if {$global_initdir eq {INITIALINSTDIR}} {
set selmode browse
} else {
set selmode extended
}
listbox .load.l.paneright.f.list -background {grey90} -listvariable file_dialog_files2 -width 20 -height 12\
-fg black -highlightcolor red -highlightthickness 2 \
-yscrollcommand ".load.l.paneright.f.yscroll set" -selectmode browse \
-highlightbackground [option get . background {}] \
-yscrollcommand ".load.l.paneright.f.yscroll set" -selectmode $selmode \
-xscrollcommand ".load.l.paneright.f.xscroll set" -exportselection 0
scrollbar .load.l.paneright.f.yscroll -command ".load.l.paneright.f.list yview" -takefocus 0
scrollbar .load.l.paneright.f.xscroll -command ".load.l.paneright.f.list xview" -orient horiz -takefocus 0
pack .load.l.paneright.f.yscroll -side right -fill y
pack .load.l.paneright.f.xscroll -side bottom -fill x
pack .load.l.paneright.f.list -side bottom -fill both -expand true
if { $loadfile == 2} {
.load.l add .load.l.recent
@ -4560,10 +4598,12 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
.load.l.paneleft.list selection set $file_dialog_index1
}
label .load.buttons_bot.label -text { File:}
entry .load.buttons_bot.entry -highlightcolor red -highlightthickness 2
entry .load.buttons_bot.entry -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}] -takefocus 0
entry_replace_selection .load.buttons_bot.entry
label .load.buttons_bot.srclab -text { Search:}
entry .load.buttons_bot.src -width 18 -highlightcolor red -highlightthickness 2
entry .load.buttons_bot.src -width 18 -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}]
entry_replace_selection .load.buttons_bot.src
.load.buttons_bot.src delete 0 end
.load.buttons_bot.src insert 0 $file_dialog_globfilter
@ -4591,28 +4631,6 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
set file_dialog_retval { }
}
# radiobutton .load.buttons_bot.all -text All -variable file_dialog_globfilter -value {*} -takefocus 0 \
# -command {
# set file_dialog_ext $file_dialog_globfilter
# setglob $file_dialog_dir1
# .load.buttons_bot.src delete 0 end
# .load.buttons_bot.src insert 0 $file_dialog_globfilter
# }
# radiobutton .load.buttons_bot.sym -text .sym -variable file_dialog_globfilter -value {*.sym} -takefocus 0 \
# -command {
# set file_dialog_ext $file_dialog_globfilter
# setglob $file_dialog_dir1
# .load.buttons_bot.src delete 0 end
# .load.buttons_bot.src insert 0 $file_dialog_globfilter
# }
# radiobutton .load.buttons_bot.sch -text .sch -variable file_dialog_globfilter -value {*.sch} -takefocus 0 \
# -command {
# set file_dialog_ext $file_dialog_globfilter
# setglob $file_dialog_dir1
# .load.buttons_bot.src delete 0 end
# .load.buttons_bot.src insert 0 $file_dialog_globfilter
# }
button .load.buttons.up -width 5 -text Up -command {load_file_dialog_up $file_dialog_dir1} -takefocus 0
label .load.buttons.mkdirlab -text { New dir: }
entry .load.buttons.newdir -width 16 -takefocus 0
@ -4635,19 +4653,28 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
file_dialog_set_colors1
.load.l.paneleft.list xview moveto 1
}
pack .load.l -expand true -fill both
pack .load.l.paneleft.yscroll -side right -fill y
pack .load.l.paneleft.xscroll -side bottom -fill x
pack .load.l.paneleft.list -fill both -expand true -padx 12
pack .load.buttons.home .load.buttons.up .load.buttons.pwd .load.buttons.path -side left
pack .load.buttons.mkdirlab -side left
pack .load.buttons.newdir -expand true -fill x -side left
pack .load.buttons.rmdir .load.buttons.mkdir -side right
# pack .load.buttons_bot.all .load.buttons_bot.sym .load.buttons_bot.sch -side left
pack .load.buttons_bot.srclab -side left
pack .load.buttons_bot.src -side left
pack .load.buttons_bot.label -side left
pack .load.buttons_bot.entry -side left -fill x -expand true
pack .load.l.paneright.f.yscroll -side right -fill y
pack .load.l.paneright.f.xscroll -side bottom -fill x
pack .load.l.paneright.f.list -side bottom -fill both -expand true
pack .load.buttons_bot.cancel .load.buttons_bot.ok -side left
pack .load.buttons_bot -side bottom -fill x
pack .load.buttons -side bottom -fill x
pack .load.l -expand true -fill both
if { [info exists file_dialog_default_geometry]} {
wm geometry .load "${file_dialog_default_geometry}"
}
@ -4681,7 +4708,8 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
destroy .load
set $global_initdir \"\$file_dialog_dir1\"
"
bind .load <KeyPress-H> {.load.buttons.home invoke }
bind .load <KeyPress-U> {.load.buttons.up invoke }
### update
if { [info exists file_dialog_v_sp0] } {
@ -4770,6 +4798,253 @@ proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}}
return [file_dialog_getresult $loadfile $confirm_overwrt]
}
#######################################################################
##### new alternate insert_symbol browser
#######################################################################
#### Display preview of selected symbol
proc insert_symbol_focusin {{paths {}} {maxdepth -1}} {
global insert_symbol new_symbol_browser_ext
xschem abort_operation
set insert_symbol(ext) $new_symbol_browser_ext
insert_symbol_filelist $paths $maxdepth
}
proc insert_symbol_preview {{paths {}}} {
# puts insert_symbol_preview
global insert_symbol
xschem preview_window close .ins.center.right {}
.ins.center.right configure -bg white
bind .ins.center.right <Expose> {}
bind .ins.center.right <Configure> {}
set sel [.ins.center.left.l curselection]
if {$sel eq {}} {
set sel [.ins.center.left.l index active]
.ins.center.left.l selection set active
}
if {$sel ne {}} {
set f [lindex $insert_symbol(fullpathlist) $sel 0]
if {$f ne {}} {
set type [is_xschem_file $f]
if {$type ne {0}} {
set dir [rel_sym_path $f $paths]
.ins.top.dir_e configure -state normal
.ins.top.dir_e delete 0 end
.ins.top.dir_e insert 0 $dir
.ins.top.dir_e configure -state readonly
.ins.top2.dir_e configure -state normal
.ins.top2.dir_e delete 0 end
.ins.top2.dir_e insert 0 $f
.ins.top2.dir_e configure -state readonly
.ins.center.right configure -bg {}
xschem preview_window create .ins.center.right {}
xschem preview_window draw .ins.center.right [list $f]
bind .ins.center.right <Expose> "xschem preview_window draw .ins.center.right [list $f]"
bind .ins.center.right <Configure> "xschem preview_window draw .ins.center.right [list $f]"
}
insert_symbol_place
}
}
}
proc get_list_of_dirs_with_symbols {{paths {}} {levels -1} {level -1}} {
global pathlist
if {$level == -1} { set level 0}
if {$paths eq {}} {set paths $pathlist}
foreach i $paths {
set filelist [glob -nocomplain -directory $i -type f *]
set there_are_symbols 0
foreach f $filelist {
if {[regexp {\.(sch|sym|tcl)$} $f]} {
# if {[is_xschem_file $f] ne {0}} { }
set there_are_symbols 1
break
}
}
if {$there_are_symbols} {
puts $i
}
set dirlist [glob -nocomplain -directory $i -type d *]
if {$levels >=0 && $level + 1 > $levels} {return}
foreach d $dirlist {
get_list_of_dirs_with_symbols $d $levels [expr {$level + 1} ]
}
}
}
#### fill list of files matching pattern
proc insert_symbol_filelist {paths {maxdepth -1}} {
# puts "insert_symbol_filelist: paths=$paths"
global insert_symbol
set insert_symbol(regex) [.ins.top.pat_e get]
#check if regex is valid
set err [catch {regexp $insert_symbol(regex) {12345}} res]
if {$err} {return}
set f [match_file $insert_symbol(regex) $paths $maxdepth]
set filelist {}
set insert_symbol(fullpathlist) {}
set sel [.ins.center.left.l curselection]
if {$sel eq {}} { set sel 0}
.ins.center.left.l activate $sel
foreach i $f {
set err [catch {regexp $insert_symbol(ext) $i} type]
if {!$err && $type} {
set fname [rel_sym_path $i $paths]
lappend filelist $fname
lappend insert_symbol(fullpathlist) $i
}
}
# sort lists using filelist as key
set files {}
foreach f $filelist ff $insert_symbol(fullpathlist) {
lappend files [list $f $ff]
}
set files [lsort -dictionary -index 0 $files]
set filelist {}
set insert_symbol(fullpathlist) {}
foreach f $files {
lassign $f ff fff
lappend filelist $ff
lappend insert_symbol(fullpathlist) $fff
}
# assign listbox variable all at the end, it is faster...
set insert_symbol(list) $filelist
set insert_symbol(nitems) [llength $filelist]
# .ins.center.left.l selection clear 0 end
# .ins.center.left.l selection set 0
}
proc insert_symbol_place {} {
# puts insert_symbol_place
global insert_symbol
set sel [.ins.center.left.l curselection]
if {$sel eq {}} {
set sel [.ins.center.left.l index active]
.ins.center.left.l selection set active
}
if {$sel ne {}} {
set f [lindex $insert_symbol(fullpathlist) $sel 0]
if {$f ne {}} {
set type [is_xschem_file $f]
if {$type ne {0}} {
xschem abort_operation
xschem place_symbol $f
}
}
}
}
#### paths: list of paths to use for listing symbols
#### maxdepth: how many levels to descend for each $paths directory (-1: no limit)
proc insert_symbol {{paths {}} {maxdepth -1} {ext {.*}}} {
global insert_symbol
set paths [cleanup_paths $paths] ;# remove ~ and other strange path combinations
# xschem set semaphore [expr {[xschem get semaphore] +1}]
set insert_symbol(ext) $ext
if {[winfo exists .ins]} {
raise .ins
return
}
toplevel .ins
frame .ins.top -takefocus 0
frame .ins.top2 -takefocus 0
panedwindow .ins.center -orient horizontal -height 8c
frame .ins.center.leftdir -takefocus 0
frame .ins.center.left -takefocus 0
frame .ins.center.right -width 250 -height 250 -bg white -takefocus 0
.ins.center add .ins.center.leftdir
.ins.center add .ins.center.left
.ins.center add .ins.center.right
frame .ins.bottom -takefocus 0
pack .ins.top -side top -fill x
pack .ins.top2 -side top -fill x
pack .ins.center -side top -expand 1 -fill both
pack .ins.bottom -side top -fill x
listbox .ins.center.leftdir.l -listvariable insert_symbol(dirs) -width 20 -height 20 \
-yscrollcommand ".ins.center.leftdir.s set" -highlightcolor red -highlightthickness 2 \
-activestyle underline -highlightbackground [option get . background {}] \
-exportselection 0
listbox .ins.center.left.l -listvariable insert_symbol(list) -width 40 -height 20 \
-yscrollcommand ".ins.center.left.s set" -highlightcolor red -highlightthickness 2 \
-activestyle underline -highlightbackground [option get . background {}] \
-exportselection 0
scrollbar .ins.center.leftdir.s -command ".ins.center.leftdir.l yview" -takefocus 0
scrollbar .ins.center.left.s -command ".ins.center.left.l yview" -takefocus 0
pack .ins.center.left.l -expand 1 -fill both -side left
pack .ins.center.left.s -fill y -side left
pack .ins.center.leftdir.l -expand 1 -fill both -side left
pack .ins.center.leftdir.s -fill y -side left
label .ins.top2.dir_l -text {Full path:}
entry .ins.top2.dir_e -width 60 -state readonly \
-readonlybackground [option get . background {}] -takefocus 0
label .ins.top.pat_l -text Pattern:
entry .ins.top.pat_e -width 20 -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}]
label .ins.top.dir_l -text { Symbol ref: }
entry .ins.top.dir_e -width 40 -state readonly \
-readonlybackground [option get . background {}] -takefocus 0
label .ins.top.ext_l -text Ext:
entry .ins.top.ext_e -width 15 -takefocus 0 -state normal -textvariable new_symbol_browser_ext
if {[info exists insert_symbol(regex)]} {
.ins.top.pat_e insert 0 $insert_symbol(regex)
}
bind .ins <KeyPress-Escape> {.ins.bottom.dismiss invoke}
bind .ins <KeyRelease> "
if {{%K} eq {Tab} && {%W} eq {.ins.center.left.l}} {
insert_symbol_filelist [list $paths] [list $maxdepth]
insert_symbol_preview [list $paths]
}
"
bind .ins.center.left.l <<ListboxSelect>> "insert_symbol_preview [list $paths]"
bind .ins.center.left.l <Enter> "insert_symbol_focusin [list $paths] [list $maxdepth]"
label .ins.bottom.n -text { N. of items:}
label .ins.bottom.nitems -textvariable insert_symbol(nitems)
button .ins.bottom.dismiss -takefocus 0 -text Dismiss -command {
if { [xschem get ui_state] & 8192 } {
xschem abort_operation
} else {
xschem preview_window close .ins.center.right {}
destroy .ins
}
}
pack .ins.bottom.dismiss -side left
pack .ins.bottom.n -side left
pack .ins.bottom.nitems -side left
pack .ins.top2.dir_l -side left
pack .ins.top2.dir_e -side left -fill x -expand 1
pack .ins.top.pat_l -side left
pack .ins.top.pat_e -side left
pack .ins.top.dir_l -side left
pack .ins.top.dir_e -side left
pack .ins.top.ext_l -side left
pack .ins.top.ext_e -side left
insert_symbol_filelist $paths $maxdepth
# tkwait window .ins
# xschem set semaphore [expr {[xschem get semaphore] -1}]
return {}
}
#######################################################################
##### /new alternate insert_symbol browser
#######################################################################
# get last n path components: example , n=1 --> /aaa/bbb/ccc/ddd.sch -> ccc/ddd.sch
proc get_cell {s n } {
set slist [file split $s]
@ -6447,12 +6722,17 @@ proc editdata {{data {}} {title {Edit data}} } {
# wm transient $window [xschem get topwindow]
frame $window.buttons
pack $window.buttons -side bottom -fill x -pady 2m
button $window.buttons.copy -text Copy -command "
clipboard clear
clipboard append \[$window.text get 1.0 {end - 1 chars}\]
"
button $window.buttons.ok -text OK -command "
set retval \[$window.text get 1.0 {end - 1 chars}\]; destroy $window
"
button $window.buttons.cancel -text Cancel -command "destroy $window"
pack $window.buttons.ok -side left -expand 1
pack $window.buttons.cancel -side left -expand 1
pack $window.buttons.copy -side left -expand 1
eval text $window.text -undo 1 -relief sunken -bd 2 -yscrollcommand \"$window.yscroll set\" -setgrid 1 \
-xscrollcommand \"$window.xscroll set\" -wrap none -height 30 $text_tabs_setting
@ -6567,27 +6847,39 @@ proc viewdata {data {ro {}} {win .view}} {
return $tctx::rcode
}
proc sub_match_file { f {paths {}} } {
global pathlist match_file_dir_arr
proc sub_match_file { f {paths {}} {maxdepth -1} } {
global pathlist match_file_dir_arr match_file_level nolist_libs
set res {}
if {$paths eq {}} {set paths $pathlist}
foreach i $paths {
foreach j [glob -nocomplain -directory $i *] {
# puts "--> $j $f"
# set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
set skip 0
foreach k $nolist_libs {
if {[regexp $k $j]} {
set skip 1
break
}
}
if {$skip} { continue }
if {[file isdirectory $j] && [file readable $j]} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
if {[array names match_file_dir_arr -exact $jj] == {}} {
set match_file_dir_arr($jj) 1
# puts "********** directory $jj"
set sub_res [sub_match_file $f $j] ;# recursive call
if {$sub_res != {} } {set res [concat $res $sub_res]}
if { $maxdepth == -1 || $match_file_level < $maxdepth} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
# if {[array names match_file_dir_arr -exact $jj] == {}} { ... }
if {![info exists match_file_dir_arr($jj)]} {
set match_file_dir_arr($jj) 1
incr match_file_level
set sub_res [sub_match_file $f $j $maxdepth] ;# recursive call
incr match_file_level -1
if {$sub_res != {} } {set res [concat $res $sub_res]}
}
}
} else {
# set fname [file tail $j]
set fname $j
if {[regexp $f $fname]} {
lappend res $j
if {![info exists match_file_dir_arr($j)]} {
set match_file_dir_arr($j) 1
if {[regexp $f $j]} {
lappend res $j
}
}
}
}
@ -6598,37 +6890,56 @@ proc sub_match_file { f {paths {}} } {
# find files into $paths directories matching $f
# use $pathlist global search path if $paths empty
# recursively descend directories
proc match_file { f {paths {}} } {
global match_file_dir_arr
proc match_file { f {paths {}} {maxdepth -1} } {
global match_file_dir_arr match_file_level
set err [catch {regexp $f {12345}} res]
if {$err} {return {}}
set match_file_level 0
catch {unset match_file_dir_arr}
set res [sub_match_file $f $paths]
set res [sub_match_file $f $paths $maxdepth]
catch {unset match_file_dir_arr}
return $res
}
proc sub_find_file { f {paths {}} {first 0} } {
global pathlist match_file_dir_arr
proc sub_find_file { f {paths {}} {first 0} {maxdepth -1}} {
global pathlist match_file_dir_arr match_file_level nolist_libs
set res {}
if {$paths eq {}} {set paths $pathlist}
foreach i $paths {
foreach j [glob -nocomplain -directory $i *] {
# puts "--> $j $f"
set skip 0
foreach k $nolist_libs {
if {[regexp $k $j]} {
set skip 1
break
}
}
if {$skip} { continue }
if {[file isdirectory $j] && [file readable $j]} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
if {[array names match_file_dir_arr -exact $jj] == {}} {
set match_file_dir_arr($jj) 1
# puts "********** directory $jj"
set sub_res [sub_find_file $f $j $first] ;# recursive call
if {$sub_res != {} } {
set res [concat $res $sub_res]
if {$first} {return $res}
if { $maxdepth == -1 || $match_file_level < $maxdepth} {
set jj [regsub {/ $} [file normalize ${j}/\ ] {}]
# if {[array names match_file_dir_arr -exact $jj] == {}} { ... }
if {![info exists match_file_dir_arr($jj)]} {
set match_file_dir_arr($jj) 1
incr match_file_level
set sub_res [sub_find_file $f $j $first $maxdepth] ;# recursive call
incr match_file_level -1
if {$sub_res != {} } {
set res [concat $res $sub_res]
if {$first} {return $res}
}
}
}
} else {
set fname [file tail $j]
if {$fname == $f} {
lappend res $j
if {$first} {return $res}
if {![info exists match_file_dir_arr($j)]} {
set match_file_dir_arr($j) 1
if {$fname == $f} {
lappend res $j
if {$first} {return $res}
}
}
}
}
@ -6639,10 +6950,11 @@ proc sub_find_file { f {paths {}} {first 0} } {
# find given file $f into $paths directories
# use $pathlist global search path if $paths empty
# recursively descend directories
proc find_file { f {paths {}} } {
global match_file_dir_arr
proc find_file { f {paths {}} {maxdepth -1}} {
global match_file_dir_arr match_file_level
set match_file_level 0
catch {unset match_file_dir_arr}
set res [sub_find_file $f $paths 0]
set res [sub_find_file $f $paths 0 $maxdepth]
catch {unset match_file_dir_arr}
return $res
}
@ -6651,10 +6963,11 @@ proc find_file { f {paths {}} } {
# use $pathlist global search path if $paths empty
# recursively descend directories
# only return FIRST FOUND
proc find_file_first { f {paths {}} } {
global match_file_dir_arr
proc find_file_first { f {paths {}} {maxdepth -1}} {
global match_file_dir_arr match_file_level
set match_file_level 0
catch {unset match_file_dir_arr}
set res [sub_find_file $f $paths 1]
set res [sub_find_file $f $paths 1 $maxdepth]
catch {unset match_file_dir_arr}
return $res
}
@ -6740,16 +7053,24 @@ proc try_download_url {dirname sch_or_sym} {
# if file is in a library directory (a $pathlist dir)
# Example: rel_sym_path /home/schippes/share/xschem/xschem_library/devices/iopin.sym
# devices/iopin.sym
proc rel_sym_path {symbol} {
proc rel_sym_path {symbol {paths {}} } {
global OS pathlist env
# puts "rel_sym_path: $symbol $paths"
if { $paths eq {}} {set paths $pathlist}
regsub {^~/} $symbol ${env(HOME)}/ symbol
if {![regexp {^/} $symbol]} {
set symbol [pwd]/$symbol
}
# if {$OS eq "Windows"} {
# if {![regexp {^[A-Za-z]\:/} $symbol]} {
# set symbol [pwd]/$symbol
# }
# } else {
# if {![regexp {^/} $symbol]} {
# set symbol [pwd]/$symbol
# }
# }
set curr_dirname [pwd]
set name {}
foreach path_elem $pathlist {
foreach path_elem $paths {
if { ![string compare $path_elem .] && [info exist curr_dirname]} {
set path_elem $curr_dirname
}
@ -6783,9 +7104,10 @@ proc rel_sym_path {symbol} {
# given a symbol reference 'sym' return its absolute path
# Example: % abs_sym_path devices/iopin.sch
# /home/schippes/share/xschem/xschem_library/devices/iopin.sym
proc abs_sym_path {fname {ext {} } } {
proc abs_sym_path {fname {ext {} } {paths {}}} {
global pathlist OS
if { $paths eq {}} {set paths $pathlist}
set curr_dirname [pwd]
## empty: do nothing
if {$fname eq {} } return {}
@ -6845,9 +7167,9 @@ proc abs_sym_path {fname {ext {} } } {
## if file does not exists but directory does return anyway
if { [file exists [file dirname "$tmpfname"]] } { return "$tmpfname" }
}
## if fname is present in one of the pathlist paths get the absolute path
## if fname is present in one of the paths paths get the absolute path
set name {}
foreach path_elem $pathlist {
foreach path_elem $paths {
if { ![string compare $path_elem .] && [info exist curr_dirname]} {
set path_elem $curr_dirname
}
@ -7848,42 +8170,36 @@ proc no_open_dialogs {} {
## "file_dialog_*" only one load_file_dialog window is allowed
set tctx::global_list {
PDK_ROOT PDK SKYWATER_MODELS SKYWATER_STDCELLS
INITIALINSTDIR INITIALLOADDIR INITIALPROPDIR INITIALTEXTDIR XSCHEM_LIBRARY_PATH
add_all_windows_drives auto_hilight auto_hilight_graph_nodes autofocus_mainwindow
autotrim_wires orthogonal_wiring snap_cursor bespice_listen_port big_grid_points bus_replacement_char cadgrid cadlayers
cadsnap cadence_compat cairo_font_name cairo_font_scale change_lw color_ps tctx::colors compare_sch constr_mv
copy_cell crosshair_layer crosshair_size cursor_2_hook snap_cursor_size custom_label_prefix custom_token
dark_colors dark_colorscheme dark_gui_colorscheme delay_flag
dim_bg dim_value disable_unique_names do_all_inst draw_crosshair
draw_grid draw_grid_axes draw_window edit_prop_pos edit_prop_size
edit_symbol_prop_new_sel editprop_sympath en_hilight_conn_inst enable_dim_bg enable_stretch
enter_text_default_geometry filetmp fix_broken_tiled_fill flat_netlist fullscreen
gaw_fd gaw_tcp_address graph_autoload graph_bus
graph_change_done graph_digital graph_dialog_default_geometry
graph_legend graph_linewidth_mult graph_logx
graph_logy graph_private_cursor graph_rainbow graph_schname graph_sel_color graph_sel_wave
graph_selected graph_sort graph_unlocked graph_use_ctrl_key
hide_empty_graphs hide_symbols tctx::hsize
incr_hilight incremental_select infix_interface infowindow_text intuitive_interface
keep_symbols launcher_default_program
light_colors line_width live_cursor2_backannotate local_netlist_dir lvs_ignore
lvs_netlist measure_text netlist_dir netlist_show netlist_type no_ask_save
no_change_attrs nolist_libs noprint_libs old_selected_tok only_probes path pathlist
persistent_command preserve_unchanged_attrs prev_symbol ps_colors ps_paper_size rainbow_colors
tctx::rcode recentfile
retval retval_orig rotated_text search_case search_exact search_found search_schematic
search_select search_value select_touch selected_tok show_hidden_texts show_infowindow
show_infowindow_after_netlist
simconf_default_geometry simconf_vpos simulate_bg spiceprefix split_files svg_colors
svg_font_name sym_txt symbol symbol_width tabstop tclcmd_txt tclstop text_line_default_geometry
text_replace_selection text_tabs_setting textwindow_fileid textwindow_filename textwindow_w
toolbar_horiz toolbar_list
toolbar_visible top_is_subckt transparent_svg undo_type use_lab_wire unselect_partial_sel_wires
use_label_prefix use_tclreadline
user_wants_copy_cell verilog_2001 verilog_bitblast viewdata_fileid viewdata_filename viewdata_w
tctx::vsize xschem_libs xschem_listen_port zoom_full_center orthogonal_wiring snap_cursor
snap_cursor_size cadence_compat use_cursor_for_selection
INITIALINSTDIR INITIALLOADDIR INITIALPROPDIR INITIALTEXTDIR PDK PDK_ROOT SKYWATER_MODELS
SKYWATER_STDCELLS XSCHEM_LIBRARY_PATH add_all_windows_drives auto_hilight
auto_hilight_graph_nodes autofocus_mainwindow autotrim_wires bespice_listen_port big_grid_points
bus_replacement_char cadence_compat cadgrid cadlayers cadsnap cairo_font_name cairo_font_scale
change_lw color_ps compare_sch constr_mv copy_cell crosshair_layer crosshair_size cursor_2_hook
custom_label_prefix custom_token dark_colors dark_colorscheme dark_gui_colorscheme delay_flag
dim_bg dim_value disable_unique_names do_all_inst draw_crosshair draw_grid draw_grid_axes
draw_window edit_prop_pos edit_prop_size edit_symbol_prop_new_sel editprop_sympath
en_hilight_conn_inst enable_dim_bg enable_stretch enter_text_default_geometry filetmp
fix_broken_tiled_fill flat_netlist fullscreen gaw_fd gaw_tcp_address graph_autoload graph_bus
graph_change_done graph_dialog_default_geometry graph_digital graph_legend graph_linewidth_mult
graph_logx graph_logy graph_private_cursor graph_rainbow graph_schname graph_sel_color
graph_sel_wave graph_selected graph_sort graph_unlocked graph_use_ctrl_key hide_empty_graphs
hide_symbols incr_hilight incremental_select infix_interface infowindow_text intuitive_interface
keep_symbols launcher_default_program light_colors line_width live_cursor2_backannotate
local_netlist_dir lvs_ignore lvs_netlist measure_text netlist_dir netlist_show netlist_type
new_symbol_browser new_symbol_browser_depth new_symbol_browser_ext new_symbol_browser_paths
no_ask_save no_change_attrs nolist_libs noprint_libs old_selected_tok only_probes
orthogonal_wiring path pathlist persistent_command preserve_unchanged_attrs prev_symbol ps_colors
ps_paper_size rainbow_colors recentfile retval retval_orig rotated_text search_case search_exact
search_found search_schematic search_select search_value select_touch selected_tok
show_hidden_texts show_infowindow show_infowindow_after_netlist simconf_default_geometry
simconf_vpos simulate_bg snap_cursor snap_cursor_size spiceprefix split_files svg_colors
svg_font_name sym_txt symbol symbol_width tabstop tclcmd_txt tclstop tctx::colors tctx::hsize
tctx::rcode tctx::vsize text_line_default_geometry text_replace_selection text_tabs_setting
textwindow_fileid textwindow_filename textwindow_w toolbar_horiz toolbar_list toolbar_visible
top_is_subckt transparent_svg undo_type unselect_partial_sel_wires uppercase_subckt
use_cursor_for_selection use_lab_wire use_label_prefix use_tclreadline user_wants_copy_cell
verilog_2001 verilog_bitblast
viewdata_fileid viewdata_filename viewdata_w xschem_libs xschem_listen_port zoom_full_center
}
## list of global arrays to save/restore on context switching
@ -8268,7 +8584,7 @@ proc load_raw {{type {}}} {
proc build_widgets { {topwin {} } } {
global XSCHEM_SHAREDIR tabbed_interface simulate_bg OS sim
global dark_gui_colorscheme draw_crosshair
global dark_gui_colorscheme draw_crosshair grid_point_size
global recentfile color_ps transparent_svg menu_debug_var enable_stretch
global netlist_show flat_netlist split_files compare_sch intuitive_interface
global draw_grid big_grid_points sym_txt change_lw incr_hilight symbol_width cadence_compat
@ -8332,7 +8648,11 @@ proc build_widgets { {topwin {} } } {
}
$topwin.menubar.file add command -label "Component browser" -accelerator {Shift-Ins, Ctrl-I} \
-command {
load_file_dialog {Insert symbol} *.sym INITIALINSTDIR 2
if {$new_symbol_browser} {
insert_symbol $new_symbol_browser_paths $new_symbol_browser_depth $new_symbol_browser_ext
} else {
load_file_dialog {Insert symbol} *.sym INITIALINSTDIR 2
}
}
$topwin.menubar.file add command -label "Open" -command "xschem load" -accelerator {Ctrl+O}
$topwin.menubar.file add command -label "Open Most Recent" \
@ -8421,6 +8741,19 @@ proc build_widgets { {topwin {} } } {
$topwin.menubar.option add checkbutton -label "Draw persistent snap cursor" -variable snap_cursor \
-selectcolor $selectcolor -accelerator {Alt-Z}
$topwin.menubar.option add cascade -label "Crosshair" \
-menu $topwin.menubar.option.crosshair
menu $topwin.menubar.option.crosshair -tearoff 0
$topwin.menubar.option.crosshair add checkbutton -label "Draw snap cursor" \
-variable snap_cursor -selectcolor $selectcolor
$topwin.menubar.option.crosshair add checkbutton -label "Draw crosshair" \
-variable draw_crosshair -selectcolor $selectcolor -accelerator {Alt-X}
$topwin.menubar.option.crosshair add command -label "Crosshair size" \
-command {
input_line "Enter crosshair size (int, 0 = full screen width):" \
"set crosshair_size" $crosshair_size
}
$topwin.menubar.option add command -label "Replace \[ and \] for buses in SPICE netlist" \
-command {
input_line "Enter two characters to replace default bus \[\] delimiters:" "set bus_replacement_char"
@ -8601,6 +8934,10 @@ proc build_widgets { {topwin {} } } {
set change_lw 0
input_line "Enter linewidth (float):" "xschem line_width"
}
$topwin.menubar.view add command -label "Set grid point size" \
-command {
input_line "Enter Grid point size (int or -1: $grid_point_size)" "set grid_point_size" $grid_point_size
}
$topwin.menubar.view add checkbutton -label "Tabbed interface" -variable tabbed_interface \
-selectcolor $selectcolor -command setup_tabbed_interface
@ -8675,6 +9012,8 @@ proc build_widgets { {topwin {} } } {
-command "xschem net_label 0" -accelerator Alt-Shift-L
$topwin.menubar.sym add command -label "Change selected inst. texts to floaters" \
-command "xschem floaters_from_selected_inst"
$topwin.menubar.sym add command -label "Unselect attached floaters" \
-command "xschem unselect_attached_floaters"
$topwin.menubar.sym add command -label "Print list of highlight nets" \
-command "xschem print_hilight_net 1" -accelerator J
$topwin.menubar.sym add command -label "Print list of highlight nets, with buses expanded" \
@ -8834,7 +9173,7 @@ proc build_widgets { {topwin {} } } {
-selectcolor $selectcolor -variable auto_hilight_graph_nodes
$topwin.menubar.simulation.graph add command -label {Add waveform graph} -command {xschem add_graph}
$topwin.menubar.simulation.graph add command -label {Add waveform reload launcher} -command {
xschem place_symbol [rel_sym_path [find_file_first launcher.sym]] "name=h5\ndescr=\"load waves\"
xschem place_symbol [find_file_first launcher.sym] "name=h5\ndescr=\"load waves\"
tclcommand=\"xschem raw_read \$netlist_dir/[file tail [file rootname [xschem get current_name]]].raw tran\"
"
}
@ -8864,7 +9203,8 @@ tclcommand=\"xschem raw_read \$netlist_dir/[file tail [file rootname [xschem get
xschem set format {}
}
}
$topwin.menubar.simulation.lvs add checkbutton -label "Upper case .SUBCKT and .ENDS" \
-selectcolor $selectcolor -variable uppercase_subckt
$topwin.menubar.simulation.lvs add checkbutton -label "Top level is a .subckt" \
-selectcolor $selectcolor -variable top_is_subckt
@ -8947,12 +9287,27 @@ proc trace_set_paths {varname idxname op} {
uplevel #0 set_paths
}
}
proc cleanup_paths {paths} {
global env
set pathlist {}
foreach i $paths {
regsub {^~$} $i ${env(HOME)} i
regsub {^~/} $i ${env(HOME)}/ i
if { ![string compare $i .] } {
lappend pathlist $i
} elseif { [ regexp {\.\.\/} $i] } {
lappend pathlist [file normalize $i]
} elseif { [ file exists $i] } {
lappend pathlist $i
}
}
return $pathlist
}
# when XSCHEM_LIBRARY_PATH is changed call this function to refresh and cache
# new library search path.
proc set_paths {} {
global XSCHEM_LIBRARY_PATH env pathlist OS add_all_windows_drives file_dialog_names1
set pathlist {}
global XSCHEM_LIBRARY_PATH pathlist OS add_all_windows_drives
# puts stderr "caching search paths"
if { [info exists XSCHEM_LIBRARY_PATH] } {
if {$OS == "Windows"} {
@ -8966,17 +9321,8 @@ proc set_paths {} {
} else {
set pathlist_orig [split $XSCHEM_LIBRARY_PATH :]
}
foreach i $pathlist_orig {
regsub {^~$} $i ${env(HOME)} i
regsub {^~/} $i ${env(HOME)}/ i
if { ![string compare $i .] } {
lappend pathlist $i
} elseif { [ regexp {\.\.\/} $i] } {
lappend pathlist [file normalize $i]
} elseif { [ file exists $i] } {
lappend pathlist $i
}
}
set pathlist [cleanup_paths $pathlist_orig]
}
if {$pathlist eq {}} { set pathlist [pwd] }
set_initial_dirs
@ -9067,6 +9413,15 @@ proc source_user_tcl_files {} {
}
}
proc eval_user_startup_commands {} {
global user_startup_commands
if {[info exists user_startup_commands]} {
if {[catch {uplevel #0 $user_startup_commands} res]} {
puts "executing $user_startup_commands:\n\n$res"
}
}
}
proc eval_postinit_commands {} {
global postinit_commands
if {[info exists postinit_commands]} {
@ -9296,6 +9651,7 @@ set_ne local_netlist_dir 0 ;# if set use <sch_dir>/simulation for netlist and si
set_ne bus_replacement_char {} ;# use {<>} to replace [] with <> in bussed signals
set_ne lvs_netlist 0
set_ne top_is_subckt 0
set_ne uppercase_subckt 0
set_ne lvs_ignore 0
set_ne hide_empty_graphs 0 ;# if set to 1 waveform boxes will be hidden if no raw file loaded
set_ne graph_use_ctrl_key 0;# if set forces to use Control key to operate on graphs
@ -9331,6 +9687,7 @@ set_ne enable_stretch 0
set_ne constr_mv 0
set_ne unselect_partial_sel_wires 0
set_ne load_file_dialog_fullpath 1
set_ne file_dialog_others {} ;# contains 2nd, 3rd, ... selected filenames on mult. selections in load file
# if set show selected elements while dragging the selection rectangle.
# once selected these can not be unselected by retracting the selection rectangle
@ -9340,6 +9697,7 @@ set_ne select_touch 1
set_ne draw_grid 1
set_ne big_grid_points 0
set_ne grid_point_size -1 ;# grid point size (>=0) or unspecified (-1)
set_ne draw_grid_axes 1
set_ne persistent_command 0
set_ne intuitive_interface 1
@ -9399,6 +9757,12 @@ set_ne tabbed_interface 1
## case insensitive symbol lookup (on case insensitive filesystems only!)
set_ne case_insensitive 0
## New alternate symbol placement browser (default: not enabled).
set_ne new_symbol_browser 0
set_ne new_symbol_browser_paths {} ;# if empty use xschem search paths
set_ne new_symbol_browser_depth 2 ;# depth to descend into each dir of the search paths
set_ne new_symbol_browser_ext {\.(sym|tcl)$} ;# file extensions (a regex) to look for
set_ne file_dialog_ext {*}
## remember edit_prop widget size

View File

@ -295,6 +295,9 @@
#### enable to scale grid point size as done with lines at close zoom, default: 0
# set big_grid_points 0
#### explicitly set grid point size in pixels. Default: -1 (not set)
# set grid_point_size 2
#### enable drawing grid axes. Default: enabled (1)
# set draw_grid_axes 1
@ -543,6 +546,17 @@
# }
# }
###########################################################################
#### TCL COMMANDS TO BE EXECUTED AFTER ANY NEW WINDOW CREATION
###########################################################################
#### this hook is useful to execute user UI code (like event binding,
#### new buttons / menu entries etc).
# set user_startup_commands {
# bind [xschem get current_win_path] <Key-plus> {
# puts Hello
# }
# }
###########################################################################
#### TCL COMMANDS TO BE EXECUTED AFTER GENERATING NETLIST
###########################################################################
@ -569,6 +583,19 @@
#### or tab is open.
# set tabbed_interface 0
###########################################################################
#### ALTERNATE SYMBOL PLACEMENT BROWSER
###########################################################################
#### uses a new symbol placement widget. Default: not enabled (0)
# set new_symbol_browser 1
#### defines a list of paths to search for. If empty uses all xschem
#### XSCHEM_LIBRARY_PATH paths
# set new_symbol_browser_paths [list ... ... ... ]
#### defines the depth to descend into each path. default: 2
# set new_symbol_browser_depth 3
#### defines the extensions to search for. Default: {\.(sym|tcl)$}
# set new_symbol_browser_ext {\.(sch|sym|tcl)$}
###########################################################################
#### CASE INSENSITIVE SYMBOL LOOKUP
###########################################################################

View File

@ -0,0 +1,33 @@
v {xschem version=3.4.6 file_version=1.2
*
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
* simulation.
* Copyright (C) 1998-2024 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
}
G {}
K {type=scope
template="name=l1"
highlight=true}
V {}
S {}
E {}
L 4 0 0 10 -20 {}
B 5 -1.25 -1.25 1.25 1.25 {name=p dir=in}
P 4 5 10 -20 10 -140 140 -140 140 -20 10 -20 {}
T {@#0:net_name} 12.5 -18.125 0 0 0.2 0.2 {layer=4}
T {@#0:spice_get_voltage} 12.5 -139.375 0 0 0.15 0.15 {layer=15}

View File

@ -0,0 +1,36 @@
v {xschem version=3.4.6 file_version=1.2
*
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
* simulation.
* Copyright (C) 1998-2024 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
}
G {}
K {type=scope
template="name=l1"
highlight=true}
V {}
S {}
E {}
L 4 0 0 10 -20 {}
L 4 0 -160 10 -140 {}
B 5 -1.25 -161.25 1.25 -158.75 {name=p dir=in}
B 5 -1.25 -1.25 1.25 1.25 {name=m dir=in}
P 4 5 10 -20 10 -140 140 -140 140 -20 10 -20 {}
T {@#1:net_name} 12.5 -18.125 0 0 0.2 0.2 {layer=4}
T {@#0:net_name} 12.5 -153.125 0 0 0.2 0.2 {layer=4}
T {@spice_get_diff_voltage} 12.5 -139.375 0 0 0.15 0.15 {layer=15}

View File

@ -0,0 +1,31 @@
v {xschem version=3.4.6 file_version=1.2
*
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
* simulation.
* Copyright (C) 1998-2024 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
}
G {}
K {type=scope
template="name=l1"
highlight=true}
V {}
S {}
E {}
P 4 5 10 -20 10 -140 140 -140 140 -20 10 -20 {}
T {@device} 12.5 -18.125 0 0 0.2 0.2 {layer=4}
T {tcleval(@spice_get_node [xschem get_fqdevice @device ] )} 12.5 -139.375 0 0 0.15 0.15 {layer=17}

View File

@ -1,4 +1,4 @@
v {xschem version=3.4.6RC file_version=1.2
v {xschem version=3.4.6 file_version=1.2
*
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
@ -24,6 +24,15 @@ K {}
V {}
S {}
E {}
B 2 520 -415 630 -315 {name=l4
flags=graph,unlocked
lock=1
color=8
node="tcleval([xschem get_fqdevice [xschem translate l4 @device]])"
y1=-0.00014
y2=0.00013
x1=0.00044464632
x2=0.00046163671}
T {( @#0:resolved_net )} 440 -265 0 1 0.2 0.2 {name=l2 layer=15}
T {( @#0:resolved_net )} 100 -285 0 1 0.2 0.2 {name=p1 layer=15}
T {( @#0:resolved_net )} 100 -235 0 1 0.2 0.2 {name=p2 layer=15}
@ -49,3 +58,6 @@ m=1}
C {parax_cap.sym} 630 -230 0 0 {name=C3 gnd=0 value=\{COUT\} m=1}
C {vsource.sym} 150 -260 1 0 {name=V1 value=0}
C {vsource.sym} 150 -210 1 0 {name=V2 value=0}
C {scope_ammeter.sym} 500 -290 0 0 {name=l4
attach=l4
device=R1}

View File

@ -26,34 +26,34 @@ K {}
V {}
S {}
E {}
L 2 105 -1005 105 -775 {}
L 2 145 -1005 145 -775 {}
L 2 185 -1005 185 -775 {}
L 2 225 -1005 225 -775 {}
L 2 265 -1005 265 -775 {}
L 2 305 -1005 305 -775 {}
L 2 345 -1005 345 -775 {}
L 2 385 -1005 385 -775 {}
L 2 65 -975 395 -975 {}
L 2 65 -935 395 -935 {}
L 2 65 -895 395 -895 {}
L 2 65 -855 395 -855 {}
L 2 65 -815 395 -815 {}
L 4 65 -1015 65 -755 {}
L 4 55 -775 405 -775 {}
L 4 105 -775 105 -765 {}
L 4 145 -775 145 -765 {}
L 4 185 -775 185 -765 {}
L 4 225 -775 225 -765 {}
L 4 265 -775 265 -765 {}
L 4 305 -775 305 -765 {}
L 4 345 -775 345 -765 {}
L 4 385 -775 385 -765 {}
L 4 55 -815 65 -815 {}
L 4 55 -855 65 -855 {}
L 4 55 -895 65 -895 {}
L 4 55 -935 65 -935 {}
L 4 55 -975 65 -975 {}
L 2 95 -1105 95 -875 {}
L 2 135 -1105 135 -875 {}
L 2 175 -1105 175 -875 {}
L 2 215 -1105 215 -875 {}
L 2 255 -1105 255 -875 {}
L 2 295 -1105 295 -875 {}
L 2 335 -1105 335 -875 {}
L 2 375 -1105 375 -875 {}
L 2 55 -1075 385 -1075 {}
L 2 55 -1035 385 -1035 {}
L 2 55 -995 385 -995 {}
L 2 55 -955 385 -955 {}
L 2 55 -915 385 -915 {}
L 4 55 -1115 55 -855 {}
L 4 45 -875 395 -875 {}
L 4 95 -875 95 -865 {}
L 4 135 -875 135 -865 {}
L 4 175 -875 175 -865 {}
L 4 215 -875 215 -865 {}
L 4 255 -875 255 -865 {}
L 4 295 -875 295 -865 {}
L 4 335 -875 335 -865 {}
L 4 375 -875 375 -865 {}
L 4 45 -915 55 -915 {}
L 4 45 -955 55 -955 {}
L 4 45 -995 55 -995 {}
L 4 45 -1035 55 -1035 {}
L 4 45 -1075 55 -1075 {}
L 4 610 -1100 630 -1140 {}
L 4 630 -1140 650 -1100 {}
L 4 650 -1100 670 -1140 {}
@ -83,13 +83,13 @@ L 4 960 -340 970 -340 {}
L 4 960 -340 970 -330 {}
L 4 970 -330 980 -340 {}
L 4 970 -340 980 -340 {}
B 2 1260 -560 1680 -390 {flags=graph
B 2 1370 -555 1790 -385 {flags=graph
y1 = -0.00068
y2 = 22
divy = 6
subdivy=1
x1=2.9358714e-05
x2=0.0010293582
x1=5e-10
x2=0.001
divx=8
node="PANEL
LED" unitx=m
@ -104,13 +104,13 @@ autoload=0
sim_type=tran
xrawfile=$netlist_dir/solar_panel.raw}
B 2 1260 -390 1680 -220 {flags=graph
B 2 1370 -385 1790 -215 {flags=graph
y1 = -0.0012
y2 = 6.8
divy = 4
subdivy=1
x1=2.9358714e-05
x2=0.0010293582
x1=5e-10
x2=0.001
divx=8
unitx=m
color="7 4 6"
@ -123,13 +123,13 @@ autoload=0
sim_type=tran
xrawfile=$netlist_dir/solar_panel.raw}
B 2 1260 -750 1680 -560 {flags=graph
B 2 1370 -745 1790 -555 {flags=graph
y1 = -2.7e-05
y2 = 100
divy = 5
subdivy=1
x1=2.9358714e-05
x2=0.0010293582
x1=5e-10
x2=0.001
divx=9
unitx=m subdivx=4
@ -146,13 +146,13 @@ autoload=0
sim_type=tran
xrawfile=$netlist_dir/solar_panel.raw}
B 2 1260 -940 1680 -750 {flags=graph
B 2 1370 -935 1790 -745 {flags=graph
y1 = 0
y2 = 1
divy = 5
subdivy=1
x1=2.9358714e-05
x2=0.0010293582
x1=5e-10
x2=0.001
divx=9
unitx=u subdivx=4
@ -169,13 +169,13 @@ autoload=0
sim_type=tran
xrawfile=$netlist_dir/solar_panel.raw}
B 2 1260 -1140 1680 -950 {flags=graph
B 2 1370 -1135 1790 -945 {flags=graph
y1 = 0
y2 = 1
divy = 5
subdivy=1
x1=2.9358714e-05
x2=0.0010293582
x1=5e-10
x2=0.001
divx=9
unitx=u subdivx=4
@ -193,29 +193,65 @@ autoload=0
sim_type=tran
xrawfile=$netlist_dir/solar_panel.raw}
B 18 65 -960 320 -775 {}
A 5 320 -960 5.590169943749475 243.434948822922 360 {fill=true}
P 7 6 395 -775 340 -931.25 335 -945 322.5 -960 310 -965 65 -975 {}
T {2x10 1W white LED} 1240 -200 0 0 0.4 0.4 {layer=8}
T {2xseries 1W white LEDs} 1220 -140 0 0 0.4 0.4 {}
T {2.5} 95 -755 0 0 0.2 0.2 {}
T {5.0} 135 -755 0 0 0.2 0.2 {}
T {7.5} 175 -755 0 0 0.2 0.2 {}
T {10.0} 215 -755 0 0 0.2 0.2 {}
T {12.5} 255 -755 0 0 0.2 0.2 {}
T {15.0} 295 -755 0 0 0.2 0.2 {}
T {17.5} 335 -755 0 0 0.2 0.2 {}
T {20.0} 375 -755 0 0 0.2 0.2 {}
T {2.5} 35 -980 0 0 0.2 0.2 {}
T {2.0} 35 -940 0 0 0.2 0.2 {}
T {1.5} 35 -895 0 0 0.2 0.2 {}
T {1.0} 35 -860 0 0 0.2 0.2 {}
T {0.5} 35 -820 0 0 0.2 0.2 {}
T {25C, 1000W/m2} 190 -1030 0 0 0.2 0.2 {}
T {V} 410 -765 0 0 0.4 0.4 {}
T {I} 40 -1020 0 0 0.4 0.4 {}
T {SOLAR PANEL} 145 -1055 0 0 0.4 0.4 {}
T {Maximum Power} 307.5 -980 0 0 0.2 0.2 {layer=8}
B 2 1210 -605 1320 -505 {name=l21
flags=graph,unlocked
lock=1
color=8
node="tcleval([xschem translate l21 @#0:net_name] [xschem translate l21 @#1:net_name] -)"
x1=5e-10
x2=0.001
y1=-4.8
y2=15}
B 2 400 -735 510 -635 {name=l22
flags=graph,unlocked
lock=1
color=8
node="tcleval([xschem translate l22 @#0:net_name])"
y1=0.00033
y2=21
x1=5e-10
x2=0.001}
B 2 600 -485 710 -385 {name=l23
flags=graph,unlocked
lock=1
color=8
node="tcleval([xschem get_fqdevice [xschem translate l23 @device]])"
x1=5e-10
x2=0.001
y1=-2.9
y2=6.8}
B 2 640 -295 750 -195 {name=l26
flags=graph,unlocked
lock=1
color=8
node="tcleval([xschem get_fqdevice [xschem translate l26 @device]])"
x1=5e-10
x2=0.001
y1=-2.9
y2=6.8}
B 18 55 -1060 310 -875 {}
A 5 310 -1060 5.590169943749475 243.434948822922 360 {fill=true}
P 7 6 385 -875 330 -1031.25 325 -1045 312.5 -1060 300 -1065 55 -1075 {}
T {2x10 1W white LED} 1350 -195 0 0 0.4 0.4 {layer=8}
T {2xseries 1W white LEDs} 1330 -135 0 0 0.4 0.4 {}
T {2.5} 85 -855 0 0 0.2 0.2 {}
T {5.0} 125 -855 0 0 0.2 0.2 {}
T {7.5} 165 -855 0 0 0.2 0.2 {}
T {10.0} 205 -855 0 0 0.2 0.2 {}
T {12.5} 245 -855 0 0 0.2 0.2 {}
T {15.0} 285 -855 0 0 0.2 0.2 {}
T {17.5} 325 -855 0 0 0.2 0.2 {}
T {20.0} 365 -855 0 0 0.2 0.2 {}
T {2.5} 25 -1080 0 0 0.2 0.2 {}
T {2.0} 25 -1040 0 0 0.2 0.2 {}
T {1.5} 25 -995 0 0 0.2 0.2 {}
T {1.0} 25 -960 0 0 0.2 0.2 {}
T {0.5} 25 -920 0 0 0.2 0.2 {}
T {25C, 1000W/m2} 180 -1130 0 0 0.2 0.2 {}
T {V} 400 -865 0 0 0.4 0.4 {}
T {I} 30 -1120 0 0 0.4 0.4 {}
T {SOLAR PANEL} 135 -1155 0 0 0.4 0.4 {}
T {Maximum Power} 297.5 -1080 0 0 0.2 0.2 {layer=8}
T {set between 0 and 1
to simulate
sun radiation
@ -232,21 +268,21 @@ T {Floater text
example} 870 -440 0 0 0.4 0.4 {}
T {@spice_get_current} 875 -598.75 0 0 0.3 0.3 {layer=7 name=L2}
T {@spice_get_current} 1015 -268.75 0 0 0.3 0.3 {layer=7 name=C1}
N 1010 -210 1100 -210 {lab=0}
N 1100 -300 1100 -210 {lab=0}
N 1010 -180 1100 -180 {lab=0}
N 1100 -300 1100 -180 {lab=0}
N 640 -610 730 -610 {lab=#net1}
N 1010 -440 1040 -440 {lab=VO}
N 1010 -440 1010 -310 {lab=VO}
N 1010 -250 1010 -210 {lab=0}
N 530 -610 580 -610 {lab=PANEL}
N 1010 -250 1010 -180 {lab=0}
N 360 -610 580 -610 {lab=PANEL}
N 1010 -610 1010 -440 {lab=VO}
N 820 -610 860 -610 {lab=SW}
N 820 -610 820 -490 {lab=SW}
N 790 -610 820 -610 {lab=SW}
N 820 -210 1010 -210 {lab=0}
N 800 -210 820 -210 {lab=0}
N 820 -180 1010 -180 {lab=0}
N 800 -180 820 -180 {lab=0}
N 1000 -610 1010 -610 {lab=VO}
N 1100 -440 1140 -440 {lab=LED}
N 1100 -440 1280 -440 {lab=LED}
N 1100 -440 1100 -360 {lab=LED}
N 820 -430 820 -390 { lab=#net2}
N 920 -610 940 -610 { lab=#net3}
@ -295,12 +331,14 @@ N 770 -1080 770 -1030 {
lab=TRIANG}
N 770 -1030 890 -1030 {
lab=TRIANG}
N 820 -330 820 -210 {
N 820 -330 820 -180 {
lab=0}
N 1190 -480 1190 -440 {lab=LED}
N 1190 -670 1190 -640 {lab=PANEL}
C {title.sym} 160 -40 0 0 {name=l1 author="Stefan Schippers"}
C {code_shown.sym} 170 -310 0 0 {name=CONTROL
C {code_shown.sym} 180 -310 0 0 {name=CONTROL
value="tcleval(
.probe alli
.option savecurrents
.control
* example of tcl evaluation of code blocks:
* current path: $path
@ -318,24 +356,26 @@ C {code.sym} 20 -240 0 0 {name=MODELS value=".MODEL DIODE D(IS=1.139e-08 RS=0.99
.MODEL swmod SW(VT=0.5 VH=0.01 RON=0.01 ROFF=10000000)
"}
C {lab_pin.sym} 650 -530 0 1 {name=l4 lab=PANEL }
C {lab_pin.sym} 800 -210 0 0 {name=l6 lab=0 }
C {lab_pin.sym} 800 -180 0 0 {name=l6 lab=0 }
C {ammeter.sym} 1070 -440 3 0 {name=Vled}
C {ind.sym} 890 -610 3 1 {name=L2
m=1
value=40u
footprint=1206
device=inductor
hide_texts=true}
C {lab_pin.sym} 1140 -440 0 1 {name=l7 lab=LED }
hide_texts=true
attach=L2}
C {lab_pin.sym} 1280 -440 0 1 {name=l7 lab=LED }
C {lab_pin.sym} 820 -550 0 1 {name=l9 lab=SW }
C {capa.sym} 1010 -280 0 0 {name=C1
m=1
value=500n
footprint=1206
device="ceramic capacitor"
hide_texts=true}
hide_texts=true
attach=C1}
C {lab_pin.sym} 1010 -400 0 1 {name=l10 lab=VO }
C {lab_pin.sym} 530 -610 0 0 {name=l3 lab=PANEL }
C {lab_pin.sym} 360 -610 0 0 {name=l3 lab=PANEL }
C {ammeter.sym} 970 -610 3 0 {name=Vind}
C {isource_table.sym} 1100 -330 0 0 {name=G2[9..0] CTRL="V(LED)" TABLE="
+ (0, 0)
@ -403,3 +443,15 @@ C {spice_probe.sym} 850 -1030 0 1 {name=p4 analysis=tran}
C {spice_probe.sym} 810 -890 0 1 {name=p5 analysis=tran}
C {spice_probe.sym} 760 -670 0 0 {name=p6 analysis=tran}
C {spice_probe.sym} 160 -450 0 0 {name=p7 analysis=tran}
C {lab_show.sym} 440 -610 2 0 {name=l24}
C {lab_pin.sym} 1190 -670 0 0 {name=l25 lab=PANEL }
C {scope2.sym} 1190 -480 0 0 {name=l21
attach=l21}
C {scope.sym} 380 -610 0 0 {name=l22
attach=l22}
C {scope_ammeter.sym} 580 -360 0 0 {name=l23
attach=l23
device=Vcap}
C {scope_ammeter.sym} 620 -170 0 0 {name=l26
attach=l26
device=Vdiode}