mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-12 12:08:19 +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
|
@ -128,6 +128,12 @@
|
||||||
# error "C++17 or later compatible compiler is required"
|
# error "C++17 or later compatible compiler is required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__has_cpp_attribute) && __has_cpp_attribute(gnu::cold)
|
||||||
|
# define YS_COLD [[gnu::cold]]
|
||||||
|
#else
|
||||||
|
# define YS_COLD
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "kernel/io.h"
|
#include "kernel/io.h"
|
||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
|
@ -32,6 +32,51 @@
|
||||||
|
|
||||||
using namespace Yosys;
|
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()
|
LibertyAst::~LibertyAst()
|
||||||
{
|
{
|
||||||
for (auto child : children)
|
for (auto child : children)
|
||||||
|
|
|
@ -90,12 +90,43 @@ namespace Yosys
|
||||||
bool eval(dict<std::string, bool>& values);
|
bool eval(dict<std::string, bool>& values);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LibertyInputStream {
|
||||||
|
std::istream &f;
|
||||||
|
std::vector<char> buffer;
|
||||||
|
size_t buf_pos = 0;
|
||||||
|
size_t buf_end = 0;
|
||||||
|
bool eof = false;
|
||||||
|
|
||||||
|
bool extend_buffer_once();
|
||||||
|
bool extend_buffer_at_least(size_t size = 1);
|
||||||
|
|
||||||
|
YS_COLD int get_cold();
|
||||||
|
|
||||||
|
public:
|
||||||
|
LibertyInputStream(std::istream &f) : f(f) {}
|
||||||
|
|
||||||
|
size_t buffered_size() { return buf_end - buf_pos; }
|
||||||
|
const char *buffered_data() { return buffer.data() + buf_pos; }
|
||||||
|
|
||||||
|
int get() {
|
||||||
|
if (buf_pos == buf_end)
|
||||||
|
return get_cold();
|
||||||
|
int c = buffer[buf_pos];
|
||||||
|
buf_pos += 1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unget() {
|
||||||
|
buf_pos -= 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LibertyMergedCells;
|
class LibertyMergedCells;
|
||||||
class LibertyParser
|
class LibertyParser
|
||||||
{
|
{
|
||||||
friend class LibertyMergedCells;
|
friend class LibertyMergedCells;
|
||||||
private:
|
private:
|
||||||
std::istream &f;
|
LibertyInputStream f;
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
/* lexer return values:
|
/* lexer return values:
|
||||||
|
|
Loading…
Reference in a new issue