3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-20 07:36:39 +00:00

Merge pull request #5033 from jix/liberty-fixes

liberty: More robust parsing
This commit is contained in:
Jannis Harder 2025-04-17 09:24:42 +02:00 committed by GitHub
commit 7f7ad87b7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 67 additions and 10 deletions

View file

@ -75,7 +75,7 @@ bool LibertyInputStream::extend_buffer_once()
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;
if (read_size < chunk_size)
eof = true;
@ -436,6 +436,9 @@ void LibertyParser::report_unexpected_token(int tok)
eReport += "'.";
error(eReport);
break;
case EOF:
error("Unexpected end of file");
break;
default:
eReport = "Unexpected token: ";
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;
@ -498,7 +501,13 @@ LibertyAst *LibertyParser::parse()
while ((tok == 'n') || (tok == ';'))
tok = lexer(str);
if (tok == '}' || tok < 0)
if (tok == EOF) {
if (top_level)
return NULL;
report_unexpected_token(tok);
}
if (tok == '}')
return NULL;
if (tok != 'v') {
@ -571,12 +580,18 @@ LibertyAst *LibertyParser::parse()
}
if (tok == '{') {
bool terminated = false;
while (1) {
LibertyAst *child = parse();
if (child == NULL)
LibertyAst *child = parse(false);
if (child == NULL) {
terminated = true;
break;
}
ast->children.push_back(child);
}
if (!terminated) {
report_unexpected_token(EOF);
}
break;
}

View file

@ -92,7 +92,7 @@ namespace Yosys
class LibertyInputStream {
std::istream &f;
std::vector<char> buffer;
std::vector<unsigned char> buffer;
size_t buf_pos = 0;
size_t buf_end = 0;
bool eof = false;
@ -107,7 +107,7 @@ namespace Yosys
LibertyInputStream(std::istream &f) : f(f) {}
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() {
if (buf_pos == buf_end)
@ -165,7 +165,7 @@ namespace Yosys
void report_unexpected_token(int tok);
void parse_vector_range(int tok);
LibertyAst *parse();
LibertyAst *parse(bool top_level);
void error() const;
void error(const std::string &str) const;
@ -174,18 +174,29 @@ namespace Yosys
const LibertyAst *ast = nullptr;
LibertyParser(std::istream &f) : f(f), line(1) {
shared_ast.reset(parse());
shared_ast.reset(parse(true));
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
LibertyParser(std::istream &f, const std::string &fname) : f(f), line(1) {
shared_ast = LibertyAstCache::instance.cached_ast(fname);
if (!shared_ast) {
shared_ast.reset(parse());
shared_ast.reset(parse(true));
LibertyAstCache::instance.parsed_ast(fname, shared_ast);
}
ast = shared_ast.get();
if (!ast) {
log_error("No entries found in liberty file `%s'.\n", fname.c_str());
}
}
#endif
};

View 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" ;
}
}
}

View file

@ -0,0 +1,12 @@
library(dummy) {
cell(buffer) {
area : 1 ;
pin(A) {
direction : input ;
}
pin(Y) {
direction : output ;
function : "A" ;
}
}
}

View file

@ -0,0 +1,5 @@
module buffer (A, Y);
input A;
output Y;
assign Y = A; // "A"
endmodule