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:
parent
c08f72b806
commit
119e998f12
3 changed files with 83 additions and 1 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue