Update to latest and fix all disabled tests

This commit is contained in:
Akash Levy 2025-09-28 01:33:08 -07:00
commit 652a9a63b2
47 changed files with 493 additions and 164 deletions

View File

@ -1,4 +1,4 @@
name: Build environment setup
4name: Build environment setup
description: Configure build env for Yosys builds
runs:
using: composite
@ -8,7 +8,8 @@ runs:
shell: bash
run: |
sudo apt-get update
sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache
sudo apt-get install libdwarf-dev libelf-dev elfutils libdw-dev ccache
sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libgtest-dev
- name: Install macOS Dependencies
if: runner.os == 'macOS'

View File

@ -48,7 +48,7 @@ jobs:
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf
make -j$procs ENABLE_LTO=1
make -j$procs
- name: Prepare docs
shell: bash

View File

@ -114,3 +114,8 @@ jobs:
shell: bash
run: |
find tests/**/*.err -print -exec cat {} \;
- name: Run unit tests
shell: bash
run: |
make -j$procs unit-test ENABLE_LIBYOSYS=1

View File

@ -78,3 +78,8 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' }}
run: |
make -C sby run_ci
- name: Run unit tests
shell: bash
run: |
make -j$procs unit-test ENABLE_LTO=1 ENABLE_LIBYOSYS=1

View File

@ -12,6 +12,8 @@ brew "boost-python3"
brew "llvm@20"
brew "lld"
brew "googletest"
brew "autoconf"
brew "dwarfutils"

View File

@ -60,14 +60,11 @@ merge; please do not use these labels if you are not a maintainer.
# Asking questions
If you have a question about how to use Yosys, please ask on our [discussions
page](https://github.com/YosysHQ/yosys/discussions) or in our [community
slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA).
The slack is also a great place to ask questions about developing or
If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/) or in our [discussions
page](https://github.com/YosysHQ/yosys/discussions).
The Discourse is also a great place to ask questions about developing or
contributing to Yosys.
We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the
We have open [dev 'jour fixe' (JF) meetings](https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing) where developers from YosysHQ and the
community come together to discuss open issues and PRs. This is also a good
place to talk to us about how to implement larger PRs. Please join the
community slack if you would like to join the next meeting, the link is
available in the description of the #devel-discuss channel.
place to talk to us about how to implement larger PRs.

View File

@ -180,7 +180,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.57+178
YOSYS_VER := 0.57+218
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2)
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3)

View File

