OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [tools/] [vcdchk/] [vcdchk.c] - Blame information for rev 325

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 284 hellwig
/*
2
 * vcdchk.c -- check the value of a signal in a VCD file
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <stdarg.h>
10
#include <ctype.h>
11
 
12
 
13
#define MAX_LINE        200
14
#define MAX_NAME        1000
15
 
16
 
17
/**************************************************************/
18
 
19
 
20
typedef int Bool;
21
 
22
#define FALSE           0
23
#define TRUE            1
24
 
25
 
26
/**************************************************************/
27
 
28
 
29
Bool debugVCD = FALSE;
30
Bool debugCHK = FALSE;
31
Bool debugCheck = FALSE;
32
 
33
 
34
/**************************************************************/
35
 
36
 
37
void error(char *fmt, ...) {
38
  va_list ap;
39
 
40
  va_start(ap, fmt);
41
  printf("Error: ");
42
  vprintf(fmt, ap);
43
  printf("\n");
44
  va_end(ap);
45
  exit(1);
46
}
47
 
48
 
49
void *allocate(int size) {
50
  void *res;
51
 
52
  res = malloc(size);
53
  if (res == NULL) {
54
    error("no memory");
55
  }
56
  return res;
57
}
58
 
59
 
60
void release(void *p) {
61
  if (p == NULL) {
62
    error("NULL pointer in release()");
63
  }
64
  free(p);
65
}
66
 
67
 
68
/**************************************************************/
69
 
70
 
71
#define KW_COMMENT      0
72
#define KW_DATE         1
73
#define KW_DUMPALL      2
74
#define KW_DUMPOFF      3
75
#define KW_DUMPON       4
76
#define KW_DUMPVARS     5
77
#define KW_END          6
78
#define KW_ENDDEFS      7
79
#define KW_SCOPE        8
80
#define KW_TIMESCALE    9
81
#define KW_UPSCOPE      10
82
#define KW_VAR          11
83
#define KW_VERSION      12
84
 
85
 
86
typedef struct {
87
  char *name;
88
  int number;
89
} Keyword;
90
 
91
 
92
static Keyword keywords[] = {
93
  { "comment",        KW_COMMENT   },
94
  { "date",           KW_DATE      },
95
  { "dumpall",        KW_DUMPALL   },
96
  { "dumpoff",        KW_DUMPOFF   },
97
  { "dumpon",         KW_DUMPON    },
98
  { "dumpvars",       KW_DUMPVARS  },
99
  { "end",            KW_END       },
100
  { "enddefinitions", KW_ENDDEFS   },
101
  { "scope",          KW_SCOPE     },
102
  { "timescale",      KW_TIMESCALE },
103
  { "upscope",        KW_UPSCOPE   },
104
  { "var",            KW_VAR       },
105
  { "version",        KW_VERSION   },
106
};
107
 
108
 
109
Keyword *lookupKeyword(char *name) {
110
  int lo, hi, tst;
111
  int res;
112
 
113
  lo = 0;
114
  hi = sizeof(keywords) / sizeof(keywords[0]) - 1;
115
  while (lo <= hi) {
116
    tst = (lo + hi) / 2;
117
    res = strcmp(keywords[tst].name, name);
118
    if (res == 0) {
119
      return &keywords[tst];
120
    }
121
    if (res < 0) {
122
      lo = tst + 1;
123
    } else {
124
      hi = tst - 1;
125
    }
126
  }
127
  return NULL;
128
}
129
 
130
 
131
/**************************************************************/
132
 
133
 
134
#define VT_EVENT        0
135
#define VT_INTEGER      1
136
#define VT_PARAMETER    2
137
#define VT_REAL         3
138
#define VT_REG          4
139
#define VT_SUPPLY0      5
140
#define VT_SUPPLY1      6
141
#define VT_TIME         7
142
#define VT_TRI          8
143
#define VT_TRI0         9
144
#define VT_TRI1         10
145
#define VT_TRIAND       11
146
#define VT_TRIOR        12
147
#define VT_TRIREG       13
148
#define VT_WAND         14
149
#define VT_WIRE         15
150
#define VT_WOR          16
151
 
152
 
153
typedef struct {
154
  char *name;
155
  int number;
156
} VarType;
157
 
158
 
159
static VarType varTypes[] = {
160
  { "event",     VT_EVENT     },
161
  { "integer",   VT_INTEGER   },
162
  { "parameter", VT_PARAMETER },
163
  { "real",      VT_REAL      },
164
  { "reg",       VT_REG       },
165
  { "supply0",   VT_SUPPLY0   },
166
  { "supply1",   VT_SUPPLY1   },
167
  { "time",      VT_TIME      },
168
  { "tri",       VT_TRI       },
169
  { "tri0",      VT_TRI0      },
170
  { "tri1",      VT_TRI1      },
171
  { "triand",    VT_TRIAND    },
172
  { "trior",     VT_TRIOR     },
173
  { "trireg",    VT_TRIREG    },
174
  { "wand",      VT_WAND      },
175
  { "wire",      VT_WIRE      },
176
  { "wor",       VT_WOR       },
177
};
178
 
179
 
180
VarType *lookupVarType(char *name) {
181
  int lo, hi, tst;
182
  int res;
183
 
184
  lo = 0;
185
  hi = sizeof(varTypes) / sizeof(varTypes[0]) - 1;
186
  while (lo <= hi) {
187
    tst = (lo + hi) / 2;
188
    res = strcmp(varTypes[tst].name, name);
189
    if (res == 0) {
190
      return &varTypes[tst];
191
    }
192
    if (res < 0) {
193
      lo = tst + 1;
194
    } else {
195
      hi = tst - 1;
196
    }
197
  }
198
  return NULL;
199
}
200
 
201
 
202
/**************************************************************/
203
 
204
 
205
typedef struct change {
206
  int code;                     /* id code of variable */
207
  char *vectorValue;            /* vector value stored as string */
208
                                /* NULL if value is scalar value */
209
  char scalarValue;             /* one of '0', '1', 'x', or 'z' */
210
                                /* '\0' if value is vector value */
211
  struct change *next;          /* next value change in this step */
212
} Change;
213
 
214
 
215
Change *newChange(int code, char *vectorValue, char scalarValue) {
216
  Change *change;
217
 
218
  change = allocate(sizeof(Change));
219
  change->code = code;
220
  if (vectorValue != NULL) {
221
    change->vectorValue = allocate(strlen(vectorValue) + 1);
222
    strcpy(change->vectorValue, vectorValue);
223
    change->scalarValue = '\0';
224
  } else {
225
    change->vectorValue = NULL;
226
    change->scalarValue = scalarValue;
227
  }
228
  change->next = NULL;
229
  return change;
230
}
231
 
232
 
233
typedef struct step {
234
  int time;                     /* simulation time for this step */
235
  struct step *prev;            /* previous time step */
236
  struct step *next;            /* next time step */
237
  Change *changes;              /* variables that changed in this step */
238
} Step;
239
 
240
 
241
Step *newStep(int time, Step *prev) {
242
  Step *step;
243
 
244
  step = allocate(sizeof(Step));
245
  step->time = time;
246
  step->prev = prev;
247
  step->next = NULL;
248
  step->changes = NULL;
249
  return step;
250
}
251
 
252
 
253
typedef struct var {
254
  int type;                     /* one of VT_xxx */
255
  int size;                     /* number of bits */
256
  int code;                     /* id code of variable */
257
  char *name;                   /* local name of variable */
258
  int msi;                      /* most significant index */
259
  int lsi;                      /* least significant index */
260
  struct var *next;             /* linked list of vars in scope */
261
} Var;
262
 
263
 
264
Var *newVar(int type, int size, int code,
265
            char *name, int msi, int lsi) {
266
  Var *var;
267
 
268
  var = allocate(sizeof(Var));
269
  var->type = type;
270
  var->size = size;
271
  var->code = code;
272
  var->name = allocate(strlen(name) + 1);
273
  strcpy(var->name, name);
274
  var->msi = msi;
275
  var->lsi = lsi;
276
  var->next = NULL;
277
  return var;
278
}
279
 
280
 
281
#define SCOPE_MODULE    0
282
#define SCOPE_TASK      1
283
#define SCOPE_FUNCTION  2
284
#define SCOPE_BEGIN     3
285
#define SCOPE_FORK      4
286
 
287
typedef struct scope {
288
  int number;                   /* every scope has a unique number */
289
  int type;                     /* one of SCOPE_xxx */
290
  char *name;                   /* the name of the scope */
291
  struct scope *parent;
292
  struct scope *siblings;
293
  struct scope *children;
294
  struct scope *lastchild;
295
  Var *variables;
296
  Var *lastvar;
297
} Scope;
298
 
299
 
300
Scope *newScope(int type, char *name, Scope *parent) {
301
  static int scopeNumber = 0;
302
  Scope *scope;
303
 
304
  scope = allocate(sizeof(Scope));
305
  scope->number = scopeNumber++;
306
  scope->type = type;
307
  scope->name = allocate(strlen(name) + 1);
308
  strcpy(scope->name, name);
309
  scope->parent = parent;
310
  scope->siblings = NULL;
311
  scope->children = NULL;
312
  scope->lastchild = NULL;
313
  scope->variables = NULL;
314
  scope->lastvar = NULL;
315
  return scope;
316
}
317
 
318
 
319
#define VCD_TS_S        0
320
#define VCD_TS_MS       1
321
#define VCD_TS_US       2
322
#define VCD_TS_NS       3
323
#define VCD_TS_PS       4
324
#define VCD_TS_FS       5
325
 
326
typedef struct {
327
  char *date;                   /* generation date */
328
  char *version;                /* simulator version */
329
  int timescaleMult;            /* 1, 10, 100 */
330
  int timescaleUnit;            /* one of VCD_TS_xx */
331
  Scope *root;                  /* root scope */
332
  Step *steps;                  /* time steps */
333
} VCD;
334
 
335
 
336
/**************************************************************/
337
 
338
 
339
#define INITIAL_HASH_SIZE       100
340
 
341
 
342
typedef struct entry {
343
  char *name;                   /* key */
344
  Var *var;                     /* value */
345
  unsigned hashValue;           /* hash value of name */
346
  struct entry *next;           /* bucket chaining */
347
} Entry;
348
 
349
 
350
static int hashSize = 0;
351
static Entry **buckets;
352
static int numEntries;
353
 
354
 
355
static unsigned hash(char *s) {
356
  unsigned h, g;
357
 
358
  h = 0;
359
  while (*s != '\0') {
360
    h = (h << 4) + *s++;
361
    g = h & 0xF0000000;
362
    if (g != 0) {
363
      h ^= g >> 24;
364
      h ^= g;
365
    }
366
  }
367
  return h;
368
}
369
 
370
 
371
static Bool isPrime(int i) {
372
  int t;
373
 
374
  if (i < 2) {
375
    return FALSE;
376
  }
377
  if (i == 2) {
378
    return TRUE;
379
  }
380
  if (i % 2 == 0) {
381
    return FALSE;
382
  }
383
  t = 3;
384
  while (t * t <= i) {
385
    if (i % t == 0) {
386
      return FALSE;
387
    }
388
    t += 2;
389
  }
390
  return TRUE;
391
}
392
 
393
 
394
static void initTable(void) {
395
  int i;
396
 
397
  hashSize = INITIAL_HASH_SIZE;
398
  while (!isPrime(hashSize)) {
399
    hashSize++;
400
  }
401
  buckets = (Entry **) allocate(hashSize * sizeof(Entry *));
402
  for (i = 0; i < hashSize; i++) {
403
    buckets[i] = NULL;
404
  }
405
  numEntries = 0;
406
}
407
 
408
 
409
static void growTable(void) {
410
  int newHashSize;
411
  Entry **newBuckets;
412
  int i, n;
413
  Entry *p, *q;
414
 
415
  /* compute new hash size */
416
  newHashSize = 2 * hashSize + 1;
417
  while (!isPrime(newHashSize)) {
418
    newHashSize += 2;
419
  }
420
  /* init new hash table */
421
  newBuckets = (Entry **) allocate(newHashSize * sizeof(Entry *));
422
  for (i = 0; i < newHashSize; i++) {
423
    newBuckets[i] = NULL;
424
  }
425
  /* rehash old entries */
426
  for (i = 0; i < hashSize; i++) {
427
    p = buckets[i];
428
    while (p != NULL) {
429
      q = p;
430
      p = p->next;
431
      n = q->hashValue % newHashSize;
432
      q->next = newBuckets[n];
433
      newBuckets[n] = q;
434
    }
435
  }
436
  /* swap tables */
437
  release(buckets);
438
  buckets = newBuckets;
439
  hashSize = newHashSize;
440
}
441
 
442
 
443
Var *lookupVar(char *name) {
444
  unsigned hashValue;
445
  int n;
446
  Entry *p;
447
 
448
  /* check for no table at all */
449
  if (hashSize == 0) {
450
    /* not found */
451
    return NULL;
452
  }
453
  /* compute hash value and bucket number */
454
  hashValue = hash(name);
455
  n = hashValue % hashSize;
456
  /* search in bucket list */
457
  p = buckets[n];
458
  while (p != NULL) {
459
    if (p->hashValue == hashValue) {
460
      if (strcmp(p->name, name) == 0) {
461
        /* found: return variable */
462
        return p->var;
463
      }
464
    }
465
    p = p->next;
466
  }
467
  /* not found */
468
  return NULL;
469
}
470
 
