3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-11 03:33:36 +00:00
This commit is contained in:
Jannis Harder 2025-04-03 14:35:07 +02:00 committed by GitHub
commit 622319bb48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 253 additions and 17 deletions

View file

@ -539,7 +539,7 @@ struct LibertyFrontend : public Frontend {
log_header(design, "Executing Liberty frontend: %s\n", filename.c_str());
LibertyParser parser(*f);
LibertyParser parser(*f, filename);
int cell_count = 0;
std::map<std::string, std::tuple<int, int, bool>> global_type_map;

View file

@ -352,7 +352,7 @@ void read_liberty_cellarea(dict<IdString, cell_area_t> &cell_area, string libert
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);
LibertyParser libparser(*f, liberty_file);
delete f;
for (auto cell : libparser.ast->children)

View file

@ -6,6 +6,7 @@ OBJS += passes/techmap/dfflibmap.o
OBJS += passes/techmap/maccmap.o
OBJS += passes/techmap/booth.o
OBJS += passes/techmap/libparse.o
OBJS += passes/techmap/libcache.o
ifeq ($(ENABLE_ABC),1)
OBJS += passes/techmap/abc.o

View file

@ -312,7 +312,7 @@ struct ClockgatePass : public Pass {
std::istream* f = uncompressed(path);
if (f->fail())
log_cmd_error("Can't open liberty file `%s': %s\n", path.c_str(), strerror(errno));
LibertyParser p(*f);
LibertyParser p(*f, path);
merged.merge(p);
delete f;
}

View file

@ -634,7 +634,7 @@ struct DfflibmapPass : public Pass {
std::istream* f = uncompressed(path);
if (f->fail())
log_cmd_error("Can't open liberty file `%s': %s\n", path.c_str(), strerror(errno));
LibertyParser p(*f);
LibertyParser p(*f, path);
merged.merge(p);
delete f;
}

130
passes/techmap/libcache.cc Normal file
View file

@ -0,0 +1,130 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2025 Jannis Harder <jix@yosyshq.com> <me@jix.one>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "passes/techmap/libparse.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct LibcachePass : public Pass {
LibcachePass() : Pass("libcache", "control caching of technology library data parsed from liberty files") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" libcache {-enable|-disable|-purge} { -all | [path]... }\n");
log("\n");
log("Controls the default and per path caching of liberty file data.\n");
log("\n");
log(" -enable Enable caching.\n");
log(" -disable Disable caching.\n");
log(" -purge Reset cache setting and forget cached data.\n");
log("\n");
log("This mode takes a list of paths as argument. If no paths are provided, this\n");
log("command does nothing. The -all option can be used to change the default cache\n");
log("setting for -enable/-disable or to reset and forget about all paths.\n");
log("\n");
log("By default caching is disabled.\n");
log("\n");
log(" libcache -list\n");
log("\n");
log("Displays the current cache settings and cached paths.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *) override
{
bool enable = false;
bool disable = false;
bool purge = false;
bool all = false;
bool list = false;
std::vector<std::string> paths;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-enable") {
enable = true;
continue;
}
if (args[argidx] == "-disable") {
enable = true;
continue;
}
if (args[argidx] == "-purge") {
purge = true;
continue;
}
if (args[argidx] == "-all") {
all = true;
continue;
}
if (args[argidx] == "-list") {
list = true;
continue;
}
std::string fname = args[argidx];
rewrite_filename(fname);
paths.push_back(fname);
break;
}
int modes = enable + disable + purge + list;
if (modes == 0)
log_cmd_error("At least one of -enable, -disable, -purge or -list is required.\n");
if (modes > 1)
log_cmd_error("Only one of -enable, -disable, -purge or -list may be present.\n");
if (all && !paths.empty())
log_cmd_error("The -all option cannot be combined with a list of paths.\n");
if (list && (all || !paths.empty()))
log_cmd_error("The -list mode takes no further options.\n");
if (!list && !all && paths.empty())
log("No paths specified, use -all to %s\n", purge ? "purge all paths" : "change the default setting");
if (list) {
log("Caching is %s by default.\n", LibertyAstCache::instance.cache_by_default ? "enabled" : "disabled");
for (auto const &entry : LibertyAstCache::instance.cache_path)
log("Caching is %s for `%s'.\n", entry.second ? "enabled" : "disabled", entry.first.c_str());
for (auto const &entry : LibertyAstCache::instance.cached)
log("Data for `%s' is currently cached.\n", entry.first.c_str());
} else if (enable || disable) {
if (all) {
LibertyAstCache::instance.cache_by_default = enable;
} else {
for (auto const &path : paths) {
LibertyAstCache::instance.cache_path[path] = enable;
}
}
} else if (purge) {
if (all) {
LibertyAstCache::instance.cached.clear();
LibertyAstCache::instance.cache_path.clear();
} else {
for (auto const &path : paths) {
LibertyAstCache::instance.cached.erase(path);
LibertyAstCache::instance.cache_path.erase(path);
}
}
} else {
log_assert(false);
}
}
} LibcachePass;
PRIVATE_NAMESPACE_END

View file

@ -32,6 +32,31 @@
using namespace Yosys;
#ifndef FILTERLIB
LibertyAstCache LibertyAstCache::instance;
std::shared_ptr<const LibertyAst> LibertyAstCache::cached_ast(const std::string &fname)
{
auto it = cached.find(fname);
if (it == cached.end())
return nullptr;
log("Using cached data for liberty file `%s'\n", fname.c_str());
return it->second;
}
void LibertyAstCache::parsed_ast(const std::string &fname, const std::shared_ptr<const LibertyAst> &ast)
{
auto it = cache_path.find(fname);
bool should_cache = it == cache_path.end() ? cache_by_default : it->second;
if (!should_cache)
return;
log("Caching data for liberty file `%s'\n", fname.c_str());
cached.emplace(fname, ast);
}
#endif
bool LibertyInputStream::extend_buffer_once()
{
if (eof)

View file

@ -132,6 +132,22 @@ namespace Yosys
}
};
#ifndef FILTERLIB
class LibertyAstCache {
LibertyAstCache() {};
~LibertyAstCache() {};
public:
dict<std::string, std::shared_ptr<const LibertyAst>> cached;
bool cache_by_default = false;
dict<std::string, bool> cache_path;
std::shared_ptr<const LibertyAst> cached_ast(const std::string &fname);
void parsed_ast(const std::string &fname, const std::shared_ptr<const LibertyAst> &ast);
static LibertyAstCache instance;
};
#endif
class LibertyMergedCells;
class LibertyParser
{
@ -152,15 +168,29 @@ namespace Yosys
void error(const std::string &str) const;
public:
const LibertyAst *ast;
std::shared_ptr<const LibertyAst> shared_ast;
const LibertyAst *ast = nullptr;
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
~LibertyParser() { if (ast) delete ast; }
LibertyParser(std::istream &f) : f(f), line(1) {
shared_ast.reset(parse());
ast = shared_ast.get();
}
#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());
LibertyAstCache::instance.parsed_ast(fname, shared_ast);
}
ast = shared_ast.get();
}
#endif
};
class LibertyMergedCells
{
std::vector<const LibertyAst *> asts;
std::vector<std::shared_ptr<const LibertyAst>> asts;
public:
std::vector<const LibertyAst *> cells;
@ -168,10 +198,7 @@ namespace Yosys
{
if (parser.ast) {
const LibertyAst *ast = parser.ast;
asts.push_back(ast);
// The parser no longer owns its top level ast, but we do.
// sketchy zone
parser.ast = nullptr;
asts.push_back(parser.shared_ast);
if (ast->id != "library")
parser.error("Top level entity isn't \"library\".\n");
for (const LibertyAst *cell : ast->children)
@ -179,11 +206,6 @@ namespace Yosys
cells.push_back(cell);
}
}
~LibertyMergedCells()
{
for (auto ast : asts)
delete ast;
}
};
}

58
tests/liberty/libcache.ys Normal file
View file

@ -0,0 +1,58 @@
libcache -enable busdef.lib
logger -expect log "Caching is disabled by default." 1
logger -expect log "Caching is enabled for `busdef.lib'." 1
libcache -list
logger -check-expected
logger -expect log "Caching data" 1
log Caching data
read_liberty normal.lib; design -reset
logger -check-expected
logger -expect log "Caching data" 1
read_liberty -lib busdef.lib; design -reset
logger -check-expected
logger -expect log "Using caching data" 1
log Using caching data
read_liberty normal.lib; design -reset
logger -check-expected
logger -expect log "Using cached data" 1
read_liberty -lib busdef.lib; design -reset
logger -check-expected
libcache -purge busdef.lib
logger -expect log "Caching is disabled by default." 1
logger -expect log "Caching is enabled for `busdef.lib'." 1
log Caching is enabled for `busdef.lib'.
libcache -list
logger -check-expected
libcache -enable -all
logger -expect log "Caching is enabled by default." 1
libcache -list
logger -check-expected
logger -expect log "Caching data" 1
read_liberty normal.lib; design -reset
logger -check-expected
logger -expect log "Caching data" 1
read_liberty -lib busdef.lib; design -reset
logger -check-expected
logger -expect log "Using cached data" 1
read_liberty -lib busdef.lib; design -reset
logger -check-expected
logger -expect log "Using cached data" 1
read_liberty normal.lib; design -reset
logger -check-expected
logger -expect log "Using cached data" 1
dfflibmap -liberty normal.lib
logger -check-expected