@ -106,7 +106,7 @@ struct Index {
info.found_blackboxes.insert(cell);
} else {
if (!submodule || submodule->get_blackbox_attribute())
log_error("Unsupported cell type: %s (%s in %s)\n",
log_warning("Unsupported cell type: %s (%s in %s)\n",
log_id(cell->type), log_id(cell), log_id(m));
}
}
@ -1017,7 +1017,7 @@ struct XAigerWriter : AigerWriter {
auto &minfo = cursor.leaf_minfo(*this);
for (auto box : minfo.found_blackboxes) {
log_debug(" - %s.%s (type %s): ", cursor.path().c_str(),
log_debug(" - %s.%s (type %s): ", cursor.path(),
RTLIL::unescape_id(box->name),
log_id(box->type));

View File

@ -67,7 +67,7 @@ The ``formatted_help()`` method
Dumping command help to json
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- `help -dump-cells-json cmds.json`
- `help -dump-cmds-json cmds.json`
+ generates a ``ContentListing`` for each command registered in Yosys
+ tries to parse unformatted ``Pass::help()`` output if

View File

@ -476,7 +476,7 @@ void AigerReader::parse_xaiger()
else if (c == 'n') {
parse_xaiger_literal(f);
f >> s;
log_debug("n: '%s'\n", s.c_str());
log_debug("n: '%s'\n", s);
}
else if (c == 'h') {
f.ignore(sizeof(uint32_t));

View File

@ -83,11 +83,11 @@ struct RpcServer {
std::string request;
json_request.dump(request);
request += '\n';
log_debug("RPC frontend request: %s", request.c_str());
log_debug("RPC frontend request: %s", request);
write(request);
std::string response = read();
log_debug("RPC frontend response: %s", response.c_str());
log_debug("RPC frontend response: %s", response);
std::string error;
Json json_response = Json::parse(response, error);
if (json_response.is_null())

View File

@ -150,14 +150,14 @@ unsigned int CellCosts::get(RTLIL::Cell *cell)
return 1;
if (design_ && design_->module(cell->type) && cell->parameters.empty()) {
log_debug("%s is a module, recurse\n", cell->name.c_str());
log_debug("%s is a module, recurse\n", cell->name);
return get(design_->module(cell->type));
} else if (cell->is_builtin_ff()) {
log_assert(cell->hasPort(ID::Q) && "Weird flip flop");
log_debug("%s is ff\n", cell->name.c_str());
log_debug("%s is ff\n", cell->name);
return cell->getParam(ID::WIDTH).as_int();
} else if (cell->type.in(ID($mem), ID($mem_v2))) {
log_debug("%s is mem\n", cell->name.c_str());
log_debug("%s is mem\n", cell->name);
return cell->getParam(ID::WIDTH).as_int() * cell->getParam(ID::SIZE).as_int();
} else if (y_coef(cell->type)) {
// linear with Y_WIDTH or WIDTH
@ -166,23 +166,23 @@ unsigned int CellCosts::get(RTLIL::Cell *cell)
int width = cell->getParam(param).as_int();
if (cell->type == ID($demux))
width <<= cell->getParam(ID::S_WIDTH).as_int();
log_debug("%s Y*coef %d * %d\n", cell->name.c_str(), width, y_coef(cell->type));
log_debug("%s Y*coef %d * %d\n", cell->name, width, y_coef(cell->type));
return width * y_coef(cell->type);
} else if (sum_coef(cell->type)) {
// linear with sum of port widths
unsigned int sum = port_width_sum(cell);
log_debug("%s sum*coef %d * %d\n", cell->name.c_str(), sum, sum_coef(cell->type));
log_debug("%s sum*coef %d * %d\n", cell->name, sum, sum_coef(cell->type));
return sum * sum_coef(cell->type);
} else if (max_inp_coef(cell->type)) {
// linear with largest input width
unsigned int max = max_inp_width(cell);
log_debug("%s max*coef %d * %d\n", cell->name.c_str(), max, max_inp_coef(cell->type));
log_debug("%s max*coef %d * %d\n", cell->name, max, max_inp_coef(cell->type));
return max * max_inp_coef(cell->type);
} else if (is_div_mod(cell->type) || cell->type == ID($mul)) {
// quadratic with sum of port widths
unsigned int sum = port_width_sum(cell);
unsigned int coef = cell->type == ID($mul) ? 3 : 5;
log_debug("%s coef*(sum**2) %d * %d\n", cell->name.c_str(), coef, sum * sum);
log_debug("%s coef*(sum**2) %d * %d\n", cell->name, coef, sum * sum);
return coef * sum * sum;
} else if (cell->type.in(ID($macc), ID($macc_v2))) {
// quadratic per term
@ -203,15 +203,15 @@ unsigned int CellCosts::get(RTLIL::Cell *cell)
} else if (cell->type == ID($lut)) {
int width = cell->getParam(ID::WIDTH).as_int();
unsigned int cost = 1U << (unsigned int)width;
log_debug("%s is 2**%d\n", cell->name.c_str(), width);
log_debug("%s is 2**%d\n", cell->name, width);
return cost;
} else if (cell->type == ID($sop)) {
int width = cell->getParam(ID::WIDTH).as_int();
int depth = cell->getParam(ID::DEPTH).as_int();
log_debug("%s is (2*%d + 1)*%d\n", cell->name.c_str(), width, depth);
log_debug("%s is (2*%d + 1)*%d\n", cell->name, width, depth);
return (2 * width + 1) * depth;
} else if (is_free(cell->type)) {
log_debug("%s is free\n", cell->name.c_str());
log_debug("%s is free\n", cell->name);
return 0;
} else if (is_mem(cell->type)) {
// SILIMATE: Memory cells have no bearing on cross module optimizations

View File

@ -164,7 +164,7 @@ void FstData::extractVarNames()
char *endptr;
int mem_addr = strtol(addr.c_str(), &endptr, 16);
if (*endptr) {
log_debug("Error parsing memory address in : %s\n", clean_name.c_str());
log_debug("Error parsing memory address in : %s\n", clean_name);
} else {
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
}
@ -178,7 +178,7 @@ void FstData::extractVarNames()
char *endptr;
int mem_addr = strtol(addr.c_str(), &endptr, 10);
if (*endptr) {
log_debug("Error parsing memory address in : %s\n", clean_name.c_str());
log_debug("Error parsing memory address in : %s\n", clean_name);
} else {
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
}

View File

@ -331,10 +331,12 @@ static void log_error_with_prefix(std::string_view prefix, std::string str)
if (log_errfile != NULL)
log_files.push_back(log_errfile);
if (log_error_stderr)
if (log_error_stderr) {
log_flush(); // Make sure we flush stdout before replacing it with stderr
for (auto &f : log_files)
if (f == stdout)
f = stderr;
}
log_last_error = std::move(str);
log("%s%s", prefix, log_last_error);
@ -405,6 +407,11 @@ void log_abort_internal(const char *file, int line)
log_error("Abort in %s:%d.\n", file, line);
}
void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message)
{
log_error("Abort in %s:%d (%s): %s\n", file, line, func, message);
}
void log_formatted_cmd_error(std::string str)
{
if (log_cmd_error_throw) {

View File

@ -4456,7 +4456,7 @@ RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const
RTLIL::SigBit RTLIL::SigChunk::operator[](int offset) const
{
log_assert(offset >= 0);
log_assert(offset <= width);
log_assert(offset < width);
RTLIL::SigBit ret;
if (wire) {
ret.wire = wire;

View File

@ -1252,7 +1252,8 @@ private:
public:
SigSpec() : width_(0), hash_(0) {}
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
SigSpec(const SigSpec &value) = default;
SigSpec(SigSpec &&value) = default;
SigSpec(const RTLIL::Const &value);
SigSpec(RTLIL::Const &&value);
SigSpec(const RTLIL::SigChunk &chunk);
@ -1269,6 +1270,9 @@ public:
SigSpec(const std::set<RTLIL::SigBit> &bits);
explicit SigSpec(bool bit);
SigSpec &operator=(const SigSpec &rhs) = default;
SigSpec &operator=(SigSpec &&rhs) = default;
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }

View File

@ -142,7 +142,12 @@
#define YOSYS_CONSTEVAL constexpr
#endif
#define YOSYS_ABORT(s) abort()
#define YOSYS_ABORT(s) YOSYS_NAMESPACE_PREFIX log_yosys_abort_message(__FILE__, __LINE__, __FUNCTION__, s)
// This has to precede including "kernel/io.h"
YOSYS_NAMESPACE_BEGIN
[[noreturn]] void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message);
YOSYS_NAMESPACE_END
#include "kernel/io.h"

View File

@ -156,9 +156,9 @@ dict<SigBit, std::vector<SelReason>> gather_selected_reps(Module* mod, const std
void explain_selections(const std::vector<SelReason>& reasons) {
for (std::variant<Wire*, Cell*> reason : reasons) {
if (Cell** cell_reason = std::get_if<Cell*>(&reason))
log_debug("\tcell %s\n", (*cell_reason)->name.c_str());
log_debug("\tcell %s\n", (*cell_reason)->name);
else if (Wire** wire_reason = std::get_if<Wire*>(&reason))
log_debug("\twire %s\n", (*wire_reason)->name.c_str());
log_debug("\twire %s\n", (*wire_reason)->name);
else
log_assert(false && "insane reason variant\n");
}

View File

@ -22,11 +22,24 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
typedef struct name_proposal {
string name;
unsigned int score;
name_proposal() : name(""), score(-1) { }
name_proposal(string name, unsigned int score) : name(name), score(score) { }
bool operator<(const name_proposal &other) const {
if (score != other.score)
return score < other.score;
else
return name.length() < other.name.length();
}
} name_proposal;
int autoname_worker(Module *module, const dict<Wire*, unsigned int>& wire_score)
{
dict<Cell*, pair<int, string>> proposed_cell_names;
dict<Wire*, pair<int, string>> proposed_wire_names;
int best_score = -1;
dict<Cell*, name_proposal> proposed_cell_names;
dict<Wire*, name_proposal> proposed_wire_names;
name_proposal best_name;
for (auto cell : module->selected_cells()) {
if (cell->name[0] == '$') {
@ -36,14 +49,14 @@ int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
if (bit.wire != nullptr && bit.wire->name[0] != '$') {
if (suffix.empty())
suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
string new_name(bit.wire->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
score = 10000*score + new_name.size();
if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) {
if (best_score < 0 || score < best_score)
best_score = score;
proposed_cell_names[cell] = make_pair(score, new_name);
name_proposal proposed_name(
bit.wire->name.str() + suffix,
cell->output(conn.first) ? 0 : wire_score.at(bit.wire)
);
if (!proposed_cell_names.count(cell) || proposed_name < proposed_cell_names.at(cell)) {
if (proposed_name < best_name)
best_name = proposed_name;
proposed_cell_names[cell] = proposed_name;
}
}
}
@ -54,37 +67,44 @@ int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) {
if (suffix.empty())
suffix = stringf("_%s", log_id(conn.first));
string new_name(cell->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
score = 10000*score + new_name.size();
if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) {
if (best_score < 0 || score < best_score)
best_score = score;
proposed_wire_names[bit.wire] = make_pair(score, new_name);
name_proposal proposed_name(
cell->name.str() + suffix,
cell->output(conn.first) ? 0 : wire_score.at(bit.wire)
);
if (!proposed_wire_names.count(bit.wire) || proposed_name < proposed_wire_names.at(bit.wire)) {
if (proposed_name < best_name)
best_name = proposed_name;
proposed_wire_names[bit.wire] = proposed_name;
}
}
}
}
}
int count = 0;
// compare against double best score for following comparisons so we don't
// pre-empt a future iteration
best_name.score *= 2;
for (auto &it : proposed_cell_names) {
if (best_score*2 < it.second.first)
if (best_name < it.second)
continue;
IdString n = module->uniquify(IdString(it.second.second));
IdString n = module->uniquify(IdString(it.second.name));
log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
module->rename(it.first, n);
count++;
}
for (auto &it : proposed_wire_names) {
if (best_score*2 < it.second.first)
if (best_name < it.second)
continue;
IdString n = module->uniquify(IdString(it.second.second));
IdString n = module->uniquify(IdString(it.second.name));
log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
module->rename(it.first, n);
count++;
}
return proposed_cell_names.size() + proposed_wire_names.size();
return count;
}
struct AutonamePass : public Pass {
@ -110,12 +130,13 @@ struct AutonamePass : public Pass {
// }
break;
}
extra_args(args, argidx, design);
log_header(design, "Executing AUTONAME pass.\n");
for (auto module : design->selected_modules())
{
dict<Wire*, int> wire_score;
dict<Wire*, unsigned int> wire_score;
for (auto cell : module->selected_cells())
for (auto &conn : cell->connections())
for (auto bit : conn.second)

View File

@ -96,7 +96,7 @@ struct BoxDerivePass : Pass {
IdString derived_type = base->derive(d, cell->parameters);
Module *derived = d->module(derived_type);
log_assert(derived && "Failed to derive module\n");
log_debug("derived %s\n", derived_type.c_str());
log_debug("derived %s\n", derived_type);
if (!naming_attr.empty() && derived->has_attribute(naming_attr)) {
IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr));

View File

@ -95,7 +95,7 @@ struct CoveragePass : public Pass {
{
log_debug("Module %s:\n", log_id(module));
for (auto wire: module->wires()) {
log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute().c_str(), log_id(wire->name));
log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), log_id(wire->name));
for (auto src: wire->get_strpool_attribute(ID::src)) {
auto filename = extract_src_filename(src);
if (filename.empty()) continue;
@ -109,7 +109,7 @@ struct CoveragePass : public Pass {
}
}
for (auto cell: module->cells()) {
log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute().c_str(), log_id(cell->name));
log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), log_id(cell->name));
for (auto src: cell->get_strpool_attribute(ID::src)) {
auto filename = extract_src_filename(src);
if (filename.empty()) continue;

View File

@ -392,7 +392,7 @@ void MemMapping::dump_configs(int stage) {
void MemMapping::dump_config(MemConfig &cfg) {
log_debug("- %s:\n", log_id(cfg.def->id));
for (auto &it: cfg.def->options)
log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second));
log_debug(" - option %s %s\n", it.first, log_const(it.second));
log_debug(" - emulation score: %d\n", cfg.score_emu);
log_debug(" - replicates (for ports): %d\n", cfg.repl_port);
log_debug(" - replicates (for data): %d\n", cfg.repl_d);
@ -403,7 +403,7 @@ void MemMapping::dump_config(MemConfig &cfg) {
for (int x: cfg.def->dbits)
os << " " << x;
std::string dbits_s = os.str();
log_debug(" - abits %d dbits%s\n", cfg.def->abits, dbits_s.c_str());
log_debug(" - abits %d dbits%s\n", cfg.def->abits, dbits_s);
if (cfg.def->byte != 0)
log_debug(" - byte width %d\n", cfg.def->byte);
log_debug(" - chosen base width %d\n", cfg.def->dbits[cfg.base_width_log2]);
@ -414,25 +414,25 @@ void MemMapping::dump_config(MemConfig &cfg) {
else
os << " " << x;
std::string swizzle_s = os.str();
log_debug(" - swizzle%s\n", swizzle_s.c_str());
log_debug(" - swizzle%s\n", swizzle_s);
os.str("");
for (int i = 0; (1 << i) <= cfg.hard_wide_mask; i++)
if (cfg.hard_wide_mask & 1 << i)
os << " " << i;
std::string wide_s = os.str();
if (cfg.hard_wide_mask)
log_debug(" - hard wide bits%s\n", wide_s.c_str());
log_debug(" - hard wide bits%s\n", wide_s);
if (cfg.emu_read_first)
log_debug(" - emulate read-first behavior\n");
for (int i = 0; i < GetSize(mem.wr_ports); i++) {
auto &pcfg = cfg.wr_ports[i];
if (pcfg.rd_port == -1)
log_debug(" - write port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str());
log_debug(" - write port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0]);
else
log_debug(" - write port %d: port group %s (shared with read port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str(), pcfg.rd_port);
log_debug(" - write port %d: port group %s (shared with read port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0], pcfg.rd_port);
for (auto &it: pcfg.def->options)
log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second));
log_debug(" - option %s %s\n", it.first, log_const(it.second));
if (cfg.def->width_mode == WidthMode::PerPort) {
std::stringstream os;
for (int i = pcfg.def->min_wr_wide_log2; i <= pcfg.def->max_wr_wide_log2; i++)
@ -441,7 +441,7 @@ void MemMapping::dump_config(MemConfig &cfg) {
const char *note = "";
if (pcfg.rd_port != -1)
note = pcfg.def->width_tied ? " (tied)" : " (independent)";
log_debug(" - widths%s%s\n", widths_s.c_str(), note);
log_debug(" - widths%s%s\n", widths_s, note);
}
for (auto i: pcfg.emu_prio)
log_debug(" - emulate priority over write port %d\n", i);
@ -449,11 +449,11 @@ void MemMapping::dump_config(MemConfig &cfg) {
for (int i = 0; i < GetSize(mem.rd_ports); i++) {
auto &pcfg = cfg.rd_ports[i];
if (pcfg.wr_port == -1)
log_debug(" - read port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str());
log_debug(" - read port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0]);
else
log_debug(" - read port %d: port group %s (shared with write port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str(), pcfg.wr_port);
log_debug(" - read port %d: port group %s (shared with write port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0], pcfg.wr_port);
for (auto &it: pcfg.def->options)
log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second));
log_debug(" - option %s %s\n", it.first, log_const(it.second));
if (cfg.def->width_mode == WidthMode::PerPort) {
std::stringstream os;
for (int i = pcfg.def->min_rd_wide_log2; i <= pcfg.def->max_rd_wide_log2; i++)
@ -462,7 +462,7 @@ void MemMapping::dump_config(MemConfig &cfg) {
const char *note = "";
if (pcfg.wr_port != -1)
note = pcfg.def->width_tied ? " (tied)" : " (independent)";
log_debug(" - widths%s%s\n", widths_s.c_str(), note);
log_debug(" - widths%s%s\n", widths_s, note);
}
if (pcfg.emu_sync)
log_debug(" - emulate data register\n");
@ -2242,7 +2242,7 @@ struct MemoryLibMapPass : public Pass {
if (!map.logic_ok) {
if (map.cfgs.empty()) {
log_debug("Rejected candidates for mapping memory %s.%s:\n", log_id(module->name), log_id(mem.memid));
log_debug("%s", map.rejected_cfg_debug_msgs.c_str());
log_debug("%s", map.rejected_cfg_debug_msgs);
log_error("no valid mapping found for memory %s.%s\n", log_id(module->name), log_id(mem.memid));
}
idx = 0;

View File

@ -204,7 +204,7 @@ void rmunused_module_cells(Module *module, bool verbose)
for (auto cell : unused) {
if (verbose)
log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
log_debug(" removing unused `%s' cell `%s'.\n", cell->type, cell->name);
module->design->scratchpad_set_bool("opt.did_something", true);
if (cell->is_builtin_ff())
ffinit.remove_init(cell->getPort(ID::Q));
@ -215,7 +215,7 @@ void rmunused_module_cells(Module *module, bool verbose)
for (auto it : mem_unused)
{
if (verbose)
log_debug(" removing unused memory `%s'.\n", it.c_str());
log_debug(" removing unused memory `%s'.\n", it);
delete module->memories.at(it);
module->memories.erase(it);
}
@ -496,7 +496,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool unused
int del_temp_wires_count = 0;
for (auto wire : del_wires_queue) {
if (ys_debug() || (check_public_name(wire->name) && verbose))
log_debug(" removing unused non-port wire %s.\n", wire->name.c_str());
log_debug(" removing unused non-port wire %s.\n", wire->name);
else
del_temp_wires_count++;
}
@ -636,7 +636,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool unusedbitsattr
}
for (auto cell : delcells) {
if (verbose)
log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
log_debug(" removing buffer cell `%s': %s = %s\n", cell->name,
log_signal(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::A)));
module->remove(cell);
}

View File

@ -162,7 +162,7 @@ struct OptLutWorker
{
if (lut_width <= dlogic_conn.first)
{
log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second));
log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second));
log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first);
legal = false;
break;
@ -173,8 +173,8 @@ struct OptLutWorker
if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic.second->getPort(dlogic_conn.second)[0]))
{
log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second));
log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic.second->getPort(dlogic_conn.second)));
log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second));
log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type, dlogic_conn.second, log_signal(lut_dlogic.second->getPort(dlogic_conn.second)));
legal = false;
break;
}
@ -182,7 +182,7 @@ struct OptLutWorker
if (legal)
{
log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second));
log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second));
lut_legal_dlogics.insert(lut_dlogic);
for (auto &dlogic_conn : dlogic_map)
lut_dlogic_inputs.insert(dlogic_conn.first);
@ -496,9 +496,9 @@ struct OptLutWorker
lutM_new_table.set(eval, (RTLIL::State) evaluate_lut(lutB, eval_inputs));
}
log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string().c_str());
log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string().c_str());
log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string());
log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string());
log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string());
lutM->setParam(ID::LUT, lutM_new_table);
lutM->setPort(ID::A, lutM_new_inputs);

