mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-23 14:23:41 +00:00
Merge remote-tracking branch 'origin/master' into xc7srl
This commit is contained in:
commit
6b90d3cf6c
15 changed files with 943 additions and 37 deletions
|
@ -24,6 +24,7 @@
|
|||
#include <istream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef FILTERLIB
|
||||
#include "kernel/log.h"
|
||||
|
@ -86,15 +87,17 @@ int LibertyParser::lexer(std::string &str)
|
|||
{
|
||||
int c;
|
||||
|
||||
// eat whitespace
|
||||
do {
|
||||
c = f.get();
|
||||
} while (c == ' ' || c == '\t' || c == '\r');
|
||||
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']') {
|
||||
// search for identifiers, numbers, plus or minus.
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') {
|
||||
str = c;
|
||||
while (1) {
|
||||
c = f.get();
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']')
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.')
|
||||
str += c;
|
||||
else
|
||||
break;
|
||||
|
@ -111,6 +114,8 @@ int LibertyParser::lexer(std::string &str)
|
|||
}
|
||||
}
|
||||
|
||||
// if it wasn't an identifer, number of array range,
|
||||
// maybe it's a string?
|
||||
if (c == '"') {
|
||||
str = "";
|
||||
while (1) {
|
||||
|
@ -125,9 +130,10 @@ int LibertyParser::lexer(std::string &str)
|
|||
return 'v';
|
||||
}
|
||||
|
||||
// if it wasn't a string, perhaps it's a comment or a forward slash?
|
||||
if (c == '/') {
|
||||
c = f.get();
|
||||
if (c == '*') {
|
||||
if (c == '*') { // start of '/*' block comment
|
||||
int last_c = 0;
|
||||
while (c > 0 && (last_c != '*' || c != '/')) {
|
||||
last_c = c;
|
||||
|
@ -136,7 +142,7 @@ int LibertyParser::lexer(std::string &str)
|
|||
line++;
|
||||
}
|
||||
return lexer(str);
|
||||
} else if (c == '/') {
|
||||
} else if (c == '/') { // start of '//' line comment
|
||||
while (c > 0 && c != '\n')
|
||||
c = f.get();
|
||||
line++;
|
||||
|
@ -144,9 +150,10 @@ int LibertyParser::lexer(std::string &str)
|
|||
}
|
||||
f.unget();
|
||||
// fprintf(stderr, "LEX: char >>/<<\n");
|
||||
return '/';
|
||||
return '/'; // a single '/' charater.
|
||||
}
|
||||
|
||||
// check for a backslash
|
||||
if (c == '\\') {
|
||||
c = f.get();
|
||||
if (c == '\r')
|
||||
|
@ -157,11 +164,15 @@ int LibertyParser::lexer(std::string &str)
|
|||
return '\\';
|
||||
}
|
||||
|
||||
// check for a new line
|
||||
if (c == '\n') {
|
||||
line++;
|
||||
return 'n';
|
||||
}
|
||||
|
||||
// anything else, such as ';' will get passed
|
||||
// through as literal items.
|
||||
|
||||
// if (c >= 32 && c < 255)
|
||||
// fprintf(stderr, "LEX: char >>%c<<\n", c);
|
||||
// else
|
||||
|
@ -191,12 +202,11 @@ LibertyAst *LibertyParser::parse()
|
|||
{
|
||||
tok = lexer(str);
|
||||
|
||||
if (tok == ';')
|
||||
// allow both ';' and new lines to
|
||||
// terminate a statement.
|
||||
if ((tok == ';') || (tok == 'n'))
|
||||
break;
|
||||
|
||||
if (tok == 'n')
|
||||
continue;
|
||||
|
||||
if (tok == ':' && ast->value.empty()) {
|
||||
tok = lexer(ast->value);
|
||||
if (tok != 'v')
|
||||
|
@ -210,7 +220,12 @@ LibertyAst *LibertyParser::parse()
|
|||
ast->value += str;
|
||||
tok = lexer(str);
|
||||
}
|
||||
if (tok == ';')
|
||||
|
||||
// In a liberty file, all key : value pairs should end in ';'
|
||||
// However, there are some liberty files in the wild that
|
||||
// just have a newline. We'll be kind and accept a newline
|
||||
// instead of the ';' too..
|
||||
if ((tok == ';') || (tok == 'n'))
|
||||
break;
|
||||
else
|
||||
error();
|
||||
|
@ -225,6 +240,48 @@ LibertyAst *LibertyParser::parse()
|
|||
continue;
|
||||
if (tok == ')')
|
||||
break;
|
||||
|
||||
// FIXME: the AST needs to be extended to store
|
||||
// these vector ranges.
|
||||
if (tok == '[')
|
||||
{
|
||||
// parse vector range [A] or [A:B]
|
||||
std::string arg;
|
||||
tok = lexer(arg);
|
||||
if (tok != 'v')
|
||||
{
|
||||
// expected a vector array index
|
||||
error("Expected a number.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// fixme: check for number A
|
||||
}
|
||||
tok = lexer(arg);
|
||||
// optionally check for : in case of [A:B]
|
||||
// if it isn't we just expect ']'
|
||||
// as we have [A]
|
||||
if (tok == ':')
|
||||
{
|
||||
tok = lexer(arg);
|
||||
if (tok != 'v')
|
||||
{
|
||||
// expected a vector array index
|
||||
error("Expected a number.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// fixme: check for number B
|
||||
tok = lexer(arg);
|
||||
}
|
||||
}
|
||||
// expect a closing bracket of array range
|
||||
if (tok != ']')
|
||||
{
|
||||
error("Expected ']' on array range.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (tok != 'v')
|
||||
error();
|
||||
ast->args.push_back(arg);
|
||||
|
@ -255,6 +312,14 @@ void LibertyParser::error()
|
|||
log_error("Syntax error in liberty file on line %d.\n", line);
|
||||
}
|
||||
|
||||
void LibertyParser::error(const std::string &str)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Syntax error in liberty file on line " << line << ".\n";
|
||||
ss << " " << str << "\n";
|
||||
log_error("%s", ss.str().c_str());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void LibertyParser::error()
|
||||
|
@ -263,25 +328,34 @@ void LibertyParser::error()
|
|||
exit(1);
|
||||
}
|
||||
|
||||
void LibertyParser::error(const std::string &str)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Syntax error in liberty file on line " << line << ".\n";
|
||||
ss << " " << str << "\n";
|
||||
printf("%s", ss.str().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/
|
||||
|
||||
#define CHECK_NV(result, check) \
|
||||
do { \
|
||||
auto _R = (result); \
|
||||
if (!(_R check)) { \
|
||||
fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \
|
||||
#result, (long int)_R, #check, __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
auto _R = (result); \
|
||||
if (!(_R check)) { \
|
||||
fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \
|
||||
#result, (long int)_R, #check, __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CHECK_COND(result) \
|
||||
do { \
|
||||
if (!(result)) { \
|
||||
fprintf(stderr, "Error from '%s' in %s:%d.\n", \
|
||||
#result, __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
if (!(result)) { \
|
||||
fprintf(stderr, "Error from '%s' in %s:%d.\n", \
|
||||
#result, __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**** END: http://svn.clifford.at/tools/trunk/examples/check.h ****/
|
||||
|
|
|
@ -46,9 +46,17 @@ namespace Yosys
|
|||
LibertyAst *ast;
|
||||
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
|
||||
~LibertyParser() { if (ast) delete ast; }
|
||||
|
||||
/* lexer return values:
|
||||
'v': identifier, string, array range [...] -> str holds the token string
|
||||
'n': newline
|
||||
anything else is a single character.
|
||||
*/
|
||||
int lexer(std::string &str);
|
||||
LibertyAst *parse();
|
||||
|
||||
LibertyAst *parse();
|
||||
void error();
|
||||
void error(const std::string &str);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue