aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap/libparse.cc
diff options
context:
space:
mode:
authorNiels Moseley <n.a.moseley@moseleyinstruments.com>2019-03-24 22:54:18 +0100
committerNiels Moseley <n.a.moseley@moseleyinstruments.com>2019-03-24 22:54:18 +0100
commit3b3b77291a21ed23a2763c79335501beebb10746 (patch)
tree0e048b43dc5a44b7a04c2d34f73de019e2375424 /passes/techmap/libparse.cc
parentccfa2fe01cffcc4d23bc989e558bd33addfea58e (diff)
downloadyosys-3b3b77291a21ed23a2763c79335501beebb10746.tar.gz
yosys-3b3b77291a21ed23a2763c79335501beebb10746.tar.bz2
yosys-3b3b77291a21ed23a2763c79335501beebb10746.zip
Updated the liberty parser to accept [A:B] ranges (AST has not been updated). Liberty parser now also accepts key : value pair lines that do not end in ';'.
Diffstat (limited to 'passes/techmap/libparse.cc')
-rw-r--r--passes/techmap/libparse.cc87
1 files changed, 81 insertions, 6 deletions
diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc
index 3927a657b..878ca3160 100644
--- a/passes/techmap/libparse.cc
+++ b/passes/techmap/libparse.cc
@@ -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
@@ -210,7 +221,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 +241,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 +313,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,6 +329,15 @@ 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) \