mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-22 07:05:51 +00:00
Merge branch 'YosysHQ:main' into main
This commit is contained in:
commit
06c614a010
45 changed files with 523 additions and 724 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -306,10 +306,9 @@ struct Abc9Pass : public ScriptPass
|
|||
}
|
||||
run("design -stash $abc9");
|
||||
run("design -load $abc9_map");
|
||||
if (help_mode) run("select =*");
|
||||
else active_design->push_complete_selection();
|
||||
run("proc");
|
||||
run("wbflip");
|
||||
run("techmap -autoproc -wb -map %$abc9 -map +/techmap.v A:abc9_flop");
|
||||
run("techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop");
|
||||
run("opt -nodffe -nosdff");
|
||||
if (dff_mode || help_mode) {
|
||||
if (!help_mode)
|
||||
|
|
@ -370,8 +369,6 @@ struct Abc9Pass : public ScriptPass
|
|||
if (saved_designs.count("$abc9_holes") || help_mode) {
|
||||
run("design -stash $abc9");
|
||||
run("design -load $abc9_holes");
|
||||
if (help_mode) run("select =*");
|
||||
else active_design->push_complete_selection();
|
||||
run("techmap -wb -map %$abc9 -map +/techmap.v");
|
||||
run("opt -purge");
|
||||
run("aigmap");
|
||||
|
|
@ -394,7 +391,7 @@ struct Abc9Pass : public ScriptPass
|
|||
}
|
||||
else {
|
||||
auto selected_modules = active_design->selected_modules();
|
||||
active_design->push_empty_selection();
|
||||
active_design->selection_stack.emplace_back(false);
|
||||
|
||||
for (auto mod : selected_modules) {
|
||||
if (mod->processes.size() > 0) {
|
||||
|
|
@ -403,9 +400,8 @@ struct Abc9Pass : public ScriptPass
|
|||
}
|
||||
|
||||
log_push();
|
||||
active_design->select(mod);
|
||||
active_design->selection().select(mod);
|
||||
|
||||
// this check does nothing because the above line adds the whole module to the selection
|
||||
if (!active_design->selected_whole_module(mod))
|
||||
log_error("Can't handle partially selected module %s!\n", log_id(mod));
|
||||
|
||||
|
|
@ -456,7 +452,7 @@ struct Abc9Pass : public ScriptPass
|
|||
log_pop();
|
||||
}
|
||||
|
||||
active_design->pop_selection();
|
||||
active_design->selection_stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ void prep_bypass(RTLIL::Design *design)
|
|||
|
||||
void prep_dff(RTLIL::Design *design)
|
||||
{
|
||||
auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection::EmptySelection(design)));
|
||||
auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false)));
|
||||
auto &modules_sel = r.first->second;
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ struct AbcNewPass : public ScriptPass {
|
|||
if (!help_mode) {
|
||||
selected_modules = order_modules(active_design,
|
||||
active_design->selected_whole_modules_warn());
|
||||
active_design->push_empty_selection();
|
||||
active_design->selection_stack.emplace_back(false);
|
||||
} else {
|
||||
selected_modules = {nullptr};
|
||||
run("foreach module in selection");
|
||||
|
|
@ -157,7 +157,7 @@ struct AbcNewPass : public ScriptPass {
|
|||
exe_options = abc_exe_options;
|
||||
log_header(active_design, "Mapping module '%s'.\n", log_id(mod));
|
||||
log_push();
|
||||
active_design->select(mod);
|
||||
active_design->selection().select(mod);
|
||||
}
|
||||
|
||||
std::string script_save;
|
||||
|
|
@ -194,7 +194,7 @@ struct AbcNewPass : public ScriptPass {
|
|||
}
|
||||
|
||||
if (!help_mode) {
|
||||
active_design->pop_selection();
|
||||
active_design->selection_stack.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,8 @@ struct AigmapPass : public Pass {
|
|||
module->remove(cell);
|
||||
|
||||
if (select_mode) {
|
||||
RTLIL::Selection& sel = design->selection();
|
||||
log_assert(!design->selection_stack.empty());
|
||||
RTLIL::Selection& sel = design->selection_stack.back();
|
||||
sel.selected_members[module->name] = std::move(new_sel);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -333,7 +333,7 @@ struct ClockgatePass : public Pass {
|
|||
dict<ClkNetInfo, GClkNetInfo> clk_nets;
|
||||
|
||||
int gated_flop_count = 0;
|
||||
for (auto module : design->selected_unboxed_whole_modules()) {
|
||||
for (auto module : design->selected_whole_modules()) {
|
||||
for (auto cell : module->cells()) {
|
||||
if (!RTLIL::builtin_ff_cell_types().count(cell->type))
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -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
130
passes/techmap/libcache.cc
Normal 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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct NlutmapWorker
|
|||
|
||||
RTLIL::Selection get_selection()
|
||||
{
|
||||
auto sel = RTLIL::Selection::EmptySelection(module->design);
|
||||
RTLIL::Selection sel(false);
|
||||
for (auto cell : module->cells())
|
||||
if (!mapped_cells.count(cell))
|
||||
sel.select(module, cell);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue