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