Skip to content

Commit 0a27601

Browse files
authored
Merge pull request #10 from antmicro/site_router_test_framework
fpga_interchange: Add initial site router test framework
2 parents 1cc7ee7 + 1cd2901 commit 0a27601

File tree

8 files changed

+268
-0
lines changed

8 files changed

+268
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include(site_router_test.cmake)
2+
add_subdirectory(lut)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import sys
2+
import yaml
3+
import os
4+
5+
def test_case(ctx):
6+
with open(os.environ['TEST_YAML'], 'r') as f:
7+
test_data = yaml.safe_load(f.read())
8+
if 'test_case' in test_data:
9+
ctx.pack()
10+
for test_step in test_data['test_case']:
11+
print(test_step)
12+
if "place" in test_step:
13+
for cell, bel in test_step["place"].items():
14+
print("Binding Bel {} to Cell {}".format(bel, cell))
15+
assert cell in ctx.cells, "Cell {} does not exist".format(cell)
16+
ctx.bindBel(bel, ctx.cells[cell], STRENGTH_WEAK)
17+
if "test" in test_step:
18+
print(test_step["test"])
19+
for bel, check in test_step["test"].items():
20+
print("Checking if location of bel {} is {}".format(bel, check))
21+
print("Test result: {}, isBelLocationValid: {}, expected: {}".format(ctx.isBelLocationValid(bel) == check, ctx.isBelLocationValid(bel), check))
22+
if "unplace" in test_step:
23+
print(test_step["unplace"])
24+
cell = test_step["unplace"]
25+
print("Unbinding Bel {}".format(cell))
26+
ctx.explain_bel_status(cell)
27+
ctx.unbindBel(cell)
28+
29+
test_case(ctx)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
yosys -import
2+
3+
read_verilog $::env(SOURCES)
4+
5+
synth_xilinx -flatten -abc9 -nosrl -nocarry -nodsp
6+
7+
# opt_expr -undriven makes sure all nets are driven, if only by the $undef
8+
# net.
9+
opt_expr -undriven
10+
opt_clean
11+
12+
setundef -zero -params
13+
14+
write_json $::env(OUT_JSON)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
add_site_router_test(
2+
name lut
3+
board arty35t
4+
test_script test.yaml
5+
sources lut.v
6+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module top(input [5:0] lut_1_in, input [4:0] lut_2_in, output lut_1_out, output lut_2_out);
2+
3+
(* keep *)
4+
LUT6 #(.INIT(64'hFFFFFFFFFFFFFFFF)) lut_1 (
5+
.I0(lut_1_in[0]),
6+
.I1(lut_1_in[1]),
7+
.I2(lut_1_in[2]),
8+
.I3(lut_1_in[3]),
9+
.I4(lut_1_in[4]),
10+
.I5(lut_1_in[5]),
11+
.O(lut_1_out)
12+
);
13+
14+
(* keep *)
15+
LUT5 #(.INIT(32'h0)) lut_2 (
16+
.I0(lut_1_in[0]),
17+
.I1(lut_2_in[1]),
18+
.I2(lut_2_in[2]),
19+
.I3(lut_2_in[3]),
20+
.I4(lut_2_in[4]),
21+
.O(lut_2_out)
22+
);
23+
24+
endmodule
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## arty-35t board
2+
set_property PACKAGE_PIN G13 [get_ports lut_1_in[0]]
3+
set_property PACKAGE_PIN B11 [get_ports lut_1_in[1]]
4+
set_property PACKAGE_PIN A11 [get_ports lut_1_in[2]]
5+
set_property PACKAGE_PIN D12 [get_ports lut_1_in[3]]
6+
set_property PACKAGE_PIN D13 [get_ports lut_1_in[4]]
7+
set_property PACKAGE_PIN B18 [get_ports lut_1_in[5]]
8+
9+
set_property PACKAGE_PIN E15 [get_ports lut_2_in[0]]
10+
set_property PACKAGE_PIN E16 [get_ports lut_2_in[1]]
11+
set_property PACKAGE_PIN D15 [get_ports lut_2_in[2]]
12+
set_property PACKAGE_PIN C15 [get_ports lut_2_in[3]]
13+
set_property PACKAGE_PIN J17 [get_ports lut_2_in[4]]
14+
15+
set_property PACKAGE_PIN H5 [get_ports lut_1_out]
16+
set_property PACKAGE_PIN J5 [get_ports lut_2_out]
17+
18+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[0]]
19+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[1]]
20+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[2]]
21+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[3]]
22+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[4]]
23+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_in[5]]
24+
25+
set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[0]]
26+
set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[1]]
27+
set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[2]]
28+
set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[3]]
29+
set_property IOSTANDARD LVCMOS33 [get_ports lut_2_in[4]]
30+
31+
set_property IOSTANDARD LVCMOS33 [get_ports lut_1_out]
32+
set_property IOSTANDARD LVCMOS33 [get_ports lut_2_out]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
test_case:
2+
- place:
3+
# Place cell `lut_2` at BEL `SLICE_X1Y8.SLICEL/A6LUT`
4+
lut_1: SLICE_X1Y8.SLICEL/A6LUT
5+
- test:
6+
# Make sure this placement is accept
7+
SLICE_X1Y8.SLICEL/A6LUT: true
8+
- unplace:
9+
SLICE_X1Y8.SLICEL/A6LUT
10+
# - place:
11+
# lut_1: SLICE_X1Y8.SLICEL/B6LUT
12+
# - test:
13+
# # Make sure this placement is accept
14+
# SLICE_X1Y8.SLICEL/A6LUT: true
15+
# SLICE_X1Y8.SLICEL/B6LUT: true
16+
# - place:
17+
# lut_1: SLICE_X1Y8.SLICEL/A6LUT
18+
# lut_2: SLICE_X1Y8.SLICEL/A5LUT
19+
# - test:
20+
# # The site is now invalid because too many signals into the A6/A5LUT
21+
# SLICE_X1Y8.SLICEL/A6LUT: false
22+
# SLICE_X1Y8.SLICEL/A5LUT: false
23+
# - unplace:
24+
# - lut_2
25+
# - test:
26+
# # By removing lut_2, the site is valid again
27+
# SLICE_X1Y8.SLICEL/A6LUT: true
28+
# SLICE_X1Y8.SLICEL/A5LUT: true
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
function(add_site_router_test)
2+
# ~~~
3+
# add_site_router_test(
4+
# name <name>
5+
# board <board>
6+
# test_script <yaml>
7+
# sources <sources list>
8+
# [top <top name>]
9+
# )
10+
#
11+
# Generates targets to run desired site router tests.
12+
#
13+
# Arguments:
14+
# - name: base test name. The real test name will be <name>_<board>
15+
# - board: name of the board to be used in the test, e.g. arty35t
16+
# - test_script: YAML description of the test case
17+
# - sources: list of HDL sources
18+
# - top (optional): name of the top level module.
19+
# If not provided, "top" is assigned as top level module
20+
21+
set(options)
22+
set(oneValueArgs name test_script board top)
23+
set(multiValueArgs sources)
24+
25+
cmake_parse_arguments(
26+
add_site_router_test
27+
"${options}"
28+
"${oneValueArgs}"
29+
"${multiValueArgs}"
30+
${ARGN}
31+
)
32+
33+
set(name ${add_site_router_test_name})
34+
set(test_script ${add_site_router_test_test_script})
35+
set(board ${add_site_router_test_board})
36+
set(top ${add_site_router_test_top})
37+
set(sources)
38+
get_property(device TARGET board-${board} PROPERTY DEVICE)
39+
get_property(package TARGET board-${board} PROPERTY PACKAGE)
40+
foreach(source ${add_site_router_test_sources})
41+
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/${source})
42+
endforeach()
43+
44+
if (NOT DEFINED top)
45+
# Setting default top value
46+
set(top "top")
47+
endif()
48+
49+
set(common_dir ${CMAKE_CURRENT_SOURCE_DIR}/../common)
50+
51+
# Synthesis
52+
set(synth_json ${CMAKE_CURRENT_BINARY_DIR}/${name}.json)
53+
add_custom_command(
54+
OUTPUT ${synth_json}
55+
COMMAND ${CMAKE_COMMAND} -E env
56+
SOURCES="${sources}"
57+
OUT_JSON=${synth_json}
58+
yosys -c ${common_dir}/synth.tcl
59+
DEPENDS ${sources}
60+
)
61+
62+
add_custom_target(site_router_tests-${name}-json DEPENDS ${synth_json})
63+
64+
# Logical Netlist
65+
get_property(device_target TARGET device-${device} PROPERTY DEVICE_TARGET)
66+
get_property(device_loc TARGET device-${device} PROPERTY DEVICE_LOC)
67+
68+
set(netlist ${CMAKE_CURRENT_BINARY_DIR}/${name}.netlist)
69+
add_custom_command(
70+
OUTPUT ${netlist}
71+
COMMAND
72+
${PYTHON_EXECUTABLE} -mfpga_interchange.yosys_json
73+
--schema_dir ${INTERCHANGE_SCHEMA_PATH}
74+
--device ${device_loc}
75+
--top ${top}
76+
${synth_json}
77+
${netlist}
78+
DEPENDS
79+
${synth_json}
80+
${device_target}
81+
${device_loc}
82+
)
83+
84+
add_custom_target(site_router_tests-${name}-netlist DEPENDS ${netlist})
85+
86+
# Logical Netlist YAML
87+
set(netlist_yaml ${CMAKE_CURRENT_BINARY_DIR}/${name}.netlist.yaml)
88+
add_custom_command(
89+
OUTPUT ${netlist_yaml}
90+
COMMAND
91+
${PYTHON_EXECUTABLE} -mfpga_interchange.convert
92+
--schema_dir ${INTERCHANGE_SCHEMA_PATH}
93+
--schema logical
94+
--input_format capnp
95+
--output_format yaml
96+
${netlist}
97+
${netlist_yaml}
98+
DEPENDS
99+
${netlist}
100+
)
101+
102+
add_custom_target(site_router_tests-${name}-netlist-yaml DEPENDS ${netlist_yaml})
103+
104+
# Physical Netlist
105+
get_target_property(chipdb_bin_target device-${device} CHIPDB_BIN_TARGET)
106+
get_target_property(chipdb_bin_loc device-${device} CHIPDB_BIN_LOC)
107+
get_target_property(nextpnr_path nextpnr-fpga_interchange BINARY_DIR)
108+
set(xdc ${CMAKE_CURRENT_SOURCE_DIR}/${name}.xdc)
109+
set(run_script ${common_dir}/run_script.py)
110+
set(test_result ${CMAKE_CURRENT_BINARY_DIR}/${name}.test_result)
111+
112+
add_custom_command(
113+
OUTPUT ${test_result}
114+
COMMAND
115+
${CMAKE_COMMAND} -E env TEST_YAML=${CMAKE_CURRENT_SOURCE_DIR}/${test_script}
116+
${nextpnr_path}/nextpnr-fpga_interchange
117+
--run ${run_script}
118+
--no-route
119+
--chipdb ${chipdb_bin_loc}
120+
--xdc ${xdc}
121+
--netlist ${netlist}
122+
--package ${package} > ${test_result}
123+
DEPENDS
124+
nextpnr-fpga_interchange
125+
${netlist}
126+
${xdc}
127+
${chipdb_bin_target}
128+
${chipdb_bin_loc}
129+
${run_script}
130+
)
131+
132+
add_custom_target(site_router_tests-${name}-test DEPENDS ${test_result})
133+
endfunction()

0 commit comments

Comments
 (0)