3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-03 22:16:09 +00:00

Merge branch 'YosysHQ:main' into master

This commit is contained in:
Eder Monteiro 2026-06-01 23:34:59 -03:00 committed by GitHub
commit fb3676ca7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
113 changed files with 1108 additions and 482 deletions

View file

@ -44,10 +44,18 @@ jobs:
- name: Runtime environment - name: Runtime environment
run: | run: |
echo "procs=$(nproc)" >> $GITHUB_ENV echo "procs=$(nproc)" >> $GITHUB_ENV
mkdir -p "${GITHUB_WORKSPACE}/coverage"
echo "LLVM_PROFILE_FILE=${GITHUB_WORKSPACE}/coverage/coverage_%p.profraw" >> $GITHUB_ENV
echo "LLVM_PROFILE_FILE_BUFFER_SIZE=0" >> $GITHUB_ENV
- name: Skip generating files
if: ${{ github.event_name != 'merge_group' && github.event_name != 'workflow_dispatch' }}
run: |
echo "LLVM_PROFILE_FILE=/dev/null" >> $GITHUB_ENV
- name: Build Yosys - name: Build Yosys
run: | run: |
make config-clang make config-gcov
echo "ENABLE_VERIFIC := 1" >> Makefile.conf echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
@ -85,6 +93,31 @@ jobs:
run: | run: |
make -C sby run_ci make -C sby run_ci
- name: Run coverage
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
run: |
make coverage
make clean_coverage
- name: Push coverage
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
run: |
git clone https://x-access-token:${{ secrets.REPORTS_TOKEN }}@github.com/YosysHQ/reports.git out
rm -rf out/coverage/main
mkdir -p out/coverage/main
cp -r coverage_html/* out/coverage/main/
cd out
# find . -name "*.html" -type f -print0 | xargs -0 sed -i -z 's#\(<td class="headerItem">Date:</td>[[:space:]]*<td class="headerValue">\)[^<]*\(</td>\)#\1\2#g'
git config user.name "yosyshq-ci"
git config user.email "105224853+yosyshq-ci@users.noreply.github.com"
git add .
if ! git diff --cached --quiet; then
git commit -m "Update coverage"
git push
else
echo "No changes to commit"
fi
test-pyosys: test-pyosys:
needs: pre_job needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }} if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}

View file

@ -66,6 +66,7 @@ jobs:
run: | run: |
mkdir -p bison mkdir -p bison
curl -L https://ftpmirror.gnu.org/gnu/bison/bison-3.8.2.tar.gz | tar --strip-components=1 -xzC bison curl -L https://ftpmirror.gnu.org/gnu/bison/bison-3.8.2.tar.gz | tar --strip-components=1 -xzC bison
sed -i 's/-Werror=unused//g' Makefile
## Software installed by default in GitHub Action Runner VMs: ## Software installed by default in GitHub Action Runner VMs:
## https://github.com/actions/runner-images ## https://github.com/actions/runner-images
- if: ${{ matrix.os.family == 'macos' }} - if: ${{ matrix.os.family == 'macos' }}

4
.gitignore vendored
View file

@ -65,10 +65,10 @@
/viz.js /viz.js
# other # other
/coverage.info /yosys.profdata
/coverage
/coverage_html /coverage_html
# these really belong in global gitignore since they're not specific to this project but rather to user tool choice # these really belong in global gitignore since they're not specific to this project but rather to user tool choice
# but too many people don't have a global gitignore configured: # but too many people don't have a global gitignore configured:
# https://docs.github.com/en/get-started/git-basics/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer # https://docs.github.com/en/get-started/git-basics/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer

View file

@ -2,9 +2,22 @@
List of major changes and improvements between releases List of major changes and improvements between releases
======================================================= =======================================================
Yosys 0.65 .. Yosys 0.66-dev Yosys 0.66 .. Yosys 0.67-dev
-------------------------- --------------------------
Yosys 0.65 .. Yosys 0.66
--------------------------
* Various
- C++ compiler with C++20 support is required.
- Please be aware that next release will also
migrate to CMake build system.
* New commands and options
- Added "lattice_dsp_nexus" pass for Lattice Nexus
DSP inference.
- Added "-scopename" option to "synth_gatemate" pass
that is propagated to "flatten".
Yosys 0.64 .. Yosys 0.65 Yosys 0.64 .. Yosys 0.65
-------------------------- --------------------------
* New commands and options * New commands and options

View file

@ -161,7 +161,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE CXXFLAGS += -D_DEFAULT_SOURCE
endif endif
YOSYS_VER := 0.65 YOSYS_VER := 0.66
ifneq (, $(shell command -v git 2>/dev/null)) ifneq (, $(shell command -v git 2>/dev/null))
ifneq (, $(shell git rev-parse --git-dir 2>/dev/null)) ifneq (, $(shell git rev-parse --git-dir 2>/dev/null))
@ -456,8 +456,11 @@ endif
endif endif
ifeq ($(ENABLE_GCOV),1) ifeq ($(ENABLE_GCOV),1)
CXXFLAGS += --coverage LLVM_PROFILE_FILE ?= $(realpath $(YOSYS_SRC))/coverage/coverage_%p.profraw
LINKFLAGS += --coverage export LLVM_PROFILE_FILE
export LLVM_PROFILE_FILE_BUFFER_SIZE=0
CXXFLAGS += -fprofile-instr-generate -fcoverage-mapping
LINKFLAGS+= -fprofile-instr-generate
endif endif
ifeq ($(ENABLE_GPROF),1) ifeq ($(ENABLE_GPROF),1)
@ -1115,12 +1118,13 @@ mrproper: clean
coverage: coverage:
./$(PROGRAM_PREFIX)yosys -qp 'help; help -all' ./$(PROGRAM_PREFIX)yosys -qp 'help; help -all'
rm -rf coverage.info coverage_html rm -rf coverage_html
lcov --capture -d . --no-external -o coverage.info llvm-profdata merge -sparse coverage/coverage_*.profraw -o yosys.profdata
genhtml coverage.info --output-directory coverage_html llvm-cov show ./$(PROGRAM_PREFIX)yosys -instr-profile=yosys.profdata -format=html -output-dir=coverage_html --compilation-dir=. -ignore-filename-regex='(^|.*/)libs/.*|/usr/include/.*|$(subst /,\/,$(VERIFIC_DIR))/.*'
clean_coverage: clean_coverage:
find . -name "*.gcda" -type f -delete rm -rf coverage
rm -f yosys.profdata
FUNC_KERNEL := functional.cc functional.h sexpr.cc sexpr.h compute_graph.h FUNC_KERNEL := functional.cc functional.h sexpr.cc sexpr.h compute_graph.h
FUNC_INCLUDES := $(addprefix --include *,functional/* $(FUNC_KERNEL)) FUNC_INCLUDES := $(addprefix --include *,functional/* $(FUNC_KERNEL))
@ -1182,7 +1186,7 @@ config-msys2-64: clean
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
config-gcov: clean config-gcov: clean
echo 'CONFIG := gcc' > Makefile.conf echo 'CONFIG := clang' > Makefile.conf
echo 'ENABLE_GCOV := 1' >> Makefile.conf echo 'ENABLE_GCOV := 1' >> Makefile.conf
echo 'ENABLE_DEBUG := 1' >> Makefile.conf echo 'ENABLE_DEBUG := 1' >> Makefile.conf

View file

@ -560,9 +560,9 @@ struct Index {
if (!first) if (!first)
ret += "."; ret += ".";
if (!cell) if (!cell)
ret += RTLIL::unescape_id(minfo.module->name); ret += minfo.module->name.unescape();
else else
ret += RTLIL::unescape_id(cell->name); ret += cell->name.unescape();
first = false; first = false;
} }
return ret; return ret;
@ -844,7 +844,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "o%d ", i); snprintf(buf, sizeof(buf), "o%d ", i);
f->write(buf, strlen(buf)); f->write(buf, strlen(buf));
std::string name = RTLIL::unescape_id(bit.wire->name); std::string name = bit.wire->name.unescape();
f->write(name.data(), name.size()); f->write(name.data(), name.size());
f->put('\n'); f->put('\n');
} }
@ -857,7 +857,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "i%d ", i); snprintf(buf, sizeof(buf), "i%d ", i);
f->write(buf, strlen(buf)); f->write(buf, strlen(buf));
std::string name = RTLIL::unescape_id(bit.wire->name); std::string name = bit.wire->name.unescape();
f->write(name.data(), name.size()); f->write(name.data(), name.size());
f->put('\n'); f->put('\n');
} }
@ -1088,7 +1088,7 @@ struct XAigerWriter : AigerWriter {
for (auto box : minfo.found_blackboxes) { for (auto box : minfo.found_blackboxes) {
log_debug(" - %s.%s (type %s): ", cursor.path(), log_debug(" - %s.%s (type %s): ", cursor.path(),
RTLIL::unescape_id(box->name), box,
box->type.unescape()); box->type.unescape());
Module *box_module = design->module(box->type), *box_derived; Module *box_module = design->module(box->type), *box_derived;

View file

@ -91,7 +91,7 @@ struct BlifDumper
const std::string str(RTLIL::IdString id) const std::string str(RTLIL::IdString id)
{ {
std::string str = RTLIL::unescape_id(id); std::string str = id.unescape();
for (size_t i = 0; i < str.size(); i++) for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>') if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?'; str[i] = '?';
@ -108,7 +108,7 @@ struct BlifDumper
return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef"; return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef";
} }
std::string str = RTLIL::unescape_id(sig.wire->name); std::string str = sig.wire->name.unescape();
for (size_t i = 0; i < str.size(); i++) for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>') if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?'; str[i] = '?';

View file

@ -3420,7 +3420,7 @@ struct CxxrtlWorker {
if (!design->selected_whole_module(module)) if (!design->selected_whole_module(module))
if (design->selected_module(module)) if (design->selected_module(module))
log_cmd_error("Can't handle partially selected module `%s'!\n", id2cstr(module->name)); log_cmd_error("Can't handle partially selected module `%s'!\n", module);
if (!design->selected_module(module)) if (!design->selected_module(module))
continue; continue;

View file

@ -30,9 +30,11 @@
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true) #define EDIF_DEF(_id) edif_names(_id.unescape(), true)
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br) #define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(_id.unescape(), true, _ren, _bl, _br)
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false) #define EDIF_REF(_id) edif_names(_id.unescape(), false)
#define EDIF_DEF_STR(_id) edif_names(RTLIL::unescape_id(_id), true)
#define EDIF_REF_STR(_id) edif_names(RTLIL::unescape_id(_id), false)
struct EdifNames struct EdifNames
{ {
@ -227,7 +229,7 @@ struct EdifBackend : public Backend {
if (top_module_name.empty()) if (top_module_name.empty())
log_error("No module found in design!\n"); log_error("No module found in design!\n");
*f << stringf("(edif %s\n", EDIF_DEF(top_module_name)); *f << stringf("(edif %s\n", EDIF_DEF_STR(top_module_name));
*f << stringf(" (edifVersion 2 0 0)\n"); *f << stringf(" (edifVersion 2 0 0)\n");
*f << stringf(" (edifLevel 0)\n"); *f << stringf(" (edifLevel 0)\n");
*f << stringf(" (keywordMap (keywordLevel 0))\n"); *f << stringf(" (keywordMap (keywordLevel 0))\n");
@ -534,7 +536,7 @@ struct EdifBackend : public Backend {
if (netname[i] == ' ' || netname[i] == '\\') if (netname[i] == ' ' || netname[i] == '\\')
netname.erase(netname.begin() + i--); netname.erase(netname.begin() + i--);
} }
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname)); *f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
for (auto &ref : it.second) for (auto &ref : it.second)
*f << stringf(" %s\n", ref.first); *f << stringf(" %s\n", ref.first);
if (sig.wire == NULL) { if (sig.wire == NULL) {
@ -572,7 +574,7 @@ struct EdifBackend : public Backend {
if (keepmode) if (keepmode)
{ {
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname)); *f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
auto &refs = net_join_db.at(mapped_sig); auto &refs = net_join_db.at(mapped_sig);
for (auto &ref : refs) for (auto &ref : refs)
@ -588,7 +590,7 @@ struct EdifBackend : public Backend {
} }
else else
{ {
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF(netname)); log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF_STR(netname));
} }
} }
} }
@ -599,8 +601,8 @@ struct EdifBackend : public Backend {
} }
*f << stringf(" )\n"); *f << stringf(" )\n");
*f << stringf(" (design %s\n", EDIF_DEF(top_module_name)); *f << stringf(" (design %s\n", EDIF_DEF_STR(top_module_name));
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name)); *f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF_STR(top_module_name));
*f << stringf(" )\n"); *f << stringf(" )\n");
*f << stringf(")\n"); *f << stringf(")\n");

View file

@ -89,7 +89,7 @@ struct CxxStruct {
} }
f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n"); f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n");
for (auto p : types) { for (auto p : types) {
f.print("\t\t\tfn(\"{}\", {});\n", RTLIL::unescape_id(p.first), scope(p.first, p.first)); f.print("\t\t\tfn(\"{}\", {});\n", p.first.unescape(), scope(p.first, p.first));
} }
f.print("\t\t}}\n"); f.print("\t\t}}\n");
f.print("\t}};\n\n"); f.print("\t}};\n\n");

View file

@ -80,7 +80,7 @@ public:
SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {} SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {}
void insert(IdString field_name, SmtSort sort) { void insert(IdString field_name, SmtSort sort) {
field_names(field_name); field_names(field_name);
auto accessor = scope.unique_name("\\" + name + "_" + RTLIL::unescape_id(field_name)); auto accessor = scope.unique_name("\\" + name + "_" + field_name.unescape());
fields.emplace_back(Field{sort, accessor}); fields.emplace_back(Field{sort, accessor});
} }
void write_definition(SExprWriter &w) { void write_definition(SExprWriter &w) {
@ -99,7 +99,7 @@ public:
w.open(list(name)); w.open(list(name));
for(auto field_name : field_names) { for(auto field_name : field_names) {
w << fn(field_name); w << fn(field_name);
w.comment(RTLIL::unescape_id(field_name), true); w.comment(field_name.unescape(), true);
} }
w.close(); w.close();
} }

View file

@ -106,7 +106,7 @@ public:
w.open(list(name)); w.open(list(name));
for(auto field_name : field_names) { for(auto field_name : field_names) {
w << fn(field_name); w << fn(field_name);
w.comment(RTLIL::unescape_id(field_name), true); w.comment(field_name.unescape(), true);
} }
w.close(); w.close();
} }
@ -281,7 +281,7 @@ struct SmtrModule {
w.push(); w.push();
w.open(list()); w.open(list());
w.open(list("assoc-result")); w.open(list("assoc-result"));
w << list("assoc", "\"" + RTLIL::unescape_id(input->name) + "\"", inputs_name); w << list("assoc", "\"" + input->name.unescape() + "\"", inputs_name);
w.pop(); w.pop();
w.open(list("if", "assoc-result")); w.open(list("if", "assoc-result"));
w << list("cdr", "assoc-result"); w << list("cdr", "assoc-result");
@ -298,7 +298,7 @@ struct SmtrModule {
w << list(*output_helper_name, outputs_name); w << list(*output_helper_name, outputs_name);
w.open(list("list")); w.open(list("list"));
for (auto output : ir.outputs()) { for (auto output : ir.outputs()) {
w << list("cons", "\"" + RTLIL::unescape_id(output->name) + "\"", output_struct.access("outputs", output->name)); w << list("cons", "\"" + output->name.unescape() + "\"", output_struct.access("outputs", output->name));
} }
w.pop(); w.pop();
} }

View file

@ -146,11 +146,11 @@ struct FunctionalTestGeneric : public Pass
log("Dumping module `%s'.\n", module->name); log("Dumping module `%s'.\n", module->name);
auto fir = Functional::IR::from_module(module); auto fir = Functional::IR::from_module(module);
for(auto node : fir) for(auto node : fir)
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n"; std::cout << node.name().unescape() << " = " << node.to_string([](auto n) { return n.name().unescape(); }) << "\n";
for(auto output : fir.all_outputs()) for(auto output : fir.all_outputs())
std::cout << RTLIL::unescape_id(output->kind) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n"; std::cout << output->kind.unescape() << " " << output->name.unescape() << " = " << output->value().name().unescape() << "\n";
for(auto state : fir.all_states()) for(auto state : fir.all_states())
std::cout << RTLIL::unescape_id(state->kind) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n"; std::cout << state->kind.unescape() << " " << state->name.unescape() << " = " << state->next_value().name().unescape() << "\n";
} }
} }
} FunctionalCxxBackend; } FunctionalCxxBackend;

View file

@ -41,7 +41,7 @@ static std::string netname(std::set<std::string> &conntypes_code, std::set<std::
return stringf("CONST_%d_0x%x", sig.size(), sig.as_int()); return stringf("CONST_%d_0x%x", sig.size(), sig.as_int());
} }
return RTLIL::unescape_id(sig.as_wire()->name); return sig.as_wire()->name.unescape();
} }
struct IntersynthBackend : public Backend { struct IntersynthBackend : public Backend {

View file

@ -91,7 +91,7 @@ struct JnyWriter
{ {
_cells.clear(); _cells.clear();
for (auto cell : mod->cells()) { for (auto cell : mod->cells()) {
const auto cell_type = escape_string(RTLIL::unescape_id(cell->type)); const auto cell_type = escape_string(cell->type.unescape());
if (_cells.find(cell_type) == _cells.end()) if (_cells.find(cell_type) == _cells.end())
_cells.emplace(cell_type, std::vector<Cell*>()); _cells.emplace(cell_type, std::vector<Cell*>());
@ -214,7 +214,7 @@ struct JnyWriter
void write_cell_conn(const std::pair<RTLIL::IdString, RTLIL::SigSpec>& sig, uint16_t indent_level = 0) { void write_cell_conn(const std::pair<RTLIL::IdString, RTLIL::SigSpec>& sig, uint16_t indent_level = 0) {
const auto _indent = gen_indent(indent_level); const auto _indent = gen_indent(indent_level);
f << _indent << " {\n"; f << _indent << " {\n";
f << _indent << " \"name\": \"" << escape_string(RTLIL::unescape_id(sig.first)) << "\",\n"; f << _indent << " \"name\": \"" << escape_string(sig.first.unescape()) << "\",\n";
f << _indent << " \"signals\": [\n"; f << _indent << " \"signals\": [\n";
write_sigspec(sig.second, indent_level + 2); write_sigspec(sig.second, indent_level + 2);
@ -232,7 +232,7 @@ struct JnyWriter
const auto _indent = gen_indent(indent_level); const auto _indent = gen_indent(indent_level);
f << _indent << "{\n"; f << _indent << "{\n";
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(mod->name))); f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(mod->name.unescape()));
f << _indent << " \"cell_sorts\": [\n"; f << _indent << " \"cell_sorts\": [\n";
bool first_sort{true}; bool first_sort{true};
@ -280,7 +280,7 @@ struct JnyWriter
f << ",\n"; f << ",\n";
f << _indent << " {\n"; f << _indent << " {\n";
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(con.first))); f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(con.first.unescape()));
f << _indent << " \"direction\": \""; f << _indent << " \"direction\": \"";
if (port_cell->input(con.first)) if (port_cell->input(con.first))
f << "i"; f << "i";
@ -351,10 +351,10 @@ struct JnyWriter
f << stringf(",\n"); f << stringf(",\n");
const auto param_val = param.second; const auto param_val = param.second;
if (!param_val.empty()) { if (!param_val.empty()) {
f << stringf(" %s\"%s\": ", _indent, escape_string(RTLIL::unescape_id(param.first))); f << stringf(" %s\"%s\": ", _indent, escape_string(param.first.unescape()));
write_param_val(param_val); write_param_val(param_val);
} else { } else {
f << stringf(" %s\"%s\": true", _indent, escape_string(RTLIL::unescape_id(param.first))); f << stringf(" %s\"%s\": true", _indent, escape_string(param.first.unescape()));
} }
first_param = false; first_param = false;
@ -366,7 +366,7 @@ struct JnyWriter
log_assert(cell != nullptr); log_assert(cell != nullptr);
f << _indent << " {\n"; f << _indent << " {\n";
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(RTLIL::unescape_id(cell->name))); f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(cell->name.unescape()));
if (_include_connections) { if (_include_connections) {
f << ",\n" << _indent << " \"connections\": [\n"; f << ",\n" << _indent << " \"connections\": [\n";

View file

@ -76,7 +76,7 @@ struct JsonWriter
string get_name(IdString name) string get_name(IdString name)
{ {
return get_string(RTLIL::unescape_id(name)); return get_string(name.unescape());
} }
string get_bits(SigSpec sig) string get_bits(SigSpec sig)

View file

@ -30,7 +30,7 @@ PRIVATE_NAMESPACE_BEGIN
static string spice_id2str(IdString id) static string spice_id2str(IdString id)
{ {
static const char *escape_chars = "$\\[]()<>="; static const char *escape_chars = "$\\[]()<>=";
string s = RTLIL::unescape_id(id); string s = id.unescape();
for (auto &ch : s) for (auto &ch : s)
if (strchr(escape_chars, ch) != nullptr) ch = '_'; if (strchr(escape_chars, ch) != nullptr) ch = '_';

View file

@ -24,19 +24,19 @@ struct FunctionalDummyBackend : public Backend {
// write node functions // write node functions
for (auto node : ir) for (auto node : ir)
*f << " assign " << id2cstr(node.name()) *f << " assign " << node.name().unescape()
<< " = " << node.to_string() << "\n"; << " = " << node.to_string() << "\n";
*f << "\n"; *f << "\n";
// write outputs and next state // write outputs and next state
for (auto output : ir.outputs()) for (auto output : ir.outputs())
*f << " " << id2cstr(output->kind) *f << " " << output->kind.unescape()
<< " " << id2cstr(output->name) << " " << output->name.unescape()
<< " = " << id2cstr(output->value().name()) << "\n"; << " = " << output->value().name().unescape() << "\n";
for (auto state : ir.states()) for (auto state : ir.states())
*f << " " << id2cstr(state->kind) *f << " " << state->kind.unescape()
<< " " << id2cstr(state->name) << " " << state->name.unescape()
<< " = " << id2cstr(state->next_value().name()) << "\n"; << " = " << state->next_value().name().unescape() << "\n";
} }
} }
} FunctionalDummyBackend; } FunctionalDummyBackend;

View file

@ -27,7 +27,7 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re
// count output lines for this module (needed only for summary output at the end) // count output lines for this module (needed only for summary output at the end)
int line_count = 0; int line_count = 0;
log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name)); log("Looking for stub wires in module %s:\n", module);
// For all ports on all cells // For all ports on all cells
for (auto &cell_iter : module->cells_) for (auto &cell_iter : module->cells_)
@ -74,11 +74,11 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re
// report stub bits and/or stub wires, don't report single bits // report stub bits and/or stub wires, don't report single bits
// if called with report_bits set to false. // if called with report_bits set to false.
if (GetSize(stub_bits) == GetSize(sig)) { if (GetSize(stub_bits) == GetSize(sig)) {
log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name)); log(" found stub wire: %s\n", wire);
} else { } else {
if (!report_bits) if (!report_bits)
continue; continue;
log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name)); log(" found wire with stub bits: %s [", wire);
for (int bit : stub_bits) for (int bit : stub_bits)
log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit); log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit);
log("]\n"); log("]\n");

View file

@ -6,7 +6,7 @@ import os
project = 'YosysHQ Yosys' project = 'YosysHQ Yosys'
author = 'YosysHQ GmbH' author = 'YosysHQ GmbH'
copyright ='2026 YosysHQ GmbH' copyright ='2026 YosysHQ GmbH'
yosys_ver = "0.65" yosys_ver = "0.66"
# select HTML theme # select HTML theme
html_theme = 'furo-ys' html_theme = 'furo-ys'

View file

@ -230,8 +230,7 @@ Use ``log_error()`` to report a non-recoverable error:
.. code:: C++ .. code:: C++
if (design->modules.count(module->name) != 0) if (design->modules.count(module->name) != 0)
log_error("A module with the name %s already exists!\n", log_error("A module with the name %s already exists!\n", module);
RTLIL::id2cstr(module->name));
Use ``log_cmd_error()`` to report a recoverable error: Use ``log_cmd_error()`` to report a recoverable error:

View file

@ -181,7 +181,7 @@ pointer ``f`` to the output file, or stdout if none is given.
For this minimal example all we are doing is printing out each node. The For this minimal example all we are doing is printing out each node. The
``node.name()`` method returns an ``RTLIL::IdString``, which we convert for ``node.name()`` method returns an ``RTLIL::IdString``, which we convert for
printing with ``id2cstr()``. Then, to print the function of the node, we use printing with ``unescape()``. Then, to print the function of the node, we use
``node.to_string()`` which gives us a string of the form ``function(args)``. The ``node.to_string()`` which gives us a string of the form ``function(args)``. The
``function`` part is the result of ``Functional::IR::fn_to_string(node.fn())``; ``function`` part is the result of ``Functional::IR::fn_to_string(node.fn())``;
while ``args`` is the zero or more arguments passed to the function, most while ``args`` is the zero or more arguments passed to the function, most

View file

@ -406,18 +406,6 @@ struct AST_INTERNAL::ProcessGenerator
if (GetSize(syncrule->signal) != 1) if (GetSize(syncrule->signal) != 1)
always->input_error("Found posedge/negedge event on a signal that is not 1 bit wide!\n"); always->input_error("Found posedge/negedge event on a signal that is not 1 bit wide!\n");
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true); addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
// Automatic (nosync) variables must not become flip-flops: remove
// them from clocked sync rules so that proc_dff does not infer
// an unnecessary register for a purely combinational temporary.
syncrule->actions.erase(
std::remove_if(syncrule->actions.begin(), syncrule->actions.end(),
[](const RTLIL::SigSig &ss) {
for (auto &chunk : ss.first.chunks())
if (chunk.wire && chunk.wire->get_bool_attribute(ID::nosync))
return true;
return false;
}),
syncrule->actions.end());
proc->syncs.push_back(syncrule); proc->syncs.push_back(syncrule);
} }
if (proc->syncs.empty()) { if (proc->syncs.empty()) {

View file

@ -41,14 +41,14 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++; expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++;
if (id_len == 0) if (id_len == 0)
log_error("Expected identifier at `%s' in %s.\n", expr, RTLIL::unescape_id(module->name)); log_error("Expected identifier at `%s' in %s.\n", expr, module);
if (id_len == 1 && (*expr == '0' || *expr == '1')) if (id_len == 1 && (*expr == '0' || *expr == '1'))
return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1; return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1;
std::string id = RTLIL::escape_id(std::string(expr, id_len)); std::string id = RTLIL::escape_id(std::string(expr, id_len));
if (!module->wires_.count(id)) if (!module->wires_.count(id))
log_error("Can't resolve wire name %s in %s.\n", RTLIL::unescape_id(id), RTLIL::unescape_id(module->name)); log_error("Can't resolve wire name %s in %s.\n", RTLIL::unescape_id(id), module);
expr += id_len; expr += id_len;
return module->wires_.at(id); return module->wires_.at(id);
@ -175,7 +175,7 @@ static RTLIL::SigSpec parse_func_expr(RTLIL::Module *module, const char *expr)
#endif #endif
if (stack.size() != 1 || stack.back().type != 3) if (stack.size() != 1 || stack.back().type != 3)
log_error("Parser error in function expr `%s'in %s.\n", orig_expr, RTLIL::unescape_id(module->name)); log_error("Parser error in function expr `%s'in %s.\n", orig_expr, module);
return stack.back().sig; return stack.back().sig;
} }
@ -211,7 +211,7 @@ static void create_ff(RTLIL::Module *module, const LibertyAst *node)
auto [iq_sig, iqn_sig] = find_latch_ff_wires(module, node); auto [iq_sig, iqn_sig] = find_latch_ff_wires(module, node);
RTLIL::SigSpec clk_sig, data_sig, clear_sig, preset_sig; RTLIL::SigSpec clk_sig, data_sig, clear_sig, preset_sig;
bool clk_polarity = true, clear_polarity = true, preset_polarity = true; bool clk_polarity = true, clear_polarity = true, preset_polarity = true;
const std::string name = RTLIL::unescape_id(module->name); const std::string name = module->name.unescape();
std::optional<char> clear_preset_var1; std::optional<char> clear_preset_var1;
std::optional<char> clear_preset_var2; std::optional<char> clear_preset_var2;
@ -339,9 +339,9 @@ static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool fla
if (enable_sig.size() == 0 || data_sig.size() == 0) { if (enable_sig.size() == 0 || data_sig.size() == 0) {
if (!flag_ignore_miss_data_latch) if (!flag_ignore_miss_data_latch)
log_error("Latch cell %s has no data_in and/or enable attribute.\n", RTLIL::unescape_id(module->name)); log_error("Latch cell %s has no data_in and/or enable attribute.\n", module);
else else
log("Ignored latch cell %s with no data_in and/or enable attribute.\n", RTLIL::unescape_id(module->name)); log("Ignored latch cell %s with no data_in and/or enable attribute.\n", module);
return false; return false;
} }
@ -632,9 +632,9 @@ struct LibertyFrontend : public Frontend {
{ {
if (!flag_ignore_miss_dir) if (!flag_ignore_miss_dir)
{ {
log_error("Missing or invalid direction for pin %s on cell %s.\n", node->args.at(0), RTLIL::unescape_id(module->name)); log_error("Missing or invalid direction for pin %s on cell %s.\n", node->args.at(0), module);
} else { } else {
log("Ignoring cell %s with missing or invalid direction for pin %s.\n", RTLIL::unescape_id(module->name), node->args.at(0)); log("Ignoring cell %s with missing or invalid direction for pin %s.\n", module, node->args.at(0));
delete module; delete module;
goto skip_cell; goto skip_cell;
} }
@ -646,7 +646,7 @@ struct LibertyFrontend : public Frontend {
if (node->id == "bus" && node->args.size() == 1) if (node->id == "bus" && node->args.size() == 1)
{ {
if (flag_ignore_buses) { if (flag_ignore_buses) {
log("Ignoring cell %s with a bus interface %s.\n", RTLIL::unescape_id(module->name), node->args.at(0)); log("Ignoring cell %s with a bus interface %s.\n", module, node->args.at(0));
delete module; delete module;
goto skip_cell; goto skip_cell;
} }
@ -663,7 +663,7 @@ struct LibertyFrontend : public Frontend {
} }
if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal")) if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal"))
log_error("Missing or invalid direction for bus %s on cell %s.\n", node->args.at(0), RTLIL::unescape_id(module->name)); log_error("Missing or invalid direction for bus %s on cell %s.\n", node->args.at(0), module);
simple_comb_cell = false; simple_comb_cell = false;
@ -758,9 +758,9 @@ struct LibertyFrontend : public Frontend {
if (dir->value != "inout") { // allow inout with missing function, can be used for power pins if (dir->value != "inout") { // allow inout with missing function, can be used for power pins
if (!flag_ignore_miss_func) if (!flag_ignore_miss_func)
{ {
log_error("Missing function on output %s of cell %s.\n", RTLIL::unescape_id(wire->name), RTLIL::unescape_id(module->name)); log_error("Missing function on output %s of cell %s.\n", wire, module);
} else { } else {
log("Ignoring cell %s with missing function on output %s.\n", RTLIL::unescape_id(module->name), RTLIL::unescape_id(wire->name)); log("Ignoring cell %s with missing function on output %s.\n", module, wire);
delete module; delete module;
goto skip_cell; goto skip_cell;
} }

View file

@ -1492,10 +1492,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
design->add(module); design->add(module);
if (is_blackbox(nl)) { if (is_blackbox(nl)) {
log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name)); log("Importing blackbox module %s.\n", module);
module->set_bool_attribute(ID::blackbox); module->set_bool_attribute(ID::blackbox);
} else { } else {
log("Importing module %s.\n", RTLIL::id2cstr(module->name)); log("Importing module %s.\n", module);
} }
import_attributes(module->attributes, nl, nl); import_attributes(module->attributes, nl, nl);
if (module->name.isPublic()) if (module->name.isPublic())

View file

@ -136,7 +136,7 @@ struct PrintVisitor : DefaultVisitor<std::string> {
std::string Node::to_string() std::string Node::to_string()
{ {
return to_string([](Node n) { return RTLIL::unescape_id(n.name()); }); return to_string([](Node n) { return n.name().unescape(); });
} }
std::string Node::to_string(std::function<std::string(Node)> np) std::string Node::to_string(std::function<std::string(Node)> np)
@ -677,7 +677,7 @@ public:
factory.update_pending(pending, node); factory.update_pending(pending, node);
} else { } else {
DriveSpec driver = driver_map(DriveSpec(wire_chunk)); DriveSpec driver = driver_map(DriveSpec(wire_chunk));
check_undriven(driver, RTLIL::unescape_id(wire_chunk.wire->name)); check_undriven(driver, wire_chunk.wire->name.unescape());
Node node = enqueue(driver); Node node = enqueue(driver);
factory.suggest_name(node, wire_chunk.wire->name); factory.suggest_name(node, wire_chunk.wire->name);
factory.update_pending(pending, node); factory.update_pending(pending, node);
@ -695,7 +695,7 @@ public:
factory.update_pending(pending, node); factory.update_pending(pending, node);
} else { } else {
DriveSpec driver = driver_map(DriveSpec(port_chunk)); DriveSpec driver = driver_map(DriveSpec(port_chunk));
check_undriven(driver, RTLIL::unescape_id(port_chunk.cell->name) + " port " + RTLIL::unescape_id(port_chunk.port)); check_undriven(driver, port_chunk.cell->name.unescape() + " port " + port_chunk.port.unescape());
factory.update_pending(pending, enqueue(driver)); factory.update_pending(pending, enqueue(driver));
} }
} else { } else {
@ -744,7 +744,7 @@ void IR::topological_sort() {
log_warning("Combinational loop:\n"); log_warning("Combinational loop:\n");
for (int *i = begin; i != end; ++i) { for (int *i = begin; i != end; ++i) {
Node node(_graph[*i]); Node node(_graph[*i]);
log("- %s = %s\n", RTLIL::unescape_id(node.name()), node.to_string()); log("- %s = %s\n", node.name().unescape(), node.to_string());
} }
log("\n"); log("\n");
scc = true; scc = true;

View file

@ -588,7 +588,7 @@ namespace Functional {
_used_names.insert(std::move(name)); _used_names.insert(std::move(name));
} }
std::string unique_name(IdString suggestion) { std::string unique_name(IdString suggestion) {
std::string str = RTLIL::unescape_id(suggestion); std::string str = suggestion.unescape();
for(size_t i = 0; i < str.size(); i++) for(size_t i = 0; i < str.size(); i++)
if(!is_character_legal(str[i], i)) if(!is_character_legal(str[i], i))
str[i] = substitution_character; str[i] = substitution_character;

View file

@ -614,7 +614,7 @@ std::string log_const(const RTLIL::Const &value, bool autoint)
const char *log_id(const RTLIL::IdString &str) const char *log_id(const RTLIL::IdString &str)
{ {
std::string unescaped = RTLIL::unescape_id(str); std::string unescaped = str.unescape();
log_id_cache.push_back(strdup(unescaped.c_str())); log_id_cache.push_back(strdup(unescaped.c_str()));
return log_id_cache.back(); return log_id_cache.back();
} }

View file

@ -1579,7 +1579,7 @@ void RTLIL::Module::makeblackbox()
void RTLIL::Module::expand_interfaces(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &) void RTLIL::Module::expand_interfaces(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
{ {
log_error("Class doesn't support expand_interfaces (module: `%s')!\n", id2cstr(name)); log_error("Class doesn't support expand_interfaces (module: `%s')!\n", name.unescape());
} }
bool RTLIL::Module::reprocess_if_necessary(RTLIL::Design *) bool RTLIL::Module::reprocess_if_necessary(RTLIL::Design *)
@ -1591,7 +1591,7 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict<RTLIL::IdString
{ {
if (mayfail) if (mayfail)
return RTLIL::IdString(); return RTLIL::IdString();
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name)); log_error("Module `%s' is used with parameters but is not parametric!\n", name.unescape());
} }
@ -1599,7 +1599,7 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict<RTLIL::IdString
{ {
if (mayfail) if (mayfail)
return RTLIL::IdString(); return RTLIL::IdString();
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name)); log_error("Module `%s' is used with parameters but is not parametric!\n", name.unescape());
} }
size_t RTLIL::Module::count_id(RTLIL::IdString id) size_t RTLIL::Module::count_id(RTLIL::IdString id)

View file

@ -102,7 +102,7 @@ struct SatGen
else else
vec.push_back(bit == (undef_mode ? RTLIL::State::Sx : RTLIL::State::S1) ? ez->CONST_TRUE : ez->CONST_FALSE); vec.push_back(bit == (undef_mode ? RTLIL::State::Sx : RTLIL::State::S1) ? ez->CONST_TRUE : ez->CONST_FALSE);
} else { } else {
std::string wire_name = RTLIL::unescape_id(bit.wire->name); std::string wire_name = bit.wire->name.unescape();
std::string name = pf + std::string name = pf +
(bit.wire->width == 1 ? wire_name : stringf("%s [%d]", wire_name, bit.offset)); (bit.wire->width == 1 ? wire_name : stringf("%s [%d]", wire_name, bit.offset));
vec.push_back(ez->frozen_literal(name)); vec.push_back(ez->frozen_literal(name));

View file

@ -100,13 +100,13 @@ static const char *attr_prefix(ScopeinfoAttrs attrs)
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id) bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id)
{ {
log_assert(scopeinfo->type == ID($scopeinfo)); log_assert(scopeinfo->type == ID($scopeinfo));
return scopeinfo->has_attribute(attr_prefix(attrs) + RTLIL::unescape_id(id)); return scopeinfo->has_attribute(attr_prefix(attrs) + id.unescape());
} }
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id) RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id)
{ {
log_assert(scopeinfo->type == ID($scopeinfo)); log_assert(scopeinfo->type == ID($scopeinfo));
auto found = scopeinfo->attributes.find(attr_prefix(attrs) + RTLIL::unescape_id(id)); auto found = scopeinfo->attributes.find(attr_prefix(attrs) + id.unescape());
if (found == scopeinfo->attributes.end()) if (found == scopeinfo->attributes.end())
return RTLIL::Const(); return RTLIL::Const();
return found->second; return found->second;

View file

@ -66,11 +66,11 @@ ThreadPool::ThreadPool(int pool_size, std::function<void(int)> b)
: body(std::move(b)) : body(std::move(b))
{ {
#ifdef YOSYS_ENABLE_THREADS #ifdef YOSYS_ENABLE_THREADS
threads.reserve(pool_size); threads.reserve(pool_size);
for (int i = 0; i < pool_size; i++) for (int i = 0; i < pool_size; i++)
threads.emplace_back([i, this]{ body(i); }); threads.emplace_back([i, this]{ body(i); });
#else #else
log_assert(pool_size == 0); (void)pool_size;
#endif #endif
} }
@ -96,11 +96,13 @@ IntRange item_range_for_worker(int num_items, int thread_num, int num_threads)
} }
ParallelDispatchThreadPool::ParallelDispatchThreadPool(int pool_size) ParallelDispatchThreadPool::ParallelDispatchThreadPool(int pool_size)
: num_worker_threads_(std::max(1, pool_size) - 1)
{
#ifdef YOSYS_ENABLE_THREADS #ifdef YOSYS_ENABLE_THREADS
main_to_workers_signal.resize(num_worker_threads_, 0); : num_worker_threads_(std::max(1, pool_size) - 1)
#else
: num_worker_threads_(0)
#endif #endif
{
main_to_workers_signal.resize(num_worker_threads_, 0);
// Don't start the threads until we've constructed all our data members. // Don't start the threads until we've constructed all our data members.
thread_pool = std::make_unique<ThreadPool>(num_worker_threads_, [this](int thread_num){ thread_pool = std::make_unique<ThreadPool>(num_worker_threads_, [this](int thread_num){
run_worker(thread_num); run_worker(thread_num);
@ -109,14 +111,12 @@ ParallelDispatchThreadPool::ParallelDispatchThreadPool(int pool_size)
ParallelDispatchThreadPool::~ParallelDispatchThreadPool() ParallelDispatchThreadPool::~ParallelDispatchThreadPool()
{ {
#ifdef YOSYS_ENABLE_THREADS
if (num_worker_threads_ == 0) if (num_worker_threads_ == 0)
return; return;
current_work = nullptr; current_work = nullptr;
num_active_worker_threads_.store(num_worker_threads_, std::memory_order_relaxed); num_active_worker_threads_.store(num_worker_threads_, std::memory_order_relaxed);
signal_workers_start(); signal_workers_start();
wait_for_workers_done(); wait_for_workers_done();
#endif
} }
void ParallelDispatchThreadPool::run(std::function<void(const RunCtx &)> work, int max_threads) void ParallelDispatchThreadPool::run(std::function<void(const RunCtx &)> work, int max_threads)
@ -127,13 +127,11 @@ void ParallelDispatchThreadPool::run(std::function<void(const RunCtx &)> work, i
work({{0}, 1}); work({{0}, 1});
return; return;
} }
#ifdef YOSYS_ENABLE_THREADS
num_active_worker_threads_.store(num_active_worker_threads, std::memory_order_relaxed); num_active_worker_threads_.store(num_active_worker_threads, std::memory_order_relaxed);
current_work = &work; current_work = &work;
signal_workers_start(); signal_workers_start();
work({{0}, num_active_worker_threads + 1}); work({{0}, num_active_worker_threads + 1});
wait_for_workers_done(); wait_for_workers_done();
#endif
} }
void ParallelDispatchThreadPool::run_worker(int thread_num) void ParallelDispatchThreadPool::run_worker(int thread_num)

View file

@ -15,6 +15,33 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
// Redirect to no-op to avoid dependence on <mutex>
// and <condition_variable> in single-threaded builds
#ifdef YOSYS_ENABLE_THREADS
using Mutex = std::mutex;
using CondVar = std::condition_variable;
using UniqueLock = std::unique_lock<Mutex>;
using LockGuard = std::lock_guard<Mutex>;
#else
struct Mutex {
void lock() {}
void unlock() {}
bool try_lock() { return true; }
};
struct CondVar {
template <class L> void wait(L &) {}
template <class L, class P> void wait(L &, P) {}
void notify_one() {}
void notify_all() {}
};
struct UniqueLock {
UniqueLock(Mutex &) {}
};
struct LockGuard {
LockGuard(Mutex &) {}
};
#endif
// Concurrent queue implementation. Not fast, but simple. // Concurrent queue implementation. Not fast, but simple.
// Multi-producer, multi-consumer, optionally bounded. // Multi-producer, multi-consumer, optionally bounded.
// When YOSYS_ENABLE_THREADS is not defined, this is just a non-thread-safe non-blocking deque. // When YOSYS_ENABLE_THREADS is not defined, this is just a non-thread-safe non-blocking deque.
@ -27,26 +54,20 @@ public:
// Push an element into the queue. If it's at capacity, block until there is room. // Push an element into the queue. If it's at capacity, block until there is room.
void push_back(T t) void push_back(T t)
{ {
#ifdef YOSYS_ENABLE_THREADS UniqueLock lock(mutex);
std::unique_lock<std::mutex> lock(mutex);
not_full_condition.wait(lock, [this] { return static_cast<int>(contents.size()) < capacity; }); not_full_condition.wait(lock, [this] { return static_cast<int>(contents.size()) < capacity; });
if (contents.empty()) if (contents.empty())
not_empty_condition.notify_one(); not_empty_condition.notify_one();
#endif
log_assert(!closed); log_assert(!closed);
contents.push_back(std::move(t)); contents.push_back(std::move(t));
#ifdef YOSYS_ENABLE_THREADS
if (static_cast<int>(contents.size()) < capacity) if (static_cast<int>(contents.size()) < capacity)
not_full_condition.notify_one(); not_full_condition.notify_one();
#endif
} }
// Signal that no more elements will be produced. `pop_front()` will return nullopt. // Signal that no more elements will be produced. `pop_front()` will return nullopt.
void close() void close()
{ {
#ifdef YOSYS_ENABLE_THREADS UniqueLock lock(mutex);
std::unique_lock<std::mutex> lock(mutex);
not_empty_condition.notify_all(); not_empty_condition.notify_all();
#endif
closed = true; closed = true;
} }
// Pop an element from the queue. Blocks until an element is available // Pop an element from the queue. Blocks until an element is available
@ -62,39 +83,28 @@ public:
return pop_front_internal(false); return pop_front_internal(false);
} }
private: private:
#ifdef YOSYS_ENABLE_THREADS
std::optional<T> pop_front_internal(bool wait) std::optional<T> pop_front_internal(bool wait)
{ {
std::unique_lock<std::mutex> lock(mutex); UniqueLock lock(mutex);
if (wait) { if (wait) {
not_empty_condition.wait(lock, [this] { return !contents.empty() || closed; }); not_empty_condition.wait(lock, [this] { return !contents.empty() || closed; });
} }
#else
std::optional<T> pop_front_internal(bool)
{
#endif
if (contents.empty()) if (contents.empty())
return std::nullopt; return std::nullopt;
#ifdef YOSYS_ENABLE_THREADS
if (static_cast<int>(contents.size()) == capacity) if (static_cast<int>(contents.size()) == capacity)
not_full_condition.notify_one(); not_full_condition.notify_one();
#endif
T result = std::move(contents.front()); T result = std::move(contents.front());
contents.pop_front(); contents.pop_front();
#ifdef YOSYS_ENABLE_THREADS
if (!contents.empty()) if (!contents.empty())
not_empty_condition.notify_one(); not_empty_condition.notify_one();
#endif
return std::move(result); return std::move(result);
} }
#ifdef YOSYS_ENABLE_THREADS Mutex mutex;
std::mutex mutex;
// Signals one waiter thread when the queue changes and is not full. // Signals one waiter thread when the queue changes and is not full.
std::condition_variable not_full_condition; CondVar not_full_condition;
// Signals one waiter thread when the queue changes and is not empty. // Signals one waiter thread when the queue changes and is not empty.
std::condition_variable not_empty_condition; CondVar not_empty_condition;
#endif
std::deque<T> contents; std::deque<T> contents;
int capacity; int capacity;
bool closed = false; bool closed = false;
@ -245,15 +255,14 @@ private:
// is maintained. // is maintained.
std::atomic<int> num_active_worker_threads_ = 0; std::atomic<int> num_active_worker_threads_ = 0;
#ifdef YOSYS_ENABLE_THREADS
// Not especially efficient for large numbers of threads. Worker wakeup could scale // Not especially efficient for large numbers of threads. Worker wakeup could scale
// better by conceptually organising workers into a tree and having workers wake // better by conceptually organising workers into a tree and having workers wake
// up their children. // up their children.
std::mutex main_to_workers_signal_mutex; Mutex main_to_workers_signal_mutex;
std::condition_variable main_to_workers_signal_cv; CondVar main_to_workers_signal_cv;
std::vector<uint8_t> main_to_workers_signal; std::vector<uint8_t> main_to_workers_signal;
void signal_workers_start() { void signal_workers_start() {
std::unique_lock lock(main_to_workers_signal_mutex); UniqueLock lock(main_to_workers_signal_mutex);
int num_active_worker_threads = num_active_worker_threads_.load(std::memory_order_relaxed); int num_active_worker_threads = num_active_worker_threads_.load(std::memory_order_relaxed);
std::fill(main_to_workers_signal.begin(), main_to_workers_signal.begin() + num_active_worker_threads, 1); std::fill(main_to_workers_signal.begin(), main_to_workers_signal.begin() + num_active_worker_threads, 1);
// When `num_active_worker_threads_` is small compared to `num_worker_threads_`, we have a "thundering herd" // When `num_active_worker_threads_` is small compared to `num_worker_threads_`, we have a "thundering herd"
@ -261,14 +270,14 @@ private:
main_to_workers_signal_cv.notify_all(); main_to_workers_signal_cv.notify_all();
} }
void worker_wait_for_start(int thread_num) { void worker_wait_for_start(int thread_num) {
std::unique_lock lock(main_to_workers_signal_mutex); UniqueLock lock(main_to_workers_signal_mutex);
main_to_workers_signal_cv.wait(lock, [this, thread_num] { return main_to_workers_signal[thread_num] > 0; }); main_to_workers_signal_cv.wait(lock, [this, thread_num] { return main_to_workers_signal[thread_num] > 0; });
main_to_workers_signal[thread_num] = 0; main_to_workers_signal[thread_num] = 0;
} }
std::atomic<int> done_workers = 0; std::atomic<int> done_workers = 0;
std::mutex workers_to_main_signal_mutex; Mutex workers_to_main_signal_mutex;
std::condition_variable workers_to_main_signal_cv; CondVar workers_to_main_signal_cv;
void signal_worker_done() { void signal_worker_done() {
// Must read `num_active_worker_threads_` before we increment `d`! Otherwise // Must read `num_active_worker_threads_` before we increment `d`! Otherwise
// it is possible we would increment `d`, and then another worker signals the // it is possible we would increment `d`, and then another worker signals the
@ -277,19 +286,18 @@ private:
int num_active_worker_threads = num_active_worker_threads_.load(std::memory_order_relaxed); int num_active_worker_threads = num_active_worker_threads_.load(std::memory_order_relaxed);
int d = done_workers.fetch_add(1, std::memory_order_release); int d = done_workers.fetch_add(1, std::memory_order_release);
if (d + 1 == num_active_worker_threads) { if (d + 1 == num_active_worker_threads) {
std::unique_lock lock(workers_to_main_signal_mutex); UniqueLock lock(workers_to_main_signal_mutex);
workers_to_main_signal_cv.notify_all(); workers_to_main_signal_cv.notify_all();
} }
} }
void wait_for_workers_done() { void wait_for_workers_done() {
std::unique_lock lock(workers_to_main_signal_mutex); UniqueLock lock(workers_to_main_signal_mutex);
workers_to_main_signal_cv.wait(lock, [this] { workers_to_main_signal_cv.wait(lock, [this] {
int num_active_worker_threads = num_active_worker_threads_.load(std::memory_order_relaxed); int num_active_worker_threads = num_active_worker_threads_.load(std::memory_order_relaxed);
return done_workers.load(std::memory_order_acquire) == num_active_worker_threads; return done_workers.load(std::memory_order_acquire) == num_active_worker_threads;
}); });
done_workers.store(0, std::memory_order_relaxed); done_workers.store(0, std::memory_order_relaxed);
} }
#endif
// Ensure `thread_pool` is destroyed before any other members, // Ensure `thread_pool` is destroyed before any other members,
// forcing all threads to be joined before destroying the // forcing all threads to be joined before destroying the
// members (e.g. workers_to_main_signal_mutex) they might be using. // members (e.g. workers_to_main_signal_mutex) they might be using.
@ -301,15 +309,11 @@ class ConcurrentStack
{ {
public: public:
void push_back(T &&t) { void push_back(T &&t) {
#ifdef YOSYS_ENABLE_THREADS LockGuard lock(mutex);
std::lock_guard<std::mutex> lock(mutex);
#endif
contents.push_back(std::move(t)); contents.push_back(std::move(t));
} }
std::optional<T> try_pop_back() { std::optional<T> try_pop_back() {
#ifdef YOSYS_ENABLE_THREADS LockGuard lock(mutex);
std::lock_guard<std::mutex> lock(mutex);
#endif
if (contents.empty()) if (contents.empty())
return std::nullopt; return std::nullopt;
T result = std::move(contents.back()); T result = std::move(contents.back());
@ -317,9 +321,7 @@ public:
return result; return result;
} }
private: private:
#ifdef YOSYS_ENABLE_THREADS Mutex mutex;
std::mutex mutex;
#endif
std::vector<T> contents; std::vector<T> contents;
}; };
@ -596,12 +598,12 @@ public:
return; return;
bool was_empty; bool was_empty;
{ {
std::unique_lock lock(thread_state.batches_lock); UniqueLock lock(thread_state.batches_lock);
was_empty = thread_state.batches.empty(); was_empty = thread_state.batches.empty();
thread_state.batches.push_back(std::move(thread_state.next_batch)); thread_state.batches.push_back(std::move(thread_state.next_batch));
} }
if (was_empty) { if (was_empty) {
std::unique_lock lock(waiters_lock); UniqueLock lock(waiters_lock);
if (num_waiters > 0) { if (num_waiters > 0) {
waiters_cv.notify_one(); waiters_cv.notify_one();
} }
@ -617,7 +619,7 @@ public:
return std::move(thread_state.next_batch); return std::move(thread_state.next_batch);
// Empty our own work queue first. // Empty our own work queue first.
{ {
std::unique_lock lock(thread_state.batches_lock); UniqueLock lock(thread_state.batches_lock);
if (!thread_state.batches.empty()) { if (!thread_state.batches.empty()) {
std::vector<T> batch = std::move(thread_state.batches.back()); std::vector<T> batch = std::move(thread_state.batches.back());
thread_state.batches.pop_back(); thread_state.batches.pop_back();
@ -634,8 +636,9 @@ public:
// them will eventually enter this loop and there will be no further // them will eventually enter this loop and there will be no further
// notifications on waiters_cv, so all will eventually increment // notifications on waiters_cv, so all will eventually increment
// num_waiters and wait, so num_waiters == num_threads() // num_waiters and wait, so num_waiters == num_threads()
// will become true. // will become true. In single-threaded builds, num_threads() is 1,
std::unique_lock lock(waiters_lock); // so we always terminate on the first iteration.
UniqueLock lock(waiters_lock);
++num_waiters; ++num_waiters;
if (num_waiters == num_threads()) { if (num_waiters == num_threads()) {
waiters_cv.notify_all(); waiters_cv.notify_all();
@ -654,7 +657,7 @@ private:
for (int i = 1; i < num_threads(); i++) { for (int i = 1; i < num_threads(); i++) {
int other_thread_num = (thread.thread_num + i) % num_threads(); int other_thread_num = (thread.thread_num + i) % num_threads();
ThreadState &other_thread_state = thread_states[other_thread_num]; ThreadState &other_thread_state = thread_states[other_thread_num];
std::unique_lock lock(other_thread_state.batches_lock); UniqueLock lock(other_thread_state.batches_lock);
if (!other_thread_state.batches.empty()) { if (!other_thread_state.batches.empty()) {
std::vector<T> batch = std::move(other_thread_state.batches.front()); std::vector<T> batch = std::move(other_thread_state.batches.front());
other_thread_state.batches.pop_front(); other_thread_state.batches.pop_front();
@ -670,15 +673,15 @@ private:
// Entirely thread-local. // Entirely thread-local.
std::vector<T> next_batch; std::vector<T> next_batch;
std::mutex batches_lock; Mutex batches_lock;
// Only the associated thread ever adds to this, and only at the back. // Only the associated thread ever adds to this, and only at the back.
// Other threads can remove elements from the front. // Other threads can remove elements from the front.
std::deque<std::vector<T>> batches; std::deque<std::vector<T>> batches;
}; };
std::vector<ThreadState> thread_states; std::vector<ThreadState> thread_states;
std::mutex waiters_lock; Mutex waiters_lock;
std::condition_variable waiters_cv; CondVar waiters_cv;
// Number of threads waiting for work. Their queues are empty. // Number of threads waiting for work. Their queues are empty.
int num_waiters = 0; int num_waiters = 0;
}; };

View file

@ -953,7 +953,7 @@ static char *readline_obj_generator(const char *text, int state)
if (design->selected_active_module.empty()) if (design->selected_active_module.empty())
{ {
for (auto mod : design->modules()) for (auto mod : design->modules())
if (RTLIL::unescape_id(mod->name).compare(0, len, text) == 0) if (mod->name.unescape().compare(0, len, text) == 0)
obj_names.push_back(strdup(mod->name.unescape().c_str())); obj_names.push_back(strdup(mod->name.unescape().c_str()));
} }
else if (design->module(design->selected_active_module) != nullptr) else if (design->module(design->selected_active_module) != nullptr)
@ -961,19 +961,19 @@ static char *readline_obj_generator(const char *text, int state)
RTLIL::Module *module = design->module(design->selected_active_module); RTLIL::Module *module = design->module(design->selected_active_module);
for (auto w : module->wires()) for (auto w : module->wires())
if (RTLIL::unescape_id(w->name).compare(0, len, text) == 0) if (w->name.unescape().compare(0, len, text) == 0)
obj_names.push_back(strdup(w->name.unescape().c_str())); obj_names.push_back(strdup(w->name.unescape().c_str()));
for (auto &it : module->memories) for (auto &it : module->memories)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) if (it.first.unescape().compare(0, len, text) == 0)
obj_names.push_back(strdup(it.first.unescape().c_str())); obj_names.push_back(strdup(it.first.unescape().c_str()));
for (auto cell : module->cells()) for (auto cell : module->cells())
if (RTLIL::unescape_id(cell->name).compare(0, len, text) == 0) if (cell->name.unescape().compare(0, len, text) == 0)
obj_names.push_back(strdup(cell->name.unescape().c_str())); obj_names.push_back(strdup(cell->name.unescape().c_str()));
for (auto &it : module->processes) for (auto &it : module->processes)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) if (it.first.unescape().compare(0, len, text) == 0)
obj_names.push_back(strdup(it.first.unescape().c_str())); obj_names.push_back(strdup(it.first.unescape().c_str()));
} }

View file

@ -71,10 +71,10 @@ struct LibertyStubber {
std::sort(sorted_ports.begin(), sorted_ports.end(), cmp); std::sort(sorted_ports.begin(), sorted_ports.end(), cmp);
std::string clock_pin_name = ""; std::string clock_pin_name = "";
for (auto x : sorted_ports) { for (auto x : sorted_ports) {
std::string port_name = RTLIL::unescape_id(x); std::string port_name = x.unescape();
bool is_input = base_type.inputs.count(x); bool is_input = base_type.inputs.count(x);
bool is_output = base_type.outputs.count(x); bool is_output = base_type.outputs.count(x);
f << "\t\tpin (" << RTLIL::unescape_id(x.str()) << ") {\n"; f << "\t\tpin (" << x.unescape() << ") {\n";
if (is_input && !is_output) { if (is_input && !is_output) {
i.item("direction", "input"); i.item("direction", "input");
} else if (!is_input && is_output) { } else if (!is_input && is_output) {
@ -132,7 +132,7 @@ struct LibertyStubber {
for (auto x : derived->ports) { for (auto x : derived->ports) {
bool is_input = base_type.inputs.count(x); bool is_input = base_type.inputs.count(x);
bool is_output = base_type.outputs.count(x); bool is_output = base_type.outputs.count(x);
f << "\t\tpin (" << RTLIL::unescape_id(x.str()) << ") {\n"; f << "\t\tpin (" << x.unescape() << ") {\n";
if (is_input && !is_output) { if (is_input && !is_output) {
f << "\t\t\tdirection : input;\n"; f << "\t\t\tdirection : input;\n";
} else if (!is_input && is_output) { } else if (!is_input && is_output) {

View file

@ -244,7 +244,7 @@ struct PortarcsPass : Pass {
if (draw_mode) { if (draw_mode) {
auto bit_str = [](SigBit bit) { auto bit_str = [](SigBit bit) {
return stringf("%s%d", RTLIL::unescape_id(bit.wire->name.str()), bit.offset); return stringf("%s%d", bit.wire, bit.offset);
}; };
std::vector<std::string> headings; std::vector<std::string> headings;

View file

@ -621,7 +621,7 @@ struct RenamePass : public Pass {
RTLIL::Module *module_to_rename = nullptr; RTLIL::Module *module_to_rename = nullptr;
for (auto module : design->modules()) for (auto module : design->modules())
if (module->name == from_name || RTLIL::unescape_id(module->name) == from_name) { if (module->name == from_name || module->name.unescape() == from_name) {
module_to_rename = module; module_to_rename = module;
break; break;
} }

View file

@ -87,7 +87,7 @@ struct SccWorker
RTLIL::Cell *c = cellStack.back(); RTLIL::Cell *c = cellStack.back();
cellStack.pop_back(); cellStack.pop_back();
cellsOnStack.erase(c); cellsOnStack.erase(c);
log(" %s", RTLIL::id2cstr(c->name)); log(" %s", c);
cell2scc[c] = sccList.size(); cell2scc[c] = sccList.size();
scc.insert(c); scc.insert(c);
} }
@ -201,7 +201,7 @@ struct SccWorker
if (!nofeedbackMode && cellToNextCell[cell].count(cell)) { if (!nofeedbackMode && cellToNextCell[cell].count(cell)) {
log("Found an SCC:"); log("Found an SCC:");
pool<RTLIL::Cell*> scc; pool<RTLIL::Cell*> scc;
log(" %s", RTLIL::id2cstr(cell->name)); log(" %s", cell);
cell2scc[cell] = sccList.size(); cell2scc[cell] = sccList.size();
scc.insert(cell); scc.insert(cell);
sccList.push_back(scc); sccList.push_back(scc);
@ -221,7 +221,7 @@ struct SccWorker
run(cell, 0, maxDepth); run(cell, 0, maxDepth);
} }
log("Found %d SCCs in module %s.\n", int(sccList.size()), RTLIL::id2cstr(module->name)); log("Found %d SCCs in module %s.\n", int(sccList.size()), module);
} }
void select(RTLIL::Selection &sel) void select(RTLIL::Selection &sel)

View file

@ -25,8 +25,6 @@
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
using RTLIL::id2cstr;
static std::vector<RTLIL::Selection> work_stack; static std::vector<RTLIL::Selection> work_stack;
static bool match_ids(RTLIL::IdString id, const std::string &pattern) static bool match_ids(RTLIL::IdString id, const std::string &pattern)
@ -1022,9 +1020,9 @@ static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::S
for (auto mod : design->all_selected_modules()) for (auto mod : design->all_selected_modules())
{ {
if (whole_modules && sel->selected_whole_module(mod->name)) if (whole_modules && sel->selected_whole_module(mod->name))
desc += stringf("%s\n", id2cstr(mod->name)); desc += stringf("%s\n", mod);
for (auto it : mod->selected_members()) for (auto it : mod->selected_members())
desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it->name)); desc += stringf("%s/%s\n", mod, it);
} }
if (push_selection) design->pop_selection(); if (push_selection) design->pop_selection();
return desc; return desc;
@ -1414,7 +1412,7 @@ struct SelectPass : public Pass {
if (arg == "-module" && argidx+1 < args.size()) { if (arg == "-module" && argidx+1 < args.size()) {
RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]); RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]);
if (design->module(mod_name) == nullptr) if (design->module(mod_name) == nullptr)
log_cmd_error("No such module: %s\n", id2cstr(mod_name)); log_cmd_error("No such module: %s\n", mod_name.unescape());
design->selected_active_module = mod_name.str(); design->selected_active_module = mod_name.str();
got_module = true; got_module = true;
continue; continue;
@ -1527,10 +1525,10 @@ struct SelectPass : public Pass {
for (auto mod : design->all_selected_modules()) for (auto mod : design->all_selected_modules())
{ {
if (sel->selected_whole_module(mod->name) && list_mode) if (sel->selected_whole_module(mod->name) && list_mode)
log("%s\n", id2cstr(mod->name)); log("%s\n", mod);
if (!list_mod_mode) if (!list_mod_mode)
for (auto it : mod->selected_members()) for (auto it : mod->selected_members())
LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it->name)) LOG_OBJECT("%s/%s\n", mod->name.unescape().c_str(), it->name.unescape().c_str())
} }
if (count_mode) if (count_mode)
{ {
@ -1654,10 +1652,10 @@ struct SelectPass : public Pass {
if (sel.full_selection) if (sel.full_selection)
log("*\n"); log("*\n");
for (auto &it : sel.selected_modules) for (auto &it : sel.selected_modules)
log("%s\n", id2cstr(it)); log("%s\n", it.unescape());
for (auto &it : sel.selected_members) for (auto &it : sel.selected_members)
for (auto &it2 : it.second) for (auto &it2 : it.second)
log("%s/%s\n", id2cstr(it.first), id2cstr(it2)); log("%s/%s\n", it.first.unescape(), it2.unescape());
return; return;
} }
@ -1779,7 +1777,7 @@ static void log_matches(const char *title, Module *module, const T &list)
log("\n%d %s:\n", int(matches.size()), title); log("\n%d %s:\n", int(matches.size()), title);
std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str()); std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str());
for (auto id : matches) for (auto id : matches)
log(" %s\n", RTLIL::id2cstr(id)); log(" %s\n", id.unescape());
} }
} }

View file

@ -549,7 +549,7 @@ struct ShowWorker
net_conn_map[node].color = nextColor(sig, net_conn_map[node].color); net_conn_map[node].color = nextColor(sig, net_conn_map[node].color);
} }
std::string proc_src = RTLIL::unescape_id(proc->name); std::string proc_src = proc->name.unescape();
if (proc->attributes.count(ID::src) > 0) if (proc->attributes.count(ID::src) > 0)
proc_src = proc->attributes.at(ID::src).decode_string(); proc_src = proc->attributes.at(ID::src).decode_string();
fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\", %s];\n", pidx, findLabel(proc->name.str()), proc_src.c_str(), findColor(proc->name).c_str()); fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\", %s];\n", pidx, findLabel(proc->name.str()), proc_src.c_str(), findColor(proc->name).c_str());

View file

@ -144,10 +144,10 @@ struct TestSelectPass : public Pass {
for (auto *mod : sub_sel) { for (auto *mod : sub_sel) {
if (mod->is_selected_whole()) { if (mod->is_selected_whole()) {
log_debug(" Adding %s.\n", id2cstr(mod->name)); log_debug(" Adding %s.\n", mod);
selected_modules.insert(mod->name); selected_modules.insert(mod->name);
} else for (auto *memb : mod->selected_members()) { } else for (auto *memb : mod->selected_members()) {
log_debug(" Adding %s.%s.\n", id2cstr(mod->name), id2cstr(memb->name)); log_debug(" Adding %s.%s.\n", mod, memb);
selected_members[mod->name].insert(memb); selected_members[mod->name].insert(memb);
} }
} }

View file

@ -227,7 +227,7 @@ struct WrapcellPass : Pass {
if (!unused_outputs.empty()) { if (!unused_outputs.empty()) {
context.unused_outputs += "_unused"; context.unused_outputs += "_unused";
for (auto chunk : collect_chunks(unused_outputs)) for (auto chunk : collect_chunks(unused_outputs))
context.unused_outputs += "_" + RTLIL::unescape_id(chunk.format(cell)); context.unused_outputs += "_" + chunk.format(cell).unescape();
} }
std::optional<std::string> unescaped_name = format_with_params(name_fmt, cell->parameters, context); std::optional<std::string> unescaped_name = format_with_params(name_fmt, cell->parameters, context);

View file

@ -285,11 +285,11 @@ struct EquivMakeWorker
for (int i = 0; i < wire->width; i++) { for (int i = 0; i < wire->width; i++) {
if (undriven_bits.count(assign_map(SigBit(gold_wire, i)))) { if (undriven_bits.count(assign_map(SigBit(gold_wire, i)))) {
log(" Skipping signal bit %s [%d]: undriven on gold side.\n", id2cstr(gold_wire->name), i); log(" Skipping signal bit %s [%d]: undriven on gold side.\n", gold_wire, i);
continue; continue;
} }
if (undriven_bits.count(assign_map(SigBit(gate_wire, i)))) { if (undriven_bits.count(assign_map(SigBit(gate_wire, i)))) {
log(" Skipping signal bit %s [%d]: undriven on gate side.\n", id2cstr(gate_wire->name), i); log(" Skipping signal bit %s [%d]: undriven on gate side.\n", gate_wire, i);
continue; continue;
} }
equiv_mod->addEquiv(NEW_ID, SigSpec(gold_wire, i), SigSpec(gate_wire, i), SigSpec(wire, i)); equiv_mod->addEquiv(NEW_ID, SigSpec(gold_wire, i), SigSpec(gate_wire, i), SigSpec(wire, i));

View file

@ -61,7 +61,7 @@ ret_false:
if (recursion_monitor.count(cellport.first)) { if (recursion_monitor.count(cellport.first)) {
log_warning("logic loop in mux tree at signal %s in module %s.\n", log_warning("logic loop in mux tree at signal %s in module %s.\n",
log_signal(sig), RTLIL::id2cstr(module->name)); log_signal(sig), module);
goto ret_false; goto ret_false;
} }

View file

@ -39,7 +39,7 @@ static void fm_set_fsm_print(RTLIL::Cell *cell, RTLIL::Module *module, FsmData &
for (int i = fsm_data.state_bits-1; i >= 0; i--) for (int i = fsm_data.state_bits-1; i >= 0; i--)
fprintf(f, " %s_reg[%d]", name[0] == '\\' ? name.substr(1).c_str() : name.c_str(), i); fprintf(f, " %s_reg[%d]", name[0] == '\\' ? name.substr(1).c_str() : name.c_str(), i);
fprintf(f, " } -name {%s_%s} {%s:/WORK/%s}\n", prefix, RTLIL::unescape_id(name).c_str(), fprintf(f, " } -name {%s_%s} {%s:/WORK/%s}\n", prefix, RTLIL::unescape_id(name).c_str(),
prefix, RTLIL::unescape_id(module->name).c_str()); prefix, module->name.unescape().c_str());
fprintf(f, "set_fsm_encoding {"); fprintf(f, "set_fsm_encoding {");
for (int i = 0; i < GetSize(fsm_data.state_table); i++) { for (int i = 0; i < GetSize(fsm_data.state_table); i++) {
@ -49,7 +49,7 @@ static void fm_set_fsm_print(RTLIL::Cell *cell, RTLIL::Module *module, FsmData &
} }
fprintf(f, " } -name {%s_%s} {%s:/WORK/%s}\n", fprintf(f, " } -name {%s_%s} {%s:/WORK/%s}\n",
prefix, RTLIL::unescape_id(name).c_str(), prefix, RTLIL::unescape_id(name).c_str(),
prefix, RTLIL::unescape_id(module->name).c_str()); prefix, module->name.unescape().c_str());
} }
static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fsm_file, FILE *encfile, std::string default_encoding) static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fsm_file, FILE *encfile, std::string default_encoding)

View file

@ -281,13 +281,13 @@ struct FlattenWorker
if (attr.first == ID::hdlname) if (attr.first == ID::hdlname)
scopeinfo->attributes.insert(attr); scopeinfo->attributes.insert(attr);
else else
scopeinfo->attributes.emplace(stringf("\\cell_%s", RTLIL::unescape_id(attr.first)), attr.second); scopeinfo->attributes.emplace(stringf("\\cell_%s", attr.first.unescape()), attr.second);
} }
for (auto const &attr : tpl->attributes) for (auto const &attr : tpl->attributes)
scopeinfo->attributes.emplace(stringf("\\module_%s", RTLIL::unescape_id(attr.first)), attr.second); scopeinfo->attributes.emplace(stringf("\\module_%s", attr.first.unescape()), attr.second);
scopeinfo->attributes.emplace(ID(module), RTLIL::unescape_id(tpl->name)); scopeinfo->attributes.emplace(ID(module), tpl->name.unescape());
} }
module->remove(cell); module->remove(cell);

View file

@ -50,7 +50,7 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
if (cell->type.begins_with("$") && !cell->type.begins_with("$__")) if (cell->type.begins_with("$") && !cell->type.begins_with("$__"))
continue; continue;
for (auto &pattern : celltypes) for (auto &pattern : celltypes)
if (patmatch(pattern.c_str(), RTLIL::unescape_id(cell->type).c_str())) if (patmatch(pattern.c_str(), cell->type.unescape().c_str()))
found_celltypes.insert(cell->type); found_celltypes.insert(cell->type);
} }
@ -87,7 +87,7 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
if (decl.index > 0) { if (decl.index > 0) {
portwidths[decl.portname] = max(portwidths[decl.portname], 1); portwidths[decl.portname] = max(portwidths[decl.portname], 1);
portwidths[decl.portname] = max(portwidths[decl.portname], portwidths[stringf("$%d", decl.index)]); portwidths[decl.portname] = max(portwidths[decl.portname], portwidths[stringf("$%d", decl.index)]);
log(" port %d: %s [%d:0] %s\n", decl.index, decl.input ? decl.output ? "inout" : "input" : "output", portwidths[decl.portname]-1, RTLIL::id2cstr(decl.portname)); log(" port %d: %s [%d:0] %s\n", decl.index, decl.input ? decl.output ? "inout" : "input" : "output", portwidths[decl.portname]-1, RTLIL::unescape_id(decl.portname));
if (indices.count(decl.index) > ports.size()) if (indices.count(decl.index) > ports.size())
log_error("Port index (%d) exceeds number of found ports (%d).\n", decl.index, int(ports.size())); log_error("Port index (%d) exceeds number of found ports (%d).\n", decl.index, int(ports.size()));
if (indices.count(decl.index) == 0) if (indices.count(decl.index) == 0)
@ -100,7 +100,7 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
while (portnames.size() > 0) { while (portnames.size() > 0) {
RTLIL::IdString portname = *portnames.begin(); RTLIL::IdString portname = *portnames.begin();
for (auto &decl : portdecls) for (auto &decl : portdecls)
if (decl.index == 0 && patmatch(decl.portname.c_str(), RTLIL::unescape_id(portname).c_str())) { if (decl.index == 0 && patmatch(decl.portname.c_str(), portname.unescape().c_str())) {
generate_port_decl_t d = decl; generate_port_decl_t d = decl;
d.portname = portname.str(); d.portname = portname.str();
d.index = *indices.begin(); d.index = *indices.begin();
@ -108,10 +108,10 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
indices.erase(d.index); indices.erase(d.index);
ports[d.index-1] = d; ports[d.index-1] = d;
portwidths[d.portname] = max(portwidths[d.portname], 1); portwidths[d.portname] = max(portwidths[d.portname], 1);
log(" port %d: %s [%d:0] %s\n", d.index, d.input ? d.output ? "inout" : "input" : "output", portwidths[d.portname]-1, RTLIL::id2cstr(d.portname)); log(" port %d: %s [%d:0] %s\n", d.index, d.input ? d.output ? "inout" : "input" : "output", portwidths[d.portname]-1, RTLIL::unescape_id(d.portname));
goto found_matching_decl; goto found_matching_decl;
} }
log_error("Can't match port %s.\n", RTLIL::id2cstr(portname)); log_error("Can't match port %s.\n", portname.unescape());
found_matching_decl:; found_matching_decl:;
portnames.erase(portname); portnames.erase(portname);
} }
@ -133,9 +133,9 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
mod->fixup_ports(); mod->fixup_ports();
for (auto &para : parameters) for (auto &para : parameters)
log(" ignoring parameter %s.\n", RTLIL::id2cstr(para)); log(" ignoring parameter %s.\n", para.unescape());
log(" module %s created.\n", RTLIL::id2cstr(mod->name)); log(" module %s created.\n", mod);
} }
} }
@ -397,7 +397,7 @@ RTLIL::Module *get_module(RTLIL::Design &design,
}; };
for (auto &ext : extensions_list) { for (auto &ext : extensions_list) {
std::string filename = dir + "/" + RTLIL::unescape_id(cell.type) + ext.first; std::string filename = dir + "/" + cell.type.unescape() + ext.first;
if (!check_file_exists(filename)) if (!check_file_exists(filename))
continue; continue;
@ -597,7 +597,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
int idx = it.second.first, num = it.second.second; int idx = it.second.first, num = it.second.second;
if (design->module(cell->type) == nullptr) if (design->module(cell->type) == nullptr)
log_error("Array cell `%s.%s' of unknown type `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); log_error("Array cell `%s.%s' of unknown type `%s'.\n", module, cell, cell->type.unescape());
RTLIL::Module *mod = design->module(cell->type); RTLIL::Module *mod = design->module(cell->type);
@ -613,12 +613,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
} }
} }
if (mod->wire(portname) == nullptr) if (mod->wire(portname) == nullptr)
log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", module, cell, conn.first.unescape());
int port_size = mod->wire(portname)->width; int port_size = mod->wire(portname)->width;
if (conn_size == port_size || conn_size == 0) if (conn_size == port_size || conn_size == 0)
continue; continue;
if (conn_size != port_size*num) if (conn_size != port_size*num)
log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", module, cell, conn.first.unescape());
conn.second = conn.second.extract(port_size*idx, port_size); conn.second = conn.second.extract(port_size*idx, port_size);
} }
} }
@ -1219,7 +1219,7 @@ struct HierarchyPass : public Pass {
if (read_id_num(p.first, &id)) { if (read_id_num(p.first, &id)) {
if (id <= 0 || id > GetSize(cell_mod->avail_parameters)) { if (id <= 0 || id > GetSize(cell_mod->avail_parameters)) {
log(" Failed to map positional parameter %d of cell %s.%s (%s).\n", log(" Failed to map positional parameter %d of cell %s.%s (%s).\n",
id, RTLIL::id2cstr(mod->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); id, mod, cell, cell->type.unescape());
} else { } else {
params_rename.insert(std::make_pair(p.first, cell_mod->avail_parameters[id - 1])); params_rename.insert(std::make_pair(p.first, cell_mod->avail_parameters[id - 1]));
} }
@ -1241,7 +1241,7 @@ struct HierarchyPass : public Pass {
RTLIL::Module *module = work.first; RTLIL::Module *module = work.first;
RTLIL::Cell *cell = work.second; RTLIL::Cell *cell = work.second;
log("Mapping positional arguments of cell %s.%s (%s).\n", log("Mapping positional arguments of cell %s.%s (%s).\n",
RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); module, cell, cell->type.unescape());
dict<RTLIL::IdString, RTLIL::SigSpec> new_connections; dict<RTLIL::IdString, RTLIL::SigSpec> new_connections;
for (auto &conn : cell->connections()) { for (auto &conn : cell->connections()) {
int id; int id;
@ -1249,7 +1249,7 @@ struct HierarchyPass : public Pass {
std::pair<RTLIL::Module*,int> key(design->module(cell->type), id); std::pair<RTLIL::Module*,int> key(design->module(cell->type), id);
if (pos_map.count(key) == 0) { if (pos_map.count(key) == 0) {
log(" Failed to map positional argument %d of cell %s.%s (%s).\n", log(" Failed to map positional argument %d of cell %s.%s (%s).\n",
id, RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); id, module, cell, cell->type.unescape());
new_connections[conn.first] = conn.second; new_connections[conn.first] = conn.second;
} else } else
new_connections[pos_map.at(key)] = conn.second; new_connections[pos_map.at(key)] = conn.second;
@ -1283,7 +1283,7 @@ struct HierarchyPass : public Pass {
if (m == nullptr) if (m == nullptr)
log_error("Cell %s.%s (%s) has implicit port connections but the module it instantiates is unknown.\n", log_error("Cell %s.%s (%s) has implicit port connections but the module it instantiates is unknown.\n",
RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); module, cell, cell->type.unescape());
// Need accurate port widths for error checking; so must derive blackboxes with dynamic port widths // Need accurate port widths for error checking; so must derive blackboxes with dynamic port widths
if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) { if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) {
@ -1312,11 +1312,11 @@ struct HierarchyPass : public Pass {
if (parent_wire == nullptr) if (parent_wire == nullptr)
log_error("No matching wire for implicit port connection `%s' of cell %s.%s (%s).\n", log_error("No matching wire for implicit port connection `%s' of cell %s.%s (%s).\n",
RTLIL::id2cstr(wire->name), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); wire, module, cell, cell->type.unescape());
if (parent_wire->width != wire->width) if (parent_wire->width != wire->width)
log_error("Width mismatch between wire (%d bits) and port (%d bits) for implicit port connection `%s' of cell %s.%s (%s).\n", log_error("Width mismatch between wire (%d bits) and port (%d bits) for implicit port connection `%s' of cell %s.%s (%s).\n",
parent_wire->width, wire->width, parent_wire->width, wire->width,
RTLIL::id2cstr(wire->name), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); wire, module, cell, cell->type.unescape());
cell->setPort(wire->name, parent_wire); cell->setPort(wire->name, parent_wire);
} }
cell->attributes.erase(ID::wildcard_port_conns); cell->attributes.erase(ID::wildcard_port_conns);

View file

@ -19,6 +19,7 @@
#include "kernel/register.h" #include "kernel/register.h"
#include "kernel/log.h" #include "kernel/log.h"
#include "kernel/log_help.h"
#include "passes/opt/opt_clean/opt_clean.h" #include "passes/opt/opt_clean/opt_clean.h"
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
@ -43,6 +44,12 @@ void rmunused_module(RTLIL::Module *module, bool rminit, CleanRunContext &clean_
struct OptCleanPass : public Pass { struct OptCleanPass : public Pass {
OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { } OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { }
bool formatted_help() override
{
auto *help = PrettyHelp::get_current();
help->set_group("passes/opt");
return false;
}
void help() override void help() override
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
@ -99,6 +106,12 @@ struct OptCleanPass : public Pass {
struct CleanPass : public Pass { struct CleanPass : public Pass {
CleanPass() : Pass("clean", "remove unused cells and wires") { } CleanPass() : Pass("clean", "remove unused cells and wires") { }
bool formatted_help() override
{
auto *help = PrettyHelp::get_current();
help->set_group("passes/opt");
return false;
}
void help() override void help() override
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|

View file

@ -200,6 +200,29 @@ struct OptMuxtreeWorker
root_muxes.at(driving_mux) = true; root_muxes.at(driving_mux) = true;
} }
struct knowledge_t
{
// Known inactive signals
// The payload is a reference counter used to manage the list
// When it is non-zero, the signal in known to be inactive
// When it reaches zero, the map element is removed
std::vector<int> known_inactive;
// database of known active signals
std::vector<int> known_active;
// this is just used to keep track of visited muxes in order to prohibit
// endless recursion in mux loops
std::vector<bool> visited_muxes;
// Initialize with the maximum possible sizes
knowledge_t(int num_bits, int num_muxes) {
known_inactive.assign(num_bits, 0);
known_active.assign(num_bits, 0);
visited_muxes.assign(num_muxes, false);
}
};
OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) : OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) :
design(design), module(module), assign_map(module), removed_count(0) design(design), module(module), assign_map(module), removed_count(0)
{ {
@ -227,11 +250,13 @@ struct OptMuxtreeWorker
populate_roots(); populate_roots();
knowledge_t shared_knowledge(GetSize(bit2info), GetSize(mux2info));
for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++) for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++)
if (root_muxes.at(mux_idx)) { if (root_muxes.at(mux_idx)) {
log_debug(" Root of a mux tree: %s%s\n", mux2info[mux_idx].cell, root_enable_muxes.at(mux_idx) ? " (pure)" : ""); log_debug(" Root of a mux tree: %s%s\n", mux2info[mux_idx].cell, root_enable_muxes.at(mux_idx) ? " (pure)" : "");
root_mux_rerun.erase(mux_idx); root_mux_rerun.erase(mux_idx);
eval_root_mux(mux_idx); eval_root_mux(shared_knowledge, mux_idx);
if (glob_evals_left == 0) { if (glob_evals_left == 0) {
log(" Giving up (too many iterations)\n"); log(" Giving up (too many iterations)\n");
return; return;
@ -243,7 +268,7 @@ struct OptMuxtreeWorker
log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", mux2info[mux_idx].cell); log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", mux2info[mux_idx].cell);
log_assert(root_enable_muxes.at(mux_idx)); log_assert(root_enable_muxes.at(mux_idx));
root_mux_rerun.erase(mux_idx); root_mux_rerun.erase(mux_idx);
eval_root_mux(mux_idx); eval_root_mux(shared_knowledge, mux_idx);
if (glob_evals_left == 0) { if (glob_evals_left == 0) {
log(" Giving up (too many iterations)\n"); log(" Giving up (too many iterations)\n");
return; return;
@ -334,29 +359,6 @@ struct OptMuxtreeWorker
return results; return results;
} }
struct knowledge_t
{
// Known inactive signals
// The payload is a reference counter used to manage the list
// When it is non-zero, the signal in known to be inactive
// When it reaches zero, the map element is removed
std::vector<int> known_inactive;
// database of known active signals
std::vector<int> known_active;
// this is just used to keep track of visited muxes in order to prohibit
// endless recursion in mux loops
std::vector<bool> visited_muxes;
// Initialize with the maximum possible sizes
knowledge_t(int num_bits, int num_muxes) {
known_inactive.assign(num_bits, 0);
known_active.assign(num_bits, 0);
visited_muxes.assign(num_muxes, false);
}
};
static void activate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) { static void activate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) {
// First, mark all other ports inactive // First, mark all other ports inactive
for (int i = 0; i < GetSize(muxinfo.ports); i++) { for (int i = 0; i < GetSize(muxinfo.ports); i++) {
@ -579,14 +581,14 @@ struct OptMuxtreeWorker
} }
} }
void eval_root_mux(int mux_idx) void eval_root_mux(knowledge_t &knowledge, int mux_idx)
{ {
log_assert(glob_evals_left > 0); log_assert(glob_evals_left > 0);
knowledge_t knowledge(GetSize(bit2info), GetSize(mux2info));
knowledge.visited_muxes[mux_idx] = true; knowledge.visited_muxes[mux_idx] = true;
limits_t limits = {}; limits_t limits = {};
limits.do_mark_ports_observable = root_enable_muxes.at(mux_idx); limits.do_mark_ports_observable = root_enable_muxes.at(mux_idx);
eval_mux(knowledge, mux_idx, limits); eval_mux(knowledge, mux_idx, limits);
knowledge.visited_muxes[mux_idx] = false;
} }
}; };

View file

@ -395,10 +395,17 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
int offset = 0; int offset = 0;
for (auto chunk : nolatches_bits.first.chunks()) { for (auto chunk : nolatches_bits.first.chunks()) {
SigSpec lhs = chunk, rhs = nolatches_bits.second.extract(offset, chunk.width); SigSpec lhs = chunk, rhs = nolatches_bits.second.extract(offset, chunk.width);
if (proc->get_bool_attribute(ID::always_latch)) bool is_nosync = true;
for (auto bit : lhs)
if (bit.wire == nullptr || !bit.wire->get_bool_attribute(ID::nosync)) {
is_nosync = false;
break;
}
if (proc->get_bool_attribute(ID::always_latch) && !is_nosync)
log_error("No latch inferred for signal `%s.%s' from always_latch process `%s.%s'.\n", log_error("No latch inferred for signal `%s.%s' from always_latch process `%s.%s'.\n",
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
else else if (!is_nosync)
log("No latch inferred for signal `%s.%s' from process `%s.%s'.\n", log("No latch inferred for signal `%s.%s' from process `%s.%s'.\n",
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
for (auto &bit : lhs) { for (auto &bit : lhs) {

View file

@ -132,7 +132,7 @@ struct CutpointPass : public Pass {
if (cell->input(conn.first)) if (cell->input(conn.first))
for (auto bit : sigmap(conn.second)) for (auto bit : sigmap(conn.second))
if (wire_drivers.count(bit)) { if (wire_drivers.count(bit)) {
log_debug(" Treating inout port '%s' as input.\n", id2cstr(conn.first)); log_debug(" Treating inout port '%s' as input.\n", conn.first.unescape());
do_cut = false; do_cut = false;
break; break;
} }
@ -140,7 +140,7 @@ struct CutpointPass : public Pass {
if (do_cut) { if (do_cut) {
module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second))); module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second)));
if (cell->input(conn.first)) { if (cell->input(conn.first)) {
log_debug(" Treating inout port '%s' as output.\n", id2cstr(conn.first)); log_debug(" Treating inout port '%s' as output.\n", conn.first.unescape());
for (auto bit : sigmap(conn.second)) for (auto bit : sigmap(conn.second))
wire_drivers.insert(bit); wire_drivers.insert(bit);
} }
@ -159,7 +159,7 @@ struct CutpointPass : public Pass {
if (attr.first == ID::hdlname) if (attr.first == ID::hdlname)
scopeinfo->attributes.insert(attr); scopeinfo->attributes.insert(attr);
else else
scopeinfo->attributes.emplace(stringf("\\cell_%s", RTLIL::unescape_id(attr.first)), attr.second); scopeinfo->attributes.emplace(stringf("\\cell_%s", attr.first.unescape()), attr.second);
} }
} }

View file

@ -471,7 +471,7 @@ struct ExposePass : public Pass {
{ {
if (!w->port_input) { if (!w->port_input) {
w->port_input = true; w->port_input = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name)); log("New module port: %s/%s\n", module, w);
wire_map[w] = NEW_ID; wire_map[w] = NEW_ID;
} }
} }
@ -479,7 +479,7 @@ struct ExposePass : public Pass {
{ {
if (!w->port_output) { if (!w->port_output) {
w->port_output = true; w->port_output = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name)); log("New module port: %s/%s\n", module, w);
} }
if (flag_cut) { if (flag_cut) {
@ -555,7 +555,7 @@ struct ExposePass : public Pass {
RTLIL::Wire *wire_q = add_new_wire(module, wire->name.str() + sep + "q", wire->width); RTLIL::Wire *wire_q = add_new_wire(module, wire->name.str() + sep + "q", wire->width);
wire_q->port_input = true; wire_q->port_input = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_q->name)); log("New module port: %s/%s\n", module, wire_q);
RTLIL::SigSig connect_q; RTLIL::SigSig connect_q;
for (size_t i = 0; i < wire_bits_vec.size(); i++) { for (size_t i = 0; i < wire_bits_vec.size(); i++) {
@ -569,12 +569,12 @@ struct ExposePass : public Pass {
RTLIL::Wire *wire_d = add_new_wire(module, wire->name.str() + sep + "d", wire->width); RTLIL::Wire *wire_d = add_new_wire(module, wire->name.str() + sep + "d", wire->width);
wire_d->port_output = true; wire_d->port_output = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_d->name)); log("New module port: %s/%s\n", module, wire_d);
module->connect(RTLIL::SigSig(wire_d, info.sig_d)); module->connect(RTLIL::SigSig(wire_d, info.sig_d));
RTLIL::Wire *wire_c = add_new_wire(module, wire->name.str() + sep + "c"); RTLIL::Wire *wire_c = add_new_wire(module, wire->name.str() + sep + "c");
wire_c->port_output = true; wire_c->port_output = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_c->name)); log("New module port: %s/%s\n", module, wire_c);
if (info.clk_polarity) { if (info.clk_polarity) {
module->connect(RTLIL::SigSig(wire_c, info.sig_clk)); module->connect(RTLIL::SigSig(wire_c, info.sig_clk));
} else { } else {
@ -590,7 +590,7 @@ struct ExposePass : public Pass {
{ {
RTLIL::Wire *wire_r = add_new_wire(module, wire->name.str() + sep + "r"); RTLIL::Wire *wire_r = add_new_wire(module, wire->name.str() + sep + "r");
wire_r->port_output = true; wire_r->port_output = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_r->name)); log("New module port: %s/%s\n", module, wire_r);
if (info.arst_polarity) { if (info.arst_polarity) {
module->connect(RTLIL::SigSig(wire_r, info.sig_arst)); module->connect(RTLIL::SigSig(wire_r, info.sig_arst));
} else { } else {
@ -604,7 +604,7 @@ struct ExposePass : public Pass {
RTLIL::Wire *wire_v = add_new_wire(module, wire->name.str() + sep + "v", wire->width); RTLIL::Wire *wire_v = add_new_wire(module, wire->name.str() + sep + "v", wire->width);
wire_v->port_output = true; wire_v->port_output = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire_v->name)); log("New module port: %s/%s\n", module, wire_v);
module->connect(RTLIL::SigSig(wire_v, info.arst_value)); module->connect(RTLIL::SigSig(wire_v, info.arst_value));
} }
} }
@ -632,13 +632,13 @@ struct ExposePass : public Pass {
if (!p->port_input && !p->port_output) if (!p->port_input && !p->port_output)
continue; continue;
RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + RTLIL::unescape_id(p->name), p->width); RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + p->name.unescape(), p->width);
if (p->port_input) if (p->port_input)
w->port_output = true; w->port_output = true;
if (p->port_output) if (p->port_output)
w->port_input = true; w->port_input = true;
log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name), RTLIL::id2cstr(cell->type)); log("New module port: %s/%s (%s)\n", module, w, cell->type.unescape());
RTLIL::SigSpec sig; RTLIL::SigSpec sig;
if (cell->hasPort(p->name)) if (cell->hasPort(p->name))
@ -654,13 +654,13 @@ struct ExposePass : public Pass {
{ {
for (auto &it : cell->connections()) for (auto &it : cell->connections())
{ {
RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + RTLIL::unescape_id(it.first), it.second.size()); RTLIL::Wire *w = add_new_wire(module, cell->name.str() + sep + it.first.unescape(), it.second.size());
if (ct.cell_input(cell->type, it.first)) if (ct.cell_input(cell->type, it.first))
w->port_output = true; w->port_output = true;
if (ct.cell_output(cell->type, it.first)) if (ct.cell_output(cell->type, it.first))
w->port_input = true; w->port_input = true;
log("New module port: %s/%s (%s)\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name), RTLIL::id2cstr(cell->type)); log("New module port: %s/%s (%s)\n", module, w, cell->type.unescape());
if (w->port_input) if (w->port_input)
module->connect(RTLIL::SigSig(it.second, w)); module->connect(RTLIL::SigSig(it.second, w));

View file

@ -139,7 +139,7 @@ struct FindReducedInputs
if (ez_cells.count(drv.first) == 0) { if (ez_cells.count(drv.first) == 0) {
satgen.setContext(&sigmap, "A"); satgen.setContext(&sigmap, "A");
if (!satgen.importCell(drv.first)) if (!satgen.importCell(drv.first))
log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(drv.first->name), RTLIL::id2cstr(drv.first->type)); log_error("Can't create SAT model for cell %s (%s)!\n", drv.first, drv.first->type.unescape());
satgen.setContext(&sigmap, "B"); satgen.setContext(&sigmap, "B");
if (!satgen.importCell(drv.first)) if (!satgen.importCell(drv.first))
log_abort(); log_abort();
@ -256,7 +256,7 @@ struct PerformReduction
std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv = drivers.at(out); std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv = drivers.at(out);
if (celldone.count(drv.first) == 0) { if (celldone.count(drv.first) == 0) {
if (!satgen.importCell(drv.first)) if (!satgen.importCell(drv.first))
log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(drv.first->name), RTLIL::id2cstr(drv.first->type)); log_error("Can't create SAT model for cell %s (%s)!\n", drv.first, drv.first->type.unescape());
celldone.insert(drv.first); celldone.insert(drv.first);
} }
int max_child_depth = 0; int max_child_depth = 0;
@ -595,14 +595,14 @@ struct FreduceWorker
void dump() void dump()
{ {
std::string filename = stringf("%s_%s_%05d.il", dump_prefix, RTLIL::id2cstr(module->name), reduce_counter); std::string filename = stringf("%s_%s_%05d.il", dump_prefix, module, reduce_counter);
log("%s Writing dump file `%s'.\n", reduce_counter ? " " : "", filename); log("%s Writing dump file `%s'.\n", reduce_counter ? " " : "", filename);
Pass::call(design, stringf("dump -outfile %s %s", filename, design->selected_active_module.empty() ? module->name.c_str() : "")); Pass::call(design, stringf("dump -outfile %s %s", filename, design->selected_active_module.empty() ? module->name.c_str() : ""));
} }
int run() int run()
{ {
log("Running functional reduction on module %s:\n", RTLIL::id2cstr(module->name)); log("Running functional reduction on module %s:\n", module);
CellTypes ct; CellTypes ct;
ct.setup_internals(); ct.setup_internals();
@ -749,7 +749,7 @@ struct FreduceWorker
} }
} }
log(" Rewired a total of %d signal bits in module %s.\n", rewired_sigbits, RTLIL::id2cstr(module->name)); log(" Rewired a total of %d signal bits in module %s.\n", rewired_sigbits, module);
return rewired_sigbits; return rewired_sigbits;
} }
}; };

View file

@ -128,7 +128,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name); log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name);
} }
log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", RTLIL::id2cstr(miter_name), RTLIL::id2cstr(gold_name), RTLIL::id2cstr(gate_name)); log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", miter_name.unescape(), gold_name.unescape(), gate_name.unescape());
RTLIL::Module *miter_module = new RTLIL::Module; RTLIL::Module *miter_module = new RTLIL::Module;
miter_module->name = miter_name; miter_module->name = miter_name;
@ -143,7 +143,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
{ {
if (gold_cross_ports.count(gold_wire)) if (gold_cross_ports.count(gold_wire))
{ {
SigSpec w = miter_module->addWire("\\cross_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); SigSpec w = miter_module->addWire("\\cross_" + gold_wire->name.unescape(), gold_wire->width);
gold_cell->setPort(gold_wire->name, w); gold_cell->setPort(gold_wire->name, w);
if (flag_ignore_gold_x) { if (flag_ignore_gold_x) {
RTLIL::SigSpec w_x = miter_module->addWire(NEW_ID, GetSize(w)); RTLIL::SigSpec w_x = miter_module->addWire(NEW_ID, GetSize(w));
@ -159,7 +159,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (gold_wire->port_input) if (gold_wire->port_input)
{ {
RTLIL::Wire *w = miter_module->addWire("\\in_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); RTLIL::Wire *w = miter_module->addWire("\\in_" + gold_wire->name.unescape(), gold_wire->width);
w->port_input = true; w->port_input = true;
gold_cell->setPort(gold_wire->name, w); gold_cell->setPort(gold_wire->name, w);
@ -168,10 +168,10 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (gold_wire->port_output) if (gold_wire->port_output)
{ {
RTLIL::Wire *w_gold = miter_module->addWire("\\gold_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); RTLIL::Wire *w_gold = miter_module->addWire("\\gold_" + gold_wire->name.unescape(), gold_wire->width);
w_gold->port_output = flag_make_outputs; w_gold->port_output = flag_make_outputs;
RTLIL::Wire *w_gate = miter_module->addWire("\\gate_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); RTLIL::Wire *w_gate = miter_module->addWire("\\gate_" + gold_wire->name.unescape(), gold_wire->width);
w_gate->port_output = flag_make_outputs; w_gate->port_output = flag_make_outputs;
gold_cell->setPort(gold_wire->name, w_gold); gold_cell->setPort(gold_wire->name, w_gold);
@ -244,7 +244,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (flag_make_outcmp) if (flag_make_outcmp)
{ {
RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + RTLIL::unescape_id(gold_wire->name)); RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + gold_wire->name.unescape());
w_cmp->port_output = true; w_cmp->port_output = true;
miter_module->connect(RTLIL::SigSig(w_cmp, this_condition)); miter_module->connect(RTLIL::SigSig(w_cmp, this_condition));
} }
@ -252,7 +252,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (flag_make_cover) if (flag_make_cover)
{ {
auto cover_condition = miter_module->Not(NEW_ID, this_condition); auto cover_condition = miter_module->Not(NEW_ID, this_condition);
miter_module->addCover("\\cover_" + RTLIL::unescape_id(gold_wire->name), cover_condition, State::S1); miter_module->addCover("\\cover_" + gold_wire->name.unescape(), cover_condition, State::S1);
} }
all_conditions.append(this_condition); all_conditions.append(this_condition);

View file

@ -275,9 +275,9 @@ struct SimInstance
} }
if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) { if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) {
fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); fstHandle id = shared->fst->getHandle(scope + "." + wire->name.unescape());
if (id==0 && wire->name.isPublic()) if (id==0 && wire->name.isPublic())
log_warning("Unable to find wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name))); log_warning("Unable to find wire %s in input file.\n", (scope + "." + wire->name.unescape()));
fst_handles[wire] = id; fst_handles[wire] = id;
} }
@ -316,7 +316,7 @@ struct SimInstance
Module *mod = module->design->module(cell->type); Module *mod = module->design->module(cell->type);
if (mod != nullptr) { if (mod != nullptr) {
dirty_children.insert(new SimInstance(shared, scope + "." + RTLIL::unescape_id(cell->name), mod, cell, this)); dirty_children.insert(new SimInstance(shared, scope + "." + cell->name.unescape(), mod, cell, this));
} }
for (auto &port : cell->connections()) { for (auto &port : cell->connections()) {
@ -1209,7 +1209,7 @@ struct SimInstance
} }
} }
if (!found) if (!found)
log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(sig_y.as_wire()->name))); log_error("Unable to find required '%s' signal in file\n",(scope + "." + sig_y.as_wire()->name.unescape()));
} }
} }
} }
@ -1495,7 +1495,7 @@ struct SimWorker : SimShared
log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module);
if (!w->port_input) if (!w->port_input)
log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module);
fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); fstHandle id = fst->getHandle(scope + "." + portname.unescape());
if (id==0) if (id==0)
log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape());
fst_clock.push_back(id); fst_clock.push_back(id);
@ -1507,7 +1507,7 @@ struct SimWorker : SimShared
log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module);
if (!w->port_input) if (!w->port_input)
log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module);
fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); fstHandle id = fst->getHandle(scope + "." + portname.unescape());
if (id==0) if (id==0)
log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape());
fst_clock.push_back(id); fst_clock.push_back(id);
@ -1517,9 +1517,9 @@ struct SimWorker : SimShared
for (auto wire : topmod->wires()) { for (auto wire : topmod->wires()) {
if (wire->port_input) { if (wire->port_input) {
fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); fstHandle id = fst->getHandle(scope + "." + wire->name.unescape());
if (id==0) if (id==0)
log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(wire->name))); log_error("Unable to find required '%s' signal in file\n",(scope + "." + wire->name.unescape()));
top->fst_inputs[wire] = id; top->fst_inputs[wire] = id;
} }
} }
@ -2114,12 +2114,12 @@ struct SimWorker : SimShared
std::stringstream f; std::stringstream f;
if (wire->width==1) if (wire->width==1)
f << stringf("%s", RTLIL::unescape_id(wire->name)); f << stringf("%s", wire);
else else
if (wire->upto) if (wire->upto)
f << stringf("[%d:%d] %s", wire->start_offset, wire->width - 1 + wire->start_offset, RTLIL::unescape_id(wire->name)); f << stringf("[%d:%d] %s", wire->start_offset, wire->width - 1 + wire->start_offset, wire);
else else
f << stringf("[%d:%d] %s", wire->width - 1 + wire->start_offset, wire->start_offset, RTLIL::unescape_id(wire->name)); f << stringf("[%d:%d] %s", wire->width - 1 + wire->start_offset, wire->start_offset, wire);
return f.str(); return f.str();
} }
@ -2127,7 +2127,7 @@ struct SimWorker : SimShared
{ {
std::stringstream f; std::stringstream f;
for(auto item=signals.begin();item!=signals.end();item++) for(auto item=signals.begin();item!=signals.end();item++)
f << stringf("%c%s", (item==signals.begin() ? ' ' : ','), RTLIL::unescape_id(item->first->name)); f << stringf("%c%s", (item==signals.begin() ? ' ' : ','), item->first);
return f.str(); return f.str();
} }
@ -2151,7 +2151,7 @@ struct SimWorker : SimShared
log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module);
if (!w->port_input) if (!w->port_input)
log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module);
fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); fstHandle id = fst->getHandle(scope + "." + portname.unescape());
if (id==0) if (id==0)
log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape());
fst_clock.push_back(id); fst_clock.push_back(id);
@ -2164,7 +2164,7 @@ struct SimWorker : SimShared
log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module);
if (!w->port_input) if (!w->port_input)
log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module);
fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); fstHandle id = fst->getHandle(scope + "." + portname.unescape());
if (id==0) if (id==0)
log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape());
fst_clock.push_back(id); fst_clock.push_back(id);
@ -2176,9 +2176,9 @@ struct SimWorker : SimShared
std::map<Wire*,fstHandle> outputs; std::map<Wire*,fstHandle> outputs;
for (auto wire : topmod->wires()) { for (auto wire : topmod->wires()) {
fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); fstHandle id = fst->getHandle(scope + "." + wire->name.unescape());
if (id==0 && (wire->port_input || wire->port_output)) if (id==0 && (wire->port_input || wire->port_output))
log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(wire->name))); log_error("Unable to find required '%s' signal in file\n",(scope + "." + wire->name.unescape()));
if (wire->port_input) if (wire->port_input)
if (clocks.find(wire)==clocks.end()) if (clocks.find(wire)==clocks.end())
inputs[wire] = id; inputs[wire] = id;
@ -2244,13 +2244,13 @@ struct SimWorker : SimShared
} }
int data_len = clk_len + inputs_len + outputs_len + 32; int data_len = clk_len + inputs_len + outputs_len + 32;
f << "\n"; f << "\n";
f << stringf("\t%s uut(",RTLIL::unescape_id(topmod->name)); f << stringf("\t%s uut(",topmod);
for(auto item=clocks.begin();item!=clocks.end();item++) for(auto item=clocks.begin();item!=clocks.end();item++)
f << stringf("%c.%s(%s)", (item==clocks.begin() ? ' ' : ','), RTLIL::unescape_id(item->first->name), RTLIL::unescape_id(item->first->name)); f << stringf("%c.%s(%s)", (item==clocks.begin() ? ' ' : ','), item->first, item->first);
for(auto &item : inputs) for(auto &item : inputs)
f << stringf(",.%s(%s)", RTLIL::unescape_id(item.first->name), RTLIL::unescape_id(item.first->name)); f << stringf(",.%s(%s)", item.first, item.first);
for(auto &item : outputs) for(auto &item : outputs)
f << stringf(",.%s(%s)", RTLIL::unescape_id(item.first->name), RTLIL::unescape_id(item.first->name)); f << stringf(",.%s(%s)", item.first, item.first);
f << ");\n"; f << ");\n";
f << "\n"; f << "\n";
f << "\tinteger i;\n"; f << "\tinteger i;\n";

View file

@ -1565,7 +1565,7 @@ void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL
{ {
if (builtin_lib) if (builtin_lib)
{ {
cell_stats[RTLIL::unescape_id(c->type)]++; cell_stats[c->type.unescape()]++;
if (c->type.in(ID(ZERO), ID(ONE))) { if (c->type.in(ID(ZERO), ID(ONE))) {
RTLIL::SigSig conn; RTLIL::SigSig conn;
RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name); RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name);
@ -1706,7 +1706,7 @@ void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL
} }
} }
else else
cell_stats[RTLIL::unescape_id(c->type)]++; cell_stats[c->type.unescape()]++;
if (c->type.in(ID(_const0_), ID(_const1_))) { if (c->type.in(ID(_const0_), ID(_const1_))) {
RTLIL::SigSig conn; RTLIL::SigSig conn;

View file

@ -626,7 +626,7 @@ struct ExtractPass : public Pass {
if (!mine_mode) if (!mine_mode)
for (auto module : map->modules()) { for (auto module : map->modules()) {
SubCircuit::Graph mod_graph; 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); log("Creating needle graph %s.\n", graph_name);
if (module2graph(mod_graph, module, constports)) { if (module2graph(mod_graph, module, constports)) {
solver.addGraph(graph_name, mod_graph); solver.addGraph(graph_name, mod_graph);
@ -637,7 +637,7 @@ struct ExtractPass : public Pass {
for (auto module : design->modules()) { for (auto module : design->modules()) {
SubCircuit::Graph mod_graph; 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); 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)) { if (module2graph(mod_graph, module, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : nullptr)) {
solver.addGraph(graph_name, mod_graph); solver.addGraph(graph_name, mod_graph);
@ -654,8 +654,8 @@ struct ExtractPass : public Pass {
for (auto needle : needle_list) for (auto needle : needle_list)
for (auto &haystack_it : haystack_map) { for (auto &haystack_it : haystack_map) {
log("Solving for %s in %s.\n", ("needle_" + RTLIL::unescape_id(needle->name)), haystack_it.first); log("Solving for %s in %s.\n", ("needle_" + needle->name.unescape()), haystack_it.first);
solver.solve(results, "needle_" + RTLIL::unescape_id(needle->name), haystack_it.first, false); solver.solve(results, "needle_" + needle->name.unescape(), haystack_it.first, false);
} }
log("Found %d matches.\n", GetSize(results)); log("Found %d matches.\n", GetSize(results));

View file

@ -389,7 +389,7 @@ struct IopadmapPass : public Pass {
if (wire->port_input && !wire->port_output) { if (wire->port_input && !wire->port_output) {
if (inpad_celltype.empty()) { 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; continue;
} }
celltype = inpad_celltype; celltype = inpad_celltype;
@ -398,7 +398,7 @@ struct IopadmapPass : public Pass {
} else } else
if (!wire->port_input && wire->port_output) { if (!wire->port_input && wire->port_output) {
if (outpad_celltype.empty()) { 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; continue;
} }
celltype = outpad_celltype; celltype = outpad_celltype;
@ -407,7 +407,7 @@ struct IopadmapPass : public Pass {
} else } else
if (wire->port_input && wire->port_output) { if (wire->port_input && wire->port_output) {
if (inoutpad_celltype.empty()) { 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; continue;
} }
celltype = inoutpad_celltype; celltype = inoutpad_celltype;
@ -417,11 +417,11 @@ struct IopadmapPass : public Pass {
log_abort(); log_abort();
if (!flag_bits && wire->width != 1 && widthparam.empty()) { 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; 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) if (flag_bits)
{ {
@ -442,7 +442,7 @@ struct IopadmapPass : public Pass {
if (!widthparam.empty()) if (!widthparam.empty())
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1); cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);
if (!nameparam.empty()) 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); cell->attributes[ID::keep] = RTLIL::Const(1);
} }
} }
@ -465,7 +465,7 @@ struct IopadmapPass : public Pass {
if (!widthparam.empty()) if (!widthparam.empty())
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width); cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
if (!nameparam.empty()) 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); cell->attributes[ID::keep] = RTLIL::Const(1);
} }

View file

@ -616,9 +616,9 @@ struct TechmapWorker
} }
if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0) 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) 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()) { for (auto &conn : cell->connections()) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape())) != 0) { if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape())) != 0) {

View file

@ -98,7 +98,7 @@ struct OpenstaPass : public Pass
f_script << "read_verilog " << verilog_filename << "\n"; f_script << "read_verilog " << verilog_filename << "\n";
f_script << "read_lib " << liberty_filename << "\n"; f_script << "read_lib " << liberty_filename << "\n";
f_script << "link_design " << RTLIL::unescape_id(top_mod->name) << "\n"; f_script << "link_design " << top_mod->name.unescape() << "\n";
f_script << "read_sdc " << sdc_filename << "\n"; f_script << "read_sdc " << sdc_filename << "\n";
f_script << "write_sdc " << sdc_expanded_filename << "\n"; f_script << "write_sdc " << sdc_expanded_filename << "\n";
f_script.close(); f_script.close();

View file

@ -56,6 +56,9 @@ struct SynthGateMatePass : public ScriptPass
log(" -noflatten\n"); log(" -noflatten\n");
log(" do not flatten design before synthesis.\n"); log(" do not flatten design before synthesis.\n");
log("\n"); log("\n");
log(" -scopename\n");
log(" create 'scopename' attributes when flattening the netlist.\n");
log("\n");
log(" -nobram\n"); log(" -nobram\n");
log(" do not use CC_BRAM_20K or CC_BRAM_40K cells in output netlist.\n"); log(" do not use CC_BRAM_20K or CC_BRAM_40K cells in output netlist.\n");
log("\n"); log("\n");
@ -94,7 +97,7 @@ struct SynthGateMatePass : public ScriptPass
} }
string top_opt, vlog_file, json_file; string top_opt, vlog_file, json_file;
bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf, abc_new; bool noflatten, scopename, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf, abc_new;
void clear_flags() override void clear_flags() override
{ {
@ -102,6 +105,7 @@ struct SynthGateMatePass : public ScriptPass
vlog_file = ""; vlog_file = "";
json_file = ""; json_file = "";
noflatten = false; noflatten = false;
scopename = false;
nobram = false; nobram = false;
noaddf = false; noaddf = false;
nomult = false; nomult = false;
@ -147,6 +151,10 @@ struct SynthGateMatePass : public ScriptPass
noflatten = true; noflatten = true;
continue; continue;
} }
if (args[argidx] == "-scopename") {
scopename = true;
continue;
}
if (args[argidx] == "-nobram") { if (args[argidx] == "-nobram") {
nobram = true; nobram = true;
continue; continue;
@ -220,7 +228,8 @@ struct SynthGateMatePass : public ScriptPass
run("proc"); run("proc");
if (!noflatten) { if (!noflatten) {
run("check"); run("check");
run("flatten"); std::string flatten_args = scopename ? " -scopename" : "";
run("flatten" + flatten_args);
} }
run("tribuf -logic"); run("tribuf -logic");
run("deminout"); run("deminout");

View file

@ -46,7 +46,7 @@ static void run_ice40_braminit(Module *module)
continue; continue;
/* Open file */ /* Open file */
log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file); log("Processing %s : %s\n", cell, init_file);
std::ifstream f; std::ifstream f;
f.open(init_file.c_str()); f.open(init_file.c_str());

View file

@ -1,6 +1,7 @@
OBJS += techlibs/lattice/synth_lattice.o OBJS += techlibs/lattice/synth_lattice.o
OBJS += techlibs/lattice/lattice_gsr.o OBJS += techlibs/lattice/lattice_gsr.o
OBJS += techlibs/lattice/lattice_dsp_nexus.o
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_ff.vh)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_ff.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_io.vh)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_io.vh))
@ -50,3 +51,10 @@ $(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_bb_ecp
$(eval $(call add_share_file,share/nexus,techlibs/lattice/parse_init.vh)) $(eval $(call add_share_file,share/nexus,techlibs/lattice/parse_init.vh))
$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_sim_nexus.v,cells_sim.v)) $(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_sim_nexus.v,cells_sim.v))
$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_bb_nexus.v,cells_xtra.v)) $(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_bb_nexus.v,cells_xtra.v))
techlibs/lattice/%_pm.h: passes/pmgen/pmgen.py techlibs/lattice/%.pmg
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^)
GENFILES += techlibs/lattice/lattice_dsp_nexus_pm.h
techlibs/lattice/lattice_dsp_nexus.o: techlibs/lattice/lattice_dsp_nexus_pm.h
$(eval $(call add_extra_objs,techlibs/lattice/lattice_dsp_nexus_pm.h))

View file

@ -77,3 +77,75 @@ module \$__NX_MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y);
.Z(Y) .Z(Y)
); );
endmodule endmodule
module \$__NX_MAC18X18 (input [17:0] A, input [17:0] B, input [47:0] C, output [53:0] Y);
parameter A_WIDTH = 18;
parameter B_WIDTH = 18;
parameter C_WIDTH = 48;
parameter Y_WIDTH = 48;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter SUBTRACT = 0;
MULTADDSUB18X18 #(
.REGINPUTA("BYPASS"),
.REGINPUTB("BYPASS"),
.REGINPUTC("BYPASS"),
.REGOUTPUT("BYPASS")
) _TECHMAP_REPLACE_ (
.A(A),
.B(B),
.C({6'b0, C}),
.SIGNED(A_SIGNED ? 1'b1 : 1'b0),
.ADDSUB(SUBTRACT ? 1'b1 : 1'b0),
.Z(Y)
);
endmodule
module \$__NX_PREADD18X18 (input [17:0] A, input [17:0] B, input [17:0] C, input CLK, output [35:0] Y);
parameter PIPELINED = 0;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter C_SIGNED = 0;
MULTPREADD18X18 #(
.REGINPUTA("BYPASS"),
.REGINPUTB("BYPASS"),
.REGINPUTC("BYPASS"),
.REGOUTPUT(PIPELINED ? "REGISTER" : "BYPASS")
) _TECHMAP_REPLACE_ (
.A(A),
.B(B),
.C(C),
.CLK(CLK),
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
.SIGNEDC(C_SIGNED ? 1'b1 : 1'b0),
.Z(Y)
);
endmodule
module \$__NX_MAC9X9WIDE_4LANE (input [8:0] A0, B0, A1, B1, A2, B2, A3, B3, output [53:0] Y);
parameter SIGNED = 0;
MULTADDSUB9X9WIDE #(
.REGINPUTAB0("BYPASS"),
.REGINPUTAB1("BYPASS"),
.REGINPUTAB2("BYPASS"),
.REGINPUTAB3("BYPASS"),
.REGINPUTC("BYPASS"),
.REGOUTPUT("BYPASS")
) _TECHMAP_REPLACE_ (
.A0(A0), .B0(B0),
.A1(A1), .B1(B1),
.A2(A2), .B2(B2),
.A3(A3), .B3(B3),
.C(54'b0),
.SIGNED(SIGNED ? 1'b1 : 1'b0),
.ADDSUB(4'b0000),
.Z(Y)
);
endmodule

View file

@ -0,0 +1,36 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#include "techlibs/lattice/lattice_dsp_nexus_pm.h"
struct LatticeDspNexusPass : public Pass {
LatticeDspNexusPass() : Pass("lattice_dsp_nexus", "Lattice Nexus DSP inference") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" lattice_dsp_nexus [options] [selection]\n");
log("\n");
log("Infer Lattice Nexus sysDSP macrocells (MULTADDSUB18X18, MULTPREADD18X18,\n");
log("MULTADDSUB9X9WIDE) from MAC and dot-product patterns.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing LATTICE_DSP_NEXUS pass.\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules()) {
lattice_dsp_nexus_pm pm(module, module->cells());
pm.run_nexus_mac9_4lane();
pm.run_nexus_mac18();
pm.run_nexus_preadd18();
}
}
} LatticeDspNexusPass;
PRIVATE_NAMESPACE_END

