1 /*
2  * Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
3  *
4  *    This source code is free software; you can redistribute it
5  *    and/or modify it in source code form under the terms of the GNU
6  *    General Public License as published by the Free Software
7  *    Foundation; either version 2 of the License, or (at your option)
8  *    any later version.
9  *
10  *    This program is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU General Public License for more details.
14  *
15  *    You should have received a copy of the GNU General Public License
16  *    along with this program; if not, write to the Free Software
17  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 # include  "edif.h"
21 # include  <stdlib.h>
22 # include  <string.h>
23 # include  <assert.h>
24 # include  "ivl_alloc.h"
25 
26 typedef enum property_e {
27       PRP_NONE = 0,
28       PRP_STRING,
29       PRP_INTEGER
30 } property_t;
31 
32 struct cellref_property_ {
33       const char*name;
34       property_t ptype;
35       union {
36 	    const char*str;
37 	    long num;
38       } value_;
39       struct cellref_property_*next;
40 };
41 
42 struct edif_s {
43       const char*name;
44 	/* List the ports of the design. */
45       unsigned nports;
46       struct __cell_port*ports;
47 	/* All the external libraries attached to me. */
48       edif_xlibrary_t xlibs;
49 	/* list the cellref instances. */
50       edif_cellref_t celref;
51 	/* The root instance has cellref properties as well. */
52       struct cellref_property_*property;
53 	/* Keep a list of all the nexa */
54       struct edif_joint_s*nexa;
55 };
56 
57 struct edif_xlibrary_s {
58 	/* Name of this library. */
59       const char*name;
60 	/* The cells that are contained in this library. */
61       struct edif_cell_s*cells;
62 	/* point to the optional celltable. */
63       const struct edif_xlib_celltable*celltable;
64 	/* used to list libraries in an edif_t. */
65       struct edif_xlibrary_s*next;
66 };
67 
68 
69 struct __cell_port {
70       const char*name;
71       const char*ename;
72       struct cellref_property_*property;
73       ivl_signal_port_t dir;
74 };
75 
76 struct edif_cell_s {
77       const char*name;
78       edif_xlibrary_t xlib;
79 
80       unsigned nports;
81       struct __cell_port*ports;
82 
83       struct cellref_property_*property;
84       struct edif_cell_s*next;
85 };
86 
87 struct edif_cellref_s {
88       struct edif_cell_s* cell;
89       unsigned u;
90       struct cellref_property_*property;
91       struct edif_cellref_s* next;
92 };
93 
94 struct joint_cell_ {
95       struct edif_cellref_s*cell;
96       unsigned port;
97       struct joint_cell_*next;
98 };
99 
100 struct edif_joint_s {
101       const char*name;
102       struct joint_cell_*links;
103       struct edif_joint_s*next;
104 };
105 
106 
is_edif_name(const char * text)107 static int is_edif_name(const char*text)
108 {
109       static const char*edif_name_chars = "abcdefghijklmnopqrstuvwxyz"
110                                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
111                                           "0123456789";
112       return (strspn(text, edif_name_chars) == strlen(text));
113 }
114 
edif_create(const char * design_name,unsigned nports)115 edif_t edif_create(const char*design_name, unsigned nports)
116 {
117       edif_t edf = malloc(sizeof(struct edif_s));
118 
119       edf->name  = design_name;
120       edf->nports= nports;
121       edf->ports = nports? calloc(nports, sizeof(struct __cell_port)) : 0;
122       edf->celref= 0;
123       edf->xlibs = 0;
124       edf->property = 0;
125       edf->nexa  = 0;
126 
127       return edf;
128 }
129 
edif_portconfig(edif_t edf,unsigned idx,const char * name,ivl_signal_port_t dir)130 void edif_portconfig(edif_t edf, unsigned idx,
131 		     const char*name, ivl_signal_port_t dir)
132 {
133       assert(idx < edf->nports);
134 
135       edf->ports[idx].name = name;
136       if (is_edif_name(name)) {
137 	    edf->ports[idx].ename = 0;
138 
139       } else {
140 	    char buf[16];
141 	    sprintf(buf, "PORT%u", idx);
142 	    edf->ports[idx].ename = strdup(buf);
143       }
144 
145       edf->ports[idx].dir  = dir;
146 }
147 
edif_port_to_joint(edif_joint_t jnt,edif_t edf,unsigned port)148 void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port)
149 {
150       struct joint_cell_* jc = malloc(sizeof(struct joint_cell_));
151 
152       jc->cell = 0;
153       jc->port = port;
154       jc->next = jnt->links;
155       jnt->links = jc;
156 }
157 
edif_pstring(edif_t edf,const char * name,const char * value)158 void edif_pstring(edif_t edf, const char*name, const char*value)
159 {
160       struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
161       prp->name = name;
162       prp->ptype = PRP_STRING;
163       prp->value_.str = value;
164       prp->next = edf->property;
165       edf->property = prp;
166 }
167 
edif_xlibrary_create(edif_t edf,const char * name)168 edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name)
169 {
170       edif_xlibrary_t xlib = malloc(sizeof(struct edif_xlibrary_s));
171 
172       xlib->name  = name;
173       xlib->cells = 0;
174       xlib->celltable = 0;
175       xlib->next = edf->xlibs;
176       edf->xlibs = xlib;
177 
178       return xlib;
179 }
180 
edif_xlibrary_set_celltable(edif_xlibrary_t xlib,const struct edif_xlib_celltable * tab)181 void edif_xlibrary_set_celltable(edif_xlibrary_t xlib,
182 				 const struct edif_xlib_celltable*tab)
183 {
184       assert(xlib->celltable == 0);
185       xlib->celltable = tab;
186 }
187 
edif_xlibrary_findcell(edif_xlibrary_t xlib,const char * cell_name)188 edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t xlib,
189 				   const char*cell_name)
190 {
191       const struct edif_xlib_celltable*tcur;
192       edif_cell_t cur;
193 
194       for (cur = xlib->cells ;  cur ;  cur = cur->next) {
195 	    if (strcmp(cell_name, cur->name) == 0)
196 		  return cur;
197       }
198 
199       if (xlib->celltable == 0)
200 	    return 0;
201 
202       for (tcur = xlib->celltable ;  tcur->cell_name ;  tcur += 1)
203 	    if (strcmp(cell_name, tcur->cell_name) == 0) {
204 		  return (tcur->cell_func)(xlib);
205 	    }
206 
207       return 0;
208 }
209 
edif_xlibrary_scope_cell(edif_xlibrary_t xlib,ivl_scope_t scope)210 edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib,
211 				     ivl_scope_t scope)
212 {
213       unsigned port_count, idx;
214       edif_cell_t cur;
215 
216 	/* Check to see if the cell is already somehow defined. */
217       cur = edif_xlibrary_findcell(xlib, ivl_scope_tname(scope));
218       if (cur) return cur;
219 
220 	/* Count the ports of the scope. */
221       port_count = 0;
222       for (idx = 0 ;  idx < ivl_scope_sigs(scope) ;  idx += 1) {
223 	    ivl_signal_t sig = ivl_scope_sig(scope, idx);
224 
225 	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
226 		  continue;
227 
228 	    port_count += 1;
229       }
230 
231       cur = edif_xcell_create(xlib, ivl_scope_tname(scope), port_count);
232 
233       port_count = 0;
234       for (idx = 0 ;  idx < ivl_scope_sigs(scope) ;  idx += 1) {
235 	    ivl_signal_t sig = ivl_scope_sig(scope, idx);
236 
237 	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
238 		  continue;
239 
240 	    edif_cell_portconfig(cur, port_count,
241 				 ivl_signal_basename(sig),
242 				 ivl_signal_port(sig));
243 	    port_count += 1;
244       }
245 
246       return cur;
247 }
248 
edif_xcell_create(edif_xlibrary_t xlib,const char * name,unsigned nports)249 edif_cell_t edif_xcell_create(edif_xlibrary_t xlib, const char*name,
250 			      unsigned nports)
251 {
252       unsigned idx;
253       edif_cell_t cell = malloc(sizeof(struct edif_cell_s));
254 
255       cell->name = name;
256       cell->xlib = xlib;
257       cell->nports = nports;
258       cell->ports  = calloc(nports, sizeof(struct __cell_port));
259       cell->property = 0;
260 
261       for (idx = 0 ;  idx < nports ;  idx += 1) {
262 	    cell->ports[idx].name = "?";
263 	    cell->ports[idx].dir = IVL_SIP_NONE;
264 	    cell->ports[idx].property = 0;
265       }
266 
267       cell->next = xlib->cells;
268       xlib->cells = cell;
269 
270       return cell;
271 }
272 
edif_cell_portconfig(edif_cell_t cell,unsigned idx,const char * name,ivl_signal_port_t dir)273 void edif_cell_portconfig(edif_cell_t cell, unsigned idx,
274 			  const char*name, ivl_signal_port_t dir)
275 {
276       assert(idx < cell->nports);
277 
278       cell->ports[idx].name = name;
279       cell->ports[idx].dir  = dir;
280 }
281 
edif_cell_port_pstring(edif_cell_t cell,unsigned idx,const char * name,const char * value)282 void edif_cell_port_pstring(edif_cell_t cell, unsigned idx,
283 			    const char*name, const char*value)
284 {
285       struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
286       prp->name  = name;
287       prp->ptype = PRP_STRING;
288       prp->value_.str = value;
289       prp->next  = cell->ports[idx].property;
290       cell->ports[idx].property = prp;
291 }
292 
edif_cell_port_byname(edif_cell_t cell,const char * name)293 unsigned edif_cell_port_byname(edif_cell_t cell, const char*name)
294 {
295       unsigned idx = 0;
296       for (idx = 0 ;  idx < cell->nports ;  idx += 1)
297 	    if (strcmp(name, cell->ports[idx].name) == 0)
298 		  break;
299 
300       return idx;
301 }
302 
edif_cell_pstring(edif_cell_t cell,const char * name,const char * value)303 void edif_cell_pstring(edif_cell_t cell, const char*name,
304 		       const char*value)
305 {
306       struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
307       prp->name  = name;
308       prp->ptype = PRP_STRING;
309       prp->value_.str = value;
310       prp->next  = cell->property;
311       cell->property = prp;
312 }
313 
edif_cell_pinteger(edif_cell_t cell,const char * name,int value)314 void edif_cell_pinteger(edif_cell_t cell, const char*name,
315 			int value)
316 {
317       struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
318       prp->name  = name;
319       prp->ptype = PRP_INTEGER;
320       prp->value_.num = value;
321       prp->next  = cell->property;
322       cell->property = prp;
323 }
324 
edif_cellref_create(edif_t edf,edif_cell_t cell)325 edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell)
326 {
327       static unsigned u_number = 0;
328       edif_cellref_t ref = malloc(sizeof(struct edif_cellref_s));
329 
330       u_number += 1;
331 
332       assert(cell);
333       assert(edf);
334 
335       ref->u = u_number;
336       ref->cell = cell;
337       ref->property = 0;
338       ref->next = edf->celref;
339       edf->celref = ref;
340 
341       return ref;
342 }
343 
edif_cellref_pstring(edif_cellref_t ref,const char * name,const char * value)344 void edif_cellref_pstring(edif_cellref_t ref, const char*name,
345 			   const char*value)
346 {
347       struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
348       prp->name = name;
349       prp->ptype = PRP_STRING;
350       prp->value_.str = value;
351       prp->next = ref->property;
352       ref->property = prp;
353 }
354 
edif_cellref_pinteger(edif_cellref_t ref,const char * name,int value)355 void edif_cellref_pinteger(edif_cellref_t ref, const char*name, int value)
356 {
357       struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
358       prp->name = name;
359       prp->ptype = PRP_INTEGER;
360       prp->value_.num = value;
361       prp->next = ref->property;
362       ref->property = prp;
363 }
364 
edif_joint_create(edif_t edf)365 edif_joint_t edif_joint_create(edif_t edf)
366 {
367       edif_joint_t jnt = malloc(sizeof(struct edif_joint_s));
368 
369       jnt->name = 0;
370       jnt->links = 0;
371       jnt->next  = edf->nexa;
372       edf->nexa  = jnt;
373       return jnt;
374 }
375 
edif_joint_of_nexus(edif_t edf,ivl_nexus_t nex)376 edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex)
377 {
378       void*tmp = ivl_nexus_get_private(nex);
379       edif_joint_t jnt;
380 
381       if (tmp == 0) {
382 	    jnt = edif_joint_create(edf);
383 	    ivl_nexus_set_private(nex, jnt);
384 	    return jnt;
385       }
386 
387       jnt = (edif_joint_t) tmp;
388       return jnt;
389 }
390 
edif_joint_rename(edif_joint_t jnt,const char * name)391 void edif_joint_rename(edif_joint_t jnt, const char*name)
392 {
393       assert(jnt->name == 0);
394       jnt->name = name;
395 }
396 
edif_add_to_joint(edif_joint_t jnt,edif_cellref_t cell,unsigned port)397 void edif_add_to_joint(edif_joint_t jnt, edif_cellref_t cell, unsigned port)
398 {
399       struct joint_cell_* jc = malloc(sizeof(struct joint_cell_));
400 
401       jc->cell = cell;
402       jc->port = port;
403       jc->next = jnt->links;
404       jnt->links = jc;
405 }
406 
fprint_property(FILE * fd,const struct cellref_property_ * prp)407 static void fprint_property(FILE*fd, const struct cellref_property_*prp)
408 {
409       fprintf(fd, "(property %s ", prp->name);
410       switch (prp->ptype) {
411 	  case PRP_NONE:
412 	    break;
413 	  case PRP_STRING:
414 	    fprintf(fd, "(string \"%s\")", prp->value_.str);
415 	    break;
416 	  case PRP_INTEGER:
417 	    fprintf(fd, "(integer %ld)", prp->value_.num);
418 	    break;
419       }
420       fprintf(fd, ")");
421 }
422 
423 /*
424  * This function takes all the data structures that have been
425  * assembled by the code generator, and writes them into an EDIF
426  * formatted file.
427  */
edif_print(FILE * fd,edif_t edf)428 void edif_print(FILE*fd, edif_t edf)
429 {
430       edif_xlibrary_t xlib;
431       edif_cell_t cell;
432       edif_cellref_t ref;
433       edif_joint_t jnt;
434       struct cellref_property_*prp;
435       unsigned idx;
436 
437       fprintf(fd, "(edif %s\n", edf->name);
438       fprintf(fd, "    (edifVersion 2 0 0)\n");
439       fprintf(fd, "    (edifLevel 0)\n");
440       fprintf(fd, "    (keywordMap (keywordLevel 0))\n");
441       fprintf(fd, "    (status\n");
442       fprintf(fd, "     (written\n");
443       fprintf(fd, "        (timeStamp 0 0 0 0 0 0)\n");
444       fprintf(fd, "        (author \"unknown\")\n");
445       fprintf(fd, "        (program \"Icarus Verilog/fpga.tgt\")))\n");
446       fflush(fd);
447 
448       for (xlib = edf->xlibs ;  xlib ;  xlib = xlib->next) {
449 
450 	    fprintf(fd, "    (external %s "
451 		    "(edifLevel 0) "
452 		    "(technology (numberDefinition))\n",
453 		    xlib->name);
454 
455 	    for (cell = xlib->cells ;  cell ;  cell = cell->next) {
456 		  fprintf(fd, "      (cell %s (cellType GENERIC)\n",
457 			  cell->name);
458 		  fprintf(fd, "            (view net\n"
459 			      "              (viewType NETLIST)\n"
460 			      "              (interface");
461 
462 		  for (idx = 0 ;  idx < cell->nports ;  idx += 1) {
463 			struct __cell_port*pp = cell->ports + idx;
464 			fprintf(fd, "\n                (port %s", pp->name);
465 			switch (pp->dir) {
466 			    case IVL_SIP_INPUT:
467 			      fprintf(fd, " (direction INPUT)");
468 			      break;
469 			    case IVL_SIP_OUTPUT:
470 			      fprintf(fd, " (direction OUTPUT)");
471 			      break;
472 			    case IVL_SIP_INOUT:
473 			      fprintf(fd, " (direction INOUT)");
474 			      break;
475 			    default:
476 			      break;
477 			}
478 
479 			for (prp = pp->property ;  prp ;  prp=prp->next) {
480 			      fprintf(fd, " ");
481 			      fprint_property(fd, prp);
482 			}
483 
484 			fprintf(fd, ")");
485 		  }
486 
487 		  for (prp = cell->property ;  prp ;  prp = prp->next) {
488 			fprintf(fd, "\n                ");
489 			fprint_property(fd, prp);
490 		  }
491 		  fprintf(fd, ")))\n");
492 	    }
493 
494 	    fprintf(fd, "    )\n"); /* terminate (external ...) sexp */
495       }
496       fflush(fd);
497 
498 	/* Write out the library header */
499       fprintf(fd, "    (library DESIGN\n");
500       fprintf(fd, "      (edifLevel 0)\n");
501       fprintf(fd, "      (technology (numberDefinition))\n");
502 
503 	/* The root module is a cell in the library. */
504       fprintf(fd, "      (cell %s\n", edf->name);
505       fprintf(fd, "        (cellType GENERIC)\n");
506       fprintf(fd, "        (view net\n");
507       fprintf(fd, "          (viewType NETLIST)\n");
508       fprintf(fd, "          (interface\n");
509 
510       for (idx = 0 ;  idx < edf->nports ;  idx += 1) {
511 	    fprintf(fd, "            (port ");
512 	    if (edf->ports[idx].ename == 0)
513 		  fprintf(fd, "%s ", edf->ports[idx].name);
514 	    else
515 		  fprintf(fd, "(rename %s \"%s\") ",
516 			  edf->ports[idx].ename,
517 			  edf->ports[idx].name);
518 
519 	    switch (edf->ports[idx].dir) {
520 		case IVL_SIP_INPUT:
521 		  fprintf(fd, "(direction INPUT)");
522 		  break;
523 		case IVL_SIP_OUTPUT:
524 		  fprintf(fd, "(direction OUTPUT)");
525 		  break;
526 		case IVL_SIP_INOUT:
527 		  fprintf(fd, "(direction INOUT)");
528 		  break;
529 		default:
530 		  break;
531 	    }
532 	    fprintf(fd, ")\n");
533       }
534 
535       fprintf(fd, "          )\n"); /* end the (interface ) sexp */
536       fflush(fd);
537 
538       fprintf(fd, "          (contents\n");
539 
540 	/* Display all the instances. */
541       for (ref = edf->celref ;  ref ;  ref = ref->next) {
542 
543 	    assert(ref->cell);
544 
545 	    fprintf(fd, "(instance U%u (viewRef net "
546 		    "(cellRef %s (libraryRef %s)))",
547 		    ref->u, ref->cell->name, ref->cell->xlib->name);
548 
549 	    for (prp = ref->property ;  prp ;  prp = prp->next) {
550 		  fprintf(fd, " ");
551 		  fprint_property(fd, prp);
552 	    }
553 
554 	    fprintf(fd, ")\n");
555       }
556 
557       fflush(fd);
558 
559 	/* Display all the joints. */
560       idx = 0;
561       for (jnt = edf->nexa ;  jnt ;  jnt = jnt->next, idx += 1) {
562 	    struct joint_cell_*jc;
563 
564 	    fprintf(fd, "(net ");
565 	    if (jnt->name != 0)
566 		  fprintf(fd, "(rename N%u \"%s\")", idx, jnt->name);
567 	    else
568 		  fprintf(fd, "N%u", idx);
569 	    fprintf(fd, " (joined");
570 
571 	    for (jc = jnt->links ;  jc ;  jc = jc->next) {
572 		  if (jc->cell) {
573 			fprintf(fd, " (portRef %s (instanceRef U%u))",
574 				jc->cell->cell->ports[jc->port].name,
575 				jc->cell->u);
576 		  } else {
577 			  /* Reference to a port of the main cell. */
578 			if (edf->ports[jc->port].ename)
579 			      fprintf(fd, " (portRef %s)",
580 				      edf->ports[jc->port].ename);
581 			else
582 			      fprintf(fd, " (portRef %s)",
583 				      edf->ports[jc->port].name);
584 		  }
585 	    }
586 	    fprintf(fd, "))\n");
587       }
588 
589       fprintf(fd, "          )\n"); /* end the (contents...) sexp */
590 
591       fprintf(fd, "        )\n"); /* end the (view ) sexp */
592       fprintf(fd, "      )\n"); /* end the (cell ) sexp */
593       fprintf(fd, "    )\n"); /* end the (library DESIGN) sexp */
594 
595 	/* Make an instance of the defined object */
596       fprintf(fd, "    (design %s\n", edf->name);
597       fprintf(fd, "      (cellRef %s (libraryRef DESIGN))\n", edf->name);
598 
599       for (prp = edf->property ;  prp ;  prp = prp->next) {
600 	    fprintf(fd, "       ");
601 	    fprint_property(fd, prp);
602 	    fprintf(fd, "\n");
603       }
604 
605       fprintf(fd, "    )\n");
606 
607 
608 
609       fprintf(fd, ")\n");
610       fflush(fd);
611 }
612