From 261bc561fa30706b51cad2e4b6944cb94d0f6035 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Sun, 5 May 2024 04:21:47 -0700 Subject: [PATCH] Allow for gzip magic in stat --- passes/cmds/stat.cc | 107 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 6 deletions(-) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index c2bb72f3b..c8daec062 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -25,6 +25,65 @@ #include "kernel/cost.h" #include "libs/json11/json11.hpp" +#ifdef YOSYS_ENABLE_ZLIB +#include + +PRIVATE_NAMESPACE_BEGIN +#define GZ_BUFFER_SIZE 8192 +void decompress_gzip(const std::string &filename, std::stringstream &out) +{ + char buffer[GZ_BUFFER_SIZE]; + int bytes_read; + gzFile gzf = gzopen(filename.c_str(), "rb"); + while(!gzeof(gzf)) { + bytes_read = gzread(gzf, reinterpret_cast(buffer), GZ_BUFFER_SIZE); + out.write(buffer, bytes_read); + } + gzclose(gzf); +} + +/* +An output stream that uses a stringbuf to buffer data internally, +using zlib to write gzip-compressed data every time the stream is flushed. +*/ +class gzip_ostream : public std::ostream { +public: + gzip_ostream() : std::ostream(nullptr) + { + rdbuf(&outbuf); + } + bool open(const std::string &filename) + { + return outbuf.open(filename); + } +private: + class gzip_streambuf : public std::stringbuf { + public: + gzip_streambuf() { }; + bool open(const std::string &filename) + { + gzf = gzopen(filename.c_str(), "wb"); + return gzf != nullptr; + } + virtual int sync() override + { + gzwrite(gzf, reinterpret_cast(str().c_str()), unsigned(str().size())); + str(""); + return 0; + } + virtual ~gzip_streambuf() + { + sync(); + gzclose(gzf); + } + private: + gzFile gzf = nullptr; + } outbuf; +}; +PRIVATE_NAMESPACE_END + +#endif + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -350,13 +409,49 @@ statdata_t hierarchy_worker(std::map &mod_stat, RTL void read_liberty_cellarea(dict &cell_area, string liberty_file) { - std::ifstream f; - f.open(liberty_file.c_str()); + std::istream *f; + std::ifstream *ff = new std::ifstream; + ff->open(liberty_file.c_str(), (liberty_file.substr(liberty_file.size() - 3) == ".gz") ? std::ifstream::binary : std::ifstream::in); yosys_input_files.insert(liberty_file); - if (f.fail()) - log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file.c_str(), strerror(errno)); - LibertyParser libparser(f); - f.close(); + if (ff->fail()) { + delete ff; + ff = nullptr; + } + f = ff; + if (f != NULL) { + // Check for gzip magic + unsigned char magic[3]; + int n = 0; + while (n < 3) + { + int c = ff->get(); + if (c != EOF) { + magic[n] = (unsigned char) c; + } + n++; + } + if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) { +#ifdef YOSYS_ENABLE_ZLIB + // log("Found gzip magic in file `%s', decompressing using zlib.\n", liberty_file.c_str()); + if (magic[2] != 8) + log_cmd_error("gzip file `%s' uses unsupported compression type %02x\n", + liberty_file.c_str(), unsigned(magic[2])); + delete ff; + std::stringstream *df = new std::stringstream(); + decompress_gzip(liberty_file, *df); + f = df; +#else + log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", liberty_file.c_str()); +#endif + } else { + ff->clear(); + ff->seekg(0, std::ios::beg); + } + } + if (f == NULL) + log_cmd_error("Can't open input file `%s' for reading: %s\n", liberty_file.c_str(), strerror(errno)); + + LibertyParser libparser(*f); for (auto cell : libparser.ast->children) {