View File

@ -25,6 +25,7 @@
#include "libs/sha1/sha1.h"
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <array>
@ -170,24 +171,20 @@ struct OptMergeWorker
}
}
if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) {
if (cell1->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
if (conn1.at(ID::A) < conn1.at(ID::B)) {
RTLIL::SigSpec tmp = conn1[ID::A];
conn1[ID::A] = conn1[ID::B];
conn1[ID::B] = tmp;
std::swap(conn1[ID::A], conn1[ID::B]);
}
if (conn2.at(ID::A) < conn2.at(ID::B)) {
RTLIL::SigSpec tmp = conn2[ID::A];
conn2[ID::A] = conn2[ID::B];
conn2[ID::B] = tmp;
std::swap(conn2[ID::A], conn2[ID::B]);
}
} else
if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
if (cell1->type.in(ID($reduce_xor), ID($reduce_xnor))) {
conn1[ID::A].sort();
conn2[ID::A].sort();
} else
if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
if (cell1->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
conn1[ID::A].sort_and_unify();
conn2[ID::A].sort_and_unify();
} else
@ -300,11 +297,11 @@ struct OptMergeWorker
}
did_something = true;
log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), other_cell->name.c_str());
log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name, other_cell->name);
for (auto &it : cell->connections()) {
if (cell->output(it.first)) {
RTLIL::SigSpec other_sig = other_cell->getPort(it.first);
log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
log_debug(" Redirecting output %s: %s = %s\n", it.first,
log_signal(it.second), log_signal(other_sig));
Const init = initvals(other_sig);
initvals.remove_init(it.second);
@ -314,7 +311,7 @@ struct OptMergeWorker
initvals.set_init(other_sig, init);
}
}
log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type, cell->name, module->name);
module->remove(cell);
total_count++;
}

