3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-05-12 18:24:44 +00:00

Merge commit

This commit is contained in:
akash 2024-03-29 19:30:48 -07:00
parent 632a70454c
commit 19dbde2891
27 changed files with 390 additions and 73 deletions

View file

@ -43,7 +43,7 @@ body:
attributes:
value: >
When providing steps to reproduce the issue, please ensure that the issue
is reproducible in the current git master of Yosys. Also ensure to
is reproducible in the current git main of Yosys. Also ensure to
provide all necessary source files needed.

View file

@ -3,7 +3,7 @@ name: Build and test doc code samples
on:
pull_request:
branches:
- master
- main
jobs:
test-docs:

View file

@ -1,4 +1,4 @@
# CONFIG := none
# CONFIG := clang
CONFIG := gcc
# CONFIG := afl-gcc
@ -141,7 +141,7 @@ LIBS += -lrt
endif
endif
YOSYS_VER := 0.39+124
YOSYS_VER := 0.39+147
# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
@ -217,7 +217,7 @@ endif
ifeq ($(CONFIG),clang)
CXX = clang++
CXXFLAGS += -std=$(CXXSTD) -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -Wno-c++11-narrowing $(ABC_ARCHFLAGS)"
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H $(ABC_ARCHFLAGS)"
ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
@ -265,7 +265,7 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),emcc)
CXX = emcc
CXXFLAGS := -std=$(CXXSTD) $(filter-out -fPIC -ggdb,$(CXXFLAGS))
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8 -Wno-c++11-narrowing"
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8"
EMCC_CXXFLAGS := -Os -Wno-warn-absolute-paths
EMCC_LINKFLAGS := --embed-file share
EMCC_LINKFLAGS += -s NO_EXIT_RUNTIME=1
@ -317,7 +317,7 @@ CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) -Os -D_WASI_EMULATED_PROCESS_CLOCKS $(fi
LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS))
LIBS := -lwasi-emulated-process-clocks $(filter-out -lrt,$(LIBS))
ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)"
ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -D_WASI_EMULATED_PROCESS_CLOCKS -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING -DABC_NO_RLIMIT -Wno-c++11-narrowing"
ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -D_WASI_EMULATED_PROCESS_CLOCKS -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING -DABC_NO_RLIMIT"
ABCMKARGS += OPTFLAGS="-Os"
EXE = .wasm
@ -360,8 +360,12 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC
ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
EXE = .exe
else ifneq ($(CONFIG),none)
$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, emcc, mxe, msys2-32, msys2-64)
else ifeq ($(CONFIG),none)
CXXFLAGS += -std=$(CXXSTD) -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H $(ABC_ARCHFLAGS)"
else
$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, emcc, mxe, msys2-32, msys2-64, none)
endif
ifeq ($(ENABLE_LIBYOSYS),1)
@ -1127,6 +1131,9 @@ echo-git-rev:
echo-abc-rev:
@echo "$(ABCREV)"
echo-cxx:
@echo "$(CXX)"
-include libs/*/*.d
-include frontends/*/*.d
-include passes/*/*.d

View file

@ -105,11 +105,17 @@ For Cygwin use the following command to install all prerequisites, or select the
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
To configure the build system to use a specific compiler, use one of
The environment variable `CXX` can be used to control the C++ compiler used, or
run one of the following:
$ make config-clang
$ make config-gcc
Note that these will result in `make` ignoring the `CXX` environment variable,
unless `CXX` is assigned in the call to make, e.g.
$ make CXX=$CXX
For other compilers and build configurations it might be
necessary to make some changes to the config section of the
Makefile.

View file

@ -124,7 +124,7 @@ struct JnyWriter
design->sort();
f << "{\n";
f << " \"$schema\": \"https://raw.githubusercontent.com/YosysHQ/yosys/master/misc/jny.schema.json\",\n";
f << " \"$schema\": \"https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json\",\n";
f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_version_str).c_str());
f << " \"version\": \"0.0.1\",\n";
f << " \"invocation\": \"" << escape_string(invk) << "\",\n";
@ -426,7 +426,7 @@ struct JnyBackend : public Backend {
log(" Don't include property information in the netlist output.\n");
log("\n");
log("The JSON schema for JNY output files is located in the \"jny.schema.json\" file\n");
log("which is located at \"https://raw.githubusercontent.com/YosysHQ/yosys/master/misc/jny.schema.json\"\n");
log("which is located at \"https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json\"\n");
log("\n");
}

View file

@ -633,9 +633,9 @@ with the mapping to ``SB_RAM40_4K`` done by :cmd:ref:`techmap` using
into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`.
.. |techlibs/ice40/brams.txt| replace:: :file:`techlibs/ice40/brams.txt`
.. _techlibs/ice40/brams.txt: https://github.com/YosysHQ/yosys/tree/master/techlibs/ice40/brams.txt
.. _techlibs/ice40/brams.txt: https://github.com/YosysHQ/yosys/tree/main/techlibs/ice40/brams.txt
.. |techlibs/ice40/brams_map.v| replace:: :file:`techlibs/ice40/brams_map.v`
.. _techlibs/ice40/brams_map.v: https://github.com/YosysHQ/yosys/tree/master/techlibs/ice40/brams_map.v
.. _techlibs/ice40/brams_map.v: https://github.com/YosysHQ/yosys/tree/main/techlibs/ice40/brams_map.v
.. literalinclude:: /cmd/synth_ice40.rst
:language: yoscrypt

View file

@ -16,8 +16,8 @@ Automatic testing
.. _Yosys Git repo: https://github.com/YosysHQ/yosys
.. |test-linux| image:: https://github.com/YosysHQ/yosys/actions/workflows/test-linux.yml/badge.svg?branch=master
.. |test-macos| image:: https://github.com/YosysHQ/yosys/actions/workflows/test-macos.yml/badge.svg?branch=master
.. |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`_.

View file

@ -18,7 +18,7 @@ in the circuit diagrams generated by it. The code used is included in the Yosys
code base under |code_examples/show|_.
.. |code_examples/show| replace:: :file:`docs/source/code_examples/show`
.. _code_examples/show: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/show
.. _code_examples/show: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/show
A simple circuit
^^^^^^^^^^^^^^^^
@ -337,7 +337,7 @@ The code used is included in the Yosys code base under
|code_examples/scrambler|_.
.. |code_examples/scrambler| replace:: :file:`docs/source/code_examples/scrambler`
.. _code_examples/scrambler: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/scrambler
.. _code_examples/scrambler: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/scrambler
Changing design hierarchy
^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -29,7 +29,7 @@ Let's take a look at an example included in the Yosys code base under
|code_examples/synth_flow|_:
.. |code_examples/synth_flow| replace:: :file:`docs/source/code_examples/synth_flow`
.. _code_examples/synth_flow: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/synth_flow
.. _code_examples/synth_flow: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/synth_flow
.. literalinclude:: /code_examples/synth_flow/techmap_01_map.v
:language: verilog
@ -81,7 +81,7 @@ The code used in this section is included in the Yosys code base under
|code_examples/axis|_.
.. |code_examples/axis| replace:: :file:`docs/source/code_examples/axis`
.. _code_examples/axis: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/axis
.. _code_examples/axis: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/axis
The following AXI4 Stream Master has a bug. But the bug is not exposed if the
slave keeps ``tready`` asserted all the time. (Something a test bench might do.)

View file

@ -405,7 +405,7 @@ those cases selection variables must be used to capture more complex selections.
Example code from |code_examples/selections|_:
.. |code_examples/selections| replace:: :file:`docs/source/code_examples/selections`
.. _code_examples/selections: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/selections
.. _code_examples/selections: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/selections
.. literalinclude:: /code_examples/selections/select.v
:language: verilog

View file

@ -21,7 +21,7 @@ detail in the :doc:`/getting_started/example_synth` document.
To learn more about these commands, check out :ref:`interactive_show`.
.. _example project: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/intro
.. _example project: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/intro
A simple counter
~~~~~~~~~~~~~~~~

View file

@ -15,7 +15,7 @@ The extract pass
Example code can be found in |code_examples/macc|_.
.. |code_examples/macc| replace:: :file:`docs/source/code_examples/macc`
.. _code_examples/macc: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/macc
.. _code_examples/macc: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/macc
.. literalinclude:: /code_examples/macc/macc_simple_test.ys

View file

@ -36,7 +36,7 @@ Example
|code_examples/synth_flow|_.
.. |code_examples/synth_flow| replace:: :file:`docs/source/code_examples/synth_flow`
.. _code_examples/synth_flow: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/synth_flow
.. _code_examples/synth_flow: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/synth_flow
.. figure:: /_images/code_examples/synth_flow/memory_01.*
:class: width-helper
@ -92,7 +92,7 @@ leftover memory cells unable to be converted are then picked up by
For more on the lib format for :cmd:ref:`memory_libmap`, see
`passes/memory/memlib.md
<https://github.com/YosysHQ/yosys/blob/master/passes/memory/memlib.md>`_
<https://github.com/YosysHQ/yosys/blob/main/passes/memory/memlib.md>`_
Supported memory patterns
^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -31,7 +31,7 @@ Example
|code_examples/synth_flow|_.
.. |code_examples/synth_flow| replace:: :file:`docs/source/code_examples/synth_flow`
.. _code_examples/synth_flow: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/synth_flow
.. _code_examples/synth_flow: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/synth_flow
.. literalinclude:: /code_examples/synth_flow/proc_01.v
:language: verilog

View file

@ -24,7 +24,7 @@ Code examples from this section are included in the
|code_examples/extensions|_ directory of the Yosys source code.
.. |code_examples/extensions| replace:: :file:`docs/source/code_examples/extensions`
.. _code_examples/extensions: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/extensions
.. _code_examples/extensions: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/extensions
Program components and data formats
@ -254,7 +254,7 @@ The following is the complete code of the "stubnets" example module. It is
included in the Yosys source distribution under |code_examples/stubnets|_.
.. |code_examples/stubnets| replace:: :file:`docs/source/code_examples/stubnets`
.. _code_examples/stubnets: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/stubnets
.. _code_examples/stubnets: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/stubnets
.. literalinclude:: /code_examples/stubnets/stubnets.cc
:language: c++

View file

@ -16,7 +16,7 @@ Code examples used in this document are included in the Yosys code base under
|code_examples/techmap|_.
.. |code_examples/techmap| replace:: :file:`docs/source/code_examples/techmap`
.. _code_examples/techmap: https://github.com/YosysHQ/yosys/tree/master/docs/source/code_examples/techmap
.. _code_examples/techmap: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/techmap
Mapping OR3X1

View file

@ -44,7 +44,7 @@ Visual Studio builds are not directly supported by build scripts, but they are s
1. Easy way
- Go to https://github.com/YosysHQ/yosys/actions/workflows/vs.yml?query=branch%3Amaster
- Go to https://github.com/YosysHQ/yosys/actions/workflows/vs.yml?query=branch%3Amain
- Click on the most recent completed run
- In Artifacts region find vcxsrc and click on it to download
- Unpack downloaded ZIP file

View file

@ -307,6 +307,87 @@ void shift_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
}
}
void packed_mem_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
log_assert(cell->type == ID($mem_v2));
Const rd_clk_enable = cell->getParam(ID::RD_CLK_ENABLE);
int n_rd_ports = cell->getParam(ID::RD_PORTS).as_int();
int abits = cell->getParam(ID::ABITS).as_int();
int width = cell->getParam(ID::WIDTH).as_int();
for (int i = 0; i < n_rd_ports; i++) {
if (rd_clk_enable[i] != State::S0) {
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::RD_ARST, i, ID::RD_DATA, i * width + k, -1);
continue;
}
for (int j = 0; j < abits; j++)
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::RD_ADDR, i * abits + j,
ID::RD_DATA, i * width + k, -1);
}
}
void memrd_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
log_assert(cell->type.in(ID($memrd), ID($memrd_v2)));
int abits = cell->getParam(ID::ABITS).as_int();
int width = cell->getParam(ID::WIDTH).as_int();
if (cell->getParam(ID::CLK_ENABLE).as_bool()) {
if (cell->type == ID($memrd_v2)) {
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::ARST, 0, ID::DATA, k, -1);
}
return;
}
for (int j = 0; j < abits; j++)
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::ADDR, j, ID::DATA, k, -1);
}
void mem_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
if (cell->type == ID($mem_v2))
packed_mem_op(db, cell);
else if (cell->type.in(ID($memrd), ID($memrd_v2)))
memrd_op(db, cell);
else if (cell->type.in(ID($memwr), ID($memwr_v2), ID($meminit)))
return; /* no edges here */
else
log_abort();
}
void ff_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
int width = cell->getPort(ID::Q).size();
if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
for (int k = 0; k < width; k++) {
db->add_edge(cell, ID::D, k, ID::Q, k, -1);
db->add_edge(cell, ID::EN, 0, ID::Q, k, -1);
}
}
if (cell->hasPort(ID::CLR))
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::CLR, 0, ID::Q, k, -1);
if (cell->hasPort(ID::SET))
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::SET, 0, ID::Q, k, -1);
if (cell->hasPort(ID::ALOAD))
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::ALOAD, 0, ID::Q, k, -1);
if (cell->hasPort(ID::AD))
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::AD, k, ID::Q, k, -1);
if (cell->hasPort(ID::ARST))
for (int k = 0; k < width; k++)
db->add_edge(cell, ID::ARST, 0, ID::Q, k, -1);
}
PRIVATE_NAMESPACE_END
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
@ -361,6 +442,18 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
return true;
}
if (cell->type.in(ID($mem_v2), ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2), ID($meminit))) {
mem_op(this, cell);
return true;
}
if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
ff_op(this, cell);
return true;
}
// FIXME: $mul $div $mod $divfloor $modfloor $slice $concat
// FIXME: $lut $sop $alu $lcu $macc $fa
// FIXME: $mul $div $mod $divfloor $modfloor $pow $slice $concat $bweqx
// FIXME: $lut $sop $alu $lcu $macc $fa $logic_and $logic_or $bwmux

View file

@ -149,7 +149,7 @@ template <typename T, typename C = std::less<T>, typename OPS = hash_ops<T>> cla
std::map<T, int, C> node_to_index;
std::vector<std::set<int, IndirectCmp>> edges;
std::vector<T> sorted;
std::set<std::set<T, C>> loops;
std::set<std::vector<T>> loops;
TopoSort() : indirect_cmp(nodes)
{
@ -220,10 +220,10 @@ template <typename T, typename C = std::less<T>, typename OPS = hash_ops<T>> cla
if (active_cells[root_index]) {
found_loops = true;
if (analyze_loops) {
std::set<T, C> loop;
std::vector<T> loop;
for (int i = GetSize(active_stack) - 1; i >= 0; i--) {
const int index = active_stack[i];
loop.insert(nodes[index]);
loop.push_back(nodes[index]);
if (index == root_index)
break;
}

View file

@ -46,7 +46,7 @@ Open "Git Bash" in this directory and run:
mv yosys yosys.bak
git clone https://github.com/YosysHQ/yosys.git yosys
cd yosys
git checkout -B master $(git rev-parse HEAD | cut -c1-10)
git checkout -B main $(git rev-parse HEAD | cut -c1-10)
unzip ../genfiles.zip
EOT

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/YosysHQ/yosys/master/misc/jny.schema.json",
"$id": "https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json",
"title": "Yosys JSON Netlist metadata",
"description": "Yosys JSON Netlist",
"type": "object",

View file

@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/celledges.h"
#include "kernel/celltypes.h"
#include "kernel/utils.h"
@ -102,10 +103,10 @@ struct CheckPass : public Pass {
SigMap sigmap(module);
dict<SigBit, vector<string>> wire_drivers;
dict<SigBit, Cell *> driver_cells;
dict<SigBit, int> wire_drivers_count;
pool<SigBit> used_wires;
TopoSort<string> topo;
TopoSort<std::pair<RTLIL::IdString, int>> topo;
for (auto &proc_it : module->processes)
{
std::vector<RTLIL::CaseRule*> all_cases = {&proc_it.second->root_case};
@ -150,6 +151,50 @@ struct CheckPass : public Pass {
}
}
struct CircuitEdgesDatabase : AbstractCellEdgesDatabase {
TopoSort<std::pair<RTLIL::IdString, int>> &topo;
SigMap sigmap;
CircuitEdgesDatabase(TopoSort<std::pair<RTLIL::IdString, int>> &topo, SigMap &sigmap)
: topo(topo), sigmap(sigmap) {}
void add_edge(RTLIL::Cell *cell, RTLIL::IdString from_port, int from_bit,
RTLIL::IdString to_port, int to_bit, int) override {
SigSpec from_portsig = cell->getPort(from_port);
SigSpec to_portsig = cell->getPort(to_port);
log_assert(from_bit >= 0 && from_bit < from_portsig.size());
log_assert(to_bit >= 0 && to_bit < to_portsig.size());
SigBit from = sigmap(from_portsig[from_bit]);
SigBit to = sigmap(to_portsig[to_bit]);
if (from.wire && to.wire)
topo.edge(std::make_pair(from.wire->name, from.offset), std::make_pair(to.wire->name, to.offset));
}
bool add_edges_from_cell(Cell *cell) {
if (AbstractCellEdgesDatabase::add_edges_from_cell(cell))
return true;
// We don't have accurate cell edges, do the fallback of all input-output pairs
for (auto &conn : cell->connections()) {
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
if (bit.wire)
topo.edge(std::make_pair(bit.wire->name, bit.offset),
std::make_pair(cell->name, -1));
if (cell->output(conn.first))
for (auto bit : sigmap(conn.second))
if (bit.wire)
topo.edge(std::make_pair(cell->name, -1),
std::make_pair(bit.wire->name, bit.offset));
}
return true;
}
};
CircuitEdgesDatabase edges_db(topo, sigmap);
for (auto cell : module->cells())
{
if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) {
@ -158,31 +203,30 @@ struct CheckPass : public Pass {
counter++;
cell_allowed:;
}
for (auto &conn : cell->connections()) {
SigSpec sig = sigmap(conn.second);
bool logic_cell = yosys_celltypes.cell_evaluable(cell->type);
if (cell->input(conn.first))
for (auto bit : sig)
if (bit.wire) {
if (logic_cell)
topo.edge(stringf("wire %s", log_signal(bit)),
stringf("cell %s (%s)", log_id(cell), log_id(cell->type)));
used_wires.insert(bit);
}
if (cell->output(conn.first))
for (int i = 0; i < GetSize(sig); i++) {
if (logic_cell)
topo.edge(stringf("cell %s (%s)", log_id(cell), log_id(cell->type)),
stringf("wire %s", log_signal(sig[i])));
if (sig[i].wire || !cell->input(conn.first))
wire_drivers[sig[i]].push_back(stringf("port %s[%d] of cell %s (%s)",
log_id(conn.first), i, log_id(cell), log_id(cell->type)));
}
if (!cell->input(conn.first) && cell->output(conn.first))
for (auto bit : sig)
if (bit.wire) wire_drivers_count[bit]++;
for (auto &conn : cell->connections()) {
bool input = cell->input(conn.first);
bool output = cell->output(conn.first);
SigSpec sig = sigmap(conn.second);
for (int i = 0; i < sig.size(); i++) {
SigBit bit = sig[i];
if (input && bit.wire)
used_wires.insert(bit);
if (output && !input && bit.wire)
wire_drivers_count[bit]++;
if (output && (bit.wire || !input))
wire_drivers[bit].push_back(stringf("port %s[%d] of cell %s (%s)", log_id(conn.first), i,
log_id(cell), log_id(cell->type)));
if (output)
driver_cells[bit] = cell;
}
}
if (yosys_celltypes.cell_evaluable(cell->type) || cell->type.in(ID($mem_v2), ID($memrd), ID($memrd_v2)) \
|| RTLIL::builtin_ff_cell_types().count(cell->type))
edges_db.add_edges_from_cell(cell);
}
pool<SigBit> init_bits;
@ -239,8 +283,72 @@ struct CheckPass : public Pass {
topo.sort();
for (auto &loop : topo.loops) {
string message = stringf("found logic loop in module %s:\n", log_id(module));
for (auto &str : loop)
message += stringf(" %s\n", str.c_str());
// `loop` only contains wire bits, or an occassional special helper node for cells for
// which we have done the edges fallback. The cell and its ports that led to an edge is
// an information we need to recover now. For that we need to have the previous wire bit
// of the loop at hand.
SigBit prev;
for (auto it = loop.rbegin(); it != loop.rend(); it++)
if (it->second != -1) { // skip the fallback helper nodes
prev = SigBit(module->wire(it->first), it->second);
break;
}
log_assert(prev != SigBit());
for (auto &pair : loop) {
if (pair.second == -1)
continue; // helper node for edges fallback, we can ignore it
struct MatchingEdgePrinter : AbstractCellEdgesDatabase {
std::string &message;
SigMap &sigmap;
SigBit from, to;
int nhits;
const int HITS_LIMIT = 3;
MatchingEdgePrinter(std::string &message, SigMap &sigmap, SigBit from, SigBit to)
: message(message), sigmap(sigmap), from(from), to(to), nhits(0) {}
void add_edge(RTLIL::Cell *cell, RTLIL::IdString from_port, int from_bit,
RTLIL::IdString to_port, int to_bit, int) override {
SigBit edge_from = sigmap(cell->getPort(from_port))[from_bit];
SigBit edge_to = sigmap(cell->getPort(to_port))[to_bit];
if (edge_from == from && edge_to == to && nhits++ < HITS_LIMIT)
message += stringf(" %s[%d] --> %s[%d]\n", log_id(from_port), from_bit,
log_id(to_port), to_bit);
if (nhits == HITS_LIMIT)
message += " ...\n";
}
};
Wire *wire = module->wire(pair.first);
log_assert(wire);
SigBit bit(module->wire(pair.first), pair.second);
log_assert(driver_cells.count(bit));
Cell *driver = driver_cells.at(bit);
std::string driver_src;
if (driver->has_attribute(ID::src)) {
std::string src_attr = driver->get_src_attribute();
driver_src = stringf(" source: %s", src_attr.c_str());
}
message += stringf(" cell %s (%s)%s\n", log_id(driver), log_id(driver->type), driver_src.c_str());
MatchingEdgePrinter printer(message, sigmap, prev, bit);
printer.add_edges_from_cell(driver);
if (wire->name.isPublic()) {
std::string wire_src;
if (wire->has_attribute(ID::src)) {
std::string src_attr = wire->get_src_attribute();
wire_src = stringf(" source: %s", src_attr.c_str());
}
message += stringf(" wire %s%s\n", log_signal(SigBit(wire, pair.second)), wire_src.c_str());
}
prev = bit;
}
log_warning("%s", message.c_str());
counter++;
}

View file

@ -7,7 +7,7 @@ module top(...);
input CLK;
input EN;
(* init = 24'h555555 *)
output [19:0] Q;
output [17:0] Q;
input SRST;
input ARST;
input [1:0] CLR;
@ -23,26 +23,20 @@ $sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_V
$dffsr #(.CLK_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff7 (.CLK(CLK), .SET(SET), .CLR(CLR), .D(Q[15:14]), .Q(Q[15:14]));
$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff8 (.CLK(CLK), .EN(EN), .SET(SET), .CLR(CLR), .D(Q[17:16]), .Q(Q[17:16]));
$dlatch #(.EN_POLARITY(1'b1), .WIDTH(2)) ff9 (.EN(EN), .D(Q[19:18]), .Q(Q[19:18]));
$adlatch #(.EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff10 (.EN(EN), .ARST(ARST), .D(Q[21:20]), .Q(Q[21:20]));
$dlatchsr #(.EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff11 (.EN(EN), .SET(SET), .CLR(CLR), .D(Q[23:22]), .Q(Q[23:22]));
endmodule
EOT
design -save orig
# Equivalence check will fail for unmapped adlatch and dlatchsr due to negative hold hack.
delete top/ff10 top/ff11
equiv_opt -undef -assert -multiclock opt_dff -keepdc
design -load orig
opt_dff -keepdc
select -assert-count 1 t:$and
select -assert-count 3 t:$dffe
select -assert-count 3 t:$dlatch
select -assert-count 3 t:$sr
select -assert-count 2 t:$dlatch
select -assert-count 2 t:$sr
select -assert-none t:$and t:$dffe t:$dlatch t:$sr %% %n t:* %i
design -load orig
@ -50,7 +44,7 @@ simplemap
opt_dff -keepdc
select -assert-count 2 t:$_AND_
select -assert-count 6 t:$_DFFE_??_
select -assert-count 6 t:$_DLATCH_?_
select -assert-count 6 t:$_SR_??_
select -assert-count 4 t:$_DLATCH_?_
select -assert-count 4 t:$_SR_??_
select -assert-none t:$_AND_ t:$_DFFE_??_ t:$_DLATCH_?_ t:$_SR_??_ %% %n t:* %i

43
tests/various/check.ys Normal file
View file

@ -0,0 +1,43 @@
design -reset
read -vlog2k <<EOF
module top(input clk, input a, input b, output [9:0] x);
wire [9:0] ripple;
reg [9:0] prev_ripple = 9'b0;
always @(posedge clk) prev_ripple <= ripple;
assign ripple = {ripple[8:0], a} ^ prev_ripple; // only cyclic at the coarse-grain level
assign x = ripple[9] + b;
endmodule
EOF
hierarchy -top top
prep
check -assert
design -reset
read -vlog2k <<EOF
module top(clk, y, sideread_addr, sideread_data);
input wire clk;
reg [7:0] mem [255:0];
reg [8:0] i;
initial begin
for (i = 0; i < 256; i = i + 1)
mem[i] = i * 371;
end
output reg [7:0] y = 1;
always @(posedge clk)
y <= mem[y];
input wire [7:0] sideread_addr;
output wire [7:0] sideread_data;
assign sideread_data = mem[sideread_addr];
endmodule
EOF
hierarchy -top top
prep -rdff
select -assert-count 1 t:$mem_v2
check -assert
memory_unpack
select -assert-count 2 t:$memrd_v2
check -assert

17
tests/various/check_2.ys Normal file
View file

@ -0,0 +1,17 @@
# just so slightly adjust the example from check.ys to induce a loop
design -reset
read -vlog2k <<EOF
module top(input clk, input a, input b, output [9:0] x);
wire [9:0] ripple;
reg [9:0] prev_ripple = 9'b0;
always @(posedge clk) prev_ripple <= ripple;
assign ripple = {ripple[8:1], a, ripple[0]} ^ prev_ripple;
assign x = ripple[9] + b;
endmodule
EOF
hierarchy -top top
prep
logger -expect warning "found logic loop in module top:" 1
logger -expect error "Found 1 problems in 'check -assert'" 1
check -assert

20
tests/various/check_3.ys Normal file
View file

@ -0,0 +1,20 @@
# loop involving asynchronous memory ports
design -reset
read -vlog2k <<EOF
module pingpong(input wire [1:0] x, output wire [3:0] y1, output wire [3:0] y2);
reg [3:0] mem [15:0];
reg [5:0] i;
initial begin
for (i = 0; i < 16; i = i + 1)
mem[i] = i * 371;
end
assign y1 = mem[{y2[3:2], x}];
assign y2 = mem[y1];
endmodule
EOF
hierarchy -top pingpong
prep
logger -nowarn "found logic loop in module pingpong:"
logger -expect error "Found [0-9]+ problems in 'check -assert'" 1
check -assert

29
tests/various/check_4.ys Normal file
View file

@ -0,0 +1,29 @@
# loop involving the asynchronous reset on a memory port
design -reset
read -vlog2k <<EOF
module top(input wire clk, input wire [3:0] addr, output reg [3:0] data);
reg [3:0] mem [15:0];
reg [5:0] i;
initial begin
for (i = 0; i < 16; i = i + 1)
mem[i] = i * 371;
end
wire arst = !data[0];
always @(posedge arst, posedge clk) begin
if (arst)
data <= 4'hx;
else
data <= mem[addr];
end
endmodule
EOF
hierarchy -top top
proc
opt -keepdc
memory_dff
opt_clean
logger -nowarn "found logic loop in module pingpong:"
logger -expect error "Found [0-9]+ problems in 'check -assert'" 1
check -assert