2011-04-28 02:08:42 +02:00
|
|
|
%option prefix="yy"
|
2006-05-17 06:15:12 +02:00
|
|
|
%option never-interactive
|
2008-01-04 20:33:03 +01:00
|
|
|
%option nounput
|
2006-05-17 06:15:12 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
%{
|
2001-03-20 03:48:40 +01:00
|
|
|
/*
|
2011-02-28 04:20:16 +01:00
|
|
|
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
2001-03-20 03:48:40 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
# include "parse_misc.h"
|
|
|
|
|
# include "compile.h"
|
|
|
|
|
# include "parse.h"
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <cstring>
|
|
|
|
|
# include <cassert>
|
2010-10-24 00:52:56 +02:00
|
|
|
# include "ivl_alloc.h"
|
2009-01-13 18:57:12 +01:00
|
|
|
|
|
|
|
|
static char* strdupnew(char const *str)
|
|
|
|
|
{
|
|
|
|
|
return str ? strcpy(new char [strlen(str)+1], str) : 0;
|
|
|
|
|
}
|
2009-02-24 22:50:18 +01:00
|
|
|
|
|
|
|
|
inline uint64_t strtouint64(const char*str, char**endptr, int base)
|
|
|
|
|
{
|
|
|
|
|
if (sizeof(unsigned long) >= sizeof(uint64_t))
|
|
|
|
|
return strtoul(str, endptr, base);
|
|
|
|
|
else
|
|
|
|
|
return strtoull(str, endptr, base);
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
2008-01-01 18:45:02 +01:00
|
|
|
/* These are some special header/footer keywords. */
|
2008-11-25 00:20:46 +01:00
|
|
|
^":ivl_version" { return K_ivl_version; }
|
2010-03-14 05:22:45 +01:00
|
|
|
^":ivl_delay_selection" { return K_ivl_delay_selection; }
|
2001-03-23 03:40:22 +01:00
|
|
|
^":vpi_module" { return K_vpi_module; }
|
2001-07-01 01:03:16 +02:00
|
|
|
^":vpi_time_precision" { return K_vpi_time_precision; }
|
2008-01-01 18:45:02 +01:00
|
|
|
^":file_names" { return K_file_names; }
|
2001-03-23 03:40:22 +01:00
|
|
|
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/* A label is any non-blank text that appears left justified. */
|
2001-06-18 05:10:34 +02:00
|
|
|
^[.$_a-zA-Z\\][.$_a-zA-Z\\0-9<>/]* {
|
2001-03-11 01:29:38 +01:00
|
|
|
yylval.text = strdup(yytext);
|
2002-03-01 06:42:50 +01:00
|
|
|
assert(yylval.text);
|
2001-03-11 01:29:38 +01:00
|
|
|
return T_LABEL; }
|
|
|
|
|
|
2001-03-16 02:44:34 +01:00
|
|
|
/* String tokens are parsed here. Return as the token value the
|
|
|
|
|
contents of the string without the enclosing quotes. */
|
2001-06-18 05:10:34 +02:00
|
|
|
\"([^\"\\]|\\.)*\" {
|
2001-03-16 02:44:34 +01:00
|
|
|
yytext[strlen(yytext)-1] = 0;
|
2009-01-13 18:57:12 +01:00
|
|
|
yylval.text = strdupnew(yytext+1);
|
2002-03-01 06:42:50 +01:00
|
|
|
assert(yylval.text);
|
2001-03-16 02:44:34 +01:00
|
|
|
return T_STRING; }
|
|
|
|
|
|
2003-02-10 00:33:26 +01:00
|
|
|
/* Binary vector tokens are parsed here. The result of this is a
|
2002-04-14 05:53:20 +02:00
|
|
|
string of binary 4-values in the yylval.vect.text string. This is
|
2003-02-10 00:33:26 +01:00
|
|
|
preceded by an 's' if the vector is signed. */
|
2002-04-14 05:53:20 +02:00
|
|
|
[1-9][0-9]*("'b"|"'sb")[01xz]+ {
|
2001-04-04 06:33:08 +02:00
|
|
|
yylval.vect.idx = strtoul(yytext, 0, 10);
|
2002-04-14 05:53:20 +02:00
|
|
|
yylval.vect.text = (char*)malloc(yylval.vect.idx + 2);
|
|
|
|
|
char*dest = yylval.vect.text;
|
2001-04-04 06:33:08 +02:00
|
|
|
|
2002-04-14 05:53:20 +02:00
|
|
|
const char*bits = strchr(yytext, '\'');
|
|
|
|
|
assert(bits);
|
|
|
|
|
bits += 1;
|
|
|
|
|
|
|
|
|
|
if (*bits == 's') {
|
|
|
|
|
*dest++ = 's';
|
|
|
|
|
bits += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(*bits == 'b');
|
2001-04-04 06:33:08 +02:00
|
|
|
bits += 1;
|
|
|
|
|
unsigned pad = 0;
|
|
|
|
|
if (strlen(bits) < yylval.vect.idx)
|
|
|
|
|
pad = yylval.vect.idx - strlen(bits);
|
|
|
|
|
|
2002-04-14 05:53:20 +02:00
|
|
|
memset(dest, '0', pad);
|
2001-04-04 06:33:08 +02:00
|
|
|
for (unsigned idx = pad ; idx < yylval.vect.idx ; idx += 1)
|
2002-04-14 05:53:20 +02:00
|
|
|
dest[idx] = bits[idx-pad];
|
2001-04-04 06:33:08 +02:00
|
|
|
|
2002-04-14 05:53:20 +02:00
|
|
|
dest[yylval.vect.idx] = 0;
|
2001-04-04 06:33:08 +02:00
|
|
|
return T_VECTOR; }
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
|
|
|
|
|
/* These are some keywords that are recognized. */
|
2005-10-12 19:23:15 +02:00
|
|
|
".alias" { return K_ALIAS; }
|
|
|
|
|
".alias/real" { return K_ALIAS_R; }
|
2008-05-07 05:37:00 +02:00
|
|
|
".abs" { return K_ARITH_ABS; }
|
2004-06-30 04:15:57 +02:00
|
|
|
".arith/div" { return K_ARITH_DIV; }
|
2005-07-06 06:29:25 +02:00
|
|
|
".arith/div.r" { return K_ARITH_DIV_R; }
|
2004-06-30 04:15:57 +02:00
|
|
|
".arith/div.s" { return K_ARITH_DIV_S; }
|
2002-01-03 05:19:01 +01:00
|
|
|
".arith/mod" { return K_ARITH_MOD; }
|
2008-01-31 03:32:27 +01:00
|
|
|
".arith/mod.r" { return K_ARITH_MOD_R; }
|
2008-11-08 03:23:04 +01:00
|
|
|
".arith/mod.s" { return K_ARITH_MOD_S; }
|
2001-06-17 01:45:05 +02:00
|
|
|
".arith/mult" { return K_ARITH_MULT; }
|
2008-01-04 08:44:14 +01:00
|
|
|
".arith/mult.r" { return K_ARITH_MULT_R; }
|
2008-02-06 04:09:30 +01:00
|
|
|
".arith/pow" { return K_ARITH_POW; }
|
2008-01-31 02:53:06 +01:00
|
|
|
".arith/pow.r" { return K_ARITH_POW_R; }
|
2008-02-09 02:32:57 +01:00
|
|
|
".arith/pow.s" { return K_ARITH_POW_S; }
|
2001-06-17 01:45:05 +02:00
|
|
|
".arith/sub" { return K_ARITH_SUB; }
|
2005-07-06 06:29:25 +02:00
|
|
|
".arith/sub.r" { return K_ARITH_SUB_R; }
|
2001-06-17 01:45:05 +02:00
|
|
|
".arith/sum" { return K_ARITH_SUM; }
|
2008-01-04 08:44:14 +01:00
|
|
|
".arith/sum.r" { return K_ARITH_SUM_R; }
|
2007-01-16 06:44:14 +01:00
|
|
|
".array" { return K_ARRAY; }
|
2007-04-10 03:26:15 +02:00
|
|
|
".array/i" { return K_ARRAY_I; }
|
|
|
|
|
".array/real" { return K_ARRAY_R; }
|
|
|
|
|
".array/s" { return K_ARRAY_S; }
|
2007-01-16 06:44:14 +01:00
|
|
|
".array/port" { return K_ARRAY_PORT; }
|
2010-10-16 19:53:20 +02:00
|
|
|
".cast/2" { return K_CAST_2; }
|
2008-06-21 03:11:11 +02:00
|
|
|
".cast/int" { return K_CAST_INT; }
|
2008-06-18 02:07:19 +02:00
|
|
|
".cast/real" { return K_CAST_REAL; }
|
2008-06-21 03:11:11 +02:00
|
|
|
".cast/real.s" { return K_CAST_REAL_S; }
|
2005-01-22 02:06:20 +01:00
|
|
|
".cmp/eeq" { return K_CMP_EEQ; }
|
2004-06-16 18:33:25 +02:00
|
|
|
".cmp/eq" { return K_CMP_EQ; }
|
2008-01-15 19:54:04 +01:00
|
|
|
".cmp/eq.r" { return K_CMP_EQ_R; }
|
2005-03-09 06:52:03 +01:00
|
|
|
".cmp/nee" { return K_CMP_NEE; }
|
2004-06-16 18:33:25 +02:00
|
|
|
".cmp/ne" { return K_CMP_NE; }
|
2008-01-15 19:54:04 +01:00
|
|
|
".cmp/ne.r" { return K_CMP_NE_R; }
|
2001-06-15 06:07:57 +02:00
|
|
|
".cmp/ge" { return K_CMP_GE; }
|
2008-01-15 19:54:04 +01:00
|
|
|
".cmp/ge.r" { return K_CMP_GE_R; }
|
2003-04-11 07:15:38 +02:00
|
|
|
".cmp/ge.s" { return K_CMP_GE_S; }
|
2001-06-15 06:07:57 +02:00
|
|
|
".cmp/gt" { return K_CMP_GT; }
|
2008-01-15 19:54:04 +01:00
|
|
|
".cmp/gt.r" { return K_CMP_GT_R; }
|
2003-04-11 07:15:38 +02:00
|
|
|
".cmp/gt.s" { return K_CMP_GT_S; }
|
2004-12-30 00:45:13 +01:00
|
|
|
".concat" { return K_CONCAT; }
|
2006-01-02 06:32:06 +01:00
|
|
|
".delay" { return K_DELAY; }
|
2005-04-24 22:07:25 +02:00
|
|
|
".dff" { return K_DFF; }
|
2010-11-22 02:24:46 +01:00
|
|
|
".enum2" { return K_ENUM2; }
|
2011-09-20 03:50:06 +02:00
|
|
|
".enum2/s" { return K_ENUM2_S; }
|
2010-11-22 02:24:46 +01:00
|
|
|
".enum4" { return K_ENUM4; }
|
2011-09-20 03:50:06 +02:00
|
|
|
".enum4/s" { return K_ENUM4_S; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".event" { return K_EVENT; }
|
|
|
|
|
".event/or" { return K_EVENT_OR; }
|
2008-06-01 06:45:55 +02:00
|
|
|
".export" { return K_EXPORT; }
|
2005-05-24 03:43:27 +02:00
|
|
|
".extend/s" { return K_EXTEND_S; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".functor" { return K_FUNCTOR; }
|
2008-06-01 06:45:55 +02:00
|
|
|
".import" { return K_IMPORT; }
|
|
|
|
|
".island" { return K_ISLAND; }
|
2010-10-11 04:39:58 +02:00
|
|
|
".modpath" { return K_MODPATH; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".net" { return K_NET; }
|
2010-10-11 04:39:58 +02:00
|
|
|
".net/2s" { return K_NET_2S; }
|
|
|
|
|
".net/2u" { return K_NET_2U; }
|
2005-11-25 18:55:26 +01:00
|
|
|
".net8" { return K_NET8; }
|
|
|
|
|
".net8/s" { return K_NET8_S; }
|
2005-07-06 06:29:25 +02:00
|
|
|
".net/real" { return K_NET_R; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".net/s" { return K_NET_S; }
|
2006-03-08 06:29:42 +01:00
|
|
|
".param/l" { return K_PARAM_L; }
|
|
|
|
|
".param/str" { return K_PARAM_STR; }
|
2008-03-22 03:16:19 +01:00
|
|
|
".param/real" { return K_PARAM_REAL; }
|
2004-12-11 03:31:25 +01:00
|
|
|
".part" { return K_PART; }
|
2005-01-09 21:11:15 +01:00
|
|
|
".part/pv" { return K_PART_PV; }
|
2005-05-09 01:40:14 +02:00
|
|
|
".part/v" { return K_PART_V; }
|
2009-09-19 02:32:39 +02:00
|
|
|
".part/v.s" { return K_PART_V_S; }
|
2008-06-01 06:45:55 +02:00
|
|
|
".port" { return K_PORT; }
|
2005-02-03 05:55:13 +01:00
|
|
|
".reduce/and" { return K_REDUCE_AND; }
|
|
|
|
|
".reduce/or" { return K_REDUCE_OR; }
|
|
|
|
|
".reduce/xor" { return K_REDUCE_XOR; }
|
|
|
|
|
".reduce/nand" { return K_REDUCE_NAND; }
|
|
|
|
|
".reduce/nor" { return K_REDUCE_NOR; }
|
|
|
|
|
".reduce/xnor" { return K_REDUCE_XNOR; }
|
2005-02-07 23:42:42 +01:00
|
|
|
".repeat" { return K_REPEAT; }
|
2001-05-09 04:53:25 +02:00
|
|
|
".resolv" { return K_RESOLV; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".scope" { return K_SCOPE; }
|
2006-06-18 06:15:50 +02:00
|
|
|
".sfunc" { return K_SFUNC; }
|
2008-12-22 22:48:34 +01:00
|
|
|
".sfunc/e" { return K_SFUNC_E; }
|
2001-07-06 06:46:44 +02:00
|
|
|
".shift/l" { return K_SHIFTL; }
|
2001-07-07 04:57:33 +02:00
|
|
|
".shift/r" { return K_SHIFTR; }
|
2006-07-30 04:51:35 +02:00
|
|
|
".shift/rs" { return K_SHIFTRS; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".thread" { return K_THREAD; }
|
2002-12-21 01:55:57 +01:00
|
|
|
".timescale" { return K_TIMESCALE; }
|
2008-06-01 06:45:55 +02:00
|
|
|
".tran" { return K_TRAN; }
|
|
|
|
|
".tranif0" { return K_TRANIF0; }
|
|
|
|
|
".tranif1" { return K_TRANIF1; }
|
2008-06-03 20:16:25 +02:00
|
|
|
".tranvp" { return K_TRANVP; }
|
2002-03-18 01:19:34 +01:00
|
|
|
".ufunc" { return K_UFUNC; }
|
2008-12-22 22:48:34 +01:00
|
|
|
".ufunc/e" { return K_UFUNC_E; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".var" { return K_VAR; }
|
2005-07-06 06:29:25 +02:00
|
|
|
".var/real" { return K_VAR_R; }
|
2001-04-14 07:10:56 +02:00
|
|
|
".var/s" { return K_VAR_S; }
|
2002-06-21 06:58:55 +02:00
|
|
|
".var/i" { return K_VAR_I; /* integer */ }
|
2010-10-08 03:01:11 +02:00
|
|
|
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
|
|
|
|
|
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
|
2001-04-24 04:23:58 +02:00
|
|
|
".udp" { return K_UDP; }
|
|
|
|
|
".udp/c"(omb)? { return K_UDP_C; }
|
|
|
|
|
".udp/s"(equ)? { return K_UDP_S; }
|
2006-11-22 07:10:05 +01:00
|
|
|
"-debug" { return K_DEBUG; }
|
2001-03-11 01:29:38 +01:00
|
|
|
|
|
|
|
|
/* instructions start with a % character. The compiler decides what
|
2001-03-16 02:44:34 +01:00
|
|
|
kind of instruction this really is. The few exceptions (that have
|
|
|
|
|
exceptional parameter requirements) are listed first. */
|
|
|
|
|
|
2011-02-28 04:20:16 +01:00
|
|
|
"%vpi_call" { return K_vpi_call; }
|
2010-06-09 20:56:00 +02:00
|
|
|
"%vpi_call/w" { return K_vpi_call_w; }
|
|
|
|
|
"%vpi_call/i" { return K_vpi_call_i; }
|
2011-02-28 04:20:16 +01:00
|
|
|
"%vpi_func" { return K_vpi_func; }
|
2003-01-27 01:14:37 +01:00
|
|
|
"%vpi_func/r" { return K_vpi_func_r; }
|
2011-02-28 04:20:16 +01:00
|
|
|
"%disable" { return K_disable; }
|
|
|
|
|
"%fork" { return K_fork; }
|
|
|
|
|
"%file_line" { return K_file_line; }
|
2001-03-16 02:44:34 +01:00
|
|
|
|
2008-05-27 23:29:08 +02:00
|
|
|
/* Handle the specialized variable access functions. */
|
|
|
|
|
|
|
|
|
|
"&A" { return K_A; }
|
|
|
|
|
"&PV" { return K_PV; }
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
"%"[.$_/a-zA-Z0-9]+ {
|
|
|
|
|
yylval.text = strdup(yytext);
|
2002-03-01 06:42:50 +01:00
|
|
|
assert(yylval.text);
|
2001-03-11 01:29:38 +01:00
|
|
|
return T_INSTR; }
|
|
|
|
|
|
|
|
|
|
[0-9][0-9]* {
|
2009-02-24 22:50:18 +01:00
|
|
|
yylval.numb = strtouint64(yytext, 0, 0);
|
2001-03-11 01:29:38 +01:00
|
|
|
return T_NUMBER; }
|
|
|
|
|
|
|
|
|
|
"0x"[0-9a-fA-F]+ {
|
2009-02-24 22:50:18 +01:00
|
|
|
yylval.numb = strtouint64(yytext, 0, 0);
|
2001-03-11 01:29:38 +01:00
|
|
|
return T_NUMBER; }
|
|
|
|
|
|
2008-01-22 02:52:40 +01:00
|
|
|
/* Handle some specialized constant/literals as symbols. */
|
2001-05-10 02:26:53 +02:00
|
|
|
|
2008-01-22 02:52:40 +01:00
|
|
|
"C4<"[01xz]*">" {
|
2001-05-10 02:26:53 +02:00
|
|
|
yylval.text = strdup(yytext);
|
2002-03-01 06:42:50 +01:00
|
|
|
assert(yylval.text);
|
2001-05-10 02:26:53 +02:00
|
|
|
return T_SYMBOL; }
|
|
|
|
|
|
2008-01-22 02:52:40 +01:00
|
|
|
"C8<"[01234567xz]*">" {
|
2008-01-07 03:57:16 +01:00
|
|
|
yylval.text = strdup(yytext);
|
|
|
|
|
assert(yylval.text);
|
|
|
|
|
return T_SYMBOL; }
|
|
|
|
|
|
2008-01-22 02:52:40 +01:00
|
|
|
"Cr<m"[a-f0-9]*"g"[a-f0-9]*">" {
|
|
|
|
|
yylval.text = strdup(yytext);
|
|
|
|
|
assert(yylval.text);
|
|
|
|
|
return T_SYMBOL; }
|
|
|
|
|
|
|
|
|
|
"T<"[0-9]*","[0-9]*","[us]">" {
|
|
|
|
|
yylval.text = strdup(yytext);
|
|
|
|
|
assert(yylval.text);
|
|
|
|
|
return T_SYMBOL; }
|
|
|
|
|
|
|
|
|
|
"W<"[0-9]*","[r]">" {
|
|
|
|
|
yylval.text = strdup(yytext);
|
|
|
|
|
assert(yylval.text);
|
|
|
|
|
return T_SYMBOL; }
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2008-04-05 03:37:15 +02:00
|
|
|
/* Symbols are pretty much what is left. They are used to refer to
|
|
|
|
|
labels so the rule must match a string that a label would match. */
|
2008-06-11 05:36:31 +02:00
|
|
|
[.$_a-zA-Z\\]([.$_a-zA-Z\\0-9/]|(\\.))* {
|
2008-04-05 03:37:15 +02:00
|
|
|
yylval.text = strdup(yytext);
|
|
|
|
|
assert(yylval.text);
|
|
|
|
|
return T_SYMBOL; }
|
|
|
|
|
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/* Accept the common assembler style comments, treat them as white
|
|
|
|
|
space. Of course, also skip white space. The semi-colon is
|
|
|
|
|
special, though, in that it is also a statement terminator. */
|
|
|
|
|
";".* { return ';'; }
|
|
|
|
|
"#".* { ; }
|
|
|
|
|
|
2002-02-27 06:46:33 +01:00
|
|
|
[ \t\b\r] { ; }
|
2001-03-11 01:29:38 +01:00
|
|
|
|
|
|
|
|
\n { yyline += 1; }
|
|
|
|
|
|
|
|
|
|
. { return yytext[0]; }
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
|
|
int yywrap()
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2009-01-14 19:26:58 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
|
|
|
|
*/
|
|
|
|
|
void destroy_lexor()
|
|
|
|
|
{
|
|
|
|
|
# ifdef FLEX_SCANNER
|
|
|
|
|
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
|
|
|
|
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
|
|
|
|
yylex_destroy();
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
}
|