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

Merge branch 'YosysHQ-main'

This commit is contained in:
akash 2024-03-29 19:31:02 -07:00
commit f9d235917f
27 changed files with 390 additions and 73 deletions

View file

@ -43,7 +43,7 @@ body:
attributes: attributes:
value: > value: >
When providing steps to reproduce the issue, please ensure that the issue 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. provide all necessary source files needed.

View file

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

View file

@ -1,4 +1,4 @@
# CONFIG := none
# CONFIG := clang # CONFIG := clang
CONFIG := gcc CONFIG := gcc
# CONFIG := afl-gcc # CONFIG := afl-gcc
@ -141,7 +141,7 @@ LIBS += -lrt
endif endif
endif endif
YOSYS_VER := 0.39+124 YOSYS_VER := 0.39+147
# Note: We arrange for .gitcommit to contain the (short) commit hash in # Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo # tarballs generated with git-archive(1) using .gitattributes. The git repo
@ -217,7 +217,7 @@ endif
ifeq ($(CONFIG),clang) ifeq ($(CONFIG),clang)
CXX = clang++ CXX = clang++
CXXFLAGS += -std=$(CXXSTD) -Os 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),) ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER)) $(info [Clang Sanitizer] $(SANITIZER))
@ -265,7 +265,7 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),emcc) else ifeq ($(CONFIG),emcc)
CXX = emcc CXX = emcc
CXXFLAGS := -std=$(CXXSTD) $(filter-out -fPIC -ggdb,$(CXXFLAGS)) 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_CXXFLAGS := -Os -Wno-warn-absolute-paths
EMCC_LINKFLAGS := --embed-file share EMCC_LINKFLAGS := --embed-file share
EMCC_LINKFLAGS += -s NO_EXIT_RUNTIME=1 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)) LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS))
LIBS := -lwasi-emulated-process-clocks $(filter-out -lrt,$(LIBS)) LIBS := -lwasi-emulated-process-clocks $(filter-out -lrt,$(LIBS))
ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)" 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" ABCMKARGS += OPTFLAGS="-Os"
EXE = .wasm 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)" ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
EXE = .exe EXE = .exe
else ifneq ($(CONFIG),none) else ifeq ($(CONFIG),none)
$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, emcc, mxe, msys2-32, msys2-64) 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 endif
ifeq ($(ENABLE_LIBYOSYS),1) ifeq ($(ENABLE_LIBYOSYS),1)
@ -1127,6 +1131,9 @@ echo-git-rev:
echo-abc-rev: echo-abc-rev:
@echo "$(ABCREV)" @echo "$(ABCREV)"
echo-cxx:
@echo "$(CXX)"
-include libs/*/*.d -include libs/*/*.d
-include frontends/*/*.d -include frontends/*/*.d
-include passes/*/*.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 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-clang
$ make config-gcc $ 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 For other compilers and build configurations it might be
necessary to make some changes to the config section of the necessary to make some changes to the config section of the
Makefile. Makefile.

View file

@ -124,7 +124,7 @@ struct JnyWriter
design->sort(); design->sort();
f << "{\n"; 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 << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_version_str).c_str());
f << " \"version\": \"0.0.1\",\n"; f << " \"version\": \"0.0.1\",\n";
f << " \"invocation\": \"" << escape_string(invk) << "\",\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(" Don't include property information in the netlist output.\n");
log("\n"); log("\n");
log("The JSON schema for JNY output files is located in the \"jny.schema.json\" file\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"); 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`. 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| 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| 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 .. literalinclude:: /cmd/synth_ice40.rst
:language: yoscrypt :language: yoscrypt

View file

@ -16,8 +16,8 @@ Automatic testing
.. _Yosys Git repo: https://github.com/YosysHQ/yosys .. _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-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=master .. |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 For up to date information, including OS versions, refer to `the git actions
page`_. 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 base under |code_examples/show|_.
.. |code_examples/show| replace:: :file:`docs/source/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 A simple circuit
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@ -337,7 +337,7 @@ The code used is included in the Yosys code base under
|code_examples/scrambler|_. |code_examples/scrambler|_.
.. |code_examples/scrambler| replace:: :file:`docs/source/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 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|_:
.. |code_examples/synth_flow| replace:: :file:`docs/source/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 .. literalinclude:: /code_examples/synth_flow/techmap_01_map.v
:language: verilog :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|_.
.. |code_examples/axis| replace:: :file:`docs/source/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 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.) 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|_: Example code from |code_examples/selections|_:
.. |code_examples/selections| replace:: :file:`docs/source/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 .. literalinclude:: /code_examples/selections/select.v
:language: verilog :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`. 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 A simple counter
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

View file

@ -15,7 +15,7 @@ The extract pass
Example code can be found in |code_examples/macc|_. Example code can be found in |code_examples/macc|_.
.. |code_examples/macc| replace:: :file:`docs/source/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 .. literalinclude:: /code_examples/macc/macc_simple_test.ys

View file

@ -36,7 +36,7 @@ Example
|code_examples/synth_flow|_. |code_examples/synth_flow|_.
.. |code_examples/synth_flow| replace:: :file:`docs/source/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.* .. figure:: /_images/code_examples/synth_flow/memory_01.*
:class: width-helper :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 For more on the lib format for :cmd:ref:`memory_libmap`, see
`passes/memory/memlib.md `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 Supported memory patterns
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -31,7 +31,7 @@ Example
|code_examples/synth_flow|_. |code_examples/synth_flow|_.
.. |code_examples/synth_flow| replace:: :file:`docs/source/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 .. literalinclude:: /code_examples/synth_flow/proc_01.v
:language: verilog :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|_ directory of the Yosys source code.
.. |code_examples/extensions| replace:: :file:`docs/source/code_examples/extensions` .. |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 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|_. included in the Yosys source distribution under |code_examples/stubnets|_.
.. |code_examples/stubnets| replace:: :file:`docs/source/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 .. literalinclude:: /code_examples/stubnets/stubnets.cc
:language: c++ :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|_.
.. |code_examples/techmap| replace:: :file:`docs/source/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 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 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 - Click on the most recent completed run
- In Artifacts region find vcxsrc and click on it to download - In Artifacts region find vcxsrc and click on it to download
- Unpack downloaded ZIP file - 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 PRIVATE_NAMESPACE_END
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell) 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; 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: $mul $div $mod $divfloor $modfloor $pow $slice $concat $bweqx
// FIXME: $lut $sop $alu $lcu $macc $fa $logic_and $logic_or $bwmux // 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::map<T, int, C> node_to_index;
std::vector<std::set<int, IndirectCmp>> edges; std::vector<std::set<int, IndirectCmp>> edges;
std::vector<T> sorted; std::vector<T> sorted;
std::set<std::set<T, C>> loops; std::set<std::vector<T>> loops;
TopoSort() : indirect_cmp(nodes) 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]) { if (active_cells[root_index]) {
found_loops = true; found_loops = true;
if (analyze_loops) { if (analyze_loops) {
std::set<T, C> loop; std::vector<T> loop;
for (int i = GetSize(active_stack) - 1; i >= 0; i--) { for (int i = GetSize(active_stack) - 1; i >= 0; i--) {
const int index = active_stack[i]; const int index = active_stack[i];
loop.insert(nodes[index]); loop.push_back(nodes[index]);
if (index == root_index) if (index == root_index)
break; break;
} }

View file

@ -46,7 +46,7 @@ Open "Git Bash" in this directory and run:
mv yosys yosys.bak mv yosys yosys.bak
git clone https://github.com/YosysHQ/yosys.git yosys git clone https://github.com/YosysHQ/yosys.git yosys
cd 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 unzip ../genfiles.zip
EOT EOT

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$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", "title": "Yosys JSON Netlist metadata",
"description": "Yosys JSON Netlist", "description": "Yosys JSON Netlist",
"type": "object", "type": "object",

View file

@ -19,6 +19,7 @@
#include "kernel/yosys.h" #include "kernel/yosys.h"
#include "kernel/sigtools.h" #include "kernel/sigtools.h"
#include "kernel/celledges.h"
#include "kernel/celltypes.h" #include "kernel/celltypes.h"
#include "kernel/utils.h" #include "kernel/utils.h"
@ -102,10 +103,10 @@ struct CheckPass : public Pass {
SigMap sigmap(module); SigMap sigmap(module);
dict<SigBit, vector<string>> wire_drivers; dict<SigBit, vector<string>> wire_drivers;
dict<SigBit, Cell *> driver_cells;
dict<SigBit, int> wire_drivers_count; dict<SigBit, int> wire_drivers_count;
pool<SigBit> used_wires; pool<SigBit> used_wires;
TopoSort<string> topo; TopoSort<std::pair<RTLIL::IdString, int>> topo;
for (auto &proc_it : module->processes) for (auto &proc_it : module->processes)
{ {
std::vector<RTLIL::CaseRule*> all_cases = {&proc_it.second->root_case}; 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()) for (auto cell : module->cells())
{ {
if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) { if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) {
@ -158,31 +203,30 @@ struct CheckPass : public Pass {
counter++; counter++;
cell_allowed:; 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)) for (auto &conn : cell->connections()) {
wire_drivers[sig[i]].push_back(stringf("port %s[%d] of cell %s (%s)", bool input = cell->input(conn.first);
log_id(conn.first), i, log_id(cell), log_id(cell->type))); 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 (!cell->input(conn.first) && cell->output(conn.first))
for (auto bit : sig)
if (bit.wire) wire_drivers_count[bit]++;
} }
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; pool<SigBit> init_bits;
@ -239,8 +283,72 @@ struct CheckPass : public Pass {
topo.sort(); topo.sort();
for (auto &loop : topo.loops) { for (auto &loop : topo.loops) {
string message = stringf("found logic loop in module %s:\n", log_id(module)); 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()); log_warning("%s", message.c_str());
counter++; counter++;
} }

View file

@ -7,7 +7,7 @@ module top(...);
input CLK; input CLK;
input EN; input EN;
(* init = 24'h555555 *) (* init = 24'h555555 *)
output [19:0] Q; output [17:0] Q;
input SRST; input SRST;
input ARST; input ARST;
input [1:0] CLR; 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])); $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])); $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 endmodule
EOT EOT
design -save orig 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 equiv_opt -undef -assert -multiclock opt_dff -keepdc
design -load orig design -load orig
opt_dff -keepdc opt_dff -keepdc
select -assert-count 1 t:$and select -assert-count 1 t:$and
select -assert-count 3 t:$dffe select -assert-count 3 t:$dffe
select -assert-count 3 t:$dlatch select -assert-count 2 t:$dlatch
select -assert-count 3 t:$sr select -assert-count 2 t:$sr
select -assert-none t:$and t:$dffe t:$dlatch t:$sr %% %n t:* %i select -assert-none t:$and t:$dffe t:$dlatch t:$sr %% %n t:* %i
design -load orig design -load orig
@ -50,7 +44,7 @@ simplemap
opt_dff -keepdc opt_dff -keepdc
select -assert-count 2 t:$_AND_ select -assert-count 2 t:$_AND_
select -assert-count 6 t:$_DFFE_??_ select -assert-count 6 t:$_DFFE_??_
select -assert-count 6 t:$_DLATCH_?_ select -assert-count 4 t:$_DLATCH_?_
select -assert-count 6 t:$_SR_??_ select -assert-count 4 t:$_SR_??_
select -assert-none t:$_AND_ t:$_DFFE_??_ t:$_DLATCH_?_ t:$_SR_??_ %% %n t:* %i 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