Bump to latest

This commit is contained in:
Akash Levy 2025-03-26 14:56:10 -07:00
commit 3d13f7aae2
14 changed files with 377 additions and 172 deletions

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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
~~~~~~~~~~~~~~~~~~~~

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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;
}

View File

@ -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++;
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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>

View File

@ -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