1 /****************************************************************************
2 Copyright (C) 1987-2015 by Jeffery P. Hansen
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 Last edit by hansen on Mon Jan 19 18:18:09 2009
19 ****************************************************************************/
20 /***************************************************************************
21 This file contains the defintion of a "symbol module instance" (SymModule).
22 A SymModule is a module that has a user defined bitmap as its symbol. It
23 is an alternate form of a normal module instance.
24
25 Problems
26 * How do we deal with a symbol, particular port arrangements, being
27 modified after we have created instances of it?
28 * What do we do if the symbol module definition is part of a library?
29 We could load the user file first, and not yet have a symbol definition.
30 * What if a user tries to change the function of a symbol module?
31 * How do we handle undo/redo Pixmap data?
32
33
34 Handling characteristics of SymModules:
35 * Each SymModule has its own pointer to a GModSymbol. Different instances of
36 the same module may have different GModSymbol definitions associated with
37 them.
38 * Newly created SymModule instances use the GModSymbol for the corresponding
39 module definition.
40 *
41 ***************************************************************************/
42
43 #ifdef __cplusplus
44 #include <cstdlib>
45 #include <cstring>
46 #else
47 #include <stdlib.h>
48 #include <string.h>
49 #endif
50
51 #include <unistd.h>
52
53 #include "tkgate.h"
54 #include "print.h"
55
56 void SymBlock_Draw(GCElement *g,int md);
57 int SymBlock_HitDistance(GCElement *g,int x,int y);
58 void SymBlock_GetExtents(GCElement *g,TargetDev_e target,int *minx,int *miny,int *maxx,int *maxy,int *bd);
59 void SymBlock_Delete(GCElement *g,GModuleDef *env,int drawp);
60 GCElement *SymBlock_Copy(GModuleDef *,GCElement *g,int x,int y,unsigned flags);
61 void SymBlock_VerSave(FILE*,GCElement*);
62 int SymBlock_EditProps(GCElement *g,int isLoadDialog);
63 void SymBlock_PSWrite(GPrint *P,GModLayout*,GCElement *g);
64
65 int Block_SimHitFunc(EditState*,GCElement*);
66
67
68 static char *psSymBlock[] = {
69 "%",
70 "% A symbol block gate",
71 "%",
72 "/pssymblock {",
73 " startgate",
74 " 1 -1 scale",
75 " {} forall translate 1 exch matrix exch image",
76 " grestore",
77 "} bind def",
78 0
79 };
80
81 GGateInfo gate_symblock_info = {
82 GC_SYMBLOCK,
83 "SYMMODULE",
84 "symblock",0x0,
85 "pssymblock",psSymBlock,
86 -1,-1,
87
88 {{0}},
89
90 0,
91
92 0,{{0}},
93 {{0,0,CT},{0,0,CT},{0,0,CT},{0,0,CT}},
94 {0,0,0,0,0,0},
95
96 {0},
97
98 Generic_Make,
99 Nop_WriteCellDef,
100 Generic_Init,
101 SymBlock_Delete,
102 SymBlock_GetExtents,
103 SymBlock_HitDistance,
104 SymBlock_Draw,
105 Generic_Move,
106 SymBlock_Copy,
107 Err_AddInput,
108 Err_AddOutput,
109 Err_AddInOut,
110 Generic_Rotate,
111 Err_RemovePort,
112 Err_ChangePin,
113 Nop_SimInitFunc,
114 Block_SimHitFunc,
115 SymBlock_PSWrite,
116 SymBlock_EditProps,
117 SymBlock_VerSave
118 };
119
120
121 /*
122 * Make a port on a gate for a module symbol
123 */
SymBlock_makePort(GCElement * g,GModSymbol * ms,GModuleDef * M,int pn)124 void SymBlock_makePort(GCElement *g,GModSymbol *ms,GModuleDef *M,int pn)
125 {
126 GSymPort *p = GModSymbol_getPort(ms,pn);
127 GPadLoc *l = &p->msp_loc[0];
128 int x = l->x1;
129 int y = l->y1;
130 GWire *e1,*e2;
131
132 #if 0
133 printf("symbolPort %s[%d] @(%d,%d) r=%d in %s\n",
134 p->msp_name,p->msp_size,x,y,p->msp_orient,
135 M ? M->m_name : "NULL");
136 #endif
137
138 wire_new(M,&e1,&e2);
139
140 ob_touch(g);
141 ob_touch(e1);
142 ob_touch(e1->nodes);
143 ob_touch(e2->nodes);
144
145 net_setSize(e1->net,p->msp_size);
146 g->wires[pn] = wire_append(0,e1);
147 e1->orient = p->msp_orient;
148 e1->gate = g;
149 e1->name = ob_strdup(p->msp_name);
150
151 e1->nodes->x = e2->nodes->x = g->xpos+x;
152 e1->nodes->y = e2->nodes->y = g->ypos+y;
153 switch (p->msp_orient) {
154 case D_RIGHT :
155 e2->nodes->x += TKGATE_STUBLEN;
156 break;
157 case D_LEFT :
158 e2->nodes->x -= TKGATE_STUBLEN;
159 break;
160 case D_UP :
161 e2->nodes->y -= TKGATE_STUBLEN;
162 break;
163 case D_DOWN :
164 e2->nodes->y += TKGATE_STUBLEN;
165 break;
166 }
167 wire_finalizeNet(e1);
168 }
169
170 /*
171 * Convert a normal block into a SymBlock.
172 *
173 * Aguments:
174 * g Block circuit element to be converted
175 * ms Module symbol to use (or null to create default symbol)
176 * M Module in which g is contained
177 * doWires Non-zero if wires should be created
178 */
SymBlock_convert(GCElement * g,GModSymbol * ms,GModuleDef * M,int doWires)179 GCElement *SymBlock_convert(GCElement *g,GModSymbol *ms,GModuleDef *M,int doWires)
180 {
181 char *modName = g->u.block.moduleName;
182 int N = GModSymbol_numPorts(ms);
183 int portBytes = requiredPortMemory(N);
184
185 ob_touch(g);
186
187 if (!ms) ms = new_GModSymbol();
188
189 #if 0
190 printf("converting %s to symblock\n",g->ename);
191 #endif
192
193 /*
194 * If portBytes is greater than zero, then we may need to reallocate the gate object
195 * to make space for ports.
196 */
197 if (portBytes > 0)
198 g = (GCElement *) ob_realloc(g,sizeof(GCElement)+portBytes);
199
200 g->typeinfo = &gate_symblock_info;
201 g->u.block.moduleName = modName;
202 g->u.block.symbol = ms;
203 GModSymbol_attach(ms);
204
205 if (doWires) {
206 int i;
207
208 for (i = 0;i < N;i++) {
209 SymBlock_makePort(g,ms,M,i);
210 }
211 }
212 #if 0
213 printf("conversion complete\n");
214 #endif
215
216 return g;
217 }
218
219 /*****************************************************************************
220 *
221 * Remake the ports for a gate in a module. Normally called for the interface
222 * representative when editing the interface.
223 *
224 * Parameters:
225 * g Circuit element to be remade
226 * M Module in which g is defined.
227 *
228 *****************************************************************************/
SymBlock_remakePorts(GCElement * g,GModuleDef * M)229 void SymBlock_remakePorts(GCElement *g,GModuleDef *M)
230 {
231 GModSymbol *ms = GCElement_getSymbol(g);
232 int N = GModSymbol_numPorts(ms);
233 int i;
234
235 if (!ms) return;
236
237 gate_cutOffWires(g,M,0);
238
239 for (i = 0;i < N;i++) {
240 SymBlock_makePort(g,ms,M,i);
241 }
242 }
243
244
SymBlock_Draw(GCElement * g,int md)245 void SymBlock_Draw(GCElement *g,int md)
246 {
247 GModSymbol *ms = g->u.block.symbol;
248
249 #if 0
250 printf("SymBlock_Draw(%s, %d)\n",g->ename,md);
251 #endif
252
253 GModSymbol_draw(ms,g->xpos,g->ypos,g->orient,g->selected);
254 gate_drawWires(g,md);
255
256 #if 0
257 /*block symbol debugging*/
258 {
259 int minx,miny,maxx,maxy,x,y;
260 char buf[STRMAX];
261
262 SymBlock_GetExtents(g,TD_X11,&minx,&miny,&maxx,&maxy,0);
263 XSetFont(TkGate.D,TkGate.instGC,TkGate.stextXF[1]);
264
265 x = maxx+2;
266 y = miny+10;
267
268 sprintf(buf,"g=%p",g);
269 RelPosDrawString(TkGate.W,TkGate.stextF[1],TkGate.instGC,x,y,buf,AtLeft);
270
271 y+=10;
272 sprintf(buf,"ms=%p",ms);
273 RelPosDrawString(TkGate.W,TkGate.stextF[1],TkGate.instGC,x,y,buf,AtLeft);
274
275 y+=10;
276 sprintf(buf,"rcount=%d",ms->ms_refCount);
277 RelPosDrawString(TkGate.W,TkGate.stextF[1],TkGate.instGC,x,y,buf,AtLeft);
278 }
279 #endif
280 }
281
SymBlock_HitDistance(GCElement * g,int x,int y)282 int SymBlock_HitDistance(GCElement *g,int x,int y)
283 {
284 int minx,miny,maxx,maxy;
285
286 SymBlock_GetExtents(g,TD_X11,&minx,&miny,&maxx,&maxy,0);
287
288 if (x >= minx && x <= maxx && y >= miny && y <= maxy)
289 return GATERANGE-2;
290 else
291 return NOHIT;
292 }
293
SymBlock_GetExtents(GCElement * g,TargetDev_e target,int * minx,int * miny,int * maxx,int * maxy,int * bd)294 void SymBlock_GetExtents(GCElement *g,TargetDev_e target,int *minx,int *miny,int *maxx,int *maxy,int *bd)
295 {
296 GModSymbol *ms = g->u.block.symbol;
297
298 GModSymbol_getExtents(ms,g->orient,minx,miny,maxx,maxy);
299
300 *minx += g->xpos;
301 *miny += g->ypos;
302 *maxx += g->xpos;
303 *maxy += g->ypos;
304 }
305
SymBlock_Delete(GCElement * g,GModuleDef * M,int drawp)306 void SymBlock_Delete(GCElement *g,GModuleDef *M,int drawp)
307 {
308 if (drawp) gate_draw(g,GD_NOWIRE);
309 gate_cutOffWires(g,M,drawp);
310 GModSymbol_detach(g->u.block.symbol);
311 g->u.block.symbol = 0;
312 if (M)
313 gate_remove(M,g);
314 }
315
SymBlock_Copy(GModuleDef * M,GCElement * g,int x,int y,unsigned flags)316 GCElement *SymBlock_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags)
317 {
318 GCElement *ng;
319
320 ng = Generic_Copy(M,g,x,y,flags);
321 ng->u.block.moduleName = ob_strdup(g->u.block.moduleName);
322 ng->u.block.symbol = g->u.block.symbol;
323 GModSymbol_attach(g->u.block.symbol);
324
325 return ng;
326 }
327
328 /*****************************************************************************
329 *
330 * Managing function for symbol block dialog properties box
331 *
332 * Parameters:
333 * g Gate that is being edited
334 * isLoadDialog 1=load values for display, 0=save modified values
335 *
336 *****************************************************************************/
SymBlock_EditProps(GCElement * g,int isLoadDialog)337 int SymBlock_EditProps(GCElement *g,int isLoadDialog)
338 {
339 if (isLoadDialog) {
340 Generic_editPropsDLBasics(g);
341 Generic_editPropsDLWires(g);
342 Block_EditParmProps(g, isLoadDialog);
343 Tcl_SetVar(TkGate.tcl,"edgat_dtype","none",TCL_GLOBAL_ONLY);
344 } else {
345 ob_touch(g);
346 Generic_editPropsULWires(g);
347 Generic_editPropsULBasics(g);
348 Block_EditParmProps(g, isLoadDialog);
349
350 FlagRedraw();
351 }
352 return 0;
353 }
354
SymBlock_writePSSymbol(GPrint * P,GModSymbol * ms)355 void SymBlock_writePSSymbol(GPrint *P,GModSymbol *ms)
356 {
357 int w = ms->ms_normal.w;
358 int h = ms->ms_normal.h;
359 int x,y;
360 int n = w*h;
361 int i,j;
362 char *p;
363
364 p = strchr(ms->ms_normal.data,'{');
365 if (!p) {
366 fprintf(P->p_f,"/ms%p [1 1 <00>] def\n",ms);
367 return;
368 }
369
370 fprintf(P->p_f,"/ms%p [%d %d\n<",ms,w,h);
371
372 for (i = 0;;i++) {
373 unsigned code, rcode;
374
375 while (*p && (p[0] != '0' || p[1] != 'x')) p++;
376 if (!*p) break;
377
378 sscanf(p,"0x%x",&code);
379
380 rcode = 0;
381 for (j = 0;j < 8;j++)
382 if ((code & (1<<j)))
383 rcode |= 1 <<(7-j);
384
385
386 fprintf(P->p_f,"%02x",((~rcode) & 0xff));
387 if ( ((i+1) % 32 == 0) && (i+1) < n) {
388 fprintf(P->p_f,"\n");
389 }
390 p++;
391 }
392
393 x = ms->ms_ix[0][0];
394 y = ms->ms_iy[0][0];
395 fprintf(P->p_f,"> %d %d] def\n",x,y);
396 }
397
398 /*****************************************************************************
399 *
400 * Symbol block postscript generation.
401 *
402 *****************************************************************************/
SymBlock_PSWrite(GPrint * P,GModLayout * L,GCElement * g)403 void SymBlock_PSWrite(GPrint *P,GModLayout *L,GCElement *g)
404 {
405 GModSymbol *ms = g->u.block.symbol;
406
407 if (!PHash_find(&P->p_genSymbols,ms)) {
408 PHash_insert(&P->p_genSymbols,ms,ms);
409
410 SymBlock_writePSSymbol(P,ms);
411 }
412
413 Generic_PSLabels(P,g);
414 fprintf(P->p_f,"ms%p %d %d %d %s\n",ms,g->xpos,g->ypos,-g->orient*90,
415 g->typeinfo->psprint);
416 }
417
SymBlock_VerSave(FILE * f,GCElement * g)418 void SymBlock_VerSave(FILE *f,GCElement *g)
419 {
420 GWire *w;
421 int i,j;
422 int first_pin;
423 int N = GCElement_numPads(g);
424 GModSymbol *ms = g->u.block.symbol;
425
426 fprintf(f," %s",g->u.block.moduleName);
427 Block_VerSaveModParms(f,g);
428 fprintf(f," %s",g->ename);
429
430 first_pin = 1;
431 fprintf(f," (");
432 for (i = 0;i < N;i++) {
433 GSymPort *msp = ms->ms_ports[i];
434
435 for (w = g->wires[i], j=0;w;w = w->next, j++) {
436 if (first_pin)
437 first_pin = 0;
438 else
439 fprintf(f,", ");
440 fprintf(f,".%s(%s)",msp->msp_name,w->net->n_signame);
441 }
442 }
443 fprintf(f,");");
444
445 fprintf(f," //: @(%d, %d) /symbol:%lu",g->xpos,g->ypos,(uintptr_t)ms);
446
447 if (!g->show_name) fprintf(f," /sn:%d",g->show_name);
448 if (g->anchored) fprintf(f," /anc:1");
449
450 if (N > 0) {
451 fprintf(f," /w:[");
452 for (i = 0;i < N;i++) {
453 for (w = g->wires[i], j=0;w;w = w->next, j++) {
454 fprintf(f," %d",w->nidx);
455 }
456 }
457 fprintf(f," ]");
458 }
459
460
461 fprintf(f,"\n");
462 }
463
init_symblock()464 void init_symblock()
465 {
466 /* I don't think we need this */
467 RegisterGate(&gate_symblock_info);
468 }
469