View File

@ -109,13 +109,43 @@ struct CutpointPass : public Pass {
SigMap sigmap(module);
pool<SigBit> cutpoint_bits;
pool<SigBit> wire_drivers;
for (auto cell : module->cells())
for (auto &conn : cell->connections())
if (cell->output(conn.first) && !cell->input(conn.first))
for (auto bit : sigmap(conn.second))
if (bit.wire)
wire_drivers.insert(bit);
for (auto wire : module->wires())
if (wire->port_input)
for (auto bit : sigmap(wire))
wire_drivers.insert(bit);
for (auto cell : module->selected_cells()) {
if (cell->type == ID($anyseq))
continue;
log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell));
for (auto &conn : cell->connections()) {
if (cell->output(conn.first))
module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second)));
if (cell->output(conn.first)) {
bool do_cut = true;
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
if (wire_drivers.count(bit)) {
log_debug(" Treating inout port '%s' as input.\n", id2cstr(conn.first));
do_cut = false;
break;
}
if (do_cut) {
module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second)));
if (cell->input(conn.first)) {
log_debug(" Treating inout port '%s' as output.\n", id2cstr(conn.first));
for (auto bit : sigmap(conn.second))
wire_drivers.insert(bit);
}
}
}
}
RTLIL::Cell *scopeinfo = nullptr;