View file

@ -0,0 +1,208 @@
pattern nexus_mac18
match mul
select mul->type.in($mul)
select GetSize(port(mul, \A)) <= 18
select GetSize(port(mul, \B)) <= 18
select GetSize(port(mul, \Y)) <= 48
endmatch
match add
select add->type.in($add, $sub)
select GetSize(port(add, \Y)) <= 48
choice <IdString> AB {\A, \B}
index <SigBit> port(add, AB)[0] === port(mul, \Y)[0]
endmatch
code
if (mul->getParam(\A_SIGNED).as_bool() != mul->getParam(\B_SIGNED).as_bool()) {
reject;
}
{
SigSpec mul_out = port(mul, \Y);
IdString add_AB;
if (GetSize(port(add, \A)) >= GetSize(mul_out) && port(add, \A).extract(0, GetSize(mul_out)) == mul_out) {
add_AB = \A;
} else if (GetSize(port(add, \B)) >= GetSize(mul_out) && port(add, \B).extract(0, GetSize(mul_out)) == mul_out) {
add_AB = \B;
} else {
reject;
}
Cell *mac = module->addCell(NEW_ID, "$__NX_MAC18X18");
IdString add_C = (add_AB == \A) ? \B : \A;
mac->setPort(\A, port(mul, \A));
mac->setPort(\B, port(mul, \B));
mac->setPort(\C, port(add, add_C));
mac->setPort(\Y, port(add, \Y));
mac->setParam(\A_SIGNED, mul->getParam(\A_SIGNED));
mac->setParam(\SUBTRACT, add->type == $sub ? State::S1 : State::S0);
autoremove(mul);
autoremove(add);
}
accept;
endcode
pattern nexus_preadd18
match preadd
select preadd->type.in($add, $sub)
select GetSize(port(preadd, \Y)) <= 19
endmatch
match mul
select mul->type.in($mul)
select GetSize(port(mul, \Y)) <= 48
choice <IdString> mul_AB {\A, \B}
index <SigBit> port(mul, mul_AB)[0] === port(preadd, \Y)[0]
endmatch
match pipe_ff
select pipe_ff->type.in($dff, $dffe, $sdff, $sdffe)
index <SigBit> port(pipe_ff, \D)[0] === port(mul, \Y)[0]
optional
endmatch
code
SigSpec preadd_out = port(preadd, \Y);
IdString actual_mul_AB;
if (GetSize(port(mul, \A)) >= GetSize(preadd_out) && port(mul, \A).extract(0, GetSize(preadd_out)) == preadd_out) {
actual_mul_AB = \A;
} else if (GetSize(port(mul, \B)) >= GetSize(preadd_out) && port(mul, \B).extract(0, GetSize(preadd_out)) == preadd_out) {
actual_mul_AB = \B;
} else {
reject;
}
{
Cell *mac = module->addCell(NEW_ID, "$__NX_PREADD18X18");
IdString mul_other = (actual_mul_AB == \A) ? \B : \A;
IdString sgn_AC = (mul_other == \A) ? \B_SIGNED : \A_SIGNED;
IdString sgn_B = (mul_other == \A) ? \A_SIGNED : \B_SIGNED;
SigSpec sig_A = port(preadd, \A);
SigSpec sig_C = port(preadd, \B);
SigSpec sig_B = port(mul, mul_other);
sig_A.extend_u0(18, false);
sig_C.extend_u0(18, false);
sig_B.extend_u0(18, false);
mac->setPort(\A, sig_A.extract(0, 18));
mac->setPort(\C, sig_C.extract(0, 18));
mac->setPort(\B, sig_B.extract(0, 18));
if (pipe_ff) {
mac->setPort(\Y, port(pipe_ff, \Q));
mac->setPort(\CLK, port(pipe_ff, \CLK));
mac->setParam(\PIPELINED, State::S1);
} else {
mac->setPort(\Y, port(mul, \Y));
mac->setPort(\CLK, State::S0);
mac->setParam(\PIPELINED, State::S0);
}
mac->setParam(\A_SIGNED, mul->getParam(sgn_AC));
mac->setParam(\B_SIGNED, mul->getParam(sgn_B));
mac->setParam(\C_SIGNED, mul->getParam(sgn_AC));
if (pipe_ff) autoremove(pipe_ff);
autoremove(mul);
autoremove(preadd);
}
accept;
endcode
pattern nexus_mac9_4lane
match add_top
select add_top->type == $add
endmatch
match add_mid
select add_mid->type == $add
index <SigBit> port(add_mid, \Y)[0] === port(add_top, \A)[0]
endmatch
match add_bot
select add_bot->type == $add
index <SigBit> port(add_bot, \Y)[0] === port(add_mid, \A)[0]
endmatch
match mul3
select mul3->type == $mul
select GetSize(port(mul3, \A)) <= 9 && GetSize(port(mul3, \B)) <= 9
index <SigBit> port(mul3, \Y)[0] === port(add_top, \B)[0]
endmatch
match mul2
select mul2->type == $mul
select GetSize(port(mul2, \A)) <= 9 && GetSize(port(mul2, \B)) <= 9
index <SigBit> port(mul2, \Y)[0] === port(add_mid, \B)[0]
endmatch
match mul1
select mul1->type == $mul
select GetSize(port(mul1, \A)) <= 9 && GetSize(port(mul1, \B)) <= 9
index <SigBit> port(mul1, \Y)[0] === port(add_bot, \B)[0]
endmatch
match mul0
select mul0->type == $mul
select GetSize(port(mul0, \A)) <= 9 && GetSize(port(mul0, \B)) <= 9
index <SigBit> port(mul0, \Y)[0] === port(add_bot, \A)[0]
endmatch
code
bool is_signed = mul0->getParam(\A_SIGNED).as_bool();
if (
mul0->getParam(\B_SIGNED).as_bool() != is_signed ||
mul1->getParam(\A_SIGNED).as_bool() != is_signed ||
mul1->getParam(\B_SIGNED).as_bool() != is_signed ||
mul2->getParam(\A_SIGNED).as_bool() != is_signed ||
mul2->getParam(\B_SIGNED).as_bool() != is_signed ||
mul3->getParam(\A_SIGNED).as_bool() != is_signed ||
mul3->getParam(\B_SIGNED).as_bool() != is_signed
) {
reject;
}
{
Cell *mac = module->addCell(NEW_ID, "$__NX_MAC9X9WIDE_4LANE");
auto ext9 = [&](SigSpec s) {
s.extend_u0(9, is_signed);
return s;
};
mac->setPort(\A0, ext9(port(mul0, \A)));
mac->setPort(\B0, ext9(port(mul0, \B)));
mac->setPort(\A1, ext9(port(mul1, \A)));
mac->setPort(\B1, ext9(port(mul1, \B)));
mac->setPort(\A2, ext9(port(mul2, \A)));
mac->setPort(\B2, ext9(port(mul2, \B)));
mac->setPort(\A3, ext9(port(mul3, \A)));
mac->setPort(\B3, ext9(port(mul3, \B)));
mac->setPort(\Y, port(add_top, \Y));
mac->setParam(\SIGNED, is_signed ? State::S1 : State::S0);
autoremove(add_top);
autoremove(add_mid);
autoremove(add_bot);
autoremove(mul0);
autoremove(mul1);
autoremove(mul2);
autoremove(mul3);
}
accept;
endcode

