3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-08-11 05:30:53 +00:00

Merge branch 'YosysHQ:main' into abc-custom-flow

This commit is contained in:
Philippe Sauter 2024-11-11 23:09:29 +01:00 committed by GitHub
commit 3f2b391036
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
291 changed files with 18481 additions and 11714 deletions

View file

@ -12,10 +12,12 @@ 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

View file

@ -220,7 +220,8 @@ struct Abc9Pass : public ScriptPass
std::string arg = args[argidx];
if ((arg == "-exe" || arg == "-script" || arg == "-D" ||
/*arg == "-S" ||*/ arg == "-lut" || arg == "-luts" ||
/*arg == "-box" ||*/ arg == "-W") &&
/*arg == "-box" ||*/ arg == "-W" || arg == "-genlib" ||
arg == "-constr" || arg == "-dont_use" || arg == "-liberty") &&
argidx+1 < args.size()) {
if (arg == "-lut" || arg == "-luts")
lut_mode = true;

View file

@ -167,8 +167,8 @@ 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,
bool show_tempdir, std::string box_file, std::string lut_file,
std::string wire_delay, std::string tempdir_name
)
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::string abc9_script;
@ -176,8 +176,17 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
else if (!lut_file.empty())
abc9_script += stringf("read_lut \"%s\"; ", lut_file.c_str());
else
log_abort();
else if (!liberty_files.empty()) {
std::string dont_use_args;
for (std::string dont_use_cell : dont_use_cells) {
dont_use_args += stringf("-X \"%s\" ", dont_use_cell.c_str());
}
for (std::string liberty_file : liberty_files) {
abc9_script += stringf("read_lib %s -w \"%s\" ; ", dont_use_args.c_str(), liberty_file.c_str());
}
if (!constr_file.empty())
abc9_script += stringf("read_constr -v \"%s\"; ", constr_file.c_str());
}
log_assert(!box_file.empty());
abc9_script += stringf("read_box \"%s\"; ", box_file.c_str());
@ -359,6 +368,26 @@ struct Abc9ExePass : public Pass {
log(" of output quality):\n");
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str());
log("\n");
log(" -constr <file>\n");
log(" pass this file with timing constraints to ABC.\n");
log(" use with -liberty.\n");
log("\n");
log(" a constr file contains two lines:\n");
log(" set_driving_cell <cell_name>\n");
log(" set_load <floating_point_number>\n");
log("\n");
log(" the set_driving_cell statement defines which cell type is assumed to\n");
log(" drive the primary inputs and the set_load statement sets the load in\n");
log(" femtofarads for each primary output.\n");
log("\n");
log(" -liberty <file>\n");
log(" read the given Liberty file as a description of the target cell library.\n");
log(" this option can be used multiple times.\n");
log("\n");
log(" -dont_use <cell_name>\n");
log(" avoid usage of the technology cell <cell_name> when mapping the design.\n");
log(" this option can be used multiple times.\n");
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");
@ -411,7 +440,8 @@ struct Abc9ExePass : public Pass {
log_header(design, "Executing ABC9_EXE pass (technology mapping using ABC9).\n");
std::string exe_file = yosys_abc_executable;
std::string script_file, clk_str, box_file, lut_file;
std::string script_file, clk_str, box_file, lut_file, constr_file;
std::vector<std::string> liberty_files, dont_use_cells;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
std::string tempdir_name;
bool fast_mode = false, dff_mode = false;
@ -499,6 +529,18 @@ struct Abc9ExePass : public Pass {
tempdir_name = args[++argidx];
continue;
}
if (arg == "-liberty" && argidx+1 < args.size()) {
liberty_files.push_back(args[++argidx]);
continue;
}
if (arg == "-dont_use" && argidx+1 < args.size()) {
dont_use_cells.push_back(args[++argidx]);
continue;
}
if (arg == "-constr" && argidx+1 < args.size()) {
constr_file = args[++argidx];
continue;
}
break;
}
extra_args(args, argidx, design);
@ -562,7 +604,8 @@ struct Abc9ExePass : public Pass {
abc9_module(design, script_file, exe_file, lut_costs, dff_mode,
delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, tempdir_name);
box_file, lut_file, liberty_files, wire_delay, tempdir_name,
constr_file, dont_use_cells);
}
} Abc9ExePass;

