3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-19 05:35:47 +00:00

Merge remote-tracking branch 'upstream/main' into silimate

This commit is contained in:
Mohamed Gaber 2026-06-09 16:22:51 +03:00
commit e58125b605
No known key found for this signature in database
834 changed files with 25281 additions and 8780 deletions

View file

@ -0,0 +1,225 @@
yosys_core(libparse
libparse.cc
libparse.h
DATA_DIR
include/passes/techmap
DATA_FILES
libparse.h
)
yosys_pass(techmap
techmap.cc
REQUIRES
maccmap
proc
read_rtlil
read_verilog
sha1
simplemap
)
yosys_pass(simplemap
simplemap.cc
)
yosys_pass(dfflibmap
dfflibmap.cc
REQUIRES
dfflegalize
libparse
)
yosys_pass(maccmap
maccmap.cc
)
yosys_pass(booth
booth.cc
)
yosys_pass(libcache
libcache.cc
REQUIRES
libparse
)
set(abc_definitions
"$<$<BOOL:${YOSYS_ABC_EXECUTABLE}>:ABCEXTERNAL=\"${YOSYS_ABC_EXECUTABLE}\">"
$<${YOSYS_LINK_ABC}:YOSYS_LINK_ABC>
)
yosys_pass(abc
abc.cc
DEFINITIONS
${abc_definitions}
LIBRARIES
$<${YOSYS_LINK_ABC}:libyosys-abc>
REQUIRES
read_blif
ENABLE_IF
YOSYS_ENABLE_ABC
)
yosys_pass(abc9_exe
abc9_exe.cc
DEFINITIONS
${abc_definitions}
LIBRARIES
$<${YOSYS_LINK_ABC}:libyosys-abc>
ENABLE_IF
YOSYS_ENABLE_ABC
)
yosys_pass(abc9_ops
abc9_ops.cc
REQUIRES
proc
)
yosys_pass(abc9
abc9.cc
DEFINITIONS
${abc_definitions}
REQUIRES
abc9_exe
abc9_ops
aigmap
delete
design
opt
portarcs
read_verilog
scc
select
setattr
submod
techmap
wbflip
)
yosys_pass(abc_new
abc_new.cc
REQUIRES
abc9_exe
abc9_ops
box_derive
read_xaiger2
write_xaiger2
)
yosys_pass(iopadmap
iopadmap.cc
)
yosys_pass(clkbufmap
clkbufmap.cc
)
yosys_pass(hilomap
hilomap.cc
)
yosys_pass(extract
extract.cc
REQUIRES
opt_clean
proc
read_rtlil
read_verilog
subcircuit
write_rtlil
)
yosys_pass(extract_fa
extract_fa.cc
)
yosys_pass(extract_counter
extract_counter.cc
)
yosys_pass(extract_reduce
extract_reduce.cc
)
yosys_pass(alumacc
alumacc.cc
)
yosys_pass(dffinit
dffinit.cc
)
yosys_pass(pmuxtree
pmuxtree.cc
)
yosys_pass(bmuxmap
bmuxmap.cc
)
yosys_pass(demuxmap
demuxmap.cc
)
yosys_pass(bwmuxmap
bwmuxmap.cc
)
yosys_pass(muxcover
muxcover.cc
)
yosys_pass(aigmap
aigmap.cc
)
yosys_pass(tribuf
tribuf.cc
)
yosys_pass(lut2mux
lut2mux.cc
)
yosys_pass(lut2bmux
lut2bmux.cc
)
yosys_pass(nlutmap
nlutmap.cc
REQUIRES
abc
lut2mux
opt_clean
)
yosys_pass(shregmap
shregmap.cc
)
yosys_pass(deminout
deminout.cc
)
yosys_pass(insbuf
insbuf.cc
)
yosys_pass(bufnorm
bufnorm.cc
)
yosys_pass(attrmvcp
attrmvcp.cc
)
yosys_pass(attrmap
attrmap.cc
PROVIDES
paramap
)
yosys_pass(zinit
zinit.cc
)
yosys_pass(dfflegalize
dfflegalize.cc
)
yosys_pass(dffunmap
dffunmap.cc
)
yosys_pass(flowmap
flowmap.cc
)
yosys_pass(extractinv
extractinv.cc
)
yosys_pass(cellmatch
cellmatch.cc
)
yosys_pass(clockgate
clockgate.cc
REQUIRES
libparse
)
yosys_pass(constmap
constmap.cc
)
yosys_pass(arith_tree
arith_tree.cc
)
if (YOSYS_ENABLE_SPAWN)
yosys_cxx_executable(yosys-filterlib
OUTPUT_NAME yosys-filterlib
INSTALL_IF YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY
)
target_sources(yosys-filterlib PRIVATE filterlib.cc)
target_link_libraries(yosys-filterlib PRIVATE yosys_common)
endif()

View file

@ -1,67 +0,0 @@
OBJS += passes/techmap/techmap.o
OBJS += passes/techmap/simplemap.o
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
OBJS += passes/techmap/abc9.o
OBJS += passes/techmap/abc9_exe.o
OBJS += passes/techmap/abc9_ops.o
OBJS += passes/techmap/abc_new.o
ifneq ($(ABCEXTERNAL),)
passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
passes/techmap/abc9_exe.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
passes/techmap/abc_new.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
endif
endif
ifneq ($(SMALL),1)
OBJS += passes/techmap/iopadmap.o
OBJS += passes/techmap/clkbufmap.o
OBJS += passes/techmap/hilomap.o
OBJS += passes/techmap/extract.o
OBJS += passes/techmap/extract_fa.o
OBJS += passes/techmap/extract_counter.o
OBJS += passes/techmap/extract_reduce.o
OBJS += passes/techmap/alumacc.o
OBJS += passes/techmap/dffinit.o
OBJS += passes/techmap/pmuxtree.o
OBJS += passes/techmap/bmuxmap.o
OBJS += passes/techmap/demuxmap.o
OBJS += passes/techmap/bwmuxmap.o
OBJS += passes/techmap/muxcover.o
OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
OBJS += passes/techmap/lut2mux.o
OBJS += passes/techmap/lut2bmux.o
OBJS += passes/techmap/nlutmap.o
OBJS += passes/techmap/shregmap.o
OBJS += passes/techmap/deminout.o
OBJS += passes/techmap/insbuf.o
OBJS += passes/techmap/bufnorm.o
OBJS += passes/techmap/attrmvcp.o
OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
OBJS += passes/techmap/dfflegalize.o
OBJS += passes/techmap/dffunmap.o
OBJS += passes/techmap/flowmap.o
OBJS += passes/techmap/extractinv.o
OBJS += passes/techmap/cellmatch.o
OBJS += passes/techmap/clockgate.o
OBJS += passes/techmap/constmap.o
endif
ifeq ($(DISABLE_SPAWN),0)
TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE)
EXTRA_OBJS += passes/techmap/filterlib.o
$(PROGRAM_PREFIX)yosys-filterlib$(EXE): passes/techmap/filterlib.o
$(Q) mkdir -p $(dir $@)
$(P) $(CXX) -o $(PROGRAM_PREFIX)yosys-filterlib$(EXE) $(LINKFLAGS) $^ $(EXE_LIBS) $(LIBS)
endif

View file

