mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Merge branch 'xc7dsp' of github.com:YosysHQ/yosys into xc7dsp
This commit is contained in:
commit
295c18bd6b
1
Brewfile
1
Brewfile
|
@ -6,3 +6,4 @@ brew "git"
|
||||||
brew "graphviz"
|
brew "graphviz"
|
||||||
brew "pkg-config"
|
brew "pkg-config"
|
||||||
brew "python3"
|
brew "python3"
|
||||||
|
brew "tcl-tk"
|
||||||
|
|
123
CHANGELOG
123
CHANGELOG
|
@ -12,7 +12,10 @@ Yosys 0.9 .. Yosys 0.9-dev
|
||||||
- Added "synth_xilinx -abc9" (experimental)
|
- Added "synth_xilinx -abc9" (experimental)
|
||||||
- Added "synth_ice40 -abc9" (experimental)
|
- Added "synth_ice40 -abc9" (experimental)
|
||||||
- Added "synth -abc9" (experimental)
|
- Added "synth -abc9" (experimental)
|
||||||
- Added "script -scriptwire
|
- Added "script -scriptwire"
|
||||||
|
- Added "synth_xilinx -nocarry"
|
||||||
|
- Added "synth_xilinx -nowidelut"
|
||||||
|
- Added "synth_ecp5 -nowidelut"
|
||||||
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
|
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
|
||||||
- Renamed labels/options in synth_ice40 (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
- Renamed labels/options in synth_ice40 (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
||||||
- Renamed labels/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
- Renamed labels/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
||||||
|
@ -23,37 +26,135 @@ Yosys 0.9 .. Yosys 0.9-dev
|
||||||
- Added automatic gzip compression (based on filename extension) for backends
|
- Added automatic gzip compression (based on filename extension) for backends
|
||||||
- Improve attribute and parameter encoding in JSON to avoid ambiguities between
|
- Improve attribute and parameter encoding in JSON to avoid ambiguities between
|
||||||
bit vectors and strings containing [01xz]*
|
bit vectors and strings containing [01xz]*
|
||||||
|
- Added "clkbufmap" pass
|
||||||
|
- Added "synth_xilinx -family xc6s" for Spartan 6 support (experimental)
|
||||||
|
- Added "synth_xilinx -ise" (experimental)
|
||||||
|
- Added "synth_xilinx -iopad"
|
||||||
|
- "synth_xilinx" now automatically inserts clock buffers (add -noclkbuf to disable)
|
||||||
- Improvements in pmgen: subpattern and recursive matches
|
- Improvements in pmgen: subpattern and recursive matches
|
||||||
- Added "opt_share" pass, run as part of "opt -full"
|
- Added "opt_share" pass, run as part of "opt -full"
|
||||||
- Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
|
- Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
|
||||||
- Removed "ice40_unlut"
|
- Removed "ice40_unlut"
|
||||||
|
- Improvements in pmgen: slices, choices, define, generate
|
||||||
|
|
||||||
Yosys 0.8 .. Yosys 0.8-dev
|
Yosys 0.8 .. Yosys 0.9
|
||||||
--------------------------
|
----------------------
|
||||||
|
|
||||||
* Various
|
* Various
|
||||||
- Added $changed support to read_verilog
|
- Many bugfixes and small improvements
|
||||||
|
- Added support for SystemVerilog interfaces and modports
|
||||||
- Added "write_edif -attrprop"
|
- Added "write_edif -attrprop"
|
||||||
- Added "ice40_unlut" pass
|
|
||||||
- Added "opt_lut" pass
|
- Added "opt_lut" pass
|
||||||
- Added "synth_ice40 -relut"
|
|
||||||
- Added "synth_ice40 -noabc"
|
|
||||||
- Added "gate2lut.v" techmap rule
|
- Added "gate2lut.v" techmap rule
|
||||||
- Added "rename -src"
|
- Added "rename -src"
|
||||||
- Added "equiv_opt" pass
|
- Added "equiv_opt" pass
|
||||||
- Added "shregmap -tech xilinx"
|
- Added "flowmap" LUT mapping pass
|
||||||
|
- Added "rename -wire" to rename cells based on the wires they drive
|
||||||
|
- Added "bugpoint" for creating minimised testcases
|
||||||
|
- Added "write_edif -gndvccy"
|
||||||
|
- "write_verilog" to escape Verilog keywords
|
||||||
|
- Fixed sign handling of real constants
|
||||||
|
- "write_verilog" to write initial statement for initial flop state
|
||||||
|
- Added pmgen pattern matcher generator
|
||||||
|
- Fixed opt_rmdff handling of $_DFFSR_???_ and $_DLATCHSR_???_
|
||||||
|
- Added "setundef -params" to replace undefined cell parameters
|
||||||
|
- Renamed "yosys -D" to "yosys -U", added "yosys -D" to set Verilog defines
|
||||||
|
- Fixed handling of defparam when default_nettype is none
|
||||||
|
- Fixed "wreduce" flipflop handling
|
||||||
|
- Fixed FIRRTL to Verilog process instance subfield assignment
|
||||||
|
- Added "write_verilog -siminit"
|
||||||
|
- Several fixes and improvements for mem2reg memories
|
||||||
|
- Fixed handling of task output ports in clocked always blocks
|
||||||
|
- Improved handling of and-with-1 and or-with-0 in "opt_expr"
|
||||||
- Added "read_aiger" frontend
|
- Added "read_aiger" frontend
|
||||||
|
- Added "mutate" pass
|
||||||
|
- Added "hdlname" attribute
|
||||||
|
- Added "rename -output"
|
||||||
|
- Added "read_ilang -lib"
|
||||||
|
- Improved "proc" full_case detection and handling
|
||||||
|
- Added "whitebox" and "lib_whitebox" attributes
|
||||||
|
- Added "read_verilog -nowb", "flatten -wb" and "wbflip"
|
||||||
|
- Added Python bindings and support for Python plug-ins
|
||||||
|
- Added "pmux2shiftx"
|
||||||
|
- Added log_debug framework for reduced default verbosity
|
||||||
|
- Improved "opt_expr" and "opt_clean" handling of (partially) undriven and/or unused wires
|
||||||
|
- Added "peepopt" peephole optimisation pass using pmgen
|
||||||
|
- Added approximate support for SystemVerilog "var" keyword
|
||||||
|
- Added parsing of "specify" blocks into $specrule and $specify[23]
|
||||||
|
- Added support for attributes on parameters and localparams
|
||||||
|
- Added support for parsing attributes on port connections
|
||||||
|
- Added "wreduce -keepdc"
|
||||||
|
- Added support for optimising $dffe and $_DFFE_* cells in "opt_rmdff"
|
||||||
|
- Added Verilog wand/wor wire type support
|
||||||
|
- Added support for elaboration system tasks
|
||||||
- Added "muxcover -mux{4,8,16}=<cost>"
|
- Added "muxcover -mux{4,8,16}=<cost>"
|
||||||
- Added "muxcover -dmux=<cost>"
|
- Added "muxcover -dmux=<cost>"
|
||||||
- Added "muxcover -nopartial"
|
- Added "muxcover -nopartial"
|
||||||
- Added "muxpack" pass
|
- Added "muxpack" pass
|
||||||
- Added "pmux2shiftx -norange"
|
- Added "pmux2shiftx -norange"
|
||||||
|
- Added support for "~" in filename parsing
|
||||||
|
- Added "read_verilog -pwires" feature to turn parameters into wires
|
||||||
|
- Fixed sign extension of unsized constants with 'bx and 'bz MSB
|
||||||
|
- Fixed genvar to be a signed type
|
||||||
|
- Added support for attributes on case rules
|
||||||
|
- Added "upto" and "offset" to JSON frontend and backend
|
||||||
|
- Several liberty file parser improvements
|
||||||
|
- Fixed handling of more complex BRAM patterns
|
||||||
|
- Add "write_aiger -I -O -B"
|
||||||
|
|
||||||
|
* Formal Verification
|
||||||
|
- Added $changed support to read_verilog
|
||||||
|
- Added "read_verilog -noassert -noassume -assert-assumes"
|
||||||
|
- Added btor ops for $mul, $div, $mod and $concat
|
||||||
|
- Added yosys-smtbmc support for btor witnesses
|
||||||
|
- Added "supercover" pass
|
||||||
|
- Fixed $global_clock handling vs autowire
|
||||||
|
- Added $dffsr support to "async2sync"
|
||||||
|
- Added "fmcombine" pass
|
||||||
|
- Added memory init support in "write_btor"
|
||||||
|
- Added "cutpoint" pass
|
||||||
|
- Changed "ne" to "neq" in btor2 output
|
||||||
|
- Added support for SVA "final" keyword
|
||||||
|
- Added "fmcombine -initeq -anyeq"
|
||||||
|
- Added timescale and generated-by header to yosys-smtbmc vcd output
|
||||||
|
- Improved BTOR2 handling of undriven wires
|
||||||
|
|
||||||
|
* Verific support
|
||||||
|
- Enabled Verific flags vhdl_support_variable_slice and veri_elaborate_top_level_modules_having_interface_ports
|
||||||
|
- Improved support for asymmetric memories
|
||||||
|
- Added "verific -chparam"
|
||||||
|
- Fixed "verific -extnets" for more complex situations
|
||||||
|
- Added "read -verific" and "read -noverific"
|
||||||
|
- Added "hierarchy -chparam"
|
||||||
|
|
||||||
|
* New back-ends
|
||||||
|
- Added initial Anlogic support
|
||||||
|
- Added initial SmartFusion2 and IGLOO2 support
|
||||||
|
|
||||||
|
* ECP5 support
|
||||||
|
- Added "synth_ecp5 -nowidelut"
|
||||||
|
- Added BRAM inference support to "synth_ecp5"
|
||||||
|
- Added support for transforming Diamond IO and flipflop primitives
|
||||||
|
|
||||||
|
* iCE40 support
|
||||||
|
- Added "ice40_unlut" pass
|
||||||
|
- Added "synth_ice40 -relut"
|
||||||
|
- Added "synth_ice40 -noabc"
|
||||||
|
- Added "synth_ice40 -dffe_min_ce_use"
|
||||||
|
- Added DSP inference support using pmgen
|
||||||
|
- Added support for initialising BRAM primitives from a file
|
||||||
|
- Added iCE40 Ultra RGB LED driver cells
|
||||||
|
|
||||||
|
* Xilinx support
|
||||||
|
- Use "write_edif -pvector bra" for Xilinx EDIF files
|
||||||
|
- Fixes for VPR place and route support with "synth_xilinx"
|
||||||
|
- Added more cell simulation models
|
||||||
|
- Added "synth_xilinx -family"
|
||||||
|
- Added "stat -tech xilinx" to estimate logic cell usage
|
||||||
- Added "synth_xilinx -nocarry"
|
- Added "synth_xilinx -nocarry"
|
||||||
- Added "synth_xilinx -nowidelut"
|
- Added "synth_xilinx -nowidelut"
|
||||||
- Added "synth_ecp5 -nowidelut"
|
|
||||||
- "synth_xilinx" to now infer hard shift registers (-nosrl to disable)
|
- "synth_xilinx" to now infer hard shift registers (-nosrl to disable)
|
||||||
- Fixed sign extension of unsized constants with 'bx and 'bz MSB
|
- Added support for mapping RAM32X1D
|
||||||
|
|
||||||
|
|
||||||
Yosys 0.7 .. Yosys 0.8
|
Yosys 0.7 .. Yosys 0.8
|
||||||
----------------------
|
----------------------
|
||||||
|
|
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at>
|
Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|
|
@ -390,6 +390,7 @@ Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
|
||||||
Release:
|
Release:
|
||||||
|
|
||||||
- set YOSYS_VER to x.y.z in Makefile
|
- set YOSYS_VER to x.y.z in Makefile
|
||||||
|
- remove "bumpversion" target from Makefile
|
||||||
- update version string in CHANGELOG
|
- update version string in CHANGELOG
|
||||||
git commit -am "Yosys x.y.z"
|
git commit -am "Yosys x.y.z"
|
||||||
|
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -91,8 +91,10 @@ PLUGIN_LDFLAGS += -undefined dynamic_lookup
|
||||||
ifneq ($(shell which brew),)
|
ifneq ($(shell which brew),)
|
||||||
BREW_PREFIX := $(shell brew --prefix)/opt
|
BREW_PREFIX := $(shell brew --prefix)/opt
|
||||||
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
||||||
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
|
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
|
||||||
LDFLAGS += -L$(BREW_PREFIX)/boost/lib
|
LDFLAGS += -L$(BREW_PREFIX)/boost/lib
|
||||||
|
endif
|
||||||
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
||||||
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
|
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
|
||||||
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
||||||
|
@ -113,10 +115,13 @@ LDFLAGS += -rdynamic
|
||||||
LDLIBS += -lrt
|
LDLIBS += -lrt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
YOSYS_VER := 0.8+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 4d4665b.. 2> /dev/null | wc -l; })
|
YOSYS_VER := 0.9+36
|
||||||
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
|
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
|
||||||
OBJS = kernel/version_$(GIT_REV).o
|
OBJS = kernel/version_$(GIT_REV).o
|
||||||
|
|
||||||
|
bumpversion:
|
||||||
|
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 8a4c6e6.. | wc -l`/;" Makefile
|
||||||
|
|
||||||
# set 'ABCREV = default' to use abc/ as it is
|
# set 'ABCREV = default' to use abc/ as it is
|
||||||
#
|
#
|
||||||
# Note: If you do ABC development, make sure that 'abc' in this directory
|
# Note: If you do ABC development, make sure that 'abc' in this directory
|
||||||
|
|
24
README.md
24
README.md
|
@ -1,7 +1,7 @@
|
||||||
```
|
```
|
||||||
yosys -- Yosys Open SYnthesis Suite
|
yosys -- Yosys Open SYnthesis Suite
|
||||||
|
|
||||||
Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at>
|
Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -69,11 +69,14 @@ prerequisites for building yosys:
|
||||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
graphviz xdot pkg-config python3 libboost-system-dev \
|
||||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
||||||
|
|
||||||
Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
|
Similarily, on Mac OS X Homebrew can be used to install dependencies:
|
||||||
|
|
||||||
$ brew tap Homebrew/bundle && brew bundle
|
$ brew tap Homebrew/bundle && brew bundle
|
||||||
|
|
||||||
|
or MacPorts:
|
||||||
|
|
||||||
$ sudo port install bison flex readline gawk libffi \
|
$ sudo port install bison flex readline gawk libffi \
|
||||||
git graphviz pkgconfig python36 boost zlib
|
git graphviz pkgconfig python36 boost zlib tcl
|
||||||
|
|
||||||
On FreeBSD use the following command to install all prerequisites:
|
On FreeBSD use the following command to install all prerequisites:
|
||||||
|
|
||||||
|
@ -329,6 +332,21 @@ Verilog Attributes and non-standard features
|
||||||
that represent module parameters or localparams (when the HDL front-end
|
that represent module parameters or localparams (when the HDL front-end
|
||||||
is run in -pwires mode).
|
is run in -pwires mode).
|
||||||
|
|
||||||
|
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
|
||||||
|
module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
|
||||||
|
from inserting another clock buffer on a net driven by such output.
|
||||||
|
|
||||||
|
- The ``clkbuf_sink`` attribute can be set on an input port of a module to
|
||||||
|
request clock buffer insertion by the ``clkbufmap`` pass.
|
||||||
|
|
||||||
|
- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent
|
||||||
|
automatic clock buffer insertion by ``clkbufmap``. This behaviour can be
|
||||||
|
overridden by providing a custom selection to ``clkbufmap``.
|
||||||
|
|
||||||
|
- The ``iopad_external_pin`` attribute on a blackbox module's port marks
|
||||||
|
it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
|
||||||
|
from inserting another pad cell on it.
|
||||||
|
|
||||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
|
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
|
||||||
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
||||||
for everything that comes after the ``{* ... *}`` statement. (Reset
|
for everything that comes after the ``{* ... *}`` statement. (Reset
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
read_verilog example.v
|
read_verilog example.v
|
||||||
synth_xilinx -top example -family xc6s
|
synth_xilinx -top example -family xc6s -ise
|
||||||
iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I
|
|
||||||
write_edif -pvector bra example.edif
|
write_edif -pvector bra example.edif
|
||||||
|
|
|
@ -150,6 +150,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
reg->str = stringf("%s[%d]", node->str.c_str(), i);
|
reg->str = stringf("%s[%d]", node->str.c_str(), i);
|
||||||
reg->is_reg = true;
|
reg->is_reg = true;
|
||||||
reg->is_signed = node->is_signed;
|
reg->is_signed = node->is_signed;
|
||||||
|
for (auto &it : node->attributes)
|
||||||
|
if (it.first != ID(mem2reg))
|
||||||
|
reg->attributes.emplace(it.first, it.second->clone());
|
||||||
|
reg->filename = node->filename;
|
||||||
|
reg->linenum = node->linenum;
|
||||||
children.push_back(reg);
|
children.push_back(reg);
|
||||||
while (reg->simplify(true, false, false, 1, -1, false, false)) { }
|
while (reg->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ void yosys_banner()
|
||||||
log(" | |\n");
|
log(" | |\n");
|
||||||
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
|
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
|
||||||
log(" | |\n");
|
log(" | |\n");
|
||||||
log(" | Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at> |\n");
|
log(" | Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at> |\n");
|
||||||
log(" | |\n");
|
log(" | |\n");
|
||||||
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
|
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
|
||||||
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
|
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
|
||||||
|
|
|
@ -508,23 +508,17 @@ class TupleTranslator(PythonDictTranslator):
|
||||||
#Generate c++ code to translate to a boost::python::tuple
|
#Generate c++ code to translate to a boost::python::tuple
|
||||||
@classmethod
|
@classmethod
|
||||||
def translate_cpp(c, varname, types, prefix, ref):
|
def translate_cpp(c, varname, types, prefix, ref):
|
||||||
text = prefix + TupleTranslator.typename + " " + varname + "___tmp = boost::python::make_tuple(" + varname + ".first, " + varname + ".second);"
|
# if the tuple is a pair of SigSpecs (aka SigSig), then we need
|
||||||
return text
|
# to call get_py_obj() on each item in the tuple
|
||||||
tmp_name = "tmp_" + str(Translator.tmp_cntr)
|
if types[0].name in classnames:
|
||||||
Translator.tmp_cntr = Translator.tmp_cntr + 1
|
first_var = types[0].name + "::get_py_obj(" + varname + ".first)"
|
||||||
if ref:
|
|
||||||
text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
|
|
||||||
else:
|
else:
|
||||||
text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
|
first_var = varname + ".first"
|
||||||
text += prefix + "{"
|
if types[1].name in classnames:
|
||||||
if types[0].name.split(" ")[-1] in primitive_types or types[0].name in enum_names:
|
second_var = types[1].name + "::get_py_obj(" + varname + ".second)"
|
||||||
text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + ");"
|
else:
|
||||||
elif types[0].name in known_containers:
|
second_var = varname + ".second"
|
||||||
text += known_containers[types[0].name].translate_cpp(tmp_name, types[0].cont.args, prefix + "\t", types[1].attr_type == attr_types.star)
|
text = prefix + TupleTranslator.typename + " " + varname + "___tmp = boost::python::make_tuple(" + first_var + ", " + second_var + ");"
|
||||||
text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "___tmp);"
|
|
||||||
elif types[0].name in classnames:
|
|
||||||
text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "));"
|
|
||||||
text += prefix + "}"
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
#Associate the Translators with their c++ type
|
#Associate the Translators with their c++ type
|
||||||
|
|
|
@ -532,10 +532,10 @@ struct EquivMakePass : public Pass {
|
||||||
log_cmd_error("Equiv module %s already exists.\n", args[argidx+2].c_str());
|
log_cmd_error("Equiv module %s already exists.\n", args[argidx+2].c_str());
|
||||||
|
|
||||||
if (worker.gold_mod->has_memories() || worker.gold_mod->has_processes())
|
if (worker.gold_mod->has_memories() || worker.gold_mod->has_processes())
|
||||||
log_cmd_error("Gold module contains memories or procresses. Run 'memory' or 'proc' respectively.\n");
|
log_cmd_error("Gold module contains memories or processes. Run 'memory' or 'proc' respectively.\n");
|
||||||
|
|
||||||
if (worker.gate_mod->has_memories() || worker.gate_mod->has_processes())
|
if (worker.gate_mod->has_memories() || worker.gate_mod->has_processes())
|
||||||
log_cmd_error("Gate module contains memories or procresses. Run 'memory' or 'proc' respectively.\n");
|
log_cmd_error("Gate module contains memories or processes. Run 'memory' or 'proc' respectively.\n");
|
||||||
|
|
||||||
worker.read_blacklists();
|
worker.read_blacklists();
|
||||||
worker.read_encfiles();
|
worker.read_encfiles();
|
||||||
|
|
|
@ -369,7 +369,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
if (design->selected(module, cell) && cell->type[0] == '$') {
|
if (design->selected(module, cell) && cell->type[0] == '$') {
|
||||||
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) &&
|
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) &&
|
||||||
cell->getPort(ID::A).size() == 1 && cell->getPort(ID::Y).size() == 1)
|
GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1)
|
||||||
invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A));
|
invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A));
|
||||||
if (cell->type.in(ID($mux), ID($_MUX_)) &&
|
if (cell->type.in(ID($mux), ID($_MUX_)) &&
|
||||||
cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0))
|
cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0))
|
||||||
|
@ -740,12 +740,34 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
|
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
|
||||||
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx);
|
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx);
|
||||||
else
|
else
|
||||||
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort(ID::Y).size()));
|
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, GetSize(cell->getPort(ID::Y))));
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID::Y).size() == 1 &&
|
if (cell->type.in(ID($shiftx), ID($shift))) {
|
||||||
|
SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
|
int width;
|
||||||
|
bool trim_x = cell->type == ID($shiftx) || !keepdc;
|
||||||
|
bool trim_0 = cell->type == ID($shift);
|
||||||
|
for (width = GetSize(sig_a); width > 1; width--) {
|
||||||
|
if ((trim_x && sig_a[width-1] == State::Sx) ||
|
||||||
|
(trim_0 && sig_a[width-1] == State::S0))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width < GetSize(sig_a)) {
|
||||||
|
cover_list("opt.opt_expr.trim", "$shiftx", "$shift", cell->type.str());
|
||||||
|
sig_a.remove(width, GetSize(sig_a)-width);
|
||||||
|
cell->setPort(ID::A, sig_a);
|
||||||
|
cell->setParam(ID(A_WIDTH), width);
|
||||||
|
did_something = true;
|
||||||
|
goto next_cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(ID::Y)) == 1 &&
|
||||||
invert_map.count(assign_map(cell->getPort(ID::A))) != 0) {
|
invert_map.count(assign_map(cell->getPort(ID::A))) != 0) {
|
||||||
cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
|
cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
|
||||||
replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A))));
|
replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A))));
|
||||||
|
@ -1142,7 +1164,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (mux_undef && cell->type.in(ID($mux), ID($pmux))) {
|
if (mux_undef && cell->type.in(ID($mux), ID($pmux))) {
|
||||||
RTLIL::SigSpec new_a, new_b, new_s;
|
RTLIL::SigSpec new_a, new_b, new_s;
|
||||||
int width = cell->getPort(ID::A).size();
|
int width = GetSize(cell->getPort(ID::A));
|
||||||
if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) ||
|
if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) ||
|
||||||
cell->getPort(ID(S)).is_fully_undef()) {
|
cell->getPort(ID(S)).is_fully_undef()) {
|
||||||
cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
|
cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
||||||
OBJS += passes/pmgen/test_pmgen.o
|
OBJS += passes/pmgen/test_pmgen.o
|
||||||
passes/pmgen/test_pmgen.o: 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
|
||||||
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
|
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
@ -23,7 +23,7 @@ $(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h))
|
||||||
|
|
||||||
OBJS += passes/pmgen/xilinx_dsp.o
|
OBJS += passes/pmgen/xilinx_dsp.o
|
||||||
passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h
|
passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h
|
||||||
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp.h))
|
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h))
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,45 @@ evaluates to `false`.
|
||||||
The `semioptional` statement marks matches that must match if at least one
|
The `semioptional` statement marks matches that must match if at least one
|
||||||
matching cell exists, but if no matching cell exists it is set to `nullptr`.
|
matching cell exists, but if no matching cell exists it is set to `nullptr`.
|
||||||
|
|
||||||
|
Slices and choices
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Cell matches can contain "slices" and "choices". Slices can be used to
|
||||||
|
create matches for different sections of a cell. For example:
|
||||||
|
|
||||||
|
state <int> pmux_slice
|
||||||
|
|
||||||
|
match pmux
|
||||||
|
select pmux->type == $pmux
|
||||||
|
slice idx GetSize(port(pmux, \S))
|
||||||
|
index <SigBit> port(pmux, \S)[idx] === port(eq, \Y)
|
||||||
|
set pmux_slice idx
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
The first argument to `slice` is the local variable name used to identify the
|
||||||
|
slice. The second argument is the number of slices that should be created for
|
||||||
|
this cell. The `set` statement can be used to copy that index into a state
|
||||||
|
variable so that later matches and/or code blocks can refer to it.
|
||||||
|
|
||||||
|
A similar mechanism is "choices", where a list of options is given as
|
||||||
|
second argument, and the matcher will iterate over those options:
|
||||||
|
|
||||||
|
state <SigSpec> foo bar
|
||||||
|
state <IdString> eq_ab eq_ba
|
||||||
|
|
||||||
|
match eq
|
||||||
|
select eq->type == $eq
|
||||||
|
choice <IdString> AB {\A, \B}
|
||||||
|
define <IdString> BA (AB == \A ? \B : \A)
|
||||||
|
index <SigSpec> port(eq, AB) === foo
|
||||||
|
index <SigSpec> port(eq, BA) === bar
|
||||||
|
set eq_ab AB
|
||||||
|
set eq_ba BA
|
||||||
|
generate
|
||||||
|
|
||||||
|
Notice how `define` can be used to define additional local variables similar
|
||||||
|
to the loop variables defined by `slice` and `choice`.
|
||||||
|
|
||||||
Additional code
|
Additional code
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -326,7 +365,7 @@ test-case generation. For example:
|
||||||
|
|
||||||
match mul
|
match mul
|
||||||
...
|
...
|
||||||
generate 10
|
generate 10 0
|
||||||
SigSpec Y = port(ff, \D);
|
SigSpec Y = port(ff, \D);
|
||||||
SigSpec A = module->addWire(NEW_ID, GetSize(Y) - rng(GetSize(Y)/2));
|
SigSpec A = module->addWire(NEW_ID, GetSize(Y) - rng(GetSize(Y)/2));
|
||||||
SigSpec B = module->addWire(NEW_ID, GetSize(Y) - rng(GetSize(Y)/2));
|
SigSpec B = module->addWire(NEW_ID, GetSize(Y) - rng(GetSize(Y)/2));
|
||||||
|
@ -335,8 +374,11 @@ test-case generation. For example:
|
||||||
|
|
||||||
The expression `rng(n)` returns a non-negative integer less than `n`.
|
The expression `rng(n)` returns a non-negative integer less than `n`.
|
||||||
|
|
||||||
The argument to `generate` is the chance of this generate block being executed
|
The first argument to `generate` is the chance of this generate block being
|
||||||
when the match block did not match anything, in percent.
|
executed when the match block did not match anything, in percent.
|
||||||
|
|
||||||
|
The second argument to `generate` is the chance of this generate block being
|
||||||
|
executed when the match block did match something, in percent.
|
||||||
|
|
||||||
The special statement `finish` can be used within generate blocks to terminate
|
The special statement `finish` can be used within generate blocks to terminate
|
||||||
the current pattern matcher run.
|
the current pattern matcher run.
|
||||||
|
|
|
@ -207,9 +207,10 @@ def process_pmgfile(f, filename):
|
||||||
state_types[current_pattern][line[1]] = "Cell*";
|
state_types[current_pattern][line[1]] = "Cell*";
|
||||||
|
|
||||||
block["if"] = list()
|
block["if"] = list()
|
||||||
block["select"] = list()
|
block["setup"] = list()
|
||||||
block["index"] = list()
|
block["index"] = list()
|
||||||
block["filter"] = list()
|
block["filter"] = list()
|
||||||
|
block["sets"] = list()
|
||||||
block["optional"] = False
|
block["optional"] = False
|
||||||
block["semioptional"] = False
|
block["semioptional"] = False
|
||||||
|
|
||||||
|
@ -228,7 +229,22 @@ def process_pmgfile(f, filename):
|
||||||
|
|
||||||
if a[0] == "select":
|
if a[0] == "select":
|
||||||
b = l.lstrip()[6:]
|
b = l.lstrip()[6:]
|
||||||
block["select"].append(rewrite_cpp(b.strip()))
|
block["setup"].append(("select", rewrite_cpp(b.strip())))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if a[0] == "slice":
|
||||||
|
m = re.match(r"^\s*slice\s+(\S+)\s+(.*?)\s*$", l)
|
||||||
|
block["setup"].append(("slice", m.group(1), rewrite_cpp(m.group(2))))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if a[0] == "choice":
|
||||||
|
m = re.match(r"^\s*choice\s+<(.*?)>\s+(\S+)\s+(.*?)\s*$", l)
|
||||||
|
block["setup"].append(("choice", m.group(1), m.group(2), rewrite_cpp(m.group(3))))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if a[0] == "define":
|
||||||
|
m = re.match(r"^\s*define\s+<(.*?)>\s+(\S+)\s+(.*?)\s*$", l)
|
||||||
|
block["setup"].append(("define", m.group(1), m.group(2), rewrite_cpp(m.group(3))))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if a[0] == "index":
|
if a[0] == "index":
|
||||||
|
@ -242,6 +258,11 @@ def process_pmgfile(f, filename):
|
||||||
block["filter"].append(rewrite_cpp(b.strip()))
|
block["filter"].append(rewrite_cpp(b.strip()))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if a[0] == "set":
|
||||||
|
m = re.match(r"^\s*set\s+(\S+)\s+(.*?)\s*$", l)
|
||||||
|
block["sets"].append((m.group(1), rewrite_cpp(m.group(2))))
|
||||||
|
continue
|
||||||
|
|
||||||
if a[0] == "optional":
|
if a[0] == "optional":
|
||||||
block["optional"] = True
|
block["optional"] = True
|
||||||
continue
|
continue
|
||||||
|
@ -252,14 +273,16 @@ def process_pmgfile(f, filename):
|
||||||
|
|
||||||
if a[0] == "generate":
|
if a[0] == "generate":
|
||||||
block["genargs"] = list([int(s) for s in a[1:]])
|
block["genargs"] = list([int(s) for s in a[1:]])
|
||||||
|
if len(block["genargs"]) == 0: block["genargs"].append(100)
|
||||||
|
if len(block["genargs"]) == 1: block["genargs"].append(0)
|
||||||
|
assert len(block["genargs"]) == 2
|
||||||
block["gencode"] = list()
|
block["gencode"] = list()
|
||||||
assert len(block["genargs"]) < 2
|
|
||||||
while True:
|
while True:
|
||||||
linenr += 1
|
linenr += 1
|
||||||
l = f.readline()
|
l = f.readline()
|
||||||
assert l != ""
|
assert l != ""
|
||||||
a = l.split()
|
a = l.split()
|
||||||
if a[0] == "endmatch": break
|
if len(a) == 1 and a[0] == "endmatch": break
|
||||||
block["gencode"].append(rewrite_cpp(l.rstrip()))
|
block["gencode"].append(rewrite_cpp(l.rstrip()))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -357,8 +380,17 @@ with open(outfile, "w") as f:
|
||||||
index_types = list()
|
index_types = list()
|
||||||
for entry in block["index"]:
|
for entry in block["index"]:
|
||||||
index_types.append(entry[0])
|
index_types.append(entry[0])
|
||||||
|
value_types = ["Cell*"]
|
||||||
|
for entry in block["setup"]:
|
||||||
|
if entry[0] == "slice":
|
||||||
|
value_types.append("int")
|
||||||
|
if entry[0] == "choice":
|
||||||
|
value_types.append(entry[1])
|
||||||
|
if entry[0] == "define":
|
||||||
|
value_types.append(entry[1])
|
||||||
print(" typedef std::tuple<{}> index_{}_key_type;".format(", ".join(index_types), index), file=f)
|
print(" typedef std::tuple<{}> index_{}_key_type;".format(", ".join(index_types), index), file=f)
|
||||||
print(" dict<index_{}_key_type, vector<Cell*>> index_{};".format(index, index), file=f)
|
print(" typedef std::tuple<{}> index_{}_value_type;".format(", ".join(value_types), index), file=f)
|
||||||
|
print(" dict<index_{}_key_type, vector<index_{}_value_type>> index_{};".format(index, index, index), file=f)
|
||||||
print(" dict<SigBit, pool<Cell*>> sigusers;", file=f)
|
print(" dict<SigBit, pool<Cell*>> sigusers;", file=f)
|
||||||
print(" pool<Cell*> blacklist_cells;", file=f)
|
print(" pool<Cell*> blacklist_cells;", file=f)
|
||||||
print(" pool<Cell*> autoremove_cells;", file=f)
|
print(" pool<Cell*> autoremove_cells;", file=f)
|
||||||
|
@ -390,8 +422,6 @@ with open(outfile, "w") as f:
|
||||||
print(" void add_siguser(const SigSpec &sig, Cell *cell) {", file=f)
|
print(" void add_siguser(const SigSpec &sig, Cell *cell) {", file=f)
|
||||||
print(" for (auto bit : sigmap(sig)) {", file=f)
|
print(" for (auto bit : sigmap(sig)) {", file=f)
|
||||||
print(" if (bit.wire == nullptr) continue;", file=f)
|
print(" if (bit.wire == nullptr) continue;", file=f)
|
||||||
print(" if (sigusers.count(bit) == 0 && bit.wire->port_id)", file=f)
|
|
||||||
print(" sigusers[bit].insert(nullptr);", file=f)
|
|
||||||
print(" sigusers[bit].insert(cell);", file=f)
|
print(" sigusers[bit].insert(cell);", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
|
@ -446,10 +476,11 @@ with open(outfile, "w") as f:
|
||||||
else:
|
else:
|
||||||
print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f)
|
print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f)
|
||||||
current_pattern = None
|
current_pattern = None
|
||||||
print(" for (auto cell : module->cells()) {", file=f)
|
print(" for (auto port : module->ports)", file=f)
|
||||||
|
print(" add_siguser(module->wire(port), nullptr);", file=f)
|
||||||
|
print(" for (auto cell : module->cells())", file=f)
|
||||||
print(" for (auto &conn : cell->connections())", file=f)
|
print(" for (auto &conn : cell->connections())", file=f)
|
||||||
print(" add_siguser(conn.second, cell);", file=f)
|
print(" add_siguser(conn.second, cell);", file=f)
|
||||||
print(" }", file=f)
|
|
||||||
print(" for (auto cell : cells) {", file=f)
|
print(" for (auto cell : cells) {", file=f)
|
||||||
|
|
||||||
for index in range(len(blocks)):
|
for index in range(len(blocks)):
|
||||||
|
@ -457,12 +488,34 @@ with open(outfile, "w") as f:
|
||||||
if block["type"] == "match":
|
if block["type"] == "match":
|
||||||
print(" do {", file=f)
|
print(" do {", file=f)
|
||||||
print(" Cell *{} = cell;".format(block["cell"]), file=f)
|
print(" Cell *{} = cell;".format(block["cell"]), file=f)
|
||||||
for expr in block["select"]:
|
print(" index_{}_value_type value;".format(index), file=f)
|
||||||
print(" if (!({})) break;".format(expr), file=f)
|
print(" std::get<0>(value) = cell;", file=f)
|
||||||
|
loopcnt = 0
|
||||||
|
valueidx = 1
|
||||||
|
for item in block["setup"]:
|
||||||
|
if item[0] == "select":
|
||||||
|
print(" if (!({})) continue;".format(item[1]), file=f)
|
||||||
|
if item[0] == "slice":
|
||||||
|
print(" int &{} = std::get<{}>(value);".format(item[1], valueidx), file=f)
|
||||||
|
print(" for ({} = 0; {} < {}; {}++) {{".format(item[1], item[1], item[2], item[1]), file=f)
|
||||||
|
valueidx += 1
|
||||||
|
loopcnt += 1
|
||||||
|
if item[0] == "choice":
|
||||||
|
print(" vector<{}> _pmg_choices_{} = {};".format(item[1], item[2], item[3]), file=f)
|
||||||
|
print(" for (const {} &{} : _pmg_choices_{}) {{".format(item[1], item[2], item[2]), file=f)
|
||||||
|
print(" std::get<{}>(value) = {};".format(valueidx, item[2]), file=f)
|
||||||
|
valueidx += 1
|
||||||
|
loopcnt += 1
|
||||||
|
if item[0] == "define":
|
||||||
|
print(" {} &{} = std::get<{}>(value);".format(item[1], item[2], valueidx), file=f)
|
||||||
|
print(" {} = {};".format(item[2], item[3]), file=f)
|
||||||
|
valueidx += 1
|
||||||
print(" index_{}_key_type key;".format(index), file=f)
|
print(" index_{}_key_type key;".format(index), file=f)
|
||||||
for field, entry in enumerate(block["index"]):
|
for field, entry in enumerate(block["index"]):
|
||||||
print(" std::get<{}>(key) = {};".format(field, entry[1]), file=f)
|
print(" std::get<{}>(key) = {};".format(field, entry[1]), file=f)
|
||||||
print(" index_{}[key].push_back(cell);".format(index), file=f)
|
print(" index_{}[key].push_back(value);".format(index), file=f)
|
||||||
|
for i in range(loopcnt):
|
||||||
|
print(" }", file=f)
|
||||||
print(" } while (0);", file=f)
|
print(" } while (0);", file=f)
|
||||||
|
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
|
@ -535,6 +588,8 @@ with open(outfile, "w") as f:
|
||||||
const_st.add(s)
|
const_st.add(s)
|
||||||
elif blocks[i]["type"] == "match":
|
elif blocks[i]["type"] == "match":
|
||||||
const_st.add(blocks[i]["cell"])
|
const_st.add(blocks[i]["cell"])
|
||||||
|
for item in blocks[i]["sets"]:
|
||||||
|
const_st.add(item[0])
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
@ -548,6 +603,10 @@ with open(outfile, "w") as f:
|
||||||
s = block["cell"]
|
s = block["cell"]
|
||||||
assert s not in const_st
|
assert s not in const_st
|
||||||
nonconst_st.add(s)
|
nonconst_st.add(s)
|
||||||
|
for item in block["sets"]:
|
||||||
|
if item[0] in const_st:
|
||||||
|
const_st.remove(item[0])
|
||||||
|
nonconst_st.add(item[0])
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
@ -570,7 +629,7 @@ with open(outfile, "w") as f:
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
for s in sorted(restore_st):
|
for s in sorted(restore_st):
|
||||||
t = state_types[current_pattern][s]
|
t = state_types[current_pattern][s]
|
||||||
print(" {} backup_{} = {};".format(t, s, s), file=f)
|
print(" {} _pmg_backup_{} = {};".format(t, s, s), file=f)
|
||||||
|
|
||||||
if block["type"] == "code":
|
if block["type"] == "code":
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
@ -610,7 +669,7 @@ with open(outfile, "w") as f:
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
for s in sorted(restore_st):
|
for s in sorted(restore_st):
|
||||||
t = state_types[current_pattern][s]
|
t = state_types[current_pattern][s]
|
||||||
print(" {} = backup_{};".format(s, s), file=f)
|
print(" {} = _pmg_backup_{};".format(s, s), file=f)
|
||||||
for s in sorted(nonconst_st):
|
for s in sorted(nonconst_st):
|
||||||
if s not in restore_st:
|
if s not in restore_st:
|
||||||
t = state_types[current_pattern][s]
|
t = state_types[current_pattern][s]
|
||||||
|
@ -622,7 +681,7 @@ with open(outfile, "w") as f:
|
||||||
elif block["type"] == "match":
|
elif block["type"] == "match":
|
||||||
assert len(restore_st) == 0
|
assert len(restore_st) == 0
|
||||||
|
|
||||||
print(" Cell* backup_{} = {};".format(block["cell"], block["cell"]), file=f)
|
print(" Cell* _pmg_backup_{} = {};".format(block["cell"], block["cell"]), file=f)
|
||||||
|
|
||||||
if len(block["if"]):
|
if len(block["if"]):
|
||||||
for expr in block["if"]:
|
for expr in block["if"]:
|
||||||
|
@ -630,7 +689,7 @@ with open(outfile, "w") as f:
|
||||||
print(" if (!({})) {{".format(expr), file=f)
|
print(" if (!({})) {{".format(expr), file=f)
|
||||||
print(" {} = nullptr;".format(block["cell"]), file=f)
|
print(" {} = nullptr;".format(block["cell"]), file=f)
|
||||||
print(" block_{}(recursion+1);".format(index+1), file=f)
|
print(" block_{}(recursion+1);".format(index+1), file=f)
|
||||||
print(" {} = backup_{};".format(block["cell"], block["cell"]), file=f)
|
print(" {} = _pmg_backup_{};".format(block["cell"], block["cell"]), file=f)
|
||||||
print(" return;", file=f)
|
print(" return;", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
|
|
||||||
|
@ -645,21 +704,37 @@ with open(outfile, "w") as f:
|
||||||
|
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" if (cells_ptr != index_{}.end()) {{".format(index), file=f)
|
print(" if (cells_ptr != index_{}.end()) {{".format(index), file=f)
|
||||||
print(" const vector<Cell*> &cells = cells_ptr->second;".format(index), file=f)
|
print(" const vector<index_{}_value_type> &cells = cells_ptr->second;".format(index), file=f)
|
||||||
print(" for (int idx = 0; idx < GetSize(cells); idx++) {", file=f)
|
print(" for (int _pmg_idx = 0; _pmg_idx < GetSize(cells); _pmg_idx++) {", file=f)
|
||||||
print(" {} = cells[idx];".format(block["cell"]), file=f)
|
print(" {} = std::get<0>(cells[_pmg_idx]);".format(block["cell"]), file=f)
|
||||||
|
valueidx = 1
|
||||||
|
for item in block["setup"]:
|
||||||
|
if item[0] == "slice":
|
||||||
|
print(" const int &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], valueidx), file=f)
|
||||||
|
valueidx += 1
|
||||||
|
if item[0] == "choice":
|
||||||
|
print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
|
||||||
|
valueidx += 1
|
||||||
|
if item[0] == "define":
|
||||||
|
print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
|
||||||
|
valueidx += 1
|
||||||
print(" if (blacklist_cells.count({})) continue;".format(block["cell"]), file=f)
|
print(" if (blacklist_cells.count({})) continue;".format(block["cell"]), file=f)
|
||||||
for expr in block["filter"]:
|
for expr in block["filter"]:
|
||||||
print(" if (!({})) continue;".format(expr), file=f)
|
print(" if (!({})) continue;".format(expr), file=f)
|
||||||
if block["semioptional"] or block["genargs"] is not None:
|
if block["semioptional"] or block["genargs"] is not None:
|
||||||
print(" found_any_match = true;", file=f)
|
print(" found_any_match = true;", file=f)
|
||||||
print(" auto rollback_ptr = rollback_cache.insert(make_pair(cells[idx], recursion));", file=f)
|
for item in block["sets"]:
|
||||||
|
print(" auto _pmg_backup_{} = {};".format(item[0], item[0]), file=f)
|
||||||
|
print(" {} = {};".format(item[0], item[1]), file=f)
|
||||||
|
print(" auto rollback_ptr = rollback_cache.insert(make_pair(std::get<0>(cells[_pmg_idx]), recursion));", file=f)
|
||||||
print(" block_{}(recursion+1);".format(index+1), file=f)
|
print(" block_{}(recursion+1);".format(index+1), file=f)
|
||||||
|
for item in block["sets"]:
|
||||||
|
print(" {} = _pmg_backup_{};".format(item[0], item[0]), file=f)
|
||||||
print(" if (rollback_ptr.second)", file=f)
|
print(" if (rollback_ptr.second)", file=f)
|
||||||
print(" rollback_cache.erase(rollback_ptr.first);", file=f)
|
print(" rollback_cache.erase(rollback_ptr.first);", file=f)
|
||||||
print(" if (rollback) {", file=f)
|
print(" if (rollback) {", file=f)
|
||||||
print(" if (rollback != recursion) {{".format(index+1), file=f)
|
print(" if (rollback != recursion) {{".format(index+1), file=f)
|
||||||
print(" {} = backup_{};".format(block["cell"], block["cell"]), file=f)
|
print(" {} = _pmg_backup_{};".format(block["cell"], block["cell"]), file=f)
|
||||||
print(" return;", file=f)
|
print(" return;", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print(" rollback = 0;", file=f)
|
print(" rollback = 0;", file=f)
|
||||||
|
@ -676,13 +751,11 @@ with open(outfile, "w") as f:
|
||||||
if block["semioptional"]:
|
if block["semioptional"]:
|
||||||
print(" if (!found_any_match) block_{}(recursion+1);".format(index+1), file=f)
|
print(" if (!found_any_match) block_{}(recursion+1);".format(index+1), file=f)
|
||||||
|
|
||||||
print(" {} = backup_{};".format(block["cell"], block["cell"]), file=f)
|
print(" {} = _pmg_backup_{};".format(block["cell"], block["cell"]), file=f)
|
||||||
|
|
||||||
if block["genargs"] is not None:
|
if block["genargs"] is not None:
|
||||||
print("#define finish do { rollback = -1; return; } while(0)", file=f)
|
print("#define finish do { rollback = -1; return; } while(0)", file=f)
|
||||||
print(" if (generate_mode && !found_any_match) {", file=f)
|
print(" if (generate_mode && rng(100) < (found_any_match ? {} : {})) {{".format(block["genargs"][1], block["genargs"][0]), file=f)
|
||||||
if len(block["genargs"]) == 1:
|
|
||||||
print(" if (rng(100) >= {}) return;".format(block["genargs"][0]), file=f)
|
|
||||||
for line in block["gencode"]:
|
for line in block["gencode"]:
|
||||||
print(" " + line, file=f)
|
print(" " + line, file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
|
|
|
@ -99,6 +99,24 @@ void reduce_tree(test_pmgen_pm &pm)
|
||||||
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
|
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opt_eqpmux(test_pmgen_pm &pm)
|
||||||
|
{
|
||||||
|
auto &st = pm.st_eqpmux;
|
||||||
|
|
||||||
|
SigSpec Y = st.pmux->getPort(ID::Y);
|
||||||
|
int width = GetSize(Y);
|
||||||
|
|
||||||
|
SigSpec EQ = st.pmux->getPort(ID::B).extract(st.pmux_slice_eq*width, width);
|
||||||
|
SigSpec NE = st.pmux->getPort(ID::B).extract(st.pmux_slice_ne*width, width);
|
||||||
|
|
||||||
|
log("Found eqpmux circuit driving %s (eq=%s, ne=%s, pmux=%s).\n",
|
||||||
|
log_signal(Y), log_id(st.eq), log_id(st.ne), log_id(st.pmux));
|
||||||
|
|
||||||
|
pm.autoremove(st.pmux);
|
||||||
|
Cell *c = pm.module->addMux(NEW_ID, NE, EQ, st.eq->getPort(ID::Y), Y);
|
||||||
|
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
|
||||||
|
}
|
||||||
|
|
||||||
#define GENERATE_PATTERN(pmclass, pattern) \
|
#define GENERATE_PATTERN(pmclass, pattern) \
|
||||||
generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
|
generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
|
||||||
|
|
||||||
|
@ -149,16 +167,17 @@ void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const
|
||||||
log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
|
log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
|
||||||
|
|
||||||
int modcnt = 0;
|
int modcnt = 0;
|
||||||
|
int maxmodcnt = 100;
|
||||||
int maxsubcnt = 4;
|
int maxsubcnt = 4;
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
vector<Module*> mods;
|
vector<Module*> mods;
|
||||||
|
|
||||||
while (modcnt < 100)
|
while (modcnt < maxmodcnt)
|
||||||
{
|
{
|
||||||
int submodcnt = 0, itercnt = 0, cellcnt = 0;
|
int submodcnt = 0, itercnt = 0, cellcnt = 0;
|
||||||
Module *mod = design->addModule(NEW_ID);
|
Module *mod = design->addModule(NEW_ID);
|
||||||
|
|
||||||
while (modcnt < 100 && submodcnt < maxsubcnt && itercnt++ < 1000)
|
while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
|
||||||
{
|
{
|
||||||
if (timeout++ > 10000)
|
if (timeout++ > 10000)
|
||||||
log_error("pmgen generator is stuck: 10000 iterations an no matching module generated.\n");
|
log_error("pmgen generator is stuck: 10000 iterations an no matching module generated.\n");
|
||||||
|
@ -232,6 +251,12 @@ struct TestPmgenPass : public Pass {
|
||||||
log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
|
log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
|
||||||
|
log("\n");
|
||||||
|
log(" test_pmgen -eqpmux [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Demo for recursive pmgen patterns. Optimize EQ/NE/PMUX circuits.\n");
|
||||||
|
log("\n");
|
||||||
|
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" test_pmgen -generate [options] <pattern_name>\n");
|
log(" test_pmgen -generate [options] <pattern_name>\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -277,6 +302,25 @@ struct TestPmgenPass : public Pass {
|
||||||
test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
|
test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void execute_eqpmux(std::vector<std::string> args, RTLIL::Design *design)
|
||||||
|
{
|
||||||
|
log_header(design, "Executing TEST_PMGEN pass (-eqpmux).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 2; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-singleton") {
|
||||||
|
// singleton_mode = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
test_pmgen_pm(module, module->selected_cells()).run_eqpmux(opt_eqpmux);
|
||||||
|
}
|
||||||
|
|
||||||
void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
|
void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
|
||||||
{
|
{
|
||||||
log_header(design, "Executing TEST_PMGEN pass (-generate).\n");
|
log_header(design, "Executing TEST_PMGEN pass (-generate).\n");
|
||||||
|
@ -299,6 +343,9 @@ struct TestPmgenPass : public Pass {
|
||||||
if (pattern == "reduce")
|
if (pattern == "reduce")
|
||||||
return GENERATE_PATTERN(test_pmgen_pm, reduce);
|
return GENERATE_PATTERN(test_pmgen_pm, reduce);
|
||||||
|
|
||||||
|
if (pattern == "eqpmux")
|
||||||
|
return GENERATE_PATTERN(test_pmgen_pm, eqpmux);
|
||||||
|
|
||||||
if (pattern == "ice40_dsp")
|
if (pattern == "ice40_dsp")
|
||||||
return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
|
return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
|
||||||
|
|
||||||
|
@ -319,6 +366,8 @@ struct TestPmgenPass : public Pass {
|
||||||
return execute_reduce_chain(args, design);
|
return execute_reduce_chain(args, design);
|
||||||
if (args[1] == "-reduce_tree")
|
if (args[1] == "-reduce_tree")
|
||||||
return execute_reduce_tree(args, design);
|
return execute_reduce_tree(args, design);
|
||||||
|
if (args[1] == "-eqpmux")
|
||||||
|
return execute_eqpmux(args, design);
|
||||||
if (args[1] == "-generate")
|
if (args[1] == "-generate")
|
||||||
return execute_generate(args, design);
|
return execute_generate(args, design);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,8 @@ code portname
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
match next
|
match next
|
||||||
select nusers(port(next, \Y)) == 2
|
|
||||||
select next->type.in($_AND_, $_OR_, $_XOR_)
|
select next->type.in($_AND_, $_OR_, $_XOR_)
|
||||||
|
select nusers(port(next, \Y)) == 2
|
||||||
index <IdString> next->type === first->type
|
index <IdString> next->type === first->type
|
||||||
index <SigSpec> port(next, \Y) === port(first, portname)
|
index <SigSpec> port(next, \Y) === port(first, portname)
|
||||||
endmatch
|
endmatch
|
||||||
|
@ -77,8 +77,8 @@ arg first
|
||||||
|
|
||||||
match next
|
match next
|
||||||
semioptional
|
semioptional
|
||||||
select nusers(port(next, \Y)) == 2
|
|
||||||
select next->type.in($_AND_, $_OR_, $_XOR_)
|
select next->type.in($_AND_, $_OR_, $_XOR_)
|
||||||
|
select nusers(port(next, \Y)) == 2
|
||||||
index <IdString> next->type === chain.back().first->type
|
index <IdString> next->type === chain.back().first->type
|
||||||
index <SigSpec> port(next, \Y) === port(chain.back().first, chain.back().second)
|
index <SigSpec> port(next, \Y) === port(chain.back().first, chain.back().second)
|
||||||
generate 10
|
generate 10
|
||||||
|
@ -104,3 +104,86 @@ finally
|
||||||
if (next)
|
if (next)
|
||||||
chain.pop_back();
|
chain.pop_back();
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
// ==================================================================
|
||||||
|
|
||||||
|
pattern eqpmux
|
||||||
|
|
||||||
|
state <bool> eq_ne_signed
|
||||||
|
state <SigSpec> eq_inA eq_inB
|
||||||
|
state <int> pmux_slice_eq pmux_slice_ne
|
||||||
|
|
||||||
|
match eq
|
||||||
|
select eq->type == $eq
|
||||||
|
choice <IdString> AB {\A, \B}
|
||||||
|
define <IdString> BA AB == \A ? \B : \A
|
||||||
|
set eq_inA port(eq, \A)
|
||||||
|
set eq_inB port(eq, \B)
|
||||||
|
set eq_ne_signed param(eq, \A_SIGNED).as_bool()
|
||||||
|
generate 100 10
|
||||||
|
SigSpec A = module->addWire(NEW_ID, rng(7)+1);
|
||||||
|
SigSpec B = module->addWire(NEW_ID, rng(7)+1);
|
||||||
|
SigSpec Y = module->addWire(NEW_ID);
|
||||||
|
module->addEq(NEW_ID, A, B, Y, rng(2));
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match pmux
|
||||||
|
select pmux->type == $pmux
|
||||||
|
slice idx GetSize(port(pmux, \S))
|
||||||
|
index <SigBit> port(pmux, \S)[idx] === port(eq, \Y)
|
||||||
|
set pmux_slice_eq idx
|
||||||
|
generate 100 10
|
||||||
|
int width = rng(7) + 1;
|
||||||
|
int numsel = rng(4) + 1;
|
||||||
|
int idx = rng(numsel);
|
||||||
|
|
||||||
|
SigSpec A = module->addWire(NEW_ID, width);
|
||||||
|
SigSpec Y = module->addWire(NEW_ID, width);
|
||||||
|
|
||||||
|
SigSpec B, S;
|
||||||
|
for (int i = 0; i < numsel; i++) {
|
||||||
|
B.append(module->addWire(NEW_ID, width));
|
||||||
|
S.append(i == idx ? port(eq, \Y) : module->addWire(NEW_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
module->addPmux(NEW_ID, A, B, S, Y);
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match ne
|
||||||
|
select ne->type == $ne
|
||||||
|
choice <IdString> AB {\A, \B}
|
||||||
|
define <IdString> BA (AB == \A ? \B : \A)
|
||||||
|
index <SigSpec> port(ne, AB) === eq_inA
|
||||||
|
index <SigSpec> port(ne, BA) === eq_inB
|
||||||
|
index <int> param(ne, \A_SIGNED).as_bool() === eq_ne_signed
|
||||||
|
generate 100 10
|
||||||
|
SigSpec A = eq_inA, B = eq_inB, Y;
|
||||||
|
if (rng(2)) {
|
||||||
|
std::swap(A, B);
|
||||||
|
}
|
||||||
|
if (rng(2)) {
|
||||||
|
for (auto bit : port(pmux, \S)) {
|
||||||
|
if (nusers(bit) < 2)
|
||||||
|
Y.append(bit);
|
||||||
|
}
|
||||||
|
if (GetSize(Y))
|
||||||
|
Y = Y[rng(GetSize(Y))];
|
||||||
|
else
|
||||||
|
Y = module->addWire(NEW_ID);
|
||||||
|
} else {
|
||||||
|
Y = module->addWire(NEW_ID);
|
||||||
|
}
|
||||||
|
module->addNe(NEW_ID, A, B, Y, rng(2));
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match pmux2
|
||||||
|
select pmux2->type == $pmux
|
||||||
|
slice idx GetSize(port(pmux2, \S))
|
||||||
|
index <Cell*> pmux2 === pmux
|
||||||
|
index <SigBit> port(pmux2, \S)[idx] === port(ne, \Y)
|
||||||
|
set pmux_slice_ne idx
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
accept;
|
||||||
|
endcode
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct Async2syncPass : public Pass {
|
||||||
log("reset value in the next cycle regardless of the data-in value at the time of\n");
|
log("reset value in the next cycle regardless of the data-in value at the time of\n");
|
||||||
log("the clock edge.\n");
|
log("the clock edge.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Currently only $adff and $dffsr cells are supported by this pass.\n");
|
log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
@ -169,6 +169,41 @@ struct Async2syncPass : public Pass {
|
||||||
cell->type = "$dff";
|
cell->type = "$dff";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cell->type.in("$dlatch"))
|
||||||
|
{
|
||||||
|
bool en_pol = cell->parameters["\\EN_POLARITY"].as_bool();
|
||||||
|
|
||||||
|
SigSpec sig_en = cell->getPort("\\EN");
|
||||||
|
SigSpec sig_d = cell->getPort("\\D");
|
||||||
|
SigSpec sig_q = cell->getPort("\\Q");
|
||||||
|
|
||||||
|
log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
|
||||||
|
log_id(module), log_id(cell), log_id(cell->type),
|
||||||
|
log_signal(sig_en), log_signal(sig_d), log_signal(sig_q));
|
||||||
|
|
||||||
|
Const init_val;
|
||||||
|
for (int i = 0; i < GetSize(sig_q); i++) {
|
||||||
|
SigBit bit = sigmap(sig_q[i]);
|
||||||
|
init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
|
||||||
|
del_initbits.insert(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
|
||||||
|
new_q->attributes["\\init"] = init_val;
|
||||||
|
|
||||||
|
if (en_pol) {
|
||||||
|
module->addMux(NEW_ID, new_q, sig_d, sig_en, sig_q);
|
||||||
|
} else {
|
||||||
|
module->addMux(NEW_ID, sig_d, new_q, sig_en, sig_q);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->setPort("\\Q", new_q);
|
||||||
|
cell->unsetPort("\\EN");
|
||||||
|
cell->unsetParam("\\EN_POLARITY");
|
||||||
|
cell->type = "$ff";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
|
|
|
@ -268,7 +268,7 @@ struct SatHelper
|
||||||
RTLIL::SigSpec removed_bits;
|
RTLIL::SigSpec removed_bits;
|
||||||
for (int i = 0; i < lhs.size(); i++) {
|
for (int i = 0; i < lhs.size(); i++) {
|
||||||
RTLIL::SigSpec bit = lhs.extract(i, 1);
|
RTLIL::SigSpec bit = lhs.extract(i, 1);
|
||||||
if (!satgen.initial_state.check_all(bit)) {
|
if (rhs[i] == State::Sx || !satgen.initial_state.check_all(bit)) {
|
||||||
removed_bits.append(bit);
|
removed_bits.append(bit);
|
||||||
lhs.remove(i, 1);
|
lhs.remove(i, 1);
|
||||||
rhs.remove(i, 1);
|
rhs.remove(i, 1);
|
||||||
|
|
|
@ -16,6 +16,7 @@ endif
|
||||||
|
|
||||||
ifneq ($(SMALL),1)
|
ifneq ($(SMALL),1)
|
||||||
OBJS += passes/techmap/iopadmap.o
|
OBJS += passes/techmap/iopadmap.o
|
||||||
|
OBJS += passes/techmap/clkbufmap.o
|
||||||
OBJS += passes/techmap/hilomap.o
|
OBJS += passes/techmap/hilomap.o
|
||||||
OBJS += passes/techmap/extract.o
|
OBJS += passes/techmap/extract.o
|
||||||
OBJS += passes/techmap/extract_fa.o
|
OBJS += passes/techmap/extract_fa.o
|
||||||
|
|
|
@ -143,6 +143,82 @@ void attrmap_apply(string objname, vector<std::unique_ptr<AttrmapAction>> &actio
|
||||||
attributes.swap(new_attributes);
|
attributes.swap(new_attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log_attrmap_paramap_options()
|
||||||
|
{
|
||||||
|
log(" -tocase <name>\n");
|
||||||
|
log(" Match attribute names case-insensitively and set it to the specified\n");
|
||||||
|
log(" name.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -rename <old_name> <new_name>\n");
|
||||||
|
log(" Rename attributes as specified\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -map <old_name>=<old_value> <new_name>=<new_value>\n");
|
||||||
|
log(" Map key/value pairs as indicated.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -imap <old_name>=<old_value> <new_name>=<new_value>\n");
|
||||||
|
log(" Like -map, but use case-insensitive match for <old_value> when\n");
|
||||||
|
log(" it is a string value.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -remove <name>=<value>\n");
|
||||||
|
log(" Remove attributes matching this pattern.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_attrmap_paramap_options(size_t &argidx, std::vector<std::string> &args, vector<std::unique_ptr<AttrmapAction>> &actions)
|
||||||
|
{
|
||||||
|
std::string arg = args[argidx];
|
||||||
|
if (arg == "-tocase" && argidx+1 < args.size()) {
|
||||||
|
auto action = new AttrmapTocase;
|
||||||
|
action->name = args[++argidx];
|
||||||
|
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (arg == "-rename" && argidx+2 < args.size()) {
|
||||||
|
auto action = new AttrmapRename;
|
||||||
|
action->old_name = args[++argidx];
|
||||||
|
action->new_name = args[++argidx];
|
||||||
|
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((arg == "-map" || arg == "-imap") && argidx+2 < args.size()) {
|
||||||
|
string arg1 = args[++argidx];
|
||||||
|
string arg2 = args[++argidx];
|
||||||
|
string val1, val2;
|
||||||
|
size_t p = arg1.find("=");
|
||||||
|
if (p != string::npos) {
|
||||||
|
val1 = arg1.substr(p+1);
|
||||||
|
arg1 = arg1.substr(0, p);
|
||||||
|
}
|
||||||
|
p = arg2.find("=");
|
||||||
|
if (p != string::npos) {
|
||||||
|
val2 = arg2.substr(p+1);
|
||||||
|
arg2 = arg2.substr(0, p);
|
||||||
|
}
|
||||||
|
auto action = new AttrmapMap;
|
||||||
|
action->imap = (arg == "-map");
|
||||||
|
action->old_name = arg1;
|
||||||
|
action->new_name = arg2;
|
||||||
|
action->old_value = val1;
|
||||||
|
action->new_value = val2;
|
||||||
|
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (arg == "-remove" && argidx+1 < args.size()) {
|
||||||
|
string arg1 = args[++argidx], val1;
|
||||||
|
size_t p = arg1.find("=");
|
||||||
|
if (p != string::npos) {
|
||||||
|
val1 = arg1.substr(p+1);
|
||||||
|
arg1 = arg1.substr(0, p);
|
||||||
|
}
|
||||||
|
auto action = new AttrmapRemove;
|
||||||
|
action->name = arg1;
|
||||||
|
action->has_value = (p != string::npos);
|
||||||
|
action->value = val1;
|
||||||
|
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct AttrmapPass : public Pass {
|
struct AttrmapPass : public Pass {
|
||||||
AttrmapPass() : Pass("attrmap", "renaming attributes") { }
|
AttrmapPass() : Pass("attrmap", "renaming attributes") { }
|
||||||
void help() YS_OVERRIDE
|
void help() YS_OVERRIDE
|
||||||
|
@ -151,25 +227,10 @@ struct AttrmapPass : public Pass {
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" attrmap [options] [selection]\n");
|
log(" attrmap [options] [selection]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("This command renames attributes and/or mapps key/value pairs to\n");
|
log("This command renames attributes and/or maps key/value pairs to\n");
|
||||||
log("other key/value pairs.\n");
|
log("other key/value pairs.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -tocase <name>\n");
|
log_attrmap_paramap_options();
|
||||||
log(" Match attribute names case-insensitively and set it to the specified\n");
|
|
||||||
log(" name.\n");
|
|
||||||
log("\n");
|
|
||||||
log(" -rename <old_name> <new_name>\n");
|
|
||||||
log(" Rename attributes as specified\n");
|
|
||||||
log("\n");
|
|
||||||
log(" -map <old_name>=<old_value> <new_name>=<new_value>\n");
|
|
||||||
log(" Map key/value pairs as indicated.\n");
|
|
||||||
log("\n");
|
|
||||||
log(" -imap <old_name>=<old_value> <new_name>=<new_value>\n");
|
|
||||||
log(" Like -map, but use case-insensitive match for <old_value> when\n");
|
|
||||||
log(" it is a string value.\n");
|
|
||||||
log("\n");
|
|
||||||
log(" -remove <name>=<value>\n");
|
|
||||||
log(" Remove attributes matching this pattern.\n");
|
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -modattr\n");
|
log(" -modattr\n");
|
||||||
log(" Operate on module attributes instead of attributes on wires and cells.\n");
|
log(" Operate on module attributes instead of attributes on wires and cells.\n");
|
||||||
|
@ -190,58 +251,9 @@ struct AttrmapPass : public Pass {
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
{
|
{
|
||||||
std::string arg = args[argidx];
|
if (parse_attrmap_paramap_options(argidx, args, actions))
|
||||||
if (arg == "-tocase" && argidx+1 < args.size()) {
|
|
||||||
auto action = new AttrmapTocase;
|
|
||||||
action->name = args[++argidx];
|
|
||||||
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
if (args[argidx] == "-modattr") {
|
||||||
if (arg == "-rename" && argidx+2 < args.size()) {
|
|
||||||
auto action = new AttrmapRename;
|
|
||||||
action->old_name = args[++argidx];
|
|
||||||
action->new_name = args[++argidx];
|
|
||||||
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((arg == "-map" || arg == "-imap") && argidx+2 < args.size()) {
|
|
||||||
string arg1 = args[++argidx];
|
|
||||||
string arg2 = args[++argidx];
|
|
||||||
string val1, val2;
|
|
||||||
size_t p = arg1.find("=");
|
|
||||||
if (p != string::npos) {
|
|
||||||
val1 = arg1.substr(p+1);
|
|
||||||
arg1 = arg1.substr(0, p);
|
|
||||||
}
|
|
||||||
p = arg2.find("=");
|
|
||||||
if (p != string::npos) {
|
|
||||||
val2 = arg2.substr(p+1);
|
|
||||||
arg2 = arg2.substr(0, p);
|
|
||||||
}
|
|
||||||
auto action = new AttrmapMap;
|
|
||||||
action->imap = (arg == "-map");
|
|
||||||
action->old_name = arg1;
|
|
||||||
action->new_name = arg2;
|
|
||||||
action->old_value = val1;
|
|
||||||
action->new_value = val2;
|
|
||||||
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg == "-remove" && argidx+1 < args.size()) {
|
|
||||||
string arg1 = args[++argidx], val1;
|
|
||||||
size_t p = arg1.find("=");
|
|
||||||
if (p != string::npos) {
|
|
||||||
val1 = arg1.substr(p+1);
|
|
||||||
arg1 = arg1.substr(0, p);
|
|
||||||
}
|
|
||||||
auto action = new AttrmapRemove;
|
|
||||||
action->name = arg1;
|
|
||||||
action->has_value = (p != string::npos);
|
|
||||||
action->value = val1;
|
|
||||||
actions.push_back(std::unique_ptr<AttrmapAction>(action));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg == "-modattr") {
|
|
||||||
modattr_mode = true;
|
modattr_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -287,4 +299,43 @@ struct AttrmapPass : public Pass {
|
||||||
}
|
}
|
||||||
} AttrmapPass;
|
} AttrmapPass;
|
||||||
|
|
||||||
|
struct ParamapPass : public Pass {
|
||||||
|
ParamapPass() : Pass("paramap", "renaming cell parameters") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" paramap [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command renames cell parameters and/or maps key/value pairs to\n");
|
||||||
|
log("other key/value pairs.\n");
|
||||||
|
log("\n");
|
||||||
|
log_attrmap_paramap_options();
|
||||||
|
log("\n");
|
||||||
|
log("For example, mapping Diamond-style ECP5 \"init\" attributes to Yosys-style:\n");
|
||||||
|
log("\n");
|
||||||
|
log(" paramap -tocase INIT t:LUT4\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing PARAMAP pass (move or copy cell parameters).\n");
|
||||||
|
|
||||||
|
vector<std::unique_ptr<AttrmapAction>> actions;
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
if (parse_attrmap_paramap_options(argidx, args, actions))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->parameters);
|
||||||
|
}
|
||||||
|
} ParamapPass;
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_END
|
PRIVATE_NAMESPACE_END
|
||||||
|
|
298
passes/techmap/clkbufmap.cc
Normal file
298
passes/techmap/clkbufmap.cc
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
* Copyright (C) 2019 Marcin Kościelnicki <mwk@0x04.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
void split_portname_pair(std::string &port1, std::string &port2)
|
||||||
|
{
|
||||||
|
size_t pos = port1.find_first_of(':');
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
port2 = port1.substr(pos+1);
|
||||||
|
port1 = port1.substr(0, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ClkbufmapPass : public Pass {
|
||||||
|
ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" clkbufmap [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Inserts global buffers between nets connected to clock inputs and their drivers.\n");
|
||||||
|
log("\n");
|
||||||
|
log("In the absence of any selection, all wires without the 'clkbuf_inhibit'\n");
|
||||||
|
log("attribute will be considered for global buffer insertion.\n");
|
||||||
|
log("Alternatively, to consider all wires without the 'buffer_type' attribute set to\n");
|
||||||
|
log("'none' or 'bufr' one would specify:\n");
|
||||||
|
log(" 'w:* a:buffer_type=none a:buffer_type=bufr %%u %%d'\n");
|
||||||
|
log("as the selection.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -buf <celltype> <portname_out>:<portname_in>\n");
|
||||||
|
log(" Specifies the cell type to use for the global buffers\n");
|
||||||
|
log(" and its port names. The first port will be connected to\n");
|
||||||
|
log(" the clock network sinks, and the second will be connected\n");
|
||||||
|
log(" to the actual clock source. This option is required.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -inpad <celltype> <portname_out>:<portname_in>\n");
|
||||||
|
log(" If specified, a PAD cell of the given type is inserted on\n");
|
||||||
|
log(" clock nets that are also top module's inputs (in addition\n");
|
||||||
|
log(" to the global buffer).\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) {
|
||||||
|
if (modules_processed.count(module))
|
||||||
|
return;
|
||||||
|
for (auto cell : module->cells()) {
|
||||||
|
Module *submodule = design->module(cell->type);
|
||||||
|
if (!submodule)
|
||||||
|
continue;
|
||||||
|
module_queue(design, submodule, modules_sorted, modules_processed);
|
||||||
|
}
|
||||||
|
modules_sorted.push_back(module);
|
||||||
|
modules_processed.insert(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
|
||||||
|
|
||||||
|
std::string buf_celltype, buf_portname, buf_portname2;
|
||||||
|
std::string inpad_celltype, inpad_portname, inpad_portname2;
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
std::string arg = args[argidx];
|
||||||
|
if (arg == "-buf" && argidx+2 < args.size()) {
|
||||||
|
buf_celltype = args[++argidx];
|
||||||
|
buf_portname = args[++argidx];
|
||||||
|
split_portname_pair(buf_portname, buf_portname2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (arg == "-inpad" && argidx+2 < args.size()) {
|
||||||
|
inpad_celltype = args[++argidx];
|
||||||
|
inpad_portname = args[++argidx];
|
||||||
|
split_portname_pair(inpad_portname, inpad_portname2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool select = false;
|
||||||
|
if (argidx < args.size()) {
|
||||||
|
if (args[argidx].compare(0, 1, "-") != 0)
|
||||||
|
select = true;
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_celltype.empty())
|
||||||
|
log_error("The -buf option is required.\n");
|
||||||
|
|
||||||
|
// Cell type, port name, bit index.
|
||||||
|
pool<pair<IdString, pair<IdString, int>>> sink_ports;
|
||||||
|
pool<pair<IdString, pair<IdString, int>>> buf_ports;
|
||||||
|
|
||||||
|
// Process submodules before module using them.
|
||||||
|
std::vector<Module *> modules_sorted;
|
||||||
|
pool<Module *> modules_processed;
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
module_queue(design, module, modules_sorted, modules_processed);
|
||||||
|
|
||||||
|
for (auto module : modules_sorted)
|
||||||
|
{
|
||||||
|
if (module->get_blackbox_attribute()) {
|
||||||
|
for (auto port : module->ports) {
|
||||||
|
auto wire = module->wire(port);
|
||||||
|
if (wire->get_bool_attribute("\\clkbuf_driver"))
|
||||||
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
|
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
|
||||||
|
if (wire->get_bool_attribute("\\clkbuf_sink"))
|
||||||
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
|
sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pool<SigBit> sink_wire_bits;
|
||||||
|
pool<SigBit> buf_wire_bits;
|
||||||
|
pool<SigBit> driven_wire_bits;
|
||||||
|
SigMap sigmap(module);
|
||||||
|
// bit -> (buffer, buffer's input)
|
||||||
|
dict<SigBit, pair<Cell *, Wire *>> buffered_bits;
|
||||||
|
|
||||||
|
// First, collect nets that could use a clock buffer.
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
for (auto port : cell->connections())
|
||||||
|
for (int i = 0; i < port.second.size(); i++)
|
||||||
|
if (sink_ports.count(make_pair(cell->type, make_pair(port.first, i))))
|
||||||
|
sink_wire_bits.insert(sigmap(port.second[i]));
|
||||||
|
|
||||||
|
// Second, collect ones that already have a clock buffer.
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
for (auto port : cell->connections())
|
||||||
|
for (int i = 0; i < port.second.size(); i++)
|
||||||
|
if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i))))
|
||||||
|
buf_wire_bits.insert(sigmap(port.second[i]));
|
||||||
|
|
||||||
|
// Collect all driven bits.
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
for (auto port : cell->connections())
|
||||||
|
if (cell->output(port.first))
|
||||||
|
for (int i = 0; i < port.second.size(); i++)
|
||||||
|
driven_wire_bits.insert(port.second[i]);
|
||||||
|
|
||||||
|
// Insert buffers.
|
||||||
|
std::vector<pair<Wire *, Wire *>> input_queue;
|
||||||
|
// Copy current wire list, as we will be adding new ones during iteration.
|
||||||
|
std::vector<Wire *> wires(module->wires());
|
||||||
|
for (auto wire : wires)
|
||||||
|
{
|
||||||
|
// Should not happen.
|
||||||
|
if (wire->port_input && wire->port_output)
|
||||||
|
continue;
|
||||||
|
bool process_wire = module->selected(wire);
|
||||||
|
if (!select && wire->get_bool_attribute("\\clkbuf_inhibit"))
|
||||||
|
process_wire = false;
|
||||||
|
if (!process_wire) {
|
||||||
|
// This wire is supposed to be bypassed, so make sure we don't buffer it in
|
||||||
|
// some buffer higher up in the hierarchy.
|
||||||
|
if (wire->port_output)
|
||||||
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
|
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool<int> input_bits;
|
||||||
|
|
||||||
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
|
{
|
||||||
|
SigBit wire_bit(wire, i);
|
||||||
|
SigBit mapped_wire_bit = sigmap(wire_bit);
|
||||||
|
if (buf_wire_bits.count(mapped_wire_bit)) {
|
||||||
|
// Already buffered downstream. If this is an output, mark it.
|
||||||
|
if (wire->port_output)
|
||||||
|
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
|
||||||
|
} else if (!sink_wire_bits.count(mapped_wire_bit)) {
|
||||||
|
// Nothing to do.
|
||||||
|
} else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute("\\top"))) {
|
||||||
|
// Clock network not yet buffered, driven by one of
|
||||||
|
// our cells or a top-level input -- buffer it.
|
||||||
|
|
||||||
|
log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
|
||||||
|
RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
|
||||||
|
Wire *iwire = module->addWire(NEW_ID);
|
||||||
|
cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
|
||||||
|
cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
|
||||||
|
if (wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute("\\top")) {
|
||||||
|
log("Inserting %s on %s.%s[%d].\n", inpad_celltype.c_str(), log_id(module), log_id(wire), i);
|
||||||
|
RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype));
|
||||||
|
cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
|
||||||
|
iwire = module->addWire(NEW_ID);
|
||||||
|
cell2->setPort(RTLIL::escape_id(inpad_portname2), iwire);
|
||||||
|
}
|
||||||
|
buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
|
||||||
|
|
||||||
|
if (wire->port_input) {
|
||||||
|
input_bits.insert(i);
|
||||||
|
}
|
||||||
|
} else if (wire->port_input) {
|
||||||
|
// A clock input in a submodule -- mark it, let higher level
|
||||||
|
// worry about it.
|
||||||
|
if (wire->port_input)
|
||||||
|
sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!input_bits.empty()) {
|
||||||
|
// This is an input port and some buffers were inserted -- we need
|
||||||
|
// to create a new input wire and transfer attributes.
|
||||||
|
Wire *new_wire = module->addWire(NEW_ID, wire);
|
||||||
|
|
||||||
|
for (int i = 0; i < wire->width; i++) {
|
||||||
|
SigBit wire_bit(wire, i);
|
||||||
|
SigBit mapped_wire_bit = sigmap(wire_bit);
|
||||||
|
auto it = buffered_bits.find(mapped_wire_bit);
|
||||||
|
if (it != buffered_bits.end()) {
|
||||||
|
|
||||||
|
module->connect(it->second.second, SigSpec(new_wire, i));
|
||||||
|
} else {
|
||||||
|
module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input_queue.push_back(make_pair(wire, new_wire));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark any newly-buffered output ports as such.
|
||||||
|
for (auto wire : module->selected_wires()) {
|
||||||
|
if (wire->port_input || !wire->port_output)
|
||||||
|
continue;
|
||||||
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
|
{
|
||||||
|
SigBit wire_bit(wire, i);
|
||||||
|
SigBit mapped_wire_bit = sigmap(wire_bit);
|
||||||
|
if (buffered_bits.count(mapped_wire_bit))
|
||||||
|
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconnect the drivers to buffer inputs.
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
for (auto port : cell->connections()) {
|
||||||
|
if (!cell->output(port.first))
|
||||||
|
continue;
|
||||||
|
SigSpec sig = port.second;
|
||||||
|
bool newsig = false;
|
||||||
|
for (auto &bit : sig) {
|
||||||
|
const auto it = buffered_bits.find(sigmap(bit));
|
||||||
|
if (it == buffered_bits.end())
|
||||||
|
continue;
|
||||||
|
// Avoid substituting buffer's own output pin.
|
||||||
|
if (cell == it->second.first)
|
||||||
|
continue;
|
||||||
|
bit = it->second.second;
|
||||||
|
newsig = true;
|
||||||
|
}
|
||||||
|
if (newsig)
|
||||||
|
cell->setPort(port.first, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This has to be done last, to avoid upsetting sigmap before the port reconnections.
|
||||||
|
for (auto &it : input_queue) {
|
||||||
|
Wire *wire = it.first;
|
||||||
|
Wire *new_wire = it.second;
|
||||||
|
module->swap_names(new_wire, wire);
|
||||||
|
wire->attributes.clear();
|
||||||
|
wire->port_id = 0;
|
||||||
|
wire->port_input = false;
|
||||||
|
wire->port_output = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
module->fixup_ports();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ClkbufmapPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -64,6 +64,11 @@ struct IopadmapPass : public Pass {
|
||||||
log(" of the tristate driver and the 2nd portname is the internal output\n");
|
log(" of the tristate driver and the 2nd portname is the internal output\n");
|
||||||
log(" buffering the external signal.\n");
|
log(" buffering the external signal.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -ignore <celltype> <portname>[:<portname>]*\n");
|
||||||
|
log(" Skips mapping inputs/outputs that are already connected to given\n");
|
||||||
|
log(" ports of the given cell. Can be used multiple times. This is in\n");
|
||||||
|
log(" addition to the cells specified as mapping targets.\n");
|
||||||
|
log("\n");
|
||||||
log(" -widthparam <param_name>\n");
|
log(" -widthparam <param_name>\n");
|
||||||
log(" Use the specified parameter name to set the port width.\n");
|
log(" Use the specified parameter name to set the port width.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -88,6 +93,7 @@ struct IopadmapPass : public Pass {
|
||||||
std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3;
|
std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3;
|
||||||
std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4;
|
std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4;
|
||||||
std::string widthparam, nameparam;
|
std::string widthparam, nameparam;
|
||||||
|
pool<pair<IdString, IdString>> ignore;
|
||||||
bool flag_bits = false;
|
bool flag_bits = false;
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
|
@ -127,6 +133,18 @@ struct IopadmapPass : public Pass {
|
||||||
split_portname_pair(tinoutpad_portname3, tinoutpad_portname4);
|
split_portname_pair(tinoutpad_portname3, tinoutpad_portname4);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "-ignore" && argidx+2 < args.size()) {
|
||||||
|
std::string ignore_celltype = args[++argidx];
|
||||||
|
std::string ignore_portname = args[++argidx];
|
||||||
|
std::string ignore_portname2;
|
||||||
|
while (!ignore_portname.empty()) {
|
||||||
|
split_portname_pair(ignore_portname, ignore_portname2);
|
||||||
|
ignore.insert(make_pair(RTLIL::escape_id(ignore_celltype), RTLIL::escape_id(ignore_portname)));
|
||||||
|
|
||||||
|
ignore_portname = ignore_portname2;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg == "-widthparam" && argidx+1 < args.size()) {
|
if (arg == "-widthparam" && argidx+1 < args.size()) {
|
||||||
widthparam = args[++argidx];
|
widthparam = args[++argidx];
|
||||||
continue;
|
continue;
|
||||||
|
@ -143,6 +161,23 @@ struct IopadmapPass : public Pass {
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
if (!inpad_portname2.empty())
|
||||||
|
ignore.insert(make_pair(RTLIL::escape_id(inpad_celltype), RTLIL::escape_id(inpad_portname2)));
|
||||||
|
if (!outpad_portname2.empty())
|
||||||
|
ignore.insert(make_pair(RTLIL::escape_id(outpad_celltype), RTLIL::escape_id(outpad_portname2)));
|
||||||
|
if (!inoutpad_portname2.empty())
|
||||||
|
ignore.insert(make_pair(RTLIL::escape_id(inoutpad_celltype), RTLIL::escape_id(inoutpad_portname2)));
|
||||||
|
if (!toutpad_portname3.empty())
|
||||||
|
ignore.insert(make_pair(RTLIL::escape_id(toutpad_celltype), RTLIL::escape_id(toutpad_portname3)));
|
||||||
|
if (!tinoutpad_portname4.empty())
|
||||||
|
ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname4)));
|
||||||
|
|
||||||
|
for (auto module : design->modules())
|
||||||
|
if (module->get_blackbox_attribute())
|
||||||
|
for (auto wire : module->wires())
|
||||||
|
if (wire->get_bool_attribute("\\iopad_external_pin"))
|
||||||
|
ignore.insert(make_pair(module->name, wire->name));
|
||||||
|
|
||||||
for (auto module : design->selected_modules())
|
for (auto module : design->selected_modules())
|
||||||
{
|
{
|
||||||
dict<IdString, pool<int>> skip_wires;
|
dict<IdString, pool<int>> skip_wires;
|
||||||
|
@ -150,28 +185,11 @@ struct IopadmapPass : public Pass {
|
||||||
SigMap sigmap(module);
|
SigMap sigmap(module);
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
{
|
for (auto port : cell->connections())
|
||||||
if (cell->type == RTLIL::escape_id(inpad_celltype) && cell->hasPort(RTLIL::escape_id(inpad_portname2)))
|
if (ignore.count(make_pair(cell->type, port.first)))
|
||||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inpad_portname2))))
|
for (auto bit : sigmap(port.second))
|
||||||
skip_wire_bits.insert(bit);
|
skip_wire_bits.insert(bit);
|
||||||
|
|
||||||
if (cell->type == RTLIL::escape_id(outpad_celltype) && cell->hasPort(RTLIL::escape_id(outpad_portname2)))
|
|
||||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(outpad_portname2))))
|
|
||||||
skip_wire_bits.insert(bit);
|
|
||||||
|
|
||||||
if (cell->type == RTLIL::escape_id(inoutpad_celltype) && cell->hasPort(RTLIL::escape_id(inoutpad_portname2)))
|
|
||||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inoutpad_portname2))))
|
|
||||||
skip_wire_bits.insert(bit);
|
|
||||||
|
|
||||||
if (cell->type == RTLIL::escape_id(toutpad_celltype) && cell->hasPort(RTLIL::escape_id(toutpad_portname3)))
|
|
||||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(toutpad_portname3))))
|
|
||||||
skip_wire_bits.insert(bit);
|
|
||||||
|
|
||||||
if (cell->type == RTLIL::escape_id(tinoutpad_celltype) && cell->hasPort(RTLIL::escape_id(tinoutpad_portname4)))
|
|
||||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(tinoutpad_portname4))))
|
|
||||||
skip_wire_bits.insert(bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
|
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
|
||||||
{
|
{
|
||||||
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
|
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
|
||||||
|
|
|
@ -346,7 +346,7 @@ struct ShregmapWorker
|
||||||
IdString q_port = opts.ffcells.at(c1->type).second;
|
IdString q_port = opts.ffcells.at(c1->type).second;
|
||||||
|
|
||||||
auto c1_conn = c1->connections();
|
auto c1_conn = c1->connections();
|
||||||
auto c2_conn = c1->connections();
|
auto c2_conn = c2->connections();
|
||||||
|
|
||||||
c1_conn.erase(d_port);
|
c1_conn.erase(d_port);
|
||||||
c1_conn.erase(q_port);
|
c1_conn.erase(q_port);
|
||||||
|
|
|
@ -943,7 +943,8 @@ struct TechmapPass : public Pass {
|
||||||
log(" instead of inlining them.\n");
|
log(" instead of inlining them.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -max_iter <number>\n");
|
log(" -max_iter <number>\n");
|
||||||
log(" only run the specified number of iterations.\n");
|
log(" only run the specified number of iterations on each module.\n");
|
||||||
|
log(" default: unlimited\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -recursive\n");
|
log(" -recursive\n");
|
||||||
log(" instead of the iterative breadth-first algorithm use a recursive\n");
|
log(" instead of the iterative breadth-first algorithm use a recursive\n");
|
||||||
|
@ -1157,15 +1158,16 @@ struct TechmapPass : public Pass {
|
||||||
RTLIL::Module *module = *worker.module_queue.begin();
|
RTLIL::Module *module = *worker.module_queue.begin();
|
||||||
worker.module_queue.erase(module);
|
worker.module_queue.erase(module);
|
||||||
|
|
||||||
|
int module_max_iter = max_iter;
|
||||||
bool did_something = true;
|
bool did_something = true;
|
||||||
std::set<RTLIL::Cell*> handled_cells;
|
std::set<RTLIL::Cell*> handled_cells;
|
||||||
while (did_something) {
|
while (did_something) {
|
||||||
did_something = false;
|
did_something = false;
|
||||||
if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false))
|
if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false))
|
||||||
did_something = true;
|
did_something = true;
|
||||||
if (did_something)
|
if (did_something)
|
||||||
module->check();
|
module->check();
|
||||||
if (max_iter > 0 && --max_iter == 0)
|
if (module_max_iter > 0 && --module_max_iter == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
OBJS += techlibs/anlogic/synth_anlogic.o
|
OBJS += techlibs/anlogic/synth_anlogic.o
|
||||||
OBJS += techlibs/anlogic/anlogic_eqn.o
|
OBJS += techlibs/anlogic/anlogic_eqn.o
|
||||||
OBJS += techlibs/anlogic/anlogic_determine_init.o
|
OBJS += techlibs/anlogic/anlogic_fixcarry.o
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
||||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* yosys -- Yosys Open SYnthesis Suite
|
|
||||||
*
|
|
||||||
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "kernel/yosys.h"
|
|
||||||
#include "kernel/sigtools.h"
|
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
struct AnlogicDetermineInitPass : public Pass {
|
|
||||||
AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { }
|
|
||||||
void help() YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log("\n");
|
|
||||||
log(" anlogic_determine_init [selection]\n");
|
|
||||||
log("\n");
|
|
||||||
log("Determine the init value of cells that doesn't allow unknown init value.\n");
|
|
||||||
log("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
Const determine_init(Const init)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < GetSize(init); i++) {
|
|
||||||
if (init[i] != State::S0 && init[i] != State::S1)
|
|
||||||
init[i] = State::S0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return init;
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log_header(design, "Executing ANLOGIC_DETERMINE_INIT pass (determine init value for cells).\n");
|
|
||||||
|
|
||||||
extra_args(args, args.size(), design);
|
|
||||||
|
|
||||||
int cnt = 0;
|
|
||||||
for (auto module : design->selected_modules())
|
|
||||||
{
|
|
||||||
for (auto cell : module->selected_cells())
|
|
||||||
{
|
|
||||||
if (cell->type == "\\EG_LOGIC_DRAM16X4")
|
|
||||||
{
|
|
||||||
cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0")));
|
|
||||||
cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1")));
|
|
||||||
cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2")));
|
|
||||||
cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3")));
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_header(design, "Updated %d cells with determined init value.\n", cnt);
|
|
||||||
}
|
|
||||||
} AnlogicDetermineInitPass;
|
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_END
|
|
130
techlibs/anlogic/anlogic_fixcarry.cc
Normal file
130
techlibs/anlogic/anlogic_fixcarry.cc
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
static SigBit get_bit_or_zero(const SigSpec &sig)
|
||||||
|
{
|
||||||
|
if (GetSize(sig) == 0)
|
||||||
|
return State::S0;
|
||||||
|
return sig[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fix_carry_chain(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> ci_bits;
|
||||||
|
dict<SigBit, SigBit> mapping_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\AL_MAP_ADDER") {
|
||||||
|
if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0) {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigSpec o = cell->getPort("\\o");
|
||||||
|
if (GetSize(o) == 2) {
|
||||||
|
SigBit bit_o = o[0];
|
||||||
|
ci_bits.insert(bit_ci);
|
||||||
|
mapping_bits[bit_ci] = bit_o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<Cell*> adders_to_fix_cells;
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\AL_MAP_ADDER") {
|
||||||
|
if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
if (!ci_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
adders_to_fix_cells.push_back(cell);
|
||||||
|
log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : adders_to_fix_cells)
|
||||||
|
{
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
auto bit = mapping_bits.at(canonical_bit);
|
||||||
|
log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
SigBit dummy_bit = module->addWire(NEW_ID);
|
||||||
|
SigSpec bits;
|
||||||
|
bits.append(dummy_bit);
|
||||||
|
bits.append(new_bit);
|
||||||
|
c->setParam("\\ALUTYPE", Const("ADD_CARRY"));
|
||||||
|
c->setPort("\\a", bit);
|
||||||
|
c->setPort("\\b", State::S0);
|
||||||
|
c->setPort("\\c", State::S0);
|
||||||
|
c->setPort("\\o", bits);
|
||||||
|
|
||||||
|
cell->setPort("\\c", new_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AnlogicCarryFixPass : public Pass {
|
||||||
|
AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" anlogic_fixcarry [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Anlogic adders to fix carry chain if needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
fix_carry_chain(module);
|
||||||
|
}
|
||||||
|
} AnlogicCarryFixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -31,7 +31,10 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
output [Y_WIDTH-1:0] X, Y;
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
input CI, BI;
|
input CI, BI;
|
||||||
output CO;
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
|
wire CIx;
|
||||||
|
wire [Y_WIDTH-1:0] COx;
|
||||||
|
|
||||||
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
|
@ -41,15 +44,16 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] AA = A_buf;
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
wire [Y_WIDTH+1:0] COx;
|
wire [Y_WIDTH-1:0] C = { COx, CIx };
|
||||||
wire [Y_WIDTH+2:0] C = {COx, CI};
|
|
||||||
|
|
||||||
wire dummy;
|
wire dummy;
|
||||||
AL_MAP_ADDER #(
|
AL_MAP_ADDER #(
|
||||||
.ALUTYPE("ADD_CARRY"))
|
.ALUTYPE("ADD_CARRY"))
|
||||||
adder_cin (
|
adder_cin (
|
||||||
.a(C[0]),
|
.a(CI),
|
||||||
.o({COx[0], dummy})
|
.b(1'b0),
|
||||||
|
.c(1'b0),
|
||||||
|
.o({CIx, dummy})
|
||||||
);
|
);
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
|
@ -59,18 +63,22 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
) adder_i (
|
) adder_i (
|
||||||
.a(AA[i]),
|
.a(AA[i]),
|
||||||
.b(BB[i]),
|
.b(BB[i]),
|
||||||
.c(C[i+1]),
|
.c(C[i]),
|
||||||
.o({COx[i+1],Y[i]})
|
.o({COx[i],Y[i]})
|
||||||
);
|
);
|
||||||
end: slice
|
|
||||||
|
wire cout;
|
||||||
|
AL_MAP_ADDER #(
|
||||||
|
.ALUTYPE("ADD"))
|
||||||
|
adder_cout (
|
||||||
|
.a(1'b0),
|
||||||
|
.b(1'b0),
|
||||||
|
.c(COx[i]),
|
||||||
|
.o({cout, CO[i]})
|
||||||
|
);
|
||||||
|
end: slice
|
||||||
endgenerate
|
endgenerate
|
||||||
/* End implementation */
|
|
||||||
AL_MAP_ADDER #(
|
/* End implementation */
|
||||||
.ALUTYPE("ADD"))
|
assign X = AA ^ BB;
|
||||||
adder_cout (
|
endmodule
|
||||||
.c(C[Y_WIDTH+1]),
|
|
||||||
.o(COx[Y_WIDTH+1])
|
|
||||||
);
|
|
||||||
assign CO = COx[Y_WIDTH+1];
|
|
||||||
assign X = AA ^ BB;
|
|
||||||
endmodule
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ struct SynthAnlogicPass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("memory_bram -rules +/anlogic/drams.txt");
|
run("memory_bram -rules +/anlogic/drams.txt");
|
||||||
run("techmap -map +/anlogic/drams_map.v");
|
run("techmap -map +/anlogic/drams_map.v");
|
||||||
run("anlogic_determine_init");
|
run("setundef -zero -params t:EG_LOGIC_DRAM16X4");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("fine"))
|
if (check_label("fine"))
|
||||||
|
@ -186,6 +186,11 @@ struct SynthAnlogicPass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("techmap -map +/anlogic/cells_map.v");
|
run("techmap -map +/anlogic/cells_map.v");
|
||||||
run("clean");
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_anlogic"))
|
||||||
|
{
|
||||||
|
run("anlogic_fixcarry");
|
||||||
run("anlogic_eqn");
|
run("anlogic_eqn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ struct SynthPass : public ScriptPass
|
||||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
if (abc == "abc9" && !lut)
|
if (abc == "abc9" && !lut)
|
||||||
log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)");
|
log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)\n");
|
||||||
|
|
||||||
log_header(design, "Executing SYNTH pass.\n");
|
log_header(design, "Executing SYNTH pass.\n");
|
||||||
log_push();
|
log_push();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o
|
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \
|
||||||
|
techlibs/ecp5/ecp5_gsr.o
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
|
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
|
||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
|
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
|
||||||
|
|
|
@ -33,7 +33,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
.CLKBMUX(CLKBMUX),
|
.CLKBMUX(CLKBMUX),
|
||||||
.WRITEMODE_A(WRITEMODE_A),
|
.WRITEMODE_A(WRITEMODE_A),
|
||||||
.WRITEMODE_B("READBEFOREWRITE"),
|
.WRITEMODE_B("READBEFOREWRITE"),
|
||||||
.GSR("DISABLED")
|
.GSR("AUTO")
|
||||||
) _TECHMAP_REPLACE_ (
|
) _TECHMAP_REPLACE_ (
|
||||||
`include "bram_conn_1.vh"
|
`include "bram_conn_1.vh"
|
||||||
.CLKA(CLK2), .CLKB(CLK3),
|
.CLKA(CLK2), .CLKB(CLK3),
|
||||||
|
@ -50,7 +50,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
.CLKBMUX(CLKBMUX),
|
.CLKBMUX(CLKBMUX),
|
||||||
.WRITEMODE_A(WRITEMODE_A),
|
.WRITEMODE_A(WRITEMODE_A),
|
||||||
.WRITEMODE_B("READBEFOREWRITE"),
|
.WRITEMODE_B("READBEFOREWRITE"),
|
||||||
.GSR("DISABLED")
|
.GSR("AUTO")
|
||||||
) _TECHMAP_REPLACE_ (
|
) _TECHMAP_REPLACE_ (
|
||||||
`include "bram_conn_2.vh"
|
`include "bram_conn_2.vh"
|
||||||
.CLKA(CLK2), .CLKB(CLK3),
|
.CLKA(CLK2), .CLKB(CLK3),
|
||||||
|
@ -67,7 +67,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
.CLKBMUX(CLKBMUX),
|
.CLKBMUX(CLKBMUX),
|
||||||
.WRITEMODE_A(WRITEMODE_A),
|
.WRITEMODE_A(WRITEMODE_A),
|
||||||
.WRITEMODE_B("READBEFOREWRITE"),
|
.WRITEMODE_B("READBEFOREWRITE"),
|
||||||
.GSR("DISABLED")
|
.GSR("AUTO")
|
||||||
) _TECHMAP_REPLACE_ (
|
) _TECHMAP_REPLACE_ (
|
||||||
`include "bram_conn_4.vh"
|
`include "bram_conn_4.vh"
|
||||||
.CLKA(CLK2), .CLKB(CLK3),
|
.CLKA(CLK2), .CLKB(CLK3),
|
||||||
|
@ -84,7 +84,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
.CLKBMUX(CLKBMUX),
|
.CLKBMUX(CLKBMUX),
|
||||||
.WRITEMODE_A(WRITEMODE_A),
|
.WRITEMODE_A(WRITEMODE_A),
|
||||||
.WRITEMODE_B("READBEFOREWRITE"),
|
.WRITEMODE_B("READBEFOREWRITE"),
|
||||||
.GSR("DISABLED")
|
.GSR("AUTO")
|
||||||
) _TECHMAP_REPLACE_ (
|
) _TECHMAP_REPLACE_ (
|
||||||
`include "bram_conn_9.vh"
|
`include "bram_conn_9.vh"
|
||||||
.CLKA(CLK2), .CLKB(CLK3),
|
.CLKA(CLK2), .CLKB(CLK3),
|
||||||
|
@ -101,7 +101,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
.CLKBMUX(CLKBMUX),
|
.CLKBMUX(CLKBMUX),
|
||||||
.WRITEMODE_A(WRITEMODE_A),
|
.WRITEMODE_A(WRITEMODE_A),
|
||||||
.WRITEMODE_B("READBEFOREWRITE"),
|
.WRITEMODE_B("READBEFOREWRITE"),
|
||||||
.GSR("DISABLED")
|
.GSR("AUTO")
|
||||||
) _TECHMAP_REPLACE_ (
|
) _TECHMAP_REPLACE_ (
|
||||||
`include "bram_conn_18.vh"
|
`include "bram_conn_18.vh"
|
||||||
.CLKA(CLK2), .CLKB(CLK3),
|
.CLKA(CLK2), .CLKB(CLK3),
|
||||||
|
|
|
@ -664,3 +664,23 @@ module PCSCLKDIV (
|
||||||
);
|
);
|
||||||
parameter GSR = "DISABLED";
|
parameter GSR = "DISABLED";
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// Note: this module is not marked keep as we want it swept away in synth (sim use only)
|
||||||
|
(* blackbox *)
|
||||||
|
module PUR (
|
||||||
|
input PUR
|
||||||
|
);
|
||||||
|
parameter RST_PULSE = 1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox, keep *)
|
||||||
|
module GSR (
|
||||||
|
input GSR
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox, keep *)
|
||||||
|
module SGSR (
|
||||||
|
input GSR, CLK
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -1,51 +1,51 @@
|
||||||
module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
// TODO: Diamond flip-flops
|
// TODO: Diamond flip-flops
|
||||||
// module FD1P3AX(); endmodule
|
// module FD1P3AX(); endmodule
|
||||||
|
|
|
@ -17,10 +17,12 @@ endmodule
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
(* abc_box_id=1, lib_whitebox *)
|
(* abc_box_id=1, lib_whitebox *)
|
||||||
module CCU2C(
|
module CCU2C(
|
||||||
(* abc_carry *) input CIN,
|
(* abc_carry *)
|
||||||
|
input CIN,
|
||||||
input A0, B0, C0, D0, A1, B1, C1, D1,
|
input A0, B0, C0, D0, A1, B1, C1, D1,
|
||||||
output S0, S1,
|
output S0, S1,
|
||||||
(* abc_carry *) output COUT
|
(* abc_carry *)
|
||||||
|
output COUT
|
||||||
);
|
);
|
||||||
parameter [15:0] INIT0 = 16'h0000;
|
parameter [15:0] INIT0 = 16'h0000;
|
||||||
parameter [15:0] INIT1 = 16'h0000;
|
parameter [15:0] INIT1 = 16'h0000;
|
||||||
|
@ -109,9 +111,12 @@ endmodule
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
//(* abc_box_id=2 *)
|
//(* abc_box_id=2 *)
|
||||||
module TRELLIS_DPR16X4 (
|
module TRELLIS_DPR16X4 (
|
||||||
(* abc_scc_break *) input [3:0] DI,
|
(* abc_scc_break *)
|
||||||
(* abc_scc_break *) input [3:0] WAD,
|
input [3:0] DI,
|
||||||
(* abc_scc_break *) input WRE,
|
(* abc_scc_break *)
|
||||||
|
input [3:0] WAD,
|
||||||
|
(* abc_scc_break *)
|
||||||
|
input WRE,
|
||||||
input WCK,
|
input WCK,
|
||||||
input [3:0] RAD,
|
input [3:0] RAD,
|
||||||
output [3:0] DO
|
output [3:0] DO
|
||||||
|
|
135
techlibs/ecp5/ecp5_gsr.cc
Normal file
135
techlibs/ecp5/ecp5_gsr.cc
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
* Copyright (C) 2019 David Shah <david@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct Ecp5GsrPass : public Pass {
|
||||||
|
Ecp5GsrPass() : Pass("ecp5_gsr", "ECP5: handle GSR") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" ecp5_gsr [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Trim active low async resets connected to GSR and resolve GSR parameter,\n");
|
||||||
|
log("if a GSR or SGSR primitive is used in the design.\n");
|
||||||
|
log("\n");
|
||||||
|
log("If any cell has the GSR parameter set to \"AUTO\", this will be resolved\n");
|
||||||
|
log("to \"ENABLED\" if a GSR primitive is present and the (* nogsr *) attribute\n");
|
||||||
|
log("is not set, otherwise it will be resolved to \"DISABLED\".\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing ECP5_GSR pass (implement FF init values).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-singleton") {
|
||||||
|
// singleton_mode = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
{
|
||||||
|
log("Handling GSR in %s.\n", log_id(module));
|
||||||
|
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
SigBit gsr;
|
||||||
|
bool found_gsr = false;
|
||||||
|
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if (cell->type != ID(GSR) && cell->type != ID(SGSR))
|
||||||
|
continue;
|
||||||
|
if (found_gsr)
|
||||||
|
log_error("Found more than one GSR or SGSR cell in module %s.\n", log_id(module));
|
||||||
|
found_gsr = true;
|
||||||
|
SigSpec sig_gsr = cell->getPort(ID(GSR));
|
||||||
|
if (GetSize(sig_gsr) < 1)
|
||||||
|
log_error("GSR cell %s has disconnected GSR input.\n", log_id(cell));
|
||||||
|
gsr = sigmap(sig_gsr[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve GSR parameter
|
||||||
|
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "AUTO")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool gsren = found_gsr;
|
||||||
|
if (cell->get_bool_attribute("\\nogsr"))
|
||||||
|
gsren = false;
|
||||||
|
cell->setParam(ID(GSR), gsren ? Const("ENABLED") : Const("DISABLED"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_gsr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// For finding active low FF inputs
|
||||||
|
pool<SigBit> inverted_gsr;
|
||||||
|
|
||||||
|
log_debug("GSR net in module %s is %s.\n", log_id(module), log_signal(gsr));
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if (cell->type != ID($_NOT_))
|
||||||
|
continue;
|
||||||
|
SigSpec sig_a = cell->getPort(ID(A)), sig_y = cell->getPort(ID(Y));
|
||||||
|
if (GetSize(sig_a) < 1 || GetSize(sig_y) < 1)
|
||||||
|
continue;
|
||||||
|
SigBit a = sigmap(sig_a[0]);
|
||||||
|
if (a == gsr)
|
||||||
|
inverted_gsr.insert(sigmap(sig_y[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if (cell->type != ID(TRELLIS_FF))
|
||||||
|
continue;
|
||||||
|
if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "ENABLED")
|
||||||
|
continue;
|
||||||
|
if (!cell->hasParam(ID(SRMODE)) || cell->getParam(ID(SRMODE)).decode_string() != "ASYNC")
|
||||||
|
continue;
|
||||||
|
SigSpec sig_lsr = cell->getPort(ID(LSR));
|
||||||
|
if (GetSize(sig_lsr) < 1)
|
||||||
|
continue;
|
||||||
|
SigBit lsr = sigmap(sig_lsr[0]);
|
||||||
|
if (!inverted_gsr.count(lsr))
|
||||||
|
continue;
|
||||||
|
cell->setParam(ID(SRMODE), Const("SYNC"));
|
||||||
|
cell->unsetPort(ID(LSR));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} Ecp5GsrPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -301,6 +301,8 @@ struct SynthEcp5Pass : public ScriptPass
|
||||||
run("opt_expr -undriven -mux_undef");
|
run("opt_expr -undriven -mux_undef");
|
||||||
run("simplemap");
|
run("simplemap");
|
||||||
run("ecp5_ffinit");
|
run("ecp5_ffinit");
|
||||||
|
run("ecp5_gsr");
|
||||||
|
run("opt_clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_luts"))
|
if (check_label("map_luts"))
|
||||||
|
|
10
techlibs/efinix/Makefile.inc
Normal file
10
techlibs/efinix/Makefile.inc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
OBJS += techlibs/efinix/synth_efinix.o
|
||||||
|
OBJS += techlibs/efinix/efinix_gbuf.o
|
||||||
|
OBJS += techlibs/efinix/efinix_fixcarry.o
|
||||||
|
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/bram.txt))
|
79
techlibs/efinix/arith_map.v
Normal file
79
techlibs/efinix/arith_map.v
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(* techmap_celltype = "$alu" *)
|
||||||
|
module _80_efinix_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
parameter A_WIDTH = 1;
|
||||||
|
parameter B_WIDTH = 1;
|
||||||
|
parameter Y_WIDTH = 1;
|
||||||
|
|
||||||
|
input [A_WIDTH-1:0] A;
|
||||||
|
input [B_WIDTH-1:0] B;
|
||||||
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
|
input CI, BI;
|
||||||
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
|
wire CIx;
|
||||||
|
wire [Y_WIDTH-1:0] COx;
|
||||||
|
|
||||||
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
||||||
|
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
||||||
|
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
|
wire [Y_WIDTH-1:0] C = { COx, CIx };
|
||||||
|
|
||||||
|
EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
|
||||||
|
adder_cin (
|
||||||
|
.I0(CI),
|
||||||
|
.I1(1'b1),
|
||||||
|
.CI(1'b0),
|
||||||
|
.CO(CIx)
|
||||||
|
);
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
|
||||||
|
EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
|
||||||
|
adder_i (
|
||||||
|
.I0(AA[i]),
|
||||||
|
.I1(BB[i]),
|
||||||
|
.CI(C[i]),
|
||||||
|
.O(Y[i]),
|
||||||
|
.CO(COx[i])
|
||||||
|
);
|
||||||
|
EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
|
||||||
|
adder_cout (
|
||||||
|
.I0(1'b0),
|
||||||
|
.I1(1'b0),
|
||||||
|
.CI(COx[i]),
|
||||||
|
.O(CO[i])
|
||||||
|
);
|
||||||
|
end: slice
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
/* End implementation */
|
||||||
|
assign X = AA ^ BB;
|
||||||
|
endmodule
|
32
techlibs/efinix/bram.txt
Normal file
32
techlibs/efinix/bram.txt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
bram $__EFINIX_5K
|
||||||
|
init 1
|
||||||
|
|
||||||
|
abits 8 @a8d16
|
||||||
|
dbits 16 @a8d16
|
||||||
|
abits 9 @a9d8
|
||||||
|
dbits 8 @a9d8
|
||||||
|
abits 10 @a10d4
|
||||||
|
dbits 4 @a10d4
|
||||||
|
abits 11 @a11d2
|
||||||
|
dbits 2 @a11d2
|
||||||
|
abits 12 @a12d1
|
||||||
|
dbits 1 @a12d1
|
||||||
|
abits 8 @a8d20
|
||||||
|
dbits 20 @a8d20
|
||||||
|
abits 9 @a9d10
|
||||||
|
dbits 10 @a9d10
|
||||||
|
|
||||||
|
groups 2
|
||||||
|
ports 1 1
|
||||||
|
wrmode 1 0
|
||||||
|
enable 1 1
|
||||||
|
transp 0 2
|
||||||
|
clocks 2 3
|
||||||
|
clkpol 2 3
|
||||||
|
endbram
|
||||||
|
|
||||||
|
match $__EFINIX_5K
|
||||||
|
min bits 256
|
||||||
|
min efficiency 5
|
||||||
|
shuffle_enable B
|
||||||
|
endmatch
|
65
techlibs/efinix/brams_map.v
Normal file
65
techlibs/efinix/brams_map.v
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
module \$__EFINIX_5K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
|
parameter CFG_ABITS = 8;
|
||||||
|
parameter CFG_DBITS = 20;
|
||||||
|
parameter CFG_ENABLE_A = 1;
|
||||||
|
|
||||||
|
parameter CLKPOL2 = 1;
|
||||||
|
parameter CLKPOL3 = 1;
|
||||||
|
parameter [5119:0] INIT = 5119'bx;
|
||||||
|
parameter TRANSP2 = 0;
|
||||||
|
|
||||||
|
input CLK2;
|
||||||
|
input CLK3;
|
||||||
|
|
||||||
|
input [CFG_ABITS-1:0] A1ADDR;
|
||||||
|
input [CFG_DBITS-1:0] A1DATA;
|
||||||
|
input [CFG_ENABLE_A-1:0] A1EN;
|
||||||
|
|
||||||
|
input [CFG_ABITS-1:0] B1ADDR;
|
||||||
|
output [CFG_DBITS-1:0] B1DATA;
|
||||||
|
input B1EN;
|
||||||
|
|
||||||
|
localparam WRITEMODE_A = TRANSP2 ? "WRITE_FIRST" : "READ_FIRST";
|
||||||
|
|
||||||
|
EFX_RAM_5K #(
|
||||||
|
.READ_WIDTH(CFG_DBITS),
|
||||||
|
.WRITE_WIDTH(CFG_DBITS),
|
||||||
|
.OUTPUT_REG(1'b0),
|
||||||
|
.RCLK_POLARITY(1'b1),
|
||||||
|
.RE_POLARITY(1'b1),
|
||||||
|
.WCLK_POLARITY(1'b1),
|
||||||
|
.WE_POLARITY(1'b1),
|
||||||
|
.WCLKE_POLARITY(1'b1),
|
||||||
|
.WRITE_MODE(WRITEMODE_A),
|
||||||
|
.INIT_0(INIT[ 0*256 +: 256]),
|
||||||
|
.INIT_1(INIT[ 1*256 +: 256]),
|
||||||
|
.INIT_2(INIT[ 2*256 +: 256]),
|
||||||
|
.INIT_3(INIT[ 3*256 +: 256]),
|
||||||
|
.INIT_4(INIT[ 4*256 +: 256]),
|
||||||
|
.INIT_5(INIT[ 5*256 +: 256]),
|
||||||
|
.INIT_6(INIT[ 6*256 +: 256]),
|
||||||
|
.INIT_7(INIT[ 7*256 +: 256]),
|
||||||
|
.INIT_8(INIT[ 8*256 +: 256]),
|
||||||
|
.INIT_9(INIT[ 9*256 +: 256]),
|
||||||
|
.INIT_A(INIT[10*256 +: 256]),
|
||||||
|
.INIT_B(INIT[11*256 +: 256]),
|
||||||
|
.INIT_C(INIT[12*256 +: 256]),
|
||||||
|
.INIT_D(INIT[13*256 +: 256]),
|
||||||
|
.INIT_E(INIT[14*256 +: 256]),
|
||||||
|
.INIT_F(INIT[15*256 +: 256]),
|
||||||
|
.INIT_10(INIT[16*256 +: 256]),
|
||||||
|
.INIT_11(INIT[17*256 +: 256]),
|
||||||
|
.INIT_12(INIT[18*256 +: 256]),
|
||||||
|
.INIT_13(INIT[19*256 +: 256])
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.WDATA(A1DATA),
|
||||||
|
.WADDR(A1ADDR),
|
||||||
|
.WE(A1EN),
|
||||||
|
.WCLK(CLK2),
|
||||||
|
.WCLKE(1'b1),
|
||||||
|
.RDATA(B1DATA),
|
||||||
|
.RADDR(B1ADDR),
|
||||||
|
.RE(B1EN),
|
||||||
|
.RCLK(CLK3)
|
||||||
|
);
|
||||||
|
endmodule
|
45
techlibs/efinix/cells_map.v
Normal file
45
techlibs/efinix/cells_map.v
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
module \$_DFF_N_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_P_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_NN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
module \$_DFFE_NP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_PN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
module \$_DFFE_PP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
`ifndef NO_LUT
|
||||||
|
module \$lut (A, Y);
|
||||||
|
parameter WIDTH = 0;
|
||||||
|
parameter LUT = 0;
|
||||||
|
|
||||||
|
input [WIDTH-1:0] A;
|
||||||
|
output Y;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (WIDTH == 1) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 2) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 3) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 4) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
|
||||||
|
end else begin
|
||||||
|
wire _TECHMAP_FAIL_ = 1;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
`endif
|
107
techlibs/efinix/cells_sim.v
Normal file
107
techlibs/efinix/cells_sim.v
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
module EFX_LUT4(
|
||||||
|
output O,
|
||||||
|
input I0,
|
||||||
|
input I1,
|
||||||
|
input I2,
|
||||||
|
input I3
|
||||||
|
);
|
||||||
|
parameter LUTMASK = 16'h0000;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_ADD(
|
||||||
|
output O,
|
||||||
|
output CO,
|
||||||
|
input I0,
|
||||||
|
input I1,
|
||||||
|
input CI
|
||||||
|
);
|
||||||
|
parameter I0_POLARITY = 1;
|
||||||
|
parameter I1_POLARITY = 1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_FF(
|
||||||
|
output Q,
|
||||||
|
input D,
|
||||||
|
input CE,
|
||||||
|
input CLK,
|
||||||
|
input SR
|
||||||
|
);
|
||||||
|
parameter CLK_POLARITY = 1;
|
||||||
|
parameter CE_POLARITY = 1;
|
||||||
|
parameter SR_POLARITY = 1;
|
||||||
|
parameter SR_SYNC = 0;
|
||||||
|
parameter SR_VALUE = 0;
|
||||||
|
parameter SR_SYNC_PRIORITY = 0;
|
||||||
|
parameter D_POLARITY = 1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_GBUFCE(
|
||||||
|
input CE,
|
||||||
|
input I,
|
||||||
|
output O
|
||||||
|
);
|
||||||
|
parameter CE_POLARITY = 1'b1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_RAM_5K(
|
||||||
|
input [WRITE_WIDTH-1:0] WDATA,
|
||||||
|
input [WRITE_ADDR_WIDTH-1:0] WADDR,
|
||||||
|
input WE,
|
||||||
|
input WCLK,
|
||||||
|
input WCLKE,
|
||||||
|
output [READ_WIDTH-1:0] RDATA,
|
||||||
|
input [READ_ADDR_WIDTH-1:0] RADDR,
|
||||||
|
input RE,
|
||||||
|
input RCLK
|
||||||
|
);
|
||||||
|
parameter READ_WIDTH = 20;
|
||||||
|
parameter WRITE_WIDTH = 20;
|
||||||
|
parameter OUTPUT_REG = 1'b0;
|
||||||
|
parameter RCLK_POLARITY = 1'b1;
|
||||||
|
parameter RE_POLARITY = 1'b1;
|
||||||
|
parameter WCLK_POLARITY = 1'b1;
|
||||||
|
parameter WE_POLARITY = 1'b1;
|
||||||
|
parameter WCLKE_POLARITY = 1'b1;
|
||||||
|
parameter WRITE_MODE = "READ_FIRST";
|
||||||
|
parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
localparam READ_ADDR_WIDTH =
|
||||||
|
(READ_WIDTH == 16) ? 8 : // 256x16
|
||||||
|
(READ_WIDTH == 8) ? 9 : // 512x8
|
||||||
|
(READ_WIDTH == 4) ? 10 : // 1024x4
|
||||||
|
(READ_WIDTH == 2) ? 11 : // 2048x2
|
||||||
|
(READ_WIDTH == 1) ? 12 : // 4096x1
|
||||||
|
(READ_WIDTH == 20) ? 8 : // 256x20
|
||||||
|
(READ_WIDTH == 10) ? 9 : // 512x10
|
||||||
|
(READ_WIDTH == 5) ? 10 : -1; // 1024x5
|
||||||
|
|
||||||
|
localparam WRITE_ADDR_WIDTH =
|
||||||
|
(WRITE_WIDTH == 16) ? 8 : // 256x16
|
||||||
|
(WRITE_WIDTH == 8) ? 9 : // 512x8
|
||||||
|
(WRITE_WIDTH == 4) ? 10 : // 1024x4
|
||||||
|
(WRITE_WIDTH == 2) ? 11 : // 2048x2
|
||||||
|
(WRITE_WIDTH == 1) ? 12 : // 4096x1
|
||||||
|
(WRITE_WIDTH == 20) ? 8 : // 256x20
|
||||||
|
(WRITE_WIDTH == 10) ? 9 : // 512x10
|
||||||
|
(WRITE_WIDTH == 5) ? 10 : -1; // 1024x5
|
||||||
|
|
||||||
|
endmodule
|
122
techlibs/efinix/efinix_fixcarry.cc
Normal file
122
techlibs/efinix/efinix_fixcarry.cc
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
static SigBit get_bit_or_zero(const SigSpec &sig)
|
||||||
|
{
|
||||||
|
if (GetSize(sig) == 0)
|
||||||
|
return State::S0;
|
||||||
|
return sig[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fix_carry_chain(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> ci_bits;
|
||||||
|
dict<SigBit, SigBit> mapping_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\EFX_ADD") {
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0) {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
|
||||||
|
SigBit bit_o = sigmap(cell->getPort("\\O"));
|
||||||
|
ci_bits.insert(bit_ci);
|
||||||
|
mapping_bits[bit_ci] = bit_o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Cell*> adders_to_fix_cells;
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\EFX_ADD") {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
if (!ci_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
adders_to_fix_cells.push_back(cell);
|
||||||
|
log("Found %s cell named %s with invalid CI signal.\n", log_id(cell->type), log_id(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : adders_to_fix_cells)
|
||||||
|
{
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
auto bit = mapping_bits.at(canonical_bit);
|
||||||
|
log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\EFX_ADD");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
c->setParam("\\I0_POLARITY", State::S1);
|
||||||
|
c->setParam("\\I1_POLARITY", State::S1);
|
||||||
|
c->setPort("\\I0", bit);
|
||||||
|
c->setPort("\\I1", State::S1);
|
||||||
|
c->setPort("\\CI", State::S0);
|
||||||
|
c->setPort("\\CO", new_bit);
|
||||||
|
|
||||||
|
cell->setPort("\\CI", new_bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EfinixCarryFixPass : public Pass {
|
||||||
|
EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" efinix_fixcarry [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Efinix adders to fix carry chain if needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing efinix_fixcarry pass (fix invalid carry chain).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
fix_carry_chain(module);
|
||||||
|
}
|
||||||
|
} EfinixCarryFixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
119
techlibs/efinix/efinix_gbuf.cc
Normal file
119
techlibs/efinix/efinix_gbuf.cc
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
static void handle_gbufs(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> clk_bits;
|
||||||
|
dict<SigBit, SigBit> rewrite_bits;
|
||||||
|
vector<pair<Cell*, SigBit>> pad_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\EFX_FF") {
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\CLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
}
|
||||||
|
if (cell->type == "\\EFX_RAM_5K") {
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\RCLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\WCLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto wire : vector<Wire*>(module->wires()))
|
||||||
|
{
|
||||||
|
if (!wire->port_input)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int index = 0; index < GetSize(wire); index++)
|
||||||
|
{
|
||||||
|
SigBit bit(wire, index);
|
||||||
|
SigBit canonical_bit = sigmap(bit);
|
||||||
|
|
||||||
|
if (!clk_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\EFX_GBUFCE");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
c->setParam("\\CE_POLARITY", State::S1);
|
||||||
|
c->setPort("\\O", new_bit);
|
||||||
|
c->setPort("\\CE", State::S1);
|
||||||
|
pad_bits.push_back(make_pair(c, bit));
|
||||||
|
rewrite_bits[canonical_bit] = new_bit;
|
||||||
|
|
||||||
|
log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rewrite_function = [&](SigSpec &s) {
|
||||||
|
for (auto &bit : s) {
|
||||||
|
SigBit canonical_bit = sigmap(bit);
|
||||||
|
if (rewrite_bits.count(canonical_bit))
|
||||||
|
bit = rewrite_bits.at(canonical_bit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module->rewrite_sigspecs(rewrite_function);
|
||||||
|
|
||||||
|
for (auto &it : pad_bits)
|
||||||
|
it.first->setPort("\\I", it.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EfinixGbufPass : public Pass {
|
||||||
|
EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" efinix_gbuf [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Efinix global clock buffers to top module as needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing efinix_gbuf pass (insert global clock buffers).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
handle_gbufs(module);
|
||||||
|
}
|
||||||
|
} EfinixGbufPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
219
techlibs/efinix/synth_efinix.cc
Normal file
219
techlibs/efinix/synth_efinix.cc
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
* Copyright (C) 2019 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/register.h"
|
||||||
|
#include "kernel/celltypes.h"
|
||||||
|
#include "kernel/rtlil.h"
|
||||||
|
#include "kernel/log.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct SynthEfinixPass : public ScriptPass
|
||||||
|
{
|
||||||
|
SynthEfinixPass() : ScriptPass("synth_efinix", "synthesis for Efinix FPGAs") { }
|
||||||
|
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" synth_efinix [options]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command runs synthesis for Efinix FPGAs.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -top <module>\n");
|
||||||
|
log(" use the specified module as top module\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -edif <file>\n");
|
||||||
|
log(" write the design to the specified EDIF file. writing of an output file\n");
|
||||||
|
log(" is omitted if this parameter is not specified.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -json <file>\n");
|
||||||
|
log(" write the design to the specified JSON file. writing of an output file\n");
|
||||||
|
log(" is omitted if this parameter is not specified.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -run <from_label>:<to_label>\n");
|
||||||
|
log(" only run the commands between the labels (see below). an empty\n");
|
||||||
|
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||||
|
log(" synonymous to the end of the command list.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -noflatten\n");
|
||||||
|
log(" do not flatten design before synthesis\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -retime\n");
|
||||||
|
log(" run 'abc' with -dff option\n");
|
||||||
|
log("\n");
|
||||||
|
log("\n");
|
||||||
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
help_script();
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string top_opt, edif_file, json_file;
|
||||||
|
bool flatten, retime;
|
||||||
|
|
||||||
|
void clear_flags() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
top_opt = "-auto-top";
|
||||||
|
edif_file = "";
|
||||||
|
json_file = "";
|
||||||
|
flatten = true;
|
||||||
|
retime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
string run_from, run_to;
|
||||||
|
clear_flags();
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
if (args[argidx] == "-top" && argidx+1 < args.size()) {
|
||||||
|
top_opt = "-top " + args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
|
||||||
|
edif_file = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-json" && argidx+1 < args.size()) {
|
||||||
|
json_file = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-run" && argidx+1 < args.size()) {
|
||||||
|
size_t pos = args[argidx+1].find(':');
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
break;
|
||||||
|
run_from = args[++argidx].substr(0, pos);
|
||||||
|
run_to = args[argidx].substr(pos+1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noflatten") {
|
||||||
|
flatten = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-retime") {
|
||||||
|
retime = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
if (!design->full_selection())
|
||||||
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
|
log_header(design, "Executing SYNTH_EFINIX pass.\n");
|
||||||
|
log_push();
|
||||||
|
|
||||||
|
run_script(design, run_from, run_to);
|
||||||
|
|
||||||
|
log_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void script() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
if (check_label("begin"))
|
||||||
|
{
|
||||||
|
run("read_verilog -lib +/efinix/cells_sim.v");
|
||||||
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
||||||
|
{
|
||||||
|
run("proc");
|
||||||
|
run("flatten");
|
||||||
|
run("tribuf -logic");
|
||||||
|
run("deminout");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("coarse"))
|
||||||
|
{
|
||||||
|
run("synth -run coarse");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_bram", "(skip if -nobram)"))
|
||||||
|
{
|
||||||
|
run("memory_bram -rules +/efinix/bram.txt");
|
||||||
|
run("techmap -map +/efinix/brams_map.v");
|
||||||
|
run("setundef -zero -params t:EFX_RAM_5K");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("fine"))
|
||||||
|
{
|
||||||
|
run("opt -fast -mux_undef -undriven -fine");
|
||||||
|
run("memory_map");
|
||||||
|
run("opt -undriven -fine");
|
||||||
|
run("techmap -map +/techmap.v -map +/efinix/arith_map.v");
|
||||||
|
if (retime || help_mode)
|
||||||
|
run("abc -dff", "(only if -retime)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_ffs"))
|
||||||
|
{
|
||||||
|
run("dffsr2dff");
|
||||||
|
run("techmap -D NO_LUT -map +/efinix/cells_map.v");
|
||||||
|
run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
|
||||||
|
run("opt_expr -mux_undef");
|
||||||
|
run("simplemap");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_luts"))
|
||||||
|
{
|
||||||
|
run("abc -lut 4");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_cells"))
|
||||||
|
{
|
||||||
|
run("techmap -map +/efinix/cells_map.v");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_gbuf"))
|
||||||
|
{
|
||||||
|
run("efinix_gbuf");
|
||||||
|
run("efinix_fixcarry");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("check"))
|
||||||
|
{
|
||||||
|
run("hierarchy -check");
|
||||||
|
run("stat");
|
||||||
|
run("check -noinit");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("edif"))
|
||||||
|
{
|
||||||
|
if (!edif_file.empty() || help_mode)
|
||||||
|
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("json"))
|
||||||
|
{
|
||||||
|
if (!json_file.empty() || help_mode)
|
||||||
|
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} SynthEfinixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -3,11 +3,11 @@
|
||||||
# NB: Inputs/Outputs must be ordered alphabetically
|
# NB: Inputs/Outputs must be ordered alphabetically
|
||||||
# (with exceptions for carry in/out)
|
# (with exceptions for carry in/out)
|
||||||
|
|
||||||
# Inputs: A B CI
|
# Inputs: A B I0 I3 CI
|
||||||
# Outputs: O CO
|
# Outputs: O CO
|
||||||
# (NB: carry chain input/output must be last
|
# (NB: carry chain input/output must be last
|
||||||
# input/output and have been moved there
|
# input/output and have been moved there
|
||||||
# overriding the alphabetical ordering)
|
# overriding the alphabetical ordering)
|
||||||
$__ICE40_FULL_ADDER 1 1 3 2
|
$__ICE40_CARRY_WRAPPER 1 1 5 2
|
||||||
400 379 316
|
400 379 449 316 316
|
||||||
259 231 126
|
259 231 - - 126
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
# NB: Inputs/Outputs must be ordered alphabetically
|
# NB: Inputs/Outputs must be ordered alphabetically
|
||||||
# (with exceptions for carry in/out)
|
# (with exceptions for carry in/out)
|
||||||
|
|
||||||
# Inputs: A B CI
|
# Inputs: A B I0 I3 CI
|
||||||
# Outputs: O CO
|
# Outputs: O CO
|
||||||
# (NB: carry chain input/output must be last
|
# (NB: carry chain input/output must be last
|
||||||
# input/output and have been moved there
|
# input/output and have been moved there
|
||||||
# overriding the alphabetical ordering)
|
# overriding the alphabetical ordering)
|
||||||
$__ICE40_FULL_ADDER 1 1 3 2
|
$__ICE40_CARRY_WRAPPER 1 1 5 2
|
||||||
589 558 465
|
589 558 661 465 465
|
||||||
675 609 186
|
675 609 - - 186
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
# NB: Inputs/Outputs must be ordered alphabetically
|
# NB: Inputs/Outputs must be ordered alphabetically
|
||||||
# (with exceptions for carry in/out)
|
# (with exceptions for carry in/out)
|
||||||
|
|
||||||
# Inputs: A B CI
|
# Inputs: A B I0 I3 CI
|
||||||
# Outputs: O CO
|
# Outputs: O CO
|
||||||
# (NB: carry chain input/output must be last
|
# (NB: carry chain input/output must be last
|
||||||
# input/output and have been moved there
|
# input/output and have been moved there
|
||||||
# overriding the alphabetical ordering)
|
# overriding the alphabetical ordering)
|
||||||
$__ICE40_FULL_ADDER 1 1 3 2
|
$__ICE40_CARRY_WRAPPER 1 1 5 2
|
||||||
1231 1205 874
|
1231 1205 1285 874 874
|
||||||
675 609 278
|
675 609 - - 278
|
||||||
|
|
|
@ -142,13 +142,16 @@ module SB_CARRY (output CO, input I0, I1, CI);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* abc_box_id = 1, lib_whitebox *)
|
(* abc_box_id = 1, lib_whitebox *)
|
||||||
module \$__ICE40_FULL_ADDER (
|
module \$__ICE40_CARRY_WRAPPER (
|
||||||
(* abc_carry *) output CO,
|
(* abc_carry *)
|
||||||
|
output CO,
|
||||||
output O,
|
output O,
|
||||||
input A,
|
input A, B,
|
||||||
input B,
|
(* abc_carry *)
|
||||||
(* abc_carry *) input CI
|
input CI,
|
||||||
|
input I0, I3
|
||||||
);
|
);
|
||||||
|
parameter LUT = 0;
|
||||||
SB_CARRY carry (
|
SB_CARRY carry (
|
||||||
.I0(A),
|
.I0(A),
|
||||||
.I1(B),
|
.I1(B),
|
||||||
|
@ -156,16 +159,12 @@ module \$__ICE40_FULL_ADDER (
|
||||||
.CO(CO)
|
.CO(CO)
|
||||||
);
|
);
|
||||||
SB_LUT4 #(
|
SB_LUT4 #(
|
||||||
// I0: 1010 1010 1010 1010
|
.LUT_INIT(LUT)
|
||||||
// I1: 1100 1100 1100 1100
|
|
||||||
// I2: 1111 0000 1111 0000
|
|
||||||
// I3: 1111 1111 0000 0000
|
|
||||||
.LUT_INIT(16'b 0110_1001_1001_0110)
|
|
||||||
) adder (
|
) adder (
|
||||||
.I0(1'b0),
|
.I0(I0),
|
||||||
.I1(A),
|
.I1(A),
|
||||||
.I2(B),
|
.I2(B),
|
||||||
.I3(CI),
|
.I3(I3),
|
||||||
.O(O)
|
.O(O)
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -84,7 +84,7 @@ static void run_ice40_opts(Module *module)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == "$__ICE40_FULL_ADDER")
|
if (cell->type == "$__ICE40_CARRY_WRAPPER")
|
||||||
{
|
{
|
||||||
SigSpec non_const_inputs, replacement_output;
|
SigSpec non_const_inputs, replacement_output;
|
||||||
int count_zeros = 0, count_ones = 0;
|
int count_zeros = 0, count_ones = 0;
|
||||||
|
@ -114,16 +114,17 @@ static void run_ice40_opts(Module *module)
|
||||||
optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
|
optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
|
||||||
module->connect(cell->getPort("\\CO")[0], replacement_output);
|
module->connect(cell->getPort("\\CO")[0], replacement_output);
|
||||||
module->design->scratchpad_set_bool("opt.did_something", true);
|
module->design->scratchpad_set_bool("opt.did_something", true);
|
||||||
log("Optimized $__ICE40_FULL_ADDER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
|
log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
|
||||||
log_id(module), log_id(cell), log_signal(replacement_output));
|
log_id(module), log_id(cell), log_signal(replacement_output));
|
||||||
cell->type = "$lut";
|
cell->type = "$lut";
|
||||||
cell->setPort("\\A", { State::S0, inbit[0], inbit[1], inbit[2] });
|
cell->setPort("\\A", { cell->getPort("\\I0"), inbit[0], inbit[1], cell->getPort("\\I3") });
|
||||||
cell->setPort("\\Y", cell->getPort("\\O"));
|
cell->setPort("\\Y", cell->getPort("\\O"));
|
||||||
cell->unsetPort("\\B");
|
cell->unsetPort("\\B");
|
||||||
cell->unsetPort("\\CI");
|
cell->unsetPort("\\CI");
|
||||||
|
cell->unsetPort("\\I0");
|
||||||
|
cell->unsetPort("\\I3");
|
||||||
cell->unsetPort("\\CO");
|
cell->unsetPort("\\CO");
|
||||||
cell->unsetPort("\\O");
|
cell->unsetPort("\\O");
|
||||||
cell->setParam("\\LUT", RTLIL::Const::from_string("0110100110010110"));
|
|
||||||
cell->setParam("\\WIDTH", 4);
|
cell->setParam("\\WIDTH", 4);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -29,24 +29,35 @@ module GND(output G);
|
||||||
assign G = 0;
|
assign G = 0;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module IBUF(output O, input I);
|
module IBUF(
|
||||||
|
output O,
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input I);
|
||||||
parameter IOSTANDARD = "default";
|
parameter IOSTANDARD = "default";
|
||||||
parameter IBUF_LOW_PWR = 0;
|
parameter IBUF_LOW_PWR = 0;
|
||||||
assign O = I;
|
assign O = I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module OBUF(output O, input I);
|
module OBUF(
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
output O,
|
||||||
|
input I);
|
||||||
parameter IOSTANDARD = "default";
|
parameter IOSTANDARD = "default";
|
||||||
parameter DRIVE = 12;
|
parameter DRIVE = 12;
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
assign O = I;
|
assign O = I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFG(output O, input I);
|
module BUFG(
|
||||||
|
(* clkbuf_driver *)
|
||||||
|
output O,
|
||||||
|
input I);
|
||||||
|
|
||||||
assign O = I;
|
assign O = I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFGCTRL(
|
module BUFGCTRL(
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O,
|
output O,
|
||||||
input I0, input I1,
|
input I0, input I1,
|
||||||
input S0, input S1,
|
input S0, input S1,
|
||||||
|
@ -72,7 +83,11 @@ assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFHCE(output O, input I, input CE);
|
module BUFHCE(
|
||||||
|
(* clkbuf_driver *)
|
||||||
|
output O,
|
||||||
|
input I,
|
||||||
|
input CE);
|
||||||
|
|
||||||
parameter [0:0] INIT_OUT = 1'b0;
|
parameter [0:0] INIT_OUT = 1'b0;
|
||||||
parameter CE_TYPE = "SYNC";
|
parameter CE_TYPE = "SYNC";
|
||||||
|
@ -183,9 +198,11 @@ endmodule
|
||||||
|
|
||||||
(* abc_box_id = 4, lib_whitebox *)
|
(* abc_box_id = 4, lib_whitebox *)
|
||||||
module CARRY4(
|
module CARRY4(
|
||||||
(* abc_carry *) output [3:0] CO,
|
(* abc_carry *)
|
||||||
|
output [3:0] CO,
|
||||||
output [3:0] O,
|
output [3:0] O,
|
||||||
(* abc_carry *) input CI,
|
(* abc_carry *)
|
||||||
|
input CI,
|
||||||
input CYINIT,
|
input CYINIT,
|
||||||
input [3:0] DI, S
|
input [3:0] DI, S
|
||||||
);
|
);
|
||||||
|
@ -219,7 +236,7 @@ endmodule
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
module FDRE (output reg Q, input C, CE, D, R);
|
module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||||
|
@ -231,7 +248,7 @@ module FDRE (output reg Q, input C, CE, D, R);
|
||||||
endcase endgenerate
|
endcase endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDSE (output reg Q, input C, CE, D, S);
|
module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
|
||||||
parameter [0:0] INIT = 1'b1;
|
parameter [0:0] INIT = 1'b1;
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||||
|
@ -243,7 +260,7 @@ module FDSE (output reg Q, input C, CE, D, S);
|
||||||
endcase endgenerate
|
endcase endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDCE (output reg Q, input C, CE, D, CLR);
|
module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||||
|
@ -257,7 +274,7 @@ module FDCE (output reg Q, input C, CE, D, CLR);
|
||||||
endcase endgenerate
|
endcase endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDPE (output reg Q, input C, CE, D, PRE);
|
module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
|
||||||
parameter [0:0] INIT = 1'b1;
|
parameter [0:0] INIT = 1'b1;
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||||
|
@ -271,25 +288,25 @@ module FDPE (output reg Q, input C, CE, D, PRE);
|
||||||
endcase endgenerate
|
endcase endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDRE_1 (output reg Q, input C, CE, D, R);
|
module FDRE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
initial Q <= INIT;
|
initial Q <= INIT;
|
||||||
always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
|
always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDSE_1 (output reg Q, input C, CE, D, S);
|
module FDSE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
|
||||||
parameter [0:0] INIT = 1'b1;
|
parameter [0:0] INIT = 1'b1;
|
||||||
initial Q <= INIT;
|
initial Q <= INIT;
|
||||||
always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
|
always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDCE_1 (output reg Q, input C, CE, D, CLR);
|
module FDCE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
initial Q <= INIT;
|
initial Q <= INIT;
|
||||||
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
|
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDPE_1 (output reg Q, input C, CE, D, PRE);
|
module FDPE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
|
||||||
parameter [0:0] INIT = 1'b1;
|
parameter [0:0] INIT = 1'b1;
|
||||||
initial Q <= INIT;
|
initial Q <= INIT;
|
||||||
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
||||||
|
@ -298,9 +315,12 @@ endmodule
|
||||||
(* abc_box_id = 5 *)
|
(* abc_box_id = 5 *)
|
||||||
module RAM32X1D (
|
module RAM32X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
(* abc_scc_break *) input D,
|
(* abc_scc_break *)
|
||||||
|
input D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WCLK,
|
input WCLK,
|
||||||
(* abc_scc_break *) input WE,
|
(* abc_scc_break *)
|
||||||
|
input WE,
|
||||||
input A0, A1, A2, A3, A4,
|
input A0, A1, A2, A3, A4,
|
||||||
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
|
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
|
||||||
);
|
);
|
||||||
|
@ -318,9 +338,12 @@ endmodule
|
||||||
(* abc_box_id = 6 *)
|
(* abc_box_id = 6 *)
|
||||||
module RAM64X1D (
|
module RAM64X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
(* abc_scc_break *) input D,
|
(* abc_scc_break *)
|
||||||
|
input D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WCLK,
|
input WCLK,
|
||||||
(* abc_scc_break *) input WE,
|
(* abc_scc_break *)
|
||||||
|
input WE,
|
||||||
input A0, A1, A2, A3, A4, A5,
|
input A0, A1, A2, A3, A4, A5,
|
||||||
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
|
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
|
||||||
);
|
);
|
||||||
|
@ -338,9 +361,12 @@ endmodule
|
||||||
(* abc_box_id = 7 *)
|
(* abc_box_id = 7 *)
|
||||||
module RAM128X1D (
|
module RAM128X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
(* abc_scc_break *) input D,
|
(* abc_scc_break *)
|
||||||
|
input D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WCLK,
|
input WCLK,
|
||||||
(* abc_scc_break *) input WE,
|
(* abc_scc_break *)
|
||||||
|
input WE,
|
||||||
input [6:0] A, DPRA
|
input [6:0] A, DPRA
|
||||||
);
|
);
|
||||||
parameter INIT = 128'h0;
|
parameter INIT = 128'h0;
|
||||||
|
@ -354,7 +380,10 @@ endmodule
|
||||||
|
|
||||||
module SRL16E (
|
module SRL16E (
|
||||||
output Q,
|
output Q,
|
||||||
input A0, A1, A2, A3, CE, CLK, D
|
input A0, A1, A2, A3, CE,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input CLK,
|
||||||
|
input D
|
||||||
);
|
);
|
||||||
parameter [15:0] INIT = 16'h0000;
|
parameter [15:0] INIT = 16'h0000;
|
||||||
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||||
|
@ -366,7 +395,30 @@ module SRL16E (
|
||||||
always @(negedge CLK) if (CE) r <= { r[14:0], D };
|
always @(negedge CLK) if (CE) r <= { r[14:0], D };
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
always @(posedge CLK) if (CE) r <= { r[14:0], D };
|
always @(posedge CLK) if (CE) r <= { r[14:0], D };
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module SRLC16E (
|
||||||
|
output Q,
|
||||||
|
output Q15,
|
||||||
|
input A0, A1, A2, A3, CE,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input CLK,
|
||||||
|
input D
|
||||||
|
);
|
||||||
|
parameter [15:0] INIT = 16'h0000;
|
||||||
|
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||||
|
|
||||||
|
reg [15:0] r = INIT;
|
||||||
|
assign Q15 = r[15];
|
||||||
|
assign Q = r[{A3,A2,A1,A0}];
|
||||||
|
generate
|
||||||
|
if (IS_CLK_INVERTED) begin
|
||||||
|
always @(negedge CLK) if (CE) r <= { r[14:0], D };
|
||||||
|
end
|
||||||
|
else
|
||||||
|
always @(posedge CLK) if (CE) r <= { r[14:0], D };
|
||||||
endgenerate
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -374,7 +426,10 @@ module SRLC32E (
|
||||||
output Q,
|
output Q,
|
||||||
output Q31,
|
output Q31,
|
||||||
input [4:0] A,
|
input [4:0] A,
|
||||||
input CE, CLK, D
|
input CE,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input CLK,
|
||||||
|
input D
|
||||||
);
|
);
|
||||||
parameter [31:0] INIT = 32'h00000000;
|
parameter [31:0] INIT = 32'h00000000;
|
||||||
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||||
|
@ -425,7 +480,7 @@ module DSP48E1 (
|
||||||
input CEINMODE,
|
input CEINMODE,
|
||||||
input CEM,
|
input CEM,
|
||||||
input CEP,
|
input CEP,
|
||||||
input CLK,
|
(* clkbuf_sink *) input CLK,
|
||||||
input [24:0] D,
|
input [24:0] D,
|
||||||
input [4:0] INMODE,
|
input [4:0] INMODE,
|
||||||
input MULTSIGNIN,
|
input MULTSIGNIN,
|
||||||
|
|
257
techlibs/xilinx/cells_xtra.py
Normal file
257
techlibs/xilinx/cells_xtra.py
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
from io import StringIO
|
||||||
|
from enum import Enum, auto
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class Cell:
|
||||||
|
def __init__(self, name, keep=False, port_attrs={}):
|
||||||
|
self.name = name
|
||||||
|
self.keep = keep
|
||||||
|
self.port_attrs = port_attrs
|
||||||
|
|
||||||
|
|
||||||
|
CELLS = [
|
||||||
|
# Design elements types listed in Xilinx UG953
|
||||||
|
Cell('BSCANE2', keep=True),
|
||||||
|
# Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFGCE', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFGCE_1', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
#Cell('BUFGCTRL', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFGMUX', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFGMUX_1', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFGMUX_CTRL', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFH', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
#Cell('BUFHCE', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFIO', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFMR', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFMRCE', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('BUFR', port_attrs={'O': ['clkbuf_driver']}),
|
||||||
|
Cell('CAPTUREE2', keep=True),
|
||||||
|
# Cell('CARRY4'),
|
||||||
|
Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}),
|
||||||
|
Cell('DCIRESET', keep=True),
|
||||||
|
Cell('DNA_PORT'),
|
||||||
|
Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}),
|
||||||
|
Cell('EFUSE_USR'),
|
||||||
|
# Cell('FDCE'),
|
||||||
|
# Cell('FDPE'),
|
||||||
|
# Cell('FDRE'),
|
||||||
|
# Cell('FDSE'),
|
||||||
|
Cell('FIFO18E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('FIFO36E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('FRAME_ECCE2'),
|
||||||
|
Cell('GTHE2_CHANNEL'),
|
||||||
|
Cell('GTHE2_COMMON'),
|
||||||
|
Cell('GTPE2_CHANNEL'),
|
||||||
|
Cell('GTPE2_COMMON'),
|
||||||
|
Cell('GTXE2_CHANNEL'),
|
||||||
|
Cell('GTXE2_COMMON'),
|
||||||
|
# Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUF_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUF_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS_DIFF_OUT_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS_GTE2', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFDS_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
|
||||||
|
Cell('ICAPE2', keep=True),
|
||||||
|
Cell('IDDR', port_attrs={'C': ['clkbuf_sink']}),
|
||||||
|
Cell('IDDR_2CLK', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
|
||||||
|
Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('IDELAYE2', port_attrs={'C': ['clkbuf_sink']}),
|
||||||
|
Cell('IN_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
|
||||||
|
Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
|
||||||
|
Cell('ISERDESE2', port_attrs={
|
||||||
|
'CLK': ['clkbuf_sink'],
|
||||||
|
'CLKB': ['clkbuf_sink'],
|
||||||
|
'OCLK': ['clkbuf_sink'],
|
||||||
|
'OCLKB': ['clkbuf_sink'],
|
||||||
|
'CLKDIV': ['clkbuf_sink'],
|
||||||
|
'CLKDIVP': ['clkbuf_sink'],
|
||||||
|
}),
|
||||||
|
Cell('KEEPER'),
|
||||||
|
Cell('LDCE'),
|
||||||
|
Cell('LDPE'),
|
||||||
|
# Cell('LUT1'),
|
||||||
|
# Cell('LUT2'),
|
||||||
|
# Cell('LUT3'),
|
||||||
|
# Cell('LUT4'),
|
||||||
|
# Cell('LUT5'),
|
||||||
|
# Cell('LUT6'),
|
||||||
|
#Cell('LUT6_2'),
|
||||||
|
Cell('MMCME2_ADV'),
|
||||||
|
Cell('MMCME2_BASE'),
|
||||||
|
# Cell('MUXF7'),
|
||||||
|
# Cell('MUXF8'),
|
||||||
|
# Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}),
|
||||||
|
Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
|
||||||
|
Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}),
|
||||||
|
Cell('OBUFTDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
|
||||||
|
Cell('ODDR', port_attrs={'C': ['clkbuf_sink']}),
|
||||||
|
Cell('ODELAYE2', port_attrs={'C': ['clkbuf_sink']}),
|
||||||
|
Cell('OSERDESE2', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
|
||||||
|
Cell('OUT_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('PHASER_IN'),
|
||||||
|
Cell('PHASER_IN_PHY'),
|
||||||
|
Cell('PHASER_OUT'),
|
||||||
|
Cell('PHASER_OUT_PHY'),
|
||||||
|
Cell('PHASER_REF'),
|
||||||
|
Cell('PHY_CONTROL'),
|
||||||
|
Cell('PLLE2_ADV'),
|
||||||
|
Cell('PLLE2_BASE'),
|
||||||
|
Cell('PS7', keep=True),
|
||||||
|
Cell('PULLDOWN'),
|
||||||
|
Cell('PULLUP'),
|
||||||
|
#Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
#Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
#Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
|
||||||
|
# Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
|
||||||
|
# Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
|
||||||
|
Cell('ROM128X1'),
|
||||||
|
Cell('ROM256X1'),
|
||||||
|
Cell('ROM32X1'),
|
||||||
|
Cell('ROM64X1'),
|
||||||
|
#Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}),
|
||||||
|
#Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}),
|
||||||
|
Cell('STARTUPE2', keep=True),
|
||||||
|
Cell('USR_ACCESSE2'),
|
||||||
|
Cell('XADC'),
|
||||||
|
]
|
||||||
|
|
||||||
|
class State(Enum):
|
||||||
|
OUTSIDE = auto()
|
||||||
|
IN_MODULE = auto()
|
||||||
|
IN_OTHER_MODULE = auto()
|
||||||
|
IN_FUNCTION = auto()
|
||||||
|
IN_TASK = auto()
|
||||||
|
|
||||||
|
def xtract_cell_decl(cell, dirs, outf):
|
||||||
|
for dir in dirs:
|
||||||
|
fname = os.path.join(dir, cell.name + '.v')
|
||||||
|
try:
|
||||||
|
with open(fname) as f:
|
||||||
|
state = State.OUTSIDE
|
||||||
|
found = False
|
||||||
|
# Probably the most horrible Verilog "parser" ever written.
|
||||||
|
for l in f:
|
||||||
|
l = l.partition('//')[0]
|
||||||
|
l = l.strip()
|
||||||
|
if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)):
|
||||||
|
if found:
|
||||||
|
print('Multiple modules in {}.'.format(fname))
|
||||||
|
sys.exit(1)
|
||||||
|
elif state != State.OUTSIDE:
|
||||||
|
print('Nested modules in {}.'.format(fname))
|
||||||
|
sys.exit(1)
|
||||||
|
found = True
|
||||||
|
state = State.IN_MODULE
|
||||||
|
if cell.keep:
|
||||||
|
outf.write('(* keep *)\n')
|
||||||
|
outf.write('module {} (...);\n'.format(cell.name))
|
||||||
|
elif l.startswith('module '):
|
||||||
|
if state != State.OUTSIDE:
|
||||||
|
print('Nested modules in {}.'.format(fname))
|
||||||
|
sys.exit(1)
|
||||||
|
state = State.IN_OTHER_MODULE
|
||||||
|
elif l.startswith('task '):
|
||||||
|
if state == State.IN_MODULE:
|
||||||
|
state = State.IN_TASK
|
||||||
|
elif l.startswith('function '):
|
||||||
|
if state == State.IN_MODULE:
|
||||||
|
state = State.IN_FUNCTION
|
||||||
|
elif l == 'endtask':
|
||||||
|
if state == State.IN_TASK:
|
||||||
|
state = State.IN_MODULE
|
||||||
|
elif l == 'endfunction':
|
||||||
|
if state == State.IN_FUNCTION:
|
||||||
|
state = State.IN_MODULE
|
||||||
|
elif l == 'endmodule':
|
||||||
|
if state == State.IN_MODULE:
|
||||||
|
outf.write(l + '\n')
|
||||||
|
outf.write('\n')
|
||||||
|
elif state != State.IN_OTHER_MODULE:
|
||||||
|
print('endmodule in weird place in {}.'.format(cell.name, fname))
|
||||||
|
sys.exit(1)
|
||||||
|
state = State.OUTSIDE
|
||||||
|
elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
|
||||||
|
if l.endswith((';', ',')):
|
||||||
|
l = l[:-1]
|
||||||
|
if ';' in l:
|
||||||
|
print('Weird port line in {} [{}].'.format(fname, l))
|
||||||
|
sys.exit(1)
|
||||||
|
kind, _, ports = l.partition(' ')
|
||||||
|
for port in ports.split(','):
|
||||||
|
port = port.strip()
|
||||||
|
for attr in cell.port_attrs.get(port, []):
|
||||||
|
outf.write(' (* {} *)\n'.format(attr))
|
||||||
|
outf.write(' {} {};\n'.format(kind, port))
|
||||||
|
elif l.startswith('parameter ') and state == State.IN_MODULE:
|
||||||
|
if 'UNPLACED' in l:
|
||||||
|
continue
|
||||||
|
if l.endswith((';', ',')):
|
||||||
|
l = l[:-1]
|
||||||
|
while ' ' in l:
|
||||||
|
l = l.replace(' ', ' ')
|
||||||
|
if ';' in l:
|
||||||
|
print('Weird parameter line in {} [{}].'.format(fname, l))
|
||||||
|
sys.exit(1)
|
||||||
|
outf.write(' {};\n'.format(l))
|
||||||
|
if state != State.OUTSIDE:
|
||||||
|
print('endmodule not found in {}.'.format(fname))
|
||||||
|
sys.exit(1)
|
||||||
|
if not found:
|
||||||
|
print('Cannot find module {} in {}.'.format(cell.name, fname))
|
||||||
|
sys.exit(1)
|
||||||
|
return
|
||||||
|
except FileNotFoundError:
|
||||||
|
continue
|
||||||
|
print('Cannot find {}.'.format(cell.name))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = ArgumentParser(description='Extract Xilinx blackbox cell definitions from Vivado.')
|
||||||
|
parser.add_argument('vivado_dir', nargs='?', default='/opt/Xilinx/Vivado/2018.1')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
dirs = [
|
||||||
|
os.path.join(args.vivado_dir, 'data/verilog/src/xeclib'),
|
||||||
|
os.path.join(args.vivado_dir, 'data/verilog/src/retarget'),
|
||||||
|
]
|
||||||
|
for dir in dirs:
|
||||||
|
if not os.path.isdir(dir):
|
||||||
|
print('{} is not a directory'.format(dir))
|
||||||
|
|
||||||
|
out = StringIO()
|
||||||
|
for cell in CELLS:
|
||||||
|
xtract_cell_decl(cell, dirs, out)
|
||||||
|
|
||||||
|
with open('cells_xtra.v', 'w') as f:
|
||||||
|
f.write('// Created by cells_xtra.py from Xilinx models\n')
|
||||||
|
f.write('\n')
|
||||||
|
f.write(out.getvalue())
|
|
@ -1,147 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
libdir="/opt/Xilinx/Vivado/2018.1/data/verilog/src"
|
|
||||||
|
|
||||||
function xtract_cell_decl()
|
|
||||||
{
|
|
||||||
for dir in $libdir/xeclib $libdir/retarget; do
|
|
||||||
[ -f $dir/$1.v ] || continue
|
|
||||||
[ -z "$2" ] || echo $2
|
|
||||||
egrep '^\s*((end)?module|parameter|input|inout|output|(end)?function|(end)?task)' $dir/$1.v |
|
|
||||||
sed -re '/UNPLACED/ d; /^\s*function/,/endfunction/ d; /^\s*task/,/endtask/ d;
|
|
||||||
s,//.*,,; s/#?\(.*/(...);/; s/^(input|output|parameter)/ \1/;
|
|
||||||
s/\s+$//; s/,$/;/; /input|output|parameter/ s/[^;]$/&;/; s/\s+/ /g;
|
|
||||||
s/^ ((end)?module)/\1/; s/^ / /; /module.*_bb/,/endmodule/ d;'
|
|
||||||
echo; return
|
|
||||||
done
|
|
||||||
echo "Can't find $1."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
echo "// Created by cells_xtra.sh from Xilinx models"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Design elements types listed in Xilinx UG953
|
|
||||||
xtract_cell_decl BSCANE2
|
|
||||||
# xtract_cell_decl BUFG
|
|
||||||
xtract_cell_decl BUFGCE
|
|
||||||
xtract_cell_decl BUFGCE_1
|
|
||||||
#xtract_cell_decl BUFGCTRL
|
|
||||||
xtract_cell_decl BUFGMUX
|
|
||||||
xtract_cell_decl BUFGMUX_1
|
|
||||||
xtract_cell_decl BUFGMUX_CTRL
|
|
||||||
xtract_cell_decl BUFH
|
|
||||||
#xtract_cell_decl BUFHCE
|
|
||||||
xtract_cell_decl BUFIO
|
|
||||||
xtract_cell_decl BUFMR
|
|
||||||
xtract_cell_decl BUFMRCE
|
|
||||||
xtract_cell_decl BUFR
|
|
||||||
xtract_cell_decl CAPTUREE2 "(* keep *)"
|
|
||||||
# xtract_cell_decl CARRY4
|
|
||||||
xtract_cell_decl CFGLUT5
|
|
||||||
xtract_cell_decl DCIRESET "(* keep *)"
|
|
||||||
xtract_cell_decl DNA_PORT
|
|
||||||
xtract_cell_decl DSP48E1
|
|
||||||
xtract_cell_decl EFUSE_USR
|
|
||||||
# xtract_cell_decl FDCE
|
|
||||||
# xtract_cell_decl FDPE
|
|
||||||
# xtract_cell_decl FDRE
|
|
||||||
# xtract_cell_decl FDSE
|
|
||||||
xtract_cell_decl FIFO18E1
|
|
||||||
xtract_cell_decl FIFO36E1
|
|
||||||
xtract_cell_decl FRAME_ECCE2
|
|
||||||
xtract_cell_decl GTHE2_CHANNEL
|
|
||||||
xtract_cell_decl GTHE2_COMMON
|
|
||||||
xtract_cell_decl GTPE2_CHANNEL
|
|
||||||
xtract_cell_decl GTPE2_COMMON
|
|
||||||
xtract_cell_decl GTXE2_CHANNEL
|
|
||||||
xtract_cell_decl GTXE2_COMMON
|
|
||||||
# xtract_cell_decl IBUF
|
|
||||||
xtract_cell_decl IBUF_IBUFDISABLE
|
|
||||||
xtract_cell_decl IBUF_INTERMDISABLE
|
|
||||||
xtract_cell_decl IBUFDS
|
|
||||||
xtract_cell_decl IBUFDS_DIFF_OUT
|
|
||||||
xtract_cell_decl IBUFDS_DIFF_OUT_IBUFDISABLE
|
|
||||||
xtract_cell_decl IBUFDS_DIFF_OUT_INTERMDISABLE
|
|
||||||
xtract_cell_decl IBUFDS_GTE2
|
|
||||||
xtract_cell_decl IBUFDS_IBUFDISABLE
|
|
||||||
xtract_cell_decl IBUFDS_INTERMDISABLE
|
|
||||||
xtract_cell_decl ICAPE2 "(* keep *)"
|
|
||||||
xtract_cell_decl IDDR
|
|
||||||
xtract_cell_decl IDDR_2CLK
|
|
||||||
xtract_cell_decl IDELAYCTRL "(* keep *)"
|
|
||||||
xtract_cell_decl IDELAYE2
|
|
||||||
xtract_cell_decl IN_FIFO
|
|
||||||
xtract_cell_decl IOBUF
|
|
||||||
xtract_cell_decl IOBUF_DCIEN
|
|
||||||
xtract_cell_decl IOBUF_INTERMDISABLE
|
|
||||||
xtract_cell_decl IOBUFDS
|
|
||||||
xtract_cell_decl IOBUFDS_DCIEN
|
|
||||||
xtract_cell_decl IOBUFDS_DIFF_OUT
|
|
||||||
xtract_cell_decl IOBUFDS_DIFF_OUT_DCIEN
|
|
||||||
xtract_cell_decl IOBUFDS_DIFF_OUT_INTERMDISABLE
|
|
||||||
xtract_cell_decl ISERDESE2
|
|
||||||
xtract_cell_decl KEEPER
|
|
||||||
xtract_cell_decl LDCE
|
|
||||||
xtract_cell_decl LDPE
|
|
||||||
# xtract_cell_decl LUT1
|
|
||||||
# xtract_cell_decl LUT2
|
|
||||||
# xtract_cell_decl LUT3
|
|
||||||
# xtract_cell_decl LUT4
|
|
||||||
# xtract_cell_decl LUT5
|
|
||||||
# xtract_cell_decl LUT6
|
|
||||||
#xtract_cell_decl LUT6_2
|
|
||||||
xtract_cell_decl MMCME2_ADV
|
|
||||||
xtract_cell_decl MMCME2_BASE
|
|
||||||
# xtract_cell_decl MUXF7
|
|
||||||
# xtract_cell_decl MUXF8
|
|
||||||
# xtract_cell_decl OBUF
|
|
||||||
xtract_cell_decl OBUFDS
|
|
||||||
xtract_cell_decl OBUFT
|
|
||||||
xtract_cell_decl OBUFTDS
|
|
||||||
xtract_cell_decl ODDR
|
|
||||||
xtract_cell_decl ODELAYE2
|
|
||||||
xtract_cell_decl OSERDESE2
|
|
||||||
xtract_cell_decl OUT_FIFO
|
|
||||||
xtract_cell_decl PHASER_IN
|
|
||||||
xtract_cell_decl PHASER_IN_PHY
|
|
||||||
xtract_cell_decl PHASER_OUT
|
|
||||||
xtract_cell_decl PHASER_OUT_PHY
|
|
||||||
xtract_cell_decl PHASER_REF
|
|
||||||
xtract_cell_decl PHY_CONTROL
|
|
||||||
xtract_cell_decl PLLE2_ADV
|
|
||||||
xtract_cell_decl PLLE2_BASE
|
|
||||||
xtract_cell_decl PS7 "(* keep *)"
|
|
||||||
xtract_cell_decl PULLDOWN
|
|
||||||
xtract_cell_decl PULLUP
|
|
||||||
#xtract_cell_decl RAM128X1D
|
|
||||||
xtract_cell_decl RAM128X1S
|
|
||||||
xtract_cell_decl RAM256X1S
|
|
||||||
xtract_cell_decl RAM32M
|
|
||||||
#xtract_cell_decl RAM32X1D
|
|
||||||
xtract_cell_decl RAM32X1S
|
|
||||||
xtract_cell_decl RAM32X1S_1
|
|
||||||
xtract_cell_decl RAM32X2S
|
|
||||||
xtract_cell_decl RAM64M
|
|
||||||
#xtract_cell_decl RAM64X1D
|
|
||||||
xtract_cell_decl RAM64X1S
|
|
||||||
xtract_cell_decl RAM64X1S_1
|
|
||||||
xtract_cell_decl RAM64X2S
|
|
||||||
# xtract_cell_decl RAMB18E1
|
|
||||||
# xtract_cell_decl RAMB36E1
|
|
||||||
xtract_cell_decl ROM128X1
|
|
||||||
xtract_cell_decl ROM256X1
|
|
||||||
xtract_cell_decl ROM32X1
|
|
||||||
xtract_cell_decl ROM64X1
|
|
||||||
#xtract_cell_decl SRL16E
|
|
||||||
#xtract_cell_decl SRLC32E
|
|
||||||
xtract_cell_decl STARTUPE2 "(* keep *)"
|
|
||||||
xtract_cell_decl USR_ACCESSE2
|
|
||||||
xtract_cell_decl XADC
|
|
||||||
} > cells_xtra.new
|
|
||||||
|
|
||||||
mv cells_xtra.new cells_xtra.v
|
|
||||||
exit 0
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Created by cells_xtra.sh from Xilinx models
|
// Created by cells_xtra.py from Xilinx models
|
||||||
|
|
||||||
|
(* keep *)
|
||||||
module BSCANE2 (...);
|
module BSCANE2 (...);
|
||||||
parameter DISABLE_JTAG = "FALSE";
|
parameter DISABLE_JTAG = "FALSE";
|
||||||
parameter integer JTAG_CHAIN = 1;
|
parameter integer JTAG_CHAIN = 1;
|
||||||
|
@ -20,29 +21,39 @@ module BUFGCE (...);
|
||||||
parameter CE_TYPE = "SYNC";
|
parameter CE_TYPE = "SYNC";
|
||||||
parameter [0:0] IS_CE_INVERTED = 1'b0;
|
parameter [0:0] IS_CE_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_I_INVERTED = 1'b0;
|
parameter [0:0] IS_I_INVERTED = 1'b0;
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input CE;
|
input CE;
|
||||||
input I;
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFGCE_1 (...);
|
module BUFGCE_1 (...);
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input CE, I;
|
input CE;
|
||||||
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFGMUX (...);
|
module BUFGMUX (...);
|
||||||
parameter CLK_SEL_TYPE = "SYNC";
|
parameter CLK_SEL_TYPE = "SYNC";
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input I0, I1, S;
|
input I0;
|
||||||
|
input I1;
|
||||||
|
input S;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFGMUX_1 (...);
|
module BUFGMUX_1 (...);
|
||||||
parameter CLK_SEL_TYPE = "SYNC";
|
parameter CLK_SEL_TYPE = "SYNC";
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input I0, I1, S;
|
input I0;
|
||||||
|
input I1;
|
||||||
|
input S;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFGMUX_CTRL (...);
|
module BUFGMUX_CTRL (...);
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input I0;
|
input I0;
|
||||||
input I1;
|
input I1;
|
||||||
|
@ -50,16 +61,19 @@ module BUFGMUX_CTRL (...);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFH (...);
|
module BUFH (...);
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input I;
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFIO (...);
|
module BUFIO (...);
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input I;
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFMR (...);
|
module BUFMR (...);
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input I;
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -68,12 +82,14 @@ module BUFMRCE (...);
|
||||||
parameter CE_TYPE = "SYNC";
|
parameter CE_TYPE = "SYNC";
|
||||||
parameter integer INIT_OUT = 0;
|
parameter integer INIT_OUT = 0;
|
||||||
parameter [0:0] IS_CE_INVERTED = 1'b0;
|
parameter [0:0] IS_CE_INVERTED = 1'b0;
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input CE;
|
input CE;
|
||||||
input I;
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module BUFR (...);
|
module BUFR (...);
|
||||||
|
(* clkbuf_driver *)
|
||||||
output O;
|
output O;
|
||||||
input CE;
|
input CE;
|
||||||
input CLR;
|
input CLR;
|
||||||
|
@ -95,8 +111,15 @@ module CFGLUT5 (...);
|
||||||
output CDO;
|
output CDO;
|
||||||
output O5;
|
output O5;
|
||||||
output O6;
|
output O6;
|
||||||
input I4, I3, I2, I1, I0;
|
input I4;
|
||||||
input CDI, CE, CLK;
|
input I3;
|
||||||
|
input I2;
|
||||||
|
input I1;
|
||||||
|
input I0;
|
||||||
|
input CDI;
|
||||||
|
input CE;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input CLK;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* keep *)
|
(* keep *)
|
||||||
|
@ -108,7 +131,10 @@ endmodule
|
||||||
module DNA_PORT (...);
|
module DNA_PORT (...);
|
||||||
parameter [56:0] SIM_DNA_VALUE = 57'h0;
|
parameter [56:0] SIM_DNA_VALUE = 57'h0;
|
||||||
output DOUT;
|
output DOUT;
|
||||||
input CLK, DIN, READ, SHIFT;
|
input CLK;
|
||||||
|
input DIN;
|
||||||
|
input READ;
|
||||||
|
input SHIFT;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module EFUSE_USR (...);
|
module EFUSE_USR (...);
|
||||||
|
@ -145,11 +171,13 @@ module FIFO18E1 (...);
|
||||||
output WRERR;
|
output WRERR;
|
||||||
input [31:0] DI;
|
input [31:0] DI;
|
||||||
input [3:0] DIP;
|
input [3:0] DIP;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input RDCLK;
|
input RDCLK;
|
||||||
input RDEN;
|
input RDEN;
|
||||||
input REGCE;
|
input REGCE;
|
||||||
input RST;
|
input RST;
|
||||||
input RSTREG;
|
input RSTREG;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WRCLK;
|
input WRCLK;
|
||||||
input WREN;
|
input WREN;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -190,11 +218,13 @@ module FIFO36E1 (...);
|
||||||
input [7:0] DIP;
|
input [7:0] DIP;
|
||||||
input INJECTDBITERR;
|
input INJECTDBITERR;
|
||||||
input INJECTSBITERR;
|
input INJECTSBITERR;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input RDCLK;
|
input RDCLK;
|
||||||
input RDEN;
|
input RDEN;
|
||||||
input REGCE;
|
input REGCE;
|
||||||
input RST;
|
input RST;
|
||||||
input RSTREG;
|
input RSTREG;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WRCLK;
|
input WRCLK;
|
||||||
input WREN;
|
input WREN;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1887,6 +1917,7 @@ module IBUF_IBUFDISABLE (...);
|
||||||
parameter SIM_DEVICE = "7SERIES";
|
parameter SIM_DEVICE = "7SERIES";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1897,6 +1928,7 @@ module IBUF_INTERMDISABLE (...);
|
||||||
parameter SIM_DEVICE = "7SERIES";
|
parameter SIM_DEVICE = "7SERIES";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
input INTERMDISABLE;
|
input INTERMDISABLE;
|
||||||
|
@ -1911,7 +1943,10 @@ module IBUFDS (...);
|
||||||
parameter IFD_DELAY_VALUE = "AUTO";
|
parameter IFD_DELAY_VALUE = "AUTO";
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
output O;
|
output O;
|
||||||
input I, IB;
|
(* iopad_external_pin *)
|
||||||
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input IB;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module IBUFDS_DIFF_OUT (...);
|
module IBUFDS_DIFF_OUT (...);
|
||||||
|
@ -1919,8 +1954,12 @@ module IBUFDS_DIFF_OUT (...);
|
||||||
parameter DQS_BIAS = "FALSE";
|
parameter DQS_BIAS = "FALSE";
|
||||||
parameter IBUF_LOW_PWR = "TRUE";
|
parameter IBUF_LOW_PWR = "TRUE";
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
output O, OB;
|
output O;
|
||||||
input I, IB;
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input IB;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module IBUFDS_DIFF_OUT_IBUFDISABLE (...);
|
module IBUFDS_DIFF_OUT_IBUFDISABLE (...);
|
||||||
|
@ -1932,7 +1971,9 @@ module IBUFDS_DIFF_OUT_IBUFDISABLE (...);
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
output OB;
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input IB;
|
input IB;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1946,7 +1987,9 @@ module IBUFDS_DIFF_OUT_INTERMDISABLE (...);
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
output OB;
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input IB;
|
input IB;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
input INTERMDISABLE;
|
input INTERMDISABLE;
|
||||||
|
@ -1959,7 +2002,9 @@ module IBUFDS_GTE2 (...);
|
||||||
output O;
|
output O;
|
||||||
output ODIV2;
|
output ODIV2;
|
||||||
input CEB;
|
input CEB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input IB;
|
input IB;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -1971,7 +2016,9 @@ module IBUFDS_IBUFDISABLE (...);
|
||||||
parameter SIM_DEVICE = "7SERIES";
|
parameter SIM_DEVICE = "7SERIES";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input IB;
|
input IB;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1984,12 +2031,50 @@ module IBUFDS_INTERMDISABLE (...);
|
||||||
parameter SIM_DEVICE = "7SERIES";
|
parameter SIM_DEVICE = "7SERIES";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input I;
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
input IB;
|
input IB;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
input INTERMDISABLE;
|
input INTERMDISABLE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module IBUFG (...);
|
||||||
|
parameter CAPACITANCE = "DONT_CARE";
|
||||||
|
parameter IBUF_DELAY_VALUE = "0";
|
||||||
|
parameter IBUF_LOW_PWR = "TRUE";
|
||||||
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input I;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module IBUFGDS (...);
|
||||||
|
parameter CAPACITANCE = "DONT_CARE";
|
||||||
|
parameter DIFF_TERM = "FALSE";
|
||||||
|
parameter IBUF_DELAY_VALUE = "0";
|
||||||
|
parameter IBUF_LOW_PWR = "TRUE";
|
||||||
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input IB;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module IBUFGDS_DIFF_OUT (...);
|
||||||
|
parameter DIFF_TERM = "FALSE";
|
||||||
|
parameter DQS_BIAS = "FALSE";
|
||||||
|
parameter IBUF_LOW_PWR = "TRUE";
|
||||||
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
|
output O;
|
||||||
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input I;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
input IB;
|
||||||
|
endmodule
|
||||||
|
|
||||||
(* keep *)
|
(* keep *)
|
||||||
module ICAPE2 (...);
|
module ICAPE2 (...);
|
||||||
parameter [31:0] DEVICE_ID = 32'h04244093;
|
parameter [31:0] DEVICE_ID = 32'h04244093;
|
||||||
|
@ -2013,6 +2098,7 @@ module IDDR (...);
|
||||||
parameter XON = "TRUE";
|
parameter XON = "TRUE";
|
||||||
output Q1;
|
output Q1;
|
||||||
output Q2;
|
output Q2;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input C;
|
input C;
|
||||||
input CE;
|
input CE;
|
||||||
input D;
|
input D;
|
||||||
|
@ -2030,7 +2116,9 @@ module IDDR_2CLK (...);
|
||||||
parameter SRTYPE = "SYNC";
|
parameter SRTYPE = "SYNC";
|
||||||
output Q1;
|
output Q1;
|
||||||
output Q2;
|
output Q2;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input C;
|
input C;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CB;
|
input CB;
|
||||||
input CE;
|
input CE;
|
||||||
input D;
|
input D;
|
||||||
|
@ -2042,6 +2130,7 @@ endmodule
|
||||||
module IDELAYCTRL (...);
|
module IDELAYCTRL (...);
|
||||||
parameter SIM_DEVICE = "7SERIES";
|
parameter SIM_DEVICE = "7SERIES";
|
||||||
output RDY;
|
output RDY;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input REFCLK;
|
input REFCLK;
|
||||||
input RST;
|
input RST;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -2061,6 +2150,7 @@ module IDELAYE2 (...);
|
||||||
parameter integer SIM_DELAY_D = 0;
|
parameter integer SIM_DELAY_D = 0;
|
||||||
output [4:0] CNTVALUEOUT;
|
output [4:0] CNTVALUEOUT;
|
||||||
output DATAOUT;
|
output DATAOUT;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input C;
|
input C;
|
||||||
input CE;
|
input CE;
|
||||||
input CINVCTRL;
|
input CINVCTRL;
|
||||||
|
@ -2092,9 +2182,11 @@ module IN_FIFO (...);
|
||||||
output [7:0] Q7;
|
output [7:0] Q7;
|
||||||
output [7:0] Q8;
|
output [7:0] Q8;
|
||||||
output [7:0] Q9;
|
output [7:0] Q9;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input RDCLK;
|
input RDCLK;
|
||||||
input RDEN;
|
input RDEN;
|
||||||
input RESET;
|
input RESET;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WRCLK;
|
input WRCLK;
|
||||||
input WREN;
|
input WREN;
|
||||||
input [3:0] D0;
|
input [3:0] D0;
|
||||||
|
@ -2115,8 +2207,10 @@ module IOBUF (...);
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
input I, T;
|
input I;
|
||||||
|
input T;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module IOBUF_DCIEN (...);
|
module IOBUF_DCIEN (...);
|
||||||
|
@ -2127,6 +2221,7 @@ module IOBUF_DCIEN (...);
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
input DCITERMDISABLE;
|
input DCITERMDISABLE;
|
||||||
input I;
|
input I;
|
||||||
|
@ -2142,6 +2237,7 @@ module IOBUF_INTERMDISABLE (...);
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
input I;
|
input I;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
|
@ -2156,8 +2252,11 @@ module IOBUFDS (...);
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
output O;
|
output O;
|
||||||
inout IO, IOB;
|
(* iopad_external_pin *)
|
||||||
input I, T;
|
inout IO;
|
||||||
|
inout IOB;
|
||||||
|
input I;
|
||||||
|
input T;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module IOBUFDS_DCIEN (...);
|
module IOBUFDS_DCIEN (...);
|
||||||
|
@ -2169,7 +2268,9 @@ module IOBUFDS_DCIEN (...);
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IOB;
|
inout IOB;
|
||||||
input DCITERMDISABLE;
|
input DCITERMDISABLE;
|
||||||
input I;
|
input I;
|
||||||
|
@ -2184,7 +2285,9 @@ module IOBUFDS_DIFF_OUT (...);
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
output O;
|
output O;
|
||||||
output OB;
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IOB;
|
inout IOB;
|
||||||
input I;
|
input I;
|
||||||
input TM;
|
input TM;
|
||||||
|
@ -2200,7 +2303,9 @@ module IOBUFDS_DIFF_OUT_DCIEN (...);
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
output OB;
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IOB;
|
inout IOB;
|
||||||
input DCITERMDISABLE;
|
input DCITERMDISABLE;
|
||||||
input I;
|
input I;
|
||||||
|
@ -2218,7 +2323,9 @@ module IOBUFDS_DIFF_OUT_INTERMDISABLE (...);
|
||||||
parameter USE_IBUFDISABLE = "TRUE";
|
parameter USE_IBUFDISABLE = "TRUE";
|
||||||
output O;
|
output O;
|
||||||
output OB;
|
output OB;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IO;
|
inout IO;
|
||||||
|
(* iopad_external_pin *)
|
||||||
inout IOB;
|
inout IOB;
|
||||||
input I;
|
input I;
|
||||||
input IBUFDISABLE;
|
input IBUFDISABLE;
|
||||||
|
@ -2266,15 +2373,21 @@ module ISERDESE2 (...);
|
||||||
input BITSLIP;
|
input BITSLIP;
|
||||||
input CE1;
|
input CE1;
|
||||||
input CE2;
|
input CE2;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLK;
|
input CLK;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKB;
|
input CLKB;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKDIV;
|
input CLKDIV;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKDIVP;
|
input CLKDIVP;
|
||||||
input D;
|
input D;
|
||||||
input DDLY;
|
input DDLY;
|
||||||
input DYNCLKDIVSEL;
|
input DYNCLKDIVSEL;
|
||||||
input DYNCLKSEL;
|
input DYNCLKSEL;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input OCLK;
|
input OCLK;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input OCLKB;
|
input OCLKB;
|
||||||
input OFB;
|
input OFB;
|
||||||
input RST;
|
input RST;
|
||||||
|
@ -2293,7 +2406,10 @@ module LDCE (...);
|
||||||
parameter MSGON = "TRUE";
|
parameter MSGON = "TRUE";
|
||||||
parameter XON = "TRUE";
|
parameter XON = "TRUE";
|
||||||
output Q;
|
output Q;
|
||||||
input CLR, D, G, GE;
|
input CLR;
|
||||||
|
input D;
|
||||||
|
input G;
|
||||||
|
input GE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module LDPE (...);
|
module LDPE (...);
|
||||||
|
@ -2303,7 +2419,10 @@ module LDPE (...);
|
||||||
parameter MSGON = "TRUE";
|
parameter MSGON = "TRUE";
|
||||||
parameter XON = "TRUE";
|
parameter XON = "TRUE";
|
||||||
output Q;
|
output Q;
|
||||||
input D, G, GE, PRE;
|
input D;
|
||||||
|
input G;
|
||||||
|
input GE;
|
||||||
|
input PRE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module MMCME2_ADV (...);
|
module MMCME2_ADV (...);
|
||||||
|
@ -2451,7 +2570,10 @@ module OBUFDS (...);
|
||||||
parameter CAPACITANCE = "DONT_CARE";
|
parameter CAPACITANCE = "DONT_CARE";
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
output O, OB;
|
(* iopad_external_pin *)
|
||||||
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
output OB;
|
||||||
input I;
|
input I;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -2460,20 +2582,27 @@ module OBUFT (...);
|
||||||
parameter integer DRIVE = 12;
|
parameter integer DRIVE = 12;
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
|
(* iopad_external_pin *)
|
||||||
output O;
|
output O;
|
||||||
input I, T;
|
input I;
|
||||||
|
input T;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module OBUFTDS (...);
|
module OBUFTDS (...);
|
||||||
parameter CAPACITANCE = "DONT_CARE";
|
parameter CAPACITANCE = "DONT_CARE";
|
||||||
parameter IOSTANDARD = "DEFAULT";
|
parameter IOSTANDARD = "DEFAULT";
|
||||||
parameter SLEW = "SLOW";
|
parameter SLEW = "SLOW";
|
||||||
output O, OB;
|
(* iopad_external_pin *)
|
||||||
input I, T;
|
output O;
|
||||||
|
(* iopad_external_pin *)
|
||||||
|
output OB;
|
||||||
|
input I;
|
||||||
|
input T;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module ODDR (...);
|
module ODDR (...);
|
||||||
output Q;
|
output Q;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input C;
|
input C;
|
||||||
input CE;
|
input CE;
|
||||||
input D1;
|
input D1;
|
||||||
|
@ -2504,6 +2633,7 @@ module ODELAYE2 (...);
|
||||||
parameter integer SIM_DELAY_D = 0;
|
parameter integer SIM_DELAY_D = 0;
|
||||||
output [4:0] CNTVALUEOUT;
|
output [4:0] CNTVALUEOUT;
|
||||||
output DATAOUT;
|
output DATAOUT;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input C;
|
input C;
|
||||||
input CE;
|
input CE;
|
||||||
input CINVCTRL;
|
input CINVCTRL;
|
||||||
|
@ -2549,7 +2679,9 @@ module OSERDESE2 (...);
|
||||||
output TBYTEOUT;
|
output TBYTEOUT;
|
||||||
output TFB;
|
output TFB;
|
||||||
output TQ;
|
output TQ;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLK;
|
input CLK;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKDIV;
|
input CLKDIV;
|
||||||
input D1;
|
input D1;
|
||||||
input D2;
|
input D2;
|
||||||
|
@ -2591,9 +2723,11 @@ module OUT_FIFO (...);
|
||||||
output [3:0] Q9;
|
output [3:0] Q9;
|
||||||
output [7:0] Q5;
|
output [7:0] Q5;
|
||||||
output [7:0] Q6;
|
output [7:0] Q6;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input RDCLK;
|
input RDCLK;
|
||||||
input RDEN;
|
input RDEN;
|
||||||
input RESET;
|
input RESET;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WRCLK;
|
input WRCLK;
|
||||||
input WREN;
|
input WREN;
|
||||||
input [7:0] D0;
|
input [7:0] D0;
|
||||||
|
@ -3577,7 +3711,17 @@ module RAM128X1S (...);
|
||||||
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
|
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
|
input A6;
|
||||||
|
input D;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAM256X1S (...);
|
module RAM256X1S (...);
|
||||||
|
@ -3586,6 +3730,7 @@ module RAM256X1S (...);
|
||||||
output O;
|
output O;
|
||||||
input [7:0] A;
|
input [7:0] A;
|
||||||
input D;
|
input D;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WCLK;
|
input WCLK;
|
||||||
input WE;
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -3608,6 +3753,7 @@ module RAM32M (...);
|
||||||
input [1:0] DIB;
|
input [1:0] DIB;
|
||||||
input [1:0] DIC;
|
input [1:0] DIC;
|
||||||
input [1:0] DID;
|
input [1:0] DID;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WCLK;
|
input WCLK;
|
||||||
input WE;
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -3616,22 +3762,48 @@ module RAM32X1S (...);
|
||||||
parameter [31:0] INIT = 32'h00000000;
|
parameter [31:0] INIT = 32'h00000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, D, WCLK, WE;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input D;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAM32X1S_1 (...);
|
module RAM32X1S_1 (...);
|
||||||
parameter [31:0] INIT = 32'h00000000;
|
parameter [31:0] INIT = 32'h00000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, D, WCLK, WE;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input D;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAM32X2S (...);
|
module RAM32X2S (...);
|
||||||
parameter [31:0] INIT_00 = 32'h00000000;
|
parameter [31:0] INIT_00 = 32'h00000000;
|
||||||
parameter [31:0] INIT_01 = 32'h00000000;
|
parameter [31:0] INIT_01 = 32'h00000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O0, O1;
|
output O0;
|
||||||
input A0, A1, A2, A3, A4, D0, D1, WCLK, WE;
|
output O1;
|
||||||
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input D0;
|
||||||
|
input D1;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAM64M (...);
|
module RAM64M (...);
|
||||||
|
@ -3652,6 +3824,7 @@ module RAM64M (...);
|
||||||
input DIB;
|
input DIB;
|
||||||
input DIC;
|
input DIC;
|
||||||
input DID;
|
input DID;
|
||||||
|
(* clkbuf_sink *)
|
||||||
input WCLK;
|
input WCLK;
|
||||||
input WE;
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -3660,46 +3833,97 @@ module RAM64X1S (...);
|
||||||
parameter [63:0] INIT = 64'h0000000000000000;
|
parameter [63:0] INIT = 64'h0000000000000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, A5, D, WCLK, WE;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
|
input D;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAM64X1S_1 (...);
|
module RAM64X1S_1 (...);
|
||||||
parameter [63:0] INIT = 64'h0000000000000000;
|
parameter [63:0] INIT = 64'h0000000000000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, A5, D, WCLK, WE;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
|
input D;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAM64X2S (...);
|
module RAM64X2S (...);
|
||||||
parameter [63:0] INIT_00 = 64'h0000000000000000;
|
parameter [63:0] INIT_00 = 64'h0000000000000000;
|
||||||
parameter [63:0] INIT_01 = 64'h0000000000000000;
|
parameter [63:0] INIT_01 = 64'h0000000000000000;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
output O0, O1;
|
output O0;
|
||||||
input A0, A1, A2, A3, A4, A5, D0, D1, WCLK, WE;
|
output O1;
|
||||||
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
|
input D0;
|
||||||
|
input D1;
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input WCLK;
|
||||||
|
input WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module ROM128X1 (...);
|
module ROM128X1 (...);
|
||||||
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
|
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, A5, A6;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
|
input A6;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module ROM256X1 (...);
|
module ROM256X1 (...);
|
||||||
parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, A5, A6, A7;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
|
input A6;
|
||||||
|
input A7;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module ROM32X1 (...);
|
module ROM32X1 (...);
|
||||||
parameter [31:0] INIT = 32'h00000000;
|
parameter [31:0] INIT = 32'h00000000;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module ROM64X1 (...);
|
module ROM64X1 (...);
|
||||||
parameter [63:0] INIT = 64'h0000000000000000;
|
parameter [63:0] INIT = 64'h0000000000000000;
|
||||||
output O;
|
output O;
|
||||||
input A0, A1, A2, A3, A4, A5;
|
input A0;
|
||||||
|
input A1;
|
||||||
|
input A2;
|
||||||
|
input A3;
|
||||||
|
input A4;
|
||||||
|
input A5;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* keep *)
|
(* keep *)
|
||||||
|
|
|
@ -63,6 +63,9 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
|
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
|
||||||
log(" (this feature is experimental and incomplete)\n");
|
log(" (this feature is experimental and incomplete)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -ise\n");
|
||||||
|
log(" generate an output netlist suitable for ISE (enables -iopad)\n");
|
||||||
|
log("\n");
|
||||||
log(" -nobram\n");
|
log(" -nobram\n");
|
||||||
log(" do not use block RAM cells in output netlist\n");
|
log(" do not use block RAM cells in output netlist\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -80,6 +83,14 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nodsp\n");
|
log(" -nodsp\n");
|
||||||
log(" do not use DSP48E1s to implement multipliers and associated logic\n");
|
log(" do not use DSP48E1s to implement multipliers and associated logic\n");
|
||||||
|
log(" -iopad\n");
|
||||||
|
log(" enable I/O buffer insertion (selected automatically by -ise)\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -noiopad\n");
|
||||||
|
log(" disable I/O buffer insertion (only useful with -ise)\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -noclkbuf\n");
|
||||||
|
log(" disable automatic clock buffer insertion\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -widemux <int>\n");
|
log(" -widemux <int>\n");
|
||||||
log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
|
log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
|
||||||
|
@ -107,7 +118,8 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string top_opt, edif_file, blif_file, family;
|
std::string top_opt, edif_file, blif_file, family;
|
||||||
bool flatten, retime, vpr, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9;
|
bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9;
|
||||||
|
bool flatten_before_abc;
|
||||||
int widemux;
|
int widemux;
|
||||||
|
|
||||||
void clear_flags() YS_OVERRIDE
|
void clear_flags() YS_OVERRIDE
|
||||||
|
@ -119,6 +131,10 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
flatten = false;
|
flatten = false;
|
||||||
retime = false;
|
retime = false;
|
||||||
vpr = false;
|
vpr = false;
|
||||||
|
ise = false;
|
||||||
|
iopad = false;
|
||||||
|
noiopad = false;
|
||||||
|
noclkbuf = false;
|
||||||
nocarry = false;
|
nocarry = false;
|
||||||
nobram = false;
|
nobram = false;
|
||||||
nolutram = false;
|
nolutram = false;
|
||||||
|
@ -127,6 +143,7 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
nowidelut = false;
|
nowidelut = false;
|
||||||
nodsp = false;
|
nodsp = false;
|
||||||
abc9 = false;
|
abc9 = false;
|
||||||
|
flatten_before_abc = false;
|
||||||
widemux = 0;
|
widemux = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +183,10 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
flatten = true;
|
flatten = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-flatten_before_abc") {
|
||||||
|
flatten_before_abc = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-retime") {
|
if (args[argidx] == "-retime") {
|
||||||
retime = true;
|
retime = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -182,6 +203,22 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
vpr = true;
|
vpr = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-ise") {
|
||||||
|
ise = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-iopad") {
|
||||||
|
iopad = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noiopad") {
|
||||||
|
noiopad = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noclkbuf") {
|
||||||
|
noclkbuf = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-nocarry") {
|
if (args[argidx] == "-nocarry") {
|
||||||
nocarry = true;
|
nocarry = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -407,6 +444,8 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
|
|
||||||
if (check_label("map_luts")) {
|
if (check_label("map_luts")) {
|
||||||
run("opt_expr -mux_undef");
|
run("opt_expr -mux_undef");
|
||||||
|
if (flatten_before_abc)
|
||||||
|
run("flatten");
|
||||||
if (help_mode)
|
if (help_mode)
|
||||||
run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')");
|
run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')");
|
||||||
else if (abc9) {
|
else if (abc9) {
|
||||||
|
@ -435,6 +474,18 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
run("clean");
|
run("clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_label("finalize")) {
|
||||||
|
bool do_iopad = iopad || (ise && !noiopad);
|
||||||
|
if (help_mode || !noclkbuf) {
|
||||||
|
if (help_mode || do_iopad)
|
||||||
|
run("clkbufmap -buf BUFG O:I -inpad IBUFG O:I", "(skip if '-noclkbuf', '-inpad' passed if '-iopad' or '-ise' and not '-noiopad')");
|
||||||
|
else
|
||||||
|
run("clkbufmap -buf BUFG O:I");
|
||||||
|
}
|
||||||
|
if (do_iopad)
|
||||||
|
run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");
|
||||||
|
}
|
||||||
|
|
||||||
if (check_label("check")) {
|
if (check_label("check")) {
|
||||||
run("hierarchy -check");
|
run("hierarchy -check");
|
||||||
run("stat -tech xilinx");
|
run("stat -tech xilinx");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module RAMB8BWER (
|
module RAMB8BWER (
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKAWRCLK,
|
input CLKAWRCLK,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKBRDCLK,
|
input CLKBRDCLK,
|
||||||
input ENAWREN,
|
input ENAWREN,
|
||||||
input ENBRDEN,
|
input ENBRDEN,
|
||||||
|
@ -87,7 +89,9 @@ module RAMB8BWER (
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAMB16BWER (
|
module RAMB16BWER (
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKA,
|
input CLKA,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKB,
|
input CLKB,
|
||||||
input ENA,
|
input ENA,
|
||||||
input ENB,
|
input ENB,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module RAMB18E1 (
|
module RAMB18E1 (
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKARDCLK,
|
input CLKARDCLK,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKBWRCLK,
|
input CLKBWRCLK,
|
||||||
input ENARDEN,
|
input ENARDEN,
|
||||||
input ENBWREN,
|
input ENBWREN,
|
||||||
|
@ -123,7 +125,9 @@ module RAMB18E1 (
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module RAMB36E1 (
|
module RAMB36E1 (
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKARDCLK,
|
input CLKARDCLK,
|
||||||
|
(* clkbuf_sink *)
|
||||||
input CLKBWRCLK,
|
input CLKBWRCLK,
|
||||||
input ENARDEN,
|
input ENARDEN,
|
||||||
input ENBWREN,
|
input ENBWREN,
|
||||||
|
|
26
tests/ice40/ice40_opt.ys
Normal file
26
tests/ice40/ice40_opt.ys
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
read_verilog -icells -formal <<EOT
|
||||||
|
module top(input CI, I0, output [1:0] CO, output O);
|
||||||
|
wire A = 1'b0, B = 1'b0;
|
||||||
|
\$__ICE40_CARRY_WRAPPER #(
|
||||||
|
// A[0]: 1010 1010 1010 1010
|
||||||
|
// A[1]: 1100 1100 1100 1100
|
||||||
|
// A[2]: 1111 0000 1111 0000
|
||||||
|
// A[3]: 1111 1111 0000 0000
|
||||||
|
.LUT(~16'b 0110_1001_1001_0110)
|
||||||
|
) u0 (
|
||||||
|
.A(A),
|
||||||
|
.B(B),
|
||||||
|
.CI(CI),
|
||||||
|
.I0(I0),
|
||||||
|
.I3(CI),
|
||||||
|
.CO(CO[0]),
|
||||||
|
.O(O)
|
||||||
|
);
|
||||||
|
SB_CARRY u1 (.I0(~A), .I1(~B), .CI(CI), .CO(CO[1]));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert -map +/ice40/cells_map.v -map +/ice40/cells_sim.v ice40_opt
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:*
|
||||||
|
select -assert-count 1 t:$lut
|
20
tests/ice40/run-test.sh
Executable file
20
tests/ice40/run-test.sh
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
{
|
||||||
|
echo "all::"
|
||||||
|
for x in *.ys; do
|
||||||
|
echo "all:: run-$x"
|
||||||
|
echo "run-$x:"
|
||||||
|
echo " @echo 'Running $x..'"
|
||||||
|
echo " @../../yosys -ql ${x%.ys}.log $x"
|
||||||
|
done
|
||||||
|
for s in *.sh; do
|
||||||
|
if [ "$s" != "run-test.sh" ]; then
|
||||||
|
echo "all:: run-$s"
|
||||||
|
echo "run-$s:"
|
||||||
|
echo " @echo 'Running $s..'"
|
||||||
|
echo " @bash $s"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} > run-test.mk
|
||||||
|
exec ${MAKE:-make} -f run-test.mk
|
|
@ -221,3 +221,73 @@ check
|
||||||
equiv_opt opt_expr -fine
|
equiv_opt opt_expr -fine
|
||||||
design -load postopt
|
design -load postopt
|
||||||
select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
|
select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shiftx_1bit(input [2:0] a, input [1:0] b, output y);
|
||||||
|
\$shiftx #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) shiftx (.A({1'bx,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shiftx r:A_WIDTH=3 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shiftx_3bit(input [9:0] a, input [3:0] b, output [2:0] y);
|
||||||
|
\$shiftx #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shiftx (.A({4'bxx00,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shiftx r:A_WIDTH=12 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shift_1bit(input [2:0] a, input [1:0] b, output y);
|
||||||
|
\$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) shift (.A({1'b0,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shift r:A_WIDTH=3 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shift_3bit(input [9:0] a, input [3:0] b, output [2:0] y);
|
||||||
|
\$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shift (.A({4'b0x0x,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shift r:A_WIDTH=10 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shift_3bit_keepdc(input [9:0] a, input [3:0] b, output [2:0] y);
|
||||||
|
\$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shift (.A({4'b0x0x,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr -keepdc
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shift r:A_WIDTH=13 %i
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module test(input clk, input [3:0] bar, output [3:0] foo);
|
module test(input clk, input [3:0] bar, output [3:0] foo, asdf);
|
||||||
reg [3:0] foo = 0;
|
reg [3:0] foo = 0;
|
||||||
reg [3:0] last_bar = 0;
|
reg [3:0] last_bar = 0;
|
||||||
|
reg [3:0] asdf = 4'b1xxx;
|
||||||
|
|
||||||
always @*
|
always @*
|
||||||
foo[1:0] <= bar[1:0];
|
foo[1:0] <= bar[1:0];
|
||||||
|
@ -11,5 +12,10 @@ module test(input clk, input [3:0] bar, output [3:0] foo);
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
last_bar <= bar;
|
last_bar <= bar;
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
asdf[3] <= bar[3];
|
||||||
|
always @*
|
||||||
|
asdf[2:0] = 3'b111;
|
||||||
|
|
||||||
assert property (foo == {last_bar[3:2], bar[1:0]});
|
assert property (foo == {last_bar[3:2], bar[1:0]});
|
||||||
endmodule
|
endmodule
|
||||||
|
|
1
tests/techmap/.gitignore
vendored
1
tests/techmap/.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
*.log
|
*.log
|
||||||
|
/*.mk
|
||||||
|
|
96
tests/techmap/clkbufmap.ys
Normal file
96
tests/techmap/clkbufmap.ys
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
read_verilog <<EOT
|
||||||
|
module clkbuf (input i, (* clkbuf_driver *) output o); endmodule
|
||||||
|
module dff ((* clkbuf_sink *) input clk, input d, output q); endmodule
|
||||||
|
module dffe ((* clkbuf_sink *) input c, input d, e, output q); endmodule
|
||||||
|
module latch (input e, d, output q); endmodule
|
||||||
|
module clkgen (output o); endmodule
|
||||||
|
|
||||||
|
module top(input clk1, clk2, clk3, d, e, output [4:0] q);
|
||||||
|
wire clk4, clk5, clk6;
|
||||||
|
dff s0 (.clk(clk1), .d(d), .q(q[0]));
|
||||||
|
dffe s1 (.c(clk2), .d(d), .e(e), .q(q[1]));
|
||||||
|
latch s2 (.e(clk3), .d(d), .q(q[2]));
|
||||||
|
sub s3 (.sclk4(clk4), .sclk5(clk5), .sclk6(clk6), .sd(d), .sq(q[3]));
|
||||||
|
dff s4 (.clk(clk4), .d(d), .q(q[4]));
|
||||||
|
dff s5 (.clk(clk5), .d(d), .q(q[4]));
|
||||||
|
dff s6 (.clk(clk6), .d(d), .q(q[4]));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub(output sclk4, output sclk5, output sclk6, input sd, output sq);
|
||||||
|
wire tmp;
|
||||||
|
clkgen s7(.o(sclk4));
|
||||||
|
clkgen s8(.o(sclk5));
|
||||||
|
clkgen s9(.o(tmp));
|
||||||
|
clkbuf s10(.i(tmp), .o(sclk6));
|
||||||
|
dff s11(.clk(sclk4), .d(sd), .q(sq));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
hierarchy -auto-top
|
||||||
|
design -save ref
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
design -load ref
|
||||||
|
clkbufmap -buf clkbuf o:i
|
||||||
|
select -assert-count 3 top/t:clkbuf
|
||||||
|
select -assert-count 2 sub/t:clkbuf
|
||||||
|
select -set clk1 w:clk1 %a %co t:clkbuf %i # Find 'clk1' fanouts that are 'clkbuf'
|
||||||
|
select -assert-count 1 @clk1 # Check there is one such fanout
|
||||||
|
select -assert-count 1 @clk1 %x:+[o] %co c:s* %i # Check that the 'o' of that clkbuf drives one fanout
|
||||||
|
select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i # And that one fanout is 's0'
|
||||||
|
select -set clk2 w:clk2 %a %co t:clkbuf %i
|
||||||
|
select -assert-count 1 @clk2
|
||||||
|
select -assert-count 1 @clk2 %x:+[o] %co c:s* %i
|
||||||
|
select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i
|
||||||
|
select -set clk5 w:clk5 %a %ci t:clkbuf %i
|
||||||
|
select -assert-count 1 @clk5
|
||||||
|
select -assert-count 1 @clk5 %x:+[o] %co c:s5 %i
|
||||||
|
select -assert-count 1 @clk5 %x:+[i] %ci c:s3 %i
|
||||||
|
select -set sclk4 w:sclk4 %a %ci t:clkbuf %i
|
||||||
|
select -assert-count 1 @sclk4
|
||||||
|
select -assert-count 1 @sclk4 %x:+[o] %co c:s11 %i
|
||||||
|
select -assert-count 1 @sclk4 %x:+[i] %ci c:s7 %i
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
design -load ref
|
||||||
|
setattr -set clkbuf_inhibit 0 w:clk1
|
||||||
|
setattr -set clkbuf_inhibit 1 w:clk2
|
||||||
|
clkbufmap -buf clkbuf o:i
|
||||||
|
select -assert-count 2 top/t:clkbuf
|
||||||
|
select -set clk1 w:clk1 %a %co t:clkbuf %i # Find 'clk1' fanouts that are 'clkbuf'
|
||||||
|
select -assert-count 1 @clk1 # Check there is one such fanout
|
||||||
|
select -assert-count 1 @clk1 %x:+[o] %co c:s* %i # Check that the 'o' of that clkbuf drives one fanout
|
||||||
|
select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i # And that one fanout is 's0'
|
||||||
|
select -assert-count 0 w:clk2 %a %co t:clkbuf %i
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
design -load ref
|
||||||
|
setattr -set clkbuf_inhibit 1 w:clk1
|
||||||
|
setattr -set buffer_type "bufg" w:clk2
|
||||||
|
clkbufmap -buf clkbuf o:i w:* a:buffer_type=none a:buffer_type=bufr %u %d
|
||||||
|
select -assert-count 3 top/t:clkbuf
|
||||||
|
select -assert-count 2 sub/t:clkbuf
|
||||||
|
select -set clk1 w:clk1 %a %co t:clkbuf %i # Find 'clk1' fanouts that are 'clkbuf'
|
||||||
|
select -assert-count 1 @clk1 # Check there is one such fanout
|
||||||
|
select -assert-count 1 @clk1 %x:+[o] %co c:s* %i # Check that the 'o' of that clkbuf drives one fanout
|
||||||
|
select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i # And that one fanout is 's0'
|
||||||
|
select -set clk2 w:clk2 %a %co t:clkbuf %i # Find 'clk1' fanouts that are 'clkbuf'
|
||||||
|
select -assert-count 1 @clk2 # Check there is one such fanout
|
||||||
|
select -assert-count 1 @clk2 %x:+[o] %co c:s* %i # Check that the 'o' of that clkbuf drives one fanout
|
||||||
|
select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i # And that one fanout is 's0'
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
design -load ref
|
||||||
|
setattr -set buffer_type "none" w:clk1
|
||||||
|
setattr -set buffer_type "bufr" w:clk2
|
||||||
|
setattr -set buffer_type "bufr" w:sclk4
|
||||||
|
setattr -set buffer_type "bufr" w:sclk5
|
||||||
|
clkbufmap -buf clkbuf o:i w:* a:buffer_type=none a:buffer_type=bufr %u %d
|
||||||
|
select -assert-count 0 w:clk1 %a %co t:clkbuf %i
|
||||||
|
select -assert-count 0 w:clk2 %a %co t:clkbuf %i
|
||||||
|
select -assert-count 0 top/t:clkbuf
|
||||||
|
select -assert-count 1 sub/t:clkbuf
|
8
tests/techmap/recursive.v
Normal file
8
tests/techmap/recursive.v
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
module top;
|
||||||
|
sub s0();
|
||||||
|
foo f0();
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module foo;
|
||||||
|
sub s0();
|
||||||
|
endmodule
|
4
tests/techmap/recursive_map.v
Normal file
4
tests/techmap/recursive_map.v
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module sub;
|
||||||
|
sub _TECHMAP_REPLACE_ ();
|
||||||
|
bar f0();
|
||||||
|
endmodule
|
3
tests/techmap/recursive_runtest.sh
Normal file
3
tests/techmap/recursive_runtest.sh
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
set -ev
|
||||||
|
|
||||||
|
../../yosys -p 'hierarchy -top top; techmap -map recursive_map.v -max_iter 1; select -assert-count 2 t:sub; select -assert-count 2 t:bar' recursive.v
|
|
@ -1,10 +1,20 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
for x in *_runtest.sh; do
|
{
|
||||||
echo "Running $x.."
|
echo "all::"
|
||||||
if ! bash $x &> ${x%.sh}.log; then
|
for x in *.ys; do
|
||||||
tail ${x%.sh}.log
|
echo "all:: run-$x"
|
||||||
echo ERROR
|
echo "run-$x:"
|
||||||
exit 1
|
echo " @echo 'Running $x..'"
|
||||||
|
echo " @../../yosys -ql ${x%.ys}.log $x"
|
||||||
|
done
|
||||||
|
for s in *.sh; do
|
||||||
|
if [ "$s" != "run-test.sh" ]; then
|
||||||
|
echo "all:: run-$s"
|
||||||
|
echo "run-$s:"
|
||||||
|
echo " @echo 'Running $s..'"
|
||||||
|
echo " @bash $s > ${s%.sh}.log 2>&1"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
} > run-test.mk
|
||||||
|
exec ${MAKE:-make} -f run-test.mk
|
||||||
|
|
14
tests/various/mem2reg.ys
Normal file
14
tests/various/mem2reg.ys
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top;
|
||||||
|
parameter DATADEPTH=2;
|
||||||
|
parameter DATAWIDTH=1;
|
||||||
|
(* keep, nomem2reg *) reg [DATAWIDTH-1:0] data1 [DATADEPTH-1:0];
|
||||||
|
(* keep, mem2reg *) reg [DATAWIDTH-1:0] data2 [DATADEPTH-1:0];
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc
|
||||||
|
cd top
|
||||||
|
select -assert-count 1 m:data1 a:src=<<EOT:4 %i
|
||||||
|
select -assert-count 2 w:data2[*] a:src=<<EOT:5 %i
|
||||||
|
select -assert-none a:mem2reg
|
Loading…
Reference in a new issue