View file

@ -1217,7 +1217,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
auto Qi = initmap(Q);
auto it = Qi.wire->attributes.find(ID::init);
if (it != Qi.wire->attributes.end())
it->second[Qi.offset] = State::Sx;
it->second.bits()[Qi.offset] = State::Sx;
}
else if (cell->type.in(ID($_AND_), ID($_NOT_)))
module->remove(cell);
@ -1528,7 +1528,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
int i = 0;
while (i < GetSize(mask)) {
for (int j = 0; j < (1 << index); j++)
std::swap(mask[i+j], mask[i+j+(1 << index)]);
std::swap(mask.bits()[i+j], mask.bits()[i+j+(1 << index)]);
i += 1 << (index+1);
}
A[index] = y_bit;
@ -1543,7 +1543,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
// and get cleaned away
clone_lut:
driver_mask = driver_lut->getParam(ID::LUT);
for (auto &b : driver_mask.bits) {
for (auto &b : driver_mask.bits()) {
if (b == RTLIL::State::S0) b = RTLIL::State::S1;
else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
}

153
passes/techmap/abc_new.cc Normal file
View file

@ -0,0 +1,153 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2024 Martin Povišer <povik@cutebit.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/register.h"
#include "kernel/rtlil.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct AbcNewPass : public ScriptPass {
AbcNewPass() : ScriptPass("abc_new", "(experimental) use ABC for SC technology mapping (new)")
{
experimental();
}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" abc_new [options] [selection]\n");
log("\n");
log("This command uses the ABC tool [1] to optimize the current design and map it to\n");
log("the target standard cell library.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
log(" -exe <command>\n");
log(" -script <file>\n");
log(" -D <picoseconds>\n");
log(" -constr <file>\n");
log(" -dont_use <cell_name>\n");
log(" -liberty <file>\n");
log(" these options are passed on to the 'abc9_exe' command which invokes\n");
log(" the ABC tool on individual modules of the design. please see\n");
log(" 'help abc9_exe' for more details\n");
log("\n");
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
log("\n");
help_script();
log("\n");
}
bool cleanup;
std::string abc_exe_options;
void execute(std::vector<std::string> args, RTLIL::Design *d) override
{
std::string run_from, run_to;
cleanup = true;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-exe" || args[argidx] == "-script" ||
args[argidx] == "-D" ||
args[argidx] == "-constr" || args[argidx] == "-dont_use" ||
args[argidx] == "-liberty") {
abc_exe_options += " " + args[argidx] + " " + args[argidx + 1];
argidx++;
} else if (args[argidx] == "-run" && argidx + 1 < args.size()) {
size_t pos = args[++argidx].find(':');
if (pos == std::string::npos)
break;
run_from = args[argidx].substr(0, pos);
run_to = args[argidx].substr(pos + 1);
} else if (args[argidx] == "-nocleanup") {
cleanup = false;
} else {
break;
}
}
extra_args(args, argidx, d);
log_header(d, "Executing ABC_NEW pass.\n");
log_push();
run_script(d, run_from, run_to);
log_pop();
}
void script() override
{
if (check_label("check")) {
run("abc9_ops -check");
}
if (check_label("prep_boxes")) {
run("box_derive");
run("abc9_ops -prep_box");
}
if (check_label("map")) {
std::vector<Module *> selected_modules;
if (!help_mode) {
selected_modules = active_design->selected_whole_modules_warn();
active_design->selection_stack.emplace_back(false);
} else {
selected_modules = {nullptr};
run("foreach module in selection");
}
for (auto mod : selected_modules) {
std::string tmpdir = "<abc-temp-dir>";
std::string modname = "<module>";
std::string exe_options = "[options]";
if (!help_mode) {
tmpdir = cleanup ? (get_base_tmpdir() + "/") : "_tmp_";
tmpdir += proc_program_prefix() + "yosys-abc-XXXXXX";
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_push();
active_design->selection().select(mod);
}
run(stringf(" abc9_ops -write_box %s/input.box", tmpdir.c_str()));
run(stringf(" write_xaiger2 -mapping_prep -map2 %s/input.map2 %s/input.xaig", tmpdir.c_str(), tmpdir.c_str()));
run(stringf(" abc9_exe %s -cwd %s -box %s/input.box", exe_options.c_str(), tmpdir.c_str(), tmpdir.c_str()));
run(stringf(" read_xaiger2 -sc_mapping -module_name %s -map2 %s/input.map2 %s/output.aig",
modname.c_str(), tmpdir.c_str(), tmpdir.c_str()));
if (!help_mode) {
active_design->selection().selected_modules.clear();
log_pop();
}
}
if (!help_mode) {
active_design->selection_stack.pop_back();
}
}
}
} AbcNewPass;
PRIVATE_NAMESPACE_END

