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, other boost_python, 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 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,8 +27,31 @@ typedef std::pair> 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; + // D lut inputs initially start at 0. + int idx_data = 0; + // Now add the control input LUT inputs. + std::vector idx_sel; + for (auto bit : select.second) { + int idx = -1; + for (int i = 0; i < GetSize(result.second); i++) + if (result.second[i] == bit) + idx = i; + if (idx == -1) { + 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. @@ -37,22 +60,13 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool idx_alt = i; // If not, add it. if (idx_alt == -1) { - idx_alt = GetSize(result.second); - result.second.push_back(alt_data); + idx_alt = 0; + result.second.insert(result.second.begin(), alt_data); + idx_data++; + for (int &sidx : idx_sel) + sidx++; } } - std::vector idx_sel; - for (auto bit : select.second) { - int idx = -1; - for (int i = 0; i < GetSize(result.second); i++) - if (result.second[i] == bit) - idx = i; - if (idx == -1) { - idx = GetSize(result.second); - result.second.push_back(bit); - } - idx_sel.push_back(idx); - } // 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 <