aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Michalak <tmichalak@antmicro.com>2021-06-09 23:01:27 +0200
committerTomasz Michalak <tmichalak@antmicro.com>2021-06-10 12:06:04 +0200
commit1cd2901d854b969a8cb1afc66e3f3388766776a0 (patch)
tree08d7000a9368b13812f2c5a89cb696e0eaebdc2f
parentcaf7261be7b34b365ab6d8449455891c2ed28faa (diff)
downloadnextpnr-tests-1cd2901d854b969a8cb1afc66e3f3388766776a0.tar.gz
nextpnr-tests-1cd2901d854b969a8cb1afc66e3f3388766776a0.tar.bz2
nextpnr-tests-1cd2901d854b969a8cb1afc66e3f3388766776a0.zip
fpga_interchange: Add initial site router test framework
Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
-rw-r--r--fpga_interchange/site_router_tests/CMakeLists.txt2
-rw-r--r--fpga_interchange/site_router_tests/common/run_script.py29
-rw-r--r--fpga_interchange/site_router_tests/common/synth.tcl14
-rw-r--r--fpga_interchange/site_router_tests/lut/CMakeLists.txt6
-rw-r--r--fpga_interchange/site_router_tests/lut/lut.v24
-rw-r--r--fpga_interchange/site_router_tests/lut/lut.xdc32
-rw-r--r--fpga_interchange/site_router_tests/lut/test.yaml28
-rw-r--r--fpga_interchange/site_router_tests/site_router_test.cmake133
8 files changed, 268 insertions, 0 deletions
diff --git a/fpga_interchange/site_router_tests/CMakeLists.txt b/fpga_interchange/site_router_tests/CMakeLists.txt
new file mode 100644
index 0000000..e67b5ff
--- /dev/null
+++ b/fpga_interchange/site_router_tests/CMakeLists.txt
@@ -0,0 +1,2 @@
+include(site_router_test.cmake)
+add_subdirectory(lut)
diff --git a/fpga_interchange/site_router_tests/common/run_script.py b/fpga_interchange/site_router_tests/common/run_script.py
new file mode 100644
index 0000000..07faf89
--- /dev/null
+++ b/fpga_interchange/site_router_tests/common/run_script.py
@@ -0,0 +1,29 @@
+import sys
+import yaml
+import os
+
+def test_case(ctx):
+ with open(os.environ['TEST_YAML'], 'r') as f:
+ test_data = yaml.safe_load(f.read())
+ if 'test_case' in test_data:
+ ctx.pack()
+ for test_step in test_data['test_case']:
+ print(test_step)
+ if "place" in test_step:
+ for cell, bel in test_step["place"].items():
+ print("Binding Bel {} to Cell {}".format(bel, cell))
+ assert cell in ctx.cells, "Cell {} does not exist".format(cell)
+ ctx.bindBel(bel, ctx.cells[cell], STRENGTH_WEAK)
+ if "test" in test_step:
+ print(test_step["test"])
+ for bel, check in test_step["test"].items():
+ print("Checking if location of bel {} is {}".format(bel, check))
+ print("Test result: {}, isBelLocationValid: {}, expected: {}".format(ctx.isBelLocationValid(bel) == check, ctx.isBelLocationValid(bel), check))
+ if "unplace" in test_step:
+ print(test_step["unplace"])
+ cell = test_step["unplace"]
+ print("Unbinding Bel {}".format(cell))
+ ctx.explain_bel_status(cell)
+ ctx.unbindBel(cell)
+
+test_case(ctx)
diff --git a/fpga_interchange/site_router_tests/common/synth.tcl b/fpga_interchange/site_router_tests/common/synth.tcl
new file mode 100644
index 0000000..cba4503
--- /dev/null
+++ b/fpga_interchange/site_router_tests/common/synth.tcl
@@ -0,0 +1,14 @@
+yosys -import
+
+read_verilog $::env(SOURCES)
+
+synth_xilinx -flatten -abc9 -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/site_router_tests/lut/CMakeLists.txt b/fpga_interchange/site_router_tests/lut/CMakeLists.txt
new file mode 100644
index 0000000..1441b38
--- /dev/null
+++ b/fpga_interchange/site_router_tests/lut/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_site_router_test(
+ name lut
+ board arty35t
+ test_script test.yaml
+ sources lut.v
+)
diff --git a/fpga_interchange/site_router_tests/lut/lut.v b/fpga_interchange/site_router_tests/lut/lut.v
new file mode 100644
index 0000000..141d7b1
--- /dev/null
+++ b/fpga_interchange/site_router_tests/lut/lut.v
@@ -0,0 +1,24 @@
+module top(input [5:0] lut_1_in, input [4:0] lut_2_in, output lut_1_out, output lut_2_out);
+
+(* keep *)
+LUT6 #(.INIT(64'hFFFFFFFFFFFFFFFF)) lut_1 (
+ .I0(lut_1_in[0]),
+ .I1(lut_1_in[1]),
+ .I2(lut_1_in[2]),
+ .I3(lut_1_in[3]),
+ .I4(lut_1_in[4]),
+ .I5(lut_1_in[5]),
+ .O(lut_1_out)
+);
+
+(* keep *)
+LUT5 #(.INIT(32'h0)) lut_2 (
+ .I0(lut_1_in[0]),
+ .I1(lut_2_in[1]),
+ .I2(lut_2_in[2]),
+ .I3(lut_2_in[3]),
+ .I4(lut_2_in[4]),
+ .O(lut_2_out)
+);
+
+endmodule
diff --git a/fpga_interchange/site_router_tests/lut/lut.xdc b/fpga_interchange/site_router_tests/lut/lut.xdc
new file mode 100644
index 0000000..426b3a9
--- /dev/null
+++ b/fpga_interchange/site_router_tests/lut/lut.xdc
@@ -0,0 +1,32 @@
+## arty-35t board
+set_property PACKAGE_PIN G13 [get_ports lut_1_in[0]]
+set_property PACKAGE_PIN B11 [get_ports lut_1_in[1]]
+set_property PACKAGE_PIN A11 [get_ports lut_1_in[2]]
+set_property PACKAGE_PIN D12 [get_ports lut_1_in[3]]
+set_property PACKAGE_PIN D13 [get_ports lut_1_in[4]]
+set_property PACKAGE_PIN B18 [get_ports lut_1_in[5]]
+
+set_property PACKAGE_PIN E15 [get_ports lut_2_in[0]]
+set_property PACKAGE_PIN E16 [get_ports lut_2_in[1]]
+set_property PACKAGE_PIN D15 [get_ports lut_2_in[2]]
+set_property PACKAGE_PIN C15 [get_ports lut_2_in[3]]
+set_property PACKAGE_PIN J17 [get_ports lut_2_in[4]]
+
+set_property PACKAGE_PIN H5 [get_ports lut_1_out]
+set_property PACKAGE_PIN J5 [get_ports lut_2_out]
+
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[0]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[1]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[2]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[3]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[4]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[5]]
+
+set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[0]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[1]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[2]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[3]]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[4]]
+
+set_property IOSTANDARD LVCMOS33 [get_ports lut_1_out]
+set_property IOSTANDARD LVCMOS33 [get_ports lut_2_out]
diff --git a/fpga_interchange/site_router_tests/lut/test.yaml b/fpga_interchange/site_router_tests/lut/test.yaml
new file mode 100644
index 0000000..e299d81
--- /dev/null
+++ b/fpga_interchange/site_router_tests/lut/test.yaml
@@ -0,0 +1,28 @@
+test_case:
+ - place:
+ # Place cell `lut_2` at BEL `SLICE_X1Y8.SLICEL/A6LUT`
+ lut_1: SLICE_X1Y8.SLICEL/A6LUT
+ - test:
+ # Make sure this placement is accept
+ SLICE_X1Y8.SLICEL/A6LUT: true
+ - unplace:
+ SLICE_X1Y8.SLICEL/A6LUT
+ # - place:
+ # lut_1: SLICE_X1Y8.SLICEL/B6LUT
+ # - test:
+ # # Make sure this placement is accept
+ # SLICE_X1Y8.SLICEL/A6LUT: true
+ # SLICE_X1Y8.SLICEL/B6LUT: true
+ # - place:
+ # lut_1: SLICE_X1Y8.SLICEL/A6LUT
+ # lut_2: SLICE_X1Y8.SLICEL/A5LUT
+ # - test:
+ # # The site is now invalid because too many signals into the A6/A5LUT
+ # SLICE_X1Y8.SLICEL/A6LUT: false
+ # SLICE_X1Y8.SLICEL/A5LUT: false
+ # - unplace:
+ # - lut_2
+ # - test:
+ # # By removing lut_2, the site is valid again
+ # SLICE_X1Y8.SLICEL/A6LUT: true
+ # SLICE_X1Y8.SLICEL/A5LUT: true
diff --git a/fpga_interchange/site_router_tests/site_router_test.cmake b/fpga_interchange/site_router_tests/site_router_test.cmake
new file mode 100644
index 0000000..26403bd
--- /dev/null
+++ b/fpga_interchange/site_router_tests/site_router_test.cmake
@@ -0,0 +1,133 @@
+function(add_site_router_test)
+ # ~~~
+ # add_site_router_test(
+ # name <name>
+ # board <board>
+ # test_script <yaml>
+ # sources <sources list>
+ # [top <top name>]
+ # )
+ #
+ # Generates targets to run desired site router tests.
+ #
+ # Arguments:
+ # - name: base test name. The real test name will be <name>_<board>
+ # - board: name of the board to be used in the test, e.g. arty35t
+ # - test_script: YAML description of the test case
+ # - sources: list of HDL sources
+ # - top (optional): name of the top level module.
+ # If not provided, "top" is assigned as top level module
+
+ set(options)
+ set(oneValueArgs name test_script board top)
+ set(multiValueArgs sources)
+
+ cmake_parse_arguments(
+ add_site_router_test
+ "${options}"
+ "${oneValueArgs}"
+ "${multiValueArgs}"
+ ${ARGN}
+ )
+
+ set(name ${add_site_router_test_name})
+ set(test_script ${add_site_router_test_test_script})
+ set(board ${add_site_router_test_board})
+ set(top ${add_site_router_test_top})
+ set(sources)
+ get_property(device TARGET board-${board} PROPERTY DEVICE)
+ get_property(package TARGET board-${board} PROPERTY PACKAGE)
+ foreach(source ${add_site_router_test_sources})
+ list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/${source})
+ endforeach()
+
+ if (NOT DEFINED top)
+ # Setting default top value
+ set(top "top")
+ endif()
+
+ set(common_dir ${CMAKE_CURRENT_SOURCE_DIR}/../common)
+
+ # Synthesis
+ set(synth_json ${CMAKE_CURRENT_BINARY_DIR}/${name}.json)
+ add_custom_command(
+ OUTPUT ${synth_json}
+ COMMAND ${CMAKE_COMMAND} -E env
+ SOURCES="${sources}"
+ OUT_JSON=${synth_json}
+ yosys -c ${common_dir}/synth.tcl
+ DEPENDS ${sources}
+ )
+
+ add_custom_target(site_router_tests-${name}-json DEPENDS ${synth_json})
+
+ # Logical Netlist
+ get_property(device_target TARGET device-${device} PROPERTY DEVICE_TARGET)
+ get_property(device_loc TARGET device-${device} PROPERTY DEVICE_LOC)
+
+ set(netlist ${CMAKE_CURRENT_BINARY_DIR}/${name}.netlist)
+ add_custom_command(
+ OUTPUT ${netlist}
+ COMMAND
+ ${PYTHON_EXECUTABLE} -mfpga_interchange.yosys_json
+ --schema_dir ${INTERCHANGE_SCHEMA_PATH}
+ --device ${device_loc}
+ --top ${top}
+ ${synth_json}
+ ${netlist}
+ DEPENDS
+ ${synth_json}
+ ${device_target}
+ ${device_loc}
+ )
+
+ add_custom_target(site_router_tests-${name}-netlist DEPENDS ${netlist})
+
+ # Logical Netlist YAML
+ set(netlist_yaml ${CMAKE_CURRENT_BINARY_DIR}/${name}.netlist.yaml)
+ add_custom_command(
+ OUTPUT ${netlist_yaml}
+ COMMAND
+ ${PYTHON_EXECUTABLE} -mfpga_interchange.convert
+ --schema_dir ${INTERCHANGE_SCHEMA_PATH}
+ --schema logical
+ --input_format capnp
+ --output_format yaml
+ ${netlist}
+ ${netlist_yaml}
+ DEPENDS
+ ${netlist}
+ )
+
+ add_custom_target(site_router_tests-${name}-netlist-yaml DEPENDS ${netlist_yaml})
+
+ # Physical Netlist
+ get_target_property(chipdb_bin_target device-${device} CHIPDB_BIN_TARGET)
+ get_target_property(chipdb_bin_loc device-${device} CHIPDB_BIN_LOC)
+ get_target_property(nextpnr_path nextpnr-fpga_interchange BINARY_DIR)
+ set(xdc ${CMAKE_CURRENT_SOURCE_DIR}/${name}.xdc)
+ set(run_script ${common_dir}/run_script.py)
+ set(test_result ${CMAKE_CURRENT_BINARY_DIR}/${name}.test_result)
+
+ add_custom_command(
+ OUTPUT ${test_result}
+ COMMAND
+ ${CMAKE_COMMAND} -E env TEST_YAML=${CMAKE_CURRENT_SOURCE_DIR}/${test_script}
+ ${nextpnr_path}/nextpnr-fpga_interchange
+ --run ${run_script}
+ --no-route
+ --chipdb ${chipdb_bin_loc}
+ --xdc ${xdc}
+ --netlist ${netlist}
+ --package ${package} > ${test_result}
+ DEPENDS
+ nextpnr-fpga_interchange
+ ${netlist}
+ ${xdc}
+ ${chipdb_bin_target}
+ ${chipdb_bin_loc}
+ ${run_script}
+ )
+
+ add_custom_target(site_router_tests-${name}-test DEPENDS ${test_result})
+endfunction()