View file

@ -70,9 +70,9 @@ struct BufnormPass : public Pass {
log(" to chain 'keep' wires first, then ports in declaration order,\n");
log(" and then the other wires in alphanumeric sort order.)\n");
log("\n");
log(" -noinit\n");
log(" Do not move 'init' attributes to the wires on FF output ports.\n");
log("\n");
// log(" -noinit\n");
// log(" Do not move 'init' attributes to the wires on FF output ports.\n");
// log("\n");
log("Run 'bufnorm' with -pos, -bits, or -conn on the whole design to remove all\n");
log("$buf buffer cells and exit 'buffered-normalized mode' again.\n");
log("\n");
@ -108,7 +108,7 @@ struct BufnormPass : public Pass {
bool nokeep_mode = false;
bool nosticky_mode = false;
bool alphasort_mode = false;
bool noinit_mode = false; // FIXME: Actually move init attributes
// bool noinit_mode = false; // FIXME: Actually move init attributes
bool nomode_mode = false;
bool pos_mode = false;
@ -169,11 +169,11 @@ struct BufnormPass : public Pass {
got_non_update_reset_opt = true;
continue;
}
if (arg == "-noinit") {
noinit_mode = true;
got_non_update_reset_opt = true;
continue;
}
// if (arg == "-noinit") {
// noinit_mode = true;
// got_non_update_reset_opt = true;
// continue;
// }
if (arg == "-pos") {
pos_mode = true;
got_non_update_reset_opt = true;
@ -438,8 +438,13 @@ struct BufnormPass : public Pass {
bool chain_this_wire = chain_this_wire_f(wire);
SigSpec keysig = sigmap(wire), insig = wire, outsig = wire;
for (int i = 0; i < GetSize(insig); i++)
insig[i] = mapped_bits.at(keysig[i], State::Sx);
for (int i = 0; i < GetSize(insig); i++) {
if (keysig[i].is_wire())
insig[i] = mapped_bits.at(keysig[i], State::Sx);
else
insig[i] = keysig[i];
}
if (chain_this_wire) {
for (int i = 0; i < GetSize(outsig); i++)
mapped_bits[keysig[i]] = outsig[i];

View file

@ -155,18 +155,22 @@ struct CellmatchPass : Pass {
log("equivalent as long as their truth tables are identical upto a permutation of\n");
log("inputs and outputs. The supported number of inputs is limited to 6.\n");
log("\n");
log(" cellmatch -derive_luts [module selection]\n");
log("\n");
log("For every port in each selected module, characterize its combinational\n");
log("function with a 'lut' attribute if possible.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *d) override
{
log_header(d, "Executing CELLMATCH pass. (match cells)\n");
size_t argidx;
bool lut_attrs = false;
bool derive_luts = false;
Design *lib = NULL;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-lut_attrs") {
// an undocumented debugging option
lut_attrs = true;
if (args[argidx] == "-derive_luts") {
derive_luts = true;
} else if (args[argidx] == "-lib" && argidx + 1 < args.size()) {
if (!saved_designs.count(args[++argidx]))
log_cmd_error("No design '%s' found!\n", args[argidx].c_str());
@ -177,8 +181,8 @@ struct CellmatchPass : Pass {
}
extra_args(args, argidx, d);
if (!lib && !lut_attrs)
log_cmd_error("Missing required -lib option.\n");
if (!lib && !derive_luts)
log_cmd_error("Missing required -lib or -derive_luts option.\n");
struct Target {
Module *module;
@ -210,7 +214,7 @@ struct CellmatchPass : Pass {
r.first->second = new Design;
Design *map_design = r.first->second;
for (auto m : d->selected_whole_modules_warn()) {
for (auto m : d->selected_whole_modules_warn(/* visit whiteboxes */derive_luts)) {
std::vector<uint64_t> luts;
if (!derive_module_luts(m, luts))
continue;
@ -218,12 +222,12 @@ struct CellmatchPass : Pass {
SigSpec inputs = module_inputs(m);
SigSpec outputs = module_outputs(m);
if (lut_attrs) {
if (derive_luts) {
int no = 0;
for (auto bit : outputs) {
log_assert(bit.is_wire());
bit.wire->attributes[ID(p_class)] = p_class(inputs.size(), luts[no]);
bit.wire->attributes[ID(lut)] = luts[no++];
bit.wire->attributes[ID(lut)] = Const(luts[no++], 1 << inputs.size());
}
}

View file

@ -118,13 +118,13 @@ struct DffinitPass : public Pass {
for (int i = 0; i < GetSize(sig); i++) {
if (initval[i] == State::Sx)
continue;
while (GetSize(value.bits) <= i)
value.bits.push_back(State::S0);
if (noreinit && value.bits[i] != State::Sx && value.bits[i] != initval[i])
while (GetSize(value) <= i)
value.bits().push_back(State::S0);
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));
value.bits[i] = initval[i];
value.bits()[i] = initval[i];
}
if (highlow_mode && GetSize(value) != 0) {

View file

@ -869,17 +869,17 @@ struct DffLegalizePass : public Pass {
if (ff.has_arst) {
if (ff.val_arst[i] == State::Sx) {
if (!(supported & (mask << 8)))
ff.val_arst[i] = State::S0;
ff.val_arst.bits()[i] = State::S0;
if (!(supported & (mask << 4)))
ff.val_arst[i] = State::S1;
ff.val_arst.bits()[i] = State::S1;
}
}
if (ff.has_srst) {
if (ff.val_srst[i] == State::Sx) {
if (!(supported & (mask << 8)))
ff.val_srst[i] = State::S0;
ff.val_srst.bits()[i] = State::S0;
if (!(supported & (mask << 4)))
ff.val_srst[i] = State::S1;
ff.val_srst.bits()[i] = State::S1;
}
}
}

View file

@ -1399,7 +1399,7 @@ struct FlowmapWorker
log_signal(node), log_signal(undef), env.c_str());
}
lut_table[i] = value.as_bool() ? State::S1 : State::S0;
lut_table.bits()[i] = value.as_bool() ? State::S1 : State::S0;
ce.pop();
}

View file

@ -684,7 +684,7 @@ struct TechmapWorker
for (auto &bit : sigmap(conn.second)) {
int val = unique_bit_id.at(bit);
for (int i = 0; i < bits; i++) {
value.bits.push_back((val & 1) != 0 ? State::S1 : State::S0);
value.bits().push_back((val & 1) != 0 ? State::S1 : State::S0);
val = val >> 1;
}
}
@ -1226,7 +1226,7 @@ struct TechmapPass : public Pass {
dict<IdString, pool<IdString>> celltypeMap;
for (auto module : map->modules()) {
if (module->attributes.count(ID::techmap_celltype) && !module->attributes.at(ID::techmap_celltype).bits.empty()) {
if (module->attributes.count(ID::techmap_celltype) && !module->attributes.at(ID::techmap_celltype).empty()) {
char *p = strdup(module->attributes.at(ID::techmap_celltype).decode_string().c_str());
for (char *q = strtok(p, " \t\r\n"); q; q = strtok(nullptr, " \t\r\n")) {
std::vector<std::string> queue;

View file

@ -73,10 +73,10 @@ struct ZinitPass : public Pass {
pool<int> bits;
for (int i = 0; i < ff.width; i++) {
if (ff.val_init.bits[i] == State::S1)
if (ff.val_init[i] == State::S1)
bits.insert(i);
else if (ff.val_init.bits[i] != State::S0 && all_mode)
ff.val_init.bits[i] = State::S0;
else if (ff.val_init[i] != State::S0 && all_mode)
ff.val_init.bits()[i] = State::S0;
}
ff.flip_bits(bits);
ff.emit();