1 |
16 |
HanySalah |
//
|
2 |
|
|
//------------------------------------------------------------------------------
|
3 |
|
|
// Copyright 2011 Mentor Graphics Corporation
|
4 |
|
|
// Copyright 2011 Cadence Design Systems, Inc.
|
5 |
|
|
// Copyright 2011 Synopsys, Inc.
|
6 |
|
|
// All Rights Reserved Worldwide
|
7 |
|
|
//
|
8 |
|
|
// Licensed under the Apache License, Version 2.0 (the
|
9 |
|
|
// "License"); you may not use this file except in
|
10 |
|
|
// compliance with the License. You may obtain a copy of
|
11 |
|
|
// the License at
|
12 |
|
|
//
|
13 |
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
14 |
|
|
//
|
15 |
|
|
// Unless required by applicable law or agreed to in
|
16 |
|
|
// writing, software distributed under the License is
|
17 |
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
18 |
|
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
19 |
|
|
// the License for the specific language governing
|
20 |
|
|
// permissions and limitations under the License.
|
21 |
|
|
//------------------------------------------------------------------------------
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
//----------------------------------------------------------------------
|
26 |
|
|
// class uvm_spell_chkr
|
27 |
|
|
//----------------------------------------------------------------------
|
28 |
|
|
class uvm_spell_chkr #(type T=int);
|
29 |
|
|
|
30 |
|
|
typedef T tab_t[string];
|
31 |
|
|
static const int unsigned max = '1;
|
32 |
|
|
|
33 |
|
|
//--------------------------------------------------------------------
|
34 |
|
|
// check
|
35 |
|
|
//
|
36 |
|
|
// primary interface to the spell checker. The function takes two
|
37 |
|
|
// arguments, a table of strings and a string to check. The table is
|
38 |
|
|
// organized as an associative array of type T. E.g.
|
39 |
|
|
//
|
40 |
|
|
// T strtab[string]
|
41 |
|
|
//
|
42 |
|
|
// It doesn't matter what T is since we are only concerned with the
|
43 |
|
|
// string keys. However, we need T in order to make argument types
|
44 |
|
|
// match.
|
45 |
|
|
//
|
46 |
|
|
// First, we do the simple thing and see if the string already is in
|
47 |
|
|
// the string table by calling the ~exists()~ method. If it does exist
|
48 |
|
|
// then there is a match and we're done. If the string doesn't exist
|
49 |
|
|
// in the table then we invoke the spell checker algorithm to see if
|
50 |
|
|
// our string is a misspelled variation on a string that does exist in
|
51 |
|
|
// the table.
|
52 |
|
|
//
|
53 |
|
|
// The main loop traverses the string table computing the levenshtein
|
54 |
|
|
// distance between each string and the string we are checking. The
|
55 |
|
|
// strings in the table with the minimum distance are considered
|
56 |
|
|
// possible alternatives. There may be more than one string in the
|
57 |
|
|
// table with a minimum distance. So all the alternatives are stored
|
58 |
|
|
// in a queue.
|
59 |
|
|
//
|
60 |
|
|
// Note: This is not a particularly efficient algorithm. It requires
|
61 |
|
|
// computing the levenshtein distance for every string in the string
|
62 |
|
|
// table. If that list were very large the run time could be long.
|
63 |
|
|
// For the resources application in UVM probably the size of the
|
64 |
|
|
// string table is not excessive and run times will be fast enough.
|
65 |
|
|
// If, on average, that proves to be an invalid assumption then we'll
|
66 |
|
|
// have to find ways to optimize this algorithm.
|
67 |
|
|
//
|
68 |
|
|
// note: strtab should not be modified inside check()
|
69 |
|
|
//--------------------------------------------------------------------
|
70 |
|
|
static function bit check ( /* const */ ref tab_t strtab, input string s);
|
71 |
|
|
|
72 |
|
|
string key;
|
73 |
|
|
int distance;
|
74 |
|
|
int unsigned min;
|
75 |
|
|
string min_key[$];
|
76 |
|
|
|
77 |
|
|
if(strtab.exists(s)) begin
|
78 |
|
|
return 1;
|
79 |
|
|
end
|
80 |
|
|
|
81 |
|
|
min = max;
|
82 |
|
|
foreach(strtab[key]) begin
|
83 |
|
|
distance = levenshtein_distance(key, s);
|
84 |
|
|
|
85 |
|
|
// A distance < 0 means either key, s, or both are empty. This
|
86 |
|
|
// should never happen here but we check for that condition just
|
87 |
|
|
// in case.
|
88 |
|
|
if(distance < 0)
|
89 |
|
|
continue;
|
90 |
|
|
|
91 |
|
|
if(distance < min) begin
|
92 |
|
|
// set a new minimum. Clean out the queue since previous
|
93 |
|
|
// alternatives are now invalidated.
|
94 |
|
|
min = distance;
|
95 |
|
|
min_key.delete();
|
96 |
|
|
min_key.push_back(key);
|
97 |
|
|
continue;
|
98 |
|
|
end
|
99 |
|
|
|
100 |
|
|
if(distance == min) begin
|
101 |
|
|
min_key.push_back(key);
|
102 |
|
|
end
|
103 |
|
|
|
104 |
|
|
end
|
105 |
|
|
|
106 |
|
|
|
107 |
|
|
// if (min == max) then the string table is empty
|
108 |
|
|
if(min == max) begin
|
109 |
|
|
`uvm_info("UVM/CONFIGDB/SPELLCHK",$sformatf("%s not located, no alternatives to suggest", s),UVM_NONE)
|
110 |
|
|
end
|
111 |
|
|
else
|
112 |
|
|
// dump all the alternatives with the minimum distance
|
113 |
|
|
begin
|
114 |
|
|
string q[$];
|
115 |
|
|
|
116 |
|
|
foreach(min_key[i]) begin
|
117 |
|
|
q.push_back(min_key[i]);
|
118 |
|
|
q.push_back("|");
|
119 |
|
|
end
|
120 |
|
|
if(q.size())
|
121 |
|
|
void'(q.pop_back());
|
122 |
|
|
|
123 |
|
|
`uvm_info("UVM/CONFIGDB/SPELLCHK",$sformatf("%s not located, did you mean %s", s, `UVM_STRING_QUEUE_STREAMING_PACK(q)),UVM_NONE)
|
124 |
|
|
end
|
125 |
|
|
|
126 |
|
|
return 0;
|
127 |
|
|
|
128 |
|
|
endfunction
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
//--------------------------------------------------------------------
|
132 |
|
|
// levenshtein_distance
|
133 |
|
|
//
|
134 |
|
|
// Compute levenshtein distance between s and t
|
135 |
|
|
// The Levenshtein distance is defined as The smallest number of
|
136 |
|
|
// insertions, deletions, and substitutions required to change one
|
137 |
|
|
// string into another. There is a tremendous amount of information
|
138 |
|
|
// available on Levenshtein distance on the internet. Two good
|
139 |
|
|
// sources are wikipedia and nist.gov. A nice, simple explanation of
|
140 |
|
|
// the algorithm is at
|
141 |
|
|
// http://www.codeproject.com/KB/recipes/Levenshtein.aspx. Use google
|
142 |
|
|
// to find others.
|
143 |
|
|
//
|
144 |
|
|
// This implementation of the Levenshtein
|
145 |
|
|
// distance computation algorithm is a SystemVerilog adaptation of the
|
146 |
|
|
// C implementatiion located at http://www.merriampark.com/ldc.htm.
|
147 |
|
|
//--------------------------------------------------------------------
|
148 |
|
|
static local function int levenshtein_distance(string s, string t);
|
149 |
|
|
|
150 |
|
|
int k, i, j, n, m, cost, distance;
|
151 |
|
|
int d[];
|
152 |
|
|
|
153 |
|
|
//Step 1
|
154 |
|
|
n = s.len() + 1;
|
155 |
|
|
m = t.len() + 1;
|
156 |
|
|
|
157 |
|
|
if(n == 1 || m == 1)
|
158 |
|
|
return -1; //a negative return value means that one or both strings are empty.
|
159 |
|
|
|
160 |
|
|
d = new[m*n];
|
161 |
|
|
|
162 |
|
|
//Step 2
|
163 |
|
|
for(k = 0; k < n; k++)
|
164 |
|
|
d[k] = k;
|
165 |
|
|
|
166 |
|
|
for(k = 0; k < m; k++)
|
167 |
|
|
d[k*n] = k;
|
168 |
|
|
|
169 |
|
|
//Steps 3 and 4
|
170 |
|
|
for(i = 1; i < n; i++) begin
|
171 |
|
|
for(j = 1; j < m; j++) begin
|
172 |
|
|
|
173 |
|
|
//Step 5
|
174 |
|
|
cost = !(s[i-1] == t[j-1]);
|
175 |
|
|
|
176 |
|
|
//Step 6
|
177 |
|
|
d[j*n+i] = minimum(d[(j-1)*n+i]+1, d[j*n+i-1]+1, d[(j-1)*n+i-1]+cost);
|
178 |
|
|
|
179 |
|
|
end
|
180 |
|
|
end
|
181 |
|
|
|
182 |
|
|
distance = d[n*m-1];
|
183 |
|
|
return distance;
|
184 |
|
|
|
185 |
|
|
endfunction
|
186 |
|
|
|
187 |
|
|
//--------------------------------------------------------------------
|
188 |
|
|
// Gets the minimum of three values
|
189 |
|
|
//--------------------------------------------------------------------
|
190 |
|
|
static local function int minimum(int a, int b, int c);
|
191 |
|
|
|
192 |
|
|
int min = a;
|
193 |
|
|
|
194 |
|
|
if(b < min)
|
195 |
|
|
min = b;
|
196 |
|
|
if(c < min)
|
197 |
|
|
min = c;
|
198 |
|
|
|
199 |
|
|
return min;
|
200 |
|
|
|
201 |
|
|
endfunction
|
202 |
|
|
|
203 |
|
|
endclass
|