210 lines
5.3 KiB
LLVM
210 lines
5.3 KiB
LLVM
%{
|
|
// OpenSTA, Static Timing Analyzer
|
|
// Copyright (c) 2019, Parallax Software, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 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, see <https://www.gnu.org/licenses/>.
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include "Machine.hh"
|
|
#include "LibertyParser.hh"
|
|
#include "LibertyParse.hh"
|
|
|
|
#define YY_NO_INPUT
|
|
|
|
#if defined(YY_FLEX_MAJOR_VERSION) \
|
|
&& defined(YY_FLEX_MINOR_VERSION) \
|
|
&& YY_FLEX_MAJOR_VERSION >=2 \
|
|
&& (YY_FLEX_MINOR_VERSION > 5 \
|
|
|| (YY_FLEX_MINOR_VERSION == 5 \
|
|
&& defined(YY_FLEX_SUBMINOR_VERSION) \
|
|
&& YY_FLEX_SUBMINOR_VERSION >= 31))
|
|
#define INCLUDE_SUPPORTED
|
|
#endif
|
|
|
|
static std::string string_buf;
|
|
|
|
void
|
|
libertyParseFlushBuffer()
|
|
{
|
|
YY_FLUSH_BUFFER;
|
|
}
|
|
|
|
%}
|
|
|
|
/* %option debug */
|
|
%option prefix="LibertyLex_"
|
|
%option outfile="lex.yy.c"
|
|
%option noyywrap
|
|
%option nounput
|
|
%option never-interactive
|
|
|
|
%x comment
|
|
%x qstring
|
|
|
|
DIGIT [0-9]
|
|
ALPHA [a-zA-Z]
|
|
FLOAT [-+]?(({DIGIT}+\.?{DIGIT}*)|(\.{DIGIT}+))([Ee][-+]?{DIGIT}+)?
|
|
BLANK [ \t]
|
|
BUS_LEFT [\[<]
|
|
BUS_RIGHT [\]>]
|
|
BUS_SUB {BUS_LEFT}{DIGIT}+{BUS_RIGHT}
|
|
BUS_RANGE {BUS_LEFT}{DIGIT}+:{DIGIT}+{BUS_RIGHT}
|
|
PIN_NAME ({ALPHA}|_)({ALPHA}|{DIGIT}|_)*
|
|
BUS_NAME {PIN_NAME}({BUS_SUB}|{BUS_RANGE})
|
|
MIXED_NAME {BUS_NAME}_{PIN_NAME}
|
|
HNAME ({PIN_NAME}|{BUS_NAME}|{MIXED_NAME})([\/.]({PIN_NAME}|{BUS_NAME}|{MIXED_NAME}))+
|
|
/* ocv_table_template(2D_ocv_template) */
|
|
/* leakage_power_unit : 1pW; */
|
|
/* default_operating_conditions : slow_100_3.00 ; */
|
|
/* revision : 1.0.17; */
|
|
/* default_wire_load : xc2v250-5_avg; */
|
|
TOKEN ({ALPHA}|{DIGIT}|_)({ALPHA}|{DIGIT}|[._\-])*
|
|
/* bus_naming_style : %s[%d] ; */
|
|
BUS_STYLE "%s"{BUS_LEFT}"%d"{BUS_RIGHT}
|
|
PUNCTUATION [,\:;|(){}+*&!'=]
|
|
TOKEN_END {PUNCTUATION}|[ \t\r\n]
|
|
EOL \r?\n
|
|
%%
|
|
|
|
{PUNCTUATION} { return ((int) LibertyLex_text[0]); }
|
|
|
|
{FLOAT}{TOKEN_END} {
|
|
/* Push back the TOKEN_END character. */
|
|
yyless(LibertyLex_leng - 1);
|
|
LibertyParse_lval.number = static_cast<float>(strtod(LibertyLex_text,
|
|
NULL));
|
|
return FLOAT;
|
|
}
|
|
|
|
{ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} {
|
|
/* Push back the TOKEN_END character. */
|
|
yyless(LibertyLex_leng - 1);
|
|
LibertyParse_lval.string = sta::stringCopy(LibertyLex_text);
|
|
return KEYWORD;
|
|
}
|
|
|
|
{PIN_NAME}{TOKEN_END} |
|
|
{BUS_NAME}{TOKEN_END} |
|
|
{MIXED_NAME}{TOKEN_END} |
|
|
{HNAME}{TOKEN_END} |
|
|
{BUS_STYLE}{TOKEN_END} |
|
|
{TOKEN}{TOKEN_END} {
|
|
/* Push back the TOKEN_END character. */
|
|
yyless(LibertyLex_leng - 1);
|
|
LibertyParse_lval.string = sta::stringCopy(LibertyLex_text);
|
|
return STRING;
|
|
}
|
|
|
|
\\?{EOL} { sta::libertyIncrLine(); }
|
|
|
|
"include_file"[ \t]*"(".+")"[ \t]*";"? {
|
|
#ifdef INCLUDE_SUPPORTED
|
|
if (sta::libertyInInclude())
|
|
sta::libertyParseError("nested include_file's are not supported\n");
|
|
else {
|
|
char *filename = &yytext[strlen("include_file")];
|
|
/* Skip blanks between include_file and '('. */
|
|
while (isspace(*filename) && *filename != '\0')
|
|
filename++;
|
|
/* Skip '('. */
|
|
filename++;
|
|
/* Skip blanks between '(' and filename. */
|
|
while (isspace(*filename) && *filename != '\0')
|
|
filename++;
|
|
char *filename_end = strpbrk(filename, ")");
|
|
if (filename_end == NULL)
|
|
sta::libertyParseError("include_file missing ')'\n");
|
|
else {
|
|
/* Trim trailing blanks. */
|
|
while (isspace(filename_end[-1]) && filename_end > filename)
|
|
filename_end--;
|
|
*filename_end = '\0';
|
|
FILE *stream = sta::libertyIncludeBegin(filename);
|
|
if (stream) {
|
|
yypush_buffer_state(yy_create_buffer(stream, YY_BUF_SIZE));
|
|
BEGIN(INITIAL);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
sta::libertyParseError("include_file is not supported.\n");
|
|
#endif
|
|
}
|
|
|
|
"/*" BEGIN(comment);
|
|
|
|
/* Straight out of the flex man page. */
|
|
<comment>[^*\r\n]* /* eat anything that's not a '*' */
|
|
<comment>"*"+[^*/\r\n]* /* eat up '*'s not followed by '/'s */
|
|
<comment>{EOL} sta::libertyIncrLine();
|
|
<comment>"*"+"/" BEGIN(INITIAL);
|
|
|
|
\" {
|
|
string_buf.erase();
|
|
BEGIN(qstring);
|
|
}
|
|
|
|
<qstring>\" {
|
|
BEGIN(INITIAL);
|
|
LibertyParse_lval.string = sta::stringCopy(string_buf.c_str());
|
|
return STRING;
|
|
}
|
|
|
|
<qstring>{EOL} {
|
|
LibertyParse_error("unterminated string constant");
|
|
BEGIN(INITIAL);
|
|
LibertyParse_lval.string = sta::stringCopy(string_buf.c_str());
|
|
return STRING;
|
|
}
|
|
|
|
<qstring>\\{EOL} {
|
|
/* Line continuation. */
|
|
sta::libertyIncrLine();
|
|
}
|
|
|
|
<qstring>\\. {
|
|
/* Escaped character. */
|
|
string_buf += '\\';
|
|
string_buf += LibertyLex_text[1];
|
|
}
|
|
|
|
<qstring>[^\\\r\n\"]+ {
|
|
/* Anything but escape, return or double quote */
|
|
string_buf += LibertyLex_text;
|
|
}
|
|
|
|
<qstring><<EOF>> {
|
|
LibertyParse_error("unterminated string constant");
|
|
BEGIN(INITIAL);
|
|
yyterminate();
|
|
}
|
|
|
|
{BLANK}* {}
|
|
/* Send out of bound characters to parser. */
|
|
. { return (int) LibertyLex_text[0]; }
|
|
|
|
<<EOF>> {
|
|
#ifdef INCLUDE_SUPPORTED
|
|
if (sta::libertyInInclude()) {
|
|
sta::libertyIncludeEnd();
|
|
yypop_buffer_state();
|
|
}
|
|
else
|
|
#endif
|
|
yyterminate();
|
|
}
|
|
|
|
%%
|