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:
commit
e58125b605
834 changed files with 25281 additions and 8780 deletions
225
passes/techmap/CMakeLists.txt
Normal file
225
passes/techmap/CMakeLists.txt
Normal 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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
426
passes/techmap/arith_tree.cc
Normal file
426
passes/techmap/arith_tree.cc
Normal 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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
145
passes/techmap/liberty_cache.h
Normal file
145
passes/techmap/liberty_cache.h
Normal 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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue