aboutsummaryrefslogtreecommitdiffstats
path: root/fpga_interchange
diff options
context:
space:
mode:
authorAlessandro Comodi <acomodi@antmicro.com>2021-07-05 13:34:34 +0200
committergatecat <gatecat@ds0.me>2021-07-06 09:57:26 +0100
commit6edc11de4de20aa5194f5cf3705a320b1891a2d6 (patch)
tree9bc2c112922b53f3009ca8cf2b72a91607d70689 /fpga_interchange
parent8a9fb810369aeb5eed128ef4e7d4de456ef1ec8f (diff)
downloadnextpnr-6edc11de4de20aa5194f5cf3705a320b1891a2d6.tar.gz
nextpnr-6edc11de4de20aa5194f5cf3705a320b1891a2d6.tar.bz2
nextpnr-6edc11de4de20aa5194f5cf3705a320b1891a2d6.zip
interchange: tests: add obuftds test
Signed-off-by: Alessandro Comodi <acomodi@antmicro.com>
Diffstat (limited to 'fpga_interchange')
-rw-r--r--fpga_interchange/examples/tests/CMakeLists.txt1
-rw-r--r--fpga_interchange/examples/tests/obuftds/CMakeLists.txt7
-rw-r--r--fpga_interchange/examples/tests/obuftds/basys3.xdc9
-rw-r--r--fpga_interchange/examples/tests/obuftds/obuftds.v37
-rw-r--r--fpga_interchange/examples/tests/obuftds/run.tcl14
-rw-r--r--fpga_interchange/macros.cc12
6 files changed, 80 insertions, 0 deletions
diff --git a/fpga_interchange/examples/tests/CMakeLists.txt b/fpga_interchange/examples/tests/CMakeLists.txt
index 1d3dd72f..f8a52a41 100644
--- a/fpga_interchange/examples/tests/CMakeLists.txt
+++ b/fpga_interchange/examples/tests/CMakeLists.txt
@@ -6,4 +6,5 @@ add_subdirectory(ff)
add_subdirectory(lut)
add_subdirectory(lut_nexus)
add_subdirectory(lutram)
+add_subdirectory(obuftds)
add_subdirectory(ram_nexus)
diff --git a/fpga_interchange/examples/tests/obuftds/CMakeLists.txt b/fpga_interchange/examples/tests/obuftds/CMakeLists.txt
new file mode 100644
index 00000000..0313c9bb
--- /dev/null
+++ b/fpga_interchange/examples/tests/obuftds/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_interchange_group_test(
+ name obuftds
+ family ${family}
+ board_list basys3
+ tcl run.tcl
+ sources obuftds.v
+)
diff --git a/fpga_interchange/examples/tests/obuftds/basys3.xdc b/fpga_interchange/examples/tests/obuftds/basys3.xdc
new file mode 100644
index 00000000..4b777233
--- /dev/null
+++ b/fpga_interchange/examples/tests/obuftds/basys3.xdc
@@ -0,0 +1,9 @@
+set_property PACKAGE_PIN V2 [get_ports sw[8] ]
+set_property PACKAGE_PIN T3 [get_ports sw[9] ]
+set_property PACKAGE_PIN T2 [get_ports sw[10]]
+set_property PACKAGE_PIN R3 [get_ports sw[11]]
+
+set_property PACKAGE_PIN U19 [get_ports diff_p[0]]
+set_property PACKAGE_PIN V19 [get_ports diff_n[0]]
+set_property PACKAGE_PIN V13 [get_ports diff_p[1]]
+set_property PACKAGE_PIN V14 [get_ports diff_n[1]]
diff --git a/fpga_interchange/examples/tests/obuftds/obuftds.v b/fpga_interchange/examples/tests/obuftds/obuftds.v
new file mode 100644
index 00000000..d4e9a603
--- /dev/null
+++ b/fpga_interchange/examples/tests/obuftds/obuftds.v
@@ -0,0 +1,37 @@
+module top(
+ input wire [11:8] sw,
+
+ output wire [1:0] diff_p,
+ output wire [1:0] diff_n
+);
+
+wire [1:0] buf_i;
+wire [1:0] buf_t;
+
+OBUFTDS # (
+ .IOSTANDARD("DIFF_SSTL135"),
+ .SLEW("FAST")
+) obuftds_0 (
+ .I(buf_i[0]),
+ .T(buf_t[0]),
+ .O(diff_p[0]),
+ .OB(diff_n[0])
+);
+
+OBUFTDS # (
+ .IOSTANDARD("DIFF_SSTL135"),
+ .SLEW("FAST")
+) obuftds_1 (
+ .I(buf_i[1]),
+ .T(buf_t[1]),
+ .O(diff_p[1]),
+ .OB(diff_n[1])
+);
+
+assign buf_i[0] = sw[ 8];
+assign buf_t[0] = sw[ 9];
+assign buf_i[1] = sw[10];
+assign buf_t[1] = sw[11];
+
+endmodule
+
diff --git a/fpga_interchange/examples/tests/obuftds/run.tcl b/fpga_interchange/examples/tests/obuftds/run.tcl
new file mode 100644
index 00000000..b8d0df72
--- /dev/null
+++ b/fpga_interchange/examples/tests/obuftds/run.tcl
@@ -0,0 +1,14 @@
+yosys -import
+
+read_verilog $::env(SOURCES)
+
+synth_xilinx -nolutram -nowidelut -nosrl -nocarry -nodsp
+
+# opt_expr -undriven makes sure all nets are driven, if only by the $undef
+# net.
+opt_expr -undriven
+opt_clean
+
+setundef -zero -params
+
+write_json $::env(OUT_JSON)
diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc
index 42c8e1ba..762615c1 100644
--- a/fpga_interchange/macros.cc
+++ b/fpga_interchange/macros.cc
@@ -58,14 +58,24 @@ void Arch::expand_macros()
std::vector<CellInfo *> next_cells;
+ bool first_iter = false;
do {
// Expand cells
for (auto cell : cells) {
// TODO: consult exception map
const MacroExpansionPOD *exp = lookup_macro_rules(chip_info, cell->type);
+
+ // Block infinite expansion loop due to a macro being expanded in the same primitive.
+ // E.g.: OBUFTDS expands into the following cells, with an infinite loop being generated:
+ // - 2 OBUFTDS
+ // - 1 INV
+ if (exp && first_iter)
+ continue;
+
const MacroPOD *macro = lookup_macro(chip_info, exp ? IdString(exp->macro_name) : cell->type);
if (macro == nullptr)
continue;
+
// Get the ultimate root of this macro expansion
IdString parent = (cell->macro_parent == IdString()) ? cell->name : cell->macro_parent;
// Create child instances
@@ -158,6 +168,8 @@ void Arch::expand_macros()
// The next iteration only needs to look at cells created in this iteration
std::swap(next_cells, cells);
next_cells.clear();
+
+ first_iter = true;
} while (!cells.empty());
// Do this at the end, otherwise we might add cells that are later destroyed
for (auto &cell : ctx->cells)