@ -43,7 +43,7 @@
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/ffinit.h"
#include "kernel/ff.h"
#include "kernel/cost.h"
@ -63,13 +63,19 @@
# include <fcntl.h>
# include <spawn.h>
# include <sys/wait.h>
# include <sys/stat.h>
#endif
#ifndef _WIN32
# include <unistd.h>
# include <dirent.h>
# include <sys/stat.h>
#endif
#if defined(__wasm)
#include <wasi/libc.h>
#endif
#include "frontends/blif/blifparse.h"
#include "liberty_cache.h"
#ifdef YOSYS_LINK_ABC
namespace abc {
@ -125,11 +131,11 @@ struct AbcConfig
std::vector<std::string> liberty_files;
std::vector<std::string> genlib_files;
std::string constr_file;
std::string abc_liberty_args;
vector<int> lut_costs;
std::string delay_target;
std::string sop_inputs;
std::string sop_products;
std::string lutin_shared;
std::vector<std::string> dont_use_cells;
bool cleanup = true;
bool keepff = false;
@ -162,7 +168,12 @@ struct AbcSigVal {
}
};
#if defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN)
// REUSE_YOSYS_ABC_PROCESSES only works when ABC is built with ENABLE_READLINE.
#if defined(__linux__) && defined(YOSYS_ENABLE_SPAWN) && defined(YOSYS_ENABLE_READLINE)
#define REUSE_YOSYS_ABC_PROCESSES
#endif
#ifdef REUSE_YOSYS_ABC_PROCESSES
struct AbcProcess
{
pid_t pid;
@ -288,6 +299,8 @@ struct RunAbcState {
bool err = false;
DeferredLogs logs;
dict<int, std::string> pi_map, po_map;
std::string abc_script;
std::string dont_use_args;
int state_index = 0;
bool clk_polarity = false;
@ -1010,92 +1023,105 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module
log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n",
module->name.c_str(), replace_tempdir(run_abc.per_run_tempdir_name, config.global_tempdir_name, run_abc.per_run_tempdir_name, config.show_tempdir).c_str());
std::string abc_script;
if (config.abc_node_retention)
abc_script = stringf("read_blif -M %d -r \"%s/input.blif\"; ", config.abc_max_node_retention_origins, run_abc.per_run_tempdir_name);
run_abc.abc_script = stringf("read_blif -M %d -r \"%s/input.blif\"; ", config.abc_max_node_retention_origins, run_abc.per_run_tempdir_name);
else
abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name);
run_abc.abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name);
if (!config.liberty_files.empty() || !config.genlib_files.empty()) {
std::string dont_use_args;
run_abc.dont_use_args = "";
for (std::string dont_use_cell : config.dont_use_cells) {
dont_use_args += stringf("-X \"%s\" ", dont_use_cell);
run_abc.dont_use_args += stringf("-X \"%s\" ", dont_use_cell);
}
bool first_lib = true;
for (std::string liberty_file : config.liberty_files) {
abc_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file);
first_lib = false;
std::string merged_scl;
if (config.abc_liberty_args.empty()) {
merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, run_abc.dont_use_args, config.exe_file);
}
if (!merged_scl.empty()) {
run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str());
} else if(!config.liberty_files.empty()) {
if (!config.abc_liberty_args.empty()) {
log("ABC: abc_liberty_args provided, using liberty format\n");
} else {
log_warning("ABC: Merged scl conversion failed, using liberty format\n");
}
bool first_lib = true;
for (std::string liberty_file : config.liberty_files) {
run_abc.abc_script += stringf("read_lib %s %s %s -w \"%s\" ; ", run_abc.dont_use_args, first_lib ? "" : "-m", config.abc_liberty_args, liberty_file);
first_lib = false;
}
}
for (std::string liberty_file : config.genlib_files)
abc_script += stringf("read_library \"%s\"; ", liberty_file);
run_abc.abc_script += stringf("read_library \"%s\"; ", liberty_file);
if (!config.constr_file.empty())
abc_script += stringf("read_constr -v \"%s\"; ", config.constr_file);
run_abc.abc_script += stringf("read_constr -v \"%s\"; ", config.constr_file);
} else
if (!config.lut_costs.empty())
abc_script += stringf("read_lut %s/lutdefs.txt; ", config.global_tempdir_name);
run_abc.abc_script += stringf("read_lut %s/lutdefs.txt; ", config.global_tempdir_name);
else
abc_script += stringf("read_library %s/stdcells.genlib; ", config.global_tempdir_name);
run_abc.abc_script += stringf("read_library %s/stdcells.genlib; ", config.global_tempdir_name);
if (!config.script_file.empty()) {
const std::string &script_file = config.script_file;
if (script_file[0] == '+') {
for (size_t i = 1; i < script_file.size(); i++)
if (script_file[i] == '\'')
abc_script += "'\\''";
run_abc.abc_script += "'\\''";
else if (script_file[i] == ',')
abc_script += " ";
run_abc.abc_script += " ";
else
abc_script += script_file[i];
run_abc.abc_script += script_file[i];
} else
abc_script += stringf("source %s", script_file);
run_abc.abc_script += stringf("source %s", script_file);
} else if (!config.lut_costs.empty()) {
bool all_luts_cost_same = true;
for (int this_cost : config.lut_costs)
if (this_cost != config.lut_costs.front())
all_luts_cost_same = false;
abc_script += config.fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
if (all_luts_cost_same && !config.fast_mode)
abc_script += "; lutpack {S}";
run_abc.abc_script += "; lutpack -S 1";
} else if (!config.liberty_files.empty() || !config.genlib_files.empty())
abc_script += config.constr_file.empty() ?
run_abc.abc_script += config.constr_file.empty() ?
(config.fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (config.fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
else if (config.sop_mode)
abc_script += config.fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP;
run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP;
else
abc_script += config.fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
if (config.script_file.empty() && !config.delay_target.empty())
for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1))
abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8);
for (size_t pos = run_abc.abc_script.find("dretime;"); pos != std::string::npos; pos = run_abc.abc_script.find("dretime;", pos+1))
run_abc.abc_script = run_abc.abc_script.substr(0, pos) + "dretime; retime -o {D};" + run_abc.abc_script.substr(pos+8);
for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
abc_script = abc_script.substr(0, pos) + config.delay_target + abc_script.substr(pos+3);
for (size_t pos = run_abc.abc_script.find("{D}"); pos != std::string::npos; pos = run_abc.abc_script.find("{D}", pos))
run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.delay_target + run_abc.abc_script.substr(pos+3);
for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{I}", pos))
abc_script = abc_script.substr(0, pos) + config.sop_inputs + abc_script.substr(pos+3);
for (size_t pos = run_abc.abc_script.find("{I}"); pos != std::string::npos; pos = run_abc.abc_script.find("{I}", pos))
run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.sop_inputs + run_abc.abc_script.substr(pos+3);
for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{P}", pos))
abc_script = abc_script.substr(0, pos) + config.sop_products + abc_script.substr(pos+3);
for (size_t pos = run_abc.abc_script.find("{P}"); pos != std::string::npos; pos = run_abc.abc_script.find("{P}", pos))
run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.sop_products + run_abc.abc_script.substr(pos+3);
for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
abc_script = abc_script.substr(0, pos) + config.lutin_shared + abc_script.substr(pos+3);
if (config.abc_dress)
abc_script += stringf("; dress \"%s/input.blif\"", run_abc.per_run_tempdir_name);
abc_script += stringf("; write_blif %s/output.blif", run_abc.per_run_tempdir_name);
abc_script = add_echos_to_abc_cmd(abc_script);
#if defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN)
abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n";
run_abc.abc_script += stringf("; dress \"%s/input.blif\"", run_abc.per_run_tempdir_name);
run_abc.abc_script += stringf("; write_blif %s/output.blif", run_abc.per_run_tempdir_name);
run_abc.abc_script = add_echos_to_abc_cmd(run_abc.abc_script);
#if defined(REUSE_YOSYS_ABC_PROCESSES)
if (config.is_yosys_abc())
run_abc.abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n";
#endif
for (size_t i = 0; i+1 < abc_script.size(); i++)
if (abc_script[i] == ';' && abc_script[i+1] == ' ')
abc_script[i+1] = '\n';
for (size_t i = 0; i+1 < run_abc.abc_script.size(); i++)
if (run_abc.abc_script[i] == ';' && run_abc.abc_script[i+1] == ' ')
run_abc.abc_script[i+1] = '\n';
std::string buffer = stringf("%s/abc.script", run_abc.per_run_tempdir_name);
FILE *f = fopen(buffer.c_str(), "wt");
if (f == nullptr)
log_error("Opening %s for writing failed: %s\n", buffer, strerror(errno));
fprintf(f, "%s\n", abc_script.c_str());
fprintf(f, "%s\n", run_abc.abc_script.c_str());
fclose(f);
if (dff_mode || !clk_str.empty())
@ -1151,6 +1177,8 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module
run_abc.clk_sig = clk_sig;
}
#if defined(REUSE_YOSYS_ABC_PROCESSES)
bool read_until_abc_done(abc_output_filter &filt, int fd, DeferredLogs &logs) {
std::string line;
char buf[1024];
@ -1189,6 +1217,7 @@ bool read_until_abc_done(abc_output_filter &filt, int fd, DeferredLogs &logs) {
line.append(start, end - start);
}
}
#endif
void RunAbcState::run(ConcurrentStack<AbcProcess> &process_pool)
{
@ -1342,9 +1371,13 @@ void RunAbcState::run(ConcurrentStack<AbcProcess> &process_pool)
logs.log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
count_gates, GetSize(signal_list), count_input, count_output);
if (count_output > 0)
{
std::string tmp_script_name = stringf("%s/abc.script", per_run_tempdir_name);
if (count_output == 0) {
logs.log("Don't call ABC as there is nothing to map.\n");
return;
}
int ret;
std::string tmp_script_name = stringf("%s/abc.script", per_run_tempdir_name);
do {
logs.log("Running ABC script: %s\n", replace_tempdir(tmp_script_name, config.global_tempdir_name, per_run_tempdir_name, config.show_tempdir));
errno = 0;
@ -1353,13 +1386,13 @@ void RunAbcState::run(ConcurrentStack<AbcProcess> &process_pool)
string temp_stdouterr_name = stringf("%s/stdouterr.txt", per_run_tempdir_name);
FILE *temp_stdouterr_w = fopen(temp_stdouterr_name.c_str(), "w");
if (temp_stdouterr_w == NULL)
log_error("ABC: cannot open a temporary file for output redirection");
logs.log_error("ABC: cannot open a temporary file for output redirection");
fflush(stdout);
fflush(stderr);
FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
#if defined(__wasm)
#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to)
#define fd_renumber(from, to) (void)__wasilibc_fd_renumber(from, to)
#else
#define fd_renumber(from, to) dup2(from, to)
#endif
@ -1375,7 +1408,7 @@ void RunAbcState::run(ConcurrentStack<AbcProcess> &process_pool)
abc_argv[2] = strdup("-f");
abc_argv[3] = strdup(tmp_script_name.c_str());
abc_argv[4] = 0;
int ret = abc::Abc_RealMain(4, abc_argv);
ret = abc::Abc_RealMain(4, abc_argv);
free(abc_argv[0]);
free(abc_argv[1]);
free(abc_argv[2]);
@ -1390,39 +1423,42 @@ void RunAbcState::run(ConcurrentStack<AbcProcess> &process_pool)
for (std::string line; std::getline(temp_stdouterr_r, line); )
filt.next_line(line + "\n");
temp_stdouterr_r.close();
#elif defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN)
AbcProcess process;
if (std::optional<AbcProcess> process_opt = process_pool.try_pop_back()) {
process = std::move(process_opt.value());
} else if (std::optional<AbcProcess> process_opt = spawn_abc(config.exe_file.c_str(), logs)) {
process = std::move(process_opt.value());
} else {
return;
}
std::string cmd = stringf(
"empty\n"
"source %s\n", tmp_script_name);
int ret = write(process.to_child_pipe, cmd.c_str(), cmd.size());
if (ret != static_cast<int>(cmd.size())) {
logs.log_error("write failed");
return;
}
ret = read_until_abc_done(filt, process.from_child_pipe, logs) ? 0 : 1;
if (ret == 0) {
process_pool.push_back(std::move(process));
}
break;
#else
std::string cmd = stringf("\"%s\" -s -f %s/abc.script 2>&1", config.exe_file.c_str(), per_run_tempdir_name.c_str());
int ret = run_command(cmd, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
#endif
if (ret != 0) {
logs.log_error("ABC: execution of script \"%s\" failed: return code %d (errno=%d).\n", tmp_script_name, ret, errno);
return;
#if defined(REUSE_YOSYS_ABC_PROCESSES)
if (config.is_yosys_abc()) {
AbcProcess process;
if (std::optional<AbcProcess> process_opt = process_pool.try_pop_back()) {
process = std::move(process_opt.value());
} else if (std::optional<AbcProcess> process_opt = spawn_abc(config.exe_file.c_str(), logs)) {
process = std::move(process_opt.value());
} else {
return;
}
std::string cmd = stringf(
"empty\n"
"source %s\n", tmp_script_name);
ret = write(process.to_child_pipe, cmd.c_str(), cmd.size());
if (ret != static_cast<int>(cmd.size())) {
logs.log_error("write failed");
return;
}
ret = read_until_abc_done(filt, process.from_child_pipe, logs) ? 0 : 1;
if (ret == 0) {
process_pool.push_back(std::move(process));
}
break;
}
did_run = true;
#endif
std::string cmd = stringf("\"%s\" -s -f %s 2>&1", config.exe_file, tmp_script_name);
ret = run_command(cmd, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
#endif
} while (false);
if (ret != 0) {
logs.log_error("ABC: execution of script \"%s\" failed: return code %d (errno=%d).\n", tmp_script_name, ret, errno);
return;
}
logs.log("Don't call ABC as there is nothing to map.\n");
did_run = true;
}
void emit_global_input_files(const AbcConfig &config)
@ -1563,7 +1599,7 @@ void AbcModuleState::extract(AbcSigMap &assign_map, dict<SigSpec, std::string> &
if (builtin_lib)
{
cell_stats[RTLIL::unescape_id(c->type)]++;
cell_stats[c->type.unescape()]++;
if (c->type.in(ID(ZERO), ID(ONE))) {
RTLIL::SigSig conn;
RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name);
@ -1735,7 +1771,7 @@ void AbcModuleState::extract(AbcSigMap &assign_map, dict<SigSpec, std::string> &
}
}
else
cell_stats[RTLIL::unescape_id(c->type)]++;
cell_stats[c->type.unescape()]++;
if (c->type.in(ID(_const0_), ID(_const1_))) {
RTLIL::SigSig conn;
@ -1952,7 +1988,7 @@ struct AbcPass : public Pass {
log("%s\n", fold_abc_cmd(ABC_COMMAND_CTR));
log("\n");
log(" for -lut/-luts (only one LUT size):\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT "; lutpack {S}"));
log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT "; lutpack -S 1"));
log("\n");
log(" for -lut/-luts (different LUT sizes):\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT));
@ -1987,8 +2023,10 @@ struct AbcPass : public Pass {
log(" file format).\n");
log("\n");
log(" -dont_use <cell_name>\n");
log(" generate netlists for the specified cell library (using the liberty\n");
log(" file format).\n");
log(" avoid usage of the technology cell <cell_name> when mapping the design.\n");
log(" this option can be used multiple times with different cell names and\n");
log(" supports simple glob patterns in the cell name.\n");
log(" only supported with Liberty cell libraries.\n");
log("\n");
log(" -genlib <file>\n");
log(" generate netlists for the specified cell library (using the SIS Genlib\n");
@ -2020,10 +2058,6 @@ struct AbcPass : public Pass {
log(" maximum number of SOP products.\n");
log(" (replaces {P} in the default scripts above)\n");
log("\n");
log(" -S <num>\n");
log(" maximum number of LUT inputs shared.\n");
log(" (replaces {S} in the default scripts above, default: -S 1)\n");
log("\n");
log(" -lut <width>\n");
log(" generate netlist using luts of (max) the specified width.\n");
log("\n");
@ -2116,6 +2150,9 @@ struct AbcPass : public Pass {
log(" number of CPU cores to reserve for the main thread and other work.\n");
log(" Default is 4. The actual number of worker threads used is:\n");
log(" min(hardware_threads - reserved_cores, max_threads)\n");
log(" -liberty_args <string>\n");
log(" when -liberty is used, also pass the specified arguments to ABC\n");
log(" command \"read_lib\". Example: -liberty_args \"-G 250\"\n");
log("\n");
log("When no target cell library is specified the Yosys standard cell library is\n");
log("loaded into ABC before the ABC script is executed.\n");
@ -2152,11 +2189,6 @@ struct AbcPass : public Pass {
if (design->scratchpad.count("abc.P")) {
config.sop_products = "-P " + design->scratchpad_get_string("abc.P");
}
if (design->scratchpad.count("abc.S")) {
config.lutin_shared = "-S " + design->scratchpad_get_string("abc.S");
} else {
config.lutin_shared = "-S 1";
}
lut_arg = design->scratchpad_get_string("abc.lut", lut_arg);
luts_arg = design->scratchpad_get_string("abc.luts", luts_arg);
config.sop_mode = design->scratchpad_get_bool("abc.sop", false);
@ -2245,10 +2277,6 @@ struct AbcPass : public Pass {
config.sop_products = "-P " + args[++argidx];
continue;
}
if (arg == "-S" && argidx+1 < args.size()) {
config.lutin_shared = "-S " + args[++argidx];
continue;
}
if (arg == "-lut" && argidx+1 < args.size()) {
lut_arg = args[++argidx];
continue;
@ -2334,6 +2362,14 @@ struct AbcPass : public Pass {
config.cdc_file = args[++argidx];
continue;
}
if (arg == "-liberty_args" && argidx+1 < args.size()) {
config.abc_liberty_args = args[++argidx];
if (!config.abc_liberty_args.empty()) {
if (config.abc_liberty_args[0] == '\"' && config.abc_liberty_args.back() == '\"')
config.abc_liberty_args = config.abc_liberty_args.substr(1, config.abc_liberty_args.size() - 2);
}
continue;
}
break;
}
extra_args(args, argidx, design);
@ -2694,7 +2730,7 @@ struct AbcPass : public Pass {
for (auto mod : design->selected_modules())
{
if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod));
log("Skipping module %s as it contains processes.\n", mod);
continue;
}
@ -2727,7 +2763,7 @@ struct AbcPass : public Pass {
sig2src[bit] = bit.wire->get_src_attribute();
}
CellTypes ct(design);
NewCellTypes ct(design);
std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
pool<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());
@ -2964,4 +3000,4 @@ struct AbcPass : public Pass {
}
} AbcPass;
PRIVATE_NAMESPACE_END
PRIVATE_NAMESPACE_END

View file

@ -38,53 +38,53 @@ struct Abc9Pass : public ScriptPass
Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
void on_register() override
{
RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f -r; &ps; &if {C} {W} {D} {R} -v; &mfs";
RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f -r; &ps; &if {C} {W} {D} {R} -a -v; &mfs";
RTLIL::constpad["abc9.script.default.fast"] = "+&if {C} {W} {D} {R} -v";
RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f -r; &ps; &if {W} {D} {R} -v; &mfs";
RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f -r; &ps; &if {W} {D} {R} -a -v; &mfs";
RTLIL::constpad["abc9.script.default.fast"] = "+&if {W} {D} {R} -v";
// Based on ABC's &flow
RTLIL::constpad["abc9.script.flow"] = "+&scorr; &sweep;" \
"&dch -C 500;" \
/* Round 1 */ \
/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 1 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
"&st; &dsdb;" \
/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 2 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
"&st; &syn2 -m -R 10; &dsdb;" \
"&blut -a -K 6;" \
/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 3 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
/* Round 2 */ \
"&st; &sopb;" \
/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 1 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
"&st; &dsdb;" \
/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 2 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
"&st; &syn2 -m -R 10; &dsdb;" \
"&blut -a -K 6;" \
/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 3 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
/* Round 3 */ \
/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 1 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
"&st; &dsdb;" \
/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \
/* Map 2 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;" \
"&st; &syn2 -m -R 10; &dsdb;" \
"&blut -a -K 6;" \
/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;";
/* Map 3 */ "&unmap; &if {W} {D} {R} -v; &save; &load; &mfs;";
// Based on ABC's &flow2
RTLIL::constpad["abc9.script.flow2"] = "+&scorr; &sweep;" \
/* Comm1 */ "&synch2 -K 6 -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
/* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
/* Comm1 */ "&synch2 -K 6 -C 500; &if -m {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
/* Comm2 */ "&dch -C 500; &if -m {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
"&load; &st; &sopb -R 10 -C 4; " \
/* Comm3 */ "&synch2 -K 6 -C 500; &if -m "/*"-E 5"*/" {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
/* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save; "\
/* Comm3 */ "&synch2 -K 6 -C 500; &if -m "/*"-E 5"*/" {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\
/* Comm2 */ "&dch -C 500; &if -m {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save; "\
"&load";
// Based on ABC's &flow3 -m
RTLIL::constpad["abc9.script.flow3"] = "+&scorr; &sweep;" \
"&if {C} {W} {D}; &save; &st; &syn2; &if {C} {W} {D} {R} -v; &save; &load;"\
"&st; &if {C} -g -K 6; &dch -f; &if {C} {W} {D} {R} -v; &save; &load;"\
"&st; &if {C} -g -K 6; &synch2; &if {C} {W} {D} {R} -v; &save; &load;"\
"&if {W} {D}; &save; &st; &syn2; &if {W} {D} {R} -v; &save; &load;"\
"&st; &if -g -K 6; &dch -f; &if {W} {D} {R} -v; &save; &load;"\
"&st; &if -g -K 6; &synch2; &if {W} {D} {R} -v; &save; &load;"\
"&mfs";
// As above, but with &mfs calls as in the original &flow3
RTLIL::constpad["abc9.script.flow3mfs"] = "+&scorr; &sweep;" \
"&if {C} {W} {D}; &save; &st; &syn2; &if {C} {W} {D} {R} -v; &save; &load;"\
"&st; &if {C} -g -K 6; &dch -f; &if {C} {W} {D} {R} -v; &mfs; &save; &load;"\
"&st; &if {C} -g -K 6; &synch2; &if {C} {W} {D} {R} -v; &mfs; &save; &load;"\
"&if {W} {D}; &save; &st; &syn2; &if {W} {D} {R} -v; &save; &load;"\
"&st; &if -g -K 6; &dch -f; &if {W} {D} {R} -v; &mfs; &save; &load;"\
"&st; &if -g -K 6; &synch2; &if {W} {D} {R} -v; &mfs; &save; &load;"\
"&mfs";
}
void help() override
@ -121,20 +121,11 @@ struct Abc9Pass : public ScriptPass
log(" if no -script parameter is given, the following scripts are used:\n");
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)));
log("\n");
log(" -fast\n");
log(" use different default scripts that are slightly faster (at the cost\n");
log(" of output quality):\n");
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)));
log("\n");
log(" -D <picoseconds>\n");
log(" set delay target. the string {D} in the default scripts above is\n");
log(" replaced by this option when used, and an empty string otherwise\n");
log(" (indicating best possible delay).\n");
log("\n");
// log(" -S <num>\n");
// log(" maximum number of LUT inputs shared.\n");
// log(" (replaces {S} in the default scripts above, default: -S 1)\n");
// log("\n");
log(" -lut <width>\n");
log(" generate netlist using luts of (max) the specified width.\n");
log("\n");
@ -226,8 +217,7 @@ struct Abc9Pass : public ScriptPass
exe_cmd << " " << arg << " " << args[++argidx];
continue;
}
if (arg == "-fast" || /* arg == "-dff" || */
/* arg == "-nocleanup" || */ arg == "-showtmp") {
if (arg == "-showtmp") {
exe_cmd << " " << arg;
continue;
}
@ -396,7 +386,7 @@ struct Abc9Pass : public ScriptPass
for (auto mod : selected_modules) {
if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod));
log("Skipping module %s as it contains processes.\n", mod);
continue;
}
@ -405,7 +395,7 @@ struct Abc9Pass : public ScriptPass
// 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));
log_error("Can't handle partially selected module %s!\n", mod);
std::string tempdir_name;
if (cleanup)
@ -426,7 +416,7 @@ struct Abc9Pass : public ScriptPass
log("Extracted %d AND gates and %d wires from module `%s' to a netlist network with %d inputs and %d outputs.\n",
active_design->scratchpad_get_int("write_xaiger.num_ands"),
active_design->scratchpad_get_int("write_xaiger.num_wires"),
log_id(mod),
mod,
active_design->scratchpad_get_int("write_xaiger.num_inputs"),
num_outputs);
if (num_outputs) {
@ -439,7 +429,7 @@ struct Abc9Pass : public ScriptPass
else
abc9_exe_cmd += stringf(" -box %s", box_file);
run_nocheck(abc9_exe_cmd);
run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name, tempdir_name));
run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", mod, tempdir_name, tempdir_name));
run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : ""));
}
else