View file

@ -425,9 +425,12 @@ struct SynthLatticePass : public ScriptPass
run("opt_clean"); run("opt_clean");
if (help_mode) { if (help_mode) {
run("lattice_dsp_nexus", "(only if -family lifcl/lfd2nx and unless -nodsp)");
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)"); run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
run("techmap -map +/lattice/dsp_map" + dsp_map + ".v", "(unless -nodsp)"); run("techmap -map +/lattice/dsp_map" + dsp_map + ".v", "(unless -nodsp)");
} else if (have_dsp && !nodsp) { } else if (have_dsp && !nodsp) {
if (is_nexus)
run("lattice_dsp_nexus");
for (const auto &rule : dsp_rules) { for (const auto &rule : dsp_rules) {
run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s", run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s",
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim)); rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim));

View file

@ -100,7 +100,7 @@ makefile-./%: %/Makefile
.PHONY: functional .PHONY: functional
functional: functional:
ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) ifeq ($(ENABLE_FUNCTIONAL_TESTS),1)
@cd functional && ./run-test.sh -@cd functional && ./run-test.sh
endif endif
vanilla-test: prep makefile-tests functional vanilla-test: prep makefile-tests functional

View file

@ -54,6 +54,8 @@ def create_tests():
"rm -f aigmap.err" "rm -f aigmap.err"
])) ]))
extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc", "SHELL := /usr/bin/env bash" ] extra = [
"SHELL := /usr/bin/env bash",
]
gen_tests_makefile.generate_custom(create_tests, extra) gen_tests_makefile.generate_custom(create_tests, extra)

