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