View file

@ -24,11 +24,15 @@
#include "kernel/register.h"
#include "kernel/log.h"
#include "liberty_cache.h"
#ifndef _WIN32
# include <unistd.h>
# include <dirent.h>
#endif
#if defined(__wasm)
#include <wasi/libc.h>
#endif
#ifdef YOSYS_LINK_ABC
namespace abc {
@ -165,7 +169,7 @@ struct abc9_output_filter
};
void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe_file,
vector<int> lut_costs, bool dff_mode, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
vector<int> lut_costs, bool dff_mode, std::string delay_target,
bool show_tempdir, std::string box_file, std::string lut_file,
std::vector<std::string> liberty_files, std::string wire_delay, std::string tempdir_name,
std::string constr_file, std::vector<std::string> dont_use_cells, std::vector<std::string> genlib_files)
@ -181,11 +185,19 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
for (std::string dont_use_cell : dont_use_cells) {
dont_use_args += stringf("-X \"%s\" ", dont_use_cell);
}
bool first_lib = true;
for (std::string liberty_file : liberty_files) {
abc9_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file);
first_lib = false;
std::string merged_scl = convert_liberty_files_to_merged_scl(liberty_files, dont_use_args, exe_file);
if (!merged_scl.empty()) {
abc9_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str());
} else if(!liberty_files.empty()) {
log_warning("ABC: Merged scl conversion failed, using liberty format\n");
bool first_lib = true;
for (std::string liberty_file : liberty_files) {
abc9_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file);
first_lib = false;
}
}
if (!constr_file.empty())
abc9_script += stringf("read_constr -v \"%s\"; ", constr_file);
} else if (!genlib_files.empty()) {
@ -210,26 +222,18 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
} else
abc9_script += stringf("source %s", script_file);
} else if (!lut_costs.empty() || !lut_file.empty()) {
abc9_script += fast_mode ? RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)
: RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos);
abc9_script += RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos);
} else if (!liberty_files.empty() || !genlib_files.empty()) {
abc9_script += RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos);
} else
log_abort();
for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos))
abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3);
//for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos))
// abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3);
for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos))
abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3);
std::string C;
if (design->scratchpad.count("abc9.if.C"))
C = "-C " + design->scratchpad_get_string("abc9.if.C");
for (size_t pos = abc9_script.find("{C}"); pos != std::string::npos; pos = abc9_script.find("{C}", pos))
abc9_script = abc9_script.substr(0, pos) + C + abc9_script.substr(pos+3);
std::string R;
if (design->scratchpad.count("abc9.if.R"))
R = "-R " + design->scratchpad_get_string("abc9.if.R");
@ -248,7 +252,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
}
abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name);
if (design->scratchpad_get_bool("abc9.verify")) {
if (design->scratchpad_get_bool("abc9.verify", true)) {
if (dff_mode)
abc9_script += "; &verify -s";
else
@ -295,7 +299,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
#if defined(__wasm)
#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to)
#define fd_renumber(from, to) (void)__wasilibc_fd_renumber(from, to)
#else
#define fd_renumber(from, to) dup2(from, to)
#endif
@ -369,11 +373,6 @@ struct Abc9ExePass : public Pass {
log(" if no -script parameter is given, the following scripts are used:\n");
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)));
log("\n");
log(" -fast\n");
log(" use different default scripts that are slightly faster (at the cost\n");
log(" of output quality):\n");
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)));
log("\n");
log(" -constr <file>\n");
log(" pass this file with timing constraints to ABC.\n");
log(" use with -liberty.\n");
@ -453,9 +452,9 @@ struct Abc9ExePass : public Pass {
std::string exe_file = yosys_abc_executable;
std::string script_file, clk_str, box_file, lut_file, constr_file;
std::vector<std::string> liberty_files, genlib_files, dont_use_cells;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
std::string delay_target, wire_delay;
std::string tempdir_name;
bool fast_mode = false, dff_mode = false;
bool dff_mode = false;
bool show_tempdir = false;
vector<int> lut_costs;
@ -472,7 +471,6 @@ struct Abc9ExePass : public Pass {
}
lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg);
luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg);
fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode);
dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode);
show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir);
box_file = design->scratchpad_get_string("abc9.box", box_file);
@ -504,20 +502,12 @@ struct Abc9ExePass : public Pass {
delay_target = "-D " + args[++argidx];
continue;
}
//if (arg == "-S" && argidx+1 < args.size()) {
// lutin_shared = "-S " + args[++argidx];
// continue;
//}
if (arg == "-lut" && argidx+1 < args.size()) {
lut_arg = args[++argidx];
continue;
}
if (arg == "-luts" && argidx+1 < args.size()) {
lut_arg = args[++argidx];
continue;
}
if (arg == "-fast") {
fast_mode = true;
luts_arg = args[++argidx];
continue;
}
if (arg == "-dff") {
@ -622,7 +612,7 @@ struct Abc9ExePass : public Pass {
log_cmd_error("abc9_exe '-genlib' is incompatible with '-dont_use'.\n");
abc9_module(design, script_file, exe_file, lut_costs, dff_mode,
delay_target, lutin_shared, fast_mode, show_tempdir,
delay_target, show_tempdir,
box_file, lut_file, liberty_files, wire_delay, tempdir_name,
constr_file, dont_use_cells, genlib_files);
}

View file

@ -21,8 +21,9 @@
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/utils.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/timinginfo.h"
#include <optional>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@ -47,7 +48,7 @@ void check(RTLIL::Design *design, bool dff_mode)
auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name));
if (!r.second)
log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
log_id(m), id, log_id(r.first->second));
m, id, r.first->second.unescape());
}
// Make carry in the last PI, and carry out the last PO
@ -59,21 +60,21 @@ void check(RTLIL::Design *design, bool dff_mode)
if (w->get_bool_attribute(ID::abc9_carry)) {
if (w->port_input) {
if (carry_in != IdString())
log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m));
log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", m);
carry_in = port_name;
}
if (w->port_output) {
if (carry_out != IdString())
log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m));
log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", m);
carry_out = port_name;
}
}
}
if (carry_in != IdString() && carry_out == IdString())
log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m));
log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", m);
if (carry_in == IdString() && carry_out != IdString())
log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m));
log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", m);
if (flop) {
int num_outputs = 0;
@ -82,7 +83,7 @@ void check(RTLIL::Design *design, bool dff_mode)
if (wire->port_output) num_outputs++;
}
if (num_outputs != 1)
log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs);
log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", m, num_outputs);
}
}
@ -96,7 +97,6 @@ void check(RTLIL::Design *design, bool dff_mode)
ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)
};
pool<IdString> processed;
for (auto module : design->selected_modules())
for (auto cell : module->cells()) {
auto inst_module = design->module(cell->type);
@ -120,7 +120,7 @@ void check(RTLIL::Design *design, bool dff_mode)
if (!derived_module->get_bool_attribute(ID::abc9_flop))
continue;
if (derived_module->get_blackbox_attribute(true /* ignore_wb */))
log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type));
log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", derived_type.unescape());
if (derived_module->has_processes())
Pass::call_on_module(design, derived_module, "proc -noopt");
@ -129,20 +129,20 @@ void check(RTLIL::Design *design, bool dff_mode)
for (auto derived_cell : derived_module->cells()) {
if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) {
if (found)
log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module));
log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", derived_module);
found = true;
SigBit Q = derived_cell->getPort(ID::Q);
log_assert(GetSize(Q.wire) == 1);
if (!Q.wire->port_output)
log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", log_id(derived_module), log_id(derived_cell->type));
log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", derived_module, derived_cell->type.unescape());
Const init = Q.wire->attributes.at(ID::init, State::Sx);
log_assert(GetSize(init) == 1);
}
else if (unsupported.count(derived_cell->type))
log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type));
log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", derived_module, derived_cell->type.unescape());
}
}
}
@ -216,7 +216,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode)
// Block sequential synthesis on cells with (* init *) != 1'b0
// because ABC9 doesn't support them
if (init != State::S0) {
log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type));
log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", derived_module, derived_cell->type.unescape());
derived_module->set_bool_attribute(ID::abc9_flop, false);
}
break;
@ -473,7 +473,7 @@ void prep_dff(RTLIL::Design *design)
// be instantiating the derived module which will have had any parameters constant-propagated.
// This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design.
// Please file a bug report!
log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", log_id(cell->name), log_id(cell->type));
log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", cell->name.unescape(), cell->type.unescape());
}
modules_sel.select(inst_module);
}
@ -587,6 +587,7 @@ void break_scc(RTLIL::Module *module)
auto id = it->second;
auto r = ids_seen.insert(id);
cell->attributes.erase(it);
// Cut exactly one representative cell per SCC id.
if (!r.second)
continue;
for (auto &c : cell->connections_) {
@ -619,7 +620,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
std::vector<Cell*> cells;
for (auto module : design->selected_modules()) {
if (module->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(module));
log("Skipping module %s as it contains processes.\n", module);
continue;
}
@ -667,7 +668,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
auto port_wire = inst_module->wire(i.first.name);
if (!port_wire)
log_error("Port %s in cell %s (type %s) from module %s does not actually exist",
log_id(i.first.name), log_id(cell), log_id(cell->type), log_id(module));
i.first.name.unescape(), cell, cell->type.unescape(), module);
log_assert(port_wire->port_input);
auto d = i.second.first;
@ -686,7 +687,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
if (ys_debug(1)) {
static pool<std::pair<IdString,TimingInfo::NameBit>> seen;
if (seen.emplace(cell->type, i.first).second) log("%s.%s[%d] abc9_required = %d\n",
log_id(cell->type), log_id(i.first.name), offset, d);
cell->type.unescape(), i.first.name.unescape(), offset, d);
}
#endif
auto r = box_cache.insert(d);
@ -710,8 +711,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
SigMap sigmap(module);
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
dict<IdString, std::vector<IdString>> box_ports;
for (auto cell : module->cells()) {
@ -750,44 +749,105 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
}
}
}
else if (!yosys_celltypes.cell_known(cell->type))
continue;
// TODO: Speed up toposort -- we care about box ordering only
for (auto conn : cell->connections()) {
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
bit_users[bit].insert(cell->name);
if (cell->output(conn.first) && !abc9_flop)
for (auto bit : sigmap(conn.second))
bit_drivers[bit].insert(cell->name);
}
toposort.node(cell->name);
}
if (box_ports.empty())
return;
for (auto &it : bit_users)
if (bit_drivers.count(it.first))
for (auto driver_cell : bit_drivers.at(it.first))
for (auto user_cell : it.second)
toposort.edge(driver_cell, user_cell);
// Build the same topo graph for the initial pass and the optional retry.
auto build_toposort = [&](TopoSort<IdString, RTLIL::sort_by_id_str> &toposort) {
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
if (ys_debug(1))
toposort.analyze_loops = true;
for (auto cell : module->cells()) {
if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
continue;
if (cell->has_keep_attr())
continue;
bool no_loops = toposort.sort();
auto inst_module = design->module(cell->type);
bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop);
if (abc9_flop && !dff)
continue;
if (!(inst_module && inst_module->get_bool_attribute(ID::abc9_box)) && !yosys_celltypes.cell_known(cell->type))
continue;
// TODO: Speed up toposort -- we care about box ordering only
for (auto conn : cell->connections()) {
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
bit_users[bit].insert(cell->name);
if (cell->output(conn.first) && !abc9_flop)
for (auto bit : sigmap(conn.second))
bit_drivers[bit].insert(cell->name);
}
toposort.node(cell->name);
}
// Build producer -> consumer edges on sigmapped nets.
for (auto &it : bit_users)
if (bit_drivers.count(it.first))
for (auto driver_cell : bit_drivers.at(it.first))
for (auto user_cell : it.second)
toposort.edge(driver_cell, user_cell);
if (ys_debug(1))
toposort.analyze_loops = true;
return toposort.sort();
};
// Build TopoSort in a container, as we may need to conditionally rebuild it on retry.
std::optional<TopoSort<IdString, RTLIL::sort_by_id_str>> toposort;
toposort.emplace();
bool no_loops = build_toposort(toposort.value());
// Fallback for residual loops after SCC cutting: insert additional
// breakers on non-box loop cells, then re-run toposort checks.
if (!no_loops) {
SigSpec I, O;
pool<IdString> broken_cells;
for (auto &loop : toposort.value().loops)
for (auto cell_name : loop) {
// Loop reports can overlap; cut each cell at most once.
if (!broken_cells.insert(cell_name).second)
continue;
auto cell = module->cell(cell_name);
log_assert(cell);
auto inst_module = design->module(cell->type);
if (inst_module && inst_module->get_bool_attribute(ID::abc9_box))
continue;
for (auto &c : cell->connections_) {
if (c.second.is_fully_const()) continue;
if (cell->output(c.first)) {
Wire *w = module->addWire(NEW_ID, GetSize(c.second));
I.append(w);
O.append(c.second);
c.second = w;
}
}
}
if (!I.empty()) {
auto cell = module->addCell(NEW_ID, ID($__ABC9_SCC_BREAKER));
log_assert(GetSize(I) == GetSize(O));
cell->setParam(ID::WIDTH, GetSize(I));
cell->setPort(ID::I, std::move(I));
cell->setPort(ID::O, std::move(O));
// Rebuild topo ordering after inserting the additional breakers.
toposort.emplace();
no_loops = build_toposort(toposort.value());
}
}
if (ys_debug(1)) {
unsigned i = 0;
for (auto &it : toposort.loops) {
for (auto &it : toposort.value().loops) {
log(" loop %d\n", i++);
for (auto cell_name : it) {
auto cell = module->cell(cell_name);
log_assert(cell);
log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute());
log("\t%s (%s @ %s)\n", cell, cell->type.unescape(), cell->get_src_attribute());
}
}
}
@ -806,7 +866,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
TimingInfo timing;
int port_id = 1, box_count = 0;
for (auto cell_name : toposort.sorted) {
for (auto cell_name : toposort.value().sorted) {
RTLIL::Cell *cell = module->cell(cell_name);
log_assert(cell);
@ -821,7 +881,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
// be instantiating the derived module which will have had any parameters constant-propagated.
// This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design.
// Please file a bug report!
log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", log_id(cell_name), log_id(cell->type));
log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", cell_name.unescape(), cell->type.unescape());
}
log_assert(box_module->get_blackbox_attribute());
@ -856,7 +916,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
}
}
else if (w->port_output)
conn = holes_module->addWire(stringf("%s.%s", cell->type, log_id(port_name)), GetSize(w));
conn = holes_module->addWire(stringf("%s.%s", cell->type, port_name.unescape()), GetSize(w));
}
}
else // box_module is a blackbox
@ -868,7 +928,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
log_assert(w);
if (!w->port_output)
continue;
Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, log_id(port_name)), GetSize(w));
Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, port_name.unescape()), GetSize(w));
holes_wire->port_output = true;
holes_wire->port_id = port_id++;
holes_module->ports.push_back(holes_wire->name);
@ -904,12 +964,12 @@ void prep_lut(RTLIL::Design *design, int maxlut)
if (o == TimingInfo::NameBit())
o = d;
else if (o != d)
log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module));
log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", module);
delays.push_back(i.second);
}
if (GetSize(delays) == 0)
log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module));
log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", module);
if (maxlut && GetSize(delays) > maxlut)
continue;
// ABC requires non-decreasing LUT input delays
@ -920,9 +980,9 @@ void prep_lut(RTLIL::Design *design, int maxlut)
auto r = table.emplace(K, entry);
if (!r.second) {
if (r.first->second.area != entry.area)
log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name));
log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", module, r.first->second.name.unescape());
if (r.first->second.delays != entry.delays)
log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name));
log_error("Modules '%s' and '%s' have conflicting specify entries.\n", module, r.first->second.name.unescape());
}
}
@ -941,7 +1001,7 @@ void prep_lut(RTLIL::Design *design, int maxlut)
ss << std::endl;
}
for (const auto &i : table) {
ss << "# " << log_id(i.second.name) << std::endl;
ss << "# " << i.second.name.unescape() << std::endl;
ss << i.first << " " << i.second.area;
for (const auto &j : i.second.delays)
ss << " " << j;
@ -985,7 +1045,7 @@ void prep_box(RTLIL::Design *design)
}
log_assert(num_outputs == 1);
ss << log_id(module) << " " << r.first->second.as_int();
ss << module->name.unescape() << " " << r.first->second.as_int();
log_assert(module->get_bool_attribute(ID::whitebox));
ss << " " << "1";
ss << " " << num_inputs << " " << num_outputs << std::endl;
@ -1000,13 +1060,13 @@ void prep_box(RTLIL::Design *design)
first = false;
else
ss << " ";
ss << log_id(wire);
ss << wire->name.unescape();
}
ss << std::endl;
auto &t = timing.setup_module(module).required;
if (t.empty())
log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module));
log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", module);
first = true;
for (auto port_name : module->ports) {
@ -1028,8 +1088,8 @@ void prep_box(RTLIL::Design *design)
#ifndef NDEBUG
if (ys_debug(1)) {
static std::set<std::pair<IdString,IdString>> seen;
if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module),
log_id(port_name), it->second.first);
if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", module,
port_name.unescape(), it->second.first);
}
#endif
}
@ -1074,7 +1134,7 @@ void prep_box(RTLIL::Design *design)
outputs.emplace_back(wire, i);
}
ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int();
ss << module->name.unescape() << " " << module->attributes.at(ID::abc9_box_id).as_int();
bool has_model = module->get_bool_attribute(ID::whitebox) || !module->get_bool_attribute(ID::blackbox);
ss << " " << (has_model ? "1" : "0");
ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl;
@ -1087,15 +1147,15 @@ void prep_box(RTLIL::Design *design)
else
ss << " ";
if (GetSize(i.wire) == 1)
ss << log_id(i.wire);
ss << i.wire->name.unescape();
else
ss << log_id(i.wire) << "[" << i.offset << "]";
ss << i.wire->name.unescape() << "[" << i.offset << "]";
}
ss << std::endl;
auto &t = timing.setup_module(module);
if (t.comb.empty() && !outputs.empty() && !inputs.empty()) {
log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module));
log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", module);
}
for (const auto &o : outputs) {
@ -1113,9 +1173,9 @@ void prep_box(RTLIL::Design *design)
}
ss << " # ";
if (GetSize(o.wire) == 1)
ss << log_id(o.wire);
ss << o.wire->name.unescape();
else
ss << log_id(o.wire) << "[" << o.offset << "]";
ss << o.wire->name.unescape() << "[" << o.offset << "]";
ss << std::endl;
}
ss << std::endl;
@ -1145,7 +1205,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name));
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module));
log_error("ABC output file does not contain a module `%s$abc'.\n", module);
for (auto w : mapped_mod->wires()) {
auto nw = module->addWire(remap_name(w->name), GetSize(w));
@ -1326,7 +1386,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
else {
RTLIL::Cell *existing_cell = module->cell(mapped_cell->name);
if (!existing_cell)
log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell));
log_error("Cannot find existing box cell with name '%s' in original design.\n", mapped_cell);
if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) {
SigBit I = mapped_cell->getPort(ID(i));
@ -1559,7 +1619,6 @@ clone_lut:
}
}
//log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
log("ABC RESULTS: input signals: %8d\n", in_wires);
log("ABC RESULTS: output signals: %8d\n", out_wires);
@ -1592,7 +1651,7 @@ static void replace_zbufs(Design *design)
if (sig[i] == State::Sz) {
Wire *w = mod->addWire(NEW_ID);
Cell *ud = mod->addCell(NEW_ID, ID($tribuf));
ud->set_bool_attribute(ID(aiger2_zbuf));
ud->set_bool_attribute(ID::aiger2_zbuf);
ud->setParam(ID::WIDTH, 1);
ud->setPort(ID::Y, w);
ud->setPort(ID::EN, State::S0);
@ -1864,12 +1923,12 @@ struct Abc9OpsPass : public Pass {
for (auto mod : design->selected_modules()) {
if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod));
log("Skipping module %s as it contains processes.\n", mod);
continue;
}
if (!design->selected_whole_module(mod))
log_error("Can't handle partially selected module %s!\n", log_id(mod));
log_error("Can't handle partially selected module %s!\n", mod);
if (!write_lut_dst.empty())
write_lut(mod, write_lut_dst);