471
 
472
void enterVar(char *name, Var *var) {
473
  char nameBuffer[500];
474
  unsigned hashValue;
475
  int n;
476
  Entry *p;
477
 
478
  /* concat module name and variable name */
479
  strcpy(nameBuffer, name);
480
  strcat(nameBuffer, var->name);
481
  /* initialize hash table if necessary */
482
  if (hashSize == 0) {
483
    initTable();
484
  }
485
  /* grow hash table if necessary */
486
  if (numEntries == hashSize) {
487
    growTable();
488
  }
489
  /* compute hash value and bucket number */
490
  hashValue = hash(nameBuffer);
491
  n = hashValue % hashSize;
492
  /* add new variable to bucket list */
493
  p = (Entry *) allocate(sizeof(Entry));
494
  p->name = (char *) allocate(strlen(nameBuffer) + 1);
495
  strcpy(p->name, nameBuffer);
496
  p->var = var;
497
  p->hashValue = hashValue;
498
  p->next = buckets[n];
499
  buckets[n] = p;
500
  numEntries++;
501
}
502
 
503
 
504
/**************************************************************/
505
 
506
 
507
static FILE *vcdFile;
508
static int vcdLine;
509
 
510
 
511
Bool skipBlanks(void) {
512
  int c;
513
 
514
  do {
515
    c = fgetc(vcdFile);
516
    if (c == EOF) {
517
      break;
518
    }
519
    if (c == '\n') {
520
      vcdLine++;
521
    }
522
  } while (c == ' ' || c == '\t' || c == '\n');
523
  if (c != EOF) {
524
    ungetc(c, vcdFile);
525
  }
526
  return c == EOF;
527
}
528
 
529
 
530
Keyword *getKeyword(void) {
531
  int c;
532
  char buf[MAX_LINE];
533
  char *p;
534
 
535
  c = fgetc(vcdFile);
536
  if (c == EOF) {
537
    return NULL;
538
  }
539
  if (c != '$') {
540
    ungetc(c, vcdFile);
541
    return NULL;
542
  }
543
  c = fgetc(vcdFile);
544
  if (c == EOF) {
545
    return NULL;
546
  }
547
  p = buf;
548
  while (isalpha(c)) {
549
    *p++ = c;
550
    c = fgetc(vcdFile);
551
  }
552
  ungetc(c, vcdFile);
553
  *p = '\0';
554
  return lookupKeyword(buf);
555
}
556
 
557
 
558
void skipPastEnd(void) {
559
  int c;
560
  Keyword *kwp;
561
 
562
  while (1) {
563
    do {
564
      c = fgetc(vcdFile);
565
      if (c == EOF) {
566
        error("unexpected end of VCD file");
567
      }
568
      if (c == '\n') {
569
        vcdLine++;
570
      }
571
    } while (c != '$');
572
    ungetc(c, vcdFile);
573
    kwp = getKeyword();
574
    if (kwp != NULL && kwp->number == KW_END) {
575
      return;
576
    }
577
  }
578
}
579
 
580
 
581
int collectTillDollar(char *buffer) {
582
  char *p;
583
  int c;
584
 
585
  p = buffer;
586
  do {
587
    c = fgetc(vcdFile);
588
    if (c == EOF) {
589
      error("unexpected end of VCD file");
590
    }
591
    if (c == '\n') {
592
      vcdLine++;
593
    }
594
    *p++ = c;
595
  } while (c != '$');
596
  ungetc(c, vcdFile);
597
  p -= 2;
598
  while (*p == ' ' || *p == '\t' || *p == '\n') {
599
    p--;
600
  }
601
  *++p = '\0';
602
  return p - buffer;
603
}
604
 
605
 
606
int getString(char *buffer) {
607
  char *p;
608
  int c;
609
 
610
  p = buffer;
611
  while (1) {
612
    c = fgetc(vcdFile);
613
    if (c == EOF) {
614
      error("unexpected end of VCD file");
615
    }
616
    if (c == ' ' || c == '\t' || c == '\n') {
617
      break;
618
    }
619
    *p++ = c;
620
  }
621
  ungetc(c, vcdFile);
622
  *p = '\0';
623
  return p - buffer;
624
}
625
 
626
 
627
Bool getIdent(char *buffer) {
628
  char *p;
629
  int c;
630
 
631
  c = fgetc(vcdFile);
632
  if (c == EOF) {
633
    return FALSE;
634
  }
635
  if (!isalpha(c) && c != '_') {
636
    ungetc(c, vcdFile);
637
    return FALSE;
638
  }
639
  p = buffer;
640
  while (isalnum(c) || c == '_' || c == '$') {
641
    *p++ = c;
642
    c = fgetc(vcdFile);
643
  }
644
  if (c != EOF) {
645
    ungetc(c, vcdFile);
646
  }
647
  *p = '\0';
648
  return TRUE;
649
}
650
 
651
 
652
int getVarCode(void) {
653
  int varCode;
654
  int weight;
655
  int c;
656
  int i;
657
 
658
  varCode = 0;
659
  weight = 1;
660
  for (i = 0; i <= 4; i++) {
661
    c = fgetc(vcdFile);
662
    if (c < '!' || c > '~') {
663
      break;
664
    }
665
    if (i == 4) {
666
      error("line %d: too many base-94 digits", vcdLine);
667
    }
668
    varCode += weight * (c - '!');
669
    weight *= 94;
670
  }
671
  if (i == 0) {
672
    error("line %d: variable code expected", vcdLine);
673
  }
674
  if (c != EOF) {
675
    ungetc(c, vcdFile);
676
  }
677
  return varCode;
678
}
679
 
680
 
681
int getInteger(void) {
682
  int val;
683
  int c;
684
 
685
  val = 0;
686
  skipBlanks();
687
  c = fgetc(vcdFile);
688
  if (!isdigit(c)) {
689
    error("line %d: number expected", vcdLine);
690
  }
691
  while (1) {
692
    if (!isdigit(c)) {
693
      break;
694
    }
695
    val = val * 10 + (c - '0');
696
    c = fgetc(vcdFile);
697
  }
698
  if (c != EOF) {
699
    ungetc(c, vcdFile);
700
  }
701
  return val;
702
}
703
 
704
 
