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 Sun Dec 21 22:27:18 2008
19 ****************************************************************************/
20
21 #ifdef __cplusplus
22 #include <cstdlib>
23 #include <cstdarg>
24 #include <cstdio>
25 #include <cassert>
26 #include <cstring>
27 #else
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <assert.h>
32 #include <string.h>
33 #endif
34
35 #include <pwd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38
39 #include "tkgate.h"
40
41 static int did_message = 0;
42 static int err_count = 0;
43 static NHash *v_wires = 0;
44
verify_error(GModuleDef * m,char * msg,...)45 void verify_error(GModuleDef *m,char *msg,...)
46 {
47 extern int quietMode;
48
49 va_list ap;
50
51 if (!quietMode) {
52 printf("\n[%s] ",m->m_name);
53 va_start(ap,msg);
54 vprintf(msg,ap);
55 va_end(ap);
56 fflush(stdout);
57
58 if (!did_message && TkGate.tcl) {
59 message(1,"A verify error has ocurred (further verify errors will be reported only to the console).");
60 did_message = 1;
61 }
62 }
63
64 err_count++;
65 }
66
verify_net(GNet * n,GModuleDef * m)67 void verify_net(GNet *n,GModuleDef *m)
68 {
69 GWireList *wl;
70 GWire **wset;
71 int i;
72 int num_wires = 0;
73
74 if (n->n_mod != m)
75 verify_error(m,"module %s contains net %s claiming to be from module %s",
76 m->m_name,n->n_signame,n->n_mod->m_name);
77
78
79 for (wl = m->m_wires;wl;wl = wl->wl_next) {
80 GWire *w = wl->wl_wire;
81 if (!w) continue;
82 if (w->net == n) num_wires++;
83 }
84
85 wset = (GWire**) ob_malloc(num_wires*sizeof(GWire*),"GWire*[]");
86 for (i = 0;i < num_wires;i++) wset[i] = 0;
87
88 for (wl = m->m_wires;wl;wl = wl->wl_next) {
89 GWire *w = wl->wl_wire;
90 if (!w) continue;
91 if (w->net != n) continue;
92
93 if (w->nidx < 0 || w->nidx >= num_wires) {
94 verify_error(m,"index %d of wire 0x%x on net %s is out of range [0..%d].",
95 w->nidx,w,n->n_signame,num_wires-1);
96 continue;
97 }
98
99 if (wset[w->nidx]) {
100 verify_error(m,"index %d on net %s is used by multiple wires 0x%x and 0x%x.",
101 w->nidx,n->n_signame,wset[w->nidx],w);
102 continue;
103 }
104 wset[w->nidx] = w;
105 }
106
107 for (i = 0;i < num_wires;i++) {
108 if (!wset[i])
109 verify_error(m,"index %d on net %s is not used.",i,n->n_signame);
110 }
111
112 ob_free(wset);
113 }
114
verify_wire(GWire * w,GModuleDef * m)115 void verify_wire(GWire *w,GModuleDef *m)
116 {
117 if (w->gate) {
118 int p,n;
119 GCElement *g = w->gate;
120
121 if (posongate(w,g,&p,&n) != 0) {
122 verify_error(m,"wire 0x%x(%s) falsly claims to be attached to gate %s(%s).",
123 w,w->net->n_signame,g->ename,g->typeinfo->name);
124 }
125 }
126 }
127
verify_gate(GCElement * g,GModuleDef * m)128 void verify_gate(GCElement *g,GModuleDef *m)
129 {
130 int N = GCElement_numPads(g);
131 int i;
132 PHash *H = new_PHash();
133
134 for (i = 0;i < N;i++) {
135 GWire *w;
136
137 for (w = g->wires[i];w;w = w->next) {
138 if (PHash_find(H,w)) {
139 verify_error(m,"wire 0x%x(%s) attached to gate %s(%s) multiple times.",
140 w,w->net->n_signame,g->ename,g->typeinfo->name);
141 continue;
142 }
143 PHash_insert(H,w,w);
144 if (w->gate != g) {
145 if (w->gate)
146 verify_error(m,"wire 0x%x(%s) attached to gate %s(%s) is really attached to %s(%s).",
147 w,w->net->n_signame,g->ename,g->typeinfo->name,w->gate->ename,w->gate->typeinfo->name);
148 else
149 verify_error(m,"wire 0x%x(%s) attached to gate %s(%s) is really unattached.",
150 w,w->net->n_signame,g->ename,g->typeinfo->name);
151 }
152 }
153 }
154
155 switch (g->typeinfo->code) {
156 case GC_TAP :
157 if (g->wires[TAP_IN]->net != g->wires[TAP_OUT]->net)
158 verify_error(m,"tap 0x%x(%s) has inconsistent attachments.",
159 g,g->ename,g->wires[TAP_IN]->net->n_signame,g->wires[TAP_OUT]->net->n_signame);
160 break;
161 }
162
163 delete_PHash(H);
164 }
165
verify_module(GModuleDef * M)166 void verify_module(GModuleDef *M)
167 {
168 HashElem *E;
169 GWireList *wl;
170
171 v_wires = new_NHash();
172
173 for (E = Hash_first(M->m_gates);E;E = Hash_next(M->m_gates,E)) {
174 GCElement *g = (GCElement*) HashElem_obj(E);
175 verify_gate(g,M);
176 }
177 for (E = Hash_first(M->m_nets);E;E = Hash_next(M->m_nets,E)) {
178 GNet *n = (GNet*) HashElem_obj(E);
179 verify_net(n,M);
180 }
181
182 for (wl = M->m_wires;wl;wl = wl->wl_next) {
183 verify_wire(wl->wl_wire,M);
184 }
185
186 delete_NHash(v_wires);
187 }
188
189
verify_circuit()190 int verify_circuit()
191 {
192 HashElem *E;
193 extern int quietMode;
194
195 err_count = 0;
196
197 if (!quietMode) {
198 printf("verifying...");
199 fflush(stdout);
200 }
201
202 for (E = Hash_first(TkGate.circuit->moduleTable);E;E = Hash_next(TkGate.circuit->moduleTable,E)) {
203 GModuleDef *M = (GModuleDef*) HashElem_obj(E);
204 verify_module(M);
205 }
206
207 if (!quietMode) {
208 if (err_count > 0) printf("\n");
209 printf("[%d inconsistencie(s) found]\n",err_count);
210 }
211
212 return err_count;
213 }
214
215