mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-18 06:39:03 +00:00
Merge upstream
This commit is contained in:
parent
12137c7ac4
commit
881080a827
73
CONTRIBUTING.md
Normal file
73
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
# Introduction
|
||||
|
||||
Thanks for thinking about contributing to the Yosys project. If this is your
|
||||
first time contributing to an open source project, please take a look at the
|
||||
following guide:
|
||||
https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project.
|
||||
|
||||
Information about the Yosys coding style is available on our Read the Docs:
|
||||
https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html.
|
||||
|
||||
# Using the issue tracker
|
||||
|
||||
The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for
|
||||
tracking bugs or other problems with Yosys or its documentation. It is also the
|
||||
place to go for requesting new features.
|
||||
When [creating a new issue](https://github.com/YosysHQ/yosys/issues/new/choose),
|
||||
we have a few templates available. Please make use of these! It will make it
|
||||
much easier for someone to respond and help.
|
||||
|
||||
### Bug reports
|
||||
|
||||
Before you submit an issue, please have a search of the existing issues in case
|
||||
one already exists. Making sure that you have a minimal, complete and
|
||||
verifiable example (MVCE) is a great way to quickly check an existing issue
|
||||
against a new one. Stack overflow has a guide on [how to create an
|
||||
MVCE](https://stackoverflow.com/help/minimal-reproducible-example). The
|
||||
[`bugpoint`
|
||||
command](https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/bugpoint.html)
|
||||
in Yosys can be helpful for this process.
|
||||
|
||||
|
||||
# Using pull requests
|
||||
|
||||
If you are working on something to add to Yosys, or fix something that isn't
|
||||
working quite right, make a [PR](https://github.com/YosysHQ/yosys/pulls)! An
|
||||
open PR, even as a draft, tells everyone that you're working on it and they
|
||||
don't have to. It can also be a useful way to solicit feedback on in-progress
|
||||
changes. See below to find the best way to [ask us
|
||||
questions](#asking-questions).
|
||||
|
||||
In general, all changes to the code are done as a PR, with [Continuous
|
||||
Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools that
|
||||
automatically run the full suite of tests compiling and running Yosys. Please
|
||||
make use of this! If you're adding a feature: add a test! Not only does it
|
||||
verify that your feature is working as expected, but it can also be a handy way
|
||||
for people to see how the feature is used. If you're fixing a bug: add a test!
|
||||
If you can, do this first; it's okay if the test starts off failing - you
|
||||
already know there is a bug. CI also helps to make sure that your changes still
|
||||
work under a range of compilers, settings, and targets.
|
||||
|
||||
|
||||
### Labels
|
||||
|
||||
We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise
|
||||
issues and PRs. If a label seems relevant to your work, please do add it; this
|
||||
also includes the labels beggining with 'status-'. The 'merge-' labels are used
|
||||
by maintainers for tracking and communicating which PRs are ready and pending
|
||||
merge; please do not use these labels if you are not a maintainer.
|
||||
|
||||
|
||||
# Asking questions
|
||||
|
||||
If you have a question about how to use Yosys, please ask on our [discussions
|
||||
page](https://github.com/YosysHQ/yosys/discussions) or in our [community
|
||||
slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA).
|
||||
The slack is also a great place to ask questions about developing or
|
||||
contributing to Yosys.
|
||||
|
||||
We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the
|
||||
community come together to discuss open issues and PRs. This is also a good
|
||||
place to talk to us about how to implement larger PRs. Please join the
|
||||
community slack if you would like to join the next meeting, the link is
|
||||
available in the description of the #devel-discuss channel.
|
7
Makefile
7
Makefile
|
@ -694,6 +694,9 @@ OBJS += yosys-slang/build/*.o
|
|||
OBJS += yosys-slang/build/slang*/lib*/*.a
|
||||
endif
|
||||
|
||||
techlibs/%_pm.h: passes/pmgen/pmgen.py techlibs/%.pmg
|
||||
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^)
|
||||
|
||||
OBJS += libs/subcircuit/subcircuit.o
|
||||
|
||||
ifneq ($(SMALL),1)
|
||||
|
@ -719,10 +722,6 @@ include $(YOSYS_SRC)/passes/equiv/Makefile.inc
|
|||
include $(YOSYS_SRC)/passes/cmds/Makefile.inc
|
||||
include $(YOSYS_SRC)/passes/silimate/Makefile.inc
|
||||
|
||||
OBJS += passes/opt/muxpack.o
|
||||
OBJS += passes/opt/opt_demorgan.o
|
||||
OBJS += passes/opt/pmux2shiftx.o
|
||||
OBJS += passes/opt/wreduce.o
|
||||
OBJS += passes/sat/sim.o
|
||||
OBJS += passes/techmap/extract.o
|
||||
OBJS += passes/techmap/extract_reduce.o
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
Contributing to Yosys
|
||||
=====================
|
||||
|
||||
.. note::
|
||||
|
||||
For information on making a pull request on github, refer to our
|
||||
|CONTRIBUTING|_ file.
|
||||
|
||||
.. |CONTRIBUTING| replace:: :file:`CONTRIBUTING.md`
|
||||
.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/CONTRIBUTING.md
|
||||
|
||||
Coding Style
|
||||
------------
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool fla
|
|||
RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_));
|
||||
enable_gate->setPort(ID::A, enable_sig);
|
||||
enable_gate->setPort(ID::B, clear_enable);
|
||||
enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID));
|
||||
enable_gate->setPort(ID::Y, enable_sig = module->addWire(NEW_ID));
|
||||
}
|
||||
|
||||
if (preset_sig.size() == 1)
|
||||
|
@ -376,7 +376,7 @@ static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool fla
|
|||
RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_));
|
||||
enable_gate->setPort(ID::A, enable_sig);
|
||||
enable_gate->setPort(ID::B, preset_enable);
|
||||
enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID));
|
||||
enable_gate->setPort(ID::Y, enable_sig = module->addWire(NEW_ID));
|
||||
}
|
||||
|
||||
cell = module->addCell(NEW_ID, stringf("$_DLATCH_%c_", enable_polarity ? 'P' : 'N'));
|
||||
|
|
|
@ -760,9 +760,10 @@ struct TclPass : public Pass {
|
|||
log("If any arguments are specified, these arguments are provided to the script via\n");
|
||||
log("the standard $argc and $argv variables.\n");
|
||||
log("\n");
|
||||
log("Note, tcl will not recieve the output of any yosys command. If the output\n");
|
||||
log("Note, tcl will not receive the output of any yosys command. If the output\n");
|
||||
log("of the tcl commands are needed, use the yosys command 'tee -s result.string'\n");
|
||||
log("to redirect yosys's output to the 'result.string' scratchpad value.\n");
|
||||
log("The 'result.string' value is then used as the tcl output value of the command.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *) override {
|
||||
|
|
1
passes/opt/.gitignore
vendored
Normal file
1
passes/opt/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/peepopt*_pm.h
|
|
@ -12,7 +12,6 @@ OBJS += passes/opt/opt_share.o
|
|||
OBJS += passes/opt/opt_clean.o
|
||||
OBJS += passes/opt/opt_expr.o
|
||||
|
||||
ifneq ($(SMALL),1)
|
||||
OBJS += passes/opt/share.o
|
||||
OBJS += passes/opt/wreduce.o
|
||||
OBJS += passes/opt/opt_demorgan.o
|
||||
|
@ -22,4 +21,19 @@ OBJS += passes/opt/opt_lut_ins.o
|
|||
OBJS += passes/opt/opt_ffinv.o
|
||||
OBJS += passes/opt/pmux2shiftx.o
|
||||
OBJS += passes/opt/muxpack.o
|
||||
endif
|
||||
|
||||
OBJS += passes/opt/peepopt.o
|
||||
GENFILES += passes/opt/peepopt_pm.h
|
||||
passes/opt/peepopt.o: passes/opt/peepopt_pm.h
|
||||
$(eval $(call add_extra_objs,passes/opt/peepopt_pm.h))
|
||||
|
||||
PEEPOPT_PATTERN = passes/opt/peepopt_shiftmul_right.pmg
|
||||
PEEPOPT_PATTERN += passes/opt/peepopt_shiftmul_left.pmg
|
||||
PEEPOPT_PATTERN += passes/opt/peepopt_shiftadd.pmg
|
||||
PEEPOPT_PATTERN += passes/opt/peepopt_muldiv.pmg
|
||||
PEEPOPT_PATTERN += passes/opt/peepopt_muldiv_c.pmg
|
||||
PEEPOPT_PATTERN += passes/opt/peepopt_muxadd.pmg
|
||||
PEEPOPT_PATTERN += passes/opt/peepopt_formal_clockgateff.pmg
|
||||
|
||||
passes/opt/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
|
||||
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^)
|
||||
|
|
|
@ -31,7 +31,7 @@ int shiftadd_max_ratio;
|
|||
// Helper function, removes LSB 0s
|
||||
SigSpec remove_bottom_padding(SigSpec sig);
|
||||
|
||||
#include "passes/pmgen/peepopt_pm.h"
|
||||
#include "passes/opt/peepopt_pm.h"
|
||||
|
||||
struct PeepoptPass : public Pass {
|
||||
PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { }
|
|
@ -1,72 +1,9 @@
|
|||
%_pm.h: passes/pmgen/pmgen.py %.pmg
|
||||
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^)
|
||||
passes/pmgen/%_pm.h: passes/pmgen/pmgen.py passes/pmgen/%.pmg
|
||||
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^)
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/test_pmgen.o
|
||||
GENFILES += passes/pmgen/test_pmgen_pm.h
|
||||
passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h passes/pmgen/xilinx_srl_pm.h
|
||||
passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h techlibs/ice40/ice40_dsp_pm.h techlibs/xilinx/xilinx_srl_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/ice40_dsp.o
|
||||
GENFILES += passes/pmgen/ice40_dsp_pm.h
|
||||
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/ice40_dsp_pm.h))
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/ice40_wrapcarry.o
|
||||
GENFILES += passes/pmgen/ice40_wrapcarry_pm.h
|
||||
passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h))
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/xilinx_dsp.o
|
||||
GENFILES += passes/pmgen/xilinx_dsp_pm.h
|
||||
GENFILES += passes/pmgen/xilinx_dsp48a_pm.h
|
||||
GENFILES += passes/pmgen/xilinx_dsp_CREG_pm.h
|
||||
GENFILES += passes/pmgen/xilinx_dsp_cascade_pm.h
|
||||
passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp48a_pm.h passes/pmgen/xilinx_dsp_CREG_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h))
|
||||
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp48a_pm.h))
|
||||
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_CREG_pm.h))
|
||||
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h))
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/microchip_dsp.o
|
||||
GENFILES += passes/pmgen/microchip_dsp_pm.h
|
||||
GENFILES += passes/pmgen/microchip_dsp_CREG_pm.h
|
||||
GENFILES += passes/pmgen/microchip_dsp_cascade_pm.h
|
||||
passes/pmgen/microchip_dsp.o: passes/pmgen/microchip_dsp_pm.h passes/pmgen/microchip_dsp_CREG_pm.h passes/pmgen/microchip_dsp_cascade_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/microchip_dsp_pm.h))
|
||||
$(eval $(call add_extra_objs,passes/pmgen/microchip_dsp_CREG_pm.h))
|
||||
$(eval $(call add_extra_objs,passes/pmgen/microchip_dsp_cascade_pm.h))
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/peepopt.o
|
||||
GENFILES += passes/pmgen/peepopt_pm.h
|
||||
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/peepopt_pm.h))
|
||||
|
||||
PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul_right.pmg
|
||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_shiftmul_left.pmg
|
||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_shiftadd.pmg
|
||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
|
||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv_c.pmg
|
||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_muxadd.pmg
|
||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_formal_clockgateff.pmg
|
||||
|
||||
passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
|
||||
$(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^)
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
OBJS += passes/pmgen/xilinx_srl.o
|
||||
GENFILES += passes/pmgen/xilinx_srl_pm.h
|
||||
passes/pmgen/xilinx_srl.o: passes/pmgen/xilinx_srl_pm.h
|
||||
$(eval $(call add_extra_objs,passes/pmgen/xilinx_srl_pm.h))
|
||||
|
|
|
@ -22,7 +22,7 @@ list of cells from that module:
|
|||
foobar_pm pm(module, module->selected_cells());
|
||||
|
||||
The caller must make sure that none of the cells in the 2nd argument are
|
||||
deleted for as long as the patter matcher instance is used.
|
||||
deleted for as long as the pattern matcher instance is used.
|
||||
|
||||
At any time it is possible to disable cells, preventing them from showing
|
||||
up in any future matches:
|
||||
|
|
|
@ -24,8 +24,8 @@ USING_YOSYS_NAMESPACE
|
|||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "passes/pmgen/test_pmgen_pm.h"
|
||||
#include "passes/pmgen/ice40_dsp_pm.h"
|
||||
#include "passes/pmgen/xilinx_srl_pm.h"
|
||||
#include "techlibs/ice40/ice40_dsp_pm.h"
|
||||
#include "techlibs/xilinx/xilinx_srl_pm.h"
|
||||
|
||||
#include "generate.h"
|
||||
|
||||
|
|
1
techlibs/.gitignore
vendored
1
techlibs/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
blackbox.v
|
||||
*_pm.h
|
||||
|
|
|
@ -14,3 +14,13 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/spram.txt))
|
|||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/spram_map.v))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_model.v))
|
||||
|
||||
OBJS += techlibs/ice40/ice40_dsp.o
|
||||
GENFILES += techlibs/ice40/ice40_dsp_pm.h
|
||||
techlibs/ice40/ice40_dsp.o: techlibs/ice40/ice40_dsp_pm.h
|
||||
$(eval $(call add_extra_objs,techlibs/ice40/ice40_dsp_pm.h))
|
||||
|
||||
OBJS += techlibs/ice40/ice40_wrapcarry.o
|
||||
GENFILES += techlibs/ice40/ice40_wrapcarry_pm.h
|
||||
techlibs/ice40/ice40_wrapcarry.o: techlibs/ice40/ice40_wrapcarry_pm.h
|
||||
$(eval $(call add_extra_objs,techlibs/ice40/ice40_wrapcarry_pm.h))
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "passes/pmgen/ice40_dsp_pm.h"
|
||||
#include "techlibs/ice40/ice40_dsp_pm.h"
|
||||
|
||||
void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||
{
|
|
@ -23,7 +23,7 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "passes/pmgen/ice40_wrapcarry_pm.h"
|
||||
#include "techlibs/ice40/ice40_wrapcarry_pm.h"
|
||||
|
||||
void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
|
||||
{
|
|
@ -29,3 +29,12 @@ $(eval $(call add_share_file,share/microchip,techlibs/microchip/LSRAM_map.v))
|
|||
$(eval $(call add_share_file,share/microchip,techlibs/microchip/LSRAM.txt))
|
||||
$(eval $(call add_share_file,share/microchip,techlibs/microchip/uSRAM_map.v))
|
||||
$(eval $(call add_share_file,share/microchip,techlibs/microchip/uSRAM.txt))
|
||||
|
||||
OBJS += techlibs/microchip/microchip_dsp.o
|
||||
GENFILES += techlibs/microchip/microchip_dsp_pm.h
|
||||
GENFILES += techlibs/microchip/microchip_dsp_CREG_pm.h
|
||||
GENFILES += techlibs/microchip/microchip_dsp_cascade_pm.h
|
||||
techlibs/microchip/microchip_dsp.o: techlibs/microchip/microchip_dsp_pm.h techlibs/microchip/microchip_dsp_CREG_pm.h techlibs/microchip/microchip_dsp_cascade_pm.h
|
||||
$(eval $(call add_extra_objs,techlibs/microchip/microchip_dsp_pm.h))
|
||||
$(eval $(call add_extra_objs,techlibs/microchip/microchip_dsp_CREG_pm.h))
|
||||
$(eval $(call add_extra_objs,techlibs/microchip/microchip_dsp_cascade_pm.h))
|
||||
|
|
|
@ -23,9 +23,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "passes/pmgen/microchip_dsp_CREG_pm.h"
|
||||
#include "passes/pmgen/microchip_dsp_cascade_pm.h"
|
||||
#include "passes/pmgen/microchip_dsp_pm.h"
|
||||
#include "techlibs/microchip/microchip_dsp_CREG_pm.h"
|
||||
#include "techlibs/microchip/microchip_dsp_cascade_pm.h"
|
||||
#include "techlibs/microchip/microchip_dsp_pm.h"
|
||||
|
||||
void microchip_dsp_pack(microchip_dsp_pm &pm)
|
||||
{
|
|
@ -6,6 +6,7 @@ OBJS += techlibs/quicklogic/ql_bram_merge.o
|
|||
OBJS += techlibs/quicklogic/ql_bram_types.o
|
||||
OBJS += techlibs/quicklogic/ql_dsp_simd.o
|
||||
OBJS += techlibs/quicklogic/ql_dsp_io_regs.o
|
||||
OBJS += techlibs/quicklogic/ql_ioff.o
|
||||
|
||||
# --------------------------------------
|
||||
|
||||
|
@ -40,4 +41,4 @@ $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf
|
|||
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v))
|
||||
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v))
|
||||
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v))
|
||||
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))
|
||||
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))
|
||||
|
|
125
techlibs/quicklogic/ql_ioff.cc
Normal file
125
techlibs/quicklogic/ql_ioff.cc
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include "kernel/log.h"
|
||||
#include "kernel/modtools.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct QlIoffPass : public Pass {
|
||||
QlIoffPass() : Pass("ql_ioff", "Infer I/O FFs for qlf_k6n10f architecture") {}
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" ql_ioff [selection]\n");
|
||||
log("\n");
|
||||
log("This pass promotes qlf_k6n10f registers directly connected to a top-level I/O\n");
|
||||
log("port to I/O FFs.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing QL_IOFF pass.\n");
|
||||
|
||||
ModWalker modwalker(design);
|
||||
Module *module = design->top_module();
|
||||
if (!module)
|
||||
return;
|
||||
modwalker.setup(module);
|
||||
pool<RTLIL::Cell *> input_ffs;
|
||||
dict<RTLIL::Wire *, std::vector<Cell*>> output_ffs;
|
||||
dict<SigBit, pool<SigBit>> output_bit_aliases;
|
||||
|
||||
for (Wire* wire : module->wires())
|
||||
if (wire->port_output) {
|
||||
output_ffs[wire].resize(wire->width, nullptr);
|
||||
for (SigBit bit : SigSpec(wire))
|
||||
output_bit_aliases[modwalker.sigmap(bit)].insert(bit);
|
||||
}
|
||||
|
||||
for (auto cell : module->selected_cells()) {
|
||||
if (cell->type.in(ID(dffsre), ID(sdffsre))) {
|
||||
log_debug("Checking cell %s.\n", cell->name.c_str());
|
||||
bool e_const = cell->getPort(ID::E).is_fully_ones();
|
||||
bool r_const = cell->getPort(ID::R).is_fully_ones();
|
||||
bool s_const = cell->getPort(ID::S).is_fully_ones();
|
||||
|
||||
if (!(e_const && r_const && s_const)) {
|
||||
log_debug("not promoting: E, R, or S is used\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
SigSpec d = cell->getPort(ID::D);
|
||||
log_assert(GetSize(d) == 1);
|
||||
if (modwalker.has_inputs(d)) {
|
||||
log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str());
|
||||
// check that d_sig has no other consumers
|
||||
pool<ModWalker::PortBit> portbits;
|
||||
modwalker.get_consumers(portbits, d);
|
||||
if (GetSize(portbits) > 1) {
|
||||
log_debug("not promoting: D has other consumers\n");
|
||||
continue;
|
||||
}
|
||||
input_ffs.insert(cell);
|
||||
continue; // prefer input FFs over output FFs
|
||||
}
|
||||
|
||||
SigSpec q = cell->getPort(ID::Q);
|
||||
log_assert(GetSize(q) == 1);
|
||||
if (modwalker.has_outputs(q) && !modwalker.has_consumers(q)) {
|
||||
log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str());
|
||||
for (SigBit bit : output_bit_aliases[modwalker.sigmap(q)]) {
|
||||
log_assert(bit.is_wire());
|
||||
output_ffs[bit.wire][bit.offset] = cell;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : input_ffs) {
|
||||
log("Promoting register %s to input IOFF.\n", log_signal(cell->getPort(ID::Q)));
|
||||
cell->type = ID(dff);
|
||||
cell->unsetPort(ID::E);
|
||||
cell->unsetPort(ID::R);
|
||||
cell->unsetPort(ID::S);
|
||||
}
|
||||
for (auto & [old_port_output, ioff_cells] : output_ffs) {
|
||||
if (std::any_of(ioff_cells.begin(), ioff_cells.end(), [](Cell * c) { return c != nullptr; }))
|
||||
{
|
||||
// create replacement output wire
|
||||
RTLIL::Wire* new_port_output = module->addWire(NEW_ID, old_port_output->width);
|
||||
new_port_output->start_offset = old_port_output->start_offset;
|
||||
module->swap_names(old_port_output, new_port_output);
|
||||
std::swap(old_port_output->port_id, new_port_output->port_id);
|
||||
std::swap(old_port_output->port_input, new_port_output->port_input);
|
||||
std::swap(old_port_output->port_output, new_port_output->port_output);
|
||||
std::swap(old_port_output->upto, new_port_output->upto);
|
||||
std::swap(old_port_output->is_signed, new_port_output->is_signed);
|
||||
std::swap(old_port_output->attributes, new_port_output->attributes);
|
||||
|
||||
// create new output FFs
|
||||
SigSpec sig_o(old_port_output);
|
||||
SigSpec sig_n(new_port_output);
|
||||
for (int i = 0; i < new_port_output->width; i++) {
|
||||
if (ioff_cells[i]) {
|
||||
log("Promoting %s to output IOFF.\n", log_signal(sig_n[i]));
|
||||
|
||||
RTLIL::Cell *new_cell = module->addCell(NEW_ID, ID(dff));
|
||||
new_cell->setPort(ID::C, ioff_cells[i]->getPort(ID::C));
|
||||
new_cell->setPort(ID::D, ioff_cells[i]->getPort(ID::D));
|
||||
new_cell->setPort(ID::Q, sig_n[i]);
|
||||
new_cell->set_bool_attribute(ID::keep);
|
||||
} else {
|
||||
module->connect(sig_n[i], sig_o[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} QlIoffPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -78,7 +78,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
}
|
||||
|
||||
string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
|
||||
bool abc9, inferAdder, nobram, bramTypes, dsp;
|
||||
bool abc9, inferAdder, nobram, bramTypes, dsp, ioff;
|
||||
|
||||
void clear_flags() override
|
||||
{
|
||||
|
@ -94,6 +94,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
bramTypes = false;
|
||||
lib_path = "+/quicklogic/";
|
||||
dsp = true;
|
||||
ioff = true;
|
||||
}
|
||||
|
||||
void set_scratchpad_defaults(RTLIL::Design *design) {
|
||||
|
@ -158,6 +159,10 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
dsp = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noioff") {
|
||||
ioff = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -328,6 +333,13 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
run("clean");
|
||||
run("opt_lut");
|
||||
}
|
||||
|
||||
if (check_label("iomap", "(for qlf_k6n10f, skip if -noioff)") && (family == "qlf_k6n10f" || help_mode)) {
|
||||
if (ioff || help_mode) {
|
||||
run("ql_ioff");
|
||||
run("opt_clean");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("check")) {
|
||||
run("autoname");
|
||||
|
|
|
@ -46,3 +46,19 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v))
|
|||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v))
|
||||
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v))
|
||||
|
||||
OBJS += techlibs/xilinx/xilinx_dsp.o
|
||||
GENFILES += techlibs/xilinx/xilinx_dsp_pm.h
|
||||
GENFILES += techlibs/xilinx/xilinx_dsp48a_pm.h
|
||||
GENFILES += techlibs/xilinx/xilinx_dsp_CREG_pm.h
|
||||
GENFILES += techlibs/xilinx/xilinx_dsp_cascade_pm.h
|
||||
techlibs/xilinx/xilinx_dsp.o: techlibs/xilinx/xilinx_dsp_pm.h techlibs/xilinx/xilinx_dsp48a_pm.h techlibs/xilinx/xilinx_dsp_CREG_pm.h techlibs/xilinx/xilinx_dsp_cascade_pm.h
|
||||
$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp_pm.h))
|
||||
$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp48a_pm.h))
|
||||
$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp_CREG_pm.h))
|
||||
$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp_cascade_pm.h))
|
||||
|
||||
OBJS += techlibs/xilinx/xilinx_srl.o
|
||||
GENFILES += techlibs/xilinx/xilinx_srl_pm.h
|
||||
techlibs/xilinx/xilinx_srl.o: techlibs/xilinx/xilinx_srl_pm.h
|
||||
$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_srl_pm.h))
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "passes/pmgen/xilinx_dsp_pm.h"
|
||||
#include "passes/pmgen/xilinx_dsp48a_pm.h"
|
||||
#include "passes/pmgen/xilinx_dsp_CREG_pm.h"
|
||||
#include "passes/pmgen/xilinx_dsp_cascade_pm.h"
|
||||
#include "techlibs/xilinx/xilinx_dsp_pm.h"
|
||||
#include "techlibs/xilinx/xilinx_dsp48a_pm.h"
|
||||
#include "techlibs/xilinx/xilinx_dsp_CREG_pm.h"
|
||||
#include "techlibs/xilinx/xilinx_dsp_cascade_pm.h"
|
||||
|
||||
static Cell* addDsp(Module *module) {
|
||||
Cell *cell = module->addCell(NEW_ID, ID(DSP48E1));
|
|
@ -24,7 +24,7 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "passes/pmgen/xilinx_srl_pm.h"
|
||||
#include "techlibs/xilinx/xilinx_srl_pm.h"
|
||||
|
||||
void run_fixed(xilinx_srl_pm &pm)
|
||||
{
|
|
@ -2,7 +2,7 @@ read_verilog ../../common/counter.v
|
|||
hierarchy -top top
|
||||
proc
|
||||
flatten
|
||||
equiv_opt -assert -multiclock -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f # equivalency check
|
||||
equiv_opt -assert -multiclock -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f -noioff # equivalency check
|
||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||
cd top # Constrain all select calls below inside the top module
|
||||
select -assert-count 4 t:$lut
|
||||
|
|
|
@ -5,7 +5,7 @@ design -save read
|
|||
|
||||
hierarchy -top my_dff
|
||||
proc
|
||||
equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f # equivalency check
|
||||
equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f -noioff # equivalency check
|
||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||
cd my_dff # Constrain all select calls below inside the top module
|
||||
select -assert-count 1 t:sdffsre
|
||||
|
@ -14,7 +14,7 @@ select -assert-none t:sdffsre %% t:* %D
|
|||
design -load read
|
||||
hierarchy -top my_dffe
|
||||
proc
|
||||
equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f # equivalency check
|
||||
equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f -noioff # equivalency check
|
||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||
cd my_dffe # Constrain all select calls below inside the top module
|
||||
select -assert-count 1 t:sdffsre
|
||||
|
|
209
tests/arch/quicklogic/qlf_k6n10f/ioff.ys
Normal file
209
tests/arch/quicklogic/qlf_k6n10f/ioff.ys
Normal file
|
@ -0,0 +1,209 @@
|
|||
# test: acceptable for output IOFF promotion
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input a, output reg o);
|
||||
always @(posedge clk) begin
|
||||
o <= ~a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 1 t:dff
|
||||
|
||||
design -reset
|
||||
# test: acceptable for output IOFF promotion
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input [3:0] a, output reg [3:0] o);
|
||||
always @(posedge clk) begin
|
||||
o <= ~a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 4 t:dff
|
||||
|
||||
design -reset
|
||||
# test: acceptable for output IOFF promotion; duplicate output FF
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input [3:0] a, output [3:0] o, output [3:0] p);
|
||||
reg [3:0] r;
|
||||
always @(posedge clk) begin
|
||||
r <= ~a;
|
||||
end
|
||||
assign o = r;
|
||||
assign p = r;
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 8 t:dff
|
||||
|
||||
design -reset
|
||||
# test: acceptable for input IOFF promotion
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input a, output o);
|
||||
reg r;
|
||||
always @(posedge clk) begin
|
||||
r <= a;
|
||||
end
|
||||
assign o = ~r;
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 1 t:dff
|
||||
|
||||
design -reset
|
||||
# test: acceptable for input IOFF promotion
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input [3:0] a, output [3:0] o);
|
||||
reg [3:0] r;
|
||||
always @(posedge clk) begin
|
||||
r <= a;
|
||||
end
|
||||
assign o = ~r;
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 4 t:dff
|
||||
|
||||
design -reset
|
||||
# test: acceptable for either IOFF promotion
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input a, output reg o);
|
||||
always @(posedge clk) begin
|
||||
o <= a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 1 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for output IOFF promotion: output signal is used
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input a, output reg o);
|
||||
always @(posedge clk) begin
|
||||
o <= ~a | o;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for output IOFF promotion: output signal is used
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input [3:0] a, output reg [3:0] o);
|
||||
always @(posedge clk) begin
|
||||
o <= ~a | o;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for input IOFF promotion: input signal is used
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input a, output o, p);
|
||||
reg r;
|
||||
always @(posedge clk) begin
|
||||
r <= a;
|
||||
end
|
||||
assign o = ~r;
|
||||
assign p = ~a;
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for input IOFF promotion: input signal is used
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input [3:0] a, output [3:0] o, output [3:0] p);
|
||||
reg [3:0] r;
|
||||
always @(posedge clk) begin
|
||||
r <= a;
|
||||
end
|
||||
assign o = ~r;
|
||||
assign p = ~a;
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for IOFF promotion: FF has reset
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input rst, input a, output reg o);
|
||||
always @(posedge clk) begin
|
||||
if (rst)
|
||||
o <= 1'b0;
|
||||
else
|
||||
o <= a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for IOFF promotion: FF has reset
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input rst, input [3:0] a, output reg [3:0] o);
|
||||
always @(posedge clk) begin
|
||||
if (rst)
|
||||
o <= 4'b0;
|
||||
else
|
||||
o <= a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for IOFF promotion: FF has enable
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input en, input a, output reg o);
|
||||
always @(posedge clk) begin
|
||||
if (en)
|
||||
o <= a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: not acceptable for IOFF promotion: FF has enable
|
||||
read_verilog <<EOF
|
||||
module top (input clk, input en, input [3:0] a, output reg [3:0] o);
|
||||
always @(posedge clk) begin
|
||||
if (en)
|
||||
o <= a;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 0 t:dff
|
||||
|
||||
design -reset
|
||||
# test: duplicate registers driving multiple output ports
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input clk,
|
||||
input en,
|
||||
input [3:0] a,
|
||||
output reg [3:0] o_1,
|
||||
output wire [3:0] o_2
|
||||
);
|
||||
always @(posedge clk) begin
|
||||
o_1[1:0] <= ~a[1:0];
|
||||
if (en)
|
||||
o_1[2] <= a[2];
|
||||
end
|
||||
always @(*) o_1[3] = a[3];
|
||||
assign o_2 = o_1;
|
||||
endmodule
|
||||
EOF
|
||||
synth_quicklogic -family qlf_k6n10f -top top
|
||||
select -assert-count 4 t:dff
|
Loading…
Reference in a new issue