3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-06-21 16:20:26 +00:00

Merge branch 'YosysHQ:main' into master

This commit is contained in:
Eder Monteiro 2026-01-13 21:34:20 +00:00 committed by GitHub
commit 75dff5a811
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
152 changed files with 2741 additions and 903 deletions

View file

@ -5,6 +5,7 @@ on:
push:
branches:
- main
merge_group:
# test PRs
pull_request:
# allow triggering tests, ignores skip check
@ -37,7 +38,7 @@ jobs:
persist-credentials: false
- run: sudo apt-get install libfl-dev
- name: Build
run: make vcxsrc YOSYS_VER=latest
run: make vcxsrc YOSYS_COMPILER="Visual Studio" VCX_DIR_NAME=yosys-win32-vcxsrc-latest
- uses: actions/upload-artifact@v4
with:
name: vcxsrc

View file

@ -1,6 +1,6 @@
name: Build docs artifact with Verific
on: [push, pull_request]
on: [push, pull_request, merge_group]
jobs:
check_docs_rebuild:

View file

@ -5,6 +5,7 @@ on:
push:
branches:
- main
merge_group:
# test PRs
pull_request:
# allow triggering tests, ignores skip check

View file

@ -5,6 +5,7 @@ on:
push:
branches:
- main
merge_group:
# test PRs
pull_request:
# allow triggering tests, ignores skip check

View file

@ -5,6 +5,7 @@ on:
push:
branches:
- main
merge_group:
# ignore PRs due to time needed
# allow triggering tests, ignores skip check
workflow_dispatch:

View file

@ -5,6 +5,7 @@ on:
push:
branches:
- main
merge_group:
# test PRs
pull_request:
# allow triggering tests, ignores skip check

View file

@ -2,9 +2,22 @@
List of major changes and improvements between releases
=======================================================
Yosys 0.60 .. Yosys 0.61-dev
Yosys 0.61 .. Yosys 0.62-dev
--------------------------
Yosys 0.60 .. Yosys 0.61
--------------------------
* Various
- Removed "cover" pass for coverage tracking.
- Avoid merging formal properties with "opt_merge" pass.
- Parallelize "opt_merge" pass.
* New commands and options
- Added "design_equal" pass to support fuzz-test comparison.
- Added "lut2bmux" pass to convert $lut to $bmux.
- Added "-legalize" option to "read_rtlil" pass to prevent
semantic errors.
Yosys 0.59 .. Yosys 0.60
--------------------------
* Various

View file

@ -1,6 +1,6 @@
ISC License
Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com>
Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -21,7 +21,6 @@ ENABLE_VERIFIC_HIER_TREE := 1
ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0
ENABLE_VERIFIC_EDIF := 0
ENABLE_VERIFIC_LIBERTY := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
ENABLE_LIBYOSYS_STATIC := 0
ENABLE_ZLIB := 1
@ -162,7 +161,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.60+0
YOSYS_VER := 0.61+0
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
@ -178,14 +177,16 @@ CXXFLAGS += -DYOSYS_VER=\\"$(YOSYS_VER)\\" \
TARBALL_GIT_REV := $(shell cat $(YOSYS_SRC)/.gitcommit)
ifneq ($(findstring Format:,$(TARBALL_GIT_REV)),)
GIT_REV := $(shell GIT_DIR=$(YOSYS_SRC)/.git git rev-parse --short=9 HEAD || echo UNKNOWN)
GIT_DIRTY := $(shell GIT_DIR=$(YOSYS_SRC)/.git git diff --exit-code --quiet 2>/dev/null; if [ $$? -ne 0 ]; then echo "-dirty"; fi)
else
GIT_REV := $(TARBALL_GIT_REV)
GIT_DIRTY := ""
endif
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 5bafeb7.. | wc -l`/;" Makefile
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 5ae48ee.. | wc -l`/;" Makefile
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
@ -249,9 +250,6 @@ ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
CXXFLAGS += -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER)
LINKFLAGS += -g -fsanitize=$(SANITIZER)
ifneq ($(findstring address,$(SANITIZER)),)
ENABLE_COVER := 0
endif
ifneq ($(findstring memory,$(SANITIZER)),)
CXXFLAGS += -fPIE -fsanitize-memory-track-origins
LINKFLAGS += -fPIE -fsanitize-memory-track-origins
@ -548,10 +546,6 @@ LIBS_VERIFIC += -Wl,--whole-archive $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VE
endif
endif
ifeq ($(ENABLE_COVER),1)
CXXFLAGS += -DYOSYS_ENABLE_COVER
endif
ifeq ($(ENABLE_CCACHE),1)
CXX := ccache $(CXX)
else
@ -651,8 +645,6 @@ $(eval $(call add_include_file,libs/sha1/sha1.h))
$(eval $(call add_include_file,libs/json11/json11.hpp))
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
$(eval $(call add_include_file,passes/techmap/libparse.h))
$(eval $(call add_include_file,frontends/ast/ast.h))
$(eval $(call add_include_file,frontends/ast/ast_binding.h))
$(eval $(call add_include_file,frontends/blif/blifparse.h))
$(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))
@ -729,7 +721,6 @@ OBJS += passes/hierarchy/hierarchy.o
OBJS += passes/cmds/select.o
OBJS += passes/cmds/show.o
OBJS += passes/cmds/stat.o
OBJS += passes/cmds/cover.o
OBJS += passes/cmds/design.o
OBJS += passes/cmds/plugin.o
@ -800,12 +791,13 @@ endif
$(Q) mkdir -p $(dir $@)
$(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $<
YOSYS_VER_STR := Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(notdir $(CXX)) $(shell \
$(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1) $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))
YOSYS_GIT_STR := $(GIT_REV)$(GIT_DIRTY)
YOSYS_COMPILER := $(notdir $(CXX)) $(shell $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1) $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS))
YOSYS_VER_STR := Yosys $(YOSYS_VER) (git sha1 $(YOSYS_GIT_STR), $(YOSYS_COMPILER))
kernel/version_$(GIT_REV).cc: $(YOSYS_SRC)/Makefile
$(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc
$(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"$(YOSYS_VER_STR)\"; }" > kernel/version_$(GIT_REV).cc
$(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"$(YOSYS_VER_STR)\"; const char *yosys_git_hash_str=\"$(YOSYS_GIT_STR)\"; }" > kernel/version_$(GIT_REV).cc
ifeq ($(ENABLE_VERIFIC),1)
CXXFLAGS_NOVERIFIC = $(foreach v,$(CXXFLAGS),$(if $(findstring $(VERIFIC_DIR),$(v)),,$(v)))
@ -1058,7 +1050,9 @@ ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
$(INSTALL_SUDO) cp -r share $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
ifeq ($(ENABLE_ABC),1)
$(INSTALL_SUDO) cp yosys-abc $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc
ifeq ($(ABCEXTERNAL),)
$(INSTALL_SUDO) cp $(PROGRAM_PREFIX)yosys-abc$(EXE) $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc$(EXE)
endif
endif
endif
endif
@ -1209,15 +1203,17 @@ qtcreator:
{ echo .; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \) -printf '%h\n' | sort -u; } > qtcreator.includes
touch qtcreator.creator
vcxsrc: $(GENFILES) $(EXTRA_TARGETS)
rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip}
VCX_DIR_NAME := yosys-win32-vcxsrc-$(YOSYS_VER)
vcxsrc: $(GENFILES) $(EXTRA_TARGETS) kernel/version_$(GIT_REV).cc
rm -rf $(VCX_DIR_NAME){,.zip}
cp -f kernel/version_$(GIT_REV).cc kernel/version.cc
set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \
echo "Analyse: $$f" >&2; cpp -std=c++17 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt
echo "libs/fst/fst_win_unistd.h" >> srcfiles.txt
bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV)
echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc
zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc
zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/
echo "kernel/version.cc" >> srcfiles.txt
bash misc/create_vcxsrc.sh $(VCX_DIR_NAME) $(YOSYS_VER)
zip $(VCX_DIR_NAME)/genfiles.zip $(GENFILES) kernel/version.cc
zip -r $(VCX_DIR_NAME).zip $(VCX_DIR_NAME)/
rm -f srcfiles.txt kernel/version.cc
config-clean: clean

2
abc

@ -1 +1 @@
Subproject commit 131a50dd773f21ebbfc51da1d182438382a04209
Subproject commit 799ba632239b2a4db2bacda81de4e6efdc486b0c

View file

@ -24,6 +24,7 @@
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@ -845,11 +846,14 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
return false;
int max = 1;
for (auto wire : mod->wires())
if (wire->port_input && !wire->port_output)
for (int i = 0; i < wire->width; i++) {
int ilevel = visit(cursor, driver->getPort(wire->name)[i]);
max = std::max(max, ilevel + 1);
for (auto wire : mod->wires()) {
if (wire->port_input && !wire->port_output) {
SigSpec port = driver->getPort(wire->name);
for (int i = 0; i < std::min(wire->width, port.size()); i++) {
int ilevel = visit(cursor, port[i]);
max = std::max(max, ilevel + 1);
}
}
}
lits[idx] = max;

View file

@ -756,7 +756,7 @@ struct CxxrtlWorker {
// 1b. Generated identifiers for internal names (beginning with `$`) start with `i_`.
// 2. An underscore is escaped with another underscore, i.e. `__`.
// 3. Any other non-alnum character is escaped with underscores around its lowercase hex code, e.g. `@` as `_40_`.
std::string mangle_name(const RTLIL::IdString &name)
std::string mangle_name(RTLIL::IdString name)
{
std::string mangled;
bool first = true;
@ -786,7 +786,7 @@ struct CxxrtlWorker {
return mangled;
}
std::string mangle_module_name(const RTLIL::IdString &name, bool is_blackbox = false)
std::string mangle_module_name(RTLIL::IdString name, bool is_blackbox = false)
{
// Class namespace.
if (is_blackbox)
@ -794,19 +794,19 @@ struct CxxrtlWorker {
return mangle_name(name);
}
std::string mangle_memory_name(const RTLIL::IdString &name)
std::string mangle_memory_name(RTLIL::IdString name)
{
// Class member namespace.
return "memory_" + mangle_name(name);
}
std::string mangle_cell_name(const RTLIL::IdString &name)
std::string mangle_cell_name(RTLIL::IdString name)
{
// Class member namespace.
return "cell_" + mangle_name(name);
}
std::string mangle_wire_name(const RTLIL::IdString &name)
std::string mangle_wire_name(RTLIL::IdString name)
{
// Class member namespace.
return mangle_name(name);

View file

@ -735,6 +735,12 @@ def ywfile_signal(sig, step, mask=None):
output = []
def ywfile_signal_error(reason, detail=None):
msg = f"Yosys witness signal mismatch for {sig.pretty()}: {reason}"
if detail:
msg += f" ({detail})"
raise ValueError(msg)
if sig.path in smt_wires:
for wire in smt_wires[sig.path]:
width, offset = wire["width"], wire["offset"]
@ -765,6 +771,12 @@ def ywfile_signal(sig, step, mask=None):
for mem in smt_mems[sig.memory_path]:
width, size, bv = mem["width"], mem["size"], mem["statebv"]
if sig.memory_addr is not None and sig.memory_addr >= size:
ywfile_signal_error(
"memory address out of bounds",
f"address={sig.memory_addr} size={size}",
)
smt_expr = smt.net_expr(topmod, f"s{step}", mem["smtpath"])
if bv:
@ -781,18 +793,34 @@ def ywfile_signal(sig, step, mask=None):
smt_expr = "((_ extract %d %d) %s)" % (slice_high, sig.offset, smt_expr)
output.append((0, sig.width, smt_expr))
else:
ywfile_signal_error("memory not found in design")
output.sort()
output = [chunk for chunk in output if chunk[0] != chunk[1]]
if not output:
if sig.memory_path:
ywfile_signal_error("memory signal has no matching bits in design")
else:
ywfile_signal_error("signal not found in design")
pos = 0
for start, end, smt_expr in output:
assert start == pos
if start != pos:
ywfile_signal_error(
"signal width/offset mismatch",
f"expected coverage at bit {pos}",
)
pos = end
assert pos == sig.width
if pos != sig.width:
ywfile_signal_error(
"signal width/offset mismatch",
f"covered {pos} of {sig.width} bits",
)
if len(output) == 1:
return output[0][-1]

View file

@ -2143,6 +2143,9 @@ void dump_case_actions(std::ostream &f, std::string indent, RTLIL::CaseRule *cs)
bool dump_proc_switch_ifelse(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw)
{
if (sw->cases.empty())
return true;
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) {
if ((*it)->compare.size() == 0) {
break;

View file

@ -5,8 +5,8 @@ import os
project = 'YosysHQ Yosys'
author = 'YosysHQ GmbH'
copyright ='2025 YosysHQ GmbH'
yosys_ver = "0.60"
copyright ='2026 YosysHQ GmbH'
yosys_ver = "0.61"
# select HTML theme
html_theme = 'furo-ys'

View file

@ -844,6 +844,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::Cell *cell = current_module->addCell(cellname, ID($check));
set_src_attr(cell, ast);
cell->set_bool_attribute(ID(keep));
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first);

View file

@ -879,7 +879,7 @@ static void check_auto_nosync(AstNode *node)
}
// remove the attributes we've "consumed"
for (const RTLIL::IdString &str : attrs_to_drop) {
for (RTLIL::IdString str : attrs_to_drop) {
auto it = node->attributes.find(str);
node->attributes.erase(it);
}
@ -4690,6 +4690,7 @@ void AstNode::expand_genblock(const std::string &prefix)
switch (child->type) {
case AST_WIRE:
case AST_AUTOWIRE:
case AST_MEMORY:
case AST_STRUCT:
case AST_UNION:
@ -4718,6 +4719,93 @@ void AstNode::expand_genblock(const std::string &prefix)
}
break;
case AST_IDENTIFIER:
if (!child->str.empty() && prefix.size() > 0) {
bool is_resolved = false;
std::string identifier_str = child->str;
if (current_ast_mod != nullptr && identifier_str.compare(0, current_ast_mod->str.size(), current_ast_mod->str) == 0) {
if (identifier_str.at(current_ast_mod->str.size()) == '.') {
identifier_str = '\\' + identifier_str.substr(current_ast_mod->str.size()+1, identifier_str.size());
}
}
// search starting in the innermost scope and then stepping outward
for (size_t ppos = prefix.size() - 1; ppos; --ppos) {
if (prefix.at(ppos) != '.') continue;
std::string new_prefix = prefix.substr(0, ppos + 1);
auto attempt_resolve = [&new_prefix](const std::string &ident) -> std::string {
std::string new_name = prefix_id(new_prefix, ident);
if (current_scope.count(new_name))
return new_name;
return {};
};
// attempt to resolve the full identifier
std::string resolved = attempt_resolve(identifier_str);
if (!resolved.empty()) {
is_resolved = true;
break;
}
// attempt to resolve hierarchical prefixes within the identifier,
// as the prefix could refer to a local scope which exists but
// hasn't yet been elaborated
for (size_t spos = identifier_str.size() - 1; spos; --spos) {
if (identifier_str.at(spos) != '.') continue;
resolved = attempt_resolve(identifier_str.substr(0, spos));
if (!resolved.empty()) {
is_resolved = true;
identifier_str = resolved + identifier_str.substr(spos);
ppos = 1; // break outer loop
break;
}
}
if (current_scope.count(identifier_str) == 0) {
AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
for (auto& node : current_scope_ast->children) {
switch (node->type) {
case AST_PARAMETER:
case AST_LOCALPARAM:
case AST_WIRE:
case AST_AUTOWIRE:
case AST_GENVAR:
case AST_MEMORY:
case AST_FUNCTION:
case AST_TASK:
case AST_DPI_FUNCTION:
if (prefix_id(new_prefix, identifier_str) == node->str) {
is_resolved = true;
current_scope[node->str] = node.get();
}
break;
case AST_ENUM:
current_scope[node->str] = node.get();
for (auto& enum_node : node->children) {
log_assert(enum_node->type==AST_ENUM_ITEM);
if (prefix_id(new_prefix, identifier_str) == enum_node->str) {
is_resolved = true;
current_scope[enum_node->str] = enum_node.get();
}
}
break;
default:
break;
}
}
}
}
if ((current_scope.count(identifier_str) == 0) && is_resolved == false) {
if (current_ast_mod == nullptr) {
input_error("Identifier `%s' is implicitly declared outside of a module.\n", child->str.c_str());
} else if (flag_autowire || identifier_str == "\\$global_clock") {
auto auto_wire = std::make_unique<AstNode>(child->location, AST_AUTOWIRE);
auto_wire->str = identifier_str;
children.push_back(std::move(auto_wire));
} else {
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", identifier_str.c_str());
}
}
}
break;
default:
break;
}

View file

@ -40,6 +40,7 @@ struct RTLILFrontendWorker {
bool flag_nooverwrite = false;
bool flag_overwrite = false;
bool flag_lib = false;
bool flag_legalize = false;
int line_num;
std::string line_buf;
@ -322,6 +323,17 @@ struct RTLILFrontendWorker {
return val;
}
RTLIL::Wire *legalize_wire(RTLIL::IdString id)
{
int wires_size = current_module->wires_size();
if (wires_size == 0)
error("No wires found for legalization");
int hash = hash_ops<RTLIL::IdString>::hash(id).yield();
RTLIL::Wire *wire = current_module->wire_at(abs(hash % wires_size));
log("Legalizing wire `%s' to `%s'.\n", log_id(id), log_id(wire->name));
return wire;
}
RTLIL::SigSpec parse_sigspec()
{
RTLIL::SigSpec sig;
@ -339,8 +351,12 @@ struct RTLILFrontendWorker {
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
RTLIL::Wire *wire = current_module->wire(*id);
if (wire == nullptr)
error("Wire `%s' not found.", *id);
if (wire == nullptr) {
if (flag_legalize)
wire = legalize_wire(*id);
else
error("Wire `%s' not found.", *id);
}
sig = RTLIL::SigSpec(wire);
} else {
sig = RTLIL::SigSpec(parse_const());
@ -349,17 +365,44 @@ struct RTLILFrontendWorker {
while (try_parse_char('[')) {
int left = parse_integer();
if (left >= sig.size() || left < 0)
error("bit index %d out of range", left);
if (left >= sig.size() || left < 0) {
if (flag_legalize) {
int legalized;
if (sig.size() == 0)
legalized = 0;
else
legalized = std::max(0, std::min(left, sig.size() - 1));
log("Legalizing bit index %d to %d.\n", left, legalized);
left = legalized;
} else {
error("bit index %d out of range", left);
}
}
if (try_parse_char(':')) {
int right = parse_integer();
if (right < 0)
error("bit index %d out of range", right);
if (left < right)
error("invalid slice [%d:%d]", left, right);
sig = sig.extract(right, left-right+1);
if (right < 0) {
if (flag_legalize) {
log("Legalizing bit index %d to %d.\n", right, 0);
right = 0;
} else
error("bit index %d out of range", right);
}
if (left < right) {
if (flag_legalize) {
log("Legalizing bit index %d to %d.\n", left, right);
left = right;
} else
error("invalid slice [%d:%d]", left, right);
}
if (flag_legalize && left >= sig.size())
log("Legalizing slice %d:%d by igoring it\n", left, right);
else
sig = sig.extract(right, left - right + 1);
} else {
sig = sig.extract(left);
if (flag_legalize && left >= sig.size())
log("Legalizing slice %d by igoring it\n", left);
else
sig = sig.extract(left);
}
expect_char(']');
}
@ -476,8 +519,14 @@ struct RTLILFrontendWorker {
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
if (current_module->wire(*id) != nullptr)
error("RTLIL error: redefinition of wire %s.", *id);
if (current_module->wire(*id) != nullptr) {
if (flag_legalize) {
log("Legalizing redefinition of wire %s.\n", *id);
pool<RTLIL::Wire*> wires = {current_module->wire(*id)};
current_module->remove(wires);
} else
error("RTLIL error: redefinition of wire %s.", *id);
}
wire = current_module->addWire(std::move(*id));
break;
}
@ -528,8 +577,13 @@ struct RTLILFrontendWorker {
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
if (current_module->memories.count(*id) != 0)
error("RTLIL error: redefinition of memory %s.", *id);
if (current_module->memories.count(*id) != 0) {
if (flag_legalize) {
log("Legalizing redefinition of memory %s.\n", *id);
current_module->remove(current_module->memories.at(*id));
} else
error("RTLIL error: redefinition of memory %s.", *id);
}
memory->name = std::move(*id);
break;
}
@ -551,14 +605,36 @@ struct RTLILFrontendWorker {
expect_eol();
}
void legalize_width_parameter(RTLIL::Cell *cell, RTLIL::IdString port_name)
{
std::string width_param_name = port_name.str() + "_WIDTH";
if (cell->parameters.count(width_param_name) == 0)
return;
RTLIL::Const &param = cell->parameters.at(width_param_name);
if (param.as_int() != 0)
return;
cell->parameters[width_param_name] = RTLIL::Const(cell->getPort(port_name).size());
}
void parse_cell()
{
RTLIL::IdString cell_type = parse_id();
RTLIL::IdString cell_name = parse_id();
expect_eol();
if (current_module->cell(cell_name) != nullptr)
error("RTLIL error: redefinition of cell %s.", cell_name);
if (current_module->cell(cell_name) != nullptr) {
if (flag_legalize) {
RTLIL::IdString new_name;
int suffix = 1;
do {
new_name = RTLIL::IdString(cell_name.str() + "_" + std::to_string(suffix));
++suffix;
} while (current_module->cell(new_name) != nullptr);
log("Legalizing redefinition of cell %s by renaming to %s.\n", cell_name, new_name);
cell_name = new_name;
} else
error("RTLIL error: redefinition of cell %s.", cell_name);
}
RTLIL::Cell *cell = current_module->addCell(cell_name, cell_type);
cell->attributes = std::move(attrbuf);
@ -587,9 +663,15 @@ struct RTLILFrontendWorker {
expect_eol();
} else if (try_parse_keyword("connect")) {
RTLIL::IdString port_name = parse_id();
if (cell->hasPort(port_name))
error("RTLIL error: redefinition of cell port %s.", port_name);
if (cell->hasPort(port_name)) {
if (flag_legalize)
log("Legalizing redefinition of cell port %s.", port_name);
else
error("RTLIL error: redefinition of cell port %s.", port_name);
}
cell->setPort(std::move(port_name), parse_sigspec());
if (flag_legalize)
legalize_width_parameter(cell, port_name);
expect_eol();
} else if (try_parse_keyword("end")) {
expect_eol();
@ -606,6 +688,11 @@ struct RTLILFrontendWorker {
error("dangling attribute");
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
if (flag_legalize) {
int min_size = std::min(s1.size(), s2.size());
s1 = s1.extract(0, min_size);
s2 = s2.extract(0, min_size);
}
current_module->connect(std::move(s1), std::move(s2));
expect_eol();
}
@ -682,8 +769,13 @@ struct RTLILFrontendWorker {
RTLIL::IdString proc_name = parse_id();
expect_eol();
if (current_module->processes.count(proc_name) != 0)
error("RTLIL error: redefinition of process %s.", proc_name);
if (current_module->processes.count(proc_name) != 0) {
if (flag_legalize) {
log("Legalizing redefinition of process %s.\n", proc_name);
current_module->remove(current_module->processes.at(proc_name));
} else
error("RTLIL error: redefinition of process %s.", proc_name);
}
RTLIL::Process *proc = current_module->addProcess(std::move(proc_name));
proc->attributes = std::move(attrbuf);
@ -804,6 +896,11 @@ struct RTLILFrontend : public Frontend {
log(" -lib\n");
log(" only create empty blackbox modules\n");
log("\n");
log(" -legalize\n");
log(" prevent semantic errors (e.g. reference to unknown wire, redefinition of wire/cell)\n");
log(" by deterministically rewriting the input into something valid. Useful when using\n");
log(" fuzzing to generate random but valid RTLIL.\n");
log("\n");
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
@ -828,6 +925,10 @@ struct RTLILFrontend : public Frontend {
worker.flag_lib = true;
continue;
}
if (arg == "-legalize") {
worker.flag_legalize = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);

View file

@ -1846,7 +1846,10 @@ struct VerificSvaImporter
if (mode_assume) c = module->addAssume(root_name, sig_a_q, sig_en_q);
if (mode_cover) c = module->addCover(root_name, sig_a_q, sig_en_q);
if (c) importer->import_attributes(c->attributes, root);
if (c) {
c->set_bool_attribute(ID(keep));
importer->import_attributes(c->attributes, root);
}
}
}
catch (ParserErrorException)

View file

@ -500,7 +500,6 @@ struct VerilogFrontend : public Frontend {
log("Parsing %s%s input from `%s' to AST representation.\n",
parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
log("verilog frontend filename %s\n", filename.c_str());
if (flag_relative_share) {
auto share_path = proc_share_dirname();
if (filename.substr(0, share_path.length()) == share_path)

View file

@ -185,50 +185,68 @@ struct AigMaker
int or_gate(int A, int B)
{
return nand_gate(not_gate(A), not_gate(B));
int not_a = not_gate(A);
int not_b = not_gate(B);
return nand_gate(not_a, not_b);
}
int nor_gate(int A, int B)
{
return and_gate(not_gate(A), not_gate(B));
int not_a = not_gate(A);
int not_b = not_gate(B);
return and_gate(not_a, not_b);
}
int xor_gate(int A, int B)
{
return nor_gate(and_gate(A, B), nor_gate(A, B));
int a_and_b = and_gate(A, B);
int a_nor_b = nor_gate(A, B);
return nor_gate(a_and_b, a_nor_b);
}
int xnor_gate(int A, int B)
{
return or_gate(and_gate(A, B), nor_gate(A, B));
int a_and_b = and_gate(A, B);
int a_nor_b = nor_gate(A, B);
return or_gate(a_and_b, a_nor_b);
}
int andnot_gate(int A, int B)
{
return and_gate(A, not_gate(B));
int not_b = not_gate(B);
return and_gate(A, not_b);
}
int ornot_gate(int A, int B)
{
return or_gate(A, not_gate(B));
int not_b = not_gate(B);
return or_gate(A, not_b);
}
int mux_gate(int A, int B, int S)
{
return or_gate(and_gate(A, not_gate(S)), and_gate(B, S));
int not_s = not_gate(S);
int a_active = and_gate(A, not_s);
int b_active = and_gate(B, S);
return or_gate(a_active, b_active);
}
vector<int> adder(const vector<int> &A, const vector<int> &B, int carry, vector<int> *X = nullptr, vector<int> *CO = nullptr)
vector<int> adder(const vector<int> &A, const vector<int> &B, int carry_in, vector<int> *X = nullptr, vector<int> *CO = nullptr)
{
vector<int> Y(GetSize(A));
log_assert(GetSize(A) == GetSize(B));
for (int i = 0; i < GetSize(A); i++) {
Y[i] = xor_gate(xor_gate(A[i], B[i]), carry);
carry = or_gate(and_gate(A[i], B[i]), and_gate(or_gate(A[i], B[i]), carry));
int a_xor_b = xor_gate(A[i], B[i]);
int a_or_b = or_gate(A[i], B[i]);
int a_and_b = and_gate(A[i], B[i]);
Y[i] = xor_gate(a_xor_b, carry_in);
int tmp = and_gate(a_or_b, carry_in);
int carry_out = or_gate(a_and_b, tmp);
if (X != nullptr)
X->at(i) = xor_gate(A[i], B[i]);
X->at(i) = a_xor_b;
if (CO != nullptr)
CO->at(i) = carry;
CO->at(i) = carry_out;
carry_in = carry_out;
}
return Y;
}
@ -307,13 +325,13 @@ Aig::Aig(Cell *cell)
int A = mk.inport(ID::A, i);
int B = mk.inport(ID::B, i);
int Y = cell->type.in(ID($and), ID($_AND_)) ? mk.and_gate(A, B) :
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
cell->type.in(ID($or), ID($_OR_)) ? mk.or_gate(A, B) :
cell->type.in(ID($_NOR_)) ? mk.nor_gate(A, B) :
cell->type.in(ID($_NOR_)) ? mk.nor_gate(A, B) :
cell->type.in(ID($xor), ID($_XOR_)) ? mk.xor_gate(A, B) :
cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
mk.outport(Y, ID::Y, i);
}
goto optimize;
@ -465,7 +483,8 @@ Aig::Aig(Cell *cell)
int B = mk.inport(ID::B);
int C = mk.inport(ID::C);
int D = mk.inport(ID::D);
int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
int a_and_b = mk.and_gate(A, B);
int Y = mk.nor_gate(a_and_b, mk.and_gate(C, D));
mk.outport(Y, ID::Y);
goto optimize;
}
@ -476,7 +495,8 @@ Aig::Aig(Cell *cell)
int B = mk.inport(ID::B);
int C = mk.inport(ID::C);
int D = mk.inport(ID::D);
int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
int a_or_b = mk.or_gate(A, B);
int Y = mk.nand_gate(a_or_b, mk.or_gate(C, D));
mk.outport(Y, ID::Y);
goto optimize;
}

View file

@ -305,18 +305,18 @@ struct CellTypes
cell_types.clear();
}
bool cell_known(const RTLIL::IdString &type) const
bool cell_known(RTLIL::IdString type) const
{
return cell_types.count(type) != 0;
}
bool cell_output(const RTLIL::IdString &type, const RTLIL::IdString &port) const
bool cell_output(RTLIL::IdString type, RTLIL::IdString port) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.outputs.count(port) != 0;
}
bool cell_input(const RTLIL::IdString &type, const RTLIL::IdString &port) const
bool cell_input(RTLIL::IdString type, RTLIL::IdString port) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.inputs.count(port) != 0;
@ -332,7 +332,7 @@ struct CellTypes
return RTLIL::PortDir(is_input + is_output * 2);
}
bool cell_evaluable(const RTLIL::IdString &type) const
bool cell_evaluable(RTLIL::IdString type) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.is_evaluable;

View file

@ -255,6 +255,7 @@ int main(int argc, char **argv)
("h,help", "print this help message. If given, print help for <command>.",
cxxopts::value<std::string>(), "[<command>]")
("V,version", "print version information and exit")
("git-hash", "print git commit hash and exit")
("infile", "input files", cxxopts::value<std::vector<std::string>>())
;
options.add_options("logging")
@ -332,6 +333,10 @@ int main(int argc, char **argv)
std::cout << yosys_version_str << std::endl;
exit(0);
}
if (result.count("git-hash")) {
std::cout << yosys_git_hash_str << std::endl;
exit(0);
}
if (result.count("S")) {
passes_commands.push_back("synth");
run_shell = false;
@ -764,33 +769,6 @@ int main(int argc, char **argv)
}
}
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE"))
{
string filename;
FILE *f;
if (getenv("YOSYS_COVER_DIR")) {
filename = stringf("%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid());
filename = make_temp_file(filename);
} else {
filename = getenv("YOSYS_COVER_FILE");
}
f = fopen(filename.c_str(), "a+");
if (f == NULL)
log_error("Can't create coverage file `%s'.\n", filename);
log("<writing coverage file \"%s\">\n", filename);
for (auto &it : get_coverage_data())
fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());
fclose(f);
}
#endif
log_check_expected();
yosys_atexit();

View file

@ -1321,6 +1321,12 @@ public:
return i < 0 ? 0 : 1;
}
int lookup(const K &key) const
{
Hasher::hash_t hash = database.do_hash(key);
return database.do_lookup_no_rehash(key, hash);
}
void expect(const K &key, int i)
{
int j = (*this)(key);

View file

@ -602,7 +602,7 @@ void format_emit_string_view(std::string &result, std::string_view spec, int *dy
}
void format_emit_idstring(std::string &result, std::string_view spec, int *dynamic_ints,
DynamicIntCount num_dynamic_ints, const IdString &arg)
DynamicIntCount num_dynamic_ints, const RTLIL::IdString &arg)
{
if (spec == "%s") {
// Format checking will have guaranteed num_dynamic_ints == 0.

View file

@ -90,11 +90,11 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&counter);
counter.QuadPart *= 1000000;
counter.QuadPart *= 1'000'000;
counter.QuadPart /= freq.QuadPart;
tv->tv_sec = long(counter.QuadPart / 1000000);
tv->tv_usec = counter.QuadPart % 1000000;
tv->tv_usec = counter.QuadPart % 1'000'000;
return 0;
}
@ -135,7 +135,7 @@ static void logv_string(std::string_view format, std::string str) {
initial_tv = tv;
if (tv.tv_usec < initial_tv.tv_usec) {
tv.tv_sec--;
tv.tv_usec += 1000000;
tv.tv_usec += 1'000'000;
}
tv.tv_sec -= initial_tv.tv_sec;
tv.tv_usec -= initial_tv.tv_usec;
@ -203,6 +203,8 @@ static void logv_string(std::string_view format, std::string str) {
void log_formatted_string(std::string_view format, std::string str)
{
log_assert(!Multithreading::active());
if (log_make_debug && !ys_debug(1))
return;
logv_string(format, std::move(str));
@ -210,6 +212,8 @@ void log_formatted_string(std::string_view format, std::string str)
void log_formatted_header(RTLIL::Design *design, std::string_view format, std::string str)
{
log_assert(!Multithreading::active());
bool pop_errfile = false;
log_spacer();
@ -249,6 +253,8 @@ void log_formatted_header(RTLIL::Design *design, std::string_view format, std::s
void log_formatted_warning(std::string_view prefix, std::string message)
{
log_assert(!Multithreading::active());
bool suppressed = false;
for (auto &re : log_nowarn_regexes)
@ -681,55 +687,4 @@ void log_check_expected()
check_err("prefixed error", pattern, item);
}
// ---------------------------------------------------
// This is the magic behind the code coverage counters
// ---------------------------------------------------
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
dict<std::string, std::pair<std::string, int>> extra_coverage_data;
void cover_extra(std::string parent, std::string id, bool increment) {
if (extra_coverage_data.count(id) == 0) {
for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++)
if (p->id == parent)
extra_coverage_data[id].first = stringf("%s:%d:%s", p->file, p->line, p->func);
log_assert(extra_coverage_data.count(id));
}
if (increment)
extra_coverage_data[id].second++;
}
dict<std::string, std::pair<std::string, int>> get_coverage_data()
{
dict<std::string, std::pair<std::string, int>> coverage_data;
for (auto &it : pass_register) {
std::string key = stringf("passes.%s", it.first);
coverage_data[key].first = stringf("%s:%d:%s", __FILE__, __LINE__, __FUNCTION__);
coverage_data[key].second += it.second->call_counter;
}
for (auto &it : extra_coverage_data) {
if (coverage_data.count(it.first))
log_warning("found duplicate coverage id \"%s\".\n", it.first);
coverage_data[it.first].first = it.second.first;
coverage_data[it.first].second += it.second.second;
}
for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++) {
if (coverage_data.count(p->id))
log_warning("found duplicate coverage id \"%s\".\n", p->id);
coverage_data[p->id].first = stringf("%s:%d:%s", p->file, p->line, p->func);
coverage_data[p->id].second += p->counter.load(std::memory_order_relaxed);
}
for (auto &it : coverage_data)
if (!it.second.first.compare(0, strlen(YOSYS_SRC "/"), YOSYS_SRC "/"))
it.second.first = it.second.first.substr(strlen(YOSYS_SRC "/"));
return coverage_data;
}
#endif
YOSYS_NAMESPACE_END

View file

@ -291,54 +291,6 @@ void log_abort_internal(const char *file, int line);
#define log_ping() YOSYS_NAMESPACE_PREFIX log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__)
// ---------------------------------------------------
// This is the magic behind the code coverage counters
// ---------------------------------------------------
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
#define cover(_id) do { \
static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \
__d.counter.fetch_add(1, std::memory_order_relaxed); \
} while (0)
struct CoverData {
const char *file, *func, *id;
int line;
std::atomic<int> counter;
};
// this two symbols are created by the linker __start_yosys_cover_listfor the "yosys_cover_list" ELF section
extern "C" struct CoverData __start_yosys_cover_list[];
extern "C" struct CoverData __stop_yosys_cover_list[];
extern dict<std::string, std::pair<std::string, int>> extra_coverage_data;
void cover_extra(std::string parent, std::string id, bool increment = true);
dict<std::string, std::pair<std::string, int>> get_coverage_data();
#define cover_list(_id, ...) do { cover(_id); \
std::string r = cover_list_worker(_id, __VA_ARGS__); \
log_assert(r.empty()); \
} while (0)
static inline std::string cover_list_worker(std::string, std::string last) {
return last;
}
template<typename... T>
std::string cover_list_worker(std::string prefix, std::string first, T... rest) {
std::string selected = cover_list_worker(prefix, rest...);
cover_extra(prefix, prefix + "." + first, first == selected);
return first == selected ? "" : selected;
}
#else
# define cover(...) do { } while (0)
# define cover_list(...) do { } while (0)
#endif
// ------------------------------------------------------------
// everything below this line are utilities for troubleshooting
// ------------------------------------------------------------

View file

@ -161,7 +161,7 @@ struct ModIndex : public RTLIL::Monitor
#endif
}
void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
void notify_connect(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
{
log_assert(module == cell->module);

View file

@ -1204,7 +1204,7 @@ struct LicensePass : public Pass {
log(" | |\n");
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
log(" | |\n");
log(" | Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com> |\n");
log(" | Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com> |\n");
log(" | |\n");
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
log(" | purpose with or without fee is hereby granted, provided that the above |\n");

View file

@ -883,8 +883,6 @@ RTLIL::State RTLIL::Const::const_iterator::operator*() const {
bool RTLIL::Const::is_fully_zero() const
{
cover("kernel.rtlil.const.is_fully_zero");
if (auto str = get_if_str()) {
for (char ch : *str)
if (ch != 0)
@ -903,8 +901,6 @@ bool RTLIL::Const::is_fully_zero() const
bool RTLIL::Const::is_fully_ones() const
{
cover("kernel.rtlil.const.is_fully_ones");
if (auto str = get_if_str()) {
for (char ch : *str)
if (ch != (char)0xff)
@ -922,8 +918,6 @@ bool RTLIL::Const::is_fully_ones() const
bool RTLIL::Const::is_fully_def() const
{
cover("kernel.rtlil.const.is_fully_def");
if (is_str())
return true;
@ -937,8 +931,6 @@ bool RTLIL::Const::is_fully_def() const
bool RTLIL::Const::is_fully_undef() const
{
cover("kernel.rtlil.const.is_fully_undef");
if (auto str = get_if_str())
return str->empty();
@ -952,8 +944,6 @@ bool RTLIL::Const::is_fully_undef() const
bool RTLIL::Const::is_fully_undef_x_only() const
{
cover("kernel.rtlil.const.is_fully_undef_x_only");
if (auto str = get_if_str())
return str->empty();
@ -967,8 +957,6 @@ bool RTLIL::Const::is_fully_undef_x_only() const
bool RTLIL::Const::is_onehot(int *pos) const
{
cover("kernel.rtlil.const.is_onehot");
bool found = false;
int size = GetSize(*this);
for (int i = 0; i < size; i++) {
@ -1029,12 +1017,12 @@ RTLIL::Const RTLIL::Const::extract(int offset, int len, RTLIL::State padding) co
}
#undef check /* check(condition) for Const */
bool RTLIL::AttrObject::has_attribute(const RTLIL::IdString &id) const
bool RTLIL::AttrObject::has_attribute(RTLIL::IdString id) const
{
return attributes.count(id);
}
void RTLIL::AttrObject::set_bool_attribute(const RTLIL::IdString &id, bool value)
void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id, bool value)
{
if (value)
attributes[id] = RTLIL::Const(1);
@ -1042,7 +1030,7 @@ void RTLIL::AttrObject::set_bool_attribute(const RTLIL::IdString &id, bool value
attributes.erase(id);
}
bool RTLIL::AttrObject::get_bool_attribute(const RTLIL::IdString &id) const
bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const
{
const auto it = attributes.find(id);
if (it == attributes.end())
@ -1050,7 +1038,7 @@ bool RTLIL::AttrObject::get_bool_attribute(const RTLIL::IdString &id) const
return it->second.as_bool();
}
void RTLIL::AttrObject::set_string_attribute(const RTLIL::IdString& id, string value)
void RTLIL::AttrObject::set_string_attribute(RTLIL::IdString id, string value)
{
if (value.empty())
attributes.erase(id);
@ -1058,7 +1046,7 @@ void RTLIL::AttrObject::set_string_attribute(const RTLIL::IdString& id, string v
attributes[id] = value;
}
string RTLIL::AttrObject::get_string_attribute(const RTLIL::IdString &id) const
string RTLIL::AttrObject::get_string_attribute(RTLIL::IdString id) const
{
std::string value;
const auto it = attributes.find(id);
@ -1067,7 +1055,7 @@ string RTLIL::AttrObject::get_string_attribute(const RTLIL::IdString &id) const
return value;
}
void RTLIL::AttrObject::set_strpool_attribute(const RTLIL::IdString& id, const pool<string> &data)
void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
{
string attrval;
for (const auto &s : data) {
@ -1078,7 +1066,7 @@ void RTLIL::AttrObject::set_strpool_attribute(const RTLIL::IdString& id, const p
set_string_attribute(id, attrval);
}
void RTLIL::AttrObject::add_strpool_attribute(const RTLIL::IdString& id, const pool<string> &data)
void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
{
pool<string> union_data = get_strpool_attribute(id);
union_data.insert(data.begin(), data.end());
@ -1086,7 +1074,7 @@ void RTLIL::AttrObject::add_strpool_attribute(const RTLIL::IdString& id, const p
set_strpool_attribute(id, union_data);
}
pool<string> RTLIL::AttrObject::get_strpool_attribute(const RTLIL::IdString &id) const
pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
{
pool<string> data;
if (attributes.count(id) != 0)
@ -1111,7 +1099,7 @@ vector<string> RTLIL::AttrObject::get_hdlname_attribute() const
return split_tokens(get_string_attribute(ID::hdlname), " ");
}
void RTLIL::AttrObject::set_intvec_attribute(const RTLIL::IdString& id, const vector<int> &data)
void RTLIL::AttrObject::set_intvec_attribute(RTLIL::IdString id, const vector<int> &data)
{
std::stringstream attrval;
for (auto &i : data) {
@ -1122,7 +1110,7 @@ void RTLIL::AttrObject::set_intvec_attribute(const RTLIL::IdString& id, const ve
attributes[id] = RTLIL::Const(attrval.str());
}
vector<int> RTLIL::AttrObject::get_intvec_attribute(const RTLIL::IdString &id) const
vector<int> RTLIL::AttrObject::get_intvec_attribute(RTLIL::IdString id) const
{
vector<int> data;
auto it = attributes.find(id);
@ -1140,7 +1128,7 @@ vector<int> RTLIL::AttrObject::get_intvec_attribute(const RTLIL::IdString &id) c
return data;
}
bool RTLIL::Selection::boxed_module(const RTLIL::IdString &mod_name) const
bool RTLIL::Selection::boxed_module(RTLIL::IdString mod_name) const
{
if (current_design != nullptr) {
auto module = current_design->module(mod_name);
@ -1151,7 +1139,7 @@ bool RTLIL::Selection::boxed_module(const RTLIL::IdString &mod_name) const
}
}
bool RTLIL::Selection::selected_module(const RTLIL::IdString &mod_name) const
bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
{
if (complete_selection)
return true;
@ -1166,7 +1154,7 @@ bool RTLIL::Selection::selected_module(const RTLIL::IdString &mod_name) const
return false;
}
bool RTLIL::Selection::selected_whole_module(const RTLIL::IdString &mod_name) const
bool RTLIL::Selection::selected_whole_module(RTLIL::IdString mod_name) const
{
if (complete_selection)
return true;
@ -1179,7 +1167,7 @@ bool RTLIL::Selection::selected_whole_module(const RTLIL::IdString &mod_name) co
return false;
}
bool RTLIL::Selection::selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const
bool RTLIL::Selection::selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const
{
if (complete_selection)
return true;
@ -1306,12 +1294,12 @@ RTLIL::ObjRange<RTLIL::Module*> RTLIL::Design::modules()
return RTLIL::ObjRange<RTLIL::Module*>(&modules_, &refcount_modules_);
}
RTLIL::Module *RTLIL::Design::module(const RTLIL::IdString& name)
RTLIL::Module *RTLIL::Design::module(RTLIL::IdString name)
{
return modules_.count(name) ? modules_.at(name) : NULL;
}
const RTLIL::Module *RTLIL::Design::module(const RTLIL::IdString& name) const
const RTLIL::Module *RTLIL::Design::module(RTLIL::IdString name) const
{
return modules_.count(name) ? modules_.at(name) : NULL;
}
@ -1500,21 +1488,21 @@ void RTLIL::Design::optimize()
it.second.optimize(this);
}
bool RTLIL::Design::selected_module(const RTLIL::IdString& mod_name) const
bool RTLIL::Design::selected_module(RTLIL::IdString mod_name) const
{
if (!selected_active_module.empty() && mod_name != selected_active_module)
return false;
return selection().selected_module(mod_name);
}
bool RTLIL::Design::selected_whole_module(const RTLIL::IdString& mod_name) const
bool RTLIL::Design::selected_whole_module(RTLIL::IdString mod_name) const
{
if (!selected_active_module.empty() && mod_name != selected_active_module)
return false;
return selection().selected_whole_module(mod_name);
}
bool RTLIL::Design::selected_member(const RTLIL::IdString& mod_name, const RTLIL::IdString& memb_name) const
bool RTLIL::Design::selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const
{
if (!selected_active_module.empty() && mod_name != selected_active_module)
return false;
@ -1705,7 +1693,7 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict<RTLIL::IdString
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
}
size_t RTLIL::Module::count_id(const RTLIL::IdString& id)
size_t RTLIL::Module::count_id(RTLIL::IdString id)
{
return wires_.count(id) + memories.count(id) + cells_.count(id) + processes.count(id);
}
@ -1730,7 +1718,7 @@ namespace {
cell->name.c_str(), cell->type.c_str(), __FILE__, linenr, buf.str().c_str());
}
int param(const RTLIL::IdString& name)
int param(RTLIL::IdString name)
{
auto it = cell->parameters.find(name);
if (it == cell->parameters.end())
@ -1739,7 +1727,7 @@ namespace {
return it->second.as_int();
}
int param_bool(const RTLIL::IdString& name)
int param_bool(RTLIL::IdString name)
{
int v = param(name);
if (GetSize(cell->parameters.at(name)) > 32)
@ -1749,7 +1737,7 @@ namespace {
return v;
}
int param_bool(const RTLIL::IdString& name, bool expected)
int param_bool(RTLIL::IdString name, bool expected)
{
int v = param_bool(name);
if (v != expected)
@ -1757,20 +1745,20 @@ namespace {
return v;
}
void param_bits(const RTLIL::IdString& name, int width)
void param_bits(RTLIL::IdString name, int width)
{
param(name);
if (GetSize(cell->parameters.at(name)) != width)
error(__LINE__);
}
std::string param_string(const RTLIL::IdString &name)
std::string param_string(RTLIL::IdString name)
{
param(name);
return cell->parameters.at(name).decode_string();
}
void port(const RTLIL::IdString& name, int width)
void port(RTLIL::IdString name, int width)
{
auto it = cell->connections_.find(name);
if (it == cell->connections_.end())
@ -3051,6 +3039,13 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
}
}
void RTLIL::Module::remove(RTLIL::Memory *memory)
{
log_assert(memories.count(memory->name) != 0);
memories.erase(memory->name);
delete memory;
}
void RTLIL::Module::remove(RTLIL::Process *process)
{
log_assert(processes.count(process->name) != 0);
@ -4378,14 +4373,14 @@ std::map<unsigned int, RTLIL::Cell*> *RTLIL::Cell::get_all_cells(void)
}
#endif
bool RTLIL::Cell::hasPort(const RTLIL::IdString& portname) const
bool RTLIL::Cell::hasPort(RTLIL::IdString portname) const
{
return connections_.count(portname) != 0;
}
// bufnorm
const RTLIL::SigSpec &RTLIL::Cell::getPort(const RTLIL::IdString& portname) const
const RTLIL::SigSpec &RTLIL::Cell::getPort(RTLIL::IdString portname) const
{
return connections_.at(portname);
}
@ -4404,7 +4399,7 @@ bool RTLIL::Cell::known() const
return false;
}
bool RTLIL::Cell::input(const RTLIL::IdString& portname) const
bool RTLIL::Cell::input(RTLIL::IdString portname) const
{
if (yosys_celltypes.cell_known(type))
return yosys_celltypes.cell_input(type, portname);
@ -4416,7 +4411,7 @@ bool RTLIL::Cell::input(const RTLIL::IdString& portname) const
return false;
}
bool RTLIL::Cell::output(const RTLIL::IdString& portname) const
bool RTLIL::Cell::output(RTLIL::IdString portname) const
{
if (yosys_celltypes.cell_known(type))
return yosys_celltypes.cell_output(type, portname);
@ -4428,7 +4423,7 @@ bool RTLIL::Cell::output(const RTLIL::IdString& portname) const
return false;
}
RTLIL::PortDir RTLIL::Cell::port_dir(const RTLIL::IdString& portname) const
RTLIL::PortDir RTLIL::Cell::port_dir(RTLIL::IdString portname) const
{
if (yosys_celltypes.cell_known(type))
return yosys_celltypes.cell_port_dir(type, portname);
@ -4444,22 +4439,22 @@ RTLIL::PortDir RTLIL::Cell::port_dir(const RTLIL::IdString& portname) const
return PortDir::PD_UNKNOWN;
}
bool RTLIL::Cell::hasParam(const RTLIL::IdString& paramname) const
bool RTLIL::Cell::hasParam(RTLIL::IdString paramname) const
{
return parameters.count(paramname) != 0;
}
void RTLIL::Cell::unsetParam(const RTLIL::IdString& paramname)
void RTLIL::Cell::unsetParam(RTLIL::IdString paramname)
{
parameters.erase(paramname);
}
void RTLIL::Cell::setParam(const RTLIL::IdString& paramname, RTLIL::Const value)
void RTLIL::Cell::setParam(RTLIL::IdString paramname, RTLIL::Const value)
{
parameters[paramname] = std::move(value);
}
const RTLIL::Const &RTLIL::Cell::getParam(const RTLIL::IdString& paramname) const
const RTLIL::Const &RTLIL::Cell::getParam(RTLIL::IdString paramname) const
{
const auto &it = parameters.find(paramname);
if (it != parameters.end())
@ -4648,8 +4643,6 @@ bool RTLIL::SigChunk::operator !=(const RTLIL::SigChunk &other) const
RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts)
{
cover("kernel.rtlil.sigspec.init.list");
init_empty_bits();
log_assert(parts.size() > 0);
auto ie = parts.begin();
@ -4660,8 +4653,6 @@ RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts)
RTLIL::SigSpec::SigSpec(const RTLIL::Const &value)
{
cover("kernel.rtlil.sigspec.init.const");
if (GetSize(value) != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(value);
@ -4673,8 +4664,6 @@ RTLIL::SigSpec::SigSpec(const RTLIL::Const &value)
RTLIL::SigSpec::SigSpec(RTLIL::Const &&value)
{
cover("kernel.rtlil.sigspec.init.const.move");
if (GetSize(value) != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(value);
@ -4686,8 +4675,6 @@ RTLIL::SigSpec::SigSpec(RTLIL::Const &&value)
RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk)
{
cover("kernel.rtlil.sigspec.init.chunk");
if (chunk.width != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(chunk);
@ -4699,8 +4686,6 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk)
RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk)
{
cover("kernel.rtlil.sigspec.init.chunk.move");
if (chunk.width != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(chunk);
@ -4712,8 +4697,6 @@ RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk)
RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire)
{
cover("kernel.rtlil.sigspec.init.wire");
if (wire->width != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(wire);
@ -4725,8 +4708,6 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire)
RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width)
{
cover("kernel.rtlil.sigspec.init.wire_part");
if (width != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(wire, offset, width);
@ -4738,8 +4719,6 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width)
RTLIL::SigSpec::SigSpec(const std::string &str)
{
cover("kernel.rtlil.sigspec.init.str");
if (str.size() != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(str);
@ -4751,8 +4730,6 @@ RTLIL::SigSpec::SigSpec(const std::string &str)
RTLIL::SigSpec::SigSpec(int val, int width)
{
cover("kernel.rtlil.sigspec.init.int");
if (width != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(val, width);
@ -4763,8 +4740,6 @@ RTLIL::SigSpec::SigSpec(int val, int width)
RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width)
{
cover("kernel.rtlil.sigspec.init.state");
if (width != 0) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(bit, width);
@ -4775,8 +4750,6 @@ RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width)
RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
{
cover("kernel.rtlil.sigspec.init.bit");
if (width != 0) {
if (bit.wire == NULL) {
rep_ = CHUNK;
@ -4797,8 +4770,6 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigChunk> &chunks)
{
cover("kernel.rtlil.sigspec.init.stdvec_chunks");
init_empty_bits();
for (const auto &c : chunks)
append(c);
@ -4807,8 +4778,6 @@ RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigChunk> &chunks)
RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigBit> &bits)
{
cover("kernel.rtlil.sigspec.init.stdvec_bits");
init_empty_bits();
for (const auto &bit : bits)
append(bit);
@ -4817,8 +4786,6 @@ RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigBit> &bits)
RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits)
{
cover("kernel.rtlil.sigspec.init.pool_bits");
init_empty_bits();
for (const auto &bit : bits)
append(bit);
@ -4827,8 +4794,6 @@ RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits)
RTLIL::SigSpec::SigSpec(const std::set<RTLIL::SigBit> &bits)
{
cover("kernel.rtlil.sigspec.init.stdset_bits");
init_empty_bits();
for (const auto &bit : bits)
append(bit);
@ -4837,8 +4802,6 @@ RTLIL::SigSpec::SigSpec(const std::set<RTLIL::SigBit> &bits)
RTLIL::SigSpec::SigSpec(bool bit)
{
cover("kernel.rtlil.sigspec.init.bool");
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(bit ? RTLIL::S1 : RTLIL::S0);
check();
@ -4874,8 +4837,6 @@ void RTLIL::SigSpec::unpack()
if (rep_ == BITS)
return;
cover("kernel.rtlil.sigspec.convert.unpack");
std::vector<RTLIL::SigBit> bits;
bits.reserve(chunk_.width);
for (int i = 0; i < chunk_.width; i++)
@ -4891,8 +4852,6 @@ void RTLIL::SigSpec::try_repack()
if (rep_ != BITS)
return;
cover("kernel.rtlil.sigspec.convert.try_repack");
int bits_size = GetSize(bits_);
if (bits_size == 0)
return;
@ -4921,8 +4880,6 @@ void RTLIL::SigSpec::try_repack()
Hasher::hash_t RTLIL::SigSpec::updhash() const
{
cover("kernel.rtlil.sigspec.hash");
Hasher h;
for (auto &c : chunks())
if (c.wire == NULL) {
@ -4943,7 +4900,6 @@ Hasher::hash_t RTLIL::SigSpec::updhash() const
void RTLIL::SigSpec::sort()
{
unpack();
cover("kernel.rtlil.sigspec.sort");
std::sort(bits_.begin(), bits_.end());
hash_.clear();
try_repack();
@ -4952,8 +4908,6 @@ void RTLIL::SigSpec::sort()
void RTLIL::SigSpec::sort_and_unify()
{
unpack();
cover("kernel.rtlil.sigspec.sort_and_unify");
// A copy of the bits vector is used to prevent duplicating the logic from
// SigSpec::SigSpec(std::vector<SigBit>). This incurrs an extra copy but
// that isn't showing up as significant in profiles.
@ -5009,8 +4963,6 @@ void RTLIL::SigSpec::replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules)
void RTLIL::SigSpec::replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules, RTLIL::SigSpec *other) const
{
cover("kernel.rtlil.sigspec.replace_dict");
log_assert(other != NULL);
log_assert(size() == other->size());
@ -5038,8 +4990,6 @@ void RTLIL::SigSpec::replace(const std::map<RTLIL::SigBit, RTLIL::SigBit> &rules
void RTLIL::SigSpec::replace(const std::map<RTLIL::SigBit, RTLIL::SigBit> &rules, RTLIL::SigSpec *other) const
{
cover("kernel.rtlil.sigspec.replace_map");
log_assert(other != NULL);
log_assert(size() == other->size());
@ -5073,11 +5023,6 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other
void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other)
{
if (other)
cover("kernel.rtlil.sigspec.remove_other");
else
cover("kernel.rtlil.sigspec.remove");
unpack();
if (other != NULL) {
log_assert(size() == other->size());
@ -5128,11 +5073,6 @@ void RTLIL::SigSpec::remove(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *
void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other)
{
if (other)
cover("kernel.rtlil.sigspec.remove_other");
else
cover("kernel.rtlil.sigspec.remove");
unpack();
if (other != NULL) {
@ -5166,11 +5106,6 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec
void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other)
{
if (other)
cover("kernel.rtlil.sigspec.remove_other");
else
cover("kernel.rtlil.sigspec.remove");
unpack();
if (other != NULL) {
@ -5204,11 +5139,6 @@ void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigS
void RTLIL::SigSpec::remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *other)
{
if (other)
cover("kernel.rtlil.sigspec.remove_other");
else
cover("kernel.rtlil.sigspec.remove");
unpack();
if (other != NULL) {
@ -5242,11 +5172,6 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *
RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const
{
if (other)
cover("kernel.rtlil.sigspec.extract_other");
else
cover("kernel.rtlil.sigspec.extract");
log_assert(other == NULL || size() == other->size());
RTLIL::SigSpec ret;
@ -5280,11 +5205,6 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLI
RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other) const
{
if (other)
cover("kernel.rtlil.sigspec.extract_other");
else
cover("kernel.rtlil.sigspec.extract");
log_assert(other == NULL || size() == other->size());
std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector();
@ -5310,8 +5230,6 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const
void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with)
{
cover("kernel.rtlil.sigspec.replace_pos");
if (with.size() == 0)
return;
@ -5336,8 +5254,6 @@ void RTLIL::SigSpec::remove_const()
{
if (rep_ == CHUNK)
{
cover("kernel.rtlil.sigspec.remove_const.packed");
if (chunk_.wire == NULL) {
chunk_.~SigChunk();
init_empty_bits();
@ -5346,8 +5262,6 @@ void RTLIL::SigSpec::remove_const()
}
else
{
cover("kernel.rtlil.sigspec.remove_const.unpacked");
std::vector<RTLIL::SigBit> new_bits;
new_bits.reserve(bits_.size());
for (auto &bit : bits_)
@ -5365,8 +5279,6 @@ void RTLIL::SigSpec::remove_const()
void RTLIL::SigSpec::remove(int offset, int length)
{
cover("kernel.rtlil.sigspec.remove_pos");
if (length == 0)
return;
@ -5389,8 +5301,6 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
log_assert(length >= 0);
log_assert(offset + length <= size());
cover("kernel.rtlil.sigspec.extract_pos");
SigSpec extracted;
Chunks cs = chunks();
auto it = cs.begin();
@ -5444,8 +5354,6 @@ void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal)
return;
}
cover("kernel.rtlil.sigspec.append");
hash_.clear();
if (rep_ == CHUNK && signal.rep_ == CHUNK && chunk_.wire == signal.chunk_.wire) {
if (chunk_.wire == NULL) {
@ -5477,8 +5385,6 @@ void RTLIL::SigSpec::append(const RTLIL::SigBit &bit)
}
if (rep_ == CHUNK && chunk_.wire == bit.wire) {
cover("kernel.rtlil.sigspec.append_bit.packed");
if (chunk_.wire == NULL) {
chunk_.data.push_back(bit.data);
chunk_.width++;
@ -5492,15 +5398,12 @@ void RTLIL::SigSpec::append(const RTLIL::SigBit &bit)
unpack();
cover("kernel.rtlil.sigspec.append_bit.unpacked");
bits_.push_back(bit);
check();
}
void RTLIL::SigSpec::extend_u0(int width, bool is_signed)
{
cover("kernel.rtlil.sigspec.extend_u0");
if (size() > width)
remove(width, size() - width);
@ -5515,8 +5418,6 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed)
RTLIL::SigSpec RTLIL::SigSpec::repeat(int num) const
{
cover("kernel.rtlil.sigspec.repeat");
RTLIL::SigSpec sig;
for (int i = 0; i < num; i++)
sig.append(*this);
@ -5528,8 +5429,6 @@ void RTLIL::SigSpec::check(Module *mod) const
{
if (rep_ == CHUNK)
{
cover("kernel.rtlil.sigspec.check.packed");
log_assert(chunk_.width != 0);
if (chunk_.wire == NULL) {
log_assert(chunk_.offset == 0);
@ -5543,14 +5442,8 @@ void RTLIL::SigSpec::check(Module *mod) const
log_assert(chunk_.wire->module == mod);
}
}
else if (size() > 64)
else if (size() <= 64)
{
cover("kernel.rtlil.sigspec.check.skip");
}
else
{
cover("kernel.rtlil.sigspec.check.unpacked");
if (mod != nullptr) {
for (const RTLIL::SigBit &bit : bits_)
if (bit.wire != nullptr)
@ -5562,8 +5455,6 @@ void RTLIL::SigSpec::check(Module *mod) const
bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec &other) const
{
cover("kernel.rtlil.sigspec.comp_lt");
if (this == &other)
return false;
@ -5577,14 +5468,11 @@ bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec &other) const
++other_it;
}
cover("kernel.rtlil.sigspec.comp_lt.equal");
return false;
}
bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const
{
cover("kernel.rtlil.sigspec.comp_eq");
if (this == &other)
return true;
@ -5598,14 +5486,11 @@ bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const
++other_it;
}
cover("kernel.rtlil.sigspec.comp_eq.equal");
return true;
}
bool RTLIL::SigSpec::is_wire() const
{
cover("kernel.rtlil.sigspec.is_wire");
Chunks cs = chunks();
auto it = cs.begin();
if (it == cs.end())
@ -5616,8 +5501,6 @@ bool RTLIL::SigSpec::is_wire() const
bool RTLIL::SigSpec::is_chunk() const
{
cover("kernel.rtlil.sigspec.is_chunk");
Chunks cs = chunks();
auto it = cs.begin();
if (it == cs.end())
@ -5635,8 +5518,6 @@ bool RTLIL::SigSpec::known_driver() const
bool RTLIL::SigSpec::is_fully_const() const
{
cover("kernel.rtlil.sigspec.is_fully_const");
for (auto &chunk : chunks())
if (chunk.width > 0 && chunk.wire != NULL)
return false;
@ -5645,8 +5526,6 @@ bool RTLIL::SigSpec::is_fully_const() const
bool RTLIL::SigSpec::is_fully_zero() const
{
cover("kernel.rtlil.sigspec.is_fully_zero");
for (auto &chunk : chunks()) {
if (chunk.width > 0 && chunk.wire != NULL)
return false;
@ -5659,8 +5538,6 @@ bool RTLIL::SigSpec::is_fully_zero() const
bool RTLIL::SigSpec::is_fully_ones() const
{
cover("kernel.rtlil.sigspec.is_fully_ones");
for (auto &chunk : chunks()) {
if (chunk.width > 0 && chunk.wire != NULL)
return false;
@ -5673,8 +5550,6 @@ bool RTLIL::SigSpec::is_fully_ones() const
bool RTLIL::SigSpec::is_fully_def() const
{
cover("kernel.rtlil.sigspec.is_fully_def");
for (auto &chunk : chunks()) {
if (chunk.width > 0 && chunk.wire != NULL)
return false;
@ -5687,8 +5562,6 @@ bool RTLIL::SigSpec::is_fully_def() const
bool RTLIL::SigSpec::is_fully_undef() const
{
cover("kernel.rtlil.sigspec.is_fully_undef");
for (auto &chunk : chunks()) {
if (chunk.width > 0 && chunk.wire != NULL)
return false;
@ -5701,8 +5574,6 @@ bool RTLIL::SigSpec::is_fully_undef() const
bool RTLIL::SigSpec::has_const() const
{
cover("kernel.rtlil.sigspec.has_const");
for (auto &chunk : chunks())
if (chunk.width > 0 && chunk.wire == NULL)
return true;
@ -5711,8 +5582,6 @@ bool RTLIL::SigSpec::has_const() const
bool RTLIL::SigSpec::has_const(State state) const
{
cover("kernel.rtlil.sigspec.has_const");
for (auto &chunk : chunks())
if (chunk.width > 0 && chunk.wire == NULL && std::find(chunk.data.begin(), chunk.data.end(), state) != chunk.data.end())
return true;
@ -5722,8 +5591,6 @@ bool RTLIL::SigSpec::has_const(State state) const
bool RTLIL::SigSpec::has_marked_bits() const
{
cover("kernel.rtlil.sigspec.has_marked_bits");
for (auto &chunk : chunks())
if (chunk.width > 0 && chunk.wire == NULL) {
for (RTLIL::State d : chunk.data)
@ -5735,8 +5602,6 @@ bool RTLIL::SigSpec::has_marked_bits() const
bool RTLIL::SigSpec::is_onehot(int *pos) const
{
cover("kernel.rtlil.sigspec.is_onehot");
if (std::optional<RTLIL::Const> c = try_as_const())
return c->is_onehot(pos);
return false;
@ -5744,8 +5609,6 @@ bool RTLIL::SigSpec::is_onehot(int *pos) const
bool RTLIL::SigSpec::as_bool() const
{
cover("kernel.rtlil.sigspec.as_bool");
std::optional<RTLIL::Const> c = try_as_const();
log_assert(c.has_value());
return c->as_bool();
@ -5753,8 +5616,6 @@ bool RTLIL::SigSpec::as_bool() const
int RTLIL::SigSpec::as_int(bool is_signed) const
{
cover("kernel.rtlil.sigspec.as_int");
std::optional<RTLIL::Const> c = try_as_const();
log_assert(c.has_value());
return c->as_int(is_signed);
@ -5762,8 +5623,6 @@ int RTLIL::SigSpec::as_int(bool is_signed) const
bool RTLIL::SigSpec::convertible_to_int(bool is_signed) const
{
cover("kernel.rtlil.sigspec.convertible_to_int");
std::optional<RTLIL::Const> c = try_as_const();
if (!c.has_value())
return false;
@ -5772,8 +5631,6 @@ bool RTLIL::SigSpec::convertible_to_int(bool is_signed) const
std::optional<int> RTLIL::SigSpec::try_as_int(bool is_signed) const
{
cover("kernel.rtlil.sigspec.try_as_int");
std::optional<RTLIL::Const> c = try_as_const();
if (!c.has_value())
return std::nullopt;
@ -5782,8 +5639,6 @@ std::optional<int> RTLIL::SigSpec::try_as_int(bool is_signed) const
int RTLIL::SigSpec::as_int_saturating(bool is_signed) const
{
cover("kernel.rtlil.sigspec.try_as_int");
std::optional<RTLIL::Const> c = try_as_const();
log_assert(c.has_value());
return c->as_int_saturating(is_signed);
@ -5791,8 +5646,6 @@ int RTLIL::SigSpec::as_int_saturating(bool is_signed) const
std::string RTLIL::SigSpec::as_string() const
{
cover("kernel.rtlil.sigspec.as_string");
std::string str;
str.reserve(size());
std::vector<RTLIL::SigChunk> chunks = *this;
@ -5808,8 +5661,6 @@ std::string RTLIL::SigSpec::as_string() const
std::optional<RTLIL::Const> RTLIL::SigSpec::try_as_const() const
{
cover("kernel.rtlil.sigspec.as_const");
Chunks cs = chunks();
auto it = cs.begin();
if (it == cs.end())
@ -5822,8 +5673,6 @@ std::optional<RTLIL::Const> RTLIL::SigSpec::try_as_const() const
RTLIL::Const RTLIL::SigSpec::as_const() const
{
cover("kernel.rtlil.sigspec.as_const");
std::optional<RTLIL::Const> c = try_as_const();
log_assert(c.has_value());
return *c;
@ -5831,8 +5680,6 @@ RTLIL::Const RTLIL::SigSpec::as_const() const
RTLIL::Wire *RTLIL::SigSpec::as_wire() const
{
cover("kernel.rtlil.sigspec.as_wire");
Chunks cs = chunks();
auto it = cs.begin();
log_assert(it != cs.end());
@ -5843,8 +5690,6 @@ RTLIL::Wire *RTLIL::SigSpec::as_wire() const
RTLIL::SigChunk RTLIL::SigSpec::as_chunk() const
{
cover("kernel.rtlil.sigspec.as_chunk");
Chunks cs = chunks();
auto it = cs.begin();
log_assert(it != cs.end());
@ -5855,14 +5700,11 @@ RTLIL::SigChunk RTLIL::SigSpec::as_chunk() const
RTLIL::SigBit RTLIL::SigSpec::as_bit() const
{
cover("kernel.rtlil.sigspec.as_bit");
return RTLIL::SigBit(*this);
}
bool RTLIL::SigSpec::match(const char* pattern) const
{
cover("kernel.rtlil.sigspec.match");
int pattern_len = strlen(pattern);
log_assert(pattern_len == size());
@ -5892,8 +5734,6 @@ bool RTLIL::SigSpec::match(const char* pattern) const
std::set<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_set() const
{
cover("kernel.rtlil.sigspec.to_sigbit_set");
std::set<RTLIL::SigBit> sigbits;
for (auto &c : chunks())
for (int i = 0; i < c.width; i++)
@ -5903,8 +5743,6 @@ std::set<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_set() const
pool<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_pool() const
{
cover("kernel.rtlil.sigspec.to_sigbit_pool");
pool<RTLIL::SigBit> sigbits;
sigbits.reserve(size());
for (auto &c : chunks())
@ -5915,8 +5753,6 @@ pool<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_pool() const
std::vector<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_vector() const
{
cover("kernel.rtlil.sigspec.to_sigbit_vector");
std::vector<RTLIL::SigBit> result;
result.reserve(size());
for (SigBit bit : *this)
@ -5926,8 +5762,6 @@ std::vector<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_vector() const
std::map<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_map(const RTLIL::SigSpec &other) const
{
cover("kernel.rtlil.sigspec.to_sigbit_map");
int this_size = size();
log_assert(this_size == other.size());
@ -5940,8 +5774,6 @@ std::map<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_map(const RTLIL
dict<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_dict(const RTLIL::SigSpec &other) const
{
cover("kernel.rtlil.sigspec.to_sigbit_dict");
int this_size = size();
log_assert(this_size == other.size());
@ -5965,9 +5797,6 @@ static void sigspec_parse_split(std::vector<std::string> &tokens, const std::str
bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str)
{
cover("kernel.rtlil.sigspec.parse");
std::vector<std::string> tokens;
sigspec_parse_split(tokens, str, ',');
@ -5981,7 +5810,6 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
continue;
if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') {
cover("kernel.rtlil.sigspec.parse.const");
VERILOG_FRONTEND::ConstParser p{Location()};
auto ast = p.const2ast(netname);
if (ast == nullptr)
@ -5993,8 +5821,6 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
if (module == NULL)
return false;
cover("kernel.rtlil.sigspec.parse.net");
if (netname[0] != '$' && netname[0] != '\\')
netname = "\\" + netname;
@ -6023,13 +5849,11 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
std::vector<std::string> index_tokens;
sigspec_parse_split(index_tokens, indices.substr(1, indices.size()-2), ':');
if (index_tokens.size() == 1) {
cover("kernel.rtlil.sigspec.parse.bit_sel");
int a = atoi(index_tokens.at(0).c_str());
if (a < 0 || a >= wire->width)
return false;
sig.append(RTLIL::SigSpec(wire, a));
} else {
cover("kernel.rtlil.sigspec.parse.part_sel");
int a = atoi(index_tokens.at(0).c_str());
int b = atoi(index_tokens.at(1).c_str());
if (a > b) {
@ -6054,8 +5878,6 @@ bool RTLIL::SigSpec::parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL
if (str.empty() || str[0] != '@')
return parse(sig, module, str);
cover("kernel.rtlil.sigspec.parse.sel");
str = RTLIL::escape_id(str.substr(1));
if (design->selection_vars.count(str) == 0)
return false;
@ -6072,13 +5894,11 @@ bool RTLIL::SigSpec::parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL
bool RTLIL::SigSpec::parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str)
{
if (str == "0") {
cover("kernel.rtlil.sigspec.parse.rhs_zeros");
sig = RTLIL::SigSpec(RTLIL::State::S0, lhs.size());
return true;
}
if (str == "~0") {
cover("kernel.rtlil.sigspec.parse.rhs_ones");
sig = RTLIL::SigSpec(RTLIL::State::S1, lhs.size());
return true;
}
@ -6088,7 +5908,6 @@ bool RTLIL::SigSpec::parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, R
long int val = strtol(p, &endptr, 10);
if (endptr && endptr != p && *endptr == 0) {
sig = RTLIL::SigSpec(val, lhs.size());
cover("kernel.rtlil.sigspec.parse.rhs_dec");
return true;
}
}

View file

@ -223,8 +223,8 @@ struct RTLIL::IdString
constexpr inline IdString() : index_(0) { }
inline IdString(const char *str) : index_(insert(std::string_view(str))) { }
constexpr inline IdString(const IdString &str) : index_(str.index_) { }
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
constexpr IdString(const IdString &str) = default;
IdString(IdString &&str) = default;
inline IdString(const std::string &str) : index_(insert(std::string_view(str))) { }
inline IdString(std::string_view str) : index_(insert(str)) { }
constexpr inline IdString(StaticId id) : index_(static_cast<short>(id)) {}
@ -241,8 +241,6 @@ struct RTLIL::IdString
*this = id;
}
constexpr inline const IdString &id_string() const { return *this; }
inline const char *c_str() const {
if (index_ >= 0)
return global_id_storage_.at(index_).buf;
@ -372,7 +370,7 @@ struct RTLIL::IdString
return Substrings(global_autoidx_id_storage_.at(index_).prefix, -index_);
}
inline bool lt_by_name(const IdString &rhs) const {
inline bool lt_by_name(IdString rhs) const {
Substrings lhs_it = substrings();
Substrings rhs_it = rhs.substrings();
std::string_view lhs_substr = lhs_it.first();
@ -399,12 +397,12 @@ struct RTLIL::IdString
}
}
inline bool operator<(const IdString &rhs) const {
inline bool operator<(IdString rhs) const {
return index_ < rhs.index_;
}
inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
inline bool operator==(IdString rhs) const { return index_ == rhs.index_; }
inline bool operator!=(IdString rhs) const { return index_ != rhs.index_; }
// The methods below are just convenience functions for better compatibility with std::string.
@ -528,7 +526,7 @@ struct RTLIL::IdString
return (... || in(args));
}
bool in(const IdString &rhs) const { return *this == rhs; }
bool in(IdString rhs) const { return *this == rhs; }
bool in(const char *rhs) const { return *this == rhs; }
bool in(const std::string &rhs) const { return *this == rhs; }
inline bool in(const pool<IdString> &rhs) const;
@ -646,13 +644,13 @@ private:
namespace hashlib {
template <>
struct hash_ops<RTLIL::IdString> {
static inline bool cmp(const RTLIL::IdString &a, const RTLIL::IdString &b) {
static inline bool cmp(RTLIL::IdString a, RTLIL::IdString b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash(const RTLIL::IdString &id) {
[[nodiscard]] static inline Hasher hash(RTLIL::IdString id) {
return id.hash_top();
}
[[nodiscard]] static inline Hasher hash_into(const RTLIL::IdString &id, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(RTLIL::IdString id, Hasher h) {
return id.hash_into(h);
}
};
@ -759,11 +757,11 @@ namespace RTLIL {
return str.substr(1);
}
static inline std::string unescape_id(const RTLIL::IdString &str) {
static inline std::string unescape_id(RTLIL::IdString str) {
return unescape_id(str.str());
}
static inline const char *id2cstr(const RTLIL::IdString &str) {
static inline const char *id2cstr(RTLIL::IdString str) {
return log_id(str);
}
@ -780,7 +778,7 @@ namespace RTLIL {
};
struct sort_by_id_str {
bool operator()(const RTLIL::IdString &a, const RTLIL::IdString &b) const {
bool operator()(RTLIL::IdString a, RTLIL::IdString b) const {
return a.lt_by_name(b);
}
};
@ -1246,22 +1244,22 @@ struct RTLIL::AttrObject
{
dict<RTLIL::IdString, RTLIL::Const> attributes;
bool has_attribute(const RTLIL::IdString &id) const;
bool has_attribute(RTLIL::IdString id) const;
void set_bool_attribute(const RTLIL::IdString &id, bool value=true);
bool get_bool_attribute(const RTLIL::IdString &id) const;
void set_bool_attribute(RTLIL::IdString id, bool value=true);
bool get_bool_attribute(RTLIL::IdString id) const;
[[deprecated("Use Module::get_blackbox_attribute() instead.")]]
bool get_blackbox_attribute(bool ignore_wb=false) const {
return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
}
void set_string_attribute(const RTLIL::IdString& id, string value);
string get_string_attribute(const RTLIL::IdString &id) const;
void set_string_attribute(RTLIL::IdString id, string value);
string get_string_attribute(RTLIL::IdString id) const;
void set_strpool_attribute(const RTLIL::IdString& id, const pool<string> &data);
void add_strpool_attribute(const RTLIL::IdString& id, const pool<string> &data);
pool<string> get_strpool_attribute(const RTLIL::IdString &id) const;
void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
pool<string> get_strpool_attribute(RTLIL::IdString id) const;
void set_src_attribute(const std::string &src) {
set_string_attribute(ID::src, src);
@ -1273,8 +1271,8 @@ struct RTLIL::AttrObject
void set_hdlname_attribute(const vector<string> &hierarchy);
vector<string> get_hdlname_attribute() const;
void set_intvec_attribute(const RTLIL::IdString& id, const vector<int> &data);
vector<int> get_intvec_attribute(const RTLIL::IdString &id) const;
void set_intvec_attribute(RTLIL::IdString id, const vector<int> &data);
vector<int> get_intvec_attribute(RTLIL::IdString id) const;
};
struct RTLIL::NamedObject : public RTLIL::AttrObject
@ -1781,18 +1779,18 @@ struct RTLIL::Selection
// checks if the given module exists in the current design and is a
// boxed module, warning the user if the current design is not set
bool boxed_module(const RTLIL::IdString &mod_name) const;
bool boxed_module(RTLIL::IdString mod_name) const;
// checks if the given module is included in this selection
bool selected_module(const RTLIL::IdString &mod_name) const;
bool selected_module(RTLIL::IdString mod_name) const;
// checks if the given module is wholly included in this selection,
// i.e. not partially selected
bool selected_whole_module(const RTLIL::IdString &mod_name) const;
bool selected_whole_module(RTLIL::IdString mod_name) const;
// checks if the given member from the given module is included in this
// selection
bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const;
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const;
// optimizes this selection for the given design by:
// - removing non-existent modules and members, any boxed modules and
@ -1862,7 +1860,7 @@ struct RTLIL::Monitor
virtual ~Monitor() { }
virtual void notify_module_add(RTLIL::Module*) { }
virtual void notify_module_del(RTLIL::Module*) { }
virtual void notify_connect(RTLIL::Cell*, const RTLIL::IdString&, const RTLIL::SigSpec&, const RTLIL::SigSpec&) { }
virtual void notify_connect(RTLIL::Cell*, RTLIL::IdString, const RTLIL::SigSpec&, const RTLIL::SigSpec&) { }
virtual void notify_connect(RTLIL::Module*, const RTLIL::SigSig&) { }
virtual void notify_connect(RTLIL::Module*, const std::vector<RTLIL::SigSig>&) { }
virtual void notify_blackout(RTLIL::Module*) { }
@ -1897,11 +1895,11 @@ struct RTLIL::Design
~Design();
RTLIL::ObjRange<RTLIL::Module*> modules();
RTLIL::Module *module(const RTLIL::IdString &name);
const RTLIL::Module *module(const RTLIL::IdString &name) const;
RTLIL::Module *module(RTLIL::IdString name);
const RTLIL::Module *module(RTLIL::IdString name) const;
RTLIL::Module *top_module() const;
bool has(const RTLIL::IdString &id) const {
bool has(RTLIL::IdString id) const {
return modules_.count(id) != 0;
}
@ -1928,15 +1926,15 @@ struct RTLIL::Design
void optimize();
// checks if the given module is included in the current selection
bool selected_module(const RTLIL::IdString &mod_name) const;
bool selected_module(RTLIL::IdString mod_name) const;
// checks if the given module is wholly included in the current
// selection, i.e. not partially selected
bool selected_whole_module(const RTLIL::IdString &mod_name) const;
bool selected_whole_module(RTLIL::IdString mod_name) const;
// checks if the given member from the given module is included in the
// current selection
bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const;
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const;
// checks if the given module is included in the current selection
bool selected_module(RTLIL::Module *mod) const;
@ -2068,7 +2066,7 @@ public:
virtual ~Module();
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail = false);
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
virtual size_t count_id(const RTLIL::IdString& id);
virtual size_t count_id(RTLIL::IdString id);
virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
virtual bool reprocess_if_necessary(RTLIL::Design *design);
@ -2120,32 +2118,37 @@ public:
return design->selected_member(name, member->name);
}
RTLIL::Wire* wire(const RTLIL::IdString &id) {
RTLIL::Wire* wire(RTLIL::IdString id) {
auto it = wires_.find(id);
return it == wires_.end() ? nullptr : it->second;
}
RTLIL::Cell* cell(const RTLIL::IdString &id) {
RTLIL::Cell* cell(RTLIL::IdString id) {
auto it = cells_.find(id);
return it == cells_.end() ? nullptr : it->second;
}
const RTLIL::Wire* wire(const RTLIL::IdString &id) const{
const RTLIL::Wire* wire(RTLIL::IdString id) const{
auto it = wires_.find(id);
return it == wires_.end() ? nullptr : it->second;
}
const RTLIL::Cell* cell(const RTLIL::IdString &id) const {
const RTLIL::Cell* cell(RTLIL::IdString id) const {
auto it = cells_.find(id);
return it == cells_.end() ? nullptr : it->second;
}
RTLIL::ObjRange<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
int wires_size() const { return wires_.size(); }
RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; }
RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }
int cells_size() const { return cells_.size(); }
RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; }
void add(RTLIL::Binding *binding);
// Removing wires is expensive. If you have to remove wires, remove them all at once.
void remove(const pool<RTLIL::Wire*> &wires);
void remove(RTLIL::Cell *cell);
void remove(RTLIL::Memory *memory);
void remove(RTLIL::Process *process);
void rename(RTLIL::Wire *wire, RTLIL::IdString new_name);
@ -2490,23 +2493,23 @@ public:
dict<RTLIL::IdString, RTLIL::Const> parameters;
// access cell ports
bool hasPort(const RTLIL::IdString &portname) const;
void unsetPort(const RTLIL::IdString &portname);
void setPort(const RTLIL::IdString &portname, RTLIL::SigSpec signal);
const RTLIL::SigSpec &getPort(const RTLIL::IdString &portname) const;
bool hasPort(RTLIL::IdString portname) const;
void unsetPort(RTLIL::IdString portname);
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal);
const RTLIL::SigSpec &getPort(RTLIL::IdString portname) const;
const dict<RTLIL::IdString, RTLIL::SigSpec> &connections() const;
// information about cell ports
bool known() const;
bool input(const RTLIL::IdString &portname) const;
bool output(const RTLIL::IdString &portname) const;
PortDir port_dir(const RTLIL::IdString &portname) const;
bool input(RTLIL::IdString portname) const;
bool output(RTLIL::IdString portname) const;
PortDir port_dir(RTLIL::IdString portname) const;
// access cell parameters
bool hasParam(const RTLIL::IdString &paramname) const;
void unsetParam(const RTLIL::IdString &paramname);
void setParam(const RTLIL::IdString &paramname, RTLIL::Const value);
const RTLIL::Const &getParam(const RTLIL::IdString &paramname) const;
bool hasParam(RTLIL::IdString paramname) const;
void unsetParam(RTLIL::IdString paramname);
void setParam(RTLIL::IdString paramname, RTLIL::Const value);
const RTLIL::Const &getParam(RTLIL::IdString paramname) const;
void sort();
void check();

View file

@ -526,7 +526,7 @@ void RTLIL::Module::bufNormalize()
pending_deleted_cells.clear();
}
void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
void RTLIL::Cell::unsetPort(RTLIL::IdString portname)
{
RTLIL::SigSpec signal;
auto conn_it = connections_.find(portname);
@ -586,7 +586,7 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
}
}
void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
{
auto r = connections_.insert(portname);
auto conn_it = r.first;

View file

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

View file

@ -433,10 +433,10 @@ enum class ScopeinfoAttrs {
};
// Check whether the flattened module or flattened cell corresponding to a $scopeinfo cell had a specific attribute.
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, const RTLIL::IdString &id);
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id);
// Get a specific attribute from the flattened module or flattened cell corresponding to a $scopeinfo cell.
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, const RTLIL::IdString &id);
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id);
// Get all attribute from the flattened module or flattened cell corresponding to a $scopeinfo cell.
dict<RTLIL::IdString, RTLIL::Const> scopeinfo_attributes(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs);

View file

@ -3,6 +3,20 @@
YOSYS_NAMESPACE_BEGIN
static int init_max_threads()
{
const char *v = getenv("YOSYS_MAX_THREADS");
if (v == nullptr)
return INT32_MAX;
return atoi(v);
}
static int get_max_threads()
{
static int max_threads = init_max_threads();
return max_threads;
}
void DeferredLogs::flush()
{
for (auto &m : logs)
@ -12,10 +26,11 @@ void DeferredLogs::flush()
YOSYS_NAMESPACE_PREFIX log("%s", m.text.c_str());
}
int ThreadPool::pool_size(int reserved_cores, int max_threads)
int ThreadPool::pool_size(int reserved_cores, int max_worker_threads)
{
#ifdef YOSYS_ENABLE_THREADS
int num_threads = std::min<int>(std::thread::hardware_concurrency() - reserved_cores, max_threads);
int available_threads = std::min<int>(std::thread::hardware_concurrency(), get_max_threads());
int num_threads = std::min(available_threads - reserved_cores, max_worker_threads);
return std::max(0, num_threads);
#else
return 0;

View file

@ -127,9 +127,9 @@ class ThreadPool
public:
// Computes the number of worker threads to use.
// `reserved_cores` cores are set aside for other threads (e.g. work on the main thread).
// `max_threads` --- don't return more workers than this.
// `max_worker_threads` --- don't return more workers than this.
// The result may be 0.
static int pool_size(int reserved_cores, int max_threads);
static int pool_size(int reserved_cores, int max_worker_threads);
// Create a pool of threads running the given closure (parameterized by thread number).
// `pool_size` must be the result of a `pool_size()` call.

View file

@ -173,7 +173,7 @@ void yosys_banner()
log("\n");
log(" /----------------------------------------------------------------------------\\\n");
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
log(" | Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com> |\n");
log(" | Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com> |\n");
log(" | Distributed under an ISC-like license, type \"license\" to see terms |\n");
log(" \\----------------------------------------------------------------------------/\n");
log(" %s\n", yosys_maybe_version());

View file

@ -81,6 +81,7 @@ extern std::set<std::string> yosys_input_files, yosys_output_files;
// from kernel/version_*.o (cc source generated from Makefile)
extern const char *yosys_version_str;
extern const char *yosys_git_hash_str;
const char* yosys_maybe_version();
// from passes/cmds/design.cc

View file

@ -299,8 +299,8 @@ RTLIL::IdString new_id_suffix(std::string_view file, int line, std::string_view
#define NEW_ID \
YOSYS_NAMESPACE_PREFIX RTLIL::IdString::new_autoidx_with_prefix([](std::string_view func) -> const std::string * { \
static const std::string *prefix = YOSYS_NAMESPACE_PREFIX create_id_prefix(__FILE__, __LINE__, func); \
return prefix; \
static std::unique_ptr<const std::string> prefix(YOSYS_NAMESPACE_PREFIX create_id_prefix(__FILE__, __LINE__, func)); \
return prefix.get(); \
}(__FUNCTION__))
#define NEW_ID_SUFFIX(suffix) \
YOSYS_NAMESPACE_PREFIX new_id_suffix(__FILE__, __LINE__, __FUNCTION__, suffix)

View file

@ -1,9 +1,8 @@
#!/bin/bash
set -ex
vcxsrc="$1-$2"
vcxsrc="$1"
yosysver="$2"
gitsha="$3"
rm -rf YosysVS-Tpl-v2.zip YosysVS
wget https://github.com/YosysHQ/yosys/releases/download/resources/YosysVS-Tpl-v2.zip
@ -33,7 +32,6 @@ popd
head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj
egrep '\.(h|hh|hpp|inc)$' srcfiles.txt | sed 's,.*,<ClInclude Include="../yosys/&" />,'
egrep -v '\.(h|hh|hpp|inc)$' srcfiles.txt | sed 's,.*,<ClCompile Include="../yosys/&" />,'
echo '<ClCompile Include="../yosys/kernel/version.cc" />'
tail -n +$((n+1)) "$vcxsrc"/YosysVS/YosysVS.vcxproj
} > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
@ -48,9 +46,6 @@ mkdir -p "$vcxsrc"/yosys
tar -cf - -T srcfiles.txt | tar -xf - -C "$vcxsrc"/yosys
cp -r share "$vcxsrc"/
echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys" \
"$yosysver (git sha1 $gitsha, Visual Studio)\"; }" > "$vcxsrc"/yosys/kernel/version.cc
cat > "$vcxsrc"/readme-git.txt << EOT
Want to use a git working copy for the yosys source code?
Open "Git Bash" in this directory and run:

View file

@ -5,6 +5,7 @@ endif
OBJS += passes/cmds/add.o
OBJS += passes/cmds/delete.o
OBJS += passes/cmds/design.o
OBJS += passes/cmds/design_equal.o
OBJS += passes/cmds/select.o
OBJS += passes/cmds/show.o
OBJS += passes/cmds/viz.o
@ -27,7 +28,6 @@ OBJS += passes/cmds/logcmd.o
OBJS += passes/cmds/tee.o
OBJS += passes/cmds/write_file.o
OBJS += passes/cmds/connwrappers.o
OBJS += passes/cmds/cover.o
OBJS += passes/cmds/trace.o
OBJS += passes/cmds/plugin.o
OBJS += passes/cmds/check.o

View file

@ -1,163 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/log_help.h"
#include <sys/types.h>
#ifndef _WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct CoverPass : public Pass {
CoverPass() : Pass("cover", "print code coverage counters") {
internal();
}
bool formatted_help() override {
auto *help = PrettyHelp::get_current();
help->set_group("passes/status");
return false;
}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" cover [options] [pattern]\n");
log("\n");
log("Print the code coverage counters collected using the cover() macro in the Yosys\n");
log("C++ code. This is useful to figure out what parts of Yosys are utilized by a\n");
log("test bench.\n");
log("\n");
log(" -q\n");
log(" Do not print output to the normal destination (console and/or log file)\n");
log("\n");
log(" -o file\n");
log(" Write output to this file, truncate if exists.\n");
log("\n");
log(" -a file\n");
log(" Write output to this file, append if exists.\n");
log("\n");
log(" -d dir\n");
log(" Write output to a newly created file in the specified directory.\n");
log("\n");
log("When one or more pattern (shell wildcards) are specified, then only counters\n");
log("matching at least one pattern are printed.\n");
log("\n");
log("\n");
log("It is also possible to instruct Yosys to print the coverage counters on program\n");
log("exit to a file using environment variables:\n");
log("\n");
log(" YOSYS_COVER_DIR=\"{dir-name}\" yosys {args}\n");
log("\n");
log(" This will create a file (with an auto-generated name) in this\n");
log(" directory and write the coverage counters to it.\n");
log("\n");
log(" YOSYS_COVER_FILE=\"{file-name}\" yosys {args}\n");
log("\n");
log(" This will append the coverage counters to the specified file.\n");
log("\n");
log("\n");
log("Hint: Use the following AWK command to consolidate Yosys coverage files:\n");
log("\n");
log(" gawk '{ p[$3] = $1; c[$3] += $2; } END { for (i in p)\n");
log(" printf \"%%-60s %%10d %%s\\n\", p[i], c[i], i; }' {files} | sort -k3\n");
log("\n");
log("\n");
log("Coverage counters are only available in Yosys for Linux.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
std::vector<FILE*> out_files;
std::vector<std::string> patterns;
bool do_log = true;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-q") {
do_log = false;
continue;
}
if ((args[argidx] == "-o" || args[argidx] == "-a" || args[argidx] == "-d") && argidx+1 < args.size()) {
const char *open_mode = args[argidx] == "-a" ? "a+" : "w";
const std::string &filename = args[++argidx];
FILE *f = nullptr;
if (args[argidx-1] == "-d") {
#if defined(_WIN32) || defined(__wasm)
log_cmd_error("The 'cover -d' option is not supported on this platform.\n");
#else
char filename_buffer[4096];
snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid());
f = fdopen(mkstemps(filename_buffer, 4), "w");
#endif
} else {
f = fopen(filename.c_str(), open_mode);
}
if (f == NULL) {
for (auto f : out_files)
fclose(f);
log_cmd_error("Can't create file %s%s.\n", args[argidx-1] == "-d" ? "in directory " : "", args[argidx]);
}
out_files.push_back(f);
continue;
}
break;
}
while (argidx < args.size() && args[argidx].compare(0, 1, "-") != 0)
patterns.push_back(args[argidx++]);
extra_args(args, argidx, design);
if (do_log) {
log_header(design, "Printing code coverage counters.\n");
log("\n");
}
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
for (auto &it : get_coverage_data()) {
if (!patterns.empty()) {
for (auto &p : patterns)
if (patmatch(p.c_str(), it.first.c_str()))
goto pattern_match;
continue;
}
pattern_match:
for (auto f : out_files)
fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());
if (do_log)
log("%-60s %10d %s\n", it.second.first, it.second.second, it.first);
}
#else
for (auto f : out_files)
fclose(f);
log_cmd_error("This version of Yosys was not built with support for code coverage counters.\n");
#endif
for (auto f : out_files)
fclose(f);
}
} CoverPass;
PRIVATE_NAMESPACE_END

352
passes/cmds/design_equal.cc Normal file
View file

@ -0,0 +1,352 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/rtlil.h"
YOSYS_NAMESPACE_BEGIN
class ModuleComparator
{
RTLIL::Module *mod_a;
RTLIL::Module *mod_b;
public:
ModuleComparator(RTLIL::Module *mod_a, RTLIL::Module *mod_b) : mod_a(mod_a), mod_b(mod_b) {}
bool compare_sigbit(const RTLIL::SigBit &a, const RTLIL::SigBit &b)
{
if (a.wire == nullptr && b.wire == nullptr)
return a.data == b.data;
if (a.wire != nullptr && b.wire != nullptr)
return a.wire->name == b.wire->name && a.offset == b.offset;
return false;
}
bool compare_sigspec(const RTLIL::SigSpec &a, const RTLIL::SigSpec &b)
{
if (a.size() != b.size()) return false;
auto it_a = a.begin(), it_b = b.begin();
for (; it_a != a.end(); ++it_a, ++it_b) {
if (!compare_sigbit(*it_a, *it_b)) return false;
}
return true;
}
std::string compare_attributes(const RTLIL::AttrObject *a, const RTLIL::AttrObject *b)
{
for (const auto &it : a->attributes) {
if (b->attributes.count(it.first) == 0)
return "missing attribute " + std::string(log_id(it.first)) + " in second design";
if (it.second != b->attributes.at(it.first))
return "attribute " + std::string(log_id(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(it.first));
}
for (const auto &it : b->attributes)
if (a->attributes.count(it.first) == 0)
return "missing attribute " + std::string(log_id(it.first)) + " in first design";
return "";
}
std::string compare_wires(const RTLIL::Wire *a, const RTLIL::Wire *b)
{
if (a->name != b->name)
return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name);
if (a->width != b->width)
return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width);
if (a->start_offset != b->start_offset)
return "start_offset mismatch: " + std::to_string(a->start_offset) + " != " + std::to_string(b->start_offset);
if (a->port_id != b->port_id)
return "port_id mismatch: " + std::to_string(a->port_id) + " != " + std::to_string(b->port_id);
if (a->port_input != b->port_input)
return "port_input mismatch: " + std::to_string(a->port_input) + " != " + std::to_string(b->port_input);
if (a->port_output != b->port_output)
return "port_output mismatch: " + std::to_string(a->port_output) + " != " + std::to_string(b->port_output);
if (a->upto != b->upto)
return "upto mismatch: " + std::to_string(a->upto) + " != " + std::to_string(b->upto);
if (a->is_signed != b->is_signed)
return "is_signed mismatch: " + std::to_string(a->is_signed) + " != " + std::to_string(b->is_signed);
if (std::string mismatch = compare_attributes(a, b); !mismatch.empty())
return mismatch;
return "";
}
void check_wires()
{
for (const auto &it : mod_a->wires_) {
if (mod_b->wires_.count(it.first) == 0)
log_error("Module %s missing wire %s in second design.\n", log_id(mod_a->name), log_id(it.first));
if (std::string mismatch = compare_wires(it.second, mod_b->wires_.at(it.first)); !mismatch.empty())
log_error("Module %s wire %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch);
}
for (const auto &it : mod_b->wires_)
if (mod_a->wires_.count(it.first) == 0)
log_error("Module %s missing wire %s in first design.\n", log_id(mod_b->name), log_id(it.first));
}
std::string compare_memories(const RTLIL::Memory *a, const RTLIL::Memory *b)
{
if (a->name != b->name)
return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name);
if (a->width != b->width)
return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width);
if (a->start_offset != b->start_offset)
return "start_offset mismatch: " + std::to_string(a->start_offset) + " != " + std::to_string(b->start_offset);
if (a->size != b->size)
return "size mismatch: " + std::to_string(a->size) + " != " + std::to_string(b->size);
if (std::string mismatch = compare_attributes(a, b); !mismatch.empty())
return mismatch;
return "";
}
std::string compare_cells(const RTLIL::Cell *a, const RTLIL::Cell *b)
{
if (a->name != b->name)
return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name);
if (a->type != b->type)
return "type mismatch: " + std::string(log_id(a->type)) + " != " + log_id(b->type);
if (std::string mismatch = compare_attributes(a, b); !mismatch.empty())
return mismatch;
for (const auto &it : a->parameters) {
if (b->parameters.count(it.first) == 0)
return "parameter mismatch: missing parameter " + std::string(log_id(it.first)) + " in second design";
if (it.second != b->parameters.at(it.first))
return "parameter mismatch: " + std::string(log_id(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(it.first));
}
for (const auto &it : b->parameters)
if (a->parameters.count(it.first) == 0)
return "parameter mismatch: missing parameter " + std::string(log_id(it.first)) + " in first design";
for (const auto &it : a->connections()) {
if (b->connections().count(it.first) == 0)
return "connection mismatch: missing connection " + std::string(log_id(it.first)) + " in second design";
if (!compare_sigspec(it.second, b->connections().at(it.first)))
return "connection " + std::string(log_id(it.first)) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(it.first));
}
for (const auto &it : b->connections())
if (a->connections().count(it.first) == 0)
return "connection mismatch: missing connection " + std::string(log_id(it.first)) + " in first design";
return "";
}
void check_cells()
{
for (const auto &it : mod_a->cells_) {
if (mod_b->cells_.count(it.first) == 0)
log_error("Module %s missing cell %s in second design.\n", log_id(mod_a->name), log_id(it.first));
if (std::string mismatch = compare_cells(it.second, mod_b->cells_.at(it.first)); !mismatch.empty())
log_error("Module %s cell %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch);
}
for (const auto &it : mod_b->cells_)
if (mod_a->cells_.count(it.first) == 0)
log_error("Module %s missing cell %s in first design.\n", log_id(mod_b->name), log_id(it.first));
}
void check_memories()
{
for (const auto &it : mod_a->memories) {
if (mod_b->memories.count(it.first) == 0)
log_error("Module %s missing memory %s in second design.\n", log_id(mod_a->name), log_id(it.first));
if (std::string mismatch = compare_memories(it.second, mod_b->memories.at(it.first)); !mismatch.empty())
log_error("Module %s memory %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch);
}
for (const auto &it : mod_b->memories)
if (mod_a->memories.count(it.first) == 0)
log_error("Module %s missing memory %s in first design.\n", log_id(mod_b->name), log_id(it.first));
}
std::string compare_case_rules(const RTLIL::CaseRule *a, const RTLIL::CaseRule *b)
{
if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch;
if (a->compare.size() != b->compare.size())
return "compare size mismatch: " + std::to_string(a->compare.size()) + " != " + std::to_string(b->compare.size());
for (size_t i = 0; i < a->compare.size(); i++)
if (!compare_sigspec(a->compare[i], b->compare[i]))
return "compare " + std::to_string(i) + " mismatch: " + log_signal(a->compare[i]) + " != " + log_signal(b->compare[i]);
if (a->actions.size() != b->actions.size())
return "actions size mismatch: " + std::to_string(a->actions.size()) + " != " + std::to_string(b->actions.size());
for (size_t i = 0; i < a->actions.size(); i++) {
if (!compare_sigspec(a->actions[i].first, b->actions[i].first))
return "action " + std::to_string(i) + " first mismatch: " + log_signal(a->actions[i].first) + " != " + log_signal(b->actions[i].first);
if (!compare_sigspec(a->actions[i].second, b->actions[i].second))
return "action " + std::to_string(i) + " second mismatch: " + log_signal(a->actions[i].second) + " != " + log_signal(b->actions[i].second);
}
if (a->switches.size() != b->switches.size())
return "switches size mismatch: " + std::to_string(a->switches.size()) + " != " + std::to_string(b->switches.size());
for (size_t i = 0; i < a->switches.size(); i++)
if (std::string mismatch = compare_switch_rules(a->switches[i], b->switches[i]); !mismatch.empty())
return "switch " + std::to_string(i) + " " + mismatch;
return "";
}
std::string compare_switch_rules(const RTLIL::SwitchRule *a, const RTLIL::SwitchRule *b)
{
if (std::string mismatch = compare_attributes(a, b); !mismatch.empty())
return mismatch;
if (!compare_sigspec(a->signal, b->signal))
return "signal mismatch: " + log_signal(a->signal) + " != " + log_signal(b->signal);
if (a->cases.size() != b->cases.size())
return "cases size mismatch: " + std::to_string(a->cases.size()) + " != " + std::to_string(b->cases.size());
for (size_t i = 0; i < a->cases.size(); i++)
if (std::string mismatch = compare_case_rules(a->cases[i], b->cases[i]); !mismatch.empty())
return "case " + std::to_string(i) + " " + mismatch;
return "";
}
std::string compare_sync_rules(const RTLIL::SyncRule *a, const RTLIL::SyncRule *b)
{
if (a->type != b->type)
return "type mismatch: " + std::to_string(a->type) + " != " + std::to_string(b->type);
if (!compare_sigspec(a->signal, b->signal))
return "signal mismatch: " + log_signal(a->signal) + " != " + log_signal(b->signal);
if (a->actions.size() != b->actions.size())
return "actions size mismatch: " + std::to_string(a->actions.size()) + " != " + std::to_string(b->actions.size());
for (size_t i = 0; i < a->actions.size(); i++) {
if (!compare_sigspec(a->actions[i].first, b->actions[i].first))
return "action " + std::to_string(i) + " first mismatch: " + log_signal(a->actions[i].first) + " != " + log_signal(b->actions[i].first);
if (!compare_sigspec(a->actions[i].second, b->actions[i].second))
return "action " + std::to_string(i) + " second mismatch: " + log_signal(a->actions[i].second) + " != " + log_signal(b->actions[i].second);
}
if (a->mem_write_actions.size() != b->mem_write_actions.size())
return "mem_write_actions size mismatch: " + std::to_string(a->mem_write_actions.size()) + " != " + std::to_string(b->mem_write_actions.size());
for (size_t i = 0; i < a->mem_write_actions.size(); i++) {
const auto &ma = a->mem_write_actions[i];
const auto &mb = b->mem_write_actions[i];
if (ma.memid != mb.memid)
return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + log_id(ma.memid) + " != " + log_id(mb.memid);
if (!compare_sigspec(ma.address, mb.address))
return "mem_write_actions " + std::to_string(i) + " address mismatch: " + log_signal(ma.address) + " != " + log_signal(mb.address);
if (!compare_sigspec(ma.data, mb.data))
return "mem_write_actions " + std::to_string(i) + " data mismatch: " + log_signal(ma.data) + " != " + log_signal(mb.data);
if (!compare_sigspec(ma.enable, mb.enable))
return "mem_write_actions " + std::to_string(i) + " enable mismatch: " + log_signal(ma.enable) + " != " + log_signal(mb.enable);
if (ma.priority_mask != mb.priority_mask)
return "mem_write_actions " + std::to_string(i) + " priority_mask mismatch: " + log_const(ma.priority_mask) + " != " + log_const(mb.priority_mask);
if (std::string mismatch = compare_attributes(&ma, &mb); !mismatch.empty())
return "mem_write_actions " + std::to_string(i) + " " + mismatch;
}
return "";
}
std::string compare_processes(const RTLIL::Process *a, const RTLIL::Process *b)
{
if (a->name != b->name) return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name);
if (std::string mismatch = compare_attributes(a, b); !mismatch.empty())
return mismatch;
if (std::string mismatch = compare_case_rules(&a->root_case, &b->root_case); !mismatch.empty())
return "case rule " + mismatch;
if (a->syncs.size() != b->syncs.size())
return "sync count mismatch: " + std::to_string(a->syncs.size()) + " != " + std::to_string(b->syncs.size());
for (size_t i = 0; i < a->syncs.size(); i++)
if (std::string mismatch = compare_sync_rules(a->syncs[i], b->syncs[i]); !mismatch.empty())
return "sync " + std::to_string(i) + " " + mismatch;
return "";
}
void check_processes()
{
for (auto &it : mod_a->processes) {
if (mod_b->processes.count(it.first) == 0)
log_error("Module %s missing process %s in second design.\n", log_id(mod_a->name), log_id(it.first));
if (std::string mismatch = compare_processes(it.second, mod_b->processes.at(it.first)); !mismatch.empty())
log_error("Module %s process %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch.c_str());
}
for (auto &it : mod_b->processes)
if (mod_a->processes.count(it.first) == 0)
log_error("Module %s missing process %s in first design.\n", log_id(mod_b->name), log_id(it.first));
}
void check_connections()
{
const auto &conns_a = mod_a->connections();
const auto &conns_b = mod_b->connections();
if (conns_a.size() != conns_b.size()) {
log_error("Module %s connection count differs: %zu != %zu\n", log_id(mod_a->name), conns_a.size(), conns_b.size());
} else {
for (size_t i = 0; i < conns_a.size(); i++) {
if (!compare_sigspec(conns_a[i].first, conns_b[i].first))
log_error("Module %s connection %zu LHS %s != %s.\n", log_id(mod_a->name), i, log_signal(conns_a[i].first), log_signal(conns_b[i].first));
if (!compare_sigspec(conns_a[i].second, conns_b[i].second))
log_error("Module %s connection %zu RHS %s != %s.\n", log_id(mod_a->name), i, log_signal(conns_a[i].second), log_signal(conns_b[i].second));
}
}
}
void check()
{
if (mod_a->name != mod_b->name)
log_error("Modules have different names: %s != %s\n", log_id(mod_a->name), log_id(mod_b->name));
if (std::string mismatch = compare_attributes(mod_a, mod_b); !mismatch.empty())
log_error("Module %s %s.\n", log_id(mod_a->name), mismatch);
check_wires();
check_cells();
check_memories();
check_connections();
check_processes();
}
};
struct DesignEqualPass : public Pass {
DesignEqualPass() : Pass("design_equal", "check if two designs are the same") { }
void help() override
{
log("\n");
log(" design_equal <name>\n");
log("\n");
log("Compare the current design with the design previously saved under the given\n");
log("name. Abort with an error if the designs are different.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
if (args.size() != 2)
log_cmd_error("Missing argument.\n");
std::string check_name = args[1];
if (saved_designs.count(check_name) == 0)
log_cmd_error("No saved design '%s' found!\n", check_name.c_str());
RTLIL::Design *other = saved_designs.at(check_name);
for (auto &it : design->modules_) {
RTLIL::Module *mod = it.second;
if (!other->has(mod->name))
log_error("Second design missing module %s.\n", log_id(mod->name));
ModuleComparator cmp(mod, other->module(mod->name));
cmp.check();
}
for (auto &it : other->modules_) {
RTLIL::Module *mod = it.second;
if (!design->has(mod->name))
log_error("First design missing module %s.\n", log_id(mod->name));
}
log("Designs are identical.\n");
}
} DesignEqualPass;
YOSYS_NAMESPACE_END

View file

@ -77,7 +77,7 @@ struct ExampleDtPass : public Pass
auto enqueue = [&](DriveSpec const &spec) {
int index = queue(spec);
if (index == GetSize(graph_nodes))
graph_nodes.emplace_back(compute_graph.add(ID($pending).id_string(), index).index());
graph_nodes.emplace_back(compute_graph.add(ID($pending), index).index());
//if (index >= GetSize(graph_nodes))
return compute_graph[graph_nodes[index]];
};

View file

@ -163,7 +163,6 @@ struct IcellLiberty : Pass {
log_header(d, "Executing ICELL_LIBERTY pass.\n");
size_t argidx;
IdString naming_attr;
std::string liberty_filename;
auto liberty_file = std::make_unique<std::ofstream>();

View file

@ -45,7 +45,7 @@ struct PrintAttrsPass : public Pass {
return stringf("%*s", indent, "");
}
static void log_const(const RTLIL::IdString &s, const RTLIL::Const &x, const unsigned int indent) {
static void log_const(RTLIL::IdString s, const RTLIL::Const &x, const unsigned int indent) {
if (x.flags & RTLIL::CONST_FLAG_STRING)
log("%s(* %s=\"%s\" *)\n", get_indent_str(indent), log_id(s), x.decode_string());
else if (x.flags == RTLIL::CONST_FLAG_NONE || x.flags == RTLIL::CONST_FLAG_SIGNED)

View file

@ -165,7 +165,12 @@ struct SdcObjects {
if (!top)
log_error("Top module couldn't be determined. Check 'top' attribute usage");
for (auto port : top->ports) {
design_ports.push_back(std::make_pair(port.str().substr(1), top->wire(port)));
RTLIL::Wire *wire = top->wire(port);
if (!wire) {
// This should not be possible. See https://github.com/YosysHQ/yosys/pull/5594#issue-3791198573
log_error("Port %s doesn't exist", log_id(port));
}
design_ports.push_back(std::make_pair(port.str().substr(1), wire));
}
std::list<std::string> hierarchy{};
sniff_module(hierarchy, top);

View file

@ -570,7 +570,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char
ct.setup(design);
if (pos < int(arg.size()) && arg[pos] == '*') {
levels = 1000000;
levels = 1'000'000;
pos++;
} else
if (pos < int(arg.size()) && '0' <= arg[pos] && arg[pos] <= '9') {

View file

@ -36,7 +36,7 @@ struct TraceMonitor : public RTLIL::Monitor
log("#TRACE# Module delete: %s\n", log_id(module));
}
void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
void notify_connect(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
{
log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig));
}

View file

@ -297,8 +297,6 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
log_debug("\n");
}
cover_list("opt.opt_expr.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str());
module->remove(cell);
did_something = true;
return true;
@ -520,7 +518,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
for (auto cell : cells.sorted)
{
#define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
#define ACTION_DO(_p_, _s_) do { replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
#define ACTION_DO_Y(_v_) ACTION_DO(ID::Y, RTLIL::SigSpec(RTLIL::State::S ## _v_))
bool detect_const_and = false;
@ -567,19 +565,16 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (detect_const_and && (found_zero || found_inv || (found_undef && consume_x))) {
cover("opt.opt_expr.const_and");
replace_cell(assign_map, module, cell, "const_and", ID::Y, RTLIL::State::S0);
goto next_cell;
}
if (detect_const_or && (found_one || found_inv || (found_undef && consume_x))) {
cover("opt.opt_expr.const_or");
replace_cell(assign_map, module, cell, "const_or", ID::Y, RTLIL::State::S1);
goto next_cell;
}
if (non_const_input != State::Sm && !found_undef) {
cover("opt.opt_expr.and_or_buffer");
replace_cell(assign_map, module, cell, "and_or_buffer", ID::Y, non_const_input);
goto next_cell;
}
@ -591,12 +586,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
SigBit sig_b = assign_map(cell->getPort(ID::B));
if (!keepdc && (sig_a == sig_b || sig_a == State::Sx || sig_a == State::Sz || sig_b == State::Sx || sig_b == State::Sz)) {
if (cell->type.in(ID($xor), ID($_XOR_))) {
cover("opt.opt_expr.const_xor");
replace_cell(assign_map, module, cell, "const_xor", ID::Y, RTLIL::State::S0);
goto next_cell;
}
if (cell->type.in(ID($xnor), ID($_XNOR_))) {
cover("opt.opt_expr.const_xnor");
// For consistency since simplemap does $xnor -> $_XOR_ + $_NOT_
int width = GetSize(cell->getPort(ID::Y));
replace_cell(assign_map, module, cell, "const_xnor", ID::Y, SigSpec(RTLIL::State::S1, width));
@ -609,7 +602,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
std::swap(sig_a, sig_b);
if (sig_b == State::S0 || sig_b == State::S1) {
if (cell->type.in(ID($xor), ID($_XOR_))) {
cover("opt.opt_expr.xor_buffer");
SigSpec sig_y;
if (cell->type == ID($xor))
sig_y = (sig_b == State::S1 ? module->Not(NEW_ID, sig_a).as_bit() : sig_a);
@ -620,7 +612,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
goto next_cell;
}
if (cell->type.in(ID($xnor), ID($_XNOR_))) {
cover("opt.opt_expr.xnor_buffer");
SigSpec sig_y;
if (cell->type == ID($xnor)) {
sig_y = (sig_b == State::S1 ? sig_a : module->Not(NEW_ID, sig_a).as_bit());
@ -641,13 +632,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1)
{
if (cell->type == ID($reduce_xnor)) {
cover("opt.opt_expr.reduce_xnor_not");
log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n",
log_id(cell->type), log_id(cell->name), log_id(module));
cell->type = ID($not);
did_something = true;
} else {
cover("opt.opt_expr.unary_buffer");
replace_cell(assign_map, module, cell, "unary_buffer", ID::Y, cell->getPort(ID::A));
}
goto next_cell;
@ -663,7 +652,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (a_fully_const != b_fully_const)
{
cover("opt.opt_expr.bitwise_logic_one_const");
log_debug("Replacing %s cell `%s' in module `%s' having one fully constant input\n",
log_id(cell->type), log_id(cell->name), log_id(module));
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
@ -815,7 +803,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
new_sig_a.append(neutral_bit);
if (GetSize(new_sig_a) < GetSize(sig_a)) {
cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
cell->setPort(ID::A, new_sig_a);
@ -838,7 +825,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
new_sig_b.append(neutral_bit);
if (GetSize(new_sig_b) < GetSize(sig_b)) {
cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
cell->setPort(ID::B, new_sig_b);
@ -864,7 +850,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
cover("opt.opt_expr.fine.$reduce_and");
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
cell->setPort(ID::A, sig_a = new_a);
@ -890,7 +875,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
cell->setPort(ID::A, sig_a = new_a);
@ -916,7 +900,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) {
cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
cell->setPort(ID::B, sig_b = new_b);
@ -951,7 +934,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
break;
}
if (i > 0) {
cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module));
SigSpec new_a = sig_a.extract_end(i);
SigSpec new_b = sig_b.extract_end(i);
@ -1008,7 +990,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
break;
}
if (i > 0) {
cover("opt.opt_expr.fine.$alu");
log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module));
SigSpec new_a = sig_a.extract_end(i);
SigSpec new_b = sig_b.extract_end(i);
@ -1047,8 +1028,6 @@ skip_fine_alu:
if (0) {
found_the_x_bit:
cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
"$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$divfloor", "$modfloor", "$pow", cell->type.str());
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx);
else
@ -1070,7 +1049,6 @@ skip_fine_alu:
}
if (width < GetSize(sig_a)) {
cover_list("opt.opt_expr.trim", "$shiftx", "$shift", cell->type.str());
sig_a.remove(width, GetSize(sig_a)-width);
cell->setPort(ID::A, sig_a);
cell->setParam(ID::A_WIDTH, width);
@ -1081,13 +1059,11 @@ skip_fine_alu:
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(ID::Y)) == 1 &&
invert_map.count(assign_map(cell->getPort(ID::A))) != 0) {
cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A))));
goto next_cell;
}
if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID::S))) != 0) {
cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
RTLIL::SigSpec tmp = cell->getPort(ID::A);
cell->setPort(ID::A, cell->getPort(ID::B));
@ -1170,7 +1146,6 @@ skip_fine_alu:
if (input.match(" 1")) ACTION_DO(ID::Y, input.extract(1, 1));
if (input.match("01 ")) ACTION_DO(ID::Y, input.extract(0, 1));
if (input.match("10 ")) {
cover("opt.opt_expr.mux_to_inv");
cell->type = ID($_NOT_);
cell->setPort(ID::A, input.extract(0, 1));
cell->unsetPort(ID::B);
@ -1197,7 +1172,6 @@ skip_fine_alu:
if (input == State::S1)
ACTION_DO(ID::Y, cell->getPort(ID::A));
if (input == State::S0 && !a.is_fully_undef()) {
cover("opt.opt_expr.action_" S__LINE__);
log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str());
cell->setPort(ID::A, SigSpec(State::Sx, GetSize(a)));
@ -1222,7 +1196,6 @@ skip_fine_alu:
log_assert(GetSize(a) == GetSize(b));
for (int i = 0; i < GetSize(a); i++) {
if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) {
cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1);
new_y.extend_u0(cell->parameters[ID::Y_WIDTH].as_int(), false);
replace_cell(assign_map, module, cell, "isneq", ID::Y, new_y);
@ -1235,7 +1208,6 @@ skip_fine_alu:
}
if (new_a.size() == 0) {
cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0);
new_y.extend_u0(cell->parameters[ID::Y_WIDTH].as_int(), false);
replace_cell(assign_map, module, cell, "empty", ID::Y, new_y);
@ -1243,7 +1215,6 @@ skip_fine_alu:
}
if (new_a.size() < a.size() || new_b.size() < b.size()) {
cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
cell->setPort(ID::A, new_a);
cell->setPort(ID::B, new_b);
cell->parameters[ID::A_WIDTH] = new_a.size();
@ -1258,7 +1229,6 @@ skip_fine_alu:
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
if (a.is_fully_const() && !b.is_fully_const()) {
cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str());
cell->setPort(ID::A, b);
cell->setPort(ID::B, a);
std::swap(a, b);
@ -1273,7 +1243,6 @@ skip_fine_alu:
RTLIL::SigSpec input = b;
ACTION_DO(ID::Y, cell->getPort(ID::A));
} else {
cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->type = ID($not);
cell->parameters.erase(ID::B_WIDTH);
@ -1288,7 +1257,6 @@ skip_fine_alu:
if (cell->type.in(ID($eq), ID($ne)) &&
(assign_map(cell->getPort(ID::A)).is_fully_zero() || assign_map(cell->getPort(ID::B)).is_fully_zero()))
{
cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
log_id(module), cell->type == ID($eq) ? "$logic_not" : "$reduce_bool");
cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool);
@ -1336,8 +1304,6 @@ skip_fine_alu:
sig_y[i] = sig_a[GetSize(sig_a)-1];
}
cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID::B))), shift_bits, log_id(module), log_signal(sig_y));
@ -1410,11 +1376,6 @@ skip_fine_alu:
if (identity_wrt_a || identity_wrt_b)
{
if (identity_wrt_a)
cover_list("opt.opt_expr.identwrt.a", "$add", "$sub", "$alu", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
if (identity_wrt_b)
cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$alu", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
@ -1463,14 +1424,12 @@ skip_identity:
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
cell->getPort(ID::A) == State::S0 && cell->getPort(ID::B) == State::S1) {
cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str());
replace_cell(assign_map, module, cell, "mux_bool", ID::Y, cell->getPort(ID::S));
goto next_cell;
}
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
cell->getPort(ID::A) == State::S1 && cell->getPort(ID::B) == State::S0) {
cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort(ID::A, cell->getPort(ID::S));
cell->unsetPort(ID::B);
@ -1489,7 +1448,6 @@ skip_identity:
}
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0) {
cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort(ID::A, cell->getPort(ID::S));
cell->unsetPort(ID::S);
@ -1509,7 +1467,6 @@ skip_identity:
}
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) {
cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort(ID::B, cell->getPort(ID::S));
cell->unsetPort(ID::S);
@ -1533,7 +1490,6 @@ skip_identity:
int width = GetSize(cell->getPort(ID::A));
if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) ||
cell->getPort(ID::S).is_fully_undef()) {
cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
replace_cell(assign_map, module, cell, "mux_undef", ID::Y, cell->getPort(ID::A));
goto next_cell;
}
@ -1552,17 +1508,14 @@ skip_identity:
new_s = new_s.extract(0, new_s.size()-1);
}
if (new_s.size() == 0) {
cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str());
replace_cell(assign_map, module, cell, "mux_empty", ID::Y, new_a);
goto next_cell;
}
if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) {
cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str());
replace_cell(assign_map, module, cell, "mux_sel01", ID::Y, new_s);
goto next_cell;
}
if (cell->getPort(ID::S).size() != new_s.size()) {
cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
GetSize(cell->getPort(ID::S)) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
cell->setPort(ID::A, new_a);
@ -1602,7 +1555,6 @@ skip_identity:
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), dummy_arg, \
cell->parameters[ID::A_SIGNED].as_bool(), false, \
cell->parameters[ID::Y_WIDTH].as_int())); \
cover("opt.opt_expr.const.$" #_t); \
replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID::Y, y); \
goto next_cell; \
} \
@ -1617,7 +1569,6 @@ skip_identity:
cell->parameters[ID::A_SIGNED].as_bool(), \
cell->parameters[ID::B_SIGNED].as_bool(), \
cell->parameters[ID::Y_WIDTH].as_int())); \
cover("opt.opt_expr.const.$" #_t); \
replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID::Y, y); \
goto next_cell; \
} \
@ -1629,7 +1580,6 @@ skip_identity:
assign_map.apply(a), assign_map.apply(b); \
if (a.is_fully_const() && b.is_fully_const()) { \
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const())); \
cover("opt.opt_expr.const.$" #_t); \
replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID::Y, y); \
goto next_cell; \
} \
@ -1642,7 +1592,6 @@ skip_identity:
assign_map.apply(a), assign_map.apply(b), assign_map.apply(s); \
if (a.is_fully_const() && b.is_fully_const() && s.is_fully_const()) { \
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), s.as_const())); \
cover("opt.opt_expr.const.$" #_t); \
replace_cell(assign_map, module, cell, stringf("%s, %s, %s", log_signal(a), log_signal(b), log_signal(s)), ID::Y, y); \
goto next_cell; \
} \
@ -1759,8 +1708,6 @@ skip_identity:
{
if (sig_a.is_fully_zero())
{
cover("opt.opt_expr.mul_shift.zero");
log_debug("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
cell->name.c_str(), module->name.c_str());
@ -1774,11 +1721,6 @@ skip_identity:
int exp;
if (sig_a.is_onehot(&exp) && !(a_signed && exp == GetSize(sig_a) - 1))
{
if (swapped_ab)
cover("opt.opt_expr.mul_shift.swapped");
else
cover("opt.opt_expr.mul_shift.unswapped");
log_debug("Replacing multiply-by-%s cell `%s' in module `%s' with shift-by-%d.\n",
log_signal(sig_a), cell->name.c_str(), module->name.c_str(), exp);
@ -1812,8 +1754,6 @@ skip_identity:
break;
if (a_zeros || b_zeros) {
int y_zeros = a_zeros + b_zeros;
cover("opt.opt_expr.mul_low_zeros");
log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n",
a_zeros, b_zeros, cell->name.c_str(), module->name.c_str());
@ -1855,8 +1795,6 @@ skip_identity:
{
if (sig_b.is_fully_zero())
{
cover("opt.opt_expr.divmod_zero");
log_debug("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
cell->name.c_str(), module->name.c_str());
@ -1872,8 +1810,6 @@ skip_identity:
{
if (cell->type.in(ID($div), ID($divfloor)))
{
cover("opt.opt_expr.div_shift");
bool is_truncating = cell->type == ID($div);
log_debug("Replacing %s-divide-by-%s cell `%s' in module `%s' with shift-by-%d.\n",
is_truncating ? "truncating" : "flooring",
@ -1902,8 +1838,6 @@ skip_identity:
}
else if (cell->type.in(ID($mod), ID($modfloor)))
{
cover("opt.opt_expr.mod_mask");
bool is_truncating = cell->type == ID($mod);
log_debug("Replacing %s-modulo-by-%s cell `%s' in module `%s' with bitmask.\n",
is_truncating ? "truncating" : "flooring",
@ -2028,7 +1962,6 @@ skip_identity:
sig_ci = p.second;
}
cover("opt.opt_expr.alu_split");
module->remove(cell);
did_something = true;

View file

@ -22,6 +22,7 @@
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "kernel/celltypes.h"
#include "kernel/threading.h"
#include "libs/sha1/sha1.h"
#include <stdlib.h>
#include <stdio.h>
@ -37,16 +38,73 @@ PRIVATE_NAMESPACE_BEGIN
template <typename T, typename U>
inline Hasher hash_pair(const T &t, const U &u) { return hash_ops<std::pair<T, U>>::hash(t, u); }
struct OptMergeWorker
// Some cell and its hash value.
struct CellHash
{
RTLIL::Design *design;
RTLIL::Module *module;
SigMap assign_map;
FfInitVals initvals;
bool mode_share_all;
// Index of a cell in the module
int cell_index;
Hasher::hash_t hash_value;
};
CellTypes ct;
int total_count;
// The algorithm:
// 1) Compute and store the hashes of all relevant cells, in parallel.
// 2) Given N = the number of threads, partition the cells into N buckets by hash value:
// bucket k contains the cells whose hash value mod N = k.
// 3) For each bucket in parallel, build a hashtable of that buckets cells (using the
// precomputed hashes) and record the duplicates found.
// 4) On the main thread, process the list of duplicates to remove cells.
// For efficiency we fuse the second step into the first step by having the parallel
// threads write the cells into buckets directly.
// To avoid synchronization overhead, we divide each bucket into N shards. Each
// thread j adds a cell to bucket k by writing to shard j of bucket k —
// no synchronization required. In the next phase, thread k builds the hashtable for
// bucket k by iterating over all shards of the bucket.
// The input to each thread in the "compute cell hashes" phase.
struct CellRange
{
int begin;
int end;
};
// The output from each thread in the "compute cell hashes" phase.
struct CellHashes
{
// Entry i contains the hashes where hash_value % bucketed_cell_hashes.size() == i
std::vector<std::vector<CellHash>> bucketed_cell_hashes;
};
// A duplicate cell that has been found.
struct DuplicateCell
{
// Remove this cell from the design
int remove_cell;
// ... and use this cell instead.
int keep_cell;
};
// The input to each thread in the "find duplicate cells" phase.
// Shards of buckets of cell hashes
struct Shards
{
std::vector<std::vector<std::vector<CellHash>>> &bucketed_cell_hashes;
};
// The output from each thread in the "find duplicate cells" phase.
struct FoundDuplicates
{
std::vector<DuplicateCell> duplicates;
};
struct OptMergeThreadWorker
{
const RTLIL::Module *module;
const SigMap &assign_map;
const FfInitVals &initvals;
const CellTypes &ct;
int workers;
bool mode_share_all;
bool mode_keepdc;
static Hasher hash_pmux_in(const SigSpec& sig_s, const SigSpec& sig_b, Hasher h)
{
@ -62,8 +120,8 @@ struct OptMergeWorker
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
{
SigSpec sig_s = conn.at(ID::S);
SigSpec sig_b = conn.at(ID::B);
const SigSpec &sig_s = conn.at(ID::S);
const SigSpec &sig_b = conn.at(ID::B);
int s_width = GetSize(sig_s);
int width = GetSize(sig_b) / s_width;
@ -144,7 +202,6 @@ struct OptMergeWorker
if (cell1->parameters != cell2->parameters)
return false;
if (cell1->connections_.size() != cell2->connections_.size())
return false;
for (const auto &it : cell1->connections_)
@ -199,7 +256,7 @@ struct OptMergeWorker
return conn1 == conn2;
}
bool has_dont_care_initval(const RTLIL::Cell *cell)
bool has_dont_care_initval(const RTLIL::Cell *cell) const
{
if (!cell->is_builtin_ff())
return false;
@ -207,31 +264,134 @@ struct OptMergeWorker
return !initvals(cell->getPort(ID::Q)).is_fully_def();
}
OptMergeWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all, bool mode_keepdc) :
design(design), module(module), mode_share_all(mode_share_all)
OptMergeThreadWorker(const RTLIL::Module *module, const FfInitVals &initvals,
const SigMap &assign_map, const CellTypes &ct, int workers,
bool mode_share_all, bool mode_keepdc) :
module(module), assign_map(assign_map), initvals(initvals), ct(ct),
workers(workers), mode_share_all(mode_share_all), mode_keepdc(mode_keepdc)
{
total_count = 0;
ct.setup_internals();
ct.setup_internals_mem();
ct.setup_stdcells();
ct.setup_stdcells_mem();
}
if (mode_nomux) {
ct.cell_types.erase(ID($mux));
ct.cell_types.erase(ID($pmux));
CellHashes compute_cell_hashes(const CellRange &cell_range) const
{
std::vector<std::vector<CellHash>> bucketed_cell_hashes(workers);
for (int cell_index = cell_range.begin; cell_index < cell_range.end; ++cell_index) {
const RTLIL::Cell *cell = module->cell_at(cell_index);
if (!module->selected(cell))
continue;
if (cell->type.in(ID($meminit), ID($meminit_v2), ID($mem), ID($mem_v2))) {
// Ignore those for performance: meminit can have an excessively large port,
// mem can have an excessively large parameter holding the init data
continue;
}
if (cell->type == ID($scopeinfo))
continue;
if (mode_keepdc && has_dont_care_initval(cell))
continue;
if (!cell->known())
continue;
if (!mode_share_all && !ct.cell_known(cell->type))
continue;
Hasher::hash_t h = hash_cell_function(cell, Hasher()).yield();
int bucket_index = h % workers;
bucketed_cell_hashes[bucket_index].push_back({cell_index, h});
}
return {std::move(bucketed_cell_hashes)};
}
ct.cell_types.erase(ID($tribuf));
ct.cell_types.erase(ID($_TBUF_));
ct.cell_types.erase(ID($anyseq));
ct.cell_types.erase(ID($anyconst));
ct.cell_types.erase(ID($allseq));
ct.cell_types.erase(ID($allconst));
FoundDuplicates find_duplicate_cells(int index, const Shards &in) const
{
// We keep a set of known cells. They're hashed with our hash_cell_function
// and compared with our compare_cell_parameters_and_connections.
struct CellHashOp {
std::size_t operator()(const CellHash &c) const {
return (std::size_t)c.hash_value;
}
};
struct CellEqualOp {
const OptMergeThreadWorker& worker;
CellEqualOp(const OptMergeThreadWorker& w) : worker(w) {}
bool operator()(const CellHash &lhs, const CellHash &rhs) const {
return worker.compare_cell_parameters_and_connections(
worker.module->cell_at(lhs.cell_index),
worker.module->cell_at(rhs.cell_index));
}
};
std::unordered_set<
CellHash,
CellHashOp,
CellEqualOp> known_cells(0, CellHashOp(), CellEqualOp(*this));
std::vector<DuplicateCell> duplicates;
for (const std::vector<std::vector<CellHash>> &buckets : in.bucketed_cell_hashes) {
// Clear out our buckets as we go. This keeps the work of deallocation
// off the main thread.
std::vector<CellHash> bucket = std::move(buckets[index]);
for (CellHash c : bucket) {
auto [cell_in_map, inserted] = known_cells.insert(c);
if (inserted)
continue;
CellHash map_c = *cell_in_map;
if (module->cell_at(c.cell_index)->has_keep_attr()) {
if (module->cell_at(map_c.cell_index)->has_keep_attr())
continue;
known_cells.erase(map_c);
known_cells.insert(c);
std::swap(c, map_c);
}
duplicates.push_back({c.cell_index, map_c.cell_index});
}
}
return {duplicates};
}
};
template <typename T>
void initialize_queues(std::vector<ConcurrentQueue<T>> &queues, int size) {
queues.reserve(size);
for (int i = 0; i < size; ++i)
queues.emplace_back(1);
}
struct OptMergeWorker
{
int total_count;
OptMergeWorker(RTLIL::Module *module, const CellTypes &ct, bool mode_share_all, bool mode_keepdc) :
total_count(0)
{
SigMap assign_map(module);
FfInitVals initvals;
initvals.set(&assign_map, module);
log("Finding identical cells in module `%s'.\n", module->name);
assign_map.set(module);
initvals.set(&assign_map, module);
// Use no more than one worker per thousand cells, rounded down, so
// we only start multithreading with at least 2000 cells.
int num_worker_threads = ThreadPool::pool_size(0, module->cells_size()/1000);
int workers = std::max(1, num_worker_threads);
// The main thread doesn't do any work, so if there is only one worker thread,
// just run everything on the main thread instead.
// This avoids creating and waiting on a thread, which is pretty high overhead
// for very small modules.
if (num_worker_threads == 1)
num_worker_threads = 0;
OptMergeThreadWorker thread_worker(module, initvals, assign_map, ct, workers, mode_share_all, mode_keepdc);
std::vector<ConcurrentQueue<CellRange>> cell_ranges_queues(num_worker_threads);
std::vector<ConcurrentQueue<CellHashes>> cell_hashes_queues(num_worker_threads);
std::vector<ConcurrentQueue<Shards>> shards_queues(num_worker_threads);
std::vector<ConcurrentQueue<FoundDuplicates>> duplicates_queues(num_worker_threads);
ThreadPool thread_pool(num_worker_threads, [&](int i) {
while (std::optional<CellRange> c = cell_ranges_queues[i].pop_front()) {
cell_hashes_queues[i].push_back(thread_worker.compute_cell_hashes(*c));
std::optional<Shards> shards = shards_queues[i].pop_front();
duplicates_queues[i].push_back(thread_worker.find_duplicate_cells(i, *shards));
}
});
bool did_something = true;
// A cell may have to go through a lot of collisions if the hash
@ -239,87 +399,99 @@ struct OptMergeWorker
// beyond the user's control.
while (did_something)
{
std::vector<RTLIL::Cell*> cells;
cells.reserve(module->cells().size());
for (auto cell : module->cells()) {
if (!design->selected(module, cell))
continue;
if (cell->type.in(ID($meminit), ID($meminit_v2), ID($mem), ID($mem_v2))) {
// Ignore those for performance: meminit can have an excessively large port,
// mem can have an excessively large parameter holding the init data
continue;
}
if (cell->type == ID($scopeinfo))
continue;
if (mode_keepdc && has_dont_care_initval(cell))
continue;
if (!cell->known())
continue;
if (!mode_share_all && !ct.cell_known(cell->type))
continue;
cells.push_back(cell);
}
int cells_size = module->cells_size();
log("Computing hashes of %d cells of `%s'.\n", cells_size, module->name);
std::vector<std::vector<std::vector<CellHash>>> sharded_bucketed_cell_hashes(workers);
did_something = false;
// We keep a set of known cells. They're hashed with our hash_cell_function
// and compared with our compare_cell_parameters_and_connections.
// Both need to capture OptMergeWorker to access initvals
struct CellPtrHash {
const OptMergeWorker& worker;
CellPtrHash(const OptMergeWorker& w) : worker(w) {}
std::size_t operator()(const Cell* c) const {
return (std::size_t)worker.hash_cell_function(c, Hasher()).yield();
}
};
struct CellPtrEqual {
const OptMergeWorker& worker;
CellPtrEqual(const OptMergeWorker& w) : worker(w) {}
bool operator()(const Cell* lhs, const Cell* rhs) const {
return worker.compare_cell_parameters_and_connections(lhs, rhs);
}
};
std::unordered_set<
RTLIL::Cell*,
CellPtrHash,
CellPtrEqual> known_cells (0, CellPtrHash(*this), CellPtrEqual(*this));
for (auto cell : cells)
int cell_index = 0;
int cells_size_mod_workers = cells_size % workers;
{
auto [cell_in_map, inserted] = known_cells.insert(cell);
if (!inserted) {
// We've failed to insert since we already have an equivalent cell
Cell* other_cell = *cell_in_map;
if (cell->has_keep_attr()) {
if (other_cell->has_keep_attr())
continue;
known_cells.erase(other_cell);
known_cells.insert(cell);
std::swap(other_cell, cell);
}
did_something = true;
log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name, other_cell->name);
for (auto &it : cell->connections()) {
if (cell->output(it.first)) {
RTLIL::SigSpec other_sig = other_cell->getPort(it.first);
log_debug(" Redirecting output %s: %s = %s\n", it.first,
log_signal(it.second), log_signal(other_sig));
Const init = initvals(other_sig);
initvals.remove_init(it.second);
initvals.remove_init(other_sig);
module->connect(RTLIL::SigSig(it.second, other_sig));
assign_map.add(it.second, other_sig);
initvals.set_init(other_sig, init);
}
}
log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type, cell->name, module->name);
module->remove(cell);
total_count++;
Multithreading multithreading;
for (int i = 0; i < workers; ++i) {
int num_cells = cells_size/workers + ((i < cells_size_mod_workers) ? 1 : 0);
CellRange c = { cell_index, cell_index + num_cells };
cell_index += num_cells;
if (num_worker_threads > 0)
cell_ranges_queues[i].push_back(c);
else
sharded_bucketed_cell_hashes[i] = std::move(thread_worker.compute_cell_hashes(c).bucketed_cell_hashes);
}
log_assert(cell_index == cells_size);
if (num_worker_threads > 0)
for (int i = 0; i < workers; ++i)
sharded_bucketed_cell_hashes[i] = std::move(cell_hashes_queues[i].pop_front()->bucketed_cell_hashes);
}
log("Finding duplicate cells in `%s'.\n", module->name);
std::vector<DuplicateCell> merged_duplicates;
{
Multithreading multithreading;
for (int i = 0; i < workers; ++i) {
Shards thread_shards = { sharded_bucketed_cell_hashes };
if (num_worker_threads > 0)
shards_queues[i].push_back(thread_shards);
else {
std::vector<DuplicateCell> d = std::move(thread_worker.find_duplicate_cells(i, thread_shards).duplicates);
merged_duplicates.insert(merged_duplicates.end(), d.begin(), d.end());
}
}
if (num_worker_threads > 0)
for (int i = 0; i < workers; ++i) {
std::vector<DuplicateCell> d = std::move(duplicates_queues[i].pop_front()->duplicates);
merged_duplicates.insert(merged_duplicates.end(), d.begin(), d.end());
}
}
std::sort(merged_duplicates.begin(), merged_duplicates.end(), [](const DuplicateCell &lhs, const DuplicateCell &rhs) {
// Sort them by the order in which duplicates would have been detected in a single-threaded
// run. The cell at which the duplicate would have been detected is the latter of the two
// cells involved.
return std::max(lhs.remove_cell, lhs.keep_cell) < std::max(rhs.remove_cell, rhs.keep_cell);
});
// Convert to cell pointers because removing cells will invalidate the indices.
std::vector<std::pair<RTLIL::Cell*, RTLIL::Cell*>> cell_ptrs;
for (DuplicateCell dup : merged_duplicates)
cell_ptrs.push_back({module->cell_at(dup.remove_cell), module->cell_at(dup.keep_cell)});
for (auto [remove_cell, keep_cell] : cell_ptrs)
{
log_debug(" Cell `%s' is identical to cell `%s'.\n", remove_cell->name, keep_cell->name);
for (auto &it : remove_cell->connections()) {
if (remove_cell->output(it.first)) {
RTLIL::SigSpec keep_sig = keep_cell->getPort(it.first);
log_debug(" Redirecting output %s: %s = %s\n", it.first,
log_signal(it.second), log_signal(keep_sig));
Const init = initvals(keep_sig);
initvals.remove_init(it.second);
initvals.remove_init(keep_sig);
module->connect(RTLIL::SigSig(it.second, keep_sig));
auto keep_sig_it = keep_sig.begin();
for (SigBit remove_sig_bit : it.second) {
assign_map.add(remove_sig_bit, *keep_sig_it);
++keep_sig_it;
}
initvals.set_init(keep_sig, init);
}
}
log_debug(" Removing %s cell `%s' from module `%s'.\n", remove_cell->type, remove_cell->name, module->name);
module->remove(remove_cell);
total_count++;
}
did_something = !merged_duplicates.empty();
}
for (ConcurrentQueue<CellRange> &q : cell_ranges_queues)
q.close();
for (ConcurrentQueue<Shards> &q : shards_queues)
q.close();
for (ConcurrentQueue<CellRange> &q : cell_ranges_queues)
q.close();
for (ConcurrentQueue<Shards> &q : shards_queues)
q.close();
log_suppressed();
}
};
@ -372,9 +544,25 @@ struct OptMergePass : public Pass {
}
extra_args(args, argidx, design);
CellTypes ct;
ct.setup_internals();
ct.setup_internals_mem();
ct.setup_stdcells();
ct.setup_stdcells_mem();
if (mode_nomux) {
ct.cell_types.erase(ID($mux));
ct.cell_types.erase(ID($pmux));
}
ct.cell_types.erase(ID($tribuf));
ct.cell_types.erase(ID($_TBUF_));
ct.cell_types.erase(ID($anyseq));
ct.cell_types.erase(ID($anyconst));
ct.cell_types.erase(ID($allseq));
ct.cell_types.erase(ID($allconst));
int total_count = 0;
for (auto module : design->selected_modules()) {
OptMergeWorker worker(design, module, mode_nomux, mode_share_all, mode_keepdc);
OptMergeWorker worker(module, ct, mode_share_all, mode_keepdc);
total_count += worker.total_count;
}

View file

@ -64,7 +64,7 @@ struct OptMuxtreeWorker
RTLIL::Module *module;
SigMap assign_map;
int removed_count;
int glob_evals_left = 10000000;
int glob_evals_left = 10'000'000;
struct bitinfo_t {
// Is bit directly used by non-mux cells or ports?

View file

@ -97,6 +97,7 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did
all_empty = false;
if (all_empty)
{
did_something = true;
for (auto cs : sw->cases)
delete cs;
sw->cases.clear();

View file

@ -39,6 +39,7 @@ OBJS += passes/techmap/muxcover.o
OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
OBJS += passes/techmap/lut2mux.o
OBJS += passes/techmap/lut2bmux.o
OBJS += passes/techmap/nlutmap.o
OBJS += passes/techmap/shregmap.o
OBJS += passes/techmap/deminout.o

View file

@ -252,8 +252,8 @@ std::optional<AbcProcess> spawn_abc(const char* abc_exe, DeferredLogs &logs) {
char arg1[] = "-s";
char* argv[] = { strdup(abc_exe), arg1, nullptr };
if (0 != posix_spawn(&result.pid, abc_exe, &file_actions, nullptr, argv, environ)) {
logs.log_error("posix_spawn %s failed", abc_exe);
if (0 != posix_spawnp(&result.pid, abc_exe, &file_actions, nullptr, argv, environ)) {
logs.log_error("posix_spawnp %s failed (errno=%s)", abc_exe, strerror(errno));
return std::nullopt;
}
free(argv[0]);

View file

@ -415,7 +415,7 @@ struct BufnormPass : public Pass {
return mapped_bits.at(bit);
};
auto make_buffer_f = [&](const IdString &type, const SigSpec &src, const SigSpec &dst)
auto make_buffer_f = [&](IdString type, const SigSpec &src, const SigSpec &dst)
{
auto it = old_buffers.find(pair<IdString, SigSpec>(type, dst));

View file

@ -40,10 +40,10 @@ int bindec(unsigned char v)
r += (~((v & 2) - 1)) & 10;
r += (~((v & 4) - 1)) & 100;
r += (~((v & 8) - 1)) & 1000;
r += (~((v & 16) - 1)) & 10000;
r += (~((v & 32) - 1)) & 100000;
r += (~((v & 64) - 1)) & 1000000;
r += (~((v & 128) - 1)) & 10000000;
r += (~((v & 16) - 1)) & 10'000;
r += (~((v & 32) - 1)) & 100'000;
r += (~((v & 64) - 1)) & 1'000'000;
r += (~((v & 128) - 1)) & 10'000'000;
return r;
}

View file

@ -0,0 +1,58 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct Lut2BmuxPass : public Pass {
Lut2BmuxPass() : Pass("lut2bmux", "convert $lut to $bmux") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" lut2bmux [options] [selection]\n");
log("\n");
log("This pass converts $lut cells to $bmux cells.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing LUT2BMUX pass (convert $lut to $bmux).\n");
size_t argidx = 1;
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
for (auto cell : module->selected_cells()) {
if (cell->type == ID($lut)) {
cell->type = ID($bmux);
cell->setPort(ID::S, cell->getPort(ID::A));
cell->setPort(ID::A, cell->getParam(ID::LUT));
cell->unsetParam(ID::LUT);
cell->fixup_parameters();
log("Converted %s.%s to BMUX cell.\n", log_id(module), log_id(cell));
}
}
}
} Lut2BmuxPass;
PRIVATE_NAMESPACE_END

View file

@ -27,7 +27,7 @@
USING_YOSYS_NAMESPACE
YOSYS_NAMESPACE_BEGIN
static void transfer_attr (Cell* to, const Cell* from, const IdString& attr) {
static void transfer_attr (Cell* to, const Cell* from, IdString attr) {
if (from->has_attribute(attr))
to->attributes[attr] = from->attributes.at(attr);
}

View file

@ -1143,7 +1143,29 @@ struct TestCellPass : public Pass {
else
uut = create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv);
if (!write_prefix.empty()) {
Pass::call(design, stringf("write_rtlil %s_%s_%05d.il", write_prefix, cell_type.c_str()+1, i));
string writer = "write_rtlil";
string suffix = "il";
if (techmap_cmd.compare("aigmap") == 0) {
// try to convert to aiger
Pass::call(design, techmap_cmd);
bool is_unconverted = false;
for (auto *mod : design->selected_modules())
for (auto *cell : mod->selected_cells())
if (!cell->type.in(ID::$_NOT_, ID::$_AND_)) {
is_unconverted = true;
break;
}
if (is_unconverted) {
// skip unconverted cells
log_warning("Skipping %s\n", cell_type);
delete design;
break;
} else {
writer = "write_aiger -ascii";
suffix = "aag";
}
}
Pass::call(design, stringf("%s %s_%s_%05d.%s", writer, write_prefix, cell_type.c_str()+1, i, suffix));
} else if (edges) {
Pass::call(design, "dump gold");
run_edges_test(design, verbose);

View file

@ -112,7 +112,7 @@ namespace pyosys {
void notify_connect(
RTLIL::Cell *cell,
const RTLIL::IdString &port,
RTLIL::IdString port,
const RTLIL::SigSpec &old_sig,
const RTLIL::SigSpec &sig
) override {
@ -228,7 +228,7 @@ namespace pyosys {
"notify_connect",
py::overload_cast<
RTLIL::Cell *,
const RTLIL::IdString &,
RTLIL::IdString,
const RTLIL::SigSpec &,
const RTLIL::SigSpec &
>(&RTLIL::Monitor::notify_connect)

View file

@ -2,6 +2,7 @@ ram block $__GOWIN_SP_ {
abits 14;
widths 1 2 4 9 18 36 per_port;
cost 128;
byte 9;
init no_undef;
port srsw "A" {
clock posedge;
@ -24,6 +25,7 @@ ram block $__GOWIN_SP_ {
rdwr old;
}
}
wrbe_separate;
}
}
@ -31,6 +33,7 @@ ram block $__GOWIN_DP_ {
abits 14;
widths 1 2 4 9 18 per_port;
cost 128;
byte 9;
init no_undef;
port srsw "A" "B" {
clock posedge;
@ -53,6 +56,7 @@ ram block $__GOWIN_DP_ {
rdwr old;
}
}
wrbe_separate;
}
}
@ -60,6 +64,7 @@ ram block $__GOWIN_SDP_ {
abits 14;
widths 1 2 4 9 18 36 per_port;
cost 128;
byte 9;
init no_undef;
port sr "R" {
clock posedge;
@ -75,5 +80,6 @@ ram block $__GOWIN_SDP_ {
port sw "W" {
clock posedge;
clken;
wrbe_separate;
}
}

View file

@ -14,7 +14,7 @@
`define x8_width(width) (width / 9 * 8 + width % 9)
`define x8_rd_data(data) {1'bx, data[31:24], 1'bx, data[23:16], 1'bx, data[15:8], 1'bx, data[7:0]}
`define x8_wr_data(data) {data[34:27], data[25:18], data[16:9], data[7:0]}
`define addrbe_always(width, addr) (width < 18 ? addr : width == 18 ? {addr[13:4], 4'b0011} : {addr[13:5], 5'b01111})
`define addrbe(width, addr, w_be) (width < 18 ? addr : width == 18 ? {addr[13:4], 2'b00, w_be[1:0]} : {addr[13:5], 1'b0, w_be[3:0]})
`define INIT(func) \
@ -90,6 +90,7 @@ parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_A_WIDTH = 36;
parameter PORT_A_OPTION_WRITE_MODE = 0;
parameter PORT_A_WR_BE_WIDTH = 4;
input PORT_A_CLK;
input PORT_A_CLK_EN;
@ -97,13 +98,14 @@ input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
`DEF_FUNCS
wire RST = OPTION_RESET_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST;
wire [13:0] AD = `addrbe_always(PORT_A_WIDTH, PORT_A_ADDR);
wire [13:0] AD = `addrbe(PORT_A_WIDTH, PORT_A_ADDR, PORT_A_WR_BE);
generate
@ -173,9 +175,11 @@ parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_A_WIDTH = 18;
parameter PORT_A_OPTION_WRITE_MODE = 0;
parameter PORT_A_WR_BE_WIDTH = 4;
parameter PORT_B_WIDTH = 18;
parameter PORT_B_OPTION_WRITE_MODE = 0;
parameter PORT_B_WR_BE_WIDTH = 4;
input PORT_A_CLK;
input PORT_A_CLK_EN;
@ -183,6 +187,7 @@ input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
@ -192,6 +197,7 @@ input PORT_B_WR_EN;
input PORT_B_RD_SRST;
input PORT_B_RD_ARST;
input [13:0] PORT_B_ADDR;
input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_B_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_B_RD_DATA;
@ -199,8 +205,8 @@ output [PORT_A_WIDTH-1:0] PORT_B_RD_DATA;
wire RSTA = OPTION_RESET_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST;
wire RSTB = OPTION_RESET_MODE == "SYNC" ? PORT_B_RD_SRST : PORT_B_RD_ARST;
wire [13:0] ADA = `addrbe_always(PORT_A_WIDTH, PORT_A_ADDR);
wire [13:0] ADB = `addrbe_always(PORT_B_WIDTH, PORT_B_ADDR);
wire [13:0] ADA = `addrbe(PORT_A_WIDTH, PORT_A_ADDR, PORT_B_WR_BE);
wire [13:0] ADB = `addrbe(PORT_B_WIDTH, PORT_B_ADDR, PORT_B_WR_BE);
generate
@ -306,6 +312,7 @@ parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_R_WIDTH = 18;
parameter PORT_W_WIDTH = 18;
parameter PORT_W_WR_BE_WIDTH = 4;
input PORT_R_CLK;
input PORT_R_CLK_EN;
@ -318,12 +325,13 @@ input PORT_W_CLK;
input PORT_W_CLK_EN;
input PORT_W_WR_EN;
input [13:0] PORT_W_ADDR;
input [PORT_W_WR_BE_WIDTH-1:0] PORT_W_WR_BE;
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
`DEF_FUNCS
wire RST = OPTION_RESET_MODE == "SYNC" ? PORT_R_RD_SRST : PORT_R_RD_ARST;
wire [13:0] ADW = `addrbe_always(PORT_W_WIDTH, PORT_W_ADDR);
wire [13:0] ADW = `addrbe(PORT_W_WIDTH, PORT_W_ADDR, PORT_W_WR_BE);
wire WRE = PORT_W_CLK_EN & PORT_W_WR_EN;
generate

View file

@ -14,7 +14,7 @@
`define x8_width(width) (width / 9 * 8 + width % 9)
`define x8_rd_data(data) {1'bx, data[31:24], 1'bx, data[23:16], 1'bx, data[15:8], 1'bx, data[7:0]}
`define x8_wr_data(data) {data[34:27], data[25:18], data[16:9], data[7:0]}
`define addrbe_always(width, addr) (width < 18 ? addr : width == 18 ? {addr[13:4], 4'b0011} : {addr[13:5], 5'b01111})
`define addrbe(width, addr, w_be) (width < 18 ? addr : width == 18 ? {addr[13:4], 2'b00, w_be[1:0]} : {addr[13:5], 1'b0, w_be[3:0]})
`define INIT(func) \
@ -90,6 +90,7 @@ parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_A_WIDTH = 36;
parameter PORT_A_OPTION_WRITE_MODE = 0;
parameter PORT_A_WR_BE_WIDTH = 4;
input PORT_A_CLK;
input PORT_A_CLK_EN;
@ -97,13 +98,14 @@ input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
`DEF_FUNCS
wire RST = OPTION_RESET_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST;
wire [13:0] AD = `addrbe_always(PORT_A_WIDTH, PORT_A_ADDR);
wire [13:0] AD = `addrbe(PORT_A_WIDTH, PORT_A_ADDR, PORT_A_WR_BE);
generate
@ -173,9 +175,11 @@ parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_A_WIDTH = 18;
parameter PORT_A_OPTION_WRITE_MODE = 0;
parameter PORT_A_WR_BE_WIDTH = 4;
parameter PORT_B_WIDTH = 18;
parameter PORT_B_OPTION_WRITE_MODE = 0;
parameter PORT_B_WR_BE_WIDTH = 4;
input PORT_A_CLK;
input PORT_A_CLK_EN;
@ -183,6 +187,7 @@ input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
@ -192,6 +197,7 @@ input PORT_B_WR_EN;
input PORT_B_RD_SRST;
input PORT_B_RD_ARST;
input [13:0] PORT_B_ADDR;
input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_B_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_B_RD_DATA;
@ -199,8 +205,8 @@ output [PORT_A_WIDTH-1:0] PORT_B_RD_DATA;
wire RSTA = OPTION_RESET_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST;
wire RSTB = OPTION_RESET_MODE == "SYNC" ? PORT_B_RD_SRST : PORT_B_RD_ARST;
wire [13:0] ADA = `addrbe_always(PORT_A_WIDTH, PORT_A_ADDR);
wire [13:0] ADB = `addrbe_always(PORT_B_WIDTH, PORT_B_ADDR);
wire [13:0] ADA = `addrbe(PORT_A_WIDTH, PORT_A_ADDR, PORT_B_WR_BE);
wire [13:0] ADB = `addrbe(PORT_B_WIDTH, PORT_B_ADDR, PORT_B_WR_BE);
generate
@ -306,6 +312,7 @@ parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_R_WIDTH = 18;
parameter PORT_W_WIDTH = 18;
parameter PORT_W_WR_BE_WIDTH = 4;
input PORT_R_CLK;
input PORT_R_CLK_EN;
@ -318,12 +325,13 @@ input PORT_W_CLK;
input PORT_W_CLK_EN;
input PORT_W_WR_EN;
input [13:0] PORT_W_ADDR;
input [PORT_W_WR_BE_WIDTH-1:0] PORT_W_WR_BE;
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
`DEF_FUNCS
wire RST = OPTION_RESET_MODE == "SYNC" ? PORT_R_RD_SRST : PORT_R_RD_ARST;
wire [13:0] ADW = `addrbe_always(PORT_W_WIDTH, PORT_W_ADDR);
wire [13:0] ADW = `addrbe(PORT_W_WIDTH, PORT_W_ADDR, PORT_W_WR_BE);
wire WRE = PORT_W_CLK_EN & PORT_W_WR_EN;
generate

View file

@ -138,7 +138,7 @@ struct Ice40WrapCarryPass : public Pass {
lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
else if (a.first == ID::src)
src = a.second;
else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived))
else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived, ID::src))
continue;
else
log_abort();

View file

@ -1,2 +1,3 @@
/*_ref.v
/neg.out/
/gate/

View file

@ -0,0 +1,7 @@
aag 3 2 0 1 1
2
4
6
6 5 2
c
Generated by Yosys

View file

@ -0,0 +1,7 @@
aag 3 2 0 1 1
2
4
6
6 4 2
c
Generated by Yosys

View file

@ -0,0 +1,9 @@
aag 5 3 0 1 2
2
4
6
10
8 4 2
10 9 7
c
Generated by Yosys

View file

@ -0,0 +1,11 @@
aag 7 4 0 1 3
2
4
6
8
14
10 4 2
12 8 6
14 13 11
c
Generated by Yosys

View file

@ -0,0 +1,5 @@
aag 1 1 0 1 0
2
2
c
Generated by Yosys

View file

@ -0,0 +1,10 @@
aag 6 3 0 1 3
2
4
6
13
8 7 2
10 6 4
12 11 9
c
Generated by Yosys

View file

@ -0,0 +1,7 @@
aag 3 2 0 1 1
2
4
7
6 4 2
c
Generated by Yosys

View file

@ -0,0 +1,10 @@
aag 6 3 0 1 3
2
4
6
12
8 7 2
10 6 4
12 11 9
c
Generated by Yosys

View file

@ -0,0 +1,7 @@
aag 3 2 0 1 1
2
4
6
6 5 3
c
Generated by Yosys

View file

@ -0,0 +1,5 @@
aag 1 1 0 1 0
2
3
c
Generated by Yosys

View file

@ -0,0 +1,9 @@
aag 5 3 0 1 2
2
4
6
11
8 5 3
10 9 6
c
Generated by Yosys

View file

@ -0,0 +1,11 @@
aag 7 4 0 1 3
2
4
6
8
15
10 5 3
12 9 7
14 13 11
c
Generated by Yosys

View file

@ -0,0 +1,7 @@
aag 3 2 0 1 1
2
4
7
6 4 3
c
Generated by Yosys

View file

@ -0,0 +1,7 @@
aag 3 2 0 1 1
2
4
7
6 5 3
c
Generated by Yosys

View file

@ -0,0 +1,9 @@
aag 5 2 0 1 3
2
4
11
6 4 2
8 5 3
10 9 7
c
Generated by Yosys

View file

@ -0,0 +1,9 @@
aag 5 2 0 1 3
2
4
10
6 4 2
8 5 3
10 9 7
c
Generated by Yosys

View file

@ -0,0 +1,62 @@
aag 51 4 0 8 47
2
4
6
8
14
30
42
54
66
78
90
102
10 6 2
12 7 3
14 13 11
16 6 2
18 8 4
20 9 5
22 21 19
24 22 16
26 21 19
28 27 11
30 29 25
32 21 16
34 33 19
36 35 22
38 33 19
40 38 27
42 41 37
44 35 21
46 45 19
48 47 22
50 45 19
52 50 27
54 53 49
56 47 21
58 57 19
60 59 22
62 57 19
64 62 27
66 65 61
68 59 21
70 69 19
72 71 22
74 69 19
76 74 27
78 77 73
80 71 21
82 81 19
84 83 22
86 81 19
88 86 27
90 89 85
92 83 21
94 93 19
96 95 22
98 93 19
100 98 27
102 101 97
c
Generated by Yosys

View file

@ -0,0 +1,45 @@
aag 33 5 0 9 28
2
4
6
8
10
27
35
36
38
40
8
48
58
66
12 8 6
14 9 7
16 15 13
18 16 2
20 15 13
22 21 3
24 23 10
26 25 19
28 8 4
30 9 5
32 31 27
34 33 29
36 35 8
38 23 19
40 31 29
42 38 10
44 23 19
46 45 11
48 47 43
50 40 27
52 31 29
54 25 19
56 54 53
58 57 51
60 35 8
62 33 29
64 62 9
66 65 61
c
Generated by Yosys

View file

@ -0,0 +1,28 @@
aag 17 11 0 8 6
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
34
34
24 14 2
26 16 4
28 18 6
30 20 8
32 22 10
34 22 12
c
Generated by Yosys

View file

@ -0,0 +1,15 @@
aag 6 6 0 6 0
2
4
6
8
10
12
2
4
6
8
10
12
c
Generated by Yosys

View file

@ -0,0 +1,46 @@
aag 38 11 0 5 27
2
4
6
8
10
12
14
16
18
20
22
76
0
0
0
0
24 10 2
26 11 3
28 27 25
30 12 4
32 13 5
34 33 31
36 35 29
38 14 6
40 15 7
42 41 39
44 43 36
46 16 8
48 17 9
50 49 47
52 51 44
54 18 8
56 19 9
58 57 55
60 59 52
62 20 8
64 21 9
66 65 63
68 67 60
70 22 8
72 23 9
74 73 71
76 75 68
c
Generated by Yosys

View file

@ -0,0 +1,9 @@
aag 3 2 0 3 1
2
4
7
0
0
6 4 3
c
Generated by Yosys

View file

@ -0,0 +1,48 @@
aag 43 10 0 2 33
2
4
6
8
10
12
14
16
18
20
86
0
22 20 7
24 21 6
26 25 23
28 18 7
30 16 7
32 14 7
34 12 7
36 10 5
38 9 2
40 8 3
42 41 38
44 11 4
46 45 43
48 47 37
50 13 6
52 51 49
54 53 35
56 15 6
58 57 55
60 59 33
62 17 6
64 63 61
66 65 31
68 19 6
70 69 67
72 71 29
74 73 25
76 75 23
78 77 26
80 25 23
82 75 23
84 82 81
86 85 79
c
Generated by Yosys

View file

@ -0,0 +1,52 @@
aag 47 12 0 2 35
2
4
6
8
10
12
14
16
18
20
22
24
94
0
26 25 8
28 24 9
30 29 27
32 23 8
34 21 8
36 19 8
38 17 8
40 15 6
42 13 4
44 11 2
46 12 5
48 47 44
50 49 43
52 14 7
54 53 51
56 55 41
58 16 9
60 59 57
62 61 39
64 18 9
66 65 63
68 67 37
70 20 9
72 71 69
74 73 35
76 22 9
78 77 75
80 79 33
82 81 29
84 83 27
86 85 30
88 29 27
90 83 27
92 90 89
94 93 87
c
Generated by Yosys

View file

@ -0,0 +1,30 @@
aag 21 11 0 6 10
2
4
6
8
10
12
14
16
18
20
22
42
0
0
0
0
0
24 5 3
26 24 7
28 26 9
30 28 11
32 30 13
34 17 15
36 34 19
38 36 21
40 38 23
42 41 33
c
Generated by Yosys

View file

@ -0,0 +1,15 @@
aag 7 4 0 5 3
2
4
6
8
14
0
0
0
0
10 5 3
12 10 7
14 12 9
c
Generated by Yosys

View file

@ -0,0 +1,29 @@
aag 21 11 0 5 10
2
4
6
8
10
12
14
16
18
20
22
43
0
0
0
0
24 5 3
26 24 7
28 26 9
30 28 11
32 30 13
34 17 15
36 34 19
38 36 21
40 38 23
42 40 32
c
Generated by Yosys

View file

@ -0,0 +1,43 @@
aag 34 9 0 6 25
2
4
6
8
10
12
14
16
18
68
0
0
0
0
0
20 19 10
22 18 11
24 23 21
26 19 8
28 17 6
30 15 4
32 12 3
34 13 2
36 35 32
38 14 5
40 39 37
42 41 31
44 16 7
46 45 43
48 47 29
50 18 9
52 51 49
54 53 27
56 55 23
58 57 21
60 59 24
62 23 21
64 57 21
66 64 63
68 67 61
c
Generated by Yosys

View file

@ -0,0 +1,10 @@
aag 6 3 0 1 3
2
4
6
13
8 7 2
10 6 4
12 11 9
c
Generated by Yosys

View file

@ -0,0 +1,40 @@
aag 29 10 0 8 19
2
4
6
8
10
12
14
16
18
20
59
0
0
0
0
0
0
0
22 12 2
24 13 3
26 25 23
28 14 4
30 15 5
32 31 29
34 33 27
36 16 6
38 17 7
40 39 37
42 41 34
44 18 8
46 19 9
48 47 45
50 49 42
52 20 10
54 21 11
56 55 53
58 57 50
c
Generated by Yosys

View file

@ -0,0 +1,11 @@
aag 6 6 0 2 0
2
4
6
8
10
12
3
5
c
Generated by Yosys

View file

@ -0,0 +1,11 @@
aag 6 4 0 2 2
2
4
6
8
11
13
10 5 3
12 7 3
c
Generated by Yosys

View file

@ -0,0 +1,9 @@
aag 1 1 0 5 0
2
2
2
2
2
2
c
Generated by Yosys

View file

@ -0,0 +1,7 @@
aag 1 1 0 3 0
2
2
0
0
c
Generated by Yosys

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