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 #include <stdlib.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <assert.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <pwd.h>
26 #include <inttypes.h>
27 #include "tkgate.h"
28 
29 static SHash *cellsUsed;	/* Table of all built-in cells used */
30 
31 
32 /*
33  * Return a string representing a port type from a gate type code.  If the gate is
34  * not a module port then the null string is returned.
35  */
iotypeStr(int code)36 const char *iotypeStr(int code)
37 {
38   switch (code) {
39   case IN :
40     return "in";
41   case OUT :
42     return "out";
43   case TRI :
44     return "inout";
45   }
46   return "unknown";
47 }
48 
49 /*
50  * Return a verilog string representing a port type from a gate type code.  If the gate is
51  * not a module port then the null string is returned.
52  */
verIotypeStr(int code)53 const char *verIotypeStr(int code)
54 {
55   switch (code) {
56   case IN :
57     return "input";
58   case OUT :
59     return "output";
60   case TRI :
61     return "inout";
62   }
63   return "unknown";
64 }
65 
66 /*
67  * Transform a string for an iotype to a code value.
68  */
strIOType(const char * code)69 int strIOType(const char *code)
70 {
71   if (strcmp(code,"in") == 0)
72     return IN;
73   else if (strcmp(code,"out") == 0)
74     return OUT;
75   else if (strcmp(code,"inout") == 0)
76     return TRI;
77   else
78     return -1;
79 }
80 
81 /*****************************************************************************
82  *
83  * Generate the gate type name for gate g of type gi
84  *
85  * Parameters:
86  *    gi		Type info for gate
87  *    g			The gate for which we are generating a name.
88  *
89  *****************************************************************************/
getTypeName(GGateInfo * gi,GCElement * g)90 char *getTypeName(GGateInfo *gi,GCElement *g)
91 {
92   static char buf[32];
93   unsigned imask = 0;
94   unsigned M = gi->vmask;
95   int i,j;
96   char *p;
97 
98   if (!M) return gi->vnames;
99 
100   j = 0;
101   for (i = 0;i < 32 && M;i++) {
102     unsigned Q = (1 << i);
103     if ((M & Q)) {
104       M &= ~Q;
105       if (g->wires[i]->invert)
106 	imask |= (1 << j);
107       j++;
108     }
109   }
110 
111   p = gi->vnames;
112   for (;imask;imask--) {
113     p += strcspn(p,":");
114     if (*p == ':') p++;
115   }
116 
117   for (i = 0;i < 31 && *p && *p != ':';)
118     buf[i++] = *p++;
119   buf[i] = 0;
120 
121   return buf;
122 }
123 
VerilogBasicGateCall(FILE * f,GCElement * g)124 int VerilogBasicGateCall(FILE *f,GCElement *g)
125 {
126   static int gateID = 0;
127   char typeName[STRMAX];
128 
129   GGateInfo_encodeTypeName(typeName,g);
130   SHash_insert(cellsUsed,typeName,0);
131 
132   fprintf(f,"  %s",typeName);
133 
134   /*
135    * If there are delay parameters generate the values.
136    */
137   if (g->typeinfo->delayNames[0]) {
138     int delays[MAXDELAYS];
139     GDelayDef *dd;
140     int i;
141 
142     if (g->cust_delay) {
143       for (i = 0;g->typeinfo->delayNames[i];i++) {
144 	delays[i] = g->delays[i];
145       }
146     } else {
147       dd = GDelayDef_findTech(g->typeinfo->delay_defs, g->tech);
148       if (!dd || GDelayDef_getDelays(dd, g, delays) < 0) {
149 	for (i = 0;i < MAXDELAYS;i++)
150 	  delays[i] = 1;
151       }
152     }
153 
154     fprintf(f," #(");
155     for (i = 0;g->typeinfo->delayNames[i];i++) {
156       if (i > 0) fprintf(f,", ");
157       fprintf(f,"%d",delays[i]);
158     }
159     fprintf(f,")");
160   }
161 
162   if (g->ename)
163     fprintf(f," %s",g->ename);
164   else {
165     fprintf(f," g%d",gateID++);
166     logError(ERL_WARN,"Saved gate with no name.");
167   }
168   return 0;
169 }
170 
VerilogBasicGateParmList(FILE * f,GCElement * g)171 int VerilogBasicGateParmList(FILE *f,GCElement *g)
172 {
173   GGateInfo *gi = g->typeinfo;
174   GWire *w;
175   int i,j;
176   int first_pin;
177 
178   first_pin = 1;
179   fprintf(f," (");
180   for (i = 0;i < gi->NumPads;i++) {
181     for (w = g->wires[i], j=0;w;w = w->next, j++) {
182       char *inv = "";
183 
184       if (!first_pin)
185 	fprintf(f,", ");
186       first_pin = 0;
187 
188       if (gi->Pad[i].iotype == IN && w->invert)
189 	inv = "~";
190 
191       if (gi->Pad[i].CanAdd)
192 	fprintf(f,".%s%d",gi->Pad[i].name,j);
193       else
194 	fprintf(f,".%s",gi->Pad[i].name);
195       if (w->net->n_signame)
196 	fprintf(f,"(%s%s)",inv,w->net->n_signame);
197       else
198 	fprintf(f,"(%sw%p)",inv,w->net);
199     }
200   }
201   fprintf(f,");");
202   return 0;
203 }
204 
VerilogBasicGateComment(FILE * f,GCElement * g,unsigned flags)205 void VerilogBasicGateComment(FILE *f,GCElement *g,unsigned flags)
206 {
207   GGateInfo *gi = g->typeinfo;
208   GWire *w;
209   int i,j;
210 
211   if ((flags & VGC_DOMARK))
212     fprintf(f,"   //:");
213   fprintf(f," @(%d,%d)",g->xpos,g->ypos);
214   if (!g->show_name)
215     fprintf(f," /sn:0");
216   if (g->orient != 0)
217     fprintf(f," /R:%d",g->orient);
218   if (g->anchored != 0)
219     fprintf(f," /anc:1");
220   if (g->cpath_cut != 0)
221     fprintf(f," /cpc:1");
222 
223   if (g->cust_delay) {
224     int i;
225 
226     fprintf(f," /delay:\"");
227     for (i = 0;gi->delayNames[i];i++) {
228       fprintf(f," %d",g->delays[i]);
229     }
230     fprintf(f,"\"");
231   } else {
232     if (strcmp(g->tech,TKGATE_DEFAULT_TECH) != 0)
233       fprintf(f," /tech:%s",g->tech);
234   }
235 
236   if (!(flags & VGC_NOWIRES)) {
237     if (gi->NumPads > 0) {
238       fprintf(f," /w:[");
239       for (i = 0;i < gi->NumPads;i++) {
240 	for (w = g->wires[i], j=0;w;w = w->next, j++) {
241 	  fprintf(f," %d",w->nidx);
242 	}
243       }
244       fprintf(f," ]");
245     }
246   }
247 }
248 
VerilogSaveWire(FILE * f,GWire * w,int doComment)249 static void VerilogSaveWire(FILE *f,GWire *w,int doComment)
250 {
251   GWireNode *n;
252   GNet *net = w->net;
253 
254   if (doComment)
255     fprintf(f,"//:");
256 
257   fprintf(f," {%d}",w->nidx);
258 
259   n = w->nodes;
260 
261   if (n->out) {
262     for (;n;n = n->out) {
263       fprintf(f,"(");
264 
265       if (n->showSize && net->n_nbits > 1)
266 	fprintf(f,"#:");
267       if (n->isLabeled)
268 	fprintf(f,"%d:",n->labelSide ? -n->offset : n->offset);
269       fprintf(f,"%d,%d)",n->x,n->y);
270       w = n->end;
271     }
272   } else {
273     for (;n;n = n->in) {
274       fprintf(f,"(");
275       if (n->in && n->in->showSize && w->net->n_nbits > 1)
276 	fprintf(f,"#:");
277       if (n->in && n->in->isLabeled)
278 	fprintf(f,"%d:",n->in->labelSide ? -n->in->offset : n->in->offset);
279       fprintf(f,"%d,%d)",n->x,n->y);
280       w = n->end;
281     }
282   }
283 
284   if (w) {
285     GCElement *g;
286     GGateInfo *gi;
287     int i;
288 
289     fprintf(f,"{%d}",w->nidx);
290     fprintf(f,"\n");
291 
292     g = w->gate;
293     if (!g) return;
294     gi = w->gate->typeinfo;
295 
296     switch (gi->code) {
297     case GC_JOINT :
298       for (i = 0;i < gi->NumPads;i++)
299 	if (g->wires[i] && g->wires[i] != w)
300 	  VerilogSaveWire(f,g->wires[i],1);
301       break;
302     case GC_TAP :
303       if (g->wires[TAP_OUT] == w)
304 	VerilogSaveWire(f,g->wires[TAP_IN],1);
305       if (g->wires[TAP_IN] == w)
306 	VerilogSaveWire(f,g->wires[TAP_OUT],1);
307       break;
308     }
309   }
310 }
311 
ClearNetMarks(GModuleDef * M)312 static void ClearNetMarks(GModuleDef *M)
313 {
314   HashElem *nl;
315 
316   for (nl = Hash_first(M->m_nets);nl;nl = Hash_next(M->m_nets,nl)) {
317     GNet *n = (GNet*) HashElem_obj(nl);
318     n->n_mark = 0;
319   }
320 }
321 
VerilogSaveOneNet(FILE * f,GNet * n)322 static void VerilogSaveOneNet(FILE *f,GNet *n)
323 {
324   if (n->n_ionet) {
325     switch (n->n_ionet->typeinfo->code) {
326     case GC_SWITCH :
327     case GC_DIP :
328       fprintf(f,"reg ");
329       break;
330     default :
331       fprintf(f,"%s ",n->n_ionet->typeinfo->vnames);
332       break;
333     }
334   } else {
335     fprintf(f,"%s ",GNet_getVType(n));
336   }
337 
338   if (n->n_nbits > 1)
339     fprintf(f,"[%d:0] ",n->n_nbits-1);
340 
341   if (n->n_signame)
342     fprintf(f,"%s;    ",n->n_signame);
343   else
344     fprintf(f,"w%p;    ",n);
345 
346   fprintf(f,"//:");
347   if (!n->n_show_name)
348     fprintf(f," /sn:0");
349 
350   VerilogSaveWire(f,wire_sigroot(n->n_driver),0);
351 }
352 
VerilogSaveNets(FILE * f,GModuleDef * M)353 static void VerilogSaveNets(FILE *f,GModuleDef *M)
354 {
355   HashElem *gl;
356   HashElem *nl;
357 
358   /* Unmark all gates */
359   for (gl = Hash_first(M->m_gates);gl;gl = Hash_next(M->m_gates,gl)) {
360     GCElement *g = (GCElement*)HashElem_obj(gl);
361     g->mark = 0;
362   }
363 
364   /*
365      Make sure all nets are finalized.
366    */
367 #if 0
368   for (wl = M->m_wires;wl;wl = wl->wl_next) {
369     wire_finalizeNet(wl->wl_wire);
370   }
371 #endif
372 
373   for (nl = Hash_first(M->m_nets);nl;nl = Hash_next(M->m_nets,nl)) {
374     GNet *n = (GNet*) HashElem_obj(nl);
375 
376     if (n->n_ionet)
377       VerilogSaveOneNet(f,n);
378   }
379   for (nl = Hash_first(M->m_nets);nl;nl = Hash_next(M->m_nets,nl)) {
380     GNet *n = (GNet*) HashElem_obj(nl);
381 
382     if (!n->n_ionet)
383       VerilogSaveOneNet(f,n);
384   }
385   fprintf(f,"//: enddecls\n\n");
386 }
387 
388 /*
389    Save the parameter list for a module.
390 */
VerilogSaveModDecl(FILE * f,GModuleDef * M)391 static void VerilogSaveModDecl(FILE *f,GModuleDef *M)
392 {
393   HashElem *gl;
394   int did_first = 0;
395 
396   if (GModuleDef_isTop(M)) {
397     if (M == TkGate.circuit->root_mod)
398       fprintf(f,";    //: root_module\n");
399     else
400       fprintf(f,";\n");
401     return;
402   }
403 
404   fprintf(f,"(");
405   for (gl = Hash_first(M->m_gates);gl;gl = Hash_next(M->m_gates,gl)) {
406     GCElement *g = (GCElement*) HashElem_obj(gl);
407     switch (g->typeinfo->code) {
408     case GC_LOGICIN :
409     case GC_LOGICOUT :
410     case GC_LOGICTRI :
411       if (did_first) fprintf(f,", ");
412       did_first = 1;
413       fprintf(f,"%s",g->wires[0]->net->n_signame); break;
414       break;
415     }
416   }
417   fprintf(f,");\n");
418 }
419 
420 /*
421  * Copy up to N characters from p up to the next end of string or newline.
422  * reposition p after the newline.  Returns the number of characters copied
423  * or -1 if p is at the end of the string.
424  */
copyline(char * buf,int N,const char ** p)425 static int copyline(char *buf,int N,const char **p)
426 {
427   int i;
428 
429   for (i = 0;i < N;i++, (*p)++) {
430     if (*(*p) == 0) {
431       buf[i] = 0;
432       if (i == 0)
433 	return -1;
434       else
435 	return i;
436     }
437     if (*(*p) == '\n') {
438       buf[i] = 0;
439       (*p)++;
440       return i;
441     }
442 
443     buf[i] = *(*p);
444   }
445 
446   buf[N-1] = 0;
447   return N;
448 }
449 
450 /******************************************************************************
451  *
452  * Save a module symbol
453  *
454  * Parameter:
455  *      f		File to which to write symbol
456  *      ms		Module symbol to save
457  *
458  * Saves a module symbol description including normal and selected icons and
459  * port positions.  Only symbols relevent to instances in the file being saved
460  * are written.  The ID numbers for symbols are considered local to each
461  * particular save file.  ID numbers may or may not be duplicated in different
462  * files.
463  *
464  ******************************************************************************/
VerilogSaveModSymbol(FILE * f,GModSymbol * ms)465 static void VerilogSaveModSymbol(FILE *f,GModSymbol *ms)
466 {
467   char buf[STRMAX];
468   char buf2[STRMAX];
469   const char *data,*p;
470   int x,y;
471   int i;
472 
473   if (!ms) return;
474 
475   fprintf(f,"\n");
476   fprintf(f,"//: /symbolBegin: %" PRIuPTR "\n",(uintptr_t)ms);
477 
478   /*
479    * Generate the normal icon data
480    */
481   data = GModSymbol_getNormalIcon(ms,&x,&y);
482   fprintf(f,"//: /iconBegin normal %lu %d %d\n",
483 	  strlen(data),x,y);
484   p = data;
485   while (copyline(buf,STRMAX,&p) >= 0) {
486     fprintf(f,"//: /data \"%s\"\n",quoteChars(buf2,buf,"\"\\"));
487   }
488   fprintf(f,"//: /iconEnd\n");
489 
490   /*
491    * Generate the select icon data
492    */
493   data = GModSymbol_getSelectIcon(ms,&x,&y);
494   fprintf(f,"//: /iconBegin select %lu %d %d\n",
495 	  strlen(data),x,y);
496   p = data;
497   while (copyline(buf,STRMAX,&p) >= 0) {
498     fprintf(f,"//: /data \"%s\"\n",quoteChars(buf2,buf,"\"\\"));
499   }
500   fprintf(f,"//: /iconEnd\n");
501 
502   /*
503    * Generate the port data
504    */
505   for (i = 0;i < GModSymbol_numPorts(ms);i++) {
506     GSymPort *msp = GModSymbol_getPort(ms,i);
507     fprintf(f,"//: /port %s %s",
508 	    verIotypeStr(msp->msp_type),
509 	    msp->msp_name);
510     if (msp->msp_size != 1)
511       fprintf(f,"[%d:0]",msp->msp_size-1);
512 
513     fprintf(f," @(%d, %d) /r:%d\n",
514 	    msp->msp_x,
515 	    msp->msp_y,
516 	    msp->msp_orient);
517   }
518   fprintf(f,"//: /symbolEnd\n");
519 }
520 
521 /*
522    Save comment for block descriptor.
523 */
VerilogSaveModInterface(FILE * f,GModuleDef * M)524 static void VerilogSaveModInterface(FILE *f,GModuleDef *M)
525 {
526   GCElement *g = M->m_interface;
527   GGateInfo *gi;
528   GWire *w;
529   int i,j;
530   static char dirchar[] = "?=><";
531 
532   if (!g) return;
533 
534   if (GCElement_getType(g) == GC_SYMBLOCK) {
535     fprintf(f,"//: /symbol:%" PRIuPTR "\n", (uintptr_t)g->u.block.symbol);
536   }
537 
538   gi = g->typeinfo;
539   fprintf(f,"//: interface ");
540   fprintf(f," /sz:(%d, %d) /bd:[",g->u.block.gwidth,g->u.block.gheight);
541   for (i = 0;i < gi->NumPads;i++) {
542     for (w = g->wires[i], j=0;w;w = w->next, j++) {
543       fprintf(f," %s%d%c",
544 	      gi->Pad[i].name,j,
545 	      dirchar[gi->Pad[i].iotype]);
546       if (w->net->n_nbits == 1)
547 	fprintf(f,"%s",w->name);
548       else
549 	fprintf(f,"%s[%d:0]",w->name,w->net->n_nbits-1);
550       fprintf(f,"(%d/%d)",w->offset.num,w->offset.den);
551     }
552   }
553   fprintf(f," ]");
554   fprintf(f," /pd: %d",M->m_protData);
555   fprintf(f," /pi: %d",M->m_protIntf);
556   fprintf(f," /pe: %d",M->m_protEdit);
557   fprintf(f," /pp: %d",M->m_pptype);
558 
559   fprintf(f,"\n");
560 }
561 
562 /*****************************************************************************
563  *
564  * Save symbols used in this circuit
565  *
566  * Parameters:
567  *      f		File to write symbols to
568  *      flags		Options
569  *
570  *****************************************************************************/
VerilogSaveSymbols(FILE * f,vsaveopts_t flags)571 static void VerilogSaveSymbols(FILE *f,vsaveopts_t flags)
572 {
573   HashElem *he;
574 
575   /*
576    * Clear the mark on all symbols
577    */
578   for (he = GModSymbol_first();he;he = GModSymbol_next(he)) {
579     GModSymbol *ms = (GModSymbol*) HashElem_obj(he);
580     ms->ms_mark = 0;
581   }
582 
583 
584   for (he = Hash_first(TkGate.circuit->moduleTable);he;he = Hash_next(TkGate.circuit->moduleTable,he)) {
585     GModuleDef *M = (GModuleDef*) HashElem_obj(he);
586     HashElem *he2;
587 
588     if (M->m_isLib && !(flags & VSO_LIBRARY)) continue;
589 
590     if (M->m_interface && GCElement_getType(M->m_interface) == GC_SYMBLOCK) {
591       GModSymbol *ms = GCElement_getSymbol(M->m_interface);
592       ms->ms_mark = 1;
593     }
594 
595 
596     for (he2 = Hash_first(M->m_gates);he2;he2 = Hash_next(M->m_gates,he2)) {
597       GCElement *g = (GCElement*) HashElem_obj(he2);
598       if (GCElement_getType(g) == GC_SYMBLOCK) {
599 	GModSymbol *ms = GCElement_getSymbol(g);
600 	ms->ms_mark = 1;
601       }
602     }
603   }
604 
605 
606   /*
607    * Save only marked symbols
608    */
609   for (he = GModSymbol_first();he;he = GModSymbol_next(he)) {
610     GModSymbol *ms = (GModSymbol*) HashElem_obj(he);
611     if (ms->ms_mark) {
612       VerilogSaveModSymbol(f,ms);
613     }
614   }
615 }
616 
617 
618 /*
619  * Save any flags this module might have
620  */
VerilogSaveModFlags(FILE * f,GModuleDef * M)621 static void VerilogSaveModFlags(FILE *f,GModuleDef *M)
622 {
623   if (M->m_protData)
624     fprintf(f,"//: property prot_data=%d\n",M->m_protData);
625   if (M->m_protIntf)
626     fprintf(f,"//: property prot_intf=%d\n",M->m_protIntf);
627   if (M->m_pptype != PPT_SCALED)
628     fprintf(f,"//: property pptype=%d\n",M->m_pptype);
629 }
630 
VerilogSaveGates(FILE * f,GModuleDef * M)631 static void VerilogSaveGates(FILE *f,GModuleDef *M)
632 {
633   HashElem *gl;
634 
635   for (gl = Hash_first(M->m_gates);gl;gl = Hash_next(M->m_gates,gl)) {
636     GCElement *g = (GCElement*) HashElem_obj(gl);
637     assert(g->typeinfo->VerSave);
638     (*g->typeinfo->VerSave)(f,g);
639   }
640   fprintf(f,"\n");
641 }
642 
VerilogSaveHdlText(FILE * f,GModuleDef * M)643 static void VerilogSaveHdlText(FILE *f,GModuleDef *M)
644 {
645   Encoder *encoder = Circuit_getSaveFileEncoder(TkGate.circuit);
646 
647   if (M->m_text && strlen(M->m_text) > 0) {
648     char *last = M->m_text + strlen(M->m_text) - 1;
649     char *buf =  recodeTextP(encoder,M->m_text);
650 
651     fprintf(f,"%s",buf);
652     if (*last != '\n')
653       fprintf(f,"\n");
654 
655     free(buf);
656   }
657 }
658 
VerilogRegisterHdlCells(GModuleDef * M)659 static void VerilogRegisterHdlCells(GModuleDef *M)
660 {
661   HashElem *e;
662 
663   for (e = Hash_first(M->m_gates);e;e = Hash_next(M->m_gates,e)) {
664     GCElement *g = (GCElement*) HashElem_obj(e);
665     const char *prefix = TkGate.circuit->c_gatePrefix;
666 
667     if (strncmp(g->u.block.moduleName,prefix,strlen(prefix)) == 0)
668       SHash_insert(cellsUsed,g->u.block.moduleName,0);
669   }
670 }
671 
672 
VerilogSaveModule(FILE * f,GModuleDef * M)673 void VerilogSaveModule(FILE *f,GModuleDef *M)
674 {
675   ClearNetMarks(M);
676   Concat_updateAutos(M,0);
677 
678   if (M->m_type == MT_NETLIST) {
679     fprintf(f,"//: /netlistBegin %s\n",M->m_name);
680     fprintf(f,"module %s",M->m_name);
681 
682     VerilogSaveModDecl(f,M);
683     if (!GModuleDef_isTop(M))
684       VerilogSaveModInterface(f,M);
685     VerilogSaveModFlags(f,M);
686     VerilogSaveNets(f,M);
687     VerilogSaveGates(f,M);
688 
689     fprintf(f,"endmodule\n");
690     fprintf(f,"//: /netlistEnd\n\n");
691   } else {
692     fprintf(f,"//: /hdlBegin %s\n",M->m_name);
693     VerilogSaveModInterface(f,M);
694     VerilogSaveModFlags(f,M);
695     if (GModuleDef_isTop(M)) {
696       fprintf(f,"//: root_module\n");
697     }
698     fprintf(f,"//: enddecls\n");
699     VerilogRegisterHdlCells(M);
700     VerilogSaveHdlText(f,M);
701     fprintf(f,"//: /hdlEnd\n\n");
702 
703     fprintf(f,"\n");
704     Timescale_save(&TkGate.circuit->c_timescale, f);
705     fprintf(f,"\n");
706   }
707 }
708 
VerilogSavePlainModule(FILE * f,GModuleDef * M)709 void VerilogSavePlainModule(FILE *f,GModuleDef *M)
710 {
711   ClearNetMarks(M);
712   Concat_updateAutos(M,0);
713 
714 
715   if (M->m_type == MT_NETLIST) {
716     fprintf(f,"module %s",M->m_name);
717 
718     VerilogSaveModDecl(f,M);
719     VerilogSaveModFlags(f,M);
720     VerilogSaveNets(f,M);
721     VerilogSaveGates(f,M);
722 
723     fprintf(f,"endmodule\n");
724   } else {
725     VerilogSaveHdlText(f,M);
726   }
727 }
728 
729 /*****************************************************************************
730  *
731  * Do initialization required before writing verilog file
732  *
733  *****************************************************************************/
VerilogWriteInit()734 void VerilogWriteInit()
735 {
736   if (!cellsUsed)
737     cellsUsed = new_SHash_noob();
738   else
739     SHash_flush(cellsUsed);
740 }
741 
742 /*****************************************************************************
743  *  Raw save of file in verilog format.
744  *****************************************************************************/
VerilogWriteModules(const char * name,vsaveopts_t flags)745 int VerilogWriteModules(const char *name,vsaveopts_t flags)
746 {
747   FILE *f;
748   HashElem *E;
749   int i;
750   int error_status;
751   char buf[STRMAX];
752   Circuit *c = TkGate.circuit;
753 
754   VerilogWriteInit();
755 
756   if (!(flags & VSO_NOHDLCHECK)) {
757     if (hdl_checkSave(0) < 0)			/* Make sure hdl is up to date */
758       return ECANCELED;
759   }
760 
761   if (!(f = fopen(name,"w"))) {
762     return ENOENT;
763   }
764 
765   fprintf(f,"//: version \"%s\"\n",VERSIONS[0].vd_name);
766   fprintf(f,"//: property encoding = \"%s\"\n",c->c_encoding);
767   fprintf(f,"//: property locale = \"%s\"\n",c->c_locale->l_code);
768   fprintf(f,"//: property prefix = \"%s\"\n",c->c_gatePrefix);
769 
770   if (c->title && *c->title)
771     fprintf(f,"//: property title = \"%s\"\n",quoteChars(buf,c->title,"\"\\"));
772 
773 
774   if (c->simClockMode)
775     fprintf(f,"//: property simClockMode = 1\n");
776   if (c->simClockName)
777     fprintf(f,"//: property simClockName = \"%s\"\n",c->simClockName);
778 
779   if (!c->useExtBars)
780     fprintf(f,"//: property useExtBars = 0\n");
781 
782   if (!c->showSwitchNets)
783     fprintf(f,"//: property showSwitchNets = 0\n");
784 
785   if (c->simAutoStart)
786     fprintf(f,"//: property simAutoStart = 1\n");
787 
788   if (c->discardChanges)
789     fprintf(f,"//: property discardChanges = 1\n");
790 
791   if (strcmp(TkGate.defaultTech,TKGATE_DEFAULT_TECH) != 0)
792     fprintf(f,"//: property technology = %s\n",TkGate.defaultTech);
793 
794   fprintf(f,"//: property timingViolationMode = %d\n",c->c_tvMode);
795   fprintf(f,"//: property initTime = \"%g %s\"\n",c->c_startup,
796 	  Timescale_codeToUnits(c->c_startupUnits));
797 
798   if (c->numInitScripts > 0) {
799     for (i = 0;i < c->numInitScripts;i++)
800       fprintf(f,"//: script \"%s\"\n",quoteChars(buf,c->initScripts[i],"\"\\"));
801     fprintf(f,"\n");
802   }
803 
804   for (E = Hash_first(TkGate.libraries);E;E = Hash_next(TkGate.libraries,E)) {
805     const char *name = SHashElem_key(E);
806     fprintf(f,"//: require \"%s\"\n",name);
807   }
808 
809   fprintf(f,"\n");
810   Timescale_save(&c->c_timescale, f);
811   fprintf(f,"\n");
812 
813   VerilogSaveSymbols(f,flags);
814 
815   /*
816    * Save the root module first, then save all other modules.
817    */
818   VerilogSaveModule(f,c->root_mod);
819   for (E = Hash_first(c->moduleTable);E;E = Hash_next(c->moduleTable,E)) {
820     GModuleDef *M = (GModuleDef*) HashElem_obj(E);
821     if (((flags & VSO_LIBRARY) || !M->m_isLib) && M != c->root_mod)
822       VerilogSaveModule(f,M);
823   }
824 
825   /*
826    * Generate built-in definitions for basic gates used.
827    */
828   if (flags & VSO_BUILTINS) {
829     fprintf(f,"\n");
830     Timescale_save(&c->c_timescale, f);
831     fprintf(f,"\n");
832 
833     for (E = Hash_first(cellsUsed);E;E = Hash_next(cellsUsed,E)) {
834       GCellSpec gcs;
835       const char *cellName = (const char*) SHashElem_key(E);
836       if (GGateInfo_decodeTypeName(cellName,&gcs)) {
837 	fprintf(f,"\n");
838 	(*gcs.gc_info->WriteCellDef)(f,&gcs);
839       }
840     }
841   }
842   SHash_flush(cellsUsed);
843 
844 
845   error_status = ferror(f);
846   fclose(f);
847 
848   return error_status;
849 }
850 
851 /*****************************************************************************
852  * Copy a file and return 0 on success or non-zero on failure.
853  *****************************************************************************/
copy_file(const char * src,const char * dst)854 static int copy_file(const char *src,const char *dst)
855 {
856   FILE *inf = 0,*outf = 0;
857   int r = 0;
858   int c;
859 
860   inf = fopen(src,"r");
861   if (inf)
862     outf = fopen(dst,"w");
863 
864   if (inf && outf) {
865     while ((c = fgetc(inf)) != EOF) {
866       if (fputc(c,outf) == EOF) break;
867     }
868 
869     if (ferror(inf)) r = -1;
870     if (ferror(outf)) r = -1;
871   } else
872     r = -1;
873 
874   if (inf)  fclose(inf);
875   if (outf) fclose(outf);
876   return r;
877 }
878 
879 /*****************************************************************************
880  *
881  * Check a file to see if it is OK by invoking tkgate in verify mode on the
882  * file.
883  *
884  *****************************************************************************/
check_file(const char * name)885 static int check_file(const char *name)
886 {
887   char cmd[STRMAX];
888   int pid = 0,status = 0;
889 
890 #if 0
891   /* Mess with the file to simulate corruption. */
892   sprintf(cmd,"xemacs %s",name);
893   system(cmd);
894 #endif
895 
896   sprintf(cmd,"%s/libexec/tkgate",TkGate.homedir);
897   if (!(pid = fork())) {
898     execl(cmd,cmd,"-Vq",name,(char*)NULL);
899     exit(1);
900   }
901 
902   waitpid(pid,&status,0);
903 
904   return status;
905 }
906 
907 
908 /*****************************************************************************
909  *
910  * Save a file without confirmation check.
911  *
912  *****************************************************************************/
VerilogQuickSave(const char * name,vsaveopts_t saveFlags)913 int VerilogQuickSave(const char *name,vsaveopts_t saveFlags)
914 {
915   int r;
916 
917   r = VerilogWriteModules(name,saveFlags);
918   if (r == ECANCELED) return ECANCELED;
919 
920   if (r != 0) {
921     message(1,msgLookup("err.badsave"),name);
922     return r;
923   }
924   if (check_file(name))
925     message(1,msgLookup("err.corruptnewsave"),name);
926   else {
927     message(0,msgLookup("msg.save"),name);
928     ClearModified();
929   }
930   return 0;
931 }
932 
933 /*****************************************************************************
934  *
935  * Make sure we have permission to write the file.
936  *
937  *****************************************************************************/
isWritable(const char * name)938 int isWritable(const char *name)
939 {
940   char dirName[STRMAX],*p;
941   struct stat sb;
942   int gid = getgid();
943   int uid = getuid();
944 
945   /*
946    * If the file exists, look at its permissions
947    */
948   if (stat(name, &sb) == 0) {
949     unsigned mode = sb.st_mode & 7;
950 
951     if (uid == sb.st_uid)
952       mode |= (sb.st_mode >> 6) & 7;
953     if (gid == sb.st_gid)
954       mode |= (sb.st_mode >> 3) & 7;
955 
956     if ((mode & 2))
957       return 1;
958     else
959       return 0;
960   }
961 
962   /*
963    * If the file does not exist, check its directory
964    */
965   if (strlen(name) > STRMAX) return 0;
966   strcpy(dirName, name);
967 
968   p = strrchr(dirName,'/');
969   if (!p)
970     strcpy(dirName,".");
971   else {
972     *p = 0;
973     while (p > dirName && p[-1] == '/')
974       *--p = 0;
975     if (p == dirName)
976       strcpy(dirName,"/");
977   }
978 
979 
980   if (stat(dirName, &sb) == 0) {
981     unsigned mode = sb.st_mode & 7;
982 
983     if (uid == sb.st_uid)
984       mode |= (sb.st_mode >> 6) & 7;
985     if (gid == sb.st_gid)
986       mode |= (sb.st_mode >> 3) & 7;
987 
988     if ((mode & 2))
989       return 1;
990     else
991       return 0;
992   }
993 
994   return 0;
995 }
996 
997 /*****************************************************************************
998  *
999  * Safely save a file in verilog format.
1000  *
1001  *****************************************************************************/
VerilogSave(const char * name)1002 int VerilogSave(const char *name)
1003 {
1004   char tempName1[STRMAX],tempName2[STRMAX];
1005   extern int doBackupOnSave;
1006   extern int doSafeSave;
1007   int file_exists = 0;
1008   vsaveopts_t saveFlags = 0;
1009   FILE *f;
1010 
1011 
1012   if (!*name) return -1;
1013 
1014   if (!isWritable(name)) {
1015     message(1,msgLookup("err.notwritable"),name);
1016     return 0;
1017   }
1018 
1019   if (TkGate.tcl) {
1020     const char *r;
1021     r = Tcl_GetVar(TkGate.tcl,"tkg_saveWithCells",TCL_GLOBAL_ONLY);
1022     if (r && *r == '1')
1023       saveFlags |= VSO_BUILTINS;
1024   }
1025 
1026 
1027   /*
1028    * Check to see if we are overwriting an existing file.
1029    */
1030   file_exists = ((f = fopen(name,"r")) != 0);
1031   if (f) fclose(f);
1032 
1033 
1034   /*
1035    * If we are overwriting an existing file and safe saving is enabled,
1036    * we will first write the circuit to a temporary file, check the file
1037    * to see if it was saved correctly, and only then move it to the
1038    * target save file.
1039    *
1040    */
1041   if (file_exists) {
1042     /*
1043      * If this is the first time we have saved and the file exists, make a backup.
1044      */
1045     if (doBackupOnSave) {
1046       char buf[STRMAX];
1047       char *p;
1048 
1049       strcpy(buf,name);
1050       p = buf+strlen(buf);
1051       if (p[-1] != '~') {	/* Don't create backup when editing a backup file */
1052 	strcpy(p,"~");
1053 	if (copy_file(name,buf) != 0)
1054 	  message(1,msgLookup("err.backupfail"),buf);
1055       }
1056       doBackupOnSave = 0;
1057     }
1058 
1059     if (doSafeSave) {
1060       int r1 = 0,r2 = 0;
1061 
1062       sprintf(tempName1,"%s#save-%d#",name,getpid());
1063       sprintf(tempName2,"%s#backup-%d#",name,getpid());
1064 
1065       r1 = copy_file(name,tempName2);
1066       if (r1 == 0) {
1067 	r2 = VerilogWriteModules(tempName1,saveFlags);
1068 	if (r2 == ECANCELED) return ECANCELED;
1069       }
1070 
1071       if (r1 != 0 || r2 != 0) {
1072 	unlink(tempName1);
1073 	unlink(tempName2);
1074 	DoTcl("yesno [format [m err.nosafesave] %s]",name);
1075 	if (strcmp(Tcl_GetStringResult(TkGate.tcl),"yes") == 0)
1076 	  VerilogQuickSave(name,saveFlags);
1077 	return 0;
1078       }
1079 
1080       if (check_file(tempName1)) {
1081 	unlink(tempName2);
1082 	message(1,msgLookup("err.corruptsave"),name,tempName1);
1083 	return 0;
1084       }
1085 
1086       if (rename(tempName1,name) != 0) {
1087 	message(1,msgLookup("err.badrename"),tempName1,name);
1088 	return 0;
1089       }
1090 
1091       unlink(tempName2);
1092       message(0,msgLookup("msg.save"),name);
1093       ClearModified();
1094     } else
1095       VerilogQuickSave(name,saveFlags);
1096     return 0;
1097   } else {
1098     VerilogQuickSave(name,saveFlags);
1099     return 0;
1100   }
1101 }
1102 
GCellSpec_writeBeginModule(FILE * f,GCellSpec * gcs)1103 void GCellSpec_writeBeginModule(FILE *f,GCellSpec *gcs)
1104 {
1105   GGateInfo *gi = gcs->gc_info;
1106   int N = gi->NumPads;
1107   int multiPad = gcs->gc_multiPad;
1108   int i,j;
1109   int isfirst = 1;
1110 
1111   fprintf(f,"//: /builtinBegin\n");
1112   fprintf(f,"module %s",gcs->gc_name);
1113 
1114   /*
1115    * Generate delay port declaration list
1116    */
1117   if (gi->delayNames[0]) {
1118     fprintf(f," #(");
1119     for (i = 0;gi->delayNames[i];i++) {
1120       if (i > 0) fprintf(f,", ");
1121       fprintf(f,".%s(1)",gi->delayNames[i]);
1122     }
1123     fprintf(f,")");
1124   }
1125 
1126   /*
1127    * Generate port declaration list
1128    */
1129   fprintf(f," (");
1130   for (i = 0;i < N;i++) {
1131     if (!isfirst) fprintf(f,", ");
1132     isfirst = 0;
1133 
1134     if (gi->Pad[i].CanAdd) {
1135       for (j = 0;j < multiPad;j++) {
1136 	if (j > 0) fprintf(f,", ");
1137 	fprintf(f,"%s%d",gi->Pad[i].name,j);
1138       }
1139     } else
1140       fprintf(f,"%s",gi->Pad[i].name);
1141   }
1142   fprintf(f,");\n");
1143 }
1144 
GCellSpec_writePortDecls(FILE * f,GCellSpec * gcs)1145 void GCellSpec_writePortDecls(FILE *f,GCellSpec *gcs)
1146 {
1147   GGateInfo *gi = gcs->gc_info;
1148   int N = gi->NumPads;
1149   int multiPad = gcs->gc_multiPad;
1150   int numBits = gcs->gc_numBits;
1151   int i,j;
1152   char bitSpec[128];
1153 
1154   if (numBits > 1)
1155     sprintf(bitSpec," [%d:0]",numBits-1);
1156   else
1157     *bitSpec = 0;
1158 
1159   for (i = 0;i < N;i++) {
1160     const char *iotype = verIotypeStr(gi->Pad[i].iotype);
1161 
1162     if (gi->Pad[i].CanAdd) {
1163       for (j = 0;j < multiPad;j++) {
1164 	fprintf(f,"%s%s %s%d;\n",iotype,bitSpec,gi->Pad[i].name,j);
1165       }
1166     } else
1167       fprintf(f,"%s%s %s;\n",iotype,bitSpec,gi->Pad[i].name);
1168   }
1169 }
1170 
GCellSpec_writeEndModule(FILE * f,GCellSpec * gcs)1171 void GCellSpec_writeEndModule(FILE *f,GCellSpec *gcs)
1172 {
1173   fprintf(f,"\n");
1174   fprintf(f,"endmodule\n");
1175   fprintf(f,"//: /builtinEnd\n\n");
1176 }
1177