aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile42
-rw-r--r--README.md8
-rw-r--r--frontends/ast/simplify.cc16
-rw-r--r--passes/sat/sim.cc2
-rw-r--r--passes/techmap/abc9.cc37
-rw-r--r--techlibs/xilinx/cells_sim.v201
-rw-r--r--techlibs/xilinx/cells_xtra.py26
-rw-r--r--techlibs/xilinx/cells_xtra.v139
-rw-r--r--techlibs/xilinx/xilinx_dffopt.cc46
-rw-r--r--tests/simple/mem_arst.v4
-rw-r--r--tests/various/bug1531.ys34
11 files changed, 339 insertions, 216 deletions
diff --git a/Makefile b/Makefile
index e268a4281..2a3332af9 100644
--- a/Makefile
+++ b/Makefile
@@ -152,7 +152,15 @@ ifeq ($(ENABLE_PYOSYS),1)
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
-PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix)
+
+ENABLE_PYTHON_CONFIG_EMBED ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1)
+ifeq ($(ENABLE_PYTHON_CONFIG_EMBED),1)
+PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config --embed
+else
+PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config
+endif
+
+PYTHON_PREFIX := $(shell $(PYTHON_CONFIG) --prefix)
PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
# Reload Makefile.conf to override python specific variables if defined
@@ -305,17 +313,17 @@ ifeq ($(ENABLE_PYOSYS),1)
#Detect name of boost_python library. Some distros usbe boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
ifeq ($(OS), Darwin)
BOOST_PYTHON_LIB ?= $(shell \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
echo ""; fi; fi; fi; fi;)
else
BOOST_PYTHON_LIB ?= $(shell \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
+ if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
echo ""; fi; fi; fi; fi;)
endif
@@ -325,19 +333,19 @@ endif
ifeq ($(OS), Darwin)
ifeq ($(PYTHON_MAJOR_VERSION),3)
-LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
+LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
+CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
else
-LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
+LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
+CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
endif
else
ifeq ($(PYTHON_MAJOR_VERSION),3)
-LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
+LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
+CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
else
-LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
+LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
+CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
endif
endif
diff --git a/README.md b/README.md
index 5cc52e842..0250c7846 100644
--- a/README.md
+++ b/README.md
@@ -454,10 +454,10 @@ Verilog Attributes and non-standard features
expressions over parameters and constant values are allowed). The intended
use for this is synthesis-time DRC.
-- There is limited support for converting specify .. endspecify statements to
- special ``$specify2``, ``$specify3``, and ``$specrule`` cells, for use in
- blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this
- functionality. (By default specify .. endspecify blocks are ignored.)
+- There is limited support for converting ``specify`` .. ``endspecify``
+ statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells,
+ for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to
+ enable this functionality. (By default these blocks are ignored.)
Non-standard or SystemVerilog features for formal verification
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 44fd32cdc..b94a8d710 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1198,6 +1198,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
varbuf = new AstNode(AST_LOCALPARAM, varbuf);
varbuf->str = init_ast->children[0]->str;
+ auto resolved = current_scope.at(init_ast->children[0]->str);
+ if (resolved->range_valid) {
+ varbuf->range_left = resolved->range_left;
+ varbuf->range_right = resolved->range_right;
+ varbuf->range_swapped = resolved->range_swapped;
+ varbuf->range_valid = resolved->range_valid;
+ }
+
AstNode *backup_scope_varbuf = current_scope[varbuf->str];
current_scope[varbuf->str] = varbuf;
@@ -2998,6 +3006,14 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
current_ast_mod->children.push_back(p);
str = p->str;
id2ast = p;
+
+ auto resolved = current_scope.at(index_var);
+ if (resolved->range_valid) {
+ p->range_left = resolved->range_left;
+ p->range_right = resolved->range_right;
+ p->range_swapped = resolved->range_swapped;
+ p->range_valid = resolved->range_valid;
+ }
}
}
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index 4c3022c70..d5634b26d 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -230,7 +230,7 @@ struct SimInstance
bool did_something = false;
sig = sigmap(sig);
- log_assert(GetSize(sig) == GetSize(value));
+ log_assert(GetSize(sig) <= GetSize(value));
for (int i = 0; i < GetSize(sig); i++)
if (state_nets.at(sig[i]) != value[i]) {
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 2bf495ec4..def347c21 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -912,29 +912,28 @@ struct Abc9Pass : public Pass {
//}
if (arg == "-lut" && argidx+1 < args.size()) {
string arg = args[++argidx];
- size_t pos = arg.find_first_of(':');
- int lut_mode = 0, lut_mode2 = 0;
- if (pos != string::npos) {
- lut_mode = atoi(arg.substr(0, pos).c_str());
- lut_mode2 = atoi(arg.substr(pos+1).c_str());
- } else {
- pos = arg.find_first_of('.');
+ if (arg.find_first_not_of("0123456789:") == std::string::npos) {
+ size_t pos = arg.find_first_of(':');
+ int lut_mode = 0, lut_mode2 = 0;
if (pos != string::npos) {
- lut_file = arg;
- rewrite_filename(lut_file);
- if (!lut_file.empty() && !is_absolute_path(lut_file))
- lut_file = std::string(pwd) + "/" + lut_file;
- }
- else {
+ lut_mode = atoi(arg.substr(0, pos).c_str());
+ lut_mode2 = atoi(arg.substr(pos+1).c_str());
+ } else {
lut_mode = atoi(arg.c_str());
lut_mode2 = lut_mode;
}
+ lut_costs.clear();
+ for (int i = 0; i < lut_mode; i++)
+ lut_costs.push_back(1);
+ for (int i = lut_mode; i < lut_mode2; i++)
+ lut_costs.push_back(2 << (i - lut_mode));
+ }
+ else {
+ lut_file = arg;
+ rewrite_filename(lut_file);
+ if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
+ lut_file = std::string(pwd) + "/" + lut_file;
}
- lut_costs.clear();
- for (int i = 0; i < lut_mode; i++)
- lut_costs.push_back(1);
- for (int i = lut_mode; i < lut_mode2; i++)
- lut_costs.push_back(2 << (i - lut_mode));
continue;
}
if (arg == "-luts" && argidx+1 < args.size()) {
@@ -1003,7 +1002,7 @@ struct Abc9Pass : public Pass {
box_file = "+/dummy.box";
rewrite_filename(box_file);
- if (!box_file.empty() && !is_absolute_path(box_file))
+ if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+')
box_file = std::string(pwd) + "/" + box_file;
dict<int,IdString> box_lookup;
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index d7dff8975..5d589bd2f 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -227,6 +227,14 @@ module MUXCY(output O, input CI, DI, S);
assign O = S ? CI : DI;
endmodule
+module MUXF5(output O, input I0, I1, S);
+ assign O = S ? I1 : I0;
+endmodule
+
+module MUXF6(output O, input I0, I1, S);
+ assign O = S ? I1 : I0;
+endmodule
+
(* abc9_box_id = 1, lib_whitebox *)
module MUXF7(output O, input I0, I1, S);
assign O = S ? I1 : I0;
@@ -237,6 +245,10 @@ module MUXF8(output O, input I0, I1, S);
assign O = S ? I1 : I0;
endmodule
+module MUXF9(output O, input I0, I1, S);
+ assign O = S ? I1 : I0;
+endmodule
+
module XORCY(output O, input CI, LI);
assign O = CI ^ LI;
endmodule
@@ -258,6 +270,26 @@ module CARRY4(
assign CO[3] = S[3] ? CO[2] : DI[3];
endmodule
+module CARRY8(
+ output [7:0] CO,
+ output [7:0] O,
+ input CI,
+ input CI_TOP,
+ input [7:0] DI, S
+);
+ parameter CARRY_TYPE = "SINGLE_CY8";
+ wire CI4 = (CARRY_TYPE == "DUAL_CY4" ? CI_TOP : CO[3]);
+ assign O = S ^ {CO[6:4], CI4, CO[2:0], CI};
+ assign CO[0] = S[0] ? CI : DI[0];
+ assign CO[1] = S[1] ? CO[0] : DI[1];
+ assign CO[2] = S[2] ? CO[1] : DI[2];
+ assign CO[3] = S[3] ? CO[2] : DI[3];
+ assign CO[4] = S[4] ? CI4 : DI[4];
+ assign CO[5] = S[5] ? CO[4] : DI[5];
+ assign CO[6] = S[6] ? CO[5] : DI[6];
+ assign CO[7] = S[7] ? CO[6] : DI[7];
+endmodule
+
`ifdef _EXPLICIT_CARRY
module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
@@ -281,6 +313,16 @@ endmodule
`endif
+module ORCY (output O, input CI, I);
+ assign O = CI | I;
+endmodule
+
+module MULT_AND (output LO, input I0, I1);
+ assign LO = I0 & I1;
+endmodule
+
+// Flip-flops and latches.
+
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250
(* abc9_box_id=1100, lib_whitebox, abc9_flop *)
@@ -394,6 +436,51 @@ module FDCE_1 (
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
endmodule
+module FDCPE (
+ output wire Q,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_C_INVERTED" *)
+ input C,
+ input CE,
+ (* invertible_pin = "IS_CLR_INVERTED" *)
+ input CLR,
+ input D,
+ (* invertible_pin = "IS_PRE_INVERTED" *)
+ input PRE
+);
+ parameter [0:0] INIT = 1'b0;
+ parameter [0:0] IS_C_INVERTED = 1'b0;
+ parameter [0:0] IS_CLR_INVERTED = 1'b0;
+ parameter [0:0] IS_PRE_INVERTED = 1'b0;
+ wire c = C ^ IS_C_INVERTED;
+ wire clr = CLR ^ IS_CLR_INVERTED;
+ wire pre = PRE ^ IS_PRE_INVERTED;
+ // Hacky model to avoid simulation-synthesis mismatches.
+ reg qc, qp, qs;
+ initial qc = INIT;
+ initial qp = INIT;
+ initial qs = 0;
+ always @(posedge c, posedge clr) begin
+ if (clr)
+ qc <= 0;
+ else if (CE)
+ qc <= D;
+ end
+ always @(posedge c, posedge pre) begin
+ if (pre)
+ qp <= 1;
+ else if (CE)
+ qp <= D;
+ end
+ always @* begin
+ if (clr)
+ qs <= 0;
+ else if (pre)
+ qs <= 1;
+ end
+ assign Q = qs ? qp : qc;
+endmodule
+
(* abc9_box_id=1104, lib_whitebox, abc9_flop *)
module FDPE (
(* abc9_arrival=303 *)
@@ -488,8 +575,8 @@ module LDCE (
wire clr = CLR ^ IS_CLR_INVERTED;
wire g = G ^ IS_G_INVERTED;
always @*
- if (clr) Q = 1'b0;
- else if (GE && g) Q = D;
+ if (clr) Q <= 1'b0;
+ else if (GE && g) Q <= D;
endmodule
module LDPE (
@@ -510,8 +597,59 @@ module LDPE (
wire g = G ^ IS_G_INVERTED;
wire pre = PRE ^ IS_PRE_INVERTED;
always @*
- if (pre) Q = 1'b1;
- else if (GE && g) Q = D;
+ if (pre) Q <= 1'b1;
+ else if (GE && g) Q <= D;
+endmodule
+
+module LDCPE (
+ output reg Q,
+ (* invertible_pin = "IS_CLR_INVERTED" *)
+ input CLR,
+ (* invertible_pin = "IS_D_INVERTED" *)
+ input D,
+ (* invertible_pin = "IS_G_INVERTED" *)
+ input G,
+ (* invertible_pin = "IS_GE_INVERTED" *)
+ input GE,
+ (* invertible_pin = "IS_PRE_INVERTED" *)
+ input PRE
+);
+ parameter [0:0] INIT = 1'b1;
+ parameter [0:0] IS_CLR_INVERTED = 1'b0;
+ parameter [0:0] IS_D_INVERTED = 1'b0;
+ parameter [0:0] IS_G_INVERTED = 1'b0;
+ parameter [0:0] IS_GE_INVERTED = 1'b0;
+ parameter [0:0] IS_PRE_INVERTED = 1'b0;
+ initial Q = INIT;
+ wire d = D ^ IS_D_INVERTED;
+ wire g = G ^ IS_G_INVERTED;
+ wire ge = GE ^ IS_GE_INVERTED;
+ wire clr = CLR ^ IS_CLR_INVERTED;
+ wire pre = PRE ^ IS_PRE_INVERTED;
+ always @*
+ if (clr) Q <= 1'b0;
+ else if (pre) Q <= 1'b1;
+ else if (ge && g) Q <= d;
+endmodule
+
+module AND2B1L (
+ output O,
+ input DI,
+ (* invertible_pin = "IS_SRI_INVERTED" *)
+ input SRI
+);
+ parameter [0:0] IS_SRI_INVERTED = 1'b0;
+ assign O = DI & ~(SRI ^ IS_SRI_INVERTED);
+endmodule
+
+module OR2L (
+ output O,
+ input DI,
+ (* invertible_pin = "IS_SRI_INVERTED" *)
+ input SRI
+);
+ parameter [0:0] IS_SRI_INVERTED = 1'b0;
+ assign O = DI | (SRI ^ IS_SRI_INVERTED);
endmodule
// LUTRAM.
@@ -1377,6 +1515,20 @@ endmodule
// Shift registers.
+module SRL16 (
+ output Q,
+ input A0, A1, A2, A3,
+ (* clkbuf_sink *)
+ input CLK,
+ input D
+);
+ parameter [15:0] INIT = 16'h0000;
+
+ reg [15:0] r = INIT;
+ assign Q = r[{A3,A2,A1,A0}];
+ always @(posedge CLK) r <= { r[14:0], D };
+endmodule
+
module SRL16E (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
(* abc9_arrival=1472 *)
@@ -1401,6 +1553,22 @@ module SRL16E (
endgenerate
endmodule
+module SRLC16 (
+ output Q,
+ output Q15,
+ input A0, A1, A2, A3,
+ (* clkbuf_sink *)
+ input CLK,
+ input D
+);
+ parameter [15:0] INIT = 16'h0000;
+
+ reg [15:0] r = INIT;
+ assign Q15 = r[15];
+ assign Q = r[{A3,A2,A1,A0}];
+ always @(posedge CLK) r <= { r[14:0], D };
+endmodule
+
module SRLC16E (
output Q,
output Q15,
@@ -1453,6 +1621,31 @@ module SRLC32E (
endgenerate
endmodule
+module CFGLUT5 (
+ output CDO,
+ output O5,
+ output O6,
+ input I4,
+ input I3,
+ input I2,
+ input I1,
+ input I0,
+ input CDI,
+ input CE,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_CLK_INVERTED" *)
+ input CLK
+);
+ parameter [31:0] INIT = 32'h00000000;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+ wire clk = CLK ^ IS_CLK_INVERTED;
+ reg [31:0] r = INIT;
+ assign CDO = r[31];
+ assign O5 = r[{1'b0, I3, I2, I1, I0}];
+ assign O6 = r[{I4, I3, I2, I1, I0}];
+ always @(posedge clk) if (CE) r <= {r[30:0], CDI};
+endmodule
+
// DSP
// Virtex 2, Virtex 2 Pro, Spartan 3.
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index 6d5adf1aa..d5c58c5d7 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -65,9 +65,9 @@ CELLS = [
# CLB -- registers/latches.
# Virtex 1/2/4/5, Spartan 3.
- Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}),
+ # Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}),
# Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}),
- Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}),
+ # Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}),
# Virtex 6, Spartan 6, Series 7, Ultrascale.
# Cell('FDCE'),
# Cell('FDPE'),
@@ -75,8 +75,8 @@ CELLS = [
# Cell('FDSE'),
# Cell('LDCE'),
# Cell('LDPE'),
- Cell('AND2B1L'),
- Cell('OR2L'),
+ # Cell('AND2B1L'),
+ # Cell('OR2L'),
# CLB -- other.
# Cell('LUT1'),
@@ -86,23 +86,23 @@ CELLS = [
# Cell('LUT5'),
# Cell('LUT6'),
# Cell('LUT6_2'),
- Cell('MUXF5'),
- Cell('MUXF6'),
+ # Cell('MUXF5'),
+ # Cell('MUXF6'),
# Cell('MUXF7'),
# Cell('MUXF8'),
- Cell('MUXF9'),
+ # Cell('MUXF9'),
# Cell('CARRY4'),
- Cell('CARRY8'),
+ # Cell('CARRY8'),
# Cell('MUXCY'),
# Cell('XORCY'),
- Cell('ORCY'),
- Cell('MULT_AND'),
- Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}),
+ # Cell('ORCY'),
+ # Cell('MULT_AND'),
+ # Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}),
- Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}),
+ # Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRLC16E', port_attrs={'CLK': ['clkbuf_sink']}),
# Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}),
- Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}),
+ # Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}),
# Block RAM.
# Virtex.
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 66b7c583f..c3e5c72f9 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -1,144 +1,5 @@
// Created by cells_xtra.py from Xilinx models
-module FDCPE (...);
- parameter [0:0] INIT = 1'b0;
- parameter [0:0] IS_C_INVERTED = 1'b0;
- parameter [0:0] IS_CLR_INVERTED = 1'b0;
- parameter [0:0] IS_PRE_INVERTED = 1'b0;
- output Q;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_C_INVERTED" *)
- input C;
- input CE;
- (* invertible_pin = "IS_CLR_INVERTED" *)
- input CLR;
- input D;
- (* invertible_pin = "IS_PRE_INVERTED" *)
- input PRE;
-endmodule
-
-module LDCPE (...);
- parameter [0:0] INIT = 1'b0;
- parameter [0:0] IS_CLR_INVERTED = 1'b0;
- parameter [0:0] IS_D_INVERTED = 1'b0;
- parameter [0:0] IS_G_INVERTED = 1'b0;
- parameter [0:0] IS_GE_INVERTED = 1'b0;
- parameter [0:0] IS_PRE_INVERTED = 1'b0;
- output Q;
- (* invertible_pin = "IS_CLR_INVERTED" *)
- input CLR;
- (* invertible_pin = "IS_D_INVERTED" *)
- input D;
- (* invertible_pin = "IS_G_INVERTED" *)
- input G;
- (* invertible_pin = "IS_GE_INVERTED" *)
- input GE;
- (* invertible_pin = "IS_PRE_INVERTED" *)
- input PRE;
-endmodule
-
-module AND2B1L (...);
- parameter [0:0] IS_SRI_INVERTED = 1'b0;
- output O;
- input DI;
- (* invertible_pin = "IS_SRI_INVERTED" *)
- input SRI;
-endmodule
-
-module OR2L (...);
- parameter [0:0] IS_SRI_INVERTED = 1'b0;
- output O;
- input DI;
- (* invertible_pin = "IS_SRI_INVERTED" *)
- input SRI;
-endmodule
-
-module MUXF5 (...);
- output O;
- input I0;
- input I1;
- input S;
-endmodule
-
-module MUXF6 (...);
- output O;
- input I0;
- input I1;
- input S;
-endmodule
-
-module MUXF9 (...);
- output O;
- input I0;
- input I1;
- input S;
-endmodule
-
-module CARRY8 (...);
- parameter CARRY_TYPE = "SINGLE_CY8";
- output [7:0] CO;
- output [7:0] O;
- input CI;
- input CI_TOP;
- input [7:0] DI;
- input [7:0] S;
-endmodule
-
-module ORCY (...);
- output O;
- input CI;
- input I;
-endmodule
-
-module MULT_AND (...);
- output LO;
- input I0;
- input I1;
-endmodule
-
-module SRL16 (...);
- parameter [15:0] INIT = 16'h0000;
- output Q;
- input A0;
- input A1;
- input A2;
- input A3;
- (* clkbuf_sink *)
- input CLK;
- input D;
-endmodule
-
-module SRLC16 (...);
- parameter [15:0] INIT = 16'h0000;
- output Q;
- output Q15;
- input A0;
- input A1;
- input A2;
- input A3;
- (* clkbuf_sink *)
- input CLK;
- input D;
-endmodule
-
-module CFGLUT5 (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- output CDO;
- output O5;
- output O6;
- input I4;
- input I3;
- input I2;
- input I1;
- input I0;
- input CDI;
- input CE;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_CLK_INVERTED" *)
- input CLK;
-endmodule
-
module RAMB16_S1 (...);
parameter [0:0] INIT = 1'h0;
parameter [0:0] SRVAL = 1'h0;
diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc
index 1256a08cb..13a0b9b83 100644
--- a/techlibs/xilinx/xilinx_dffopt.cc
+++ b/techlibs/xilinx/xilinx_dffopt.cc
@@ -27,20 +27,13 @@ typedef std::pair<Const, std::vector<SigBit>> LutData;
// Compute a LUT implementing (select ^ select_inv) ? alt_data : data. Returns true if successful.
bool merge_lut(LutData &result, const LutData &data, const LutData select, bool select_inv, SigBit alt_data, int max_lut_size) {
- // First, gather input signals.
+ // First, gather input signals -- insert new signals at the beginning
+ // of the vector, so they don't disturb the likely-critical D LUT input
+ // timings.
result.second = data.second;
- int idx_alt = -1;
- if (alt_data.wire) {
- // Check if we already have it.
- for (int i = 0; i < GetSize(result.second); i++)
- if (result.second[i] == alt_data)
- idx_alt = i;
- // If not, add it.
- if (idx_alt == -1) {
- idx_alt = GetSize(result.second);
- result.second.push_back(alt_data);
- }
- }
+ // D lut inputs initially start at 0.
+ int idx_data = 0;
+ // Now add the control input LUT inputs.
std::vector<int> idx_sel;
for (auto bit : select.second) {
int idx = -1;
@@ -48,11 +41,32 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool
if (result.second[i] == bit)
idx = i;
if (idx == -1) {
- idx = GetSize(result.second);
- result.second.push_back(bit);
+ idx = 0;
+ // Insert new signal at the beginning and bump all indices.
+ result.second.insert(result.second.begin(), bit);
+ idx_data++;
+ for (int &sidx : idx_sel)
+ sidx++;
}
idx_sel.push_back(idx);
}
+ // Insert the Q signal, if any, to the slowest input -- it will have
+ // no problem meeting timing.
+ int idx_alt = -1;
+ if (alt_data.wire) {
+ // Check if we already have it.
+ for (int i = 0; i < GetSize(result.second); i++)
+ if (result.second[i] == alt_data)
+ idx_alt = i;
+ // If not, add it.
+ if (idx_alt == -1) {
+ idx_alt = 0;
+ result.second.insert(result.second.begin(), alt_data);
+ idx_data++;
+ for (int &sidx : idx_sel)
+ sidx++;
+ }
+ }
// If LUT would be too large, bail.
if (GetSize(result.second) > max_lut_size)
@@ -75,7 +89,7 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool
new_bit = alt_data.data == State::S1;
} else {
// Use original LUT.
- int lut_idx = i & ((1 << GetSize(data.second)) - 1);
+ int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1);
new_bit = data.first.bits[lut_idx] == State::S1;
}
result.first.bits[i] = new_bit ? State::S1 : State::S0;
diff --git a/tests/simple/mem_arst.v b/tests/simple/mem_arst.v
index 9bd38fcb3..88d0553b9 100644
--- a/tests/simple/mem_arst.v
+++ b/tests/simple/mem_arst.v
@@ -7,11 +7,9 @@ module MyMem #(
input Clk_i,
input [AddrWidth-1:0] Addr_i,
input [DataWidth-1:0] Data_i,
- output [DataWidth-1:0] Data_o,
+ output reg [DataWidth-1:0] Data_o,
input WR_i);
- reg [DataWidth-1:0] Data_o;
-
localparam Size = 2**AddrWidth;
(* mem2reg *)
diff --git a/tests/various/bug1531.ys b/tests/various/bug1531.ys
new file mode 100644
index 000000000..542223030
--- /dev/null
+++ b/tests/various/bug1531.ys
@@ -0,0 +1,34 @@
+read_verilog <<EOT
+module top (y, clk, w);
+ output reg y = 1'b0;
+ input clk, w;
+ reg [1:0] i = 2'b00;
+ always @(posedge clk)
+ // If the constant below is set to 2'b00, the correct output is generated.
+ // vvvv
+ for (i = 1'b0; i < 2'b01; i = i + 2'b01)
+ y <= w || i[1:1];
+endmodule
+EOT
+
+synth
+design -stash gate
+
+read_verilog <<EOT
+module gold (y, clk, w);
+ input clk;
+ wire [1:0] i;
+ input w;
+ output y;
+ reg y = 1'h0;
+ always @(posedge clk)
+ y <= w;
+ assign i = 2'h0;
+endmodule
+EOT
+proc gold
+
+design -import gate -as gate
+
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -seq 10 -verify -prove-asserts -show-ports miter