705
void getIndexRange(int *msip, int *lsip) {
706
  int c;
707
 
708
  *msip = -1;
709
  *lsip = -1;
710
  skipBlanks();
711
  c = fgetc(vcdFile);
712
  if (c == EOF) {
713
    return;
714
  }
715
  if (c != '[') {
716
    ungetc(c, vcdFile);
717
    return;
718
  }
719
  *msip = getInteger();
720
  skipBlanks();
721
  c = fgetc(vcdFile);
722
  if (c != ':' && c != ']') {
723
    error("line %d: ':' or ']' expected", vcdLine);
724
  }
725
  if (c == ':') {
726
    skipBlanks();
727
    *lsip = getInteger();
728
    skipBlanks();
729
    c = fgetc(vcdFile);
730
  }
731
  if (c != ']') {
732
    error("line %d: ']' expected", vcdLine);
733
  }
734
}
735
 
736
 
737
int getTime(void) {
738
  int c;
739
 
740
  c = fgetc(vcdFile);
741
  if (c != '#') {
742
    ungetc(c, vcdFile);
743
    return -1;
744
  }
745
  return getInteger();
746
}
747
 
748
 
749
Change *getChange(void) {
750
  int c;
751
  int varCode;
752
  Change *change;
753
  char buffer[MAX_LINE];
754
  char *p;
755
 
756
  c = fgetc(vcdFile);
757
  if (c != '0' && c != '1' && c != 'x' && c != 'X' &&
758
      c != 'z' && c != 'Z' && c != 'b' && c != 'B') {
759
    if (c == 'r' || c == 'R') {
760
      error("line %d: real numbers are not supported, sorry", vcdLine);
761
    }
762
    if (c != EOF) {
763
      ungetc(c, vcdFile);
764
    }
765
    return NULL;
766
  }
767
  if (c == 'b' || c == 'B') {
768
    /* vector */
769
    p = buffer;
770
    do {
771
      c = fgetc(vcdFile);
772
      switch (c) {
773
        case '0':
774
        case '1':
775
        case 'x':
776
        case 'z':
777
          *p++ = c;
778
          break;
779
        case 'X':
780
        case 'Z':
781
          *p++ = tolower(c);
782
          break;
783
        default:
784
          break;
785
      }
786
    } while (c == '0' || c == '1' || c == 'x' ||
787
             c == 'X' || c == 'z' || c == 'Z');
788
    if (c != EOF) {
789
      ungetc(c, vcdFile);
790
    }
791
    *p = '\0';
792
    skipBlanks();
793
    varCode = getVarCode();
794
    change = newChange(varCode, buffer, '\0');
795
  } else {
796
    /* scalar */
797
    if (c == 'X') {
798
      c = 'x';
799
    } else
800
    if (c == 'Z') {
801
      c = 'z';
802
    }
803
    varCode = getVarCode();
804
    change = newChange(varCode, NULL, c);
805
  }
806
  return change;
807
}
808
 
809
 
810
VCD *parseVCD(FILE *input) {
811
  VCD *vcd;
812
  int section;
813
  Keyword *kwp;
814
  char buffer[MAX_LINE];
815
  int length;
816
  char *endptr;
817
  Scope *currentScope;
818
  Scope *scope;
819
  int scopeType;
820
  char currentPrefix[MAX_NAME];
821
  VarType *vtp;
822
  int varType;
823
  int varSize;
824
  int varCode;
825
  int msi;
826
  int lsi;
827
  Var *var;
828
  Step *currentStep;
829
  Step *step;
830
  int time;
831
  Change *currentChange;
832
  Change *change;
833
 
834
  /* allocate a VCD structure */
835
  vcd = allocate(sizeof(VCD));
836
  vcd->date = NULL;
837
  vcd->version = NULL;
838
  vcd->timescaleMult = -1;
839
  vcd->timescaleUnit = -1;
840
  vcd->root = NULL;
841
  vcd->steps = NULL;
842
  /* start parsing */
843
  vcdFile = input;
844
  vcdLine = 1;
845
  section = 1;
846
  /* read header and node information */
847
  currentScope = NULL;
848
  currentPrefix[0] = '\0';
849
  while (section == 1) {
850
    skipBlanks();
851
    kwp = getKeyword();
852
    if (kwp == NULL) {
853
      error("line %d: keyword expected", vcdLine);
854
    }
855
    switch (kwp->number) {
856
      case KW_COMMENT:
857
        /* ignore comment */
858
        skipPastEnd();
859
        break;
860
      case KW_DATE:
861
        /* record date as string */
862
        skipBlanks();
863
        length = collectTillDollar(buffer);
864
        vcd->date = allocate(length + 1);
865
        strcpy(vcd->date, buffer);
866
        skipPastEnd();
867
        break;
868
      case KW_VERSION:
869
        /* record version as string */
870
        skipBlanks();
871
        length = collectTillDollar(buffer);
872
        vcd->version = allocate(length + 1);
873
        strcpy(vcd->version, buffer);
874
        skipPastEnd();
875
        break;
876
      case KW_TIMESCALE:
877
        /* record timescale as multiplier and unit */
878
        skipBlanks();
879
        length = collectTillDollar(buffer);
880
        /* get multiplier */
881
        vcd->timescaleMult = strtol(buffer, &endptr, 10);
882
        if (vcd->timescaleMult != 1 &&
883
            vcd->timescaleMult != 10 &&
884
            vcd->timescaleMult != 100) {
885
          error("line %d: illegal timescale multiplier (%d)",
886
                vcdLine, vcd->timescaleMult);
887
        }
888
        /* multiplier and unit may be separated by whitespace */
889
        while (*endptr == ' ' || *endptr == '\t') {
890
          endptr++;
891
        }
892
        /* get unit */
893
        if (endptr[0] == 's' && endptr[1] == '\0') {
894
          vcd->timescaleUnit = VCD_TS_S;
895
        } else
896
        if (endptr[0] == 'm' && endptr[1] == 's' && endptr[2] == '\0') {
897
          vcd->timescaleUnit = VCD_TS_MS;
898
        } else
899
        if (endptr[0] == 'u' && endptr[1] == 's' && endptr[2] == '\0') {
900
          vcd->timescaleUnit = VCD_TS_US;
901
        } else
902
        if (endptr[0] == 'n' && endptr[1] == 's' && endptr[2] == '\0') {
903
          vcd->timescaleUnit = VCD_TS_NS;
904
        } else
905
        if (endptr[0] == 'p' && endptr[1] == 's' && endptr[2] == '\0') {
906
          vcd->timescaleUnit = VCD_TS_PS;
907
        } else
908
        if (endptr[0] == 'f' && endptr[1] == 's' && endptr[2] == '\0') {
909
          vcd->timescaleUnit = VCD_TS_FS;
910
        } else {
911
          error("line %d: illegal timescale unit (%s)",
912
                vcdLine, endptr);
913
        }
914
        skipPastEnd();
915
        break;
916
      case KW_SCOPE:
917
        /* open a new scope */
918
        skipBlanks();
919
        /* get type */
920
        getString(buffer);
921
        if (strcmp(buffer, "module") == 0) {
922
          scopeType = SCOPE_MODULE;
923
        } else
924
        if (strcmp(buffer, "task") == 0) {
925
          scopeType = SCOPE_TASK;
926
        } else
927
        if (strcmp(buffer, "function") == 0) {
928
          scopeType = SCOPE_FUNCTION;
929
        } else
930
        if (strcmp(buffer, "begin") == 0) {
931
          scopeType = SCOPE_BEGIN;
932
        } else
933
        if (strcmp(buffer, "fork") == 0) {
934
          scopeType = SCOPE_FORK;
935
        } else {
936
          error("line %d: unknown scope type '%s'", vcdLine, buffer);
937
        }
938
        skipBlanks();
939
        /* get name */
940
        if (!getIdent(buffer)) {
941
          error("line %d: identifier expected", vcdLine);
942
        }
943
        /* allocate and link a new scope */
944
        scope = newScope(scopeType, buffer, currentScope);
945
        if (currentScope == NULL) {
946
          /* new scope is a top-level scope */
947
          if (vcd->root == NULL) {
948
            /* first top-level scope */
949
            vcd->root = scope;
950
          } else {
951
            /* another top-level scope */
952
            /* append, use currentScope as auxiliary variable */
953
            currentScope = vcd->root;
954
            while (currentScope->siblings != NULL) {
955
              currentScope = currentScope->siblings;
956
            }
957
            currentScope->siblings = scope;
958
          }
959
        } else {
960
          /* new scope is not a top-level scope */
961
          if (currentScope->children == NULL) {
962
            currentScope->children = scope;
963
          } else {
964
            currentScope->lastchild->siblings = scope;
965
          }
966
          currentScope->lastchild = scope;
967
        }
968
        currentScope = scope;
969
        /* augment current prefix */
970
        strcat(currentPrefix, currentScope->name);
971
        strcat(currentPrefix, ".");
972
        skipPastEnd();
973
        break;
974
      case KW_UPSCOPE:
975
        /* close the current scope */
976
        if (currentScope == NULL) {
977
          error("line %d: no $scope for this $upscope", vcdLine);
978
        }
979
        currentScope = currentScope->parent;
980
        /* prune current prefix */
981
        length = strlen(currentPrefix) - 2;
982
        while (length >= 0 && currentPrefix[length] != '.') {
983
          length--;
984
        }
985
        length++;
986
        currentPrefix[length] = '\0';
987
        skipPastEnd();
988
        break;
989
      case KW_VAR:
990
        /* record a new variable */
991
        skipBlanks();
992
        /* get type */
993
        getString(buffer);
994
        vtp = lookupVarType(buffer);
995
        if (vtp == NULL) {
996
          error("line %d: unknown variable type '%s'", vcdLine, buffer);
997
        }
998
        varType = vtp->number;
999
        skipBlanks();
1000
        /* get size */
1001
        getString(buffer);
1002
        varSize = strtol(buffer, &endptr, 10);
1003
        if (*endptr != '\0' || varSize <= 0) {
1004
          error("line %d: cannot read variable size", vcdLine);
1005
        }
1006
        skipBlanks();
1007
        /* get code */
1008
        varCode = getVarCode();
1009
        skipBlanks();
1010
        /* get name */
1011
        if (!getIdent(buffer)) {
1012
          error("line %d: identifier expected", vcdLine);
1013
        }
1014
        skipBlanks();
1015
        /* get optional index range */
1016
        getIndexRange(&msi, &lsi);
1017
        /* allocate and link a new variable */
1018
        var = newVar(varType, varSize, varCode, buffer, msi, lsi);
1019
        if (currentScope->variables == NULL) {
1020
          currentScope->variables = var;
1021
        } else {
1022
          currentScope->lastvar->next = var;
1023
        }
1024
        currentScope->lastvar = var;
1025
        /* additionally, enter variable in var table */
1026
        enterVar(currentPrefix, var);
1027
        skipPastEnd();
1028
        break;
1029
      case KW_ENDDEFS:
1030
        /* end the first section of the VCD file */
1031
        section = 2;
1032
        skipPastEnd();
1033
        break;
1034
      default:
1035
        error("line %d: unexpected keyword '$%s'", vcdLine, kwp->name);
1036
        break;
1037
    }
1038
  }
1039
  /* read value changes */
1040
  currentStep = NULL;
1041
  currentChange = NULL;
1042
  while (1) {
1043
    if (skipBlanks()) {
1044
      break;
1045
    }
1046
    kwp = getKeyword();
1047
    if (kwp != NULL) {
1048
      switch (kwp->number) {
1049
        case KW_COMMENT:
1050
          /* ignore comment */
1051
          skipPastEnd();
1052
          break;
1053
        case KW_DUMPVARS:
1054
        case KW_DUMPALL:
1055
        case KW_DUMPOFF:
1056
        case KW_DUMPON:
1057
          /* record value changes */
1058
          while (1) {
1059
            skipBlanks();
1060
            change = getChange();
1061
            if (change == NULL) {
1062
              break;
1063
            }
1064
            if (currentChange == NULL) {
1065
              if (currentStep == NULL) {
1066
                error("line %d: value change without simulation time",
1067
                      vcdLine);
1068
              }
1069
              currentStep->changes = change;
1070
            } else {
1071
              currentChange->next = change;
1072
            }
1073
            currentChange = change;
1074
          }
1075
          skipPastEnd();
1076
          break;
1077
        default:
1078
          error("line %d: unexpected keyword '%s'", vcdLine, kwp->name);
1079
          break;
1080
      }
1081
      continue;
1082
    }
1083
    time = getTime();
1084
    if (time >= 0) {
1085
      if (currentStep != NULL && currentStep->time >= time) {
1086
        error("line %d: time step has illegal simulation time", vcdLine);
1087
      }
1088
      step = newStep(time, currentStep);
1089
      if (currentStep == NULL) {
1090
        vcd->steps = step;
1091
      } else {
1092
        currentStep->next = step;
1093
      }
1094
      currentStep = step;
1095
      currentChange = NULL;
1096
      continue;
1097
    }
1098
    change = getChange();
1099
    if (change != NULL) {
1100
      if (currentChange == NULL) {
1101
        if (currentStep == NULL) {
1102
          error("line %d: value change without simulation time", vcdLine);
1103
        }
1104
        currentStep->changes = change;
1105
      } else {
1106
        currentChange->next = change;
1107
      }
1108
      currentChange = change;
1109
      continue;
1110
    }
1111
    error("line %d: keyword, time, or value change expected", vcdLine);
1112
  }
1113
  /* done */
1114
  return vcd;
1115
}
1116
 
1117
 
1118
char *varType[] = {
1119
  "event",
1120
  "integer",
1121
  "parameter",
1122
  "real",
1123
  "reg",
1124
  "supply0",
1125
  "supply1",
1126
  "time",
1127
  "tri",
1128
  "tri0",
1129
  "tri1",
1130
  "triand",
1131
  "trior",
1132
  "trireg",
1133
  "wand",
1134
  "wire",
1135
  "wor",
1136
};
1137
 
1138
 
1139
char *scopeType[] = {
1140
  "module",
1141
  "task",
1142
  "function",
1143
  "begin",
1144
  "fork",
1145
};
1146
 
1147
 
1148
void showVarPrefix(Scope *scope) {
1149
  if (scope == NULL) {
1150
    return;
1151
  }
1152
  showVarPrefix(scope->parent);
1153
  printf("%s.", scope->name);
1154
}
1155
 
1156
 
1157
void showScope(Scope *scope) {
1158
  Var *var;
1159
 
1160
  printf("    scope #%d\n", scope->number);
1161
  printf("        type       :  %s\n", scopeType[scope->type]);
1162
  printf("        name       :  %s\n", scope->name);
1163
  printf("        parent     :  ");
1164
  if (scope->parent == NULL) {
1165
    printf("-- none --");
1166
  } else {
1167
    printf("scope #%d", scope->parent->number);
1168
  }
1169
  printf("\n");
1170
  printf("        siblings   :  ");
1171
  if (scope->siblings == NULL) {
1172
    printf("-- none --");
1173
  } else {
1174
    printf("scope #%d", scope->siblings->number);
1175
  }
1176
  printf("\n");
1177
  printf("        children   :  ");
1178
  if (scope->children == NULL) {
1179
    printf("-- none --");
1180
  } else {
1181
    printf("scope #%d", scope->children->number);
1182
  }
1183
  printf("\n");
1184
  printf("        lastchild  :  ");
1185
  if (scope->lastchild == NULL) {
1186
    printf("-- none --");
1187
  } else {
1188
    printf("scope #%d", scope->lastchild->number);
1189
  }
1190
  printf("\n");
1191
  printf("        var prefix :  ");
1192
  showVarPrefix(scope);
1193
  printf("\n");
1194
  printf("        variables  :  ");
1195
  if (scope->variables == NULL) {
1196
    printf("-- none --\n");
1197
  } else {
1198
    printf("\n");
1199
    var = scope->variables;
1200
    while (var != NULL) {
1201
      printf("            ");
1202
      printf("%s", var->name);
1203
      if (var->msi != -1) {
1204
        printf(" [%d", var->msi);
1205
        if (var->lsi != -1) {
1206
          printf(":%d", var->lsi);
1207
        }
1208
        printf("]");
1209
      }
1210
      printf("\n");
1211
      printf("                ");
1212
      printf("type = %-9s   ", varType[var->type]);
1213
      printf("size = %4d    ", var->size);
1214
      printf("code = %6d\n", var->code);
1215
      var = var->next;
1216
    }
1217
  }
1218
  if (scope->siblings != NULL) {
1219
    showScope(scope->siblings);
1220
  }
1221
  if (scope->children != NULL) {
1222
    showScope(scope->children);
1223
  }
1224
}
1225
 
1226
 
1227
void showSteps(Step *steps) {
1228
  Change *changes;
1229
 
1230
  while (steps != NULL) {
1231
    printf("    #%d\n", steps->time);
1232
    changes = steps->changes;
1233
    while (changes != NULL) {
1234
      printf("        code %8d : value ", changes->code);
1235
      if (changes->vectorValue != NULL) {
1236
        printf("'%s'", changes->vectorValue);
1237
      } else {
1238
        printf("'%c'", changes->scalarValue);
1239
      }
1240
      printf("\n");
1241
      changes = changes->next;
1242
    }
1243
    steps = steps->next;
1244
  }
1245
}
1246
 
1247
 
1248
char *tsUnit[6] = {
1249
  "s", "ms", "us",
1250
  "ns", "ps", "fs"
1251
};
1252
 
1253
 
1254
void showVCD(VCD *vcd) {
1255
  printf("Value Change Dump Data\n");
1256
 
1257
  printf("date          :  ");
1258
  if (vcd->date == NULL) {
1259
    printf("-- none --");
1260
  } else {
1261
    printf("%s", vcd->date);
1262
  }
1263
  printf("\n");
1264
 
1265
  printf("version       :  ");
1266
  if (vcd->version == NULL) {
1267
    printf("-- none --");
1268
  } else {
1269
    printf("%s", vcd->version);
1270
  }
1271
  printf("\n");
1272
 
1273
  printf("timescale     :  ");
1274
  if (vcd->timescaleMult < 0 ||
1275
      vcd->timescaleUnit < 0) {
1276
    printf("-- none --");
1277
  } else {
1278
    printf("%d %s", vcd->timescaleMult, tsUnit[vcd->timescaleUnit]);
1279
  }
1280
  printf("\n");
1281
 
1282
  printf("root scope    :  ");
1283
  if (vcd->root == NULL) {
1284
    printf("-- none --");
1285
    printf("\n");
1286
  } else {
1287
    printf("%d", vcd->root->number);
1288
    printf("\n");
1289
    showScope(vcd->root);
1290
  }
1291
 
1292
  printf("value changes :  ");
1293
  if (vcd->steps == NULL) {
1294
    printf("-- none --");
1295
    printf("\n");
1296
  } else {
1297
    printf("\n");
1298
    showSteps(vcd->steps);
1299
  }
1300
}
1301
 
1302
 
1303
/**************************************************************/
1304
 
1305
 
1306
typedef struct chk {
1307
  int timeMult;         /* this many timeUnits */
1308
  int timeUnit;         /* one of VCD_TS_xxx */
1309
  char *name;           /* name of variable to check */
1310
  int width;            /* width of variable to check */
1311
  char *value;          /* value to check variable against */
1312
  struct chk *next;     /* list elements are connected by 'and' */
1313
} CHK;
1314
 
1315
 
1316
void shift(char *buffer, int width, int amount, char *val) {
1317
  int j, i;
1318
 
1319
  for (j = 0; j < amount; j++) {
1320
    for (i = 0; i < width - 1; i++) {
1321
      buffer[i] = buffer[i + 1];
1322
    }
1323
    buffer[i] = val[j];
1324
  }
1325
}
1326
 
1327
 
1328
char *bitval1[2] = {
1329
  "0", "1"
1330
};
1331
 
1332
 
1333
char *bitval4[16] = {
1334
  "0000", "0001", "0010", "0011",
1335
  "0100", "0101", "0110", "0111",
1336
  "1000", "1001", "1010", "1011",
1337
  "1100", "1101", "1110", "1111"
1338
};
1339
 
1340
 
1341
int skipSpace(int c, FILE *chkFile) {
1342
  while (1) {
1343
    while (c == ' ' || c == '\t' || c == '\n') {
1344
      c = fgetc(chkFile);
1345
    }
1346
    if (c != '/') {
1347
      return c;
1348
    }
1349
    c = fgetc(chkFile);
1350
    if (c == EOF) {
1351
      error("chk spec: unexpected end of input");
1352
    }
1353
    if (c != '/') {
1354
      ungetc(c, chkFile);
1355
      return '/';
1356
    }
1357
    do {
1358
      c = fgetc(chkFile);
1359
      if (c == EOF) {
1360
        return EOF;
1361
      }
1362
    } while (c != '\n');
1363
  }
1364
}
1365
 
1366
 
1367
CHK *parseSingleChk(FILE *chkFile) {
1368
  CHK *chk;
1369
  int c, d;
1370
  char name[MAX_LINE];
1371
  char *p;
1372
  int base;
1373
  int i;
1374
 
1375
  chk = allocate(sizeof(CHK));
1376
  c = fgetc(chkFile);
1377
  c = skipSpace(c, chkFile);
1378
  chk->timeMult = 0;
1379
  if (!isdigit(c)) {
1380
    error("chk spec: time multiplier does not start with a digit");
1381
  }
1382
  while (isdigit(c)) {
1383
    chk->timeMult = chk->timeMult * 10 + (c - '0');
1384
    c = fgetc(chkFile);
1385
  }
1386
  c = skipSpace(c, chkFile);
1387
  if (c == 's') {
1388
    chk->timeUnit = VCD_TS_S;
1389
  } else {
1390
    d = fgetc(chkFile);
1391
    if (c == 'm' && d == 's') {
1392
      chk->timeUnit = VCD_TS_MS;
1393
    } else
1394
    if (c == 'u' && d == 's') {
1395
      chk->timeUnit = VCD_TS_US;
1396
    } else
1397
    if (c == 'n' && d == 's') {
1398
      chk->timeUnit = VCD_TS_NS;
1399
    } else
1400
    if (c == 'p' && d == 's') {
1401
      chk->timeUnit = VCD_TS_PS;
1402
    } else
1403
    if (c == 'f' && d == 's') {
1404
      chk->timeUnit = VCD_TS_FS;
1405
    } else {
1406
      error("chk spec: illegal time unit");
1407
    }
1408
  }
1409
  c = fgetc(chkFile);
1410
  c = skipSpace(c, chkFile);
1411
  p = name;
1412
  if (!isalpha(c) && c != '_') {
1413
    error("chk spec: name does not start with a letter");
1414
  }
1415
  while (isalnum(c) || c == '_' || c == '$' || c == '.') {
1416
    *p++ = c;
1417
    c = fgetc(chkFile);
1418
  }
1419
  *p = '\0';
1420
  chk->name = allocate(p - name + 1);
1421
  strcpy(chk->name, name);
1422
  c = skipSpace(c, chkFile);
1423
  chk->width = 0;
1424
  if (!isdigit(c)) {
1425
    error("chk spec: bit width does not start with a digit");
1426
  }
1427
  while (isdigit(c)) {
1428
    chk->width = chk->width * 10 + (c - '0');
1429
    c = fgetc(chkFile);
1430
  }
1431
  if (chk->width <= 0) {
1432
    error("chk spec: illegal bit width");
1433
  }
1434
  chk->value = allocate(chk->width + 1);
1435
  if (c != '\'') {
1436
    error("chk spec: apostrophe missing after bit width");
1437
  }
1438
  c = fgetc(chkFile);
1439
  if (c == 'b') {
1440
    base = 2;
1441
  } else
1442
  if (c == 'h') {
1443
    base = 16;
1444
  } else {
1445
    error("chk spec: illegal number base");
1446
  }
1447
  c = fgetc(chkFile);
1448
  if (c == 'x' || c == 'X') {
1449
    for (i = 0; i < chk->width; i++) {
1450
      chk->value[i] = 'x';
1451
    }
1452
  } else
1453
  if (c == 'z' || c == 'Z') {
1454
    for (i = 0; i < chk->width; i++) {
1455
      chk->value[i] = 'z';
1456
    }
1457
  } else {
1458
    for (i = 0; i < chk->width; i++) {
1459
      chk->value[i] = '0';
1460
    }
1461
  }
1462
  chk->value[chk->width] = '\0';
1463
  if (base == 2) {
1464
    if (c != 'x' && c != 'X' &&
1465
        c != 'z' && c != 'Z' &&
1466
        c != '0' && c != '1') {
1467
      error("chk spec: base-2 number does not start with binary digit");
1468
    }
1469
    while (1) {
1470
      if (c == 'x' || c == 'X') {
1471
        shift(chk->value, chk->width, 1, "x");
1472
      } else
1473
      if (c == 'z' || c == 'Z') {
1474
        shift(chk->value, chk->width, 1, "z");
1475
      } else
1476
      if (c == '0' || c == '1') {
1477
        shift(chk->value, chk->width, 1, bitval1[c - '0']);
1478
      } else {
1479
        break;
1480
      }
1481
      c = fgetc(chkFile);
1482
    }
1483
  } else
1484
  if (base == 16) {
1485
    if (c != 'x' && c != 'X' &&
1486
        c != 'z' && c != 'Z' &&
1487
        !isxdigit(c)) {
1488
      error("chk spec: base-16 number does not start with hex digit");
1489
    }
1490
    while (1) {
1491
      if (c == 'x' || c == 'X') {
1492
        shift(chk->value, chk->width, 4, "xxxx");
1493
      } else
1494
      if (c == 'z' || c == 'Z') {
1495
        shift(chk->value, chk->width, 4, "zzzz");
1496
      } else
1497
      if (c >= '0' && c <= '9') {
1498
        shift(chk->value, chk->width, 4, bitval4[c - '0']);
1499
      } else
1500
      if (c >= 'A' && c <= 'F') {
1501
        shift(chk->value, chk->width, 4, bitval4[c - 'A' + 10]);
1502
      } else
1503
      if (c >= 'a' && c <= 'f') {
1504
        shift(chk->value, chk->width, 4, bitval4[c - 'a' + 10]);
1505
      } else {
1506
        break;
1507
      }
1508
      c = fgetc(chkFile);
1509
    }
1510
  }
1511
  c = skipSpace(c, chkFile);
1512
  if (c != EOF) {
1513
    ungetc(c, chkFile);
1514
  }
1515
  chk->next = NULL;
1516
  return chk;
1517
}
1518
 
