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