View File

@ -181,8 +181,10 @@ 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 -w \"%s\" ; ", dont_use_args, liberty_file);
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);

View File

@ -1600,7 +1600,6 @@ static void replace_zbufs(Design *design)
sig[i] = w;
}
}
log("XXX %s -> %s\n", log_signal(cell->getPort(ID::A)), log_signal(sig));
cell->setPort(ID::A, sig);
}

View File

@ -85,7 +85,7 @@ static std::pair<std::optional<ClockGateCell>, std::optional<ClockGateCell>>
continue;
}
log_debug("maybe valid icg: %s\n", cell_name.c_str());
log_debug("maybe valid icg: %s\n", cell_name);
ClockGateCell icg_interface;
icg_interface.name = RTLIL::escape_id(cell_name);
@ -162,9 +162,9 @@ static std::pair<std::optional<ClockGateCell>, std::optional<ClockGateCell>>
winning = cost < goal;
if (winning)
log_debug("%s beats %s\n", icg_interface.name.c_str(), icg_to_beat->name.c_str());
log_debug("%s beats %s\n", icg_interface.name, icg_to_beat->name);
} else {
log_debug("%s is the first of its polarity\n", icg_interface.name.c_str());
log_debug("%s is the first of its polarity\n", icg_interface.name);
winning = true;
}
if (winning) {
@ -396,7 +396,7 @@ struct ClockgatePass : public Pass {
if (!it->second.new_net)
continue;
log_debug("Fix up FF %s\n", cell->name.c_str());
log_debug("Fix up FF %s\n", cell->name);
// Now we start messing with the design
ff.has_ce = false;
// Construct the clock gate

View File

@ -117,11 +117,11 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
// the next_state variable isn't just a pin name; perhaps this is an enable?
auto helper = LibertyExpression::Lexer(expr);
auto tree = LibertyExpression::parse(helper);
// log_debug("liberty expression:\n%s\n", tree.str().c_str());
// log_debug("liberty expression:\n%s\n", tree.str());
if (tree.kind == LibertyExpression::Kind::EMPTY) {
if (!warned_cells.count(cell_name)) {
log_debug("Invalid expression '%s' in next_state attribute of cell '%s' - skipping.\n", expr.c_str(), cell_name.c_str());
log_debug("Invalid expression '%s' in next_state attribute of cell '%s' - skipping.\n", expr, cell_name);
warned_cells.insert(cell_name);
}
return false;
@ -140,7 +140,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
// position that gives better diagnostics here.
if (!pin_names.count(ff_output)) {
if (!warned_cells.count(cell_name)) {
log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not contain ff output '%s' - skipping.\n", expr.c_str(), cell_name.c_str(), ff_output.c_str());
log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not contain ff output '%s' - skipping.\n", expr, cell_name, ff_output);
warned_cells.insert(cell_name);
}
return false;
@ -189,7 +189,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
}
if (!warned_cells.count(cell_name)) {
log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not evaluate to an enable flop - skipping.\n", expr.c_str(), cell_name.c_str());
log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not evaluate to an enable flop - skipping.\n", expr, cell_name);
warned_cells.insert(cell_name);
}
return false;
@ -225,10 +225,10 @@ static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::strin
For now, we'll simply produce a warning to let the user know something is up.
*/
if (pin_name.find_first_of("^*|&") == std::string::npos) {
log_debug("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str());
log_debug("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name, cell->args[0]);
}
else {
log_debug("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str());
log_debug("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name, cell->args[0]);
}
return false;

View File

@ -27,6 +27,14 @@
USING_YOSYS_NAMESPACE
YOSYS_NAMESPACE_BEGIN
static void transfer_attr (Cell* to, const Cell* from, const IdString& attr) {
if (from->has_attribute(attr))
to->attributes[attr] = from->attributes.at(attr);
}
static void transfer_src (Cell* to, const Cell* from) {
transfer_attr(to, from, ID::src);
}
void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
@ -261,21 +269,21 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
bool is_ne = cell->type.in(ID($ne), ID($nex));
RTLIL::SigSpec xor_out = module->addWire(NEW_ID2_SUFFIX("xor"), max(GetSize(sig_a), GetSize(sig_b))); // SILIMATE: Improve the naming
RTLIL::Cell *xor_cell = module->addXor(NEW_ID2, sig_a, sig_b, xor_out, is_signed, cell->get_src_attribute()); // SILIMATE: Improve the naming
RTLIL::Cell *xor_cell = module->addXor(NEW_ID2, sig_a, sig_b, xor_out, is_signed); // SILIMATE: Improve the naming
xor_cell->attributes = cell->attributes;
simplemap_bitop(module, xor_cell);
module->remove(xor_cell);
RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID2_SUFFIX("reduce_out")); // SILIMATE: Improve the naming
RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID2_SUFFIX("reduce_or"), xor_out, reduce_out, false, cell->get_src_attribute()); // SILIMATE: Improve the naming
RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID2_SUFFIX("reduce_or"), xor_out, reduce_out, false); // SILIMATE: Improve the naming
reduce_cell->attributes = cell->attributes;
simplemap_reduce(module, reduce_cell);
module->remove(reduce_cell);
if (!is_ne) {
RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID2_SUFFIX("not"), reduce_out, sig_y, false, cell->get_src_attribute()); // SILIMATE: Improve the naming
RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID2_SUFFIX("not"), reduce_out, sig_y, false); // SILIMATE: Improve the naming
not_cell->attributes = cell->attributes;
simplemap_lognot(module, not_cell);
simplemap_lognot(module, not_cell);
module->remove(not_cell);
}
}

View File

@ -592,7 +592,7 @@ struct TechmapWorker
log_msg_cache.insert(msg);
log("%s\n", msg);
}
log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), 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, log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
}
else
{
@ -601,7 +601,7 @@ struct TechmapWorker
log_msg_cache.insert(msg);
log("%s\n", msg);
}
log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), extmapper_name);
if (extmapper_name == "simplemap") {
if (simplemap_mappers.count(cell->type) == 0)
@ -953,7 +953,7 @@ struct TechmapWorker
module_queue.insert(m);
}
log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(m_name));
cell->type = m_name;
cell->parameters.clear();
}
@ -964,7 +964,7 @@ struct TechmapWorker
log_msg_cache.insert(msg);
log("%s\n", msg);
}
log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl));
log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(tpl));
techmap_module_worker(design, module, cell, tpl);
cell = nullptr;
}
@ -1295,7 +1295,7 @@ struct TechmapPass : public Pass {
std::string maps = "";
for (auto &map : i.second)
maps += stringf(" %s", log_id(map));
log_debug(" %s:%s\n", log_id(i.first), maps.c_str());
log_debug(" %s:%s\n", log_id(i.first), maps);
}
log_debug("\n");

