1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: simwindow.c
6 * Simulation tool: signal window control
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 #include "config.h"
33 #if SIMTOOL
34
35 #include "global.h"
36 #include "egraphics.h"
37 #include "edialogs.h"
38 #include "efunction.h"
39 #include "network.h"
40 #include "sim.h"
41 #include "simals.h"
42 #include "tecgen.h"
43 #include "tecschem.h"
44 #include "tecart.h"
45 #include "usr.h"
46 #include "usrtrack.h"
47 #include <math.h>
48 #include <float.h>
49
50 /*
51 * WINDOW CONTROL:
52 * sim_window_init() Initialize simulation window system (do only once)
53 * BOOLEAN sim_window_create(f, np, chw, chs, fmt) Make simulation window with "f" frames, format "fmt"
54 * in cell "np" charhandlers "chw/s" (l=0 to restore)
55 * sim_window_titleinfo(info) adds "info" to title of simulation window
56 * void sim_window_stopsimulation() Stops simulation
57 * INTBIG sim_window_isactive(np) Returns nonzero if simulating, returns cell if so
58 * sim_window_redraw() Redraws simulation window
59 * INTBIG sim_window_getnumframes() Returns number of frames in sim window
60 * sim_window_setnumframes(count) Sets number of frames in simulation window
61 * INTBIG sim_window_getnumvisframes() Returns number of visible frames in sim window
62 * INTBIG sim_window_gettopvisframe() Returns topmost visible frame in simulation window
63 * sim_window_settopvisframe(count) Sets topmost visible frame in simulation window
64 * sim_window_savegraph() Preserves plot in database
65 * sim_window_writespicecmd() Writes vectors as SPICE commands
66 * c = sim_window_getdisplaycolor(s) Get color of strength/state "s"
67 * sim_window_setdisplaycolor(s, c) Set color of strength/state "s" to "c"
68 *
69 * FRAME CONTROL
70 * sim_window_auto_anarange(void) Zooms all frames to fit their traces (TODO: all->frameno)
71 * sim_window_zoom_frame(INTBIG frameno) Zooms In frame "frameno" by scale 2
72 * sim_window_zoomout_frame(INTBIG frameno) Zooms Out frame "frameno" by scale 2
73 * sim_window_shiftup_frame(INTBIG frameno) Shifts Up frame "frameno" by 1/4 of height
74 * sim_window_shiftdown_frame(INTBIG frameno) Shifts Dowm frame "frameno" by 1/4 of height
75 * sim_window_renumberlines() Renumbers frames so that they have no gaps
76 *
77 * CONTROL OF TRACES:
78 * INTBIG sim_window_newtrace(frame, name, data) Creates trace in "frame" called "name" with user "data"
79 * BOOLEAN sim_window_buscommand() Creates a bus from currently selected signals
80 * sim_window_loaddigtrace(tr, num, time, sta) Loads trace "tr" with "num" digital signals "time/sta"
81 * sim_window_loadanatrace(tr, num, time, val) Loads trace "tr" with "num" analog signals "time/val"
82 * sim_window_settraceframe(tr, frame) Sets frame number for trace "tr"
83 * sim_window_killtrace(tr) Deletes trace "tr"
84 * sim_window_killalltraces(save) Deletes all traces
85 * sim_window_supresstraceprefix(prefix) Ignore this prefix when displaying trace names
86 *
87 * TRACE INFORMATION:
88 * INTBIG *sim_window_getbustraces(tr) Returns 0-terminated list of traces in bus "tr"
89 * INTBIG sim_window_gettraceframe(tr) Returns frame number for trace "tr"
90 * INTBIG sim_window_getcurframe() Returns current frame number
91 * char *sim_window_gettracename(tr) Returns name for trace "tr"
92 * INTBIG sim_window_gettracedata(tr) Returns user data for trace "tr"
93 * float sim_window_getanatracevalue(tr, time) Returns analog value for trace "tr" at time "time"
94 * sim_window_getdigtracevalue(tr, time, &lev, &str) Returns digital value for trace "tr" at time "time"
95 * CHAR *sim_window_getbustracevalue(tr, time) Returns bus value for trace "tr" at time "time"
96 * INTBIG *sim_window_findtrace(name, &count) Locates the traces with this name
97 * sim_window_inittraceloop() Begin search of all traces
98 * sim_window_inittraceloop2() Begin search of all traces
99 * INTBIG sim_window_nexttraceloop() Returns next trace (0 when done)
100 * INTBIG sim_window_nexttraceloop2() Returns next trace (0 when done)
101 *
102 * TRACE HIGHLIGHTING:
103 * sim_window_cleartracehighlight() Unhighlights all traces
104 * sim_window_addhighlighttrace(tr) Adds trace "tr" to highlighting
105 * sim_window_deletehighlighttrace(tr) Removes trace "tr" from highlighting
106 * INTBIG sim_window_gethighlighttrace() Returns highlighted trace (0 if none)
107 * INTBIG *sim_window_gethighlighttraces() Returns 0-terminated list of highlighted traces
108 * sim_window_showhighlightedtraces() Makes sure highlighted traces are seen
109 *
110 * TIME AND CURSOR CONTROL:
111 * sim_window_setmaincursor(time) Sets position of main cursor
112 * double sim_window_getmaincursor() Returns position of main cursor
113 * sim_window_setextensioncursor(time) Sets position of extension cursor
114 * double sim_window_getextensioncursor() Returns position of extension cursor
115 * sim_window_settimerange(tr, min, max) Sets trace time range from "min" to "max"
116 * sim_window_gettimerange(tr, min, max) Returns trace time range
117 * sim_window_gettimeextents(min, max) Returns data time range
118 */
119
120 #define BUSANGLE 4 /* defines look of busses */
121
122 #define NOTRACE ((TRACE *)-1)
123
124 /* the meaning of TRACE->flags */
125 #define TRACESELECTED 01 /* set if this trace is selected */
126 #define TRACEMARK 02 /* for temporarily marking a trace */
127 #define TRACETYPE 014 /* the type of this trace */
128 #define TRACEISDIGITAL 0 /* this trace is a digital signal */
129 #define TRACEISANALOG 04 /* this trace is an analog signal */
130 #define TRACEISBUS 010 /* this trace is a bus */
131 #define TRACEISOPENBUS 014 /* this trace is an opened bus */
132 #define TRACENOTDRAWN 020 /* set if trace is not to be drawn */
133 #define TRACEHIGHCHANGED 040 /* set if trace highlighting changed */
134
135 typedef struct Itrace
136 {
137 CHAR *name; /* name of this trace */
138 CHAR *origname; /* original name of this trace */
139 INTBIG flags; /* state bits for this trace (see above) */
140 INTBIG nodeptr; /* "user" data for this trace */
141 INTBIG busindex; /* index of this trace in the bus (when part of a bus) */
142 INTBIG color; /* color of this trace (analog only) */
143 INTBIG nameoff; /* offset of trace name (when many per frame) */
144 INTBIG frameno; /* frame number of this trace in window */
145 INTBIG numsteps; /* number of steps along this trace */
146 INTBIG timelimit; /* maximum times allocated for this trace */
147 INTBIG statelimit; /* maximum states allocated for this trace */
148 INTBIG valuelimit; /* maximum values allocated for this trace */
149 double *timearray; /* time steps along this trace */
150 INTBIG *statearray; /* states along this trace (digital) */
151 float *valuearray; /* values along this trace (analog) */
152 double mintime, maxtime; /* displayed range along horozintal axis */
153 float anadislow; /* low vertical axis for this trace (analog) */
154 float anadishigh; /* high vertical axis for this trace (analog) */
155 float anadisrange; /* vertical range for this trace (analog) */
156 struct Itrace *buschannel;
157 struct Itrace *nexttrace;
158 } TRACE;
159
160 static GRAPHICS sim_window_desc = {LAYERA, ALLOFF, SOLIDC, SOLIDC,
161 {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
162 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
163 static GRAPHICS sim_window_udesc = {LAYERA, ALLOFF, PATTERNED, PATTERNED,
164 {0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,
165 0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555}, NOVARIABLE, 0};
166 static INTBIG sim_window_anacolor[] = {RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, ORANGE,
167 PURPLE, LGRAY, LRED, LGREEN, LBLUE, 0};
168
169 #define DEFWAVEXNAMEEND 112 /* default x position where signal names end */
170 #define DEFWAVEXNAMEENDANA 100 /* default X position where signal names end (if analog) */
171 #define DEFWAVEXBAR 113 /* default X position of the bar between names and waveforms */
172 #define DEFWAVEXSIGSTART 114 /* default X position where waveforms start */
173 #define WAVEXSIGEND 767 /* the X position where waveforms end */
174
175 #define WAVEYTIMETOP 30
176 #define WAVEYSIGBOT 31
177 #define WAVEYSIGTOP 560
178 #define WAVEYSIGRANGE (WAVEYSIGTOP-WAVEYSIGBOT) /* was 540 */
179 #define WAVEYSIGGAP 10
180 #define WAVEYCURSTOP 571
181 #define WAVEYTEXTBOT 561
182 #define WAVEYTEXTTOP 600
183
184 #define TOPBARSIZE 20 /* size of title bar in waveform window */
185
186 #define MINTHUMB 25 /* minimum horizontal thumb size */
187
188 /* still need to convert "sim_window_drawcursors()" */
189
190 /*
191 * In X:
192 * 0 to 112 is signal name
193 * 113 is bar
194 * 114-767 is signal waveform
195 * In Y:
196 * 0 to 30 is axis label
197 * 31 to 560 is signal waveforms
198 * 31 to 571 is the cursors
199 * 561 to 600 is text values (main and extension coordinates)
200 */
201 static INTBIG sim_window_curx, sim_window_cury;
202 static INTBIG sim_window_textsize;
203 static INTBIG sim_window_lines = 0;
204 static INTBIG sim_window_lines_limit = 0;
205 static INTBIG sim_window_visframes; /* frames (or lines) visible in window */
206 static INTBIG sim_window_topframes; /* upper visible frame in window */
207 static INTBIG sim_window_highframe; /* highlighted frame in window */
208 static INTBIG sim_window_txthei;
209 static INTBIG sim_window_curanacolor;
210 static INTBIG sim_window_offx, sim_window_offy;
211 static INTBIG sim_window_basex, sim_window_basey;
212 INTBIG sim_window_statekey; /* key for "SIM_window_state" */
213 INTBIG sim_window_state; /* cached value of "SIM_window_state" */
214 INTBIG sim_window_format; /* type of simulation in window */
215 INTBIG sim_window_signalorder_key;/* key for "SIM_window_signalorder" */
216 INTBIG sim_window_hierpos_key; /* key for "SIM_window_hierarchy_pos" */
217 static double sim_window_maincursor, sim_window_extensioncursor;
218 static float sim_window_analow, sim_window_anahigh, sim_window_anarange;
219 static float *sim_window_frame_analow=NULL, *sim_window_frame_anahigh=NULL;
220 static float *sim_window_frame_topval=NULL, *sim_window_frame_botval=NULL;
221 static INTBIG sim_window_highlightedtracecount;
222 static INTBIG sim_window_highlightedtracetotal = 0;
223 static TRACE **sim_window_highlightedtraces;
224 static INTBIG sim_window_bustracetotal = 0;
225 static TRACE **sim_window_bustraces;
226 static TRACE *sim_window_firstrace;
227 static TRACE *sim_window_tracefree;
228 static TRACE *sim_window_loop;
229 static TRACE *sim_window_loop2;
230 INTBIG sim_colorstrengthoff; /* color of off-strength */
231 INTBIG sim_colorstrengthnode; /* color of node-strength */
232 INTBIG sim_colorstrengthgate; /* color of gate-strength */
233 INTBIG sim_colorstrengthpower; /* color of power-strength */
234 INTBIG sim_colorlevellow; /* color of low-levels */
235 INTBIG sim_colorlevelhigh; /* color of high-levels */
236 INTBIG sim_colorlevelundef; /* color of undefined levels */
237 INTBIG sim_colorlevelzdef; /* color of Z levels */
238 INTBIG sim_colorstrengthoff_key; /* key for "SIM_window_color_str0" */
239 INTBIG sim_colorstrengthnode_key; /* key for "SIM_window_color_str1" */
240 INTBIG sim_colorstrengthgate_key; /* key for "SIM_window_color_str2" */
241 INTBIG sim_colorstrengthpower_key;/* key for "SIM_window_color_str3" */
242 INTBIG sim_colorlevellow_key; /* key for "SIM_window_color_low" */
243 INTBIG sim_colorlevelhigh_key; /* key for "SIM_window_color_high" */
244 INTBIG sim_colorlevelundef_key; /* key for "SIM_window_color_X" */
245 INTBIG sim_colorlevelzdef_key; /* key for "SIM_window_color_Z" */
246 static WINDOWPART *sim_waveformwindow; /* current window when arrows are clicked */
247 static INTBIG sim_waveformsliderpart; /* 0:down arrow 1:below thumb 2:thumb 3:above thumb 4:up arrow */
248 static INTBIG sim_window_tracedragyoff; /* Y offset when dragging */
249 static INTBIG sim_window_initialx; /* initial X coordinate when dragging */
250 static INTBIG sim_window_initialy; /* initial Y coordinate when dragging */
251 static INTBIG sim_window_currentdragy; /* current Y coordinate when dragging */
252 static INTBIG sim_window_deltasofar; /* for dragging thumb button on side */
253 static INTBIG sim_window_initialthumb; /* for dragging thumb button on side */
254 static TRACE *sim_window_tracedragtr; /* signal being dragged */
255 static INTBIG sim_window_sigtotal = 0;
256 static INTBIG *sim_window_sigvalues;
257 static INTBIG sim_window_zoominix, sim_window_zoominiy; /* initial zoom coordinate */
258 static INTBIG sim_window_zoomothx, sim_window_zoomothy; /* final zoom coordinate */
259 static INTBIG sim_waveforminiththumbpos;
260 static double sim_waveformhrange;
261 static float sim_window_maxtime, sim_window_mintime;
262 static float sim_window_max_timetick, sim_window_min_timetick;
263 static float sim_window_time_separation;
264 static float sim_window_percent[] = { 0.1f, 0.5f, 0.9f };
265 #define PERCENTSIZE ((INTBIG)(sizeof(sim_window_percent)/sizeof(sim_window_percent[0])))
266 static float sim_window_vdd;
267 static CHAR *sim_window_title = 0;
268 static CHAR *sim_window_traceprefix = 0;
269 static void *sim_veroldstringarray = 0; /* string array that holds a cell's former signal order */
270 static INTBIG sim_window_wavexnameend; /* the X position where signal names end */
271 static INTBIG sim_window_wavexnameendana;/* the X position where signal names end (if analog) */
272 INTBIG sim_window_wavexbar; /* the X position of the bar between names and waveforms */
273 static INTBIG sim_window_wavexsigstart; /* the X position where waveforms start */
274 static BOOLEAN sim_window_dragshown; /* TRUE if dragging divider between names and waveforms */
275 static BOOLEAN sim_window_draghighoff; /* TRUE if highlights are off during divider dragging */
276 static INTBIG sim_window_draglastx; /* last position of divider between names and waveforms */
277 static INTBIG sim_window_playing; /* state of VCR controls */
278 static UINTBIG sim_window_lastadvance; /* time the VCR last advanced */
279 static UINTBIG sim_window_advancespeed; /* speed of the VCR (in screen pixels) */
280 static INTBIG sim_window_measureframe; /* frame in which measurement is being done */
281 static INTBIG sim_window_firstmeasurex; /* starting screen X coordinate of measurement */
282 static INTBIG sim_window_firstmeasurey; /* starting screen Y coordinate of measurement */
283 static INTBIG sim_window_lastmeasurex; /* current screen X coordinate of measurement */
284 static INTBIG sim_window_lastmeasurey; /* current screen Y coordinate of measurement */
285 static double sim_window_firstmeasuretime; /* current time coordinate of measurement */
286 static double sim_window_firstmeasureyval; /* current value coordinate of measurement */
287 static POLYGON *sim_window_dragpoly = NOPOLYGON; /* polygon for displaying measurement */
288
289 /* the meaning of "sim_window_playing" */
290 #define VCRSTOP 0 /* VCR is stopped */
291 #define VCRPLAYFOREWARD 1 /* VCR is playing forward */
292 #define VCRPLAYBACKWARD 2 /* VCR is playing backward */
293
294 /* prototypes for local routines */
295 static void sim_window_addsegment(WINDOWPART*, INTBIG*, INTBIG*, INTBIG, INTBIG, INTBIG, INTBIG);
296 static void sim_window_addtrace(TRACE *tr, TRACE *aftertr);
297 static TRACE *sim_window_alloctrace(void);
298 static void sim_window_buttonhandler(WINDOWPART*, INTBIG, INTBIG, INTBIG);
299 static CHAR *sim_windowconvertengineeringnotation2(double time, INTBIG precpower);
300 static BOOLEAN sim_window_distancedown(INTBIG x, INTBIG y);
301 static void sim_window_distanceinit(WINDOWPART *wavewin);
302 static void sim_window_distanceup(void);
303 static void sim_window_dividerdone(void);
304 static BOOLEAN sim_window_dividerdown(INTBIG x, INTBIG y);
305 static void sim_window_dividerinit(WINDOWPART *w);
306 static void sim_window_donehighlightchange(WINDOWPART *wavewin);
307 static void sim_window_draw_timeticks(WINDOWPART *wavewin, INTBIG y1, INTBIG y2, BOOLEAN grid);
308 static void sim_window_drawdistance(void);
309 static void sim_window_drawareazoom(WINDOWPART *w, BOOLEAN on, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty);
310 static void sim_window_drawbox(WINDOWPART*, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
311 static void sim_window_drawcstring(WINDOWPART*, CHAR*);
312 static void sim_window_drawcursors(WINDOWPART*);
313 static void sim_window_drawframe(INTBIG frame, WINDOWPART *wavewin);
314 static void sim_window_drawgraph(WINDOWPART*);
315 static void sim_window_drawhcstring(WINDOWPART *w, CHAR *s);
316 static void sim_window_drawtimescale(WINDOWPART*);
317 static void sim_window_drawto(WINDOWPART*, INTBIG, INTBIG, INTBIG);
318 static void sim_window_drawtracedrag(WINDOWPART*, BOOLEAN on);
319 static void sim_window_drawtraceselect(WINDOWPART *wavewin, INTBIG y1, INTBIG y2, BOOLEAN on);
320 static void sim_window_drawulstring(WINDOWPART *w, CHAR *s);
321 static BOOLEAN sim_window_eachbdown(INTBIG, INTBIG);
322 static void sim_window_eachcursordown(INTBIG x, INTBIG y,double *cursor);
323 static BOOLEAN sim_window_eachdown(INTBIG x, INTBIG y);
324 static BOOLEAN sim_window_eachwdown(INTBIG, INTBIG);
325 static INTBIG sim_window_ensurespace(TRACE *tr);
326 static BOOLEAN sim_window_findcross(TRACE *tr, double val, double *time);
327 static WINDOWPART *sim_window_findschematics(void);
328 static void sim_window_findthistrace(CHAR *name);
329 static WINDOWPART *sim_window_findwaveform(void);
330 static float sim_window_get_analow(int traceno);
331 static float sim_window_get_anahigh(int traceno);
332 static float sim_window_get_anarange(int traceno);
333 static float sim_window_get_botval(int frameno);
334 static float sim_window_get_extanarange(int frameno);
335 static float sim_window_get_topval(int frameno);
336 static void sim_window_gethighlightcolor(INTBIG state, INTBIG *texture, INTBIG *color);
337 static void sim_window_highlightname(WINDOWPART *wavewin, TRACE *tr, BOOLEAN on);
338 static BOOLEAN sim_window_horizontalslider(INTBIG x, INTBIG y);
339 static void sim_window_hthumbtrackingcallback(INTBIG delta);
340 static void sim_window_inithighlightchange(void);
341 static BOOLEAN sim_window_lineseg(WINDOWPART *wavewin, INTBIG xf, INTBIG yf, INTBIG xt,
342 INTBIG yt, INTBIG style, INTBIG x, INTBIG y, BOOLEAN thick);
343 static CHAR *sim_window_makewidevalue(INTBIG count, INTBIG *value);
344 static void sim_window_mapcoord(WINDOWPART*, INTBIG*, INTBIG*);
345 static void sim_window_moveto(INTBIG, INTBIG);
346 static CHAR *sim_window_namesignals(INTBIG count, TRACE **list);
347 static BOOLEAN sim_window_plottrace(TRACE *tr, WINDOWPART *wavewin, INTBIG style, INTBIG x, INTBIG y);
348 static CHAR *sim_window_prettyprint(float v, int i1, int i2);
349 static void sim_window_putvalueontrace(TRACE *tr, NODEPROTO *simnt);
350 static void sim_window_redisphandler(WINDOWPART*);
351 static void sim_window_removetrace(TRACE *tr);
352 static void sim_window_savesignalorder(void);
353 static void sim_window_scaletowindow(WINDOWPART*, INTBIG*, INTBIG*);
354 static BOOLEAN sim_window_seleachdown(INTBIG x, INTBIG y);
355 static float sim_window_sensible_value(float *h, float *l, INTBIG *i1, INTBIG *i2, INTBIG n);
356 static double sim_window_sensibletimevalue(double time);
357 static void sim_window_set_anahigh(int frameno, float value);
358 static void sim_window_set_analow(int frameno, float value);
359 static void sim_window_set_botval(int frameno, float value);
360 static int sim_window_set_frames(int n);
361 static void sim_window_set_topval(int frameno, float value);
362 static void sim_window_setcolor(INTBIG);
363 static void sim_window_setmask(INTBIG);
364 static void sim_window_setviewport(WINDOWPART*);
365 static void sim_window_showtracebar(WINDOWPART *wavewin, INTBIG frame, INTBIG style);
366 static void sim_window_termhandler(WINDOWPART *w);
367 static INTBIG sim_window_timetoxpos(double);
368 static void sim_window_trace_range(INTBIG tri) ;
369 static INTBIG sim_window_valtoypos(INTBIG frameno, double val);
370 static BOOLEAN sim_window_verticalslider(INTBIG x, INTBIG y);
371 static void sim_window_vthumbtrackingcallback(INTBIG delta);
372 static void sim_window_writetracename(WINDOWPART*, TRACE*);
373 static double sim_window_xpostotime(INTBIG);
374 static INTBIG sim_window_ypostoval(INTBIG ypos, double *val);
375 static BOOLEAN sim_window_zoomdown(INTBIG, INTBIG);
376
377 /********************************* WINDOW CONTROL *********************************/
378
379 /*
380 * routine to initialize the simulation window
381 */
sim_window_init(void)382 void sim_window_init(void)
383 {
384 sim_window_signalorder_key = makekey(x_("SIM_window_signalorder"));
385 sim_window_hierpos_key = makekey(x_("SIM_window_hierarchy_pos"));
386
387 sim_window_statekey = makekey(x_("SIM_window_state"));
388 #if SIMTOOLIRSIM == 0
389 sim_window_state = FULLSTATE | SHOWWAVEFORM;
390 #else
391 sim_window_state = FULLSTATE | SHOWWAVEFORM | SIMENGINEIRSIM;
392 #endif
393 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_window_statekey,
394 sim_window_state, VINTEGER|VDONTSAVE);
395
396 sim_window_maincursor = 0.0000002f;
397 sim_window_extensioncursor = 0.0000003f;
398 (void)sim_window_set_frames(0) ;
399 sim_window_visframes = 0;
400 sim_window_topframes = 0;
401 sim_window_highframe = -1;
402 sim_window_firstrace = NOTRACE;
403 sim_window_tracefree = NOTRACE;
404 sim_window_highlightedtracecount = 0;
405 sim_window_wavexnameend = DEFWAVEXNAMEEND;
406 sim_window_wavexnameendana = DEFWAVEXNAMEENDANA;
407 sim_window_wavexbar = DEFWAVEXBAR;
408 sim_window_wavexsigstart = DEFWAVEXSIGSTART;
409 sim_window_playing = VCRSTOP;
410 sim_window_advancespeed = 2;
411
412 /* setup simulation window colors */
413 sim_colorstrengthoff = BLUE;
414 sim_colorstrengthnode = GREEN;
415 sim_colorstrengthgate = MAGENTA;
416 sim_colorstrengthpower = BLACK;
417 sim_colorlevellow = BLUE;
418 sim_colorlevelhigh = MAGENTA;
419 sim_colorlevelundef = BLACK;
420 sim_colorlevelzdef = LGRAY;
421 sim_colorstrengthoff_key = makekey(x_("SIM_window_color_str0"));
422 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthoff_key, sim_colorstrengthoff, VINTEGER|VDONTSAVE);
423 sim_colorstrengthnode_key = makekey(x_("SIM_window_color_str1"));
424 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthnode_key, sim_colorstrengthnode, VINTEGER|VDONTSAVE);
425 sim_colorstrengthgate_key = makekey(x_("SIM_window_color_str2"));
426 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthgate_key, sim_colorstrengthgate, VINTEGER|VDONTSAVE);
427 sim_colorstrengthpower_key = makekey(x_("SIM_window_color_str3"));
428 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthpower_key, sim_colorstrengthpower, VINTEGER|VDONTSAVE);
429 sim_colorlevellow_key = makekey(x_("SIM_window_color_low"));
430 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevellow_key, sim_colorlevellow, VINTEGER|VDONTSAVE);
431 sim_colorlevelhigh_key = makekey(x_("SIM_window_color_high"));
432 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevelhigh_key, sim_colorlevelhigh, VINTEGER|VDONTSAVE);
433 sim_colorlevelundef_key = makekey(x_("SIM_window_color_X"));
434 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevelundef_key, sim_colorlevelundef, VINTEGER|VDONTSAVE);
435 sim_colorlevelzdef_key = makekey(x_("SIM_window_color_Z"));
436 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevelzdef_key, sim_colorlevelzdef, VINTEGER|VDONTSAVE);
437 }
438
439 /*
440 * routine to terminate the simulation window module memory
441 */
sim_freewindowmemory(void)442 void sim_freewindowmemory(void)
443 {
444 REGISTER TRACE *tr;
445
446 sim_window_killalltraces(FALSE);
447
448 while (sim_window_tracefree != NOTRACE)
449 {
450 tr = sim_window_tracefree;
451 sim_window_tracefree = sim_window_tracefree->nexttrace;
452 if (tr->timelimit > 0) efree((CHAR *)tr->timearray);
453 if (tr->statelimit > 0) efree((CHAR *)tr->statearray);
454 if (tr->valuelimit > 0) efree((CHAR *)tr->valuearray);
455 efree((CHAR *)tr);
456 }
457 if (sim_window_highlightedtracetotal > 0) efree((CHAR *)sim_window_highlightedtraces);
458 if (sim_window_bustracetotal > 0) efree((CHAR *)sim_window_bustraces);
459 if (sim_window_sigtotal > 0)
460 {
461 efree((CHAR *)sim_window_sigvalues);
462 sim_window_sigtotal = 0;
463 }
464 if (sim_window_lines_limit > 0)
465 {
466 efree((CHAR *)sim_window_frame_analow);
467 efree((CHAR *)sim_window_frame_anahigh);
468 efree((CHAR *)sim_window_frame_topval);
469 efree((CHAR *)sim_window_frame_botval);
470 }
471 if (sim_window_title != 0) efree((CHAR *)sim_window_title);
472 if (sim_window_traceprefix != 0) efree((CHAR *)sim_window_traceprefix);
473 if (sim_veroldstringarray == 0)
474 killstringarray(sim_veroldstringarray);
475 }
476
477 /*
478 * routine to start a simulation window with room for "framecount" traces and associated cell "np".
479 * The character handler to use in the waveform window is in "charhandlerwave", the character
480 * handler to use in the schematic/layout window is in "charhandlerschem". Returns true on error.
481 */
sim_window_create(INTBIG framecount,NODEPROTO * np,BOOLEAN (* charhandlerwave)(WINDOWPART *,INTSML,INTBIG),BOOLEAN (* charhandlerschem)(WINDOWPART *,INTSML,INTBIG),INTBIG format)482 BOOLEAN sim_window_create(INTBIG framecount, NODEPROTO *np, BOOLEAN (*charhandlerwave)(WINDOWPART*, INTSML, INTBIG),
483 BOOLEAN (*charhandlerschem)(WINDOWPART*, INTSML, INTBIG), INTBIG format)
484 {
485 REGISTER WINDOWPART *wavewin, *schemwin;
486 REGISTER NODEPROTO *simnp;
487
488 /* sorry, can't have more than 1 simulation window at a time */
489 wavewin = sim_window_findwaveform();
490 schemwin = sim_window_findschematics();
491 simnp = NONODEPROTO;
492 if (wavewin != NOWINDOWPART && (wavewin->state&WINDOWSIMMODE) != 0)
493 simnp = wavewin->curnodeproto;
494 if (schemwin != NOWINDOWPART) simnp = schemwin->curnodeproto;
495 if (simnp != NONODEPROTO && simnp != np)
496 {
497 ttyputerr(x_("Sorry, already simulating cell %s"), describenodeproto(simnp));
498 return(TRUE);
499 }
500
501 /* reinitialize waveform display if number of lines is specified */
502 if (framecount > 0)
503 {
504 sim_window_killalltraces(TRUE);
505 if (sim_window_set_frames(framecount) == 0) return TRUE;
506 sim_window_topframes = 0;
507 }
508
509 /* save simulation format */
510 sim_window_format = format;
511
512 /* determine the number of visible signals */
513 sim_window_visframes = sim_window_lines;
514 sim_window_curanacolor = 0;
515 sim_window_vdd = 0.0;
516
517 /* remove title information */
518 if (sim_window_title != 0) efree((CHAR *)sim_window_title);
519 sim_window_title = 0;
520
521 /* remove trace prefix information */
522 if (sim_window_traceprefix != 0) efree((CHAR *)sim_window_traceprefix);
523 sim_window_traceprefix = 0;
524
525 /* create waveform window if requested */
526 if (charhandlerwave != 0)
527 {
528 if (wavewin == NOWINDOWPART)
529 {
530 /* get window state information */
531 switch (sim_window_state&WAVEPLACE)
532 {
533 case WAVEPLACECAS:
534 wavewin = (WINDOWPART *)asktool(us_tool, x_("window-new"));
535 break;
536 case WAVEPLACETHOR:
537 wavewin = (WINDOWPART *)asktool(us_tool, x_("window-horiz-new"));
538 break;
539 case WAVEPLACETVER:
540 wavewin = (WINDOWPART *)asktool(us_tool, x_("window-vert-new"));
541 break;
542 }
543 if (wavewin == NOWINDOWPART) return(TRUE);
544 }
545 sim_window_setviewport(wavewin);
546
547 startobjectchange((INTBIG)wavewin, VWINDOWPART);
548 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("state"), (wavewin->state & ~WINDOWTYPE) | WAVEFORMWINDOW |
549 WINDOWSIMMODE, VINTEGER);
550 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("curnodeproto"), (INTBIG)np, VNODEPROTO);
551 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("buttonhandler"), (INTBIG)sim_window_buttonhandler, VADDRESS);
552 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("charhandler"), (INTBIG)charhandlerwave, VADDRESS);
553 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("redisphandler"), (INTBIG)sim_window_redisphandler, VADDRESS);
554 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("termhandler"), (INTBIG)sim_window_termhandler, VADDRESS);
555 endobjectchange((INTBIG)wavewin, VWINDOWPART);
556 us_setcellname(wavewin);
557 }
558
559 /* find and setup associated schematics/layout window if requested */
560 if (charhandlerschem != 0)
561 {
562 for(schemwin = el_topwindowpart; schemwin != NOWINDOWPART;
563 schemwin = schemwin->nextwindowpart)
564 {
565 if ((schemwin->state&WINDOWTYPE) != DISPWINDOW &&
566 (schemwin->state&WINDOWTYPE) != DISP3DWINDOW) continue;
567 if (schemwin->curnodeproto == np) break;
568 }
569 if (schemwin != NOWINDOWPART)
570 {
571 startobjectchange((INTBIG)schemwin, VWINDOWPART);
572 (void)setval((INTBIG)schemwin, VWINDOWPART, x_("state"), schemwin->state |
573 WINDOWSIMMODE, VINTEGER);
574 (void)setval((INTBIG)schemwin, VWINDOWPART, x_("charhandler"),
575 (INTBIG)charhandlerschem, VADDRESS);
576 endobjectchange((INTBIG)schemwin, VWINDOWPART);
577 }
578 }
579 return(FALSE);
580 }
581
sim_window_titleinfo(CHAR * title)582 void sim_window_titleinfo(CHAR *title)
583 {
584 if (sim_window_title != 0) efree((CHAR *)sim_window_title);
585 allocstring(&sim_window_title, title, sim_tool->cluster);
586 }
587
588 /*
589 * Routine to stop simulation.
590 */
sim_window_stopsimulation(void)591 void sim_window_stopsimulation(void)
592 {
593 REGISTER WINDOWPART *schemwin, *wavewin;
594
595 /* disable simulation control in schematics/layout window */
596 schemwin = sim_window_findschematics();
597 if (schemwin != NOWINDOWPART)
598 {
599 startobjectchange((INTBIG)schemwin, VWINDOWPART);
600 (void)setval((INTBIG)schemwin, VWINDOWPART, x_("state"), schemwin->state &
601 ~WINDOWSIMMODE, VINTEGER);
602 (void)setval((INTBIG)schemwin, VWINDOWPART, x_("charhandler"),
603 (INTBIG)DEFAULTCHARHANDLER, VADDRESS);
604 endobjectchange((INTBIG)schemwin, VWINDOWPART);
605 }
606
607 /* disable waveform window */
608 wavewin = sim_window_findwaveform();
609 if (wavewin != NOWINDOWPART)
610 {
611 startobjectchange((INTBIG)wavewin, VWINDOWPART);
612 (void)setval((INTBIG)wavewin, VWINDOWPART, x_("state"), wavewin->state &
613 ~WINDOWSIMMODE, VINTEGER);
614 endobjectchange((INTBIG)wavewin, VWINDOWPART);
615 }
616 }
617
618 /*
619 * Routine to set vdd value used for grid
620 */
sim_window_setvdd(float vdd)621 void sim_window_setvdd(float vdd)
622 {
623 sim_window_vdd = vdd;
624 }
625
626 /*
627 * routine that returns:
628 * 0 if there is no active simulation
629 * SIMWINDOWWAVEFORM if simulating and have a waveform window
630 * SIMWINDOWSCHEMATIC if simulating and have a schematics window
631 * SIMWINDOWWAVEFORM|SIMWINDOWSCHEMATIC if simulating and have both windows
632 * If there is active simulation, the cell being simulated is returned in "np"
633 */
sim_window_isactive(NODEPROTO ** np)634 INTBIG sim_window_isactive(NODEPROTO **np)
635 {
636 REGISTER INTBIG activity;
637 REGISTER WINDOWPART *wavewin, *schemwin;
638
639 *np = NONODEPROTO;
640 activity = 0;
641 schemwin = sim_window_findschematics();
642 if (schemwin != NOWINDOWPART)
643 {
644 activity |= SIMWINDOWSCHEMATIC;
645 *np = schemwin->curnodeproto;
646 }
647 wavewin = sim_window_findwaveform();
648 if (wavewin != NOWINDOWPART && (wavewin->state&WINDOWSIMMODE) != 0)
649 {
650 activity |= SIMWINDOWWAVEFORM;
651 *np = wavewin->curnodeproto;
652 }
653 return(activity);
654 }
655
656 /*
657 * this procedure redraws everything, including the waveforms.
658 */
sim_window_redraw(void)659 void sim_window_redraw(void)
660 {
661 REGISTER WINDOWPART *wavewin;
662
663 /* get the waveform window */
664 wavewin = sim_window_findwaveform();
665 if (wavewin == NOWINDOWPART) return;
666 sim_window_redisphandler(wavewin);
667 }
668
669 /*
670 * routine that changes the number of trace frames in the simulation window to "count"
671 */
sim_window_setnumframes(INTBIG count)672 void sim_window_setnumframes(INTBIG count)
673 {
674 (void)sim_window_set_frames(count);
675 if (sim_window_lines < sim_window_visframes)
676 sim_window_visframes = sim_window_lines;
677 }
678
679 /*
680 * routine that returns the number of signals in the simulation window
681 */
sim_window_getnumframes(void)682 INTBIG sim_window_getnumframes(void)
683 {
684 return(sim_window_lines);
685 }
686
687 /*
688 * routine that returns the number of visible signals in the simulation window
689 */
sim_window_getnumvisframes(void)690 INTBIG sim_window_getnumvisframes(void)
691 {
692 return(sim_window_visframes);
693 }
694
695 /*
696 * routine that changes the top visible trace frame in the simulation window to "count"
697 */
sim_window_settopvisframe(INTBIG top)698 void sim_window_settopvisframe(INTBIG top)
699 {
700 if (top < 0) top = 0;
701 sim_window_topframes = top;
702 }
703
704 /*
705 * routine that returns the top visible signal in the simulation window.
706 */
sim_window_gettopvisframe(void)707 INTBIG sim_window_gettopvisframe(void)
708 {
709 return(sim_window_topframes);
710 }
711
712 /********************************* CONTROL OF TRACES *********************************/
713
714 /*
715 * routine to create a new trace to be displayed in window frame
716 * "frameno". Its name is set to "name", and "userdata" is
717 * associated with it. A pointer to the trace is returned (zero on error).
718 */
sim_window_newtrace(INTBIG frameno,CHAR * name,INTBIG userdata)719 INTBIG sim_window_newtrace(INTBIG frameno, CHAR *name, INTBIG userdata)
720 {
721 REGISTER TRACE *tr, *otr, *lasttr;
722
723 /* create a new trace */
724 tr = sim_window_alloctrace();
725 if (tr == NOTRACE) return(0);
726 tr->nodeptr = userdata;
727 tr->mintime = sim_window_maincursor;
728 tr->maxtime = sim_window_extensioncursor;
729
730 /* set name and convert if it has array index form */
731 (void)allocstring(&tr->name, name, sim_tool->cluster);
732 (void)allocstring(&tr->origname, name, sim_tool->cluster);
733
734 /* put in active list */
735 lasttr = NOTRACE;
736 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
737 lasttr = otr;
738 sim_window_addtrace(tr, lasttr);
739
740 if (frameno >= 0) tr->frameno = frameno; else
741 {
742 tr->frameno = -1;
743 sim_window_renumberlines();
744
745 sim_window_setnumframes(sim_window_lines);
746 sim_window_redraw();
747 }
748
749 /* save the new configuration */
750 sim_window_savesignalorder();
751
752 return((INTBIG)tr);
753 }
754
755 /*
756 * Routine to open/close a bus. Returns true on error.
757 */
sim_window_buscommand(void)758 BOOLEAN sim_window_buscommand(void)
759 {
760 REGISTER TRACE *tr;
761 REGISTER INTBIG i, count, newtr;
762 INTBIG *tracelist;
763
764 if (sim_window_highlightedtracecount == 0) return(TRUE);
765 if (sim_window_highlightedtracecount == 1)
766 {
767 tr = sim_window_highlightedtraces[0];
768 switch (tr->flags&TRACETYPE)
769 {
770 case TRACEISDIGITAL:
771 case TRACEISANALOG:
772 ttyputerr(_("Must select multiple signals to pack into a bus"));
773 break;
774 case TRACEISBUS:
775 ttyputmsg(_("Double-click the bus name to open it"));
776 break;
777 case TRACEISOPENBUS:
778 ttyputmsg(_("Double-click the bus name to close it"));
779 break;
780 }
781 return(TRUE);
782 }
783
784 /* copy highlighted traces to an array and remove highlighting */
785 count = sim_window_highlightedtracecount;
786 tracelist = (INTBIG *)emalloc(count * SIZEOFINTBIG, sim_tool->cluster);
787 if (tracelist == 0) return(TRUE);
788 for(i=0; i<count; i++)
789 tracelist[i] = (INTBIG)sim_window_highlightedtraces[i];
790 sim_window_cleartracehighlight();
791
792 /* make the bus */
793 newtr = sim_window_makebus(count, tracelist, 0);
794 efree((CHAR *)tracelist);
795 if (newtr == 0) return(TRUE);
796 sim_window_addhighlighttrace(newtr);
797
798 /* redisplay */
799 sim_window_redraw();
800
801 /* save the new configuration */
802 sim_window_savesignalorder();
803 return(FALSE);
804 }
805
sim_window_makebus(INTBIG count,INTBIG * traces,CHAR * busname)806 INTBIG sim_window_makebus(INTBIG count, INTBIG *traces, CHAR *busname)
807 {
808 REGISTER TRACE *tr, *lasttr, *newtr, **tracelist;
809 REGISTER INTBIG i, flags;
810
811 /* check for errors */
812 tracelist = (TRACE **)traces;
813 for(i=0; i<count; i++)
814 {
815 flags = tracelist[i]->flags & TRACETYPE;
816 if (flags == TRACEISBUS || flags == TRACEISOPENBUS)
817 {
818 ttyputerr(_("Cannot place a bus into another bus"));
819 return(0);
820 }
821 if (tracelist[i]->buschannel != NOTRACE)
822 {
823 ttyputerr(_("Signal '%s' is already on bus '%s'"), tracelist[i]->name,
824 tracelist[i]->buschannel->name);
825 return(0);
826 }
827 }
828 if (count > MAXSIMWINDOWBUSWIDTH)
829 {
830 ttyputerr(_("Can only handle busses that are %d bits wide"), MAXSIMWINDOWBUSWIDTH);
831 return(0);
832 }
833
834 /* find place to insert bus */
835 lasttr = NOTRACE;
836 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
837 {
838 for(i=0; i<count; i++)
839 if (tracelist[i] == tr) break;
840 if (i < count) break;
841 lasttr = tr;
842 }
843
844 /* create a new trace that combines all of these */
845 newtr = sim_window_alloctrace();
846 if (newtr == NOTRACE) return(0);
847 if (busname != 0) (void)allocstring(&newtr->name, busname, sim_tool->cluster); else
848 (void)allocstring(&newtr->name, sim_window_namesignals(count, tracelist),
849 sim_tool->cluster);
850 (void)allocstring(&newtr->origname, newtr->name, sim_tool->cluster);
851 newtr->nodeptr = 0;
852 newtr->flags = TRACEISBUS;
853
854 /* insert it after "lasttr" */
855 sim_window_addtrace(newtr, lasttr);
856
857 /* flag the signals as part of this bus */
858 for(i=0; i<count; i++)
859 {
860 tr = tracelist[i];
861 tr->buschannel = newtr;
862 tr->flags |= TRACENOTDRAWN;
863 if (i == 0)
864 {
865 newtr->mintime = tr->mintime;
866 newtr->maxtime = tr->maxtime;
867 } else
868 {
869 if (tr->mintime < newtr->mintime) newtr->mintime = tr->mintime;
870 if (tr->maxtime > newtr->maxtime) newtr->maxtime = tr->maxtime;
871 }
872 }
873
874 /* renumber the lines in the display */
875 sim_window_renumberlines();
876 return((INTBIG)newtr);
877 }
878
879 /*
880 * Routine to generate a bus name for the "count" signals in "list".
881 */
sim_window_namesignals(INTBIG count,TRACE ** list)882 CHAR *sim_window_namesignals(INTBIG count, TRACE **list)
883 {
884 REGISTER INTBIG i, j, rootlen, lastvalue, thisvalue, direction;
885 REGISTER TRACE *tr, *ptr;
886 REGISTER void *infstr;
887
888 /* look for common root */
889 rootlen = 0;
890 for(i=1; i<count; i++)
891 {
892 ptr = list[i-1];
893 tr = list[i];
894 for(j=0; ; j++)
895 {
896 if (ptr->name[j] == 0 || tr->name[0] == 0) break;
897 if (ptr->name[j] != tr->name[j]) break;
898 }
899 if (i == 1 || j < rootlen) rootlen = j;
900 }
901
902 /* if there is a common root, make sure it is proper */
903 if (rootlen > 0)
904 {
905 tr = list[0];
906 if (tr->name[rootlen-1] != '[')
907 {
908 for(i=0; i<count; i++)
909 {
910 tr = list[i];
911 if (isdigit(tr->name[rootlen]) == 0) break;
912 }
913 if (i < count) rootlen = 0;
914 }
915 }
916
917 /* if there is a common root, use it */
918 if (rootlen > 0)
919 {
920 infstr = initinfstr();
921 tr = list[0];
922 for(j=0; j<rootlen; j++) (void)addtoinfstr(infstr, tr->name[j]);
923
924 for(i=0; i<count; i++)
925 {
926 tr = list[i];
927 if (i != 0) addtoinfstr(infstr, ',');
928 for(j=rootlen; tr->name[j] != ']' && tr->name[j] != 0; j++)
929 addtoinfstr(infstr, tr->name[j]);
930
931 /* see if there is a sequence */
932 thisvalue = 0;
933 lastvalue = eatoi(&tr->name[rootlen]);
934 direction = 0;
935 for(j=i+1; j<count; j++)
936 {
937 thisvalue = eatoi(&list[j]->name[rootlen]);
938 if (direction == 0)
939 {
940 if (lastvalue+1 == thisvalue) direction = 1; else
941 if (lastvalue-1 == thisvalue) direction = -1; else
942 break;
943 }
944 if (lastvalue + direction != thisvalue) break;
945 lastvalue = thisvalue;
946 }
947 if (j > i+1)
948 {
949 formatinfstr(infstr, x_(":%ld"), thisvalue);
950 i = j;
951 }
952 }
953 if (tr->name[rootlen-1] == '[') addtoinfstr(infstr, ']');
954 return(returninfstr(infstr));
955 }
956
957 /* no common root: concatenate all signal names */
958 infstr = initinfstr();
959 for(i=0; i<count; i++)
960 {
961 if (i != 0) addtoinfstr(infstr, ',');
962 tr = list[i];
963 addstringtoinfstr(infstr, tr->name);
964 }
965 return(returninfstr(infstr));
966 }
967
968 /*
969 * Routine called when simulating, and the current cell changes to "cell".
970 * caches the signal order for that cell, and updates the waveform window to
971 * be associated with that cell.
972 *
973 * The list of signals can be found by calling "sim_window_getcachedsignals()"
974 */
sim_window_grabcachedsignalsoncell(NODEPROTO * cell)975 void sim_window_grabcachedsignalsoncell(NODEPROTO *cell)
976 {
977 REGISTER VARIABLE *var;
978 REGISTER INTBIG i, count;
979 REGISTER WINDOWPART *w;
980
981 if (sim_veroldstringarray == 0)
982 sim_veroldstringarray = newstringarray(sim_tool->cluster);
983 clearstrings(sim_veroldstringarray);
984 var = getvalkey((INTBIG)cell, VNODEPROTO, VSTRING|VISARRAY,
985 sim_window_signalorder_key);
986 if (var != NOVARIABLE)
987 {
988 count = getlength(var);
989 for(i=0; i<count; i++)
990 addtostringarray(sim_veroldstringarray, ((CHAR **)var->addr)[i]);
991 }
992
993 /* find the waveform window and make sure it has the right cell */
994 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
995 {
996 if ((w->state & WINDOWTYPE) != WAVEFORMWINDOW) continue;
997 w->curnodeproto = cell;
998 break;
999 }
1000 }
1001
1002 /*
1003 * Routine to return the number of strings that were found on the cell that
1004 * was passed to "sim_window_grabcachedsignalsoncell()". The strings are returned
1005 * in "strings".
1006 */
sim_window_getcachedsignals(CHAR *** strings)1007 INTBIG sim_window_getcachedsignals(CHAR ***strings)
1008 {
1009 INTBIG count;
1010
1011 *strings = getstringarray(sim_veroldstringarray, &count);
1012 return(count);
1013 }
1014
sim_window_savesignalorder(void)1015 void sim_window_savesignalorder(void)
1016 {
1017 REGISTER TRACE *tr, *otr;
1018 NODEPROTO *np;
1019 CHAR **strings;
1020 INTBIG count, i, j;
1021 REGISTER void *infstr;
1022
1023 if (sim_window_isactive(&np) == 0) return;
1024 for(count = 0, tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1025 if ((tr->flags&TRACENOTDRAWN) == 0 && tr->buschannel == NOTRACE) count++;
1026 if (count == 0)
1027 {
1028 if (getvalkey((INTBIG)np, VNODEPROTO, VSTRING|VISARRAY, sim_window_signalorder_key) != NOVARIABLE)
1029 (void)delvalkey((INTBIG)np, VNODEPROTO, sim_window_signalorder_key);
1030 } else
1031 {
1032 strings = (CHAR **)emalloc(count * (sizeof (CHAR *)), sim_tool->cluster);
1033 for(i=0, j=0, tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace, i++)
1034 {
1035 if ((tr->flags&TRACENOTDRAWN) != 0 || tr->buschannel != NOTRACE) continue;
1036 if ((tr->flags&TRACETYPE) == TRACEISBUS || (tr->flags&TRACETYPE) == TRACEISOPENBUS)
1037 {
1038 /* construct name for this bus */
1039 infstr = initinfstr();
1040 addstringtoinfstr(infstr, tr->origname);
1041 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
1042 {
1043 if (otr->buschannel != tr) continue;
1044 formatinfstr(infstr, x_("\t%ld:%s"), otr->frameno, otr->origname);
1045 }
1046 (void)allocstring(&strings[j++], returninfstr(infstr), sim_tool->cluster);
1047 } else
1048 {
1049 infstr = initinfstr();
1050 formatinfstr(infstr, x_("%ld:%s"), tr->frameno, tr->origname);
1051 (void)allocstring(&strings[j++], returninfstr(infstr), sim_tool->cluster);
1052 }
1053 }
1054 (void)setvalkey((INTBIG)np, VNODEPROTO, sim_window_signalorder_key, (INTBIG)strings,
1055 VSTRING|VISARRAY|(count<<VLENGTHSH));
1056 for(i=0; i<count; i++) efree((CHAR *)strings[i]);
1057 efree((CHAR *)strings);
1058 }
1059 }
1060
1061 /*
1062 * routine to load trace "tri" with "count" digital events. The events occur
1063 * at time "time" and have state "state". "State" is encoded with a
1064 * level in the upper 8 bits (LOGIC_LOW, LOGIC_HIGH, LOGIC_X, or LOGIC_Z) and a
1065 * strength in the lower 8 bits (OFF_STRENGTH, NODE_STRENGTH, GATE_STRENGTH,
1066 * or VDD_STRENGTH).
1067 */
sim_window_loaddigtrace(INTBIG tri,INTBIG count,double * time,INTSML * state)1068 void sim_window_loaddigtrace(INTBIG tri, INTBIG count, double *time, INTSML *state)
1069 {
1070 REGISTER INTBIG wanted, i;
1071 REGISTER TRACE *tr;
1072
1073 /* ensure space in the arrays */
1074 tr = (TRACE *)tri;
1075 if (tr == NOTRACE || tr == 0) return;
1076 if (count > tr->timelimit)
1077 {
1078 if (tr->timelimit > 0)
1079 {
1080 efree((CHAR *)tr->timearray);
1081 tr->timelimit = 0;
1082 }
1083 wanted = count + 10;
1084 tr->timearray = (double *)emalloc(wanted * (sizeof (double)), sim_tool->cluster);
1085 if (tr->timearray == 0) return;
1086 tr->timelimit = wanted;
1087 }
1088 if (count > tr->statelimit)
1089 {
1090 if (tr->statelimit > 0)
1091 {
1092 efree((CHAR *)tr->statearray);
1093 tr->statelimit = 0;
1094 }
1095 wanted = count + 10;
1096 tr->statearray = (INTBIG *)emalloc(wanted * SIZEOFINTBIG, sim_tool->cluster);
1097 tr->statelimit = wanted;
1098 }
1099
1100 /* load the data */
1101 for(i=0; i<count; i++)
1102 {
1103 tr->timearray[i] = time[i];
1104 tr->statearray[i] = state[i];
1105 }
1106 tr->flags = (tr->flags & ~TRACETYPE) | TRACEISDIGITAL;
1107 tr->numsteps = count;
1108 }
1109
1110 /*
1111 * routine to load trace "tri" with "count" analog events. The events occur
1112 * at time "time" and have value "value".
1113 */
sim_window_loadanatrace(INTBIG tri,INTBIG count,double * time,float * value)1114 void sim_window_loadanatrace(INTBIG tri, INTBIG count, double *time, float *value)
1115 {
1116 REGISTER INTBIG wanted, i;
1117 REGISTER TRACE *tr;
1118
1119 /* ensure space in the arrays */
1120 tr = (TRACE *)tri;
1121 if (tr == NOTRACE || tr == 0) return;
1122 if (count > tr->timelimit)
1123 {
1124 if (tr->timelimit > 0)
1125 {
1126 efree((CHAR *)tr->timearray);
1127 tr->timelimit = 0;
1128 }
1129 wanted = count + 10;
1130 tr->timearray = (double *)emalloc(wanted * (sizeof (double)), sim_tool->cluster);
1131 if (tr->timearray == 0) return;
1132 tr->timelimit = wanted;
1133 }
1134 if (count > tr->valuelimit)
1135 {
1136 if (tr->valuelimit > 0)
1137 {
1138 efree((CHAR *)tr->valuearray);
1139 tr->valuelimit = 0;
1140 }
1141 wanted = count + 10;
1142 tr->valuearray = (float *)emalloc(wanted * (sizeof (float)), sim_tool->cluster);
1143 if (tr->valuearray == 0) return;
1144 tr->valuelimit = wanted;
1145 }
1146
1147 /* load the data */
1148 for(i=0; i<count; i++)
1149 {
1150 tr->timearray[i] = time[i];
1151 tr->valuearray[i] = value[i];
1152 }
1153 tr->flags = (tr->flags & ~TRACETYPE) | TRACEISANALOG;
1154 tr->color = sim_window_anacolor[sim_window_curanacolor];
1155 sim_window_curanacolor++;
1156 if (sim_window_anacolor[sim_window_curanacolor] == 0) sim_window_curanacolor = 0;
1157 tr->numsteps = count;
1158 sim_window_trace_range(tri);
1159 #if 1
1160 sim_window_auto_anarange();
1161 #endif
1162 }
1163
sim_window_settraceframe(INTBIG tri,INTBIG frameno)1164 void sim_window_settraceframe(INTBIG tri, INTBIG frameno)
1165 {
1166 REGISTER TRACE *tr;
1167
1168 tr = (TRACE *)tri;
1169 if (tr == NOTRACE || tr == 0) return;
1170 tr->frameno = frameno;
1171 }
1172
1173 /*
1174 * routine to delete the trace "tri"
1175 */
sim_window_killtrace(INTBIG tri)1176 void sim_window_killtrace(INTBIG tri)
1177 {
1178 REGISTER TRACE *tr, *str, *ltr, *otr;
1179 REGISTER INTBIG frameno;
1180
1181 tr = (TRACE *)tri;
1182 if (tr == NOTRACE || tr == 0) return;
1183 frameno = tr->frameno;
1184 ltr = NOTRACE;
1185 for(str = sim_window_firstrace; str != NOTRACE; str = str->nexttrace)
1186 {
1187 if (str == tr) break;
1188 ltr = str;
1189 }
1190 if (ltr == NOTRACE) sim_window_firstrace = tr->nexttrace; else
1191 ltr->nexttrace = tr->nexttrace;
1192 tr->nexttrace = sim_window_tracefree;
1193 sim_window_tracefree = tr;
1194 efree(tr->name);
1195 efree(tr->origname);
1196
1197 /* if a bus was deleted, make it's individual signals be visible and independent */
1198 if ((tr->flags&TRACETYPE) == TRACEISBUS || (tr->flags&TRACETYPE) == TRACEISOPENBUS)
1199 {
1200 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
1201 {
1202 if (otr->buschannel != tr) continue;
1203 otr->buschannel = NOTRACE;
1204 otr->flags &= ~TRACENOTDRAWN;
1205 }
1206 }
1207
1208 /* renumber the lines in the display */
1209 sim_window_renumberlines();
1210
1211 /* save the new configuration */
1212 sim_window_savesignalorder();
1213
1214 /* if the number of lines is less than the number of visible lines, redisplay */
1215 if (sim_window_lines < sim_window_visframes)
1216 {
1217 sim_window_setnumframes(sim_window_lines);
1218 sim_window_redraw();
1219 }
1220 }
1221
1222 /*
1223 * routine to delete all traces
1224 */
sim_window_killalltraces(BOOLEAN save)1225 void sim_window_killalltraces(BOOLEAN save)
1226 {
1227 REGISTER TRACE *tr, *nexttr;
1228
1229 /* return all plot channels to the free list */
1230 for(tr = sim_window_firstrace; tr != NOTRACE; tr = nexttr)
1231 {
1232 nexttr = tr->nexttrace;
1233 tr->nexttrace = sim_window_tracefree;
1234 sim_window_tracefree = tr;
1235 efree(tr->name);
1236 efree(tr->origname);
1237 }
1238 sim_window_firstrace = NOTRACE;
1239 sim_window_highlightedtracecount = 0;
1240
1241 /* save the new configuration */
1242 if (save) sim_window_savesignalorder();
1243 sim_window_set_frames(1);
1244 sim_window_visframes = 1;
1245 sim_window_topframes = 0;
1246 sim_window_highframe = -1;
1247 }
1248
1249 /*
1250 * Ignore "prefix" when it appears at the start of a trace name.
1251 */
sim_window_supresstraceprefix(CHAR * prefix)1252 void sim_window_supresstraceprefix(CHAR *prefix)
1253 {
1254 if (sim_window_traceprefix != 0) efree((CHAR *)sim_window_traceprefix);
1255 allocstring(&sim_window_traceprefix, prefix, sim_tool->cluster);
1256 }
1257
1258 /********************************* TRACE INFORMATION *********************************/
1259
sim_window_getbustraces(INTBIG tri)1260 INTBIG *sim_window_getbustraces(INTBIG tri)
1261 {
1262 REGISTER TRACE *tr, *otr;
1263 REGISTER INTBIG count, newtotal, i;
1264 REGISTER TRACE **newbustraces;
1265 static INTBIG nullbustraces[1];
1266
1267 tr = (TRACE *)tri;
1268 count = 0;
1269 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
1270 {
1271 if (otr->buschannel != tr) continue;
1272 if (count+1 >= sim_window_bustracetotal)
1273 {
1274 newtotal = sim_window_bustracetotal*2;
1275 if (newtotal == 0) newtotal = 5;
1276 if (count+1 > newtotal) newtotal = count+1;
1277 newbustraces = (TRACE **)emalloc(newtotal * (sizeof (TRACE *)),
1278 sim_tool->cluster);
1279 if (newbustraces == 0) return(0);
1280 for(i=0; i<count; i++)
1281 newbustraces[i] = sim_window_bustraces[i];
1282 if (sim_window_bustracetotal > 0) efree((CHAR *)sim_window_bustraces);
1283 sim_window_bustraces = newbustraces;
1284 sim_window_bustracetotal = newtotal;
1285 }
1286 sim_window_bustraces[count++] = otr;
1287 sim_window_bustraces[count] = 0;
1288 }
1289 if (count == 0)
1290 {
1291 nullbustraces[0] = 0;
1292 return(nullbustraces);
1293 }
1294 return((INTBIG *)sim_window_bustraces);
1295 }
1296
1297 /*
1298 * routine to return the frame number associated with trace "tri"
1299 */
sim_window_gettraceframe(INTBIG tri)1300 INTBIG sim_window_gettraceframe(INTBIG tri)
1301 {
1302 REGISTER TRACE *tr;
1303
1304 tr = (TRACE *)tri;
1305 if (tr == NOTRACE || tr == 0) return(0);
1306 return(tr->frameno);
1307 }
1308
1309 /*
1310 * routine to return the current frame number
1311 */
sim_window_getcurframe(void)1312 INTBIG sim_window_getcurframe(void)
1313 {
1314 return(sim_window_highframe);
1315 }
1316
1317 /*
1318 * routine to return the name of trace "tri".
1319 */
sim_window_gettracename(INTBIG tri)1320 CHAR *sim_window_gettracename(INTBIG tri)
1321 {
1322 REGISTER TRACE *tr;
1323
1324 tr = (TRACE *)tri;
1325 if (tr == NOTRACE || tr == 0) return(x_(""));
1326 return(tr->origname);
1327 }
1328
1329 /*
1330 * routine to return the "user" data associated with trace "tri"
1331 */
sim_window_gettracedata(INTBIG tri)1332 INTBIG sim_window_gettracedata(INTBIG tri)
1333 {
1334 REGISTER TRACE *tr;
1335
1336 tr = (TRACE *)tri;
1337 if (tr == NOTRACE || tr == 0) return(0);
1338 return(tr->nodeptr);
1339 }
1340
1341 /*
1342 * Routine to return the value of analog trace "tri" at time "time".
1343 * Interpolates the data to get the answer.
1344 */
sim_window_getanatracevalue(INTBIG tri,double time)1345 float sim_window_getanatracevalue(INTBIG tri, double time)
1346 {
1347 REGISTER TRACE *tr;
1348 REGISTER INTBIG j;
1349 REGISTER float lastvalue, thisvalue, v;
1350 REGISTER double lasttime, thistime;
1351
1352 tr = (TRACE *)tri;
1353 if (tr == NOTRACE || tr == 0) return(0.0);
1354
1355 /* must be an analog trace */
1356 if ((tr->flags&TRACETYPE) != TRACEISANALOG) return(0.0);
1357
1358 lastvalue = 0.0;
1359 lasttime = 0.0;
1360 for(j=0; j<tr->numsteps; j++)
1361 {
1362 thistime = tr->timearray[j];
1363 thisvalue = tr->valuearray[j];
1364 if (thistime == time) return(thisvalue);
1365 if (time > thistime)
1366 {
1367 lasttime = thistime;
1368 lastvalue = thisvalue;
1369 continue;
1370 }
1371 if (j == 0) return(thisvalue);
1372 v = (float)(lastvalue + (time-lasttime) * (thisvalue-lastvalue) / (thistime-lasttime));
1373 return(v);
1374 }
1375
1376 return(lastvalue);
1377 }
1378
1379 /*
1380 * Routine to return the value of digital trace "tri" at time "time".
1381 * Sets the level (high/low/etc) in "level" and the strength in "strength".
1382 */
sim_window_getdigtracevalue(INTBIG tri,double time,INTBIG * level,INTBIG * strength)1383 void sim_window_getdigtracevalue(INTBIG tri, double time, INTBIG *level, INTBIG *strength)
1384 {
1385 REGISTER TRACE *tr;
1386 REGISTER INTBIG j;
1387 REGISTER double thistime;
1388
1389 *level = *strength = 0;
1390 tr = (TRACE *)tri;
1391 if (tr == NOTRACE || tr == 0) return;
1392
1393 /* must be an analog trace */
1394 if ((tr->flags&TRACETYPE) != TRACEISDIGITAL) return;
1395
1396 for(j=0; j<tr->numsteps; j++)
1397 {
1398 thistime = tr->timearray[j];
1399 if (thistime > time) break;
1400 *level = tr->statearray[j] >> 8;
1401 *strength = tr->statearray[j] & 0377;
1402 }
1403 }
1404
1405 /*
1406 * Routine to return the value of bus trace "tri" at time "time".
1407 * Returns the value as a string.
1408 */
sim_window_getbustracevalue(INTBIG tri,double time)1409 CHAR *sim_window_getbustracevalue(INTBIG tri, double time)
1410 {
1411 REGISTER TRACE *tr, *bustr;
1412 REGISTER INTBIG j, sigcount;
1413
1414 tr = (TRACE *)tri;
1415 if (tr == NOTRACE || tr == 0) return(x_(""));
1416
1417 /* must be an analog trace */
1418 if ((tr->flags&TRACETYPE) != TRACEISBUS &&
1419 (tr->flags&TRACETYPE) != TRACEISOPENBUS) return(x_(""));
1420
1421 sigcount = sim_window_ensurespace(tr);
1422 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
1423 {
1424 if (bustr->buschannel != tr) continue;
1425 for(j=0; j<bustr->numsteps; j++)
1426 if (time < bustr->timearray[j]) break;
1427 if (j > 0) j--;
1428 sim_window_sigvalues[bustr->busindex] = bustr->statearray[j] >> 8;
1429 }
1430 return(sim_window_makewidevalue(sigcount, sim_window_sigvalues));
1431 }
1432
1433 LISTINTBIG *sim_window_foundtraces = 0;
1434
1435 /*
1436 * Routine to return the traces associated with name "name" (if it is a bus, there may be
1437 * multiple traces). The number of traces is returned in "count" and the trace list is
1438 * returned by the routine.
1439 */
sim_window_findtrace(CHAR * name,INTBIG * count)1440 INTBIG *sim_window_findtrace(CHAR *name, INTBIG *count)
1441 {
1442 REGISTER TRACE *tr;
1443 REGISTER CHAR *pt;
1444 CHAR **strings;
1445 REGISTER INTBIG len, i;
1446
1447 if (sim_window_foundtraces == 0)
1448 sim_window_foundtraces = newintlistobj(sim_tool->cluster);
1449 clearintlistobj(sim_window_foundtraces);
1450
1451 /* look for this name without modifications */
1452 sim_window_findthistrace(name);
1453
1454 /* look for bus names in the requested string */
1455 for(pt = name; *pt != 0; pt++)
1456 if (*pt == '[') break;
1457 if (*pt == '[')
1458 {
1459 /* parse into individual signal names */
1460 len = net_evalbusname(APBUS, name, &strings, NOARCINST, NONODEPROTO, 0);
1461 for(i=0; i<len; i++)
1462 sim_window_findthistrace(strings[i]);
1463 } else
1464 {
1465 /* look for bus names that have no indexing */
1466 len = estrlen(name);
1467 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1468 {
1469 if ((tr->flags&TRACETYPE) != TRACEISBUS &&
1470 (tr->flags&TRACETYPE) != TRACEISOPENBUS) continue;
1471 if (namesamen(tr->name, name, len) == 0 && tr->name[len] == '[')
1472 addtointlistobj(sim_window_foundtraces, (INTBIG)tr, FALSE);
1473 }
1474 }
1475 return(getintlistobj(sim_window_foundtraces, count));
1476 }
1477
sim_window_findthistrace(CHAR * name)1478 void sim_window_findthistrace(CHAR *name)
1479 {
1480 REGISTER TRACE *tr;
1481 REGISTER INTBIG i, len;
1482 REGISTER CHAR *tempname;
1483 REGISTER void *infstr;
1484
1485 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1486 {
1487 if (namesame(tr->name, name) == 0)
1488 {
1489 addtointlistobj(sim_window_foundtraces, (INTBIG)tr, FALSE);
1490 if (tr->buschannel != NOTRACE)
1491 addtointlistobj(sim_window_foundtraces, (INTBIG)tr->buschannel, TRUE);
1492 return;
1493 }
1494 }
1495
1496 /* see if the name is found when considering the prefix */
1497 if (sim_window_traceprefix != 0)
1498 {
1499 len = estrlen(sim_window_traceprefix);
1500 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1501 {
1502 if (namesamen(tr->name, sim_window_traceprefix, len) == 0 &&
1503 namesame(&tr->name[len], name) == 0)
1504 {
1505 addtointlistobj(sim_window_foundtraces, (INTBIG)tr, FALSE);
1506 if (tr->buschannel != NOTRACE)
1507 addtointlistobj(sim_window_foundtraces, (INTBIG)tr->buschannel, TRUE);
1508 return;
1509 }
1510 }
1511 }
1512
1513 /* keywords get the letters "NV" added to the end */
1514 infstr = initinfstr();
1515 addstringtoinfstr(infstr, name);
1516 addstringtoinfstr(infstr, x_("NV"));
1517 tempname = returninfstr(infstr);
1518 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1519 {
1520 if (namesame(tr->name, tempname) == 0)
1521 {
1522 addtointlistobj(sim_window_foundtraces, (INTBIG)tr, FALSE);
1523 return;
1524 }
1525 }
1526
1527 /* handle "v(" and "l(" prefixes of HSPICE (see also "dbtext.c:getcomplexnetworks()") */
1528 len = estrlen(name);
1529 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1530 {
1531 if ((tr->name[0] == 'l' || tr->name[0] == 'v') && tr->name[1] == '(')
1532 {
1533 if (namesamen(&tr->name[2], name, len) == 0)
1534 {
1535 if (tr->name[len+2] == 0 || tr->name[len+2] == ')')
1536 {
1537 addtointlistobj(sim_window_foundtraces, (INTBIG)tr, FALSE);
1538 return;
1539 }
1540 }
1541 }
1542 }
1543
1544 /* allow "_" in simulator text to match any punctuation in desired name */
1545 len = estrlen(name);
1546 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1547 {
1548 for(i=0; ; i++)
1549 {
1550 if (tr->name[i] == 0 || tolower(name[i]) == 0) break;
1551 if (tolower(tr->name[i]) == tolower(name[i])) continue;
1552 if (tr->name[i] == '_' && ispunct(name[i])) continue;
1553 break;
1554 }
1555 if (tr->name[i] == 0 && tolower(name[i]) == 0)
1556 {
1557 addtointlistobj(sim_window_foundtraces, (INTBIG)tr, FALSE);
1558 return;
1559 }
1560 }
1561 }
1562
sim_window_inittraceloop(void)1563 void sim_window_inittraceloop(void)
1564 {
1565 sim_window_loop = sim_window_firstrace;
1566 }
1567
sim_window_inittraceloop2(void)1568 void sim_window_inittraceloop2(void)
1569 {
1570 sim_window_loop2 = sim_window_firstrace;
1571 }
1572
sim_window_nexttraceloop(void)1573 INTBIG sim_window_nexttraceloop(void)
1574 {
1575 REGISTER TRACE *tr;
1576
1577 tr = sim_window_loop;
1578 if (tr == NOTRACE) return(0);
1579 sim_window_loop = tr->nexttrace;
1580 return((INTBIG)tr);
1581 }
1582
sim_window_nexttraceloop2(void)1583 INTBIG sim_window_nexttraceloop2(void)
1584 {
1585 REGISTER TRACE *tr;
1586
1587 tr = sim_window_loop2;
1588 if (tr == NOTRACE) return(0);
1589 sim_window_loop2 = tr->nexttrace;
1590 return((INTBIG)tr);
1591 }
1592
1593 /********************************* TRACE/FRAME HIGHLIGHTING *********************************/
1594
1595 /*
1596 * Routine to initialize changes to the trace highlighting. After calling this, any
1597 * trace whose highlighting changes should have the "TRACEHIGHCHANGED" bit set in its flags.
1598 */
sim_window_inithighlightchange(void)1599 void sim_window_inithighlightchange(void)
1600 {
1601 REGISTER TRACE *tr;
1602
1603 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1604 tr->flags &= ~TRACEHIGHCHANGED;
1605 }
1606
1607 /*
1608 * Routine to terminate changes to the trace highlighting. Redisplays any frames
1609 * where the trace highlighting changed.
1610 */
sim_window_donehighlightchange(WINDOWPART * wavewin)1611 void sim_window_donehighlightchange(WINDOWPART *wavewin)
1612 {
1613 REGISTER TRACE *tr, *otr;
1614 REGISTER INTBIG highframe;
1615
1616 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1617 {
1618 if ((tr->flags&TRACEHIGHCHANGED) == 0) continue;
1619 sim_window_drawframe(tr->frameno, wavewin);
1620 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
1621 if (otr->frameno == tr->frameno)
1622 otr->flags &= ~TRACEHIGHCHANGED;
1623 }
1624
1625 /* see if a single frame is highlighted */
1626 highframe = -1;
1627 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1628 {
1629 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
1630 if ((tr->flags&TRACESELECTED) == 0) continue;
1631 // if ((tr->flags&TRACETYPE) != TRACEISANALOG) continue;
1632 if (highframe == -1) highframe = tr->frameno;
1633 if (highframe != tr->frameno) highframe = -2;
1634 }
1635
1636 if (highframe == -2) highframe = -1;
1637 if (highframe != sim_window_highframe)
1638 {
1639 sim_window_setviewport(wavewin);
1640
1641 if (sim_window_highframe >= 0)
1642 sim_window_showtracebar(wavewin, sim_window_highframe, 2);
1643 sim_window_highframe = highframe;
1644 if (sim_window_highframe >= 0)
1645 sim_window_showtracebar(wavewin, sim_window_highframe, 1);
1646 }
1647 }
1648
1649 /*
1650 * Routine to highlight trace "tr" in window "wavewin". If "on" is TRUE, highlight it,
1651 * otherwise remove highlighting.
1652 */
sim_window_highlightname(WINDOWPART * wavewin,TRACE * tr,BOOLEAN on)1653 void sim_window_highlightname(WINDOWPART *wavewin, TRACE *tr, BOOLEAN on)
1654 {
1655 REGISTER INTBIG lx, hx, ly, hy, color, temp_trace_spacing, slot, y_min;
1656
1657 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
1658 slot = tr->frameno - sim_window_topframes;
1659 if (slot < 0 || slot >= sim_window_visframes) return;
1660 y_min = (sim_window_visframes - 1 - slot) * temp_trace_spacing + WAVEYSIGBOT;
1661
1662 /* highlight/unhighlight trace name */
1663 ly = y_min + tr->nameoff+1; hy = ly + sim_window_txthei;
1664 lx = 0; hx = sim_window_wavexnameend;
1665 sim_window_setmask(LAYERH);
1666 if (on) color = HIGHLIT; else color = 0;
1667 sim_window_setcolor(color);
1668 sim_window_moveto(lx, ly);
1669 sim_window_drawto(wavewin, hx, ly, 0);
1670 sim_window_drawto(wavewin, hx, hy, 0);
1671 sim_window_drawto(wavewin, lx, hy, 0);
1672 sim_window_drawto(wavewin, lx, ly, 0);
1673 sim_window_setmask(LAYERA);
1674 }
1675
1676 /*
1677 * Routine to make sure the highlighted traces are visible (not scrolled away)
1678 */
sim_window_showhighlightedtraces(void)1679 void sim_window_showhighlightedtraces(void)
1680 {
1681 REGISTER INTBIG slot;
1682 REGISTER TRACE *tr;
1683
1684 if (sim_window_visframes == 0) return;
1685 if (sim_window_highlightedtracecount == 0) return;
1686 tr = sim_window_highlightedtraces[0];
1687 slot = tr->frameno - sim_window_topframes;
1688 if (slot >= 0 && slot < sim_window_visframes) return;
1689
1690 /* shift the scroll */
1691 sim_window_topframes = tr->frameno - sim_window_visframes/2;
1692 if (sim_window_topframes < 0) sim_window_topframes = 0;
1693 sim_window_redraw();
1694 }
1695
1696 /*
1697 * Routine to clear all highlighting in the waveform window.
1698 */
sim_window_cleartracehighlight(void)1699 void sim_window_cleartracehighlight(void)
1700 {
1701 REGISTER WINDOWPART *wavewin;
1702 REGISTER INTBIG i;
1703 REGISTER TRACE *tr;
1704
1705 /* get the waveform window */
1706 wavewin = sim_window_findwaveform();
1707 if (wavewin == NOWINDOWPART) return;
1708 sim_window_setviewport(wavewin);
1709
1710 /* initialize changes to highlighted traces */
1711 sim_window_inithighlightchange();
1712
1713 /* clear all highlighting */
1714 for(i=0; i<sim_window_highlightedtracecount; i++)
1715 {
1716 tr = sim_window_highlightedtraces[i];
1717 tr->flags &= ~TRACESELECTED;
1718 tr->flags |= TRACEHIGHCHANGED;
1719 sim_window_highlightname(wavewin, tr, FALSE);
1720 }
1721 sim_window_highlightedtracecount = 0;
1722
1723 /* show changes to highlighted traces */
1724 sim_window_donehighlightchange(wavewin);
1725
1726 sim_window_drawcursors(wavewin);
1727 }
1728
1729 /*
1730 * routine that adds trace "tri" to the highlighted traces in the waveform window
1731 */
sim_window_addhighlighttrace(INTBIG tri)1732 void sim_window_addhighlighttrace(INTBIG tri)
1733 {
1734 REGISTER TRACE *tr, **newtraces;
1735 REGISTER WINDOWPART *wavewin;
1736 REGISTER INTBIG newtotal, i;
1737
1738 tr = (TRACE *)tri;
1739
1740 /* get the waveform window */
1741 wavewin = sim_window_findwaveform();
1742 if (wavewin == NOWINDOWPART) return;
1743 sim_window_setviewport(wavewin);
1744
1745 /* initialize changes to trace highlighting */
1746 sim_window_inithighlightchange();
1747
1748 /* add this signal to highlighting */
1749 if (sim_window_highlightedtracecount+1 >= sim_window_highlightedtracetotal)
1750 {
1751 newtotal = sim_window_highlightedtracetotal * 2;
1752 if (newtotal == 0) newtotal = 2;
1753 if (sim_window_highlightedtracecount+1 > newtotal)
1754 newtotal = sim_window_highlightedtracecount+1;
1755 newtraces = (TRACE **)emalloc(newtotal * (sizeof (TRACE *)), sim_tool->cluster);
1756 if (newtraces == 0) return;
1757 for(i=0; i<sim_window_highlightedtracecount; i++)
1758 newtraces[i] = sim_window_highlightedtraces[i];
1759 if (sim_window_highlightedtracetotal > 0) efree((CHAR *)sim_window_highlightedtraces);
1760 sim_window_highlightedtraces = newtraces;
1761 sim_window_highlightedtracetotal = newtotal;
1762 }
1763 sim_window_highlightedtraces[sim_window_highlightedtracecount++] = tr;
1764 tr->flags |= (TRACESELECTED | TRACEHIGHCHANGED);
1765 sim_window_highlightedtraces[sim_window_highlightedtracecount] = 0;
1766 sim_window_highlightname(wavewin, tr, TRUE);
1767
1768 /* show highlighting */
1769 sim_window_donehighlightchange(wavewin);
1770 sim_window_drawcursors(wavewin);
1771 }
1772
1773 /*
1774 * routine that removes trace "tri" from the highlighted traces in the waveform window
1775 */
sim_window_deletehighlighttrace(INTBIG tri)1776 void sim_window_deletehighlighttrace(INTBIG tri)
1777 {
1778 REGISTER TRACE *tr;
1779 REGISTER WINDOWPART *wavewin;
1780 REGISTER INTBIG k, j, i;
1781
1782 tr = (TRACE *)tri;
1783
1784 /* get the waveform window */
1785 wavewin = sim_window_findwaveform();
1786 if (wavewin == NOWINDOWPART) return;
1787 sim_window_setviewport(wavewin);
1788
1789 /* find this signal in the highlighting */
1790 for(j=0; j<sim_window_highlightedtracecount; j++)
1791 if (tr == sim_window_highlightedtraces[j]) break;
1792 if (j < sim_window_highlightedtracecount)
1793 {
1794 /* erase highlighting */
1795 sim_window_inithighlightchange();
1796
1797 /* remove the signal from the list */
1798 k = 0;
1799 for(i=0; i<sim_window_highlightedtracecount; i++)
1800 {
1801 if (i == j) continue;
1802 sim_window_highlightedtraces[k++] = sim_window_highlightedtraces[i];
1803 }
1804 sim_window_highlightedtracecount = k;
1805 tr->flags &= ~TRACESELECTED;
1806 tr->flags |= TRACEHIGHCHANGED;
1807 sim_window_highlightname(wavewin, tr, FALSE);
1808
1809 /* show highlighting */
1810 sim_window_donehighlightchange(wavewin);
1811 }
1812 sim_window_drawcursors(wavewin);
1813 }
1814
1815 /*
1816 * routine that returns the highlighted trace in the waveform window
1817 */
sim_window_gethighlighttrace(void)1818 INTBIG sim_window_gethighlighttrace(void)
1819 {
1820 if (sim_window_highlightedtracecount == 0) return(0);
1821 return((INTBIG)sim_window_highlightedtraces[0]);
1822 }
1823
1824 /*
1825 * routine that returns a 0-terminated list of highlighted traces in the waveform window
1826 */
sim_window_gethighlighttraces(void)1827 INTBIG *sim_window_gethighlighttraces(void)
1828 {
1829 static INTBIG nothing[1];
1830
1831 nothing[0] = 0;
1832 if (sim_window_highlightedtracecount == 0) return(nothing);
1833 return((INTBIG *)sim_window_highlightedtraces);
1834 }
1835
1836 /*
1837 * Routine to update associated layout windows when the main cursor changes
1838 */
sim_window_updatelayoutwindow(void)1839 void sim_window_updatelayoutwindow(void)
1840 {
1841 REGISTER TRACE *tr, *otr;
1842 REGISTER NETWORK *net;
1843 REGISTER ARCINST *ai;
1844 REGISTER NODEINST *ni;
1845 REGISTER PORTARCINST *pi;
1846 REGISTER INTBIG fx, fy, tx, ty, i, x, y, count;
1847 REGISTER NODEPROTO *simnt;
1848 REGISTER VARIABLE *var;
1849 REGISTER WINDOWPART *schemwin;
1850 INTBIG texture, color, lx, hx, ly, hy;
1851 static POLYGON *poly = NOPOLYGON;
1852 XARRAY trans;
1853
1854 /* make sure there is a layout/schematic window being simulated */
1855 schemwin = sim_window_findschematics();
1856 if (schemwin == NOWINDOWPART) return;
1857 simnt = schemwin->curnodeproto;
1858
1859 /* reset all values on networks */
1860 for(net = simnt->firstnetwork; net != NONETWORK; net = net->nextnetwork)
1861 net->temp1 = net->temp2 = -1;
1862
1863 /* assign values from simulation window traces to networks */
1864 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
1865 {
1866 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
1867
1868 /* can only handle digital waveforms right now */
1869 if ((tr->flags&TRACETYPE) == TRACEISDIGITAL)
1870 {
1871 sim_window_putvalueontrace(tr, simnt);
1872 } else if ((tr->flags&TRACETYPE) == TRACEISBUS || (tr->flags&TRACETYPE) == TRACEISOPENBUS)
1873 {
1874 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
1875 {
1876 if (otr->buschannel != tr) continue;
1877 sim_window_putvalueontrace(otr, simnt);
1878 }
1879 }
1880 }
1881
1882 /* light up any simulation-probe objects */
1883 for(ni = simnt->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1884 {
1885 if (ni->proto != gen_simprobeprim) continue;
1886 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1887 {
1888 ai = pi->conarcinst;
1889 if (ai->network == NONETWORK) continue;
1890 if (ai->network->temp1 != -1) break;
1891 }
1892 if (pi == NOPORTARCINST) continue;
1893
1894 sim_window_gethighlightcolor(ai->network->temp1, &texture, &color);
1895 sim_window_desc.col = color;
1896 var = gettrace(ni);
1897 if (var != NOVARIABLE)
1898 {
1899 count = getlength(var) / 2;
1900 (void)needstaticpolygon(&poly, count, sim_tool->cluster);
1901 x = (ni->highx + ni->lowx) / 2; y = (ni->highy + ni->lowy) / 2;
1902 for(i=0; i<count; i++)
1903 {
1904 poly->xv[i] = applyxscale(schemwin, ((INTBIG *)var->addr)[i*2] + x - schemwin->screenlx) + schemwin->uselx;
1905 poly->yv[i] = applyyscale(schemwin, ((INTBIG *)var->addr)[i*2+1] + y - schemwin->screenly) + schemwin->usely;
1906 }
1907 poly->count = count;
1908 poly->style = FILLED;
1909 makerot(ni, trans);
1910 xformpoly(poly, trans);
1911 clippoly(poly, schemwin->uselx, schemwin->usehx, schemwin->usely, schemwin->usehy);
1912 if (poly->count > 1)
1913 {
1914 if (poly->count > 2)
1915 {
1916 /* always clockwise */
1917 if (areapoly(poly) < 0.0) reversepoly(poly);
1918 screendrawpolygon(schemwin, poly->xv, poly->yv, poly->count, &sim_window_desc);
1919 } else screendrawline(schemwin, poly->xv[0], poly->yv[0], poly->xv[1], poly->yv[1],
1920 &sim_window_desc, 0);
1921 }
1922 ai->network->temp2 = 0;
1923 } else
1924 {
1925 lx = ni->geom->lowx; hx = ni->geom->highx;
1926 ly = ni->geom->lowy; hy = ni->geom->highy;
1927 if (!us_makescreen(&lx, &ly, &hx, &hy, schemwin))
1928 {
1929 screendrawbox(schemwin, lx, hx, ly, hy, &sim_window_desc);
1930 ai->network->temp2 = 0;
1931 }
1932 }
1933 }
1934
1935 /* redraw all arcs in the layout/schematic window */
1936 sim_window_desc.bits = LAYERA;
1937 for(ai = simnt->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1938 {
1939 net = ai->network;
1940 if (net == NONETWORK) continue;
1941 if (net->temp1 == -1 || net->temp2 != -1) continue;
1942
1943 /* get extent of arc */
1944 fx = ai->end[0].xpos; fy = ai->end[0].ypos;
1945 tx = ai->end[1].xpos; ty = ai->end[1].ypos;
1946 if (ai->proto == sch_wirearc)
1947 {
1948 /* for schematic wires, ask technology about drawing so negating bubbles work */
1949 (void)needstaticpolygon(&poly, 4, sim_tool->cluster);
1950 (void)arcpolys(ai, NOWINDOWPART);
1951 shapearcpoly(ai, 0, poly);
1952 fx = poly->xv[0]; fy = poly->yv[0];
1953 tx = poly->xv[1]; ty = poly->yv[1];
1954 }
1955
1956 sim_window_gethighlightcolor(net->temp1, &texture, &color);
1957
1958 /* reset background arc if trace is textured */
1959 if (texture != 0)
1960 {
1961 sim_window_desc.col = ALLOFF;
1962 us_wanttodraw(fx, fy, tx, ty, schemwin, &sim_window_desc, 0);
1963 if (texture < 0) texture = 0;
1964 }
1965 sim_window_desc.col = color;
1966
1967 /* draw the trace on the arc */
1968 us_wanttodraw(fx, fy, tx, ty, schemwin, &sim_window_desc, texture);
1969 }
1970 }
1971
sim_window_gethighlightcolor(INTBIG state,INTBIG * texture,INTBIG * color)1972 void sim_window_gethighlightcolor(INTBIG state, INTBIG *texture, INTBIG *color)
1973 {
1974 REGISTER INTBIG strength;
1975
1976 if ((sim_window_state&FULLSTATE) != 0)
1977 {
1978 /* 12-state display: determine trace texture */
1979 strength = state & 0377;
1980 if (strength == 0) *texture = -1; else
1981 if (strength <= NODE_STRENGTH) *texture = 1; else
1982 if (strength <= GATE_STRENGTH) *texture = 0; else
1983 *texture = 2;
1984
1985 /* determine trace color */
1986 switch (state >> 8)
1987 {
1988 case LOGIC_LOW: *color = sim_colorlevellow; break;
1989 case LOGIC_X: *color = sim_colorlevelundef; break;
1990 case LOGIC_HIGH: *color = sim_colorlevelhigh; break;
1991 case LOGIC_Z: *color = sim_colorlevelzdef; break;
1992 }
1993 } else
1994 {
1995 /* 2-state display */
1996 *texture = 0;
1997 if ((state >> 8) == LOGIC_HIGH) *color = sim_colorstrengthgate; else
1998 *color = sim_colorstrengthoff;
1999 }
2000 }
2001
sim_window_putvalueontrace(TRACE * tr,NODEPROTO * simnt)2002 void sim_window_putvalueontrace(TRACE *tr, NODEPROTO *simnt)
2003 {
2004 REGISTER NETWORK *net, **netlist;
2005 REGISTER INTBIG j;
2006
2007 if (tr->statearray == 0) return;
2008
2009 /* set simulation value on the network in the associated layout/schematic window */
2010 netlist = getcomplexnetworks(tr->name, simnt);
2011 net = netlist[0];
2012 if (net != NONETWORK && netlist[1] == NONETWORK)
2013 {
2014 /* find the proper data for the time of the main cursor */
2015 for(j=1; j<tr->numsteps; j++)
2016 if (sim_window_maincursor < tr->timearray[j]) break;
2017 j--;
2018 net->temp1 = tr->statearray[j];
2019 }
2020 }
2021
2022 /********************************* TIME AND CURSOR CONTROL *********************************/
2023
2024 /*
2025 * routine to set the time for the "main" cursor in the simulation window
2026 */
sim_window_setmaincursor(double time)2027 void sim_window_setmaincursor(double time)
2028 {
2029 REGISTER WINDOWPART *wavewin;
2030
2031 /* get the waveform window */
2032 wavewin = sim_window_findwaveform();
2033 if (wavewin == NOWINDOWPART) return;
2034
2035 sim_window_maincursor = time;
2036 sim_window_updatelayoutwindow();
2037 sim_window_drawcursors(wavewin);
2038 }
2039
2040 /*
2041 * routine to return the time of the "main" cursor in the simulation window
2042 */
sim_window_getmaincursor(void)2043 double sim_window_getmaincursor(void)
2044 {
2045 return(sim_window_maincursor);
2046 }
2047
2048 /*
2049 * routine to set the time for the "extension" cursor in the simulation window
2050 */
sim_window_setextensioncursor(double time)2051 void sim_window_setextensioncursor(double time)
2052 {
2053 REGISTER WINDOWPART *wavewin;
2054
2055 /* get the waveform window */
2056 wavewin = sim_window_findwaveform();
2057 if (wavewin == NOWINDOWPART) return;
2058
2059 sim_window_extensioncursor = time;
2060 sim_window_drawcursors(wavewin);
2061 }
2062
2063 /*
2064 * routine to return the time of the "extension" cursor in the simulation window
2065 */
sim_window_getextensioncursor(void)2066 double sim_window_getextensioncursor(void)
2067 {
2068 return(sim_window_extensioncursor);
2069 }
2070
2071 /*
2072 * routine to set the simulation trace "tri" to run from time "min" to time "max"
2073 */
sim_window_settimerange(INTBIG tri,double min,double max)2074 void sim_window_settimerange(INTBIG tri, double min, double max)
2075 {
2076 REGISTER TRACE *tr, *otr;
2077
2078 tr = (TRACE *)tri;
2079 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
2080 {
2081 if (tr != 0 && otr->frameno != tr->frameno) continue;
2082 otr->mintime = min;
2083 otr->maxtime = max;
2084 }
2085 }
2086
2087 /*
2088 * routine to return the range of time displayed in the simulation window
2089 */
sim_window_gettimerange(INTBIG tri,double * min,double * max)2090 void sim_window_gettimerange(INTBIG tri, double *min, double *max)
2091 {
2092 REGISTER TRACE *tr;
2093
2094 tr = (TRACE *)tri;
2095 *min = tr->mintime;
2096 *max = tr->maxtime;
2097 }
2098
2099 /*
2100 * routine to return the average range of time displayed in the simulation window
2101 */
sim_window_getaveragetimerange(double * totmintime,double * totmaxtime)2102 void sim_window_getaveragetimerange(double *totmintime, double *totmaxtime)
2103 {
2104 double mintime, maxtime;
2105 REGISTER INTBIG tottraces, tr, j;
2106
2107 sim_window_inittraceloop();
2108 *totmintime = *totmaxtime = 0.0;
2109 tottraces = 0;
2110 for(j=0; ; j++)
2111 {
2112 tr = sim_window_nexttraceloop();
2113 if (tr == 0) break;
2114 sim_window_gettimerange(tr, &mintime, &maxtime);
2115 *totmintime += mintime;
2116 *totmaxtime += maxtime;
2117 tottraces++;
2118 }
2119 if (tottraces > 0)
2120 {
2121 *totmintime /= tottraces;
2122 *totmaxtime /= tottraces;
2123 }
2124 }
2125
2126 /*
2127 * routine to return the range of time that is in the data
2128 */
sim_window_gettimeextents(double * min,double * max)2129 void sim_window_gettimeextents(double *min, double *max)
2130 {
2131 REGISTER TRACE *tr;
2132 double time;
2133 REGISTER INTBIG j;
2134
2135 /* initially enclose the cursors */
2136 *min = sim_window_maincursor;
2137 *max = sim_window_extensioncursor;
2138 if (*max < *min)
2139 {
2140 *min = sim_window_extensioncursor;
2141 *max = sim_window_maincursor;
2142 }
2143
2144 /* also enclose all of the data */
2145 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2146 {
2147 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
2148 for(j=0; j<tr->numsteps; j++)
2149 {
2150 time = tr->timearray[j];
2151 if (time < *min) *min = time;
2152 if (time > *max) *max = time;
2153 }
2154 }
2155 if (*min > 0.0) *min = 0.0;
2156 }
2157
2158 /********************************* WINDOW METHODS *********************************/
2159
sim_window_zoomdown(INTBIG x,INTBIG y)2160 BOOLEAN sim_window_zoomdown(INTBIG x, INTBIG y)
2161 {
2162 REGISTER WINDOWPART *wavewin;
2163
2164 /* get the waveform window */
2165 wavewin = sim_window_findwaveform();
2166 if (wavewin == NOWINDOWPART) return(FALSE);
2167
2168 sim_window_drawareazoom(wavewin, FALSE, sim_window_zoominix, sim_window_zoominiy,
2169 sim_window_zoomothx, sim_window_zoomothy);
2170 sim_window_scaletowindow(wavewin, &x, &y);
2171 sim_window_zoomothx = x;
2172 sim_window_zoomothy = y;
2173 sim_window_drawareazoom(wavewin, TRUE, sim_window_zoominix, sim_window_zoominiy,
2174 sim_window_zoomothx, sim_window_zoomothy);
2175 return(FALSE);
2176 }
2177
sim_window_drawareazoom(WINDOWPART * w,BOOLEAN on,INTBIG fx,INTBIG fy,INTBIG tx,INTBIG ty)2178 void sim_window_drawareazoom(WINDOWPART *w, BOOLEAN on, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty)
2179 {
2180 sim_window_setmask(LAYERH);
2181 if (on) sim_window_setcolor(HIGHLIT); else
2182 sim_window_setcolor(ALLOFF);
2183 sim_window_moveto(fx, fy);
2184 sim_window_drawto(w, fx, ty, 0);
2185 sim_window_drawto(w, tx, ty, 0);
2186 sim_window_drawto(w, tx, fy, 0);
2187 sim_window_drawto(w, fx, fy, 0);
2188 }
2189
sim_window_eachwdown(INTBIG x,INTBIG y)2190 BOOLEAN sim_window_eachwdown(INTBIG x, INTBIG y)
2191 {
2192 sim_window_eachcursordown(x, y, &sim_window_maincursor);
2193 sim_window_updatelayoutwindow();
2194 return(FALSE);
2195 }
2196
sim_window_eachbdown(INTBIG x,INTBIG y)2197 BOOLEAN sim_window_eachbdown(INTBIG x, INTBIG y)
2198 {
2199 sim_window_eachcursordown(x, y, &sim_window_extensioncursor);
2200 return(FALSE);
2201 }
2202
sim_window_eachcursordown(INTBIG x,INTBIG y,double * cursor)2203 void sim_window_eachcursordown(INTBIG x, INTBIG y, double *cursor)
2204 {
2205 REGISTER WINDOWPART *wavewin;
2206 REGISTER TRACE *tr, *trh;
2207 double val, valh;
2208 INTBIG frameno, yh;
2209
2210 /* get the waveform window */
2211 wavewin = sim_window_findwaveform();
2212 if (wavewin == NOWINDOWPART) return;
2213
2214 tr = (TRACE *)sim_window_firstrace;
2215 if (tr == NOTRACE) return;
2216 sim_window_scaletowindow(wavewin, &x, &y);
2217 *cursor = sim_window_xpostotime(x);
2218 if (*cursor < tr->mintime) *cursor = tr->mintime;
2219 if (*cursor > tr->maxtime) *cursor = tr->maxtime;
2220
2221 /* check if mouse is near voltage threshold horizontal line */
2222 yh = -1;
2223 valh = 0.0;
2224 frameno = sim_window_ypostoval(y, &val);
2225 if (frameno >= 0 && sim_window_vdd != 0)
2226 {
2227 INTBIG ymax = 10;
2228 int i;
2229 for (i = 0; i < PERCENTSIZE; i++)
2230 {
2231 double v = sim_window_vdd * sim_window_percent[i];
2232 INTBIG yp = sim_window_valtoypos(frameno, v);
2233 if (yp >= 0 && labs(yp - y) < ymax)
2234 {
2235 ymax = labs(yp - y);
2236 yh = yp;
2237 valh = v;
2238 }
2239 }
2240 }
2241
2242 /* check if mouse is near crosspoint of some trace */
2243 trh = NOTRACE;
2244 if (yh >= 0)
2245 {
2246 double th = 0;
2247 for (tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2248 {
2249 double t = *cursor;
2250
2251 if (tr->frameno != frameno) continue;
2252 if (sim_window_findcross(tr, valh, &t) && (trh == NOTRACE || fabs(t - *cursor) < fabs(th - *cursor)))
2253 {
2254 th = t;
2255 trh = tr;
2256 }
2257 }
2258
2259 /* align cursor time to crosspoint */
2260 if (trh != NOTRACE)
2261 {
2262 if (labs(sim_window_timetoxpos(*cursor) - sim_window_timetoxpos(th)) <= 10)
2263 *cursor = th;
2264 else
2265 trh = NOTRACE;
2266 }
2267 }
2268 sim_window_drawcursors(wavewin);
2269 if (trh != NOTRACE)
2270 {
2271 /* highlight crossing trace and threshold line */
2272 sim_window_setmask(LAYERH);
2273 sim_window_setcolor(HIGHLIT);
2274 sim_window_moveto(sim_window_wavexsigstart, yh);
2275 sim_window_drawto(wavewin, WAVEXSIGEND, yh, 1);
2276 sim_window_plottrace(trh, wavewin, 2, 0, 0);
2277 }
2278 }
2279
sim_window_hthumbtrackingcallback(INTBIG delta)2280 void sim_window_hthumbtrackingcallback(INTBIG delta)
2281 {
2282 REGISTER INTBIG thumbarea, j, tr;
2283 double mintime, maxtime, range, truerange;
2284
2285 if (delta == 0) return;
2286 sim_waveforminiththumbpos += delta;
2287 thumbarea = sim_waveformwindow->usehx - sim_waveformwindow->uselx - DISPLAYSLIDERSIZE*2;
2288 sim_window_gettimeextents(&mintime, &maxtime);
2289 range = maxtime * 2.0;
2290 range = sim_waveformhrange;
2291 sim_window_inittraceloop();
2292 for(j=0; ; j++)
2293 {
2294 tr = sim_window_nexttraceloop();
2295 if (tr == 0) break;
2296 sim_window_gettimerange(tr, &mintime, &maxtime);
2297 truerange = maxtime - mintime;
2298
2299 mintime = (sim_waveforminiththumbpos -
2300 (sim_waveformwindow->uselx+DISPLAYSLIDERSIZE+2)) * range / thumbarea;
2301 if (mintime < 0.0) mintime = 0.0;
2302 maxtime = mintime + truerange;
2303
2304 sim_window_settimerange(tr, mintime, maxtime);
2305 }
2306 if (sim_window_format == ALS) (void)simals_initialize_simulator(TRUE); else
2307 sim_window_redraw();
2308 }
2309
sim_window_vthumbtrackingcallback(INTBIG delta)2310 void sim_window_vthumbtrackingcallback(INTBIG delta)
2311 {
2312 REGISTER INTBIG thumbarea, point;
2313
2314 sim_window_deltasofar += delta;
2315 thumbarea = sim_waveformwindow->usehy - sim_waveformwindow->usely - DISPLAYSLIDERSIZE*2;
2316 point = (sim_waveformwindow->usehy - DISPLAYSLIDERSIZE -
2317 (sim_window_initialthumb + sim_window_deltasofar)) *
2318 sim_window_lines / thumbarea;
2319 if (point < 0) point = 0;
2320 if (point > sim_window_lines-sim_window_visframes)
2321 point = sim_window_lines-sim_window_visframes;
2322 if (point == sim_window_topframes) return;
2323 sim_window_topframes = point;
2324 sim_window_redisphandler(sim_waveformwindow);
2325 }
2326
2327 /*
2328 * Routine for drawing highlight around dragged trace name.
2329 */
sim_window_drawtracedrag(WINDOWPART * wavewin,BOOLEAN on)2330 void sim_window_drawtracedrag(WINDOWPART *wavewin, BOOLEAN on)
2331 {
2332 INTBIG y_pos, temp_trace_spacing, frameno, lx, hx, ly, hy;
2333
2334 /* compute positions */
2335 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
2336 frameno = sim_window_tracedragtr->frameno - sim_window_topframes;
2337 if (frameno < 0 || frameno >= sim_window_visframes) return;
2338 y_pos = (sim_window_visframes - 1 - frameno) * temp_trace_spacing +
2339 WAVEYSIGBOT + sim_window_tracedragyoff;
2340 ly = y_pos + sim_window_tracedragtr->nameoff + 1;
2341 hy = ly + sim_window_txthei;
2342 lx = 0;
2343 hx = sim_window_wavexnameend;
2344
2345 sim_window_setmask(LAYERH);
2346 if (on) sim_window_setcolor(HIGHLIT); else
2347 sim_window_setcolor(ALLOFF);
2348 sim_window_moveto(lx, ly);
2349 sim_window_drawto(wavewin, hx, ly, 0);
2350 sim_window_drawto(wavewin, hx, hy, 0);
2351 sim_window_drawto(wavewin, lx, hy, 0);
2352 sim_window_drawto(wavewin, lx, ly, 0);
2353 }
2354
2355 /*
2356 * Routine for tracking the drag of signal names in the waveform window.
2357 */
sim_window_eachdown(INTBIG x,INTBIG y)2358 BOOLEAN sim_window_eachdown(INTBIG x, INTBIG y)
2359 {
2360 REGISTER WINDOWPART *wavewin;
2361
2362 /* get the waveform window */
2363 wavewin = sim_window_findwaveform();
2364 if (wavewin == NOWINDOWPART) return(FALSE);
2365
2366 sim_window_scaletowindow(wavewin, &x, &y);
2367 sim_window_drawtracedrag(wavewin, FALSE);
2368 sim_window_tracedragyoff = y - sim_window_initialy;
2369 sim_window_drawtracedrag(wavewin, TRUE);
2370 return(FALSE);
2371 }
2372
2373 /*
2374 * Routine for drawing highlight around selected trace names.
2375 */
sim_window_drawtraceselect(WINDOWPART * wavewin,INTBIG y1,INTBIG y2,BOOLEAN on)2376 void sim_window_drawtraceselect(WINDOWPART *wavewin, INTBIG y1, INTBIG y2, BOOLEAN on)
2377 {
2378 INTBIG x, ly, hy;
2379
2380 /* compute positions */
2381 if (y1 == y2) return;
2382 ly = mini(y1, y2);
2383 hy = maxi(y1, y2);
2384 x = sim_window_initialx;
2385
2386 sim_window_setmask(LAYERH);
2387 if (!on) sim_window_setcolor(ALLOFF); else
2388 sim_window_setcolor(HIGHLIT);
2389 sim_window_moveto(x, ly);
2390 sim_window_drawto(wavewin, x, hy, 0);
2391 }
2392
2393 /*
2394 * Routine for tracking the selection of signal names in the waveform window.
2395 */
sim_window_seleachdown(INTBIG x,INTBIG y)2396 BOOLEAN sim_window_seleachdown(INTBIG x, INTBIG y)
2397 {
2398 REGISTER WINDOWPART *wavewin;
2399 INTBIG lowy, highy, ind, i, redo, ypos, temp_trace_spacing;
2400 REGISTER TRACE *tr;
2401
2402 /* get the waveform window */
2403 wavewin = sim_window_findwaveform();
2404 if (wavewin == NOWINDOWPART) return(FALSE);
2405
2406 sim_window_scaletowindow(wavewin, &x, &y);
2407
2408 /* undraw former selection line */
2409 sim_window_drawtraceselect(wavewin, sim_window_currentdragy, sim_window_initialy, FALSE);
2410 if (y < sim_window_initialy)
2411 {
2412 lowy = y; highy = sim_window_initialy;
2413 } else
2414 {
2415 lowy = sim_window_initialy; highy = y;
2416 }
2417
2418 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2419 tr->flags &= ~TRACEMARK;
2420 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
2421 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2422 {
2423 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
2424 ind = tr->frameno - sim_window_topframes;
2425 ypos = (sim_window_visframes - 1 - ind) * temp_trace_spacing + WAVEYSIGBOT + tr->nameoff;
2426 if (ypos > highy || ypos + sim_window_txthei < lowy) continue;
2427 tr->flags |= TRACEMARK;
2428 }
2429
2430 /* see if what is highlighted has changed */
2431 redo = 0;
2432 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2433 {
2434 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
2435 for(i=0; i<sim_window_highlightedtracecount; i++)
2436 if (sim_window_highlightedtraces[i] == tr) break;
2437 if (i < sim_window_highlightedtracecount)
2438 {
2439 /* this signal was highlighted */
2440 if ((tr->flags&TRACEMARK) == 0) redo++;
2441 } else
2442 {
2443 /* this signal was not highlighted */
2444 if ((tr->flags&TRACEMARK) != 0) redo++;
2445 }
2446 }
2447
2448 /* redo highlighting if it changed */
2449 if (redo != 0)
2450 {
2451 sim_window_cleartracehighlight();
2452 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2453 if ((tr->flags&TRACEMARK) != 0) sim_window_addhighlighttrace((INTBIG)tr);
2454 }
2455
2456 /* show what is dragged out */
2457 sim_window_currentdragy = y;
2458 sim_window_drawtraceselect(wavewin, sim_window_currentdragy, sim_window_initialy, TRUE);
2459 return(FALSE);
2460 }
2461
2462 /*
2463 * Routine called when vertical slider parts are clicked.
2464 */
sim_window_verticalslider(INTBIG x,INTBIG y)2465 BOOLEAN sim_window_verticalslider(INTBIG x, INTBIG y)
2466 {
2467 INTBIG newtopframe;
2468
2469 if (x >= sim_waveformwindow->uselx) return(FALSE);
2470 switch (sim_waveformsliderpart)
2471 {
2472 case 0: /* down arrow clicked */
2473 if (y > sim_waveformwindow->usely + DISPLAYSLIDERSIZE) return(FALSE);
2474 if (y < sim_waveformwindow->usely) return(FALSE);
2475 if (sim_window_topframes + sim_window_visframes < sim_window_lines)
2476 {
2477 sim_window_topframes++;
2478 sim_window_redisphandler(sim_waveformwindow);
2479 }
2480 break;
2481 case 1: /* below thumb */
2482 if (y > sim_waveformwindow->thumbly) return(FALSE);
2483 newtopframe = sim_window_topframes + sim_window_visframes - 1;
2484 if (newtopframe + sim_window_visframes > sim_window_lines)
2485 newtopframe = sim_window_lines - sim_window_visframes;
2486 if (sim_window_topframes == newtopframe) break;
2487 sim_window_topframes = newtopframe;
2488 sim_window_redisphandler(sim_waveformwindow);
2489 break;
2490 case 2: /* on thumb (not handled here) */
2491 break;
2492 case 3: /* above thumb */
2493 if (y < sim_waveformwindow->thumbhy) return(FALSE);
2494 if (sim_window_topframes == 0) return(FALSE);
2495 sim_window_topframes -= sim_window_visframes - 1;
2496 if (sim_window_topframes < 0) sim_window_topframes = 0;
2497 sim_window_redisphandler(sim_waveformwindow);
2498 break;
2499 case 4: /* up arrow clicked */
2500 if (y < sim_waveformwindow->usehy - DISPLAYSLIDERSIZE) return(FALSE);
2501 if (sim_window_topframes > 0)
2502 {
2503 sim_window_topframes--;
2504 sim_window_redisphandler(sim_waveformwindow);
2505 }
2506 break;
2507 }
2508 return(FALSE);
2509 }
2510
2511 /*
2512 * Routine called when horizontal slider parts are clicked.
2513 */
sim_window_horizontalslider(INTBIG x,INTBIG y)2514 BOOLEAN sim_window_horizontalslider(INTBIG x, INTBIG y)
2515 {
2516 double range;
2517 REGISTER TRACE *tr;
2518
2519 tr = (TRACE *)sim_window_firstrace;
2520 if (tr == NOTRACE) return(FALSE);
2521 if (y >= sim_waveformwindow->usely) return(FALSE);
2522 switch (sim_waveformsliderpart)
2523 {
2524 case 0: /* left arrow clicked */
2525 if (x > sim_waveformwindow->uselx + DISPLAYSLIDERSIZE*11) return(FALSE);
2526 if (tr->mintime <= 0.0) break;
2527 range = tr->maxtime - tr->mintime;
2528 tr->mintime -= range/DISPLAYSMALLSHIFT;
2529 tr->maxtime -= range/DISPLAYSMALLSHIFT;
2530 if (tr->mintime < 0.0)
2531 {
2532 tr->maxtime -= tr->mintime;
2533 tr->mintime = 0.0;
2534 }
2535 if (sim_window_format == ALS) (void)simals_initialize_simulator(TRUE); else
2536 sim_window_redraw();
2537 break;
2538 case 1: /* left of thumb */
2539 if (x > sim_waveformwindow->thumblx) return(FALSE);
2540 if (tr->mintime <= 0.0) break;
2541 range = tr->maxtime - tr->mintime;
2542 tr->mintime -= range/DISPLAYLARGESHIFT;
2543 tr->maxtime -= range/DISPLAYLARGESHIFT;
2544 if (tr->mintime < 0.0)
2545 {
2546 tr->maxtime -= tr->mintime;
2547 tr->mintime = 0.0;
2548 }
2549 if (sim_window_format == ALS) (void)simals_initialize_simulator(TRUE); else
2550 sim_window_redraw();
2551 break;
2552 case 2: /* on thumb (not handled here) */
2553 break;
2554 case 3: /* right of thumb */
2555 if (x < sim_waveformwindow->thumbhx) return(FALSE);
2556 range = tr->maxtime - tr->mintime;
2557 tr->mintime += range/DISPLAYLARGESHIFT;
2558 tr->maxtime += range/DISPLAYLARGESHIFT;
2559 if (sim_window_format == ALS) (void)simals_initialize_simulator(TRUE); else
2560 sim_window_redraw();
2561 break;
2562 case 4: /* right arrow clicked */
2563 if (x < sim_waveformwindow->usehx - DISPLAYSLIDERSIZE) return(FALSE);
2564 range = tr->maxtime - tr->mintime;
2565 tr->mintime += range/DISPLAYSMALLSHIFT;
2566 tr->maxtime += range/DISPLAYSMALLSHIFT;
2567 if (sim_window_format == ALS) (void)simals_initialize_simulator(TRUE); else
2568 sim_window_redraw();
2569 break;
2570 }
2571 return(FALSE);
2572 }
2573
sim_window_buttonhandler(WINDOWPART * w,INTBIG button,INTBIG inx,INTBIG iny)2574 void sim_window_buttonhandler(WINDOWPART *w, INTBIG button, INTBIG inx, INTBIG iny)
2575 {
2576 INTBIG x, y, xpos, ypos, j, ind, temp_trace_spacing, traceframesmoved, important;
2577 REGISTER INTBIG lx, hx, ly, hy, ind1, ind2, y_min, y_max, frame;
2578 CHAR *par[2], *butname;
2579 double range, highdisp, lowdisp, mintime, maxtime, endtime;
2580 float flow, fhigh;
2581 BOOLEAN areaselect;
2582 REGISTER TRACE *tr, *otr, *otrprev, *nexttr, *addloc,
2583 *buschain, *endbuschain;
2584
2585 /* changes to the mouse-wheel are handled by the user interface */
2586 if (wheelbutton(button))
2587 {
2588 us_buttonhandler(w, button, inx, iny);
2589 return;
2590 }
2591 ttynewcommand();
2592
2593 /* if in distance-measurement mode, track measurement */
2594 if ((us_state&MEASURINGDISTANCE) != 0)
2595 {
2596 if ((us_state&MEASURINGDISTANCEINI) != 0)
2597 {
2598 us_state &= ~MEASURINGDISTANCEINI;
2599 sim_window_distanceinit(w);
2600 }
2601 trackcursor(FALSE, us_ignoreup, us_nullvoid, sim_window_distancedown,
2602 us_stoponchar, sim_window_distanceup, TRACKDRAGGING);
2603 return;
2604 }
2605
2606 /* hit in slider on left */
2607 if (inx < w->uselx)
2608 {
2609 if (iny < w->usely)
2610 {
2611 /* toggle the cell explorer */
2612 par[0] = "explore";
2613 us_window(1, par);
2614 return;
2615 }
2616 if (iny <= w->usely + DISPLAYSLIDERSIZE)
2617 {
2618 /* hit in bottom arrow: go down 1 (may repeat) */
2619 sim_waveformwindow = w;
2620 sim_waveformsliderpart = 0;
2621 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_verticalslider, us_nullchar,
2622 us_nullvoid, TRACKNORMAL);
2623 return;
2624 }
2625 if (iny < w->thumbly)
2626 {
2627 /* hit below thumb: go down lots (may repeat) */
2628 sim_waveformwindow = w;
2629 sim_waveformsliderpart = 1;
2630 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_verticalslider, us_nullchar,
2631 us_nullvoid, TRACKNORMAL);
2632 return;
2633 }
2634 if (iny <= w->thumbhy)
2635 {
2636 /* hit on thumb: track thumb motion */
2637 sim_waveformwindow = w;
2638 sim_window_deltasofar = 0;
2639 sim_window_initialthumb = w->thumbhy;
2640 us_vthumbbegin(iny, w, w->uselx-DISPLAYSLIDERSIZE, w->usely, w->usehy,
2641 TRUE, sim_window_vthumbtrackingcallback);
2642 trackcursor(FALSE, us_nullup, us_nullvoid, us_vthumbdown, us_nullchar,
2643 us_vthumbdone, TRACKNORMAL);
2644 return;
2645 }
2646 if (iny < w->usehy - DISPLAYSLIDERSIZE)
2647 {
2648 /* hit above thumb: go up lots (may repeat) */
2649 sim_waveformwindow = w;
2650 sim_waveformsliderpart = 3;
2651 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_verticalslider, us_nullchar,
2652 us_nullvoid, TRACKNORMAL);
2653 return;
2654 }
2655
2656 /* hit in up arrow: go up 1 (may repeat) */
2657 sim_waveformwindow = w;
2658 sim_waveformsliderpart = 4;
2659 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_verticalslider, us_nullchar,
2660 us_nullvoid, TRACKNORMAL);
2661 return;
2662 }
2663
2664 /* hit in slider on bottom */
2665 if (iny < w->usely)
2666 {
2667 if (inx <= w->uselx + DISPLAYSLIDERSIZE*1)
2668 {
2669 /* hit in blank button */
2670 return;
2671 }
2672 if (inx <= w->uselx + DISPLAYSLIDERSIZE*2)
2673 {
2674 /* hit in rewind button */
2675 sim_window_playing = VCRSTOP;
2676 sim_window_maincursor = 0.0;
2677 sim_window_drawcursors(w);
2678 sim_window_updatelayoutwindow();
2679 return;
2680 }
2681 if (inx <= w->uselx + DISPLAYSLIDERSIZE*3)
2682 {
2683 /* hit in play backwards button */
2684 sim_window_playing = VCRPLAYBACKWARD;
2685 sim_window_lastadvance = ticktime();
2686 return;
2687 }
2688 if (inx <= w->uselx + DISPLAYSLIDERSIZE*4)
2689 {
2690 /* hit in stop button */
2691 sim_window_playing = VCRSTOP;
2692 return;
2693 }
2694 if (inx <= w->uselx + DISPLAYSLIDERSIZE*5)
2695 {
2696 /* hit in play button */
2697 sim_window_playing = VCRPLAYFOREWARD;
2698 sim_window_lastadvance = ticktime();
2699 return;
2700 }
2701 if (inx <= w->uselx + DISPLAYSLIDERSIZE*6)
2702 {
2703 /* hit in advance to end button */
2704 endtime = 0.0;
2705 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2706 if (tr->maxtime > endtime) endtime = tr->maxtime;
2707 sim_window_playing = VCRSTOP;
2708 sim_window_maincursor = endtime;
2709 sim_window_drawcursors(w);
2710 sim_window_updatelayoutwindow();
2711 return;
2712 }
2713 if (inx <= w->uselx + DISPLAYSLIDERSIZE*7)
2714 {
2715 /* hit in blank button */
2716 return;
2717 }
2718 if (inx <= w->uselx + DISPLAYSLIDERSIZE*8)
2719 {
2720 /* hit in faster button */
2721 j = sim_window_advancespeed / 4;
2722 if (j <= 0) j = 1;
2723 sim_window_advancespeed += j;
2724 return;
2725 }
2726 if (inx <= w->uselx + DISPLAYSLIDERSIZE*9)
2727 {
2728 /* hit in slower button */
2729 j = sim_window_advancespeed / 4;
2730 if (j <= 0) j = 1;
2731 sim_window_advancespeed -= j;
2732 if (sim_window_advancespeed <= 0) sim_window_advancespeed = 1;
2733 return;
2734 }
2735 if (inx <= w->uselx + DISPLAYSLIDERSIZE*10)
2736 {
2737 /* hit in blank button */
2738 return;
2739 }
2740 if (inx <= w->uselx + DISPLAYSLIDERSIZE*11)
2741 {
2742 /* hit in left arrow: small shift down in time (may repeat) */
2743 sim_waveformwindow = w;
2744 sim_waveformsliderpart = 0;
2745 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_horizontalslider, us_nullchar,
2746 us_nullvoid, TRACKNORMAL);
2747 return;
2748 }
2749 if (inx < w->thumblx)
2750 {
2751 /* hit to left of thumb: large shift down in time (may repeat) */
2752 sim_waveformwindow = w;
2753 sim_waveformsliderpart = 1;
2754 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_horizontalslider, us_nullchar,
2755 us_nullvoid, TRACKNORMAL);
2756 return;
2757 }
2758 if (inx <= w->thumbhx)
2759 {
2760 /* hit on thumb: track thumb motion */
2761 sim_waveformwindow = w;
2762 sim_window_gettimeextents(&mintime, &maxtime);
2763 sim_waveformhrange = maxtime * 2.0;
2764 sim_window_getaveragetimerange(&mintime, &maxtime);
2765 if (maxtime*2.0 > sim_waveformhrange) sim_waveformhrange = maxtime*2.0;
2766
2767 sim_waveforminiththumbpos = w->thumblx;
2768 us_hthumbbegin(inx, w, w->usely, w->uselx, w->usehx,
2769 sim_window_hthumbtrackingcallback);
2770 trackcursor(FALSE, us_nullup, us_nullvoid, us_hthumbdown, us_nullchar,
2771 us_hthumbdone, TRACKNORMAL);
2772 return;
2773 }
2774 if (inx < w->usehx - DISPLAYSLIDERSIZE)
2775 {
2776 /* hit to right of thumb: large shift up in time (may repeat) */
2777 sim_waveformwindow = w;
2778 sim_waveformsliderpart = 3;
2779 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_horizontalslider, us_nullchar,
2780 us_nullvoid, TRACKNORMAL);
2781 return;
2782 }
2783
2784 /* hit in right arrow: small shift up in time (may repeat) */
2785 sim_waveformwindow = w;
2786 sim_waveformsliderpart = 4;
2787 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_horizontalslider, us_nullchar,
2788 us_nullvoid, TRACKNORMAL);
2789 return;
2790 }
2791
2792 sim_window_setviewport(w);
2793 x = inx; y = iny;
2794 sim_window_scaletowindow(w, &x, &y);
2795
2796 /* see if the divider between names and signals was hit */
2797 if (abs(x - sim_window_wavexbar) <= 3 && y >= 560)
2798 {
2799 sim_window_dividerinit(w);
2800 sim_window_draghighoff = TRUE;
2801 for(j=0; j<sim_window_highlightedtracecount; j++)
2802 sim_window_highlightname(w, sim_window_highlightedtraces[j], FALSE);
2803 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_dividerdown, us_nullchar,
2804 sim_window_dividerdone, TRACKNORMAL);
2805 if (sim_window_draghighoff)
2806 {
2807 for(j=0; j<sim_window_highlightedtracecount; j++)
2808 sim_window_highlightname(w, sim_window_highlightedtraces[j], TRUE);
2809 }
2810 return;
2811 }
2812
2813 /* see if a signal name was hit */
2814 if (x <= sim_window_wavexnameend)
2815 {
2816 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
2817 ind = sim_window_visframes - 1 - (y - WAVEYSIGBOT) / temp_trace_spacing;
2818 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
2819 {
2820 if ((tr->flags&TRACENOTDRAWN) == 0)
2821 {
2822 if (tr->frameno == ind + sim_window_topframes)
2823 {
2824 ypos = (sim_window_visframes - 1 - ind) * temp_trace_spacing + WAVEYSIGBOT + tr->nameoff;
2825 if (y >= ypos && y <= ypos + sim_window_txthei) break;
2826 }
2827 }
2828 }
2829 if (tr == NOTRACE)
2830 {
2831 /* not over any signal: drag out selection of signal names */
2832 sim_window_initialx = x;
2833 sim_window_initialy = y;
2834 sim_window_currentdragy = y;
2835 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_seleachdown,
2836 us_nullchar, us_nullvoid, TRACKDRAGGING);
2837 sim_window_drawtraceselect(w, sim_window_currentdragy, sim_window_initialy, FALSE);
2838 return;
2839 }
2840
2841 /* see if it is a double-click on a bus name */
2842 if (doublebutton(button))
2843 {
2844 if ((tr->flags&TRACETYPE) == TRACEISBUS)
2845 {
2846 /* closed bus: open it up */
2847 j = 0;
2848 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
2849 {
2850 if (otr->buschannel != tr) continue;
2851 otr->flags &= ~TRACENOTDRAWN;
2852 otr->frameno = --j;
2853 }
2854 tr->flags = (tr->flags & ~TRACETYPE) | TRACEISOPENBUS;
2855
2856 /* renumber lines in the display */
2857 sim_window_renumberlines();
2858
2859 /* adjust the number of visible lines */
2860 sim_window_setviewport(w);
2861
2862 sim_window_redraw();
2863 return;
2864 }
2865 if ((tr->flags&TRACETYPE) == TRACEISOPENBUS)
2866 {
2867 /* opened bus: close it up */
2868 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
2869 if (otr->buschannel == tr) otr->flags |= TRACENOTDRAWN;
2870 tr->flags = (tr->flags & ~TRACETYPE) | TRACEISBUS;
2871
2872 /* renumber lines in the display */
2873 sim_window_renumberlines();
2874
2875 sim_window_redraw();
2876 return;
2877 }
2878 return;
2879 }
2880
2881 /* see if the signal shares a line with any others */
2882 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
2883 {
2884 if ((otr->flags&TRACENOTDRAWN) != 0) continue;
2885 if (otr != tr && otr->frameno == tr->frameno) break;
2886 }
2887 if (otr == NOTRACE)
2888 {
2889 /* not a shared signal: handle dragging of the name */
2890 sim_window_tracedragyoff = 0;
2891 sim_window_initialy = y;
2892 sim_window_tracedragtr = tr;
2893 sim_window_drawtracedrag(w, TRUE);
2894 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_eachdown,
2895 us_nullchar, us_nullvoid, TRACKDRAGGING);
2896 sim_window_drawtracedrag(w, FALSE);
2897
2898 /* see if the signal name was dragged to a new location */
2899 traceframesmoved = sim_window_tracedragyoff / temp_trace_spacing;
2900 if (traceframesmoved != 0)
2901 {
2902 /* erase highlighting */
2903 sim_window_cleartracehighlight();
2904
2905 /* find which signal name it was dragged to */
2906 otrprev = NOTRACE;
2907 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
2908 {
2909 if ((otr->flags&TRACENOTDRAWN) == 0)
2910 {
2911 if (otr->frameno == tr->frameno - traceframesmoved) break;
2912 }
2913 if (otr != tr) otrprev = otr;
2914 }
2915 if (otr != NOTRACE)
2916 {
2917 /* pull out the selected signal */
2918 sim_window_removetrace(tr);
2919
2920 /* insert signal in new location */
2921 if (tr->frameno < otr->frameno)
2922 {
2923 sim_window_addtrace(tr, otr);
2924 } else
2925 {
2926 sim_window_addtrace(tr, otrprev);
2927 }
2928
2929 /* move any bus signals inside of this */
2930 buschain = endbuschain = NOTRACE;
2931 for(otr = sim_window_firstrace; otr != NOTRACE; otr = nexttr)
2932 {
2933 nexttr = otr->nexttrace;
2934 if (otr->buschannel == tr)
2935 {
2936 sim_window_removetrace(otr);
2937 if (endbuschain == NOTRACE) endbuschain = buschain = otr; else
2938 {
2939 endbuschain->nexttrace = otr;
2940 endbuschain = otr;
2941 }
2942 otr->nexttrace = NOTRACE;
2943 }
2944 }
2945 addloc = tr;
2946 for(otr = buschain; otr != NOTRACE; otr = nexttr)
2947 {
2948 nexttr = otr->nexttrace;
2949 sim_window_addtrace(otr, addloc);
2950 addloc = otr;
2951 }
2952
2953 /* renumber lines in the display */
2954 sim_window_renumberlines();
2955
2956 /* redisplay window */
2957 sim_window_redraw();
2958
2959 /* save the new configuration */
2960 sim_window_savesignalorder();
2961 }
2962 sim_window_addhighlighttrace((INTBIG)tr);
2963 par[0] = x_("highlight");
2964 telltool(net_tool, 1, par);
2965 return;
2966 }
2967 }
2968
2969 /* highlight the selected signal */
2970 if (!shiftbutton(button))
2971 {
2972 /* shift not held: simply highlight this signal */
2973 sim_window_cleartracehighlight();
2974 sim_window_addhighlighttrace((INTBIG)tr);
2975 } else
2976 {
2977 /* complement state of this signal */
2978 for(j=0; j<sim_window_highlightedtracecount; j++)
2979 if (tr == sim_window_highlightedtraces[j]) break;
2980 if (j < sim_window_highlightedtracecount)
2981 {
2982 /* signal already highlighted: unhighlight it */
2983 sim_window_deletehighlighttrace((INTBIG)tr);
2984 } else
2985 {
2986 /* signal new: add to highlight */
2987 sim_window_addhighlighttrace((INTBIG)tr);
2988 }
2989
2990 }
2991 par[0] = x_("highlight");
2992 telltool(net_tool, 1, par);
2993 return;
2994 }
2995
2996 /* see if an area-select was requested */
2997 butname = buttonname(button, &important);
2998 areaselect = FALSE;
2999 #ifdef WIN32
3000 if (namesame(butname, x_("SARIGHT")) == 0) areaselect = TRUE;
3001 #endif
3002 #ifdef MACOS
3003 if (namesame(butname, x_("SMOButton")) == 0) areaselect = TRUE;
3004 #endif
3005 #ifdef ONUNIX
3006 if (namesame(butname, x_("SMRIGHT")) == 0) areaselect = TRUE;
3007 #endif
3008 if (areaselect)
3009 {
3010 /* select an area of the waveform window */
3011 sim_window_zoominix = sim_window_zoomothx = x;
3012 sim_window_zoominiy = sim_window_zoomothy = y;
3013 sim_window_drawareazoom(w, TRUE, sim_window_zoominix, sim_window_zoominiy,
3014 sim_window_zoomothx, sim_window_zoomothy);
3015 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_zoomdown,
3016 us_nullchar, us_nullvoid, TRACKDRAGGING);
3017 sim_window_drawareazoom(w, FALSE, sim_window_zoominix, sim_window_zoominiy,
3018 sim_window_zoomothx, sim_window_zoomothy);
3019
3020 /* find the area */
3021 lx = mini(sim_window_zoominix, sim_window_zoomothx);
3022 hx = maxi(sim_window_zoominix, sim_window_zoomothx);
3023 ly = mini(sim_window_zoominiy, sim_window_zoomothy);
3024 hy = maxi(sim_window_zoominiy, sim_window_zoomothy);
3025 lowdisp = sim_window_xpostotime(lx);
3026 highdisp = sim_window_xpostotime(hx);
3027 range = highdisp - lowdisp;
3028
3029 /* zoom into it horizontally */
3030 if (sim_window_maincursor < lowdisp || sim_window_maincursor > highdisp)
3031 sim_window_setmaincursor(lowdisp);
3032 if (sim_window_extensioncursor < lowdisp || sim_window_extensioncursor > highdisp)
3033 sim_window_setextensioncursor(highdisp);
3034 sim_window_settimerange(0, lowdisp-range/15.0f, highdisp+range/15.0f);
3035
3036 /* zoom vertically as well */
3037 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
3038 ind1 = sim_window_visframes - 1 - (ly - WAVEYSIGBOT) / temp_trace_spacing;
3039 ind2 = sim_window_visframes - 1 - (hy - WAVEYSIGBOT) / temp_trace_spacing;
3040 y_min = (sim_window_visframes - 1 - ind1) * temp_trace_spacing + WAVEYSIGBOT;
3041 y_max = y_min + temp_trace_spacing - WAVEYSIGGAP;
3042 if (ind1 == ind2)
3043 {
3044 /* dragging happend all in one frame, see if it is analog */
3045 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
3046 {
3047 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
3048 if (tr->frameno != ind1 + sim_window_topframes) continue;
3049 if ((tr->flags & TRACETYPE) == TRACEISANALOG) break;
3050 }
3051 if (tr != NOTRACE)
3052 {
3053 /* invert the display computation to get real units from screen coordinates */
3054 frame = ind1 + sim_window_topframes;
3055 flow = ((ly-y_min) / (float)(y_max - y_min)) * sim_window_get_extanarange(frame) + sim_window_get_botval(frame);
3056 fhigh = ((hy-y_min) / (float)(y_max - y_min)) * sim_window_get_extanarange(frame) + sim_window_get_botval(frame);
3057 range = fhigh - flow;
3058 sim_window_set_analow(frame, flow-(float)range/15.0f);
3059 sim_window_set_anahigh(frame, fhigh+(float)range/15.0f);
3060 }
3061 }
3062 sim_window_redisphandler(w);
3063 return;
3064 }
3065
3066 /* see if a cursor was hit */
3067 xpos = sim_window_timetoxpos(sim_window_maincursor);
3068 if (abs(x-xpos) < 10 && y < 560)
3069 {
3070 /* main cursor hit */
3071 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_eachwdown,
3072 us_nullchar, us_nullvoid, TRACKDRAGGING);
3073 return;
3074 }
3075 xpos = sim_window_timetoxpos(sim_window_extensioncursor);
3076 if (abs(x-xpos) < 10 && y < 560)
3077 {
3078 /* extension cursor hit */
3079 trackcursor(FALSE, us_nullup, us_nullvoid, sim_window_eachbdown,
3080 us_nullchar, us_nullvoid, TRACKDRAGGING);
3081 return;
3082 }
3083
3084 /* see if the line of a signal was hit */
3085 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
3086 {
3087 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
3088 if (sim_window_plottrace(tr, w, 1, x, y)) break;
3089 }
3090 if (tr != NOTRACE)
3091 {
3092 /* highlight the selected signal */
3093 if (!shiftbutton(button))
3094 {
3095 /* shift not held: simply highlight this signal */
3096 sim_window_cleartracehighlight();
3097 sim_window_addhighlighttrace((INTBIG)tr);
3098 } else
3099 {
3100 /* complement state of this signal */
3101 for(j=0; j<sim_window_highlightedtracecount; j++)
3102 if (tr == sim_window_highlightedtraces[j]) break;
3103 if (j < sim_window_highlightedtracecount)
3104 {
3105 /* signal already highlighted: unhighlight it */
3106 sim_window_deletehighlighttrace((INTBIG)tr);
3107 } else
3108 {
3109 /* signal new: add to highlight */
3110 sim_window_addhighlighttrace((INTBIG)tr);
3111 }
3112
3113 }
3114 par[0] = x_("highlight");
3115 telltool(net_tool, 1, par);
3116 } else
3117 {
3118 sim_window_cleartracehighlight();
3119 }
3120 }
3121
3122 /*
3123 * Routine called when VCR is playing. Advances time if appropriate.
3124 */
sim_window_advancetime(void)3125 void sim_window_advancetime(void)
3126 {
3127 REGISTER UINTBIG curtime;
3128 double dtime;
3129 REGISTER TRACE *tr;
3130 REGISTER WINDOWPART *wavewin;
3131
3132 if (sim_window_playing == VCRSTOP) return;
3133
3134 /* see if there is a waveform window */
3135 wavewin = sim_window_findwaveform();
3136 if (wavewin == NOWINDOWPART) return;
3137
3138 /* see if it is time to advance the VCR */
3139 curtime = ticktime();
3140 if (curtime - sim_window_lastadvance < 5) return;
3141 sim_window_lastadvance = curtime;
3142
3143 /* determine how much the time changes */
3144 tr = sim_window_firstrace;
3145 if (tr == NOTRACE) return;
3146 dtime = sim_window_advancespeed * (tr->maxtime-tr->mintime) / (WAVEXSIGEND-sim_window_wavexsigstart);
3147
3148 if (sim_window_playing == VCRPLAYFOREWARD)
3149 {
3150 /* advance time forward */
3151 sim_window_maincursor += dtime;
3152 } else
3153 {
3154 /* advance time backward */
3155 sim_window_maincursor -= dtime;
3156 if (sim_window_maincursor < 0.0) sim_window_maincursor = 0.0;
3157 }
3158 sim_window_drawcursors(wavewin);
3159 sim_window_updatelayoutwindow();
3160 }
3161
3162 /*
3163 * Routine to initialize the display of measurements.
3164 */
sim_window_distanceinit(WINDOWPART * w)3165 void sim_window_distanceinit(WINDOWPART *w)
3166 {
3167 sim_window_measureframe = -1;
3168 sim_waveformwindow = w;
3169 }
3170
3171 /*
3172 * Routine called each time the cursor advances during measurement.
3173 */
sim_window_distancedown(INTBIG x,INTBIG y)3174 BOOLEAN sim_window_distancedown(INTBIG x, INTBIG y)
3175 {
3176 REGISTER INTBIG frame, y_min, y_max, slot, dragx, dragy, temp_trace_spacing;
3177 INTBIG i1, i2;
3178 double xval, yval, position;
3179 float mintime, maxtime;
3180 static CHAR distancemessage[200];
3181
3182 /* initialize polygon */
3183 (void)needstaticpolygon(&sim_window_dragpoly, 4, sim_tool->cluster);
3184 sim_window_dragpoly->desc = &sim_window_desc;
3185 sim_window_desc.bits = LAYERH;
3186
3187 /* determine coordinates of this measurement */
3188 sim_window_scaletowindow(sim_waveformwindow, &x, &y);
3189 frame = sim_window_ypostoval(y, &yval);
3190 xval = sim_window_xpostotime(x);
3191
3192 /* convert coordinates back to screen */
3193 dragx = sim_window_timetoxpos(xval);
3194 slot = frame - sim_window_topframes;
3195 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
3196 y_min = (sim_window_visframes - 1 - slot) * temp_trace_spacing + WAVEYSIGBOT;
3197 y_max = y_min + temp_trace_spacing - WAVEYSIGGAP;
3198 position = (double)(y_max - y_min);
3199 position *= (yval - sim_window_get_botval(frame)) / sim_window_get_extanarange(frame);
3200 dragy = (INTBIG)position + y_min;
3201
3202 if (sim_window_measureframe < 0)
3203 {
3204 sim_window_firstmeasurex = dragx; sim_window_firstmeasurey = dragy;
3205 sim_window_firstmeasuretime = xval;
3206 sim_window_firstmeasureyval = yval;
3207 sim_window_measureframe = frame;
3208 } else
3209 {
3210 /* if it didn't actually move, go no further */
3211 if (dragx == sim_window_lastmeasurex && dragy == sim_window_lastmeasurey) return(FALSE);
3212
3213 /* if it changed frames, go no further */
3214 if (sim_window_measureframe != frame) return(FALSE);
3215
3216 /* undraw the distance */
3217 sim_window_desc.col = 0;
3218 sim_window_drawdistance();
3219 }
3220 sim_window_lastmeasurex = dragx; sim_window_lastmeasurey = dragy;
3221
3222 /* draw the new measurement */
3223 sim_window_desc.col = HIGHLIT;
3224 TDCLEAR(sim_window_dragpoly->textdescript);
3225 TDSETSIZE(sim_window_dragpoly->textdescript, TXTSETPOINTS(12));
3226 sim_window_dragpoly->tech = el_curtech;
3227
3228 mintime = sim_window_mintime;
3229 maxtime = sim_window_maxtime;
3230 (void)sim_window_sensible_value(&maxtime, &mintime, &i1, &i2, 5);
3231 (void)esnprintf(distancemessage, 200, x_("dX=%s dY=%g"),
3232 sim_windowconvertengineeringnotation2(xval - sim_window_firstmeasuretime, i2),
3233 yval - sim_window_firstmeasureyval);
3234 sim_window_dragpoly->string = distancemessage;
3235 sim_window_drawdistance();
3236 sim_window_measureframe = 1;
3237 return(FALSE);
3238 }
3239
3240 /*
3241 * Routine to display the current measurement information.
3242 */
sim_window_drawdistance(void)3243 void sim_window_drawdistance(void)
3244 {
3245 INTBIG fx, fy, tx, ty;
3246
3247 sim_window_dragpoly->count = 1;
3248 sim_window_dragpoly->style = TEXTBOTLEFT;
3249 fx = sim_window_firstmeasurex; fy = sim_window_firstmeasurey;
3250 tx = sim_window_lastmeasurex; ty = sim_window_lastmeasurey;
3251 if (!clipline(&fx, &fy, &tx, &ty, sim_waveformwindow->screenlx, sim_waveformwindow->screenhx,
3252 sim_waveformwindow->screenly, sim_waveformwindow->screenhy))
3253 {
3254 sim_window_dragpoly->xv[0] = (fx+tx) / 2;
3255 sim_window_dragpoly->yv[0] = (fy+ty) / 2;
3256 us_showpoly(sim_window_dragpoly, sim_waveformwindow);
3257 }
3258
3259 /* draw the line */
3260 sim_window_dragpoly->xv[0] = sim_window_firstmeasurex;
3261 sim_window_dragpoly->yv[0] = sim_window_firstmeasurey;
3262 sim_window_dragpoly->xv[1] = sim_window_lastmeasurex;
3263 sim_window_dragpoly->yv[1] = sim_window_lastmeasurey;
3264 sim_window_dragpoly->count = 2;
3265 sim_window_dragpoly->style = OPENED;
3266 us_showpoly(sim_window_dragpoly, sim_waveformwindow);
3267
3268 /* draw crosses at the end */
3269 sim_window_dragpoly->xv[0] = sim_window_firstmeasurex;
3270 sim_window_dragpoly->yv[0] = sim_window_firstmeasurey;
3271 sim_window_dragpoly->count = 1;
3272 sim_window_dragpoly->style = CROSS;
3273 us_showpoly(sim_window_dragpoly, sim_waveformwindow);
3274 sim_window_dragpoly->xv[0] = sim_window_lastmeasurex;
3275 sim_window_dragpoly->yv[0] = sim_window_lastmeasurey;
3276 us_showpoly(sim_window_dragpoly, sim_waveformwindow);
3277 }
3278
3279 /*
3280 * Routine called when the button is released during measurement.
3281 */
sim_window_distanceup(void)3282 void sim_window_distanceup(void)
3283 {
3284 if (sim_window_measureframe >= 0)
3285 {
3286 /* leave the results in the messages window */
3287 ttyputmsg(x_("%s"), sim_window_dragpoly->string);
3288 }
3289 }
3290
3291 /*
3292 * Routine to initialize the dragging of the divider between the signal names and the waveforms.
3293 */
sim_window_dividerinit(WINDOWPART * w)3294 void sim_window_dividerinit(WINDOWPART *w)
3295 {
3296 sim_waveformwindow = w;
3297 sim_window_dragshown = FALSE;
3298 }
3299
3300 /*
3301 * Routine called whenever the mouse moves during dragging of the divider between the signal
3302 * names and the waveforms.
3303 */
sim_window_dividerdown(INTBIG x,INTBIG y)3304 BOOLEAN sim_window_dividerdown(INTBIG x, INTBIG y)
3305 {
3306 INTBIG dummyx, lowy, highy;
3307 Q_UNUSED( y );
3308
3309 dummyx = 0;
3310 lowy = 31;
3311 highy = WAVEYTEXTTOP;
3312 sim_window_mapcoord(sim_waveformwindow, &dummyx, &lowy);
3313 sim_window_mapcoord(sim_waveformwindow, &dummyx, &highy);
3314 if (sim_window_dragshown)
3315 {
3316 /* if it didn't actually move, go no further */
3317 if (x == sim_window_draglastx) return(FALSE);
3318
3319 /* undraw the line */
3320 sim_window_desc.bits = LAYERH;
3321 sim_window_desc.col = ALLOFF;
3322 screendrawline(sim_waveformwindow, sim_window_draglastx, lowy,
3323 sim_window_draglastx, highy, &sim_window_desc, 0);
3324 }
3325
3326 sim_window_draglastx = x;
3327 if (sim_window_draglastx >= sim_waveformwindow->usehx)
3328 sim_window_draglastx = sim_waveformwindow->usehx-1;
3329 if (sim_window_draglastx < sim_waveformwindow->uselx)
3330 sim_window_draglastx = sim_waveformwindow->uselx;
3331
3332 /* draw the outline */
3333 sim_window_desc.bits = LAYERH;
3334 sim_window_desc.col = HIGHLIT;
3335 screendrawline(sim_waveformwindow, sim_window_draglastx, lowy,
3336 sim_window_draglastx, highy, &sim_window_desc, 0);
3337
3338 sim_window_dragshown = TRUE;
3339 return(FALSE);
3340 }
3341
3342 /*
3343 * Routine called when the mouse is released after dragging of the divider between the signal
3344 * names and the waveforms.
3345 */
sim_window_dividerdone(void)3346 void sim_window_dividerdone(void)
3347 {
3348 REGISTER INTBIG newbar;
3349 INTBIG dummyx, lowy, highy;
3350
3351 if (sim_window_dragshown)
3352 {
3353 /* undraw the outline */
3354 sim_window_desc.bits = LAYERH;
3355 sim_window_desc.col = ALLOFF;
3356
3357 dummyx = 0;
3358 lowy = 31;
3359 highy = 560;
3360 sim_window_mapcoord(sim_waveformwindow, &dummyx, &lowy);
3361 sim_window_mapcoord(sim_waveformwindow, &dummyx, &highy);
3362 screendrawline(sim_waveformwindow, sim_window_draglastx, lowy,
3363 sim_window_draglastx, highy, &sim_window_desc, 0);
3364
3365 /* compute new bar position and redraw */
3366 newbar = muldiv(sim_window_draglastx - sim_waveformwindow->uselx,
3367 sim_waveformwindow->screenhx - sim_waveformwindow->screenlx,
3368 sim_waveformwindow->usehx - sim_waveformwindow->uselx) +
3369 sim_waveformwindow->screenlx;
3370 if (newbar != sim_window_wavexbar && newbar > 20 && newbar < WAVEXSIGEND-10)
3371 {
3372 sim_window_wavexbar = newbar;
3373 sim_window_wavexsigstart = newbar+1;
3374 sim_window_wavexnameend = newbar-1;
3375 sim_window_wavexnameendana = newbar-13;
3376 sim_window_redisphandler(sim_waveformwindow);
3377 sim_window_draghighoff = FALSE;
3378 }
3379 }
3380 }
3381
sim_window_termhandler(WINDOWPART * w)3382 void sim_window_termhandler(WINDOWPART *w)
3383 {
3384 REGISTER WINDOWPART *schemwin;
3385 REGISTER WINDOWPART *ww;
3386 Q_UNUSED( w );
3387
3388 /* see if there is another simulation window (because this one split) */
3389 for(ww = el_topwindowpart; ww != NOWINDOWPART; ww = ww->nextwindowpart)
3390 {
3391 if (ww == w) continue;
3392 if ((ww->state&WINDOWTYPE) == WAVEFORMWINDOW) break;
3393 }
3394 if (ww != NOWINDOWPART) return;
3395
3396 /* disable simulation control in schematics/layout window */
3397 schemwin = sim_window_findschematics();
3398 if (schemwin == NOWINDOWPART) return;
3399
3400 startobjectchange((INTBIG)schemwin, VWINDOWPART);
3401 (void)setval((INTBIG)schemwin, VWINDOWPART, x_("state"), schemwin->state &
3402 ~WINDOWSIMMODE, VINTEGER);
3403 (void)setval((INTBIG)schemwin, VWINDOWPART, x_("charhandler"),
3404 (INTBIG)DEFAULTCHARHANDLER, VADDRESS);
3405 endobjectchange((INTBIG)schemwin, VWINDOWPART);
3406 }
3407
3408 static INTBIG sim_rewinddots[] = {
3409 1,9, 1,8, 1,7, 1,6, 1,5, 1,4, 1,3, 1,2, 1,1,
3410 2,5,
3411 3,4, 3,5, 3,6,
3412 4,4, 4,5, 4,6,
3413 5,3, 5,4, 5,5, 5,6, 5,7,
3414 6,3, 6,4, 6,5, 6,6, 6,7,
3415 7,2, 7,3, 7,4, 7,5, 7,6, 7,7, 7,8,
3416 8,2, 8,3, 8,4, 8,5, 8,6, 8,7, 8,8,
3417 9,1, 9,2, 9,3, 9,4, 9,5, 9,6, 9,7, 9,8, 9,9,
3418 -1,-1};
3419 static INTBIG sim_playbackwardsdots[] = {
3420 1,5,
3421 2,5,
3422 3,4, 3,5, 3,6,
3423 4,4, 4,5, 4,6,
3424 5,3, 5,4, 5,5, 5,6, 5,7,
3425 6,3, 6,4, 6,5, 6,6, 6,7,
3426 7,2, 7,3, 7,4, 7,5, 7,6, 7,7, 7,8,
3427 8,2, 8,3, 8,4, 8,5, 8,6, 8,7, 8,8,
3428 9,1, 9,2, 9,3, 9,4, 9,5, 9,6, 9,7, 9,8, 9,9,
3429 -1,-1};
3430 static INTBIG sim_stopdots[] = {
3431 2,2, 2,3, 2,4, 2,5, 2,6, 2,7, 2,8,
3432 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 3,8,
3433 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 4,8,
3434 5,2, 5,3, 5,4, 5,5, 5,6, 5,7, 5,8,
3435 6,2, 6,3, 6,4, 6,5, 6,6, 6,7, 6,8,
3436 7,2, 7,3, 7,4, 7,5, 7,6, 7,7, 7,8,
3437 8,2, 8,3, 8,4, 8,5, 8,6, 8,7, 8,8,
3438 -1,-1};
3439 static INTBIG sim_playforwarddots[] = {
3440 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 1,8, 1,9,
3441 2,2, 2,3, 2,4, 2,5, 2,6, 2,7, 2,8,
3442 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 3,8,
3443 4,3, 4,4, 4,5, 4,6, 4,7,
3444 5,3, 5,4, 5,5, 5,6, 5,7,
3445 6,4, 6,5, 6,6,
3446 7,4, 7,5, 7,6,
3447 8,5,
3448 9,5,
3449 -1,-1};
3450 static INTBIG sim_fastforwarddots[] = {
3451 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 1,8, 1,9,
3452 2,2, 2,3, 2,4, 2,5, 2,6, 2,7, 2,8,
3453 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 3,8,
3454 4,3, 4,4, 4,5, 4,6, 4,7,
3455 5,3, 5,4, 5,5, 5,6, 5,7,
3456 6,4, 6,5, 6,6,
3457 7,4, 7,5, 7,6,
3458 8,5,
3459 9,1, 9,2, 9,3, 9,4, 9,5, 9,6, 9,7, 9,8, 9,9,
3460 -1,-1};
3461 static INTBIG sim_fasterdots[] = {
3462 2,7,
3463 3,7, 3,8,
3464 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 4,8, 4,9,
3465 5,7, 5,8,
3466 6,7,
3467 7,1, 7,2, 7,3, 7,4, 7,5,
3468 8,3, 8,5,
3469 9,5,
3470 -1,-1};
3471 static INTBIG sim_slowerdots[] = {
3472 2,3,
3473 3,2, 3,3,
3474 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 4,8, 4,9,
3475 5,2, 5,3,
3476 6,3,
3477 7,5, 7,7, 7,8, 7,9,
3478 8,5, 8,7, 8,9,
3479 9,5, 9,6, 9,7, 9,9,
3480 -1,-1};
3481
3482 /*
3483 * This procedure redraws the display, allowing for resize.
3484 */
sim_window_redisphandler(WINDOWPART * w)3485 void sim_window_redisphandler(WINDOWPART *w)
3486 {
3487 INTBIG lx, hx, ly, hy;
3488 UINTBIG descript[TEXTDESCRIPTSIZE];
3489 double range;
3490 REGISTER INTBIG thumbtop, thumbarea, thumbsize, extraroom;
3491 REGISTER TRACE *tr;
3492 REGISTER CHAR *simname;
3493 REGISTER void *infstr;
3494
3495 sim_window_setviewport(w);
3496
3497 /* clear the window */
3498 sim_window_desc.bits = LAYERA;
3499 sim_window_desc.col = ALLOFF;
3500 w->uselx -= DISPLAYSLIDERSIZE;
3501 w->usely -= DISPLAYSLIDERSIZE;
3502 lx = w->uselx; hx = w->usehx;
3503 ly = w->usely; hy = w->usehy;
3504 screendrawbox(w, lx, hx, ly, hy, &sim_window_desc);
3505
3506 /* draw vertical slider on the left */
3507 us_drawverticalslider(w, lx-2, ly+DISPLAYSLIDERSIZE, hy, TRUE);
3508 if (sim_window_lines > 0)
3509 {
3510 thumbsize = sim_window_visframes * 100 / sim_window_lines;
3511 if (thumbsize >= 100) thumbsize = 100;
3512 if (thumbsize == 100 && sim_window_topframes == 0)
3513 {
3514 w->thumbly = 0; w->thumbhy = -1;
3515 } else
3516 {
3517 thumbtop = sim_window_topframes * 100 / sim_window_lines;
3518 thumbarea = w->usehy - w->usely - DISPLAYSLIDERSIZE*2;
3519
3520 w->thumbhy = w->usehy - DISPLAYSLIDERSIZE - thumbarea * thumbtop / 100;
3521 w->thumbly = w->thumbhy - thumbarea * thumbsize / 100;
3522 if (w->thumbhy > w->usehy-DISPLAYSLIDERSIZE-2) w->thumbhy = w->usehy-DISPLAYSLIDERSIZE-2;
3523 if (w->thumbly < w->usely+DISPLAYSLIDERSIZE*2+2) w->thumbly = w->usely+DISPLAYSLIDERSIZE*2+2;
3524 }
3525 us_drawverticalsliderthumb(w, lx-2, ly+DISPLAYSLIDERSIZE, hy, w->thumbly, w->thumbhy);
3526 }
3527
3528 /* draw horizontal slider on the bottom */
3529 tr = (TRACE *)sim_window_firstrace;
3530 if (tr != NOTRACE)
3531 {
3532 extraroom = DISPLAYSLIDERSIZE * 10;
3533 us_drawhorizontalslider(w, ly+DISPLAYSLIDERSIZE, lx+DISPLAYSLIDERSIZE+extraroom, hx, 0);
3534 thumbarea = w->usehx - w->uselx - DISPLAYSLIDERSIZE*2 - extraroom;
3535 if (tr->mintime <= 0.0)
3536 {
3537 w->thumblx = w->uselx+extraroom+DISPLAYSLIDERSIZE*2+2;
3538 w->thumbhx = w->thumblx + thumbarea/2;
3539 } else
3540 {
3541 range = tr->maxtime * 2.0;
3542 w->thumblx = (INTBIG)(w->uselx+extraroom+DISPLAYSLIDERSIZE*2+2 + tr->mintime/range*thumbarea);
3543 w->thumbhx = (INTBIG)(w->uselx+extraroom+DISPLAYSLIDERSIZE*2+2 + tr->maxtime/range*thumbarea);
3544 if (w->thumbhx < w->thumblx + MINTHUMB) w->thumbhx = w->thumblx + MINTHUMB;
3545 }
3546 if (w->thumbhx > w->usehx-DISPLAYSLIDERSIZE-2) w->thumbhx = w->usehx-DISPLAYSLIDERSIZE-2;
3547 if (w->thumblx < w->uselx+DISPLAYSLIDERSIZE*2+2) w->thumblx = w->uselx+DISPLAYSLIDERSIZE*2+2;
3548 us_drawhorizontalsliderthumb(w, ly+DISPLAYSLIDERSIZE, lx+DISPLAYSLIDERSIZE+extraroom, hx, w->thumblx, w->thumbhx, 0);
3549 }
3550
3551 /* draw the VCR controls in horizontal slider */
3552 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*2, ly, sim_rewinddots);
3553 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*3, ly, sim_playbackwardsdots);
3554 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*4, ly, sim_stopdots);
3555 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*5, ly, sim_playforwarddots);
3556 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*6, ly, sim_fastforwarddots);
3557 us_drawslidercorner(w, lx+DISPLAYSLIDERSIZE*7, lx+DISPLAYSLIDERSIZE*7-1, ly, ly+DISPLAYSLIDERSIZE-1, TRUE);
3558 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*8, ly, sim_fasterdots);
3559 us_drawwindowicon(w, lx+DISPLAYSLIDERSIZE*9, ly, sim_slowerdots);
3560 us_drawslidercorner(w, lx+DISPLAYSLIDERSIZE*10, lx+DISPLAYSLIDERSIZE*10-1, ly, ly+DISPLAYSLIDERSIZE-1, TRUE);
3561
3562 /* draw explorer icon in corner of sliders */
3563 us_drawexplorericon(w, lx, ly);
3564
3565 /* reset bounds */
3566 w->uselx += DISPLAYSLIDERSIZE;
3567 w->usely += DISPLAYSLIDERSIZE;
3568
3569 /* draw red outline */
3570 if ((w->state&WINDOWSIMMODE) != 0)
3571 us_showwindowmode(w);
3572
3573 /* write banner at top of window */
3574 TDCLEAR(descript);
3575 TDSETSIZE(descript, TXTSETPOINTS(12));
3576 screensettextinfo(w, NOTECHNOLOGY, descript);
3577 sim_window_desc.col = el_colmentxt;
3578 simname = 0;
3579 switch (sim_window_state & SIMENGINECUR)
3580 {
3581 case SIMENGINECURALS: simname = "ALS"; break;
3582 case SIMENGINECURIRSIM: simname = "IRSIM"; break;
3583 case SIMENGINECURVERILOG: simname = "Verilog"; break;
3584 case SIMENGINECURSPICE: simname = "Spice"; break;
3585 }
3586 infstr = initinfstr();
3587 if ((w->state&WINDOWSIMMODE) == 0)
3588 {
3589 formatinfstr(infstr, _("Inactive %s Simulation Window"), simname);
3590 } else
3591 {
3592 formatinfstr(infstr, _("%s Simulation Window"), simname);
3593 }
3594 if (sim_window_title != 0) formatinfstr(infstr, x_(", %s"), sim_window_title);
3595 addstringtoinfstr(infstr, x_(", ? for help"));
3596 lx = w->uselx;
3597 screendrawtext(w, lx+5, hy-TOPBARSIZE+2, returninfstr(infstr), &sim_window_desc);
3598 screeninvertbox(w, lx, hx, hy-TOPBARSIZE, hy);
3599
3600 sim_window_drawtimescale(w);
3601 sim_window_drawgraph(w);
3602 sim_window_drawcursors(w);
3603 if (sim_window_highframe >= 0)
3604 sim_window_showtracebar(w, sim_window_highframe, 1);
3605 }
3606
3607 /****************************** SUPPORT FUNCTIONS ******************************/
3608
3609 /*
3610 * Routine to convert from simulation time to the proper X position in the waveform window.
3611 */
sim_window_timetoxpos(double time)3612 INTBIG sim_window_timetoxpos(double time)
3613 {
3614 double result;
3615 REGISTER TRACE *tr;
3616
3617 tr = sim_window_firstrace;
3618 if (tr == NOTRACE) return(0);
3619 result = (WAVEXSIGEND-sim_window_wavexsigstart) * (time - tr->mintime) /
3620 (tr->maxtime - tr->mintime) + sim_window_wavexsigstart;
3621 return(rounddouble(result));
3622 }
3623
3624 /*
3625 * Routine to convert from the X position in the waveform window to simulation time.
3626 */
sim_window_xpostotime(INTBIG xpos)3627 double sim_window_xpostotime(INTBIG xpos)
3628 {
3629 double result;
3630 REGISTER TRACE *tr;
3631
3632 tr = sim_window_firstrace;
3633 if (tr == NOTRACE) return(xpos);
3634 result = (xpos-sim_window_wavexsigstart) * (tr->maxtime-tr->mintime) /
3635 (WAVEXSIGEND-sim_window_wavexsigstart) + tr->mintime;
3636 return(result);
3637 }
3638
3639 /*
3640 * Routine to convert from framno and simulation value to the proper Y position in the waveform window.
3641 */
sim_window_valtoypos(INTBIG frameno,double val)3642 INTBIG sim_window_valtoypos(INTBIG frameno, double val)
3643 {
3644 float topval, botval;
3645 INTBIG y_min, y, trace_spacing;
3646
3647 topval = sim_window_get_topval(frameno);
3648 botval = sim_window_get_botval(frameno);
3649 if (val < botval || val > topval || topval == botval) return(-1);
3650 if (sim_window_visframes <= 0) return(-1);
3651 trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
3652 y_min = (sim_window_visframes - 1 - (frameno - sim_window_topframes)) *
3653 trace_spacing + WAVEYSIGBOT;
3654 y = (INTBIG) ((val - botval) / (topval - botval) * (trace_spacing - WAVEYSIGGAP));
3655 return y_min + y;
3656 }
3657
3658 /*
3659 * Routine to convert from the Y position in the waveform window to simulation value and frameno.
3660 */
sim_window_ypostoval(INTBIG ypos,double * val)3661 INTBIG sim_window_ypostoval(INTBIG ypos, double *val)
3662 {
3663 INTBIG frameno, trace_spacing;
3664 float topval, botval;
3665
3666 if (sim_window_visframes <= 0) return(-1);
3667 trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
3668 frameno = (INTBIG)((ypos - WAVEYSIGBOT)/(double)trace_spacing);
3669 ypos -= WAVEYSIGBOT + frameno*trace_spacing;
3670 if (ypos < 0 || ypos > trace_spacing - WAVEYSIGGAP) return(-1);
3671 frameno = sim_window_visframes - 1 - (frameno - sim_window_topframes);
3672 topval = sim_window_get_topval(frameno);
3673 botval = sim_window_get_botval(frameno);
3674 if (topval == botval) return(-1);
3675 *val = botval + (topval - botval)*ypos/(trace_spacing - WAVEYSIGGAP);
3676 return(frameno);
3677 }
3678
3679 /*
3680 * This procedure prints out the time scale on the bottom of the waveform window.
3681 */
sim_window_drawtimescale(WINDOWPART * wavewin)3682 void sim_window_drawtimescale(WINDOWPART *wavewin)
3683 {
3684 INTBIG x_pos;
3685 float time;
3686 REGISTER TRACE *tr;
3687 INTBIG i1, i2;
3688
3689 tr = sim_window_firstrace;
3690 if (tr == NOTRACE) return;
3691
3692 sim_window_setmask(LAYERA);
3693 sim_window_setcolor(MENTXT);
3694 sim_window_max_timetick = sim_window_maxtime = (float)tr->maxtime;
3695 sim_window_min_timetick = sim_window_mintime = (float)tr->mintime;
3696 sim_window_time_separation = sim_window_sensible_value(&sim_window_max_timetick, &sim_window_min_timetick, &i1, &i2, 5);
3697 if (sim_window_time_separation == 0.0) return;
3698
3699 time = sim_window_min_timetick;
3700 for(;;)
3701 {
3702 if (time > sim_window_maxtime) break;
3703 x_pos = sim_window_timetoxpos(time);
3704 sim_window_moveto(x_pos, 0);
3705 sim_window_drawcstring(wavewin, sim_windowconvertengineeringnotation2(time, i2));
3706 time += sim_window_time_separation;
3707 }
3708 }
3709
sim_window_draw_timeticks(WINDOWPART * wavewin,INTBIG y1,INTBIG y2,BOOLEAN grid)3710 void sim_window_draw_timeticks(WINDOWPART *wavewin, INTBIG y1, INTBIG y2, BOOLEAN grid)
3711 {
3712 INTBIG x_pos;
3713 float time;
3714
3715 time = sim_window_max_timetick;
3716
3717 for(;;)
3718 {
3719 if (time < sim_window_mintime) break;
3720 x_pos = sim_window_timetoxpos(time);
3721
3722 if (grid == TRUE) {
3723 sim_window_moveto(x_pos, y1);
3724 sim_window_drawto(wavewin, x_pos, y2, 1);
3725 }
3726
3727 sim_window_moveto(x_pos, y1);
3728 sim_window_drawto(wavewin, x_pos, y1+10, 0);
3729 sim_window_moveto(x_pos, y2);
3730 sim_window_drawto(wavewin, x_pos, y2-10, 0);
3731 time -= sim_window_time_separation;
3732 }
3733 }
3734
3735 /*
3736 * Routine to truncate the time value "time" to the next lower value that is "integral"
3737 */
sim_window_sensibletimevalue(double time)3738 double sim_window_sensibletimevalue(double time)
3739 {
3740 double scale;
3741
3742 if (time != 0.0)
3743 {
3744 scale = 1.0;
3745 while (doubleslessthan(time, 1.0))
3746 {
3747 time *= 10.0;
3748 scale /= 10.0;
3749 }
3750 time = doublefloor(time) * scale;
3751 }
3752 return(time);
3753 }
3754
3755 /*
3756 * Routine to show the vertical bar between signal names and waveform data.
3757 * If "style" is 0, draw it solid
3758 * If "style" is 1, highlight it
3759 * If "style" is 2, unhighlight it
3760 */
sim_window_showtracebar(WINDOWPART * wavewin,INTBIG frame,INTBIG style)3761 void sim_window_showtracebar(WINDOWPART *wavewin, INTBIG frame, INTBIG style)
3762 {
3763 INTBIG y_pos, temp_trace_spacing, visframe, ly, hy, xpos;
3764
3765 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
3766 visframe = frame - sim_window_topframes;
3767 if (visframe < 0 || visframe >= sim_window_visframes) return;
3768 y_pos = (sim_window_visframes - 1 - visframe) * temp_trace_spacing + WAVEYSIGBOT;
3769
3770 /* draw the vertical line between the label and the trace */
3771 switch (style)
3772 {
3773 case 0:
3774 sim_window_setcolor(MENGLY);
3775 sim_window_moveto(sim_window_wavexbar, y_pos);
3776 sim_window_drawto(wavewin, sim_window_wavexbar, y_pos+temp_trace_spacing-WAVEYSIGGAP, 0);
3777 break;
3778 case 1:
3779 sim_window_setcolor(HIGHLIT);
3780 sim_window_setmask(LAYERH);
3781 ly = y_pos; xpos = 0;
3782 sim_window_mapcoord(wavewin, &xpos, &ly);
3783 hy = y_pos+temp_trace_spacing-WAVEYSIGGAP;
3784 xpos = sim_window_wavexbar;
3785 sim_window_mapcoord(wavewin, &xpos, &hy);
3786 screendrawbox(wavewin, xpos-3, xpos+1, ly, hy, &sim_window_desc);
3787 sim_window_setmask(LAYERA);
3788 break;
3789 case 2:
3790 sim_window_setcolor(ALLOFF);
3791 sim_window_setmask(LAYERH);
3792 ly = y_pos; xpos = 0;
3793 sim_window_mapcoord(wavewin, &xpos, &ly);
3794 hy = y_pos+temp_trace_spacing-WAVEYSIGGAP;
3795 xpos = sim_window_wavexbar;
3796 sim_window_mapcoord(wavewin, &xpos, &hy);
3797 screendrawbox(wavewin, xpos-3, xpos+1, ly, hy, &sim_window_desc);
3798 sim_window_setmask(LAYERA);
3799 break;
3800 }
3801 }
3802
sim_window_writetracename(WINDOWPART * wavewin,TRACE * tr)3803 void sim_window_writetracename(WINDOWPART *wavewin, TRACE *tr)
3804 {
3805 INTBIG y_pos, temp_trace_spacing, frameno, px, py, textwid,
3806 maxheight, maxwidth, len, save, size;
3807 REGISTER CHAR *pt;
3808 UINTBIG descript[TEXTDESCRIPTSIZE];
3809 INTBIG wid, hei;
3810
3811 /* compute positions */
3812 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
3813 frameno = tr->frameno - sim_window_topframes;
3814 if (frameno < 0 || frameno >= sim_window_visframes) return;
3815 y_pos = (sim_window_visframes - 1 - frameno) * temp_trace_spacing + WAVEYSIGBOT;
3816
3817 /* draw the vertical line between the label and the trace */
3818 sim_window_showtracebar(wavewin, tr->frameno, 0);
3819
3820 /* set the text color */
3821 if ((tr->flags&TRACETYPE) == TRACEISANALOG) sim_window_setcolor(tr->color); else
3822 sim_window_setcolor(MENTXT);
3823
3824 /* write the text */
3825 if (tr->buschannel == NOTRACE) px = 1; else px = 10;
3826 if ((tr->flags&TRACETYPE) == TRACEISANALOG) textwid = sim_window_wavexnameendana; else
3827 textwid = sim_window_wavexnameend;
3828 py = y_pos + tr->nameoff;
3829 maxheight = applyyscale(wavewin, temp_trace_spacing);
3830 maxwidth = applyxscale(wavewin, textwid-px);
3831 sim_window_mapcoord(wavewin, &px, &py);
3832 pt = tr->name;
3833 if (sim_window_traceprefix != 0)
3834 {
3835 len = estrlen(sim_window_traceprefix);
3836 if (namesamen(pt, sim_window_traceprefix, len) == 0)
3837 pt += len;
3838 }
3839 len = estrlen(pt);
3840 TDCLEAR(descript);
3841 for(size = sim_window_textsize; size >= 4; size--)
3842 {
3843 TDSETSIZE(descript, TXTSETPOINTS(size));
3844 screensettextinfo(wavewin, NOTECHNOLOGY, descript);
3845 screengettextsize(wavewin, pt, &wid, &hei);
3846 if (hei > maxheight && size > 4) continue;
3847 sim_window_txthei = hei * (wavewin->screenhy - wavewin->screenly) /
3848 (wavewin->usehy - wavewin->usely - 20);
3849 while (len > 1 && wid > maxwidth)
3850 {
3851 len--;
3852 save = pt[len]; pt[len] = 0;
3853 screengettextsize(wavewin, pt, &wid, &hei);
3854 pt[len] = (CHAR)save;
3855 }
3856 save = pt[len]; pt[len] = 0;
3857 screendrawtext(wavewin, px, py, pt, &sim_window_desc);
3858 pt[len] = (CHAR)save;
3859 break;
3860 }
3861 }
3862
3863 /*
3864 * This procedure draws the cursors on the timing diagram. The other color
3865 * planes are write protected so that the cursor doesn't alter any of the
3866 * timing diagram information.
3867 */
sim_window_drawcursors(WINDOWPART * wavewin)3868 void sim_window_drawcursors(WINDOWPART *wavewin)
3869 {
3870 INTBIG x_pos;
3871 INTBIG lx, ly, hx, hy, swap, textwid, extx, deltax, level, strength;
3872 CHAR s2[60];
3873 double mainv, extv, deltav;
3874 REGISTER TRACE *tr;
3875
3876 /* erase all cursors */
3877 sim_window_setcolor(ALLOFF);
3878 sim_window_setmask(LAYERH);
3879 sim_window_drawbox(wavewin, sim_window_wavexsigstart, 0, WAVEXSIGEND, WAVEYCURSTOP, 0);
3880 sim_window_setcolor(HIGHLIT);
3881
3882 /* draw main cursor */
3883 x_pos = sim_window_timetoxpos(sim_window_maincursor);
3884 if (x_pos >= sim_window_wavexsigstart && x_pos <= WAVEXSIGEND)
3885 {
3886 sim_window_moveto(x_pos, WAVEYSIGBOT);
3887 sim_window_drawto(wavewin, x_pos, WAVEYCURSTOP, 0);
3888 }
3889
3890 /* draw extension cursor */
3891 x_pos = sim_window_timetoxpos(sim_window_extensioncursor);
3892 if (x_pos >= sim_window_wavexsigstart && x_pos <= WAVEXSIGEND)
3893 {
3894 sim_window_moveto(x_pos, WAVEYSIGBOT);
3895 sim_window_drawto(wavewin, x_pos, WAVEYCURSTOP, 0);
3896 sim_window_moveto(x_pos-5, WAVEYCURSTOP-12);
3897 sim_window_drawto(wavewin, x_pos+5, WAVEYCURSTOP-2, 0);
3898 sim_window_moveto(x_pos+5, WAVEYCURSTOP-12);
3899 sim_window_drawto(wavewin, x_pos-5, WAVEYCURSTOP-2, 0);
3900 }
3901
3902 /* draw cursor locations textually */
3903 sim_window_setmask(LAYERA & ~LAYERH);
3904 sim_window_setcolor(ALLOFF);
3905 lx = sim_window_wavexsigstart; ly = WAVEYTEXTBOT;
3906 hx = WAVEXSIGEND; hy = WAVEYTEXTTOP;
3907 sim_window_mapcoord(wavewin, &lx, &ly);
3908 sim_window_mapcoord(wavewin, &hx, &hy);
3909 if (lx > hx) { swap = lx; lx = hx; hx = swap; }
3910 if (ly > hy) { swap = ly; ly = hy; hy = swap; }
3911 screendrawbox(wavewin, lx, hx, ly+1, hy, &sim_window_desc);
3912
3913 sim_window_setcolor(MENTXT);
3914 sim_window_moveto(sim_window_wavexsigstart, WAVEYTEXTTOP);
3915 estrcpy(s2, _("Main: "));
3916 estrcat(s2, sim_windowconvertengineeringnotation(sim_window_maincursor));
3917 sim_window_drawulstring(wavewin, s2);
3918
3919 textwid = (WAVEXSIGEND - sim_window_wavexsigstart) / 3;
3920 extx = sim_window_wavexsigstart + textwid;
3921 deltax = WAVEXSIGEND - textwid;
3922 if (sim_window_highlightedtracecount == 1)
3923 {
3924 tr = sim_window_highlightedtraces[0];
3925 switch (tr->flags&TRACETYPE)
3926 {
3927 case TRACEISANALOG:
3928 mainv = sim_window_getanatracevalue((INTBIG)tr, sim_window_maincursor);
3929 sim_window_moveto(sim_window_wavexsigstart, 585);
3930 esnprintf(s2, 60, x_("Y=%g"), mainv);
3931 sim_window_drawulstring(wavewin, s2);
3932
3933 extv = sim_window_getanatracevalue((INTBIG)tr, sim_window_extensioncursor);
3934 sim_window_moveto(extx, 585);
3935 esnprintf(s2, 60, x_("Y=%g"), extv);
3936 sim_window_drawulstring(wavewin, s2);
3937
3938 deltav = fabs(mainv-extv);
3939 sim_window_moveto(deltax, 585);
3940 esnprintf(s2, 60, x_("dY=%g"), deltav);
3941 sim_window_drawulstring(wavewin, s2);
3942 break;
3943 case TRACEISDIGITAL:
3944 sim_window_getdigtracevalue((INTBIG)tr, sim_window_maincursor, &level, &strength);
3945 switch (level)
3946 {
3947 case LOGIC_LOW: estrcpy(s2, x_("=LOW")); break;
3948 case LOGIC_HIGH: estrcpy(s2, x_("=HIGH")); break;
3949 case LOGIC_X: estrcpy(s2, x_("=X")); break;
3950 case LOGIC_Z: estrcpy(s2, x_("=Z")); break;
3951 default: estrcpy(s2, x_("=?")); break;
3952 }
3953 sim_window_moveto(sim_window_wavexsigstart, 585);
3954 sim_window_drawulstring(wavewin, s2);
3955
3956 sim_window_getdigtracevalue((INTBIG)tr, sim_window_extensioncursor, &level, &strength);
3957 switch (level)
3958 {
3959 case LOGIC_LOW: estrcpy(s2, x_("=LOW")); break;
3960 case LOGIC_HIGH: estrcpy(s2, x_("=HIGH")); break;
3961 case LOGIC_X: estrcpy(s2, x_("=X")); break;
3962 case LOGIC_Z: estrcpy(s2, x_("=Z")); break;
3963 default: estrcpy(s2, x_("=?")); break;
3964 }
3965 sim_window_moveto(extx, 585);
3966 sim_window_drawulstring(wavewin, s2);
3967 break;
3968 case TRACEISBUS:
3969 case TRACEISOPENBUS:
3970 sim_window_moveto(sim_window_wavexsigstart, 585);
3971 esnprintf(s2, 60, x_("=%s"),
3972 sim_window_getbustracevalue((INTBIG)tr, sim_window_maincursor));
3973 sim_window_drawulstring(wavewin, s2);
3974
3975 sim_window_moveto(extx, 585);
3976 esnprintf(s2, 60, x_("=%s"),
3977 sim_window_getbustracevalue((INTBIG)tr, sim_window_extensioncursor));
3978 sim_window_drawulstring(wavewin, s2);
3979 break;
3980 }
3981 }
3982
3983 sim_window_moveto(extx, WAVEYTEXTTOP);
3984 estrcpy(s2, _("Ext: "));
3985 estrcat(s2, sim_windowconvertengineeringnotation(sim_window_extensioncursor));
3986 sim_window_drawulstring(wavewin, s2);
3987
3988 sim_window_moveto(deltax, WAVEYTEXTTOP);
3989 estrcpy(s2, _("Delta: "));
3990 deltav = sim_window_extensioncursor - sim_window_maincursor;
3991 if (deltav < 0.0) deltav = -deltav;
3992 estrcat(s2, sim_windowconvertengineeringnotation(deltav));
3993 sim_window_drawulstring(wavewin, s2);
3994 }
3995
sim_window_drawgraph(WINDOWPART * wavewin)3996 void sim_window_drawgraph(WINDOWPART *wavewin)
3997 {
3998 REGISTER INTBIG i, lx, ly;
3999 INTBIG x, y, wid, hei;
4000 UINTBIG descript[TEXTDESCRIPTSIZE];
4001 CHAR *msg;
4002
4003 /* determine height of text in the window */
4004 TDCLEAR(descript);
4005 TDSETSIZE(descript, TXTSETPOINTS(sim_window_textsize));
4006 screensettextinfo(wavewin, NOTECHNOLOGY, descript);
4007 screengettextsize(wavewin, x_("Xy"), &x, &y);
4008 sim_window_txthei = y * (wavewin->screenhy - wavewin->screenly) /
4009 (wavewin->usehy - wavewin->usely - 20);
4010
4011 /* draw vertical divider between signal names and signal waveforms */
4012 sim_window_setcolor(MENTXT);
4013 sim_window_moveto(sim_window_wavexbar, WAVEYTEXTBOT);
4014 sim_window_drawto(wavewin, sim_window_wavexbar, WAVEYTEXTTOP, 0);
4015
4016 /* plot it all */
4017 if (sim_window_firstrace == NOTRACE)
4018 {
4019 sim_window_setcolor(MENTXT);
4020 TDCLEAR(descript);
4021 TDSETSIZE(descript, TXTSETPOINTS(20));
4022 screensettextinfo(wavewin, NOTECHNOLOGY, descript);
4023 msg = _("Nothing plotted: type 'a' to add a signal");
4024 screengettextsize(wavewin, msg, &wid, &hei);
4025 lx = (wavewin->usehx + wavewin->uselx) / 2 - wid / 2;
4026 ly = (wavewin->usehy + wavewin->usely) / 2 - hei / 2;
4027 screendrawtext(wavewin, lx, ly, msg, &sim_window_desc);
4028 } else
4029 {
4030 /* draw the frames */
4031 for(i=0; i<sim_window_visframes; i++)
4032 sim_window_drawframe(i+sim_window_topframes, wavewin);
4033 for(i=0; i<sim_window_highlightedtracecount; i++)
4034 sim_window_highlightname(wavewin, sim_window_highlightedtraces[i], TRUE);
4035 }
4036 }
4037
4038 /*
4039 * Routine to draw frame "frame" in waveform window "wavewin".
4040 */
sim_window_drawframe(INTBIG frame,WINDOWPART * wavewin)4041 void sim_window_drawframe(INTBIG frame, WINDOWPART *wavewin)
4042 {
4043 INTBIG y_min, y_max, y_pos, maxoff, slot, i, temp_trace_spacing, i1, i2;
4044 BOOLEAN hasana, last, drawtext, grid=TRUE;
4045 UINTBIG descript[TEXTDESCRIPTSIZE];
4046 INTBIG x, y, px, py;
4047 float separation, topval, botval, val;
4048 CHAR *s2;
4049 REGISTER TRACE *tr, *onetr;
4050 int vgrid;
4051
4052 /* see how many traces are in this frame, determine whether it is analog */
4053 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
4054 hasana = FALSE;
4055 maxoff = 0;
4056 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4057 {
4058 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
4059 if (tr->frameno != frame) continue;
4060 tr->nameoff = -1;
4061 maxoff++;
4062 if ((tr->flags&TRACETYPE) == TRACEISANALOG) hasana = TRUE;
4063 onetr = tr;
4064 }
4065 if (maxoff == 1)
4066 {
4067 /* only one trace: center it */
4068 onetr->nameoff = (temp_trace_spacing - WAVEYSIGGAP - sim_window_txthei) / 2;
4069 if (onetr->nameoff < 0) onetr->nameoff = 0;
4070 } else
4071 {
4072 /* multiple traces: compute them */
4073 slot = 0;
4074 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4075 {
4076 if (tr->frameno != frame) continue;
4077 tr->nameoff = muldiv(slot, temp_trace_spacing - WAVEYSIGGAP - sim_window_txthei, maxoff-1);
4078 slot++;
4079 }
4080 }
4081
4082 if (wavewin->state & GRIDON) grid = TRUE;
4083 else grid = FALSE;
4084
4085 /* clear the waveform area */
4086 y_min = (sim_window_visframes - 1 - (frame - sim_window_topframes)) *
4087 temp_trace_spacing + WAVEYSIGBOT;
4088 y_max = y_min + temp_trace_spacing - WAVEYSIGGAP;
4089
4090 /* if there are analog traces on this line, show height values */
4091 if (hasana)
4092 {
4093 sim_window_setmask(LAYERA);
4094 sim_window_setcolor(MENTXT);
4095 sim_window_drawbox(wavewin, sim_window_wavexsigstart, y_min, WAVEXSIGEND, y_max, 0);
4096 topval = sim_window_get_anahigh(frame);
4097 botval = sim_window_get_analow(frame);
4098 vgrid = (y_max-y_min) / (2 * sim_window_txthei);
4099 if (vgrid < 1) vgrid = 1;
4100 if (vgrid > 4) vgrid = 4 + (vgrid-4)/3;
4101 separation = sim_window_sensible_value(&topval, &botval, &i1, &i2, vgrid);
4102 sim_window_set_topval(frame, topval);
4103 sim_window_set_botval(frame, botval);
4104 if (sim_window_vdd > 0.0)
4105 {
4106 /* draw voltage thresholds */
4107 sim_window_setcolor(ALLOFF);
4108 for(i=0; i < PERCENTSIZE; i++)
4109 {
4110 y = sim_window_valtoypos(frame, sim_window_percent[i] * sim_window_vdd);
4111 if (y < 0) continue;
4112 sim_window_moveto(sim_window_wavexsigstart, y);
4113 sim_window_drawto(wavewin, WAVEXSIGEND, y, 1);
4114 }
4115 }
4116 sim_window_setcolor(MENTXT);
4117 sim_window_draw_timeticks(wavewin, y_min, y_max, grid);
4118 val = topval;
4119 if (separation > 0.0)
4120 {
4121 for(i=0; ; i++)
4122 {
4123 if (val + 0.5f * separation < botval) break;
4124
4125 y_pos = roundfloat((val-botval) / (topval-botval) * (float)(y_max-y_min)) + y_min;
4126 sim_window_moveto(sim_window_wavexnameendana, y_pos);
4127 sim_window_drawto(wavewin, sim_window_wavexbar, y_pos, 0);
4128
4129 if (grid)
4130 {
4131 sim_window_moveto(sim_window_wavexsigstart, y_pos);
4132 sim_window_drawto(wavewin, WAVEXSIGEND, y_pos, 1);
4133 }
4134
4135 if (val - 0.5f*separation < botval) last = TRUE; else
4136 last = FALSE;
4137
4138 /* see if the text should be drawn */
4139 drawtext = FALSE;
4140 if (sim_window_txthei*2 < temp_trace_spacing)
4141 {
4142 if (sim_window_txthei*4 < temp_trace_spacing)
4143 {
4144 drawtext = TRUE;
4145 } else
4146 {
4147 if (i == 0 || last) drawtext = TRUE;
4148 }
4149 }
4150 if (drawtext)
4151 {
4152 s2 = sim_window_prettyprint(val, i1, i2);
4153
4154 TDCLEAR(descript);
4155 TDSETSIZE(descript, TXTSETPOINTS(sim_window_textsize));
4156 screensettextinfo(wavewin, NOTECHNOLOGY, descript);
4157 screengettextsize(wavewin, s2, &x, &y);
4158 px = sim_window_wavexnameendana; py = y_pos;
4159 sim_window_mapcoord(wavewin, &px, &py);
4160 if (!last)
4161 {
4162 if (i == 0) py -= y; else
4163 py -= y/2;
4164 }
4165 screendrawtext(wavewin, px-x, py, s2, &sim_window_desc);
4166 }
4167 val -= separation;
4168 }
4169 }
4170 } else
4171 {
4172 sim_window_setmask(LAYERA);
4173 sim_window_setcolor(0);
4174 sim_window_drawbox(wavewin, sim_window_wavexsigstart, y_min, WAVEXSIGEND, y_max, 2);
4175 sim_window_set_topval(frame, 0.0);
4176 sim_window_set_botval(frame, 0.0);
4177 }
4178
4179 /* draw the highlighted traces in this frame */
4180 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4181 {
4182 if (tr->frameno != frame) continue;
4183 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
4184 if ((tr->flags&TRACESELECTED) == 0) continue;
4185 (void)sim_window_plottrace(tr, wavewin, 0, 0, 0);
4186 }
4187
4188 /* draw the unhighlighted traces in this frame */
4189 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4190 {
4191 if (tr->frameno != frame) continue;
4192 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
4193 if ((tr->flags&TRACESELECTED) != 0) continue;
4194 (void)sim_window_plottrace(tr, wavewin, 0, 0, 0);
4195 }
4196 }
4197
4198 /*
4199 * Routine to draw a trace "tr" in waveform window "wavewin". "style" is:
4200 * 0 draw normal trace
4201 * 1 search for point (x,y) on trace, return TRUE if found
4202 * 2 draw trace in highlight
4203 */
sim_window_plottrace(TRACE * tr,WINDOWPART * wavewin,INTBIG style,INTBIG x,INTBIG y)4204 BOOLEAN sim_window_plottrace(TRACE *tr, WINDOWPART *wavewin, INTBIG style, INTBIG x, INTBIG y)
4205 {
4206 INTBIG x_min, x_max, y_min, y_max, y_ctr, j, state, laststate, first,
4207 slot, temp_trace_spacing, fx, fy, tx, ty, color, strength,
4208 cfx, cfy, ctx, cty, sigcount, flags;
4209 CHAR s2[50];
4210 REGISTER BOOLEAN hitpoint, firstinbus, thick;
4211 REGISTER TRACE *bustr;
4212 double time, position, nexttime;
4213
4214 /* get coordinates */
4215 if (sim_window_visframes == 0) return(FALSE);
4216 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
4217 slot = tr->frameno - sim_window_topframes;
4218 if (slot < 0 || slot >= sim_window_visframes) return(FALSE);
4219 y_min = (sim_window_visframes - 1 - slot) * temp_trace_spacing + WAVEYSIGBOT;
4220 y_max = y_min + temp_trace_spacing - WAVEYSIGGAP;
4221
4222 if ((tr->flags&TRACESELECTED) != 0) thick = TRUE; else
4223 thick = FALSE;
4224
4225 /* handle name field on the left */
4226 if (style == 0)
4227 {
4228 /* draw normal trace name */
4229 sim_window_writetracename(wavewin, tr);
4230 }
4231 hitpoint = FALSE;
4232
4233 /* handle busses */
4234 flags = tr->flags & TRACETYPE;
4235 if (flags == TRACEISBUS || flags == TRACEISOPENBUS)
4236 {
4237 /* enumerate signals on the bus and make sure the global array has room */
4238 sigcount = sim_window_ensurespace(tr);
4239
4240 /* find starting time */
4241 firstinbus = TRUE;
4242 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4243 {
4244 if (bustr->buschannel != tr) continue;
4245
4246 /* LINTED "time" used in proper order */
4247 if (firstinbus || bustr->timearray[0] < time)
4248 time = bustr->timearray[0];
4249 firstinbus = FALSE;
4250 }
4251
4252 /* draw the waveform */
4253 x_min = sim_window_wavexsigstart;
4254 for(;;)
4255 {
4256 /* compute signal value at time "time" */
4257 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4258 {
4259 if (bustr->buschannel != tr) continue;
4260 for(j=0; j<bustr->numsteps; j++)
4261 if (time < bustr->timearray[j]) break;
4262 if (j > 0) j--;
4263 sim_window_sigvalues[bustr->busindex] = bustr->statearray[j] >> 8;
4264 }
4265
4266 /* compute the value string */
4267 estrcpy(s2, sim_window_makewidevalue(sigcount, sim_window_sigvalues));
4268
4269 /* draw the value */
4270 x_max = sim_window_timetoxpos(time);
4271 if (x_max < sim_window_wavexsigstart) x_max = sim_window_wavexsigstart;
4272 if (x_max > WAVEXSIGEND) break;
4273 if (x_max > x_min)
4274 {
4275 if (style == 0)
4276 {
4277 sim_window_setcolor(sim_colorstrengthpower);
4278 sim_window_moveto(x_max+BUSANGLE/2, (y_min+y_max)/2);
4279 sim_window_drawhcstring(wavewin, s2);
4280 }
4281 hitpoint |= sim_window_lineseg(wavewin, x_min, (y_min+y_max)/2, x_min+BUSANGLE, y_min,
4282 style, x, y, thick);
4283 hitpoint |= sim_window_lineseg(wavewin, x_min+BUSANGLE, y_min, x_max-BUSANGLE, y_min,
4284 style, x, y, thick);
4285 hitpoint |= sim_window_lineseg(wavewin, x_max-BUSANGLE, y_min, x_max, (y_min+y_max)/2,
4286 style, x, y, thick);
4287 hitpoint |= sim_window_lineseg(wavewin, x_max, (y_min+y_max)/2, x_max-BUSANGLE, y_max,
4288 style, x, y, thick);
4289 hitpoint |= sim_window_lineseg(wavewin, x_max-BUSANGLE, y_max, x_min+BUSANGLE, y_max,
4290 style, x, y, thick);
4291 hitpoint |= sim_window_lineseg(wavewin, x_min+BUSANGLE, y_max, x_min, (y_min+y_max)/2,
4292 style, x, y, thick);
4293 x_min = x_max;
4294 }
4295
4296 /* advance to the next time */
4297 nexttime = time;
4298 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4299 {
4300 if (bustr->buschannel != tr) continue;
4301 for(j=0; j<bustr->numsteps; j++)
4302 if (bustr->timearray[j] > time) break;
4303 if (j < bustr->numsteps)
4304 {
4305 if (nexttime == time || bustr->timearray[j] < nexttime)
4306 nexttime = bustr->timearray[j];
4307 }
4308 }
4309 if (nexttime == time) break;
4310 time = nexttime;
4311 }
4312 if (x_min < WAVEXSIGEND)
4313 {
4314 x_max = WAVEXSIGEND;
4315 sim_window_setcolor(sim_colorstrengthpower);
4316 hitpoint |= sim_window_lineseg(wavewin, x_min, (y_min+y_max)/2, x_min+BUSANGLE, y_min,
4317 style, x, y, thick);
4318 hitpoint |= sim_window_lineseg(wavewin, x_min+BUSANGLE, y_min, x_max-BUSANGLE, y_min,
4319 style, x, y, thick);
4320 hitpoint |= sim_window_lineseg(wavewin, x_max-BUSANGLE, y_min, x_max, (y_min+y_max)/2,
4321 style, x, y, thick);
4322 hitpoint |= sim_window_lineseg(wavewin, x_max, (y_min+y_max)/2, x_max-BUSANGLE, y_max,
4323 style, x, y, thick);
4324 hitpoint |= sim_window_lineseg(wavewin, x_max-BUSANGLE, y_max, x_min+BUSANGLE, y_max,
4325 style, x, y, thick);
4326 hitpoint |= sim_window_lineseg(wavewin, x_min+BUSANGLE, y_max, x_min, (y_min+y_max)/2,
4327 style, x, y, thick);
4328 }
4329 return(hitpoint);
4330 }
4331
4332 /* handle digital waveform */
4333 if (flags == TRACEISDIGITAL)
4334 {
4335 first = 1;
4336 for(j=0; j<tr->numsteps; j++)
4337 {
4338 time = tr->timearray[j];
4339 if (j == tr->numsteps-1) x_max = WAVEXSIGEND; else
4340 {
4341 x_max = sim_window_timetoxpos(tr->timearray[j+1]);
4342 if (x_max < sim_window_wavexsigstart) continue;
4343 if (x_max > WAVEXSIGEND) x_max = WAVEXSIGEND;
4344 }
4345 x_min = sim_window_timetoxpos(time);
4346 if (x_min < sim_window_wavexsigstart) x_min = sim_window_wavexsigstart;
4347 if (x_min > WAVEXSIGEND) continue;
4348
4349 state = tr->statearray[j] >> 8;
4350 strength = tr->statearray[j] & 0377;
4351 if (strength == 0) color = sim_colorstrengthoff; else
4352 if (strength <= NODE_STRENGTH) color = sim_colorstrengthnode; else
4353 if (strength <= GATE_STRENGTH) color = sim_colorstrengthgate; else
4354 color = sim_colorstrengthpower;
4355 sim_window_setcolor(color);
4356
4357 /* LINTED "laststate" used in proper order */
4358 if (first == 0 && state != laststate)
4359 {
4360 hitpoint |= sim_window_lineseg(wavewin, x_min, y_min, x_min, y_max,
4361 style, x, y, thick);
4362 }
4363 first = 0;
4364 switch (state)
4365 {
4366 case LOGIC_LOW:
4367 hitpoint |= sim_window_lineseg(wavewin, x_min, y_min, x_max, y_min,
4368 style, x, y, thick);
4369 break;
4370 case LOGIC_X:
4371 if (style == 1)
4372 {
4373 if (x >= x_min && x <= x_max && y >= y_min && y <= y_max)
4374 hitpoint = TRUE;
4375 } else
4376 {
4377 sim_window_drawbox(wavewin, x_min, y_min, x_max, y_max, 1);
4378 }
4379 break;
4380 case LOGIC_HIGH:
4381 hitpoint |= sim_window_lineseg(wavewin, x_min, y_max, x_max, y_max,
4382 style, x, y, thick);
4383 break;
4384 case LOGIC_Z:
4385 y_ctr = (y_min+y_max)/2;
4386 hitpoint |= sim_window_lineseg(wavewin, x_min, y_ctr, x_max, y_ctr,
4387 style, x, y, thick);
4388 break;
4389 default:
4390 if (style == 1)
4391 {
4392 if (x >= x_min && x <= x_max && y >= y_min && y <= y_max)
4393 hitpoint = TRUE;
4394 } else
4395 {
4396 sim_window_drawbox(wavewin, x_min, y_min, x_max, y_max, 0);
4397 if ((x_max - x_min) <= 1) break;
4398 sim_window_setcolor(ALLOFF);
4399 sim_window_drawbox(wavewin, x_min+1, y_min+1, x_max-1, y_max-1, 0);
4400 (void)esnprintf(s2, 50, x_("0x%lX"), state);
4401 sim_window_moveto((x_min + x_max) / 2, y_min+3);
4402 sim_window_setcolor(color);
4403 sim_window_drawcstring(wavewin, s2);
4404 }
4405 break;
4406 }
4407 laststate = state;
4408 }
4409 return(hitpoint);
4410 }
4411
4412 /* handle analog waveform */
4413 first = 1;
4414 for(j=0; j<tr->numsteps; j++)
4415 {
4416 time = tr->timearray[j];
4417 tx = sim_window_timetoxpos(time);
4418 position = (double)(y_max - y_min);
4419 position *= (tr->valuearray[j] - sim_window_get_botval(tr->frameno)) / sim_window_get_extanarange(tr->frameno);
4420 ty = (INTBIG)position + y_min;
4421 if (j != 0 && tx >= sim_window_wavexsigstart)
4422 {
4423 if (tx > WAVEXSIGEND)
4424 {
4425 /* "to" data point off the screen: interpolate */
4426 /* LINTED "fx" and "fy" used in proper order */
4427 ty = (ty-fy) * (WAVEXSIGEND-fx) / (tx-fx) + fy;
4428 tx = WAVEXSIGEND;
4429 }
4430
4431 if (first != 0 && fx < sim_window_wavexsigstart)
4432 {
4433 /* "from" data point off the screen: interpolate */
4434 fy = (ty-fy) * (sim_window_wavexsigstart-fx) / (tx-fx) + fy;
4435 fx = sim_window_wavexsigstart;
4436 }
4437 first = 0;
4438 if (style != 2) sim_window_setcolor(tr->color);
4439 if (fy >= y_min && fy <= y_max &&
4440 ty >= y_min && ty <= y_max)
4441 {
4442 hitpoint |= sim_window_lineseg(wavewin, fx, fy, tx, ty, style, x, y, thick);
4443 } else
4444 {
4445 cfx = fx; cfy = fy;
4446 ctx = tx; cty = ty;
4447 if (!clipline(&cfx, &cfy, &ctx, &cty, sim_window_wavexsigstart, WAVEXSIGEND,
4448 y_min, y_max))
4449 {
4450 hitpoint |= sim_window_lineseg(wavewin, cfx, cfy, ctx, cty, style, x, y, thick);
4451 }
4452 }
4453 }
4454 fx = tx; fy = ty;
4455 if (fx >= WAVEXSIGEND) break;
4456 }
4457 return(hitpoint);
4458 }
4459
sim_window_ensurespace(TRACE * tr)4460 INTBIG sim_window_ensurespace(TRACE *tr)
4461 {
4462 REGISTER INTBIG sigcount, newtotal;
4463 REGISTER TRACE *bustr;
4464
4465 sigcount = 0;
4466 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4467 {
4468 if (bustr->buschannel == tr)
4469 bustr->busindex = sigcount++;
4470 }
4471
4472 /* make sure there is room for all of the signal values */
4473 if (sigcount > sim_window_sigtotal)
4474 {
4475 newtotal = sim_window_sigtotal * 2;
4476 if (newtotal == 0) newtotal = 8;
4477 if (newtotal < sigcount) newtotal = sigcount;
4478 if (sim_window_sigtotal > 0) efree((CHAR *)sim_window_sigvalues);
4479 sim_window_sigtotal = 0;
4480 sim_window_sigvalues = (INTBIG *)emalloc(newtotal * SIZEOFINTBIG, sim_tool->cluster);
4481 if (sim_window_sigvalues == 0) return(0);
4482 sim_window_sigtotal = newtotal;
4483 }
4484 return(sigcount);
4485 }
4486
4487 /*
4488 * Routine to draw from (xf,yf) to (xt,yt) in window "wavewin". If "style" is zero, draw it.
4489 * If "style" is 1, do not draw, but return TRUE if (x,y) is on the line.
4490 */
sim_window_lineseg(WINDOWPART * wavewin,INTBIG xf,INTBIG yf,INTBIG xt,INTBIG yt,INTBIG style,INTBIG x,INTBIG y,BOOLEAN thick)4491 BOOLEAN sim_window_lineseg(WINDOWPART *wavewin, INTBIG xf, INTBIG yf, INTBIG xt, INTBIG yt,
4492 INTBIG style, INTBIG x, INTBIG y, BOOLEAN thick)
4493 {
4494 REGISTER INTBIG dist, drawstyle;
4495
4496 if (style != 1)
4497 {
4498 sim_window_moveto(xf, yf);
4499 if (thick) drawstyle = 3; else
4500 drawstyle = 0;
4501 sim_window_drawto(wavewin, xt, yt, drawstyle);
4502 return(FALSE);
4503 }
4504 dist = disttoline(xf, yf, xt, yt, x, y);
4505 if (dist < 5) return(TRUE);
4506 return(FALSE);
4507 }
4508
4509 /*
4510 * Routine to find cross of a trace "tr" with horizontal line "val" nearest to "time".
4511 * Return TRUE if crass was found
4512 */
sim_window_findcross(TRACE * tr,double val,double * time)4513 BOOLEAN sim_window_findcross(TRACE *tr, double val, double *time)
4514 {
4515 INTBIG j;
4516 double btime, ctime;
4517 BOOLEAN bfound;
4518
4519 /* handle analog waveform */
4520 bfound = FALSE;
4521 btime = 0;
4522 for(j=1; j<tr->numsteps; j++)
4523 {
4524 if ((tr->valuearray[j-1] > val && tr->valuearray[j] > val) ||
4525 (tr->valuearray[j-1] < val && tr->valuearray[j] < val)) continue;
4526 if (tr->valuearray[j-1] == val && tr->valuearray[j] == val)
4527 {
4528 if (*time < tr->timearray[j-1]) ctime = tr->timearray[j-1];
4529 else if (tr->timearray[j] < *time) ctime = tr->timearray[j];
4530 else ctime = *time;
4531 } else
4532 {
4533 ctime = (val - tr->valuearray[j-1]) / (tr->valuearray[j] - tr->valuearray[j-1]) *
4534 (tr->timearray[j] - tr->timearray[j-1]) + tr->timearray[j-1];
4535 }
4536 if (!bfound || fabs(ctime - *time) < fabs(btime - *time))
4537 {
4538 bfound = TRUE;
4539 btime = ctime;
4540 }
4541 }
4542 if (bfound)
4543 *time = btime;
4544 return(bfound);
4545 }
4546
4547 /*
4548 * routine to snapshot the simulation window in a cell with artwork primitives
4549 */
sim_window_savegraph(void)4550 void sim_window_savegraph(void)
4551 {
4552 REGISTER INTBIG x_min, x_max, y_min, y_max, j, maxoff, state, laststate, color, first,
4553 slot, temp_trace_spacing, range, lastcolor, fx, fy, tx, ty, strength,
4554 sigcount, cx, cy, *data, maxsteps, len;
4555 UINTBIG descript[TEXTDESCRIPTSIZE];
4556 REGISTER BOOLEAN hasana, firstinbus;
4557 INTBIG x, y, busdescr[12], tx1, ty1, tx2, ty2, datapos, cfx, cfy, ctx, cty;
4558 CHAR s2[15], *pt, *newname;
4559 REGISTER NODEPROTO *np, *plotnp;
4560 REGISTER NODEINST *ni;
4561 REGISTER VARIABLE *var;
4562 REGISTER WINDOWPART *wavewin;
4563 REGISTER TRACE *tr, *otr, *bustr;
4564 double time, position, separation, nexttime;
4565 REGISTER void *infstr;
4566
4567 /* get cell being saved */
4568 np = getcurcell();
4569 if (np == NONODEPROTO) return;
4570
4571 /* get waveform window */
4572 wavewin = sim_window_findwaveform();
4573 if (wavewin == NOWINDOWPART) return;
4574
4575 /* determine height of text in the window */
4576 TDCLEAR(descript);
4577 TDSETSIZE(descript, TXTSETPOINTS(sim_window_textsize));
4578 screensettextinfo(wavewin, NOTECHNOLOGY, descript);
4579 screengettextsize(wavewin, x_("Xy"), &x, &y);
4580 sim_window_txthei = y * (wavewin->screenhy - wavewin->screenly) /
4581 (wavewin->usehy - wavewin->usely - 20);
4582
4583 /* create the plot cell */
4584 infstr = initinfstr();
4585 addstringtoinfstr(infstr, np->protoname);
4586 addstringtoinfstr(infstr, x_("{sim}"));
4587 plotnp = newnodeproto(returninfstr(infstr), el_curlib);
4588 if (plotnp == NONODEPROTO) return;
4589 setactivity(x_("Make Simulation Plot"));
4590
4591 /* determine maximum number of steps */
4592 maxsteps = 1;
4593 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4594 {
4595 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
4596 if (tr->numsteps > maxsteps) maxsteps = tr->numsteps;
4597 }
4598
4599 /* make space */
4600 data = (INTBIG *)emalloc(maxsteps * 4 * SIZEOFINTBIG, el_tempcluster);
4601 if (data == 0) return;
4602
4603 /* compute transformation for points in the plot area */
4604 tx1 = sim_window_wavexsigstart; ty1 = WAVEYSIGBOT; sim_window_mapcoord(wavewin, &tx1, &ty1);
4605 tx2 = WAVEXSIGEND; ty2 = WAVEYCURSTOP; sim_window_mapcoord(wavewin, &tx2, &ty2);
4606 sim_window_offx = (tx2 - tx1) / 2; sim_window_basex = tx1;
4607 sim_window_offy = (ty2 - ty1) / 2; sim_window_basey = ty1;
4608
4609 /* write the header */
4610 tx1 = 383; ty1 = WAVEYTEXTTOP; sim_window_mapcoord(wavewin, &tx1, &ty1);
4611 ni = newnodeinst(gen_invispinprim, tx1, tx1, ty1, ty1, 0, 0, plotnp);
4612 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4613 infstr = initinfstr();
4614 addstringtoinfstr(infstr, x_("Simulation snapshot of cell "));
4615 addstringtoinfstr(infstr, describenodeproto(np));
4616 allocstring(&newname, returninfstr(infstr), el_tempcluster);
4617 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)newname, VSTRING|VDISPLAY);
4618 efree(newname);
4619 if (var != NOVARIABLE)
4620 {
4621 TDSETSIZE(var->textdescript, TXTSETPOINTS(14));
4622 TDSETPOS(var->textdescript, VTPOSUP);
4623 }
4624 endobjectchange((INTBIG)ni, VNODEINST);
4625
4626 /* set name offsets */
4627 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace) tr->nameoff = -1;
4628 temp_trace_spacing = WAVEYSIGRANGE / sim_window_visframes;
4629 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4630 {
4631 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
4632 slot = tr->frameno - sim_window_topframes;
4633 if (slot < 0 || slot >= sim_window_visframes) continue;
4634
4635 /* determine position of trace label on the line */
4636 if (tr->nameoff < 0)
4637 {
4638 hasana = FALSE;
4639 maxoff = 0;
4640 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
4641 {
4642 if ((otr->flags&TRACENOTDRAWN) != 0) continue;
4643 if (otr->frameno != tr->frameno) continue;
4644 maxoff++;
4645 if ((otr->flags&TRACETYPE) == TRACEISANALOG) hasana = TRUE;
4646 }
4647 if (maxoff == 1)
4648 {
4649 /* only one trace: center it */
4650 tr->nameoff = (temp_trace_spacing - WAVEYSIGGAP - sim_window_txthei) / 2;
4651 if (tr->nameoff < 0) tr->nameoff = 0;
4652 } else
4653 {
4654 /* multiple traces: compute them */
4655 range = (temp_trace_spacing - WAVEYSIGGAP - sim_window_txthei*3) / (maxoff-1);
4656 if (range <= 0) range = 1;
4657 slot = 0;
4658 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
4659 {
4660 if ((otr->flags&TRACENOTDRAWN) != 0) continue;
4661 if (otr->frameno != tr->frameno) continue;
4662 otr->nameoff = slot * range + sim_window_txthei;
4663 slot++;
4664 }
4665 }
4666
4667 /* if there are analog traces on this line, show height values */
4668 if (hasana)
4669 {
4670 y_min = (sim_window_visframes - 1 - (tr->frameno - sim_window_topframes)) *
4671 temp_trace_spacing + WAVEYSIGBOT;
4672 y_max = y_min + temp_trace_spacing - WAVEYSIGGAP;
4673
4674 tx1 = sim_window_wavexnameendana; ty1 = y_min; sim_window_mapcoord(wavewin, &tx1, &ty1);
4675 tx2 = sim_window_wavexbar; ty2 = y_min; sim_window_mapcoord(wavewin, &tx2, &ty2);
4676 data[0] = -(tx2-tx1)/2; data[1] = 0;
4677 data[2] = (tx2-tx1)/2; data[3] = 0;
4678 ni = newnodeinst(art_openedpolygonprim, tx1,tx2, ty1,ty2, 0, 0, plotnp);
4679 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4680 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
4681 VINTEGER|VISARRAY|(4<<VLENGTHSH));
4682 endobjectchange((INTBIG)ni, VNODEINST);
4683
4684 (void)esnprintf(s2, 15, x_("%g"), sim_window_get_analow(tr->frameno));
4685 tx1 = sim_window_wavexnameend; ty1 = y_min; sim_window_mapcoord(wavewin, &tx1, &ty1);
4686 ni = newnodeinst(gen_invispinprim, tx1, tx1, ty1, ty1, 0, 0, plotnp);
4687 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4688 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)s2, VSTRING|VDISPLAY);
4689 if (var != NOVARIABLE)
4690 {
4691 TDSETSIZE(var->textdescript, TXTSETPOINTS(10));
4692 TDSETPOS(var->textdescript, VTPOSUPLEFT);
4693 }
4694 endobjectchange((INTBIG)ni, VNODEINST);
4695
4696 tx1 = sim_window_wavexnameendana; ty1 = y_max; sim_window_mapcoord(wavewin, &tx1, &ty1);
4697 tx2 = sim_window_wavexbar; ty2 = y_max; sim_window_mapcoord(wavewin, &tx2, &ty2);
4698 data[0] = -(tx2-tx1)/2; data[1] = 0;
4699 data[2] = (tx2-tx1)/2; data[3] = 0;
4700 ni = newnodeinst(art_openedpolygonprim, tx1,tx2, ty1,ty2, 0, 0, plotnp);
4701 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4702 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
4703 VINTEGER|VISARRAY|(4<<VLENGTHSH));
4704 endobjectchange((INTBIG)ni, VNODEINST);
4705
4706 (void)esnprintf(s2, 15, x_("%g"), sim_window_get_anahigh(tr->frameno));
4707 tx1 = sim_window_wavexnameend; ty1 = y_max; sim_window_mapcoord(wavewin, &tx1, &ty1);
4708 ni = newnodeinst(gen_invispinprim, tx1, tx1, ty1, ty1, 0, 0, plotnp);
4709 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4710 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)s2, VSTRING|VDISPLAY);
4711 if (var != NOVARIABLE)
4712 {
4713 TDSETSIZE(var->textdescript, TXTSETPOINTS(10));
4714 TDSETPOS(var->textdescript, VTPOSDOWNLEFT);
4715 }
4716 endobjectchange((INTBIG)ni, VNODEINST);
4717 }
4718 }
4719 }
4720
4721 /* plot time values */
4722 tr = sim_window_firstrace;
4723 if (tr != NOTRACE)
4724 {
4725 separation = sim_window_sensibletimevalue((tr->maxtime - tr->mintime) / 5.0);
4726 time = sim_window_sensibletimevalue(tr->maxtime);
4727 while (time + separation <tr->maxtime)
4728 time += separation;
4729 for(;;)
4730 {
4731 if (time < tr->mintime) break;
4732 x = sim_window_timetoxpos(time);
4733 tx1 = x; ty1 = 0; sim_window_mapcoord(wavewin, &tx1, &ty1);
4734 ni = newnodeinst(gen_invispinprim, tx1, tx1, ty1, ty1, 0, 0, plotnp);
4735 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4736 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey,
4737 (INTBIG)sim_windowconvertengineeringnotation(time), VSTRING|VDISPLAY);
4738 if (var != NOVARIABLE)
4739 {
4740 TDSETSIZE(var->textdescript, TXTSETPOINTS(10));
4741 TDSETPOS(var->textdescript, VTPOSUP);
4742 }
4743 endobjectchange((INTBIG)ni, VNODEINST);
4744 time -= separation;
4745 }
4746 }
4747
4748 /* plot it all */
4749 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
4750 {
4751 if ((tr->flags&TRACENOTDRAWN) != 0) continue;
4752 if (stopping(STOPREASONDISPLAY)) break;
4753
4754 /* compute positions */
4755 slot = tr->frameno - sim_window_topframes;
4756 if (slot < 0 || slot >= sim_window_visframes) continue;
4757 y_min = (sim_window_visframes - 1 - slot) * temp_trace_spacing + WAVEYSIGBOT;
4758 y_max = y_min + temp_trace_spacing - WAVEYSIGGAP;
4759
4760 /* draw the vertical line between the label and the trace */
4761 tx1 = sim_window_wavexbar; ty1 = y_min; sim_window_mapcoord(wavewin, &tx1, &ty1);
4762 tx2 = sim_window_wavexbar; ty2 = y_min+temp_trace_spacing-WAVEYSIGGAP; sim_window_mapcoord(wavewin, &tx2, &ty2);
4763 data[0] = 0; data[1] = -(ty2-ty1)/2;
4764 data[2] = 0; data[3] = (ty2-ty1)/2;
4765 ni = newnodeinst(art_openedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4766 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4767 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
4768 VINTEGER|VISARRAY|(4<<VLENGTHSH));
4769 endobjectchange((INTBIG)ni, VNODEINST);
4770
4771 /* write the text */
4772 (void)esnprintf(s2, 15, x_("%g"), sim_window_get_anahigh(tr->frameno));
4773 tx1 = 1; ty1 = (y_min + y_max)/2; sim_window_mapcoord(wavewin, &tx1, &ty1);
4774 ni = newnodeinst(gen_invispinprim, tx1, tx1, ty1, ty1, 0, 0, plotnp);
4775 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4776 pt = tr->name;
4777 if (sim_window_traceprefix != 0)
4778 {
4779 len = estrlen(sim_window_traceprefix);
4780 if (namesamen(pt, sim_window_traceprefix, len) == 0)
4781 pt += len;
4782 }
4783 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)pt, VSTRING|VDISPLAY);
4784 if (var != NOVARIABLE)
4785 {
4786 TDSETSIZE(var->textdescript, TXTSETPOINTS(10));
4787 TDSETPOS(var->textdescript, VTPOSRIGHT);
4788 }
4789 endobjectchange((INTBIG)ni, VNODEINST);
4790 if ((tr->flags&TRACETYPE) == TRACEISANALOG)
4791 {
4792 tx1 = 0; ty1 = y_min + tr->nameoff;
4793 sim_window_mapcoord(wavewin, &tx1, &ty1);
4794 tx2 = sim_window_wavexnameendana; ty2 = y_min + tr->nameoff;
4795 sim_window_mapcoord(wavewin, &tx2, &ty2);
4796 data[0] = -(tx2-tx1)/2; data[1] = 0;
4797 data[2] = (tx2-tx1)/2; data[3] = 0;
4798 ni = newnodeinst(art_openedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4799 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4800 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
4801 VINTEGER|VISARRAY|(4<<VLENGTHSH));
4802 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, tr->color, VINTEGER);
4803 endobjectchange((INTBIG)ni, VNODEINST);
4804 }
4805
4806 /* write busses */
4807 if ((tr->flags&TRACETYPE) == TRACEISBUS ||
4808 (tr->flags&TRACETYPE) == TRACEISOPENBUS)
4809 {
4810 /* enumerate signals on the bus and make sure the global array has room */
4811 sigcount = sim_window_ensurespace(tr);
4812
4813 /* find starting time */
4814 firstinbus = TRUE;
4815 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4816 {
4817 if (bustr->buschannel != tr) continue;
4818
4819 /* LINTED "time" used in proper order */
4820 if (firstinbus || bustr->timearray[0] < time)
4821 time = bustr->timearray[0];
4822 firstinbus = FALSE;
4823 }
4824
4825 /* draw the waveform */
4826 x_min = sim_window_wavexsigstart;
4827 for(;;)
4828 {
4829 /* compute signal value at time "time" */
4830 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4831 {
4832 if (bustr->buschannel != tr) continue;
4833 for(j=0; j<bustr->numsteps; j++)
4834 if (time < bustr->timearray[j]) break;
4835 if (j > 0) j--;
4836 sim_window_sigvalues[bustr->busindex] = bustr->statearray[j] >> 8;
4837 }
4838
4839 /* draw the value */
4840 x_max = sim_window_timetoxpos(time);
4841 if (x_max < sim_window_wavexsigstart) x_max = sim_window_wavexsigstart;
4842 if (x_max > WAVEXSIGEND) break;
4843 if (x_max > x_min)
4844 {
4845 tx1 = x_min; ty1 = y_min; sim_window_mapcoord(wavewin, &tx1, &ty1);
4846 tx2 = x_max; ty2 = y_max; sim_window_mapcoord(wavewin, &tx2, &ty2);
4847 cx = (tx1 + tx2) / 2; cy = (ty1 + ty2) / 2;
4848 ni = newnodeinst(art_closedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4849 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4850 busdescr[0] = x_min; busdescr[1] = (y_min+y_max)/2;
4851 busdescr[2] = x_min+BUSANGLE; busdescr[3] = y_min;
4852 busdescr[4] = x_max-BUSANGLE; busdescr[5] = y_min;
4853 busdescr[6] = x_max; busdescr[7] = (y_min+y_max)/2;
4854 busdescr[8] = x_max-BUSANGLE; busdescr[9] = y_max;
4855 busdescr[10] = x_min+BUSANGLE; busdescr[11] = y_max;
4856 for(j=0; j<12; j += 2)
4857 {
4858 sim_window_mapcoord(wavewin, &busdescr[j], &busdescr[j+1]);
4859 busdescr[j] -= cx;
4860 busdescr[j+1] -= cy;
4861 }
4862 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)busdescr,
4863 VINTEGER|VISARRAY|(12<<VLENGTHSH));
4864 endobjectchange((INTBIG)ni, VNODEINST);
4865
4866 /* draw the value string */
4867 estrcpy(s2, sim_window_makewidevalue(sigcount, sim_window_sigvalues));
4868 tx1 = x_max+BUSANGLE/2; ty1 = (y_min+y_max)/2; sim_window_mapcoord(wavewin, &tx1, &ty1);
4869 ni = newnodeinst(gen_invispinprim, tx1, tx1, ty1, ty1, 0, 0, plotnp);
4870 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4871 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)s2, VSTRING|VDISPLAY);
4872 if (var != NOVARIABLE)
4873 {
4874 TDSETSIZE(var->textdescript, TXTSETPOINTS(10));
4875 TDSETPOS(var->textdescript, VTPOSRIGHT);
4876 }
4877 endobjectchange((INTBIG)ni, VNODEINST);
4878 x_min = x_max;
4879 }
4880
4881 /* advance to the next time */
4882 nexttime = time;
4883 for(bustr = sim_window_firstrace; bustr != NOTRACE; bustr = bustr->nexttrace)
4884 {
4885 if (bustr->buschannel != tr) continue;
4886 for(j=0; j<bustr->numsteps; j++)
4887 if (bustr->timearray[j] > time) break;
4888 if (j < bustr->numsteps)
4889 {
4890 if (nexttime == time || bustr->timearray[j] < nexttime)
4891 nexttime = bustr->timearray[j];
4892 }
4893 }
4894 if (nexttime == time) break;
4895 time = nexttime;
4896 }
4897 if (x_min < WAVEXSIGEND)
4898 {
4899 x_max = WAVEXSIGEND;
4900 tx1 = x_min; ty1 = y_min; sim_window_mapcoord(wavewin, &tx1, &ty1);
4901 tx2 = x_max; ty2 = y_max; sim_window_mapcoord(wavewin, &tx2, &ty2);
4902 cx = (tx1 + tx2) / 2; cy = (ty1 + ty2) / 2;
4903 ni = newnodeinst(art_closedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4904 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4905 busdescr[0] = x_min; busdescr[1] = (y_min+y_max)/2;
4906 busdescr[2] = x_min+BUSANGLE; busdescr[3] = y_min;
4907 busdescr[4] = x_max-BUSANGLE; busdescr[5] = y_min;
4908 busdescr[6] = x_max; busdescr[7] = (y_min+y_max)/2;
4909 busdescr[8] = x_max-BUSANGLE; busdescr[9] = y_max;
4910 busdescr[10] = x_min+BUSANGLE; busdescr[11] = y_max;
4911 for(j=0; j<12; j += 2)
4912 {
4913 sim_window_mapcoord(wavewin, &busdescr[j], &busdescr[j+1]);
4914 busdescr[j] -= cx;
4915 busdescr[j+1] -= cy;
4916 }
4917 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)busdescr,
4918 VINTEGER|VISARRAY|(12<<VLENGTHSH));
4919 endobjectchange((INTBIG)ni, VNODEINST);
4920 }
4921 continue;
4922 }
4923
4924 first = 1;
4925 datapos = 0;
4926 lastcolor = ALLOFF;
4927 fx = fy = 0;
4928 laststate = -1;
4929 for(j=0; j<tr->numsteps; j++)
4930 {
4931 time = tr->timearray[j];
4932 if ((tr->flags&TRACETYPE) == TRACEISDIGITAL)
4933 {
4934 /* digital waveform */
4935 if (j == tr->numsteps-1) x_max = WAVEXSIGEND; else
4936 {
4937 x_max = sim_window_timetoxpos(tr->timearray[j+1]);
4938 if (x_max < sim_window_wavexsigstart) continue;
4939 }
4940 x_min = sim_window_timetoxpos(time);
4941 if (x_min < sim_window_wavexsigstart) x_min = sim_window_wavexsigstart;
4942 if (x_min > WAVEXSIGEND) continue;
4943
4944 strength = tr->statearray[j] & 0377;
4945 if (strength == 0) color = sim_colorstrengthoff; else
4946 if (strength <= NODE_STRENGTH) color = sim_colorstrengthnode; else
4947 if (strength <= GATE_STRENGTH) color = sim_colorstrengthgate; else
4948 color = sim_colorstrengthpower;
4949
4950 /* LINTED "lastcolor" used in proper order */
4951 if (datapos > 0 && color != lastcolor)
4952 {
4953 /* strength has changed, dump out data so far */
4954 tx1 = sim_window_wavexsigstart; ty1 = WAVEYSIGBOT; sim_window_mapcoord(wavewin, &tx1, &ty1);
4955 tx2 = WAVEXSIGEND; ty2 = WAVEYCURSTOP; sim_window_mapcoord(wavewin, &tx2, &ty2);
4956 ni = newnodeinst(art_openedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4957 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4958 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
4959 VINTEGER|VISARRAY|(datapos<<VLENGTHSH));
4960 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, lastcolor, VINTEGER);
4961 endobjectchange((INTBIG)ni, VNODEINST);
4962 datapos = 0;
4963 }
4964 lastcolor = color;
4965
4966 state = tr->statearray[j] >> 8;
4967 switch (state)
4968 {
4969 case LOGIC_LOW:
4970 if (laststate == LOGIC_HIGH)
4971 sim_window_addsegment(wavewin, data, &datapos, x_min, y_max, x_min, y_min);
4972 sim_window_addsegment(wavewin, data, &datapos, x_min, y_min, x_max, y_min);
4973 break;
4974 case LOGIC_HIGH:
4975 if (laststate == LOGIC_LOW)
4976 sim_window_addsegment(wavewin, data, &datapos, x_min, y_min, x_min, y_max);
4977 sim_window_addsegment(wavewin, data, &datapos, x_min, y_max, x_max, y_max);
4978 break;
4979 default:
4980 if (datapos > 0)
4981 {
4982 /* doing unknown block, dump out any line data */
4983 tx1 = sim_window_wavexsigstart; ty1 = WAVEYSIGBOT; sim_window_mapcoord(wavewin, &tx1, &ty1);
4984 tx2 = WAVEXSIGEND; ty2 = WAVEYCURSTOP; sim_window_mapcoord(wavewin, &tx2, &ty2);
4985 ni = newnodeinst(art_openedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4986 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4987 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
4988 VINTEGER|VISARRAY|(datapos<<VLENGTHSH));
4989 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, lastcolor,
4990 VINTEGER);
4991 endobjectchange((INTBIG)ni, VNODEINST);
4992 }
4993 datapos = 0;
4994 tx1 = x_min; ty1 = y_min; sim_window_mapcoord(wavewin, &tx1, &ty1);
4995 tx2 = x_max; ty2 = y_max; sim_window_mapcoord(wavewin, &tx2, &ty2);
4996 ni = newnodeinst(art_filledboxprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
4997 if (ni == NONODEINST) { efree((CHAR *)data); return; }
4998 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, lastcolor, VINTEGER);
4999 endobjectchange((INTBIG)ni, VNODEINST);
5000 break;
5001 }
5002 laststate = state;
5003 first = 0;
5004 } else
5005 {
5006 /* analog waveform */
5007 tx = sim_window_timetoxpos(time);
5008 position = (double)(y_max - y_min);
5009 position *= (tr->valuearray[j] - sim_window_get_analow(tr->frameno)) / sim_window_get_anarange(tr->frameno);
5010 ty = (INTBIG)position + y_min;
5011 if (j != 0 && tx >= sim_window_wavexsigstart)
5012 {
5013 if (tx > WAVEXSIGEND)
5014 {
5015 /* "to" data point off the screen: interpolate */
5016 /* LINTED "fx" and "fy" used in proper order */
5017 ty = (ty-fy) * (WAVEXSIGEND-fx) / (tx-fx) + fy;
5018 tx = WAVEXSIGEND;
5019 }
5020
5021 if (first != 0 && fx < sim_window_wavexsigstart)
5022 {
5023 /* "from" data point off the screen: interpolate */
5024 fy = (ty-fy) * (sim_window_wavexsigstart-fx) / (tx-fx) + fy;
5025 fx = sim_window_wavexsigstart;
5026 }
5027 first = 0;
5028 if (fy >= y_min && fy <= y_max &&
5029 ty >= y_min && ty <= y_max)
5030 {
5031 sim_window_addsegment(wavewin, data, &datapos, fx, fy, tx, ty);
5032 } else
5033 {
5034 cfx = fx; cfy = fy;
5035 ctx = tx; cty = ty;
5036 if (!clipline(&cfx, &cfy, &ctx, &cty, sim_window_wavexsigstart, WAVEXSIGEND, y_min, y_max))
5037 {
5038 sim_window_addsegment(wavewin, data, &datapos, cfx, cfy, ctx, cty);
5039 }
5040 }
5041 }
5042 fx = tx; fy = ty;
5043 if (fx >= WAVEXSIGEND) break;
5044 }
5045 }
5046 if (datapos > 0)
5047 {
5048 tx1 = sim_window_wavexsigstart; ty1 = WAVEYSIGBOT; sim_window_mapcoord(wavewin, &tx1, &ty1);
5049 tx2 = WAVEXSIGEND; ty2 = WAVEYCURSTOP; sim_window_mapcoord(wavewin, &tx2, &ty2);
5050 ni = newnodeinst(art_openedpolygonprim, tx1, tx2, ty1, ty2, 0, 0, plotnp);
5051 if (ni == NONODEINST) { efree((CHAR *)data); return; }
5052 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)data,
5053 VINTEGER|VISARRAY|(datapos<<VLENGTHSH));
5054 if ((tr->flags&TRACETYPE) == TRACEISANALOG)
5055 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, tr->color, VINTEGER); else
5056 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, lastcolor, VINTEGER);
5057 endobjectchange((INTBIG)ni, VNODEINST);
5058 }
5059 }
5060
5061 /* ensure that the cell has the right size */
5062 (*el_curconstraint->solve)(plotnp);
5063
5064 /* clean up */
5065 ttyputmsg(x_("Created cell %s"), describenodeproto(plotnp));
5066 efree((CHAR *)data);
5067 }
5068
5069 /*
5070 * Set the display color for strength "strength" to "color".
5071 */
sim_window_setdisplaycolor(INTBIG strength,INTBIG color)5072 void sim_window_setdisplaycolor(INTBIG strength, INTBIG color)
5073 {
5074 if (strength == LOGIC_LOW)
5075 {
5076 if (color != sim_colorlevellow)
5077 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevellow_key, color, VINTEGER);
5078 } else if (strength == LOGIC_HIGH)
5079 {
5080 if (color != sim_colorlevelhigh)
5081 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevelhigh_key, color, VINTEGER);
5082 } else if (strength == LOGIC_X)
5083 {
5084 if (color != sim_colorlevelundef)
5085 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevelundef_key, color, VINTEGER);
5086 } else if (strength == LOGIC_Z)
5087 {
5088 if (color != sim_colorlevelzdef)
5089 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorlevelzdef_key, color, VINTEGER);
5090 } else if (strength == OFF_STRENGTH)
5091 {
5092 if (color != sim_colorstrengthoff)
5093 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthoff_key, color, VINTEGER);
5094 } else if (strength <= NODE_STRENGTH)
5095 {
5096 if (color != sim_colorstrengthnode)
5097 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthnode_key, color, VINTEGER);
5098 } else if (strength <= GATE_STRENGTH)
5099 {
5100 if (color != sim_colorstrengthgate)
5101 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthgate_key, color, VINTEGER);
5102 } else if (strength <= VDD_STRENGTH)
5103 {
5104 if (color != sim_colorstrengthpower)
5105 (void)setvalkey((INTBIG)sim_tool, VTOOL, sim_colorstrengthpower_key, color, VINTEGER);
5106 }
5107 }
5108
5109 /*
5110 * Returns the display color for strength "strength".
5111 */
sim_window_getdisplaycolor(INTBIG strength)5112 INTBIG sim_window_getdisplaycolor(INTBIG strength)
5113 {
5114 if (strength == LOGIC_LOW) return(sim_colorlevellow);
5115 if (strength == LOGIC_HIGH) return(sim_colorlevelhigh);
5116 if (strength == LOGIC_X) return(sim_colorlevelundef);
5117 if (strength == LOGIC_Z) return(sim_colorlevelzdef);
5118 if (strength == OFF_STRENGTH) return(sim_colorstrengthoff);
5119 if (strength <= NODE_STRENGTH) return(sim_colorstrengthnode);
5120 if (strength <= GATE_STRENGTH) return(sim_colorstrengthgate);
5121 if (strength <= VDD_STRENGTH) return(sim_colorstrengthpower);
5122 return(0);
5123 }
5124
sim_window_addsegment(WINDOWPART * wavewin,INTBIG * data,INTBIG * datapos,INTBIG fx,INTBIG fy,INTBIG tx,INTBIG ty)5125 void sim_window_addsegment(WINDOWPART *wavewin, INTBIG *data, INTBIG *datapos, INTBIG fx, INTBIG fy,
5126 INTBIG tx, INTBIG ty)
5127 {
5128 REGISTER INTBIG truefx, truefy, pos;
5129 INTBIG x, y;
5130
5131 x = fx; y = fy; sim_window_mapcoord(wavewin, &x, &y);
5132 truefx = (x-sim_window_basex) - sim_window_offx;
5133 truefy = (y-sim_window_basey) - sim_window_offy;
5134
5135 pos = *datapos;
5136 if (pos < 2 || data[pos-2] != truefx || data[pos-1] != truefy)
5137 {
5138 data[pos++] = truefx;
5139 data[pos++] = truefy;
5140 }
5141
5142 x = tx; y = ty; sim_window_mapcoord(wavewin, &x, &y);
5143 data[pos++] = (x-sim_window_basex) - sim_window_offx;
5144 data[pos++] = (y-sim_window_basey) - sim_window_offy;
5145 *datapos = pos;
5146 }
5147
5148 #define SIMSTEPSIZE 1e-11f
5149 #define EDGERATE 3e-11f
5150 #define SUPPLY 1.8
5151
5152 /*
5153 * Routine to dump vectors in SPICE format.
5154 */
sim_window_writespicecmd(void)5155 void sim_window_writespicecmd(void)
5156 {
5157 FILE *fptr;
5158 int j, state, prevstate;
5159 double simDuration;
5160 CHAR hvar[80], *pt;
5161 REGISTER TRACE *tr;
5162 REGISTER NETWORK *net, **netlist;
5163 REGISTER PORTPROTO *pp;
5164 REGISTER NODEPROTO *cell, *simnt;
5165 REGISTER WINDOWPART *schemwin;
5166
5167 /* get cell being saved */
5168 cell = getcurcell();
5169 if (cell == NONODEPROTO) return;
5170 schemwin = sim_window_findschematics();
5171 if (schemwin == NOWINDOWPART)
5172 {
5173 ttyputerr(_("Must have original schematics or layout circuit as well as waveform"));
5174 return;
5175 }
5176 simnt = schemwin->curnodeproto;
5177
5178 /* SPICE command file named fname.cmd.sp */
5179 fptr = xcreate(cell->protoname, sim_filetypespicecmd, _("SPICE Command File"), &pt);
5180 if (fptr == NULL) return;
5181 ttyputmsg(_("Writing %s"), pt);
5182
5183 /* Initialize variables */
5184 simDuration = 0.0;
5185
5186 /* Create the SPICE command file */
5187 efprintf(fptr, x_("* %s\n"), pt);
5188 efprintf(fptr, x_("* SPICE command file for cell %s from library %s\n"),
5189 describenodeproto(cell), cell->lib->libname);
5190 us_emitcopyright(fptr, x_("* "), x_(""));
5191 if ((us_useroptions&NODATEORVERSION) == 0)
5192 {
5193 (void)esnprintf(hvar, 80, x_("%s"), timetostring(getcurrenttime()));
5194 efprintf(fptr, x_("* Written on %s by Electric VLSI Design System, %s\n\n"),
5195 hvar, el_version);
5196 } else
5197 {
5198 efprintf(fptr, x_("* Written by Electric VLSI Design System\n\n"));
5199 }
5200
5201 efprintf(fptr, x_(".include %s.spi\n\n"), cell->protoname);
5202
5203 efprintf(fptr, x_("* Power Supply\n"));
5204 efprintf(fptr, x_(".param SUPPLY=%g\n"), SUPPLY);
5205 efprintf(fptr, x_("VVDD VDD GND SUPPLY\n\n"));
5206
5207 efprintf(fptr, x_("* Inputs\n"));
5208 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
5209 {
5210 /* only interested in digital traces with information on them */
5211 if ((tr->flags&TRACETYPE) != TRACEISDIGITAL) continue;
5212 if (tr->numsteps <= 0) continue;
5213
5214 /* find the export associated with this signal */
5215 netlist = getcomplexnetworks(tr->name, simnt);
5216 net = netlist[0];
5217 if (net == NONETWORK || netlist[1] != NONETWORK) continue;
5218 for(pp = simnt->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
5219 if (pp->network == net) break;
5220 if (pp == NOPORTPROTO) continue;
5221
5222 /* dump information for input and bidirectional exports */
5223 if ((pp->userbits&STATEBITS) == INPORT ||
5224 (pp->userbits&STATEBITS) == BIDIRPORT)
5225 {
5226 efprintf(fptr, x_("V%s %s GND PWL "), tr->name, tr->name);
5227 for(j=0; j<tr->numsteps; j++)
5228 {
5229 state = tr->statearray[j] >> 8;
5230 if (j == 0)
5231 {
5232 efprintf(fptr, x_("0 %s "), (state==LOGIC_HIGH) ? x_("SUPPLY") : x_("0"));
5233 } else
5234 {
5235 pt = displayedunits((float)tr->timearray[j], VTUNITSTIME, INTTIMEUNITNSEC);
5236 efprintf(fptr, x_("%s %s "), pt, (prevstate==LOGIC_HIGH) ? x_("SUPPLY") : x_("0"));
5237 }
5238 if (tr->timearray[j] > 0)
5239 {
5240 pt = displayedunits((float)tr->timearray[j]+EDGERATE, VTUNITSTIME, INTTIMEUNITNSEC);
5241 efprintf(fptr, x_("%s %s "), pt, (state==LOGIC_HIGH) ? x_("SUPPLY") : x_("0"));
5242 }
5243 prevstate = state;
5244 if (tr->timearray[j] > simDuration) simDuration = tr->timearray[j];
5245 }
5246 efprintf(fptr, x_("\n"));
5247 }
5248 efprintf(fptr, x_("R%s %s GND 1G\n"), tr->name, tr->name);
5249 }
5250 efprintf(fptr, x_("\n"));
5251
5252 efprintf(fptr, x_("* Simulation Commands\n"));
5253 efprintf(fptr, x_(".options post\n"));
5254 estrcpy(hvar, displayedunits(SIMSTEPSIZE, VTUNITSTIME, INTTIMEUNITNSEC));
5255 pt = displayedunits((float)simDuration+30.0f*EDGERATE, VTUNITSTIME, INTTIMEUNITNSEC);
5256 efprintf(fptr, x_(".tran %s %s\n"), hvar, pt);
5257 efprintf(fptr, x_(".end\n"));
5258 xclose(fptr);
5259 }
5260
5261 /*
5262 * Routine to remove trace "tr" from the waveform window's linked list.
5263 */
sim_window_removetrace(TRACE * tr)5264 void sim_window_removetrace(TRACE *tr)
5265 {
5266 TRACE *lasttr, *otr;
5267
5268 lasttr = NOTRACE;
5269 for(otr = sim_window_firstrace; otr != NOTRACE; otr = otr->nexttrace)
5270 {
5271 if (otr == tr) break;
5272 lasttr = otr;
5273 }
5274 if (lasttr == NOTRACE) sim_window_firstrace = tr->nexttrace; else
5275 lasttr->nexttrace = tr->nexttrace;
5276 }
5277
5278 /*
5279 * Routine to renumber the traces in the window.
5280 */
sim_window_renumberlines(void)5281 void sim_window_renumberlines(void)
5282 {
5283 REGISTER INTBIG i, lastframeno;
5284 REGISTER TRACE *tr, *otr;
5285
5286 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
5287 tr->flags &= ~TRACEMARK;
5288 i = 0;
5289 for(tr = sim_window_firstrace; tr != NOTRACE; tr = tr->nexttrace)
5290 {
5291 if ((tr->flags&TRACENOTDRAWN) != 0) {tr->frameno = -1; continue; }
5292 if ((tr->flags&TRACEMARK) != 0) continue;
5293 lastframeno = tr->frameno;
5294 tr->frameno = i;
5295 tr->flags |= TRACEMARK;
5296 for(otr = tr->nexttrace; otr != NOTRACE; otr = otr->nexttrace)
5297 {
5298 if ((otr->flags&TRACENOTDRAWN) != 0) {otr->frameno = -1; continue; }
5299 if (otr->frameno != lastframeno) continue;
5300 otr->frameno = i;
5301 otr->flags |= TRACEMARK;
5302 }
5303 i++;
5304 }
5305
5306 (void)sim_window_set_frames(i);
5307 sim_window_auto_anarange();
5308 }
5309
5310 /*
5311 * Routine to insert trace "tr" after "aftertr" in the waveform window's linked list.
5312 */
sim_window_addtrace(TRACE * tr,TRACE * aftertr)5313 void sim_window_addtrace(TRACE *tr, TRACE *aftertr)
5314 {
5315 if (aftertr == NOTRACE)
5316 {
5317 tr->nexttrace = sim_window_firstrace;
5318 sim_window_firstrace = tr;
5319 } else
5320 {
5321 tr->nexttrace = aftertr->nexttrace;
5322 aftertr->nexttrace = tr;
5323 }
5324 }
5325
sim_window_alloctrace(void)5326 TRACE *sim_window_alloctrace(void)
5327 {
5328 REGISTER TRACE *tr;
5329
5330 if (sim_window_tracefree == NOTRACE)
5331 {
5332 tr = (TRACE *)emalloc(sizeof (TRACE), sim_tool->cluster);
5333 if (tr == 0) return(0);
5334 } else
5335 {
5336 tr = sim_window_tracefree;
5337 sim_window_tracefree = tr->nexttrace;
5338 }
5339 tr->flags = 0;
5340 tr->timelimit = 0;
5341 tr->statelimit = 0;
5342 tr->valuelimit = 0;
5343 tr->numsteps = 0;
5344 tr->nameoff = 0;
5345 tr->statearray = 0;
5346 tr->buschannel = NOTRACE;
5347 return(tr);
5348 }
5349
5350 /********************************* LOW LEVEL GRAPHICS *********************************/
5351
sim_window_setviewport(WINDOWPART * w)5352 void sim_window_setviewport(WINDOWPART *w)
5353 {
5354 float scalex, scaley;
5355 REGISTER INTBIG maxlines;
5356
5357 w->screenlx = 0; w->screenhx = WAVEXSIGEND;
5358 w->screenly = 0; w->screenhy = WAVEYTEXTTOP;
5359 computewindowscale(w);
5360
5361 scalex = (w->usehx - w->uselx) / (float)WAVEXSIGEND;
5362 scaley = ((w->usehy-20) - w->usely) / (float)WAVEYTEXTTOP;
5363 if (scalex > 2.0 && scaley > 2.0) sim_window_textsize = 0; else
5364 if (scalex > 1.0 && scaley > 1.0) sim_window_textsize = 16; else
5365 sim_window_textsize = 12;
5366
5367 maxlines = ((w->usehy - w->usely) * WAVEYSIGRANGE / WAVEYTEXTTOP) / 25;
5368 if (maxlines != sim_window_visframes)
5369 {
5370 if (sim_window_lines > sim_window_visframes)
5371 sim_window_visframes = sim_window_lines;
5372 if (sim_window_visframes > maxlines)
5373 sim_window_visframes = maxlines;
5374 }
5375 }
5376
5377 /*
5378 * Routine to return the WINDOWPART that has the waveform display
5379 */
sim_window_findwaveform(void)5380 WINDOWPART *sim_window_findwaveform(void)
5381 {
5382 WINDOWPART *w;
5383
5384 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
5385 if ((w->state & WINDOWTYPE) == WAVEFORMWINDOW)
5386 return(w);
5387 return(NOWINDOWPART);
5388 }
5389
5390 /*
5391 * Routine to return the WINDOWPART that has the schematics/layout being simulated
5392 */
sim_window_findschematics(void)5393 WINDOWPART *sim_window_findschematics(void)
5394 {
5395 WINDOWPART *w;
5396 INTBIG state;
5397
5398 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
5399 {
5400 state = w->state & (WINDOWTYPE|WINDOWSIMMODE);
5401 if (state == (DISPWINDOW|WINDOWSIMMODE) ||
5402 state == (DISP3DWINDOW|WINDOWSIMMODE))
5403 return(w);
5404 }
5405 return(NOWINDOWPART);
5406 }
5407
sim_window_mapcoord(WINDOWPART * w,INTBIG * x,INTBIG * y)5408 void sim_window_mapcoord(WINDOWPART *w, INTBIG *x, INTBIG *y)
5409 {
5410 REGISTER INTBIG newx, newy;
5411
5412 newx = w->uselx + applyxscale(w, *x - w->screenlx);
5413 newy = w->usely + (*y - w->screenly) *
5414 ((w->usehy-20) - (w->usely)) / (w->screenhy - w->screenly);
5415 *x = newx; *y = newy;
5416 }
5417
sim_window_scaletowindow(WINDOWPART * w,INTBIG * x,INTBIG * y)5418 void sim_window_scaletowindow(WINDOWPART *w, INTBIG *x, INTBIG *y)
5419 {
5420 *x = muldiv(*x - w->uselx, w->screenhx - w->screenlx,
5421 w->usehx - w->uselx) + w->screenlx;
5422 *y = muldiv(*y - w->usely, w->screenhy - w->screenly,
5423 (w->usehy-20) - w->usely) + w->screenly;
5424 }
5425
5426 /* Some Control Sequences for the graphics terminal */
sim_window_setcolor(INTBIG color)5427 void sim_window_setcolor(INTBIG color)
5428 {
5429 sim_window_desc.col = color;
5430 }
5431
sim_window_setmask(INTBIG mask)5432 void sim_window_setmask(INTBIG mask)
5433 {
5434 sim_window_desc.bits = mask;
5435 }
5436
5437 /* Graphics Commands */
sim_window_moveto(INTBIG x,INTBIG y)5438 void sim_window_moveto(INTBIG x, INTBIG y)
5439 {
5440 sim_window_curx = x;
5441 sim_window_cury = y;
5442 }
5443
sim_window_drawto(WINDOWPART * w,INTBIG x,INTBIG y,INTBIG texture)5444 void sim_window_drawto(WINDOWPART *w, INTBIG x, INTBIG y, INTBIG texture)
5445 {
5446 INTBIG fx, fy, tx, ty, cfx, cfy, ctx, cty;
5447
5448 fx = sim_window_curx; fy = sim_window_cury;
5449 tx = x; ty = y;
5450 sim_window_mapcoord(w, &fx, &fy);
5451 sim_window_mapcoord(w, &tx, &ty);
5452 cfx = fx; cfy = fy;
5453 ctx = tx; cty = ty;
5454 if (!clipline(&cfx, &cfy, &ctx, &cty, w->uselx, w->usehx, w->usely, w->usehy))
5455 {
5456 fx = cfx; fy = cfy;
5457 tx = ctx; ty = cty;
5458 screendrawline(w, fx, fy, tx, ty, &sim_window_desc, texture);
5459 }
5460 sim_window_curx = x;
5461 sim_window_cury = y;
5462 }
5463
5464 /*
5465 * Routine to draw from "xll" to "xur" and from "yll" to "yur" in window "w". "style" is:
5466 * 0 to draw solid
5467 * 1 to draw texture
5468 * 2 to draw solid but expand the Y values by 1 pixel
5469 */
sim_window_drawbox(WINDOWPART * w,INTBIG xll,INTBIG yll,INTBIG xur,INTBIG yur,INTBIG style)5470 void sim_window_drawbox(WINDOWPART *w, INTBIG xll, INTBIG yll, INTBIG xur, INTBIG yur, INTBIG style)
5471 {
5472 INTBIG lx, ly, hx, hy, swap;
5473
5474 lx = xll; ly = yll;
5475 hx = xur; hy = yur;
5476 sim_window_mapcoord(w, &lx, &ly);
5477 sim_window_mapcoord(w, &hx, &hy);
5478 if (lx > hx) { swap = lx; lx = hx; hx = swap; }
5479 if (ly > hy) { swap = ly; ly = hy; hy = swap; }
5480 if (style == 1)
5481 {
5482 sim_window_udesc.bits = sim_window_desc.bits;
5483 sim_window_udesc.col = sim_window_desc.col;
5484 screendrawbox(w, lx, hx, ly, hy, &sim_window_udesc);
5485 } else
5486 {
5487 if (style == 2)
5488 {
5489 ly--; hy++;
5490 }
5491 screendrawbox(w, lx, hx, ly, hy, &sim_window_desc);
5492 }
5493 }
5494
5495 /*
5496 * Routine to draw string "s" in window "w" with highlighting and by erasing what
5497 * is underneath first
5498 */
sim_window_drawhcstring(WINDOWPART * w,CHAR * s)5499 void sim_window_drawhcstring(WINDOWPART *w, CHAR *s)
5500 {
5501 INTBIG xw, yw, oldcol, oldmask;
5502 INTBIG px, py;
5503 UINTBIG descript[TEXTDESCRIPTSIZE];
5504
5505 px = sim_window_curx; py = sim_window_cury;
5506 sim_window_mapcoord(w, &px, &py);
5507
5508 TDCLEAR(descript);
5509 TDSETSIZE(descript, TXTSETPOINTS(sim_window_textsize));
5510 screensettextinfo(w, NOTECHNOLOGY, descript);
5511 screengettextsize(w, s, &xw, &yw);
5512 py -= yw/2;
5513
5514 /* erase the area underneath */
5515 oldcol = sim_window_desc.col;
5516 oldmask = sim_window_desc.bits;
5517 sim_window_desc.col = ALLOFF;
5518 sim_window_desc.bits = LAYERA;
5519 screendrawbox(w, px, px+xw, py, py+yw, &sim_window_desc);
5520 sim_window_desc.col = oldcol;
5521 sim_window_desc.bits = oldmask;
5522
5523 /* draw the text */
5524 screendrawtext(w, px, py, s, &sim_window_desc);
5525 }
5526
sim_window_drawcstring(WINDOWPART * w,CHAR * s)5527 void sim_window_drawcstring(WINDOWPART *w, CHAR *s)
5528 {
5529 INTBIG wid, hei;
5530 INTBIG px, py;
5531 UINTBIG descript[TEXTDESCRIPTSIZE];
5532
5533 px = sim_window_curx; py = sim_window_cury;
5534 sim_window_mapcoord(w, &px, &py);
5535 TDCLEAR(descript);
5536 TDSETSIZE(descript, TXTSETPOINTS(sim_window_textsize));
5537 screensettextinfo(w, NOTECHNOLOGY, descript);
5538 screengettextsize(w, s, &wid, &hei);
5539 screendrawtext(w, px-wid/2, py, s, &sim_window_desc);
5540 }
5541
sim_window_drawulstring(WINDOWPART * w,CHAR * s)5542 void sim_window_drawulstring(WINDOWPART *w, CHAR *s)
5543 {
5544 INTBIG wid, hei;
5545 INTBIG px, py;
5546 UINTBIG descript[TEXTDESCRIPTSIZE];
5547
5548 px = sim_window_curx; py = sim_window_cury;
5549 sim_window_mapcoord(w, &px, &py);
5550 TDCLEAR(descript);
5551 TDSETSIZE(descript, TXTSETPOINTS(sim_window_textsize));
5552 screensettextinfo(w, NOTECHNOLOGY, descript);
5553 screengettextsize(w, s, &wid, &hei);
5554 screendrawtext(w, px, py-hei, s, &sim_window_desc);
5555 }
5556
5557 /*
5558 * Name: sim_windowconvertengineeringnotation
5559 *
5560 * Description:
5561 * This procedure converts a floating point number and represents time
5562 * in engineering units such as pico, micro, milli, etc.
5563 *
5564 * Calling Arguments:
5565 * time = floating point value to be converted to Engineering notation
5566 * s1 = pointer to a string that will be used to print the converted value
5567 */
sim_windowconvertengineeringnotation(double time)5568 CHAR *sim_windowconvertengineeringnotation(double time)
5569 {
5570 REGISTER INTBIG timeleft, timeright;
5571 double scaled;
5572 INTBIG inttime;
5573 CHAR *sectype;
5574 REGISTER CHAR *negative;
5575 static CHAR s1[50];
5576
5577 negative = x_("");
5578 if (time < 0.0)
5579 {
5580 negative = x_("-");
5581 time = - time;
5582 }
5583 if (doublesequal(time, 0.0))
5584 {
5585 (void)esnprintf(s1, 50, x_("0 %s"), _("s"));
5586 return(s1);
5587 }
5588 if (time < 1.0E-15 || time >= 1000.0)
5589 {
5590 (void)esnprintf(s1, 50, x_("%s%g%s"), negative, time, _("s"));
5591 return(s1);
5592 }
5593
5594 /* get proper time unit to use */
5595 scaled = time * 1.0E17; inttime = rounddouble(scaled);
5596 if (scaled < 200000.0 && inttime < 100000)
5597 {
5598 sectype = _("fs");
5599 } else
5600 {
5601 scaled = time * 1.0E14; inttime = rounddouble(scaled);
5602 if (scaled < 200000.0 && inttime < 100000)
5603 {
5604 sectype = _("ps");
5605 } else
5606 {
5607 scaled = time * 1.0E11; inttime = rounddouble(scaled);
5608 if (scaled < 200000.0 && inttime < 100000)
5609 {
5610 sectype = _("ns");
5611 } else
5612 {
5613 scaled = time * 1.0E8; inttime = rounddouble(scaled);
5614 if (scaled < 200000.0 && inttime < 100000)
5615 {
5616 sectype = _("us");
5617 } else
5618 {
5619 scaled = time * 1.0E5; inttime = rounddouble(scaled);
5620 if (scaled < 200000.0 && inttime < 100000)
5621 {
5622 sectype = _("ms");
5623 } else
5624 {
5625 inttime = rounddouble(time * 1.0E2);
5626 sectype = _("s");
5627 }
5628 }
5629 }
5630 }
5631 }
5632 timeleft = inttime / 100;
5633 timeright = inttime % 100;
5634 if (timeright == 0)
5635 {
5636 (void)esnprintf(s1, 50, x_("%s%ld%s"), negative, timeleft, sectype);
5637 } else
5638 {
5639 if ((timeright%10) == 0)
5640 {
5641 (void)esnprintf(s1, 50, x_("%s%ld.%ld%s"), negative, timeleft, timeright/10, sectype);
5642 } else
5643 {
5644 (void)esnprintf(s1, 50, x_("%s%ld.%02ld%s"), negative, timeleft, timeright, sectype);
5645 }
5646 }
5647 return(s1);
5648 }
5649
5650 /*
5651 * Name: sim_windowconvertengineeringnotation2
5652 *
5653 * Description:
5654 * This procedure converts a floating point number and represents time
5655 * in engineering units such as pico, micro, milli, etc.
5656 *
5657 * Calling Arguments:
5658 * time = floating point value to be converted to Engineering notation
5659 * precpower = decimal power of necessary time precision
5660 * s1 = pointer to a string that will be used to print the converted value
5661 */
sim_windowconvertengineeringnotation2(double time,INTBIG precpower)5662 CHAR *sim_windowconvertengineeringnotation2(double time, INTBIG precpower)
5663 {
5664 REGISTER INTBIG timeleft, timeright;
5665 double scaled;
5666 INTBIG inttime;
5667 CHAR *sectype;
5668 REGISTER CHAR *negative;
5669 INTBIG scalepower;
5670 static CHAR s1[50];
5671
5672 negative = x_("");
5673 if (time < 0.0)
5674 {
5675 negative = x_("-");
5676 time = - time;
5677 }
5678 if (doublesequal(time, 0.0))
5679 {
5680 (void)esnprintf(s1, 50, x_("0 %s"), _("s"));
5681 return(s1);
5682 }
5683 if (time < 1.0E-15 || time >= 1000.0)
5684 {
5685 (void)esnprintf(s1, 50, x_("%s%g%s"), negative, time, _("s"));
5686 return(s1);
5687 }
5688
5689 /* get proper time unit to use */
5690 scaled = time * 1.0E17; inttime = rounddouble(scaled);
5691 if (scaled < 200000.0 && inttime < 100000)
5692 {
5693 sectype = _("fs");
5694 scalepower = -15;
5695 } else
5696 {
5697 scaled = time * 1.0E14; inttime = rounddouble(scaled);
5698 if (scaled < 200000.0 && inttime < 100000)
5699 {
5700 sectype = _("ps");
5701 scalepower = -12;
5702 } else
5703 {
5704 scaled = time * 1.0E11; inttime = rounddouble(scaled);
5705 if (scaled < 200000.0 && inttime < 100000)
5706 {
5707 sectype = _("ns");
5708 scalepower = -9;
5709 } else
5710 {
5711 scaled = time * 1.0E8; inttime = rounddouble(scaled);
5712 if (scaled < 200000.0 && inttime < 100000)
5713 {
5714 sectype = _("us");
5715 scalepower = -6;
5716 } else
5717 {
5718 scaled = time * 1.0E5; inttime = rounddouble(scaled);
5719 if (scaled < 200000.0 && inttime < 100000)
5720 {
5721 sectype = _("ms");
5722 scalepower = -3;
5723 } else
5724 {
5725 scaled = time * 1.0E2; inttime = rounddouble(scaled);
5726 sectype = _("s");
5727 scalepower = 0;
5728 }
5729 }
5730 }
5731 }
5732 }
5733 if (precpower < scalepower)
5734 {
5735 scaled /= 1.0E2;
5736 esnprintf(s1, 50, x_("%s%.*f%s"), negative, (int)(scalepower - precpower), scaled, sectype);
5737 } else
5738 {
5739 timeleft = inttime / 100;
5740 timeright = inttime % 100;
5741 if (timeright == 0)
5742 {
5743 (void)esnprintf(s1, 50, x_("%s%ld%s"), negative, timeleft, sectype);
5744 } else
5745 {
5746 if ((timeright%10) == 0)
5747 {
5748 (void)esnprintf(s1, 50, x_("%s%ld.%ld%s"), negative, timeleft, timeright/10, sectype);
5749 } else
5750 {
5751 (void)esnprintf(s1, 50, x_("%s%ld.%02ld%s"), negative, timeleft, timeright, sectype);
5752 }
5753 }
5754 }
5755 return(s1);
5756 }
5757
5758 /*
5759 * Routine to look at the "count" signal values in "value" and convert them to a readable
5760 * value in the current simulation display base.
5761 */
sim_window_makewidevalue(INTBIG count,INTBIG * value)5762 CHAR *sim_window_makewidevalue(INTBIG count, INTBIG *value)
5763 {
5764 REGISTER INTBIG i, j, k, val, base, groupsize;
5765 INTHUGE bigval;
5766 static CHAR s2[MAXSIMWINDOWBUSWIDTH+3];
5767 static CHAR *hexstring = x_("0123456789ABCDEF");
5768
5769 /* if any values are undefined, the result is "XX" */
5770 for(i=0; i<count; i++)
5771 if (value[i] != LOGIC_LOW && value[i] != LOGIC_HIGH) return(x_("XX"));
5772
5773 /* bases 2, 8 and 16 are simple */
5774 base = sim_window_state & BUSBASEBITS;
5775 if (base == BUSBASE10 && count > 64) base = BUSBASE16;
5776 if (base == BUSBASE2 || base == BUSBASE8 || base == BUSBASE16)
5777 {
5778 switch (base)
5779 {
5780 case BUSBASE2: groupsize = 1; break;
5781 case BUSBASE8: groupsize = 3; break;
5782 case BUSBASE16: groupsize = 4; break;
5783 default: return(0);
5784 }
5785 j = MAXSIMWINDOWBUSWIDTH+3;
5786 s2[--j] = 0;
5787 for(i = count-1; i >= 0; i -= groupsize)
5788 {
5789 val = 0;
5790 for(k=0; k<groupsize; k++)
5791 {
5792 if (i-k < 0) break;
5793 if (value[i-k] == LOGIC_HIGH) val |= (1<<k);
5794 }
5795 s2[--j] = hexstring[val];
5796 }
5797 switch (base)
5798 {
5799 case BUSBASE2: s2[--j] = 'b'; s2[--j] = '0'; break;
5800 case BUSBASE8: s2[--j] = '0'; break;
5801 case BUSBASE16: s2[--j] = 'x'; s2[--j] = '0'; break;
5802 }
5803 return(&s2[j]);
5804 }
5805
5806 bigval = 0;
5807 for(i=0; i<count; i++)
5808 {
5809 bigval <<= 1;
5810 if (value[i] == LOGIC_HIGH) bigval |= 1;
5811 }
5812 return(hugeinttoa(bigval));
5813 }
5814
5815 /* Simulation: Wide Value */
5816 static DIALOGITEM sim_widedialogitems[] =
5817 {
5818 /* 1 */ {0, {48,188,72,268}, BUTTON, N_("OK")},
5819 /* 2 */ {0, {12,188,36,268}, BUTTON, N_("Cancel")},
5820 /* 3 */ {0, {8,8,24,168}, MESSAGE, N_("Value to set on bus:")},
5821 /* 4 */ {0, {32,8,48,168}, EDITTEXT, x_("")},
5822 /* 5 */ {0, {56,8,72,72}, MESSAGE, N_("Base:")},
5823 /* 6 */ {0, {56,76,72,144}, POPUP, x_("")}
5824 };
5825 static DIALOG sim_widedialog = {{75,75,156,352}, N_("Set Wide Value"), 0, 6, sim_widedialogitems, 0, 0};
5826
5827 /* special items for the "wide value" dialog: */
5828 #define DSWV_VALUE 4 /* value (edit text) */
5829 #define DSWV_BASE 6 /* base (popup) */
5830
5831 /*
5832 * Routine to prompt for a wide value and return the number of bits.
5833 * The bit values are stored in "bits".
5834 * Returns negative on abort/error.
5835 */
sim_window_getwidevalue(INTBIG ** bits)5836 INTBIG sim_window_getwidevalue(INTBIG **bits)
5837 {
5838 REGISTER INTBIG i, j, itemHit, groupsize, testbit, val;
5839 REGISTER UINTHUGE bigval, bigtestbit;
5840 REGISTER CHAR *pt, chr;
5841 REGISTER void *dia;
5842 static INTBIG theBits[MAXSIMWINDOWBUSWIDTH];
5843 static INTBIG lastbase = 2;
5844 static CHAR *base[4] = {x_("2"), x_("8"), x_("10"), x_("16")};
5845
5846 dia = DiaInitDialog(&sim_widedialog);
5847 if (dia == 0) return(-1);
5848 DiaSetPopup(dia, DSWV_BASE, 4, base);
5849 DiaSetPopupEntry(dia, DSWV_BASE, lastbase);
5850 DiaSetText(dia, -DSWV_VALUE, x_("0"));
5851 for(;;)
5852 {
5853 itemHit = DiaNextHit(dia);
5854 if (itemHit == OK || itemHit == CANCEL) break;
5855 }
5856 lastbase = DiaGetPopupEntry(dia, DSWV_BASE);
5857 if (lastbase == 2)
5858 {
5859 /* base 10 is special */
5860 bigval = 0;
5861 for(pt = DiaGetText(dia, DSWV_VALUE); *pt != 0; pt++)
5862 {
5863 if (!isdigit(*pt)) break;
5864 bigval = bigval * 10 + (*pt - '0');
5865 }
5866 bigtestbit = INTHUGECONST(0x8000000000000000);
5867 for(i=0; i<64; i++)
5868 {
5869 if ((bigval & bigtestbit) != 0) theBits[i] = 1; else
5870 theBits[i] = 0;
5871 bigtestbit >>= 1;
5872 }
5873 DiaDoneDialog(dia);
5874 *bits = theBits;
5875 return(64);
5876 }
5877
5878 /* bases 2, 8, and 16 are simpler */
5879 switch (lastbase)
5880 {
5881 case 0: groupsize = 1; break; /* base 2 */
5882 case 1: groupsize = 3; break; /* base 8 */
5883 case 3: groupsize = 4; break; /* base 16 */
5884 default: return(-1);
5885 }
5886 j = 0;
5887 for(pt = DiaGetText(dia, DSWV_VALUE); *pt != 0; pt++)
5888 {
5889 chr = tolower(*pt);
5890 if (chr >= '0' && chr <= '9') val = chr - '0'; else
5891 if (chr >= 'a' && chr <= 'f') val = chr - 'a' + 10; else
5892 val = 100;
5893 if (val >= (1 << groupsize))
5894 {
5895 DiaMessageInDialog(_("Invalid base %s value"), base[lastbase]);
5896 break;
5897 }
5898 testbit = 1 << (groupsize-1);
5899 for(i=0; i<groupsize; i++)
5900 {
5901 if ((val&testbit) != 0) theBits[j] = 1; else
5902 theBits[j] = 0;
5903 j++;
5904 testbit >>= 1;
5905 }
5906 }
5907 DiaDoneDialog(dia);
5908 *bits = theBits;
5909 return(j);
5910 }
5911
sim_window_auto_anarange(void)5912 void sim_window_auto_anarange(void)
5913 {
5914 TRACE *tr;
5915 int i, *t;
5916 double l, h;
5917
5918 if (sim_window_lines > 0)
5919 t = (int *)emalloc(sim_window_lines*sizeof(int), sim_tool->cluster);
5920 else
5921 t = NULL;
5922 for(i=0; i < sim_window_lines; i++) t[i] = 0;
5923
5924 l = 0; h = 1;
5925 for(i=0, tr = sim_window_firstrace; tr != NOTRACE; ++i, tr = tr->nexttrace) {
5926
5927 if (i == 0 ) {
5928 l = tr->anadislow;
5929 h = tr->anadishigh;
5930 } else {
5931 if ( tr->anadislow < l ) l = tr->anadislow;
5932 if ( tr->anadishigh > h ) h = tr->anadishigh;
5933 }
5934
5935 if (tr->frameno < sim_window_lines && tr->frameno >=0 ) {
5936 if (t[tr->frameno] == 0) {
5937 sim_window_frame_analow[tr->frameno] = tr->anadislow;
5938 sim_window_frame_anahigh[tr->frameno] = tr->anadishigh;
5939 t[tr->frameno] = 1;
5940 } else {
5941 if (sim_window_frame_analow[tr->frameno] > tr->anadislow)
5942 sim_window_frame_analow[tr->frameno] = tr->anadislow;
5943
5944 if (sim_window_frame_anahigh[tr->frameno] < tr->anadishigh)
5945 sim_window_frame_anahigh[tr->frameno] = tr->anadishigh;
5946 }
5947 }
5948 }
5949
5950 if (t) efree((CHAR *)t);
5951
5952 sim_window_analow = (float)l;
5953 sim_window_anahigh = (float)h;
5954 sim_window_anarange = (float)(h - l);
5955
5956 }
5957
sim_window_trace_range(INTBIG tri)5958 void sim_window_trace_range(INTBIG tri)
5959 {
5960 TRACE *tr;
5961 int j;
5962 float h, l;
5963
5964 tr = (TRACE *)tri;
5965
5966 if (tr->numsteps >0) {
5967 h = tr->valuearray[0];
5968 l = tr->valuearray[0];
5969 }
5970
5971 for (j=1; j<tr->numsteps; ++j) {
5972 if ( tr->valuearray[j] < l ) l = tr->valuearray[j];
5973 if ( tr->valuearray[j] > h ) h = tr->valuearray[j];
5974 }
5975
5976 /*
5977 d = fabs(h-l);
5978 if (d/(h+l)<DBL_EPSILON) d = 0.5;
5979 double m = 1.0;
5980 while ( d > 10.0 ) { d/=10.0; m*=10.0; }
5981 while ( d < 1.0 ) { d*=10.0; m/=10.0; }
5982
5983 int li = (int)(l/m);
5984 int hi = (int)(h/m);
5985 if (li < 0) --li;
5986 if (hi > 0) ++hi;
5987 l = li * m;
5988 h = hi * m;
5989 */
5990
5991 #if 1
5992 if (l == h)
5993 {
5994 l -= 0.5;
5995 h += 0.5;
5996 }
5997 #endif
5998 tr->anadislow = l;
5999 tr->anadishigh = h;
6000 tr->anadisrange = h-l;
6001 }
6002
sim_window_set_frames(int n)6003 int sim_window_set_frames(int n)
6004 {
6005 int i;
6006 INTBIG newlimit;
6007 float *newanalow, *newanahigh, *newtopval, *newbotval;
6008
6009 if (n > sim_window_lines_limit)
6010 {
6011 newlimit = (sim_window_lines_limit < 16 ? 16 : sim_window_lines_limit);
6012 while(newlimit < n) newlimit *= 2;
6013 newanalow = (float *)emalloc(newlimit*sizeof(float), sim_tool->cluster);
6014 newanahigh = (float *)emalloc(newlimit*sizeof(float), sim_tool->cluster);
6015 newtopval = (float *)emalloc(newlimit*sizeof(float), sim_tool->cluster);
6016 newbotval = (float *)emalloc(newlimit*sizeof(float), sim_tool->cluster);
6017 if(newanalow == NULL || newanahigh == NULL || newtopval == NULL || newbotval == NULL)
6018 {
6019 if(newanalow != NULL) efree((CHAR *)newanalow);
6020 if(newanahigh != NULL) efree((CHAR *)newanahigh);
6021 if(newtopval != NULL) efree((CHAR *)newtopval);
6022 if(newbotval != NULL) efree((CHAR *)newbotval);
6023 return 0;
6024 }
6025 for (i=0; i<sim_window_lines; ++i) {
6026 newanalow[i] = sim_window_frame_analow[i];
6027 newanahigh[i] = sim_window_frame_anahigh[i];
6028 newtopval[i] = sim_window_frame_topval[i];
6029 newbotval[i] = sim_window_frame_botval[i];
6030 }
6031 if (sim_window_lines_limit > 0)
6032 {
6033 efree((CHAR *)sim_window_frame_analow);
6034 efree((CHAR *)sim_window_frame_anahigh);
6035 efree((CHAR *)sim_window_frame_topval);
6036 efree((CHAR *)sim_window_frame_botval);
6037 }
6038 sim_window_frame_analow = newanalow;
6039 sim_window_frame_anahigh = newanahigh;
6040 sim_window_frame_topval = newtopval;
6041 sim_window_frame_botval = newbotval;
6042 sim_window_lines_limit = newlimit;
6043 }
6044
6045 for (i=sim_window_lines; i<n; ++i) {
6046 sim_window_frame_analow[i] = sim_window_analow;
6047 sim_window_frame_anahigh[i] = sim_window_anahigh;
6048 sim_window_frame_topval[i] = sim_window_analow;
6049 sim_window_frame_botval[i] = sim_window_anahigh;
6050 }
6051
6052 sim_window_lines = n;
6053 return 1;
6054 }
6055
sim_window_get_analow(int frameno)6056 float sim_window_get_analow(int frameno)
6057 {
6058 if (frameno >=0 && frameno < sim_window_lines)
6059 return sim_window_frame_analow[frameno];
6060 else
6061 return sim_window_analow;
6062 }
6063
sim_window_get_anahigh(int frameno)6064 float sim_window_get_anahigh(int frameno)
6065 {
6066 if (frameno >=0 && frameno < sim_window_lines)
6067 return sim_window_frame_anahigh[frameno];
6068 else
6069 return sim_window_anahigh;
6070 }
6071
sim_window_get_topval(int frameno)6072 float sim_window_get_topval(int frameno)
6073 {
6074 if (frameno >=0 && frameno < sim_window_lines)
6075 return sim_window_frame_topval[frameno];
6076 else
6077 return sim_window_anahigh;
6078 }
6079
sim_window_get_botval(int frameno)6080 float sim_window_get_botval(int frameno)
6081 {
6082 if (frameno >=0 && frameno < sim_window_lines)
6083 return sim_window_frame_botval[frameno];
6084 else
6085 return sim_window_analow;
6086 }
6087
sim_window_set_anahigh(int frameno,float value)6088 void sim_window_set_anahigh(int frameno, float value)
6089 {
6090 if (frameno >=0 && frameno < sim_window_lines)
6091 sim_window_frame_anahigh[frameno] = value;
6092 }
6093
sim_window_set_analow(int frameno,float value)6094 void sim_window_set_analow(int frameno, float value)
6095 {
6096 if (frameno >=0 && frameno < sim_window_lines)
6097 sim_window_frame_analow[frameno] = value;
6098 }
6099
sim_window_set_topval(int frameno,float value)6100 void sim_window_set_topval(int frameno, float value)
6101 {
6102 if (frameno >=0 && frameno < sim_window_lines)
6103 sim_window_frame_topval[frameno] = value;
6104 }
6105
sim_window_set_botval(int frameno,float value)6106 void sim_window_set_botval(int frameno, float value)
6107 {
6108 if (frameno >=0 && frameno < sim_window_lines)
6109 sim_window_frame_botval[frameno] = value;
6110 }
6111
sim_window_get_anarange(int frameno)6112 float sim_window_get_anarange(int frameno)
6113 {
6114 if (frameno >=0 && frameno < sim_window_lines)
6115 return sim_window_frame_anahigh[frameno] - sim_window_frame_analow[frameno];
6116 else
6117 return sim_window_anarange;
6118 }
6119
sim_window_get_extanarange(int frameno)6120 float sim_window_get_extanarange(int frameno)
6121 {
6122 if (frameno >=0 && frameno < sim_window_lines)
6123 {
6124 float diff;
6125 diff = sim_window_frame_topval[frameno] - sim_window_frame_botval[frameno];
6126 if (!floatsequal(diff, 0.0)) return(diff);
6127 return(sim_window_frame_anahigh[frameno] - sim_window_frame_analow[frameno]);
6128 }
6129 else
6130 return sim_window_anarange;
6131 }
6132
sim_window_zoom_frame(INTBIG frameno)6133 void sim_window_zoom_frame(INTBIG frameno)
6134 {
6135 float v;
6136 if (frameno >=0 && frameno < sim_window_lines) {
6137 v = sim_window_get_anarange(frameno);
6138 v /= 4.0f;
6139 sim_window_frame_anahigh[frameno] -=v;
6140 sim_window_frame_analow[frameno] +=v;
6141 }
6142 }
6143
sim_window_zoomout_frame(INTBIG frameno)6144 void sim_window_zoomout_frame(INTBIG frameno)
6145 {
6146 float v;
6147 if (frameno >=0 && frameno < sim_window_lines) {
6148 v = sim_window_get_anarange(frameno);
6149 v /= 2.0f;
6150 sim_window_frame_anahigh[frameno] +=v;
6151 sim_window_frame_analow[frameno] -=v;
6152 }
6153 }
6154
sim_window_shiftup_frame(INTBIG frameno)6155 void sim_window_shiftup_frame(INTBIG frameno)
6156 {
6157 float v;
6158 if (frameno >=0 && frameno < sim_window_lines) {
6159 v = sim_window_get_anarange(frameno);
6160 v /= 4.0f;
6161 sim_window_frame_anahigh[frameno] +=v;
6162 sim_window_frame_analow[frameno] +=v;
6163 }
6164 }
6165
sim_window_shiftdown_frame(INTBIG frameno)6166 void sim_window_shiftdown_frame(INTBIG frameno)
6167 {
6168 float v;
6169 if (frameno >=0 && frameno < sim_window_lines) {
6170 v = sim_window_get_anarange(frameno);
6171 v /= 4.0f;
6172 sim_window_frame_anahigh[frameno] -=v;
6173 sim_window_frame_analow[frameno] -=v;
6174 }
6175 }
6176
6177 /* This function takes a high value h, a low value l, chops the interval between
6178 h and l in n bits, and rounds the high, low and the interval to a 1,2,5
6179 range. The integers i1 and i2 are the powers of 10 that belong to the
6180 largest value in the interval and the step size. These integers can be
6181 used for printing the scale. */
6182
sim_window_sensible_value(float * h,float * l,INTBIG * i1,INTBIG * i2,INTBIG n)6183 float sim_window_sensible_value(float *h, float *l, INTBIG *i1, INTBIG *i2, INTBIG n)
6184 {
6185 float d, m, max;
6186 int di, hi, li;
6187
6188 if (fabs(*h) > fabs(*l)) max = (float)fabs(*h); else max = (float)fabs(*l);
6189 *i1 = *i2 = 0;
6190 if (max == 0.0) return(0.0);
6191
6192 while ( max >= 10.0 ) { max/=10.0; ++*i1; }
6193 while ( max <= 1.0 ) { max*=10.0; --*i1; }
6194
6195 d = (float)fabs(*h - *l)/(float)n;
6196
6197 if ((float)fabs(d/(*h+*l))<FLT_EPSILON) d = 0.1f;
6198 m=1.0;
6199 while ( d >= 10.0 ) { d/=10.0; m*=10.0; ++*i2; }
6200 while ( d <= 1.0 ) { d*=10.0; m/=10.0; --*i2; }
6201
6202 di = (int)d;
6203
6204 if (di > 2 && di <= 5) di=5;
6205 else
6206 if (di > 5) di = 10;
6207
6208 li = (int)(*l/m);
6209 hi = (int)(*h/m);
6210 li = (li/di)*di;
6211 hi = (hi/di)*di;
6212 if (li<0) li-=di;
6213 if (hi>0) hi+=di;
6214 *l = (float)((double)li*m);
6215 *h = (float)((double)hi*m);
6216
6217 return (float)di*m;
6218 }
6219
sim_window_prettyprint(float v,int i1,int i2)6220 CHAR *sim_window_prettyprint(float v, int i1, int i2)
6221 {
6222 double d;
6223 int i, p;
6224 static CHAR s[20];
6225
6226 d = 1.0;
6227 if (i2 > 0)
6228 for (i = 0; i < i2; ++i) d *= 10.0;
6229 if (i2 < 0)
6230 for (i = 0; i > i2; --i) d /= 10.0;
6231
6232 if (fabs((double)v)*100.0 < d)
6233 {
6234 esnprintf(s, 20, x_("0"));
6235 } else
6236 {
6237 if (i1 <= 4 && i1 >=0 && i2 >=0)
6238 {
6239 esnprintf(s, 20, x_("%.0f"), v);
6240 } else
6241 {
6242 if (i1 <= 4 && i1 >= -2 && i2 < 0)
6243 {
6244 esnprintf(s, 20, x_("%.*f"), (-i2), v);
6245 } else
6246 {
6247 p = i1-12-1;
6248 if (p < 0) p=0;
6249 esnprintf(s, 20, x_("%.*fe%+2d"), p, (double)v/d, i2);
6250 }
6251 }
6252 }
6253 return(s);
6254 }
6255
6256 #endif /* SIMTOOL - at top */
6257