3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-12 09:03:27 +00:00

read_liberty: Faster input handling for the liberty lexer

The lexer for liberty files was using istream's `get` and `unget` which
are notorious for bad performance and that showed up during profiling.

This replaces the direct `istream` use with a custom LibertyInputStream
that does its own buffering to provide `get` and `unget` that behave the
same way but are implemented with a fast path that is easy to inline and
optimize.
This commit is contained in:
Jannis Harder 2025-04-01 13:48:44 +02:00
parent c08f72b806
commit 119e998f12
3 changed files with 83 additions and 1 deletions

View file

@ -32,6 +32,51 @@
using namespace Yosys;
bool LibertyInputStream::extend_buffer_once()
{
if (eof)
return false;
// To support unget we leave the last already read character in the buffer
if (buf_pos > 1) {
size_t move_pos = buf_pos - 1;
memmove(buffer.data(), buffer.data() + move_pos, buf_end - move_pos);
buf_pos -= move_pos;
buf_end -= move_pos;
}
const size_t chunk_size = 4096;
if (buffer.size() < buf_end + chunk_size) {
buffer.resize(buf_end + chunk_size);
}
size_t read_size = f.rdbuf()->sgetn(buffer.data() + buf_end, chunk_size);
buf_end += read_size;
if (read_size < chunk_size)
eof = true;
return read_size != 0;
}
bool LibertyInputStream::extend_buffer_at_least(size_t size) {
while (buffered_size() < size) {
if (!extend_buffer_once())
return false;
}
return true;
}
int LibertyInputStream::get_cold()
{
if (buf_pos == buf_end) {
if (!extend_buffer_at_least())
return EOF;
}
int c = buffer[buf_pos];
buf_pos += 1;
return c;
}
LibertyAst::~LibertyAst()
{
for (auto child : children)