mirror of https://github.com/openXC7/prjxray.git
Merge pull request #1539 from dnltz/WIP/dnltz/refactory_database
Refactor fabric data in database
This commit is contained in:
commit
30890e0e04
|
|
@ -2,7 +2,19 @@ env
|
|||
build
|
||||
build_*
|
||||
logs_*
|
||||
database
|
||||
database/*
|
||||
!database/artix7
|
||||
database/artix7/*
|
||||
!database/artix7/mapping
|
||||
!database/kintex7
|
||||
database/kintex7/*
|
||||
!database/kintex7/mapping
|
||||
!database/zynq7
|
||||
database/zynq7/*
|
||||
!database/zynq7/mapping
|
||||
!database/spartan7
|
||||
database/spartan7/*
|
||||
!database/spartan7/mapping
|
||||
.Xil
|
||||
**/specimen_*
|
||||
**/output
|
||||
|
|
|
|||
15
Makefile
15
Makefile
|
|
@ -199,16 +199,11 @@ db-extras-artix7-parts: $(addprefix db-part-only-,$(ARTIX_PARTS))
|
|||
# override the XRAY_PIN_0X setting below to pick a pin that *is* bonded.
|
||||
db-extras-artix7-harness:
|
||||
+source settings/artix7.sh && \
|
||||
XRAY_PIN_00=N15 XRAY_PART=xc7a100tcsg324-1 XRAY_EQUIV_PART=xc7a100tfgg676-1 \
|
||||
$(MAKE) -C fuzzers roi_only
|
||||
XRAY_PART=xc7a100tcsg324-1 $(MAKE) -C fuzzers roi_only
|
||||
+source settings/artix7_50t.sh && \
|
||||
XRAY_PIN_00=J13 XRAY_PIN_01=J14 XRAY_PIN_02=K15 XRAY_PIN_03=K16 \
|
||||
XRAY_PART=xc7a35tftg256-1 XRAY_EQUIV_PART=xc7a50tfgg484-1 \
|
||||
$(MAKE) -C fuzzers roi_only
|
||||
XRAY_PART=xc7a35tftg256-1 $(MAKE) -C fuzzers roi_only
|
||||
+source settings/artix7_200t.sh && \
|
||||
XRAY_PIN_00=V10 XRAY_PIN_01=W10 XRAY_PIN_02=Y11 XRAY_PIN_03=Y12 \
|
||||
XRAY_PART=xc7a200tsbg484-1 XRAY_EQUIV_PART=xc7a200tffg1156-1 \
|
||||
$(MAKE) -C fuzzers roi_only
|
||||
XRAY_PART=xc7a200tsbg484-1 $(MAKE) -C fuzzers roi_only
|
||||
+source minitests/roi_harness/basys3-swbut.sh && $(MAKE) -C fuzzers roi_only
|
||||
+source minitests/roi_harness/arty-uart.sh && $(MAKE) -C fuzzers roi_only
|
||||
+source minitests/roi_harness/basys3-swbut.sh && \
|
||||
|
|
@ -238,9 +233,7 @@ db-extras-zynq7-parts: $(addprefix db-part-only-,$(ZYNQ_PARTS))
|
|||
|
||||
db-extras-zynq7-harness:
|
||||
+source settings/zynq7.sh && \
|
||||
XRAY_PIN_00=T9 XRAY_PIN_01=P14 XRAY_PIN_02=T14 XRAY_PIN_03=R18 \
|
||||
XRAY_PART=xc7z020clg400-1 XRAY_EQUIV_PART=xc7z020clg484-1 \
|
||||
$(MAKE) -C fuzzers roi_only
|
||||
XRAY_PART=xc7z020clg400-1 $(MAKE) -C fuzzers roi_only
|
||||
db-check:
|
||||
@true
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# device to fabric mapping
|
||||
"xc7a200t":
|
||||
fabric: "xc7a200t"
|
||||
"xc7a100t":
|
||||
fabric: "xc7a100t"
|
||||
"xc7a50t":
|
||||
fabric: "xc7a50t"
|
||||
"xc7a35t":
|
||||
fabric: "xc7a50t"
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# part number to device, package and speed grade mapping
|
||||
"xc7a200tffg1156-1":
|
||||
device: "xc7a200t"
|
||||
package: "ffg1156"
|
||||
speedgrade: "1"
|
||||
"xc7a200tsbg484-1":
|
||||
device: "xc7a200t"
|
||||
package: "sbg484"
|
||||
speedgrade: "1"
|
||||
"xc7a100tfgg676-1":
|
||||
device: "xc7a100t"
|
||||
package: "fgg676"
|
||||
speedgrade: "1"
|
||||
"xc7a100tcsg324-1":
|
||||
device: "xc7a100t"
|
||||
package: "csg324"
|
||||
speedgrade: "1"
|
||||
"xc7a50tfgg484-1":
|
||||
device: "xc7a50t"
|
||||
package: "fgg484"
|
||||
speedgrade: "1"
|
||||
"xc7a35tcsg324-1":
|
||||
device: "xc7a35t"
|
||||
package: "csg324"
|
||||
speedgrade: "1"
|
||||
"xc7a35tftg256-1":
|
||||
device: "xc7a35t"
|
||||
package: "ftg256"
|
||||
speedgrade: "1"
|
||||
"xc7a35tcpg236-1":
|
||||
device: "xc7a35t"
|
||||
package: "cpg236"
|
||||
speedgrade: "1"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# device to fabric mapping
|
||||
"xc7k70t":
|
||||
fabric: "xc7k70t"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# part number to device, package and speed grade mapping
|
||||
"xc7k70tfbg676-2":
|
||||
device: "xc7k70t"
|
||||
package: "fbg676"
|
||||
speedgrade: "2"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# device to fabric mapping
|
||||
"xc7z020s":
|
||||
fabric: "xc7z020s"
|
||||
"xc7z010s":
|
||||
fabric: "xc7z010s"
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# part number to device, package and speed grade mapping
|
||||
"xc7z020clg484-1":
|
||||
device: "xc7z020s"
|
||||
package: "clg481"
|
||||
speedgrade: "1"
|
||||
"xc7z020clg400-1":
|
||||
device: "xc7z020s"
|
||||
package: "clg400"
|
||||
speedgrade: "1"
|
||||
"xc7z010clg400-1":
|
||||
device: "xc7z010s"
|
||||
package: "clg400"
|
||||
speedgrade: "1"
|
||||
|
|
@ -11,7 +11,7 @@ needed. You just need to rerun some fuzzers for the new device to
|
|||
understand how the tiles are connected to each other and to IOs.
|
||||
|
||||
*If you are*\ \ **just**\ \ *adding a new package for a device that is
|
||||
already supported, you can skip Steps 2 through 4.*
|
||||
already supported, you can skip Steps 2 through 5.*
|
||||
|
||||
Note: Since this guide was written, the xc7a100t has become the primary
|
||||
device in the database, not a secondary device as it was when it was
|
||||
|
|
@ -88,14 +88,7 @@ Update the following values in the new settings file:
|
|||
`comments <https://github.com/SymbiFlow/prjxray/blob/master/fuzzers/005-tilegrid/generate_full.py#L401>`__
|
||||
in the 005 fuzzer for more information.
|
||||
|
||||
- ``XRAY_PIN_00`` – this must be a clock pin. You can look at the device in the Vivado GUI
|
||||
interactively (click on IOs and check their properties until you find
|
||||
one with IS_CLOCK=true), or run a small clocked design in Vivado and see
|
||||
which pin is assigned to ‘clk’.
|
||||
|
||||
- ``XRAY_PIN_01`` and on – these should be normal data pins on the device.
|
||||
|
||||
`This <https://github.com/tcal-x/prjxray/blob/fbf4dd897d5a1025ebfeb7c51c5077a6b6c9bc47/settings/artix7_100t.sh>`__
|
||||
`This <https://github.com/SymbiFlow/prjxray/blob/master/settings/artix7_100t.sh>`__
|
||||
is what the new settings file looked like in the example.
|
||||
|
||||
Source this new settings file:
|
||||
|
|
@ -107,6 +100,54 @@ Source this new settings file:
|
|||
Step 3
|
||||
~~~~~~
|
||||
|
||||
Add all informations about the part. YAML files for each family are located
|
||||
at database/<family>/mapping/, which contain the part information (parts.yaml),
|
||||
device to fabric mapping (devices.yaml) or hints about resources
|
||||
(resources.yaml).
|
||||
|
||||
The first file contains a mapping between a part number and informations
|
||||
about the device, package and speed grade used by the fuzzers. The
|
||||
complete part number is used as key. Device, package and speedgrade are parts
|
||||
of the part numbers.
|
||||
|
||||
::
|
||||
"xc7a100tcsg324-1":
|
||||
device: "xc7a100t"
|
||||
package: "csg324"
|
||||
speedgrade: "1"
|
||||
pins:
|
||||
0: "N15"
|
||||
1: "U17"
|
||||
2: "V17"
|
||||
3: "V16"
|
||||
4: "V14"
|
||||
5: "U14"
|
||||
6: "U16"
|
||||
|
||||
The second file maps devices to fabrics. Because some fabrics are added to
|
||||
multiple devices, they are only generated for one and parts with the same link
|
||||
to the result.
|
||||
|
||||
::
|
||||
"xc7a50t":
|
||||
fabric: "xc7a50t"
|
||||
"xc7a35t":
|
||||
fabric: "xc7a50t"
|
||||
|
||||
The last file contains information about the information about a resource
|
||||
to support the fuzzers generating the informations. The dictionary pins
|
||||
defines package pins with the following purpose:
|
||||
|
||||
- ``00`` – this must be a clock pin. You can look at the device in the Vivado
|
||||
GUI interactively (click on IOs and check their properties until you find
|
||||
one with IS_CLOCK=true), or run a small clocked design in Vivado and see
|
||||
which pin is assigned to ‘clk’.
|
||||
|
||||
- ``01`` and on – these should be normal data pins on the device.
|
||||
|
||||
Step 4
|
||||
~~~~~~
|
||||
|
||||
Edit the top Makefile
|
||||
|
||||
- Update the Makefile by adding the new device to the `correct
|
||||
|
|
@ -125,7 +166,7 @@ Edit the top Makefile
|
|||
|
||||
ARTIX_PARTS=artix7_200t artix7_100t
|
||||
|
||||
Step 4
|
||||
Step 5
|
||||
~~~~~~
|
||||
|
||||
Make sure you’ve sourced your new device settings file (see the end of
|
||||
|
|
@ -176,7 +217,7 @@ file that was added. For example,
|
|||
- Rerun the top make command,
|
||||
e.g. ``make -j32 MAX_VIVADO_PROCESS=32 db-part-only-artix7_100t``
|
||||
|
||||
Step 5
|
||||
Step 6
|
||||
~~~~~~
|
||||
|
||||
The next task is handling the extra parts – those not fully bonded out.
|
||||
|
|
@ -194,13 +235,9 @@ These are usually the parts you actually have on the boards you buy.
|
|||
|
||||
db-extras-artix7-harness:
|
||||
+source settings/artix7.sh && \
|
||||
XRAY_PIN_00=J13 XRAY_PIN_01=J14 XRAY_PIN_02=K15 XRAY_PIN_03=K16 \
|
||||
XRAY_PART=xc7a35tftg256-1 XRAY_EQUIV_PART=xc7a50tfgg484-1 \
|
||||
$(MAKE) -C fuzzers roi_only
|
||||
XRAY_PART=xc7a35tftg256-1 $(MAKE) -C fuzzers roi_only
|
||||
+ +source settings/artix7_100t.sh && \
|
||||
+ XRAY_PIN_00=N15 \
|
||||
+ XRAY_PART=xc7a100tcsg324-1 XRAY_EQUIV_PART=xc7a100tfgg676-1 \
|
||||
+ $(MAKE) -C fuzzers roi_only
|
||||
+ XRAY_PART=xc7a100tcsg324-1 $(MAKE) -C fuzzers roi_only
|
||||
+source settings/artix7_200t.sh && \
|
||||
XRAY_PIN_00=V10 XRAY_PIN_01=W10 XRAY_PIN_02=Y11 XRAY_PIN_03=Y12 \
|
||||
XRAY_PART=xc7a200tsbg484-1 XRAY_EQUIV_PART=xc7a200tffg1156-1 \
|
||||
|
|
@ -215,7 +252,7 @@ Make the appropriate harness target (adjusting for your family):
|
|||
This target will make updates for the extra parts of all of the family
|
||||
devices, not just your new device.
|
||||
|
||||
Step 6
|
||||
Step 7
|
||||
~~~~~~
|
||||
|
||||
Do a spot check.
|
||||
|
|
@ -224,26 +261,24 @@ Do a spot check.
|
|||
|
||||
::
|
||||
|
||||
$ ll database/artix7/xc7a100*
|
||||
database/artix7/xc7a100tcsg324-1:
|
||||
total 19884
|
||||
drwxrwxr-x 2 tcal tcal 4096 Apr 29 08:01 ./
|
||||
drwxrwxr-x 13 tcal tcal 32768 Apr 29 08:00 ../
|
||||
-rw-rw-r-- 1 tcal tcal 10364 Apr 29 08:00 package_pins.csv
|
||||
-rw-rw-r-- 1 tcal tcal 32142 Apr 29 08:01 part.json
|
||||
-rw-rw-r-- 1 tcal tcal 22440 Apr 29 08:01 part.yaml
|
||||
-rw-rw-r-- 1 tcal tcal 8601612 Apr 29 08:01 tileconn.json
|
||||
-rw-rw-r-- 1 tcal tcal 11648042 Apr 29 08:01 tilegrid.json
|
||||
$ ll database/artix7/xc7a*
|
||||
xc7a35tftg256-1:
|
||||
total 48
|
||||
-rw-rw-r-- 1 daniel daniel 8234 Jan 9 13:01 package_pins.csv
|
||||
-rw-rw-r-- 1 daniel daniel 18816 Jan 9 13:01 part.json
|
||||
-rw-rw-r-- 1 daniel daniel 13099 Jan 9 13:01 part.yaml
|
||||
|
||||
database/artix7/xc7a100tfgg676-1:
|
||||
total 19892
|
||||
drwxrwxr-x 2 tcal tcal 4096 Apr 29 02:03 ./
|
||||
drwxrwxr-x 13 tcal tcal 32768 Apr 29 08:00 ../
|
||||
-rw-rw-r-- 1 tcal tcal 16645 Apr 28 22:16 package_pins.csv
|
||||
-rw-rw-r-- 1 tcal tcal 32165 Apr 28 22:17 part.json
|
||||
-rw-rw-r-- 1 tcal tcal 22440 Apr 28 22:17 part.yaml
|
||||
-rw-rw-r-- 1 tcal tcal 8601612 Apr 29 02:03 tileconn.json
|
||||
-rw-rw-r-- 1 tcal tcal 11648042 Apr 28 22:37 tilegrid.json
|
||||
xc7a50t:
|
||||
total 15480
|
||||
-rw-rw-r-- 1 daniel daniel 695523 Jan 9 12:53 node_wires.json
|
||||
-rw-rw-r-- 1 daniel daniel 8587682 Jan 9 12:53 tileconn.json
|
||||
-rw-rw-r-- 1 daniel daniel 6562851 Jan 9 10:31 tilegrid.json
|
||||
|
||||
xc7a50tfgg484-1:
|
||||
total 52
|
||||
-rw-rw-r-- 1 daniel daniel 13056 Jan 9 09:54 package_pins.csv
|
||||
-rw-rw-r-- 1 daniel daniel 18840 Jan 9 09:58 part.json
|
||||
-rw-rw-r-- 1 daniel daniel 13099 Jan 9 09:58 part.yaml
|
||||
|
||||
In this case, the tile grid is the same size since it’s the same chip,
|
||||
but the size of the package pins files differs, since there are
|
||||
|
|
@ -255,7 +290,7 @@ that your changes in ``prjxray`` will do the right thing when the
|
|||
official database is fully rebuilt. See “Database Updates” below for
|
||||
more information.
|
||||
|
||||
Step 7
|
||||
Step 8
|
||||
~~~~~~
|
||||
|
||||
Assuming everything looks good, commit to your ``prjxray`` fork/branch.
|
||||
|
|
@ -270,7 +305,7 @@ of the example for reference).
|
|||
git status
|
||||
git commit --signoff
|
||||
|
||||
Step 8
|
||||
Step 9
|
||||
~~~~~~
|
||||
|
||||
Push to GitHub:
|
||||
|
|
|
|||
|
|
@ -97,7 +97,10 @@ $(DB_FILES_PATH):
|
|||
${XRAY_FAMILY_DIR}/${XRAY_PART}:
|
||||
mkdir -p ${XRAY_FAMILY_DIR}/${XRAY_PART}
|
||||
|
||||
pushdb: $(DB_FILES_PATH) ${XRAY_FAMILY_DIR}/${XRAY_PART}
|
||||
${XRAY_FAMILY_DIR}/${XRAY_FABRIC}:
|
||||
mkdir -p ${XRAY_FAMILY_DIR}/${XRAY_FABRIC}
|
||||
|
||||
pushdb: $(DB_FILES_PATH) ${XRAY_FAMILY_DIR}/${XRAY_PART} ${XRAY_FAMILY_DIR}/${XRAY_FABRIC}
|
||||
@true
|
||||
|
||||
run:
|
||||
|
|
|
|||
|
|
@ -49,22 +49,23 @@ else
|
|||
TILEGRID_TDB_DEPENDENCIES += dsp_int/$(BUILD_FOLDER)/segbits_tilegrid.tdb
|
||||
endif
|
||||
|
||||
BASICDB_TILEGRID=$(BUILD_FOLDER)/basicdb/${XRAY_PART}/tilegrid.json
|
||||
BASICDB_TILEGRID=$(BUILD_FOLDER)/basicdb/${XRAY_FABRIC}/tilegrid.json
|
||||
|
||||
database: $(BUILD_FOLDER)/tilegrid.json
|
||||
|
||||
pushdb: $(BUILD_FOLDER)/tilegrid.json
|
||||
cp $(BUILD_FOLDER)/tilegrid.json ${XRAY_FAMILY_DIR}/${XRAY_PART}/tilegrid.json
|
||||
cp $(BUILD_FOLDER)/tilegrid.json ${XRAY_FAMILY_DIR}/${XRAY_FABRIC}/tilegrid.json
|
||||
|
||||
$(BUILD_FOLDER)/tiles/tiles.txt:
|
||||
bash generate.sh $(BUILD_FOLDER)/tiles tiles
|
||||
|
||||
${BASICDB_TILEGRID}: generate.py $(BUILD_FOLDER)/tiles/tiles.txt
|
||||
mkdir -p $(BUILD_FOLDER)/basicdb/${XRAY_PART}
|
||||
mkdir -p $(BUILD_FOLDER)/basicdb/${XRAY_FABRIC}
|
||||
ln -sf $(XRAY_DATABASE_DIR)/$(XRAY_DATABASE)/mapping $(BUILD_FOLDER)/basicdb/
|
||||
cd $(BUILD_FOLDER) && python3 ${FUZDIR}/generate.py \
|
||||
--tiles $(BUILD_DIR)/tiles/tiles.txt \
|
||||
--pin_func $(BUILD_DIR)/tiles/pin_func.txt \
|
||||
--out ${BUILD_DIR}/basicdb/${XRAY_PART}/tilegrid.json
|
||||
--out ${BUILD_DIR}/basicdb/${XRAY_FABRIC}/tilegrid.json
|
||||
|
||||
clb/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
|
||||
cd clb && $(MAKE)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ pushdb:
|
|||
cp $(BUILD_DIR)/output/tile_type_*.json ${XRAY_FAMILY_DIR}/
|
||||
rm ${XRAY_FAMILY_DIR}/tile_type_*_site_type_*.json
|
||||
cp $(BUILD_DIR)/output/site_type_*.json ${XRAY_FAMILY_DIR}/
|
||||
cp $(BUILD_DIR)/output/tileconn.json ${XRAY_FAMILY_DIR}/$(XRAY_PART)/
|
||||
cp $(BUILD_DIR)/output/node_wires.json ${XRAY_FAMILY_DIR}/$(XRAY_PART)/
|
||||
cp $(BUILD_DIR)/output/tileconn.json ${XRAY_FAMILY_DIR}/$(XRAY_FABRIC)/
|
||||
cp $(BUILD_DIR)/output/node_wires.json ${XRAY_FAMILY_DIR}/$(XRAY_FABRIC)/
|
||||
|
||||
$(SPECIMENS_OK):
|
||||
bash generate.sh $(subst /OK,,$@) -p=$(MAX_VIVADO_PROCESS) -t=$(MAX_TILES_INSTANCE) -n=$(MAX_NODES_INSTANCE)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ def main():
|
|||
args = parser.parse_args()
|
||||
|
||||
print('{} Reading tilegrid'.format(datetime.datetime.now()))
|
||||
with open(os.path.join(util.get_db_root(), util.get_part(),
|
||||
with open(os.path.join(util.get_db_root(), util.get_fabric(),
|
||||
'tilegrid.json')) as f:
|
||||
tilegrid = json.load(f)
|
||||
grid = Grid(db=None, tilegrid=tilegrid)
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ def main():
|
|||
wire_map_file = os.path.join(args.output_dir, 'wiremap.pickle')
|
||||
|
||||
print('{} Reading tilegrid'.format(datetime.datetime.now()))
|
||||
with open(os.path.join(util.get_db_root(), util.get_part(),
|
||||
with open(os.path.join(util.get_db_root(), util.get_fabric(),
|
||||
'tilegrid.json')) as f:
|
||||
grid = json.load(f)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ def main():
|
|||
|
||||
# Read tile grid and raw node data.
|
||||
print('{} Reading tilegrid'.format(datetime.datetime.now()))
|
||||
with open(os.path.join(util.get_db_root(), util.get_part(),
|
||||
with open(os.path.join(util.get_db_root(), util.get_fabric(),
|
||||
'tilegrid.json')) as f:
|
||||
grid = Grid(db=None, tilegrid=json.load(f))
|
||||
|
||||
|
|
|
|||
|
|
@ -169,9 +169,5 @@ quick:
|
|||
# roi_only runs the fuzzers required for supporting additional parts when building
|
||||
# a roi harness.
|
||||
roi_only: 000-init-db/run.${XRAY_PART}.ok 001-part-yaml/run.${XRAY_PART}.ok 075-pins/run.${XRAY_PART}.ok
|
||||
# Copy tilegrid and tileconn
|
||||
cp ${XRAY_FAMILY_DIR}/${XRAY_EQUIV_PART}/tilegrid.json ${XRAY_FAMILY_DIR}/${XRAY_PART}/tilegrid.json
|
||||
cp ${XRAY_FAMILY_DIR}/${XRAY_EQUIV_PART}/tileconn.json ${XRAY_FAMILY_DIR}/${XRAY_PART}/tileconn.json
|
||||
cp ${XRAY_FAMILY_DIR}/${XRAY_EQUIV_PART}/node_wires.json ${XRAY_FAMILY_DIR}/${XRAY_PART}/node_wires.json
|
||||
|
||||
.PHONY: all clean clean_fuzzers clean_logs quick part_only roi_only
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import signal
|
|||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
from prjxray.util import get_part_information, get_part_resources
|
||||
from prjxray.util import get_fabric_for_part
|
||||
|
||||
import junit_xml
|
||||
|
||||
|
|
@ -447,6 +449,21 @@ def main(argv):
|
|||
os.makedirs(fuzzer_logdir)
|
||||
assert os.path.exists(fuzzer_logdir)
|
||||
|
||||
# Set part information from the mapping files and set into the env
|
||||
db_root = os.path.join(
|
||||
os.environ['XRAY_DATABASE_DIR'], os.environ['XRAY_DATABASE'])
|
||||
part = get_part_information(db_root, os.environ['XRAY_PART'])
|
||||
os.environ['XRAY_DEVICE'] = part['device']
|
||||
os.environ['XRAY_PACKAGE'] = part['package']
|
||||
os.environ['XRAY_SPEED_GRADE'] = part['speedgrade']
|
||||
fabric = get_fabric_for_part(db_root, os.environ['XRAY_PART'])
|
||||
os.environ['XRAY_FABRIC'] = fabric
|
||||
res_path = os.path.join(
|
||||
os.environ['XRAY_DIR'], 'settings', os.environ['XRAY_DATABASE'])
|
||||
resources = get_part_resources(res_path, os.environ['XRAY_PART'])
|
||||
for number, pin in resources['pins'].items():
|
||||
os.environ['XRAY_PIN_{:02d}'.format(number)] = pin
|
||||
|
||||
exit_code = -1
|
||||
args.retries += 1
|
||||
for retry_count in range(0, args.retries):
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
import os, sys, json, re
|
||||
from io import StringIO
|
||||
from prjxray.util import get_fabric_for_part
|
||||
|
||||
|
||||
def mk_get_setting(settings_filename):
|
||||
|
|
@ -234,9 +235,9 @@ class Tweaks():
|
|||
pass
|
||||
|
||||
|
||||
def load_tilegrid(db_dir, part, verbose=False, allow_fake=False):
|
||||
def load_tilegrid(db_dir, fabric, verbose=False, allow_fake=False):
|
||||
print("Loading tilegrid.")
|
||||
with db_open(os.path.join(part, "tilegrid.json"), db_dir) as f:
|
||||
with db_open(os.path.join(fabric, "tilegrid.json"), db_dir) as f:
|
||||
data = f.read()
|
||||
if not data:
|
||||
assert allow_fake, 'No tilegrid.json found'
|
||||
|
|
@ -983,11 +984,9 @@ def run(settings, output, verbose=False, allow_fake=False):
|
|||
|
||||
# Load source data
|
||||
dbstate = DBState()
|
||||
fabric = get_fabric_for_part(db_dir, get_setting("XRAY_PART"))
|
||||
grid = load_tilegrid(
|
||||
db_dir,
|
||||
get_setting("XRAY_PART"),
|
||||
verbose=verbose,
|
||||
allow_fake=allow_fake)
|
||||
db_dir, fabric, verbose=verbose, allow_fake=allow_fake)
|
||||
db_reads(dbstate, db_dir)
|
||||
|
||||
# Create pages
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
source $(dirname ${BASH_SOURCE[0]})/../../settings/artix7_50t.sh
|
||||
|
||||
export XRAY_PART=xc7a35tcsg324-1
|
||||
export XRAY_EQUIV_PART=xc7a50tfgg484-1
|
||||
|
||||
if [ -z "$XRAY_PINCFG" ]; then
|
||||
echo "XRAY_PINCFG not set"
|
||||
|
|
@ -25,15 +24,6 @@ if [ -z "$XRAY_DOUT_N_LARGE" ]; then
|
|||
return 1
|
||||
fi
|
||||
|
||||
# For generating DB
|
||||
export XRAY_PIN_00="G13"
|
||||
export XRAY_PIN_01="B11"
|
||||
export XRAY_PIN_02="E15"
|
||||
export XRAY_PIN_03="U12"
|
||||
export XRAY_PIN_04="D13"
|
||||
export XRAY_PIN_05="J17"
|
||||
export XRAY_PIN_06="U14"
|
||||
|
||||
# HCLK Tile
|
||||
export XRAY_ROI_HCLK="CLK_HROW_TOP_R_X60Y130/CLK_HROW_CK_BUFHCLK_L0"
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
source $(dirname ${BASH_SOURCE[0]})/../../settings/artix7_50t.sh
|
||||
|
||||
export XRAY_PART=xc7a35tcpg236-1
|
||||
export XRAY_EQUIV_PART=xc7a50tfgg484-1
|
||||
|
||||
if [ -z "$XRAY_PINCFG" ]; then
|
||||
echo "XRAY_PINCFG not set"
|
||||
return 1
|
||||
|
|
@ -24,15 +24,6 @@ if [ -z "$XRAY_DOUT_N_LARGE" ]; then
|
|||
return 1
|
||||
fi
|
||||
|
||||
# For generating DB
|
||||
export XRAY_PIN_00="V17"
|
||||
export XRAY_PIN_01="V16"
|
||||
export XRAY_PIN_02="W16"
|
||||
export XRAY_PIN_03="W17"
|
||||
export XRAY_PIN_04="W15"
|
||||
export XRAY_PIN_05="V15"
|
||||
export XRAY_PIN_06="W14"
|
||||
|
||||
# ROI is in the top left
|
||||
export XRAY_ROI_LARGE=SLICE_X0Y100:SLICE_X35Y149
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
export XRAY_PART=xc7z010clg400-1
|
||||
export XRAY_EQUIV_PART=xc7z010clg400-1
|
||||
|
||||
if [ -z "$XRAY_PINCFG" ]; then
|
||||
echo "XRAY_PINCFG not set"
|
||||
|
|
@ -22,15 +21,6 @@ if [ -z "$XRAY_DOUT_N_LARGE" ]; then
|
|||
return 1
|
||||
fi
|
||||
|
||||
# For generating DB
|
||||
export XRAY_PIN_00="G15"
|
||||
export XRAY_PIN_01="P15"
|
||||
export XRAY_PIN_02="W13"
|
||||
export XRAY_PIN_03="T16"
|
||||
export XRAY_PIN_04="K18"
|
||||
export XRAY_PIN_05="P16"
|
||||
export XRAY_PIN_06="K19"
|
||||
|
||||
# ROI is in top right
|
||||
export XRAY_ROI_LARGE="SLICE_X22Y50:SLICE_X43Y99"
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
import os.path
|
||||
import pathlib
|
||||
import simplejson as json
|
||||
from prjxray import grid
|
||||
from prjxray import tile
|
||||
|
|
@ -16,6 +17,7 @@ from prjxray import tile_segbits
|
|||
from prjxray import site_type
|
||||
from prjxray import connections
|
||||
from prjxray.node_model import NodeModel
|
||||
from prjxray.util import get_fabric_for_part
|
||||
|
||||
|
||||
def get_available_databases(prjxray_root):
|
||||
|
|
@ -45,6 +47,8 @@ class Database(object):
|
|||
"""
|
||||
self.db_root = db_root
|
||||
self.part = part
|
||||
self.fabric = get_fabric_for_part(db_root, part)
|
||||
|
||||
# tilegrid.json JSON object
|
||||
self.tilegrid = None
|
||||
self.tileconn = None
|
||||
|
|
@ -129,21 +133,21 @@ class Database(object):
|
|||
def _read_tilegrid(self):
|
||||
""" Read tilegrid database if not already read. """
|
||||
if not self.tilegrid:
|
||||
with open(os.path.join(self.db_root, self.part,
|
||||
with open(os.path.join(self.db_root, self.fabric,
|
||||
'tilegrid.json')) as f:
|
||||
self.tilegrid = json.load(f)
|
||||
|
||||
def _read_tileconn(self):
|
||||
""" Read tileconn database if not already read. """
|
||||
if not self.tileconn:
|
||||
with open(os.path.join(self.db_root, self.part,
|
||||
with open(os.path.join(self.db_root, self.fabric,
|
||||
'tileconn.json')) as f:
|
||||
self.tileconn = json.load(f)
|
||||
|
||||
def _read_node_wires(self):
|
||||
""" Read node wires if not already read. """
|
||||
if self.node_wires is None:
|
||||
with open(os.path.join(self.db_root, self.part,
|
||||
with open(os.path.join(self.db_root, self.fabric,
|
||||
'node_wires.json')) as f:
|
||||
self.node_wires = json.load(f)
|
||||
|
||||
|
|
|
|||
|
|
@ -834,7 +834,7 @@ def main():
|
|||
# Build (baseaddr, offset) -> tile name map
|
||||
database_dir = os.path.join(
|
||||
os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"),
|
||||
os.getenv("XRAY_PART"))
|
||||
os.getenv("XRAY_FABRIC"))
|
||||
tilegrid_file = os.path.join(database_dir, "tilegrid.json")
|
||||
address_map = build_address_map(tilegrid_file)
|
||||
|
||||
|
|
|
|||
|
|
@ -82,15 +82,16 @@ def add_site_group_zero(segmk, site, prefix, vals, zero_val, val):
|
|||
|
||||
|
||||
class Segmaker:
|
||||
def __init__(self, bitsfile, verbose=None, db_root=None, part=None):
|
||||
def __init__(self, bitsfile, verbose=None, db_root=None, fabric=None):
|
||||
self.db_root = db_root
|
||||
if self.db_root is None:
|
||||
self.db_root = util.get_db_root()
|
||||
assert self.db_root, "No db root specified."
|
||||
|
||||
self.part = part
|
||||
if self.part is None:
|
||||
self.part = util.get_part()
|
||||
assert self.part, "No part specified."
|
||||
self.fabric = fabric
|
||||
if self.fabric is None:
|
||||
self.fabric = util.get_fabric()
|
||||
assert self.fabric, "No fabric specified."
|
||||
|
||||
self.verbose = verbose if verbose is not None else os.getenv(
|
||||
'VERBOSE', 'N') == 'Y'
|
||||
|
|
@ -128,7 +129,7 @@ class Segmaker:
|
|||
|
||||
def load_grid(self):
|
||||
'''Load self.grid holding tile addresses'''
|
||||
with open(os.path.join(self.db_root, self.part, "tilegrid.json"),
|
||||
with open(os.path.join(self.db_root, self.fabric, "tilegrid.json"),
|
||||
"r") as f:
|
||||
self.grid = json.load(f)
|
||||
assert "segments" not in self.grid, "Old format tilegrid.json"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import math
|
|||
import os
|
||||
import random
|
||||
import re
|
||||
import yaml
|
||||
from .roi import Roi
|
||||
|
||||
|
||||
|
|
@ -31,6 +32,47 @@ def get_part():
|
|||
return ret
|
||||
|
||||
|
||||
def get_fabric():
|
||||
ret = os.getenv("XRAY_FABRIC", None)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def get_part_information(db_root, part):
|
||||
filename = os.path.join(db_root, "mapping", "parts.yaml")
|
||||
assert os.path.isfile(filename), \
|
||||
"Mapping file {} does not exists".format(filename)
|
||||
with open(filename, 'r') as stream:
|
||||
part_mapping = yaml.load(stream, Loader=yaml.FullLoader)
|
||||
part = part_mapping.get(part, None)
|
||||
assert part, "Part {} not found in {}".format(part, part_mapping)
|
||||
return part
|
||||
|
||||
|
||||
def get_part_resources(file_path, part):
|
||||
filename = os.path.join(file_path, "resources.yaml")
|
||||
assert os.path.isfile(filename), \
|
||||
"Mapping file {} does not exists".format(filename)
|
||||
with open(filename, 'r') as stream:
|
||||
res_mapping = yaml.load(stream, Loader=yaml.FullLoader)
|
||||
res = res_mapping.get(part, None)
|
||||
assert res, "Part {} not found in {}".format(part, part_mapping)
|
||||
return res
|
||||
|
||||
|
||||
def get_fabric_for_part(db_root, part):
|
||||
filename = os.path.join(db_root, "mapping", "devices.yaml")
|
||||
assert os.path.isfile(filename), \
|
||||
"Mapping file {} does not exists".format(filename)
|
||||
part = get_part_information(db_root, part)
|
||||
with open(filename, 'r') as stream:
|
||||
device_mapping = yaml.load(stream, Loader=yaml.FullLoader)
|
||||
device = device_mapping.get(part['device'], None)
|
||||
assert device, "Device {} not found in {}".format(
|
||||
part['device'], device_mapping)
|
||||
return device['fabric']
|
||||
|
||||
|
||||
def roi_xy():
|
||||
x1 = int(os.getenv('XRAY_ROI_GRID_X1', 0))
|
||||
x2 = int(os.getenv('XRAY_ROI_GRID_X2', 58))
|
||||
|
|
|
|||
|
|
@ -31,15 +31,4 @@ export XRAY_ROI_GRID_X2="77"
|
|||
export XRAY_ROI_GRID_Y1="0"
|
||||
export XRAY_ROI_GRID_Y2="51"
|
||||
|
||||
# clock pin
|
||||
export XRAY_PIN_00="Y22"
|
||||
# data pins
|
||||
export XRAY_PIN_01="U17"
|
||||
export XRAY_PIN_02="V17"
|
||||
export XRAY_PIN_03="V16"
|
||||
export XRAY_PIN_04="V14"
|
||||
export XRAY_PIN_05="U14"
|
||||
export XRAY_PIN_06="U16"
|
||||
|
||||
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
# part number to pins
|
||||
"xc7a200tffg1156-1":
|
||||
pins:
|
||||
0: "R26"
|
||||
1: "P26"
|
||||
2: "N26"
|
||||
3: "M27"
|
||||
4: "U25"
|
||||
5: "T25"
|
||||
6: "P24"
|
||||
"xc7a200tsbg484-1":
|
||||
pins:
|
||||
0: "V10"
|
||||
1: "W10"
|
||||
2: "Y11"
|
||||
3: "Y12"
|
||||
4: "U25"
|
||||
5: "T25"
|
||||
6: "P24"
|
||||
"xc7a100tfgg676-1":
|
||||
pins:
|
||||
0: "Y22"
|
||||
1: "U17"
|
||||
2: "V17"
|
||||
3: "V16"
|
||||
4: "V14"
|
||||
5: "U14"
|
||||
6: "U16"
|
||||
"xc7a100tcsg324-1":
|
||||
pins:
|
||||
0: "N15"
|
||||
1: "U17"
|
||||
2: "V17"
|
||||
3: "V16"
|
||||
4: "V14"
|
||||
5: "U14"
|
||||
6: "U16"
|
||||
"xc7a50tfgg484-1":
|
||||
pins:
|
||||
0: "E22"
|
||||
1: "D22"
|
||||
2: "E21"
|
||||
3: "D21"
|
||||
4: "G21"
|
||||
5: "G22"
|
||||
6: "F21"
|
||||
"xc7a35tcsg324-1":
|
||||
pins:
|
||||
0: "G13"
|
||||
1: "B11"
|
||||
2: "E15"
|
||||
3: "U12"
|
||||
4: "D13"
|
||||
5: "J17"
|
||||
6: "U14"
|
||||
"xc7a35tftg256-1":
|
||||
pins:
|
||||
0: "J13"
|
||||
1: "J14"
|
||||
2: "K15"
|
||||
3: "K16"
|
||||
4: "G21"
|
||||
5: "G22"
|
||||
6: "F21"
|
||||
"xc7a35tcpg236-1":
|
||||
pins:
|
||||
0: "V17"
|
||||
1: "V16"
|
||||
2: "W16"
|
||||
3: "W17"
|
||||
4: "W15"
|
||||
5: "V15"
|
||||
6: "W14"
|
||||
|
|
@ -21,14 +21,4 @@ export XRAY_EXCLUDE_ROI_TILEGRID=""
|
|||
# If you have a FASM mismatch or unknown bits in IOIs, CHECK THIS FIRST.
|
||||
export XRAY_IOI3_TILES="RIOI3_X105Y9 LIOI3_X0Y9"
|
||||
|
||||
# clock pin
|
||||
export XRAY_PIN_00="R26"
|
||||
# data pins
|
||||
export XRAY_PIN_01="P26"
|
||||
export XRAY_PIN_02="N26"
|
||||
export XRAY_PIN_03="M27"
|
||||
export XRAY_PIN_04="U25"
|
||||
export XRAY_PIN_05="T25"
|
||||
export XRAY_PIN_06="P24"
|
||||
|
||||
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh
|
||||
|
|
|
|||
|
|
@ -30,14 +30,4 @@ export XRAY_ROI_GRID_X2="58"
|
|||
export XRAY_ROI_GRID_Y1="0"
|
||||
export XRAY_ROI_GRID_Y2="51"
|
||||
|
||||
# clock pin
|
||||
export XRAY_PIN_00="E22"
|
||||
# data pins
|
||||
export XRAY_PIN_01="D22"
|
||||
export XRAY_PIN_02="E21"
|
||||
export XRAY_PIN_03="D21"
|
||||
export XRAY_PIN_04="G21"
|
||||
export XRAY_PIN_05="G22"
|
||||
export XRAY_PIN_06="F21"
|
||||
|
||||
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh
|
||||
|
|
|
|||
|
|
@ -25,13 +25,4 @@ export XRAY_ROI_GRID_X2="38"
|
|||
export XRAY_ROI_GRID_Y1="104"
|
||||
export XRAY_ROI_GRID_Y2="156"
|
||||
|
||||
# Choose the first N High Range I/Os
|
||||
export XRAY_PIN_00="K25"
|
||||
export XRAY_PIN_01="K26"
|
||||
export XRAY_PIN_02="L24"
|
||||
export XRAY_PIN_03="L25"
|
||||
export XRAY_PIN_04="M19"
|
||||
export XRAY_PIN_05="M20"
|
||||
export XRAY_PIN_06="M21"
|
||||
|
||||
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
# part number to pins
|
||||
"xc7k70tfbg676-2":
|
||||
pins:
|
||||
0: "K25"
|
||||
1: "K26"
|
||||
2: "L24"
|
||||
3: "L25"
|
||||
4: "M19"
|
||||
5: "M20"
|
||||
6: "M21"
|
||||
|
|
@ -27,9 +27,4 @@ export XRAY_ROI_GRID_X2="86"
|
|||
export XRAY_ROI_GRID_Y1="105"
|
||||
export XRAY_ROI_GRID_Y2="155"
|
||||
|
||||
export XRAY_PIN_00="Y9"
|
||||
export XRAY_PIN_01="U10"
|
||||
export XRAY_PIN_02="N17"
|
||||
export XRAY_PIN_03="P18"
|
||||
|
||||
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# part number to pins
|
||||
"xc7z020clg484-1":
|
||||
pins:
|
||||
0: "Y9"
|
||||
1: "U10"
|
||||
2: "N17"
|
||||
3: "P18"
|
||||
"xc7z020clg400-1":
|
||||
pins:
|
||||
0: "T9"
|
||||
1: "P14"
|
||||
2: "T14"
|
||||
3: "R18"
|
||||
"xc7z010clg400-1":
|
||||
pins:
|
||||
0: "L14"
|
||||
1: "L15"
|
||||
2: "M14"
|
||||
3: "M15"
|
||||
4: "K16"
|
||||
5: "J16"
|
||||
6: "J15"
|
||||
|
|
@ -27,12 +27,4 @@ export XRAY_ROI_GRID_X2="118"
|
|||
export XRAY_ROI_GRID_Y1="0"
|
||||
export XRAY_ROI_GRID_Y2="51"
|
||||
|
||||
export XRAY_PIN_00="L14"
|
||||
export XRAY_PIN_01="L15"
|
||||
export XRAY_PIN_02="M14"
|
||||
export XRAY_PIN_03="M15"
|
||||
export XRAY_PIN_04="K16"
|
||||
export XRAY_PIN_05="J16"
|
||||
export XRAY_PIN_06="J15"
|
||||
|
||||
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
from os import environ, getcwd, chdir
|
||||
from os import environ, getcwd, chdir, mkdir, environ
|
||||
import json
|
||||
from tempfile import TemporaryDirectory
|
||||
from contextlib import contextmanager
|
||||
|
|
@ -19,7 +19,7 @@ from unittest import TestCase, main
|
|||
# in the current subdirectory, which will be a temporary one, to allow concurent
|
||||
# testing.
|
||||
environ['XRAY_DATABASE_ROOT'] = '.'
|
||||
environ['XRAY_PART'] = './'
|
||||
environ['XRAY_PART'] = 'xc7a200tffg1156-1'
|
||||
|
||||
from prjxray.util import get_roi, get_db_root
|
||||
from prjxray.overlay import Overlay
|
||||
|
|
@ -31,9 +31,18 @@ def setup_database(contents):
|
|||
with TemporaryDirectory() as d:
|
||||
olddir = getcwd()
|
||||
chdir(d)
|
||||
mkdir('xc7a200t')
|
||||
mkdir('mapping')
|
||||
environ['XRAY_DATABASE_ROOT'] = d
|
||||
e = None
|
||||
with open('tilegrid.json', 'w') as fd:
|
||||
with open('xc7a200t/tilegrid.json', 'w') as fd:
|
||||
json.dump(contents, fd)
|
||||
# Create some dummy data
|
||||
with open('mapping/devices.yaml', 'w') as fd:
|
||||
json.dump({'xc7a200t': {'fabric': "xc7a200t"}}, fd)
|
||||
with open('mapping/parts.yaml', 'w') as fd:
|
||||
json.dump({'xc7a200tffg1156-1': {"device": "xc7a200t"}}, fd)
|
||||
|
||||
try:
|
||||
yield
|
||||
except Exception as ereal:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ fi
|
|||
export XRAY_PART_YAML="${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/${XRAY_PART}/part.yaml"
|
||||
source $XRAY_UTILS_DIR/environment.python.sh
|
||||
|
||||
# Set environment to default output and overwrite localisation settings
|
||||
export LC_ALL=C
|
||||
|
||||
# tools
|
||||
export XRAY_GENHEADER="${XRAY_UTILS_DIR}/genheader.sh"
|
||||
export XRAY_BITREAD="${XRAY_TOOLS_DIR}/bitread --part_file ${XRAY_PART_YAML}"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
# device to fabric mapping
|
||||
"xc7a200t":
|
||||
fabric: "xc7a200t"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# part number to device, package and speed grade mapping
|
||||
"xc7a200tffg1156-1":
|
||||
device: "xc7a200t"
|
||||
package: "ffg1156"
|
||||
speedgrade: "1"
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# part number to pins
|
||||
"xc7a200tffg1156-1":
|
||||
pins:
|
||||
0: "R26"
|
||||
1: "P26"
|
||||
2: "N26"
|
||||
3: "M27"
|
||||
4: "U25"
|
||||
5: "T25"
|
||||
6: "P24"
|
||||
|
|
@ -79,7 +79,8 @@ class TestStringMethods(unittest.TestCase):
|
|||
|
||||
fout = StringIO()
|
||||
fasm2frames.run(
|
||||
self.filename_test_data('db'), "xc7", fin.name, fout, **kw)
|
||||
self.filename_test_data('db'), "xc7a200tffg1156-1", fin.name,
|
||||
fout, **kw)
|
||||
|
||||
return fout.getvalue()
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ def load(f):
|
|||
data = data.decode('utf-8')
|
||||
# Strip out of !<tags>
|
||||
data = re.sub("!<[^>]*>", "", data)
|
||||
return yaml.load(io.StringIO(data))
|
||||
return yaml.safe_load(io.StringIO(data))
|
||||
|
||||
|
||||
def tojson(f):
|
||||
|
|
|
|||
Loading…
Reference in New Issue