View file

@ -18,7 +18,7 @@
*/
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/yosys_common.h"
#include "kernel/utils.h"
USING_YOSYS_NAMESPACE
@ -27,7 +27,8 @@ PRIVATE_NAMESPACE_BEGIN
std::vector<Module*> order_modules(Design *design, std::vector<Module *> modules)
{
std::set<Module *> modules_set(modules.begin(), modules.end());
TopoSort<Module*> sort;
using Order = IdString::compare_ptr_by_name<RTLIL::NamedObject>;
TopoSort<Module*, Order> sort;
for (auto m : modules) {
sort.node(m);
@ -49,6 +50,17 @@ struct AbcNewPass : public ScriptPass {
experimental();
}
void on_register() override
{
RTLIL::constpad["abc_new.script.speed"] = "+&st; &dch -r;" \
"&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \
"&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \
"&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \
"&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \
"&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \
"&nf";
}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
@ -109,6 +121,11 @@ struct AbcNewPass : public ScriptPass {
}
extra_args(args, argidx, d);
// If no script provided, use a default.
if (abc_exe_options.find("-script") == std::string::npos) {
d->scratchpad_set_string("abc9.script", RTLIL::constpad["abc_new.script.speed"]);
}
log_header(d, "Executing ABC_NEW pass.\n");
log_push();
run_script(d, run_from, run_to);
@ -161,7 +178,7 @@ struct AbcNewPass : public ScriptPass {
tmpdir = make_temp_dir(tmpdir);
modname = mod->name.str();
exe_options = abc_exe_options;
log_header(active_design, "Mapping module '%s'.\n", log_id(mod));
log_header(active_design, "Mapping module '%s'.\n", mod);
log_push();
active_design->select(mod);
}

View file

@ -186,21 +186,21 @@ struct AigmapPass : public Pass {
if (not_replaced_count == 0 && replaced_cells.empty())
continue;
log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", log_id(module),
log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", module,
GetSize(replaced_cells), GetSize(module->cells()) - orig_num_cells, not_replaced_count);
if (!stat_replaced.empty()) {
stat_replaced.sort();
log(" replaced %d cell types:\n", GetSize(stat_replaced));
for (auto &it : stat_replaced)
log("%8d %s\n", it.second, log_id(it.first));
log("%8d %s\n", it.second, it.first.unescape());
}
if (!stat_not_replaced.empty()) {
stat_not_replaced.sort();
log(" not replaced %d cell types:\n", GetSize(stat_not_replaced));
for (auto &it : stat_not_replaced)
log("%8d %s\n", it.second, log_id(it.first));
log("%8d %s\n", it.second, it.first.unescape());
}
for (auto cell : replaced_cells)

View file

@ -156,7 +156,7 @@ struct AlumaccWorker
if (!cell->type.in(ID($pos), ID($neg), ID($add), ID($sub), ID($mul)))
continue;
log(" creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type));
log(" creating $macc model for %s (%s).\n", cell, cell->type.unescape());
maccnode_t *n = new maccnode_t;
Macc::term_t new_term;
@ -267,7 +267,7 @@ struct AlumaccWorker
if (GetSize(other_n->y) != GetSize(n->y) && macc_may_overflow(other_n->macc, GetSize(other_n->y), port.is_signed))
continue;
log(" merging $macc model for %s into %s.\n", log_id(other_n->cell), log_id(n->cell));
log(" merging $macc model for %s into %s.\n", other_n->cell, n->cell);
bool do_subtract = port.do_subtract;
for (int j = 0; j < GetSize(other_n->macc.terms); j++) {
@ -351,7 +351,7 @@ struct AlumaccWorker
if (!subtract_b && B < A && GetSize(B))
std::swap(A, B);
log(" creating $alu model for $macc %s.\n", log_id(n->cell));
log(" creating $alu model for $macc %s.\n", n->cell);
alunode = new alunode_t;
alunode->cells.push_back(n->cell);
@ -383,7 +383,7 @@ struct AlumaccWorker
macc_counter++;
log(" creating $macc cell for %s: %s\n", log_id(n->cell), log_id(cell));
log(" creating $macc cell for %s: %s\n", n->cell, cell);
for (auto attr: n->cell->attributes) {
cell->attributes[attr.first] = attr.second;
@ -413,7 +413,7 @@ struct AlumaccWorker
for (auto cell : lge_cells)
{
log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type));
log(" creating $alu model for %s (%s):", cell, cell->type.unescape());
bool cmp_less = cell->type.in(ID($lt), ID($le));
bool cmp_equal = cell->type.in(ID($le), ID($ge));
@ -452,7 +452,7 @@ struct AlumaccWorker
sig_alu[RTLIL::SigSig(A, B)].insert(n);
log(" new $alu\n");
} else {
log(" merged with %s.\n", log_id(n->cells.front()));
log(" merged with %s.\n", n->cells.front());
}
n->cells.push_back(cell);
@ -485,7 +485,7 @@ struct AlumaccWorker
}
if (n != nullptr) {
log(" creating $alu model for %s (%s): merged with %s.\n", log_id(cell), log_id(cell->type), log_id(n->cells.front()));
log(" creating $alu model for %s (%s): merged with %s.\n", cell, cell->type.unescape(), n->cells.front());
n->cells.push_back(cell);
n->cmp.push_back(std::make_tuple(false, false, cmp_equal, !cmp_equal, false, Y));
}
@ -508,8 +508,8 @@ struct AlumaccWorker
log(" creating $pos cell for ");
for (int i = 0; i < GetSize(n->cells); i++)
log("%s%s", i ? ", ": "", log_id(n->cells[i]));
log(": %s\n", log_id(n->alu_cell));
log("%s%s", i ? ", ": "", n->cells[i]);
log(": %s\n", n->alu_cell);
goto delete_node;
}
@ -519,8 +519,8 @@ struct AlumaccWorker
log(" creating $alu cell for ");
for (int i = 0; i < GetSize(n->cells); i++)
log("%s%s", i ? ", ": "", log_id(n->cells[i]));
log(": %s\n", log_id(n->alu_cell));
log("%s%s", i ? ", ": "", n->cells[i]);
log(": %s\n", n->alu_cell);
if (n->cells.size() > 0) {
for (auto attr : n->cells[0]->attributes)
@ -569,7 +569,7 @@ struct AlumaccWorker
void run()
{
log("Extracting $alu and $macc cells in module %s:\n", log_id(module));
log("Extracting $alu and $macc cells in module %s:\n", module);
count_bit_users();
extract_macc();

View file

@ -0,0 +1,426 @@
/**
* Replaces chains of $add/$sub and $macc cells with carry-save adder trees
*
* Terminology:
* - parent: Cells that consume another cell's output
* - chainable: Adds/subs with no carry-out usage
* - chain: Connected path of chainable cells
*/
#include "kernel/macc.h"
#include "kernel/sigtools.h"
#include "kernel/wallace_tree.h"
#include "kernel/yosys.h"
#include <queue>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct Operand {
SigSpec sig;
bool is_signed;
bool negate;
};
struct Traversal {
SigMap sigmap;
dict<SigBit, pool<Cell *>> bit_consumers;
dict<SigBit, int> fanout;
Traversal(Module *module) : sigmap(module)
{
for (auto cell : module->cells())
for (auto &conn : cell->connections())
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
bit_consumers[bit].insert(cell);
for (auto &pair : bit_consumers)
fanout[pair.first] = pair.second.size();
for (auto wire : module->wires())
if (wire->port_output)
for (auto bit : sigmap(SigSpec(wire)))
fanout[bit]++;
}
};
struct Cells {
pool<Cell *> addsub;
pool<Cell *> alu;
pool<Cell *> macc;
static bool is_addsub(Cell *cell) { return cell->type == ID($add) || cell->type == ID($sub); }
static bool is_alu(Cell *cell) { return cell->type == ID($alu); }
static bool is_macc(Cell *cell) { return cell->type == ID($macc) || cell->type == ID($macc_v2); }
bool empty() { return addsub.empty() && alu.empty() && macc.empty(); }
Cells(Module *module)
{
for (auto cell : module->cells()) {
if (is_addsub(cell))
addsub.insert(cell);
else if (is_alu(cell))
alu.insert(cell);
else if (is_macc(cell))
macc.insert(cell);
}
}
};
struct AluInfo {
Cells &cells;
Traversal &traversal;
bool is_subtract(Cell *cell)
{
SigSpec bi = traversal.sigmap(cell->getPort(ID::BI));
SigSpec ci = traversal.sigmap(cell->getPort(ID::CI));
return GetSize(bi) == 1 && bi[0] == State::S1 && GetSize(ci) == 1 && ci[0] == State::S1;
}
bool is_add(Cell *cell)
{
SigSpec bi = traversal.sigmap(cell->getPort(ID::BI));
SigSpec ci = traversal.sigmap(cell->getPort(ID::CI));
return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0;
}
bool is_chainable(Cell *cell)
{
if (!(is_add(cell) || is_subtract(cell)))
return false;
for (auto bit : traversal.sigmap(cell->getPort(ID::X)))
if (traversal.fanout.count(bit) && traversal.fanout[bit] > 0)
return false;
for (auto bit : traversal.sigmap(cell->getPort(ID::CO)))
if (traversal.fanout.count(bit) && traversal.fanout[bit] > 0)
return false;
return true;
}
};
struct Rewriter {
Module *module;
Cells &cells;
Traversal traversal;
AluInfo alu_info;
Rewriter(Module *module, Cells &cells) : module(module), cells(cells), traversal(module), alu_info{cells, traversal} {}
Cell *sole_chainable_consumer(SigSpec sig, const pool<Cell *> &candidates)
{
Cell *consumer = nullptr;
for (auto bit : sig) {
if (!traversal.fanout.count(bit) || traversal.fanout[bit] != 1)
return nullptr;
if (!traversal.bit_consumers.count(bit) || traversal.bit_consumers[bit].size() != 1)
return nullptr;
Cell *c = *traversal.bit_consumers[bit].begin();
if (!candidates.count(c))
return nullptr;
if (consumer == nullptr)
consumer = c;
else if (consumer != c)
return nullptr;
}
return consumer;
}
dict<Cell *, Cell *> find_parents(const pool<Cell *> &candidates)
{
dict<Cell *, Cell *> parent_of;
for (auto cell : candidates) {
Cell *consumer = sole_chainable_consumer(traversal.sigmap(cell->getPort(ID::Y)), candidates);
if (consumer && consumer != cell)
parent_of[cell] = consumer;
}
return parent_of;
}
std::pair<dict<Cell *, pool<Cell *>>, pool<Cell *>> invert_parent_map(const dict<Cell *, Cell *> &parent_of)
{
dict<Cell *, pool<Cell *>> children_of;
pool<Cell *> has_parent;
for (auto &[child, parent] : parent_of) {
children_of[parent].insert(child);
has_parent.insert(child);
}
return {children_of, has_parent};
}
pool<Cell *> collect_chain(Cell *root, const dict<Cell *, pool<Cell *>> &children_of)
{
pool<Cell *> chain;
std::queue<Cell *> q;
q.push(root);
while (!q.empty()) {
Cell *cur = q.front();
q.pop();
if (!chain.insert(cur).second)
continue;
auto it = children_of.find(cur);
if (it != children_of.end())
for (auto child : it->second)
q.push(child);
}
return chain;
}
pool<SigBit> internal_bits(const pool<Cell *> &chain)
{
pool<SigBit> bits;
for (auto cell : chain)
for (auto bit : traversal.sigmap(cell->getPort(ID::Y)))
bits.insert(bit);
return bits;
}
static bool overlaps(SigSpec sig, const pool<SigBit> &bits)
{
for (auto bit : sig)
if (bits.count(bit))
return true;
return false;
}
bool feeds_subtracted_port(Cell *child, Cell *parent)
{
bool parent_subtracts;
if (parent->type == ID($sub))
parent_subtracts = true;
else if (cells.is_alu(parent))
parent_subtracts = alu_info.is_subtract(parent);
else
return false;
if (!parent_subtracts)
return false;
// Check if any bit of child's Y connects to parent's B
SigSpec child_y = traversal.sigmap(child->getPort(ID::Y));
SigSpec parent_b = traversal.sigmap(parent->getPort(ID::B));
for (auto bit : child_y)
for (auto pbit : parent_b)
if (bit == pbit)
return true;
return false;
}
std::vector<Operand> extract_chain_operands(const pool<Cell *> &chain, Cell *root, const dict<Cell *, Cell *> &parent_of, int &neg_compensation)
{
pool<SigBit> chain_bits = internal_bits(chain);
// Propagate negation flags through chain
dict<Cell *, bool> negated;
negated[root] = false;
{
std::queue<Cell *> q;
q.push(root);
while (!q.empty()) {
Cell *cur = q.front();
q.pop();
for (auto cell : chain) {
if (!parent_of.count(cell) || parent_of.at(cell) != cur)
continue;
if (negated.count(cell))
continue;
negated[cell] = negated[cur] ^ feeds_subtracted_port(cell, cur);
q.push(cell);
}
}
}
// Extract leaf operands
std::vector<Operand> operands;
neg_compensation = 0;
for (auto cell : chain) {
bool cell_neg = negated.count(cell) ? negated[cell] : false;
SigSpec a = traversal.sigmap(cell->getPort(ID::A));
SigSpec b = traversal.sigmap(cell->getPort(ID::B));
bool a_signed = cell->getParam(ID::A_SIGNED).as_bool();
bool b_signed = cell->getParam(ID::B_SIGNED).as_bool();
bool b_sub = (cell->type == ID($sub)) || (cells.is_alu(cell) && alu_info.is_subtract(cell));
// Only add operands not produced by other chain cells
if (!overlaps(a, chain_bits)) {
operands.push_back({a, a_signed, cell_neg});
if (cell_neg)
neg_compensation++;
}
if (!overlaps(b, chain_bits)) {
bool neg = cell_neg ^ b_sub;
operands.push_back({b, b_signed, neg});
if (neg)
neg_compensation++;
}
}
return operands;
}
bool extract_macc_operands(Cell *cell, std::vector<Operand> &operands, int &neg_compensation)
{
Macc macc(cell);
neg_compensation = 0;
for (auto &term : macc.terms) {
// Bail on multiplication
if (GetSize(term.in_b) != 0)
return false;
operands.push_back({term.in_a, term.is_signed, term.do_subtract});
if (term.do_subtract)
neg_compensation++;
}
return true;
}
SigSpec extend_operand(SigSpec sig, bool is_signed, int width)
{
if (GetSize(sig) < width) {
SigBit pad;
if (is_signed && GetSize(sig) > 0)
pad = sig[GetSize(sig) - 1];
else
pad = State::S0;
sig.append(SigSpec(pad, width - GetSize(sig)));
}
if (GetSize(sig) > width)
sig = sig.extract(0, width);
return sig;
}
void replace_with_carry_save_tree(std::vector<Operand> &operands, SigSpec result_y, int neg_compensation, const char *desc)
{
int width = GetSize(result_y);
std::vector<SigSpec> extended;
extended.reserve(operands.size() + 1);
for (auto &op : operands) {
SigSpec s = extend_operand(op.sig, op.is_signed, width);
if (op.negate)
s = module->Not(NEW_ID, s);
extended.push_back(s);
}
// Add correction for negated operands (-x = ~x + 1 so 1 per negation)
if (neg_compensation > 0)
extended.push_back(SigSpec(neg_compensation, width));
int compressor_count;
auto [a, b] = wallace_reduce_scheduled(module, extended, width, &compressor_count);
log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, compressor_count, (int)operands.size(), module);
// Emit final add
module->addAdd(NEW_ID, a, b, result_y, false);
}
void process_chains()
{
pool<Cell *> candidates;
for (auto cell : cells.addsub)
candidates.insert(cell);
for (auto cell : cells.alu)
if (alu_info.is_chainable(cell))
candidates.insert(cell);
if (candidates.empty())
return;
auto parent_of = find_parents(candidates);
auto [children_of, has_parent] = invert_parent_map(parent_of);
pool<Cell *> to_remove;
for (auto root : candidates) {
if (has_parent.count(root) || to_remove.count(root))
continue; // Not a tree root
pool<Cell *> chain = collect_chain(root, children_of);
if (chain.size() < 2)
continue;
int neg_compensation;
auto operands = extract_chain_operands(chain, root, parent_of, neg_compensation);
if (operands.size() < 3)
continue;
for (auto c : chain)
to_remove.insert(c);
replace_with_carry_save_tree(operands, root->getPort(ID::Y), neg_compensation, "Replaced add/sub chain");
}
for (auto cell : to_remove)
module->remove(cell);
}
void process_maccs()
{
for (auto cell : cells.macc) {
std::vector<Operand> operands;
int neg_compensation;
if (!extract_macc_operands(cell, operands, neg_compensation))
continue;
if (operands.size() < 3)
continue;
replace_with_carry_save_tree(operands, cell->getPort(ID::Y), neg_compensation, "Replaced $macc");
module->remove(cell);
}
}
};
void run(Module *module)
{
Cells cells(module);
if (cells.empty())
return;
Rewriter rewriter{module, cells};
rewriter.process_chains();
rewriter.process_maccs();
}
struct ArithTreePass : public Pass {
ArithTreePass() : Pass("arith_tree", "convert add/sub/macc chains to carry-save adder trees") {}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" arith_tree [selection]\n");
log("\n");
log("This pass replaces chains of $add/$sub cells, $alu cells (with constant\n");
log("BI/CI), and $macc/$macc_v2 cells (without multiplications) with carry-save\n");
log("adder trees using $fa cells and a single final $add.\n");
log("\n");
log("The tree uses Wallace-tree scheduling: at each level, ready operands are\n");
log("grouped into triplets and compressed via full adders, giving\n");
log("O(log_{1.5} N) depth for N input operands.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing ARITH_TREE pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
break;
extra_args(args, argidx, design);
for (auto module : design->selected_modules()) {
run(module);
}
}
} ArithTreePass;
PRIVATE_NAMESPACE_END