1519
 
1520
CHK *parseCHK(FILE *chkFile) {
1521
  CHK *chk;
1522
  CHK *cur;
1523
  int c;
1524
 
1525
  chk = parseSingleChk(chkFile);
1526
  cur = chk;
1527
  c = fgetc(chkFile);
1528
  while (c != EOF) {
1529
    ungetc(c, chkFile);
1530
    cur->next = parseSingleChk(chkFile);
1531
    cur = cur->next;
1532
    c = fgetc(chkFile);
1533
  }
1534
  return chk;
1535
}
1536
 
1537
 
1538
void showSingleCHK(CHK *chk) {
1539
  printf("time mult = %d\n", chk->timeMult);
1540
  printf("time unit = %s\n", tsUnit[chk->timeUnit]);
1541
  printf("var name  = %s\n", chk->name);
1542
  printf("var width = %d\n", chk->width);
1543
  printf("var value = %s\n", chk->value);
1544
}
1545
 
1546
 
1547
void showCHK(CHK *chk) {
1548
  do {
1549
    showSingleCHK(chk);
1550
    chk = chk->next;
1551
    if (chk != NULL) {
1552
      printf("&&\n");
1553
    }
1554
  } while (chk != NULL);
1555
}
1556
 
1557
 
1558
/**************************************************************/
1559
 
1560
 
1561
#define bitEqual(v, c)  ((v) == (c) || (c) == 'x')
1562
 
1563
 
1564
Bool compare(Change *change, char *check, int width) {
1565
  char *value;
1566
  int i, n;
1567
 
1568
  if (change->vectorValue != NULL) {
1569
    /* compare two vectors */
1570
    value = allocate(width + 1);
1571
    n = strlen(change->vectorValue);
1572
    if (change->vectorValue[0] == 'x') {
1573
      for (i = 0; i < width - n; i++) {
1574
        value[i] = 'x';
1575
      }
1576
    } else
1577
    if (change->vectorValue[0] == 'z') {
1578
      for (i = 0; i < width - n; i++) {
1579
        value[i] = 'z';
1580
      }
1581
    } else {
1582
      for (i = 0; i < width - n; i++) {
1583
        value[i] = '0';
1584
      }
1585
    }
1586
    for (i = 0; i < n; i++) {
1587
      value[width - n + i] = change->vectorValue[i];
1588
    }
1589
    value[width] = '\0';
1590
    if (debugCheck) {
1591
      printf("v = '%s'\nc = '%s'\n", value, check);
1592
    }
1593
    for (i = 0; i < width; i++) {
1594
      if (!bitEqual(value[i], check[i])) {
1595
        return FALSE;
1596
      }
1597
    }
1598
    return TRUE;
1599
  } else {
1600
    /* compare two scalars */
1601
    if (debugCheck) {
1602
      printf("v = '%c'\nc = '%c'\n", change->scalarValue, check[0]);
1603
    }
1604
    return bitEqual(change->scalarValue, check[0]);
1605
  }
1606
}
1607
 
1608
 
1609
Bool check(VCD *vcd, CHK *chk) {
1610
  Var *var;
1611
  int time;
1612
  Step *step;
1613
  Step *next;
1614
  Change *change;
1615
 
1616
  /* locate variable */
1617
  var = lookupVar(chk->name);
1618
  if (var == NULL) {
1619
    error("check: variable '%s' not found", chk->name);
1620
  }
1621
  /* check sizes */
1622
  if (var->size != chk->width) {
1623
    error("check: variable size in vcd and chk different");
1624
  }
1625
  /* check time units */
1626
  if (vcd->timescaleUnit != chk->timeUnit) {
1627
    error("check: time units in vcd and chk different");
1628
  }
1629
  /* locate time step just before specified time */
1630
  time = chk->timeMult;
1631
  step = vcd->steps;
1632
  if (step == NULL) {
1633
    error("check: no simulation time steps at all");
1634
  }
1635
  if (time < step->time) {
1636
    error("check: check time < first simulation time step");
1637
  }
1638
  next = step->next;
1639
  while (next != NULL && time >= next->time) {
1640
    step = next;
1641
    next = step->next;
1642
  }
1643
  /* find oldest time step in which the variable changed */
1644
  while (step != NULL) {
1645
    change = step->changes;
1646
    while (change != NULL) {
1647
      if (change->code == var->code) {
1648
        /* value change found */
1649
        return compare(change, chk->value, chk->width);
1650
      }
1651
      change = change->next;
1652
    }
1653
    step = step->prev;
1654
  }
1655
  error("check: variable '%s' was never dumped", chk->name);
1656
  return FALSE;
1657
}
1658
 
1659
 
1660
/**************************************************************/
1661
 
1662
 
1663
void usage(char *myself) {
1664
  printf("Usage: %s <VCD file> <CHK file>\n", myself);
1665
  exit(1);
1666
}
1667
 
1668
 
1669
int main(int argc, char *argv[]) {
1670
  char *vcdName;
1671
  FILE *vcdFile;
1672
  VCD *vcd;
1673
  char *chkName;
1674
  FILE *chkFile;
1675
  CHK *chk;
1676
 
1677
  if (argc != 3) {
1678
    usage(argv[0]);
1679
  }
1680
  vcdName = argv[1];
1681
  vcdFile = fopen(vcdName, "r");
1682
  if (vcdFile == NULL) {
1683
    error("cannot open VCD file '%s'", vcdName);
1684
  }
1685
  vcd = parseVCD(vcdFile);
1686
  fclose(vcdFile);
1687
  if (debugVCD) {
1688
    showVCD(vcd);
1689
  }
1690
  chkName = argv[2];
1691
  chkFile = fopen(chkName, "r");
1692
  if (chkFile == NULL) {
1693
    error("cannot open CHK file '%s'", chkName);
1694
  }
1695
  chk = parseCHK(chkFile);
1696
  if (debugCHK) {
1697
    showCHK(chk);
1698
  }
1699
  fclose(chkFile);
1700
  while (chk != NULL) {
1701
    if (!check(vcd, chk)) {
1702
      printf("failure, check:\n");
1703
      showSingleCHK(chk);
1704
      return 1;
1705
    }
1706
    chk = chk->next;
1707
  }
1708
  printf("success\n");
1709
  return 0;
1710
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.