View file

@ -0,0 +1,76 @@
// https://github.com/YosysHQ/yosys/issues/5906
module mac (
input bit clk, rst,
input bit [17:0] a, b,
input bit clear,
output bit [47:0] p
);
bit [17:0] a_r, b_r; bit clear_r; bit [47:0] p_r;
always_ff @(posedge clk) begin
if (rst) begin a_r<=0; b_r<=0; clear_r<=0; p_r<=0; end
else begin
a_r<=a; b_r<=b; clear_r<=clear;
p_r <= clear_r ? 48'(a_r*b_r) : 48'(p_r + 48'(a_r*b_r));
end
end
assign p = p_r;
endmodule
module madd_pre (
input bit clk, rst,
input bit [17:0] a, b, c, d,
output bit [47:0] p
);
bit [17:0] a_r, b_r, c_r, d_r; bit [47:0] m_r, p_r;
always_ff @(posedge clk) begin
if (rst) begin a_r<=0; b_r<=0; c_r<=0; d_r<=0; m_r<=0; p_r<=0; end
else begin
a_r<=a; b_r<=b; c_r<=c; d_r<=d;
m_r <= 48'((a_r - d_r) * b_r);
p_r <= 48'(m_r + 48'(c_r));
end
end
assign p = p_r;
endmodule
module dot4 (
input bit clk, rst,
input bit [8:0] a0, b0, a1, b1, a2, b2, a3, b3,
output bit [19:0] p
);
bit [8:0] a0_r, b0_r, a1_r, b1_r, a2_r, b2_r, a3_r, b3_r;
bit [19:0] p_r;
always_ff @(posedge clk) begin
if (rst) begin
a0_r<=0; b0_r<=0; a1_r<=0; b1_r<=0;
a2_r<=0; b2_r<=0; a3_r<=0; b3_r<=0;
p_r<=0;
end else begin
a0_r<=a0; b0_r<=b0; a1_r<=a1; b1_r<=b1;
a2_r<=a2; b2_r<=b2; a3_r<=a3; b3_r<=b3;
p_r <= 20'(20'(a0_r*b0_r) + 20'(a1_r*b1_r) + 20'(a2_r*b2_r) + 20'(a3_r*b3_r));
end
end
assign p = p_r;
endmodule
// Oversized 24x24 MAC
module neg_mac24 (input clk, clear, input [23:0] a, b, output [47:0] p);
reg [23:0] a_r, b_r; reg [47:0] p_r; reg clear_r;
always_ff @(posedge clk) begin
a_r <= a; b_r <= b; clear_r <= clear;
p_r <= clear_r ? 48'(a_r*b_r) : 48'(p_r + 48'(a_r*b_r));
end
assign p = p_r;
endmodule
// Dot product with mixed 9x9 and 18x18 lanes
module neg_dot_mixed (input clk, input [8:0] a0,b0,a1,b1, input [17:0] a2, b2, output [35:0] p);
reg [8:0] a0_r,b0_r,a1_r,b1_r; reg [17:0] a2_r, b2_r; reg [35:0] p_r;
always_ff @(posedge clk) begin
a0_r<=a0; b0_r<=b0; a1_r<=a1; b1_r<=b1; a2_r<=a2; b2_r<=b2;
p_r <= 36'(36'(a0_r*b0_r) + 36'(a1_r*b1_r) + 36'(a2_r*b2_r));
end
assign p = p_r;
endmodule