View file

@ -131,13 +131,13 @@ void attrmap_apply(string objname, vector<std::unique_ptr<AttrmapAction>> &actio
if (new_attr != attr)
log("Changed attribute on %s: %s=%s -> %s=%s\n", objname,
log_id(attr.first), log_const(attr.second), log_id(new_attr.first), log_const(new_attr.second));
attr.first.unescape(), log_const(attr.second), new_attr.first.unescape(), log_const(new_attr.second));
new_attributes[new_attr.first] = new_attr.second;
if (0)
delete_this_attr:
log("Removed attribute on %s: %s=%s\n", objname, log_id(attr.first), log_const(attr.second));
log("Removed attribute on %s: %s=%s\n", objname, attr.first.unescape(), log_const(attr.second));
}
attributes.swap(new_attributes);
@ -264,14 +264,14 @@ struct AttrmapPass : public Pass {
if (modattr_mode)
{
for (auto module : design->all_selected_whole_modules())
attrmap_apply(stringf("%s", log_id(module)), actions, module->attributes);
attrmap_apply(stringf("%s", module), actions, module->attributes);
}
else
{
for (auto module : design->all_selected_modules())
{
for (auto memb : module->selected_members())
attrmap_apply(stringf("%s.%s", log_id(module), log_id(memb)), actions, memb->attributes);
attrmap_apply(stringf("%s.%s", module, memb), actions, memb->attributes);
// attrmap already applied to process itself during above loop, but not its children
for (auto proc : module->selected_processes())
@ -280,10 +280,10 @@ struct AttrmapPass : public Pass {
while (!all_cases.empty()) {
RTLIL::CaseRule *cs = all_cases.back();
all_cases.pop_back();
attrmap_apply(stringf("%s.%s (case)", log_id(module), log_id(proc)), actions, cs->attributes);
attrmap_apply(stringf("%s.%s (case)", module, proc), actions, cs->attributes);
for (auto &sw : cs->switches) {
attrmap_apply(stringf("%s.%s (switch)", log_id(module), log_id(proc)), actions, sw->attributes);
attrmap_apply(stringf("%s.%s (switch)", module, proc), actions, sw->attributes);
all_cases.insert(all_cases.end(), sw->cases.begin(), sw->cases.end());
}
}
@ -328,7 +328,7 @@ struct ParamapPass : public Pass {
for (auto module : design->selected_modules())
for (auto cell : module->selected_cells())
attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->parameters);
attrmap_apply(stringf("%s.%s", module, cell), actions, cell->parameters);
}
} ParamapPass;

View file

@ -121,8 +121,8 @@ struct AttrmvcpPass : public Pass {
for (auto bit : sigmap(wire))
if (net2cells.count(bit))
for (auto cell : net2cells.at(bit)) {
log("Moving attribute %s=%s from %s.%s to %s.%s.\n", log_id(attr.first), log_const(attr.second),
log_id(module), log_id(wire), log_id(module), log_id(cell));
log("Moving attribute %s=%s from %s.%s to %s.%s.\n", attr.first.unescape(), log_const(attr.second),
module, wire, module, cell);
cell->attributes[attr.first] = attr.second;
did_something = true;
}

View file

@ -58,6 +58,7 @@ synth -top my_design -booth
#include "kernel/sigtools.h"
#include "kernel/yosys.h"
#include "kernel/macc.h"
#include "kernel/wallace_tree.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@ -223,7 +224,7 @@ struct BoothPassWorker {
macc.from_cell(cell);
if (!macc.is_simple_product()) {
log_debug("Not mapping cell %s: not a simple macc cell\n", log_id(cell));
log_debug("Not mapping cell %s: not a simple macc cell\n", cell);
continue;
}
@ -239,11 +240,11 @@ struct BoothPassWorker {
if (x_sz < 4 || y_sz < 4 || z_sz < 8) {
log_debug("Not mapping cell %s sized at %dx%x, %x: size below threshold\n",
log_id(cell), x_sz, y_sz, z_sz);
cell, x_sz, y_sz, z_sz);
continue;
}
log("Mapping cell %s to %s Booth multiplier\n", log_id(cell), is_signed ? "signed" : "unsigned");
log("Mapping cell %s to %s Booth multiplier\n", cell, is_signed ? "signed" : "unsigned");
// To simplify the generator size the arguments
// to be the same. Then allow logic synthesis to
@ -317,36 +318,6 @@ struct BoothPassWorker {
}
}
SigSig WallaceSum(int width, std::vector<SigSpec> summands)
{
for (auto &s : summands)
s.extend_u0(width);
while (summands.size() > 2) {
std::vector<SigSpec> new_summands;
int i;
for (i = 0; i < (int) summands.size() - 2; i += 3) {
SigSpec x = module->addWire(NEW_ID, width);
SigSpec y = module->addWire(NEW_ID, width);
BuildBitwiseFa(module, NEW_ID.str(), summands[i], summands[i + 1],
summands[i + 2], x, y);
new_summands.push_back(y);
new_summands.push_back({x.extract(0, width - 1), State::S0});
}
new_summands.insert(new_summands.begin(), summands.begin() + i, summands.end());
std::swap(summands, new_summands);
}
if (!summands.size())
return SigSig(SigSpec(width, State::S0), SigSpec(width, State::S0));
else if (summands.size() == 1)
return SigSig(summands[0], SigSpec(width, State::S0));
else
return SigSig(summands[0], summands[1]);
}
/*
Build Multiplier.
-------------------------
@ -415,16 +386,16 @@ struct BoothPassWorker {
// Later on yosys will clean up unused constants
// DebugDumpAlignPP(aligned_pp);
SigSig wtree_sum = WallaceSum(z_sz, aligned_pp);
auto [wtree_a, wtree_b] = wallace_reduce_scheduled(module, aligned_pp, z_sz);
// Debug code: Dump out the csa trees
// DumpCSATrees(debug_csa_trees);
// Build the CPA to do the final accumulation.
log_assert(wtree_sum.second[0] == State::S0);
log_assert(wtree_b[0] == State::S0);
if (mapped_cpa)
BuildCPA(module, wtree_sum.first, {State::S0, wtree_sum.second.extract_end(1)}, Z);
BuildCPA(module, wtree_a, wtree_b, Z);
else
module->addAdd(NEW_ID, wtree_sum.first, {wtree_sum.second.extract_end(1), State::S0}, Z);
module->addAdd(NEW_ID, wtree_a, wtree_b, Z);
}
/*

View file

@ -249,7 +249,7 @@ struct BufnormPass : public Pass {
for (auto module : design->selected_modules())
{
log("Buffer-normalizing module %s.\n", log_id(module));
log("Buffer-normalizing module %s.\n", module);
SigMap sigmap(module);
module->new_connections({});
@ -293,7 +293,7 @@ struct BufnormPass : public Pass {
bit2wires[keybit].insert(wire);
if (wire->port_input) {
log(" primary input: %s\n", log_id(wire));
log(" primary input: %s\n", wire);
for (auto bit : SigSpec(wire))
mapped_bits[sigmap(bit)] = bit;
} else {
@ -392,7 +392,7 @@ struct BufnormPass : public Pass {
if (w->name.isPublic())
log(" directly driven by cell %s port %s: %s\n",
log_id(cell), log_id(conn.first), log_id(w));
cell, conn.first.unescape(), w);
for (auto bit : SigSpec(w))
mapped_bits[sigmap(bit)] = bit;
@ -502,7 +502,7 @@ struct BufnormPass : public Pass {
if (conn.second != newsig) {
log(" fixing input signal on cell %s port %s: %s\n",
log_id(cell), log_id(conn.first), log_signal(newsig));
cell, conn.first.unescape(), log_signal(newsig));
cell->setPort(conn.first, newsig);
count_updated_cellports++;
}

View file

@ -20,7 +20,7 @@ SigSpec module_inputs(Module *m)
continue;
if (w->width != 1)
log_error("Unsupported wide port (%s) of non-unit width found in module %s.\n",
log_id(w), log_id(m));
w, m);
ret.append(w);
}
return ret;
@ -36,7 +36,7 @@ SigSpec module_outputs(Module *m)
continue;
if (w->width != 1)
log_error("Unsupported wide port (%s) of non-unit width found in module %s.\n",
log_id(w), log_id(m));
w, m);
ret.append(w);
}
return ret;
@ -96,7 +96,7 @@ bool derive_module_luts(Module *m, std::vector<uint64_t> &luts)
ff_types.setup_stdcells_mem();
for (auto cell : m->cells()) {
if (ff_types.cell_known(cell->type)) {
log("Ignoring module '%s' which isn't purely combinational.\n", log_id(m));
log("Ignoring module '%s' which isn't purely combinational.\n", m);
return false;
}
}
@ -106,7 +106,7 @@ bool derive_module_luts(Module *m, std::vector<uint64_t> &luts)
int ninputs = inputs.size(), noutputs = outputs.size();
if (ninputs > 6) {
log_warning("Skipping module %s with more than 6 inputs bits.\n", log_id(m));
log_warning("Skipping module %s with more than 6 inputs bits.\n", m);
return false;
}
@ -123,7 +123,7 @@ bool derive_module_luts(Module *m, std::vector<uint64_t> &luts)
if (!ceval.eval(bit)) {
log("Failed to evaluate output '%s' in module '%s'.\n",
log_signal(outputs[j]), log_id(m));
log_signal(outputs[j]), m);
return false;
}
@ -203,7 +203,7 @@ struct CellmatchPass : Pass {
for (auto lut : luts)
p_classes.insert(p_class(ninputs, lut));
log_debug("Registered %s\n", log_id(m));
log_debug("Registered %s\n", m);
// save as a viable target
targets[p_classes].push_back(Target{m, luts});
@ -237,7 +237,7 @@ struct CellmatchPass : Pass {
p_classes.insert(p_class(inputs.size(), lut));
for (auto target : targets[p_classes]) {
log_debug("Candidate %s for matching to %s\n", log_id(target.module), log_id(m));
log_debug("Candidate %s for matching to %s\n", target.module, m);
SigSpec target_inputs = module_inputs(target.module);
SigSpec target_outputs = module_outputs(target.module);
@ -271,10 +271,10 @@ struct CellmatchPass : Pass {
}
if (match) {
log("Module %s matches %s\n", log_id(m), log_id(target.module));
log("Module %s matches %s\n", m, target.module);
// Add target.module to map_design ("$cellmatch")
// as a techmap rule to match m and replace it with target.module
Module *map = map_design->addModule(stringf("\\_60_%s_%s", log_id(m), log_id(target.module)));
Module *map = map_design->addModule(stringf("\\_60_%s_%s", m, target.module));
Cell *cell = map->addCell(ID::_TECHMAP_REPLACE_, target.module->name);
map->attributes[ID(techmap_celltype)] = m->name.str();

View file

@ -257,14 +257,14 @@ struct ClkbufmapPass : public Pass {
RTLIL::Cell *cell = nullptr;
bool is_input = wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top);
if (!buf_celltype.empty() && (!is_input || buffer_inputs)) {
log("Inserting %s on %s.%s[%d].\n", buf_celltype, log_id(module), log_id(wire), i);
log("Inserting %s on %s.%s[%d].\n", buf_celltype, module, wire, i);
cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
iwire = module->addWire(NEW_ID);
cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
}
if (is_input) {
log("Inserting %s on %s.%s[%d].\n", inpad_celltype, log_id(module), log_id(wire), i);
log("Inserting %s on %s.%s[%d].\n", inpad_celltype, module, wire, i);
RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype));
if (iwire) {
cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);

View file

@ -415,6 +415,8 @@ struct ClockgatePass : public Pass {
FfData ff(nullptr, cell);
// It would be odd to get constants, but we better handle it
if (ff.has_ce) {
if (ff.has_srst && !ff.ce_over_srst)
continue;
if (!ff.sig_clk.is_bit() || !ff.sig_ce.is_bit())
continue;
if (!ff.sig_clk[0].is_wire() || !ff.sig_ce[0].is_wire())

View file

@ -71,6 +71,8 @@ struct ConstmapPass : public Pass {
}
extra_args(args, argidx, design);
if (celltype.empty())
log_cmd_error("Missing required option -cell.\n");
if (design->has(celltype)) {
Module *existing = design->module(celltype);

View file

@ -126,7 +126,7 @@ struct DeminoutPass : public Pass {
}
if (new_input != new_output) {
log("Demoting inout port %s.%s to %s.\n", log_id(module), log_id(wire), new_input ? "input" : "output");
log("Demoting inout port %s.%s to %s.\n", module, wire, new_input ? "input" : "output");
wire->port_input = new_input;
wire->port_output = new_output;
keep_running = true;

View file

@ -123,14 +123,14 @@ struct DffinitPass : public Pass {
if (noreinit && value[i] != State::Sx && value[i] != initval[i])
log_error("Trying to assign a different init value for %s.%s.%s which technically "
"have a conflicted init value.\n",
log_id(module), log_id(cell), log_id(it.second));
module, cell, it.second.unescape());
value.set(i, initval[i]);
}
if (highlow_mode && GetSize(value) != 0) {
if (GetSize(value) != 1)
log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n",
log_id(module), log_id(cell), log_id(it.second));
module, cell, it.second.unescape());
if (value[0] == State::S1)
value = Const(high_string);
else
@ -138,8 +138,8 @@ struct DffinitPass : public Pass {
}
if (value.size() != 0) {
log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second),
log_id(it.first), log_signal(sig), log_signal(value));
log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", module, cell, it.second.unescape(),
it.first.unescape(), log_signal(sig), log_signal(value));
cell->setParam(it.second, value);
}
}

View file

@ -263,7 +263,7 @@ struct DffLegalizePass : public Pass {
}
void fail_ff(const FfData &ff, const char *reason) {
log_error("FF %s.%s (type %s) cannot be legalized: %s\n", log_id(ff.module->name), log_id(ff.cell->name), log_id(ff.cell->type), reason);
log_error("FF %s.%s (type %s) cannot be legalized: %s\n", ff.module->name.unescape(), ff.cell->name.unescape(), ff.cell->type.unescape(), reason);
}
bool try_flip(FfData &ff, int supported_mask) {
@ -381,7 +381,7 @@ struct DffLegalizePass : public Pass {
if (ff.has_ce && !supported_cells[FF_ADFFE])
ff.unmap_ce();
log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name));
log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape());
log_assert(ff.width == 1);
ff.remove();
@ -600,7 +600,7 @@ struct DffLegalizePass : public Pass {
ff.unmap_ce();
if (ff.cell)
log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name));
log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape());
emulate_split_init_arst(ff);
return;
}
@ -752,7 +752,7 @@ struct DffLegalizePass : public Pass {
// The only hope left is breaking down to adlatch + dlatch + dlatch + mux.
if (ff.cell)
log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name));
log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape());
ff.remove();
emulate_split_init_arst(ff);

View file

@ -155,12 +155,12 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports,
std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref;
if (sel && !sel->selected(mod)) {
log(" Skipping module %s as it is not selected.\n", log_id(mod->name));
log(" Skipping module %s as it is not selected.\n", mod->name.unescape());
return false;
}
if (mod->processes.size() > 0) {
log(" Skipping module %s as it contains unprocessed processes.\n", log_id(mod->name));
log(" Skipping module %s as it contains unprocessed processes.\n", mod->name.unescape());
return false;
}
@ -626,7 +626,7 @@ struct ExtractPass : public Pass {
if (!mine_mode)
for (auto module : map->modules()) {
SubCircuit::Graph mod_graph;
std::string graph_name = "needle_" + RTLIL::unescape_id(module->name);
std::string graph_name = "needle_" + module->name.unescape();
log("Creating needle graph %s.\n", graph_name);
if (module2graph(mod_graph, module, constports)) {
solver.addGraph(graph_name, mod_graph);
@ -637,7 +637,7 @@ struct ExtractPass : public Pass {
for (auto module : design->modules()) {
SubCircuit::Graph mod_graph;
std::string graph_name = "haystack_" + RTLIL::unescape_id(module->name);
std::string graph_name = "haystack_" + module->name.unescape();
log("Creating haystack graph %s.\n", graph_name);
if (module2graph(mod_graph, module, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : nullptr)) {
solver.addGraph(graph_name, mod_graph);
@ -654,8 +654,8 @@ struct ExtractPass : public Pass {
for (auto needle : needle_list)
for (auto &haystack_it : haystack_map) {
log("Solving for %s in %s.\n", ("needle_" + RTLIL::unescape_id(needle->name)), haystack_it.first);
solver.solve(results, "needle_" + RTLIL::unescape_id(needle->name), haystack_it.first, false);
log("Solving for %s in %s.\n", ("needle_" + needle->name.unescape()), haystack_it.first);
solver.solve(results, "needle_" + needle->name.unescape(), haystack_it.first, false);
}
log("Found %d matches.\n", GetSize(results));
@ -674,7 +674,7 @@ struct ExtractPass : public Pass {
}
RTLIL::Cell *new_cell = replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result);
design->select(haystack_map.at(result.haystackGraphId), new_cell);
log(" new cell: %s\n", log_id(new_cell->name));
log(" new cell: %s\n", new_cell->name.unescape());
}
}
}
@ -691,12 +691,12 @@ struct ExtractPass : public Pass {
for (auto &result: results)
{
log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
log(" primary match in %s:", log_id(haystack_map.at(result.graphId)->name));
log(" primary match in %s:", haystack_map.at(result.graphId)->name.unescape());
for (auto &node : result.nodes)
log(" %s", RTLIL::unescape_id(node.nodeId));
log("\n");
for (auto &it : result.matchesPerGraph)
log(" matches in %s: %d\n", log_id(haystack_map.at(it.first)->name), it.second);
log(" matches in %s: %d\n", haystack_map.at(it.first)->name.unescape(), it.second);
RTLIL::Module *mod = haystack_map.at(result.graphId);
std::set<RTLIL::Cell*> cells;
@ -716,7 +716,7 @@ struct ExtractPass : public Pass {
}
RTLIL::Module *newMod = new RTLIL::Module;
newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, log_id(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits);
newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, haystack_map.at(result.graphId)->name.unescape(), result.totalMatchesAfterLimits);
map->add(newMod);
for (auto wire : wires) {

View file

@ -541,7 +541,7 @@ void counter_worker(
{
extract_value = *sa.begin();
log(" Signal %s declared at %s has COUNT_EXTRACT = %s\n",
log_id(port_wire),
port_wire,
count_reg_src.c_str(),
extract_value.c_str());
@ -604,14 +604,14 @@ void counter_worker(
{
log_error(
"Counter extraction is set to FORCE on register %s, but a counter could not be inferred (%s)\n",
log_id(port_wire),
port_wire,
reasons[reason]);
}
return;
}
//Get new cell name
string countname = string("$COUNTx$") + log_id(extract.rwire->name.str());
string countname = string("$COUNTx$") + extract.rwire->name.unescape();
//Wipe all of the old connections to the ALU
cell->unsetPort(ID::A);
@ -697,7 +697,7 @@ void counter_worker(
//Hook up any parallel outputs
for(auto load : extract.pouts)
{
log(" Counter has parallel output to cell %s port %s\n", log_id(load.cell->name), log_id(load.port));
log(" Counter has parallel output to cell %s port %s\n", load.cell->name.unescape(), load.port.unescape());
}
if(extract.has_pout)
{
@ -731,7 +731,7 @@ void counter_worker(
countname.c_str(),
extract.count_is_up ? "to" : "from",
extract.count_value,
log_id(extract.rwire->name),
extract.rwire->name.unescape(),
count_reg_src.c_str());
//Optimize the counter
@ -887,13 +887,13 @@ struct ExtractCounterPass : public Pass {
for(auto cell : cells_to_remove)
{
//log("Removing cell %s\n", log_id(cell->name));
//log("Removing cell %s\n", cell);
module->remove(cell);
}
for(auto cpair : cells_to_rename)
{
//log("Renaming cell %s to %s\n", log_id(cpair.first->name), cpair.second);
//log("Renaming cell %s to %s\n", cpair.first, cpair.second);
module->rename(cpair.first, cpair.second);
}
}

View file

@ -289,7 +289,7 @@ struct ExtractFaWorker
void run()
{
log("Extracting full/half adders from %s:\n", log_id(module));
log("Extracting full/half adders from %s:\n", module);
for (auto it : driver)
{
@ -381,7 +381,7 @@ struct ExtractFaWorker
auto &fa = facache.at(fakey);
X = get<0>(fa);
Y = get<1>(fa);
log(" Reusing $fa cell %s.\n", log_id(get<2>(fa)));
log(" Reusing $fa cell %s.\n", get<2>(fa));
}
else
if (facache.count(fakey_inv))
@ -390,14 +390,14 @@ struct ExtractFaWorker
invert_xy = true;
X = get<0>(fa);
Y = get<1>(fa);
log(" Reusing $fa cell %s.\n", log_id(get<2>(fa)));
log(" Reusing $fa cell %s.\n", get<2>(fa));
}
else
{
Cell *cell = module->addCell(NEW_ID, ID($fa));
cell->setParam(ID::WIDTH, 1);
log(" Created $fa cell %s.\n", log_id(cell));
log(" Created $fa cell %s.\n", cell);
cell->setPort(ID::A, f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
cell->setPort(ID::B, f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
@ -488,7 +488,7 @@ struct ExtractFaWorker
auto &fa = facache.at(fakey);
X = get<0>(fa);
Y = get<1>(fa);
log(" Reusing $fa cell %s.\n", log_id(get<2>(fa)));
log(" Reusing $fa cell %s.\n", get<2>(fa));
}
else
if (facache.count(fakey_inv))
@ -497,14 +497,14 @@ struct ExtractFaWorker
invert_xy = true;
X = get<0>(fa);
Y = get<1>(fa);
log(" Reusing $fa cell %s.\n", log_id(get<2>(fa)));
log(" Reusing $fa cell %s.\n", get<2>(fa));
}
else
{
Cell *cell = module->addCell(NEW_ID, ID($fa));
cell->setParam(ID::WIDTH, 1);
log(" Created $fa cell %s.\n", log_id(cell));
log(" Created $fa cell %s.\n", cell);
cell->setPort(ID::A, f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
cell->setPort(ID::B, f2i.inv_b ? module->NotGate(NEW_ID, B) : B);

View file

@ -100,7 +100,7 @@ struct ExtractinvPass : public Pass {
continue;
SigSpec sig = port.second;
if (it2->second.size() != sig.size())
log_error("The inversion parameter needs to be the same width as the port (%s.%s port %s parameter %s)", log_id(module->name), log_id(cell->type), log_id(port.first), log_id(param_name));
log_error("The inversion parameter needs to be the same width as the port (%s.%s port %s parameter %s)", module->name.unescape(), cell->type.unescape(), port.first.unescape(), param_name.unescape());
RTLIL::Const invmask = it2->second;
cell->parameters.erase(param_name);
if (invmask.is_fully_zero())
@ -111,7 +111,7 @@ struct ExtractinvPass : public Pass {
RTLIL::Cell *icell = module->addCell(NEW_ID, RTLIL::escape_id(inv_celltype));
icell->setPort(RTLIL::escape_id(inv_portname), SigSpec(iwire, i));
icell->setPort(RTLIL::escape_id(inv_portname2), sig[i]);
log("Inserting %s on %s.%s.%s[%d].\n", inv_celltype, log_id(module), log_id(cell->type), log_id(port.first), i);
log("Inserting %s on %s.%s.%s[%d].\n", inv_celltype, module, cell->type.unescape(), port.first.unescape(), i);
sig[i] = SigBit(iwire, i);
}
cell->setPort(port.first, sig);

View file

@ -598,7 +598,7 @@ struct FlowmapWorker
continue;
if (!cell->known())
log_error("Cell %s (%s.%s) is unknown.\n", cell->type, log_id(module), log_id(cell));
log_error("Cell %s (%s.%s) is unknown.\n", cell->type, module, cell);
pool<RTLIL::SigBit> fanout;
for (auto conn : cell->connections())
@ -636,7 +636,7 @@ struct FlowmapWorker
if (fanin > order)
log_error("Cell %s (%s.%s) with fan-in %d cannot be mapped to a %d-LUT.\n",
cell->type.c_str(), log_id(module), log_id(cell), fanin, order);
cell->type.c_str(), module, cell, fanin, order);
gate_count++;
gate_area += 1 << fanin;
@ -1246,14 +1246,14 @@ struct FlowmapWorker
}
}
log(" Breaking LUT %s to %s LUT %s (potential %d).\n",
log_signal(breaking_lut), lut_nodes[breaking_gate] ? "reuse" : "extract", log_signal(breaking_gate), best_potential);
log_signal(breaking_lut), lut_nodes[breaking_gate] ? "reuse" : "extract", log_signal(breaking_gate), best_potential);
if (debug_relax)
log(" Removing breaking gate %s from LUT.\n", log_signal(breaking_gate));
lut_gates[breaking_lut].erase(breaking_gate);
auto cut_inputs = cut_lut_at_gate(breaking_lut, breaking_gate);
pool<RTLIL::SigBit> gate_inputs = cut_inputs.first, other_inputs = cut_inputs.second;
pool<RTLIL::SigBit> gate_inputs = cut_inputs.first;
pool<RTLIL::SigBit> worklist = lut_gates[breaking_lut];
pool<RTLIL::SigBit> elim_gates = gate_inputs;
@ -1356,14 +1356,14 @@ struct FlowmapWorker
auto origin = node_origins[node];
if (origin.cell->getPort(origin.port).size() == 1)
log("Packing %s.%s.%s (%s).\n",
log_id(module), log_id(origin.cell), origin.port.c_str(), log_signal(node));
module, origin.cell, origin.port.c_str(), log_signal(node));
else
log("Packing %s.%s.%s [%d] (%s).\n",
log_id(module), log_id(origin.cell), origin.port.c_str(), origin.offset, log_signal(node));
module, origin.cell, origin.port.c_str(), origin.offset, log_signal(node));
}
else
{
log("Packing %s.%s.\n", log_id(module), log_signal(node));
log("Packing %s.%s.\n", module, log_signal(node));
}
for (auto gate_node : lut_gates[node])
@ -1376,10 +1376,10 @@ struct FlowmapWorker
auto gate_origin = node_origins[gate_node];
if (gate_origin.cell->getPort(gate_origin.port).size() == 1)
log(" Packing %s.%s.%s (%s).\n",
log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), log_signal(gate_node));
module, gate_origin.cell, gate_origin.port.c_str(), log_signal(gate_node));
else
log(" Packing %s.%s.%s [%d] (%s).\n",
log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node));
module, gate_origin.cell, gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node));
}
vector<RTLIL::SigBit> input_nodes(lut_edges_bw[node].begin(), lut_edges_bw[node].end());
@ -1423,9 +1423,9 @@ struct FlowmapWorker
lut_area += lut_table.size();
if ((int)input_nodes.size() >= minlut)
log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), log_id(module), log_id(lut));
log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), module, lut);
else
log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), log_id(module), log_id(lut), minlut);
log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), module, lut, minlut);
}
for (auto node : mapped_nodes)

View file

@ -83,7 +83,7 @@ struct InsbufPass : public Pass {
if (!lhs.wire || !design->selected(module, lhs.wire)) {
new_conn.first.append(lhs);
new_conn.second.append(rhs);
log("Skip %s: %s -> %s\n", log_id(module), log_signal(rhs), log_signal(lhs));
log("Skip %s: %s -> %s\n", module, log_signal(rhs), log_signal(lhs));
continue;
}
@ -98,7 +98,7 @@ struct InsbufPass : public Pass {
cell->setPort(in_portname, rhs);
cell->setPort(out_portname, lhs);
log("Add %s/%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs));
log("Add %s/%s: %s -> %s\n", module, cell, log_signal(rhs), log_signal(lhs));
bufcells.insert(cell);
}
@ -115,8 +115,8 @@ struct InsbufPass : public Pass {
auto s = sigmap(port.second);
if (s == port.second)
continue;
log("Rewrite %s/%s/%s: %s -> %s\n", log_id(module), log_id(cell),
log_id(port.first), log_signal(port.second), log_signal(s));
log("Rewrite %s/%s/%s: %s -> %s\n", module, cell,
port.first.unescape(), log_signal(port.second), log_signal(s));
cell->setPort(port.first, s);
}
}

View file

@ -231,7 +231,7 @@ struct IopadmapPass : public Pass {
for (int i = 0; i < GetSize(wire); i++)
if (buf_bits.count(sigmap(SigBit(wire, i)))) {
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
log("Marking already mapped port: %s.%s[%d].\n", log_id(module), log_id(wire), i);
log("Marking already mapped port: %s.%s[%d].\n", module, wire, i);
}
}
@ -324,10 +324,10 @@ struct IopadmapPass : public Pass {
if (wire->port_input)
{
log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype);
log("Mapping port %s.%s[%d] using %s.\n", module, wire, i, tinoutpad_celltype);
Cell *cell = module->addCell(
module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
module->uniquify(stringf("$iopadmap$%s.%s[%d]", module, wire, i)),
RTLIL::escape_id(tinoutpad_celltype));
if (tinoutpad_neg_oe)
@ -348,10 +348,10 @@ struct IopadmapPass : public Pass {
if (!tinoutpad_portname_pad.empty())
rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad));
} else {
log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype);
log("Mapping port %s.%s[%d] using %s.\n", module, wire, i, toutpad_celltype);
Cell *cell = module->addCell(
module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
module->uniquify(stringf("$iopadmap$%s.%s[%d]", module, wire, i)),
RTLIL::escape_id(toutpad_celltype));
if (toutpad_neg_oe)
@ -389,7 +389,7 @@ struct IopadmapPass : public Pass {
if (wire->port_input && !wire->port_output) {
if (inpad_celltype.empty()) {
log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
log("Don't map input port %s.%s: Missing option -inpad.\n", module, wire);
continue;
}
celltype = inpad_celltype;
@ -398,7 +398,7 @@ struct IopadmapPass : public Pass {
} else
if (!wire->port_input && wire->port_output) {
if (outpad_celltype.empty()) {
log("Don't map output port %s.%s: Missing option -outpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
log("Don't map output port %s.%s: Missing option -outpad.\n", module, wire);
continue;
}
celltype = outpad_celltype;
@ -407,7 +407,7 @@ struct IopadmapPass : public Pass {
} else
if (wire->port_input && wire->port_output) {
if (inoutpad_celltype.empty()) {
log("Don't map inout port %s.%s: Missing option -inoutpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
log("Don't map inout port %s.%s: Missing option -inoutpad.\n", module, wire);
continue;
}
celltype = inoutpad_celltype;
@ -417,11 +417,11 @@ struct IopadmapPass : public Pass {
log_abort();
if (!flag_bits && wire->width != 1 && widthparam.empty()) {
log("Don't map multi-bit port %s.%s: Missing option -widthparam or -bits.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
log("Don't map multi-bit port %s.%s: Missing option -widthparam or -bits.\n", module, wire);
continue;
}
log("Mapping port %s.%s using %s.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name), celltype);
log("Mapping port %s.%s using %s.\n", module, wire, celltype);
if (flag_bits)
{
@ -433,7 +433,7 @@ struct IopadmapPass : public Pass {
SigBit wire_bit(wire, i);
RTLIL::Cell *cell = module->addCell(
module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))),
module->uniquify(stringf("$iopadmap$%s.%s", module->name.unescape(), wire->name.unescape())),
RTLIL::escape_id(celltype));
cell->setPort(RTLIL::escape_id(portname_int), wire_bit);
@ -442,21 +442,21 @@ struct IopadmapPass : public Pass {
if (!widthparam.empty())
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);
if (!nameparam.empty())
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(stringf("%s[%d]", RTLIL::id2cstr(wire->name), i));
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(stringf("%s[%d]", wire, i));
cell->attributes[ID::keep] = RTLIL::Const(1);
}
}
else
{
RTLIL::Cell *cell = module->addCell(
module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))),
module->uniquify(stringf("$iopadmap$%s.%s", module->name.unescape(), wire->name.unescape())),
RTLIL::escape_id(celltype));
cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire));
if (!portname_pad.empty()) {
RTLIL::Wire *new_wire = NULL;
new_wire = module->addWire(
module->uniquify(stringf("$iopadmap$%s", log_id(wire))),
module->uniquify(stringf("$iopadmap$%s", wire)),
wire);
module->swap_names(new_wire, wire);
wire->attributes.clear();
@ -465,7 +465,7 @@ struct IopadmapPass : public Pass {
if (!widthparam.empty())
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
if (!nameparam.empty())
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(RTLIL::id2cstr(wire->name));
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(wire->name.unescape());
cell->attributes[ID::keep] = RTLIL::Const(1);
}
@ -500,7 +500,7 @@ struct IopadmapPass : public Pass {
for (auto &it : rewrite_bits) {
RTLIL::Wire *wire = it.first;
RTLIL::Wire *new_wire = module->addWire(
module->uniquify(stringf("$iopadmap$%s", log_id(wire))),
module->uniquify(stringf("$iopadmap$%s", wire)),
wire);
module->swap_names(new_wire, wire);
wire->attributes.clear();

View file

@ -0,0 +1,145 @@
#ifndef LIBERTY_CACHE_H
#define LIBERTY_CACHE_H
#include "kernel/yosys.h"
#ifdef YOSYS_LINK_ABC
namespace abc {
int Abc_RealMain(int argc, char *argv[]);
}
#endif
YOSYS_NAMESPACE_BEGIN
/*
* convert_liberty_files_to_merged_scl() - Convert multiple Liberty files to a single merged SCL cache file.
* @liberty_files: Vector of liberty file paths to merge
* @dont_use_args: Pre-built ABC -X flags string
* @abc_exe: Path to ABC executable for conversion
*
* Return: Path to merged SCL cache file, or empty string if conversion fails
*/
inline std::string convert_liberty_files_to_merged_scl(const std::vector<std::string> &liberty_files, const std::string &dont_use_args, const std::string &abc_exe)
{
if (liberty_files.empty())
return "";
std::string cache_dir = get_base_tmpdir() + "/yosys-liberty-scl-cache";
if (!create_directory(cache_dir)) {
log_warning("ABC: cannot create cache directory %s, falling back to liberty format\n", cache_dir.c_str());
return "";
}
// Sort to ensure consistent hash regardless of order
std::vector<std::string> sorted_files = liberty_files;
std::sort(sorted_files.begin(), sorted_files.end());
std::string hash_input;
time_t newest_mtime = 0;
for (const std::string &liberty_file : sorted_files) {
struct stat liberty_stat;
if (stat(liberty_file.c_str(), &liberty_stat) != 0) {
log_error("ABC: cannot stat liberty file: %s\n", liberty_file.c_str());
return "";
}
hash_input += liberty_file + "|";
if (liberty_stat.st_mtime > newest_mtime)
newest_mtime = liberty_stat.st_mtime;
}
hash_input += dont_use_args;
unsigned int hash = 0;
for (char c : hash_input)
hash = hash * 31 + c;
std::string merged_scl = stringf("%s/yosys_merged_%08x.scl", cache_dir.c_str(), hash);
bool need_convert = true;
struct stat scl_stat;
// Check if merged SCL exists and is newer than all liberty files
if (stat(merged_scl.c_str(), &scl_stat) == 0) {
if (scl_stat.st_mtime >= newest_mtime) {
log("ABC: using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size());
need_convert = false;
}
}
if (need_convert) {
// read_lib -X cell1 -X cell2 file1 ; read_lib -X cell1 -X cell2 -m file2 ; ... ; write_scl merged.scl
std::string temp_scl = merged_scl + ".tmp";
#ifdef YOSYS_LINK_ABC
std::string script_path = stringf("%s/yosys_merged_scl_convert_%08x.script", cache_dir.c_str(), hash);
FILE *f = fopen(script_path.c_str(), "w");
if (f == NULL) {
log_warning("ABC: cannot open %s for writing, falling back to liberty format\n", script_path.c_str());
return "";
}
bool first = true;
for (const std::string &liberty_file : liberty_files) {
fprintf(f, "read_lib %s%s-w \"%s\"\n", dont_use_args.c_str(), first ? "" : "-m ", liberty_file.c_str());
first = false;
}
fprintf(f, "write_scl \"%s\"\n", temp_scl.c_str());
fclose(f);
char *abc_argv[5];
abc_argv[0] = strdup(abc_exe.empty() ? "yosys-abc" : abc_exe.c_str());
abc_argv[1] = strdup("-s");
abc_argv[2] = strdup("-f");
abc_argv[3] = strdup(script_path.c_str());
abc_argv[4] = 0;
int ret = abc::Abc_RealMain(4, abc_argv);
free(abc_argv[0]);
free(abc_argv[1]);
free(abc_argv[2]);
free(abc_argv[3]);
remove(script_path.c_str());
if (ret != 0) {
log_warning("ABC: merged SCL conversion failed (ret=%d), falling back to liberty format\n", ret);
remove(temp_scl.c_str());
return "";
}
#else
std::string abc_script;
bool first = true;
for (const std::string &liberty_file : liberty_files) {
abc_script += stringf("read_lib %s%s-w \\\"%s\\\" ; ", dont_use_args.c_str(), first ? "" : "-m ", liberty_file.c_str());
first = false;
}
abc_script += stringf("write_scl \\\"%s\\\"", temp_scl.c_str());
std::string cmd = stringf("\"%s\" -c \"%s\" 2>&1", abc_exe.c_str(), abc_script.c_str());
std::string abc_output;
int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; });
if (ret != 0) {
log_warning("ABC: merged SCL conversion failed, falling back to liberty format\n");
if (!abc_output.empty()) {
log("ABC: conversion output:\n%s", abc_output.c_str());
}
remove(temp_scl.c_str());
return "";
}
#endif
if (rename(temp_scl.c_str(), merged_scl.c_str()) != 0) {
log_warning("ABC: failed to rename %s to %s, falling back to liberty format\n", temp_scl.c_str(), merged_scl.c_str());
remove(temp_scl.c_str());
return "";
}
}
return merged_scl;
}
YOSYS_NAMESPACE_END
#endif // LIBERTY_CACHE_H

View file

@ -49,7 +49,7 @@ struct Lut2BmuxPass : public Pass {
cell->setPort(ID::A, cell->getParam(ID::LUT));
cell->unsetParam(ID::LUT);
cell->fixup_parameters();
log("Converted %s.%s to BMUX cell.\n", log_id(module), log_id(cell));
log("Converted %s.%s to BMUX cell.\n", module, cell);
}
}
}

