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 Fri Jan  9 19:52:33 2009
19 ****************************************************************************/
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <pwd.h>
27 #include "hash.h"
28 #include "parser.h"
29 #include "grammar.h"
30 #include "gmac.h"
31 
32 /****************************************************************************
33  *
34  * This is the Gate Microcode and Assembler Compiler (gmac).
35  *
36  * Code example:
37  *
38 
39 // Microcode memory bank declarations
40 
41 microcode bank[31:0] iunit.m1;
42 microcode bank[63:32] iunit.m2;
43 microcode bank[95:64] iunit.m3;
44 map bank[7:0] iunit.map;
45 
46 macrocode bank[7:0] iunit.m1;
47 
48 // Microcode field declarations
49 
50 field ~ldir[0], ~ldpc[1], cin[2], next[95:88];
51 field func[7:4]={add=0, sub=1, lshift=2, rshift=3, arshift=4,
52   rroll=5, lroll=6, and=7, or=8, xor=9, not=10, neg=11, nand=12,
53   nor=13, eq=14, nop=15 };
54 field mcpc[87:85]={next=0, jmp=1, jne=2, jlt=3, jgt=4, jeq=5, jc=6, jmap=7};
55 field next[31:24];
56 
57 // Assembler declarations
58 
59 registers R0=0, R1=1, R2=2, R3=3, R4=4, R5=5, R6=6, R7=7;
60 
61 operands basic {
62     %1,%2 = { +0[3:2]=0, +0[1:0]=0, +1[7:4]=%1, +1[3:0]=%2 };
63     %1,#2 = { +0[3:2]=0, +0[1:0]=1, +1[7:4]=%1, +2=#2[7:0], +3=#2[15:8] };
64     %1,%2,#3 = { +0[3:2]=0, +0[1:0]=1, +1[7:4]=%1, +1[3:0]=%2,
65 			+2=#3[7:0], +3=#3[15:8] };
66     #1(%2),%3 = { +0[3:2]=0 };
67     (%1),%2 = { +0[3:2]=0 };
68 };
69 
70 op add {
71   map 0x21 = add;       // Opcode to microcode mapping
72   +0[7:4]=0x21;          // Top nibble of first word contians opcode
73   operands basic;
74 };
75 
76 begin microcode @ 0
77   start:	ldpc  func=nop mcpc=next;
78   		mcpc=jmap;
79   nop:	mcpc=jne next=add ;
80   add:	mcpc=jne next=nop;
81 end
82 
83 begin macrocode @ 0
84   mov	#123,R0;
85   mov	#128,R1;
86   mov	(R0),R3;
87   add	R1,R3;
88   mov	R3,(R0);
89 end
90 
91 ****************************************************************************/
92 
93 int outputFormat = OF_VERILOG;
94 
95 Code *ucode = 0;
96 Code *mcode = 0;
97 Code *map = 0;
98 
99 /*
100  * These undoable object functions are only used in the main tkgate code, but
101  * since they are used in the common hash table code we provide stubs here for
102  * the hash table code to use.
103  */
ob_malloc(int s,char * x)104 void *ob_malloc(int s,char *x) { return malloc(s); }
ob_calloc(int n,int s,char * x)105 void *ob_calloc(int n,int s,char *x) { return calloc(n,s); }
ob_free(void * p)106 void ob_free(void *p) { free(p); }
ob_strdup(char * s)107 char *ob_strdup(char *s) { return strdup(s); }
ob_set_type(void * o,char * n)108 void ob_set_type(void *o,char *n) {}
ob_touch(void * o)109 void ob_touch(void *o) {}
110 
111 static unsigned last_addr = 0;
112 
printindent(int n,FILE * f)113 void printindent(int n,FILE *f)
114 {
115   while (n-- > 0) fprintf(f," ");
116 }
117 
118 
Range_print(Range * R,FILE * f)119 void Range_print(Range *R,FILE *f)
120 {
121   if (R->msb == -1 && R->lsb == -1) return;
122 
123   if (R->msb == R->lsb)
124     fprintf(f,"[%d]",R->msb);
125   else
126     fprintf(f,"[%d:%d]",R->msb,R->lsb);
127 }
128 
new_Bank(char * name,int msb,int lsb,int start,int end)129 Bank *new_Bank(char *name,int msb,int lsb,int start,int end)
130 {
131   Bank *b = new(Bank);
132 
133   b->b_name = strdup(name);
134   b->b_range.msb = msb;
135   b->b_range.lsb = lsb;
136   b->b_start = imin(start,end);
137   b->b_end = imax(start,end);
138 
139   return b;
140 }
141 
new_MemInst(int addr,int dmsb,int dlsb)142 MemInst *new_MemInst(int addr,int dmsb,int dlsb)
143 {
144   MemInst *mi = new(MemInst);
145 
146   mi->mi_addr = addr;
147   mi->mi_dRange.msb = dmsb;
148   mi->mi_dRange.lsb = dlsb;
149   mi->mi_sRange.msb = dmsb-dlsb;
150   mi->mi_sRange.lsb = 0;
151   mi->mi_valType = NT_VALUE;
152   mi->mi_offset = 0;
153   mi->mi_value.d = 0;
154   mi->mi_next = 0;
155 
156   return mi;
157 }
158 
MemInst_setNumValue(MemInst * mi,int val)159 void MemInst_setNumValue(MemInst *mi,int val)
160 {
161   mi->mi_valType = NT_VALUE;
162   mi->mi_offset = 0;
163   mi->mi_value.d = val;
164 }
165 
MemInst_setSymValue(MemInst * mi,char * val,int offset,int msb,int lsb)166 void MemInst_setSymValue(MemInst *mi,char *val,int offset,int msb,int lsb)
167 {
168   mi->mi_valType = NT_SYMBOL;
169   mi->mi_offset = offset;
170   mi->mi_value.s = val;
171   mi->mi_sRange.msb = msb;
172   mi->mi_sRange.lsb = lsb;
173 }
174 
MemInst_makeReal(MemInst * mi,Code * c,Code * xc)175 int MemInst_makeReal(MemInst *mi,Code *c,Code *xc)
176 {
177   int *n;
178   char *gname = 0;
179 
180   if (mi->mi_valType == NT_VALUE) return 0;
181 
182   if ((gname = strchr(mi->mi_value.s,'.')))
183     gname++;
184 
185   n = Code_findLabel(c,mi->mi_value.s);
186   if (!n && gname) n = Code_findLabel(c,gname);
187   if (!n && xc) n = Code_findLabel(xc,mi->mi_value.s);
188   if (!n && xc && gname) n = Code_findLabel(xc,gname);
189 
190   if (!n) {
191     yyerror("Undefined symbol '%s'.",mi->mi_value.s);
192     return -1;
193   }
194 
195   mi->mi_value.d = *n + mi->mi_offset;
196   mi->mi_valType = NT_VALUE;
197 
198   return 0;
199 }
200 
MemInst_print(MemInst * mi,FILE * f)201 void MemInst_print(MemInst *mi,FILE *f)
202 {
203   fprintf(f,"<@%x [%d:%d]",mi->mi_addr,mi->mi_dRange.msb,mi->mi_dRange.lsb);
204   switch (mi->mi_valType) {
205   case NT_VALUE :
206     fprintf(f,"=0x%x",mi->mi_value.d);
207     break;
208   case NT_SYMBOL :
209     fprintf(f,"=%s",mi->mi_value.s);
210     break;
211   }
212   fprintf(f,">");
213 }
214 
MemInst_value(MemInst * mi)215 int MemInst_value(MemInst *mi)
216 {
217   int n;
218 
219   if (mi->mi_sRange.msb < 0) return mi->mi_value.d;
220 
221   n = mi->mi_sRange.msb-mi->mi_sRange.lsb+1;
222   return (mi->mi_value.d >> mi->mi_sRange.lsb) & NMASK(n);
223 }
224 
225 
new_MemProg(int nbits,int base)226 MemProg *new_MemProg(int nbits,int base)
227 {
228   MemProg *mb = new(MemProg);
229 
230   mb->mb_nbits = nbits;
231   mb->mb_base = mb->mb_current = base;
232   mb->mb_first = mb->mb_last = 0;
233 
234   return mb;
235 }
236 
MemProg_addInst(MemProg * mb,MemInst * mi)237 void MemProg_addInst(MemProg *mb,MemInst *mi)
238 {
239   if (mb->mb_last) {
240     mb->mb_last->mi_next = mi;
241     mb->mb_last = mi;
242   } else
243     mb->mb_first = mb->mb_last = mi;
244   mi->mi_next = 0;
245 }
246 
new_UField(char * name,int msb,int lsb,int isComp)247 UField *new_UField(char *name,int msb,int lsb,int isComp)
248 {
249   UField *f = new(UField);
250 
251   f->uf_name = strdup(name);
252   f->uf_msb = msb;
253   f->uf_lsb = lsb;
254   f->uf_isNegative = isComp;
255   SHash_init(&f->uf_codes);
256 
257   return f;
258 }
259 
new_Opr(int type,int rnum,int dnum)260 Opr *new_Opr(int type,int rnum,int dnum)
261 {
262   Opr *O = new(Opr);
263 
264   O->od_type = type;
265   O->od_reg = rnum;
266   O->od_val = dnum;
267 
268   return O;
269 }
270 
Opr_print(Opr * O,FILE * f)271 void Opr_print(Opr *O,FILE *f)
272 {
273   switch (O->od_type) {
274   case AM_IMMEDIATE :
275     fprintf(f,"#%d",O->od_val);
276     break;
277   case AM_IMMIND :
278     fprintf(f,"(#%d)",O->od_val);
279     break;
280   case AM_DIRECT :
281     fprintf(f,"%%%d",O->od_reg);
282     break;
283   case AM_INDIRECT :
284     fprintf(f,"(%%%d)",O->od_reg);
285     break;
286   case AM_INDEXED :
287     fprintf(f,"#%d(%%%d)",O->od_val,O->od_reg);
288     break;
289   default :
290     fprintf(f,"?[#%d %% %d]",O->od_val,O->od_reg);
291     break;
292   }
293 }
294 
new_OpInst(int otype,int base,int dmsb,int dlsb,int val,int smsb,int slsb,int offset)295 OpInst *new_OpInst(int otype,int base,int dmsb,int dlsb,int val,int smsb,int slsb,int offset)
296 {
297   OpInst *oi = new(OpInst);
298 
299   oi->oi_type = otype;
300   oi->oi_base = base;
301   oi->oi_dRange.msb = dmsb;
302   oi->oi_dRange.lsb = dlsb;
303   oi->oi_sRange.msb = smsb;
304   oi->oi_sRange.lsb = slsb;
305   oi->oi_value = val;
306 
307   if (oi->oi_sRange.msb < 0) {
308     oi->oi_sRange.msb = oi->oi_dRange.msb-oi->oi_dRange.lsb;
309     oi->oi_sRange.lsb = 0;
310   }
311 
312   return oi;
313 }
314 
OpInst_print(OpInst * oi,FILE * f)315 void OpInst_print(OpInst *oi,FILE *f)
316 {
317   fprintf(f,"+%d",oi->oi_base);
318   Range_print(&oi->oi_dRange,f);
319   fprintf(f,"=");
320 
321   switch (oi->oi_type) {
322   case OI_DATA :
323     fprintf(f,"%d",oi->oi_value);
324     break;
325   case OI_REGOP :
326     fprintf(f,"%%%d",oi->oi_value);
327     break;
328   case OI_NUMOP :
329     fprintf(f,"#%d",oi->oi_value);
330     break;
331   case OI_RELNUMOP :
332     fprintf(f,"#%d-@%d",oi->oi_value,oi->oi_offset);
333     break;
334   default :
335     fprintf(f,"?");
336     break;
337   }
338   Range_print(&oi->oi_sRange,f);
339 }
340 
OpInst_genMemInst(OpInst * oi,MemProg * mp,int * r,Number ** n)341 MemInst *OpInst_genMemInst(OpInst *oi,MemProg *mp,int *r,Number **n)
342 {
343   MemInst *mi;
344   unsigned mask;
345   int b;
346 
347   if ((!r || !n) && oi->oi_type != OI_DATA)
348     return 0;
349 
350 
351   if (oi->oi_dRange.msb >= 0) {
352     mi = new_MemInst(MemProg_current(mp)+oi->oi_base,oi->oi_dRange.msb,oi->oi_dRange.lsb);
353     b = oi->oi_dRange.msb-oi->oi_dRange.lsb+1;
354   }  else {
355     mi = new_MemInst(MemProg_current(mp)+oi->oi_base,mp->mb_nbits-1,0);
356     b = mp->mb_nbits;
357   }
358 
359   if (b < 32)
360     mask = (1 << b)-1;
361   else
362     mask = 0xffffffff;
363 
364   switch (oi->oi_type) {
365   case OI_DATA :
366     MemInst_setNumValue(mi,mask&(oi->oi_value >> oi->oi_sRange.lsb));
367     break;
368   case OI_REGOP :
369     MemInst_setNumValue(mi,mask&(r[oi->oi_value] >> oi->oi_sRange.lsb));
370     break;
371   case OI_NUMOP :
372     if (n[oi->oi_value]->ntype == NT_VALUE)
373       MemInst_setNumValue(mi,mask&(n[oi->oi_value]->v.d  >> oi->oi_sRange.lsb));
374     else
375       MemInst_setSymValue(mi,n[oi->oi_value]->v.s,0,oi->oi_sRange.msb,oi->oi_sRange.lsb);
376     break;
377   case OI_RELNUMOP :
378     if (n[oi->oi_value]->ntype == NT_VALUE)
379       MemInst_setNumValue(mi,mask&((n[oi->oi_value]->v.d-MemProg_current(mp))  >> oi->oi_sRange.lsb));
380     else
381       MemInst_setSymValue(mi,n[oi->oi_value]->v.s,-MemProg_current(mp),oi->oi_sRange.msb,oi->oi_sRange.lsb);
382     break;
383   }
384   return mi;
385 }
386 
new_OprDef(int nbits)387 OprDef *new_OprDef(int nbits)
388 {
389   OprDef *D = new(OprDef);
390 
391   D->od_numOprs = 0;
392   D->od_oprs = (Opr**)malloc(sizeof(Opr*));
393 
394   D->od_numInsts = 0;
395   D->od_insts = (OpInst**)malloc(sizeof(OpInst*));
396 
397   D->od_next = 0;
398 
399   return D;
400 }
401 
OprDef_addOpInst(OprDef * D,OpInst * I)402 void OprDef_addOpInst(OprDef *D,OpInst *I)
403 {
404   D->od_insts = (OpInst**)realloc(D->od_insts,(D->od_numInsts+1)*sizeof(OpInst*));
405   D->od_insts[D->od_numInsts++] = I;
406 }
407 
OprDef_addOpr(OprDef * D,int type,int rnum,int dnum)408 void OprDef_addOpr(OprDef *D,int type,int rnum,int dnum)
409 {
410   D->od_oprs = (Opr**)realloc(D->od_oprs,(D->od_numOprs+1)*sizeof(Opr*));
411   D->od_oprs[D->od_numOprs++] = new_Opr(type,rnum,dnum);
412 }
413 
OprDef_print(OprDef * D,FILE * f)414 void OprDef_print(OprDef *D,FILE *f)
415 {
416   int i;
417 
418   if (D->od_numOprs == 0)
419     fprintf(f,"-");
420   else {
421     for (i = 0;i < D->od_numOprs;i++) {
422       if (i) fprintf(f,", ");
423       Opr_print(D->od_oprs[i],f);
424     }
425   }
426   fprintf(f," = {");
427   for (i = 0;i < D->od_numInsts;i++) {
428     if (i) fprintf(f,", ");
429     OpInst_print(D->od_insts[i],f);
430   }
431 
432   fprintf(f,"}\n");
433 }
434 
OprDef_isMatch(OprDef * od,int * opr,int nopr)435 int OprDef_isMatch(OprDef *od,int *opr,int nopr)
436 {
437   int i;
438 
439   if (nopr != od->od_numOprs)
440     return 0;
441 
442   for (i = 0;i < nopr;i++)
443     if (od->od_oprs[i]->od_type != opr[i])
444       return 0;
445 
446   return 1;
447 }
448 
OprDef_check(OprDef * od)449 int OprDef_check(OprDef *od)
450 {
451   int a[MAXOPRS*2];
452   int i;
453 
454   for (i = 0;i < MAXOPRS*2;i++)
455     a[i] = -1;
456 
457   for (i = 0;i < od->od_numOprs;i++) {
458     Opr *p = od->od_oprs[i];
459     switch (p->od_type) {
460     case AM_IMMEDIATE :
461     case AM_IMMIND :
462       if (p->od_val < 0 || p->od_val >= MAXOPRS*2) return GE_IDRANGE;
463       if (a[p->od_val] >= 0) return GE_REDECID;
464       a[p->od_val] = 1;
465       break;
466     case AM_DIRECT :
467     case AM_INDIRECT :
468       if (p->od_reg < 0 || p->od_reg >= MAXOPRS*2) return GE_IDRANGE;
469       if (a[p->od_reg] >= 0) return GE_REDECID;
470       a[p->od_reg] = 2;
471       break;
472     case AM_INDEXED :
473       if (p->od_reg < 0 || p->od_reg >= MAXOPRS*2) return GE_IDRANGE;
474       if (p->od_val < 0 || p->od_val >= MAXOPRS*2) return GE_IDRANGE;
475       if (a[p->od_reg] >= 0) return GE_REDECID;
476       if (a[p->od_val] >= 0) return GE_REDECID;
477       a[p->od_val] = 1;
478       a[p->od_reg] = 2;
479       break;
480     }
481   }
482 
483   for (i = 0;i < od->od_numInsts;i++) {
484     OpInst *oi = od->od_insts[i];
485     switch (oi->oi_type) {
486     case OI_REGOP :
487       if (oi->oi_value < 0 || oi->oi_value >= MAXOPRS*2) return GE_IDRANGE;
488       if (a[oi->oi_value] == 1) return GE_BADTYPE;
489       if (a[oi->oi_value] != 2) return GE_UNDEFID;
490       break;
491     case OI_NUMOP :
492     case OI_RELNUMOP :
493       if (oi->oi_value < 0 || oi->oi_value >= MAXOPRS*2) return GE_IDRANGE;
494       if (a[oi->oi_value] == 2) return GE_BADTYPE;
495       if (a[oi->oi_value] != 1) return GE_UNDEFID;
496       break;
497       break;
498     }
499   }
500 
501   return GE_OK;
502 }
503 
504 
new_OprGroup(char * name,int nbits)505 OprGroup *new_OprGroup(char *name,int nbits)
506 {
507   OprGroup *G = new(OprGroup);
508 
509   G->og_name = strdup(name);
510   G->og_nbits = nbits;
511   G->og_numOdefs = 0;
512   G->og_odefs = (OprDef**)malloc(sizeof(OprDef*));
513 
514   return G;
515 }
516 
OprGroup_addOprDef(OprGroup * G)517 OprDef *OprGroup_addOprDef(OprGroup *G)
518 {
519   OprDef *D = new_OprDef(G->og_nbits);
520 
521   G->og_odefs = (OprDef**)realloc(G->og_odefs,(G->og_numOdefs+1)*sizeof(OprDef*));
522   G->og_odefs[G->og_numOdefs++] = D;
523 
524   return D;
525 }
526 
OprGroup_print(OprGroup * og,int indent,FILE * f)527 void OprGroup_print(OprGroup *og,int indent,FILE *f)
528 {
529   int i;
530 
531   printindent(indent,f); fprintf(f,"operands %s {\n",og->og_name);
532   for (i = 0;i < og->og_numOdefs;i++) {
533     printindent(indent+2,f);
534     OprDef_print(og->og_odefs[i],f);
535   }
536   printindent(indent,f); fprintf(f,"}\n");
537 }
538 
539 
OprGroup_findOpr(OprGroup * og,int * opr,int nopr)540 OprDef *OprGroup_findOpr(OprGroup *og,int *opr,int nopr)
541 {
542   int i;
543 
544   for (i = 0;i < og->og_numOdefs;i++) {
545     if (OprDef_isMatch(og->og_odefs[i],opr,nopr))
546       return og->og_odefs[i];
547   }
548   return 0;
549 }
550 
new_OpDef(char * name,int nbits)551 OpDef *new_OpDef(char *name,int nbits)
552 {
553   OpDef *od = new(OpDef);
554 
555   od->od_name = strdup(name);
556   od->od_numGroups = 0;
557   od->od_groups = (OprGroup**)malloc(sizeof(OprGroup*));
558   od->od_groups[0] = new_OprGroup("*local*",nbits);
559   od->od_numInsts = 0;
560   od->od_insts = (OpInst**)malloc(sizeof(OpInst*));
561 
562   return od;
563 }
564 
OpDef_addOpInst(OpDef * od,OpInst * oi)565 void OpDef_addOpInst(OpDef *od,OpInst *oi)
566 {
567   od->od_insts = (OpInst**)realloc(od->od_insts,(od->od_numInsts+1)*sizeof(OpInst*));
568   od->od_insts[od->od_numInsts++] = oi;
569 }
570 
OpDef_addGroup(OpDef * od,OprGroup * og)571 void OpDef_addGroup(OpDef *od,OprGroup *og)
572 {
573   od->od_groups = (OprGroup**)realloc(od->od_groups,(od->od_numGroups+1)*sizeof(OprGroup*));
574   od->od_groups[od->od_numGroups++] = og;
575 }
576 
OpDef_print(OpDef * od,FILE * f)577 void OpDef_print(OpDef *od,FILE *f)
578 {
579   int i;
580 
581   fprintf(f,"op %s {\n",od->od_name);
582   for (i = 0;i < od->od_numInsts;i++) {
583     fprintf(f,"   ");
584     OpInst_print(od->od_insts[i],f);
585     fprintf(f,"\n");
586   }
587   for (i = 0;i < od->od_numGroups;i++) {
588     OprGroup_print(od->od_groups[i],3,f);
589   }
590   fprintf(f,"}\n");
591 }
592 
OpDef_findOpr(OpDef * od,int * opr,int nopr)593 OprDef *OpDef_findOpr(OpDef *od,int *opr,int nopr)
594 {
595   OprDef *d;
596   int i;
597 
598   for (i = 0;i < od->od_numGroups;i++) {
599     if ((d = OprGroup_findOpr(od->od_groups[i],opr,nopr)))
600       return d;
601   }
602   return 0;
603 }
604 
605 
606 
new_Code(int type)607 Code *new_Code(int type)
608 {
609   Code *c = new(Code);
610 
611   c->c_type = type;
612   SHash_init(&c->c_ops);
613   SHash_init(&c->c_oprs);
614   SHash_init(&c->c_labels);
615 
616   c->c_nbits = 0;
617   c->c_numBlocks = 0;
618   c->c_numBanks = 0;
619 
620   return c;
621 }
622 
Code_addBank(Code * c,Bank * b)623 void Code_addBank(Code *c,Bank *b)
624 {
625   c->c_nbits = imax(c->c_nbits,b->b_range.msb+1);
626   c->c_banks[c->c_numBanks++] = b;
627 }
628 
Code_addMemProg(Code * c,MemProg * mb)629 void Code_addMemProg(Code *c,MemProg *mb)
630 {
631   c->c_blocks[c->c_numBlocks++] = mb;
632 }
633 
Code_addField(Code * c,UField * f)634 void Code_addField(Code *c,UField *f)
635 {
636   SHash_insert(&c->c_ops,UField_name(f),f);
637 }
638 
Code_addLabel(Code * c,char * lab,int addr)639 void Code_addLabel(Code *c,char *lab,int addr)
640 {
641   int *n = new(int);
642   *n = addr;
643   SHash_insert(&c->c_labels,lab,n);
644 }
645 
Code_realizeMems(Code * c,Code * xc)646 int Code_realizeMems(Code *c,Code *xc)
647 {
648   int i;
649   int code = 0;
650 
651   for (i = 0;i < c->c_numBlocks;i++) {
652     MemProg *mb = c->c_blocks[i];
653     MemInst *mi;
654 
655     for (mi = MemProg_firstMI(mb);mi;mi = MemInst_next(mi))
656       if (MemInst_makeReal(mi,c,xc) < 0)
657 	code = -1;
658   }
659 
660   return code;
661 }
662 
gen_reset()663 static void gen_reset()
664 {
665   last_addr = 0;
666 }
667 
668 /*
669  * Generate a word of output
670  */
gen_word(FILE * f,unsigned addr,unsigned data,int * num_on_line)671 static void gen_word(FILE *f,unsigned addr,unsigned data,int *num_on_line)
672 {
673   int do_addr = 0;
674 
675   if (*num_on_line == WORDSPERLINE) {
676     fprintf(f,"\n");
677     *num_on_line = 0;
678   }
679 
680   switch (outputFormat) {
681   case OF_OLDGATE :
682     if (*num_on_line == 0)
683       fprintf(f,"%x/",addr);
684     fprintf(f," %x",data);
685     break;
686   case OF_VERILOG:
687     //
688     // No current address, or a skip in addresses
689     //
690     if ((last_addr+1) != addr)
691       do_addr = 1;
692 
693     //
694     // Address begins a block of 256
695     //
696     if ((addr & 0xff) == 0)
697       do_addr = 1;
698 
699     if (do_addr) {
700       fprintf(f,"\n@%x\n",addr);
701       (*num_on_line) = 0;
702     }
703     if (*num_on_line !=  0)
704       fprintf(f," ");
705     fprintf(f,"%x",data);
706     last_addr = addr;
707     break;
708   }
709   (*num_on_line)++;
710 }
711 
Code_generate(Code * c,FILE * f)712 void Code_generate(Code *c,FILE *f)
713 {
714   unsigned data;
715   int i,j;
716 
717   data = 0;
718 
719   for (i = 0;i < c->c_numBanks;i++) {
720     Bank *b = c->c_banks[i];
721     MemInst *mi;
722 
723     if (c->c_numBlocks == 0) continue;
724 
725     if (outputFormat == OF_VERILOG)
726       fprintf(f,"\n@memory %s\n",Bank_name(b));
727     else
728       fprintf(f,"\nmemory %s\n",Bank_name(b));
729 
730     gen_reset();
731 
732     for (j = 0;j < c->c_numBlocks;j++) {
733       MemProg *mb = c->c_blocks[j];
734       int num_on_line = 0;
735       int cur_addr = -1;
736 
737       if (!Bank_noAddrRange(b) && !isOverlap(Bank_start(b),Bank_end(b),
738 					     MemProg_start(mb),MemProg_end(mb)))
739 	continue;
740 
741       for (mi = MemProg_firstMI(mb);mi;mi = MemInst_next(mi)) {
742 	int shift;
743 	HashElem *E;
744 
745 	if (!Bank_noAddrRange(b)) {
746 	  if (mi->mi_addr < Bank_start(b)) { continue; }
747 	  if (mi->mi_addr > Bank_end(b)) { break; }
748 	}
749 
750 	if (mi->mi_addr != cur_addr) {
751 	  if (cur_addr >= 0) {
752 	    gen_word(f,cur_addr,data,&num_on_line);
753 	    if (mi->mi_addr != cur_addr+1) {
754 	      fprintf(f,"\n");
755 	      num_on_line = 0;
756 	    }
757 	  }
758 
759 	  data = 0;
760 	  cur_addr = mi->mi_addr;
761 
762 	  if (c->c_type == MICROCODE) {
763 	    for (E = Hash_first(&c->c_ops);E;E = Hash_next(&c->c_ops,E)) {
764 	      UField *F = (UField *) HashElem_obj(E);
765 	      int x;
766 
767 	      if (!F->uf_isNegative) continue;
768 	      x = F->uf_lsb - Bank_lsb(b);
769 	      if (x >= 0  && x < 32) {
770 		data |= 1 << x;
771 	      }
772 	    }
773 	  }
774 	}
775 
776 	if (isOverlap(mi->mi_dRange.lsb,mi->mi_dRange.msb,Bank_lsb(b),Bank_msb(b))) {
777 	  shift = mi->mi_dRange.lsb-Bank_lsb(b);
778 	  if  (shift > 0)
779 	    data ^= MemInst_value(mi) << shift;
780 	  else
781 	    data ^= MemInst_value(mi) >> -shift;
782 	}
783       }
784       if (cur_addr >= 0)
785 	gen_word(f,cur_addr,data,&num_on_line);
786       fprintf(f,"\n");
787     }
788   }
789 }
790 
writeOutput(FILE * f)791 void writeOutput(FILE *f)
792 {
793   if (Code_numMBlocks(ucode)) {
794     Code_realizeMems(ucode,0);
795     Code_realizeMems(map,ucode);
796     Code_generate(ucode,f);
797     Code_generate(map,f);
798   }
799   if (Code_numMBlocks(mcode)) {
800     Code_realizeMems(mcode,0);
801     Code_generate(mcode,f);
802   }
803 }
804 
q_strcmp(const void * va,const void * vb)805 int q_strcmp(const void *va,const void *vb)
806 {
807   char *a = *(char**)va;
808   char *b = *(char**)vb;
809 
810   return strcmp(a,b);
811 }
812 
get_sorted_symbol_list(SHash * H)813 char **get_sorted_symbol_list(SHash *H)
814 {
815   HashElem *E;
816   char **sym_list;
817   int n = Hash_numElems(H);
818   int i;
819 
820   sym_list = (char**) malloc(sizeof(char*)*(n+1));
821   i = 0;
822   for (E = Hash_first(H);E;E = Hash_next(H,E)) {
823     sym_list[i++] = SHashElem_key(E);
824   }
825   if (n > 1)
826     qsort(sym_list,n,sizeof(char*),q_strcmp);
827 
828   return sym_list;
829 }
830 
writeMap(FILE * f)831 void writeMap(FILE *f)
832 {
833   int i;
834 
835   if (ucode) {
836     int n = Hash_numElems(&ucode->c_labels);
837     char **sym_list = get_sorted_symbol_list(&ucode->c_labels);
838 
839     fprintf(f,"Microcode Symbols (total=%d):\n",n);
840     fprintf(f,"  ---------------------------------------\n");
841     for (i = 0;i < n;i++) {
842       char *label = sym_list[i];
843       unsigned addr = *(unsigned*)SHash_find(&ucode->c_labels,label);
844       fprintf(f,"  %-30s %08x\n",label,addr);
845     }
846     fprintf(f,"\n\n");
847   }
848   if (mcode) {
849     int n = Hash_numElems(&mcode->c_labels);
850     char **sym_list = get_sorted_symbol_list(&mcode->c_labels);
851 
852     fprintf(f,"Macrocode Symbols (total=%d):\n",Hash_numElems(&mcode->c_labels));
853     fprintf(f,"  Global         Local\n");
854     fprintf(f,"  ---------------------------------------\n");
855     for (i = 0;i < n;i++) {
856       char *label = sym_list[i];
857       unsigned addr = *(unsigned*)SHash_find(&mcode->c_labels,label);
858       char *p = strchr(label,'.');
859       if (p)
860 	fprintf(f,"                 %-15s %08x\n",p+1,addr);
861       else
862 	fprintf(f,"  %-30s %08x\n",label,addr);
863     }
864     fprintf(f,"\n\n");
865   }
866 }
867 
868 
usage()869 void usage()
870 {
871   fprintf(stderr,"Usage: gmac [-o outfile][-m mapfile][infiles...]\n");
872   exit(1);
873 }
874 
main(int argc,char * argv[])875 int main(int argc,char *argv[])
876 {
877   //extern char *optarg;
878   //extern int optind;
879 #if OPTRESET
880   extern int optreset;
881 #endif
882   char *outf = 0;
883   char *mapFile = 0;
884   int c;
885 
886   mcode = new_Code(MACROCODE);
887   ucode = new_Code(MICROCODE);
888   map = new_Code(MAP);
889 
890   while (argc > 0) {
891     while ((c = getopt(argc,argv,"go:m:")) != EOF) {
892       switch (c) {
893       case 'g' :
894 	outputFormat = OF_OLDGATE;
895 	break;
896       case 'o' :
897 	if (outf) usage();
898 	outf = optarg;
899 	break;
900       case 'm' :
901 	if (mapFile) usage();
902 	mapFile = optarg;
903 	break;
904       default :
905 	usage();
906 	break;
907       }
908     }
909     argc -= optind;
910     argv += optind;
911 #if OPTRESET
912     optreset = 1;
913 #endif
914     optind = 0;
915     if (argc > 0) {
916       ParseFile(argv[0]);
917       argc--;
918       argv++;
919     }
920   }
921 
922   if (outf) {
923     FILE *f;
924 
925     if (!(f = fopen(outf,"w"))) {
926       fprintf(stderr,"Failed to open output file '%s'.",outf);
927     }
928     writeOutput(f);
929     fclose(f);
930   } else {
931     writeOutput(stdout);
932   }
933 
934   if (mapFile) {
935     FILE *f;
936 
937     if (!(f = fopen(mapFile,"w"))) {
938       fprintf(stderr,"Failed to open map file '%s' for output.",mapFile);
939     }
940     writeMap(f);
941     fclose(f);
942   }
943 
944 
945   return 0;
946 }
947 
948