View file

@ -0,0 +1,35 @@
read_verilog -sv fuse_mac.sv
design -save pristine
# 18x18 MAC
design -load pristine
hierarchy -top mac;
synth_nexus -family lifcl -top mac
select -assert-count 1 t:MULTADDSUB18X18
select -assert-count 0 t:CCU2
# 18x18 pre-add MAC
design -load pristine
hierarchy -top madd_pre;
synth_nexus -family lifcl -top madd_pre
select -assert-count 1 t:MULTPREADD18X18
# 4-lane 9x9 dot product
design -load pristine
hierarchy -top dot4;
synth_nexus -family lifcl -top dot4
select -assert-count 1 t:MULTADDSUB9X9WIDE
# 24x24 MAC
design -load pristine
hierarchy -top neg_mac24;
synth_nexus -family lifcl -top neg_mac24
select -assert-count 0 t:MULTADDSUB18X18
# mixed
design -load pristine
hierarchy -top neg_dot_mixed;
synth_nexus -family lifcl -top neg_dot_mixed
select -assert-count 0 t:MULTADDSUB9X9WIDE
select -assert-count 2 t:MULTADDSUB18X18

View file

@ -1,6 +1,6 @@
../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v ${YOSYS} -qp "synth_xilinx -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v
iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v
vvp -N ./test_macc vvp -N ./test_macc
../../../yosys -qp "synth_xilinx -family xc6s -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v ${YOSYS} -qp "synth_xilinx -family xc6s -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v
iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v
vvp -N ./test_macc vvp -N ./test_macc

View file

@ -1,5 +1,5 @@
../../../yosys -f verilog -qp "synth_xilinx" ../common/tribuf.v ${YOSYS} -f verilog -qp "synth_xilinx" ../common/tribuf.v
../../../yosys -f verilog -qp "synth_xilinx -iopad; \ ${YOSYS} -f verilog -qp "synth_xilinx -iopad; \
select -assert-count 2 t:IBUF; \ select -assert-count 2 t:IBUF; \
select -assert-count 1 t:INV; \ select -assert-count 1 t:INV; \
select -assert-count 1 t:OBUFT" ../common/tribuf.v select -assert-count 1 t:OBUFT" ../common/tribuf.v

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
../../yosys -qq -f verilog -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \ ${YOSYS} -qq -f verilog -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \
-l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v
iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1 -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \ iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1 -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \
temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v

View file

@ -1,29 +1,29 @@
write_file fail.temp << EOF write_file fail.temp << EOF
logger -expect error "Missing -script or -command option." 1 logger -expect error "Missing -script or -command option." 1
bugpoint -suffix fail -yosys ../../yosys bugpoint -suffix fail -yosys ${YOSYS}
EOF EOF
exec -expect-return 0 -- ../../yosys -qq mods.il -s fail.temp exec -expect-return 0 -- ${YOSYS} -qq mods.il -s fail.temp
write_file fail.temp << EOF write_file fail.temp << EOF
logger -expect error "do not crash on this design" 1 logger -expect error "do not crash on this design" 1
bugpoint -suffix fail -yosys ../../yosys -command "dump" bugpoint -suffix fail -yosys ${YOSYS} -command "dump"
EOF EOF
exec -expect-return 0 -- ../../yosys -qq mods.il -s fail.temp exec -expect-return 0 -- ${YOSYS} -qq mods.il -s fail.temp
write_file fail.temp << EOF write_file fail.temp << EOF
logger -expect error "returned value 3 instead of expected 7" 1 logger -expect error "returned value 3 instead of expected 7" 1
bugpoint -suffix fail -yosys ../../yosys -command raise_error -expect-return 7 bugpoint -suffix fail -yosys ${YOSYS} -command raise_error -expect-return 7
EOF EOF
exec -expect-return 0 -- ../../yosys -qq mods.il -s fail.temp exec -expect-return 0 -- ${YOSYS} -qq mods.il -s fail.temp
write_file fail.temp << EOF write_file fail.temp << EOF
logger -expect error "not found in the log file!" 1 logger -expect error "not found in the log file!" 1
bugpoint -suffix fail -yosys ../../yosys -command raise_error -grep "nope" bugpoint -suffix fail -yosys ${YOSYS} -command raise_error -grep "nope"
EOF EOF
exec -expect-return 0 -- ../../yosys -qq mods.il -s fail.temp exec -expect-return 0 -- ${YOSYS} -qq mods.il -s fail.temp
write_file fail.temp << EOF write_file fail.temp << EOF
logger -expect error "not found in stderr log!" 1 logger -expect error "not found in stderr log!" 1
bugpoint -suffix fail -yosys ../../yosys -command raise_error -err-grep "nope" bugpoint -suffix fail -yosys ${YOSYS} -command raise_error -err-grep "nope"
EOF EOF
exec -expect-return 0 -- ../../yosys -qq mods.il -s fail.temp exec -expect-return 0 -- ${YOSYS} -qq mods.il -s fail.temp

View file

@ -6,35 +6,35 @@ design -stash base
# everything is removed by default # everything is removed by default
design -load base design -load base
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3
select -assert-count 1 w:* select -assert-count 1 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-none c:* select -assert-none c:*
# don't remove wires # don't remove wires
design -load base design -load base
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 -modules -cells bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3 -modules -cells
select -assert-count 3 w:* select -assert-count 3 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-none c:* select -assert-none c:*
# don't remove cells or their connections # don't remove cells or their connections
design -load base design -load base
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 -wires -modules bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3 -wires -modules
select -assert-count 5 w:* select -assert-count 5 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-count 4 c:* select -assert-count 4 c:*
# don't remove cells but do remove their connections # don't remove cells but do remove their connections
design -load base design -load base
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 -wires -modules -connections bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3 -wires -modules -connections
select -assert-count 1 w:* select -assert-count 1 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-count 4 c:* select -assert-count 4 c:*
# don't remove modules # don't remove modules
design -load base design -load base
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 -wires -cells bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3 -wires -cells
select -assert-count 1 w:* select -assert-count 1 w:*
select -assert-mod-count 3 =* select -assert-mod-count 3 =*
select -assert-none c:* select -assert-none c:*
@ -42,7 +42,7 @@ select -assert-none c:*
# can keep wires # can keep wires
design -load base design -load base
setattr -set bugpoint_keep 1 w:w_b setattr -set bugpoint_keep 1 w:w_b
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3
select -assert-count 2 w:* select -assert-count 2 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-none c:* select -assert-none c:*
@ -50,7 +50,7 @@ select -assert-none c:*
# a wire with keep won't keep the cell/module containing it # a wire with keep won't keep the cell/module containing it
design -load base design -load base
setattr -set bugpoint_keep 1 w:w_o setattr -set bugpoint_keep 1 w:w_o
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3
select -assert-count 1 w:* select -assert-count 1 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-none c:* select -assert-none c:*
@ -58,7 +58,7 @@ select -assert-none c:*
# can keep cells (and do it without the associated module) # can keep cells (and do it without the associated module)
design -load base design -load base
setattr -set bugpoint_keep 1 c:c_a setattr -set bugpoint_keep 1 c:c_a
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3
select -assert-count 1 w:* select -assert-count 1 w:*
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-count 1 c:* select -assert-count 1 c:*
@ -66,7 +66,7 @@ select -assert-count 1 c:*
# can keep modules # can keep modules
design -load base design -load base
setattr -mod -set bugpoint_keep 1 m_a setattr -mod -set bugpoint_keep 1 m_a
bugpoint -suffix mods -yosys ../../yosys -command raise_error -expect-return 3 bugpoint -suffix mods -yosys ${YOSYS} -command raise_error -expect-return 3
select -assert-count 1 w:* select -assert-count 1 w:*
select -assert-mod-count 2 =* select -assert-mod-count 2 =*
select -assert-none c:* select -assert-none c:*
@ -77,7 +77,7 @@ write_file script.temp << EOF
select -assert-none w:w_a %co* w:w_c %ci* %i select -assert-none w:w_a %co* w:w_c %ci* %i
EOF EOF
design -load base design -load base
bugpoint -suffix mods -yosys ../../yosys -script script.temp -grep "Assertion failed" bugpoint -suffix mods -yosys ${YOSYS} -script script.temp -grep "Assertion failed"
select -assert-count 5 w:* select -assert-count 5 w:*
select -assert-mod-count 2 =* select -assert-mod-count 2 =*
select -assert-count 2 c:* select -assert-count 2 c:*

View file

@ -4,18 +4,18 @@ design -stash err_q
# processes get removed by default # processes get removed by default
design -load err_q design -load err_q
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4
select -assert-none p:* select -assert-none p:*
# individual processes can be kept # individual processes can be kept
design -load err_q design -load err_q
setattr -set bugpoint_keep 1 p:proc_a setattr -set bugpoint_keep 1 p:proc_a
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4
select -assert-count 1 p:* select -assert-count 1 p:*
# all processes can be kept # all processes can be kept
design -load err_q design -load err_q
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 -wires bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4 -wires
select -assert-count 2 p:* select -assert-count 2 p:*
# d and clock are connected after proc # d and clock are connected after proc
@ -26,24 +26,24 @@ select -assert-count 3 w:clock %co
# no assigns means no d # no assigns means no d
design -load err_q design -load err_q
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 -assigns bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4 -assigns
proc proc
select -assert-count 1 w:d %co select -assert-count 1 w:d %co
# no updates means no clock # no updates means no clock
design -load err_q design -load err_q
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 -updates bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4 -updates
proc proc
select -assert-count 1 w:clock %co select -assert-count 1 w:clock %co
# can remove ports # can remove ports
design -load err_q design -load err_q
select -assert-count 5 x:* select -assert-count 5 x:*
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 -ports bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4 -ports
select -assert-none x:* select -assert-none x:*
# can keep ports # can keep ports
design -load err_q design -load err_q
setattr -set bugpoint_keep 1 i:d o:q setattr -set bugpoint_keep 1 i:d o:q
bugpoint -suffix procs -yosys ../../yosys -command raise_error -expect-return 4 -ports bugpoint -suffix procs -yosys ${YOSYS} -command raise_error -expect-return 4 -ports
select -assert-count 2 x:* select -assert-count 2 x:*

View file

@ -24,21 +24,21 @@ logger -check-expected
design -load read design -load read
setattr -mod -unset raise_error def other setattr -mod -unset raise_error def other
dump dump
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 7 bugpoint -suffix error -yosys ${YOSYS} -command raise_error -expect-return 7
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-mod-count 1 top select -assert-mod-count 1 top
# raise_error -always still uses 'raise_error' attribute if possible # raise_error -always still uses 'raise_error' attribute if possible
design -load read design -load read
setattr -mod -unset raise_error def other setattr -mod -unset raise_error def other
bugpoint -suffix error -yosys ../../yosys -command "raise_error -always" -expect-return 7 bugpoint -suffix error -yosys ${YOSYS} -command "raise_error -always" -expect-return 7
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-mod-count 1 top select -assert-mod-count 1 top
# raise_error with string prints message and exits with 1 # raise_error with string prints message and exits with 1
design -load read design -load read
setattr -mod -unset raise_error top def setattr -mod -unset raise_error top def
bugpoint -suffix error -yosys ../../yosys -command raise_error -grep "help me" -expect-return 1 bugpoint -suffix error -yosys ${YOSYS} -command raise_error -grep "help me" -expect-return 1
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-mod-count 1 other select -assert-mod-count 1 other
@ -46,18 +46,18 @@ select -assert-mod-count 1 other
design -load read design -load read
setattr -mod -unset raise_error top setattr -mod -unset raise_error top
delete other delete other
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 1 bugpoint -suffix error -yosys ${YOSYS} -command raise_error -expect-return 1
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-mod-count 1 def select -assert-mod-count 1 def
# raise_error -stderr prints to stderr and exits with 1 # raise_error -stderr prints to stderr and exits with 1
design -load read design -load read
setattr -mod -unset raise_error top def setattr -mod -unset raise_error top def
bugpoint -suffix error -yosys ../../yosys -command "raise_error -stderr" -err-grep "help me" -expect-return 1 bugpoint -suffix error -yosys ${YOSYS} -command "raise_error -stderr" -err-grep "help me" -expect-return 1
select -assert-mod-count 1 =* select -assert-mod-count 1 =*
select -assert-mod-count 1 other select -assert-mod-count 1 other
# empty design can raise_error -always # empty design can raise_error -always
design -reset design -reset
bugpoint -suffix error -yosys ../../yosys -command "raise_error -always" -grep "ERROR: No 'raise_error' attribute found" -expect-return 1 bugpoint -suffix error -yosys ${YOSYS} -command "raise_error -always" -grep "ERROR: No 'raise_error' attribute found" -expect-return 1
bugpoint -suffix error -yosys ../../yosys -command "raise_error -always -stderr" -err-grep "No 'raise_error' attribute found" -expect-return 1 bugpoint -suffix error -yosys ${YOSYS} -command "raise_error -always -stderr" -err-grep "No 'raise_error' attribute found" -expect-return 1

View file

@ -1,3 +1,28 @@
ROOT_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
BUILD_DIR ?= $(ROOT_DIR)/..
ifneq ($(wildcard $(ROOT_DIR)/../Makefile.conf),)
include $(ROOT_DIR)/../Makefile.conf
endif
SBY ?= sby
YOSYS ?= $(BUILD_DIR)/yosys
ifneq ($(ABCEXTERNAL),)
ABC ?= $(ABCEXTERNAL)
else
ABC ?= $(BUILD_DIR)/yosys-abc
endif
YOSYS_FILTERLIB ?= $(BUILD_DIR)/yosys-filterlib
YOSYS_CONFIG ?= $(BUILD_DIR)/yosys-config
YOSYS_SMTBMC ?= $(BUILD_DIR)/yosys-smtbmc
YOSYS_MAX_THREADS ?= 4
export YOSYS
export YOSYS_CONFIG
export YOSYS_SMTBMC
export ABC
export SBY
export YOSYS_MAX_THREADS
all: all:
ifndef OVERRIDE_MAIN ifndef OVERRIDE_MAIN

View file

@ -1,6 +1,6 @@
import subprocess import subprocess
import pytest import pytest
import sys import os
import shlex import shlex
from pathlib import Path from pathlib import Path
@ -18,7 +18,7 @@ def run(cmd, **kwargs):
assert status.returncode == 0, f"{cmd[0]} failed" assert status.returncode == 0, f"{cmd[0]} failed"
def yosys(script): def yosys(script):
run([base_path / 'yosys', '-Q', '-p', script]) run([os.environ.get("YOSYS", "../../yosys"), '-Q', '-p', script])
def compile_cpp(in_path, out_path, args): def compile_cpp(in_path, out_path, args):
run(['g++', '-g', '-std=c++20'] + args + [str(in_path), '-o', str(out_path)]) run(['g++', '-g', '-std=c++20'] + args + [str(in_path), '-o', str(out_path)])
@ -35,7 +35,7 @@ def yosys_sim(rtlil_file, vcd_reference_file, vcd_out_file, preprocessing = ""):
# since yosys sim aborts on simulation mismatch to generate vcd output # since yosys sim aborts on simulation mismatch to generate vcd output
# we have to re-run with a different set of flags # we have to re-run with a different set of flags
# on this run we ignore output and return code, we just want a best-effort attempt to get a vcd # on this run we ignore output and return code, we just want a best-effort attempt to get a vcd
subprocess.run([base_path / 'yosys', '-Q', '-p', subprocess.run([os.environ.get("YOSYS", "../../yosys"), '-Q', '-p',
f'read_rtlil {quote(rtlil_file)}; sim -vcd {quote(vcd_out_file)} -a -r {quote(vcd_reference_file)} -scope gold -timescale 1us -fst-noinit'], f'read_rtlil {quote(rtlil_file)}; sim -vcd {quote(vcd_out_file)} -a -r {quote(vcd_reference_file)} -scope gold -timescale 1us -fst-noinit'],
capture_output=True, check=False) capture_output=True, check=False)
raise raise

View file

