mirror of https://github.com/YosysHQ/yosys.git
Bump to latest
This commit is contained in:
commit
3d13f7aae2
12
Makefile
12
Makefile
|
|
@ -129,6 +129,12 @@ LIBS += -ldw # SILIMATE: support for backward-cpp
|
|||
CXXFLAGS += -I/usr/include/libdwarf/ -DBACKWARD_HAS_DW # SILIMATE: support for backward-cpp
|
||||
endif
|
||||
|
||||
ifneq ($(shell :; command -v rsync),)
|
||||
RSYNC_CP ?= rsync -rc
|
||||
else
|
||||
RSYNC_CP ?= cp -ru
|
||||
endif
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
PLUGIN_LINKFLAGS += -undefined dynamic_lookup
|
||||
LINKFLAGS += -rdynamic
|
||||
|
|
@ -169,7 +175,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.51+46
|
||||
YOSYS_VER := 0.51+85
|
||||
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
||||
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2)
|
||||
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3)
|
||||
|
|
@ -1074,13 +1080,13 @@ docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS)
|
|||
$(Q) mkdir -p docs/source/cmd
|
||||
$(Q) mkdir -p temp/docs/source/cmd
|
||||
$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual'
|
||||
$(Q) rsync -rc temp/docs/source/cmd docs/source
|
||||
$(Q) $(RSYNC_CP) temp/docs/source/cmd docs/source
|
||||
$(Q) rm -rf temp
|
||||
docs/source/cell/word_add.rst: $(TARGETS) $(EXTRA_TARGETS)
|
||||
$(Q) mkdir -p docs/source/cell
|
||||
$(Q) mkdir -p temp/docs/source/cell
|
||||
$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-cells-manual'
|
||||
$(Q) rsync -rc temp/docs/source/cell docs/source
|
||||
$(Q) $(RSYNC_CP) temp/docs/source/cell docs/source
|
||||
$(Q) rm -rf temp
|
||||
|
||||
docs/source/generated/cells.json: docs/source/generated $(TARGETS) $(EXTRA_TARGETS)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@ all: examples all_tex
|
|||
# set a fake time in pdf generation to prevent unnecessary differences in output
|
||||
FAKETIME := TZ='Z' faketime -f '2022-01-01 00:00:00 x0,001'
|
||||
|
||||
ifneq ($(shell :; command -v rsync),)
|
||||
RSYNC_CP ?= rsync -t
|
||||
else
|
||||
RSYNC_CP ?= cp -a
|
||||
endif
|
||||
|
||||
# find all code example makefiles
|
||||
.PHONY: examples
|
||||
CODE_EXAMPLES := ../code_examples/*/Makefile
|
||||
|
|
@ -19,7 +25,7 @@ FORCE:
|
|||
../%/Makefile: FORCE
|
||||
@make -C $(@D) dots
|
||||
@mkdir -p $*
|
||||
@find $(@D) -name *.dot -exec rsync -t {} $* \;
|
||||
@find $(@D) -name *.dot -exec $(RSYNC_CP) {} $* \;
|
||||
|
||||
# find and build all tex files
|
||||
.PHONY: all_tex
|
||||
|
|
|
|||
|
|
@ -16,15 +16,17 @@ html_theme_options: dict[str] = {
|
|||
"source_branch": "main",
|
||||
"source_directory": "docs/source/",
|
||||
}
|
||||
html_context: dict[str] = {}
|
||||
|
||||
# try to fix the readthedocs detection
|
||||
html_context: dict[str] = {
|
||||
"READTHEDOCS": True,
|
||||
"display_github": True,
|
||||
"github_user": "YosysHQ",
|
||||
"github_repo": "yosys",
|
||||
"slug": "yosys",
|
||||
}
|
||||
if os.getenv("READTHEDOCS"):
|
||||
html_context.update({
|
||||
"READTHEDOCS": True,
|
||||
"display_github": True,
|
||||
"github_user": "YosysHQ",
|
||||
"github_repo": "yosys",
|
||||
"slug": "yosys",
|
||||
})
|
||||
|
||||
# override source_branch if not main
|
||||
git_slug = os.getenv("READTHEDOCS_VERSION_NAME")
|
||||
|
|
|
|||
|
|
@ -34,31 +34,18 @@ Targeted architectures
|
|||
|
||||
The `OSS CAD Suite`_ releases `nightly builds`_ for the following architectures:
|
||||
|
||||
.. only:: html
|
||||
- **linux-x64** - Most personal Linux based computers
|
||||
- **darwin-x64** - macOS 12 or later with Intel CPU
|
||||
- **darwin-arm64** - macOS 12 or later with M1/M2 CPU
|
||||
- **windows-x64** - Targeted for Windows 10 and 11
|
||||
- **linux-arm64** - Devices such as Raspberry Pi with 64bit OS
|
||||
|
||||
- linux-x64 |linux-x64|
|
||||
- Most personal Linux based computers
|
||||
|
||||
- darwin-x64 |darwin-x64|
|
||||
- macOS 12 or later with Intel CPU
|
||||
|
||||
- darwin-arm64 |darwin-arm64|
|
||||
- macOS 12 or later with M1/M2 CPU
|
||||
|
||||
- windows-x64 |windows-x64|
|
||||
- Targeted for Windows 10 and 11
|
||||
|
||||
- linux-arm64 |linux-arm64|
|
||||
For more information about the targeted architectures, and the current build
|
||||
status, check the `OSS CAD Suite`_ git repository.
|
||||
|
||||
.. _OSS CAD Suite: https://github.com/YosysHQ/oss-cad-suite-build
|
||||
.. _nightly builds: https://github.com/YosysHQ/oss-cad-suite-build/releases/latest
|
||||
|
||||
.. |linux-x64| image:: https://github.com/YosysHQ/oss-cad-suite-build/actions/workflows/linux-x64.yml/badge.svg
|
||||
.. |darwin-x64| image:: https://github.com/YosysHQ/oss-cad-suite-build/actions/workflows/darwin-x64.yml/badge.svg
|
||||
.. |darwin-arm64| image:: https://github.com/YosysHQ/oss-cad-suite-build/actions/workflows/darwin-arm64.yml/badge.svg
|
||||
.. |windows-x64| image:: https://github.com/YosysHQ/oss-cad-suite-build/actions/workflows/windows-x64.yml/badge.svg
|
||||
.. |linux-arm64| image:: https://github.com/YosysHQ/oss-cad-suite-build/actions/workflows/linux-arm64.yml/badge.svg
|
||||
|
||||
Building from source
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -6,22 +6,12 @@ Testing Yosys
|
|||
Automatic testing
|
||||
-----------------
|
||||
|
||||
.. only:: html
|
||||
|
||||
The `Yosys Git repo`_ has automatic testing of builds and running of the
|
||||
included test suite on the following platforms:
|
||||
|
||||
- Ubuntu |test-linux|
|
||||
- macOS |test-macos|
|
||||
The `Yosys Git repo`_ has automatic testing of builds and running of the
|
||||
included test suite on both Ubuntu and macOS, as well as across range of
|
||||
compiler versions. For up to date information, including OS versions, refer to
|
||||
`the git actions page`_.
|
||||
|
||||
.. _Yosys Git repo: https://github.com/YosysHQ/yosys
|
||||
|
||||
.. |test-linux| image:: https://github.com/YosysHQ/yosys/actions/workflows/test-linux.yml/badge.svg?branch=main
|
||||
.. |test-macos| image:: https://github.com/YosysHQ/yosys/actions/workflows/test-macos.yml/badge.svg?branch=main
|
||||
|
||||
For up to date information, including OS versions, refer to `the git actions
|
||||
page`_.
|
||||
|
||||
.. _the git actions page: https://github.com/YosysHQ/yosys/actions
|
||||
|
||||
.. todo:: are unit tests currently working
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
--- fstapi.cc
|
||||
+++ fstapi.cc
|
||||
@@ -4723,7 +4723,10 @@ if(gzread_pass_status)
|
||||
hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0);
|
||||
|
||||
fstFread(&dcheck, 8, 1, xc->f);
|
||||
- xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST);
|
||||
+ /*
|
||||
+ * Yosys patch: Fix double endian check for i386 targets built in modern gcc
|
||||
+ */
|
||||
+ xc->double_endian_match = (dcheck == (double)FST_DOUBLE_ENDTEST);
|
||||
if(!xc->double_endian_match)
|
||||
{
|
||||
union {
|
||||
|
|
@ -19,3 +19,4 @@ patch -p0 < 00_PATCH_win_zlib.patch
|
|||
patch -p0 < 00_PATCH_win_io.patch
|
||||
patch -p1 < 00_PATCH_strict_alignment.patch
|
||||
patch -p0 < 00_PATCH_wx_len_overread.patch
|
||||
patch -p0 < 00_PATCH_i386_endian.patch
|
||||
|
|
|
|||
|
|
@ -4723,7 +4723,10 @@ if(gzread_pass_status)
|
|||
hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0);
|
||||
|
||||
fstFread(&dcheck, 8, 1, xc->f);
|
||||
xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST);
|
||||
/*
|
||||
* Yosys patch: Fix double endian check for i386 targets built in modern gcc
|
||||
*/
|
||||
xc->double_endian_match = (dcheck == (double)FST_DOUBLE_ENDTEST);
|
||||
if(!xc->double_endian_match)
|
||||
{
|
||||
union {
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ struct Slice {
|
|||
}
|
||||
|
||||
static int parse_index(const char *begin, const char *end, const std::string &slice) {
|
||||
int value;
|
||||
int value = 0;
|
||||
auto result = std::from_chars(begin, end, value, 10);
|
||||
if (result.ptr != end || result.ptr == begin)
|
||||
if (result.ptr != end || result.ptr == begin)
|
||||
syntax_error(slice);
|
||||
return value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
|
@ -42,6 +44,22 @@ struct OptMergeWorker
|
|||
CellTypes ct;
|
||||
int total_count;
|
||||
|
||||
static vector<pair<SigBit, SigSpec>> sorted_pmux_in(const dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
|
||||
{
|
||||
SigSpec sig_s = conn.at(ID::S);
|
||||
SigSpec sig_b = conn.at(ID::B);
|
||||
|
||||
int s_width = GetSize(sig_s);
|
||||
int width = GetSize(sig_b) / s_width;
|
||||
|
||||
vector<pair<SigBit, SigSpec>> sb_pairs;
|
||||
for (int i = 0; i < s_width; i++)
|
||||
sb_pairs.push_back(pair<SigBit, SigSpec>(sig_s[i], sig_b.extract(i*width, width)));
|
||||
|
||||
std::sort(sb_pairs.begin(), sb_pairs.end());
|
||||
return sb_pairs;
|
||||
}
|
||||
|
||||
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
|
||||
{
|
||||
SigSpec sig_s = conn.at(ID::S);
|
||||
|
|
@ -65,95 +83,78 @@ struct OptMergeWorker
|
|||
}
|
||||
}
|
||||
|
||||
std::string int_to_hash_string(unsigned int v)
|
||||
Hasher hash_cell_inputs(const RTLIL::Cell *cell, Hasher h) const
|
||||
{
|
||||
if (v == 0)
|
||||
return "0";
|
||||
std::string str = "";
|
||||
while (v > 0) {
|
||||
str += 'a' + (v & 15);
|
||||
v = v >> 4;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
uint64_t hash_cell_parameters_and_connections(const RTLIL::Cell *cell)
|
||||
{
|
||||
vector<string> hash_conn_strings;
|
||||
std::string hash_string = cell->type.str() + "\n";
|
||||
|
||||
const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections();
|
||||
dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
|
||||
|
||||
// TODO: when implemented, use celltypes to match:
|
||||
// (builtin || stdcell) && (unary || binary) && symmetrical
|
||||
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
|
||||
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
|
||||
alt_conn = *conn;
|
||||
if (assign_map(alt_conn.at(ID::A)) < assign_map(alt_conn.at(ID::B))) {
|
||||
alt_conn[ID::A] = conn->at(ID::B);
|
||||
alt_conn[ID::B] = conn->at(ID::A);
|
||||
std::array<RTLIL::SigSpec, 2> inputs = {
|
||||
assign_map(cell->getPort(ID::A)),
|
||||
assign_map(cell->getPort(ID::B))
|
||||
};
|
||||
std::sort(inputs.begin(), inputs.end());
|
||||
h = hash_ops<std::array<RTLIL::SigSpec, 2>>::hash_into(inputs, h);
|
||||
} else if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
|
||||
SigSpec a = assign_map(cell->getPort(ID::A));
|
||||
a.sort();
|
||||
h = a.hash_into(h);
|
||||
} else if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
|
||||
SigSpec a = assign_map(cell->getPort(ID::A));
|
||||
a.sort_and_unify();
|
||||
h = a.hash_into(h);
|
||||
} else if (cell->type == ID($pmux)) {
|
||||
dict<RTLIL::IdString, RTLIL::SigSpec> conn = cell->connections();
|
||||
assign_map.apply(conn.at(ID::A));
|
||||
assign_map.apply(conn.at(ID::B));
|
||||
assign_map.apply(conn.at(ID::S));
|
||||
for (const auto& [s_bit, b_chunk] : sorted_pmux_in(conn)) {
|
||||
h = s_bit.hash_into(h);
|
||||
h = b_chunk.hash_into(h);
|
||||
}
|
||||
conn = &alt_conn;
|
||||
} else
|
||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
|
||||
alt_conn = *conn;
|
||||
assign_map.apply(alt_conn.at(ID::A));
|
||||
alt_conn.at(ID::A).sort();
|
||||
conn = &alt_conn;
|
||||
} else
|
||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
|
||||
alt_conn = *conn;
|
||||
assign_map.apply(alt_conn.at(ID::A));
|
||||
alt_conn.at(ID::A).sort_and_unify();
|
||||
conn = &alt_conn;
|
||||
} else
|
||||
if (cell->type == ID($pmux)) {
|
||||
alt_conn = *conn;
|
||||
assign_map.apply(alt_conn.at(ID::A));
|
||||
assign_map.apply(alt_conn.at(ID::B));
|
||||
assign_map.apply(alt_conn.at(ID::S));
|
||||
sort_pmux_conn(alt_conn);
|
||||
conn = &alt_conn;
|
||||
}
|
||||
|
||||
for (auto &it : *conn) {
|
||||
RTLIL::SigSpec sig;
|
||||
if (cell->output(it.first)) {
|
||||
if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell->type)) {
|
||||
// For the 'Q' output of state elements,
|
||||
// use its (* init *) attribute value
|
||||
sig = initvals(it.second);
|
||||
h = assign_map(cell->getPort(ID::A)).hash_into(h);
|
||||
} else {
|
||||
std::vector<std::pair<IdString, SigSpec>> conns;
|
||||
for (const auto& conn : cell->connections()) {
|
||||
conns.push_back(conn);
|
||||
}
|
||||
std::sort(conns.begin(), conns.end());
|
||||
for (const auto& [port, sig] : conns) {
|
||||
if (!cell->output(port)) {
|
||||
h = port.hash_into(h);
|
||||
h = assign_map(sig).hash_into(h);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
sig = assign_map(it.second);
|
||||
string s = "C " + it.first.str() + "=";
|
||||
for (auto &chunk : sig.chunks()) {
|
||||
if (chunk.wire)
|
||||
s += "{" + chunk.wire->name.str() + " " +
|
||||
int_to_hash_string(chunk.offset) + " " +
|
||||
int_to_hash_string(chunk.width) + "}";
|
||||
else
|
||||
s += RTLIL::Const(chunk.data).as_string();
|
||||
}
|
||||
hash_conn_strings.push_back(s + "\n");
|
||||
|
||||
if (RTLIL::builtin_ff_cell_types().count(cell->type))
|
||||
h = initvals(cell->getPort(ID::Q)).hash_into(h);
|
||||
|
||||
}
|
||||
|
||||
for (auto &it : cell->parameters)
|
||||
hash_conn_strings.push_back("P " + it.first.str() + "=" + it.second.as_string() + "\n");
|
||||
|
||||
std::sort(hash_conn_strings.begin(), hash_conn_strings.end());
|
||||
|
||||
for (auto it : hash_conn_strings)
|
||||
hash_string += it;
|
||||
|
||||
return std::hash<std::string>{}(hash_string);
|
||||
return h;
|
||||
}
|
||||
|
||||
bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2)
|
||||
static Hasher hash_cell_parameters(const RTLIL::Cell *cell, Hasher h)
|
||||
{
|
||||
log_assert(cell1 != cell2);
|
||||
using Paramvec = std::vector<std::pair<IdString, Const>>;
|
||||
Paramvec params;
|
||||
for (const auto& param : cell->parameters) {
|
||||
params.push_back(param);
|
||||
}
|
||||
std::sort(params.begin(), params.end());
|
||||
return hash_ops<Paramvec>::hash_into(params, h);
|
||||
}
|
||||
|
||||
Hasher hash_cell_function(const RTLIL::Cell *cell, Hasher h) const
|
||||
{
|
||||
h.eat(cell->type);
|
||||
h = hash_cell_inputs(cell, h);
|
||||
h = hash_cell_parameters(cell, h);
|
||||
return h;
|
||||
}
|
||||
|
||||
bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) const
|
||||
{
|
||||
if (cell1 == cell2) return true;
|
||||
if (cell1->type != cell2->type) return false;
|
||||
|
||||
if (cell1->parameters != cell2->parameters)
|
||||
|
|
@ -252,21 +253,51 @@ struct OptMergeWorker
|
|||
initvals.set(&assign_map, module);
|
||||
|
||||
bool did_something = true;
|
||||
// A cell may have to go through a lot of collisions if the hash
|
||||
// function is performing poorly, but it's a symptom of something bad
|
||||
// beyond the user's control.
|
||||
while (did_something)
|
||||
{
|
||||
std::vector<RTLIL::Cell*> cells;
|
||||
cells.reserve(module->cells_.size());
|
||||
for (auto &it : module->cells_) {
|
||||
if (!design->selected(module, it.second))
|
||||
cells.reserve(module->cells().size());
|
||||
for (auto cell : module->cells()) {
|
||||
if (!design->selected(module, cell))
|
||||
continue;
|
||||
if (mode_keepdc && has_dont_care_initval(it.second))
|
||||
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 (ct.cell_known(it.second->type) || (mode_share_all && it.second->known()))
|
||||
cells.push_back(it.second);
|
||||
}
|
||||
if (mode_keepdc && has_dont_care_initval(cell))
|
||||
continue;
|
||||
if (ct.cell_known(cell->type) || (mode_share_all && cell->known()))
|
||||
cells.push_back(cell);
|
||||
}
|
||||
|
||||
did_something = false;
|
||||
dict<uint64_t, RTLIL::Cell*> sharemap;
|
||||
|
||||
// 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)
|
||||
{
|
||||
if ((!mode_share_all && !ct.cell_known(cell->type)) || !cell->known())
|
||||
|
|
@ -275,40 +306,36 @@ struct OptMergeWorker
|
|||
if (cell->type == ID($scopeinfo))
|
||||
continue;
|
||||
|
||||
uint64_t hash = hash_cell_parameters_and_connections(cell);
|
||||
auto r = sharemap.insert(std::make_pair(hash, cell));
|
||||
if (!r.second) {
|
||||
if (compare_cell_parameters_and_connections(cell, r.first->second)) {
|
||||
// SILIMATE: Keep the shorter name always
|
||||
if (cell->name.str() < r.first->second->name.str())
|
||||
std::swap(r.first->second, cell);
|
||||
|
||||
if (cell->has_keep_attr()) {
|
||||
if (r.first->second->has_keep_attr())
|
||||
continue;
|
||||
std::swap(r.first->second, cell);
|
||||
}
|
||||
|
||||
|
||||
did_something = true;
|
||||
log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), r.first->second->name.c_str());
|
||||
for (auto &it : cell->connections()) {
|
||||
if (cell->output(it.first)) {
|
||||
RTLIL::SigSpec other_sig = r.first->second->getPort(it.first);
|
||||
log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
|
||||
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.c_str(), cell->name.c_str(), module->name.c_str());
|
||||
module->remove(cell);
|
||||
total_count++;
|
||||
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.c_str(), other_cell->name.c_str());
|
||||
for (auto &it : cell->connections()) {
|
||||
if (cell->output(it.first)) {
|
||||
RTLIL::SigSpec other_sig = other_cell->getPort(it.first);
|
||||
log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
|
||||
log_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.c_str(), cell->name.c_str(), module->name.c_str());
|
||||
module->remove(cell);
|
||||
total_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ struct CutpointPass : public Pass {
|
|||
log("This command adds formal cut points to the design.\n");
|
||||
log("\n");
|
||||
log(" -undef\n");
|
||||
log(" set cupoint nets to undef (x). the default behavior is to create a\n");
|
||||
log(" $anyseq cell and drive the cutpoint net from that\n");
|
||||
log(" set cutpoint nets to undef (x). the default behavior is to create\n");
|
||||
log(" an $anyseq cell and drive the cutpoint net from that\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
|
|
|
|||
|
|
@ -2224,10 +2224,10 @@ module \$print (EN, TRG, ARGS);
|
|||
parameter PRIORITY = 0;
|
||||
|
||||
parameter FORMAT = "";
|
||||
parameter ARGS_WIDTH = 0;
|
||||
parameter signed ARGS_WIDTH = 0;
|
||||
|
||||
parameter TRG_ENABLE = 1;
|
||||
parameter TRG_WIDTH = 0;
|
||||
parameter signed TRG_WIDTH = 0;
|
||||
parameter TRG_POLARITY = 0;
|
||||
|
||||
input EN;
|
||||
|
|
|
|||
|
|
@ -241,7 +241,10 @@ struct CtlzTest
|
|||
{
|
||||
if (a == 0)
|
||||
return bits;
|
||||
return __builtin_clzl(a) - (64 - bits);
|
||||
if (sizeof(long) == 4)
|
||||
return __builtin_clzll(a) - (64 - bits);
|
||||
else
|
||||
return __builtin_clzl(a) - (64 - bits);
|
||||
}
|
||||
|
||||
template<size_t Bits>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,166 @@
|
|||
read_verilog <<EOT
|
||||
module top(A, B, X, Y);
|
||||
input [7:0] A, B;
|
||||
output [7:0] X, Y;
|
||||
assign X = A + B;
|
||||
assign Y = A + B;
|
||||
endmodule
|
||||
EOT
|
||||
# Most basic case
|
||||
# Binary
|
||||
select -assert-count 2 t:$add
|
||||
equiv_opt -assert opt_merge
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$add
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(A, B, C, X, Y);
|
||||
input [7:0] A, B, C;
|
||||
output [7:0] X, Y;
|
||||
assign X = A + B;
|
||||
assign Y = A + C; // <- look here
|
||||
endmodule
|
||||
EOT
|
||||
# Reject on a different input
|
||||
select -assert-count 2 t:$add
|
||||
opt_merge
|
||||
select -assert-count 2 t:$add
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(A, X, Y);
|
||||
input [7:0] A;
|
||||
output X, Y;
|
||||
assign X = ^A;
|
||||
assign Y = ^A;
|
||||
endmodule
|
||||
EOT
|
||||
# Unary
|
||||
select -assert-count 2 t:$reduce_xor
|
||||
dump
|
||||
opt_merge
|
||||
select -assert-count 1 t:$reduce_xor
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOT
|
||||
module top(A, B, X, Y);
|
||||
input [7:0] A, B;
|
||||
output X, Y;
|
||||
\$reduce_xor #(
|
||||
.A_SIGNED(32'd0),
|
||||
.A_WIDTH(32'd16),
|
||||
.Y_WIDTH(32'd1),
|
||||
) one (
|
||||
.A({A, B}), // <- look here
|
||||
.Y(X)
|
||||
);
|
||||
\$reduce_xor #(
|
||||
.A_SIGNED(32'd0),
|
||||
.A_WIDTH(32'd16),
|
||||
.Y_WIDTH(32'd1),
|
||||
) other (
|
||||
.A({B, A}), // <- look here
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
EOT
|
||||
# Unary is sorted
|
||||
opt_expr
|
||||
select -assert-count 2 t:$reduce_xor
|
||||
equiv_opt -assert opt_merge
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$reduce_xor
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOT
|
||||
module top(A, B, X, Y);
|
||||
input [7:0] A, B;
|
||||
output X, Y;
|
||||
\$reduce_or #(
|
||||
.A_SIGNED(32'd0),
|
||||
.A_WIDTH(32'd24),
|
||||
.Y_WIDTH(32'd1),
|
||||
) one (
|
||||
.A({A, B, B}), // <- look here
|
||||
.Y(X)
|
||||
);
|
||||
\$reduce_or #(
|
||||
.A_SIGNED(32'd0),
|
||||
.A_WIDTH(32'd24),
|
||||
.Y_WIDTH(32'd1),
|
||||
) other (
|
||||
.A({A, A, B}), // <- look here
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
EOT
|
||||
# Unary is unified when valid
|
||||
opt_expr
|
||||
select -assert-count 2 t:$reduce_or
|
||||
equiv_opt -assert opt_merge
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$reduce_or
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOT
|
||||
module top(A, B, X, Y);
|
||||
input [7:0] A, B;
|
||||
output X, Y;
|
||||
\$reduce_xor #(
|
||||
.A_SIGNED(32'd0),
|
||||
.A_WIDTH(32'd24),
|
||||
.Y_WIDTH(32'd1),
|
||||
) one (
|
||||
.A({A, B, B}), // <- look here
|
||||
.Y(X)
|
||||
);
|
||||
\$reduce_xor #(
|
||||
.A_SIGNED(32'd0),
|
||||
.A_WIDTH(32'd24),
|
||||
.Y_WIDTH(32'd1),
|
||||
) other (
|
||||
.A({A, A, B}), // <- look here
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
EOT
|
||||
# Unary isn't unified when that would be invalid
|
||||
opt_expr
|
||||
select -assert-count 2 t:$reduce_xor
|
||||
equiv_opt -assert opt_merge
|
||||
design -load postopt
|
||||
select -assert-count 2 t:$reduce_xor
|
||||
|
||||
# TODO pmux
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(A, B, X, Y);
|
||||
input [7:0] A, B;
|
||||
output X, Y;
|
||||
assign X = A > B;
|
||||
assign Y = A > B;
|
||||
endmodule
|
||||
EOT
|
||||
# Exercise the general case in hash_cell_inputs - accept
|
||||
opt_expr
|
||||
select -assert-count 2 t:$gt
|
||||
equiv_opt -assert opt_merge
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$gt
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(A, B, C, X, Y);
|
||||
input [7:0] A, B, C;
|
||||
output X, Y;
|
||||
assign X = A > B;
|
||||
assign Y = A > C; // <- look here
|
||||
endmodule
|
||||
EOT
|
||||
# Exercise the general case in hash_cell_inputs - reject
|
||||
opt_expr
|
||||
select -assert-count 2 t:$gt
|
||||
opt_merge
|
||||
select -assert-count 2 t:$gt
|
||||
Loading…
Reference in New Issue