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