mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-05 21:53:24 +00:00
Merge pull request #5033 from jix/liberty-fixes
liberty: More robust parsing
This commit is contained in:
commit
7f7ad87b7b
5 changed files with 67 additions and 10 deletions
|
@ -75,7 +75,7 @@ bool LibertyInputStream::extend_buffer_once()
|
||||||
buffer.resize(buf_end + chunk_size);
|
buffer.resize(buf_end + chunk_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t read_size = f.rdbuf()->sgetn(buffer.data() + buf_end, chunk_size);
|
size_t read_size = f.rdbuf()->sgetn((char *)buffer.data() + buf_end, chunk_size);
|
||||||
buf_end += read_size;
|
buf_end += read_size;
|
||||||
if (read_size < chunk_size)
|
if (read_size < chunk_size)
|
||||||
eof = true;
|
eof = true;
|
||||||
|
@ -436,6 +436,9 @@ void LibertyParser::report_unexpected_token(int tok)
|
||||||
eReport += "'.";
|
eReport += "'.";
|
||||||
error(eReport);
|
error(eReport);
|
||||||
break;
|
break;
|
||||||
|
case EOF:
|
||||||
|
error("Unexpected end of file");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
eReport = "Unexpected token: ";
|
eReport = "Unexpected token: ";
|
||||||
eReport += static_cast<char>(tok);
|
eReport += static_cast<char>(tok);
|
||||||
|
@ -484,7 +487,7 @@ void LibertyParser::parse_vector_range(int tok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyAst *LibertyParser::parse()
|
LibertyAst *LibertyParser::parse(bool top_level)
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
||||||
|
@ -498,7 +501,13 @@ LibertyAst *LibertyParser::parse()
|
||||||
while ((tok == 'n') || (tok == ';'))
|
while ((tok == 'n') || (tok == ';'))
|
||||||
tok = lexer(str);
|
tok = lexer(str);
|
||||||
|
|
||||||
if (tok == '}' || tok < 0)
|
if (tok == EOF) {
|
||||||
|
if (top_level)
|
||||||
|
return NULL;
|
||||||
|
report_unexpected_token(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tok == '}')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (tok != 'v') {
|
if (tok != 'v') {
|
||||||
|
@ -571,12 +580,18 @@ LibertyAst *LibertyParser::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
|
bool terminated = false;
|
||||||
while (1) {
|
while (1) {
|
||||||
LibertyAst *child = parse();
|
LibertyAst *child = parse(false);
|
||||||
if (child == NULL)
|
if (child == NULL) {
|
||||||
|
terminated = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
ast->children.push_back(child);
|
ast->children.push_back(child);
|
||||||
}
|
}
|
||||||
|
if (!terminated) {
|
||||||
|
report_unexpected_token(EOF);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace Yosys
|
||||||
|
|
||||||
class LibertyInputStream {
|
class LibertyInputStream {
|
||||||
std::istream &f;
|
std::istream &f;
|
||||||
std::vector<char> buffer;
|
std::vector<unsigned char> buffer;
|
||||||
size_t buf_pos = 0;
|
size_t buf_pos = 0;
|
||||||
size_t buf_end = 0;
|
size_t buf_end = 0;
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
|
@ -107,7 +107,7 @@ namespace Yosys
|
||||||
LibertyInputStream(std::istream &f) : f(f) {}
|
LibertyInputStream(std::istream &f) : f(f) {}
|
||||||
|
|
||||||
size_t buffered_size() { return buf_end - buf_pos; }
|
size_t buffered_size() { return buf_end - buf_pos; }
|
||||||
const char *buffered_data() { return buffer.data() + buf_pos; }
|
const unsigned char *buffered_data() { return buffer.data() + buf_pos; }
|
||||||
|
|
||||||
int get() {
|
int get() {
|
||||||
if (buf_pos == buf_end)
|
if (buf_pos == buf_end)
|
||||||
|
@ -165,7 +165,7 @@ namespace Yosys
|
||||||
|
|
||||||
void report_unexpected_token(int tok);
|
void report_unexpected_token(int tok);
|
||||||
void parse_vector_range(int tok);
|
void parse_vector_range(int tok);
|
||||||
LibertyAst *parse();
|
LibertyAst *parse(bool top_level);
|
||||||
void error() const;
|
void error() const;
|
||||||
void error(const std::string &str) const;
|
void error(const std::string &str) const;
|
||||||
|
|
||||||
|
@ -174,18 +174,29 @@ namespace Yosys
|
||||||
const LibertyAst *ast = nullptr;
|
const LibertyAst *ast = nullptr;
|
||||||
|
|
||||||
LibertyParser(std::istream &f) : f(f), line(1) {
|
LibertyParser(std::istream &f) : f(f), line(1) {
|
||||||
shared_ast.reset(parse());
|
shared_ast.reset(parse(true));
|
||||||
ast = shared_ast.get();
|
ast = shared_ast.get();
|
||||||
|
if (!ast) {
|
||||||
|
#ifdef FILTERLIB
|
||||||
|
fprintf(stderr, "No entries found in liberty file.\n");
|
||||||
|
exit(1);
|
||||||
|
#else
|
||||||
|
log_error("No entries found in liberty file.\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FILTERLIB
|
#ifndef FILTERLIB
|
||||||
LibertyParser(std::istream &f, const std::string &fname) : f(f), line(1) {
|
LibertyParser(std::istream &f, const std::string &fname) : f(f), line(1) {
|
||||||
shared_ast = LibertyAstCache::instance.cached_ast(fname);
|
shared_ast = LibertyAstCache::instance.cached_ast(fname);
|
||||||
if (!shared_ast) {
|
if (!shared_ast) {
|
||||||
shared_ast.reset(parse());
|
shared_ast.reset(parse(true));
|
||||||
LibertyAstCache::instance.parsed_ast(fname, shared_ast);
|
LibertyAstCache::instance.parsed_ast(fname, shared_ast);
|
||||||
}
|
}
|
||||||
ast = shared_ast.get();
|
ast = shared_ast.get();
|
||||||
|
if (!ast) {
|
||||||
|
log_error("No entries found in liberty file `%s'.\n", fname.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
14
tests/liberty/non-ascii.lib
Normal file
14
tests/liberty/non-ascii.lib
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// The parser used to choke on the copyright symbol even in comments
|
||||||
|
// © ® ø Φ
|
||||||
|
library(dummy) {
|
||||||
|
cell(buffer) {
|
||||||
|
area : 1 ;
|
||||||
|
pin(A) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(Y) {
|
||||||
|
direction : output ;
|
||||||
|
function : "A" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
tests/liberty/non-ascii.lib.filtered.ok
Normal file
12
tests/liberty/non-ascii.lib.filtered.ok
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
library(dummy) {
|
||||||
|
cell(buffer) {
|
||||||
|
area : 1 ;
|
||||||
|
pin(A) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(Y) {
|
||||||
|
direction : output ;
|
||||||
|
function : "A" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
tests/liberty/non-ascii.lib.verilogsim.ok
Normal file
5
tests/liberty/non-ascii.lib.verilogsim.ok
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module buffer (A, Y);
|
||||||
|
input A;
|
||||||
|
output Y;
|
||||||
|
assign Y = A; // "A"
|
||||||
|
endmodule
|
Loading…
Add table
Add a link
Reference in a new issue