View file

@ -97,7 +97,7 @@ struct Lut2muxPass : public Pass {
if (cell->type == ID($lut)) {
IdString cell_name = cell->name;
int count = lut2mux(cell, word_mode);
log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count);
log("Converted %s.%s to %d MUX cells.\n", module, cell_name.unescape(), count);
}
}
}

View file

@ -404,7 +404,7 @@ struct MaccmapPass : public Pass {
for (auto mod : design->selected_modules())
for (auto cell : mod->selected_cells())
if (cell->type.in(ID($macc), ID($macc_v2))) {
log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
log("Mapping %s.%s (%s).\n", mod, cell, cell->type.unescape());
maccmap(mod, cell, unmap_mode);
mod->remove(cell);
}

View file

@ -596,7 +596,7 @@ struct MuxcoverWorker
void run()
{
log("Covering MUX trees in module %s..\n", log_id(module));
log("Covering MUX trees in module %s..\n", module);
treeify();

View file

@ -284,7 +284,7 @@ struct ShregmapWorker
Cell *last_cell = chain[cursor+depth-1];
log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n",
log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth);
module, first_cell, module, last_cell, depth);
dff_count += depth;
shreg_count += 1;

View file

@ -443,6 +443,48 @@ void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell)
}
}
void simplemap_pmux(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_s = cell->getPort(ID::S);
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
int width = GetSize(sig_a);
int s_width = GetSize(sig_s);
// Implement: |S
RTLIL::SigSpec any_s = sig_s;
logic_reduce(module, any_s, cell);
for (int i = 0; i < width; i++) {
RTLIL::SigSpec b_and_bits;
// Implement: B_AND_BITS = B_AND_S[WIDTH*j+i]
for (int j = 0; j < s_width; j++) {
RTLIL::Cell *and_gate = module->addCell(NEW_ID, ID($_AND_));
transfer_src(and_gate, cell);
and_gate->setPort(ID::A, sig_b[j * width + i]);
and_gate->setPort(ID::B, sig_s[j]);
RTLIL::SigSpec and_y = module->addWire(NEW_ID, 1);
and_gate->setPort(ID::Y, and_y);
b_and_bits.append(and_y);
}
// Implement: Y_B[i] = |B_AND_BITS
logic_reduce(module, b_and_bits, cell);
// Implement: Y[i] = |S ? Y_B[i] : A[i]
RTLIL::Cell *mux_gate = module->addCell(NEW_ID, ID($_MUX_));
transfer_src(mux_gate, cell);
mux_gate->setPort(ID::A, sig_a[i]);
mux_gate->setPort(ID::B, b_and_bits);
mux_gate->setPort(ID::S, any_s);
mux_gate->setPort(ID::Y, sig_y[i]);
}
}
void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
{
mappers[ID($not)] = simplemap_not;
@ -466,6 +508,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
mappers[ID($ne)] = simplemap_eqne;
mappers[ID($nex)] = simplemap_eqne;
mappers[ID($mux)] = simplemap_mux;
mappers[ID($pmux)] = simplemap_pmux;
mappers[ID($bwmux)] = simplemap_bwmux;
mappers[ID($tribuf)] = simplemap_tribuf;
mappers[ID($bmux)] = simplemap_bmux;
@ -520,7 +563,7 @@ struct SimplemapPass : public Pass {
log("\n");
log(" $not, $pos, $and, $or, $xor, $xnor\n");
log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n");
log(" $logic_not, $logic_and, $logic_or, $mux, $pmux, $tribuf\n");
log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff,\n");
log(" $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n");
log("\n");
@ -542,7 +585,7 @@ struct SimplemapPass : public Pass {
continue;
if (!design->selected(mod, cell))
continue;
log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
log("Mapping %s.%s (%s).\n", mod, cell, cell->type.unescape());
mappers.at(cell->type)(mod, cell);
mod->remove(cell);
}

View file

@ -93,17 +93,17 @@ struct TechmapWorker
RTLIL::SigBit bit = sigmap(conn.second[i]);
if (bit.wire == nullptr) {
if (verbose)
log(" Constant input on bit %d of port %s: %s\n", i, log_id(conn.first), log_signal(bit));
constmap_info += stringf("|%s %d %d", log_id(conn.first), i, bit.data);
log(" Constant input on bit %d of port %s: %s\n", i, conn.first.unescape(), log_signal(bit));
constmap_info += stringf("|%s %d %d", conn.first.unescape(), i, bit.data);
} else if (connbits_map.count(bit)) {
if (verbose)
log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, log_id(conn.first),
connbits_map.at(bit).second, log_id(connbits_map.at(bit).first));
constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i,
log_id(connbits_map.at(bit).first), connbits_map.at(bit).second);
log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, conn.first.unescape(),
connbits_map.at(bit).second, connbits_map.at(bit).first.unescape());
constmap_info += stringf("|%s %d %s %d", conn.first.unescape(), i,
connbits_map.at(bit).first.unescape(), connbits_map.at(bit).second);
} else {
connbits_map.emplace(bit, std::make_pair(conn.first, i));
constmap_info += stringf("|%s %d", log_id(conn.first), i);
constmap_info += stringf("|%s %d", conn.first.unescape(), i);
}
}
@ -146,7 +146,7 @@ struct TechmapWorker
if (tpl->processes.size() != 0) {
log("Technology map yielded processes:");
for (auto &it : tpl->processes)
log(" %s",log_id(it.first));
log(" %s",it.first.unescape());
log("\n");
if (autoproc_mode) {
Pass::call_on_module(tpl->design, tpl, "proc");
@ -444,7 +444,7 @@ struct TechmapWorker
if (celltypeMap.count(cell->type) == 0) {
if (assert_mode && !cell->type.ends_with("_"))
log_error("(ASSERT MODE) No matching template cell for type %s found.\n", log_id(cell->type));
log_error("(ASSERT MODE) No matching template cell for type %s found.\n", cell->type.unescape());
continue;
}
@ -507,10 +507,10 @@ struct TechmapWorker
{
if ((extern_mode && !in_recursion) || extmapper_name == "wrap")
{
std::string m_name = stringf("$extern:%s:%s", extmapper_name, log_id(cell->type));
std::string m_name = stringf("$extern:%s:%s", extmapper_name, cell->type.unescape());
for (auto &c : cell->parameters)
m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second));
m_name += stringf(":%s=%s", c.first.unescape(), log_signal(c.second));
if (extmapper_name == "wrap")
m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string());
@ -541,24 +541,24 @@ struct TechmapWorker
extmapper_module->check();
if (extmapper_name == "simplemap") {
log("Creating %s with simplemap.\n", log_id(extmapper_module));
log("Creating %s with simplemap.\n", extmapper_module);
if (simplemap_mappers.count(extmapper_cell->type) == 0)
log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type));
log_error("No simplemap mapper for cell type %s found!\n", extmapper_cell->type.unescape());
simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell);
extmapper_module->remove(extmapper_cell);
}
if (extmapper_name == "maccmap") {
log("Creating %s with maccmap.\n", log_id(extmapper_module));
log("Creating %s with maccmap.\n", extmapper_module);
if (!extmapper_cell->type.in(ID($macc), ID($macc_v2)))
log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", log_id(extmapper_cell->type));
log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", extmapper_cell->type.unescape());
maccmap(extmapper_module, extmapper_cell);
extmapper_module->remove(extmapper_cell);
}
if (extmapper_name == "wrap") {
std::string cmd_string = tpl->attributes.at(ID::techmap_wrap).decode_string();
log("Running \"%s\" on wrapper %s.\n", cmd_string, log_id(extmapper_module));
log("Running \"%s\" on wrapper %s.\n", cmd_string, extmapper_module);
mkdebug.on();
Pass::call_on_module(extmapper_design, extmapper_module, cmd_string);
log_continue = true;
@ -573,31 +573,31 @@ struct TechmapWorker
goto use_wrapper_tpl;
}
auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type));
auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_module, cell->type.unescape());
if (!log_msg_cache.count(msg)) {
log_msg_cache.insert(msg);
log("%s\n", msg);
}
log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), extmapper_module);
}
else
{
auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name, log_id(cell->type));
auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name, cell->type.unescape());
if (!log_msg_cache.count(msg)) {
log_msg_cache.insert(msg);
log("%s\n", msg);
}
log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), extmapper_name);
log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), extmapper_name);
if (extmapper_name == "simplemap") {
if (simplemap_mappers.count(cell->type) == 0)
log_error("No simplemap mapper for cell type %s found!\n", log_id(cell->type));
log_error("No simplemap mapper for cell type %s found!\n", cell->type.unescape());
simplemap_mappers.at(cell->type)(module, cell);
}
if (extmapper_name == "maccmap") {
if (!cell->type.in(ID($macc), ID($macc_v2)))
log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", log_id(cell->type));
log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", cell->type.unescape());
maccmap(module, cell);
}
@ -626,26 +626,26 @@ struct TechmapWorker
}
if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0)
parameters.emplace(ID::_TECHMAP_CELLTYPE_, RTLIL::unescape_id(cell->type));
parameters.emplace(ID::_TECHMAP_CELLTYPE_, cell->type.unescape());
if (tpl->avail_parameters.count(ID::_TECHMAP_CELLNAME_) != 0)
parameters.emplace(ID::_TECHMAP_CELLNAME_, RTLIL::unescape_id(cell->name));
parameters.emplace(ID::_TECHMAP_CELLNAME_, cell->name.unescape());
for (auto &conn : cell->connections()) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape())) != 0) {
std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector();
for (auto &bit : v)
bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0);
parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const());
parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const());
}
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first))) != 0) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape())) != 0) {
std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector();
for (auto &bit : v)
if (bit.wire != nullptr)
bit = RTLIL::SigBit(RTLIL::State::Sx);
parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const());
parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const());
}
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) {
parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), initvals(conn.second));
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape())) != 0) {
parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape()), initvals(conn.second));
}
}
@ -658,7 +658,7 @@ struct TechmapWorker
unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++;
for (auto &conn : cell->connections())
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) {
for (auto &bit : sigmap(conn.second))
if (unique_bit_id.count(bit) == 0)
unique_bit_id[bit] = unique_bit_id_counter++;
@ -675,7 +675,7 @@ struct TechmapWorker
parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits;
for (auto &conn : cell->connections())
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) {
SigSpec sm = sigmap(conn.second);
RTLIL::Const::Builder builder(GetSize(sm) * bits);
for (auto &bit : sm) {
@ -685,7 +685,7 @@ struct TechmapWorker
val = val >> 1;
}
}
parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), builder.build());
parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape()), builder.build());
}
}
@ -734,7 +734,7 @@ struct TechmapWorker
RTLIL::SigSpec value = elem.value;
if (value.is_fully_const() && value.as_bool()) {
log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n",
derived_name.c_str(), log_id(elem.wire->name), log_signal(value));
derived_name.c_str(), elem.wire->name.unescape(), log_signal(value));
techmap_do_cache[tpl] = false;
}
}
@ -751,7 +751,7 @@ struct TechmapWorker
auto &data = it.second.front();
if (!data.value.is_fully_const())
log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(data.wire->name), log_signal(data.value));
log_error("Techmap yielded config wire %s with non-const value %s.\n", data.wire->name.unescape(), log_signal(data.value));
techmap_wire_names.erase(it.first);
@ -768,7 +768,7 @@ struct TechmapWorker
log("Analyzing pattern of constant bits for this cell:\n");
IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true);
log("Creating constmapped module `%s'.\n", log_id(new_tpl_name));
log("Creating constmapped module `%s'.\n", new_tpl_name.unescape());
log_assert(map->module(new_tpl_name) == nullptr);
RTLIL::Module *new_tpl = map->addModule(new_tpl_name);
@ -875,16 +875,16 @@ struct TechmapWorker
TechmapWires twd = techmap_find_special_wires(tpl);
for (auto &it : twd) {
if (!it.first.ends_with("_TECHMAP_FAIL_") && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.contains("_TECHMAP_DO_") && !it.first.contains("_TECHMAP_DONE_"))
log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first));
log_error("Techmap yielded unknown config wire %s.\n", it.first.unescape());
if (techmap_do_cache[tpl])
for (auto &it2 : it.second)
if (!it2.value.is_fully_const())
log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(it2.wire->name), log_signal(it2.value));
log_error("Techmap yielded config wire %s with non-const value %s.\n", it2.wire->name.unescape(), log_signal(it2.value));
techmap_wire_names.erase(it.first);
}
for (auto &it : techmap_wire_names)
log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", log_id(it));
log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", it.unescape());
if (recursive_mode) {
if (log_continue) {
@ -924,7 +924,7 @@ struct TechmapWorker
if (extern_mode && !in_recursion)
{
std::string m_name = stringf("$extern:%s", log_id(tpl));
std::string m_name = stringf("$extern:%s", tpl);
if (!design->module(m_name))
{
@ -934,18 +934,18 @@ struct TechmapWorker
module_queue.insert(m);
}
log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(m_name));
log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, module, cell, m_name);
cell->type = m_name;
cell->parameters.clear();
}
else
{
auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), log_id(cell->type));
auto msg = stringf("Using template %s for cells of type %s.", tpl, cell->type.unescape());
if (!log_msg_cache.count(msg)) {
log_msg_cache.insert(msg);
log("%s\n", msg);
}
log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(tpl));
log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), tpl);
techmap_module_worker(design, module, cell, tpl);
cell = nullptr;
}
@ -955,7 +955,7 @@ struct TechmapWorker
}
if (assert_mode && !mapped_cell)
log_error("(ASSERT MODE) Failed to map cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
log_error("(ASSERT MODE) Failed to map cell %s.%s (%s).\n", module, cell, cell->type.unescape());
handled_cells.insert(cell);
}
@ -1275,8 +1275,8 @@ struct TechmapPass : public Pass {
i.second.sort(RTLIL::sort_by_id_str());
std::string maps = "";
for (auto &map : i.second)
maps += stringf(" %s", log_id(map));
log_debug(" %s:%s\n", log_id(i.first), maps);
maps += stringf(" %s", map.unescape());
log_debug(" %s:%s\n", i.first.unescape(), maps);
}
log_debug("\n");

View file

@ -142,7 +142,7 @@ struct TribufWorker {
auto conflict = module->And(NEW_ID, cell_s, other_s);
std::string name = stringf("$tribuf_conflict$%s", log_id(cell->name));
std::string name = stringf("$tribuf_conflict$%s", cell->name.unescape());
auto assert_cell = module->addAssert(name, module->Not(NEW_ID, conflict), SigSpec(true));
assert_cell->set_src_attribute(cell->get_src_attribute());

View file

@ -68,7 +68,7 @@ struct ZinitPass : public Pass {
FfData ff(&initvals, cell);
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
log("FF init value for cell %s (%s): %s = %s\n", cell, cell->type.unescape(),
log_signal(ff.sig_q), log_signal(ff.val_init));
pool<int> bits;