View File

@ -1185,7 +1185,7 @@ struct TestCellPass : public Pass {
// Expected to run once
int num_cells_estimate = costs.get(uut);
if (num_cells <= num_cells_estimate) {
log_debug("Correct upper bound for %s: %d <= %d\n", cell_type.c_str(), num_cells, num_cells_estimate);
log_debug("Correct upper bound for %s: %d <= %d\n", cell_type, num_cells, num_cells_estimate);
} else {
failed++;
if (worst_abs < num_cells - num_cells_estimate) {

View File

@ -283,9 +283,16 @@ module _90_alu (A, B, CI, BI, X, Y, CO);
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
\$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO));
(* force_downto *)
wire [Y_WIDTH-1:0] P;
wire [Y_WIDTH-1:0] G;
wire [Y_WIDTH-1:0] Cnull;
assign Cnull = 1'b0;
assign X = AA ^ BB;
\$fa #(.WIDTH(Y_WIDTH)) fa (.A(AA), .B(BB), .C(Cnull), .X(G), .Y(P));
\$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(CO));
assign X = P;
assign Y = X ^ {CO, CI};
endmodule

View File

@ -42,7 +42,7 @@ struct QlIoffPass : public Pass {
for (auto cell : module->selected_cells()) {
if (cell->type.in(ID(dffsre), ID(sdffsre))) {
log_debug("Checking cell %s.\n", cell->name.c_str());
log_debug("Checking cell %s.\n", cell->name);
bool e_const = cell->getPort(ID::E).is_fully_ones();
bool r_const = cell->getPort(ID::R).is_fully_ones();
bool s_const = cell->getPort(ID::S).is_fully_ones();
@ -55,7 +55,7 @@ struct QlIoffPass : public Pass {
SigSpec d = cell->getPort(ID::D);
log_assert(GetSize(d) == 1);
if (modwalker.has_inputs(d)) {
log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str());
log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name);
// check that d_sig has no other consumers
pool<ModWalker::PortBit> portbits;
modwalker.get_consumers(portbits, d);
@ -70,7 +70,7 @@ struct QlIoffPass : public Pass {
SigSpec q = cell->getPort(ID::Q);
log_assert(GetSize(q) == 1);
if (modwalker.has_outputs(q) && !modwalker.has_consumers(q)) {
log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str());
log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name);
for (SigBit bit : output_bit_aliases[modwalker.sigmap(q)]) {
log_assert(bit.is_wire());
output_ffs[bit.wire][bit.offset] = cell;

View File

@ -32,8 +32,8 @@ proc
equiv_opt -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
select -assert-count 1 t:LUT1
select -assert-count 10 t:LUT3
select -assert-count 3 t:LUT1
select -assert-count 2 t:LUT3
select -assert-count 1 t:LUT4
select -assert-count 5 t:MUX2_LUT5
select -assert-count 2 t:MUX2_LUT6

View File

@ -1,5 +0,0 @@
# Opt tests
## Disabled
- `opt_lut`: we do not support `abc9`

View File

@ -1,11 +1,27 @@
GTESTFLAG := -lgtest -lgtest_main
RPATH := -Wl,-rpath
EXTRAFLAGS := -lyosys -pthreads
UNAME_S := $(shell uname -s)
# GoogleTest flags
GTEST_PREFIX := $(shell brew --prefix googletest 2>/dev/null)
ifeq ($(GTEST_PREFIX),)
GTEST_CXXFLAGS :=
GTEST_LDFLAGS := -lgtest -lgtest_main
else
GTEST_CXXFLAGS := -I$(GTEST_PREFIX)/include
GTEST_LDFLAGS := -L$(GTEST_PREFIX)/lib -lgtest -lgtest_main
endif
ifeq ($(UNAME_S),Darwin)
RPATH = -Wl,-rpath,$(ROOTPATH)
else
RPATH = -Wl,-rpath=$(ROOTPATH)
endif
EXTRAFLAGS := -lyosys -pthread
OBJTEST := objtest
BINTEST := bintest
ALLTESTFILE := $(shell find -name '*Test.cc' -printf '%P ')
ALLTESTFILE := $(shell find . -name '*Test.cc' | sed 's|^\./||' | tr '\n' ' ')
TESTDIRS := $(sort $(dir $(ALLTESTFILE)))
TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o)))
@ -15,16 +31,26 @@ TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o)))
all: prepare $(TESTS) run-tests
$(BINTEST)/%: $(OBJTEST)/%.o
$(CXX) -L$(ROOTPATH) $(RPATH)=$(ROOTPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \
$(GTESTFLAG) $(EXTRAFLAGS)
$(CXX) -L$(ROOTPATH) $(RPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \
$(GTEST_LDFLAGS) $(EXTRAFLAGS)
$(OBJTEST)/%.o: $(basename $(subst $(OBJTEST),.,%)).cc
$(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $^
$(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $(GTEST_CXXFLAGS) $^
.PHONY: prepare run-tests clean
run-tests: $(TESTS)
$(subst Test ,Test&& ,$^)
ifeq ($(UNAME_S),Darwin)
@for t in $^; do \
echo "Running $$t"; \
DYLD_LIBRARY_PATH=$(ROOTPATH) $$t || exit 1; \
done
else
@for t in $^; do \
echo "Running $$t"; \
$$t || exit 1; \
done
endif
prepare:
mkdir -p $(addprefix $(BINTEST)/,$(TESTDIRS))

View File

@ -20,6 +20,9 @@ namespace RTLIL {
KernelRtlilTest() {
if (log_files.empty()) log_files.emplace_back(stdout);
}
virtual void SetUp() override {
IdString::ensure_prepopulated();
}
};
TEST_F(KernelRtlilTest, ConstAssignCompare)

View File

@ -1,12 +0,0 @@
# Various tests
## Disabled
- `abc9`: we do not support `abc9`
- `check`: we do not support memory initialization
- `ice40_mince_abc9`: we do not support `abc9`
- `plugin`: we do not support plugins
## FIXME
- `cutpoint_blackbox`: unknown issue, needs to be looked into

View File

@ -1,10 +1,11 @@
# prefer output name
design -reset
read_rtlil <<EOT
autoidx 2
module \top
wire output 3 $y
wire output 3 \y
wire input 1 \a
wire input 2 \b
cell $and \b_$and_B
cell $and $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
@ -12,8 +13,193 @@ module \top
parameter \Y_WIDTH 1
connect \A \a
connect \B \b
connect \Y \y
end
end
EOT
logger -expect log "Rename cell .name in top to y_.and_Y" 1
logger -expect log "Renamed 1 objects" 1
debug autoname
logger -check-expected
# fallback to shortest name if output is private
design -reset
read_rtlil <<EOT
autoidx 2
module \top
wire output 3 $y
wire input 1 \ab
wire input 2 \abcd
cell $or $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \ab
connect \B \abcd
connect \Y $y
end
end
EOT
autoname
logger -expect log "Rename cell .name in top to ab_.or_A" 1
logger -expect log "Renamed 1 objects" 1
debug autoname
logger -check-expected
# prefer low fanout over low name length
design -reset
read_rtlil <<EOT
module \top
wire output 1 $y
wire input 2 \a
wire input 3 \bcd
wire input 4 \c_has_a_long_name
cell $and $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \bcd
connect \Y $y
end
cell $or $name2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \c_has_a_long_name
connect \Y $y
end
end
EOT
logger -expect log "Rename cell .name in top to bcd_.and_B" 1
logger -expect log "Rename cell .name2 in top to c_has_a_long_name_.or_B" 1
logger -expect log "Renamed 2 objects" 1
debug autoname
logger -check-expected
# names are unique
design -reset
read_rtlil <<EOT
module \top
wire output 3 \y
wire input 1 \a
wire input 2 \b
cell $and $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \b
connect \Y \y
end
cell $and $name2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \b
connect \Y \y
end
end
EOT
logger -expect log "Rename cell .name in top to y_.and_Y" 1
logger -expect log "Rename cell .name2 in top to y_.and_Y_1" 1
logger -expect log "Renamed 2 objects" 1
debug autoname
logger -check-expected
# wires get autonames too
design -reset
read_rtlil <<EOT
module \top
wire output 1 $y
wire input 2 \a
wire input 3 \bcd
wire $c
wire $d
wire $e
cell $__unknown $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \bcd
connect \Y $c
end
cell $or \or
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \bcd
connect \Y $d
end
cell $or $name2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A $c
connect \B $d
connect \Y $e
end
cell $and $name3
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A $c
connect \B $e
connect \Y $y
end
end
EOT
design -save order_test
# wires are named for being cell outputs
logger -expect log "Rename wire .d in top to or_Y" 1
logger -expect log "Rename cell .name2 in top to or_Y_.or_B" 1
logger -expect log "Renamed 2 objects" 1
debug autoname t:$or
logger -check-expected
# $name gets shortest name (otherwise bcd_$__unknown_B)
logger -expect log "Rename cell .name in top to a_.__unknown_A" 1
# another output wire
logger -expect log "Rename wire .e in top to or_Y_.or_B_Y" 1
logger -expect log "Renamed 4 objects" 1
debug autoname
logger -check-expected
# don't rename prematurely (some objects should be named after $name2)
design -load order_test
# $c gets shortest name, since the cell driving it doesn't have known port
# directions (otherwise a_$__unknown_A_Y)
logger -expect log "Rename wire .c in top to or_Y_.or_B_A" 1
# $name3 named for lowest fanout wire (otherwise a_$__unknown_A_Y_$and_A)
logger -expect log "Rename cell .name3 in top to or_Y_.or_B_Y_.and_B" 1
logger -expect log "Renamed 6 objects" 1
debug autoname
logger -check-expected

View File

@ -67,6 +67,47 @@ select -read cutpoint.gold.sel
#select -assert-none % %n
design -load gold
select -read cutpoint.gate.sel
select -read cutpoint.gold.sel
# nothing in gold but not gate
#select -assert-none % %n
select -assert-none % %n
# replacing the blackbox with a verific-style unknown module should work too
# (note this specific example loses the values of SOME_PARAM which would
# normally be retained by verific)
design -load hier
delete =bb
read_rtlil << EOT
attribute \blackbox 1
module \bb
parameter \SOME_PARAM 0
wire inout 3 \o
wire inout 2 \b
wire inout 1 \a
end
EOT
cutpoint -blackbox
check -assert
# also concatenated signals, and signals between two inout ports
design -load hier
delete top =bb
read_verilog << EOT
module top(input [1:0] a, b, output [1:0] o);
wire [1:0] c, d, e;
bb #(.SOME_PARAM(1)) bb1 (.a ({a[0], e[1]}), .b (b), .o (c));
bb #(.SOME_PARAM(2)) bb2 (.a ({c[1], a[0]}), .b (c), .o (d));
wb wb1 (.a (a), .b (b), .o (e));
some_mod some_inst (.a (c), .b (d), .c (e), .o (o));
endmodule
EOT
read_rtlil << EOT
attribute \blackbox 1
module \bb
parameter \SOME_PARAM 0
wire inout 3 width 2 \o
wire inout 2 width 2 \b
wire inout 1 width 2 \a
end
EOT
cutpoint -blackbox
check -assert