@ -1,3 +1,4 @@
import os
import json import json
import shutil import shutil
import subprocess import subprocess
@ -21,7 +22,7 @@ def write_smt2(tmp_path, verilog_text):
vfile = tmp_path / "design.v" vfile = tmp_path / "design.v"
smt2 = tmp_path / "design.smt2" smt2 = tmp_path / "design.smt2"
vfile.write_text(verilog_text) vfile.write_text(verilog_text)
run([base_path / "yosys", "-Q", "-p", run([os.environ.get("YOSYS", "../../yosys"), "-Q", "-p",
f"read_verilog {vfile}; prep -top top; write_smt2 {smt2}"]) f"read_verilog {vfile}; prep -top top; write_smt2 {smt2}"])
return smt2 return smt2
@ -61,7 +62,7 @@ def write_yw(yw_path, signals, bits):
def run_smtbmc(smt2_path, yw_path): def run_smtbmc(smt2_path, yw_path):
"""Run yosys-smtbmc on the SMT2 file with a witness trace.""" """Run yosys-smtbmc on the SMT2 file with a witness trace."""
cmd = [ cmd = [
base_path / "yosys-smtbmc", os.environ.get("YOSYS_SMTBMC", "../../yosys-smtbmc"),
"-s", "z3", "-s", "z3",
"-m", "top", "-m", "top",
"--check-witness", "--check-witness",

View file

@ -94,9 +94,6 @@ def generate_tests(argv, cmds):
def print_header(extra=None): def print_header(extra=None):
print(f"include {common_mk}") print(f"include {common_mk}")
print(f"YOSYS ?= {yosys_basedir}/yosys")
print("")
print("export YOSYS_MAX_THREADS := 4")
if extra: if extra:
for line in extra: for line in extra:
print(line) print(line)
@ -125,7 +122,7 @@ def generate_custom(callback, extra=None):
callback() callback()
def generate_autotest_file(test_file, commands): def generate_autotest_file(test_file, commands):
cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file}; \\\n{commands}" cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} -Y ${{YOSYS}} ${{EXTRA_FLAGS}} {test_file}; \\\n{commands}"
generate_target(test_file, cmd) generate_target(test_file, cmd)
def generate_autotest(pattern, extra_flags, cmds=""): def generate_autotest(pattern, extra_flags, cmds=""):

View file

@ -36,8 +36,7 @@ def main():
lib_tests() lib_tests()
ys_tests() ys_tests()
gen_tests_makefile.generate_custom(callback, gen_tests_makefile.generate_custom(callback)
[f"YOSYS_FILTERLIB ?= {gen_tests_makefile.yosys_basedir}/yosys-filterlib"])
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -40,19 +40,19 @@ def create_tests():
gen_tests_makefile.generate_cmd_test("child_content1", [ gen_tests_makefile.generate_cmd_test("child_content1", [
f"{setup}", f"{setup}",
'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' 'cd temp && $(YOSYS) -qp "read_verilog -defer ../memory.v; '
'chparam -set MEMFILE \\"content1.dat\\" memory"' 'chparam -set MEMFILE \\"content1.dat\\" memory"'
]) ])
gen_tests_makefile.generate_cmd_test("child_content2_temp", [ gen_tests_makefile.generate_cmd_test("child_content2_temp", [
f"{setup}", f"{setup}",
'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' 'cd temp && $(YOSYS) -qp "read_verilog -defer ../memory.v; '
'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"'
]) ])
gen_tests_makefile.generate_cmd_test("child_content2_direct", [ gen_tests_makefile.generate_cmd_test("child_content2_direct", [
f"{setup}", f"{setup}",
'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' 'cd temp && $(YOSYS) -qp "read_verilog -defer ../memory.v; '
'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"'
]) ])

View file

@ -1574,7 +1574,7 @@ def create_tests():
for lib in t.libs: for lib in t.libs:
libs_args += f" -l memlib_{lib}.v" libs_args += f" -l memlib_{lib}.v"
cmd = ( cmd = (
f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} " f"../tools/autotest.sh -G -j ${{SEEDOPT}} -Y ${{YOSYS}} "
f"-p 'script ../t_{t.name}.ys'" f"-p 'script ../t_{t.name}.ys'"
f"{libs_args} " f"{libs_args} "
f"t_{t.name}.v || (cat t_{t.name}.err; exit 1)" f"t_{t.name}.v || (cat t_{t.name}.err; exit 1)"

View file

@ -8,51 +8,5 @@ import gen_tests_makefile
gen_tests_makefile.generate_autotest("*.v", "", gen_tests_makefile.generate_autotest("*.v", "",
"""if grep -Eq 'expect-(wr-ports|rd-ports|rd-clk)' $@; then \\ """if grep -Eq 'expect-(wr-ports|rd-ports|rd-clk)' $@; then \\
$(YOSYS) -f verilog -qp "proc; opt; memory -nomap; dump -outfile $(@:.v=).dmp t:\\$$mem_v2" $@; \\ $(YOSYS) -f verilog -qp "proc; opt; memory -nomap; dump -outfile $(@:.v=).dmp t:\\$$mem_v2" $@; \\
if grep -q expect-wr-ports $@; then \\ python3 validate.py $@ $(@:.v=).dmp; \\
val=$$(gawk '/expect-wr-ports/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\WR_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of write ports."; exit 1; }; \\
fi; \\
if grep -q expect-wr-wide-continuation $@; then \\
val=$$(gawk '/expect-wr-wide-continuation/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\WR_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected write wide continuation."; exit 1; }; \\
fi; \\
if grep -q expect-rd-ports $@; then \\
val=$$(gawk '/expect-rd-ports/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\RD_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of read ports."; exit 1; }; \\
fi; \\
if grep -q expect-rd-clk $@; then \\
val=$$(gawk '/expect-rd-clk/ { print $$3; }' $@); \\
grep -Fq "connect \\\\RD_CLK $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read clock."; exit 1; }; \\
fi; \\
if grep -q expect-rd-en $@; then \\
val=$$(gawk '/expect-rd-en/ { print $$3; }' $@); \\
grep -Fq "connect \\\\RD_EN $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read enable."; exit 1; }; \\
fi; \\
if grep -q expect-rd-srst-sig $@; then \\
val=$$(gawk '/expect-rd-srst-sig/ { print $$3; }' $@); \\
grep -Fq "connect \\\\RD_SRST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset."; exit 1; }; \\
fi; \\
if grep -q expect-rd-srst-val $@; then \\
val=$$(gawk '/expect-rd-srst-val/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\RD_SRST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset value."; exit 1; }; \\
fi; \\
if grep -q expect-rd-arst-sig $@; then \\
val=$$(gawk '/expect-rd-arst-sig/ { print $$3; }' $@); \\
grep -Fq "connect \\\\RD_ARST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset."; exit 1; }; \\
fi; \\
if grep -q expect-rd-arst-val $@; then \\
val=$$(gawk '/expect-rd-arst-val/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\RD_ARST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset value."; exit 1; }; \\
fi; \\
if grep -q expect-rd-init-val $@; then \\
val=$$(gawk '/expect-rd-init-val/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\RD_INIT_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read init value."; exit 1; }; \\
fi; \\
if grep -q expect-rd-wide-continuation $@; then \\
val=$$(gawk '/expect-rd-wide-continuation/ { print $$3; }' $@); \\
grep -Fq "parameter \\\\RD_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read wide continuation."; exit 1; }; \\
fi; \\
if grep -q expect-no-rd-clk $@; then \\
grep -Fq "connect \\\\RD_CLK 1'x" $(@:.v=).dmp || { echo " ERROR: Expected no read clock."; exit 1; }; \\
fi; \\
fi""") fi""")

116
tests/memories/validate.py Normal file
View file

@ -0,0 +1,116 @@
#!/usr/bin/env python3
import re
import sys
from pathlib import Path
CHECKS = [
(
"expect-wr-ports",
r"parameter \\WR_PORTS {val}$",
"ERROR: Unexpected number of write ports.",
),
(
"expect-wr-wide-continuation",
r"parameter \\WR_WIDE_CONTINUATION {val}$",
"ERROR: Unexpected write wide continuation.",
),
(
"expect-rd-ports",
r"parameter \\RD_PORTS {val}$",
"ERROR: Unexpected number of read ports.",
),
(
"expect-rd-clk",
r"connect \\RD_CLK {val}$",
"ERROR: Unexpected read clock.",
),
(
"expect-rd-en",
r"connect \\RD_EN {val}$",
"ERROR: Unexpected read enable.",
),
(
"expect-rd-srst-sig",
r"connect \\RD_SRST {val}$",
"ERROR: Unexpected read sync reset.",
),
(
"expect-rd-srst-val",
r"parameter \\RD_SRST_VALUE {val}$",
"ERROR: Unexpected read sync reset value.",
),
(
"expect-rd-arst-sig",
r"connect \\RD_ARST {val}$",
"ERROR: Unexpected read async reset.",
),
(
"expect-rd-arst-val",
r"parameter \\RD_ARST_VALUE {val}$",
"ERROR: Unexpected read async reset value.",
),
(
"expect-rd-init-val",
r"parameter \\RD_INIT_VALUE {val}$",
"ERROR: Unexpected read init value.",
),
(
"expect-rd-wide-continuation",
r"parameter \\RD_WIDE_CONTINUATION {val}$",
"ERROR: Unexpected read wide continuation.",
),
(
"expect-no-rd-clk",
r"connect \\RD_CLK 1'x$",
"ERROR: Expected no read clock.",
),
]
def extract_expect_value(src_text: str, key: str):
pattern = rf"{re.escape(key)}\s+(\S+)"
m = re.search(pattern, src_text)
return m.group(1) if m else None
def main():
if len(sys.argv) != 3:
print(f"Usage: {sys.argv[0]} <source.v> <dump.dmp>", file=sys.stderr)
return 2
srcfile = Path(sys.argv[1])
dmpfile = Path(sys.argv[2])
try:
src_text = srcfile.read_text()
except Exception as e:
print(f"ERROR: Failed to read {srcfile}: {e}", file=sys.stderr)
return 2
try:
dmp_text = dmpfile.read_text()
except Exception as e:
print(f"ERROR: Failed to read {dmpfile}: {e}", file=sys.stderr)
return 2
for key, pattern_template, errmsg in CHECKS:
if "{val}" in pattern_template:
val = extract_expect_value(src_text, key)
if val is None:
continue
pattern = pattern_template.format(val=re.escape(val))
else:
if key not in src_text:
continue
pattern = pattern_template
if not re.search(pattern, dmp_text, re.MULTILINE):
print(errmsg, file=sys.stderr)
return 1
print("ok.")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -87,7 +87,7 @@ def main():
sock.bind(args.path) sock.bind(args.path)
try: try:
sock.listen(1) sock.listen(1)
ys_proc = subprocess.Popen(["../../yosys", "-ql", "unix.log", "-p", "connect_rpc -path {}; read_verilog design.v; hierarchy -top top; flatten; select -assert-count 1 t:$neg".format(args.path)]) ys_proc = subprocess.Popen([os.environ.get("YOSYS", "../../yosys"), "-ql", "unix.log", "-p", "connect_rpc -path {}; read_verilog design.v; hierarchy -top top; flatten; select -assert-count 1 t:$neg".format(args.path)])
conn, addr = sock.accept() conn, addr = sock.accept()
file = conn.makefile("rw") file = conn.makefile("rw")
while True: while True:

View file

@ -1,10 +1,9 @@
set -euo pipefail set -euo pipefail
YS=../../yosys
mkdir -p temp mkdir -p temp
$YS -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-push.il; design -push; design -pop; write_rtlil temp/roundtrip-design-pop.il" ${YOSYS} -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-push.il; design -push; design -pop; write_rtlil temp/roundtrip-design-pop.il"
diff temp/roundtrip-design-push.il temp/roundtrip-design-pop.il diff temp/roundtrip-design-push.il temp/roundtrip-design-pop.il
$YS -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-save.il; design -save foo; design -load foo; write_rtlil temp/roundtrip-design-load.il" ${YOSYS} -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-save.il; design -save foo; design -load foo; write_rtlil temp/roundtrip-design-load.il"
diff temp/roundtrip-design-save.il temp/roundtrip-design-load.il diff temp/roundtrip-design-save.il temp/roundtrip-design-load.il

View file

@ -1,5 +1,4 @@
set -euo pipefail set -euo pipefail
YS=../../yosys
mkdir -p temp mkdir -p temp
@ -11,7 +10,7 @@ remove_empty_lines() {
} }
# write_rtlil and dump are equivalent # write_rtlil and dump are equivalent
$YS -p "read_verilog -sv everything.v; copy alu zzz; proc zzz; dump -o temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.write.il" ${YOSYS} -p "read_verilog -sv everything.v; copy alu zzz; proc zzz; dump -o temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.write.il"
remove_empty_lines temp/roundtrip-text.dump.il remove_empty_lines temp/roundtrip-text.dump.il
remove_empty_lines temp/roundtrip-text.write.il remove_empty_lines temp/roundtrip-text.write.il
# Trim first line ("Generated by Yosys ...") # Trim first line ("Generated by Yosys ...")
@ -19,13 +18,13 @@ tail -n +2 temp/roundtrip-text.write.il > temp/roundtrip-text.write-nogen.il
diff temp/roundtrip-text.dump.il temp/roundtrip-text.write-nogen.il diff temp/roundtrip-text.dump.il temp/roundtrip-text.write-nogen.il
# Loading and writing it out again doesn't change the RTLIL # Loading and writing it out again doesn't change the RTLIL
$YS -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload.il" ${YOSYS} -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload.il"
remove_empty_lines temp/roundtrip-text.reload.il remove_empty_lines temp/roundtrip-text.reload.il
tail -n +2 temp/roundtrip-text.reload.il > temp/roundtrip-text.reload-nogen.il tail -n +2 temp/roundtrip-text.reload.il > temp/roundtrip-text.reload-nogen.il
diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-nogen.il diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-nogen.il
# Hashing differences don't change the RTLIL # Hashing differences don't change the RTLIL
$YS --hash-seed=2345678 -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload-hash.il" ${YOSYS} --hash-seed=2345678 -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload-hash.il"
remove_empty_lines temp/roundtrip-text.reload-hash.il remove_empty_lines temp/roundtrip-text.reload-hash.il
tail -n +2 temp/roundtrip-text.reload-hash.il > temp/roundtrip-text.reload-hash-nogen.il tail -n +2 temp/roundtrip-text.reload-hash.il > temp/roundtrip-text.reload-hash-nogen.il
diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-hash-nogen.il diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-hash-nogen.il

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
../../yosys -p 'read_verilog alu_sub.v; proc; hierarchy -auto-top; sdc side-effects.sdc' | grep 'This should print something: ${YOSYS} -p 'read_verilog alu_sub.v; proc; hierarchy -auto-top; sdc side-effects.sdc' | grep 'This should print something:
YOSYS_SDC_MAGIC_NODE_0' YOSYS_SDC_MAGIC_NODE_0'

View file

@ -2,4 +2,4 @@
set -euo pipefail set -euo pipefail
! ../../yosys -p 'read_verilog alu_sub.v; proc; hierarchy -auto-top; sdc get_foo.sdc' 2>&1 | grep 'Unknown getter' ! ${YOSYS} -p 'read_verilog alu_sub.v; proc; hierarchy -auto-top; sdc get_foo.sdc' 2>&1 | grep 'Unknown getter'

View file

@ -1,3 +1,5 @@
OVERRIDE_MAIN=1
include ../common.mk
TESTS = $(sort $(basename $(wildcard *.sv)) $(basename $(wildcard *.vhd))) TESTS = $(sort $(basename $(wildcard *.sv)) $(basename $(wildcard *.vhd)))

View file

@ -59,16 +59,16 @@ generate_sby() {
if [ -f $prefix.ys ]; then if [ -f $prefix.ys ]; then
set -x set -x
$PWD/../../yosys -q -e "Assert .* failed." -s $prefix.ys ${YOSYS} -q -e "Assert .* failed." -s $prefix.ys
elif [ -f $prefix.sv ]; then elif [ -f $prefix.sv ]; then
generate_sby pass > ${prefix}_pass.sby generate_sby pass > ${prefix}_pass.sby
generate_sby fail > ${prefix}_fail.sby generate_sby fail > ${prefix}_fail.sby
# Check that SBY is up to date enough for this yosys version # Check that SBY is up to date enough for this yosys version
if sby --help | grep -q -e '--status'; then if ${SBY} --help | grep -q -e '--status'; then
set -x set -x
sby --yosys $PWD/../../yosys -f ${prefix}_pass.sby ${SBY} --yosys ${YOSYS} -f ${prefix}_pass.sby
sby --yosys $PWD/../../yosys -f ${prefix}_fail.sby ${SBY} --yosys ${YOSYS} -f ${prefix}_fail.sby
else else
echo "sva test '${prefix}' requires an up to date SBY, skipping" echo "sva test '${prefix}' requires an up to date SBY, skipping"
fi fi
@ -76,9 +76,9 @@ else
generate_sby pass > ${prefix}.sby generate_sby pass > ${prefix}.sby
# Check that SBY is up to date enough for this yosys version # Check that SBY is up to date enough for this yosys version
if sby --help | grep -q -e '--status'; then if ${SBY} --help | grep -q -e '--status'; then
set -x set -x
sby --yosys $PWD/../../yosys -f ${prefix}.sby ${SBY} --yosys ${YOSYS} -f ${prefix}.sby
else else
echo "sva test '${prefix}' requires an up to date SBY, skipping" echo "sva test '${prefix}' requires an up to date SBY, skipping"
fi fi

View file

@ -5,7 +5,7 @@ if ! which timeout ; then
exit 0 exit 0
fi fi
if ! timeout 10 ../../yosys bug5495.v -p 'hierarchy; techmap; abc -script bug5495.abc' ; then if ! timeout 10 ${YOSYS} bug5495.v -p 'hierarchy; techmap; abc -script bug5495.abc' ; then
echo "Yosys failed to complete" echo "Yosys failed to complete"
exit 1 exit 1
fi fi

View file

@ -1,3 +1,3 @@
#!/usr/bin/env bash #!/usr/bin/env bash
exec ../tools/autotest.sh -G -j $@ -p 'proc; opt; memory -nomap; techmap -map ../mem_simple_4x1_map.v;; techmap; opt; abc;; stat' mem_simple_4x1_uut.v exec ../tools/autotest.sh -G -Y ${YOSYS} -j $@ -p 'proc; opt; memory -nomap; techmap -map ../mem_simple_4x1_map.v;; techmap; opt; abc;; stat' mem_simple_4x1_uut.v

View file

@ -1,3 +1,3 @@
set -e set -e
../../yosys -p 'read_verilog recursive.v; hierarchy -top top; techmap -map recursive_map.v -max_iter 1; select -assert-count 2 t:sub; select -assert-count 2 t:bar' ${YOSYS} -p 'read_verilog recursive.v; hierarchy -top top; techmap -map recursive_map.v -max_iter 1; select -assert-count 2 t:sub; select -assert-count 2 t:bar'

View file

@ -24,6 +24,7 @@ warn_iverilog_git=false
firrtl2verilog="" firrtl2verilog=""
xfirrtl="../xfirrtl" xfirrtl="../xfirrtl"
abcprog="$toolsdir/../../yosys-abc" abcprog="$toolsdir/../../yosys-abc"
yosysprog="$toolsdir/../../yosys"
exec {lock}<"$toolsdir"; flock "$lock" 1>&2 exec {lock}<"$toolsdir"; flock "$lock" 1>&2
if [ ! -f "$toolsdir/cmp_tbdata" -o "$toolsdir/cmp_tbdata.c" -nt "$toolsdir/cmp_tbdata" ]; then if [ ! -f "$toolsdir/cmp_tbdata" -o "$toolsdir/cmp_tbdata.c" -nt "$toolsdir/cmp_tbdata" ]; then
@ -31,7 +32,7 @@ if [ ! -f "$toolsdir/cmp_tbdata" -o "$toolsdir/cmp_tbdata.c" -nt "$toolsdir/cmp_
fi fi
flock -u "$lock"; exec {lock}>&- flock -u "$lock"; exec {lock}>&-
while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do while getopts xmGl:wkjvref:s:p:n:S:I:A:Y:-: opt; do
case "$opt" in case "$opt" in
x) x)
use_xsim=true ;; use_xsim=true ;;
@ -70,6 +71,8 @@ while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do
minclude_opts="$minclude_opts +incdir+$OPTARG" ;; minclude_opts="$minclude_opts +incdir+$OPTARG" ;;
A) A)
abcprog="$OPTARG" ;; abcprog="$OPTARG" ;;
Y)
yosysprog="$OPTARG" ;;
-) -)
case "${OPTARG}" in case "${OPTARG}" in
xfirrtl) xfirrtl)
@ -159,7 +162,7 @@ do
fi fi
if [ ! -f ../${bn}_tb.v ]; then if [ ! -f ../${bn}_tb.v ]; then
"$toolsdir"/../../yosys -f "$frontend $include_opts -D_AUTOTB" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext} $yosysprog -f "$frontend $include_opts -D_AUTOTB" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext}
else else
cp ../${bn}_tb.v ${bn}_tb.v cp ../${bn}_tb.v ${bn}_tb.v
fi fi
@ -173,7 +176,7 @@ do
test_count=0 test_count=0
test_passes() { test_passes() {
"$toolsdir"/../../yosys -b "verilog $backend_opts" -o ${bn}_syn${test_count}.v "$@" $yosysprog -b "verilog $backend_opts" -o ${bn}_syn${test_count}.v "$@"
touch ${bn}.iverilog touch ${bn}.iverilog
compile_and_run ${bn}_tb_syn${test_count} ${bn}_out_syn${test_count} \ compile_and_run ${bn}_tb_syn${test_count} ${bn}_out_syn${test_count} \
${bn}_tb.v ${bn}_syn${test_count}.v "${libs[@]}" \ ${bn}_tb.v ${bn}_syn${test_count}.v "${libs[@]}" \
@ -203,7 +206,7 @@ do
test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext} test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}
if [ -n "$firrtl2verilog" ]; then if [ -n "$firrtl2verilog" ]; then
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine; pmuxtree" ${bn}_ref.${refext} $yosysprog -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine; pmuxtree" ${bn}_ref.${refext}
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v $firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine" ${bn}_ref.fir.v test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine" ${bn}_ref.fir.v
fi fi

View file

@ -109,8 +109,10 @@ TEST_F(ThreadingTest, IntRangeIteration) {
TEST_F(ThreadingTest, IntRangeEmpty) { TEST_F(ThreadingTest, IntRangeEmpty) {
IntRange range{5, 5}; IntRange range{5, 5};
for (int _ : range) for (int _ : range) {
(void)_;
FAIL(); FAIL();
}
} }
TEST_F(ThreadingTest, ItemRangeForWorker) { TEST_F(ThreadingTest, ItemRangeForWorker) {

View file

@ -1,9 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -ex set -ex
../../yosys -q -o async_syn.v -r uut -p 'synth; rename uut syn' async.v ${YOSYS} -q -o async_syn.v -r uut -p 'synth; rename uut syn' async.v
../../yosys -q -o async_prp.v -r uut -p 'prep; rename uut prp' async.v ${YOSYS} -q -o async_prp.v -r uut -p 'prep; rename uut prp' async.v
../../yosys -q -o async_a2s.v -r uut -p 'prep; async2sync; rename uut a2s' async.v ${YOSYS} -q -o async_a2s.v -r uut -p 'prep; async2sync; rename uut a2s' async.v
../../yosys -q -o async_ffl.v -r uut -p 'prep; clk2fflogic; rename uut ffl' async.v ${YOSYS} -q -o async_ffl.v -r uut -p 'prep; clk2fflogic; rename uut ffl' async.v
iverilog -o async_sim -DTESTBENCH async.v async_???.v iverilog -o async_sim -DTESTBENCH async.v async_???.v
vvp -N async_sim > async.out vvp -N async_sim > async.out
tail async.out tail async.out

Some files were not shown because too many files have changed in this diff Show more