mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'upstream/master'
# Conflicts: # CHANGELOG # frontends/verific/verific.cc # frontends/verilog/verilog_parser.y
This commit is contained in:
commit
f4d500f98e
|
@ -0,0 +1,7 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = tab
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
|
@ -134,9 +134,9 @@ matrix:
|
|||
|
||||
# Latest clang on Mac OS X
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
osx_image: xcode9.4
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
||||
|
||||
before_install:
|
||||
- ./.travis/setup.sh
|
||||
|
|
|
@ -64,7 +64,6 @@ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
|||
brew tap Homebrew/bundle
|
||||
brew bundle
|
||||
brew install ccache
|
||||
brew install gcc@7
|
||||
echo
|
||||
echo -en 'travis_fold:end:before_install.brew\\r'
|
||||
echo
|
||||
|
|
16
CHANGELOG
16
CHANGELOG
|
@ -3,6 +3,22 @@ List of major changes and improvements between releases
|
|||
=======================================================
|
||||
|
||||
|
||||
Yosys 0.8 .. Yosys 0.8-dev
|
||||
--------------------------
|
||||
|
||||
* Various
|
||||
- Added $changed support to read_verilog
|
||||
- Added "write_edif -attrprop"
|
||||
- Added "ice40_unlut" pass
|
||||
- Added "opt_lut" pass
|
||||
- Added "synth_ice40 -relut"
|
||||
- Added "synth_ice40 -noabc"
|
||||
- Added "gate2lut.v" techmap rule
|
||||
- Added "rename -src"
|
||||
- Added "equiv_opt" pass
|
||||
|
||||
|
||||
>>>>>>> upstream/master
|
||||
Yosys 0.7 .. Yosys 0.8
|
||||
----------------------
|
||||
|
||||
|
|
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2012 - 2017 Clifford Wolf <clifford@clifford.at>
|
||||
Copyright (C) 2012 - 2018 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
|
||||
|
|
20
Makefile
20
Makefile
|
@ -72,6 +72,7 @@ PKG_CONFIG ?= pkg-config
|
|||
SED ?= sed
|
||||
BISON ?= bison
|
||||
STRIP ?= strip
|
||||
AWK ?= awk
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
PLUGIN_LDFLAGS += -undefined dynamic_lookup
|
||||
|
@ -99,7 +100,7 @@ LDFLAGS += -rdynamic
|
|||
LDLIBS += -lrt
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.7+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 61f6811.. | wc -l; })
|
||||
YOSYS_VER := 0.8+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 4d4665b.. | wc -l; })
|
||||
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
|
||||
OBJS = kernel/version_$(GIT_REV).o
|
||||
|
||||
|
@ -109,7 +110,7 @@ OBJS = kernel/version_$(GIT_REV).o
|
|||
# is just a symlink to your actual ABC working directory, as 'make mrproper'
|
||||
# will remove the 'abc' directory and you do not want to accidentally
|
||||
# delete your work on ABC..
|
||||
ABCREV = ae6716b
|
||||
ABCREV = 2ddc57d
|
||||
ABCPULL = 1
|
||||
ABCURL ?= https://github.com/berkeley-abc/abc
|
||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
|
||||
|
@ -357,10 +358,14 @@ endif
|
|||
|
||||
ifeq ($(ENABLE_VERIFIC),1)
|
||||
VERIFIC_DIR ?= /usr/local/src/verific_lib_eval
|
||||
VERIFIC_COMPONENTS ?= verilog vhdl database util containers sdf hier_tree
|
||||
VERIFIC_COMPONENTS ?= verilog vhdl database util containers hier_tree
|
||||
CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC
|
||||
ifeq ($(OS), Darwin)
|
||||
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-mac.a,$(VERIFIC_COMPONENTS)) -lz
|
||||
else
|
||||
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PROTOBUF),1)
|
||||
LDLIBS += $(shell pkg-config --cflags --libs protobuf)
|
||||
|
@ -391,8 +396,8 @@ endef
|
|||
ifeq ($(PRETTY), 1)
|
||||
P_STATUS = 0
|
||||
P_OFFSET = 0
|
||||
P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | gawk 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }'))
|
||||
P_SHOW = [$(shell gawk "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%]
|
||||
P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | $(AWK) 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }'))
|
||||
P_SHOW = [$(shell $(AWK) "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%]
|
||||
P = @echo "$(if $(findstring $@,$(TARGETS) $(EXTRA_TARGETS)),$(eval P_OFFSET = 10))$(call P_UPDATE)$(call P_SHOW) Building $@";
|
||||
Q = @
|
||||
S = -s
|
||||
|
@ -573,6 +578,8 @@ test: $(TARGETS) $(EXTRA_TARGETS)
|
|||
+cd tests/bram && bash run-test.sh $(SEEDOPT)
|
||||
+cd tests/various && bash run-test.sh
|
||||
+cd tests/sat && bash run-test.sh
|
||||
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
|
||||
+cd tests/opt && bash run-test.sh
|
||||
@echo ""
|
||||
@echo " Passed \"make test\"."
|
||||
@echo ""
|
||||
|
@ -594,7 +601,7 @@ vloghtb: $(TARGETS) $(EXTRA_TARGETS)
|
|||
ystests: $(TARGETS) $(EXTRA_TARGETS)
|
||||
rm -rf tests/ystests
|
||||
git clone https://github.com/YosysHQ/yosys-tests.git tests/ystests
|
||||
+PATH="$$PWD:$$PATH" cd tests/ystests && $(MAKE)
|
||||
+$(MAKE) PATH="$$PWD:$$PATH" -C tests/ystests
|
||||
@echo ""
|
||||
@echo " Finished \"make ystests\"."
|
||||
@echo ""
|
||||
|
@ -655,6 +662,7 @@ clean:
|
|||
rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log
|
||||
rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp
|
||||
rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
|
||||
rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
|
||||
rm -f tests/tools/cmp_tbdata
|
||||
|
||||
clean-abc:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
```
|
||||
yosys -- Yosys Open SYnthesis Suite
|
||||
|
||||
Copyright (C) 2012 - 2017 Clifford Wolf <clifford@clifford.at>
|
||||
Copyright (C) 2012 - 2018 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
|
||||
|
@ -452,6 +452,9 @@ from SystemVerilog:
|
|||
into a design with ``read_verilog``, all its packages are available to
|
||||
SystemVerilog files being read into the same design afterwards.
|
||||
|
||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
||||
ports are inputs or outputs are supported.
|
||||
|
||||
|
||||
Building the documentation
|
||||
==========================
|
||||
|
|
|
@ -100,7 +100,7 @@ struct AigerWriter
|
|||
return aig_map.at(bit);
|
||||
}
|
||||
|
||||
AigerWriter(Module *module, bool zinit_mode) : module(module), zinit_mode(zinit_mode), sigmap(module)
|
||||
AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
|
||||
{
|
||||
pool<SigBit> undriven_bits;
|
||||
pool<SigBit> unused_bits;
|
||||
|
@ -293,6 +293,10 @@ struct AigerWriter
|
|||
aig_map[bit] = 2*aig_m;
|
||||
}
|
||||
|
||||
if (imode && input_bits.empty()) {
|
||||
aig_m++, aig_i++;
|
||||
}
|
||||
|
||||
if (zinit_mode)
|
||||
{
|
||||
for (auto it : ff_map) {
|
||||
|
@ -371,6 +375,11 @@ struct AigerWriter
|
|||
aig_outputs.push_back(bit2aig(bit));
|
||||
}
|
||||
|
||||
if (omode && output_bits.empty()) {
|
||||
aig_o++;
|
||||
aig_outputs.push_back(0);
|
||||
}
|
||||
|
||||
for (auto it : asserts) {
|
||||
aig_b++;
|
||||
int bit_a = bit2aig(it.first);
|
||||
|
@ -378,6 +387,11 @@ struct AigerWriter
|
|||
aig_outputs.push_back(mkgate(bit_a^1, bit_en));
|
||||
}
|
||||
|
||||
if (bmode && asserts.empty()) {
|
||||
aig_b++;
|
||||
aig_outputs.push_back(0);
|
||||
}
|
||||
|
||||
for (auto it : assumes) {
|
||||
aig_c++;
|
||||
int bit_a = bit2aig(it.first);
|
||||
|
@ -689,6 +703,11 @@ struct AigerBackend : public Backend {
|
|||
log(" -vmap <filename>\n");
|
||||
log(" like -map, but more verbose\n");
|
||||
log("\n");
|
||||
log(" -I, -O, -B\n");
|
||||
log(" If the design contains no input/output/assert then create one\n");
|
||||
log(" dummy input/output/bad_state pin to make the tools reading the\n");
|
||||
log(" AIGER file happy.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
|
@ -697,6 +716,9 @@ struct AigerBackend : public Backend {
|
|||
bool miter_mode = false;
|
||||
bool symbols_mode = false;
|
||||
bool verbose_map = false;
|
||||
bool imode = false;
|
||||
bool omode = false;
|
||||
bool bmode = false;
|
||||
std::string map_filename;
|
||||
|
||||
log_header(design, "Executing AIGER backend.\n");
|
||||
|
@ -729,6 +751,18 @@ struct AigerBackend : public Backend {
|
|||
verbose_map = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-I") {
|
||||
imode = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-O") {
|
||||
omode = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-B") {
|
||||
bmode = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
@ -738,7 +772,7 @@ struct AigerBackend : public Backend {
|
|||
if (top_module == nullptr)
|
||||
log_error("Can't find top module in current design!\n");
|
||||
|
||||
AigerWriter writer(top_module, zinit_mode);
|
||||
AigerWriter writer(top_module, zinit_mode, imode, omode, bmode);
|
||||
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
||||
|
||||
if (!map_filename.empty()) {
|
||||
|
|
|
@ -133,12 +133,13 @@ struct BtorWorker
|
|||
cell_recursion_guard.insert(cell);
|
||||
btorf_push(log_id(cell));
|
||||
|
||||
if (cell->type.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx",
|
||||
"$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
|
||||
if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx",
|
||||
"$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
|
||||
{
|
||||
string btor_op;
|
||||
if (cell->type == "$add") btor_op = "add";
|
||||
if (cell->type == "$sub") btor_op = "sub";
|
||||
if (cell->type == "$mul") btor_op = "mul";
|
||||
if (cell->type.in("$shl", "$sshl")) btor_op = "sll";
|
||||
if (cell->type == "$shr") btor_op = "srl";
|
||||
if (cell->type == "$sshr") btor_op = "sra";
|
||||
|
@ -146,6 +147,7 @@ struct BtorWorker
|
|||
if (cell->type.in("$and", "$_AND_")) btor_op = "and";
|
||||
if (cell->type.in("$or", "$_OR_")) btor_op = "or";
|
||||
if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor";
|
||||
if (cell->type == "$concat") btor_op = "concat";
|
||||
if (cell->type == "$_NAND_") btor_op = "nand";
|
||||
if (cell->type == "$_NOR_") btor_op = "nor";
|
||||
if (cell->type.in("$xnor", "$_XNOR_")) btor_op = "xnor";
|
||||
|
@ -214,6 +216,40 @@ struct BtorWorker
|
|||
goto okay;
|
||||
}
|
||||
|
||||
if (cell->type.in("$div", "$mod"))
|
||||
{
|
||||
string btor_op;
|
||||
if (cell->type == "$div") btor_op = "div";
|
||||
if (cell->type == "$mod") btor_op = "rem";
|
||||
log_assert(!btor_op.empty());
|
||||
|
||||
int width = GetSize(cell->getPort("\\Y"));
|
||||
width = std::max(width, GetSize(cell->getPort("\\A")));
|
||||
width = std::max(width, GetSize(cell->getPort("\\B")));
|
||||
|
||||
bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false;
|
||||
bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false;
|
||||
|
||||
int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed);
|
||||
int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed);
|
||||
|
||||
int sid = get_bv_sid(width);
|
||||
int nid = next_nid++;
|
||||
btorf("%d %c%s %d %d %d\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b);
|
||||
|
||||
SigSpec sig = sigmap(cell->getPort("\\Y"));
|
||||
|
||||
if (GetSize(sig) < width) {
|
||||
int sid = get_bv_sid(GetSize(sig));
|
||||
int nid2 = next_nid++;
|
||||
btorf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1);
|
||||
nid = nid2;
|
||||
}
|
||||
|
||||
add_nid_sig(nid, sig);
|
||||
goto okay;
|
||||
}
|
||||
|
||||
if (cell->type.in("$_ANDNOT_", "$_ORNOT_"))
|
||||
{
|
||||
int sid = get_bv_sid(1);
|
||||
|
@ -506,6 +542,18 @@ struct BtorWorker
|
|||
}
|
||||
}
|
||||
|
||||
Const initval;
|
||||
for (int i = 0; i < GetSize(sig_q); i++)
|
||||
if (initbits.count(sig_q[i]))
|
||||
initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
|
||||
else
|
||||
initval.bits.push_back(State::Sx);
|
||||
|
||||
int nid_init_val = -1;
|
||||
|
||||
if (!initval.is_fully_undef())
|
||||
nid_init_val = get_sig_nid(initval);
|
||||
|
||||
int sid = get_bv_sid(GetSize(sig_q));
|
||||
int nid = next_nid++;
|
||||
|
||||
|
@ -514,15 +562,7 @@ struct BtorWorker
|
|||
else
|
||||
btorf("%d state %d %s\n", nid, sid, log_id(symbol));
|
||||
|
||||
Const initval;
|
||||
for (int i = 0; i < GetSize(sig_q); i++)
|
||||
if (initbits.count(sig_q[i]))
|
||||
initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
|
||||
else
|
||||
initval.bits.push_back(State::Sx);
|
||||
|
||||
if (!initval.is_fully_undef()) {
|
||||
int nid_init_val = get_sig_nid(initval);
|
||||
if (nid_init_val >= 0) {
|
||||
int nid_init = next_nid++;
|
||||
if (verbose)
|
||||
btorf("; initval = %s\n", log_signal(initval));
|
||||
|
|
|
@ -554,7 +554,9 @@ struct Smt2Worker
|
|||
|
||||
if (cell->type.in("$shift", "$shiftx")) {
|
||||
if (cell->getParam("\\B_SIGNED").as_bool()) {
|
||||
/* FIXME */
|
||||
return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) "
|
||||
"(bvlshr A B) (bvlshr A (bvneg B)))",
|
||||
GetSize(cell->getPort("\\B")), 0), 's');
|
||||
} else {
|
||||
return export_bvop(cell, "(bvlshr A B)", 's');
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ cexfile = None
|
|||
aimfile = None
|
||||
aiwfile = None
|
||||
aigheader = True
|
||||
btorwitfile = None
|
||||
vlogtbfile = None
|
||||
vlogtbtop = None
|
||||
inconstr = list()
|
||||
|
@ -92,6 +93,9 @@ yosys-smtbmc [options] <yosys_smt2_output>
|
|||
the AIGER witness file does not include the status and
|
||||
properties lines.
|
||||
|
||||
--btorwit <btor_witness_filename>
|
||||
read a BTOR witness.
|
||||
|
||||
--noinfo
|
||||
only run the core proof, do not collect and print any
|
||||
additional information (e.g. which assert failed)
|
||||
|
@ -152,7 +156,7 @@ yosys-smtbmc [options] <yosys_smt2_output>
|
|||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts +
|
||||
["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "presat",
|
||||
["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "btorwit=", "presat",
|
||||
"dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append=",
|
||||
"smtc-init", "smtc-top=", "noinit"])
|
||||
except:
|
||||
|
@ -189,6 +193,8 @@ for o, a in opts:
|
|||
aiwfile = a + ".aiw"
|
||||
elif o == "--aig-noheader":
|
||||
aigheader = False
|
||||
elif o == "--btorwit":
|
||||
btorwitfile = a
|
||||
elif o == "--dump-vcd":
|
||||
vcdfile = a
|
||||
elif o == "--dump-vlogtb":
|
||||
|
@ -575,6 +581,103 @@ if aimfile is not None:
|
|||
num_steps = max(num_steps, step+1)
|
||||
step += 1
|
||||
|
||||
if btorwitfile is not None:
|
||||
with open(btorwitfile, "r") as f:
|
||||
step = None
|
||||
suffix = None
|
||||
altsuffix = None
|
||||
header_okay = False
|
||||
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
|
||||
if line == "sat":
|
||||
header_okay = True
|
||||
continue
|
||||
|
||||
if not header_okay:
|
||||
continue
|
||||
|
||||
if line == "" or line[0] == "b" or line[0] == "j":
|
||||
continue
|
||||
|
||||
if line == ".":
|
||||
break
|
||||
|
||||
if line[0] == '#' or line[0] == '@':
|
||||
step = int(line[1:])
|
||||
suffix = line
|
||||
altsuffix = suffix
|
||||
if suffix[0] == "@":
|
||||
altsuffix = "#" + suffix[1:]
|
||||
else:
|
||||
altsuffix = "@" + suffix[1:]
|
||||
continue
|
||||
|
||||
line = line.split()
|
||||
|
||||
if len(line) == 0:
|
||||
continue
|
||||
|
||||
if line[-1].endswith(suffix):
|
||||
line[-1] = line[-1][0:len(line[-1]) - len(suffix)]
|
||||
|
||||
if line[-1].endswith(altsuffix):
|
||||
line[-1] = line[-1][0:len(line[-1]) - len(altsuffix)]
|
||||
|
||||
if line[-1][0] == "$":
|
||||
continue
|
||||
|
||||
# BV assignments
|
||||
if len(line) == 3 and line[1][0] != "[":
|
||||
value = line[1]
|
||||
name = line[2]
|
||||
|
||||
path = smt.get_path(topmod, name)
|
||||
|
||||
if not smt.net_exists(topmod, path):
|
||||
continue
|
||||
|
||||
width = smt.net_width(topmod, path)
|
||||
|
||||
if width == 1:
|
||||
assert value in ["0", "1"]
|
||||
value = "true" if value == "1" else "false"
|
||||
else:
|
||||
value = "#b" + value
|
||||
|
||||
smtexpr = "(= [%s] %s)" % (name, value)
|
||||
constr_assumes[step].append((btorwitfile, smtexpr))
|
||||
|
||||
# Array assignments
|
||||
if len(line) == 4 and line[1][0] == "[":
|
||||
index = line[1]
|
||||
value = line[2]
|
||||
name = line[3]
|
||||
|
||||
path = smt.get_path(topmod, name)
|
||||
|
||||
if not smt.mem_exists(topmod, path):
|
||||
continue
|
||||
|
||||
meminfo = smt.mem_info(topmod, path)
|
||||
|
||||
if meminfo[1] == 1:
|
||||
assert value in ["0", "1"]
|
||||
value = "true" if value == "1" else "false"
|
||||
else:
|
||||
value = "#b" + value
|
||||
|
||||
assert index[0] == "["
|
||||
assert index[-1] == "]"
|
||||
index = "#b" + index[1:-1]
|
||||
|
||||
smtexpr = "(= (select [%s] %s) %s)" % (name, index, value)
|
||||
constr_assumes[step].append((btorwitfile, smtexpr))
|
||||
|
||||
skip_steps = step
|
||||
num_steps = step+1
|
||||
|
||||
def write_vcd_trace(steps_start, steps_stop, index):
|
||||
filename = vcdfile.replace("%", index)
|
||||
print_msg("Writing trace to VCD file: %s" % (filename))
|
||||
|
@ -1259,7 +1362,11 @@ elif covermode:
|
|||
smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i))
|
||||
smt_assert_consequent(get_constr_expr(constr_assumes, i))
|
||||
print_msg("Re-solving with appended steps..")
|
||||
assert smt_check_sat() == "sat"
|
||||
if smt_check_sat() == "unsat":
|
||||
print("%s Cannot appended steps without violating assumptions!" % smt.timestamp())
|
||||
found_failed_assert = True
|
||||
retstatus = False
|
||||
break
|
||||
|
||||
reached_covers = smt.bv2bin(smt.get("(covers_%d s%d)" % (coveridx, step)))
|
||||
assert len(reached_covers) == len(cover_desc)
|
||||
|
@ -1377,7 +1484,11 @@ else: # not tempind, covermode
|
|||
smt_assert_antecedent("(|%s_h| s%d)" % (topmod, i))
|
||||
smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i))
|
||||
smt_assert_consequent(get_constr_expr(constr_assumes, i))
|
||||
assert smt_check_sat() == "sat"
|
||||
print_msg("Re-solving with appended steps..")
|
||||
if smt_check_sat() == "unsat":
|
||||
print("%s Cannot appended steps without violating assumptions!" % smt.timestamp())
|
||||
retstatus = False
|
||||
break
|
||||
print_anyconsts(step)
|
||||
for i in range(step, last_check_step+1):
|
||||
print_failed_asserts(i)
|
||||
|
|
|
@ -31,11 +31,19 @@ from threading import Thread
|
|||
# does not run out of stack frames when parsing large expressions
|
||||
if os.name == "posix":
|
||||
smtio_reclimit = 64 * 1024
|
||||
smtio_stacksize = 128 * 1024 * 1024
|
||||
if sys.getrecursionlimit() < smtio_reclimit:
|
||||
sys.setrecursionlimit(smtio_reclimit)
|
||||
if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize:
|
||||
resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1))
|
||||
|
||||
current_rlimit_stack = resource.getrlimit(resource.RLIMIT_STACK)
|
||||
if current_rlimit_stack[0] != resource.RLIM_INFINITY:
|
||||
smtio_stacksize = 128 * 1024 * 1024
|
||||
if os.uname().sysname == "Darwin":
|
||||
# MacOS has rather conservative stack limits
|
||||
smtio_stacksize = 16 * 1024 * 1024
|
||||
if current_rlimit_stack[1] != resource.RLIM_INFINITY:
|
||||
smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1])
|
||||
if current_rlimit_stack[0] < smtio_stacksize:
|
||||
resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1]))
|
||||
|
||||
|
||||
# currently running solvers (so we can kill them)
|
||||
|
@ -158,19 +166,28 @@ class SmtIo:
|
|||
self.unroll = False
|
||||
|
||||
if self.solver == "yices":
|
||||
self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts
|
||||
if self.noincr:
|
||||
self.popen_vargs = ['yices-smt2'] + self.solver_opts
|
||||
else:
|
||||
self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts
|
||||
|
||||
if self.solver == "z3":
|
||||
self.popen_vargs = ['z3', '-smt2', '-in'] + self.solver_opts
|
||||
|
||||
if self.solver == "cvc4":
|
||||
self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts
|
||||
if self.noincr:
|
||||
self.popen_vargs = ['cvc4', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts
|
||||
else:
|
||||
self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts
|
||||
|
||||
if self.solver == "mathsat":
|
||||
self.popen_vargs = ['mathsat'] + self.solver_opts
|
||||
|
||||
if self.solver == "boolector":
|
||||
self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts
|
||||
if self.noincr:
|
||||
self.popen_vargs = ['boolector', '--smt2'] + self.solver_opts
|
||||
else:
|
||||
self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts
|
||||
self.unroll = True
|
||||
|
||||
if self.solver == "abc":
|
||||
|
|
|
@ -42,7 +42,7 @@ struct SmvWorker
|
|||
|
||||
pool<Wire*> partial_assignment_wires;
|
||||
dict<SigBit, std::pair<const char*, int>> partial_assignment_bits;
|
||||
vector<string> assignments, invarspecs;
|
||||
vector<string> inputvars, vars, definitions, assignments, invarspecs;
|
||||
|
||||
const char *cid()
|
||||
{
|
||||
|
@ -195,7 +195,7 @@ struct SmvWorker
|
|||
return rvalue(sig);
|
||||
|
||||
const char *temp_id = cid();
|
||||
f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig));
|
||||
// f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig));
|
||||
|
||||
int offset = 0;
|
||||
for (auto bit : sig) {
|
||||
|
@ -210,14 +210,14 @@ struct SmvWorker
|
|||
void run()
|
||||
{
|
||||
f << stringf("MODULE %s\n", cid(module->name));
|
||||
f << stringf(" VAR\n");
|
||||
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (SigSpec(wire) != sigmap(wire))
|
||||
partial_assignment_wires.insert(wire);
|
||||
|
||||
f << stringf(" %s : unsigned word[%d]; -- %s\n", cid(wire->name), wire->width, log_id(wire));
|
||||
if (wire->port_input)
|
||||
inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire)));
|
||||
|
||||
if (wire->attributes.count("\\init"))
|
||||
assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at("\\init"))));
|
||||
|
@ -275,8 +275,8 @@ struct SmvWorker
|
|||
const char *b_shr = rvalue_u(sig_b);
|
||||
const char *b_shl = cid();
|
||||
|
||||
f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b));
|
||||
assignments.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b)));
|
||||
// f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b));
|
||||
definitions.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b)));
|
||||
|
||||
string expr_shl = stringf("resize(%s << %s[%d:0], %d)", expr_a.c_str(), b_shl, shift_b_width-1, width_y);
|
||||
string expr_shr = stringf("resize(%s >> %s[%d:0], %d)", expr_a.c_str(), b_shr, shift_b_width-1, width_y);
|
||||
|
@ -303,7 +303,7 @@ struct SmvWorker
|
|||
GetSize(sig_b)-shift_b_width, width_y, expr.c_str());
|
||||
}
|
||||
|
||||
assignments.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str()));
|
||||
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str()));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -319,12 +319,12 @@ struct SmvWorker
|
|||
|
||||
if (cell->getParam("\\A_SIGNED").as_bool())
|
||||
{
|
||||
assignments.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")),
|
||||
op.c_str(), rvalue_s(cell->getPort("\\A"), width)));
|
||||
}
|
||||
else
|
||||
{
|
||||
assignments.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")),
|
||||
op.c_str(), rvalue_u(cell->getPort("\\A"), width)));
|
||||
}
|
||||
|
||||
|
@ -346,12 +346,12 @@ struct SmvWorker
|
|||
|
||||
if (cell->getParam("\\A_SIGNED").as_bool())
|
||||
{
|
||||
assignments.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width)));
|
||||
}
|
||||
else
|
||||
{
|
||||
assignments.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")),
|
||||
rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width)));
|
||||
}
|
||||
|
||||
|
@ -370,12 +370,12 @@ struct SmvWorker
|
|||
|
||||
if (cell->getParam("\\A_SIGNED").as_bool())
|
||||
{
|
||||
assignments.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width), width_y));
|
||||
}
|
||||
else
|
||||
{
|
||||
assignments.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width), width_y));
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ struct SmvWorker
|
|||
expr_b = stringf("resize(%s, %d)", rvalue(cell->getPort("\\B")), width);
|
||||
}
|
||||
|
||||
assignments.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")),
|
||||
expr_a.c_str(), op.c_str(), expr_b.c_str(), GetSize(cell->getPort("\\Y"))));
|
||||
|
||||
continue;
|
||||
|
@ -425,7 +425,7 @@ struct SmvWorker
|
|||
if (cell->type == "$reduce_or") expr = stringf("%s != 0ub%d_0", expr_a, width_a);
|
||||
if (cell->type == "$reduce_bool") expr = stringf("%s != 0ub%d_0", expr_a, width_a);
|
||||
|
||||
assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
|
||||
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -444,7 +444,7 @@ struct SmvWorker
|
|||
if (cell->type == "$reduce_xnor")
|
||||
expr = "!(" + expr + ")";
|
||||
|
||||
assignments.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y));
|
||||
definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@ struct SmvWorker
|
|||
if (cell->type == "$logic_and") expr = expr_a + " & " + expr_b;
|
||||
if (cell->type == "$logic_or") expr = expr_a + " | " + expr_b;
|
||||
|
||||
assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
|
||||
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -474,7 +474,7 @@ struct SmvWorker
|
|||
string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a);
|
||||
const char *expr_y = lvalue(cell->getPort("\\Y"));
|
||||
|
||||
assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y));
|
||||
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -490,12 +490,13 @@ struct SmvWorker
|
|||
expr += stringf("bool(%s) ? %s : ", rvalue(sig_s[i]), rvalue(sig_b.extract(i*width, width)));
|
||||
expr += rvalue(sig_a);
|
||||
|
||||
assignments.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str()));
|
||||
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$dff")
|
||||
{
|
||||
vars.push_back(stringf("%s : unsigned word[%d]; -- %s", lvalue(cell->getPort("\\Q")), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q"))));
|
||||
assignments.push_back(stringf("next(%s) := %s;", lvalue(cell->getPort("\\Q")), rvalue(cell->getPort("\\D"))));
|
||||
continue;
|
||||
}
|
||||
|
@ -503,7 +504,7 @@ struct SmvWorker
|
|||
if (cell->type.in("$_BUF_", "$_NOT_"))
|
||||
{
|
||||
string op = cell->type == "$_NOT_" ? "!" : "";
|
||||
assignments.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A"))));
|
||||
definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -517,49 +518,49 @@ struct SmvWorker
|
|||
if (cell->type.in("$_XNOR_")) op = "xnor";
|
||||
|
||||
if (cell->type.in("$_ANDNOT_", "$_ORNOT_"))
|
||||
assignments.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
|
||||
else
|
||||
if (cell->type.in("$_NAND_", "$_NOR_"))
|
||||
assignments.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
|
||||
else
|
||||
assignments.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_MUX_")
|
||||
{
|
||||
assignments.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_AOI3_")
|
||||
{
|
||||
assignments.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_OAI3_")
|
||||
{
|
||||
assignments.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_AOI4_")
|
||||
{
|
||||
assignments.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_OAI4_")
|
||||
{
|
||||
assignments.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")),
|
||||
definitions.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D"))));
|
||||
continue;
|
||||
}
|
||||
|
@ -567,13 +568,13 @@ struct SmvWorker
|
|||
if (cell->type[0] == '$')
|
||||
log_error("Found currently unsupported cell type %s (%s.%s).\n", log_id(cell->type), log_id(module), log_id(cell));
|
||||
|
||||
f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
|
||||
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
if (cell->output(conn.first))
|
||||
assignments.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first)));
|
||||
definitions.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first)));
|
||||
else
|
||||
assignments.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second)));
|
||||
definitions.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second)));
|
||||
}
|
||||
|
||||
for (Wire *wire : partial_assignment_wires)
|
||||
|
@ -657,7 +658,25 @@ struct SmvWorker
|
|||
}
|
||||
}
|
||||
|
||||
assignments.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str()));
|
||||
definitions.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str()));
|
||||
}
|
||||
|
||||
if (!inputvars.empty()) {
|
||||
f << stringf(" IVAR\n");
|
||||
for (const string &line : inputvars)
|
||||
f << stringf(" %s\n", line.c_str());
|
||||
}
|
||||
|
||||
if (!vars.empty()) {
|
||||
f << stringf(" VAR\n");
|
||||
for (const string &line : vars)
|
||||
f << stringf(" %s\n", line.c_str());
|
||||
}
|
||||
|
||||
if (!definitions.empty()) {
|
||||
f << stringf(" DEFINE\n");
|
||||
for (const string &line : definitions)
|
||||
f << stringf(" %s\n", line.c_str());
|
||||
}
|
||||
|
||||
if (!assignments.empty()) {
|
||||
|
|
|
@ -388,7 +388,7 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
|
|||
void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory)
|
||||
{
|
||||
dump_attributes(f, indent, memory->attributes);
|
||||
f << stringf("%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1);
|
||||
f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size+memory->start_offset-1, memory->start_offset);
|
||||
}
|
||||
|
||||
void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true)
|
||||
|
@ -678,6 +678,35 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
#undef HANDLE_UNIOP
|
||||
#undef HANDLE_BINOP
|
||||
|
||||
if (cell->type == "$shift")
|
||||
{
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort("\\Y"));
|
||||
f << stringf(" = ");
|
||||
if (cell->getParam("\\B_SIGNED").as_bool())
|
||||
{
|
||||
f << stringf("$signed(");
|
||||
dump_sigspec(f, cell->getPort("\\B"));
|
||||
f << stringf(")");
|
||||
f << stringf(" < 0 ? ");
|
||||
dump_sigspec(f, cell->getPort("\\A"));
|
||||
f << stringf(" << - ");
|
||||
dump_sigspec(f, cell->getPort("\\B"));
|
||||
f << stringf(" : ");
|
||||
dump_sigspec(f, cell->getPort("\\A"));
|
||||
f << stringf(" >> ");
|
||||
dump_sigspec(f, cell->getPort("\\B"));
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_sigspec(f, cell->getPort("\\A"));
|
||||
f << stringf(" >> ");
|
||||
dump_sigspec(f, cell->getPort("\\B"));
|
||||
}
|
||||
f << stringf(";\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$shiftx")
|
||||
{
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
|
@ -952,6 +981,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
std::string mem_id = id(cell->parameters["\\MEMID"].decode_string());
|
||||
int abits = cell->parameters["\\ABITS"].as_int();
|
||||
int size = cell->parameters["\\SIZE"].as_int();
|
||||
int offset = cell->parameters["\\OFFSET"].as_int();
|
||||
int width = cell->parameters["\\WIDTH"].as_int();
|
||||
bool use_init = !(RTLIL::SigSpec(cell->parameters["\\INIT"]).is_fully_undef());
|
||||
|
||||
|
@ -960,7 +990,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
// initial begin
|
||||
// memid[0] = ...
|
||||
// end
|
||||
f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size-1, 0);
|
||||
f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset);
|
||||
if (use_init)
|
||||
{
|
||||
f << stringf("%s" "initial begin\n", indent.c_str());
|
||||
|
@ -1351,6 +1381,8 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
|
|||
|
||||
if (sync->type == RTLIL::STa) {
|
||||
f << stringf("%s" "always @* begin\n", indent.c_str());
|
||||
} else if (sync->type == RTLIL::STi) {
|
||||
f << stringf("%s" "initial begin\n", indent.c_str());
|
||||
} else {
|
||||
f << stringf("%s" "always @(", indent.c_str());
|
||||
if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1)
|
||||
|
@ -1418,7 +1450,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
|||
log_warning("Module %s contains unmapped RTLIL proccesses. RTLIL processes\n"
|
||||
"can't always be mapped directly to Verilog always blocks. Unintended\n"
|
||||
"changes in simulation behavior are possible! Use \"proc\" to convert\n"
|
||||
"processes to logic networks and registers.", log_id(module));
|
||||
"processes to logic networks and registers.\n", log_id(module));
|
||||
|
||||
f << stringf("\n");
|
||||
for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||
* Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.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
|
||||
|
@ -171,8 +172,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
|
|||
|
||||
AstNode *attr = attributes.at(id);
|
||||
if (attr->type != AST_CONSTANT)
|
||||
log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
id.c_str());
|
||||
log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str());
|
||||
|
||||
return attr->integer != 0;
|
||||
}
|
||||
|
@ -903,9 +903,9 @@ RTLIL::Const AstNode::realAsConst(int width)
|
|||
}
|
||||
|
||||
// create a new AstModule from an AST_MODULE AST node
|
||||
static AstModule* process_module(AstNode *ast, bool defer)
|
||||
static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL)
|
||||
{
|
||||
log_assert(ast->type == AST_MODULE);
|
||||
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
|
||||
|
||||
if (defer)
|
||||
log("Storing AST representation for module `%s'.\n", ast->str.c_str());
|
||||
|
@ -916,9 +916,14 @@ static AstModule* process_module(AstNode *ast, bool defer)
|
|||
current_module->ast = NULL;
|
||||
current_module->name = ast->str;
|
||||
current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum);
|
||||
current_module->set_bool_attribute("\\cells_not_processed");
|
||||
|
||||
current_ast_mod = ast;
|
||||
AstNode *ast_before_simplify = ast->clone();
|
||||
AstNode *ast_before_simplify;
|
||||
if (original_ast != NULL)
|
||||
ast_before_simplify = original_ast;
|
||||
else
|
||||
ast_before_simplify = ast->clone();
|
||||
|
||||
if (flag_dump_ast1) {
|
||||
log("Dumping Verilog AST before simplification:\n");
|
||||
|
@ -963,8 +968,7 @@ static AstModule* process_module(AstNode *ast, bool defer)
|
|||
|
||||
for (auto &attr : ast->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
current_module->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
for (size_t i = 0; i < ast->children.size(); i++) {
|
||||
|
@ -989,6 +993,8 @@ static AstModule* process_module(AstNode *ast, bool defer)
|
|||
ignoreThisSignalsInInitial = RTLIL::SigSpec();
|
||||
}
|
||||
|
||||
if (ast->type == AST_INTERFACE)
|
||||
current_module->set_bool_attribute("\\is_interface");
|
||||
current_module->ast = ast_before_simplify;
|
||||
current_module->nolatches = flag_nolatches;
|
||||
current_module->nomeminit = flag_nomeminit;
|
||||
|
@ -1031,7 +1037,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
|||
log_assert(current_ast->type == AST_DESIGN);
|
||||
for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)
|
||||
{
|
||||
if ((*it)->type == AST_MODULE)
|
||||
if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE)
|
||||
{
|
||||
for (auto n : design->verilog_globals)
|
||||
(*it)->children.push_back(n->clone());
|
||||
|
@ -1053,8 +1059,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
|||
if (design->has((*it)->str)) {
|
||||
RTLIL::Module *existing_mod = design->module((*it)->str);
|
||||
if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
|
||||
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n",
|
||||
(*it)->str.c_str());
|
||||
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
|
||||
} else if (nooverwrite) {
|
||||
log("Ignoring re-definition of module `%s' at %s:%d.\n",
|
||||
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
|
||||
|
@ -1083,8 +1088,264 @@ AstModule::~AstModule()
|
|||
delete ast;
|
||||
}
|
||||
|
||||
|
||||
// An interface port with modport is specified like this:
|
||||
// <interface_name>.<modport_name>
|
||||
// This function splits the interface_name from the modport_name, and fails if it is not a valid combination
|
||||
std::pair<std::string,std::string> AST::split_modport_from_type(std::string name_type)
|
||||
{
|
||||
std::string interface_type = "";
|
||||
std::string interface_modport = "";
|
||||
size_t ndots = std::count(name_type.begin(), name_type.end(), '.');
|
||||
// Separate the interface instance name from any modports:
|
||||
if (ndots == 0) { // Does not have modport
|
||||
interface_type = name_type;
|
||||
}
|
||||
else {
|
||||
std::stringstream name_type_stream(name_type);
|
||||
std::string segment;
|
||||
std::vector<std::string> seglist;
|
||||
while(std::getline(name_type_stream, segment, '.')) {
|
||||
seglist.push_back(segment);
|
||||
}
|
||||
if (ndots == 1) { // Has modport
|
||||
interface_type = seglist[0];
|
||||
interface_modport = seglist[1];
|
||||
}
|
||||
else { // Erroneous port type
|
||||
log_error("More than two '.' in signal port type (%s)\n", name_type.c_str());
|
||||
}
|
||||
}
|
||||
return std::pair<std::string,std::string>(interface_type, interface_modport);
|
||||
|
||||
}
|
||||
|
||||
AstNode * AST::find_modport(AstNode *intf, std::string name)
|
||||
{
|
||||
for (auto &ch : intf->children)
|
||||
if (ch->type == AST_MODPORT)
|
||||
if (ch->str == name) // Modport found
|
||||
return ch;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Iterate over all wires in an interface and add them as wires in the AST module:
|
||||
void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport)
|
||||
{
|
||||
for (auto &wire_it : intfmodule->wires_){
|
||||
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
|
||||
std::string origname = log_id(wire_it.first);
|
||||
std::string newname = intfname + "." + origname;
|
||||
wire->str = newname;
|
||||
if (modport != NULL) {
|
||||
bool found_in_modport = false;
|
||||
// Search for the current wire in the wire list for the current modport
|
||||
for (auto &ch : modport->children) {
|
||||
if (ch->type == AST_MODPORTMEMBER) {
|
||||
std::string compare_name = "\\" + origname;
|
||||
if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output
|
||||
found_in_modport = true;
|
||||
wire->is_input = ch->is_input;
|
||||
wire->is_output = ch->is_output;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_in_modport) {
|
||||
module_ast->children.push_back(wire);
|
||||
}
|
||||
else { // If not found in modport, do not create port
|
||||
delete wire;
|
||||
}
|
||||
}
|
||||
else { // If no modport, set inout
|
||||
wire->is_input = true;
|
||||
wire->is_output = true;
|
||||
module_ast->children.push_back(wire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
|
||||
// from AST. The interface members are copied into the AST module with the prefix of the interface.
|
||||
void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module*> local_interfaces)
|
||||
{
|
||||
bool is_top = false;
|
||||
AstNode *new_ast = ast->clone();
|
||||
for (auto &intf : local_interfaces) {
|
||||
std::string intfname = intf.first.str();
|
||||
RTLIL::Module *intfmodule = intf.second;
|
||||
for (auto &wire_it : intfmodule->wires_){
|
||||
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
|
||||
std::string newname = log_id(wire_it.first);
|
||||
newname = intfname + "." + newname;
|
||||
wire->str = newname;
|
||||
new_ast->children.push_back(wire);
|
||||
}
|
||||
}
|
||||
|
||||
AstNode *ast_before_replacing_interface_ports = new_ast->clone();
|
||||
|
||||
// Explode all interface ports. Note this will only have an effect on 'top
|
||||
// level' modules. Other sub-modules will have their interface ports
|
||||
// exploded via the derive(..) function
|
||||
for (size_t i =0; i<new_ast->children.size(); i++)
|
||||
{
|
||||
AstNode *ch2 = new_ast->children[i];
|
||||
if (ch2->type == AST_INTERFACEPORT) { // Is an interface port
|
||||
std::string name_port = ch2->str; // Name of the interface port
|
||||
if (ch2->children.size() > 0) {
|
||||
for(size_t j=0; j<ch2->children.size();j++) {
|
||||
AstNode *ch = ch2->children[j];
|
||||
if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface
|
||||
std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
|
||||
std::string interface_type = res.first;
|
||||
std::string interface_modport = res.second; // Is "", if no modport
|
||||
if (design->modules_.count(interface_type) > 0) {
|
||||
// Add a cell to the module corresponding to the interface port such that
|
||||
// it can further propagated down if needed:
|
||||
AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE);
|
||||
celltype_for_intf->str = interface_type;
|
||||
AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf);
|
||||
cell_for_intf->str = name_port + "_inst_from_top_dummy";
|
||||
new_ast->children.push_back(cell_for_intf);
|
||||
|
||||
// Get all members of this non-overridden dummy interface instance:
|
||||
RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming
|
||||
// reprocess_module is called from the hierarchy pass) be
|
||||
// present in design->modules_
|
||||
AstModule *ast_module_of_interface = (AstModule*)intfmodule;
|
||||
std::string interface_modport_compare_str = "\\" + interface_modport;
|
||||
AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport
|
||||
// Iterate over all wires in the interface and add them to the module:
|
||||
explode_interface_port(new_ast, intfmodule, name_port, modport);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The old module will be deleted. Rename and mark for deletion:
|
||||
std::string original_name = this->name.str();
|
||||
std::string changed_name = original_name + "_before_replacing_local_interfaces";
|
||||
design->rename(this, changed_name);
|
||||
this->set_bool_attribute("\\to_delete");
|
||||
|
||||
// Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
|
||||
// new module.
|
||||
if (this->get_bool_attribute("\\initial_top")) {
|
||||
this->attributes.erase("\\initial_top");
|
||||
is_top = true;
|
||||
}
|
||||
|
||||
// Generate RTLIL from AST for the new module and add to the design:
|
||||
AstModule *newmod = process_module(new_ast, false, ast_before_replacing_interface_ports);
|
||||
delete(new_ast);
|
||||
design->add(newmod);
|
||||
RTLIL::Module* mod = design->module(original_name);
|
||||
if (is_top)
|
||||
mod->set_bool_attribute("\\top");
|
||||
|
||||
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
|
||||
mod->set_bool_attribute("\\interfaces_replaced_in_module");
|
||||
}
|
||||
|
||||
// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
|
||||
// This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
|
||||
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail)
|
||||
{
|
||||
AstNode *new_ast = NULL;
|
||||
std::string modname = derive_common(design, parameters, &new_ast, mayfail);
|
||||
|
||||
// Since interfaces themselves may be instantiated with different parameters,
|
||||
// "modname" must also take those into account, so that unique modules
|
||||
// are derived for any variant of interface connections:
|
||||
std::string interf_info = "";
|
||||
|
||||
bool has_interfaces = false;
|
||||
for(auto &intf : interfaces) {
|
||||
interf_info += log_id(intf.second->name);
|
||||
has_interfaces = true;
|
||||
}
|
||||
|
||||
if (has_interfaces)
|
||||
modname += "$interfaces$" + interf_info;
|
||||
|
||||
|
||||
if (!design->has(modname)) {
|
||||
new_ast->str = modname;
|
||||
|
||||
// Iterate over all interfaces which are ports in this module:
|
||||
for(auto &intf : interfaces) {
|
||||
RTLIL::Module * intfmodule = intf.second;
|
||||
std::string intfname = intf.first.str();
|
||||
// Check if a modport applies for the interface port:
|
||||
AstNode *modport = NULL;
|
||||
if (modports.count(intfname) > 0) {
|
||||
std::string interface_modport = modports.at(intfname).str();
|
||||
AstModule *ast_module_of_interface = (AstModule*)intfmodule;
|
||||
AstNode *ast_node_of_interface = ast_module_of_interface->ast;
|
||||
modport = find_modport(ast_node_of_interface, interface_modport);
|
||||
}
|
||||
// Iterate over all wires in the interface and add them to the module:
|
||||
explode_interface_port(new_ast, intfmodule, intfname, modport);
|
||||
}
|
||||
|
||||
design->add(process_module(new_ast, false));
|
||||
design->module(modname)->check();
|
||||
|
||||
RTLIL::Module* mod = design->module(modname);
|
||||
|
||||
// Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
|
||||
for(auto &intf : interfaces) {
|
||||
if(mod->wires_.count(intf.first)) {
|
||||
mod->wires_.erase(intf.first);
|
||||
mod->fixup_ports();
|
||||
// We copy the cell of the interface to the sub-module such that it can further be found if it is propagated
|
||||
// down to sub-sub-modules etc.
|
||||
RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name);
|
||||
new_subcell->set_bool_attribute("\\is_interface");
|
||||
}
|
||||
else {
|
||||
log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
|
||||
if (interfaces.size() > 0) {
|
||||
mod->set_bool_attribute("\\interfaces_replaced_in_module");
|
||||
}
|
||||
|
||||
} else {
|
||||
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
|
||||
}
|
||||
|
||||
delete new_ast;
|
||||
return modname;
|
||||
}
|
||||
|
||||
// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
|
||||
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail)
|
||||
{
|
||||
AstNode *new_ast = NULL;
|
||||
std::string modname = derive_common(design, parameters, &new_ast, mayfail);
|
||||
|
||||
if (!design->has(modname)) {
|
||||
new_ast->str = modname;
|
||||
design->add(process_module(new_ast, false));
|
||||
design->module(modname)->check();
|
||||
} else {
|
||||
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
|
||||
}
|
||||
|
||||
delete new_ast;
|
||||
return modname;
|
||||
}
|
||||
|
||||
// create a new parametric module (when needed) and return the name of the generated module
|
||||
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool)
|
||||
std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool)
|
||||
{
|
||||
std::string stripped_name = name.str();
|
||||
|
||||
|
@ -1156,15 +1417,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
|
|||
else
|
||||
modname = "$paramod" + stripped_name + para_info;
|
||||
|
||||
if (!design->has(modname)) {
|
||||
new_ast->str = modname;
|
||||
design->add(process_module(new_ast, false));
|
||||
design->module(modname)->check();
|
||||
} else {
|
||||
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
|
||||
}
|
||||
|
||||
delete new_ast;
|
||||
(*new_ast_out) = new_ast;
|
||||
return modname;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,11 @@ namespace AST
|
|||
AST_NEGEDGE,
|
||||
AST_EDGE,
|
||||
|
||||
AST_INTERFACE,
|
||||
AST_INTERFACEPORT,
|
||||
AST_INTERFACEPORTTYPE,
|
||||
AST_MODPORT,
|
||||
AST_MODPORTMEMBER,
|
||||
AST_PACKAGE
|
||||
};
|
||||
|
||||
|
@ -284,6 +289,9 @@ namespace AST
|
|||
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
|
||||
~AstModule() YS_OVERRIDE;
|
||||
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
|
||||
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
|
||||
std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail);
|
||||
void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;
|
||||
RTLIL::Module *clone() const YS_OVERRIDE;
|
||||
};
|
||||
|
||||
|
@ -300,6 +308,11 @@ namespace AST
|
|||
|
||||
// call a DPI function
|
||||
AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args);
|
||||
|
||||
// Helper functions related to handling SystemVerilog interfaces
|
||||
std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
|
||||
AstNode * find_modport(AstNode *intf, std::string name);
|
||||
void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport);
|
||||
}
|
||||
|
||||
namespace AST_INTERNAL
|
||||
|
|
|
@ -55,8 +55,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
|
|||
if (gen_attributes)
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
|
@ -89,8 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
|
|||
if (that != NULL)
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
|
@ -117,8 +115,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi
|
|||
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
|
@ -152,8 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
|
|||
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
|
@ -480,8 +476,7 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
|
||||
for (auto &attr : ast->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
sw->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
|
@ -648,8 +643,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
|
||||
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
||||
this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
|
||||
delete left_at_zero_ast;
|
||||
delete right_at_zero_ast;
|
||||
|
@ -778,7 +772,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
|
||||
if (children[0]->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
width_hint = max(width_hint, int(children[0]->asInt(true)));
|
||||
}
|
||||
break;
|
||||
|
@ -799,8 +793,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
default:
|
||||
for (auto f : log_files)
|
||||
current_ast->dumpAst(f, "verilog-ast> ");
|
||||
log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n",
|
||||
type2str(type).c_str());
|
||||
log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
|
||||
}
|
||||
|
||||
if (*found_real)
|
||||
|
@ -853,6 +846,35 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
case AST_GENIF:
|
||||
case AST_GENCASE:
|
||||
case AST_PACKAGE:
|
||||
case AST_MODPORT:
|
||||
case AST_MODPORTMEMBER:
|
||||
break;
|
||||
case AST_INTERFACEPORT: {
|
||||
// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
|
||||
// This is used by the hierarchy pass to know when it can replace interface connection with the individual
|
||||
// signals.
|
||||
RTLIL::Wire *wire = current_module->addWire(str, 1);
|
||||
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
wire->start_offset = 0;
|
||||
wire->port_id = port_id;
|
||||
wire->port_input = true;
|
||||
wire->port_output = true;
|
||||
wire->set_bool_attribute("\\is_interface");
|
||||
if (children.size() > 0) {
|
||||
for(size_t i=0; i<children.size();i++) {
|
||||
if(children[i]->type == AST_INTERFACEPORTTYPE) {
|
||||
std::pair<std::string,std::string> res = AST::split_modport_from_type(children[i]->str);
|
||||
wire->attributes["\\interface_type"] = res.first;
|
||||
if (res.second != "")
|
||||
wire->attributes["\\interface_modport"] = res.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
wire->upto = 0;
|
||||
}
|
||||
break;
|
||||
case AST_INTERFACEPORTTYPE:
|
||||
break;
|
||||
|
||||
// remember the parameter, needed for example in techmap
|
||||
|
@ -863,11 +885,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
// create an RTLIL::Wire for an AST_WIRE node
|
||||
case AST_WIRE: {
|
||||
if (current_module->wires_.count(str) != 0)
|
||||
log_file_error(filename, linenum, "Re-definition of signal `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str());
|
||||
if (!range_valid)
|
||||
log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str());
|
||||
|
||||
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
|
||||
|
||||
|
@ -881,8 +901,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
wire->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
}
|
||||
|
@ -891,16 +910,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
// create an RTLIL::Memory for an AST_MEMORY node
|
||||
case AST_MEMORY: {
|
||||
if (current_module->memories.count(str) != 0)
|
||||
log_file_error(filename, linenum, "Re-definition of memory `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str());
|
||||
|
||||
log_assert(children.size() >= 2);
|
||||
log_assert(children[0]->type == AST_RANGE);
|
||||
log_assert(children[1]->type == AST_RANGE);
|
||||
|
||||
if (!children[0]->range_valid || !children[1]->range_valid)
|
||||
log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str());
|
||||
|
||||
RTLIL::Memory *memory = new RTLIL::Memory;
|
||||
memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
|
@ -917,8 +934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
memory->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
}
|
||||
|
@ -937,8 +953,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
case AST_REALVALUE:
|
||||
{
|
||||
RTLIL::SigSpec sig = realAsConst(width_hint);
|
||||
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
|
||||
realvalue, log_signal(sig));
|
||||
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
@ -949,6 +964,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
{
|
||||
RTLIL::Wire *wire = NULL;
|
||||
RTLIL::SigChunk chunk;
|
||||
bool is_interface = false;
|
||||
|
||||
int add_undef_bits_msb = 0;
|
||||
int add_undef_bits_lsb = 0;
|
||||
|
@ -964,19 +980,42 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
}
|
||||
else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
|
||||
if (id2ast->children[0]->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str());
|
||||
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
||||
goto use_const_chunk;
|
||||
}
|
||||
else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
|
||||
id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
|
||||
log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
|
||||
str.c_str());
|
||||
else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
|
||||
RTLIL::Wire *current_wire = current_module->wire(str);
|
||||
if (current_wire->get_bool_attribute("\\is_interface"))
|
||||
is_interface = true;
|
||||
// Ignore
|
||||
}
|
||||
// If an identifier is found that is not already known, assume that it is an interface:
|
||||
else if (1) { // FIXME: Check if sv_mode first?
|
||||
is_interface = true;
|
||||
}
|
||||
else {
|
||||
log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str());
|
||||
}
|
||||
|
||||
if (id2ast->type == AST_MEMORY)
|
||||
log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str());
|
||||
|
||||
// If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface'
|
||||
// This makes it possible for the hierarchy pass to see what are interface connections and then replace them
|
||||
// with the individual signals:
|
||||
if (is_interface) {
|
||||
RTLIL::Wire *dummy_wire;
|
||||
std::string dummy_wire_name = "$dummywireforinterface" + str;
|
||||
if (current_module->wires_.count(dummy_wire_name))
|
||||
dummy_wire = current_module->wires_[dummy_wire_name];
|
||||
else {
|
||||
dummy_wire = current_module->addWire(dummy_wire_name);
|
||||
dummy_wire->set_bool_attribute("\\is_interface");
|
||||
}
|
||||
RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
wire = current_module->wires_[str];
|
||||
chunk.wire = wire;
|
||||
|
@ -995,8 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
|
||||
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
||||
int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
|
||||
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
|
||||
children[0]->children[1]->clone() : children[0]->children[0]->clone());
|
||||
|
@ -1025,10 +1063,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
|
||||
if (chunk.width == 1)
|
||||
log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
|
||||
str.c_str());
|
||||
str.c_str());
|
||||
else
|
||||
log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n",
|
||||
str.c_str(), chunk.width);
|
||||
log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
|
||||
children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);
|
||||
chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
|
||||
} else {
|
||||
if (chunk.width + chunk.offset > source_width) {
|
||||
|
@ -1041,11 +1079,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
chunk.offset += add_undef_bits_lsb;
|
||||
}
|
||||
if (add_undef_bits_lsb)
|
||||
log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
|
||||
str.c_str(), add_undef_bits_lsb);
|
||||
log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
|
||||
children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);
|
||||
if (add_undef_bits_msb)
|
||||
log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
|
||||
str.c_str(), add_undef_bits_msb);
|
||||
log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
|
||||
children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1380,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
|
@ -1403,9 +1440,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
new_right.append(right[i]);
|
||||
}
|
||||
log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
|
||||
" old assignment: %s = %s\n new assignment: %s = %s.\n",
|
||||
log_signal(left), log_signal(right),
|
||||
log_signal(new_left), log_signal(new_right));
|
||||
" old assignment: %s = %s\n new assignment: %s = %s.\n",
|
||||
log_signal(left), log_signal(right),
|
||||
log_signal(new_left), log_signal(new_right));
|
||||
left = new_left;
|
||||
right = new_right;
|
||||
}
|
||||
|
@ -1423,6 +1460,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
RTLIL::Cell *cell = current_module->addCell(str, "");
|
||||
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
// Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
|
||||
cell->set_bool_attribute("\\module_not_derived");
|
||||
|
||||
for (auto it = children.begin(); it != children.end(); it++) {
|
||||
AstNode *child = *it;
|
||||
|
@ -1436,14 +1475,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
|
||||
if (child->children[0]->type == AST_REALVALUE) {
|
||||
log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n",
|
||||
log_id(cell), log_id(paraname), child->children[0]->realvalue);
|
||||
log_id(cell), log_id(paraname), child->children[0]->realvalue);
|
||||
auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
|
||||
strnode->cloneInto(child->children[0]);
|
||||
delete strnode;
|
||||
}
|
||||
if (child->children[0]->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n",
|
||||
log_id(cell), log_id(paraname));
|
||||
log_id(cell), log_id(paraname));
|
||||
cell->parameters[paraname] = child->children[0]->asParaConst();
|
||||
continue;
|
||||
}
|
||||
|
@ -1464,8 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
}
|
||||
for (auto &attr : attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
|
||||
attr.first.c_str());
|
||||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
}
|
||||
|
@ -1493,18 +1531,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
|
||||
if (GetSize(children) > 1)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n",
|
||||
RTLIL::unescape_id(str).c_str(), GetSize(children));
|
||||
RTLIL::unescape_id(str).c_str(), GetSize(children));
|
||||
|
||||
if (GetSize(children) == 1) {
|
||||
if (children[0]->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
width = children[0]->asInt(true);
|
||||
}
|
||||
|
||||
if (width <= 0)
|
||||
log_file_error(filename, linenum, "Failed to detect width of %s!\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());
|
||||
|
||||
Cell *cell = current_module->addCell(myid, str.substr(1));
|
||||
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
|
@ -1531,8 +1568,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
for (auto f : log_files)
|
||||
current_ast->dumpAst(f, "verilog-ast> ");
|
||||
type_name = type2str(type);
|
||||
log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n",
|
||||
type_name.c_str());
|
||||
log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str());
|
||||
}
|
||||
|
||||
return RTLIL::SigSpec();
|
||||
|
|
|
@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
|
||||
if (stage == 0)
|
||||
{
|
||||
log_assert(type == AST_MODULE);
|
||||
log_assert(type == AST_MODULE || type == AST_INTERFACE);
|
||||
last_blocking_assignment_warn = pair<string, int>();
|
||||
|
||||
deep_recursion_warning = true;
|
||||
|
@ -196,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
int nargs = GetSize(children);
|
||||
if (nargs < 1)
|
||||
log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
|
||||
str.c_str(), int(children.size()));
|
||||
str.c_str(), int(children.size()));
|
||||
|
||||
// First argument is the format string
|
||||
AstNode *node_string = children[0];
|
||||
|
@ -240,7 +240,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
case 'X':
|
||||
if (next_arg >= GetSize(children))
|
||||
log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
|
||||
cformat, str.c_str());
|
||||
cformat, str.c_str());
|
||||
|
||||
node_arg = children[next_arg++];
|
||||
while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
|
||||
|
@ -450,8 +450,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
|
||||
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
|
||||
log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
|
||||
if (type == AST_ASSIGN && children[0]->id2ast->is_reg)
|
||||
log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
|
||||
if (type == AST_ASSIGN && children[0]->id2ast->is_reg) {
|
||||
bool is_rand_reg = false;
|
||||
if (children[1]->type == AST_FCALL) {
|
||||
if (children[1]->str == "\\$anyconst")
|
||||
is_rand_reg = true;
|
||||
if (children[1]->str == "\\$anyseq")
|
||||
is_rand_reg = true;
|
||||
if (children[1]->str == "\\$allconst")
|
||||
is_rand_reg = true;
|
||||
if (children[1]->str == "\\$allseq")
|
||||
is_rand_reg = true;
|
||||
}
|
||||
if (!is_rand_reg)
|
||||
log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
|
||||
}
|
||||
children[0]->was_checked = true;
|
||||
}
|
||||
break;
|
||||
|
@ -732,7 +745,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
|
||||
if (current_scope.at(modname)->type != AST_CELL)
|
||||
log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
|
||||
RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
|
||||
RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
|
||||
|
||||
AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
|
||||
paraset->str = paramname;
|
||||
|
@ -880,7 +893,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
if (children[0]->type == AST_REALVALUE) {
|
||||
RTLIL::Const constvalue = children[0]->realAsConst(width);
|
||||
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
|
||||
children[0]->realvalue, log_signal(constvalue));
|
||||
children[0]->realvalue, log_signal(constvalue));
|
||||
delete children[0];
|
||||
children[0] = mkconst_bits(constvalue.bits, sign_hint);
|
||||
did_something = true;
|
||||
|
@ -1299,8 +1312,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
if (type == AST_PRIMITIVE)
|
||||
{
|
||||
if (children.size() < 2)
|
||||
log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());
|
||||
|
||||
std::vector<AstNode*> children_list;
|
||||
for (auto child : children) {
|
||||
|
@ -1315,8 +1327,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
|
||||
{
|
||||
if (children_list.size() != 3)
|
||||
log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str());
|
||||
|
||||
std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
|
||||
|
||||
|
@ -1336,6 +1347,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
str.clear();
|
||||
type = AST_ASSIGN;
|
||||
children.push_back(children_list.at(0));
|
||||
children.back()->was_checked = true;
|
||||
children.push_back(node);
|
||||
did_something = true;
|
||||
}
|
||||
|
@ -1372,6 +1384,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
str.clear();
|
||||
type = AST_ASSIGN;
|
||||
children.push_back(children_list[0]);
|
||||
children.back()->was_checked = true;
|
||||
children.push_back(node);
|
||||
did_something = true;
|
||||
}
|
||||
|
@ -1401,8 +1414,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
|
||||
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
|
||||
str.c_str());
|
||||
log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
||||
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
|
||||
}
|
||||
did_something = true;
|
||||
|
@ -1530,6 +1542,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
wire_tmp_id->str = wire_tmp->str;
|
||||
|
||||
newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone()));
|
||||
newNode->children.back()->was_checked = true;
|
||||
|
||||
int cursor = 0;
|
||||
for (auto child : children[0]->children)
|
||||
|
@ -1772,11 +1785,11 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
|
||||
if (GetSize(children) != 1 && GetSize(children) != 2)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
|
||||
if (!current_always_clocked)
|
||||
log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
|
||||
if (GetSize(children) == 2)
|
||||
{
|
||||
|
@ -1797,6 +1810,11 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
|
||||
log_assert(block != nullptr);
|
||||
|
||||
if (num_steps == 0) {
|
||||
newNode = children[0]->clone();
|
||||
goto apply_newNode;
|
||||
}
|
||||
|
||||
int myidx = autoidx++;
|
||||
AstNode *outreg = nullptr;
|
||||
|
||||
|
@ -1815,6 +1833,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
AstNode *regid = new AstNode(AST_IDENTIFIER);
|
||||
regid->str = reg->str;
|
||||
regid->id2ast = reg;
|
||||
regid->was_checked = true;
|
||||
|
||||
AstNode *rhs = nullptr;
|
||||
|
||||
|
@ -1840,11 +1859,11 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
{
|
||||
if (GetSize(children) != 1)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
|
||||
if (!current_always_clocked)
|
||||
log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
|
||||
AstNode *present = children.at(0)->clone();
|
||||
AstNode *past = clone();
|
||||
|
@ -1857,10 +1876,14 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
newNode = new AstNode(AST_NE, past, present);
|
||||
|
||||
else if (str == "\\$rose")
|
||||
newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present);
|
||||
newNode = new AstNode(AST_LOGIC_AND,
|
||||
new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))),
|
||||
new AstNode(AST_BIT_AND, present, mkconst_int(1,false)));
|
||||
|
||||
else if (str == "\\$fell")
|
||||
newNode = new AstNode(AST_LOGIC_AND, past, new AstNode(AST_LOGIC_NOT, present));
|
||||
newNode = new AstNode(AST_LOGIC_AND,
|
||||
new AstNode(AST_BIT_AND, past, mkconst_int(1,false)),
|
||||
new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false))));
|
||||
|
||||
else
|
||||
log_abort();
|
||||
|
@ -1878,7 +1901,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
{
|
||||
if (children.size() != 1)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
|
||||
AstNode *buf = children[0]->clone();
|
||||
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
|
||||
|
@ -1895,7 +1918,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
if (arg_value.bits.at(i) == RTLIL::State::S1)
|
||||
result = i + 1;
|
||||
|
||||
newNode = mkconst_int(result, false);
|
||||
newNode = mkconst_int(result, true);
|
||||
goto apply_newNode;
|
||||
}
|
||||
|
||||
|
@ -1903,11 +1926,11 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
{
|
||||
if (str == "\\$bits" && children.size() != 1)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
|
||||
if (str == "\\$size" && children.size() != 1 && children.size() != 2)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
|
||||
int dim = 1;
|
||||
if (str == "\\$size" && children.size() == 2) {
|
||||
|
@ -1981,18 +2004,18 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
if (func_with_two_arguments) {
|
||||
if (children.size() != 2)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
} else {
|
||||
if (children.size() != 1)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
}
|
||||
|
||||
if (children.size() >= 1) {
|
||||
while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
|
||||
if (!children[0]->isConst())
|
||||
log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
int child_width_hint = width_hint;
|
||||
bool child_sign_hint = sign_hint;
|
||||
children[0]->detectSignWidth(child_width_hint, child_sign_hint);
|
||||
|
@ -2003,7 +2026,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
|
||||
if (!children[1]->isConst())
|
||||
log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
int child_width_hint = width_hint;
|
||||
bool child_sign_hint = sign_hint;
|
||||
children[1]->detectSignWidth(child_width_hint, child_sign_hint);
|
||||
|
@ -2091,7 +2114,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
{
|
||||
if (GetSize(children) < 2 || GetSize(children) > 4)
|
||||
log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n",
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
RTLIL::unescape_id(str).c_str(), int(children.size()));
|
||||
|
||||
AstNode *node_filename = children[0]->clone();
|
||||
while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
|
||||
|
@ -2204,6 +2227,8 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
|
||||
AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,
|
||||
new AstNode(AST_ASSIGN_EQ, lvalue, clone())));
|
||||
always->children[0]->children[0]->was_checked = true;
|
||||
|
||||
current_ast_mod->children.push_back(always);
|
||||
|
||||
goto replace_fcall_with_id;
|
||||
|
@ -2253,6 +2278,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
AstNode *assign = child->is_input ?
|
||||
new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :
|
||||
new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone());
|
||||
assign->children[0]->was_checked = true;
|
||||
|
||||
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
|
||||
if (*it != current_block_child)
|
||||
|
@ -2323,6 +2349,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
AstNode *assign = child->is_input ?
|
||||
new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
|
||||
new AstNode(AST_ASSIGN_EQ, arg, wire_id);
|
||||
assign->children[0]->was_checked = true;
|
||||
|
||||
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
|
||||
if (*it != current_block_child)
|
||||
|
@ -2762,6 +2789,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
|
|||
block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
|
||||
block->children.back()->children[0]->str = memory->str;
|
||||
block->children.back()->children[0]->id2ast = memory;
|
||||
block->children.back()->children[0]->was_checked = true;
|
||||
}
|
||||
|
||||
cursor += increment;
|
||||
|
@ -3022,6 +3050,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
|||
|
||||
AstNode *newNode = clone();
|
||||
newNode->type = AST_ASSIGN_EQ;
|
||||
newNode->children[0]->was_checked = true;
|
||||
async_block->children[0]->children.push_back(newNode);
|
||||
|
||||
newNode = new AstNode(AST_NONE);
|
||||
|
@ -3067,6 +3096,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
|||
|
||||
AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
|
||||
assign_addr->children[0]->str = id_addr;
|
||||
assign_addr->children[0]->was_checked = true;
|
||||
block->children.insert(block->children.begin()+assign_idx+1, assign_addr);
|
||||
|
||||
AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
|
||||
|
@ -3090,6 +3120,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
|||
children[0]->id2ast = NULL;
|
||||
children[0]->str = id_data;
|
||||
type = AST_ASSIGN_EQ;
|
||||
children[0]->was_checked = true;
|
||||
|
||||
did_something = true;
|
||||
}
|
||||
|
@ -3247,12 +3278,12 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
|
|||
if (!children.empty()) {
|
||||
if (children.size() != 1 || children.at(0)->type != AST_RANGE)
|
||||
log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
children.at(0)->replace_variables(variables, fcall);
|
||||
while (simplify(true, false, false, 1, -1, false, true)) { }
|
||||
if (!children.at(0)->range_valid)
|
||||
log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
offset = min(children.at(0)->range_left, children.at(0)->range_right);
|
||||
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
|
||||
}
|
||||
|
@ -3292,7 +3323,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
while (child->simplify(true, false, false, 1, -1, false, true)) { }
|
||||
if (!child->range_valid)
|
||||
log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
|
||||
child->str.c_str(), fcall->filename.c_str(), fcall->linenum);
|
||||
child->str.c_str(), fcall->filename.c_str(), fcall->linenum);
|
||||
variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
|
||||
variables[child->str].offset = min(child->range_left, child->range_right);
|
||||
variables[child->str].is_signed = child->is_signed;
|
||||
|
@ -3336,15 +3367,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
|
||||
if (stmt->children.at(1)->type != AST_CONSTANT)
|
||||
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
|
||||
if (stmt->children.at(0)->type != AST_IDENTIFIER)
|
||||
log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
|
||||
if (!variables.count(stmt->children.at(0)->str))
|
||||
log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
|
||||
if (stmt->children.at(0)->children.empty()) {
|
||||
variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
|
||||
|
@ -3352,7 +3383,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
AstNode *range = stmt->children.at(0)->children.at(0);
|
||||
if (!range->range_valid)
|
||||
log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
int offset = min(range->range_left, range->range_right);
|
||||
int width = std::abs(range->range_left - range->range_right) + 1;
|
||||
varinfo_t &v = variables[stmt->children.at(0)->str];
|
||||
|
@ -3384,7 +3415,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
|
||||
if (cond->type != AST_CONSTANT)
|
||||
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
|
||||
if (cond->asBool()) {
|
||||
block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
|
||||
|
@ -3405,7 +3436,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
|
||||
if (num->type != AST_CONSTANT)
|
||||
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
|
||||
block->children.erase(block->children.begin());
|
||||
for (int i = 0; i < num->bitsAsConst().as_int(); i++)
|
||||
|
@ -3443,7 +3474,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
|
||||
if (cond->type != AST_CONSTANT)
|
||||
log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
|
||||
found_match = cond->asBool();
|
||||
delete cond;
|
||||
|
@ -3473,7 +3504,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
}
|
||||
|
||||
log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
fcall->filename.c_str(), fcall->linenum);
|
||||
log_abort();
|
||||
}
|
||||
|
||||
|
|
|
@ -387,17 +387,13 @@ sigspec:
|
|||
$$ = new RTLIL::SigSpec(current_module->wires_[$1]);
|
||||
free($1);
|
||||
} |
|
||||
TOK_ID '[' TOK_INT ']' {
|
||||
if (current_module->wires_.count($1) == 0)
|
||||
rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
|
||||
$$ = new RTLIL::SigSpec(current_module->wires_[$1], $3);
|
||||
free($1);
|
||||
sigspec '[' TOK_INT ']' {
|
||||
$$ = new RTLIL::SigSpec($1->extract($3));
|
||||
delete $1;
|
||||
} |
|
||||
TOK_ID '[' TOK_INT ':' TOK_INT ']' {
|
||||
if (current_module->wires_.count($1) == 0)
|
||||
rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
|
||||
$$ = new RTLIL::SigSpec(current_module->wires_[$1], $5, $3 - $5 + 1);
|
||||
free($1);
|
||||
sigspec '[' TOK_INT ':' TOK_INT ']' {
|
||||
$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
|
||||
delete $1;
|
||||
} |
|
||||
'{' sigspec_list '}' {
|
||||
$$ = $2;
|
||||
|
|
|
@ -36,7 +36,8 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
|
|||
|
||||
int id_len = 0;
|
||||
while (('a' <= expr[id_len] && expr[id_len] <= 'z') || ('A' <= expr[id_len] && expr[id_len] <= 'Z') ||
|
||||
('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || expr[id_len] == '_') id_len++;
|
||||
('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' ||
|
||||
expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++;
|
||||
|
||||
if (id_len == 0)
|
||||
log_error("Expected identifier at `%s'.\n", expr);
|
||||
|
@ -634,9 +635,12 @@ struct LibertyFrontend : public Frontend {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto node : cell->children)
|
||||
if (!flag_lib)
|
||||
{
|
||||
if (!flag_lib) {
|
||||
// some liberty files do not put ff/latch at the beginning of a cell
|
||||
// try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes
|
||||
for (auto node : cell->children)
|
||||
{
|
||||
if (node->id == "ff" && node->args.size() == 2)
|
||||
create_ff(module, node);
|
||||
if (node->id == "latch" && node->args.size() == 2)
|
||||
|
@ -645,7 +649,10 @@ struct LibertyFrontend : public Frontend {
|
|||
goto skip_cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto node : cell->children)
|
||||
{
|
||||
if (node->id == "pin" && node->args.size() == 1)
|
||||
{
|
||||
LibertyAst *dir = node->find("direction");
|
||||
|
|
|
@ -130,6 +130,15 @@ bool is_blackbox(Netlist *nl)
|
|||
return false;
|
||||
}
|
||||
|
||||
RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
|
||||
{
|
||||
std::string s = stringf("$verific$%s", obj->Name());
|
||||
if (obj->Linefile())
|
||||
s += stringf("$%s:%d", Verific::LineFile::GetFileName(obj->Linefile()), Verific::LineFile::GetLineNo(obj->Linefile()));
|
||||
s += stringf("$%d", autoidx++);
|
||||
return s;
|
||||
}
|
||||
|
||||
void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)
|
||||
{
|
||||
MapIter mi;
|
||||
|
@ -215,7 +224,7 @@ RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*,
|
|||
dummy_wire = NULL;
|
||||
} else {
|
||||
if (dummy_wire == NULL)
|
||||
dummy_wire = module->addWire(NEW_ID);
|
||||
dummy_wire = module->addWire(new_verific_id(inst));
|
||||
else
|
||||
dummy_wire->width++;
|
||||
sig.append(RTLIL::SigSpec(dummy_wire, dummy_wire->width - 1));
|
||||
|
@ -231,8 +240,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
|
|||
}
|
||||
|
||||
if (inst->Type() == PRIM_NAND) {
|
||||
RTLIL::SigSpec tmp = module->addWire(NEW_ID);
|
||||
module->addAndGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
|
||||
module->addAndGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput()));
|
||||
return true;
|
||||
}
|
||||
|
@ -243,8 +252,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
|
|||
}
|
||||
|
||||
if (inst->Type() == PRIM_NOR) {
|
||||
RTLIL::SigSpec tmp = module->addWire(NEW_ID);
|
||||
module->addOrGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
|
||||
module->addOrGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput()));
|
||||
return true;
|
||||
}
|
||||
|
@ -284,16 +293,16 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
|
|||
if (inst->Type() == PRIM_FADD)
|
||||
{
|
||||
RTLIL::SigSpec a = net_map_at(inst->GetInput1()), b = net_map_at(inst->GetInput2()), c = net_map_at(inst->GetCin());
|
||||
RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(NEW_ID);
|
||||
RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID);
|
||||
RTLIL::SigSpec tmp1 = module->addWire(NEW_ID);
|
||||
RTLIL::SigSpec tmp2 = module->addWire(NEW_ID);
|
||||
RTLIL::SigSpec tmp3 = module->addWire(NEW_ID);
|
||||
module->addXorGate(NEW_ID, a, b, tmp1);
|
||||
RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(new_verific_id(inst));
|
||||
RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst));
|
||||
RTLIL::SigSpec tmp1 = module->addWire(new_verific_id(inst));
|
||||
RTLIL::SigSpec tmp2 = module->addWire(new_verific_id(inst));
|
||||
RTLIL::SigSpec tmp3 = module->addWire(new_verific_id(inst));
|
||||
module->addXorGate(new_verific_id(inst), a, b, tmp1);
|
||||
module->addXorGate(inst_name, tmp1, c, y);
|
||||
module->addAndGate(NEW_ID, tmp1, c, tmp2);
|
||||
module->addAndGate(NEW_ID, a, b, tmp3);
|
||||
module->addOrGate(NEW_ID, tmp2, tmp3, x);
|
||||
module->addAndGate(new_verific_id(inst), tmp1, c, tmp2);
|
||||
module->addAndGate(new_verific_id(inst), a, b, tmp3);
|
||||
module->addOrGate(new_verific_id(inst), tmp2, tmp3, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -320,63 +329,78 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
|
|||
|
||||
bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdString inst_name)
|
||||
{
|
||||
RTLIL::Cell *cell = nullptr;
|
||||
|
||||
if (inst->Type() == PRIM_AND) {
|
||||
module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_NAND) {
|
||||
RTLIL::SigSpec tmp = module->addWire(NEW_ID);
|
||||
module->addAnd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
|
||||
RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
|
||||
cell = module->addAnd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
import_attributes(cell->attributes, inst);
|
||||
cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_OR) {
|
||||
module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_NOR) {
|
||||
RTLIL::SigSpec tmp = module->addWire(NEW_ID);
|
||||
module->addOr(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
|
||||
RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst));
|
||||
cell = module->addOr(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);
|
||||
import_attributes(cell->attributes, inst);
|
||||
cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_XOR) {
|
||||
module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_XNOR) {
|
||||
module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_INV) {
|
||||
module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_MUX) {
|
||||
module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_TRI) {
|
||||
module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_FADD)
|
||||
{
|
||||
RTLIL::SigSpec a_plus_b = module->addWire(NEW_ID, 2);
|
||||
RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID);
|
||||
RTLIL::SigSpec a_plus_b = module->addWire(new_verific_id(inst), 2);
|
||||
RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst));
|
||||
if (inst->GetCout())
|
||||
y.append(net_map_at(inst->GetCout()));
|
||||
module->addAdd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b);
|
||||
module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y);
|
||||
cell = module->addAdd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b);
|
||||
import_attributes(cell->attributes, inst);
|
||||
cell = module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -387,24 +411,26 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
log_assert(clocking.body_net == nullptr);
|
||||
|
||||
if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd())
|
||||
clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
cell = clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
else if (inst->GetSet()->IsGnd())
|
||||
clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0);
|
||||
cell = clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0);
|
||||
else if (inst->GetReset()->IsGnd())
|
||||
clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1);
|
||||
cell = clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1);
|
||||
else
|
||||
clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
|
||||
cell = clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
|
||||
net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_DLATCHRS)
|
||||
{
|
||||
if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd())
|
||||
module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
else
|
||||
module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
|
||||
cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
|
||||
net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -420,37 +446,45 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
if (inst->GetCout() != NULL)
|
||||
out.append(net_map_at(inst->GetCout()));
|
||||
if (inst->GetCin()->IsGnd()) {
|
||||
module->addAdd(inst_name, IN1, IN2, out, SIGNED);
|
||||
cell = module->addAdd(inst_name, IN1, IN2, out, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
} else {
|
||||
RTLIL::SigSpec tmp = module->addWire(NEW_ID, GetSize(out));
|
||||
module->addAdd(NEW_ID, IN1, IN2, tmp, SIGNED);
|
||||
module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false);
|
||||
RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst), GetSize(out));
|
||||
cell = module->addAdd(new_verific_id(inst), IN1, IN2, tmp, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
cell = module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false);
|
||||
import_attributes(cell->attributes, inst);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_MULTIPLIER) {
|
||||
module->addMul(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addMul(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_DIVIDER) {
|
||||
module->addDiv(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addDiv(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_MODULO) {
|
||||
module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_REMAINDER) {
|
||||
module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_SHIFT_LEFT) {
|
||||
module->addShl(inst_name, IN1, IN2, OUT, false);
|
||||
cell = module->addShl(inst_name, IN1, IN2, OUT, false);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -460,7 +494,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
for (unsigned i = 1; i < inst->OutputSize(); i++) {
|
||||
vec.append(RTLIL::State::S0);
|
||||
}
|
||||
module->addShl(inst_name, vec, IN, OUT, false);
|
||||
cell = module->addShl(inst_name, vec, IN, OUT, false);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -470,7 +505,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
for (unsigned i = 1; i < inst->OutputSize(); i++) {
|
||||
vec.append(RTLIL::State::S0);
|
||||
}
|
||||
module->addShl(inst_name, vec, IN, OUT, false);
|
||||
cell = module->addShl(inst_name, vec, IN, OUT, false);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -478,108 +514,127 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
Net *net_cin = inst->GetCin();
|
||||
Net *net_a_msb = inst->GetInput1Bit(0);
|
||||
if (net_cin->IsGnd())
|
||||
module->addShr(inst_name, IN1, IN2, OUT, false);
|
||||
cell = module->addShr(inst_name, IN1, IN2, OUT, false);
|
||||
else if (net_cin == net_a_msb)
|
||||
module->addSshr(inst_name, IN1, IN2, OUT, true);
|
||||
cell = module->addSshr(inst_name, IN1, IN2, OUT, true);
|
||||
else
|
||||
log_error("Can't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", inst->Name());
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_REDUCE_AND) {
|
||||
module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_REDUCE_OR) {
|
||||
module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_REDUCE_XOR) {
|
||||
module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_REDUCE_XNOR) {
|
||||
module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_REDUCE_NOR) {
|
||||
SigSpec t = module->ReduceOr(NEW_ID, IN, SIGNED);
|
||||
module->addNot(inst_name, t, net_map_at(inst->GetOutput()));
|
||||
SigSpec t = module->ReduceOr(new_verific_id(inst), IN, SIGNED);
|
||||
cell = module->addNot(inst_name, t, net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_LESSTHAN) {
|
||||
Net *net_cin = inst->GetCin();
|
||||
if (net_cin->IsGnd())
|
||||
module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
else if (net_cin->IsPwr())
|
||||
module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
else
|
||||
log_error("Can't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", inst->Name());
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_AND) {
|
||||
module->addAnd(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addAnd(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_OR) {
|
||||
module->addOr(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addOr(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_XOR) {
|
||||
module->addXor(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addXor(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_XNOR) {
|
||||
module->addXnor(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addXnor(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_BUF) {
|
||||
module->addPos(inst_name, IN, FILTERED_OUT, SIGNED);
|
||||
cell = module->addPos(inst_name, IN, FILTERED_OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_INV) {
|
||||
module->addNot(inst_name, IN, OUT, SIGNED);
|
||||
cell = module->addNot(inst_name, IN, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_MINUS) {
|
||||
module->addSub(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
cell = module->addSub(inst_name, IN1, IN2, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_UMINUS) {
|
||||
module->addNeg(inst_name, IN, OUT, SIGNED);
|
||||
cell = module->addNeg(inst_name, IN, OUT, SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_EQUAL) {
|
||||
module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_NEQUAL) {
|
||||
module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
cell = module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_MUX) {
|
||||
module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT);
|
||||
cell = module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_NTO1MUX) {
|
||||
module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
|
||||
cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -599,25 +654,29 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
padded_data.append(d);
|
||||
}
|
||||
|
||||
module->addShr(inst_name, padded_data, sel, out);
|
||||
cell = module->addShr(inst_name, padded_data, sel, out);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_SELECTOR)
|
||||
{
|
||||
module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput()));
|
||||
cell = module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput()));
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_SELECTOR)
|
||||
{
|
||||
SigSpec out = OUT;
|
||||
module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out);
|
||||
cell = module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_TRI) {
|
||||
module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT);
|
||||
cell = module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT);
|
||||
import_attributes(cell->attributes, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -631,9 +690,10 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
RTLIL::SigSpec sig_reset = operatorInport(inst, "reset");
|
||||
|
||||
if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool())
|
||||
clocking.addDff(inst_name, IN, OUT);
|
||||
cell = clocking.addDff(inst_name, IN, OUT);
|
||||
else
|
||||
clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT);
|
||||
cell = clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT);
|
||||
import_attributes(cell->attributes, inst);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -862,7 +922,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
ascii_initdata++;
|
||||
}
|
||||
if (initval_valid) {
|
||||
RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit");
|
||||
RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit");
|
||||
cell->parameters["\\WORDS"] = 1;
|
||||
if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound())
|
||||
cell->setPort("\\ADDR", word_idx);
|
||||
|
@ -925,7 +985,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
if (net->Bus())
|
||||
continue;
|
||||
|
||||
RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : NEW_ID);
|
||||
RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net));
|
||||
|
||||
if (verific_verbose)
|
||||
log(" importing net %s as %s.\n", net->Name(), log_id(wire_name));
|
||||
|
@ -949,7 +1009,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
|
||||
if (found_new_net)
|
||||
{
|
||||
RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : NEW_ID);
|
||||
RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus));
|
||||
|
||||
if (verific_verbose)
|
||||
log(" importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name));
|
||||
|
@ -1025,16 +1085,16 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
}
|
||||
|
||||
if (GetSize(anyconst_sig))
|
||||
module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig)));
|
||||
module->connect(anyconst_sig, module->Anyconst(new_verific_id(netbus), GetSize(anyconst_sig)));
|
||||
|
||||
if (GetSize(anyseq_sig))
|
||||
module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig)));
|
||||
module->connect(anyseq_sig, module->Anyseq(new_verific_id(netbus), GetSize(anyseq_sig)));
|
||||
|
||||
if (GetSize(allconst_sig))
|
||||
module->connect(allconst_sig, module->Allconst(NEW_ID, GetSize(allconst_sig)));
|
||||
module->connect(allconst_sig, module->Allconst(new_verific_id(netbus), GetSize(allconst_sig)));
|
||||
|
||||
if (GetSize(allseq_sig))
|
||||
module->connect(allseq_sig, module->Allseq(NEW_ID, GetSize(allseq_sig)));
|
||||
module->connect(allseq_sig, module->Allseq(new_verific_id(netbus), GetSize(allseq_sig)));
|
||||
}
|
||||
|
||||
for (auto it : init_nets)
|
||||
|
@ -1058,10 +1118,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
}
|
||||
|
||||
for (auto net : anyconst_nets)
|
||||
module->connect(net_map_at(net), module->Anyconst(NEW_ID));
|
||||
module->connect(net_map_at(net), module->Anyconst(new_verific_id(net)));
|
||||
|
||||
for (auto net : anyseq_nets)
|
||||
module->connect(net_map_at(net), module->Anyseq(NEW_ID));
|
||||
module->connect(net_map_at(net), module->Anyseq(new_verific_id(net)));
|
||||
|
||||
pool<Instance*, hash_ptr_ops> sva_asserts;
|
||||
pool<Instance*, hash_ptr_ops> sva_assumes;
|
||||
|
@ -1072,7 +1132,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
|
||||
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
|
||||
{
|
||||
RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : NEW_ID);
|
||||
RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst));
|
||||
|
||||
if (verific_verbose)
|
||||
log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name));
|
||||
|
@ -1196,7 +1256,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
log_assert(inst->Input1Size() == inst->OutputSize());
|
||||
|
||||
SigSpec sig_d, sig_q, sig_o;
|
||||
sig_q = module->addWire(NEW_ID, inst->Input1Size());
|
||||
sig_q = module->addWire(new_verific_id(inst), inst->Input1Size());
|
||||
|
||||
for (int i = int(inst->Input1Size())-1; i >= 0; i--){
|
||||
sig_d.append(net_map_at(inst->GetInput1Bit(i)));
|
||||
|
@ -1210,8 +1270,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
log_signal(sig_d), log_signal(sig_q), log_signal(sig_o));
|
||||
}
|
||||
|
||||
clocking.addDff(NEW_ID, sig_d, sig_q);
|
||||
module->addXnor(NEW_ID, sig_d, sig_q, sig_o);
|
||||
clocking.addDff(new_verific_id(inst), sig_d, sig_q);
|
||||
module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o);
|
||||
|
||||
if (!mode_keep)
|
||||
continue;
|
||||
|
@ -1225,7 +1285,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
|
||||
SigSpec sig_d = net_map_at(inst->GetInput1());
|
||||
SigSpec sig_o = net_map_at(inst->GetOutput());
|
||||
SigSpec sig_q = module->addWire(NEW_ID);
|
||||
SigSpec sig_q = module->addWire(new_verific_id(inst));
|
||||
|
||||
if (verific_verbose) {
|
||||
log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",
|
||||
|
@ -1234,8 +1294,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
log_signal(sig_d), log_signal(sig_q), log_signal(sig_o));
|
||||
}
|
||||
|
||||
clocking.addDff(NEW_ID, sig_d, sig_q);
|
||||
module->addXnor(NEW_ID, sig_d, sig_q, sig_o);
|
||||
clocking.addDff(new_verific_id(inst), sig_d, sig_q);
|
||||
module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o);
|
||||
|
||||
if (!mode_keep)
|
||||
continue;
|
||||
|
@ -1254,7 +1314,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",
|
||||
log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig));
|
||||
|
||||
past_ffs.insert(clocking.addDff(NEW_ID, sig_d, sig_q));
|
||||
past_ffs.insert(clocking.addDff(new_verific_id(inst), sig_d, sig_q));
|
||||
|
||||
if (!mode_keep)
|
||||
continue;
|
||||
|
@ -1268,14 +1328,14 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
|
||||
SigBit sig_d = net_map_at(inst->GetInput1());
|
||||
SigBit sig_o = net_map_at(inst->GetOutput());
|
||||
SigBit sig_q = module->addWire(NEW_ID);
|
||||
SigBit sig_q = module->addWire(new_verific_id(inst));
|
||||
|
||||
if (verific_verbose)
|
||||
log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",
|
||||
log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig));
|
||||
|
||||
clocking.addDff(NEW_ID, sig_d, sig_q);
|
||||
module->addEq(NEW_ID, {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o);
|
||||
clocking.addDff(new_verific_id(inst), sig_d, sig_q);
|
||||
module->addEq(new_verific_id(inst), {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o);
|
||||
|
||||
if (!mode_keep)
|
||||
continue;
|
||||
|
@ -1298,9 +1358,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
|
||||
Cell *cell = nullptr;
|
||||
if (assume_attr != nullptr && !strcmp(assume_attr, "1"))
|
||||
cell = module->addAssume(NEW_ID, cond, State::S1);
|
||||
cell = module->addAssume(new_verific_id(inst), cond, State::S1);
|
||||
else
|
||||
cell = module->addAssert(NEW_ID, cond, State::S1);
|
||||
cell = module->addAssert(new_verific_id(inst), cond, State::S1);
|
||||
|
||||
import_attributes(cell->attributes, inst);
|
||||
continue;
|
||||
|
@ -1342,7 +1402,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
IdString port_name_id = RTLIL::escape_id(port_name);
|
||||
auto &sigvec = cell_port_conns[port_name_id];
|
||||
if (GetSize(sigvec) <= port_offset) {
|
||||
SigSpec zwires = module->addWire(NEW_ID, port_offset+1-GetSize(sigvec));
|
||||
SigSpec zwires = module->addWire(new_verific_id(inst), port_offset+1-GetSize(sigvec));
|
||||
for (auto bit : zwires)
|
||||
sigvec.push_back(bit);
|
||||
}
|
||||
|
@ -1835,6 +1895,7 @@ struct VerificPass : public Pass {
|
|||
Message::RegisterCallBackMsg(msg_func);
|
||||
RuntimeFlags::SetVar("db_preserve_user_nets", 1);
|
||||
RuntimeFlags::SetVar("db_allow_external_nets", 1);
|
||||
RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);
|
||||
RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
|
||||
RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
|
||||
RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
|
||||
|
@ -2093,42 +2154,6 @@ struct VerificPass : public Pass {
|
|||
|
||||
if (mode_all)
|
||||
{
|
||||
#if 0
|
||||
log("Running veri_file::ElaborateAll().\n");
|
||||
if (!veri_file::ElaborateAll())
|
||||
log_cmd_error("Elaboration of Verilog modules failed.\n");
|
||||
|
||||
log("Running vhdl_file::ElaborateAll().\n");
|
||||
if (!vhdl_file::ElaborateAll())
|
||||
log_cmd_error("Elaboration of VHDL modules failed.\n");
|
||||
|
||||
Library *lib = Netlist::PresentDesign()->Owner()->Owner();
|
||||
|
||||
if (argidx == GetSize(args))
|
||||
{
|
||||
MapIter iter;
|
||||
char *iter_name;
|
||||
Verific::Cell *iter_cell;
|
||||
|
||||
FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) {
|
||||
if (*iter_name != '$')
|
||||
nl_todo.insert(iter_cell->GetFirstNetlist());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; argidx < GetSize(args); argidx++)
|
||||
{
|
||||
Verific::Cell *cell = lib->GetCell(args[argidx].c_str());
|
||||
|
||||
if (cell == nullptr)
|
||||
log_cmd_error("Module not found: %s\n", args[argidx].c_str());
|
||||
|
||||
nl_todo.insert(cell->GetFirstNetlist());
|
||||
cell->GetFirstNetlist()->SetPresentDesign();
|
||||
}
|
||||
}
|
||||
#else
|
||||
log("Running hier_tree::ElaborateAll().\n");
|
||||
|
||||
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
|
||||
|
@ -2145,28 +2170,12 @@ struct VerificPass : public Pass {
|
|||
FOREACH_ARRAY_ITEM(netlists, i, nl)
|
||||
nl_todo.insert(nl);
|
||||
delete netlists;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argidx == GetSize(args))
|
||||
log_cmd_error("No top module specified.\n");
|
||||
|
||||
#if 0
|
||||
for (; argidx < GetSize(args); argidx++) {
|
||||
if (veri_file::GetModule(args[argidx].c_str())) {
|
||||
log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str());
|
||||
if (!veri_file::Elaborate(args[argidx].c_str()))
|
||||
log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str());
|
||||
nl_todo.insert(Netlist::PresentDesign());
|
||||
} else {
|
||||
log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str());
|
||||
if (!vhdl_file::Elaborate(args[argidx].c_str()))
|
||||
log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str());
|
||||
nl_todo.insert(Netlist::PresentDesign());
|
||||
}
|
||||
}
|
||||
#else
|
||||
Array veri_modules, vhdl_units;
|
||||
for (; argidx < GetSize(args); argidx++)
|
||||
{
|
||||
|
@ -2198,7 +2207,6 @@ struct VerificPass : public Pass {
|
|||
FOREACH_ARRAY_ITEM(netlists, i, nl)
|
||||
nl_todo.insert(nl);
|
||||
delete netlists;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!verific_error_msg.empty())
|
||||
|
|
|
@ -78,6 +78,7 @@ struct VerificImporter
|
|||
|
||||
RTLIL::SigBit net_map_at(Verific::Net *net);
|
||||
|
||||
RTLIL::IdString new_verific_id(Verific::DesignObj *obj);
|
||||
void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj);
|
||||
|
||||
RTLIL::SigSpec operatorInput(Verific::Instance *inst);
|
||||
|
|
|
@ -135,6 +135,9 @@ YOSYS_NAMESPACE_END
|
|||
frontend_verilog_yyerror("Unsupported default nettype: %s", p);
|
||||
}
|
||||
|
||||
"`protect"[^\n]* /* ignore `protect*/
|
||||
"`endprotect"[^\n]* /* ignore `endprotect*/
|
||||
|
||||
"`"[a-zA-Z_$][a-zA-Z0-9_$]* {
|
||||
frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);
|
||||
}
|
||||
|
@ -150,6 +153,9 @@ YOSYS_NAMESPACE_END
|
|||
"specparam" { return TOK_SPECPARAM; }
|
||||
"package" { SV_KEYWORD(TOK_PACKAGE); }
|
||||
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
|
||||
"interface" { SV_KEYWORD(TOK_INTERFACE); }
|
||||
"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
|
||||
"modport" { SV_KEYWORD(TOK_MODPORT); }
|
||||
"parameter" { return TOK_PARAMETER; }
|
||||
"localparam" { return TOK_LOCALPARAM; }
|
||||
"defparam" { return TOK_DEFPARAM; }
|
||||
|
@ -295,6 +301,11 @@ supply1 { return TOK_SUPPLY1; }
|
|||
return TOK_ID;
|
||||
}
|
||||
|
||||
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
|
||||
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
|
||||
return TOK_ID;
|
||||
}
|
||||
|
||||
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
|
||||
static bool printed_warning = false;
|
||||
if (!printed_warning) {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
%{
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <string.h>
|
||||
#include "frontends/verilog/verilog_frontend.h"
|
||||
#include "kernel/log.h"
|
||||
|
@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN
|
|||
namespace VERILOG_FRONTEND {
|
||||
int port_counter;
|
||||
std::map<std::string, int> port_stubs;
|
||||
std::map<std::string, AstNode*> attr_list, default_attr_list;
|
||||
std::map<std::string, AstNode*> *attr_list, default_attr_list;
|
||||
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
|
||||
std::map<std::string, AstNode*> *albuf;
|
||||
std::vector<AstNode*> ast_stack;
|
||||
struct AstNode *astbuf1, *astbuf2, *astbuf3;
|
||||
|
@ -61,6 +63,7 @@ namespace VERILOG_FRONTEND {
|
|||
bool noassert_mode, noassume_mode, norestrict_mode;
|
||||
bool assume_asserts_mode, assert_assumes_mode;
|
||||
bool current_wire_rand, current_wire_const;
|
||||
bool current_modport_input, current_modport_output;
|
||||
std::istream *lexin;
|
||||
}
|
||||
YOSYS_NAMESPACE_END
|
||||
|
@ -106,6 +109,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
|||
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
||||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
|
||||
%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT
|
||||
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC
|
||||
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
|
||||
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
|
||||
|
@ -123,7 +127,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
|||
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
|
||||
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
|
||||
%type <string> opt_label tok_prim_wrapper hierarchical_id
|
||||
%type <boolean> opt_signed unique_case_attr
|
||||
%type <boolean> opt_signed opt_property unique_case_attr
|
||||
%type <al> attr case_attr
|
||||
|
||||
// operator precedence from low to high
|
||||
|
@ -168,19 +172,23 @@ design:
|
|||
param_decl design |
|
||||
localparam_decl design |
|
||||
package design |
|
||||
interface design |
|
||||
/* empty */;
|
||||
|
||||
attr:
|
||||
{
|
||||
for (auto &it : attr_list)
|
||||
delete it.second;
|
||||
attr_list.clear();
|
||||
if (attr_list != nullptr)
|
||||
attr_list_stack.push(attr_list);
|
||||
attr_list = new std::map<std::string, AstNode*>;
|
||||
for (auto &it : default_attr_list)
|
||||
attr_list[it.first] = it.second->clone();
|
||||
(*attr_list)[it.first] = it.second->clone();
|
||||
} attr_opt {
|
||||
std::map<std::string, AstNode*> *al = new std::map<std::string, AstNode*>;
|
||||
al->swap(attr_list);
|
||||
$$ = al;
|
||||
$$ = attr_list;
|
||||
if (!attr_list_stack.empty()) {
|
||||
attr_list = attr_list_stack.top();
|
||||
attr_list_stack.pop();
|
||||
} else
|
||||
attr_list = nullptr;
|
||||
};
|
||||
|
||||
attr_opt:
|
||||
|
@ -189,15 +197,20 @@ attr_opt:
|
|||
|
||||
defattr:
|
||||
DEFATTR_BEGIN {
|
||||
if (attr_list != nullptr)
|
||||
attr_list_stack.push(attr_list);
|
||||
attr_list = new std::map<std::string, AstNode*>;
|
||||
for (auto &it : default_attr_list)
|
||||
delete it.second;
|
||||
default_attr_list.clear();
|
||||
for (auto &it : attr_list)
|
||||
delete it.second;
|
||||
attr_list.clear();
|
||||
} opt_attr_list {
|
||||
default_attr_list = attr_list;
|
||||
attr_list.clear();
|
||||
attr_list->swap(default_attr_list);
|
||||
delete attr_list;
|
||||
if (!attr_list_stack.empty()) {
|
||||
attr_list = attr_list_stack.top();
|
||||
attr_list_stack.pop();
|
||||
} else
|
||||
attr_list = nullptr;
|
||||
} DEFATTR_END;
|
||||
|
||||
opt_attr_list:
|
||||
|
@ -209,15 +222,15 @@ attr_list:
|
|||
|
||||
attr_assign:
|
||||
hierarchical_id {
|
||||
if (attr_list.count(*$1) != 0)
|
||||
delete attr_list[*$1];
|
||||
attr_list[*$1] = AstNode::mkconst_int(1, false);
|
||||
if (attr_list->count(*$1) != 0)
|
||||
delete (*attr_list)[*$1];
|
||||
(*attr_list)[*$1] = AstNode::mkconst_int(1, false);
|
||||
delete $1;
|
||||
} |
|
||||
hierarchical_id '=' expr {
|
||||
if (attr_list.count(*$1) != 0)
|
||||
delete attr_list[*$1];
|
||||
attr_list[*$1] = $3;
|
||||
if (attr_list->count(*$1) != 0)
|
||||
delete (*attr_list)[*$1];
|
||||
(*attr_list)[*$1] = $3;
|
||||
delete $1;
|
||||
};
|
||||
|
||||
|
@ -302,7 +315,7 @@ module_arg_opt_assignment:
|
|||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
|
||||
} else
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value.");
|
||||
} |
|
||||
/* empty */;
|
||||
|
||||
|
@ -320,6 +333,21 @@ module_arg:
|
|||
}
|
||||
delete $1;
|
||||
} module_arg_opt_assignment |
|
||||
TOK_ID {
|
||||
astbuf1 = new AstNode(AST_INTERFACEPORT);
|
||||
astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE));
|
||||
astbuf1->children[0]->str = *$1;
|
||||
delete $1;
|
||||
} TOK_ID { /* SV interfaces */
|
||||
if (!sv_mode)
|
||||
frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str());
|
||||
astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type.
|
||||
astbuf2->str = *$3;
|
||||
delete $3;
|
||||
astbuf2->port_id = ++port_counter;
|
||||
ast_stack.back()->children.push_back(astbuf2);
|
||||
delete astbuf1; // really only needed if multiple instances of same type.
|
||||
} module_arg_opt_assignment |
|
||||
attr wire_type range TOK_ID {
|
||||
AstNode *node = $2;
|
||||
node->str = *$4;
|
||||
|
@ -357,6 +385,33 @@ package_body:
|
|||
package_body_stmt:
|
||||
localparam_decl;
|
||||
|
||||
interface:
|
||||
TOK_INTERFACE TOK_ID {
|
||||
do_not_require_port_stubs = false;
|
||||
AstNode *intf = new AstNode(AST_INTERFACE);
|
||||
ast_stack.back()->children.push_back(intf);
|
||||
ast_stack.push_back(intf);
|
||||
current_ast_mod = intf;
|
||||
port_stubs.clear();
|
||||
port_counter = 0;
|
||||
intf->str = *$2;
|
||||
delete $2;
|
||||
} module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE {
|
||||
if (port_stubs.size() != 0)
|
||||
frontend_verilog_yyerror("Missing details for module port `%s'.",
|
||||
port_stubs.begin()->first.c_str());
|
||||
ast_stack.pop_back();
|
||||
log_assert(ast_stack.size() == 1);
|
||||
current_ast_mod = NULL;
|
||||
};
|
||||
|
||||
interface_body:
|
||||
interface_body interface_body_stmt |;
|
||||
|
||||
interface_body_stmt:
|
||||
param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
|
||||
modport_stmt;
|
||||
|
||||
non_opt_delay:
|
||||
'#' TOK_ID { delete $2; } |
|
||||
'#' TOK_CONSTVAL { delete $2; } |
|
||||
|
@ -627,7 +682,7 @@ task_func_port:
|
|||
astbuf2 = $3;
|
||||
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
||||
if (astbuf2) {
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)");
|
||||
} else {
|
||||
astbuf2 = new AstNode(AST_RANGE);
|
||||
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
|
||||
|
@ -635,7 +690,7 @@ task_func_port:
|
|||
}
|
||||
}
|
||||
if (astbuf2 && astbuf2->children.size() != 2)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("task/function argument range must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
|
||||
} wire_name | wire_name;
|
||||
|
||||
task_func_body:
|
||||
|
@ -838,7 +893,7 @@ param_signed:
|
|||
param_integer:
|
||||
TOK_INTEGER {
|
||||
if (astbuf1->children.size() != 1)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("Internal error in param_integer - should not happen?");
|
||||
astbuf1->children.push_back(new AstNode(AST_RANGE));
|
||||
astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));
|
||||
astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true));
|
||||
|
@ -848,7 +903,7 @@ param_integer:
|
|||
param_real:
|
||||
TOK_REAL {
|
||||
if (astbuf1->children.size() != 1)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real.");
|
||||
astbuf1->children.push_back(new AstNode(AST_REALVALUE));
|
||||
} | /* empty */;
|
||||
|
||||
|
@ -856,7 +911,7 @@ param_range:
|
|||
range {
|
||||
if ($1 != NULL) {
|
||||
if (astbuf1->children.size() != 1)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("integer/real parameters should not have a range.");
|
||||
astbuf1->children.push_back($1);
|
||||
}
|
||||
};
|
||||
|
@ -885,7 +940,7 @@ single_param_decl:
|
|||
AstNode *node;
|
||||
if (astbuf1 == nullptr) {
|
||||
if (!sv_mode)
|
||||
frontend_verilog_yyerror("syntax error");
|
||||
frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword");
|
||||
node = new AstNode(AST_PARAMETER);
|
||||
node->children.push_back(AstNode::mkconst_int(0, true));
|
||||
} else {
|
||||
|
@ -921,7 +976,7 @@ wire_decl:
|
|||
astbuf2 = $3;
|
||||
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
||||
if (astbuf2) {
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions.");
|
||||
} else {
|
||||
astbuf2 = new AstNode(AST_RANGE);
|
||||
astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
|
||||
|
@ -929,7 +984,7 @@ wire_decl:
|
|||
}
|
||||
}
|
||||
if (astbuf2 && astbuf2->children.size() != 2)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
|
||||
} wire_name_list {
|
||||
delete astbuf1;
|
||||
if (astbuf2 != NULL)
|
||||
|
@ -1023,7 +1078,7 @@ wire_name_and_opt_assign:
|
|||
wire_name:
|
||||
TOK_ID range_or_multirange {
|
||||
if (astbuf1 == nullptr)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node.");
|
||||
AstNode *node = astbuf1->clone();
|
||||
node->str = *$1;
|
||||
append_attr_clone(node, albuf);
|
||||
|
@ -1031,7 +1086,7 @@ wire_name:
|
|||
node->children.push_back(astbuf2->clone());
|
||||
if ($2 != NULL) {
|
||||
if (node->is_input || node->is_output)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions.");
|
||||
if (!astbuf2) {
|
||||
AstNode *rng = new AstNode(AST_RANGE);
|
||||
rng->children.push_back(AstNode::mkconst_int(0, true));
|
||||
|
@ -1275,11 +1330,51 @@ opt_label:
|
|||
};
|
||||
|
||||
opt_property:
|
||||
TOK_PROPERTY | /* empty */;
|
||||
TOK_PROPERTY {
|
||||
$$ = true;
|
||||
} |
|
||||
/* empty */ {
|
||||
$$ = false;
|
||||
};
|
||||
|
||||
opt_stmt_label:
|
||||
TOK_ID ':' | /* empty */;
|
||||
|
||||
modport_stmt:
|
||||
TOK_MODPORT TOK_ID {
|
||||
AstNode *modport = new AstNode(AST_MODPORT);
|
||||
ast_stack.back()->children.push_back(modport);
|
||||
ast_stack.push_back(modport);
|
||||
modport->str = *$2;
|
||||
delete $2;
|
||||
} modport_args_opt {
|
||||
ast_stack.pop_back();
|
||||
log_assert(ast_stack.size() == 2);
|
||||
} ';'
|
||||
|
||||
modport_args_opt:
|
||||
'(' ')' | '(' modport_args optional_comma ')';
|
||||
|
||||
modport_args:
|
||||
modport_arg | modport_args ',' modport_arg;
|
||||
|
||||
modport_arg:
|
||||
modport_type_token modport_member |
|
||||
modport_member
|
||||
|
||||
modport_member:
|
||||
TOK_ID {
|
||||
AstNode *modport_member = new AstNode(AST_MODPORTMEMBER);
|
||||
ast_stack.back()->children.push_back(modport_member);
|
||||
modport_member->str = *$1;
|
||||
modport_member->is_input = current_modport_input;
|
||||
modport_member->is_output = current_modport_output;
|
||||
delete $1;
|
||||
}
|
||||
|
||||
modport_type_token:
|
||||
TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
|
||||
|
||||
assert:
|
||||
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
||||
if (noassert_mode)
|
||||
|
@ -1319,12 +1414,16 @@ assert:
|
|||
delete $5;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
|
||||
if (!$3)
|
||||
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
||||
} |
|
||||
opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||
if (norestrict_mode)
|
||||
delete $6;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
|
||||
if (!$3)
|
||||
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
||||
};
|
||||
|
||||
assert_property:
|
||||
|
@ -1398,7 +1497,7 @@ behavioral_stmt:
|
|||
node->str = *$3;
|
||||
} behavioral_stmt_list TOK_END opt_label {
|
||||
if ($3 != NULL && $7 != NULL && *$3 != *$7)
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);
|
||||
if ($3 != NULL)
|
||||
delete $3;
|
||||
if ($7 != NULL)
|
||||
|
@ -1714,7 +1813,7 @@ basic_expr:
|
|||
} |
|
||||
'(' expr ')' TOK_CONSTVAL {
|
||||
if ($4->substr(0, 1) != "'")
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
|
||||
AstNode *bits = $2;
|
||||
AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
|
||||
if (val == NULL)
|
||||
|
@ -1724,7 +1823,7 @@ basic_expr:
|
|||
} |
|
||||
hierarchical_id TOK_CONSTVAL {
|
||||
if ($2->substr(0, 1) != "'")
|
||||
frontend_verilog_yyerror("Syntax error.");
|
||||
frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
|
||||
AstNode *bits = new AstNode(AST_IDENTIFIER);
|
||||
bits->str = *$1;
|
||||
AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
|
||||
|
|
|
@ -257,7 +257,7 @@ struct CellTypes
|
|||
return v;
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
|
||||
{
|
||||
if (type == "$sshr" && !signed1)
|
||||
type = "$shr";
|
||||
|
@ -329,10 +329,15 @@ struct CellTypes
|
|||
if (type == "$_ORNOT_")
|
||||
return const_or(arg1, eval_not(arg2), false, false, 1);
|
||||
|
||||
if (errp != nullptr) {
|
||||
*errp = true;
|
||||
return State::Sm;
|
||||
}
|
||||
|
||||
log_abort();
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2)
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
|
||||
{
|
||||
if (cell->type == "$slice") {
|
||||
RTLIL::Const ret;
|
||||
|
@ -415,10 +420,10 @@ struct CellTypes
|
|||
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
|
||||
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
|
||||
int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
|
||||
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
|
||||
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp);
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
|
||||
{
|
||||
if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
|
||||
RTLIL::Const ret = arg1;
|
||||
|
@ -436,10 +441,10 @@ struct CellTypes
|
|||
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
|
||||
|
||||
log_assert(arg3.bits.size() == 0);
|
||||
return eval(cell, arg1, arg2);
|
||||
return eval(cell, arg1, arg2, errp);
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4)
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr)
|
||||
{
|
||||
if (cell->type == "$_AOI4_")
|
||||
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
|
||||
|
@ -447,7 +452,7 @@ struct CellTypes
|
|||
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
|
||||
|
||||
log_assert(arg4.bits.size() == 0);
|
||||
return eval(cell, arg1, arg2, arg3);
|
||||
return eval(cell, arg1, arg2, arg3, errp);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -321,8 +321,13 @@ struct ConstEval
|
|||
if (sig_d.size() > 0 && !eval(sig_d, undef, cell))
|
||||
return false;
|
||||
|
||||
set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(),
|
||||
sig_c.as_const(), sig_d.as_const()));
|
||||
bool eval_err = false;
|
||||
RTLIL::Const eval_ret = CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(), sig_c.as_const(), sig_d.as_const(), &eval_err);
|
||||
|
||||
if (eval_err)
|
||||
return false;
|
||||
|
||||
set(sig_y, eval_ret);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -639,6 +639,11 @@ RTLIL::Module::~Module()
|
|||
delete it->second;
|
||||
}
|
||||
|
||||
void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>)
|
||||
{
|
||||
log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name));
|
||||
}
|
||||
|
||||
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, bool mayfail)
|
||||
{
|
||||
if (mayfail)
|
||||
|
@ -646,6 +651,14 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLI
|
|||
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
|
||||
}
|
||||
|
||||
|
||||
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, dict<RTLIL::IdString, RTLIL::Module*>, dict<RTLIL::IdString, RTLIL::IdString>, bool mayfail)
|
||||
{
|
||||
if (mayfail)
|
||||
return RTLIL::IdString();
|
||||
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
|
||||
}
|
||||
|
||||
size_t RTLIL::Module::count_id(RTLIL::IdString id)
|
||||
{
|
||||
return wires_.count(id) + memories.count(id) + cells_.count(id) + processes.count(id);
|
||||
|
|
|
@ -907,7 +907,9 @@ public:
|
|||
Module();
|
||||
virtual ~Module();
|
||||
virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail = false);
|
||||
virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail = false);
|
||||
virtual size_t count_id(RTLIL::IdString id);
|
||||
virtual void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces);
|
||||
|
||||
virtual void sort();
|
||||
virtual void check();
|
||||
|
|
|
@ -799,7 +799,7 @@ static void handle_label(std::string &command, bool &from_to_active, const std::
|
|||
while (pos < GetSize(command) && command[pos] != ' ' && command[pos] != '\t' && command[pos] != '\r' && command[pos] != '\n')
|
||||
label += command[pos++];
|
||||
|
||||
if (label.back() == ':' && GetSize(label) > 1)
|
||||
if (GetSize(label) > 1 && label.back() == ':')
|
||||
{
|
||||
label = label.substr(0, GetSize(label)-1);
|
||||
command = command.substr(pos);
|
||||
|
@ -821,7 +821,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
command = "verilog";
|
||||
else if (filename.size() > 2 && filename.substr(filename.size()-3) == ".sv")
|
||||
command = "verilog -sv";
|
||||
else if (filename.size() > 2 && filename.substr(filename.size()-4) == ".vhd")
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-4) == ".vhd")
|
||||
command = "vhdl";
|
||||
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
|
||||
command = "blif";
|
||||
|
@ -833,7 +833,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
command = "ilang";
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
|
||||
command = "script";
|
||||
else if (filename.size() > 2 && filename.substr(filename.size()-4) == ".tcl")
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-4) == ".tcl")
|
||||
command = "tcl";
|
||||
else if (filename == "-")
|
||||
command = "script";
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -52,6 +52,15 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
|
|||
log_cmd_error("Object `%s' not found!\n", from_name.c_str());
|
||||
}
|
||||
|
||||
static std::string derive_name_from_src(const std::string &src, int counter)
|
||||
{
|
||||
std::string src_base = src.substr(0, src.find('|'));
|
||||
if (src_base.empty())
|
||||
return stringf("$%d", counter);
|
||||
else
|
||||
return stringf("\\%s$%d", src_base.c_str(), counter);
|
||||
}
|
||||
|
||||
struct RenamePass : public Pass {
|
||||
RenamePass() : Pass("rename", "rename object in the design") { }
|
||||
void help() YS_OVERRIDE
|
||||
|
@ -63,6 +72,10 @@ struct RenamePass : public Pass {
|
|||
log("Rename the specified object. Note that selection patterns are not supported\n");
|
||||
log("by this command.\n");
|
||||
log("\n");
|
||||
log(" rename -src [selection]\n");
|
||||
log("\n");
|
||||
log("Assign names auto-generated from the src attribute to all selected wires and\n");
|
||||
log("cells with private names.\n");
|
||||
log("\n");
|
||||
log(" rename -enumerate [-pattern <pattern>] [selection]\n");
|
||||
log("\n");
|
||||
|
@ -84,6 +97,7 @@ struct RenamePass : public Pass {
|
|||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
std::string pattern_prefix = "_", pattern_suffix = "_";
|
||||
bool flag_src = false;
|
||||
bool flag_enumerate = false;
|
||||
bool flag_hide = false;
|
||||
bool flag_top = false;
|
||||
|
@ -93,6 +107,11 @@ struct RenamePass : public Pass {
|
|||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-src" && !got_mode) {
|
||||
flag_src = true;
|
||||
got_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-enumerate" && !got_mode) {
|
||||
flag_enumerate = true;
|
||||
got_mode = true;
|
||||
|
@ -117,6 +136,37 @@ struct RenamePass : public Pass {
|
|||
break;
|
||||
}
|
||||
|
||||
if (flag_src)
|
||||
{
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto &mod : design->modules_)
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
RTLIL::Module *module = mod.second;
|
||||
if (!design->selected(module))
|
||||
continue;
|
||||
|
||||
dict<RTLIL::IdString, RTLIL::Wire*> new_wires;
|
||||
for (auto &it : module->wires_) {
|
||||
if (it.first[0] == '$' && design->selected(module, it.second))
|
||||
it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
|
||||
new_wires[it.second->name] = it.second;
|
||||
}
|
||||
module->wires_.swap(new_wires);
|
||||
module->fixup_ports();
|
||||
|
||||
dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
|
||||
for (auto &it : module->cells_) {
|
||||
if (it.first[0] == '$' && design->selected(module, it.second))
|
||||
it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
|
||||
new_cells[it.second->name] = it.second;
|
||||
}
|
||||
module->cells_.swap(new_cells);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (flag_enumerate)
|
||||
{
|
||||
extra_args(args, argidx, design);
|
||||
|
|
|
@ -896,6 +896,29 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
|
|||
select_filter_active_mod(design, work_stack.back());
|
||||
}
|
||||
|
||||
static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::Selection *sel)
|
||||
{
|
||||
std::string desc = "Selection contains:\n";
|
||||
for (auto mod_it : design->modules_)
|
||||
{
|
||||
if (sel->selected_module(mod_it.first)) {
|
||||
for (auto &it : mod_it.second->wires_)
|
||||
if (sel->selected_member(mod_it.first, it.first))
|
||||
desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
|
||||
for (auto &it : mod_it.second->memories)
|
||||
if (sel->selected_member(mod_it.first, it.first))
|
||||
desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
|
||||
for (auto &it : mod_it.second->cells_)
|
||||
if (sel->selected_member(mod_it.first, it.first))
|
||||
desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
|
||||
for (auto &it : mod_it.second->processes)
|
||||
if (sel->selected_member(mod_it.first, it.first))
|
||||
desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -1394,7 +1417,12 @@ struct SelectPass : public Pass {
|
|||
log_cmd_error("No selection to check.\n");
|
||||
work_stack.back().optimize(design);
|
||||
if (!work_stack.back().empty())
|
||||
log_error("Assertion failed: selection is not empty:%s\n", sel_str.c_str());
|
||||
{
|
||||
RTLIL::Selection *sel = &work_stack.back();
|
||||
sel->optimize(design);
|
||||
std::string desc = describe_selection_for_assert(design, sel);
|
||||
log_error("Assertion failed: selection is not empty:%s\n%s", sel_str.c_str(), desc.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1404,7 +1432,12 @@ struct SelectPass : public Pass {
|
|||
log_cmd_error("No selection to check.\n");
|
||||
work_stack.back().optimize(design);
|
||||
if (work_stack.back().empty())
|
||||
log_error("Assertion failed: selection is empty:%s\n", sel_str.c_str());
|
||||
{
|
||||
RTLIL::Selection *sel = &work_stack.back();
|
||||
sel->optimize(design);
|
||||
std::string desc = describe_selection_for_assert(design, sel);
|
||||
log_error("Assertion failed: selection is empty:%s\n%s", sel_str.c_str(), desc.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1431,14 +1464,23 @@ struct SelectPass : public Pass {
|
|||
total_count++;
|
||||
}
|
||||
if (assert_count >= 0 && assert_count != total_count)
|
||||
log_error("Assertion failed: selection contains %d elements instead of the asserted %d:%s\n",
|
||||
total_count, assert_count, sel_str.c_str());
|
||||
{
|
||||
std::string desc = describe_selection_for_assert(design, sel);
|
||||
log_error("Assertion failed: selection contains %d elements instead of the asserted %d:%s\n%s",
|
||||
total_count, assert_count, sel_str.c_str(), desc.c_str());
|
||||
}
|
||||
if (assert_max >= 0 && assert_max < total_count)
|
||||
log_error("Assertion failed: selection contains %d elements, more than the maximum number %d:%s\n",
|
||||
total_count, assert_max, sel_str.c_str());
|
||||
{
|
||||
std::string desc = describe_selection_for_assert(design, sel);
|
||||
log_error("Assertion failed: selection contains %d elements, more than the maximum number %d:%s\n%s",
|
||||
total_count, assert_max, sel_str.c_str(), desc.c_str());
|
||||
}
|
||||
if (assert_min >= 0 && assert_min > total_count)
|
||||
log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n",
|
||||
total_count, assert_min, sel_str.c_str());
|
||||
{
|
||||
std::string desc = describe_selection_for_assert(design, sel);
|
||||
log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n%s",
|
||||
total_count, assert_min, sel_str.c_str(), desc.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,4 +9,4 @@ OBJS += passes/equiv/equiv_induct.o
|
|||
OBJS += passes/equiv/equiv_struct.o
|
||||
OBJS += passes/equiv/equiv_purge.o
|
||||
OBJS += passes/equiv/equiv_mark.o
|
||||
|
||||
OBJS += passes/equiv/equiv_opt.o
|
||||
|
|
|
@ -40,6 +40,16 @@ struct EquivMakeWorker
|
|||
pool<SigBit> undriven_bits;
|
||||
SigMap assign_map;
|
||||
|
||||
dict<SigBit, pool<Cell*>> bit2driven; // map: bit <--> and its driven cells
|
||||
|
||||
CellTypes comb_ct;
|
||||
|
||||
EquivMakeWorker()
|
||||
{
|
||||
comb_ct.setup_internals();
|
||||
comb_ct.setup_stdcells();
|
||||
}
|
||||
|
||||
void read_blacklists()
|
||||
{
|
||||
for (auto fn : blacklists)
|
||||
|
@ -278,16 +288,31 @@ struct EquivMakeWorker
|
|||
}
|
||||
}
|
||||
|
||||
init_bit2driven();
|
||||
|
||||
pool<Cell*> visited_cells;
|
||||
for (auto c : cells_list)
|
||||
for (auto &conn : c->connections())
|
||||
if (!ct.cell_output(c->type, conn.first)) {
|
||||
SigSpec old_sig = assign_map(conn.second);
|
||||
SigSpec new_sig = rd_signal_map(old_sig);
|
||||
if (old_sig != new_sig) {
|
||||
log("Changing input %s of cell %s (%s): %s -> %s\n",
|
||||
log_id(conn.first), log_id(c), log_id(c->type),
|
||||
log_signal(old_sig), log_signal(new_sig));
|
||||
c->setPort(conn.first, new_sig);
|
||||
|
||||
if(old_sig != new_sig) {
|
||||
SigSpec tmp_sig = old_sig;
|
||||
for (int i = 0; i < GetSize(old_sig); i++) {
|
||||
SigBit old_bit = old_sig[i], new_bit = new_sig[i];
|
||||
|
||||
visited_cells.clear();
|
||||
if (check_signal_in_fanout(visited_cells, old_bit, new_bit))
|
||||
continue;
|
||||
|
||||
log("Changing input %s of cell %s (%s): %s -> %s\n",
|
||||
log_id(conn.first), log_id(c), log_id(c->type),
|
||||
log_signal(old_bit), log_signal(new_bit));
|
||||
|
||||
tmp_sig[i] = new_bit;
|
||||
}
|
||||
c->setPort(conn.first, tmp_sig);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,6 +403,57 @@ struct EquivMakeWorker
|
|||
}
|
||||
}
|
||||
|
||||
void init_bit2driven()
|
||||
{
|
||||
for (auto cell : equiv_mod->cells()) {
|
||||
if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_"))
|
||||
continue;
|
||||
for (auto &conn : cell->connections())
|
||||
{
|
||||
if (yosys_celltypes.cell_input(cell->type, conn.first))
|
||||
for (auto bit : assign_map(conn.second))
|
||||
{
|
||||
bit2driven[bit].insert(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool check_signal_in_fanout(pool<Cell*> & visited_cells, SigBit source_bit, SigBit target_bit)
|
||||
{
|
||||
if (source_bit == target_bit)
|
||||
return true;
|
||||
|
||||
if (bit2driven.count(source_bit) == 0)
|
||||
return false;
|
||||
|
||||
auto driven_cells = bit2driven.at(source_bit);
|
||||
for (auto driven_cell: driven_cells)
|
||||
{
|
||||
bool is_comb = comb_ct.cell_known(driven_cell->type);
|
||||
if (!is_comb)
|
||||
continue;
|
||||
|
||||
if (visited_cells.count(driven_cell) > 0)
|
||||
continue;
|
||||
visited_cells.insert(driven_cell);
|
||||
|
||||
for (auto &conn: driven_cell->connections())
|
||||
{
|
||||
if (yosys_celltypes.cell_input(driven_cell->type, conn.first))
|
||||
continue;
|
||||
|
||||
for (auto bit: conn.second) {
|
||||
bool is_in_fanout = check_signal_in_fanout(visited_cells, bit, target_bit);
|
||||
if (is_in_fanout == true)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
copy_to_equiv();
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2018 whitequark <whitequark@whitequark.org>
|
||||
*
|
||||
* 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"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct EquivOptPass:public ScriptPass
|
||||
{
|
||||
EquivOptPass() : ScriptPass("equiv_opt", "prove equivalence for optimized circuit") { }
|
||||
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" equiv_opt [options] [command]\n");
|
||||
log("\n");
|
||||
log("This command checks circuit equivalence before and after an optimization pass.\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 the start of the command list, and empty to\n");
|
||||
log(" label is synonymous to the end of the command list.\n");
|
||||
log("\n");
|
||||
log(" -map <filename>\n");
|
||||
log(" expand the modules in this file before proving equivalence. this is\n");
|
||||
log(" useful for handling architecture-specific primitives.\n");
|
||||
log("\n");
|
||||
log(" -assert\n");
|
||||
log(" produce an error if the circuits are not equivalent\n");
|
||||
log("\n");
|
||||
log("The following commands are executed by this verification command:\n");
|
||||
help_script();
|
||||
log("\n");
|
||||
}
|
||||
|
||||
std::string command, techmap_opts;
|
||||
bool assert;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
command = "";
|
||||
techmap_opts = "";
|
||||
assert = 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] == "-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] == "-map" && argidx + 1 < args.size()) {
|
||||
techmap_opts += " -map " + args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-assert") {
|
||||
assert = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (; argidx < args.size(); argidx++) {
|
||||
if (command.empty()) {
|
||||
if (args[argidx].substr(0, 1) == "-")
|
||||
cmd_error(args, argidx, "Unknown option.");
|
||||
} else {
|
||||
command += " ";
|
||||
}
|
||||
command += args[argidx];
|
||||
}
|
||||
|
||||
if (command.empty())
|
||||
log_cmd_error("No optimization pass specified!\n");
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing EQUIV_OPT pass.\n");
|
||||
log_push();
|
||||
|
||||
run_script(design, run_from, run_to);
|
||||
|
||||
log_pop();
|
||||
}
|
||||
|
||||
void script() YS_OVERRIDE
|
||||
{
|
||||
if (check_label("run_pass")) {
|
||||
run("hierarchy -auto-top");
|
||||
run("design -save preopt");
|
||||
if (help_mode)
|
||||
run("[command]");
|
||||
else
|
||||
run(command);
|
||||
run("design -stash postopt");
|
||||
}
|
||||
|
||||
if (check_label("prepare")) {
|
||||
run("design -copy-from preopt -as gold A:top");
|
||||
run("design -copy-from postopt -as gate A:top");
|
||||
}
|
||||
|
||||
if ((!techmap_opts.empty() || help_mode) && check_label("techmap", "(only with -map)")) {
|
||||
string opts;
|
||||
if (help_mode)
|
||||
opts = " -map <filename> ...";
|
||||
else
|
||||
opts = techmap_opts;
|
||||
run("techmap -D EQUIV -autoproc" + opts);
|
||||
}
|
||||
|
||||
if (check_label("prove")) {
|
||||
run("equiv_make gold gate equiv");
|
||||
run("equiv_induct equiv");
|
||||
if (help_mode)
|
||||
run("equiv_status [-assert] equiv");
|
||||
else if (assert)
|
||||
run("equiv_status -assert equiv");
|
||||
else
|
||||
run("equiv_status equiv");
|
||||
}
|
||||
|
||||
if (check_label("restore")) {
|
||||
run("design -load preopt");
|
||||
}
|
||||
}
|
||||
} EquivOptPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -2,6 +2,7 @@
|
|||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||
* Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.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
|
||||
|
@ -145,9 +146,36 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
|
||||
std::string filename;
|
||||
|
||||
bool has_interface_ports = false;
|
||||
|
||||
// If any of the ports are actually interface ports, we will always need to
|
||||
// reprocess the module:
|
||||
if(!module->get_bool_attribute("\\interfaces_replaced_in_module")) {
|
||||
for (auto &wire : module->wires_) {
|
||||
if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface"))
|
||||
has_interface_ports = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Always keep track of all derived interfaces available in the current module in 'interfaces_in_module':
|
||||
dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
|
||||
for (auto &cell_it : module->cells_)
|
||||
{
|
||||
RTLIL::Cell *cell = cell_it.second;
|
||||
if(cell->get_bool_attribute("\\is_interface")) {
|
||||
RTLIL::Module *intf_module = design->modules_[cell->type];
|
||||
interfaces_in_module[cell->name] = intf_module;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &cell_it : module->cells_)
|
||||
{
|
||||
RTLIL::Cell *cell = cell_it.second;
|
||||
bool has_interfaces_not_found = false;
|
||||
|
||||
std::vector<RTLIL::IdString> connections_to_remove;
|
||||
std::vector<RTLIL::IdString> connections_to_add_name;
|
||||
std::vector<RTLIL::SigSpec> connections_to_add_signal;
|
||||
|
||||
if (cell->type.substr(0, 7) == "$array:") {
|
||||
int pos_idx = cell->type.str().find_first_of(':');
|
||||
|
@ -158,6 +186,8 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
array_cells[cell] = std::pair<int, int>(idx, num);
|
||||
cell->type = cell->type.str().substr(pos_type + 1);
|
||||
}
|
||||
dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
|
||||
dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule;
|
||||
|
||||
if (design->modules_.count(cell->type) == 0)
|
||||
{
|
||||
|
@ -200,11 +230,85 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
if (design->modules_.count(cell->type) == 0)
|
||||
log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
|
||||
did_something = true;
|
||||
} else
|
||||
} else {
|
||||
|
||||
RTLIL::Module *mod = design->module(cell->type);
|
||||
|
||||
// Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to
|
||||
// some lists, so that the ports for sub-modules can be replaced further down:
|
||||
for (auto &conn : cell->connections()) {
|
||||
if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list
|
||||
//const pool<string> &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_type");
|
||||
//for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module (not crucially important, but good for robustness)
|
||||
//}
|
||||
|
||||
// Find if the sub-module has set a modport for the current interface connection:
|
||||
const pool<string> &interface_modport_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_modport");
|
||||
std::string interface_modport = "";
|
||||
for (auto &d : interface_modport_pool) {
|
||||
interface_modport = "\\" + d;
|
||||
}
|
||||
if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) { // Check if the connected wire is a potential interface in the parent module
|
||||
std::string interface_name_str = conn.second.bits()[0].wire->name.str();
|
||||
interface_name_str.replace(0,23,""); // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name
|
||||
interface_name_str = "\\" + interface_name_str;
|
||||
RTLIL::IdString interface_name = interface_name_str;
|
||||
bool not_found_interface = false;
|
||||
if(module->get_bool_attribute("\\interfaces_replaced_in_module")) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either
|
||||
// Check if the interface instance is present in module:
|
||||
// Interface instances may either have the plain name or the name appended with '_inst_from_top_dummy'.
|
||||
// Check for both of them here
|
||||
int nexactmatch = interfaces_in_module.count(interface_name) > 0;
|
||||
std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy";
|
||||
RTLIL::IdString interface_name2 = interface_name_str2;
|
||||
int nmatch2 = interfaces_in_module.count(interface_name2) > 0;
|
||||
if (nexactmatch > 0 || nmatch2 > 0) {
|
||||
if (nexactmatch != 0) // Choose the one with the plain name if it exists
|
||||
interface_name2 = interface_name;
|
||||
RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2);
|
||||
for (auto &mod_wire : mod_replace_ports->wires_) { // Go over all wires in interface, and add replacements to lists.
|
||||
std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire.first);
|
||||
std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire.first);
|
||||
connections_to_add_name.push_back(RTLIL::IdString(signal_name1));
|
||||
if(module->wires_.count(signal_name2) == 0) {
|
||||
log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), log_id(module->name));
|
||||
}
|
||||
else {
|
||||
RTLIL::Wire *wire_in_parent = module->wire(signal_name2);
|
||||
connections_to_add_signal.push_back(wire_in_parent);
|
||||
}
|
||||
}
|
||||
connections_to_remove.push_back(conn.first);
|
||||
interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name2);
|
||||
|
||||
// Add modports to a dict which will be passed to AstModule::derive
|
||||
if (interface_modport != "") {
|
||||
modports_used_in_submodule[conn.first] = interface_modport;
|
||||
}
|
||||
}
|
||||
else not_found_interface = true;
|
||||
}
|
||||
else not_found_interface = true;
|
||||
// If the interface instance has not already been derived in the module, we cannot complete at this stage. Set "has_interfaces_not_found"
|
||||
// which will delay the expansion of this cell:
|
||||
if (not_found_interface) {
|
||||
// If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error:
|
||||
if(!(module->get_bool_attribute("\\cells_not_processed"))) {
|
||||
log_warning("Could not find interface instance for `%s' in `%s'\n", log_id(interface_name), log_id(module));
|
||||
}
|
||||
else {
|
||||
// Only set has_interfaces_not_found if it would be possible to find them, since otherwiser we will end up in an infinite loop:
|
||||
has_interfaces_not_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
if (flag_check || flag_simcheck)
|
||||
{
|
||||
RTLIL::Module *mod = design->module(cell->type);
|
||||
for (auto &conn : cell->connections())
|
||||
for (auto &conn : cell->connections()) {
|
||||
if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
|
||||
int id = atoi(conn.first.c_str()+1);
|
||||
if (id <= 0 || id > GetSize(mod->ports))
|
||||
|
@ -213,11 +317,15 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
} else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0)
|
||||
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first));
|
||||
}
|
||||
for (auto ¶m : cell->parameters)
|
||||
if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
|
||||
log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
|
||||
|
||||
}
|
||||
}
|
||||
RTLIL::Module *mod = design->modules_[cell->type];
|
||||
|
||||
if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) {
|
||||
if (flag_simcheck)
|
||||
|
@ -226,14 +334,61 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cell->parameters.size() == 0)
|
||||
// If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here:
|
||||
if(has_interfaces_not_found) {
|
||||
did_something = true; // waiting for interfaces to be handled
|
||||
continue;
|
||||
}
|
||||
|
||||
RTLIL::Module *mod = design->modules_[cell->type];
|
||||
cell->type = mod->derive(design, cell->parameters);
|
||||
// Do the actual replacements of the SV interface port connection with the individual signal connections:
|
||||
for(unsigned int i=0;i<connections_to_add_name.size();i++) {
|
||||
cell->connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
|
||||
}
|
||||
// Remove the connection for the interface itself:
|
||||
for(unsigned int i=0;i<connections_to_remove.size();i++) {
|
||||
cell->connections_.erase(connections_to_remove[i]);
|
||||
}
|
||||
|
||||
// If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type
|
||||
// for the cell:
|
||||
if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute("\\module_not_derived")))) {
|
||||
// If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:",
|
||||
// so that the signals of the interface are added to the parent module.
|
||||
if (mod->get_bool_attribute("\\is_interface")) {
|
||||
goto handle_interface_instance;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule, modports_used_in_submodule);
|
||||
cell->parameters.clear();
|
||||
did_something = true;
|
||||
|
||||
handle_interface_instance:
|
||||
|
||||
// We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter
|
||||
// an interface instance:
|
||||
if (mod->get_bool_attribute("\\is_interface") && cell->get_bool_attribute("\\module_not_derived")) {
|
||||
cell->set_bool_attribute("\\is_interface");
|
||||
RTLIL::Module *derived_module = design->modules_[cell->type];
|
||||
interfaces_in_module[cell->name] = derived_module;
|
||||
did_something = true;
|
||||
}
|
||||
// We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell)
|
||||
cell->attributes.erase("\\module_not_derived");
|
||||
}
|
||||
// Clear the attribute 'cells_not_processed' such that it can be known that we
|
||||
// have been through all cells at least once, and that we can know whether
|
||||
// to flag an error because of interface instances not found:
|
||||
module->attributes.erase("\\cells_not_processed");
|
||||
|
||||
|
||||
// If any interface instances or interface ports were found in the module, we need to rederive it completely:
|
||||
if ((interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute("\\interfaces_replaced_in_module")) {
|
||||
module->reprocess_module(design, interfaces_in_module);
|
||||
return did_something;
|
||||
}
|
||||
|
||||
|
||||
for (auto &it : array_cells)
|
||||
{
|
||||
|
@ -303,6 +458,20 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
|
|||
for (auto &it : design->modules_)
|
||||
if (used.count(it.second) == 0)
|
||||
del_modules.push_back(it.second);
|
||||
else {
|
||||
// Now all interface ports must have been exploded, and it is hence
|
||||
// safe to delete all of the remaining dummy interface ports:
|
||||
pool<RTLIL::Wire*> del_wires;
|
||||
for(auto &wire : it.second->wires_) {
|
||||
if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface")) {
|
||||
del_wires.insert(wire.second);
|
||||
}
|
||||
}
|
||||
if (del_wires.size() > 0) {
|
||||
it.second->remove(del_wires);
|
||||
it.second->fixup_ports();
|
||||
}
|
||||
}
|
||||
|
||||
int del_counter = 0;
|
||||
for (auto mod : del_modules) {
|
||||
|
@ -341,6 +510,20 @@ int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db)
|
|||
return db.at(module);
|
||||
}
|
||||
|
||||
RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod)
|
||||
{
|
||||
if(top_mod != NULL && top_mod->get_bool_attribute("\\initial_top"))
|
||||
return top_mod;
|
||||
else {
|
||||
for (auto mod : design->modules()) {
|
||||
if (mod->get_bool_attribute("\\top")) {
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct HierarchyPass : public Pass {
|
||||
HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
|
||||
void help() YS_OVERRIDE
|
||||
|
@ -568,6 +751,14 @@ struct HierarchyPass : public Pass {
|
|||
if (flag_simcheck && top_mod == nullptr)
|
||||
log_error("Design has no top module.\n");
|
||||
|
||||
if (top_mod != NULL) {
|
||||
for (auto &mod_it : design->modules_)
|
||||
if (mod_it.second == top_mod)
|
||||
mod_it.second->attributes["\\initial_top"] = RTLIL::Const(1);
|
||||
else
|
||||
mod_it.second->attributes.erase("\\initial_top");
|
||||
}
|
||||
|
||||
bool did_something = true;
|
||||
while (did_something)
|
||||
{
|
||||
|
@ -586,19 +777,43 @@ struct HierarchyPass : public Pass {
|
|||
if (expand_module(design, module, flag_check, flag_simcheck, libdirs))
|
||||
did_something = true;
|
||||
}
|
||||
|
||||
|
||||
// The top module might have changed if interface instances have been detected in it:
|
||||
RTLIL::Module *tmp_top_mod = check_if_top_has_changed(design, top_mod);
|
||||
if (tmp_top_mod != NULL) {
|
||||
if (tmp_top_mod != top_mod){
|
||||
top_mod = tmp_top_mod;
|
||||
did_something = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete modules marked as 'to_delete':
|
||||
std::vector<RTLIL::Module *> modules_to_delete;
|
||||
for(auto &mod_it : design->modules_) {
|
||||
if (mod_it.second->get_bool_attribute("\\to_delete")) {
|
||||
modules_to_delete.push_back(mod_it.second);
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<modules_to_delete.size(); i++) {
|
||||
design->remove(modules_to_delete[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (top_mod != NULL) {
|
||||
log_header(design, "Analyzing design hierarchy..\n");
|
||||
hierarchy_clean(design, top_mod, purge_lib);
|
||||
}
|
||||
|
||||
if (top_mod != NULL) {
|
||||
for (auto &mod_it : design->modules_)
|
||||
for (auto &mod_it : design->modules_) {
|
||||
if (mod_it.second == top_mod)
|
||||
mod_it.second->attributes["\\top"] = RTLIL::Const(1);
|
||||
else
|
||||
mod_it.second->attributes.erase("\\top");
|
||||
mod_it.second->attributes.erase("\\initial_top");
|
||||
}
|
||||
}
|
||||
|
||||
if (!nokeep_asserts) {
|
||||
|
|
|
@ -472,8 +472,12 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
|
|||
std::vector<SigSpec> new_wr_en(GetSize(old_wr_en));
|
||||
std::vector<SigSpec> new_wr_data(GetSize(old_wr_data));
|
||||
std::vector<SigSpec> new_rd_data(GetSize(old_rd_data));
|
||||
std::vector<std::vector<State>> new_initdata;
|
||||
std::vector<int> shuffle_map;
|
||||
|
||||
if (cell_init)
|
||||
new_initdata.resize(mem_size);
|
||||
|
||||
for (auto &it : en_order)
|
||||
{
|
||||
auto &bits = bits_wr_en.at(it);
|
||||
|
@ -489,6 +493,10 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
|
|||
}
|
||||
for (int j = 0; j < rd_ports; j++)
|
||||
new_rd_data[j].append(old_rd_data[j][bits[i]]);
|
||||
if (cell_init) {
|
||||
for (int j = 0; j < mem_size; j++)
|
||||
new_initdata[j].push_back(initdata[j][bits[i]]);
|
||||
}
|
||||
shuffle_map.push_back(bits[i]);
|
||||
}
|
||||
|
||||
|
@ -499,6 +507,10 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
|
|||
}
|
||||
for (int j = 0; j < rd_ports; j++)
|
||||
new_rd_data[j].append(State::Sx);
|
||||
if (cell_init) {
|
||||
for (int j = 0; j < mem_size; j++)
|
||||
new_initdata[j].push_back(State::Sx);
|
||||
}
|
||||
shuffle_map.push_back(-1);
|
||||
}
|
||||
}
|
||||
|
@ -522,6 +534,11 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
|
|||
|
||||
for (int i = 0; i < rd_ports; i++)
|
||||
rd_data.replace(i*mem_width, new_rd_data[i]);
|
||||
|
||||
if (cell_init) {
|
||||
for (int i = 0; i < mem_size; i++)
|
||||
initdata[i] = Const(new_initdata[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// assign write ports
|
||||
|
@ -623,6 +640,7 @@ grow_read_ports:;
|
|||
pi.sig_addr = SigSpec();
|
||||
pi.sig_data = SigSpec();
|
||||
pi.sig_en = SigSpec();
|
||||
pi.make_outreg = false;
|
||||
}
|
||||
new_portinfos.push_back(pi);
|
||||
if (pi.dupidx == dup_count-1) {
|
||||
|
|
|
@ -41,7 +41,7 @@ struct MemoryDffWorker
|
|||
if (wire->attributes.count("\\init") == 0)
|
||||
continue;
|
||||
SigSpec sig = sigmap(wire);
|
||||
Const initval = wire->attributes.count("\\init");
|
||||
Const initval = wire->attributes.at("\\init");
|
||||
for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
|
||||
if (initval[i] == State::S0 || initval[i] == State::S1)
|
||||
init_bits.insert(sig[i]);
|
||||
|
|
|
@ -6,6 +6,7 @@ OBJS += passes/opt/opt_reduce.o
|
|||
OBJS += passes/opt/opt_rmdff.o
|
||||
OBJS += passes/opt/opt_clean.o
|
||||
OBJS += passes/opt/opt_expr.o
|
||||
OBJS += passes/opt/opt_lut.o
|
||||
|
||||
ifneq ($(SMALL),1)
|
||||
OBJS += passes/opt/share.o
|
||||
|
|
|
@ -1406,7 +1406,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false)
|
||||
{
|
||||
if (sigConst.is_fully_zero()) {
|
||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, 1);
|
||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, GetSize(cell->getPort("\\Y")));
|
||||
if (is_lt) {
|
||||
log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n",
|
||||
log_id(cell->type), log_id(cell));
|
||||
|
|
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2018 whitequark <whitequark@whitequark.org>
|
||||
*
|
||||
* 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"
|
||||
#include "kernel/modtools.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct OptLutWorker
|
||||
{
|
||||
dict<IdString, dict<int, IdString>> &dlogic;
|
||||
RTLIL::Module *module;
|
||||
ModIndex index;
|
||||
SigMap sigmap;
|
||||
|
||||
pool<RTLIL::Cell*> luts;
|
||||
dict<RTLIL::Cell*, int> luts_arity;
|
||||
dict<RTLIL::Cell*, pool<RTLIL::Cell*>> luts_dlogics;
|
||||
dict<RTLIL::Cell*, pool<int>> luts_dlogic_inputs;
|
||||
|
||||
int combined_count = 0;
|
||||
|
||||
bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
|
||||
{
|
||||
SigSpec lut_input = sigmap(lut->getPort("\\A"));
|
||||
int lut_width = lut->getParam("\\WIDTH").as_int();
|
||||
Const lut_table = lut->getParam("\\LUT");
|
||||
int lut_index = 0;
|
||||
|
||||
for (int i = 0; i < lut_width; i++)
|
||||
{
|
||||
SigBit input = sigmap(lut_input[i]);
|
||||
if (inputs.count(input))
|
||||
{
|
||||
lut_index |= inputs[input] << i;
|
||||
}
|
||||
else
|
||||
{
|
||||
lut_index |= SigSpec(lut_input[i]).as_bool() << i;
|
||||
}
|
||||
}
|
||||
|
||||
return lut_table.extract(lut_index).as_bool();
|
||||
}
|
||||
|
||||
void show_stats_by_arity()
|
||||
{
|
||||
dict<int, int> arity_counts;
|
||||
dict<IdString, int> dlogic_counts;
|
||||
int max_arity = 0;
|
||||
|
||||
for (auto lut_arity : luts_arity)
|
||||
{
|
||||
max_arity = max(max_arity, lut_arity.second);
|
||||
arity_counts[lut_arity.second]++;
|
||||
}
|
||||
|
||||
for (auto &lut_dlogics : luts_dlogics)
|
||||
{
|
||||
for (auto &lut_dlogic : lut_dlogics.second)
|
||||
{
|
||||
dlogic_counts[lut_dlogic->type]++;
|
||||
}
|
||||
}
|
||||
|
||||
log("Number of LUTs: %8zu\n", luts.size());
|
||||
for (int arity = 1; arity <= max_arity; arity++)
|
||||
{
|
||||
if (arity_counts[arity])
|
||||
log(" %d-LUT %16d\n", arity, arity_counts[arity]);
|
||||
}
|
||||
for (auto &dlogic_count : dlogic_counts)
|
||||
{
|
||||
log(" with %-12s %4d\n", dlogic_count.first.c_str(), dlogic_count.second);
|
||||
}
|
||||
}
|
||||
|
||||
OptLutWorker(dict<IdString, dict<int, IdString>> &dlogic, RTLIL::Module *module, int limit) :
|
||||
dlogic(dlogic), module(module), index(module), sigmap(module)
|
||||
{
|
||||
log("Discovering LUTs.\n");
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type == "$lut")
|
||||
{
|
||||
int lut_width = cell->getParam("\\WIDTH").as_int();
|
||||
SigSpec lut_input = cell->getPort("\\A");
|
||||
int lut_arity = 0;
|
||||
|
||||
log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
|
||||
luts.insert(cell);
|
||||
|
||||
// First, find all dedicated logic we're connected to. This results in an overapproximation
|
||||
// of such connections.
|
||||
pool<RTLIL::Cell*> lut_all_dlogics;
|
||||
for (int i = 0; i < lut_width; i++)
|
||||
{
|
||||
SigBit bit = lut_input[i];
|
||||
for (auto &port : index.query_ports(bit))
|
||||
{
|
||||
if (dlogic.count(port.cell->type))
|
||||
{
|
||||
auto &dlogic_map = dlogic[port.cell->type];
|
||||
if (dlogic_map.count(i))
|
||||
{
|
||||
if (port.port == dlogic_map[i])
|
||||
{
|
||||
lut_all_dlogics.insert(port.cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second, make sure that the connection to dedicated logic is legal. If it is not legal,
|
||||
// it means one of the two things:
|
||||
// * The connection is spurious. I.e. this is dedicated logic that will be packed
|
||||
// with some other LUT, and it just happens to be conected to this LUT as well.
|
||||
// * The connection is illegal.
|
||||
// In either of these cases, we don't need to concern ourselves with preserving the connection
|
||||
// between this LUT and this dedicated logic cell.
|
||||
pool<RTLIL::Cell*> lut_legal_dlogics;
|
||||
pool<int> lut_dlogic_inputs;
|
||||
for (auto lut_dlogic : lut_all_dlogics)
|
||||
{
|
||||
auto &dlogic_map = dlogic[lut_dlogic->type];
|
||||
bool legal = true;
|
||||
for (auto &dlogic_conn : dlogic_map)
|
||||
{
|
||||
if (lut_width <= dlogic_conn.first)
|
||||
{
|
||||
log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
|
||||
log(" LUT input A[%d] not present.\n", dlogic_conn.first);
|
||||
legal = false;
|
||||
break;
|
||||
}
|
||||
if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second)))
|
||||
{
|
||||
log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
|
||||
log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second)));
|
||||
legal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (legal)
|
||||
{
|
||||
log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
|
||||
lut_legal_dlogics.insert(lut_dlogic);
|
||||
for (auto &dlogic_conn : dlogic_map)
|
||||
lut_dlogic_inputs.insert(dlogic_conn.first);
|
||||
}
|
||||
}
|
||||
|
||||
// Third, determine LUT arity. An n-wide LUT that has k constant inputs and m inputs shared with dedicated
|
||||
// logic implements an (n-k-m)-ary function.
|
||||
for (int i = 0; i < lut_width; i++)
|
||||
{
|
||||
SigBit bit = lut_input[i];
|
||||
if (bit.wire || lut_dlogic_inputs.count(i))
|
||||
lut_arity++;
|
||||
}
|
||||
|
||||
log(" Cell implements a %d-LUT.\n", lut_arity);
|
||||
luts_arity[cell] = lut_arity;
|
||||
luts_dlogics[cell] = lut_legal_dlogics;
|
||||
luts_dlogic_inputs[cell] = lut_dlogic_inputs;
|
||||
}
|
||||
}
|
||||
show_stats_by_arity();
|
||||
|
||||
log("\n");
|
||||
log("Combining LUTs.\n");
|
||||
pool<RTLIL::Cell*> worklist = luts;
|
||||
while (worklist.size())
|
||||
{
|
||||
if (limit == 0)
|
||||
{
|
||||
log("Limit reached.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
auto lutA = worklist.pop();
|
||||
SigSpec lutA_input = sigmap(lutA->getPort("\\A"));
|
||||
SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]);
|
||||
int lutA_width = lutA->getParam("\\WIDTH").as_int();
|
||||
int lutA_arity = luts_arity[lutA];
|
||||
pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
|
||||
|
||||
auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y"));
|
||||
if (lutA_output_ports.size() != 2)
|
||||
continue;
|
||||
|
||||
for (auto &port : lutA_output_ports)
|
||||
{
|
||||
if (port.cell == lutA)
|
||||
continue;
|
||||
|
||||
if (luts.count(port.cell))
|
||||
{
|
||||
auto lutB = port.cell;
|
||||
SigSpec lutB_input = sigmap(lutB->getPort("\\A"));
|
||||
SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]);
|
||||
int lutB_width = lutB->getParam("\\WIDTH").as_int();
|
||||
int lutB_arity = luts_arity[lutB];
|
||||
pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
|
||||
|
||||
log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
|
||||
|
||||
if (index.query_is_output(lutA->getPort("\\Y")))
|
||||
{
|
||||
log(" Not combining LUTs (cascade connection feeds module output).\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
pool<SigBit> lutA_inputs;
|
||||
pool<SigBit> lutB_inputs;
|
||||
for (auto &bit : lutA_input)
|
||||
{
|
||||
if (bit.wire)
|
||||
lutA_inputs.insert(sigmap(bit));
|
||||
}
|
||||
for (auto &bit : lutB_input)
|
||||
{
|
||||
if (bit.wire)
|
||||
lutB_inputs.insert(sigmap(bit));
|
||||
}
|
||||
|
||||
pool<SigBit> common_inputs;
|
||||
for (auto &bit : lutA_inputs)
|
||||
{
|
||||
if (lutB_inputs.count(bit))
|
||||
common_inputs.insert(bit);
|
||||
}
|
||||
|
||||
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
|
||||
if (lutA_dlogic_inputs.size())
|
||||
log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
|
||||
else
|
||||
log(" Cell A is a %d-LUT. ", lutA_arity);
|
||||
if (lutB_dlogic_inputs.size())
|
||||
log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
|
||||
else
|
||||
log("Cell B is a %d-LUT.\n", lutB_arity);
|
||||
log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
|
||||
|
||||
const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
|
||||
int combine_mask = 0;
|
||||
if (lutM_arity > lutA_width)
|
||||
{
|
||||
log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n");
|
||||
}
|
||||
else if (lutB_dlogic_inputs.size() > 0)
|
||||
{
|
||||
log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
|
||||
}
|
||||
else if (lutB->get_bool_attribute("\\lut_keep"))
|
||||
{
|
||||
log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
combine_mask |= COMBINE_A;
|
||||
}
|
||||
if (lutM_arity > lutB_width)
|
||||
{
|
||||
log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n");
|
||||
}
|
||||
else if (lutA_dlogic_inputs.size() > 0)
|
||||
{
|
||||
log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
|
||||
}
|
||||
else if (lutA->get_bool_attribute("\\lut_keep"))
|
||||
{
|
||||
log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
combine_mask |= COMBINE_B;
|
||||
}
|
||||
|
||||
int combine = combine_mask;
|
||||
if (combine == COMBINE_EITHER)
|
||||
{
|
||||
log(" Can combine into either cell.\n");
|
||||
if (lutA_arity == 1)
|
||||
{
|
||||
log(" Cell A is a buffer or inverter, combining into cell B.\n");
|
||||
combine = COMBINE_B;
|
||||
}
|
||||
else if (lutB_arity == 1)
|
||||
{
|
||||
log(" Cell B is a buffer or inverter, combining into cell A.\n");
|
||||
combine = COMBINE_A;
|
||||
}
|
||||
else
|
||||
{
|
||||
log(" Arbitrarily combining into cell A.\n");
|
||||
combine = COMBINE_A;
|
||||
}
|
||||
}
|
||||
|
||||
RTLIL::Cell *lutM, *lutR;
|
||||
pool<SigBit> lutM_inputs, lutR_inputs;
|
||||
pool<int> lutM_dlogic_inputs;
|
||||
if (combine == COMBINE_A)
|
||||
{
|
||||
log(" Combining LUTs into cell A.\n");
|
||||
lutM = lutA;
|
||||
lutM_inputs = lutA_inputs;
|
||||
lutM_dlogic_inputs = lutA_dlogic_inputs;
|
||||
lutR = lutB;
|
||||
lutR_inputs = lutB_inputs;
|
||||
}
|
||||
else if (combine == COMBINE_B)
|
||||
{
|
||||
log(" Combining LUTs into cell B.\n");
|
||||
lutM = lutB;
|
||||
lutM_inputs = lutB_inputs;
|
||||
lutM_dlogic_inputs = lutB_dlogic_inputs;
|
||||
lutR = lutA;
|
||||
lutR_inputs = lutA_inputs;
|
||||
}
|
||||
else
|
||||
{
|
||||
log(" Cannot combine LUTs.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
pool<SigBit> lutR_unique;
|
||||
for (auto &bit : lutR_inputs)
|
||||
{
|
||||
if (!common_inputs.count(bit) && bit != lutA_output)
|
||||
lutR_unique.insert(bit);
|
||||
}
|
||||
|
||||
int lutM_width = lutM->getParam("\\WIDTH").as_int();
|
||||
SigSpec lutM_input = sigmap(lutM->getPort("\\A"));
|
||||
std::vector<SigBit> lutM_new_inputs;
|
||||
for (int i = 0; i < lutM_width; i++)
|
||||
{
|
||||
bool input_unused = false;
|
||||
if (sigmap(lutM_input[i]) == lutA_output)
|
||||
input_unused = true;
|
||||
if (!lutM_input[i].wire && !lutM_dlogic_inputs.count(i))
|
||||
input_unused = true;
|
||||
|
||||
if (input_unused && lutR_unique.size())
|
||||
{
|
||||
SigBit new_input = lutR_unique.pop();
|
||||
log(" Connecting input %d as %s.\n", i, log_signal(new_input));
|
||||
lutM_new_inputs.push_back(new_input);
|
||||
}
|
||||
else if (sigmap(lutM_input[i]) == lutA_output)
|
||||
{
|
||||
log(" Disconnecting cascade input %d.\n", i);
|
||||
lutM_new_inputs.push_back(SigBit());
|
||||
}
|
||||
else
|
||||
{
|
||||
log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i]));
|
||||
lutM_new_inputs.push_back(lutM_input[i]);
|
||||
}
|
||||
}
|
||||
log_assert(lutR_unique.size() == 0);
|
||||
|
||||
RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width);
|
||||
for (int eval = 0; eval < 1 << lutM_width; eval++)
|
||||
{
|
||||
dict<SigBit, bool> eval_inputs;
|
||||
for (size_t i = 0; i < lutM_new_inputs.size(); i++)
|
||||
{
|
||||
eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1;
|
||||
}
|
||||
eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs);
|
||||
lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
|
||||
}
|
||||
|
||||
log(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
|
||||
log(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
|
||||
log(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
|
||||
|
||||
lutM->setParam("\\LUT", lutM_new_table);
|
||||
lutM->setPort("\\A", lutM_new_inputs);
|
||||
lutM->setPort("\\Y", lutB_output);
|
||||
|
||||
luts_arity[lutM] = lutM_arity;
|
||||
luts.erase(lutR);
|
||||
luts_arity.erase(lutR);
|
||||
lutR->module->remove(lutR);
|
||||
|
||||
worklist.insert(lutM);
|
||||
worklist.erase(lutR);
|
||||
|
||||
combined_count++;
|
||||
if (limit > 0)
|
||||
limit--;
|
||||
}
|
||||
}
|
||||
}
|
||||
show_stats_by_arity();
|
||||
}
|
||||
};
|
||||
|
||||
static void split(std::vector<std::string> &tokens, const std::string &text, char sep)
|
||||
{
|
||||
size_t start = 0, end = 0;
|
||||
while ((end = text.find(sep, start)) != std::string::npos) {
|
||||
tokens.push_back(text.substr(start, end - start));
|
||||
start = end + 1;
|
||||
}
|
||||
tokens.push_back(text.substr(start));
|
||||
}
|
||||
|
||||
struct OptLutPass : public Pass {
|
||||
OptLutPass() : Pass("opt_lut", "optimize LUT cells") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" opt_lut [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This pass combines cascaded $lut cells with unused inputs.\n");
|
||||
log("\n");
|
||||
log(" -dlogic <type>:<cell-port>=<LUT-input>[:<cell-port>=<LUT-input>...]\n");
|
||||
log(" preserve connections to dedicated logic cell <type> that has ports\n");
|
||||
log(" <cell-port> connected to LUT inputs <LUT-input>. this includes\n");
|
||||
log(" the case where both LUT and dedicated logic input are connected to\n");
|
||||
log(" the same constant.\n");
|
||||
log("\n");
|
||||
log(" -limit N\n");
|
||||
log(" only perform the first N combines, then stop. useful for debugging.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n");
|
||||
|
||||
dict<IdString, dict<int, IdString>> dlogic;
|
||||
int limit = -1;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
if (args[argidx] == "-dlogic" && argidx+1 < args.size())
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
split(tokens, args[++argidx], ':');
|
||||
if (tokens.size() < 2)
|
||||
log_cmd_error("The -dlogic option requires at least one connection.\n");
|
||||
IdString type = "\\" + tokens[0];
|
||||
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) {
|
||||
std::vector<std::string> conn_tokens;
|
||||
split(conn_tokens, *it, '=');
|
||||
if (conn_tokens.size() != 2)
|
||||
log_cmd_error("Invalid format of -dlogic signal mapping.\n");
|
||||
IdString logic_port = "\\" + conn_tokens[0];
|
||||
int lut_input = atoi(conn_tokens[1].c_str());
|
||||
dlogic[type][lut_input] = logic_port;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-limit" && argidx + 1 < args.size())
|
||||
{
|
||||
limit = atoi(args[++argidx].c_str());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
int total_count = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
OptLutWorker worker(dlogic, module, limit - total_count);
|
||||
total_count += worker.combined_count;
|
||||
}
|
||||
if (total_count)
|
||||
design->scratchpad_set_bool("opt.did_something", true);
|
||||
log("\n");
|
||||
log("Combined %d LUTs.\n", total_count);
|
||||
}
|
||||
} OptLutPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -36,6 +36,7 @@ struct OptMuxtreeWorker
|
|||
RTLIL::Module *module;
|
||||
SigMap assign_map;
|
||||
int removed_count;
|
||||
int glob_abort_cnt = 100000;
|
||||
|
||||
struct bitinfo_t {
|
||||
bool seen_non_mux;
|
||||
|
@ -293,6 +294,9 @@ struct OptMuxtreeWorker
|
|||
|
||||
void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx, bool do_replace_known, bool do_enable_ports, int abort_count)
|
||||
{
|
||||
if (glob_abort_cnt == 0)
|
||||
return;
|
||||
|
||||
muxinfo_t &muxinfo = mux2info[mux_idx];
|
||||
|
||||
if (do_enable_ports)
|
||||
|
@ -315,7 +319,7 @@ struct OptMuxtreeWorker
|
|||
knowledge.visited_muxes[m] = true;
|
||||
parent_muxes.push_back(m);
|
||||
}
|
||||
for (int m : parent_muxes)
|
||||
for (int m : parent_muxes) {
|
||||
if (root_enable_muxes.at(m))
|
||||
continue;
|
||||
else if (root_muxes.at(m)) {
|
||||
|
@ -327,6 +331,9 @@ struct OptMuxtreeWorker
|
|||
eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1);
|
||||
} else
|
||||
eval_mux(knowledge, m, do_replace_known, do_enable_ports, abort_count);
|
||||
if (glob_abort_cnt == 0)
|
||||
return;
|
||||
}
|
||||
for (int m : parent_muxes)
|
||||
knowledge.visited_muxes[m] = false;
|
||||
|
||||
|
@ -390,6 +397,12 @@ struct OptMuxtreeWorker
|
|||
|
||||
void eval_mux(knowledge_t &knowledge, int mux_idx, bool do_replace_known, bool do_enable_ports, int abort_count)
|
||||
{
|
||||
if (glob_abort_cnt == 0) {
|
||||
log(" Giving up (too many iterations)\n");
|
||||
return;
|
||||
}
|
||||
glob_abort_cnt--;
|
||||
|
||||
muxinfo_t &muxinfo = mux2info[mux_idx];
|
||||
|
||||
// set input ports to constants if we find known active or inactive signals
|
||||
|
@ -433,6 +446,9 @@ struct OptMuxtreeWorker
|
|||
if (knowledge.known_inactive.at(portinfo.ctrl_sig))
|
||||
continue;
|
||||
eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports, abort_count);
|
||||
|
||||
if (glob_abort_cnt == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,9 +83,9 @@ struct DeminoutPass : public Pass {
|
|||
for (auto bit : sigmap(conn.second))
|
||||
bits_used.insert(bit);
|
||||
|
||||
if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
|
||||
if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_", "$tribuf"))
|
||||
{
|
||||
bool tribuf = (cell->type == "$_TBUF_");
|
||||
bool tribuf = (cell->type == "$_TBUF_" || cell->type == "$tribuf");
|
||||
|
||||
if (!tribuf) {
|
||||
for (auto &c : cell->connections()) {
|
||||
|
@ -113,7 +113,8 @@ struct DeminoutPass : public Pass {
|
|||
{
|
||||
if (bits_numports[bit] > 1 || bits_inout.count(bit))
|
||||
new_input = true, new_output = true;
|
||||
|
||||
if (bit == State::S0 || bit == State::S1)
|
||||
new_output = true;
|
||||
if (bits_written.count(bit)) {
|
||||
new_output = true;
|
||||
if (bits_tribuf.count(bit))
|
||||
|
|
|
@ -267,6 +267,10 @@ struct Dff2dffePass : public Pass {
|
|||
log(" operate in the opposite direction: replace $dffe cells with combinations\n");
|
||||
log(" of $dff and $mux cells. the options below are ignore in unmap mode.\n");
|
||||
log("\n");
|
||||
log(" -unmap-mince N\n");
|
||||
log(" Same as -unmap but only unmap $dffe where the clock enable port\n");
|
||||
log(" signal is used by less $dffe than the specified number\n");
|
||||
log("\n");
|
||||
log(" -direct <internal_gate_type> <external_gate_type>\n");
|
||||
log(" map directly to external gate type. <internal_gate_type> can\n");
|
||||
log(" be any internal gate-level FF cell (except $_DFFE_??_). the\n");
|
||||
|
@ -289,6 +293,7 @@ struct Dff2dffePass : public Pass {
|
|||
log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
|
||||
|
||||
bool unmap_mode = false;
|
||||
int min_ce_use = -1;
|
||||
dict<IdString, IdString> direct_dict;
|
||||
|
||||
size_t argidx;
|
||||
|
@ -297,6 +302,11 @@ struct Dff2dffePass : public Pass {
|
|||
unmap_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-unmap-mince" && argidx + 1 < args.size()) {
|
||||
unmap_mode = true;
|
||||
min_ce_use = std::stoi(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
|
||||
string direct_from = RTLIL::escape_id(args[++argidx]);
|
||||
string direct_to = RTLIL::escape_id(args[++argidx]);
|
||||
|
@ -343,8 +353,21 @@ struct Dff2dffePass : public Pass {
|
|||
if (!mod->has_processes_warn())
|
||||
{
|
||||
if (unmap_mode) {
|
||||
SigMap sigmap(mod);
|
||||
for (auto cell : mod->selected_cells()) {
|
||||
if (cell->type == "$dffe") {
|
||||
if (min_ce_use >= 0) {
|
||||
int ce_use = 0;
|
||||
for (auto cell_other : mod->selected_cells()) {
|
||||
if (cell_other->type != cell->type)
|
||||
continue;
|
||||
if (sigmap(cell->getPort("\\EN")) == sigmap(cell_other->getPort("\\EN")))
|
||||
ce_use++;
|
||||
}
|
||||
if (ce_use >= min_ce_use)
|
||||
continue;
|
||||
}
|
||||
|
||||
RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D")));
|
||||
mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool());
|
||||
if (cell->getParam("\\EN_POLARITY").as_bool())
|
||||
|
@ -355,6 +378,18 @@ struct Dff2dffePass : public Pass {
|
|||
continue;
|
||||
}
|
||||
if (cell->type.substr(0, 7) == "$_DFFE_") {
|
||||
if (min_ce_use >= 0) {
|
||||
int ce_use = 0;
|
||||
for (auto cell_other : mod->selected_cells()) {
|
||||
if (cell_other->type != cell->type)
|
||||
continue;
|
||||
if (sigmap(cell->getPort("\\E")) == sigmap(cell_other->getPort("\\E")))
|
||||
ce_use++;
|
||||
}
|
||||
if (ce_use >= min_ce_use)
|
||||
continue;
|
||||
}
|
||||
|
||||
bool clk_pol = cell->type.substr(7, 1) == "P";
|
||||
bool en_pol = cell->type.substr(8, 1) == "P";
|
||||
RTLIL::SigSpec tmp = mod->addWire(NEW_ID);
|
||||
|
|
|
@ -100,6 +100,18 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
|
|||
for (auto child : cell->children)
|
||||
if (child->id == "pin" && child->args.size() == 1 && child->args[0] == pin_name)
|
||||
return true;
|
||||
|
||||
/* If we end up here, the pin specified in the attribute does not exist, which is an error,
|
||||
or, the attribute contains an expression which we do not yet support.
|
||||
For now, we'll simply produce a warning to let the user know something is up.
|
||||
*/
|
||||
if (pin_name.find_first_of("^*|&") == std::string::npos) {
|
||||
log_warning("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str());
|
||||
}
|
||||
else {
|
||||
log_warning("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,11 +90,11 @@ int LibertyParser::lexer(std::string &str)
|
|||
c = f.get();
|
||||
} while (c == ' ' || c == '\t' || c == '\r');
|
||||
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') {
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']') {
|
||||
str = c;
|
||||
while (1) {
|
||||
c = f.get();
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.')
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']')
|
||||
str += c;
|
||||
else
|
||||
break;
|
||||
|
@ -159,7 +159,7 @@ int LibertyParser::lexer(std::string &str)
|
|||
|
||||
if (c == '\n') {
|
||||
line++;
|
||||
return ';';
|
||||
return 'n';
|
||||
}
|
||||
|
||||
// if (c >= 32 && c < 255)
|
||||
|
@ -175,7 +175,7 @@ LibertyAst *LibertyParser::parse()
|
|||
|
||||
int tok = lexer(str);
|
||||
|
||||
while (tok == ';')
|
||||
while (tok == 'n')
|
||||
tok = lexer(str);
|
||||
|
||||
if (tok == '}' || tok < 0)
|
||||
|
@ -194,6 +194,9 @@ LibertyAst *LibertyParser::parse()
|
|||
if (tok == ';')
|
||||
break;
|
||||
|
||||
if (tok == 'n')
|
||||
continue;
|
||||
|
||||
if (tok == ':' && ast->value.empty()) {
|
||||
tok = lexer(ast->value);
|
||||
if (tok != 'v')
|
||||
|
@ -249,14 +252,14 @@ LibertyAst *LibertyParser::parse()
|
|||
|
||||
void LibertyParser::error()
|
||||
{
|
||||
log_error("Syntax error in line %d.\n", line);
|
||||
log_error("Syntax error in liberty file on line %d.\n", line);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void LibertyParser::error()
|
||||
{
|
||||
fprintf(stderr, "Syntax error in line %d.\n", line);
|
||||
fprintf(stderr, "Syntax error in liberty file on line %d.\n", line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ int lut2mux(Cell *cell)
|
|||
|
||||
if (GetSize(sig_a) == 1)
|
||||
{
|
||||
cell->module->addMuxGate(NEW_ID, lut[0], lut[1], sig_a, sig_y);
|
||||
cell->module->addMuxGate(NEW_ID, lut.extract(0)[0], lut.extract(1)[0], sig_a, sig_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
OBJS += techlibs/anlogic/synth_anlogic.o
|
||||
OBJS += techlibs/anlogic/anlogic_eqn.o
|
||||
|
||||
$(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/cells_sim.v))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams.txt))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams_map.v))
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2018 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
|
||||
|
||||
struct AnlogicEqnPass : public Pass {
|
||||
AnlogicEqnPass() : Pass("anlogic_eqn", "Anlogic: Calculate equations for luts") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
log("\n");
|
||||
log(" anlogic_eqn [selection]\n");
|
||||
log("\n");
|
||||
log("Calculate equations for luts since bitstream generator depends on it.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
Const init2eqn(Const init, int inputs)
|
||||
{
|
||||
std::string init_bits = init.as_string();
|
||||
const char* names[] = { "A" , "B", "C", "D", "E", "F" };
|
||||
|
||||
std::string eqn;
|
||||
int width = (int)pow(2,inputs);
|
||||
for(int i=0;i<width;i++)
|
||||
{
|
||||
if (init_bits[width-1-i]=='1')
|
||||
{
|
||||
eqn += "(";
|
||||
for(int j=0;j<inputs;j++)
|
||||
{
|
||||
if (i & (1<<j))
|
||||
eqn += names[j];
|
||||
else
|
||||
eqn += std::string("~") + names[j];
|
||||
|
||||
if (j!=(inputs-1)) eqn += "*";
|
||||
}
|
||||
eqn += ")+";
|
||||
}
|
||||
}
|
||||
if (eqn.empty()) return Const("0");
|
||||
eqn = eqn.substr(0, eqn.length()-1);
|
||||
return Const(eqn);
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing ANLOGIC_EQN pass (calculate equations for luts).\n");
|
||||
|
||||
extra_args(args, args.size(), design);
|
||||
|
||||
size_t cnt = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type == "\\AL_MAP_LUT1")
|
||||
{
|
||||
cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),1));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == "\\AL_MAP_LUT2")
|
||||
{
|
||||
cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),2));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == "\\AL_MAP_LUT3")
|
||||
{
|
||||
cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),3));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == "\\AL_MAP_LUT4")
|
||||
{
|
||||
cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),4));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == "\\AL_MAP_LUT5")
|
||||
{
|
||||
cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),5));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == "\\AL_MAP_LUT6")
|
||||
{
|
||||
cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),6));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
log_header(design, "Updated %lu of AL_MAP_LUT* elements with equation.\n", cnt);
|
||||
}
|
||||
} AnlogicEqnPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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_anlogic_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 CO;
|
||||
|
||||
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] COx;
|
||||
wire [Y_WIDTH+1:0] C = {COx, CI};
|
||||
|
||||
wire dummy;
|
||||
(* keep *)
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD_CARRY"))
|
||||
adder_cin (
|
||||
.a(C[0]),
|
||||
.o({COx[0], dummy})
|
||||
);
|
||||
|
||||
genvar i;
|
||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
|
||||
if(i==Y_WIDTH-1) begin
|
||||
(* keep *)
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD"))
|
||||
adder_cout (
|
||||
.c(C[Y_WIDTH]),
|
||||
.o(COx[Y_WIDTH])
|
||||
);
|
||||
assign CO = COx[Y_WIDTH];
|
||||
end
|
||||
else
|
||||
begin
|
||||
(* keep *)
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD")
|
||||
) adder_i (
|
||||
.a(AA[i]),
|
||||
.b(BB[i]),
|
||||
.c(C[i+1]),
|
||||
.o({COx[i+1],Y[i]})
|
||||
);
|
||||
end
|
||||
end: slice
|
||||
endgenerate
|
||||
/* End implementation */
|
||||
assign X = AA ^ BB;
|
||||
endmodule
|
|
@ -0,0 +1,49 @@
|
|||
module \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule
|
||||
module \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(1'b0)); endmodule
|
||||
|
||||
module \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
|
||||
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); 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
|
||||
AL_MAP_LUT1 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]));
|
||||
end else
|
||||
if (WIDTH == 2) begin
|
||||
AL_MAP_LUT2 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]));
|
||||
end else
|
||||
if (WIDTH == 3) begin
|
||||
AL_MAP_LUT3 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]));
|
||||
end else
|
||||
if (WIDTH == 4) begin
|
||||
AL_MAP_LUT4 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]), .d(A[3]));
|
||||
end else
|
||||
if (WIDTH == 5) begin
|
||||
AL_MAP_LUT5 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]), .d(A[3]), .e(A[4]));
|
||||
end else
|
||||
if (WIDTH == 6) begin
|
||||
AL_MAP_LUT6 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]), .d(A[3]), .e(A[4]), .f(A[5]));
|
||||
end else begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
`endif
|
|
@ -0,0 +1,103 @@
|
|||
module AL_MAP_SEQ (
|
||||
output q,
|
||||
input ce,
|
||||
input clk,
|
||||
input sr,
|
||||
input d
|
||||
);
|
||||
parameter DFFMODE = "FF"; //FF,LATCH
|
||||
parameter REGSET = "RESET"; //RESET/SET
|
||||
parameter SRMUX = "SR"; //SR/INV
|
||||
parameter SRMODE = "SYNC"; //SYNC/ASYNC
|
||||
endmodule
|
||||
|
||||
module AL_MAP_LUT1 (
|
||||
output o,
|
||||
input a
|
||||
);
|
||||
parameter [1:0] INIT = 2'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign Y = INIT >> A;
|
||||
endmodule
|
||||
|
||||
module AL_MAP_LUT2 (
|
||||
output o,
|
||||
input a,
|
||||
input b
|
||||
);
|
||||
parameter [3:0] INIT = 4'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign o = INIT >> {b, a};
|
||||
endmodule
|
||||
|
||||
module AL_MAP_LUT3 (
|
||||
output o,
|
||||
input a,
|
||||
input b,
|
||||
input c
|
||||
);
|
||||
parameter [7:0] INIT = 8'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign o = INIT >> {c, b, a};
|
||||
endmodule
|
||||
|
||||
module AL_MAP_LUT4 (
|
||||
output o,
|
||||
input a,
|
||||
input b,
|
||||
input c,
|
||||
input d
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign o = INIT >> {d, c, b, a};
|
||||
endmodule
|
||||
|
||||
module AL_MAP_LUT5 (
|
||||
output o,
|
||||
input a,
|
||||
input b,
|
||||
input c,
|
||||
input d,
|
||||
input e
|
||||
);
|
||||
parameter [31:0] INIT = 32'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign o = INIT >> {e, d, c, b, a};
|
||||
endmodule
|
||||
|
||||
|
||||
module AL_MAP_LUT6 (
|
||||
output o,
|
||||
input a,
|
||||
input b,
|
||||
input c,
|
||||
input d,
|
||||
input e,
|
||||
input f
|
||||
);
|
||||
parameter [63:0] INIT = 64'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign o = INIT >> {f, e, d, c, b, a};
|
||||
endmodule
|
||||
|
||||
module AL_MAP_ALU2B (
|
||||
input cin,
|
||||
input a0, b0, c0, d0,
|
||||
input a1, b1, c1, d1,
|
||||
output s0, s1, cout
|
||||
);
|
||||
parameter [15:0] INIT0 = 16'h0000;
|
||||
parameter [15:0] INIT1 = 16'h0000;
|
||||
parameter FUNC0 = "NO";
|
||||
parameter FUNC1 = "NO";
|
||||
endmodule
|
||||
|
||||
module AL_MAP_ADDER (
|
||||
input a,
|
||||
input b,
|
||||
input c,
|
||||
output [1:0] o
|
||||
);
|
||||
parameter ALUTYPE = "ADD";
|
||||
endmodule
|
|
@ -0,0 +1,16 @@
|
|||
bram $__ANLOGIC_DRAM16X4
|
||||
init 0
|
||||
abits 4
|
||||
dbits 2
|
||||
groups 2
|
||||
ports 1 1
|
||||
wrmode 0 1
|
||||
enable 0 1
|
||||
transp 0 0
|
||||
clocks 0 1
|
||||
clkpol 0 1
|
||||
endbram
|
||||
|
||||
match $__ANLOGIC_DRAM16X4
|
||||
make_outreg
|
||||
endmatch
|
|
@ -0,0 +1,19 @@
|
|||
module \$__ANLOGIC_DRAM16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||
input CLK1;
|
||||
|
||||
input [3:0] A1ADDR;
|
||||
output [3:0] A1DATA;
|
||||
|
||||
input [3:0] B1ADDR;
|
||||
input [3:0] B1DATA;
|
||||
input B1EN;
|
||||
|
||||
EG_LOGIC_DRAM16X4 _TECHMAP_REPLACE_ (
|
||||
.di(B1DATA),
|
||||
.waddr(B1ADDR),
|
||||
.wclk(CLK1),
|
||||
.we(B1EN),
|
||||
.raddr(A1ADDR),
|
||||
.do(A1DATA)
|
||||
);
|
||||
endmodule
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||
* Copyright (C) 2018 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 SynthAnlogicPass : public ScriptPass
|
||||
{
|
||||
SynthAnlogicPass() : ScriptPass("synth_anlogic", "synthesis for Anlogic FPGAs") { }
|
||||
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" synth_anlogic [options]\n");
|
||||
log("\n");
|
||||
log("This command runs synthesis for Anlogic 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 comannd only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_ANLOGIC 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 +/anlogic/cells_sim.v +/anlogic/eagle_bb.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("dram"))
|
||||
{
|
||||
run("memory_bram -rules +/anlogic/drams.txt");
|
||||
run("techmap -map +/anlogic/drams_map.v");
|
||||
}
|
||||
|
||||
if (check_label("fine"))
|
||||
{
|
||||
run("opt -fast -mux_undef -undriven -fine");
|
||||
run("memory_map");
|
||||
run("opt -undriven -fine");
|
||||
run("techmap -map +/techmap.v -map +/anlogic/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 +/anlogic/cells_map.v");
|
||||
run("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
}
|
||||
|
||||
if (check_label("map_luts"))
|
||||
{
|
||||
run("abc -lut 6");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label("map_cells"))
|
||||
{
|
||||
run("techmap -map +/anlogic/cells_map.v");
|
||||
run("clean");
|
||||
run("anlogic_eqn");
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
} SynthAnlogicPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -25,5 +25,6 @@ $(eval $(call add_share_file,share,techlibs/common/techmap.v))
|
|||
$(eval $(call add_share_file,share,techlibs/common/pmux2mux.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/adff2dff.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/dff2ff.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/gate2lut.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/cells.lib))
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
(* techmap_celltype = "$_NOT_" *)
|
||||
module _90_lut_not (A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
|
||||
wire [`LUT_WIDTH-1:0] AA;
|
||||
assign AA = {A};
|
||||
|
||||
\$lut #(
|
||||
.WIDTH(`LUT_WIDTH),
|
||||
.LUT(4'b01)
|
||||
) lut (
|
||||
.A(AA),
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* techmap_celltype = "$_OR_" *)
|
||||
module _90_lut_or (A, B, Y);
|
||||
input A, B;
|
||||
output Y;
|
||||
|
||||
wire [`LUT_WIDTH-1:0] AA;
|
||||
assign AA = {B, A};
|
||||
|
||||
\$lut #(
|
||||
.WIDTH(`LUT_WIDTH),
|
||||
.LUT(4'b1110)
|
||||
) lut (
|
||||
.A(AA),
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* techmap_celltype = "$_AND_" *)
|
||||
module _90_lut_and (A, B, Y);
|
||||
input A, B;
|
||||
output Y;
|
||||
|
||||
wire [`LUT_WIDTH-1:0] AA;
|
||||
assign AA = {B, A};
|
||||
|
||||
\$lut #(
|
||||
.WIDTH(`LUT_WIDTH),
|
||||
.LUT(4'b1000)
|
||||
) lut (
|
||||
.A(AA),
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* techmap_celltype = "$_XOR_" *)
|
||||
module _90_lut_xor (A, B, Y);
|
||||
input A, B;
|
||||
output Y;
|
||||
|
||||
wire [`LUT_WIDTH-1:0] AA;
|
||||
assign AA = {B, A};
|
||||
|
||||
\$lut #(
|
||||
.WIDTH(`LUT_WIDTH),
|
||||
.LUT(4'b0110)
|
||||
) lut (
|
||||
.A(AA),
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* techmap_celltype = "$_MUX_" *)
|
||||
module _90_lut_mux (A, B, S, Y);
|
||||
input A, B, S;
|
||||
output Y;
|
||||
|
||||
wire [`LUT_WIDTH-1:0] AA;
|
||||
assign AA = {S, B, A};
|
||||
|
||||
\$lut #(
|
||||
.WIDTH(`LUT_WIDTH),
|
||||
// A 1010 1010
|
||||
// B 1100 1100
|
||||
// S 1111 0000
|
||||
.LUT(8'b_1100_1010)
|
||||
) lut (
|
||||
.A(AA),
|
||||
.Y(Y)
|
||||
);
|
||||
endmodule
|
|
@ -465,7 +465,7 @@ endmodule
|
|||
//-
|
||||
//- $_SR_NP_ (S, R, Q)
|
||||
//-
|
||||
//- A set-reset latch with negative polarity SET and positive polarioty RESET.
|
||||
//- A set-reset latch with negative polarity SET and positive polarity RESET.
|
||||
//-
|
||||
//- Truth table: S R | Q
|
||||
//- -----+---
|
||||
|
@ -489,7 +489,7 @@ endmodule
|
|||
//-
|
||||
//- $_SR_PN_ (S, R, Q)
|
||||
//-
|
||||
//- A set-reset latch with positive polarity SET and negative polarioty RESET.
|
||||
//- A set-reset latch with positive polarity SET and negative polarity RESET.
|
||||
//-
|
||||
//- Truth table: S R | Q
|
||||
//- -----+---
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
bram_init_1_2_4.vh
|
||||
bram_init_9_18_36.vh
|
||||
brams_init.mk
|
||||
bram_conn_1.vh
|
||||
bram_conn_2.vh
|
||||
bram_conn_4.vh
|
||||
bram_conn_9.vh
|
||||
bram_conn_18.vh
|
||||
brams_connect.mk
|
|
@ -3,6 +3,42 @@ OBJS += techlibs/ecp5/synth_ecp5.o
|
|||
|
||||
$(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_bb.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v))
|
||||
|
||||
EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
|
||||
.SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
|
||||
|
||||
techlibs/ecp5/brams_init.mk: techlibs/ecp5/brams_init.py
|
||||
$(Q) mkdir -p techlibs/ecp5
|
||||
$(P) python3 $<
|
||||
$(Q) touch $@
|
||||
|
||||
techlibs/ecp5/brams_connect.mk: techlibs/ecp5/brams_connect.py
|
||||
$(Q) mkdir -p techlibs/ecp5
|
||||
$(P) python3 $<
|
||||
$(Q) touch $@
|
||||
|
||||
|
||||
techlibs/ecp5/bram_init_1_2_4.vh: techlibs/ecp5/brams_init.mk
|
||||
techlibs/ecp5/bram_init_9_18_36.vh: techlibs/ecp5/brams_init.mk
|
||||
|
||||
techlibs/ecp5/bram_conn_1.vh: techlibs/ecp5/brams_connect.mk
|
||||
techlibs/ecp5/bram_conn_2.vh: techlibs/ecp5/brams_connect.mk
|
||||
techlibs/ecp5/bram_conn_4.vh: techlibs/ecp5/brams_connect.mk
|
||||
techlibs/ecp5/bram_conn_9.vh: techlibs/ecp5/brams_connect.mk
|
||||
techlibs/ecp5/bram_conn_18.vh: techlibs/ecp5/brams_connect.mk
|
||||
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_1_2_4.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_9_18_36.vh))
|
||||
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_1.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_2.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_4.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_9.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_18.vh))
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
bram $__ECP5_DP16KD
|
||||
init 1
|
||||
|
||||
abits 10 @a10d18
|
||||
dbits 18 @a10d18
|
||||
abits 11 @a11d9
|
||||
dbits 9 @a11d9
|
||||
abits 12 @a12d4
|
||||
dbits 4 @a12d4
|
||||
abits 13 @a13d2
|
||||
dbits 2 @a13d2
|
||||
abits 14 @a14d1
|
||||
dbits 1 @a14d1
|
||||
|
||||
groups 2
|
||||
ports 1 1
|
||||
wrmode 1 0
|
||||
enable 2 1 @a10d18
|
||||
enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
|
||||
transp 0 2
|
||||
clocks 2 3
|
||||
clkpol 2 3
|
||||
endbram
|
||||
|
||||
match $__ECP5_DP16KD
|
||||
min bits 2048
|
||||
min efficiency 5
|
||||
shuffle_enable B
|
||||
endmatch
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
def write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits):
|
||||
ada_conn = [".ADA%d(%s)" % (i, ada_bits[i]) for i in range(len(ada_bits))]
|
||||
adb_conn = [".ADB%d(%s)" % (i, adb_bits[i]) for i in range(len(adb_bits))]
|
||||
dia_conn = [".DIA%d(%s)" % (i, dia_bits[i]) for i in range(len(dia_bits))]
|
||||
dob_conn = [".DOB%d(%s)" % (i, dob_bits[i]) for i in range(len(dob_bits))]
|
||||
print(" %s," % ", ".join(ada_conn), file=f)
|
||||
print(" %s," % ", ".join(adb_conn), file=f)
|
||||
print(" %s," % ", ".join(dia_conn), file=f)
|
||||
print(" %s," % ", ".join(dob_conn), file=f)
|
||||
|
||||
with open("techlibs/ecp5/bram_conn_1.vh", "w") as f:
|
||||
ada_bits = ["A1ADDR[%d]" % i for i in range(14)]
|
||||
adb_bits = ["B1ADDR[%d]" % i for i in range(14)]
|
||||
dia_bits = ["A1DATA[0]"] + ["1'b0" for i in range(17)]
|
||||
dob_bits = ["B1DATA[0]"]
|
||||
write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
|
||||
|
||||
with open("techlibs/ecp5/bram_conn_2.vh", "w") as f:
|
||||
ada_bits = ["1'b0"] + ["A1ADDR[%d]" % i for i in range(13)]
|
||||
adb_bits = ["1'b0"] + ["B1ADDR[%d]" % i for i in range(13)]
|
||||
dia_bits = ["A1DATA[%d]" % i for i in range(2)] + ["1'b0" for i in range(16)]
|
||||
dob_bits = ["B1DATA[%d]" % i for i in range(2)]
|
||||
write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
|
||||
|
||||
with open("techlibs/ecp5/bram_conn_4.vh", "w") as f:
|
||||
ada_bits = ["1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(12)]
|
||||
adb_bits = ["1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(12)]
|
||||
dia_bits = ["A1DATA[%d]" % i for i in range(4)] + ["1'b0" for i in range(14)]
|
||||
dob_bits = ["B1DATA[%d]" % i for i in range(4)]
|
||||
write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
|
||||
|
||||
with open("techlibs/ecp5/bram_conn_9.vh", "w") as f:
|
||||
ada_bits = ["1'b0", "1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(11)]
|
||||
adb_bits = ["1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(11)]
|
||||
dia_bits = ["A1DATA[%d]" % i for i in range(9)] + ["1'b0" for i in range(9)]
|
||||
dob_bits = ["B1DATA[%d]" % i for i in range(9)]
|
||||
write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
|
||||
|
||||
with open("techlibs/ecp5/bram_conn_18.vh", "w") as f:
|
||||
ada_bits = ["A1EN[0]", "A1EN[1]", "1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(10)]
|
||||
adb_bits = ["1'b0", "1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(10)]
|
||||
dia_bits = ["A1DATA[%d]" % i for i in range(18)]
|
||||
dob_bits = ["B1DATA[%d]" % i for i in range(18)]
|
||||
write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
with open("techlibs/ecp5/bram_init_1_2_4.vh", "w") as f:
|
||||
for i in range(0, 0x40):
|
||||
init_snippets = []
|
||||
for j in range(32):
|
||||
init_snippets.append("INIT[%4d*8 +: 8]" % (32 * i + j))
|
||||
init_snippets.append("3'b000" if (j % 2 == 1) else "1'b0")
|
||||
init_snippets = list(reversed(init_snippets))
|
||||
for k in range(8, 64, 8):
|
||||
init_snippets[k] = "\n " + init_snippets[k]
|
||||
print(".INITVAL_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
|
||||
|
||||
with open("techlibs/ecp5/bram_init_9_18_36.vh", "w") as f:
|
||||
for i in range(0, 0x40):
|
||||
init_snippets = []
|
||||
for j in range(16):
|
||||
init_snippets.append("INIT[%3d*18 +: 18]" % (16 * i + j))
|
||||
init_snippets.append("2'b00")
|
||||
init_snippets = list(reversed(init_snippets))
|
||||
for k in range(8, 32, 8):
|
||||
init_snippets[k] = "\n " + init_snippets[k]
|
||||
print(".INITVAL_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
|
|
@ -0,0 +1,115 @@
|
|||
module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||
parameter CFG_ABITS = 10;
|
||||
parameter CFG_DBITS = 18;
|
||||
parameter CFG_ENABLE_A = 2;
|
||||
|
||||
parameter CLKPOL2 = 1;
|
||||
parameter CLKPOL3 = 1;
|
||||
parameter [18431:0] INIT = 18432'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 CLKAMUX = CLKPOL2 ? "CLKA" : "INV";
|
||||
localparam CLKBMUX = CLKPOL3 ? "CLKB" : "INV";
|
||||
|
||||
localparam WRITEMODE_A = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE";
|
||||
|
||||
generate if (CFG_DBITS == 1) begin
|
||||
DP16KD #(
|
||||
`include "bram_init_1_2_4.vh"
|
||||
.DATA_WIDTH_A(1),
|
||||
.DATA_WIDTH_B(1),
|
||||
.CLKAMUX(CLKAMUX),
|
||||
.CLKBMUX(CLKBMUX),
|
||||
.WRITEMODE_A(WRITEMODE_A),
|
||||
.WRITEMODE_B("READBEFOREWRITE"),
|
||||
.GSR("DISABLED")
|
||||
) _TECHMAP_REPLACE_ (
|
||||
`include "bram_conn_1.vh"
|
||||
.CLKA(CLK2), .CLKB(CLK3),
|
||||
.WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
|
||||
.WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
|
||||
.RSTA(1'b0), .RSTB(1'b0)
|
||||
);
|
||||
end else if (CFG_DBITS == 2) begin
|
||||
DP16KD #(
|
||||
`include "bram_init_1_2_4.vh"
|
||||
.DATA_WIDTH_A(2),
|
||||
.DATA_WIDTH_B(2),
|
||||
.CLKAMUX(CLKAMUX),
|
||||
.CLKBMUX(CLKBMUX),
|
||||
.WRITEMODE_A(WRITEMODE_A),
|
||||
.WRITEMODE_B("READBEFOREWRITE"),
|
||||
.GSR("DISABLED")
|
||||
) _TECHMAP_REPLACE_ (
|
||||
`include "bram_conn_2.vh"
|
||||
.CLKA(CLK2), .CLKB(CLK3),
|
||||
.WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
|
||||
.WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
|
||||
.RSTA(1'b0), .RSTB(1'b0)
|
||||
);
|
||||
end else if (CFG_DBITS <= 4) begin
|
||||
DP16KD #(
|
||||
`include "bram_init_1_2_4.vh"
|
||||
.DATA_WIDTH_A(4),
|
||||
.DATA_WIDTH_B(4),
|
||||
.CLKAMUX(CLKAMUX),
|
||||
.CLKBMUX(CLKBMUX),
|
||||
.WRITEMODE_A(WRITEMODE_A),
|
||||
.WRITEMODE_B("READBEFOREWRITE"),
|
||||
.GSR("DISABLED")
|
||||
) _TECHMAP_REPLACE_ (
|
||||
`include "bram_conn_4.vh"
|
||||
.CLKA(CLK2), .CLKB(CLK3),
|
||||
.WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
|
||||
.WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
|
||||
.RSTA(1'b0), .RSTB(1'b0)
|
||||
);
|
||||
end else if (CFG_DBITS <= 9) begin
|
||||
DP16KD #(
|
||||
`include "bram_init_9_18_36.vh"
|
||||
.DATA_WIDTH_A(9),
|
||||
.DATA_WIDTH_B(9),
|
||||
.CLKAMUX(CLKAMUX),
|
||||
.CLKBMUX(CLKBMUX),
|
||||
.WRITEMODE_A(WRITEMODE_A),
|
||||
.WRITEMODE_B("READBEFOREWRITE"),
|
||||
.GSR("DISABLED")
|
||||
) _TECHMAP_REPLACE_ (
|
||||
`include "bram_conn_9.vh"
|
||||
.CLKA(CLK2), .CLKB(CLK3),
|
||||
.WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
|
||||
.WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
|
||||
.RSTA(1'b0), .RSTB(1'b0)
|
||||
);
|
||||
end else if (CFG_DBITS <= 18) begin
|
||||
DP16KD #(
|
||||
`include "bram_init_9_18_36.vh"
|
||||
.DATA_WIDTH_A(18),
|
||||
.DATA_WIDTH_B(18),
|
||||
.CLKAMUX(CLKAMUX),
|
||||
.CLKBMUX(CLKBMUX),
|
||||
.WRITEMODE_A(WRITEMODE_A),
|
||||
.WRITEMODE_B("READBEFOREWRITE"),
|
||||
.GSR("DISABLED")
|
||||
) _TECHMAP_REPLACE_ (
|
||||
`include "bram_conn_18.vh"
|
||||
.CLKA(CLK2), .CLKB(CLK3),
|
||||
.WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
|
||||
.WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
|
||||
.RSTA(1'b0), .RSTB(1'b0)
|
||||
);
|
||||
end else begin
|
||||
wire TECHMAP_FAIL = 1'b1;
|
||||
end endgenerate
|
||||
endmodule
|
|
@ -0,0 +1,514 @@
|
|||
// ECP5 Blackbox cells
|
||||
// FIXME: Create sim models
|
||||
|
||||
(* blackbox *)
|
||||
module MULT18X18D(
|
||||
input A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17,
|
||||
input B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16, B17,
|
||||
input C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17,
|
||||
input SIGNEDA, SIGNEDB, SOURCEA, SOURCEB,
|
||||
input CLK0, CLK1, CLK2, CLK3,
|
||||
input CE0, CE1, CE2, CE3,
|
||||
input RST0, RST1, RST2, RST3,
|
||||
input SRIA0, SRIA1, SRIA2, SRIA3, SRIA4, SRIA5, SRIA6, SRIA7, SRIA8, SRIA9, SRIA10, SRIA11, SRIA12, SRIA13, SRIA14, SRIA15, SRIA16, SRIA17,
|
||||
input SRIB0, SRIB1, SRIB2, SRIB3, SRIB4, SRIB5, SRIB6, SRIB7, SRIB8, SRIB9, SRIB10, SRIB11, SRIB12, SRIB13, SRIB14, SRIB15, SRIB16, SRIB17,
|
||||
output SROA0, SROA1, SROA2, SROA3, SROA4, SROA5, SROA6, SROA7, SROA8, SROA9, SROA10, SROA11, SROA12, SROA13, SROA14, SROA15, SROA16, SROA17,
|
||||
output SROB0, SROB1, SROB2, SROB3, SROB4, SROB5, SROB6, SROB7, SROB8, SROB9, SROB10, SROB11, SROB12, SROB13, SROB14, SROB15, SROB16, SROB17,
|
||||
output ROA0, ROA1, ROA2, ROA3, ROA4, ROA5, ROA6, ROA7, ROA8, ROA9, ROA10, ROA11, ROA12, ROA13, ROA14, ROA15, ROA16, ROA17,
|
||||
output ROB0, ROB1, ROB2, ROB3, ROB4, ROB5, ROB6, ROB7, ROB8, ROB9, ROB10, ROB11, ROB12, ROB13, ROB14, ROB15, ROB16, ROB17,
|
||||
output ROC0, ROC1, ROC2, ROC3, ROC4, ROC5, ROC6, ROC7, ROC8, ROC9, ROC10, ROC11, ROC12, ROC13, ROC14, ROC15, ROC16, ROC17,
|
||||
output P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35,
|
||||
output SIGNEDP
|
||||
);
|
||||
parameter REG_INPUTA_CLK = "NONE";
|
||||
parameter REG_INPUTA_CE = "CE0";
|
||||
parameter REG_INPUTA_RST = "RST0";
|
||||
parameter REG_INPUTB_CLK = "NONE";
|
||||
parameter REG_INPUTB_CE = "CE0";
|
||||
parameter REG_INPUTB_RST = "RST0";
|
||||
parameter REG_INPUTC_CLK = "NONE";
|
||||
parameter REG_PIPELINE_CLK = "NONE";
|
||||
parameter REG_PIPELINE_CE = "CE0";
|
||||
parameter REG_PIPELINE_RST = "RST0";
|
||||
parameter REG_OUTPUT_CLK = "NONE";
|
||||
parameter [127:0] CLK0_DIV = "ENABLED";
|
||||
parameter [127:0] CLK1_DIV = "ENABLED";
|
||||
parameter [127:0] CLK2_DIV = "ENABLED";
|
||||
parameter [127:0] CLK3_DIV = "ENABLED";
|
||||
parameter [127:0] GSR = "ENABLED";
|
||||
parameter [127:0] SOURCEB_MODE = "B_SHIFT";
|
||||
parameter [127:0] RESETMODE = "SYNC";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module ALU54B(
|
||||
input CLK0, CLK1, CLK2, CLK3,
|
||||
input CE0, CE1, CE2, CE3,
|
||||
input RST0, RST1, RST2, RST3,
|
||||
input SIGNEDIA, SIGNEDIB, SIGNEDCIN,
|
||||
input A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35,
|
||||
input B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19, B20, B21, B22, B23, B24, B25, B26, B27, B28, B29, B30, B31, B32, B33, B34, B35,
|
||||
input C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26, C27, C28, C29, C30, C31, C32, C33, C34, C35, C36, C37, C38, C39, C40, C41, C42, C43, C44, C45, C46, C47, C48, C49, C50, C51, C52, C53,
|
||||
input CFB0, CFB1, CFB2, CFB3, CFB4, CFB5, CFB6, CFB7, CFB8, CFB9, CFB10, CFB11, CFB12, CFB13, CFB14, CFB15, CFB16, CFB17, CFB18, CFB19, CFB20, CFB21, CFB22, CFB23, CFB24, CFB25, CFB26, CFB27, CFB28, CFB29, CFB30, CFB31, CFB32, CFB33, CFB34, CFB35, CFB36, CFB37, CFB38, CFB39, CFB40, CFB41, CFB42, CFB43, CFB44, CFB45, CFB46, CFB47, CFB48, CFB49, CFB50, CFB51, CFB52, CFB53,
|
||||
input MA0, MA1, MA2, MA3, MA4, MA5, MA6, MA7, MA8, MA9, MA10, MA11, MA12, MA13, MA14, MA15, MA16, MA17, MA18, MA19, MA20, MA21, MA22, MA23, MA24, MA25, MA26, MA27, MA28, MA29, MA30, MA31, MA32, MA33, MA34, MA35,
|
||||
input MB0, MB1, MB2, MB3, MB4, MB5, MB6, MB7, MB8, MB9, MB10, MB11, MB12, MB13, MB14, MB15, MB16, MB17, MB18, MB19, MB20, MB21, MB22, MB23, MB24, MB25, MB26, MB27, MB28, MB29, MB30, MB31, MB32, MB33, MB34, MB35,
|
||||
input CIN0, CIN1, CIN2, CIN3, CIN4, CIN5, CIN6, CIN7, CIN8, CIN9, CIN10, CIN11, CIN12, CIN13, CIN14, CIN15, CIN16, CIN17, CIN18, CIN19, CIN20, CIN21, CIN22, CIN23, CIN24, CIN25, CIN26, CIN27, CIN28, CIN29, CIN30, CIN31, CIN32, CIN33, CIN34, CIN35, CIN36, CIN37, CIN38, CIN39, CIN40, CIN41, CIN42, CIN43, CIN44, CIN45, CIN46, CIN47, CIN48, CIN49, CIN50, CIN51, CIN52, CIN53,
|
||||
input OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7, OP8, OP9, OP10,
|
||||
output R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53,
|
||||
output CO0, CO1, CO2, CO3, CO4, CO5, CO6, CO7, CO8, CO9, CO10, CO11, CO12, CO13, CO14, CO15, CO16, CO17, CO18, CO19, CO20, CO21, CO22, CO23, CO24, CO25, CO26, CO27, CO28, CO29, CO30, CO31, CO32, CO33, CO34, CO35, CO36, CO37, CO38, CO39, CO40, CO41, CO42, CO43, CO44, CO45, CO46, CO47, CO48, CO49, CO50, CO51, CO52, CO53,
|
||||
output EQZ, EQZM, EQOM, EQPAT, EQPATB,
|
||||
output OVER, UNDER, OVERUNDER,
|
||||
output SIGNEDR
|
||||
);
|
||||
parameter REG_INPUTC0_CLK = "NONE";
|
||||
parameter REG_INPUTC1_CLK = "NONE";
|
||||
parameter REG_OPCODEOP0_0_CLK = "NONE";
|
||||
parameter REG_OPCODEOP0_0_CE = "CE0";
|
||||
parameter REG_OPCODEOP0_0_RST = "RST0";
|
||||
parameter REG_OPCODEOP1_0_CLK = "NONE";
|
||||
parameter REG_OPCODEOP0_1_CLK = "NONE";
|
||||
parameter REG_OPCODEOP0_1_CE = "CE0";
|
||||
parameter REG_OPCODEOP0_1_RST = "RST0";
|
||||
parameter REG_OPCODEIN_0_CLK = "NONE";
|
||||
parameter REG_OPCODEIN_0_CE = "CE0";
|
||||
parameter REG_OPCODEIN_0_RST = "RST0";
|
||||
parameter REG_OPCODEIN_1_CLK = "NONE";
|
||||
parameter REG_OPCODEIN_1_CE = "CE0";
|
||||
parameter REG_OPCODEIN_1_RST = "RST0";
|
||||
parameter REG_OUTPUT0_CLK = "NONE";
|
||||
parameter REG_OUTPUT1_CLK = "NONE";
|
||||
parameter REG_FLAG_CLK = "NONE";
|
||||
parameter [127:0] MCPAT_SOURCE = "STATIC";
|
||||
parameter [127:0] MASKPAT_SOURCE = "STATIC";
|
||||
parameter MASK01 = "0x00000000000000";
|
||||
parameter [127:0] CLK0_DIV = "ENABLED";
|
||||
parameter [127:0] CLK1_DIV = "ENABLED";
|
||||
parameter [127:0] CLK2_DIV = "ENABLED";
|
||||
parameter [127:0] CLK3_DIV = "ENABLED";
|
||||
parameter MCPAT = "0x00000000000000";
|
||||
parameter MASKPAT = "0x00000000000000";
|
||||
parameter RNDPAT = "0x00000000000000";
|
||||
parameter [127:0] GSR = "ENABLED";
|
||||
parameter [127:0] RESETMODE = "SYNC";
|
||||
parameter FORCE_ZERO_BARREL_SHIFT = "DISABLED";
|
||||
parameter LEGACY = "DISABLED";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module EHXPLLL (
|
||||
input CLKI, CLKFB,
|
||||
input PHASESEL1, PHASESEL0, PHASEDIR, PHASESTEP, PHASELOADREG,
|
||||
input STDBY, PLLWAKESYNC,
|
||||
input RST, ENCLKOP, ENCLKOS, ENCLKOS2, ENCLKOS3,
|
||||
output CLKOP, CLKOS, CLKOS2, CLKOS3,
|
||||
output LOCK, INTLOCK,
|
||||
output REFCLK, CLKINTFB
|
||||
);
|
||||
parameter CLKI_DIV = 1;
|
||||
parameter CLKFB_DIV = 1;
|
||||
parameter CLKOP_DIV = 8;
|
||||
parameter CLKOS_DIV = 8;
|
||||
parameter CLKOS2_DIV = 8;
|
||||
parameter CLKOS3_DIV = 8;
|
||||
parameter CLKOP_ENABLE = "ENABLED";
|
||||
parameter CLKOS_ENABLE = "DISABLED";
|
||||
parameter CLKOS2_ENABLE = "DISABLED";
|
||||
parameter CLKOS3_ENABLE = "DISABLED";
|
||||
parameter CLKOP_CPHASE = 0;
|
||||
parameter CLKOS_CPHASE = 0;
|
||||
parameter CLKOS2_CPHASE = 0;
|
||||
parameter CLKOS3_CPHASE = 0;
|
||||
parameter CLKOP_FPHASE = 0;
|
||||
parameter CLKOS_FPHASE = 0;
|
||||
parameter CLKOS2_FPHASE = 0;
|
||||
parameter CLKOS3_FPHASE = 0;
|
||||
parameter FEEDBK_PATH = "CLKOP";
|
||||
parameter CLKOP_TRIM_POL = "RISING";
|
||||
parameter CLKOP_TRIM_DELAY = 0;
|
||||
parameter CLKOS_TRIM_POL = "RISING";
|
||||
parameter CLKOS_TRIM_DELAY = 0;
|
||||
parameter OUTDIVIDER_MUXA = "DIVA";
|
||||
parameter OUTDIVIDER_MUXB = "DIVB";
|
||||
parameter OUTDIVIDER_MUXC = "DIVC";
|
||||
parameter OUTDIVIDER_MUXD = "DIVD";
|
||||
parameter PLL_LOCK_MODE = 0;
|
||||
parameter PLL_LOCK_DELAY = 200;
|
||||
parameter STDBY_ENABLE = "DISABLED";
|
||||
parameter REFIN_RESET = "DISABLED";
|
||||
parameter SYNC_ENABLE = "DISABLED";
|
||||
parameter INT_LOCK_STICKY = "ENABLED";
|
||||
parameter DPHASE_SOURCE = "DISABLED";
|
||||
parameter PLLRST_ENA = "DISABLED";
|
||||
parameter INTFB_WAKE = "DISABLED";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module DTR(
|
||||
input STARTPULSE,
|
||||
output DTROUT7, DTROUT6, DTROUT5, DTROUT4, DTROUT3, DTROUT2, DTROUT1, DTROUT0
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module OSCG(
|
||||
output OSC
|
||||
);
|
||||
parameter DIV = 128;
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module IDDRX1F(
|
||||
input D, SCLK, RST,
|
||||
output Q0, Q1
|
||||
);
|
||||
parameter GSR = "ENABLED";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module ODDRX1F(
|
||||
input SCLK, RST, D0, D1,
|
||||
output Q
|
||||
);
|
||||
parameter GSR = "ENABLED";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module CLKDIVF(
|
||||
input CLKI, RST, ALIGNWD,
|
||||
output CDIVX
|
||||
);
|
||||
parameter GSR = "DISABLED";
|
||||
parameter DIV = "2.0";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module DCCA(
|
||||
input CLKI, CE,
|
||||
output CLKO
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* blackbox *) (* keep *)
|
||||
module DCUA(
|
||||
input CH0_HDINP, CH1_HDINP, CH0_HDINN, CH1_HDINN,
|
||||
input D_TXBIT_CLKP_FROM_ND, D_TXBIT_CLKN_FROM_ND, D_SYNC_ND, D_TXPLL_LOL_FROM_ND,
|
||||
input CH0_RX_REFCLK, CH1_RX_REFCLK, CH0_FF_RXI_CLK, CH1_FF_RXI_CLK, CH0_FF_TXI_CLK, CH1_FF_TXI_CLK, CH0_FF_EBRD_CLK, CH1_FF_EBRD_CLK,
|
||||
input CH0_FF_TX_D_0, CH1_FF_TX_D_0, CH0_FF_TX_D_1, CH1_FF_TX_D_1, CH0_FF_TX_D_2, CH1_FF_TX_D_2, CH0_FF_TX_D_3, CH1_FF_TX_D_3,
|
||||
input CH0_FF_TX_D_4, CH1_FF_TX_D_4, CH0_FF_TX_D_5, CH1_FF_TX_D_5, CH0_FF_TX_D_6, CH1_FF_TX_D_6, CH0_FF_TX_D_7, CH1_FF_TX_D_7,
|
||||
input CH0_FF_TX_D_8, CH1_FF_TX_D_8, CH0_FF_TX_D_9, CH1_FF_TX_D_9, CH0_FF_TX_D_10, CH1_FF_TX_D_10, CH0_FF_TX_D_11, CH1_FF_TX_D_11,
|
||||
input CH0_FF_TX_D_12, CH1_FF_TX_D_12, CH0_FF_TX_D_13, CH1_FF_TX_D_13, CH0_FF_TX_D_14, CH1_FF_TX_D_14, CH0_FF_TX_D_15, CH1_FF_TX_D_15,
|
||||
input CH0_FF_TX_D_16, CH1_FF_TX_D_16, CH0_FF_TX_D_17, CH1_FF_TX_D_17, CH0_FF_TX_D_18, CH1_FF_TX_D_18, CH0_FF_TX_D_19, CH1_FF_TX_D_19,
|
||||
input CH0_FF_TX_D_20, CH1_FF_TX_D_20, CH0_FF_TX_D_21, CH1_FF_TX_D_21, CH0_FF_TX_D_22, CH1_FF_TX_D_22, CH0_FF_TX_D_23, CH1_FF_TX_D_23,
|
||||
input CH0_FFC_EI_EN, CH1_FFC_EI_EN, CH0_FFC_PCIE_DET_EN, CH1_FFC_PCIE_DET_EN, CH0_FFC_PCIE_CT, CH1_FFC_PCIE_CT, CH0_FFC_SB_INV_RX, CH1_FFC_SB_INV_RX,
|
||||
input CH0_FFC_ENABLE_CGALIGN, CH1_FFC_ENABLE_CGALIGN, CH0_FFC_SIGNAL_DETECT, CH1_FFC_SIGNAL_DETECT, CH0_FFC_FB_LOOPBACK, CH1_FFC_FB_LOOPBACK, CH0_FFC_SB_PFIFO_LP, CH1_FFC_SB_PFIFO_LP,
|
||||
input CH0_FFC_PFIFO_CLR, CH1_FFC_PFIFO_CLR, CH0_FFC_RATE_MODE_RX, CH1_FFC_RATE_MODE_RX, CH0_FFC_RATE_MODE_TX, CH1_FFC_RATE_MODE_TX, CH0_FFC_DIV11_MODE_RX, CH1_FFC_DIV11_MODE_RX, CH0_FFC_RX_GEAR_MODE, CH1_FFC_RX_GEAR_MODE, CH0_FFC_TX_GEAR_MODE, CH1_FFC_TX_GEAR_MODE,
|
||||
input CH0_FFC_DIV11_MODE_TX, CH1_FFC_DIV11_MODE_TX, CH0_FFC_LDR_CORE2TX_EN, CH1_FFC_LDR_CORE2TX_EN, CH0_FFC_LANE_TX_RST, CH1_FFC_LANE_TX_RST, CH0_FFC_LANE_RX_RST, CH1_FFC_LANE_RX_RST,
|
||||
input CH0_FFC_RRST, CH1_FFC_RRST, CH0_FFC_TXPWDNB, CH1_FFC_TXPWDNB, CH0_FFC_RXPWDNB, CH1_FFC_RXPWDNB, CH0_LDR_CORE2TX, CH1_LDR_CORE2TX,
|
||||
input D_SCIWDATA0, D_SCIWDATA1, D_SCIWDATA2, D_SCIWDATA3, D_SCIWDATA4, D_SCIWDATA5, D_SCIWDATA6, D_SCIWDATA7,
|
||||
input D_SCIADDR0, D_SCIADDR1, D_SCIADDR2, D_SCIADDR3, D_SCIADDR4, D_SCIADDR5, D_SCIENAUX, D_SCISELAUX,
|
||||
input CH0_SCIEN, CH1_SCIEN, CH0_SCISEL, CH1_SCISEL, D_SCIRD, D_SCIWSTN, D_CYAWSTN, D_FFC_SYNC_TOGGLE,
|
||||
input D_FFC_DUAL_RST, D_FFC_MACRO_RST, D_FFC_MACROPDB, D_FFC_TRST, CH0_FFC_CDR_EN_BITSLIP, CH1_FFC_CDR_EN_BITSLIP, D_SCAN_ENABLE, D_SCAN_IN_0,
|
||||
input D_SCAN_IN_1, D_SCAN_IN_2, D_SCAN_IN_3, D_SCAN_IN_4, D_SCAN_IN_5, D_SCAN_IN_6, D_SCAN_IN_7, D_SCAN_MODE,
|
||||
input D_SCAN_RESET, D_CIN0, D_CIN1, D_CIN2, D_CIN3, D_CIN4, D_CIN5, D_CIN6,D_CIN7, D_CIN8, D_CIN9, D_CIN10, D_CIN11,
|
||||
output CH0_HDOUTP, CH1_HDOUTP, CH0_HDOUTN, CH1_HDOUTN, D_TXBIT_CLKP_TO_ND, D_TXBIT_CLKN_TO_ND, D_SYNC_PULSE2ND, D_TXPLL_LOL_TO_ND,
|
||||
output CH0_FF_RX_F_CLK, CH1_FF_RX_F_CLK, CH0_FF_RX_H_CLK, CH1_FF_RX_H_CLK, CH0_FF_TX_F_CLK, CH1_FF_TX_F_CLK, CH0_FF_TX_H_CLK, CH1_FF_TX_H_CLK,
|
||||
output CH0_FF_RX_PCLK, CH1_FF_RX_PCLK, CH0_FF_TX_PCLK, CH1_FF_TX_PCLK, CH0_FF_RX_D_0, CH1_FF_RX_D_0, CH0_FF_RX_D_1, CH1_FF_RX_D_1,
|
||||
output CH0_FF_RX_D_2, CH1_FF_RX_D_2, CH0_FF_RX_D_3, CH1_FF_RX_D_3, CH0_FF_RX_D_4, CH1_FF_RX_D_4, CH0_FF_RX_D_5, CH1_FF_RX_D_5,
|
||||
output CH0_FF_RX_D_6, CH1_FF_RX_D_6, CH0_FF_RX_D_7, CH1_FF_RX_D_7, CH0_FF_RX_D_8, CH1_FF_RX_D_8, CH0_FF_RX_D_9, CH1_FF_RX_D_9,
|
||||
output CH0_FF_RX_D_10, CH1_FF_RX_D_10, CH0_FF_RX_D_11, CH1_FF_RX_D_11, CH0_FF_RX_D_12, CH1_FF_RX_D_12, CH0_FF_RX_D_13, CH1_FF_RX_D_13,
|
||||
output CH0_FF_RX_D_14, CH1_FF_RX_D_14, CH0_FF_RX_D_15, CH1_FF_RX_D_15, CH0_FF_RX_D_16, CH1_FF_RX_D_16, CH0_FF_RX_D_17, CH1_FF_RX_D_17,
|
||||
output CH0_FF_RX_D_18, CH1_FF_RX_D_18, CH0_FF_RX_D_19, CH1_FF_RX_D_19, CH0_FF_RX_D_20, CH1_FF_RX_D_20, CH0_FF_RX_D_21, CH1_FF_RX_D_21,
|
||||
output CH0_FF_RX_D_22, CH1_FF_RX_D_22, CH0_FF_RX_D_23, CH1_FF_RX_D_23, CH0_FFS_PCIE_DONE, CH1_FFS_PCIE_DONE, CH0_FFS_PCIE_CON, CH1_FFS_PCIE_CON,
|
||||
output CH0_FFS_RLOS, CH1_FFS_RLOS, CH0_FFS_LS_SYNC_STATUS, CH1_FFS_LS_SYNC_STATUS, CH0_FFS_CC_UNDERRUN, CH1_FFS_CC_UNDERRUN, CH0_FFS_CC_OVERRUN, CH1_FFS_CC_OVERRUN,
|
||||
output CH0_FFS_RXFBFIFO_ERROR, CH1_FFS_RXFBFIFO_ERROR, CH0_FFS_TXFBFIFO_ERROR, CH1_FFS_TXFBFIFO_ERROR, CH0_FFS_RLOL, CH1_FFS_RLOL, CH0_FFS_SKP_ADDED, CH1_FFS_SKP_ADDED,
|
||||
output CH0_FFS_SKP_DELETED, CH1_FFS_SKP_DELETED, CH0_LDR_RX2CORE, CH1_LDR_RX2CORE, D_SCIRDATA0, D_SCIRDATA1, D_SCIRDATA2, D_SCIRDATA3,
|
||||
output D_SCIRDATA4, D_SCIRDATA5, D_SCIRDATA6, D_SCIRDATA7, D_SCIINT, D_SCAN_OUT_0, D_SCAN_OUT_1, D_SCAN_OUT_2, D_SCAN_OUT_3, D_SCAN_OUT_4, D_SCAN_OUT_5, D_SCAN_OUT_6, D_SCAN_OUT_7,
|
||||
output D_COUT0, D_COUT1, D_COUT2, D_COUT3, D_COUT4, D_COUT5, D_COUT6, D_COUT7, D_COUT8, D_COUT9, D_COUT10, D_COUT11, D_COUT12, D_COUT13, D_COUT14, D_COUT15, D_COUT16, D_COUT17, D_COUT18, D_COUT19,
|
||||
|
||||
input D_REFCLKI,
|
||||
output D_FFS_PLOL
|
||||
);
|
||||
parameter CH0_AUTO_CALIB_EN = "0b0";
|
||||
parameter CH0_AUTO_FACQ_EN = "0b0";
|
||||
parameter CH0_BAND_THRESHOLD = "0b000000";
|
||||
parameter CH0_CALIB_CK_MODE = "0b0";
|
||||
parameter CH0_CC_MATCH_1 = "0b0000000000";
|
||||
parameter CH0_CC_MATCH_2 = "0b0000000000";
|
||||
parameter CH0_CC_MATCH_3 = "0b0000000000";
|
||||
parameter CH0_CC_MATCH_4 = "0b0000000000";
|
||||
parameter CH0_CDR_CNT4SEL = "0b00";
|
||||
parameter CH0_CDR_CNT8SEL = "0b00";
|
||||
parameter CH0_CTC_BYPASS = "0b0";
|
||||
parameter CH0_DCOATDCFG = "0b00";
|
||||
parameter CH0_DCOATDDLY = "0b00";
|
||||
parameter CH0_DCOBYPSATD = "0b0";
|
||||
parameter CH0_DCOCALDIV = "0b000";
|
||||
parameter CH0_DCOCTLGI = "0b000";
|
||||
parameter CH0_DCODISBDAVOID = "0b0";
|
||||
parameter CH0_DCOFLTDAC = "0b00";
|
||||
parameter CH0_DCOFTNRG = "0b000";
|
||||
parameter CH0_DCOIOSTUNE = "0b000";
|
||||
parameter CH0_DCOITUNE = "0b00";
|
||||
parameter CH0_DCOITUNE4LSB = "0b000";
|
||||
parameter CH0_DCOIUPDNX2 = "0b0";
|
||||
parameter CH0_DCONUOFLSB = "0b000";
|
||||
parameter CH0_DCOSCALEI = "0b00";
|
||||
parameter CH0_DCOSTARTVAL = "0b000";
|
||||
parameter CH0_DCOSTEP = "0b00";
|
||||
parameter CH0_DEC_BYPASS = "0b0";
|
||||
parameter CH0_ENABLE_CG_ALIGN = "0b0";
|
||||
parameter CH0_ENC_BYPASS = "0b0";
|
||||
parameter CH0_FF_RX_F_CLK_DIS = "0b0";
|
||||
parameter CH0_FF_RX_H_CLK_EN = "0b0";
|
||||
parameter CH0_FF_TX_F_CLK_DIS = "0b0";
|
||||
parameter CH0_FF_TX_H_CLK_EN = "0b0";
|
||||
parameter CH0_GE_AN_ENABLE = "0b0";
|
||||
parameter CH0_INVERT_RX = "0b0";
|
||||
parameter CH0_INVERT_TX = "0b0";
|
||||
parameter CH0_LDR_CORE2TX_SEL = "0b0";
|
||||
parameter CH0_LDR_RX2CORE_SEL = "0b0";
|
||||
parameter CH0_LEQ_OFFSET_SEL = "0b0";
|
||||
parameter CH0_LEQ_OFFSET_TRIM = "0b000";
|
||||
parameter CH0_LSM_DISABLE = "0b0";
|
||||
parameter CH0_MATCH_2_ENABLE = "0b0";
|
||||
parameter CH0_MATCH_4_ENABLE = "0b0";
|
||||
parameter CH0_MIN_IPG_CNT = "0b00";
|
||||
parameter CH0_PCIE_EI_EN = "0b0";
|
||||
parameter CH0_PCIE_MODE = "0b0";
|
||||
parameter CH0_PCS_DET_TIME_SEL = "0b00";
|
||||
parameter CH0_PDEN_SEL = "0b0";
|
||||
parameter CH0_PRBS_ENABLE = "0b0";
|
||||
parameter CH0_PRBS_LOCK = "0b0";
|
||||
parameter CH0_PRBS_SELECTION = "0b0";
|
||||
parameter CH0_RATE_MODE_RX = "0b0";
|
||||
parameter CH0_RATE_MODE_TX = "0b0";
|
||||
parameter CH0_RCV_DCC_EN = "0b0";
|
||||
parameter CH0_REG_BAND_OFFSET = "0b0000";
|
||||
parameter CH0_REG_BAND_SEL = "0b000000";
|
||||
parameter CH0_REG_IDAC_EN = "0b0";
|
||||
parameter CH0_REG_IDAC_SEL = "0b0000000000";
|
||||
parameter CH0_REQ_EN = "0b0";
|
||||
parameter CH0_REQ_LVL_SET = "0b00";
|
||||
parameter CH0_RIO_MODE = "0b0";
|
||||
parameter CH0_RLOS_SEL = "0b0";
|
||||
parameter CH0_RPWDNB = "0b0";
|
||||
parameter CH0_RTERM_RX = "0b00000";
|
||||
parameter CH0_RTERM_TX = "0b00000";
|
||||
parameter CH0_RXIN_CM = "0b00";
|
||||
parameter CH0_RXTERM_CM = "0b00";
|
||||
parameter CH0_RX_DCO_CK_DIV = "0b000";
|
||||
parameter CH0_RX_DIV11_SEL = "0b0";
|
||||
parameter CH0_RX_GEAR_BYPASS = "0b0";
|
||||
parameter CH0_RX_GEAR_MODE = "0b0";
|
||||
parameter CH0_RX_LOS_CEQ = "0b00";
|
||||
parameter CH0_RX_LOS_EN = "0b0";
|
||||
parameter CH0_RX_LOS_HYST_EN = "0b0";
|
||||
parameter CH0_RX_LOS_LVL = "0b000";
|
||||
parameter CH0_RX_RATE_SEL = "0b0000";
|
||||
parameter CH0_RX_SB_BYPASS = "0b0";
|
||||
parameter CH0_SB_BYPASS = "0b0";
|
||||
parameter CH0_SEL_SD_RX_CLK = "0b0";
|
||||
parameter CH0_TDRV_DAT_SEL = "0b00";
|
||||
parameter CH0_TDRV_POST_EN = "0b0";
|
||||
parameter CH0_TDRV_PRE_EN = "0b0";
|
||||
parameter CH0_TDRV_SLICE0_CUR = "0b000";
|
||||
parameter CH0_TDRV_SLICE0_SEL = "0b00";
|
||||
parameter CH0_TDRV_SLICE1_CUR = "0b000";
|
||||
parameter CH0_TDRV_SLICE1_SEL = "0b00";
|
||||
parameter CH0_TDRV_SLICE2_CUR = "0b00";
|
||||
parameter CH0_TDRV_SLICE2_SEL = "0b00";
|
||||
parameter CH0_TDRV_SLICE3_CUR = "0b00";
|
||||
parameter CH0_TDRV_SLICE3_SEL = "0b00";
|
||||
parameter CH0_TDRV_SLICE4_CUR = "0b00";
|
||||
parameter CH0_TDRV_SLICE4_SEL = "0b00";
|
||||
parameter CH0_TDRV_SLICE5_CUR = "0b00";
|
||||
parameter CH0_TDRV_SLICE5_SEL = "0b00";
|
||||
parameter CH0_TPWDNB = "0b0";
|
||||
parameter CH0_TX_CM_SEL = "0b00";
|
||||
parameter CH0_TX_DIV11_SEL = "0b0";
|
||||
parameter CH0_TX_GEAR_BYPASS = "0b0";
|
||||
parameter CH0_TX_GEAR_MODE = "0b0";
|
||||
parameter CH0_TX_POST_SIGN = "0b0";
|
||||
parameter CH0_TX_PRE_SIGN = "0b0";
|
||||
parameter CH0_UC_MODE = "0b0";
|
||||
parameter CH0_UDF_COMMA_A = "0b0000000000";
|
||||
parameter CH0_UDF_COMMA_B = "0b0000000000";
|
||||
parameter CH0_UDF_COMMA_MASK = "0b0000000000";
|
||||
parameter CH0_WA_BYPASS = "0b0";
|
||||
parameter CH0_WA_MODE = "0b0";
|
||||
parameter CH1_AUTO_CALIB_EN = "0b0";
|
||||
parameter CH1_AUTO_FACQ_EN = "0b0";
|
||||
parameter CH1_BAND_THRESHOLD = "0b000000";
|
||||
parameter CH1_CALIB_CK_MODE = "0b0";
|
||||
parameter CH1_CC_MATCH_1 = "0b0000000000";
|
||||
parameter CH1_CC_MATCH_2 = "0b0000000000";
|
||||
parameter CH1_CC_MATCH_3 = "0b0000000000";
|
||||
parameter CH1_CC_MATCH_4 = "0b0000000000";
|
||||
parameter CH1_CDR_CNT4SEL = "0b00";
|
||||
parameter CH1_CDR_CNT8SEL = "0b00";
|
||||
parameter CH1_CTC_BYPASS = "0b0";
|
||||
parameter CH1_DCOATDCFG = "0b00";
|
||||
parameter CH1_DCOATDDLY = "0b00";
|
||||
parameter CH1_DCOBYPSATD = "0b0";
|
||||
parameter CH1_DCOCALDIV = "0b000";
|
||||
parameter CH1_DCOCTLGI = "0b000";
|
||||
parameter CH1_DCODISBDAVOID = "0b0";
|
||||
parameter CH1_DCOFLTDAC = "0b00";
|
||||
parameter CH1_DCOFTNRG = "0b000";
|
||||
parameter CH1_DCOIOSTUNE = "0b000";
|
||||
parameter CH1_DCOITUNE = "0b00";
|
||||
parameter CH1_DCOITUNE4LSB = "0b000";
|
||||
parameter CH1_DCOIUPDNX2 = "0b0";
|
||||
parameter CH1_DCONUOFLSB = "0b000";
|
||||
parameter CH1_DCOSCALEI = "0b00";
|
||||
parameter CH1_DCOSTARTVAL = "0b000";
|
||||
parameter CH1_DCOSTEP = "0b00";
|
||||
parameter CH1_DEC_BYPASS = "0b0";
|
||||
parameter CH1_ENABLE_CG_ALIGN = "0b0";
|
||||
parameter CH1_ENC_BYPASS = "0b0";
|
||||
parameter CH1_FF_RX_F_CLK_DIS = "0b0";
|
||||
parameter CH1_FF_RX_H_CLK_EN = "0b0";
|
||||
parameter CH1_FF_TX_F_CLK_DIS = "0b0";
|
||||
parameter CH1_FF_TX_H_CLK_EN = "0b0";
|
||||
parameter CH1_GE_AN_ENABLE = "0b0";
|
||||
parameter CH1_INVERT_RX = "0b0";
|
||||
parameter CH1_INVERT_TX = "0b0";
|
||||
parameter CH1_LDR_CORE2TX_SEL = "0b0";
|
||||
parameter CH1_LDR_RX2CORE_SEL = "0b0";
|
||||
parameter CH1_LEQ_OFFSET_SEL = "0b0";
|
||||
parameter CH1_LEQ_OFFSET_TRIM = "0b000";
|
||||
parameter CH1_LSM_DISABLE = "0b0";
|
||||
parameter CH1_MATCH_2_ENABLE = "0b0";
|
||||
parameter CH1_MATCH_4_ENABLE = "0b0";
|
||||
parameter CH1_MIN_IPG_CNT = "0b00";
|
||||
parameter CH1_PCIE_EI_EN = "0b0";
|
||||
parameter CH1_PCIE_MODE = "0b0";
|
||||
parameter CH1_PCS_DET_TIME_SEL = "0b00";
|
||||
parameter CH1_PDEN_SEL = "0b0";
|
||||
parameter CH1_PRBS_ENABLE = "0b0";
|
||||
parameter CH1_PRBS_LOCK = "0b0";
|
||||
parameter CH1_PRBS_SELECTION = "0b0";
|
||||
parameter CH1_RATE_MODE_RX = "0b0";
|
||||
parameter CH1_RATE_MODE_TX = "0b0";
|
||||
parameter CH1_RCV_DCC_EN = "0b0";
|
||||
parameter CH1_REG_BAND_OFFSET = "0b0000";
|
||||
parameter CH1_REG_BAND_SEL = "0b000000";
|
||||
parameter CH1_REG_IDAC_EN = "0b0";
|
||||
parameter CH1_REG_IDAC_SEL = "0b0000000000";
|
||||
parameter CH1_REQ_EN = "0b0";
|
||||
parameter CH1_REQ_LVL_SET = "0b00";
|
||||
parameter CH1_RIO_MODE = "0b0";
|
||||
parameter CH1_RLOS_SEL = "0b0";
|
||||
parameter CH1_RPWDNB = "0b0";
|
||||
parameter CH1_RTERM_RX = "0b00000";
|
||||
parameter CH1_RTERM_TX = "0b00000";
|
||||
parameter CH1_RXIN_CM = "0b00";
|
||||
parameter CH1_RXTERM_CM = "0b00";
|
||||
parameter CH1_RX_DCO_CK_DIV = "0b000";
|
||||
parameter CH1_RX_DIV11_SEL = "0b0";
|
||||
parameter CH1_RX_GEAR_BYPASS = "0b0";
|
||||
parameter CH1_RX_GEAR_MODE = "0b0";
|
||||
parameter CH1_RX_LOS_CEQ = "0b00";
|
||||
parameter CH1_RX_LOS_EN = "0b0";
|
||||
parameter CH1_RX_LOS_HYST_EN = "0b0";
|
||||
parameter CH1_RX_LOS_LVL = "0b000";
|
||||
parameter CH1_RX_RATE_SEL = "0b0000";
|
||||
parameter CH1_RX_SB_BYPASS = "0b0";
|
||||
parameter CH1_SB_BYPASS = "0b0";
|
||||
parameter CH1_SEL_SD_RX_CLK = "0b0";
|
||||
parameter CH1_TDRV_DAT_SEL = "0b00";
|
||||
parameter CH1_TDRV_POST_EN = "0b0";
|
||||
parameter CH1_TDRV_PRE_EN = "0b0";
|
||||
parameter CH1_TDRV_SLICE0_CUR = "0b000";
|
||||
parameter CH1_TDRV_SLICE0_SEL = "0b00";
|
||||
parameter CH1_TDRV_SLICE1_CUR = "0b000";
|
||||
parameter CH1_TDRV_SLICE1_SEL = "0b00";
|
||||
parameter CH1_TDRV_SLICE2_CUR = "0b00";
|
||||
parameter CH1_TDRV_SLICE2_SEL = "0b00";
|
||||
parameter CH1_TDRV_SLICE3_CUR = "0b00";
|
||||
parameter CH1_TDRV_SLICE3_SEL = "0b00";
|
||||
parameter CH1_TDRV_SLICE4_CUR = "0b00";
|
||||
parameter CH1_TDRV_SLICE4_SEL = "0b00";
|
||||
parameter CH1_TDRV_SLICE5_CUR = "0b00";
|
||||
parameter CH1_TDRV_SLICE5_SEL = "0b00";
|
||||
parameter CH1_TPWDNB = "0b0";
|
||||
parameter CH1_TX_CM_SEL = "0b00";
|
||||
parameter CH1_TX_DIV11_SEL = "0b0";
|
||||
parameter CH1_TX_GEAR_BYPASS = "0b0";
|
||||
parameter CH1_TX_GEAR_MODE = "0b0";
|
||||
parameter CH1_TX_POST_SIGN = "0b0";
|
||||
parameter CH1_TX_PRE_SIGN = "0b0";
|
||||
parameter CH1_UC_MODE = "0b0";
|
||||
parameter CH1_UDF_COMMA_A = "0b0000000000";
|
||||
parameter CH1_UDF_COMMA_B = "0b0000000000";
|
||||
parameter CH1_UDF_COMMA_MASK = "0b0000000000";
|
||||
parameter CH1_WA_BYPASS = "0b0";
|
||||
parameter CH1_WA_MODE = "0b0";
|
||||
parameter D_BITCLK_FROM_ND_EN = "0b0";
|
||||
parameter D_BITCLK_LOCAL_EN = "0b0";
|
||||
parameter D_BITCLK_ND_EN = "0b0";
|
||||
parameter D_BUS8BIT_SEL = "0b0";
|
||||
parameter D_CDR_LOL_SET = "0b00";
|
||||
parameter D_CMUSETBIASI = "0b00";
|
||||
parameter D_CMUSETI4CPP = "0b0000";
|
||||
parameter D_CMUSETI4CPZ = "0b0000";
|
||||
parameter D_CMUSETI4VCO = "0b00";
|
||||
parameter D_CMUSETICP4P = "0b00";
|
||||
parameter D_CMUSETICP4Z = "0b000";
|
||||
parameter D_CMUSETINITVCT = "0b00";
|
||||
parameter D_CMUSETISCL4VCO = "0b000";
|
||||
parameter D_CMUSETP1GM = "0b000";
|
||||
parameter D_CMUSETP2AGM = "0b000";
|
||||
parameter D_CMUSETZGM = "0b000";
|
||||
parameter D_DCO_CALIB_TIME_SEL = "0b00";
|
||||
parameter D_HIGH_MARK = "0b0000";
|
||||
parameter D_IB_PWDNB = "0b0";
|
||||
parameter D_ISETLOS = "0b00000000";
|
||||
parameter D_LOW_MARK = "0b0000";
|
||||
parameter D_MACROPDB = "0b0";
|
||||
parameter D_PD_ISET = "0b00";
|
||||
parameter D_PLL_LOL_SET = "0b00";
|
||||
parameter D_REFCK_MODE = "0b000";
|
||||
parameter D_REQ_ISET = "0b000";
|
||||
parameter D_RG_EN = "0b0";
|
||||
parameter D_RG_SET = "0b00";
|
||||
parameter D_SETICONST_AUX = "0b00";
|
||||
parameter D_SETICONST_CH = "0b00";
|
||||
parameter D_SETIRPOLY_AUX = "0b00";
|
||||
parameter D_SETIRPOLY_CH = "0b00";
|
||||
parameter D_SETPLLRC = "0b000000";
|
||||
parameter D_SYNC_LOCAL_EN = "0b0";
|
||||
parameter D_SYNC_ND_EN = "0b0";
|
||||
parameter D_TXPLL_PWDNB = "0b0";
|
||||
parameter D_TX_VCO_CK_DIV = "0b000";
|
||||
parameter D_XGE_MODE = "0b0";
|
||||
|
||||
// These parameters don't do anything but are
|
||||
// needed for compatability with Diamond
|
||||
parameter D_TX_MAX_RATE = "2.5";
|
||||
parameter D_RX_MAX_RATE = "2.5";
|
||||
parameter CH0_TXAMPLITUDE = "0d1300";
|
||||
parameter CH1_TXAMPLITUDE = "0d1300";
|
||||
parameter CH0_PROTOCOL = "8B10B";
|
||||
parameter CH1_PROTOCOL = "8B10B";
|
||||
parameter CH0_CDR_MAX_RATE = "2.5";
|
||||
parameter CH1_CDR_MAX_RATE = "2.5";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module EXTREFB (
|
||||
input REFCLKP, REFCLKN,
|
||||
output REFCLKO
|
||||
);
|
||||
parameter REFCK_PWDNB = "0b0";
|
||||
parameter REFCK_RTERM = "0b0";
|
||||
parameter REFCK_DCBIAS_EN = "0b0";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module PCSCLKDIV (
|
||||
input CLKI, RST, SEL2, SEL1, SEL0,
|
||||
output CDIV1, CDIVX
|
||||
);
|
||||
parameter GSR = "DISABLED";
|
||||
endmodule
|
|
@ -7,40 +7,40 @@ module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .C
|
|||
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_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 \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .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("INV"), .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("INV"), .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("INV"), .REGSET("SET"), .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("DISABLED"), .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_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_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_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_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_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_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 \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .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("INV"), .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("INV"), .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("INV"), .REGSET("SET"), .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("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_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_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_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_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_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_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_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 \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .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("INV"), .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("INV"), .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("INV"), .REGSET("SET"), .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("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_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_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_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_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_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_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_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 \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .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("INV"), .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("INV"), .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("INV"), .REGSET("SET"), .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("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_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_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_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_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_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
|
||||
|
|
|
@ -257,7 +257,7 @@ assign O = I;
|
|||
endmodule
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
(* keep *)
|
||||
module TRELLIS_IO(
|
||||
inout B,
|
||||
input I,
|
||||
|
@ -265,16 +265,18 @@ module TRELLIS_IO(
|
|||
output O
|
||||
);
|
||||
parameter DIR = "INPUT";
|
||||
reg T_pd;
|
||||
always @(*) if (T === 1'bz) T_pd <= 1'b0; else T_pd <= T;
|
||||
|
||||
generate
|
||||
if (DIR == "INPUT") begin
|
||||
assign B = 1'bz;
|
||||
assign O = B;
|
||||
end else if (DIR == "OUTPUT") begin
|
||||
assign B = T ? 1'bz : I;
|
||||
assign B = T_pd ? 1'bz : I;
|
||||
assign O = 1'bx;
|
||||
end else if (DIR == "INOUT") begin
|
||||
assign B = T ? 1'bz : I;
|
||||
end else if (DIR == "BIDIR") begin
|
||||
assign B = T_pd ? 1'bz : I;
|
||||
assign O = B;
|
||||
end else begin
|
||||
ERROR_UNKNOWN_IO_MODE error();
|
||||
|
@ -446,3 +448,102 @@ module TRELLIS_SLICE(
|
|||
);
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module DP16KD(
|
||||
input DIA17, DIA16, DIA15, DIA14, DIA13, DIA12, DIA11, DIA10, DIA9, DIA8, DIA7, DIA6, DIA5, DIA4, DIA3, DIA2, DIA1, DIA0,
|
||||
input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0,
|
||||
input CEA, OCEA, CLKA, WEA, RSTA,
|
||||
input CSA2, CSA1, CSA0,
|
||||
output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0,
|
||||
|
||||
input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0,
|
||||
input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0,
|
||||
input CEB, OCEB, CLKB, WEB, RSTB,
|
||||
input CSB2, CSB1, CSB0,
|
||||
output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
|
||||
);
|
||||
parameter DATA_WIDTH_A = 18;
|
||||
parameter DATA_WIDTH_B = 18;
|
||||
|
||||
parameter REGMODE_A = "NOREG";
|
||||
parameter REGMODE_B = "NOREG";
|
||||
|
||||
parameter RESETMODE = "SYNC";
|
||||
parameter ASYNC_RESET_RELEASE = "SYNC";
|
||||
|
||||
parameter CSDECODE_A = "0b000";
|
||||
parameter CSDECODE_B = "0b000";
|
||||
|
||||
parameter WRITEMODE_A = "NORMAL";
|
||||
parameter WRITEMODE_B = "NORMAL";
|
||||
|
||||
parameter CLKAMUX = "CLKA";
|
||||
parameter CLKBMUX = "CLKB";
|
||||
|
||||
parameter GSR = "ENABLED";
|
||||
|
||||
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
endmodule
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
module \$_DLATCH_N_ (E, D, Q);
|
||||
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
|
||||
input E, D;
|
||||
output Q = !E ? D : Q;
|
||||
endmodule
|
||||
|
||||
module \$_DLATCH_P_ (E, D, Q);
|
||||
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
|
||||
input E, D;
|
||||
output Q = E ? D : Q;
|
||||
endmodule
|
|
@ -203,7 +203,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
{
|
||||
if (check_label("begin"))
|
||||
{
|
||||
run("read_verilog -lib +/ecp5/cells_sim.v");
|
||||
run("read_verilog -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
|
||||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||
}
|
||||
|
||||
|
@ -222,11 +222,8 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
|
||||
if (!nobram && check_label("bram", "(skip if -nobram)"))
|
||||
{
|
||||
//TODO
|
||||
#if 0
|
||||
run("memory_bram -rules +/ecp5/brams.txt");
|
||||
run("memory_bram -rules +/ecp5/bram.txt");
|
||||
run("techmap -map +/ecp5/brams_map.v");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!nodram && check_label("dram", "(skip if -nodram)"))
|
||||
|
@ -269,10 +266,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
if (abc2 || help_mode) {
|
||||
run("abc", " (only if -abc2)");
|
||||
}
|
||||
//TODO
|
||||
#if 0
|
||||
run("techmap -map +/ecp5/latches_map.v");
|
||||
#endif
|
||||
if (nomux)
|
||||
run("abc -lut 4");
|
||||
else
|
||||
|
|
|
@ -3,4 +3,5 @@ OBJS += techlibs/gowin/synth_gowin.o
|
|||
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v))
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||
* Copyright (C) 2018 David Shah <dave@ds0.me>
|
||||
*
|
||||
* 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_gw1n_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 _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 = {CO, CI};
|
||||
|
||||
genvar i;
|
||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
||||
ALU #(.ALU_MODE(32'b0))
|
||||
alu(.I0(AA[i]),
|
||||
.I1(BB[i]),
|
||||
.I3(1'b0),
|
||||
.CIN(C[i]),
|
||||
.COUT(CO[i]),
|
||||
.SUM(Y[i])
|
||||
);
|
||||
end endgenerate
|
||||
assign X = AA ^ BB;
|
||||
endmodule
|
||||
|
|
@ -57,3 +57,9 @@ endmodule
|
|||
module GSR (input GSRI);
|
||||
wire GSRO = GSRI;
|
||||
endmodule
|
||||
|
||||
module ALU (input I0, input I1, input I3, input CIN, output COUT, output SUM);
|
||||
parameter [3:0] ALU_MODE = 0; // default 0 = ADD
|
||||
assign {COUT, SUM} = CIN + I1 + I0;
|
||||
endmodule // alu
|
||||
|
||||
|
|
|
@ -49,6 +49,9 @@ struct SynthGowinPass : public ScriptPass
|
|||
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(" -nobram\n");
|
||||
log(" do not use BRAM cells in output netlist\n");
|
||||
log("\n");
|
||||
log(" -retime\n");
|
||||
log(" run 'abc' with -dff option\n");
|
||||
log("\n");
|
||||
|
@ -59,13 +62,14 @@ struct SynthGowinPass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, vout_file;
|
||||
bool retime;
|
||||
bool retime, nobram;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
top_opt = "-auto-top";
|
||||
vout_file = "";
|
||||
retime = false;
|
||||
nobram = true;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -96,6 +100,10 @@ struct SynthGowinPass : public ScriptPass
|
|||
retime = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nobram") {
|
||||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -119,7 +127,7 @@ struct SynthGowinPass : public ScriptPass
|
|||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||
}
|
||||
|
||||
if (check_label("flatten"))
|
||||
if (check_label("flatten") && check_label("flatten", "(unless -noflatten)"))
|
||||
{
|
||||
run("proc");
|
||||
run("flatten");
|
||||
|
@ -131,13 +139,18 @@ struct SynthGowinPass : public ScriptPass
|
|||
{
|
||||
run("synth -run coarse");
|
||||
}
|
||||
|
||||
if (!nobram && check_label("bram", "(skip if -nobram)"))
|
||||
{
|
||||
run("memory_bram -rules +/gowin/bram.txt");
|
||||
run("techmap -map +/gowin/brams_map.v");
|
||||
}
|
||||
if (check_label("fine"))
|
||||
{
|
||||
run("opt -fast -mux_undef -undriven -fine");
|
||||
run("memory_map");
|
||||
run("opt -undriven -fine");
|
||||
run("techmap");
|
||||
run("techmap -map +/techmap.v -map +/gowin/arith_map.v");
|
||||
run("opt -fine");
|
||||
run("clean -purge");
|
||||
run("splitnets -ports");
|
||||
run("setundef -undriven -zero");
|
||||
|
|
|
@ -3,6 +3,7 @@ OBJS += techlibs/ice40/synth_ice40.o
|
|||
OBJS += techlibs/ice40/ice40_ffssr.o
|
||||
OBJS += techlibs/ice40/ice40_ffinit.o
|
||||
OBJS += techlibs/ice40/ice40_opt.o
|
||||
OBJS += techlibs/ice40/ice40_unlut.o
|
||||
|
||||
GENFILES += techlibs/ice40/brams_init1.vh
|
||||
GENFILES += techlibs/ice40/brams_init2.vh
|
||||
|
|
|
@ -409,6 +409,7 @@ module SB_RAM40_4K (
|
|||
|
||||
initial begin
|
||||
for (i=0; i<16; i=i+1) begin
|
||||
`ifdef YOSYS
|
||||
memory[ 0*16 + i] <= INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] <= INIT_1[16*i +: 16];
|
||||
memory[ 2*16 + i] <= INIT_2[16*i +: 16];
|
||||
|
@ -425,6 +426,24 @@ module SB_RAM40_4K (
|
|||
memory[13*16 + i] <= INIT_D[16*i +: 16];
|
||||
memory[14*16 + i] <= INIT_E[16*i +: 16];
|
||||
memory[15*16 + i] <= INIT_F[16*i +: 16];
|
||||
`else
|
||||
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
||||
memory[ 2*16 + i] = INIT_2[16*i +: 16];
|
||||
memory[ 3*16 + i] = INIT_3[16*i +: 16];
|
||||
memory[ 4*16 + i] = INIT_4[16*i +: 16];
|
||||
memory[ 5*16 + i] = INIT_5[16*i +: 16];
|
||||
memory[ 6*16 + i] = INIT_6[16*i +: 16];
|
||||
memory[ 7*16 + i] = INIT_7[16*i +: 16];
|
||||
memory[ 8*16 + i] = INIT_8[16*i +: 16];
|
||||
memory[ 9*16 + i] = INIT_9[16*i +: 16];
|
||||
memory[10*16 + i] = INIT_A[16*i +: 16];
|
||||
memory[11*16 + i] = INIT_B[16*i +: 16];
|
||||
memory[12*16 + i] = INIT_C[16*i +: 16];
|
||||
memory[13*16 + i] = INIT_D[16*i +: 16];
|
||||
memory[14*16 + i] = INIT_E[16*i +: 16];
|
||||
memory[15*16 + i] = INIT_F[16*i +: 16];
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -928,6 +947,7 @@ module SB_SPRAM256KA (
|
|||
output reg [15:0] DATAOUT
|
||||
);
|
||||
`ifndef BLACKBOX
|
||||
`ifndef EQUIV
|
||||
reg [15:0] mem [0:16383];
|
||||
wire off = SLEEP || !POWEROFF;
|
||||
integer i;
|
||||
|
@ -954,6 +974,7 @@ module SB_SPRAM256KA (
|
|||
end
|
||||
end
|
||||
`endif
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
|
|
|
@ -81,6 +81,9 @@ struct Ice40FfssrPass : public Pass {
|
|||
|
||||
for (auto cell : ff_cells)
|
||||
{
|
||||
if (cell->get_bool_attribute("\\dont_touch"))
|
||||
continue;
|
||||
|
||||
SigSpec sig_d = cell->getPort("\\D");
|
||||
|
||||
if (GetSize(sig_d) < 1)
|
||||
|
|
|
@ -33,7 +33,7 @@ static SigBit get_bit_or_zero(const SigSpec &sig)
|
|||
return sig[0];
|
||||
}
|
||||
|
||||
static void run_ice40_opts(Module *module, bool unlut_mode)
|
||||
static void run_ice40_opts(Module *module)
|
||||
{
|
||||
pool<SigBit> optimized_co;
|
||||
vector<Cell*> sb_lut_cells;
|
||||
|
@ -95,9 +95,6 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
|
|||
inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
|
||||
sigmap.apply(inbits);
|
||||
|
||||
if (unlut_mode)
|
||||
goto remap_lut;
|
||||
|
||||
if (optimized_co.count(inbits[0])) goto remap_lut;
|
||||
if (optimized_co.count(inbits[1])) goto remap_lut;
|
||||
if (optimized_co.count(inbits[2])) goto remap_lut;
|
||||
|
@ -152,14 +149,10 @@ struct Ice40OptPass : public Pass {
|
|||
log(" opt_clean\n");
|
||||
log(" while <changed design>\n");
|
||||
log("\n");
|
||||
log("When called with the option -unlut, this command will transform all already\n");
|
||||
log("mapped SB_LUT4 cells back to logic.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
string opt_expr_args = "-mux_undef -undriven";
|
||||
bool unlut_mode = false;
|
||||
|
||||
log_header(design, "Executing ICE40_OPT pass (performing simple optimizations).\n");
|
||||
log_push();
|
||||
|
@ -170,10 +163,6 @@ struct Ice40OptPass : public Pass {
|
|||
opt_expr_args += " -full";
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-unlut") {
|
||||
unlut_mode = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -184,7 +173,7 @@ struct Ice40OptPass : public Pass {
|
|||
|
||||
log_header(design, "Running ICE40 specific optimizations.\n");
|
||||
for (auto module : design->selected_modules())
|
||||
run_ice40_opts(module, unlut_mode);
|
||||
run_ice40_opts(module);
|
||||
|
||||
Pass::call(design, "opt_expr " + opt_expr_args);
|
||||
Pass::call(design, "opt_merge");
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* 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"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.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 run_ice40_unlut(Module *module)
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type == "\\SB_LUT4")
|
||||
{
|
||||
SigSpec inbits;
|
||||
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
|
||||
sigmap.apply(inbits);
|
||||
|
||||
log("Mapping SB_LUT4 cell %s.%s to $lut.\n", log_id(module), log_id(cell));
|
||||
|
||||
cell->type ="$lut";
|
||||
cell->setParam("\\WIDTH", 4);
|
||||
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
|
||||
cell->unsetParam("\\LUT_INIT");
|
||||
|
||||
cell->setPort("\\A", SigSpec({
|
||||
get_bit_or_zero(cell->getPort("\\I3")),
|
||||
get_bit_or_zero(cell->getPort("\\I2")),
|
||||
get_bit_or_zero(cell->getPort("\\I1")),
|
||||
get_bit_or_zero(cell->getPort("\\I0"))
|
||||
}));
|
||||
cell->setPort("\\Y", cell->getPort("\\O")[0]);
|
||||
cell->unsetPort("\\I0");
|
||||
cell->unsetPort("\\I1");
|
||||
cell->unsetPort("\\I2");
|
||||
cell->unsetPort("\\I3");
|
||||
cell->unsetPort("\\O");
|
||||
|
||||
cell->check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Ice40UnlutPass : public Pass {
|
||||
Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: perform simple optimizations") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" ice40_unlut [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This command transforms all SB_LUT4 cells to generic $lut cells.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing ICE40_UNLUT pass (convert SB_LUT4 to $lut).\n");
|
||||
log_push();
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
// if (args[argidx] == "-???") {
|
||||
// continue;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
run_ice40_unlut(module);
|
||||
}
|
||||
} Ice40UnlutPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -63,15 +63,25 @@ struct SynthIce40Pass : public ScriptPass
|
|||
log(" -retime\n");
|
||||
log(" run 'abc' with -dff option\n");
|
||||
log("\n");
|
||||
log(" -relut\n");
|
||||
log(" combine LUTs after synthesis\n");
|
||||
log("\n");
|
||||
log(" -nocarry\n");
|
||||
log(" do not use SB_CARRY cells in output netlist\n");
|
||||
log("\n");
|
||||
log(" -nodffe\n");
|
||||
log(" do not use SB_DFFE* cells in output netlist\n");
|
||||
log("\n");
|
||||
log(" -dffe_min_ce_use <min_ce_use>\n");
|
||||
log(" do not use SB_DFFE* cells if the resulting CE line would go to less\n");
|
||||
log(" than min_ce_use SB_DFFE*in output netlist\n");
|
||||
log("\n");
|
||||
log(" -nobram\n");
|
||||
log(" do not use SB_RAM40_4K* cells in output netlist\n");
|
||||
log("\n");
|
||||
log(" -noabc\n");
|
||||
log(" use built-in Yosys LUT techmapping instead of abc\n");
|
||||
log("\n");
|
||||
log(" -abc2\n");
|
||||
log(" run two passes of 'abc' for slightly improved logic density\n");
|
||||
log("\n");
|
||||
|
@ -86,7 +96,8 @@ struct SynthIce40Pass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, blif_file, edif_file, json_file;
|
||||
bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
|
||||
bool nocarry, nodffe, nobram, flatten, retime, relut, noabc, abc2, vpr;
|
||||
int min_ce_use;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
|
@ -96,9 +107,12 @@ struct SynthIce40Pass : public ScriptPass
|
|||
json_file = "";
|
||||
nocarry = false;
|
||||
nodffe = false;
|
||||
min_ce_use = -1;
|
||||
nobram = false;
|
||||
flatten = true;
|
||||
retime = false;
|
||||
relut = false;
|
||||
noabc = false;
|
||||
abc2 = false;
|
||||
vpr = false;
|
||||
}
|
||||
|
@ -147,6 +161,10 @@ struct SynthIce40Pass : public ScriptPass
|
|||
retime = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-relut") {
|
||||
relut = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nocarry") {
|
||||
nocarry = true;
|
||||
continue;
|
||||
|
@ -155,10 +173,18 @@ struct SynthIce40Pass : public ScriptPass
|
|||
nodffe = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
|
||||
min_ce_use = std::stoi(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nobram") {
|
||||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noabc") {
|
||||
noabc = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-abc2") {
|
||||
abc2 = true;
|
||||
continue;
|
||||
|
@ -209,11 +235,15 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run("techmap -map +/ice40/brams_map.v");
|
||||
}
|
||||
|
||||
if (check_label("fine"))
|
||||
if (check_label("map"))
|
||||
{
|
||||
run("opt -fast -mux_undef -undriven -fine");
|
||||
run("memory_map");
|
||||
run("opt -undriven -fine");
|
||||
}
|
||||
|
||||
if (check_label("map_gates"))
|
||||
{
|
||||
if (nocarry)
|
||||
run("techmap");
|
||||
else
|
||||
|
@ -228,6 +258,10 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run("dffsr2dff");
|
||||
if (!nodffe)
|
||||
run("dff2dffe -direct-match $_DFF_*");
|
||||
if (min_ce_use >= 0) {
|
||||
run("opt_merge");
|
||||
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
|
||||
}
|
||||
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
|
||||
run("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
|
@ -243,8 +277,18 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run("ice40_opt", "(only if -abc2)");
|
||||
}
|
||||
run("techmap -map +/ice40/latches_map.v");
|
||||
run("abc -lut 4");
|
||||
if (noabc || help_mode) {
|
||||
run("simplemap", " (only if -noabc)");
|
||||
run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
|
||||
}
|
||||
if (!noabc) {
|
||||
run("abc -lut 4", "(skip if -noabc)");
|
||||
}
|
||||
run("clean");
|
||||
if (relut || help_mode) {
|
||||
run("ice40_unlut", " (only if -relut)");
|
||||
run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3", "(only if -relut)");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("map_cells"))
|
||||
|
|
|
@ -2,8 +2,8 @@ module \$__M9K_ALTSYNCRAM_SINGLEPORT_FULL (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1A
|
|||
|
||||
parameter CFG_ABITS = 8;
|
||||
parameter CFG_DBITS = 36;
|
||||
parameter ABITS = "1";
|
||||
parameter DBITS = "1";
|
||||
parameter ABITS = 1;
|
||||
parameter DBITS = 1;
|
||||
parameter CLKPOL2 = 1;
|
||||
parameter CLKPOL3 = 1;
|
||||
|
||||
|
@ -63,21 +63,21 @@ module \$__M9K_ALTSYNCRAM_SINGLEPORT_FULL (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1A
|
|||
.width_byteena_a (1), // Forced value
|
||||
.numwords_b ( NUMWORDS ),
|
||||
.numwords_a ( NUMWORDS ),
|
||||
.widthad_b ( CFG_ABITS ),
|
||||
.width_b ( CFG_DBITS ),
|
||||
.widthad_a ( CFG_ABITS ),
|
||||
.width_a ( CFG_DBITS )
|
||||
.widthad_b ( CFG_DBITS ),
|
||||
.width_b ( CFG_ABITS ),
|
||||
.widthad_a ( CFG_DBITS ),
|
||||
.width_a ( CFG_ABITS )
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.data_a(B1DATA),
|
||||
.address_a(B1ADDR),
|
||||
.wren_a(B1EN),
|
||||
.rden_a(A1EN),
|
||||
.q_a(A1DATA),
|
||||
.data_b(1'b0),
|
||||
.data_b(B1DATA),
|
||||
.address_b(0),
|
||||
.wren_b(1'b0),
|
||||
.rden_b(1'b0),
|
||||
.q_b(1'b0),
|
||||
.q_b(),
|
||||
.clock0(CLK2),
|
||||
.clock1(1'b1), // Unused in single port mode
|
||||
.clocken0(1'b1),
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
OBJS += techlibs/sf2/synth_sf2.o
|
||||
|
||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
|
||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
|
||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_sim.v))
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// nothing here yet
|
|
@ -0,0 +1,68 @@
|
|||
// module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
|
||||
|
||||
module \$_DFF_P_ (input D, C, output Q);
|
||||
SLE _TECHMAP_REPLACE_ (
|
||||
.D(D),
|
||||
.CLK(C),
|
||||
.EN(1'b1),
|
||||
.ALn(1'b1),
|
||||
.ADn(1'b1),
|
||||
.SLn(1'b1),
|
||||
.SD(1'b0),
|
||||
.LAT(1'b0),
|
||||
.Q(Q)
|
||||
);
|
||||
endmodule
|
||||
|
||||
// module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||
// module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||
//
|
||||
// module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||
// module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||
//
|
||||
// module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
||||
// module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
||||
// module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
||||
// module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
||||
//
|
||||
// module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
||||
// module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
||||
// module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
||||
// module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
||||
//
|
||||
// module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||
// module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||
// module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||
// module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||
//
|
||||
// module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||
// module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
||||
// module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||
// module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); 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
|
||||
CFG1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]));
|
||||
end else
|
||||
if (WIDTH == 2) begin
|
||||
CFG2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]));
|
||||
end else
|
||||
if (WIDTH == 3) begin
|
||||
CFG3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]), .C(A[2]));
|
||||
end else
|
||||
if (WIDTH == 4) begin
|
||||
CFG4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
|
||||
end else begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
`endif
|
|
@ -0,0 +1,75 @@
|
|||
module SLE (
|
||||
output Q,
|
||||
input ADn,
|
||||
input ALn,
|
||||
input CLK,
|
||||
input D,
|
||||
input LAT,
|
||||
input SD,
|
||||
input EN,
|
||||
input SLn
|
||||
);
|
||||
reg q_latch, q_ff;
|
||||
|
||||
always @(posedge CLK, negedge ALn) begin
|
||||
if (!ALn) begin
|
||||
q_ff <= !ADn;
|
||||
end else if (EN) begin
|
||||
if (!SLn)
|
||||
q_ff <= SD;
|
||||
else
|
||||
q_ff <= D;
|
||||
end
|
||||
end
|
||||
|
||||
always @* begin
|
||||
if (!ALn) begin
|
||||
q_latch <= !ADn;
|
||||
end else if (CLK && EN) begin
|
||||
if (!SLn)
|
||||
q_ff <= SD;
|
||||
else
|
||||
q_ff <= D;
|
||||
end
|
||||
end
|
||||
|
||||
assign Q = LAT ? q_latch : q_ff;
|
||||
endmodule
|
||||
|
||||
module CFG1 (
|
||||
output Y,
|
||||
input A
|
||||
);
|
||||
parameter [1:0] INIT = 2'h0;
|
||||
assign Y = INIT >> A;
|
||||
endmodule
|
||||
|
||||
module CFG2 (
|
||||
output Y,
|
||||
input A,
|
||||
input B
|
||||
);
|
||||
parameter [3:0] INIT = 4'h0;
|
||||
assign Y = INIT >> {B, A};
|
||||
endmodule
|
||||
|
||||
module CFG3 (
|
||||
output Y,
|
||||
input A,
|
||||
input B,
|
||||
input C
|
||||
);
|
||||
parameter [7:0] INIT = 8'h0;
|
||||
assign Y = INIT >> {C, B, A};
|
||||
endmodule
|
||||
|
||||
module CFG4 (
|
||||
output Y,
|
||||
input A,
|
||||
input B,
|
||||
input C,
|
||||
input D
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0;
|
||||
assign Y = INIT >> {D, C, B, A};
|
||||
endmodule
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* 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/register.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct SynthSf2Pass : public ScriptPass
|
||||
{
|
||||
SynthSf2Pass() : ScriptPass("synth_sf2", "synthesis for SmartFusion2 and IGLOO2 FPGAs") { }
|
||||
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" synth_sf2 [options]\n");
|
||||
log("\n");
|
||||
log("This command runs synthesis for SmartFusion2 and IGLOO2 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 comannd only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_SF2 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 +/sf2/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("fine"))
|
||||
{
|
||||
run("opt -fast -mux_undef -undriven -fine");
|
||||
run("memory_map");
|
||||
run("opt -undriven -fine");
|
||||
run("techmap -map +/techmap.v -map +/sf2/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 +/sf2/cells_map.v");
|
||||
run("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
// run("sf2_ffinit");
|
||||
// run("sf2_ffssr");
|
||||
// run("sf2_opt -full");
|
||||
}
|
||||
|
||||
if (check_label("map_luts"))
|
||||
{
|
||||
run("abc -lut 4");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label("map_cells"))
|
||||
{
|
||||
run("techmap -map +/sf2/cells_map.v");
|
||||
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()));
|
||||
}
|
||||
}
|
||||
} SynthSf2Pass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -112,6 +112,7 @@ function xtract_cell_decl()
|
|||
xtract_cell_decl PHY_CONTROL
|
||||
xtract_cell_decl PLLE2_ADV
|
||||
xtract_cell_decl PLLE2_BASE
|
||||
xtract_cell_decl PS7
|
||||
xtract_cell_decl PULLDOWN
|
||||
xtract_cell_decl PULLUP
|
||||
# xtract_cell_decl RAM128X1D
|
||||
|
|
|
@ -3057,6 +3057,629 @@ module PLLE2_BASE (...);
|
|||
input RST;
|
||||
endmodule
|
||||
|
||||
module PS7 (...);
|
||||
output DMA0DAVALID;
|
||||
output DMA0DRREADY;
|
||||
output DMA0RSTN;
|
||||
output DMA1DAVALID;
|
||||
output DMA1DRREADY;
|
||||
output DMA1RSTN;
|
||||
output DMA2DAVALID;
|
||||
output DMA2DRREADY;
|
||||
output DMA2RSTN;
|
||||
output DMA3DAVALID;
|
||||
output DMA3DRREADY;
|
||||
output DMA3RSTN;
|
||||
output EMIOCAN0PHYTX;
|
||||
output EMIOCAN1PHYTX;
|
||||
output EMIOENET0GMIITXEN;
|
||||
output EMIOENET0GMIITXER;
|
||||
output EMIOENET0MDIOMDC;
|
||||
output EMIOENET0MDIOO;
|
||||
output EMIOENET0MDIOTN;
|
||||
output EMIOENET0PTPDELAYREQRX;
|
||||
output EMIOENET0PTPDELAYREQTX;
|
||||
output EMIOENET0PTPPDELAYREQRX;
|
||||
output EMIOENET0PTPPDELAYREQTX;
|
||||
output EMIOENET0PTPPDELAYRESPRX;
|
||||
output EMIOENET0PTPPDELAYRESPTX;
|
||||
output EMIOENET0PTPSYNCFRAMERX;
|
||||
output EMIOENET0PTPSYNCFRAMETX;
|
||||
output EMIOENET0SOFRX;
|
||||
output EMIOENET0SOFTX;
|
||||
output EMIOENET1GMIITXEN;
|
||||
output EMIOENET1GMIITXER;
|
||||
output EMIOENET1MDIOMDC;
|
||||
output EMIOENET1MDIOO;
|
||||
output EMIOENET1MDIOTN;
|
||||
output EMIOENET1PTPDELAYREQRX;
|
||||
output EMIOENET1PTPDELAYREQTX;
|
||||
output EMIOENET1PTPPDELAYREQRX;
|
||||
output EMIOENET1PTPPDELAYREQTX;
|
||||
output EMIOENET1PTPPDELAYRESPRX;
|
||||
output EMIOENET1PTPPDELAYRESPTX;
|
||||
output EMIOENET1PTPSYNCFRAMERX;
|
||||
output EMIOENET1PTPSYNCFRAMETX;
|
||||
output EMIOENET1SOFRX;
|
||||
output EMIOENET1SOFTX;
|
||||
output EMIOI2C0SCLO;
|
||||
output EMIOI2C0SCLTN;
|
||||
output EMIOI2C0SDAO;
|
||||
output EMIOI2C0SDATN;
|
||||
output EMIOI2C1SCLO;
|
||||
output EMIOI2C1SCLTN;
|
||||
output EMIOI2C1SDAO;
|
||||
output EMIOI2C1SDATN;
|
||||
output EMIOPJTAGTDO;
|
||||
output EMIOPJTAGTDTN;
|
||||
output EMIOSDIO0BUSPOW;
|
||||
output EMIOSDIO0CLK;
|
||||
output EMIOSDIO0CMDO;
|
||||
output EMIOSDIO0CMDTN;
|
||||
output EMIOSDIO0LED;
|
||||
output EMIOSDIO1BUSPOW;
|
||||
output EMIOSDIO1CLK;
|
||||
output EMIOSDIO1CMDO;
|
||||
output EMIOSDIO1CMDTN;
|
||||
output EMIOSDIO1LED;
|
||||
output EMIOSPI0MO;
|
||||
output EMIOSPI0MOTN;
|
||||
output EMIOSPI0SCLKO;
|
||||
output EMIOSPI0SCLKTN;
|
||||
output EMIOSPI0SO;
|
||||
output EMIOSPI0SSNTN;
|
||||
output EMIOSPI0STN;
|
||||
output EMIOSPI1MO;
|
||||
output EMIOSPI1MOTN;
|
||||
output EMIOSPI1SCLKO;
|
||||
output EMIOSPI1SCLKTN;
|
||||
output EMIOSPI1SO;
|
||||
output EMIOSPI1SSNTN;
|
||||
output EMIOSPI1STN;
|
||||
output EMIOTRACECTL;
|
||||
output EMIOUART0DTRN;
|
||||
output EMIOUART0RTSN;
|
||||
output EMIOUART0TX;
|
||||
output EMIOUART1DTRN;
|
||||
output EMIOUART1RTSN;
|
||||
output EMIOUART1TX;
|
||||
output EMIOUSB0VBUSPWRSELECT;
|
||||
output EMIOUSB1VBUSPWRSELECT;
|
||||
output EMIOWDTRSTO;
|
||||
output EVENTEVENTO;
|
||||
output MAXIGP0ARESETN;
|
||||
output MAXIGP0ARVALID;
|
||||
output MAXIGP0AWVALID;
|
||||
output MAXIGP0BREADY;
|
||||
output MAXIGP0RREADY;
|
||||
output MAXIGP0WLAST;
|
||||
output MAXIGP0WVALID;
|
||||
output MAXIGP1ARESETN;
|
||||
output MAXIGP1ARVALID;
|
||||
output MAXIGP1AWVALID;
|
||||
output MAXIGP1BREADY;
|
||||
output MAXIGP1RREADY;
|
||||
output MAXIGP1WLAST;
|
||||
output MAXIGP1WVALID;
|
||||
output SAXIACPARESETN;
|
||||
output SAXIACPARREADY;
|
||||
output SAXIACPAWREADY;
|
||||
output SAXIACPBVALID;
|
||||
output SAXIACPRLAST;
|
||||
output SAXIACPRVALID;
|
||||
output SAXIACPWREADY;
|
||||
output SAXIGP0ARESETN;
|
||||
output SAXIGP0ARREADY;
|
||||
output SAXIGP0AWREADY;
|
||||
output SAXIGP0BVALID;
|
||||
output SAXIGP0RLAST;
|
||||
output SAXIGP0RVALID;
|
||||
output SAXIGP0WREADY;
|
||||
output SAXIGP1ARESETN;
|
||||
output SAXIGP1ARREADY;
|
||||
output SAXIGP1AWREADY;
|
||||
output SAXIGP1BVALID;
|
||||
output SAXIGP1RLAST;
|
||||
output SAXIGP1RVALID;
|
||||
output SAXIGP1WREADY;
|
||||
output SAXIHP0ARESETN;
|
||||
output SAXIHP0ARREADY;
|
||||
output SAXIHP0AWREADY;
|
||||
output SAXIHP0BVALID;
|
||||
output SAXIHP0RLAST;
|
||||
output SAXIHP0RVALID;
|
||||
output SAXIHP0WREADY;
|
||||
output SAXIHP1ARESETN;
|
||||
output SAXIHP1ARREADY;
|
||||
output SAXIHP1AWREADY;
|
||||
output SAXIHP1BVALID;
|
||||
output SAXIHP1RLAST;
|
||||
output SAXIHP1RVALID;
|
||||
output SAXIHP1WREADY;
|
||||
output SAXIHP2ARESETN;
|
||||
output SAXIHP2ARREADY;
|
||||
output SAXIHP2AWREADY;
|
||||
output SAXIHP2BVALID;
|
||||
output SAXIHP2RLAST;
|
||||
output SAXIHP2RVALID;
|
||||
output SAXIHP2WREADY;
|
||||
output SAXIHP3ARESETN;
|
||||
output SAXIHP3ARREADY;
|
||||
output SAXIHP3AWREADY;
|
||||
output SAXIHP3BVALID;
|
||||
output SAXIHP3RLAST;
|
||||
output SAXIHP3RVALID;
|
||||
output SAXIHP3WREADY;
|
||||
output [11:0] MAXIGP0ARID;
|
||||
output [11:0] MAXIGP0AWID;
|
||||
output [11:0] MAXIGP0WID;
|
||||
output [11:0] MAXIGP1ARID;
|
||||
output [11:0] MAXIGP1AWID;
|
||||
output [11:0] MAXIGP1WID;
|
||||
output [1:0] DMA0DATYPE;
|
||||
output [1:0] DMA1DATYPE;
|
||||
output [1:0] DMA2DATYPE;
|
||||
output [1:0] DMA3DATYPE;
|
||||
output [1:0] EMIOUSB0PORTINDCTL;
|
||||
output [1:0] EMIOUSB1PORTINDCTL;
|
||||
output [1:0] EVENTSTANDBYWFE;
|
||||
output [1:0] EVENTSTANDBYWFI;
|
||||
output [1:0] MAXIGP0ARBURST;
|
||||
output [1:0] MAXIGP0ARLOCK;
|
||||
output [1:0] MAXIGP0ARSIZE;
|
||||
output [1:0] MAXIGP0AWBURST;
|
||||
output [1:0] MAXIGP0AWLOCK;
|
||||
output [1:0] MAXIGP0AWSIZE;
|
||||
output [1:0] MAXIGP1ARBURST;
|
||||
output [1:0] MAXIGP1ARLOCK;
|
||||
output [1:0] MAXIGP1ARSIZE;
|
||||
output [1:0] MAXIGP1AWBURST;
|
||||
output [1:0] MAXIGP1AWLOCK;
|
||||
output [1:0] MAXIGP1AWSIZE;
|
||||
output [1:0] SAXIACPBRESP;
|
||||
output [1:0] SAXIACPRRESP;
|
||||
output [1:0] SAXIGP0BRESP;
|
||||
output [1:0] SAXIGP0RRESP;
|
||||
output [1:0] SAXIGP1BRESP;
|
||||
output [1:0] SAXIGP1RRESP;
|
||||
output [1:0] SAXIHP0BRESP;
|
||||
output [1:0] SAXIHP0RRESP;
|
||||
output [1:0] SAXIHP1BRESP;
|
||||
output [1:0] SAXIHP1RRESP;
|
||||
output [1:0] SAXIHP2BRESP;
|
||||
output [1:0] SAXIHP2RRESP;
|
||||
output [1:0] SAXIHP3BRESP;
|
||||
output [1:0] SAXIHP3RRESP;
|
||||
output [28:0] IRQP2F;
|
||||
output [2:0] EMIOSDIO0BUSVOLT;
|
||||
output [2:0] EMIOSDIO1BUSVOLT;
|
||||
output [2:0] EMIOSPI0SSON;
|
||||
output [2:0] EMIOSPI1SSON;
|
||||
output [2:0] EMIOTTC0WAVEO;
|
||||
output [2:0] EMIOTTC1WAVEO;
|
||||
output [2:0] MAXIGP0ARPROT;
|
||||
output [2:0] MAXIGP0AWPROT;
|
||||
output [2:0] MAXIGP1ARPROT;
|
||||
output [2:0] MAXIGP1AWPROT;
|
||||
output [2:0] SAXIACPBID;
|
||||
output [2:0] SAXIACPRID;
|
||||
output [2:0] SAXIHP0RACOUNT;
|
||||
output [2:0] SAXIHP1RACOUNT;
|
||||
output [2:0] SAXIHP2RACOUNT;
|
||||
output [2:0] SAXIHP3RACOUNT;
|
||||
output [31:0] EMIOTRACEDATA;
|
||||
output [31:0] FTMTP2FDEBUG;
|
||||
output [31:0] MAXIGP0ARADDR;
|
||||
output [31:0] MAXIGP0AWADDR;
|
||||
output [31:0] MAXIGP0WDATA;
|
||||
output [31:0] MAXIGP1ARADDR;
|
||||
output [31:0] MAXIGP1AWADDR;
|
||||
output [31:0] MAXIGP1WDATA;
|
||||
output [31:0] SAXIGP0RDATA;
|
||||
output [31:0] SAXIGP1RDATA;
|
||||
output [3:0] EMIOSDIO0DATAO;
|
||||
output [3:0] EMIOSDIO0DATATN;
|
||||
output [3:0] EMIOSDIO1DATAO;
|
||||
output [3:0] EMIOSDIO1DATATN;
|
||||
output [3:0] FCLKCLK;
|
||||
output [3:0] FCLKRESETN;
|
||||
output [3:0] FTMTF2PTRIGACK;
|
||||
output [3:0] FTMTP2FTRIG;
|
||||
output [3:0] MAXIGP0ARCACHE;
|
||||
output [3:0] MAXIGP0ARLEN;
|
||||
output [3:0] MAXIGP0ARQOS;
|
||||
output [3:0] MAXIGP0AWCACHE;
|
||||
output [3:0] MAXIGP0AWLEN;
|
||||
output [3:0] MAXIGP0AWQOS;
|
||||
output [3:0] MAXIGP0WSTRB;
|
||||
output [3:0] MAXIGP1ARCACHE;
|
||||
output [3:0] MAXIGP1ARLEN;
|
||||
output [3:0] MAXIGP1ARQOS;
|
||||
output [3:0] MAXIGP1AWCACHE;
|
||||
output [3:0] MAXIGP1AWLEN;
|
||||
output [3:0] MAXIGP1AWQOS;
|
||||
output [3:0] MAXIGP1WSTRB;
|
||||
output [5:0] SAXIGP0BID;
|
||||
output [5:0] SAXIGP0RID;
|
||||
output [5:0] SAXIGP1BID;
|
||||
output [5:0] SAXIGP1RID;
|
||||
output [5:0] SAXIHP0BID;
|
||||
output [5:0] SAXIHP0RID;
|
||||
output [5:0] SAXIHP0WACOUNT;
|
||||
output [5:0] SAXIHP1BID;
|
||||
output [5:0] SAXIHP1RID;
|
||||
output [5:0] SAXIHP1WACOUNT;
|
||||
output [5:0] SAXIHP2BID;
|
||||
output [5:0] SAXIHP2RID;
|
||||
output [5:0] SAXIHP2WACOUNT;
|
||||
output [5:0] SAXIHP3BID;
|
||||
output [5:0] SAXIHP3RID;
|
||||
output [5:0] SAXIHP3WACOUNT;
|
||||
output [63:0] EMIOGPIOO;
|
||||
output [63:0] EMIOGPIOTN;
|
||||
output [63:0] SAXIACPRDATA;
|
||||
output [63:0] SAXIHP0RDATA;
|
||||
output [63:0] SAXIHP1RDATA;
|
||||
output [63:0] SAXIHP2RDATA;
|
||||
output [63:0] SAXIHP3RDATA;
|
||||
output [7:0] EMIOENET0GMIITXD;
|
||||
output [7:0] EMIOENET1GMIITXD;
|
||||
output [7:0] SAXIHP0RCOUNT;
|
||||
output [7:0] SAXIHP0WCOUNT;
|
||||
output [7:0] SAXIHP1RCOUNT;
|
||||
output [7:0] SAXIHP1WCOUNT;
|
||||
output [7:0] SAXIHP2RCOUNT;
|
||||
output [7:0] SAXIHP2WCOUNT;
|
||||
output [7:0] SAXIHP3RCOUNT;
|
||||
output [7:0] SAXIHP3WCOUNT;
|
||||
inout DDRCASB;
|
||||
inout DDRCKE;
|
||||
inout DDRCKN;
|
||||
inout DDRCKP;
|
||||
inout DDRCSB;
|
||||
inout DDRDRSTB;
|
||||
inout DDRODT;
|
||||
inout DDRRASB;
|
||||
inout DDRVRN;
|
||||
inout DDRVRP;
|
||||
inout DDRWEB;
|
||||
inout PSCLK;
|
||||
inout PSPORB;
|
||||
inout PSSRSTB;
|
||||
inout [14:0] DDRA;
|
||||
inout [2:0] DDRBA;
|
||||
inout [31:0] DDRDQ;
|
||||
inout [3:0] DDRDM;
|
||||
inout [3:0] DDRDQSN;
|
||||
inout [3:0] DDRDQSP;
|
||||
inout [53:0] MIO;
|
||||
input DMA0ACLK;
|
||||
input DMA0DAREADY;
|
||||
input DMA0DRLAST;
|
||||
input DMA0DRVALID;
|
||||
input DMA1ACLK;
|
||||
input DMA1DAREADY;
|
||||
input DMA1DRLAST;
|
||||
input DMA1DRVALID;
|
||||
input DMA2ACLK;
|
||||
input DMA2DAREADY;
|
||||
input DMA2DRLAST;
|
||||
input DMA2DRVALID;
|
||||
input DMA3ACLK;
|
||||
input DMA3DAREADY;
|
||||
input DMA3DRLAST;
|
||||
input DMA3DRVALID;
|
||||
input EMIOCAN0PHYRX;
|
||||
input EMIOCAN1PHYRX;
|
||||
input EMIOENET0EXTINTIN;
|
||||
input EMIOENET0GMIICOL;
|
||||
input EMIOENET0GMIICRS;
|
||||
input EMIOENET0GMIIRXCLK;
|
||||
input EMIOENET0GMIIRXDV;
|
||||
input EMIOENET0GMIIRXER;
|
||||
input EMIOENET0GMIITXCLK;
|
||||
input EMIOENET0MDIOI;
|
||||
input EMIOENET1EXTINTIN;
|
||||
input EMIOENET1GMIICOL;
|
||||
input EMIOENET1GMIICRS;
|
||||
input EMIOENET1GMIIRXCLK;
|
||||
input EMIOENET1GMIIRXDV;
|
||||
input EMIOENET1GMIIRXER;
|
||||
input EMIOENET1GMIITXCLK;
|
||||
input EMIOENET1MDIOI;
|
||||
input EMIOI2C0SCLI;
|
||||
input EMIOI2C0SDAI;
|
||||
input EMIOI2C1SCLI;
|
||||
input EMIOI2C1SDAI;
|
||||
input EMIOPJTAGTCK;
|
||||
input EMIOPJTAGTDI;
|
||||
input EMIOPJTAGTMS;
|
||||
input EMIOSDIO0CDN;
|
||||
input EMIOSDIO0CLKFB;
|
||||
input EMIOSDIO0CMDI;
|
||||
input EMIOSDIO0WP;
|
||||
input EMIOSDIO1CDN;
|
||||
input EMIOSDIO1CLKFB;
|
||||
input EMIOSDIO1CMDI;
|
||||
input EMIOSDIO1WP;
|
||||
input EMIOSPI0MI;
|
||||
input EMIOSPI0SCLKI;
|
||||
input EMIOSPI0SI;
|
||||
input EMIOSPI0SSIN;
|
||||
input EMIOSPI1MI;
|
||||
input EMIOSPI1SCLKI;
|
||||
input EMIOSPI1SI;
|
||||
input EMIOSPI1SSIN;
|
||||
input EMIOSRAMINTIN;
|
||||
input EMIOTRACECLK;
|
||||
input EMIOUART0CTSN;
|
||||
input EMIOUART0DCDN;
|
||||
input EMIOUART0DSRN;
|
||||
input EMIOUART0RIN;
|
||||
input EMIOUART0RX;
|
||||
input EMIOUART1CTSN;
|
||||
input EMIOUART1DCDN;
|
||||
input EMIOUART1DSRN;
|
||||
input EMIOUART1RIN;
|
||||
input EMIOUART1RX;
|
||||
input EMIOUSB0VBUSPWRFAULT;
|
||||
input EMIOUSB1VBUSPWRFAULT;
|
||||
input EMIOWDTCLKI;
|
||||
input EVENTEVENTI;
|
||||
input FPGAIDLEN;
|
||||
input FTMDTRACEINCLOCK;
|
||||
input FTMDTRACEINVALID;
|
||||
input MAXIGP0ACLK;
|
||||
input MAXIGP0ARREADY;
|
||||
input MAXIGP0AWREADY;
|
||||
input MAXIGP0BVALID;
|
||||
input MAXIGP0RLAST;
|
||||
input MAXIGP0RVALID;
|
||||
input MAXIGP0WREADY;
|
||||
input MAXIGP1ACLK;
|
||||
input MAXIGP1ARREADY;
|
||||
input MAXIGP1AWREADY;
|
||||
input MAXIGP1BVALID;
|
||||
input MAXIGP1RLAST;
|
||||
input MAXIGP1RVALID;
|
||||
input MAXIGP1WREADY;
|
||||
input SAXIACPACLK;
|
||||
input SAXIACPARVALID;
|
||||
input SAXIACPAWVALID;
|
||||
input SAXIACPBREADY;
|
||||
input SAXIACPRREADY;
|
||||
input SAXIACPWLAST;
|
||||
input SAXIACPWVALID;
|
||||
input SAXIGP0ACLK;
|
||||
input SAXIGP0ARVALID;
|
||||
input SAXIGP0AWVALID;
|
||||
input SAXIGP0BREADY;
|
||||
input SAXIGP0RREADY;
|
||||
input SAXIGP0WLAST;
|
||||
input SAXIGP0WVALID;
|
||||
input SAXIGP1ACLK;
|
||||
input SAXIGP1ARVALID;
|
||||
input SAXIGP1AWVALID;
|
||||
input SAXIGP1BREADY;
|
||||
input SAXIGP1RREADY;
|
||||
input SAXIGP1WLAST;
|
||||
input SAXIGP1WVALID;
|
||||
input SAXIHP0ACLK;
|
||||
input SAXIHP0ARVALID;
|
||||
input SAXIHP0AWVALID;
|
||||
input SAXIHP0BREADY;
|
||||
input SAXIHP0RDISSUECAP1EN;
|
||||
input SAXIHP0RREADY;
|
||||
input SAXIHP0WLAST;
|
||||
input SAXIHP0WRISSUECAP1EN;
|
||||
input SAXIHP0WVALID;
|
||||
input SAXIHP1ACLK;
|
||||
input SAXIHP1ARVALID;
|
||||
input SAXIHP1AWVALID;
|
||||
input SAXIHP1BREADY;
|
||||
input SAXIHP1RDISSUECAP1EN;
|
||||
input SAXIHP1RREADY;
|
||||
input SAXIHP1WLAST;
|
||||
input SAXIHP1WRISSUECAP1EN;
|
||||
input SAXIHP1WVALID;
|
||||
input SAXIHP2ACLK;
|
||||
input SAXIHP2ARVALID;
|
||||
input SAXIHP2AWVALID;
|
||||
input SAXIHP2BREADY;
|
||||
input SAXIHP2RDISSUECAP1EN;
|
||||
input SAXIHP2RREADY;
|
||||
input SAXIHP2WLAST;
|
||||
input SAXIHP2WRISSUECAP1EN;
|
||||
input SAXIHP2WVALID;
|
||||
input SAXIHP3ACLK;
|
||||
input SAXIHP3ARVALID;
|
||||
input SAXIHP3AWVALID;
|
||||
input SAXIHP3BREADY;
|
||||
input SAXIHP3RDISSUECAP1EN;
|
||||
input SAXIHP3RREADY;
|
||||
input SAXIHP3WLAST;
|
||||
input SAXIHP3WRISSUECAP1EN;
|
||||
input SAXIHP3WVALID;
|
||||
input [11:0] MAXIGP0BID;
|
||||
input [11:0] MAXIGP0RID;
|
||||
input [11:0] MAXIGP1BID;
|
||||
input [11:0] MAXIGP1RID;
|
||||
input [19:0] IRQF2P;
|
||||
input [1:0] DMA0DRTYPE;
|
||||
input [1:0] DMA1DRTYPE;
|
||||
input [1:0] DMA2DRTYPE;
|
||||
input [1:0] DMA3DRTYPE;
|
||||
input [1:0] MAXIGP0BRESP;
|
||||
input [1:0] MAXIGP0RRESP;
|
||||
input [1:0] MAXIGP1BRESP;
|
||||
input [1:0] MAXIGP1RRESP;
|
||||
input [1:0] SAXIACPARBURST;
|
||||
input [1:0] SAXIACPARLOCK;
|
||||
input [1:0] SAXIACPARSIZE;
|
||||
input [1:0] SAXIACPAWBURST;
|
||||
input [1:0] SAXIACPAWLOCK;
|
||||
input [1:0] SAXIACPAWSIZE;
|
||||
input [1:0] SAXIGP0ARBURST;
|
||||
input [1:0] SAXIGP0ARLOCK;
|
||||
input [1:0] SAXIGP0ARSIZE;
|
||||
input [1:0] SAXIGP0AWBURST;
|
||||
input [1:0] SAXIGP0AWLOCK;
|
||||
input [1:0] SAXIGP0AWSIZE;
|
||||
input [1:0] SAXIGP1ARBURST;
|
||||
input [1:0] SAXIGP1ARLOCK;
|
||||
input [1:0] SAXIGP1ARSIZE;
|
||||
input [1:0] SAXIGP1AWBURST;
|
||||
input [1:0] SAXIGP1AWLOCK;
|
||||
input [1:0] SAXIGP1AWSIZE;
|
||||
input [1:0] SAXIHP0ARBURST;
|
||||
input [1:0] SAXIHP0ARLOCK;
|
||||
input [1:0] SAXIHP0ARSIZE;
|
||||
input [1:0] SAXIHP0AWBURST;
|
||||
input [1:0] SAXIHP0AWLOCK;
|
||||
input [1:0] SAXIHP0AWSIZE;
|
||||
input [1:0] SAXIHP1ARBURST;
|
||||
input [1:0] SAXIHP1ARLOCK;
|
||||
input [1:0] SAXIHP1ARSIZE;
|
||||
input [1:0] SAXIHP1AWBURST;
|
||||
input [1:0] SAXIHP1AWLOCK;
|
||||
input [1:0] SAXIHP1AWSIZE;
|
||||
input [1:0] SAXIHP2ARBURST;
|
||||
input [1:0] SAXIHP2ARLOCK;
|
||||
input [1:0] SAXIHP2ARSIZE;
|
||||
input [1:0] SAXIHP2AWBURST;
|
||||
input [1:0] SAXIHP2AWLOCK;
|
||||
input [1:0] SAXIHP2AWSIZE;
|
||||
input [1:0] SAXIHP3ARBURST;
|
||||
input [1:0] SAXIHP3ARLOCK;
|
||||
input [1:0] SAXIHP3ARSIZE;
|
||||
input [1:0] SAXIHP3AWBURST;
|
||||
input [1:0] SAXIHP3AWLOCK;
|
||||
input [1:0] SAXIHP3AWSIZE;
|
||||
input [2:0] EMIOTTC0CLKI;
|
||||
input [2:0] EMIOTTC1CLKI;
|
||||
input [2:0] SAXIACPARID;
|
||||
input [2:0] SAXIACPARPROT;
|
||||
input [2:0] SAXIACPAWID;
|
||||
input [2:0] SAXIACPAWPROT;
|
||||
input [2:0] SAXIACPWID;
|
||||
input [2:0] SAXIGP0ARPROT;
|
||||
input [2:0] SAXIGP0AWPROT;
|
||||
input [2:0] SAXIGP1ARPROT;
|
||||
input [2:0] SAXIGP1AWPROT;
|
||||
input [2:0] SAXIHP0ARPROT;
|
||||
input [2:0] SAXIHP0AWPROT;
|
||||
input [2:0] SAXIHP1ARPROT;
|
||||
input [2:0] SAXIHP1AWPROT;
|
||||
input [2:0] SAXIHP2ARPROT;
|
||||
input [2:0] SAXIHP2AWPROT;
|
||||
input [2:0] SAXIHP3ARPROT;
|
||||
input [2:0] SAXIHP3AWPROT;
|
||||
input [31:0] FTMDTRACEINDATA;
|
||||
input [31:0] FTMTF2PDEBUG;
|
||||
input [31:0] MAXIGP0RDATA;
|
||||
input [31:0] MAXIGP1RDATA;
|
||||
input [31:0] SAXIACPARADDR;
|
||||
input [31:0] SAXIACPAWADDR;
|
||||
input [31:0] SAXIGP0ARADDR;
|
||||
input [31:0] SAXIGP0AWADDR;
|
||||
input [31:0] SAXIGP0WDATA;
|
||||
input [31:0] SAXIGP1ARADDR;
|
||||
input [31:0] SAXIGP1AWADDR;
|
||||
input [31:0] SAXIGP1WDATA;
|
||||
input [31:0] SAXIHP0ARADDR;
|
||||
input [31:0] SAXIHP0AWADDR;
|
||||
input [31:0] SAXIHP1ARADDR;
|
||||
input [31:0] SAXIHP1AWADDR;
|
||||
input [31:0] SAXIHP2ARADDR;
|
||||
input [31:0] SAXIHP2AWADDR;
|
||||
input [31:0] SAXIHP3ARADDR;
|
||||
input [31:0] SAXIHP3AWADDR;
|
||||
input [3:0] DDRARB;
|
||||
input [3:0] EMIOSDIO0DATAI;
|
||||
input [3:0] EMIOSDIO1DATAI;
|
||||
input [3:0] FCLKCLKTRIGN;
|
||||
input [3:0] FTMDTRACEINATID;
|
||||
input [3:0] FTMTF2PTRIG;
|
||||
input [3:0] FTMTP2FTRIGACK;
|
||||
input [3:0] SAXIACPARCACHE;
|
||||
input [3:0] SAXIACPARLEN;
|
||||
input [3:0] SAXIACPARQOS;
|
||||
input [3:0] SAXIACPAWCACHE;
|
||||
input [3:0] SAXIACPAWLEN;
|
||||
input [3:0] SAXIACPAWQOS;
|
||||
input [3:0] SAXIGP0ARCACHE;
|
||||
input [3:0] SAXIGP0ARLEN;
|
||||
input [3:0] SAXIGP0ARQOS;
|
||||
input [3:0] SAXIGP0AWCACHE;
|
||||
input [3:0] SAXIGP0AWLEN;
|
||||
input [3:0] SAXIGP0AWQOS;
|
||||
input [3:0] SAXIGP0WSTRB;
|
||||
input [3:0] SAXIGP1ARCACHE;
|
||||
input [3:0] SAXIGP1ARLEN;
|
||||
input [3:0] SAXIGP1ARQOS;
|
||||
input [3:0] SAXIGP1AWCACHE;
|
||||
input [3:0] SAXIGP1AWLEN;
|
||||
input [3:0] SAXIGP1AWQOS;
|
||||
input [3:0] SAXIGP1WSTRB;
|
||||
input [3:0] SAXIHP0ARCACHE;
|
||||
input [3:0] SAXIHP0ARLEN;
|
||||
input [3:0] SAXIHP0ARQOS;
|
||||
input [3:0] SAXIHP0AWCACHE;
|
||||
input [3:0] SAXIHP0AWLEN;
|
||||
input [3:0] SAXIHP0AWQOS;
|
||||
input [3:0] SAXIHP1ARCACHE;
|
||||
input [3:0] SAXIHP1ARLEN;
|
||||
input [3:0] SAXIHP1ARQOS;
|
||||
input [3:0] SAXIHP1AWCACHE;
|
||||
input [3:0] SAXIHP1AWLEN;
|
||||
input [3:0] SAXIHP1AWQOS;
|
||||
input [3:0] SAXIHP2ARCACHE;
|
||||
input [3:0] SAXIHP2ARLEN;
|
||||
input [3:0] SAXIHP2ARQOS;
|
||||
input [3:0] SAXIHP2AWCACHE;
|
||||
input [3:0] SAXIHP2AWLEN;
|
||||
input [3:0] SAXIHP2AWQOS;
|
||||
input [3:0] SAXIHP3ARCACHE;
|
||||
input [3:0] SAXIHP3ARLEN;
|
||||
input [3:0] SAXIHP3ARQOS;
|
||||
input [3:0] SAXIHP3AWCACHE;
|
||||
input [3:0] SAXIHP3AWLEN;
|
||||
input [3:0] SAXIHP3AWQOS;
|
||||
input [4:0] SAXIACPARUSER;
|
||||
input [4:0] SAXIACPAWUSER;
|
||||
input [5:0] SAXIGP0ARID;
|
||||
input [5:0] SAXIGP0AWID;
|
||||
input [5:0] SAXIGP0WID;
|
||||
input [5:0] SAXIGP1ARID;
|
||||
input [5:0] SAXIGP1AWID;
|
||||
input [5:0] SAXIGP1WID;
|
||||
input [5:0] SAXIHP0ARID;
|
||||
input [5:0] SAXIHP0AWID;
|
||||
input [5:0] SAXIHP0WID;
|
||||
input [5:0] SAXIHP1ARID;
|
||||
input [5:0] SAXIHP1AWID;
|
||||
input [5:0] SAXIHP1WID;
|
||||
input [5:0] SAXIHP2ARID;
|
||||
input [5:0] SAXIHP2AWID;
|
||||
input [5:0] SAXIHP2WID;
|
||||
input [5:0] SAXIHP3ARID;
|
||||
input [5:0] SAXIHP3AWID;
|
||||
input [5:0] SAXIHP3WID;
|
||||
input [63:0] EMIOGPIOI;
|
||||
input [63:0] SAXIACPWDATA;
|
||||
input [63:0] SAXIHP0WDATA;
|
||||
input [63:0] SAXIHP1WDATA;
|
||||
input [63:0] SAXIHP2WDATA;
|
||||
input [63:0] SAXIHP3WDATA;
|
||||
input [7:0] EMIOENET0GMIIRXD;
|
||||
input [7:0] EMIOENET1GMIIRXD;
|
||||
input [7:0] SAXIACPWSTRB;
|
||||
input [7:0] SAXIHP0WSTRB;
|
||||
input [7:0] SAXIHP1WSTRB;
|
||||
input [7:0] SAXIHP2WSTRB;
|
||||
input [7:0] SAXIHP3WSTRB;
|
||||
endmodule
|
||||
|
||||
module PULLDOWN (...);
|
||||
output O;
|
||||
endmodule
|
||||
|
|
|
@ -235,10 +235,9 @@ struct SynthXilinxPass : public Pass
|
|||
|
||||
if (check_label(active, run_from, run_to, "map_cells"))
|
||||
{
|
||||
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
|
||||
if (vpr)
|
||||
Pass::call(design, "techmap -D NO_LUT -map +/xilinx/cells_map.v");
|
||||
else
|
||||
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
|
||||
Pass::call(design, "techmap -map +/xilinx/lut2lut.v");
|
||||
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
|
||||
Pass::call(design, "clean");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module a;
|
||||
integer [31:0]w;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module a;
|
||||
task to (
|
||||
input integer [3:0]x
|
||||
);
|
||||
endtask
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module a;
|
||||
task to (
|
||||
input [3]x
|
||||
);
|
||||
endtask
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module a;
|
||||
wire [3]x;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module a;
|
||||
input x[2:0];
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
module a;
|
||||
initial
|
||||
begin : label1
|
||||
end: label2
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
module a;
|
||||
wire [5:0]x;
|
||||
wire [3:0]y;
|
||||
assign y = (4)55;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
module a;
|
||||
wire [5:0]x;
|
||||
wire [3:0]y;
|
||||
assign y = x 55;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
module a(input wire x = 1'b0);
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
module a;
|
||||
parameter integer [2:0]x=0;
|
||||
endmodule
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue