diff options
| -rw-r--r-- | fpga_interchange/site_router_tests/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/common/run_script.py | 29 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/common/synth.tcl | 14 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/lut/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/lut/lut.v | 24 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/lut/lut.xdc | 32 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/lut/test.yaml | 28 | ||||
| -rw-r--r-- | fpga_interchange/site_router_tests/site_router_test.cmake | 133 | 
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()  | 
