1
by Colin Watson
Import upstream version 5.5.4 |
1 |
/*
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
2 |
* $Id: verilog.c 573 2007-06-26 05:41:27Z elliotth $
|
1
by Colin Watson
Import upstream version 5.5.4 |
3 |
*
|
4 |
* Copyright (c) 2003, Darren Hiebert
|
|
5 |
*
|
|
6 |
* This source code is released for free distribution under the terms of the
|
|
7 |
* GNU General Public License.
|
|
8 |
*
|
|
9 |
* This module contains functions for generating tags for the Verilog HDL
|
|
10 |
* (Hardware Description Language).
|
|
11 |
*
|
|
12 |
* Language definition documents:
|
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
13 |
* http://www.eg.bucknell.edu/~cs320/verilog/verilog-manual.html
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
14 |
* http://www.sutherland-hdl.com/on-line_ref_guide/vlog_ref_top.html
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
15 |
* http://www.verilog.com/VerilogBNF.html
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
16 |
* http://eesun.free.fr/DOC/VERILOG/verilog_manual1.html
|
1
by Colin Watson
Import upstream version 5.5.4 |
17 |
*/
|
18 |
||
19 |
/*
|
|
20 |
* INCLUDE FILES
|
|
21 |
*/
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
22 |
#include "general.h" /* must always come first */ |
1
by Colin Watson
Import upstream version 5.5.4 |
23 |
|
24 |
#include <string.h> |
|
25 |
#include <setjmp.h> |
|
26 |
||
27 |
#include "debug.h" |
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
28 |
#include "get.h" |
1
by Colin Watson
Import upstream version 5.5.4 |
29 |
#include "keyword.h" |
30 |
#include "parse.h" |
|
31 |
#include "read.h" |
|
32 |
#include "vstring.h" |
|
33 |
||
34 |
/*
|
|
35 |
* DATA DECLARATIONS
|
|
36 |
*/
|
|
37 |
typedef enum eException { ExceptionNone, ExceptionEOF } exception_t; |
|
38 |
||
39 |
typedef enum { |
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
40 |
K_UNDEFINED = -1, |
41 |
K_CONSTANT, |
|
42 |
K_EVENT, |
|
43 |
K_FUNCTION, |
|
44 |
K_MODULE, |
|
45 |
K_NET, |
|
46 |
K_PORT, |
|
47 |
K_REGISTER, |
|
48 |
K_TASK
|
|
1
by Colin Watson
Import upstream version 5.5.4 |
49 |
} verilogKind; |
50 |
||
51 |
typedef struct { |
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
52 |
const char *keyword; |
53 |
verilogKind kind; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
54 |
} keywordAssoc; |
55 |
||
56 |
/*
|
|
57 |
* DATA DEFINITIONS
|
|
58 |
*/
|
|
59 |
static int Ungetc; |
|
60 |
static int Lang_verilog; |
|
61 |
static jmp_buf Exception; |
|
62 |
||
63 |
static kindOption VerilogKinds [] = { |
|
64 |
{ TRUE, 'c', "constant", "constants (define, parameter, specparam)" }, |
|
65 |
{ TRUE, 'e', "event", "events" }, |
|
66 |
{ TRUE, 'f', "function", "functions" }, |
|
67 |
{ TRUE, 'm', "module", "modules" }, |
|
68 |
{ TRUE, 'n', "net", "net data types" }, |
|
69 |
{ TRUE, 'p', "port", "ports" }, |
|
70 |
{ TRUE, 'r', "register", "register data types" }, |
|
71 |
{ TRUE, 't', "task", "tasks" } |
|
72 |
};
|
|
73 |
||
74 |
static keywordAssoc VerilogKeywordTable [] = { |
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
75 |
{ "`define", K_CONSTANT }, |
76 |
{ "event", K_EVENT }, |
|
77 |
{ "function", K_FUNCTION }, |
|
78 |
{ "inout", K_PORT }, |
|
79 |
{ "input", K_PORT }, |
|
80 |
{ "integer", K_REGISTER }, |
|
81 |
{ "module", K_MODULE }, |
|
82 |
{ "output", K_PORT }, |
|
83 |
{ "parameter", K_CONSTANT }, |
|
84 |
{ "real", K_REGISTER }, |
|
85 |
{ "realtime", K_REGISTER }, |
|
86 |
{ "reg", K_REGISTER }, |
|
87 |
{ "specparam", K_CONSTANT }, |
|
88 |
{ "supply0", K_NET }, |
|
89 |
{ "supply1", K_NET }, |
|
90 |
{ "task", K_TASK }, |
|
91 |
{ "time", K_REGISTER }, |
|
92 |
{ "tri0", K_NET }, |
|
93 |
{ "tri1", K_NET }, |
|
94 |
{ "triand", K_NET }, |
|
95 |
{ "tri", K_NET }, |
|
96 |
{ "trior", K_NET }, |
|
97 |
{ "trireg", K_NET }, |
|
98 |
{ "wand", K_NET }, |
|
99 |
{ "wire", K_NET }, |
|
100 |
{ "wor", K_NET } |
|
1
by Colin Watson
Import upstream version 5.5.4 |
101 |
};
|
102 |
||
103 |
/*
|
|
104 |
* FUNCTION DEFINITIONS
|
|
105 |
*/
|
|
106 |
||
107 |
static void initialize (const langType language) |
|
108 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
109 |
size_t i; |
110 |
const size_t count = |
|
111 |
sizeof (VerilogKeywordTable) / sizeof (VerilogKeywordTable [0]); |
|
112 |
Lang_verilog = language; |
|
113 |
for (i = 0 ; i < count ; ++i) |
|
114 |
{
|
|
115 |
const keywordAssoc* const p = &VerilogKeywordTable [i]; |
|
116 |
addKeyword (p->keyword, language, (int) p->kind); |
|
117 |
}
|
|
1
by Colin Watson
Import upstream version 5.5.4 |
118 |
}
|
119 |
||
120 |
static void vUngetc (int c) |
|
121 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
122 |
Assert (Ungetc == '\0'); |
123 |
Ungetc = c; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
124 |
}
|
125 |
||
126 |
static int vGetc (void) |
|
127 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
128 |
int c; |
129 |
if (Ungetc == '\0') |
|
1
by Colin Watson
Import upstream version 5.5.4 |
130 |
c = fileGetc (); |
1.1.1
by Colin Watson
Import upstream version 5.6 |
131 |
else
|
132 |
{
|
|
133 |
c = Ungetc; |
|
134 |
Ungetc = '\0'; |
|
135 |
}
|
|
136 |
if (c == '/') |
|
137 |
{
|
|
138 |
int c2 = fileGetc (); |
|
139 |
if (c2 == EOF) |
|
140 |
longjmp (Exception, (int) ExceptionEOF); |
|
141 |
else if (c2 == '/') /* strip comment until end-of-line */ |
|
142 |
{
|
|
143 |
do
|
|
144 |
c = fileGetc (); |
|
145 |
while (c != '\n' && c != EOF); |
|
146 |
}
|
|
147 |
else if (c2 == '*') /* strip block comment */ |
|
148 |
{
|
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
149 |
c = skipOverCComment(); |
1.1.1
by Colin Watson
Import upstream version 5.6 |
150 |
}
|
151 |
else
|
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
152 |
{
|
153 |
fileUngetc (c2); |
|
154 |
}
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
155 |
}
|
156 |
else if (c == '"') /* strip string contents */ |
|
157 |
{
|
|
158 |
int c2; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
159 |
do
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
160 |
c2 = fileGetc (); |
161 |
while (c2 != '"' && c2 != EOF); |
|
162 |
c = '@'; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
163 |
}
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
164 |
if (c == EOF) |
165 |
longjmp (Exception, (int) ExceptionEOF); |
|
166 |
return c; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
167 |
}
|
168 |
||
169 |
static boolean isIdentifierCharacter (const int c) |
|
170 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
171 |
return (boolean)(isalnum (c) || c == '_' || c == '`'); |
1
by Colin Watson
Import upstream version 5.5.4 |
172 |
}
|
173 |
||
174 |
static int skipWhite (int c) |
|
175 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
176 |
while (isspace (c)) |
177 |
c = vGetc (); |
|
178 |
return c; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
179 |
}
|
180 |
||
181 |
static int skipPastMatch (const char *const pair) |
|
182 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
183 |
const int begin = pair [0], end = pair [1]; |
184 |
int matchLevel = 1; |
|
185 |
int c; |
|
186 |
do
|
|
187 |
{
|
|
188 |
c = vGetc (); |
|
189 |
if (c == begin) |
|
190 |
++matchLevel; |
|
191 |
else if (c == end) |
|
192 |
--matchLevel; |
|
193 |
}
|
|
194 |
while (matchLevel > 0); |
|
195 |
return vGetc (); |
|
1
by Colin Watson
Import upstream version 5.5.4 |
196 |
}
|
197 |
||
198 |
static boolean readIdentifier (vString *const name, int c) |
|
199 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
200 |
vStringClear (name); |
201 |
if (isIdentifierCharacter (c)) |
|
1
by Colin Watson
Import upstream version 5.5.4 |
202 |
{
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
203 |
while (isIdentifierCharacter (c)) |
204 |
{
|
|
205 |
vStringPut (name, c); |
|
206 |
c = vGetc (); |
|
207 |
}
|
|
208 |
vUngetc (c); |
|
209 |
vStringTerminate (name); |
|
1
by Colin Watson
Import upstream version 5.5.4 |
210 |
}
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
211 |
return (boolean)(name->length > 0); |
212 |
}
|
|
213 |
||
214 |
static void tagNameList (const verilogKind kind, int c) |
|
215 |
{
|
|
216 |
vString *name = vStringNew (); |
|
217 |
boolean repeat; |
|
218 |
Assert (isIdentifierCharacter (c)); |
|
219 |
do
|
|
220 |
{
|
|
221 |
repeat = FALSE; |
|
222 |
if (isIdentifierCharacter (c)) |
|
223 |
{
|
|
224 |
readIdentifier (name, c); |
|
225 |
makeSimpleTag (name, VerilogKinds, kind); |
|
226 |
}
|
|
227 |
else
|
|
228 |
break; |
|
229 |
c = skipWhite (vGetc ()); |
|
230 |
if (c == '[') |
|
231 |
c = skipPastMatch ("[]"); |
|
232 |
c = skipWhite (c); |
|
233 |
if (c == '=') |
|
234 |
{
|
|
235 |
if (c == '{') |
|
236 |
skipPastMatch ("{}"); |
|
237 |
else
|
|
238 |
{
|
|
239 |
do
|
|
240 |
c = vGetc (); |
|
241 |
while (c != ',' && c != ';'); |
|
242 |
}
|
|
243 |
}
|
|
244 |
if (c == ',') |
|
245 |
{
|
|
246 |
c = skipWhite (vGetc ()); |
|
247 |
repeat = TRUE; |
|
248 |
}
|
|
249 |
else
|
|
250 |
repeat = FALSE; |
|
251 |
} while (repeat); |
|
252 |
vStringDelete (name); |
|
1
by Colin Watson
Import upstream version 5.5.4 |
253 |
vUngetc (c); |
254 |
}
|
|
255 |
||
256 |
static void findTag (vString *const name) |
|
257 |
{
|
|
1.1.2
by Colin Watson
Import upstream version 5.7 |
258 |
const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog); |
259 |
if (kind == K_CONSTANT && vStringItem (name, 0) == '`') |
|
260 |
{
|
|
261 |
/* Bug #961001: Verilog compiler directives are line-based. */
|
|
262 |
int c = skipWhite (vGetc ()); |
|
263 |
readIdentifier (name, c); |
|
264 |
makeSimpleTag (name, VerilogKinds, kind); |
|
265 |
/* Skip the rest of the line. */
|
|
266 |
do { |
|
267 |
c = vGetc(); |
|
268 |
} while (c != '\n'); |
|
269 |
vUngetc (c); |
|
270 |
}
|
|
271 |
else if (kind != K_UNDEFINED) |
|
1
by Colin Watson
Import upstream version 5.5.4 |
272 |
{
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
273 |
int c = skipWhite (vGetc ()); |
274 |
||
275 |
/* Many keywords can have bit width.
|
|
276 |
* reg [3:0] net_name;
|
|
277 |
* inout [(`DBUSWIDTH-1):0] databus;
|
|
278 |
*/
|
|
279 |
if (c == '(') |
|
280 |
c = skipPastMatch ("()"); |
|
281 |
c = skipWhite (c); |
|
282 |
if (c == '[') |
|
283 |
c = skipPastMatch ("[]"); |
|
284 |
c = skipWhite (c); |
|
285 |
if (c == '#') |
|
286 |
{
|
|
287 |
c = vGetc (); |
|
288 |
if (c == '(') |
|
289 |
c = skipPastMatch ("()"); |
|
290 |
}
|
|
291 |
c = skipWhite (c); |
|
292 |
if (isIdentifierCharacter (c)) |
|
293 |
tagNameList (kind, c); |
|
1
by Colin Watson
Import upstream version 5.5.4 |
294 |
}
|
295 |
}
|
|
296 |
||
297 |
static void findVerilogTags (void) |
|
298 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
299 |
vString *const name = vStringNew (); |
300 |
volatile boolean newStatement = TRUE; |
|
301 |
volatile int c = '\0'; |
|
302 |
exception_t exception = (exception_t) setjmp (Exception); |
|
1
by Colin Watson
Import upstream version 5.5.4 |
303 |
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
304 |
if (exception == ExceptionNone) while (c != EOF) |
1
by Colin Watson
Import upstream version 5.5.4 |
305 |
{
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
306 |
c = vGetc (); |
307 |
switch (c) |
|
308 |
{
|
|
309 |
case ';': |
|
310 |
case '\n': |
|
311 |
newStatement = TRUE; |
|
312 |
break; |
|
313 |
||
314 |
case ' ': |
|
315 |
case '\t': |
|
316 |
break; |
|
317 |
||
318 |
default: |
|
319 |
if (newStatement && readIdentifier (name, c)) |
|
320 |
findTag (name); |
|
321 |
newStatement = FALSE; |
|
322 |
break; |
|
323 |
}
|
|
1
by Colin Watson
Import upstream version 5.5.4 |
324 |
}
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
325 |
vStringDelete (name); |
1
by Colin Watson
Import upstream version 5.5.4 |
326 |
}
|
327 |
||
328 |
extern parserDefinition* VerilogParser (void) |
|
329 |
{
|
|
1.1.1
by Colin Watson
Import upstream version 5.6 |
330 |
static const char *const extensions [] = { "v", NULL }; |
331 |
parserDefinition* def = parserNew ("Verilog"); |
|
332 |
def->kinds = VerilogKinds; |
|
333 |
def->kindCount = KIND_COUNT (VerilogKinds); |
|
334 |
def->extensions = extensions; |
|
335 |
def->parser = findVerilogTags; |
|
336 |
def->initialize = initialize; |
|
337 |
return def; |
|
1
by Colin Watson
Import upstream version 5.5.4 |
338 |
}
|
339 |
||
1.1.1
by Colin Watson
Import upstream version 5.6 |
340 |
/* vi:set tabstop=4 shiftwidth=4: */
|