diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..978c1f3d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,38 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[*.{v,md,rpt,xml}] +charset = unset +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset +indent_style = unset +indent_size = unset + +[Makefile] +indent_style = tab + +[*.{sh,py,rs}] +indent_style = space +indent_size = 4 + +[*.{tcl,scala}] +indent_style = space +indent_size = 2 + +[{runtime,toolflow}/bin/*] +indent_style = space +indent_size = 4 + +[runtime/kernel/**.{c,h}] +indent_style = tab + +[runtime/**.{c,h,cpp,hpp}] +indent_style = space +indent_size = 2 + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e1f4608c..0d9538d1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -109,7 +109,7 @@ build_scala_tapasco_centos_8: - ./gradlew buildRPM artifacts: paths: - - toolflow/scala/build/distributions/tapasco-2020-10.x86_64.rpm + - toolflow/scala/build/distributions/tapasco-2021-01.x86_64.rpm build_scala_tapasco_fedora_30: image: fedora:30 @@ -136,7 +136,7 @@ build_scala_tapasco_fedora_31: - ./gradlew buildDEB artifacts: paths: - - toolflow/scala/build/distributions/tapasco_2020-10_amd64.deb + - toolflow/scala/build/distributions/tapasco_2021-01_amd64.deb build_scala_tapasco_ubuntu_16_04: image: ubuntu:xenial @@ -265,6 +265,7 @@ build_kernel_fedora_31_debug: variables: PACKAGE_TYPE: "RPM" before_script: + - dnf -y update libarchive - dnf -y install kernel-devel make gcc gcc-c++ elfutils-libelf-devel cmake ncurses-devel python3 libatomic git rpm-build curl artifacts: paths: @@ -392,11 +393,12 @@ tapasco_compose_ubuntu: - source $XILINX_VIVADO/settings64.sh - apt-get -y update - apt-get -y install libtinfo5 build-essential - - apt -y install ./toolflow/scala/build/distributions/tapasco_2020-10_amd64.deb + - apt -y install ./toolflow/scala/build/distributions/tapasco_2021-01_amd64.deb - /opt/tapasco/tapasco-init-toolflow.sh - source tapasco-setup-toolflow.sh - - tapasco -v hls counter -p pynq - - tapasco -v --maxThreads 3 compose [counter x 3] @ 100 MHz -p pynq + - tapasco -v hls arrayinit -p pynq + - tapasco import toolflow/examples/Counter.zip as 14 -p pynq + - tapasco -v --maxThreads 3 compose [arrayinit x 2, Counter x 3] @ 100 MHz -p pynq .tapasco_compose: stage: build_hw @@ -419,12 +421,13 @@ tapasco_compose_ubuntu: script: - source $XILINX_VIVADO/settings64.sh - which vivado - - which vivado_hls - - dnf -y install toolflow/scala/build/distributions/tapasco-2020-10.x86_64.rpm + - which vivado_hls || which vitis_hls + - dnf -y install toolflow/scala/build/distributions/tapasco-2021-01.x86_64.rpm - /opt/tapasco/tapasco-init-toolflow.sh - source tapasco-setup-toolflow.sh - - tapasco hls counter -p $PLATFORM --skipEvaluation - - tapasco -v --maxThreads 3 compose [counter x 3] @ 100 MHz -p $PLATFORM $FLAGS + - tapasco hls arrayinit -p $PLATFORM --skipEvaluation + - tapasco import toolflow/examples/Counter.zip as 14 -p $PLATFORM --skipEvaluation + - tapasco -v --maxThreads 3 compose [arrayinit x 2, Counter x 3] @ 100 MHz -p $PLATFORM $FLAGS tapasco_compose_17_4: variables: @@ -462,6 +465,18 @@ tapasco_compose_20_1: XILINX_VIVADO: "/opt/cad/xilinx/vitis/Vivado/${VIVADO_VERSION}" extends: .tapasco_compose +tapasco_compose_20_2: + variables: + VIVADO_VERSION: "2020.2" + XILINX_VIVADO: "/opt/cad/xilinx/vitis/Vivado/${VIVADO_VERSION}" + extends: .tapasco_compose + +tapasco_compose_21_1: + variables: + VIVADO_VERSION: "2021.1" + XILINX_VIVADO: "/opt/cad/xilinx/vitis/Vivado/${VIVADO_VERSION}" + extends: .tapasco_compose + tapasco_compose_pcie: variables: VIVADO_VERSION: "2018.3" diff --git a/README.md b/README.md index d596843d..b7b68bce 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,12 @@ Next to the setup and usage instructions in this README, you can find additional We welcome contributions from anyone interested in this field, check the [contributor's guide](https://github.com/esa-tu-darmstadt/tapasco/wiki/Contributor's-Guide) for more information. +Supported FPGA devices +---------------------- + +* Zynq-based: PYNQ-Z1, ZC706, ZedBoard, Ultra96V2, ZCU102 +* PCIe cards: VC709, NetFPGA-SUME, VCU108, VCU118, VCU1525, Alveo U250, Alveo U280, BittWare XUP-VVH + System Requirements ------------------- @@ -189,40 +195,18 @@ A List of publications about TaPaSCo or TaPaSCo-related research can be found [h If you want to cite TaPaSCo, please use the following information: -[Korinth2019] Korinth, Jens, Jaco Hofmann, Carsten Heinz, and Andreas Koch. 2019. **The -Tapasco Open-Source Toolflow for the Automated Composition of Task-Based -Parallel Reconfigurable Computing Systems.** In *International Symposium -on Applied Reconfigurable Computing (Arc)*. +[Heinz2021a] Heinz, Carsten, Jaco Hofmann, Jens Korinth, Lukas Sommer, Lukas Weber, and Andreas Koch. 2021. **The +Tapasco Open-Source Toolflow.** In *Journal of Signal Processing Systems*. Releases ---------------- We provided pre-compiled packages for many popular Linux distributions. All packages are build for the x86_64 variant. + +| Distribution | Kernel Driver | Kernel Driver (Debug) | Runtime | Runtime (Debug) | Toolflow | +|:-------------|:-------------:|:---------------------:|:-------:|:---------------:|:--------:| +| Ubuntu 16.04 | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_16_04) | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_16_04_debug) | [DEB](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.deb?job=build_tapasco_ubuntu_16_04) | [DEB](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.deb?job=build_tapasco_ubuntu_16_04_debug) | [DEB](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco_2021-01_amd64.deb?job=build_scala_tapasco_ubuntu_16_04) | +| Ubuntu 18.04 | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_18_04) | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_18_04_debug) | [DEB](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.deb?job=build_tapasco_ubuntu_18_04) | [DEB](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.deb?job=build_tapasco_ubuntu_18_04_debug) | [DEB](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco_2021-01_amd64.deb?job=build_scala_tapasco_ubuntu_18_04) | +| Fedora 30 | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_30) | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_30_debug) | [RPM](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.rpm?job=build_tapasco_fedora_30) | [RPM](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.rpm?job=build_tapasco_fedora_30_debug) | [RPM](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco-2021-01.x86_64.rpm?job=build_scala_tapasco_fedora_30) | +| Fedora 31 | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_31) | [Download](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_31_debug) | [RPM](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.rpm?job=build_tapasco_fedora_31) | [RPM](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2021.01.0-Linux.rpm?job=build_tapasco_fedora_31_debug) | [RPM](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco-2021-01.x86_64.rpm?job=build_scala_tapasco_fedora_31) | -### Ubuntu 16.04 -[Kernel Driver](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_16_04) -[Kernel Driver Debug](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_16_04_debug) -[Runtime (DEB)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.deb?job=build_tapasco_ubuntu_16_04) -[Runtime Debug (DEB)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.deb?job=build_tapasco_ubuntu_16_04_debug) -[Toolflow](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco_2020-10_amd64.deb?job=build_scala_tapasco_ubuntu_16_04) - -### Ubuntu 18.04 -[Kernel Driver](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_18_04) -[Kernel Driver Debug](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_ubuntu_18_04_debug) -[Runtime (DEB)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.deb?job=build_tapasco_ubuntu_18_04) -[Runtime Debug (DEB)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.deb?job=build_tapasco_ubuntu_18_04_debug) -[Toolflow](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco_2020-10_amd64.deb?job=build_scala_tapasco_ubuntu_18_04) - -### Fedora 30 -[Kernel Driver](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_30) -[Kernel Driver Debug](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_30_debug) -[Runtime (RPM)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.rpm?job=build_tapasco_fedora_30) -[Runtime Debug (RPM)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.rpm?job=build_tapasco_fedora_30_debug) -[Toolflow](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco-2020-10.x86_64.rpm?job=build_scala_tapasco_fedora_30) - -### Fedora 31 -[Kernel Driver](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_31) -[Kernel Driver Debug](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/runtime/kernel/tlkm.ko?job=build_kernel_fedora_31_debug) -[Runtime (RPM)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.rpm?job=build_tapasco_fedora_31) -[Runtime Debug (RPM)](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/build/tapasco-2020.10.0-Linux.rpm?job=build_tapasco_fedora_31_debug) -[Toolflow](https://git.esa.informatik.tu-darmstadt.de/tapasco/tapasco/-/jobs/artifacts/master/raw/toolflow/scala/build/distributions/tapasco-2020-10.x86_64.rpm?job=build_scala_tapasco_fedora_31) diff --git a/misc/documentation/sfpplus.md b/misc/documentation/sfpplus.md index 7a20ece6..6631b858 100644 --- a/misc/documentation/sfpplus.md +++ b/misc/documentation/sfpplus.md @@ -8,9 +8,10 @@ can be found [here](tapasco-features.md). ## Configuration format -The configuration format is split into two parts: +The configuration format is split into three parts: 1. The [Port Definition](#port-definition) 2. The [Connections of PEs](#pe-connections) to ports + 3. (Optional) The [Mode](#mode) if the platform supports multiple modes ### Port Definition @@ -101,6 +102,53 @@ SFPPLUS { } ] } - ] + ], + ... +} +``` + + +### Mode + +Some platforms provide multiple modes. This can be configured by supplying the name of the mode which should be used. +If no mode is given the default mode for this platform is used. + +Example: + +``` +SFPPLUS { + ... + "Mode": "100G" } -``` \ No newline at end of file +``` + + + +## 100G (UltraScale+) + +The CMAC-IP (100G Ethernet) for Xilinx UltraScale(+) FPGAs has some specialities which need to be respected when using it. +Some of these concern the FPGA itself, others are for the connection partner (switch, nic, ...). +TaPaSCo will automate the FPGA-related specialities to some extent. You need to do the following: + + - Configure the link partner: Disable "Auto Negotiation", fix speed to 100G, activate RS-FEC + - Load Bitstream + - The CMAC automatically resets and the Ethernet link should come up + + +The complete procedure as a reference: + + - IP Configuration: Typically you want to configure with "Enable FCS Insertion/Stripping", "RS-FEC", "Check Preamble" and "Check SFD" enabled. + "Auto Negotiation/Link Training" can also be useful but needs a separate license and is *not* required. + - The link partner needs to be configured to match these settings (if "Auto Negotiation" is disabled): It is (at least) necessary to also disable "Auto Negotiation", fix the speed to 100G and enable RS-FEC. + - Depending on the board there may be specific QSFP28-related board pins (Enable, LowPower, Reset, Interrupt, ...) which need to be respected + - The CMAC-IP has a required startup procedure (which is only partly documented in PG203). All of these steps can be done via the input pins of the IP or via the optional AXI-Lite Interface. These are the steps for the input pins, see PG203 for the AXI-Lite: + - Enable RS-FEC: Set ctl_rx_rsfec_enable, ctl_tx_rsfec_enable, ctl_rx_rsfec_enable_correction, ctl_rx_rsfec_enable_indication to 0x1 + - Reset the core via core_rx_reset and core_tx_reset + - Enable RX: ctl_rx_enable = 0x1 and ctl_tx_send_rfi = 0x1 + - Wait for stat_rx_aligned (output of IP core) + - Enable TX: ctl_tx_send_rfi = 0x0 and ctl_tx_enable = 0x1 + - Sometimes it may be necessary to configure the QSFP28-Transceiver. On the FPGA this is typically possible via I2C. The Transceiver has some status and configuration registers which are specified in SFF-8636. Important registers include + - Interrupt Flags (Byte 3-5, 9-14) + - Power Monitoring (Byte 34-57) + - Control (Byte 86-99) + diff --git a/misc/documentation/tapasco-features.md b/misc/documentation/tapasco-features.md index ed5a6f75..bfa2ca45 100644 --- a/misc/documentation/tapasco-features.md +++ b/misc/documentation/tapasco-features.md @@ -40,7 +40,7 @@ FanControl { #### SFPPLUS The configuration for this feature can be found [here](sfpplus.md) -The ZC706 provides one SFP+ Ports (0). +The ZC706 provides one Mode (10G) with one SFP+ Ports (0). ### ZCU102 @@ -79,7 +79,7 @@ Cache { #### SFPPLUS The configuration for this feature can be found [here](sfpplus.md) -The VC709 provides four SFP+ Ports (0 - 3). +The VC709 provides one Mode (10G) with four SFP+ Ports (0 - 3). ### NetFPGA SUME @@ -94,10 +94,10 @@ The VC709 provides four SFP+ Ports (0 - 3). #### SFPPLUS The configuration for this feature can be found [here](sfpplus.md) -The XUP-VVH provides four QSFP28 Cages. In TaPaSCo each cage provides four physical ports (10GbE each). -So in total you can use up to 16 ports (port numbers 0 - 15) in your design. -The ports 0 - 3 are connected to the top QSFP28 Cage (farthest away from the PCIe connector), -the ports 12 - 15 are connected to the bottom QSFP28 Cage (next to the PCIe connector) +The XUP-VVH provides four QSFP28 Cages. +There are two modes: + - In the default mode (10G) each cage provides four physical ports (10GbE each). So in total you can use up to 16 ports (port numbers 0 - 15) in your design. The ports 0 - 3 are connected to the top QSFP28 Cage (farthest away from the PCIe connector), the ports 12 - 15 are connected to the bottom QSFP28 Cage (next to the PCIe connector). + - In 100G mode there four physical ports (100GbE each). Port 0 is the top QSFP28 Cage, Port 3 is the bottom QSFP28 Cage. #### HBM Allows to connect a subset of the AXI master interfaces of PEs to HBM memory instead of DDR. Each AXI master will be connected to its individual memory block (-> no data sharing possible) of size 256 MB. Up to 32 AXI masters can be connected to HBM. This is configured by specifying "groups" consisting of a PE-ID, a count and one or multiple interface names. diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index b8308c16..ddf28ebe 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -23,8 +23,8 @@ project(TapascoInstall) set(CPACK_GENERATOR "RPM" "DEB" "TGZ" "ZIP" "STGZ" "TBZ2") set(CPACK_PACKAGE_CONTACT "tapasco@esa.tu-darmstadt.de") -set(CPACK_PACKAGE_VERSION_MAJOR 2020) -set(CPACK_PACKAGE_VERSION_MINOR 10) +set(CPACK_PACKAGE_VERSION_MAJOR 2021) +set(CPACK_PACKAGE_VERSION_MINOR 1) set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_NAME tapasco) diff --git a/runtime/examples/CMakeLists.txt b/runtime/examples/CMakeLists.txt index a8b4df66..9eef62fa 100644 --- a/runtime/examples/CMakeLists.txt +++ b/runtime/examples/CMakeLists.txt @@ -33,3 +33,5 @@ add_subdirectory(C++/tapasco-benchmark) add_subdirectory(C++/bandwidth) add_subdirectory(C++/job_completion) add_subdirectory(C++/memtest) + +add_subdirectory(Rust/libtapasco_tests) diff --git a/runtime/examples/Rust/libtapasco_tests/CMakeLists.txt b/runtime/examples/Rust/libtapasco_tests/CMakeLists.txt new file mode 100644 index 00000000..4a567283 --- /dev/null +++ b/runtime/examples/Rust/libtapasco_tests/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (c) 2014-2021 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR) +project(libtapasco_tests) + +# Add a Rust/Cargo project to CMake watching all files in the current directory because Cargo already doesn't do anything if nothing has changed. +add_executable(libtapasco_tests .) + +# Use Cargo to build this project in debug mode by defining a custom target running after the tapasco target has been built. +add_custom_target(libtapasco_tests_cargo_build_debug + COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} cargo build -q + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + DEPENDS tapasco + COMMENT "Building libtapasco_tests with Cargo") + +# Use Cargo to build this project in release mode by defining a custom target running after the tapasco target has been built. +add_custom_target(libtapasco_tests_cargo_build_release + COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} cargo build -q --release + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + DEPENDS tapasco + COMMENT "Building libtapasco_tests with Cargo") + +# Check if building should be in Debug or Release mode +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(TARGET_DIR "debug") + add_dependencies(libtapasco_tests libtapasco_tests_cargo_build_debug) +else() + set(TARGET_DIR "release") + add_dependencies(libtapasco_tests libtapasco_tests_cargo_build_release) +endif() + + +# This tells CMake that this is a C++ executable (but it's Rust) because CMake really wants to know how to link this executable +set_target_properties(libtapasco_tests PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON LINKER_LANGUAGE CXX) +# but it has already been linked by Cargo, so we then tell CMake to use the most failure-proof linker available (none, it's just /usr/bin/true). +# You can't tell CMake not to link this at all, so this is the dirty workaround: +set(CMAKE_CXX_LINK_EXECUTABLE "true") + +# Install the executable in the TaPaSCo PATH +install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR}/libtapasco_tests + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/Tapasco/bin) diff --git a/runtime/examples/Rust/libtapasco_tests/Cargo.toml b/runtime/examples/Rust/libtapasco_tests/Cargo.toml index 14d4fbe5..1596abfe 100644 --- a/runtime/examples/Rust/libtapasco_tests/Cargo.toml +++ b/runtime/examples/Rust/libtapasco_tests/Cargo.toml @@ -17,7 +17,7 @@ log = "0.4.8" snafu = "0.6.6" indicatif = "0.14.0" average = "0.10.4" -uom = "0.27.0" +uom = "0.31.1" rayon = "1.3.0" num_cpus = "1.13.0" crossbeam = "0.7.3" diff --git a/runtime/examples/Rust/libtapasco_tests/src/main.rs b/runtime/examples/Rust/libtapasco_tests/src/main.rs index 305af9db..72b06d54 100644 --- a/runtime/examples/Rust/libtapasco_tests/src/main.rs +++ b/runtime/examples/Rust/libtapasco_tests/src/main.rs @@ -327,7 +327,7 @@ fn test_copy(_: &ArgMatches) -> Result<()> { let a = mem .allocator() .lock()? - .allocate(256 * 4) + .allocate(len as u64, None) .context(AllocatorError)?; let mut golden_samples: Vec = Vec::new(); @@ -417,7 +417,7 @@ fn evaluate_copy(_m: &ArgMatches) -> Result<()> { let a = mem .allocator() .lock()? - .allocate(chunk as u64) + .allocate(chunk as u64, None) .context(AllocatorError)?; let now = Instant::now(); @@ -505,7 +505,7 @@ fn transfer_to( let a = mem .allocator() .lock()? - .allocate(chunk as u64) + .allocate(chunk as u64, None) .context(AllocatorError)?; let mut transferred = 0; let mut incr = 0; @@ -534,7 +534,7 @@ fn transfer_from( let a = mem .allocator() .lock()? - .allocate(chunk as u64) + .allocate(chunk as u64, None) .context(AllocatorError)?; let mut transferred = 0; let mut incr = 0; diff --git a/runtime/kernel/pcie/pcie_irq.c b/runtime/kernel/pcie/pcie_irq.c index 5fa61b6c..a9f0cd84 100644 --- a/runtime/kernel/pcie/pcie_irq.c +++ b/runtime/kernel/pcie/pcie_irq.c @@ -50,7 +50,8 @@ irqreturn_t intr_handler_platform(int irq, void *data) { struct tlkm_irq_mapping *mapping = (struct tlkm_irq_mapping *)data; struct tlkm_pcie_device *dev = mapping->dev->private_data; - eventfd_signal(mapping->eventfd, 1); + if (mapping->eventfd != 0) + eventfd_signal(mapping->eventfd, 1); dev->ack_register[0] = mapping->irq_no; return IRQ_HANDLED; } diff --git a/runtime/libtapasco/Cargo.toml b/runtime/libtapasco/Cargo.toml index 5bba55d9..ac073d27 100644 --- a/runtime/libtapasco/Cargo.toml +++ b/runtime/libtapasco/Cargo.toml @@ -28,6 +28,7 @@ bytes = "0.5.4" libc = "0.2.70" config = "0.10.1" serde = "1.0.115" +vfio-bindings = "0.2.0" [build-dependencies] prost-build = "0.6.1" diff --git a/runtime/libtapasco/config/default.toml b/runtime/libtapasco/config/default.toml index 7f2b7d0c..608ae91f 100644 --- a/runtime/libtapasco/config/default.toml +++ b/runtime/libtapasco/config/default.toml @@ -6,4 +6,5 @@ write_buffer_size = 262144 [tlkm] main_driver_file = "/dev/tlkm" -device_driver_file = "/dev/tlkm_" \ No newline at end of file +device_driver_file = "/dev/tlkm_" +vfio_device = "/sys/devices/platform/tapasco/iommu_group" diff --git a/runtime/libtapasco/src/allocator.rs b/runtime/libtapasco/src/allocator.rs index f2af72a5..70171e28 100644 --- a/runtime/libtapasco/src/allocator.rs +++ b/runtime/libtapasco/src/allocator.rs @@ -23,6 +23,7 @@ use crate::device::DeviceSize; use crate::tlkm::tlkm_ioctl_alloc; use crate::tlkm::tlkm_ioctl_free; use crate::tlkm::tlkm_mm_cmd; +use crate::vfio::*; use core::fmt::Debug; use snafu::ResultExt; use std::fs::File; @@ -48,6 +49,10 @@ pub enum Error { IOCTLFree { source: nix::Error }, #[snafu(display("Fixed allocator is not implemented in driver."))] NoFixedInDriver {}, + #[snafu(display("VFIO ioctl failed: {}", func))] + VfioError {func: String}, + #[snafu(display("VFIO allocator requires va argument, none given"))] + VfioNoVa {}, } type Result = std::result::Result; @@ -58,7 +63,7 @@ type Result = std::result::Result; /// The returned address will match the desired location or an error is return if that /// location is not free. pub trait Allocator: Debug { - fn allocate(&mut self, size: DeviceSize) -> Result; + fn allocate(&mut self, size: DeviceSize, va: Option) -> Result; fn allocate_fixed(&mut self, size: DeviceSize, offset: DeviceAddress) -> Result; fn free(&mut self, ptr: DeviceAddress) -> Result<()>; } @@ -136,7 +141,7 @@ impl GenericAllocator { } impl Allocator for GenericAllocator { - fn allocate(&mut self, size: DeviceSize) -> Result { + fn allocate(&mut self, size: DeviceSize, _va: Option) -> Result { if size == 0 { return Err(Error::InvalidSize { size: size }); } @@ -285,7 +290,10 @@ mod allocator_tests { use crate::allocator::Allocator; use crate::allocator::Error; use crate::allocator::GenericAllocator; + use crate::allocator::VfioAllocator; use crate::allocator::Result; + use crate::vfio::*; + use std::sync::Arc; fn init() { let _ = env_logger::builder().is_test(true).try_init(); @@ -295,7 +303,7 @@ mod allocator_tests { fn complete_allocate() -> Result<()> { init(); let mut a = GenericAllocator::new(0, 1024, 64)?; - let m = a.allocate(1024)?; + let m = a.allocate(1024, None)?; assert_eq!(m, 0); assert_eq!(a.free(m), Ok(())); Ok(()) @@ -308,7 +316,7 @@ mod allocator_tests { let m = a.allocate_fixed(128, 512)?; assert_eq!(m, 512); assert_eq!(a.free(m), Ok(())); - let m2 = a.allocate(1024)?; + let m2 = a.allocate(1024, None)?; assert_eq!(m2, 0); assert_eq!(a.free(m2), Ok(())); Ok(()) @@ -334,7 +342,7 @@ mod allocator_tests { fn allocated_fixed_large() -> Result<()> { init(); let mut a = GenericAllocator::new(0, 0x100000, 64)?; - let m = a.allocate(1228)?; + let m = a.allocate(1228, None)?; assert_eq!(m, 0); let m2 = a.allocate_fixed(2048, 0x80000)?; assert_eq!(m2, 0x80000); @@ -347,10 +355,10 @@ mod allocator_tests { fn alloc_free_alloc() -> Result<()> { init(); let mut a = GenericAllocator::new(0, 1024, 64)?; - let m = a.allocate(1024)?; + let m = a.allocate(1024, None)?; assert_eq!(m, 0); assert_eq!(a.free(m), Ok(())); - let m2 = a.allocate(1024)?; + let m2 = a.allocate(1024, None)?; assert_eq!(m2, 0); assert_eq!(a.free(m2), Ok(())); Ok(()) @@ -360,14 +368,14 @@ mod allocator_tests { fn alloc_free_alloc2() -> Result<()> { init(); let mut a = GenericAllocator::new(0, 1024, 64)?; - let m = a.allocate(512)?; - let m2 = a.allocate(512)?; + let m = a.allocate(512, None)?; + let m2 = a.allocate(512, None)?; assert_eq!(m, 0); assert_eq!(m2, 512); assert_eq!(a.free(m), Ok(())); - assert_eq!(a.allocate(1024), Err(Error::OutOfMemory { size: 1024 })); + assert_eq!(a.allocate(1024, None), Err(Error::OutOfMemory { size: 1024 })); assert_eq!(a.free(m2), Ok(())); - let m3 = a.allocate(768)?; + let m3 = a.allocate(768, None)?; assert_eq!(m3, 0); assert_eq!(a.free(m3), Ok(())); Ok(()) @@ -377,20 +385,20 @@ mod allocator_tests { fn alloc_free_alloc3() -> Result<()> { init(); let mut a = GenericAllocator::new(0, 1024, 64)?; - let m = a.allocate(512)?; - let m2 = a.allocate(512)?; + let m = a.allocate(512, None)?; + let m2 = a.allocate(512, None)?; assert_eq!(m, 0); assert_eq!(m2, 512); assert_eq!(a.free(m), Ok(())); - let m4 = a.allocate(8)?; - let m5 = a.allocate(32)?; - assert_eq!(a.allocate(1024), Err(Error::OutOfMemory { size: 1024 })); + let m4 = a.allocate(8, None)?; + let m5 = a.allocate(32, None)?; + assert_eq!(a.allocate(1024, None), Err(Error::OutOfMemory { size: 1024 })); assert_eq!(a.free(m2), Ok(())); - let m3 = a.allocate(768)?; + let m3 = a.allocate(768, None)?; assert_eq!(a.free(m3), Ok(())); assert_eq!(a.free(m4), Ok(())); assert_eq!(a.free(m5), Ok(())); - let _ = a.allocate(1024)?; + let _ = a.allocate(1024, None)?; Ok(()) } @@ -406,10 +414,37 @@ mod allocator_tests { fn empty_allocate() -> Result<()> { init(); let mut a = GenericAllocator::new(0, 1024, 64)?; - let m = a.allocate(0); + let m = a.allocate(0, None); assert_eq!(m, Err(Error::InvalidSize { size: 0 })); Ok(()) } + + #[test] + fn vfio_alloc() -> Result<()> { + init(); + let vfio_dev = Arc::new(VfioDev::default()); + let mut a = VfioAllocator::new(&vfio_dev)?; + let r0 = a.allocate(100, Some(1000)); + let m = vfio_dev.mappings.lock().unwrap(); + assert_eq!(r0, Ok(1000)); + assert_eq!(m[0].size, IOMMU_PAGESIZE); + assert_eq!(m[0].iova, 0); + std::mem::drop(m); + + let r1 = a.allocate(100, Some(4090)); + let m = vfio_dev.mappings.lock().unwrap(); + assert_eq!(r1, Ok(IOMMU_PAGESIZE + 4090)); + assert_eq!(m[1].size, 2*IOMMU_PAGESIZE); + assert_eq!(m[1].iova, IOMMU_PAGESIZE); + std::mem::drop(m); + + let r2 = a.allocate(5000, Some(4090)); + let m = vfio_dev.mappings.lock().unwrap(); + assert_eq!(r2, Ok(3*IOMMU_PAGESIZE + 4090)); + assert_eq!(m[2].size, 3*IOMMU_PAGESIZE); + assert_eq!(m[2].iova, 3*IOMMU_PAGESIZE); + Ok(()) + } } /// Allocate memory through TLKM @@ -430,7 +465,7 @@ impl DriverAllocator { } impl Allocator for DriverAllocator { - fn allocate(&mut self, size: DeviceSize) -> Result { + fn allocate(&mut self, size: DeviceSize, _va: Option) -> Result { trace!("Allocating {} bytes through driver.", size); let mut cmd = tlkm_mm_cmd { sz: size as usize, @@ -463,3 +498,65 @@ impl Allocator for DriverAllocator { Ok(()) } } + + +/// Allocate memory through VFIO +/// +/// This version may be used on ZynqMP based devices as an alternative to DriverAllocator. +/// Allocator keeps track of memory regions that are mapped using the SMMU of the ZynqMP. +#[derive(Debug, Getters)] +pub struct VfioAllocator { + vfio_dev: Arc, +} +impl VfioAllocator { + pub fn new(vfio_dev: &Arc) -> Result { + Ok(VfioAllocator { + vfio_dev: vfio_dev.clone(), + }) + } +} + +impl Allocator for VfioAllocator { + fn allocate(&mut self, size: DeviceSize, va: Option) -> Result { + let mut maps = self.vfio_dev.mappings.lock().unwrap(); + let iova_start = match maps.last() { + Some(e) => e.iova + e.size, // new alloc starts right of last alloc + None => 0 + }; + let offset = match va { + Some(a) => (a % IOMMU_PAGESIZE), // position of data within page + None => return Err(Error::VfioNoVa{}) + }; + let iova_end = to_page_boundary(iova_start + offset + size + IOMMU_PAGESIZE - 1); + + trace!("Allocating {} bytes starting at iova=0x{:x} offs=0x{:x} through vfio.", + size, iova_start, offset); + maps.push(VfioMapping { + size: iova_end - iova_start, + iova: iova_start + }); + Ok(iova_start + offset) + } + + fn allocate_fixed( + &mut self, + _size: DeviceSize, + _offset: DeviceAddress, + ) -> Result { + Err(Error::NoFixedInDriver {}) + } + + fn free(&mut self, ptr: DeviceAddress) -> Result<()> { + trace!("Deallocating address 0x{:x} through vfio.", ptr); + + let mut maps = self.vfio_dev.mappings.lock().unwrap(); + let iova = to_page_boundary(ptr); + match maps.iter().position(|x| x.iova == iova) { + Some(idx) => match vfio_dma_unmap(&self.vfio_dev, HP_OFFS + maps[idx].iova, maps[idx].size) { + Ok(()) => { maps.remove(idx); Ok(()) } + Err(e) => Err(Error::VfioError {func: e.to_string()}), + }, + None => Err(Error::UnknownMemory { ptr: iova }) + } + } +} diff --git a/runtime/libtapasco/src/device.rs b/runtime/libtapasco/src/device.rs index be109a25..48994898 100644 --- a/runtime/libtapasco/src/device.rs +++ b/runtime/libtapasco/src/device.rs @@ -18,9 +18,9 @@ * along with this program. If not, see . */ -use crate::allocator::{Allocator, DriverAllocator, GenericAllocator}; +use crate::allocator::{Allocator, DriverAllocator, GenericAllocator, VfioAllocator}; use crate::debug::DebugGenerator; -use crate::dma::{DMAControl, DirectDMA, DriverDMA}; +use crate::dma::{DMAControl, DirectDMA, DriverDMA, VfioDMA}; use crate::dma_user_space::UserSpaceDMA; use crate::job::Job; use crate::pe::PEId; @@ -30,6 +30,7 @@ use crate::tlkm::tlkm_ioctl_create; use crate::tlkm::tlkm_ioctl_destroy; use crate::tlkm::tlkm_ioctl_device_cmd; use crate::tlkm::DeviceId; +use crate::vfio::*; use config::Config; use memmap::MmapMut; use memmap::MmapOptions; @@ -100,6 +101,9 @@ pub enum Error { #[snafu(display("Could not parse configuration {}", source))] ConfigError { source: config::ConfigError }, + + #[snafu(display("Could not initialize VFIO subsystem: {}", source))] + VfioInitError { source: crate::vfio::Error }, } type Result = std::result::Result; @@ -321,6 +325,7 @@ impl Device { // has been updated to contain the required information. info!("Using static memory allocation due to lack of dynamic data in the status core."); let mut allocator = Vec::new(); + let zynqmp_vfio_mode = true; let mut is_pcie = false; if name == "pcie" { info!("Allocating the default of 4GB at 0x0 for a PCIe platform"); @@ -375,7 +380,7 @@ impl Device { .context(DMAError)?, ), })); - } else if name == "zynq" || name == "zynqmp" { + } else if name == "zynq" || (name == "zynqmp" && !zynqmp_vfio_mode) { info!("Using driver allocation for Zynq/ZynqMP based platform."); allocator.push(Arc::new(OffchipMemory { allocator: Mutex::new(Box::new( @@ -383,6 +388,17 @@ impl Device { )), dma: Box::new(DriverDMA::new(&tlkm_dma_file)), })); + } else if name == "zynqmp" { + info!("Using VFIO mode for ZynqMP based platform."); + let vfio_dev = Arc::new(init_vfio(settings.clone()) + .context(VfioInitError)? + ); + allocator.push(Arc::new(OffchipMemory { + allocator: Mutex::new(Box::new( + VfioAllocator::new(&vfio_dev).context(AllocatorError)?, + )), + dma: Box::new(VfioDMA::new(&tlkm_dma_file, &vfio_dev)), + })); } else { return Err(Error::DeviceType { name: name }); } diff --git a/runtime/libtapasco/src/dma.rs b/runtime/libtapasco/src/dma.rs index 7a7eb6cb..502a35b3 100644 --- a/runtime/libtapasco/src/dma.rs +++ b/runtime/libtapasco/src/dma.rs @@ -24,6 +24,7 @@ use crate::tlkm::tlkm_copy_cmd_from; use crate::tlkm::tlkm_copy_cmd_to; use crate::tlkm::tlkm_ioctl_copy_from; use crate::tlkm::tlkm_ioctl_copy_to; +use crate::vfio::*; use core::fmt::Debug; use memmap::MmapMut; use snafu::ResultExt; @@ -71,6 +72,9 @@ pub enum Error { "Got interrupt but outstanding buffers are empty. This should never happen." ))] TooManyInterrupts {}, + + #[snafu(display("VFIO failed: {}", source))] + VfioError {source: crate::vfio::Error}, } type Result = std::result::Result; @@ -142,6 +146,62 @@ impl DMAControl for DriverDMA { } } +#[derive(Debug, Getters)] +pub struct VfioDMA { + tlkm_file: Arc, + vfio_dev: Arc, +} + +impl VfioDMA { + pub fn new(tlkm_file: &Arc, vfio_dev: &Arc) -> VfioDMA { + VfioDMA { + tlkm_file: tlkm_file.clone(), + vfio_dev: vfio_dev.clone(), + } + } +} + +/// Use VFIO to transfer data +/// +/// This version may be used on ZynqMP based devices as an alternative to DriverDMA. +/// It makes use of the SMMU to provide direct access to userspace memory to the PL. +impl DMAControl for VfioDMA { + fn copy_to(&self, data: &[u8], iova: DeviceAddress) -> Result<()> { + // No actual data is copied here. Instead, the page-aligned address region + // [va_start, va_start+map_len] is mapped to the I/O virtual address region + // [iova_start, iova_start+map_len] using the SMMU. + // + // The interval [va_start, va_start+map_len] is the smallest page-aligned + // interval that contains the 'data' buffer. + let va_start = to_page_boundary(data.as_ptr() as u64); + let iova_start = to_page_boundary(iova); + let map_len = self.vfio_dev + .get_region_size(iova_start) + .context(VfioError)?; + + trace!( + "Copy Host({:?}) -> Device(0x{:x}) ({} Bytes). Map va=0x{:x} -> iova=0x{:x} len=0x{:x}", + data.as_ptr(), iova, data.len(), va_start, iova_start, map_len + ); + return match vfio_dma_map(&self.vfio_dev, map_len, HP_OFFS + iova_start, va_start) { + Ok(_) => Ok(()), + Err(e) => Err(Error::VfioError {source: e}) + } + } + + fn copy_from(&self, iova: DeviceAddress, data: &mut [u8]) -> Result<()> { + trace!( + "Copy Device(0x{:x}) -> Host({:?}) ({} Bytes)", + iova, + data.as_mut_ptr(), + data.len() + ); + + // nothing to copy, 'data' is same buffer that PE operated on + Ok(()) + } +} + /// Use the CPU to transfer data /// /// Can be used for all memory that is directly accessible by the host. diff --git a/runtime/libtapasco/src/ffi.rs b/runtime/libtapasco/src/ffi.rs index dde2b33a..f8e6886a 100644 --- a/runtime/libtapasco/src/ffi.rs +++ b/runtime/libtapasco/src/ffi.rs @@ -760,7 +760,7 @@ pub extern "C" fn tapasco_memory_allocate( .allocator() .lock() .unwrap() - .allocate(len as u64) + .allocate(len as u64, None) .context(AllocatorError) { Ok(x) => x, diff --git a/runtime/libtapasco/src/job.rs b/runtime/libtapasco/src/job.rs index e9ef8d5f..1a1dcf02 100644 --- a/runtime/libtapasco/src/job.rs +++ b/runtime/libtapasco/src/job.rs @@ -153,7 +153,7 @@ impl Job { .memory .allocator() .lock()? - .allocate(x.data.len() as u64) + .allocate(x.data.len() as u64, Some(x.data.as_ptr() as u64)) .context(AllocatorError)?, }; diff --git a/runtime/libtapasco/src/lib.rs b/runtime/libtapasco/src/lib.rs index ffa83aad..4120f59c 100644 --- a/runtime/libtapasco/src/lib.rs +++ b/runtime/libtapasco/src/lib.rs @@ -45,4 +45,5 @@ pub mod interrupt; pub mod job; pub mod pe; pub mod scheduler; +pub mod vfio; pub mod tlkm; diff --git a/runtime/libtapasco/src/vfio.rs b/runtime/libtapasco/src/vfio.rs new file mode 100644 index 00000000..1f5b5b7e --- /dev/null +++ b/runtime/libtapasco/src/vfio.rs @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. + * + * This file is part of TaPaSCo + * (see https://github.com/esa-tu-darmstadt/tapasco). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +use snafu::ResultExt; +use std::ffi::CString; +use std::os::unix::io::FromRawFd; +use std::fs::{File, OpenOptions, read_link}; +use std::os::unix::io::AsRawFd; +use std::sync::{Mutex, Arc}; +use vfio_bindings::bindings::vfio::*; +use config::Config; + +pub const IOMMU_PAGESIZE: u64 = 4096; +pub const HP_OFFS: u64 = 0x800000000; // AXI Offset IP block between PE and PS + +// VFIO ioctl import +// +// Magic ioctl numbers and ioctl arguments are taken from : +// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/vfio.h +ioctl_none_bad!( + vfio_get_api_version, + request_code_none!(VFIO_TYPE, VFIO_BASE + 0) +); + +ioctl_write_int_bad!( + vfio_check_extension, + request_code_none!(VFIO_TYPE, VFIO_BASE + 1) +); + +ioctl_read_bad!( + vfio_group_get_status, + request_code_none!(VFIO_TYPE, VFIO_BASE + 3), + vfio_group_status +); + +ioctl_write_int_bad!( + vfio_set_iommu, + request_code_none!(VFIO_TYPE, VFIO_BASE + 2) +); + +ioctl_write_ptr_bad!( + vfio_group_set_container, + request_code_none!(VFIO_TYPE, VFIO_BASE + 4), + i32 +); + +ioctl_write_ptr_bad!( + vfio_group_get_device_fd, + request_code_none!(VFIO_TYPE, VFIO_BASE + 6), + u8 +); + +ioctl_read_bad!( + vfio_device_get_info, + request_code_none!(VFIO_TYPE, VFIO_BASE + 7), + vfio_device_info +); + +ioctl_readwrite_bad!( + vfio_device_get_region_info, + request_code_none!(VFIO_TYPE, VFIO_BASE + 8), + vfio_region_info +); + +ioctl_read_bad!( + vfio_iommu_get_info, + request_code_none!(VFIO_TYPE, VFIO_BASE + 12), + vfio_iommu_type1_info +); + +ioctl_write_ptr_bad!( + vfio_iommu_map_dma, + request_code_none!(VFIO_TYPE, VFIO_BASE + 13), + vfio_iommu_type1_dma_map +); + +ioctl_readwrite_bad!( + vfio_iommu_unmap_dma, + request_code_none!(VFIO_TYPE, VFIO_BASE + 14), + vfio_iommu_type1_dma_unmap +); + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("Could not open {}: {}", file, source))] + VfioOpen { + source: std::io::Error, + file: String + }, + + #[snafu(display("Make sure the vfio_platform driver is loaded: {}, {}", file, source))] + VfioNoGroup { + source: std::io::Error, + file: String + }, + + #[snafu(display("Could not parse configuration {}", source))] + ConfigError { source: config::ConfigError }, + + #[snafu(display("IOCTL {} failed", name))] + IoctlError { name: String }, + + #[snafu(display("IOMMU mapping for iova=0x{:x} not found", iova))] + MappingError { iova: u64 }, +} + +/// Instance of an SMMU mapping +/// +/// iova: virtual memory address used by PL +/// size: Size of the mapped memory region +#[derive(Debug)] +pub struct VfioMapping { + pub iova: u64, + pub size: u64 +} + +/// Instance of the current VFIO context +#[derive(Debug)] +pub struct VfioDev { + container: File, + group: File, + device: File, + pub mappings: Mutex> +} +impl VfioDev { + pub fn get_region_size(&self, iova: u64) -> Result { + let m = self.mappings.lock().unwrap(); + match m.iter().find(|x| x.iova == iova) { + Some(e) => Ok(e.size), + None => Err(Error::MappingError { iova }) + } + } +} +impl Default for VfioDev { + // only used for testing + fn default() -> VfioDev { + VfioDev { + container: File::open("/dev/null").unwrap(), + group: File::open("/dev/null").unwrap(), + device: File::open("/dev/null").unwrap(), + mappings: Mutex::new(Vec::new()) + } + } +} + +pub fn to_page_boundary(x: u64) -> u64 { + return x - (x % IOMMU_PAGESIZE); +} + +// get VFIO group number of tapasco platform device from sysfs +fn get_vfio_group(settings: Arc) -> Result { + let dev_path = settings + .get_str("tlkm.vfio_device") + .context(ConfigError)?; + let iommu_group_path = read_link(&dev_path) + .context(VfioNoGroup {file: &dev_path} )?; + let iommu_group = iommu_group_path.file_name().unwrap().to_str().unwrap(); + + return Ok(iommu_group.parse().unwrap()) +} + +pub fn init_vfio(settings: Arc) -> Result { + trace!("Initializing VFIO"); + let container_path = "/dev/vfio/vfio"; + let container = OpenOptions::new() + .read(true) + .write(true) + .open(container_path) + .context(VfioOpen { file: container_path })?; + + let mut ret = unsafe { vfio_get_api_version(container.as_raw_fd()) }.unwrap(); + if ret != VFIO_API_VERSION as i32 { + error!("VFIO version is {} should be {}", ret, VFIO_API_VERSION); + return Err(Error::IoctlError{ name: "vfio_get_api_version".to_string() }); + } else { + trace!("VFIO version is {}, okay!", ret); + } + + ret = unsafe { vfio_check_extension(container.as_raw_fd(), VFIO_TYPE1_IOMMU as i32) }.unwrap(); + if ret > 0 { + trace!("VFIO_TYPE1_IOMMU okay!"); + } else { + error!("VFIO_TYPE1_IOMMU not supported"); + return Err(Error::IoctlError{ name: "vfio_check_extension".to_string() }); + } + + let group_path = format!("/dev/vfio/{}", get_vfio_group(settings)?); + let group = OpenOptions::new() + .read(true) + .write(true) + .open(&group_path) + .context(VfioNoGroup {file: &group_path} )?; + + let mut group_status = vfio_group_status { + argsz: std::mem::size_of::() as u32, + flags: 0, + }; + ret = unsafe { vfio_group_get_status(group.as_raw_fd(), &mut group_status) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_group_get_status".to_string() }); + } else if (group_status.flags & VFIO_GROUP_FLAGS_VIABLE) != VFIO_GROUP_FLAGS_VIABLE { + error!("VFIO group is not viable\n"); + return Err(Error::IoctlError{ name: "vfio_group_get_status".to_string() }); + } else { + trace!("VFIO group is okay\n"); + } + + ret = unsafe { vfio_group_set_container(group.as_raw_fd(), &container.as_raw_fd()) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_group_set_container".to_string() }); + } else { + trace!("VFIO set container okay\n"); + } + + ret = unsafe { vfio_set_iommu(container.as_raw_fd(), VFIO_TYPE1_IOMMU as i32) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_set_iommu".to_string() }); + } else { + trace!("vfio_set_iommu okay\n"); + } + + let dev_name = CString::new("tapasco").unwrap(); + let dev_fd = unsafe { vfio_group_get_device_fd( + group.as_raw_fd(), + dev_name.as_ptr() as *const u8 + ) }.unwrap(); + if dev_fd < 0 { + return Err(Error::IoctlError{ name: "vfio_group_get_device_fd".to_string() }); + } else { + trace!("vfio_group_get_device_fd okay: fd={}\n", dev_fd); + } + + Ok(VfioDev{ + container, + group, + device: unsafe { File::from_raw_fd(dev_fd) }, + mappings: Mutex::new(Vec::new()) + }) +} + +pub fn vfio_get_info(dev: &VfioDev) -> Result { + let mut iommu_info = vfio_iommu_type1_info { + argsz: std::mem::size_of::() as u32, + flags: 0, + iova_pgsizes: 0, + }; + let ret = unsafe { vfio_iommu_get_info(dev.container.as_raw_fd(), &mut iommu_info) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_iommu_get_info".to_string() }); + } else { + trace!("flags={}, Pagesize bitvector=0x{:x}!\n", iommu_info.flags, iommu_info.iova_pgsizes); + Ok(iommu_info) + } +} + +pub fn vfio_get_region_info(dev: &VfioDev) -> Result { + let mut dev_info = vfio_device_info { + argsz: std::mem::size_of::() as u32, + flags: 0, + num_regions: 0, + num_irqs: 0, + }; + let ret = unsafe { vfio_device_get_info(dev.device.as_raw_fd(), &mut dev_info) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_device_get_info".to_string() }); + } else { + trace!("VFIO device has {} regions\n", dev_info.num_regions); + } + + // get info for all regions + for r in 0..dev_info.num_regions { + let mut reg_info = vfio_region_info { + argsz: std::mem::size_of::() as u32, + flags: 0, + index: r, + cap_offset: 0, + size: 0, + offset: 0, + }; + let ret = unsafe { vfio_device_get_region_info(dev.device.as_raw_fd(), &mut reg_info) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_device_get_region_info".to_string() }); + } else { + trace!("Region {}: sz=0x{:x}, offs=0x{:x}\n", r, reg_info.size, reg_info.offset); + } + } + Ok(dev_info) +} + +pub fn vfio_dma_map(dev: &VfioDev, size: u64, iova: u64, vaddr: u64) -> Result<(), Error> { + let dma_map_src = vfio_iommu_type1_dma_map { + argsz: std::mem::size_of::() as u32, + flags: VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, + vaddr, + iova, + size, + }; + + let ret = unsafe { vfio_iommu_map_dma(dev.container.as_raw_fd(), &dma_map_src) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_iommu_map_dma".to_string() }); + } else { + trace!("vfio_iommu_map_dma: va=0x{:x} -> iova=0x{:x}, size=0x{:x}\n", vaddr, iova, size); + Ok(()) + } +} + +pub fn vfio_dma_unmap(dev: &VfioDev, iova: u64, size: u64) -> Result<(), Error> { + let mut dma_unmap = vfio_iommu_type1_dma_unmap { + argsz: std::mem::size_of::() as u32, + flags: 0, + iova, + size, + }; + + let ret = unsafe { vfio_iommu_unmap_dma(dev.container.as_raw_fd(), &mut dma_unmap) }.unwrap(); + if ret < 0 { + return Err(Error::IoctlError{ name: "vfio_iommu_unmap_dma".to_string() }); + } else { + trace!("vfio_iommu_unmap_dma: iova=0x{:x}, size=0x{:x}\n", iova, size); + Ok(()) + } +} diff --git a/runtime/scripts/zynq/bit_reload.sh b/runtime/scripts/zynq/bit_reload.sh index 974c6706..63bc75f4 100755 --- a/runtime/scripts/zynq/bit_reload.sh +++ b/runtime/scripts/zynq/bit_reload.sh @@ -32,6 +32,8 @@ set -e # init paths DRIVER=tlkm DRIVERPATH="$TAPASCO_HOME_RUNTIME/kernel" +VFIO_RST_REQ="/sys/module/vfio_platform/parameters/reset_required" +VFIO_UNSAFE_INTR="/sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts" show_usage() { cat << EOF @@ -133,7 +135,27 @@ if [ -n $BITSTREAM ] && [[ $BITSTREAM == *.bit || $BITSTREAM == *.bin ]]; then if [ $INSMOD_RET -ne 0 ]; then echo "Loading driver failed, returned non-zero exit code $INSMOD_RET" else - echo "Driver loaded sucessfully!" + echo "Driver loaded successfully!" + fi + + if [ ! -f "$VFIO_RST_REQ" ] || [ "$(cat $VFIO_RST_REQ)" != "N" ]; then + echo "VFIO configuration error! Need to add bootarg 'vfio_platform.reset_required=0'" + else + # register tapasco device with VFIO + sudo sh -c "echo vfio-platform > /sys/bus/platform/devices/tapasco/driver_override" + sudo sh -c "echo tapasco > /sys/bus/platform/drivers_probe" + PROBE_RET=$? + if [ $PROBE_RET -ne 0 ]; then + echo "Probing VFIO platform driver failed, returned non-zero exit code $PROBE_RET" + else + echo "VFIO loaded successfully!" + fi + sudo chmod a+rw /dev/vfio/* + fi + + # is required on the zcu102 + if [ -f "$VFIO_UNSAFE_INTR" ] && [ "$(cat $VFIO_UNSAFE_INTR)" == "N" ]; then + sudo sh -c "echo Y > $VFIO_UNSAFE_INTR" fi fi fi diff --git a/toolflow/bin/json_to_status b/toolflow/bin/json_to_status index e790cb19..c0ed246f 100755 Binary files a/toolflow/bin/json_to_status and b/toolflow/bin/json_to_status differ diff --git a/toolflow/boot/bootscr/boot-zcu102.txt b/toolflow/boot/bootscr/boot-zcu102.txt new file mode 100644 index 00000000..ff9d961b --- /dev/null +++ b/toolflow/boot/bootscr/boot-zcu102.txt @@ -0,0 +1,3 @@ +mw.size 0xff180408 0xff +setenv bootargs $bootargs root=/dev/mmcblk0p2 rw rootwait vfio_platform.reset_required=0 +if mmcinfo; then load mmc 0 ${kernel_addr_r} Image && load mmc 0 ${fdt_addr_r} system.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}; fi diff --git a/toolflow/boot/configs/tapasco_zynqmp_defconfig b/toolflow/boot/configs/tapasco_zynqmp_defconfig index 5c826d17..b09c6475 100644 --- a/toolflow/boot/configs/tapasco_zynqmp_defconfig +++ b/toolflow/boot/configs/tapasco_zynqmp_defconfig @@ -398,3 +398,6 @@ CONFIG_MAGIC_SYSRQ=y # TaPaSCO specific CONFIG_LOCALVERSION="-tapasco" CONFIG_DEFAULT_HOSTNAME="$BOARD" +CONFIG_VFIO=y +CONFIG_VFIO_PLATFORM=y +CONFIG_VFIO_IOMMU_TYPE1=y diff --git a/toolflow/boot/generate_boot_image.sh b/toolflow/boot/generate_boot_image.sh index e0c0bb21..1cc706a2 100755 --- a/toolflow/boot/generate_boot_image.sh +++ b/toolflow/boot/generate_boot_image.sh @@ -11,8 +11,8 @@ LINUX_XLNX_URL="https://github.com/xilinx/linux-xlnx.git" UBOOT_URL="https://github.com/xilinx/u-boot-xlnx.git" ATF_URL="https://github.com/Xilinx/arm-trusted-firmware.git" ARTYZ7_DTS_URL="https://raw.githubusercontent.com/Digilent/linux-digilent/master/arch/arm/boot/dts/zynq-artyz7.dts" -ROOTFS_URL="http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04-base-armhf.tar.gz" -ROOTFS64_URL="http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04-base-arm64.tar.gz" +ROOTFS_URL="http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.2-base-armhf.tar.gz" +ROOTFS64_URL="http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.2-base-arm64.tar.gz" ROOTFS_TAR_GZ="$DIR/ubuntu_armhf_20.04.tar.gz" ROOTFS64_TAR_GZ="$DIR/ubuntu_arm64_20.04.tar.gz" UDEV_RULES="$TAPASCO_HOME/platform/zynq/module/99-tapasco.rules" @@ -182,7 +182,6 @@ build_u-boot() { case $BOARD in "pynq") # based on zybo z7, but requires a few changes - DEFCONFIG=zynq_zybo_z7_defconfig echo "CONFIG_DEBUG_UART_BASE=0xe0000000" >> $DIR/u-boot-xlnx/configs/$DEFCONFIG # modify devicetree # change uart1 to uart0 @@ -191,23 +190,30 @@ build_u-boot() { sed -i 's/33333333/50000000/' $DIR/u-boot-xlnx/arch/arm/dts/zynq-zybo-z7.dts # set memory size to 512 MB sed -i 's/40000000/20000000/' $DIR/u-boot-xlnx/arch/arm/dts/zynq-zybo-z7.dts + DEVICE_TREE="zynq-zybo-z7" ;; "zedboard") - DEFCONFIG=zynq_zed_defconfig + DEVICE_TREE="zynq-zed" ;; "zc706") - DEFCONFIG=zynq_zc706_defconfig + DEVICE_TREE="zynq-zc706" ;; "ultra96v2") - DEFCONFIG=avnet_ultra96_rev1_defconfig + DEVICE_TREE="avnet-ultra96-rev1" ;; "zcu102") - DEFCONFIG=xilinx_zynqmp_zcu102_rev1_0_defconfig + DEVICE_TREE="zynqmp-zcu102-rev1.0" ;; *) return $(error_ret "unknown board: $BOARD") ;; esac + # use common defconfigs introduced with Vivado 2020.1 + if [[ $ARCH == arm ]]; then + DEFCONFIG=xilinx_zynq_virt_defconfig + else + DEFCONFIG=xilinx_zynqmp_virt_defconfig + fi cd $DIR/u-boot-xlnx # disable network boot for all devices echo "# CONFIG_CMD_NET is not set" >> configs/$DEFCONFIG @@ -215,10 +221,10 @@ build_u-boot() { echo "CONFIG_OF_EMBED=y" >> $DIR/u-boot-xlnx/configs/$DEFCONFIG echo "# CONFIG_OF_SEPARATE is not set" >> $DIR/u-boot-xlnx/configs/$DEFCONFIG fi - make CROSS_COMPILE=$CROSS_COMPILE $DEFCONFIG || + make CROSS_COMPILE=$CROSS_COMPILE $DEFCONFIG DEVICE_TREE=$DEVICE_TREE || return $(error_ret "$LINENO: could not make defconfig $DEFCONFIG") if [[ $ARCH != arm64 ]]; then - make CROSS_COMPILE=$CROSS_COMPILE HOSTCFLAGS=$HOSTCFLAGS HOSTLDFLAGS="$HOSTLDFLAGS" tools -j $JOBCOUNT || + make CROSS_COMPILE=$CROSS_COMPILE HOSTCFLAGS=$HOSTCFLAGS HOSTLDFLAGS="$HOSTLDFLAGS" DEVICE_TREE=$DEVICE_TREE tools -j $JOBCOUNT || return $(error_ret "$LINENO: could not build u-boot tools") fi else @@ -287,6 +293,10 @@ build_ssbl() { echo "$DIR/u-boot-xlnx/u-boot already exists, skipping." fi + if [[ ! -f $DIR/boot.scr && -e $SCRIPTDIR/bootscr/boot-$BOARD.txt ]]; then + $DIR/u-boot-xlnx/tools/mkimage -A arm -T script -O linux -d $SCRIPTDIR/bootscr/boot-$BOARD.txt $DIR/boot.scr + fi + if [[ $ARCH != arm64 ]]; then cp $DIR/u-boot-xlnx/u-boot $DIR/u-boot-xlnx/u-boot.elf || return $(error_ret "$LINENO: could not copy to $DIR/u-boot-xlnx/u-boot.elf failed") @@ -453,8 +463,14 @@ build_bootbin() { if [[ ! -f $DIR/BOOT.BIN ]]; then echo "Building BOOT.BIN ..." if [[ $ARCH == arm64 ]]; then + # set brdc_inner bit of the lpd_apu register in the LPD_SLCR module for VFIO/SMMU support + cat > $DIR/regs.init << EOF + .set. 0xFF41A040 = 0x3; +EOF + cat > $DIR/bootimage.bif << EOF - image: { + boot_image : { + [init] $DIR/regs.init [bootloader,destination_cpu=a53-0] $DIR/fsbl/executable.elf [pmufw_image] $DIR/pmufw/executable.elf [destination_cpu=a53-0, exception_level=el-3,trustzone] $DIR/arm-trusted-firmware/build/zynqmp/release/bl31/bl31.elf @@ -465,7 +481,7 @@ EOF return $(error_ret "$LINENO: could not generate BOOT.bin") else cat > $DIR/bootimage.bif << EOF - image : { + boot_image : { [bootloader]$DIR/fsbl/executable.elf $DIR/u-boot-xlnx/u-boot.elf } @@ -508,6 +524,9 @@ build_devtree() { echo >> $DIR/devicetree.dts if [[ $ARCH == arm64 ]]; then echo "/include/ \"$SCRIPTDIR/misc/tapasco_zynqmp.dtsi\"" >> $DIR/devicetree.dts + + # re-add label that was lost during compilation, so that we can reference it in dtsi + sed -i 's/smmu@fd800000/smmu: smmu@fd800000/' $DIR/devicetree.dts else echo "/include/ \"$SCRIPTDIR/misc/tapasco.dtsi\"" >> $DIR/devicetree.dts fi @@ -604,6 +623,11 @@ copy_files_to_boot() { echo >&2 "$LINENO: WARNING: could not copy Image" echo "Copying $DIR/devicetree.dtb to $TO/system.dtb ..." dusudo cp $DIR/devicetree.dtb $TO/system.dtb || echo >&2 "$LINENO: WARNING: could not copy devicetree" + if [[ -f uenv/uEnv-$BOARD.txt ]]; then + echo "Copying uenv/uEnv-$BOARD.txt to $TO/uEnv.txt ..." + dusudo cp uenv/uEnv-$BOARD.txt $TO/uEnv.txt || + echo >&2 "$LINENO: WARNING: could not copy uEnv.txt" + fi else echo "Copying $DIR/linux-xlnx/arch/arm/boot/uImage to $TO ..." dusudo cp $DIR/linux-xlnx/arch/arm/boot/uImage $TO || @@ -614,6 +638,10 @@ copy_files_to_boot() { echo "Copying $DIR/devicetree.dtb to $TO ..." dusudo cp $DIR/devicetree.dtb $TO || echo >&2 "$LINENO: WARNING: could not copy devicetree" fi + if [[ -f $DIR/boot.scr ]]; then + echo "Copying $DIR/boot.scr to $TO/boot.scr ..." + dusudo cp $DIR/boot.scr $TO/boot.scr || echo >&2 "$LINENO: WARNING: could not copy boot.scr" + fi dusudo umount $TO rmdir $TO 2> /dev/null && echo "Boot partition ready." @@ -654,7 +682,7 @@ apt-get -y upgrade # runtime dependencies (without linux-headers) DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential python cmake libelf-dev libncurses-dev git rpm # additional tools -apt-get install -y vim-tiny sudo iproute2 ssh kmod ifupdown net-tools jitterentropy-rngd haveged +apt-get install -y vim-tiny sudo iproute2 ssh kmod ifupdown net-tools jitterentropy-rngd haveged libssl-dev bc rsync systemctl enable ssh systemctl enable getty@ttyPS0.service useradd -G sudo -m -s /bin/bash tapasco @@ -676,7 +704,7 @@ make clean rm -rf source sudo -u tapasco git clone https://github.com/esa-tu-darmstadt/tapasco.git /home/tapasco/tapasco -echo '' /etc/resolv.conf +echo '' > /etc/resolv.conf EOF" dusudo rm $TO/usr/bin/qemu-* dusudo cp $SCRIPTDIR/misc/resizefs $TO/home/tapasco/ @@ -752,7 +780,7 @@ if [[ $ARCH == arm64 ]]; then echo "Building U-Boot SSBL (output in $BUILD_SSBL_LOG) and Arm Trusted Firmware (output in $BUILD_ARM_TRUSTED_FIRMWARE_LOG) ... " build_arm_trusted_firmware &> $BUILD_ARM_TRUSTED_FIRMWARE_LOG & BUILD_ARM_TRUSTED_FIRMWARE_OK=$! - wait $BUILD_ARM_TRUSTED_FIRMWARE || error_exit "Building Arm Trusted Firmware failed, check log: $ARM_TRUSTED_FIRMWARE_LOG" + wait $BUILD_ARM_TRUSTED_FIRMWARE_OK || error_exit "Building Arm Trusted Firmware failed, check log: $ARM_TRUSTED_FIRMWARE_LOG" else echo "Building U-Boot SSBL (output in $BUILD_SSBL_LOG) and uImage (output in $BUILD_UIMAGE_LOG) ..." build_uimage &> $BUILD_UIMAGE_LOG & diff --git a/toolflow/boot/misc/tapasco_zynqmp.dtsi b/toolflow/boot/misc/tapasco_zynqmp.dtsi index 7725e8c2..d8809ac4 100644 --- a/toolflow/boot/misc/tapasco_zynqmp.dtsi +++ b/toolflow/boot/misc/tapasco_zynqmp.dtsi @@ -16,5 +16,10 @@ compatible = "tapasco"; interrupt-parent = <0x4>; interrupts = <0x0 0x59 0x4 0x0 0x5a 0x4 0x0 0x5b 0x4 0x0 0x5c 0x4 0x0 0x5d 0x4 0x0 0x5e 0x4 0x0 0x5f 0x4 0x0 0x60 0x4 0x0 0x68 0x4 0x0 0x69 0x4 0x0 0x6a 0x4 0x0 0x6b 0x4 0x0 0x6c 0x4 0x0 0x6d 0x4 0x0 0x6e 0x4 0x0 0x6f 0x4>; + iommus = <&smmu 0x200 0x3f>; }; }; + +&smmu { + status = "okay"; +}; diff --git a/toolflow/boot/uenv/uEnv-ultra96v2.txt b/toolflow/boot/uenv/uEnv-ultra96v2.txt new file mode 100644 index 00000000..136261d2 --- /dev/null +++ b/toolflow/boot/uenv/uEnv-ultra96v2.txt @@ -0,0 +1 @@ +sdroot0=setenv bootargs $bootargs root=/dev/mmcblk0p2 rw rootwait vfio_platform.reset_required=0 diff --git a/toolflow/boot/uenv/uEnv-zcu102.txt b/toolflow/boot/uenv/uEnv-zcu102.txt new file mode 100644 index 00000000..136261d2 --- /dev/null +++ b/toolflow/boot/uenv/uEnv-zcu102.txt @@ -0,0 +1 @@ +sdroot0=setenv bootargs $bootargs root=/dev/mmcblk0p2 rw rootwait vfio_platform.reset_required=0 diff --git a/toolflow/examples/Counter.zip b/toolflow/examples/Counter.zip new file mode 100644 index 00000000..b242f85e Binary files /dev/null and b/toolflow/examples/Counter.zip differ diff --git a/toolflow/examples/kernel-examples/counter/counter.cpp b/toolflow/examples/kernel-examples/counter/counter.cpp deleted file mode 100644 index 503a1ef3..00000000 --- a/toolflow/examples/kernel-examples/counter/counter.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (C) 2014 Jens Korinth, TU Darmstadt -// -// This file is part of Tapasco (TPC). -// -// Tapasco is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Tapasco is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Tapasco. If not, see . -// -/** - * @file counter.cpp - * @brief HLS implementation of a simple 32bit counter: - * Waits the number of clock cycles specified in first arg before - * raising the interrupt. - * @author J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de) - **/ -#include "counter.h" -#ifndef __SYNTHESIS__ - #include - #include - using namespace std; -#else - #include -#endif - -uint32_t counter(const uint32_t clock_cycles) -{ - #ifdef __SYNTHESIS__ - // 15 clock cycles seems to be the minimum overhead (2015.2) - // compare with values found in interval report for co-simulation - if (clock_cycles > 15) - { - #pragma HLS PROTOCOL fixed - wait(clock_cycles - 15); - } - #else - usleep(clock_cycles); // only an approximation - #endif - return clock_cycles; -} - -#ifndef __SYNTHESIS__ -int main(int argc, char **argv) -{ - for (uint32_t i = 0; i < 1000; ++i) { - if (counter(i) != i) return 1; - } -} -#endif -/* vim: set foldmarker=@{,@} foldlevel=0 foldmethod=marker : */ diff --git a/toolflow/examples/kernel-examples/counter/counter.h b/toolflow/examples/kernel-examples/counter/counter.h deleted file mode 100644 index de3b4ebc..00000000 --- a/toolflow/examples/kernel-examples/counter/counter.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (C) 2014 Jens Korinth, TU Darmstadt -// -// This file is part of Tapasco (TPC). -// -// Tapasco is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Tapasco is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Tapasco. If not, see . -// -/** - * @file counter.h - * @brief HLS implementation of a simple 32bit counter: - * Waits the number of clock cycles specified in first arg before - * raising the interrupt. - * @author J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de) - **/ -#ifndef __COUNTER_H__ -#define __COUNTER_H__ - -#ifdef __cplusplus -#include -#else -#include -#endif - -uint32_t counter(const uint32_t clock_cycles); - -#endif /* __COUNTER_H__ */ -/* vim: set foldmarker=@{,@} foldlevel=0 foldmethod=marker : */ diff --git a/toolflow/examples/kernel-examples/counter/kernel.json b/toolflow/examples/kernel-examples/counter/kernel.json deleted file mode 100644 index 52054079..00000000 --- a/toolflow/examples/kernel-examples/counter/kernel.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Description" : "Simple counter, raises interrupt after specified clock cycles.", - "Name" : "counter", - "Id" : 14, - "Version" : "0.9", - "TopFunction" : "counter", - "Files" : ["counter.cpp"], - "CompilerFlags" : [ "-Wall", "-std=c++0x" ], - "TestbenchFiles" : ["counter.cpp"], - "TestbenchCompilerFlags" : [ "-Wall", "-std=c++0x" ], - "Arguments" : [ {"Name" : "clock_cycles"} ] -} diff --git a/toolflow/scala/build.gradle b/toolflow/scala/build.gradle index effbb689..e3c5dac4 100644 --- a/toolflow/scala/build.gradle +++ b/toolflow/scala/build.gradle @@ -71,8 +71,8 @@ application { ospackage { packageName = "tapasco" - version = "2020" - release = "10" + version = "2021" + release = "01" license = "GNU Lesser General Public License v3.0" vendor = "Embedded Systems and Applications Group, TU Darmstadt" url = "https://github.com/esa-tu-darmstadt/tapasco" diff --git a/toolflow/scala/src/main/scala/tapasco/activity/hls/VivadoHighLevelSynthesis.scala b/toolflow/scala/src/main/scala/tapasco/activity/hls/VivadoHighLevelSynthesis.scala index aaf9487b..982d6fa8 100644 --- a/toolflow/scala/src/main/scala/tapasco/activity/hls/VivadoHighLevelSynthesis.scala +++ b/toolflow/scala/src/main/scala/tapasco/activity/hls/VivadoHighLevelSynthesis.scala @@ -23,6 +23,9 @@ package tapasco.activity.hls import java.io.FileWriter import java.nio.file._ +import scala.io.Source +import scala.sys.process._ +import scala.util.Properties.{lineSeparator => NL} import tapasco.Common import tapasco.Logging._ @@ -30,10 +33,6 @@ import tapasco.base._ import tapasco.filemgmt.LogTrackingFileWatcher import tapasco.util._ -import scala.io.Source -import scala.sys.process._ -import scala.util.Properties.{lineSeparator => NL} - private object VivadoHighLevelSynthesis extends HighLevelSynthesizer { import HighLevelSynthesizer._ @@ -70,10 +69,17 @@ private object VivadoHighLevelSynthesis extends HighLevelSynthesizer { } // execute Vivado HLS (max. runtime: 1 day) - val vivado_hls_cmd = Seq("timeout", (cfg.hlsTimeOut getOrElse (24 * 60 * 60)).toString, "vivado_hls", + if(hlsCommand.isEmpty){ + // If the command to use for HLS is still undefined, try to auto-detect it + if(!detectHLSCommand()){ + logger.error("Neither vitis_hls nor vivado_hls were available on the PATH") + OtherError(HighLevelSynthesizerLog(logfile), new RuntimeException()) + } + } + val vivado_hls_cmd = Seq("timeout", (cfg.hlsTimeOut getOrElse (24 * 60 * 60)).toString, hlsCommand.get, "-f", script.toString, "-l", logfile.toString) - val process = Process(vivado_hls_cmd, script.getParent.toFile) + val process = Process(vivado_hls_cmd, script.getParent.toFile) val vivadoRet = InterruptibleProcess(process, waitMillis = Some(( cfg.hlsTimeOut getOrElse (24 * 60 * 60) ) * 1000 + 1000) ) .!(ProcessLogger(line => logger.trace("Vivado HLS: {}", line), @@ -205,4 +211,31 @@ private object VivadoHighLevelSynthesis extends HighLevelSynthesizer { } } fold true) (_ && _) } + + private var hlsCommand : Option[String] = None + + private def detectHLSCommand(): Boolean = { + // Vivado/Vitis 2020.2 has renamed vivado_hls to vitis_hls, but the interfaces are still compatible. + // We try to detect the correct command here by trying to run each command and see which gives us + // a zero return value. + try { + if(Seq("vitis_hls", "-version").! == 0) { + hlsCommand = Some("vitis_hls") + return true + } + } catch { + // If vitis_hls is not available, the test might result in an exception that we catch here. + case _ : Throwable => logger.trace("vitis_hls not available") + } + try{ + if(Seq("vivado_hls", "-version").! == 0){ + hlsCommand = Some("vivado_hls") + return true + } + } catch { + // If vivado_hls is not available, the test might result in an exception that we catch here. + case _ : Throwable => logger.trace("vivado_hls not available") + } + return false + } } diff --git a/toolflow/scala/src/main/scala/tapasco/base/json/package.scala b/toolflow/scala/src/main/scala/tapasco/base/json/package.scala index 2d5cf570..3e49983f 100644 --- a/toolflow/scala/src/main/scala/tapasco/base/json/package.scala +++ b/toolflow/scala/src/main/scala/tapasco/base/json/package.scala @@ -422,8 +422,8 @@ package object json { (JsPath \ "Slurm").write[Boolean] ~ (JsPath \ "Parallel").write[Boolean] ~ (JsPath \ "MaxThreads").writeNullable[Int] ~ - (JsPath \ "HlsTimeOut").writeNullable[Int] ~ (JsPath \ "MaxTasks").writeNullable[Int] ~ + (JsPath \ "HlsTimeOut").writeNullable[Int] ~ (JsPath \ "DryRun").writeNullable[Path].transform((js: JsObject) => js - "DryRun") ~ (JsPath \ "Verbose").writeNullable[String] ~ (JsPath \ "Jobs").write[Seq[Job]] diff --git a/toolflow/vivado/arch/axi4mm/axi4mm.tcl b/toolflow/vivado/arch/axi4mm/axi4mm.tcl index 99652b85..6838ff18 100644 --- a/toolflow/vivado/arch/axi4mm/axi4mm.tcl +++ b/toolflow/vivado/arch/axi4mm/axi4mm.tcl @@ -98,15 +98,66 @@ namespace eval arch { puts "Creating $no_inst instances of target IP core ..." puts " VLNV: $vlnv" for {set j 0} {$j < $no_inst} {incr j} { + # Create PE instance set name [format "target_ip_%02d_%03d" $i $j] - set inst [lindex [tapasco::call_plugins "post-pe-create" [create_bd_cell -type ip -vlnv "$vlnv" $name]] 0] - lappend insts $inst + set inst [create_bd_cell -type ip -vlnv "$vlnv" "internal_$name"] + + # Only create a wrapper around PEs if atleast one plugin is present + if {[llength [tapasco::get_plugins "post-pe-create"]] > 0} { + set bd_inst [current_bd_instance .] + set group [create_wrapper_around_pe $inst $name] + + set inst [lindex [tapasco::call_plugins "post-pe-create" $inst] 0] + # Return to the same block design instance as before + current_bd_instance $bd_inst + + # return the wrapper so that it can be connected + lappend insts $group + } else { + lappend insts $inst + } } } puts "insts = $insts" return $insts } + # Create a wrapper around a PE to embed plugins + proc create_wrapper_around_pe {inst name} { + # create group, move instance into group + set group [create_bd_cell -type hier $name] + move_bd_cells $group $inst + + current_bd_instance $group + set bd_inst [current_bd_instance .] + + # bypass existing AXI4Lite slaves + set lite_ports [list] + set lites [get_bd_intf_pins -of_objects $inst -filter {MODE == Slave && CONFIG.PROTOCOL == AXI4LITE}] + foreach ls $lites { + set op [create_bd_intf_pin -vlnv "xilinx.com:interface:aximm_rtl:1.0" -mode Slave [get_property NAME $ls]] + connect_bd_intf_net $op $ls + lappend lite_ports $ls + } + puts "lite_ports = $lite_ports" + + # create master ports + set maxi_ports [list] + foreach mp [get_bd_intf_pins -of_objects $inst -filter {MODE == Master && CONFIG.PROTOCOL == AXI4}] { + set op [create_bd_intf_pin -vlnv "xilinx.com:interface:aximm_rtl:1.0" -mode Master [get_property NAME $mp]] + connect_bd_intf_net $mp $op + lappend maxi_ports $mp + } + puts "maxi_ports = $maxi_ports" + + # create interrupt port + foreach interrupt [get_bd_pins -of_objects $inst -filter {TYPE == intr}] { + connect_bd_net $interrupt [create_bd_pin -type intr -dir O [get_property NAME $interrupt]] + } + + return $group + } + # Retrieve AXI-MM interfaces of given instance of kernel kind and mode. proc get_aximm_interfaces {kind inst {mode "Master"}} { set name [format "target_ip_%02d_%03d" $kind $inst] @@ -317,7 +368,8 @@ namespace eval arch { # Connect internal clock lines. proc arch_connect_clocks {} { connect_bd_net [tapasco::subsystem::get_port "design" "clk"] \ - [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == clk && DIR == I"] + [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == clk && DIR == I"] \ + [get_bd_pins -of_objects [get_bd_cells -hier -filter {PATH =~ "*target_ip*"}] -filter "TYPE == clk && DIR == I"] } # Connect internal reset lines. @@ -326,8 +378,8 @@ namespace eval arch { [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == rst && NAME =~ *interconnect_aresetn && DIR == I"] connect_bd_net [tapasco::subsystem::get_port "design" "rst" "peripheral" "resetn"] \ [get_bd_pins -of_objects [get_bd_cells -of_objects [current_bd_instance .]] -filter "TYPE == rst && NAME =~ *peripheral_aresetn && DIR == I"] \ - [get_bd_pins -filter { TYPE == rst && DIR == I && CONFIG.POLARITY != ACTIVE_HIGH } -of_objects [get_bd_cells -filter {NAME =~ "target_ip*"}]] - set active_high_resets [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == rst && DIR == I && CONFIG.POLARITY == ACTIVE_HIGH"] + [get_bd_pins -filter { TYPE == rst && DIR == I && CONFIG.POLARITY != ACTIVE_HIGH } -of_objects [get_bd_cells -hier -filter {PATH =~ "*target_ip*"}]] + set active_high_resets [get_bd_pins -of_objects [get_bd_cells -hier] -filter "TYPE == rst && DIR == I && CONFIG.POLARITY == ACTIVE_HIGH"] if {[llength $active_high_resets] > 0} { connect_bd_net [tapasco::subsystem::get_port "design" "rst" "peripheral" "reset"] $active_high_resets } diff --git a/toolflow/vivado/arch/axi4mm/plugins/dmi_over_axi.tcl b/toolflow/vivado/arch/axi4mm/plugins/dmi_over_axi.tcl new file mode 100644 index 00000000..1cf73508 --- /dev/null +++ b/toolflow/vivado/arch/axi4mm/plugins/dmi_over_axi.tcl @@ -0,0 +1,38 @@ +namespace eval dmi_over_axi { + proc connect_dmi {inst {args {}}} { + set inst [get_bd_cells $inst] + set name [get_property NAME $inst] + + set bd_inst [current_bd_instance .] + + # Get the number of the target IP + set kind [scan [regsub {.*target_ip_.*([0-9][0-9][0-9])} $name {\1}] %d] + + set dmi_pin [get_bd_intf_pins -of_objects $inst \ + -filter "VLNV == esa.informatik.tu-darmstadt.de:user:DMI_rtl:1.0"] + + puts "DMI intf found = $dmi_pin for IP $inst" + + set axi_to_dmi_converter [tapasco::ip::create_axi_to_dmi "axi_to_dmi"] + # Get Converter Module interface + set convert_interface [get_bd_intf_pins -of_objects $axi_to_dmi_converter \ + -filter "VLNV == esa.informatik.tu-darmstadt.de:user:DMI_rtl:1.0"] + + # Create AXI slave port + set axi_port [create_bd_intf_pin -vlnv \ + [tapasco::ip::get_vlnv "aximm_intf"] -mode Slave "S_DMI_DEBUG"] + + # Connect AXI to converter module + connect_bd_intf_net $axi_port [get_bd_intf_pins -of_objects $axi_to_dmi_converter \ + -filter "VLNV == [tapasco::ip::get_vlnv "aximm_intf"] && MODE == Slave"] + + # Connect DMI port + connect_bd_intf_net $convert_interface $dmi_pin + + return [list $inst $args] + } +} + +if {[tapasco::is_feature_enabled "DmiDebug"]} { + tapasco::register_plugin "arch::dmi_over_axi::connect_dmi" "post-pe-create" +} diff --git a/toolflow/vivado/arch/axi4mm/plugins/full_axi_slave_wrapper.tcl b/toolflow/vivado/arch/axi4mm/plugins/full_axi_slave_wrapper.tcl index 98fe97ad..6011a970 100644 --- a/toolflow/vivado/arch/axi4mm/plugins/full_axi_slave_wrapper.tcl +++ b/toolflow/vivado/arch/axi4mm/plugins/full_axi_slave_wrapper.tcl @@ -22,65 +22,27 @@ namespace eval full_axi_wrapper { # check interfaces: AXI3/AXI4 slaves will be wrappped set inst [get_bd_cells $inst] set full_slave_ifs [get_bd_intf_pins -of_objects $inst -filter {MODE == Slave && (CONFIG.PROTOCOL == AXI3 || CONFIG.PROTOCOL == AXI4)}] - # if {[llength $full_slave_ifs] > 1} { error "full_axi_wrapper plugin: Found [llength $full_slave_ifs] full slave interfaces, this is not supported at the moment" } if {[llength $full_slave_ifs] > 0} { puts " IP has full slaves, will add protocol converter" puts " found full slave interfaces: $full_slave_ifs" - set name [get_property NAME $inst] - - set bd_inst [current_bd_instance .] - # create group, move instance into group - set_property NAME "internal_$name" $inst - set group [create_bd_cell -type hier $name] - move_bd_cells $group $inst - set ninst [get_bd_cells $group/internal_$name] - current_bd_instance $group + } + set name [get_property NAME $inst] - # rewire full slaves - set si 0 - foreach fs $full_slave_ifs { - # create slave port - set saxi_port [create_bd_intf_pin -vlnv "xilinx.com:interface:aximm_rtl:1.0" -mode Slave "S_AXI_LITE_$si"] - set conv [tapasco::ip::create_proto_conv "conv_$si" "AXI4LITE" [get_property CONFIG.PROTOCOL $fs]] - connect_bd_intf_net $saxi_port [get_bd_intf_pins -of_objects $conv -filter {MODE == Slave}] - connect_bd_intf_net [get_bd_intf_pins -filter {MODE == Master} -of_objects $conv] $fs - incr si - } + set bd_inst [current_bd_instance .] - # bypass existing AXI4Lite slaves - set lite_ports [list] - set lites [get_bd_intf_pins -of_objects $inst -filter {MODE == Slave && CONFIG.PROTOCOL == AXI4LITE}] - foreach ls $lites { - set op [create_bd_intf_pin -vlnv "xilinx.com:interface:aximm_rtl:1.0" -mode Slave [get_property NAME $ls]] - connect_bd_intf_net $op $ls - lappend lite_ports $ls - } - puts "lite_ports = $lite_ports" - - # create master ports - set maxi_ports [list] - foreach mp [get_bd_intf_pins -of_objects $ninst -filter {MODE == Master}] { - set op [create_bd_intf_pin -vlnv "xilinx.com:interface:aximm_rtl:1.0" -mode Master [get_property NAME $mp]] - connect_bd_intf_net $mp $op - lappend maxi_ports $mp - } - puts "maxi_ports = $maxi_ports" - - # create clock and reset ports - set clks [get_bd_pins -filter {DIR == I && TYPE == clk} -of_objects [get_bd_cells $group/*]] - set rsts [get_bd_pins -filter {DIR == I && TYPE == rst && CONFIG.POLARITY == ACTIVE_LOW} -of_objects [get_bd_cells $group/*]] - set clk [create_bd_pin -type clk -dir I "aclk"] - set rst [create_bd_pin -type rst -dir I "aresetn"] - - connect_bd_net $clk $clks - connect_bd_net $rst $rsts - - # create interrupt port - connect_bd_net [get_bd_pin -of_objects $ninst -filter {NAME == interrupt}] [create_bd_pin -type intr -dir O "interrupt"] - - current_bd_instance $bd_inst - return [list $group $args] + # rewire full slaves + set si 0 + foreach fs $full_slave_ifs { + # create slave port + set saxi_port [create_bd_intf_pin -vlnv "xilinx.com:interface:aximm_rtl:1.0" -mode Slave "S_AXI_LITE_$si"] + set conv [tapasco::ip::create_proto_conv "conv_$si" "AXI4LITE" [get_property CONFIG.PROTOCOL $fs]] + connect_bd_intf_net $saxi_port [get_bd_intf_pins -of_objects $conv -filter {MODE == Slave}] + connect_bd_intf_net [get_bd_intf_pins -filter {MODE == Master} -of_objects $conv] $fs + + incr si } + + return [list $inst $args] } diff --git a/toolflow/vivado/common/common.tcl b/toolflow/vivado/common/common.tcl index da64d075..2abe383f 100644 --- a/toolflow/vivado/common/common.tcl +++ b/toolflow/vivado/common/common.tcl @@ -106,7 +106,7 @@ namespace eval tapasco { # Returns the Tapasco version. proc get_tapasco_version {} { - return "2020.10" + return "2021.1" } # Returns the interface pin groups for all AXI MM interfaces on cell. diff --git a/toolflow/vivado/common/common_2019.1.tcl b/toolflow/vivado/common/common_2019.1.tcl index 4c8d4aba..ea90f0d8 100644 --- a/toolflow/vivado/common/common_2019.1.tcl +++ b/toolflow/vivado/common/common_2019.1.tcl @@ -24,4 +24,6 @@ dict set stdcomps axi_pcie3_0_usp vlnv "xilinx.com:ip:xdma:4.1" dict set stdcomps clk_wiz vlnv "xilinx.com:ip:clk_wiz:6.0" dict set stdcomps mig_core vlnv "xilinx.com:ip:mig_7series:4.2" dict set stdcomps ultra_ps vlnv "xilinx.com:ip:zynq_ultra_ps_e:3.3" -dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.0" +dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.0" +dict set stdcomps 100g_ethernet vlnv "xilinx.com:ip:cmac_usplus:2.6" +dict set stdcomps aurora vlnv "xilinx.com:ip:aurora_64b66b:12.0" diff --git a/toolflow/vivado/common/common_2019.2.tcl b/toolflow/vivado/common/common_2019.2.tcl index 3049c6da..963fdcb9 100644 --- a/toolflow/vivado/common/common_2019.2.tcl +++ b/toolflow/vivado/common/common_2019.2.tcl @@ -24,6 +24,8 @@ dict set stdcomps axi_pcie3_0_usp vlnv "xilinx.com:ip:xdma:4.1" dict set stdcomps clk_wiz vlnv "xilinx.com:ip:clk_wiz:6.0" dict set stdcomps mig_core vlnv "xilinx.com:ip:mig_7series:4.2" dict set stdcomps ultra_ps vlnv "xilinx.com:ip:zynq_ultra_ps_e:3.3" -dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.1" +dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.1" +dict set stdcomps 100g_ethernet vlnv "xilinx.com:ip:cmac_usplus:3.0" +dict set stdcomps aurora vlnv "xilinx.com:ip:aurora_64b66b:12.0" dict set stdcomps system_cache vlnv "xilinx.com:ip:system_cache:5.0" dict set stdcomps axi_cache vlnv "xilinx.com:ip:system_cache:5.0" diff --git a/toolflow/vivado/common/common_2020.1.tcl b/toolflow/vivado/common/common_2020.1.tcl index 28f67bb1..6023faab 100644 --- a/toolflow/vivado/common/common_2020.1.tcl +++ b/toolflow/vivado/common/common_2020.1.tcl @@ -24,5 +24,8 @@ dict set stdcomps axi_pcie3_0_usp vlnv "xilinx.com:ip:xdma:4.1" dict set stdcomps clk_wiz vlnv "xilinx.com:ip:clk_wiz:6.0" dict set stdcomps mig_core vlnv "xilinx.com:ip:mig_7series:4.2" dict set stdcomps ultra_ps vlnv "xilinx.com:ip:zynq_ultra_ps_e:3.3" +dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.2" +dict set stdcomps 100g_ethernet vlnv "xilinx.com:ip:cmac_usplus:3.1" +dict set stdcomps aurora vlnv "xilinx.com:ip:aurora_64b66b:12.0" dict set stdcomps system_cache vlnv "xilinx.com:ip:system_cache:5.0" dict set stdcomps axi_cache vlnv "xilinx.com:ip:system_cache:5.0" diff --git a/toolflow/vivado/common/common_2020.2.tcl b/toolflow/vivado/common/common_2020.2.tcl new file mode 100644 index 00000000..535b104d --- /dev/null +++ b/toolflow/vivado/common/common_2020.2.tcl @@ -0,0 +1,30 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +# create a dictionary of compatible VLNVs +source $::env(TAPASCO_HOME_TCL)/common/common_ip.tcl +dict set stdcomps system_ila vlnv "xilinx.com:ip:system_ila:1.1" +dict set stdcomps axi_pcie3_0_usp vlnv "xilinx.com:ip:xdma:4.1" +dict set stdcomps clk_wiz vlnv "xilinx.com:ip:clk_wiz:6.0" +dict set stdcomps mig_core vlnv "xilinx.com:ip:mig_7series:4.2" +dict set stdcomps ultra_ps vlnv "xilinx.com:ip:zynq_ultra_ps_e:3.3" +dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.3" +dict set stdcomps aurora vlnv "xilinx.com:ip:aurora_64b66b:12.0" +dict set stdcomps system_cache vlnv "xilinx.com:ip:system_cache:5.0" +dict set stdcomps axi_cache vlnv "xilinx.com:ip:system_cache:5.0" diff --git a/toolflow/vivado/common/common_2021.1.tcl b/toolflow/vivado/common/common_2021.1.tcl new file mode 100644 index 00000000..535b104d --- /dev/null +++ b/toolflow/vivado/common/common_2021.1.tcl @@ -0,0 +1,30 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +# create a dictionary of compatible VLNVs +source $::env(TAPASCO_HOME_TCL)/common/common_ip.tcl +dict set stdcomps system_ila vlnv "xilinx.com:ip:system_ila:1.1" +dict set stdcomps axi_pcie3_0_usp vlnv "xilinx.com:ip:xdma:4.1" +dict set stdcomps clk_wiz vlnv "xilinx.com:ip:clk_wiz:6.0" +dict set stdcomps mig_core vlnv "xilinx.com:ip:mig_7series:4.2" +dict set stdcomps ultra_ps vlnv "xilinx.com:ip:zynq_ultra_ps_e:3.3" +dict set stdcomps xxv_ethernet vlnv "xilinx.com:ip:xxv_ethernet:3.3" +dict set stdcomps aurora vlnv "xilinx.com:ip:aurora_64b66b:12.0" +dict set stdcomps system_cache vlnv "xilinx.com:ip:system_cache:5.0" +dict set stdcomps axi_cache vlnv "xilinx.com:ip:system_cache:5.0" diff --git a/toolflow/vivado/common/common_ip.tcl b/toolflow/vivado/common/common_ip.tcl index 7a934b1c..57c311d6 100644 --- a/toolflow/vivado/common/common_ip.tcl +++ b/toolflow/vivado/common/common_ip.tcl @@ -65,3 +65,5 @@ dict set stdcomps bram_ctrl vlnv "xilinx.com:ip:blk_mem_gen" dict set stdcomps axi_gpio vlnv "xilinx.com:ip:axi_gpio:2.0" dict set stdcomps axioffset_hbm vlnv "esa.informatik.tu-darmstadt.de:user:AXIOffsetHBM:1.0" dict set stdcomps sume_clock_prog vlnv "esa.informatik.tu-darmstadt.de:user:SumeClockProgrammer:1.0" +dict set stdcomps dmi vlnv "esa.informatik.tu-darmstadt.de:user:DMI_rtl:1.0" +dict set stdcomps axi_to_dmi vlnv "esa.informatik.tu-darmstadt.de:user:AXI_to_Dmi:1.0" diff --git a/toolflow/vivado/common/hls.tcl.template b/toolflow/vivado/common/hls.tcl.template index 32b8440b..a273ed44 100644 --- a/toolflow/vivado/common/hls.tcl.template +++ b/toolflow/vivado/common/hls.tcl.template @@ -85,6 +85,7 @@ if {$do_cosim > 0} { # export to IP-XACT (skip evaluation, will be done manually) export_design -format ipxact -display_name {@@NAME@@} -vendor {@@VENDOR@@} -version {@@VERSION@@} # remove .zip +file delete [glob -nocomplain "@@PROJECT@@/@@SOLUTION@@/impl/*.zip"] file delete [glob "@@PROJECT@@/@@SOLUTION@@/impl/ip/*.zip"] # replace logo file copy -force "$::env(TAPASCO_HOME_TCL)/common/logo.png" "@@PROJECT@@/@@SOLUTION@@/impl/ip/misc/logo.png" diff --git a/toolflow/vivado/common/ip.tcl b/toolflow/vivado/common/ip.tcl index ebbc6a41..5a8858c1 100644 --- a/toolflow/vivado/common/ip.tcl +++ b/toolflow/vivado/common/ip.tcl @@ -536,7 +536,7 @@ namespace eval ::tapasco::ip { puts " processing $intf: [dict get $addr $intf kind] ..." switch [dict get $addr $intf "kind"] { "register" { - set kind [format "%d" [regsub {.*target_ip_([0-9][0-9]).*} $intf {\1}]] + set kind [scan [regsub {.*target_ip_([0-9][0-9]).*} $intf {\1}] "%d"] set kid [dict get [::tapasco::get_composition] $kind id] set vlnv [dict get [::tapasco::get_composition] $kind vlnv] diff --git a/toolflow/vivado/common/ip/AXI_to_Dmi/component.xml b/toolflow/vivado/common/ip/AXI_to_Dmi/component.xml new file mode 100644 index 00000000..581e192e --- /dev/null +++ b/toolflow/vivado/common/ip/AXI_to_Dmi/component.xml @@ -0,0 +1,1556 @@ + + + esa.informatik.tu-darmstadt.de + user + AXI_to_Dmi + 1.0 + + + s_AXI_Dmi + + + + + + + + + AWID + + + s_AXI_Dmi_awid + + + + + AWADDR + + + s_AXI_Dmi_awaddr + + + + + AWLEN + + + s_AXI_Dmi_awlen + + + + + AWSIZE + + + s_AXI_Dmi_awsize + + + + + AWBURST + + + s_AXI_Dmi_awburst + + + + + AWLOCK + + + s_AXI_Dmi_awlock + + + + + AWCACHE + + + s_AXI_Dmi_awcache + + + + + AWPROT + + + s_AXI_Dmi_awprot + + + + + AWREGION + + + s_AXI_Dmi_awregion + + + + + AWQOS + + + s_AXI_Dmi_awqos + + + + + AWVALID + + + s_AXI_Dmi_awvalid + + + + + AWREADY + + + s_AXI_Dmi_awready + + + + + WDATA + + + s_AXI_Dmi_wdata + + + + + WSTRB + + + s_AXI_Dmi_wstrb + + + + + WLAST + + + s_AXI_Dmi_wlast + + + + + WVALID + + + s_AXI_Dmi_wvalid + + + + + WREADY + + + s_AXI_Dmi_wready + + + + + BID + + + s_AXI_Dmi_bid + + + + + BRESP + + + s_AXI_Dmi_bresp + + + + + BVALID + + + s_AXI_Dmi_bvalid + + + + + BREADY + + + s_AXI_Dmi_bready + + + + + ARID + + + s_AXI_Dmi_arid + + + + + ARADDR + + + s_AXI_Dmi_araddr + + + + + ARLEN + + + s_AXI_Dmi_arlen + + + + + ARSIZE + + + s_AXI_Dmi_arsize + + + + + ARBURST + + + s_AXI_Dmi_arburst + + + + + ARLOCK + + + s_AXI_Dmi_arlock + + + + + ARCACHE + + + s_AXI_Dmi_arcache + + + + + ARPROT + + + s_AXI_Dmi_arprot + + + + + ARREGION + + + s_AXI_Dmi_arregion + + + + + ARQOS + + + s_AXI_Dmi_arqos + + + + + ARVALID + + + s_AXI_Dmi_arvalid + + + + + ARREADY + + + s_AXI_Dmi_arready + + + + + RID + + + s_AXI_Dmi_rid + + + + + RDATA + + + s_AXI_Dmi_rdata + + + + + RRESP + + + s_AXI_Dmi_rresp + + + + + RLAST + + + s_AXI_Dmi_rlast + + + + + RVALID + + + s_AXI_Dmi_rvalid + + + + + RREADY + + + s_AXI_Dmi_rready + + + + + + ARESETN + + + + + + + RST + + + ARESETN + + + + + + POLARITY + ACTIVE_LOW + + + + + ACLK + + + + + + + CLK + + + ACLK + + + + + + ASSOCIATED_BUSIF + s_AXI_Dmi + + + ASSOCIATED_RESET + ARESETN + + + + + user_DMI + + + + + + + REQ_VALID + + + REQ_VALID + + + + + REQ_ADDRESS + + + REQ_ADDRESS + + + + + REQ_W_ADDRESS + + + REQ_W_ADDRESS + + + + + REQ_DATA + + + REQ_DATA + + + + + REQ_OP + + + REQ_OP + + + + + REQ_READ + + + REQ_READ + + + + + REQ_WRITE + + + REQ_WRITE + + + + + REQ_ACCESS + + + REQ_ACCESS + + + + + RSP_VALID + + + RSP_VALID + + + + + RSP_READY + + + RSP_READY + + + + + RSP_DATA + + + RSP_DATA + + + + + RSP_OP + + + RSP_OP + + + + + + + + s_AXI_Dmi + + DmiDebugMem + 0 + 4096 + 16 + memory + + + + + + + xilinx_anylanguagesynthesis + Synthesis + :vivado.xilinx.com:synthesis + Verilog + mkAXI_to_Dmi + + xilinx_anylanguagesynthesis_view_fileset + + + + viewChecksum + 14531295 + + + + + xilinx_anylanguagebehavioralsimulation + Simulation + :vivado.xilinx.com:simulation + Verilog + mkAXI_to_Dmi + + xilinx_anylanguagebehavioralsimulation_view_fileset + + + + viewChecksum + 14531295 + + + + + xilinx_xpgui + UI Layout + :vivado.xilinx.com:xgui.ui + + xilinx_xpgui_view_fileset + + + + viewChecksum + f92e9879 + + + + + + + ACLK + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + ARESETN + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_arvalid + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_arready + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_arid + + in + + 11 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_araddr + + in + + 31 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_arlen + + in + + 7 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_arsize + + in + + 2 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_arburst + + in + + 1 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 1 + + + + + s_AXI_Dmi_arlock + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_arcache + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 3 + + + + + s_AXI_Dmi_arprot + + in + + 2 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_arqos + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_arregion + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_rready + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_rvalid + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_rid + + out + + 11 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_rdata + + out + + 31 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_rresp + + out + + 1 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_rlast + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_awready + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_awvalid + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awid + + in + + 11 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awaddr + + in + + 31 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awlen + + in + + 7 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awsize + + in + + 2 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_awburst + + in + + 1 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 1 + + + + + s_AXI_Dmi_awlock + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awcache + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 3 + + + + + s_AXI_Dmi_awprot + + in + + 2 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awqos + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_awregion + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_wready + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_wvalid + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_wdata + + in + + 31 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_wstrb + + in + + 3 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 1 + + + + + s_AXI_Dmi_wlast + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_bready + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + s_AXI_Dmi_bvalid + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_bresp + + out + + 1 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + s_AXI_Dmi_bid + + out + + 11 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_ADDRESS + + out + + 6 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_W_ADDRESS + + out + + 6 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_DATA + + out + + 31 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_VALID + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_OP + + out + + 1 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_ACCESS + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_READ + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + REQ_WRITE + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + RSP_DATA + + in + + 31 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + RSP_OP + + in + + 1 + 0 + + + + std_logic_vector + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + RSP_VALID + + in + + + std_logic + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 1 + + + + + RSP_READY + + out + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + slave_select + + out + + 4 + 0 + + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + + + + + + choice_list_9d8b0d81 + ACTIVE_HIGH + ACTIVE_LOW + + + + + xilinx_anylanguagesynthesis_view_fileset + + src/FIFO2.v + verilogSource + + + src/mkAXI_to_Dmi.v + verilogSource + CHECKSUM_20fd8fe6 + + + + xilinx_anylanguagebehavioralsimulation_view_fileset + + src/FIFO2.v + verilogSource + + + src/mkAXI_to_Dmi.v + verilogSource + + + + xilinx_xpgui_view_fileset + + xgui/AXI_to_Dmi_v1_0.tcl + tclSource + CHECKSUM_f92e9879 + XGUI_VERSION_2 + + + + AXI_to_Dmi + + + Component_Name + mkAXI_to_Dmi_v1_0 + + + + + + zynq + virtex7 + kintex7 + artix7 + zynquplus + qvirtex7 + kintex7l + qkintex7 + qkintex7l + artix7l + aartix7 + qartix7 + qzynq + azynq + spartan7 + virtexu + virtexuplus + virtexuplusHBM + kintexuplus + kintexu + + + /UserIP + + AXI_to_Dmi + package_project + 1 + 2020-10-01T08:42:01Z + + + + + + 2019.1 + + + + + + + + diff --git a/toolflow/vivado/common/ip/AXI_to_Dmi/src/FIFO2.v b/toolflow/vivado/common/ip/AXI_to_Dmi/src/FIFO2.v new file mode 100644 index 00000000..adacec5a --- /dev/null +++ b/toolflow/vivado/common/ip/AXI_to_Dmi/src/FIFO2.v @@ -0,0 +1,153 @@ + +`ifdef BSV_ASSIGNMENT_DELAY +`else + `define BSV_ASSIGNMENT_DELAY +`endif + +`ifdef BSV_POSITIVE_RESET + `define BSV_RESET_VALUE 1'b1 + `define BSV_RESET_EDGE posedge +`else + `define BSV_RESET_VALUE 1'b0 + `define BSV_RESET_EDGE negedge +`endif + +`ifdef BSV_ASYNC_RESET + `define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST +`else + `define BSV_ARESET_EDGE_META +`endif + +`ifdef BSV_RESET_FIFO_HEAD + `define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META +`else + `define BSV_ARESET_EDGE_HEAD +`endif + +// Depth 2 FIFO +module FIFO2(CLK, + RST, + D_IN, + ENQ, + FULL_N, + D_OUT, + DEQ, + EMPTY_N, + CLR); + + parameter width = 1; + parameter guarded = 1; + + input CLK ; + input RST ; + input [width - 1 : 0] D_IN; + input ENQ; + input DEQ; + input CLR ; + + output FULL_N; + output EMPTY_N; + output [width - 1 : 0] D_OUT; + + reg full_reg; + reg empty_reg; + reg [width - 1 : 0] data0_reg; + reg [width - 1 : 0] data1_reg; + + assign FULL_N = full_reg ; + assign EMPTY_N = empty_reg ; + assign D_OUT = data0_reg ; + + + // Optimize the loading logic since state encoding is not power of 2! + wire d0di = (ENQ && ! empty_reg ) || ( ENQ && DEQ && full_reg ) ; + wire d0d1 = DEQ && ! full_reg ; + wire d0h = ((! DEQ) && (! ENQ )) || (!DEQ && empty_reg ) || ( ! ENQ &&full_reg) ; + wire d1di = ENQ & empty_reg ; + +`ifdef BSV_NO_INITIAL_BLOCKS +`else // not BSV_NO_INITIAL_BLOCKS + // synopsys translate_off + initial + begin + data0_reg = {((width + 1)/2) {2'b10}} ; + data1_reg = {((width + 1)/2) {2'b10}} ; + empty_reg = 1'b0; + full_reg = 1'b1; + end // initial begin + // synopsys translate_on +`endif // BSV_NO_INITIAL_BLOCKS + + always@(posedge CLK `BSV_ARESET_EDGE_META) + begin + if (RST == `BSV_RESET_VALUE) + begin + empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; + full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; + end // if (RST == `BSV_RESET_VALUE) + else + begin + if (CLR) + begin + empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; + full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; + end // if (CLR) + else if ( ENQ && ! DEQ ) // just enq + begin + empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; + full_reg <= `BSV_ASSIGNMENT_DELAY ! empty_reg ; + end + else if ( DEQ && ! ENQ ) + begin + full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; + empty_reg <= `BSV_ASSIGNMENT_DELAY ! full_reg; + end // if ( DEQ && ! ENQ ) + end // else: !if(RST == `BSV_RESET_VALUE) + + end // always@ (posedge CLK or `BSV_RESET_EDGE RST) + + + always@(posedge CLK `BSV_ARESET_EDGE_HEAD) + begin +`ifdef BSV_RESET_FIFO_HEAD + if (RST == `BSV_RESET_VALUE) + begin + data0_reg <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ; + data1_reg <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ; + end + else +`endif + begin + data0_reg <= `BSV_ASSIGNMENT_DELAY + {width{d0di}} & D_IN | {width{d0d1}} & data1_reg | {width{d0h}} & data0_reg ; + data1_reg <= `BSV_ASSIGNMENT_DELAY + d1di ? D_IN : data1_reg ; + end // else: !if(RST == `BSV_RESET_VALUE) + end // always@ (posedge CLK or `BSV_RESET_EDGE RST) + + + + // synopsys translate_off + always@(posedge CLK) + begin: error_checks + reg deqerror, enqerror ; + + deqerror = 0; + enqerror = 0; + if (RST == ! `BSV_RESET_VALUE) + begin + if ( ! empty_reg && DEQ ) + begin + deqerror = 1; + $display( "Warning: FIFO2: %m -- Dequeuing from empty fifo" ) ; + end + if ( ! full_reg && ENQ && (!DEQ || guarded) ) + begin + enqerror = 1; + $display( "Warning: FIFO2: %m -- Enqueuing to a full fifo" ) ; + end + end + end // always@ (posedge CLK) + // synopsys translate_on + +endmodule diff --git a/toolflow/vivado/common/ip/AXI_to_Dmi/src/mkAXI_to_Dmi.v b/toolflow/vivado/common/ip/AXI_to_Dmi/src/mkAXI_to_Dmi.v new file mode 100644 index 00000000..c6304334 --- /dev/null +++ b/toolflow/vivado/common/ip/AXI_to_Dmi/src/mkAXI_to_Dmi.v @@ -0,0 +1,1222 @@ +// +// Generated by Bluespec Compiler (build e76ca21) +// +// On Thu Oct 1 10:41:28 CEST 2020 +// +// +// Ports: +// Name I/O size props +// s_AXI_Dmi_arready O 1 +// s_AXI_Dmi_rvalid O 1 +// s_AXI_Dmi_rid O 12 +// s_AXI_Dmi_rdata O 32 +// s_AXI_Dmi_rresp O 2 +// s_AXI_Dmi_rlast O 1 +// s_AXI_Dmi_awready O 1 +// s_AXI_Dmi_wready O 1 +// s_AXI_Dmi_bvalid O 1 +// s_AXI_Dmi_bresp O 2 +// s_AXI_Dmi_bid O 12 +// REQ_ADDRESS O 7 reg +// REQ_W_ADDRESS O 7 reg +// REQ_DATA O 32 reg +// REQ_VALID O 1 const +// REQ_OP O 2 reg +// REQ_ACCESS O 1 reg +// REQ_READ O 1 reg +// REQ_WRITE O 1 reg +// RSP_READY O 1 const +// slave_select O 5 const +// ACLK I 1 clock +// ARESETN I 1 reset +// s_AXI_Dmi_arvalid I 1 +// s_AXI_Dmi_arid I 12 +// s_AXI_Dmi_araddr I 32 +// s_AXI_Dmi_arlen I 8 +// s_AXI_Dmi_arsize I 3 +// s_AXI_Dmi_arburst I 2 +// s_AXI_Dmi_arlock I 1 +// s_AXI_Dmi_arcache I 4 +// s_AXI_Dmi_arprot I 3 +// s_AXI_Dmi_arqos I 4 +// s_AXI_Dmi_arregion I 4 +// s_AXI_Dmi_rready I 1 +// s_AXI_Dmi_awvalid I 1 +// s_AXI_Dmi_awid I 12 +// s_AXI_Dmi_awaddr I 32 +// s_AXI_Dmi_awlen I 8 +// s_AXI_Dmi_awsize I 3 +// s_AXI_Dmi_awburst I 2 +// s_AXI_Dmi_awlock I 1 +// s_AXI_Dmi_awcache I 4 +// s_AXI_Dmi_awprot I 3 +// s_AXI_Dmi_awqos I 4 +// s_AXI_Dmi_awregion I 4 +// s_AXI_Dmi_wvalid I 1 +// s_AXI_Dmi_wdata I 32 +// s_AXI_Dmi_wstrb I 4 +// s_AXI_Dmi_wlast I 1 +// s_AXI_Dmi_bready I 1 +// RSP_DATA I 32 reg +// RSP_OP I 2 reg +// RSP_VALID I 1 +// +// No combinational paths from inputs to outputs +// +// + +`ifdef BSV_ASSIGNMENT_DELAY +`else + `define BSV_ASSIGNMENT_DELAY +`endif + +`ifdef BSV_POSITIVE_RESET + `define BSV_RESET_VALUE 1'b1 + `define BSV_RESET_EDGE posedge +`else + `define BSV_RESET_VALUE 1'b0 + `define BSV_RESET_EDGE negedge +`endif + +module mkAXI_to_Dmi(ACLK, + ARESETN, + + s_AXI_Dmi_arvalid, + + s_AXI_Dmi_arready, + + s_AXI_Dmi_arid, + s_AXI_Dmi_araddr, + s_AXI_Dmi_arlen, + s_AXI_Dmi_arsize, + s_AXI_Dmi_arburst, + s_AXI_Dmi_arlock, + s_AXI_Dmi_arcache, + s_AXI_Dmi_arprot, + s_AXI_Dmi_arqos, + s_AXI_Dmi_arregion, + + s_AXI_Dmi_rready, + + s_AXI_Dmi_rvalid, + + s_AXI_Dmi_rid, + + s_AXI_Dmi_rdata, + + s_AXI_Dmi_rresp, + + s_AXI_Dmi_rlast, + + s_AXI_Dmi_awready, + + s_AXI_Dmi_awvalid, + + s_AXI_Dmi_awid, + s_AXI_Dmi_awaddr, + s_AXI_Dmi_awlen, + s_AXI_Dmi_awsize, + s_AXI_Dmi_awburst, + s_AXI_Dmi_awlock, + s_AXI_Dmi_awcache, + s_AXI_Dmi_awprot, + s_AXI_Dmi_awqos, + s_AXI_Dmi_awregion, + + s_AXI_Dmi_wready, + + s_AXI_Dmi_wvalid, + + s_AXI_Dmi_wdata, + s_AXI_Dmi_wstrb, + s_AXI_Dmi_wlast, + + s_AXI_Dmi_bready, + + s_AXI_Dmi_bvalid, + + s_AXI_Dmi_bresp, + + s_AXI_Dmi_bid, + + REQ_ADDRESS, + + REQ_W_ADDRESS, + + REQ_DATA, + REQ_VALID, + + REQ_OP, + + REQ_ACCESS, + + REQ_READ, + + REQ_WRITE, + + RSP_DATA, + RSP_OP, + RSP_VALID, + RSP_READY, + + slave_select); + input ACLK; + input ARESETN; + + // action method s_AXI_Dmi_s_read_fab_parvalid + input s_AXI_Dmi_arvalid; + + // value method s_AXI_Dmi_s_read_fab_arready + output s_AXI_Dmi_arready; + + // action method s_AXI_Dmi_s_read_fab_parchannel + input [11 : 0] s_AXI_Dmi_arid; + input [31 : 0] s_AXI_Dmi_araddr; + input [7 : 0] s_AXI_Dmi_arlen; + input [2 : 0] s_AXI_Dmi_arsize; + input [1 : 0] s_AXI_Dmi_arburst; + input s_AXI_Dmi_arlock; + input [3 : 0] s_AXI_Dmi_arcache; + input [2 : 0] s_AXI_Dmi_arprot; + input [3 : 0] s_AXI_Dmi_arqos; + input [3 : 0] s_AXI_Dmi_arregion; + + // action method s_AXI_Dmi_s_read_fab_prready + input s_AXI_Dmi_rready; + + // value method s_AXI_Dmi_s_read_fab_rvalid + output s_AXI_Dmi_rvalid; + + // value method s_AXI_Dmi_s_read_fab_rid + output [11 : 0] s_AXI_Dmi_rid; + + // value method s_AXI_Dmi_s_read_fab_rdata + output [31 : 0] s_AXI_Dmi_rdata; + + // value method s_AXI_Dmi_s_read_fab_rresp + output [1 : 0] s_AXI_Dmi_rresp; + + // value method s_AXI_Dmi_s_read_fab_rlast + output s_AXI_Dmi_rlast; + + // value method s_AXI_Dmi_s_read_fab_ruser + + // value method s_AXI_Dmi_s_write_fab_awready + output s_AXI_Dmi_awready; + + // action method s_AXI_Dmi_s_write_fab_pawvalid + input s_AXI_Dmi_awvalid; + + // action method s_AXI_Dmi_s_write_fab_pawchannel + input [11 : 0] s_AXI_Dmi_awid; + input [31 : 0] s_AXI_Dmi_awaddr; + input [7 : 0] s_AXI_Dmi_awlen; + input [2 : 0] s_AXI_Dmi_awsize; + input [1 : 0] s_AXI_Dmi_awburst; + input s_AXI_Dmi_awlock; + input [3 : 0] s_AXI_Dmi_awcache; + input [2 : 0] s_AXI_Dmi_awprot; + input [3 : 0] s_AXI_Dmi_awqos; + input [3 : 0] s_AXI_Dmi_awregion; + + // value method s_AXI_Dmi_s_write_fab_wready + output s_AXI_Dmi_wready; + + // action method s_AXI_Dmi_s_write_fab_pwvalid + input s_AXI_Dmi_wvalid; + + // action method s_AXI_Dmi_s_write_fab_pwchannel + input [31 : 0] s_AXI_Dmi_wdata; + input [3 : 0] s_AXI_Dmi_wstrb; + input s_AXI_Dmi_wlast; + + // action method s_AXI_Dmi_s_write_fab_pbready + input s_AXI_Dmi_bready; + + // value method s_AXI_Dmi_s_write_fab_bvalid + output s_AXI_Dmi_bvalid; + + // value method s_AXI_Dmi_s_write_fab_bresp + output [1 : 0] s_AXI_Dmi_bresp; + + // value method s_AXI_Dmi_s_write_fab_bid + output [11 : 0] s_AXI_Dmi_bid; + + // value method s_AXI_Dmi_s_write_fab_buser + + // value method dmi_master_req_address + output [6 : 0] REQ_ADDRESS; + + // value method dmi_master_req_w_address + output [6 : 0] REQ_W_ADDRESS; + + // value method dmi_master_req_data + output [31 : 0] REQ_DATA; + output REQ_VALID; + + // value method dmi_master_req_op + output [1 : 0] REQ_OP; + + // value method dmi_master_req_access + output REQ_ACCESS; + + // value method dmi_master_req_read + output REQ_READ; + + // value method dmi_master_req_write + output REQ_WRITE; + + // action method dmi_master_rsp_action + input [31 : 0] RSP_DATA; + input [1 : 0] RSP_OP; + input RSP_VALID; + output RSP_READY; + + // value method slave_select + output [4 : 0] slave_select; + + // signals for module outputs + wire [31 : 0] REQ_DATA, s_AXI_Dmi_rdata; + wire [11 : 0] s_AXI_Dmi_bid, s_AXI_Dmi_rid; + wire [6 : 0] REQ_ADDRESS, REQ_W_ADDRESS; + wire [4 : 0] slave_select; + wire [1 : 0] REQ_OP, s_AXI_Dmi_bresp, s_AXI_Dmi_rresp; + wire REQ_ACCESS, + REQ_READ, + REQ_VALID, + REQ_WRITE, + RSP_READY, + s_AXI_Dmi_arready, + s_AXI_Dmi_awready, + s_AXI_Dmi_bvalid, + s_AXI_Dmi_rlast, + s_AXI_Dmi_rvalid, + s_AXI_Dmi_wready; + + // inlined wires + wire [73 : 0] axi_to_dmi_internal_s_read_in_rv$port1__read, + axi_to_dmi_internal_s_read_in_rv$port1__write_1, + axi_to_dmi_internal_s_read_in_rv$port2__read, + axi_to_dmi_internal_s_write_in_addr_rv$port1__read, + axi_to_dmi_internal_s_write_in_addr_rv$port1__write_1, + axi_to_dmi_internal_s_write_in_addr_rv$port2__read; + wire [72 : 0] axi_to_dmi_internal_s_read_arinpkg$wget, + axi_to_dmi_internal_s_write_arinpkg_addr$wget; + wire [47 : 0] axi_to_dmi_internal_s_read_out_rv$port1__read, + axi_to_dmi_internal_s_read_out_rv$port1__write_1, + axi_to_dmi_internal_s_read_out_rv$port2__read; + wire [37 : 0] axi_to_dmi_internal_s_write_in_data_rv$port1__read, + axi_to_dmi_internal_s_write_in_data_rv$port1__write_1, + axi_to_dmi_internal_s_write_in_data_rv$port2__read; + wire [36 : 0] axi_to_dmi_internal_s_write_arinpkg_data$wget; + wire [14 : 0] axi_to_dmi_internal_s_write_out_rv$port1__read, + axi_to_dmi_internal_s_write_out_rv$port1__write_1, + axi_to_dmi_internal_s_write_out_rv$port2__read; + wire axi_to_dmi_internal_s_read_in_rv$EN_port1__write, + axi_to_dmi_internal_s_read_out_rv$EN_port0__write, + axi_to_dmi_internal_s_read_out_rv$EN_port1__write, + axi_to_dmi_internal_s_write_in_addr_rv$EN_port1__write, + axi_to_dmi_internal_s_write_in_data_rv$EN_port1__write, + axi_to_dmi_internal_s_write_out_rv$EN_port0__write, + axi_to_dmi_internal_s_write_out_rv$EN_port1__write; + + // register axi_to_dmi_access_type + reg axi_to_dmi_access_type; + wire axi_to_dmi_access_type$D_IN, axi_to_dmi_access_type$EN; + + // register axi_to_dmi_address + reg [31 : 0] axi_to_dmi_address; + wire [31 : 0] axi_to_dmi_address$D_IN; + wire axi_to_dmi_address$EN; + + // register axi_to_dmi_address_pcie + reg [31 : 0] axi_to_dmi_address_pcie; + wire [31 : 0] axi_to_dmi_address_pcie$D_IN; + wire axi_to_dmi_address_pcie$EN; + + // register axi_to_dmi_data + reg [31 : 0] axi_to_dmi_data; + wire [31 : 0] axi_to_dmi_data$D_IN; + wire axi_to_dmi_data$EN; + + // register axi_to_dmi_data_pcie + reg [31 : 0] axi_to_dmi_data_pcie; + wire [31 : 0] axi_to_dmi_data_pcie$D_IN; + wire axi_to_dmi_data_pcie$EN; + + // register axi_to_dmi_dmi_handler_dmi_busy + reg axi_to_dmi_dmi_handler_dmi_busy; + wire axi_to_dmi_dmi_handler_dmi_busy$D_IN, + axi_to_dmi_dmi_handler_dmi_busy$EN; + + // register axi_to_dmi_dmi_handler_internal_req_access + reg axi_to_dmi_dmi_handler_internal_req_access; + wire axi_to_dmi_dmi_handler_internal_req_access$D_IN, + axi_to_dmi_dmi_handler_internal_req_access$EN; + + // register axi_to_dmi_dmi_handler_internal_req_address + reg [6 : 0] axi_to_dmi_dmi_handler_internal_req_address; + wire [6 : 0] axi_to_dmi_dmi_handler_internal_req_address$D_IN; + wire axi_to_dmi_dmi_handler_internal_req_address$EN; + + // register axi_to_dmi_dmi_handler_internal_req_data + reg [31 : 0] axi_to_dmi_dmi_handler_internal_req_data; + wire [31 : 0] axi_to_dmi_dmi_handler_internal_req_data$D_IN; + wire axi_to_dmi_dmi_handler_internal_req_data$EN; + + // register axi_to_dmi_dmi_handler_internal_req_op + reg [1 : 0] axi_to_dmi_dmi_handler_internal_req_op; + wire [1 : 0] axi_to_dmi_dmi_handler_internal_req_op$D_IN; + wire axi_to_dmi_dmi_handler_internal_req_op$EN; + + // register axi_to_dmi_dmi_handler_internal_rsp_data + reg [31 : 0] axi_to_dmi_dmi_handler_internal_rsp_data; + wire [31 : 0] axi_to_dmi_dmi_handler_internal_rsp_data$D_IN; + wire axi_to_dmi_dmi_handler_internal_rsp_data$EN; + + // register axi_to_dmi_dmi_handler_internal_rsp_op + reg [1 : 0] axi_to_dmi_dmi_handler_internal_rsp_op; + wire [1 : 0] axi_to_dmi_dmi_handler_internal_rsp_op$D_IN; + wire axi_to_dmi_dmi_handler_internal_rsp_op$EN; + + // register axi_to_dmi_dmi_handler_latency + reg [3 : 0] axi_to_dmi_dmi_handler_latency; + wire [3 : 0] axi_to_dmi_dmi_handler_latency$D_IN; + wire axi_to_dmi_dmi_handler_latency$EN; + + // register axi_to_dmi_internal_s_read_in_rv + reg [73 : 0] axi_to_dmi_internal_s_read_in_rv; + wire [73 : 0] axi_to_dmi_internal_s_read_in_rv$D_IN; + wire axi_to_dmi_internal_s_read_in_rv$EN; + + // register axi_to_dmi_internal_s_read_isRst_isInReset + reg axi_to_dmi_internal_s_read_isRst_isInReset; + wire axi_to_dmi_internal_s_read_isRst_isInReset$D_IN, + axi_to_dmi_internal_s_read_isRst_isInReset$EN; + + // register axi_to_dmi_internal_s_read_out_rv + reg [47 : 0] axi_to_dmi_internal_s_read_out_rv; + wire [47 : 0] axi_to_dmi_internal_s_read_out_rv$D_IN; + wire axi_to_dmi_internal_s_read_out_rv$EN; + + // register axi_to_dmi_internal_s_write_in_addr_rv + reg [73 : 0] axi_to_dmi_internal_s_write_in_addr_rv; + wire [73 : 0] axi_to_dmi_internal_s_write_in_addr_rv$D_IN; + wire axi_to_dmi_internal_s_write_in_addr_rv$EN; + + // register axi_to_dmi_internal_s_write_in_data_rv + reg [37 : 0] axi_to_dmi_internal_s_write_in_data_rv; + wire [37 : 0] axi_to_dmi_internal_s_write_in_data_rv$D_IN; + wire axi_to_dmi_internal_s_write_in_data_rv$EN; + + // register axi_to_dmi_internal_s_write_isRst_isInReset + reg axi_to_dmi_internal_s_write_isRst_isInReset; + wire axi_to_dmi_internal_s_write_isRst_isInReset$D_IN, + axi_to_dmi_internal_s_write_isRst_isInReset$EN; + + // register axi_to_dmi_internal_s_write_out_rv + reg [14 : 0] axi_to_dmi_internal_s_write_out_rv; + wire [14 : 0] axi_to_dmi_internal_s_write_out_rv$D_IN; + wire axi_to_dmi_internal_s_write_out_rv$EN; + + // register axi_to_dmi_read_id + reg [11 : 0] axi_to_dmi_read_id; + wire [11 : 0] axi_to_dmi_read_id$D_IN; + wire axi_to_dmi_read_id$EN; + + // register axi_to_dmi_received_addr + reg axi_to_dmi_received_addr; + wire axi_to_dmi_received_addr$D_IN, axi_to_dmi_received_addr$EN; + + // register axi_to_dmi_received_data + reg axi_to_dmi_received_data; + wire axi_to_dmi_received_data$D_IN, axi_to_dmi_received_data$EN; + + // register axi_to_dmi_strb + reg [3 : 0] axi_to_dmi_strb; + wire [3 : 0] axi_to_dmi_strb$D_IN; + wire axi_to_dmi_strb$EN; + + // register axi_to_dmi_write_counter + reg [4 : 0] axi_to_dmi_write_counter; + reg [4 : 0] axi_to_dmi_write_counter$D_IN; + wire axi_to_dmi_write_counter$EN; + + // register axi_to_dmi_write_id + reg [11 : 0] axi_to_dmi_write_id; + wire [11 : 0] axi_to_dmi_write_id$D_IN; + wire axi_to_dmi_write_id$EN; + + // ports of submodule axi_to_dmi_dmi_handler_dmi_request + wire [39 : 0] axi_to_dmi_dmi_handler_dmi_request$D_IN, + axi_to_dmi_dmi_handler_dmi_request$D_OUT; + wire axi_to_dmi_dmi_handler_dmi_request$CLR, + axi_to_dmi_dmi_handler_dmi_request$DEQ, + axi_to_dmi_dmi_handler_dmi_request$EMPTY_N, + axi_to_dmi_dmi_handler_dmi_request$ENQ, + axi_to_dmi_dmi_handler_dmi_request$FULL_N; + + // ports of submodule axi_to_dmi_dmi_handler_dmi_response + wire [33 : 0] axi_to_dmi_dmi_handler_dmi_response$D_IN, + axi_to_dmi_dmi_handler_dmi_response$D_OUT; + wire axi_to_dmi_dmi_handler_dmi_response$CLR, + axi_to_dmi_dmi_handler_dmi_response$DEQ, + axi_to_dmi_dmi_handler_dmi_response$EMPTY_N, + axi_to_dmi_dmi_handler_dmi_response$ENQ, + axi_to_dmi_dmi_handler_dmi_response$FULL_N; + + // rule scheduling signals + wire WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_latency, + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request, + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_response, + WILL_FIRE_RL_axi_to_dmi_receive_read_req, + WILL_FIRE_RL_axi_to_dmi_send_axi_rsp, + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request; + + // inputs to muxes for submodule ports + reg [33 : 0] MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1; + wire [39 : 0] MUX_axi_to_dmi_dmi_handler_dmi_request$enq_1__VAL_1, + MUX_axi_to_dmi_dmi_handler_dmi_request$enq_1__VAL_2; + wire [33 : 0] MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_2; + wire [14 : 0] MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__VAL_1; + wire [3 : 0] MUX_axi_to_dmi_dmi_handler_latency$write_1__VAL_2; + wire [1 : 0] MUX_axi_to_dmi_dmi_handler_internal_req_op$write_1__VAL_1; + wire MUX_axi_to_dmi_access_type$write_1__SEL_1, + MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1, + MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__SEL_1, + MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__SEL_1, + MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__SEL_2, + MUX_axi_to_dmi_received_addr$write_1__SEL_2, + MUX_axi_to_dmi_received_data$write_1__SEL_2; + + // remaining internal signals + reg [3 : 0] CASE_axi_to_dmi_internal_s_read_arinpkgwget_B_ETC__q3, + CASE_axi_to_dmi_internal_s_write_arinpkg_addr_ETC__q4, + CASE_s_AXI_Dmi_arcache_0_s_AXI_Dmi_arcache_1_s_ETC__q1, + CASE_s_AXI_Dmi_awcache_0_s_AXI_Dmi_awcache_1_s_ETC__q2; + wire [31 : 0] x_dmi_data__h5498; + wire [14 : 0] IF_s_AXI_Dmi_arcache_EQ_0_82_OR_s_AXI_Dmi_arca_ETC___d197, + IF_s_AXI_Dmi_awcache_EQ_0_10_OR_s_AXI_Dmi_awca_ETC___d225; + wire [4 : 0] x__h5723; + + // value method s_AXI_Dmi_s_read_fab_arready + assign s_AXI_Dmi_arready = + !axi_to_dmi_internal_s_read_isRst_isInReset && + !axi_to_dmi_internal_s_read_in_rv$port1__read[73] ; + + // value method s_AXI_Dmi_s_read_fab_rvalid + assign s_AXI_Dmi_rvalid = + !axi_to_dmi_internal_s_read_isRst_isInReset && + axi_to_dmi_internal_s_read_out_rv[47] ; + + // value method s_AXI_Dmi_s_read_fab_rid + assign s_AXI_Dmi_rid = + axi_to_dmi_internal_s_read_out_rv[47] ? + axi_to_dmi_internal_s_read_out_rv[46:35] : + 12'd0 ; + + // value method s_AXI_Dmi_s_read_fab_rdata + assign s_AXI_Dmi_rdata = + axi_to_dmi_internal_s_read_out_rv[47] ? + axi_to_dmi_internal_s_read_out_rv[34:3] : + 32'd0 ; + + // value method s_AXI_Dmi_s_read_fab_rresp + assign s_AXI_Dmi_rresp = + axi_to_dmi_internal_s_read_out_rv[47] ? + axi_to_dmi_internal_s_read_out_rv[2:1] : + 2'd0 ; + + // value method s_AXI_Dmi_s_read_fab_rlast + assign s_AXI_Dmi_rlast = + axi_to_dmi_internal_s_read_out_rv[47] && + axi_to_dmi_internal_s_read_out_rv[0] ; + + // value method s_AXI_Dmi_s_write_fab_awready + assign s_AXI_Dmi_awready = + !axi_to_dmi_internal_s_write_isRst_isInReset && + !axi_to_dmi_internal_s_write_in_addr_rv$port1__read[73] ; + + // value method s_AXI_Dmi_s_write_fab_wready + assign s_AXI_Dmi_wready = + !axi_to_dmi_internal_s_write_isRst_isInReset && + !axi_to_dmi_internal_s_write_in_data_rv$port1__read[37] ; + + // value method s_AXI_Dmi_s_write_fab_bvalid + assign s_AXI_Dmi_bvalid = + !axi_to_dmi_internal_s_write_isRst_isInReset && + axi_to_dmi_internal_s_write_out_rv[14] ; + + // value method s_AXI_Dmi_s_write_fab_bresp + assign s_AXI_Dmi_bresp = + axi_to_dmi_internal_s_write_out_rv[14] ? + axi_to_dmi_internal_s_write_out_rv[1:0] : + 2'd0 ; + + // value method s_AXI_Dmi_s_write_fab_bid + assign s_AXI_Dmi_bid = + axi_to_dmi_internal_s_write_out_rv[14] ? + axi_to_dmi_internal_s_write_out_rv[13:2] : + 12'd0 ; + + // value method dmi_master_req_address + assign REQ_ADDRESS = axi_to_dmi_dmi_handler_internal_req_address ; + + // value method dmi_master_req_w_address + assign REQ_W_ADDRESS = axi_to_dmi_dmi_handler_internal_req_address ; + + // value method dmi_master_req_data + assign REQ_DATA = axi_to_dmi_dmi_handler_internal_req_data ; + assign REQ_VALID = 1'd1 ; + + // value method dmi_master_req_op + assign REQ_OP = axi_to_dmi_dmi_handler_internal_req_op ; + + // value method dmi_master_req_access + assign REQ_ACCESS = axi_to_dmi_dmi_handler_internal_req_access ; + + // value method dmi_master_req_read + assign REQ_READ = axi_to_dmi_dmi_handler_internal_req_op[0] ; + + // value method dmi_master_req_write + assign REQ_WRITE = axi_to_dmi_dmi_handler_internal_req_op[1] ; + + // action method dmi_master_rsp_action + assign RSP_READY = 1'd1 ; + + // value method slave_select + assign slave_select = 5'h0A ; + + // submodule axi_to_dmi_dmi_handler_dmi_request + FIFO2 #(.width(32'd40), + .guarded(32'd1)) axi_to_dmi_dmi_handler_dmi_request(.RST(ARESETN), + .CLK(ACLK), + .D_IN(axi_to_dmi_dmi_handler_dmi_request$D_IN), + .ENQ(axi_to_dmi_dmi_handler_dmi_request$ENQ), + .DEQ(axi_to_dmi_dmi_handler_dmi_request$DEQ), + .CLR(axi_to_dmi_dmi_handler_dmi_request$CLR), + .D_OUT(axi_to_dmi_dmi_handler_dmi_request$D_OUT), + .FULL_N(axi_to_dmi_dmi_handler_dmi_request$FULL_N), + .EMPTY_N(axi_to_dmi_dmi_handler_dmi_request$EMPTY_N)); + + // submodule axi_to_dmi_dmi_handler_dmi_response + FIFO2 #(.width(32'd34), + .guarded(32'd1)) axi_to_dmi_dmi_handler_dmi_response(.RST(ARESETN), + .CLK(ACLK), + .D_IN(axi_to_dmi_dmi_handler_dmi_response$D_IN), + .ENQ(axi_to_dmi_dmi_handler_dmi_response$ENQ), + .DEQ(axi_to_dmi_dmi_handler_dmi_response$DEQ), + .CLR(axi_to_dmi_dmi_handler_dmi_response$CLR), + .D_OUT(axi_to_dmi_dmi_handler_dmi_response$D_OUT), + .FULL_N(axi_to_dmi_dmi_handler_dmi_response$FULL_N), + .EMPTY_N(axi_to_dmi_dmi_handler_dmi_response$EMPTY_N)); + + // rule RL_axi_to_dmi_send_dmi_write_request + assign WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request = + axi_to_dmi_dmi_handler_dmi_request$FULL_N && + !axi_to_dmi_internal_s_write_out_rv$port1__read[14] && + axi_to_dmi_received_addr && + axi_to_dmi_received_data && + !WILL_FIRE_RL_axi_to_dmi_send_axi_rsp && + !WILL_FIRE_RL_axi_to_dmi_receive_read_req ; + + // rule RL_axi_to_dmi_send_axi_rsp + assign WILL_FIRE_RL_axi_to_dmi_send_axi_rsp = + axi_to_dmi_dmi_handler_dmi_response$EMPTY_N && + !axi_to_dmi_internal_s_write_out_rv$port1__read[14] && + !axi_to_dmi_internal_s_read_out_rv$port1__read[47] ; + + // rule RL_axi_to_dmi_receive_read_req + assign WILL_FIRE_RL_axi_to_dmi_receive_read_req = + axi_to_dmi_internal_s_read_in_rv[73] && + axi_to_dmi_dmi_handler_dmi_request$FULL_N ; + + // rule RL_axi_to_dmi_dmi_handler_handle_request + assign WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request = + axi_to_dmi_dmi_handler_dmi_request$EMPTY_N && + axi_to_dmi_dmi_handler_dmi_response$FULL_N && + !axi_to_dmi_dmi_handler_dmi_busy ; + + // rule RL_axi_to_dmi_dmi_handler_handle_latency + assign WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_latency = + axi_to_dmi_dmi_handler_dmi_busy && + axi_to_dmi_dmi_handler_latency != 4'd0 ; + + // rule RL_axi_to_dmi_dmi_handler_handle_response + assign WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_response = + axi_to_dmi_dmi_handler_dmi_response$FULL_N && + axi_to_dmi_dmi_handler_dmi_busy && + axi_to_dmi_dmi_handler_latency == 4'd0 ; + + // inputs to muxes for submodule ports + assign MUX_axi_to_dmi_access_type$write_1__SEL_1 = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + (axi_to_dmi_strb == 4'hF || axi_to_dmi_write_counter == 5'd3) ; + assign MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1 = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] == 7'd12 ; + assign MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__SEL_1 = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] != 7'd12 ; + assign MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__SEL_1 = + WILL_FIRE_RL_axi_to_dmi_send_axi_rsp && axi_to_dmi_access_type ; + assign MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__SEL_2 = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + axi_to_dmi_strb != 4'hF && + axi_to_dmi_write_counter != 5'd3 ; + assign MUX_axi_to_dmi_received_addr$write_1__SEL_2 = + axi_to_dmi_internal_s_write_in_addr_rv[73] && + !axi_to_dmi_received_addr ; + assign MUX_axi_to_dmi_received_data$write_1__SEL_2 = + axi_to_dmi_internal_s_write_in_data_rv[37] && + !axi_to_dmi_received_data ; + assign MUX_axi_to_dmi_dmi_handler_dmi_request$enq_1__VAL_1 = + { (axi_to_dmi_strb == 4'hF) ? + axi_to_dmi_address[6:0] : + axi_to_dmi_address_pcie[6:0], + (axi_to_dmi_strb == 4'hF) ? + axi_to_dmi_data : + x_dmi_data__h5498, + 1'd1 } ; + assign MUX_axi_to_dmi_dmi_handler_dmi_request$enq_1__VAL_2 = + { axi_to_dmi_internal_s_read_in_rv[35:29], 33'd0 } ; + always@(axi_to_dmi_dmi_handler_dmi_request$D_OUT) + begin + case (axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33]) + 7'd0: MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1 = 34'd204100; + 7'd4: MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1 = 34'd13572; + 7'd8: MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1 = 34'd220464; + 7'd16: + MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1 = 34'd178004; + default: MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1 = + 34'h37AB6FBBC; + endcase + end + assign MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_2 = + { axi_to_dmi_dmi_handler_internal_rsp_data, 2'd0 } ; + assign MUX_axi_to_dmi_dmi_handler_internal_req_op$write_1__VAL_1 = + axi_to_dmi_dmi_handler_dmi_request$D_OUT[0] ? 2'b10 : 2'b01 ; + assign MUX_axi_to_dmi_dmi_handler_latency$write_1__VAL_2 = + axi_to_dmi_dmi_handler_latency - 4'd1 ; + assign MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__VAL_1 = + { 1'd1, axi_to_dmi_write_id, 2'd0 } ; + + // inlined wires + assign axi_to_dmi_internal_s_read_arinpkg$wget = + { s_AXI_Dmi_arid, + s_AXI_Dmi_araddr, + s_AXI_Dmi_arlen, + s_AXI_Dmi_arsize, + s_AXI_Dmi_arburst, + s_AXI_Dmi_arlock, + IF_s_AXI_Dmi_arcache_EQ_0_82_OR_s_AXI_Dmi_arca_ETC___d197 } ; + assign axi_to_dmi_internal_s_write_arinpkg_addr$wget = + { s_AXI_Dmi_awid, + s_AXI_Dmi_awaddr, + s_AXI_Dmi_awlen, + s_AXI_Dmi_awsize, + s_AXI_Dmi_awburst, + s_AXI_Dmi_awlock, + IF_s_AXI_Dmi_awcache_EQ_0_10_OR_s_AXI_Dmi_awca_ETC___d225 } ; + assign axi_to_dmi_internal_s_write_arinpkg_data$wget = + { s_AXI_Dmi_wdata, s_AXI_Dmi_wstrb, s_AXI_Dmi_wlast } ; + assign axi_to_dmi_internal_s_read_in_rv$port1__read = + WILL_FIRE_RL_axi_to_dmi_receive_read_req ? + 74'h0AAAAAAAAAAAAAAAAAA : + axi_to_dmi_internal_s_read_in_rv ; + assign axi_to_dmi_internal_s_read_in_rv$EN_port1__write = + !axi_to_dmi_internal_s_read_in_rv$port1__read[73] && + !axi_to_dmi_internal_s_read_isRst_isInReset && + s_AXI_Dmi_arvalid ; + assign axi_to_dmi_internal_s_read_in_rv$port1__write_1 = + { 1'd1, + axi_to_dmi_internal_s_read_arinpkg$wget[72:15], + CASE_axi_to_dmi_internal_s_read_arinpkgwget_B_ETC__q3, + axi_to_dmi_internal_s_read_arinpkg$wget[10:0] } ; + assign axi_to_dmi_internal_s_read_in_rv$port2__read = + axi_to_dmi_internal_s_read_in_rv$EN_port1__write ? + axi_to_dmi_internal_s_read_in_rv$port1__write_1 : + axi_to_dmi_internal_s_read_in_rv$port1__read ; + assign axi_to_dmi_internal_s_read_out_rv$EN_port0__write = + axi_to_dmi_internal_s_read_out_rv[47] && + !axi_to_dmi_internal_s_read_isRst_isInReset && + s_AXI_Dmi_rready ; + assign axi_to_dmi_internal_s_read_out_rv$port1__read = + axi_to_dmi_internal_s_read_out_rv$EN_port0__write ? + 48'h2AAAAAAAAAAA : + axi_to_dmi_internal_s_read_out_rv ; + assign axi_to_dmi_internal_s_read_out_rv$EN_port1__write = + WILL_FIRE_RL_axi_to_dmi_send_axi_rsp && !axi_to_dmi_access_type ; + assign axi_to_dmi_internal_s_read_out_rv$port1__write_1 = + { 1'd1, + axi_to_dmi_read_id, + axi_to_dmi_dmi_handler_dmi_response$D_OUT[33:2], + 3'd1 } ; + assign axi_to_dmi_internal_s_read_out_rv$port2__read = + axi_to_dmi_internal_s_read_out_rv$EN_port1__write ? + axi_to_dmi_internal_s_read_out_rv$port1__write_1 : + axi_to_dmi_internal_s_read_out_rv$port1__read ; + assign axi_to_dmi_internal_s_write_in_addr_rv$port1__read = + MUX_axi_to_dmi_received_addr$write_1__SEL_2 ? + 74'h0AAAAAAAAAAAAAAAAAA : + axi_to_dmi_internal_s_write_in_addr_rv ; + assign axi_to_dmi_internal_s_write_in_addr_rv$EN_port1__write = + !axi_to_dmi_internal_s_write_in_addr_rv$port1__read[73] && + !axi_to_dmi_internal_s_write_isRst_isInReset && + s_AXI_Dmi_awvalid ; + assign axi_to_dmi_internal_s_write_in_addr_rv$port1__write_1 = + { 1'd1, + axi_to_dmi_internal_s_write_arinpkg_addr$wget[72:15], + CASE_axi_to_dmi_internal_s_write_arinpkg_addr_ETC__q4, + axi_to_dmi_internal_s_write_arinpkg_addr$wget[10:0] } ; + assign axi_to_dmi_internal_s_write_in_addr_rv$port2__read = + axi_to_dmi_internal_s_write_in_addr_rv$EN_port1__write ? + axi_to_dmi_internal_s_write_in_addr_rv$port1__write_1 : + axi_to_dmi_internal_s_write_in_addr_rv$port1__read ; + assign axi_to_dmi_internal_s_write_in_data_rv$port1__read = + MUX_axi_to_dmi_received_data$write_1__SEL_2 ? + 38'h0AAAAAAAAA : + axi_to_dmi_internal_s_write_in_data_rv ; + assign axi_to_dmi_internal_s_write_in_data_rv$EN_port1__write = + !axi_to_dmi_internal_s_write_in_data_rv$port1__read[37] && + !axi_to_dmi_internal_s_write_isRst_isInReset && + s_AXI_Dmi_wvalid ; + assign axi_to_dmi_internal_s_write_in_data_rv$port1__write_1 = + { 1'd1, axi_to_dmi_internal_s_write_arinpkg_data$wget } ; + assign axi_to_dmi_internal_s_write_in_data_rv$port2__read = + axi_to_dmi_internal_s_write_in_data_rv$EN_port1__write ? + axi_to_dmi_internal_s_write_in_data_rv$port1__write_1 : + axi_to_dmi_internal_s_write_in_data_rv$port1__read ; + assign axi_to_dmi_internal_s_write_out_rv$EN_port0__write = + axi_to_dmi_internal_s_write_out_rv[14] && + !axi_to_dmi_internal_s_write_isRst_isInReset && + s_AXI_Dmi_bready ; + assign axi_to_dmi_internal_s_write_out_rv$port1__read = + axi_to_dmi_internal_s_write_out_rv$EN_port0__write ? + 15'd10922 : + axi_to_dmi_internal_s_write_out_rv ; + assign axi_to_dmi_internal_s_write_out_rv$EN_port1__write = + WILL_FIRE_RL_axi_to_dmi_send_axi_rsp && axi_to_dmi_access_type || + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + axi_to_dmi_strb != 4'hF && + axi_to_dmi_write_counter != 5'd3 ; + assign axi_to_dmi_internal_s_write_out_rv$port1__write_1 = + MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__SEL_1 ? + MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__VAL_1 : + MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__VAL_1 ; + assign axi_to_dmi_internal_s_write_out_rv$port2__read = + axi_to_dmi_internal_s_write_out_rv$EN_port1__write ? + axi_to_dmi_internal_s_write_out_rv$port1__write_1 : + axi_to_dmi_internal_s_write_out_rv$port1__read ; + + // register axi_to_dmi_access_type + assign axi_to_dmi_access_type$D_IN = + MUX_axi_to_dmi_access_type$write_1__SEL_1 ; + assign axi_to_dmi_access_type$EN = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + (axi_to_dmi_strb == 4'hF || axi_to_dmi_write_counter == 5'd3) || + WILL_FIRE_RL_axi_to_dmi_receive_read_req ; + + // register axi_to_dmi_address + assign axi_to_dmi_address$D_IN = + axi_to_dmi_internal_s_write_in_addr_rv[60:29] ; + assign axi_to_dmi_address$EN = MUX_axi_to_dmi_received_addr$write_1__SEL_2 ; + + // register axi_to_dmi_address_pcie + assign axi_to_dmi_address_pcie$D_IN = axi_to_dmi_address ; + assign axi_to_dmi_address_pcie$EN = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + axi_to_dmi_strb != 4'hF && + axi_to_dmi_write_counter == 5'd0 ; + + // register axi_to_dmi_data + assign axi_to_dmi_data$D_IN = axi_to_dmi_internal_s_write_in_data_rv[36:5] ; + assign axi_to_dmi_data$EN = MUX_axi_to_dmi_received_data$write_1__SEL_2 ; + + // register axi_to_dmi_data_pcie + assign axi_to_dmi_data_pcie$D_IN = + (axi_to_dmi_write_counter == 5'd0) ? + axi_to_dmi_data : + x_dmi_data__h5498 ; + assign axi_to_dmi_data_pcie$EN = + MUX_axi_to_dmi_internal_s_write_out_rv$port1__write_1__SEL_2 ; + + // register axi_to_dmi_dmi_handler_dmi_busy + assign axi_to_dmi_dmi_handler_dmi_busy$D_IN = + MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1 ; + assign axi_to_dmi_dmi_handler_dmi_busy$EN = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] == 7'd12 || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_response ; + + // register axi_to_dmi_dmi_handler_internal_req_access + assign axi_to_dmi_dmi_handler_internal_req_access$D_IN = + MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1 ; + assign axi_to_dmi_dmi_handler_internal_req_access$EN = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] == 7'd12 || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_response || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_latency ; + + // register axi_to_dmi_dmi_handler_internal_req_address + assign axi_to_dmi_dmi_handler_internal_req_address$D_IN = + axi_to_dmi_dmi_handler_dmi_request$D_OUT[7:1] ; + assign axi_to_dmi_dmi_handler_internal_req_address$EN = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] == 7'd16 ; + + // register axi_to_dmi_dmi_handler_internal_req_data + assign axi_to_dmi_dmi_handler_internal_req_data$D_IN = + axi_to_dmi_dmi_handler_dmi_request$D_OUT[32:1] ; + assign axi_to_dmi_dmi_handler_internal_req_data$EN = + MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1 ; + + // register axi_to_dmi_dmi_handler_internal_req_op + assign axi_to_dmi_dmi_handler_internal_req_op$D_IN = + MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1 ? + MUX_axi_to_dmi_dmi_handler_internal_req_op$write_1__VAL_1 : + 2'b0 ; + assign axi_to_dmi_dmi_handler_internal_req_op$EN = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] == 7'd12 || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_response || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_latency ; + + // register axi_to_dmi_dmi_handler_internal_rsp_data + assign axi_to_dmi_dmi_handler_internal_rsp_data$D_IN = RSP_DATA ; + assign axi_to_dmi_dmi_handler_internal_rsp_data$EN = RSP_VALID ; + + // register axi_to_dmi_dmi_handler_internal_rsp_op + assign axi_to_dmi_dmi_handler_internal_rsp_op$D_IN = RSP_OP ; + assign axi_to_dmi_dmi_handler_internal_rsp_op$EN = RSP_VALID ; + + // register axi_to_dmi_dmi_handler_latency + assign axi_to_dmi_dmi_handler_latency$D_IN = + MUX_axi_to_dmi_dmi_handler_dmi_busy$write_1__SEL_1 ? + 4'd2 : + MUX_axi_to_dmi_dmi_handler_latency$write_1__VAL_2 ; + assign axi_to_dmi_dmi_handler_latency$EN = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] == 7'd12 || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_latency ; + + // register axi_to_dmi_internal_s_read_in_rv + assign axi_to_dmi_internal_s_read_in_rv$D_IN = + axi_to_dmi_internal_s_read_in_rv$port2__read ; + assign axi_to_dmi_internal_s_read_in_rv$EN = 1'b1 ; + + // register axi_to_dmi_internal_s_read_isRst_isInReset + assign axi_to_dmi_internal_s_read_isRst_isInReset$D_IN = 1'd0 ; + assign axi_to_dmi_internal_s_read_isRst_isInReset$EN = + axi_to_dmi_internal_s_read_isRst_isInReset ; + + // register axi_to_dmi_internal_s_read_out_rv + assign axi_to_dmi_internal_s_read_out_rv$D_IN = + axi_to_dmi_internal_s_read_out_rv$port2__read ; + assign axi_to_dmi_internal_s_read_out_rv$EN = 1'b1 ; + + // register axi_to_dmi_internal_s_write_in_addr_rv + assign axi_to_dmi_internal_s_write_in_addr_rv$D_IN = + axi_to_dmi_internal_s_write_in_addr_rv$port2__read ; + assign axi_to_dmi_internal_s_write_in_addr_rv$EN = 1'b1 ; + + // register axi_to_dmi_internal_s_write_in_data_rv + assign axi_to_dmi_internal_s_write_in_data_rv$D_IN = + axi_to_dmi_internal_s_write_in_data_rv$port2__read ; + assign axi_to_dmi_internal_s_write_in_data_rv$EN = 1'b1 ; + + // register axi_to_dmi_internal_s_write_isRst_isInReset + assign axi_to_dmi_internal_s_write_isRst_isInReset$D_IN = 1'd0 ; + assign axi_to_dmi_internal_s_write_isRst_isInReset$EN = + axi_to_dmi_internal_s_write_isRst_isInReset ; + + // register axi_to_dmi_internal_s_write_out_rv + assign axi_to_dmi_internal_s_write_out_rv$D_IN = + axi_to_dmi_internal_s_write_out_rv$port2__read ; + assign axi_to_dmi_internal_s_write_out_rv$EN = 1'b1 ; + + // register axi_to_dmi_read_id + assign axi_to_dmi_read_id$D_IN = axi_to_dmi_internal_s_read_in_rv[72:61] ; + assign axi_to_dmi_read_id$EN = WILL_FIRE_RL_axi_to_dmi_receive_read_req ; + + // register axi_to_dmi_received_addr + assign axi_to_dmi_received_addr$D_IN = + !WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request ; + assign axi_to_dmi_received_addr$EN = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request || + axi_to_dmi_internal_s_write_in_addr_rv[73] && + !axi_to_dmi_received_addr ; + + // register axi_to_dmi_received_data + assign axi_to_dmi_received_data$D_IN = + !WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request ; + assign axi_to_dmi_received_data$EN = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request || + axi_to_dmi_internal_s_write_in_data_rv[37] && + !axi_to_dmi_received_data ; + + // register axi_to_dmi_strb + assign axi_to_dmi_strb$D_IN = axi_to_dmi_internal_s_write_in_data_rv[4:1] ; + assign axi_to_dmi_strb$EN = MUX_axi_to_dmi_received_data$write_1__SEL_2 ; + + // register axi_to_dmi_write_counter + always@(axi_to_dmi_write_counter or x__h5723) + begin + case (axi_to_dmi_write_counter) + 5'd0: axi_to_dmi_write_counter$D_IN = x__h5723; + 5'd3: axi_to_dmi_write_counter$D_IN = 5'd0; + default: axi_to_dmi_write_counter$D_IN = x__h5723; + endcase + end + assign axi_to_dmi_write_counter$EN = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + axi_to_dmi_strb != 4'hF ; + + // register axi_to_dmi_write_id + assign axi_to_dmi_write_id$D_IN = + axi_to_dmi_internal_s_write_in_addr_rv[72:61] ; + assign axi_to_dmi_write_id$EN = + MUX_axi_to_dmi_received_addr$write_1__SEL_2 ; + + // submodule axi_to_dmi_dmi_handler_dmi_request + assign axi_to_dmi_dmi_handler_dmi_request$D_IN = + MUX_axi_to_dmi_access_type$write_1__SEL_1 ? + MUX_axi_to_dmi_dmi_handler_dmi_request$enq_1__VAL_1 : + MUX_axi_to_dmi_dmi_handler_dmi_request$enq_1__VAL_2 ; + assign axi_to_dmi_dmi_handler_dmi_request$ENQ = + WILL_FIRE_RL_axi_to_dmi_send_dmi_write_request && + (axi_to_dmi_strb == 4'hF || axi_to_dmi_write_counter == 5'd3) || + WILL_FIRE_RL_axi_to_dmi_receive_read_req ; + assign axi_to_dmi_dmi_handler_dmi_request$DEQ = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request ; + assign axi_to_dmi_dmi_handler_dmi_request$CLR = 1'b0 ; + + // submodule axi_to_dmi_dmi_handler_dmi_response + assign axi_to_dmi_dmi_handler_dmi_response$D_IN = + MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__SEL_1 ? + MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_1 : + MUX_axi_to_dmi_dmi_handler_dmi_response$enq_1__VAL_2 ; + assign axi_to_dmi_dmi_handler_dmi_response$ENQ = + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_request && + axi_to_dmi_dmi_handler_dmi_request$D_OUT[39:33] != 7'd12 || + WILL_FIRE_RL_axi_to_dmi_dmi_handler_handle_response ; + assign axi_to_dmi_dmi_handler_dmi_response$DEQ = + WILL_FIRE_RL_axi_to_dmi_send_axi_rsp ; + assign axi_to_dmi_dmi_handler_dmi_response$CLR = 1'b0 ; + + // remaining internal signals + assign IF_s_AXI_Dmi_arcache_EQ_0_82_OR_s_AXI_Dmi_arca_ETC___d197 = + { CASE_s_AXI_Dmi_arcache_0_s_AXI_Dmi_arcache_1_s_ETC__q1, + s_AXI_Dmi_arprot, + s_AXI_Dmi_arqos, + s_AXI_Dmi_arregion } ; + assign IF_s_AXI_Dmi_awcache_EQ_0_10_OR_s_AXI_Dmi_awca_ETC___d225 = + { CASE_s_AXI_Dmi_awcache_0_s_AXI_Dmi_awcache_1_s_ETC__q2, + s_AXI_Dmi_awprot, + s_AXI_Dmi_awqos, + s_AXI_Dmi_awregion } ; + assign x__h5723 = axi_to_dmi_write_counter + 5'd1 ; + assign x_dmi_data__h5498 = axi_to_dmi_data_pcie | axi_to_dmi_data ; + always@(s_AXI_Dmi_arcache) + begin + case (s_AXI_Dmi_arcache) + 4'd0, 4'd1, 4'd2, 4'd3, 4'd10, 4'd14, 4'd15: + CASE_s_AXI_Dmi_arcache_0_s_AXI_Dmi_arcache_1_s_ETC__q1 = + s_AXI_Dmi_arcache; + default: CASE_s_AXI_Dmi_arcache_0_s_AXI_Dmi_arcache_1_s_ETC__q1 = 4'd11; + endcase + end + always@(s_AXI_Dmi_awcache) + begin + case (s_AXI_Dmi_awcache) + 4'd0, 4'd1, 4'd2, 4'd3, 4'd6, 4'd7, 4'd14: + CASE_s_AXI_Dmi_awcache_0_s_AXI_Dmi_awcache_1_s_ETC__q2 = + s_AXI_Dmi_awcache; + default: CASE_s_AXI_Dmi_awcache_0_s_AXI_Dmi_awcache_1_s_ETC__q2 = 4'd15; + endcase + end + always@(axi_to_dmi_internal_s_read_arinpkg$wget) + begin + case (axi_to_dmi_internal_s_read_arinpkg$wget[14:11]) + 4'd0, 4'd1, 4'd2, 4'd3, 4'd10, 4'd14, 4'd15: + CASE_axi_to_dmi_internal_s_read_arinpkgwget_B_ETC__q3 = + axi_to_dmi_internal_s_read_arinpkg$wget[14:11]; + default: CASE_axi_to_dmi_internal_s_read_arinpkgwget_B_ETC__q3 = 4'd11; + endcase + end + always@(axi_to_dmi_internal_s_write_arinpkg_addr$wget) + begin + case (axi_to_dmi_internal_s_write_arinpkg_addr$wget[14:11]) + 4'd0, 4'd1, 4'd2, 4'd3, 4'd6, 4'd7, 4'd14: + CASE_axi_to_dmi_internal_s_write_arinpkg_addr_ETC__q4 = + axi_to_dmi_internal_s_write_arinpkg_addr$wget[14:11]; + default: CASE_axi_to_dmi_internal_s_write_arinpkg_addr_ETC__q4 = 4'd15; + endcase + end + + // handling of inlined registers + + always@(posedge ACLK) + begin + if (ARESETN == `BSV_RESET_VALUE) + begin + axi_to_dmi_access_type <= `BSV_ASSIGNMENT_DELAY 1'd0; + axi_to_dmi_address <= `BSV_ASSIGNMENT_DELAY 32'd0; + axi_to_dmi_address_pcie <= `BSV_ASSIGNMENT_DELAY 32'd0; + axi_to_dmi_data <= `BSV_ASSIGNMENT_DELAY 32'd0; + axi_to_dmi_data_pcie <= `BSV_ASSIGNMENT_DELAY 32'd0; + axi_to_dmi_dmi_handler_dmi_busy <= `BSV_ASSIGNMENT_DELAY 1'd0; + axi_to_dmi_dmi_handler_internal_req_access <= `BSV_ASSIGNMENT_DELAY + 1'd0; + axi_to_dmi_dmi_handler_internal_req_address <= `BSV_ASSIGNMENT_DELAY + 7'd0; + axi_to_dmi_dmi_handler_internal_req_data <= `BSV_ASSIGNMENT_DELAY + 32'd0; + axi_to_dmi_dmi_handler_internal_req_op <= `BSV_ASSIGNMENT_DELAY 2'd0; + axi_to_dmi_dmi_handler_internal_rsp_data <= `BSV_ASSIGNMENT_DELAY + 32'd0; + axi_to_dmi_dmi_handler_internal_rsp_op <= `BSV_ASSIGNMENT_DELAY 2'd0; + axi_to_dmi_dmi_handler_latency <= `BSV_ASSIGNMENT_DELAY 4'd0; + axi_to_dmi_internal_s_read_in_rv <= `BSV_ASSIGNMENT_DELAY + 74'h0AAAAAAAAAAAAAAAAAA; + axi_to_dmi_internal_s_read_out_rv <= `BSV_ASSIGNMENT_DELAY + 48'h2AAAAAAAAAAA; + axi_to_dmi_internal_s_write_in_addr_rv <= `BSV_ASSIGNMENT_DELAY + 74'h0AAAAAAAAAAAAAAAAAA; + axi_to_dmi_internal_s_write_in_data_rv <= `BSV_ASSIGNMENT_DELAY + 38'h0AAAAAAAAA; + axi_to_dmi_internal_s_write_out_rv <= `BSV_ASSIGNMENT_DELAY 15'd10922; + axi_to_dmi_read_id <= `BSV_ASSIGNMENT_DELAY 12'd0; + axi_to_dmi_received_addr <= `BSV_ASSIGNMENT_DELAY 1'd0; + axi_to_dmi_received_data <= `BSV_ASSIGNMENT_DELAY 1'd0; + axi_to_dmi_strb <= `BSV_ASSIGNMENT_DELAY 4'd0; + axi_to_dmi_write_counter <= `BSV_ASSIGNMENT_DELAY 5'd0; + axi_to_dmi_write_id <= `BSV_ASSIGNMENT_DELAY 12'd0; + end + else + begin + if (axi_to_dmi_access_type$EN) + axi_to_dmi_access_type <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_access_type$D_IN; + if (axi_to_dmi_address$EN) + axi_to_dmi_address <= `BSV_ASSIGNMENT_DELAY axi_to_dmi_address$D_IN; + if (axi_to_dmi_address_pcie$EN) + axi_to_dmi_address_pcie <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_address_pcie$D_IN; + if (axi_to_dmi_data$EN) + axi_to_dmi_data <= `BSV_ASSIGNMENT_DELAY axi_to_dmi_data$D_IN; + if (axi_to_dmi_data_pcie$EN) + axi_to_dmi_data_pcie <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_data_pcie$D_IN; + if (axi_to_dmi_dmi_handler_dmi_busy$EN) + axi_to_dmi_dmi_handler_dmi_busy <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_dmi_busy$D_IN; + if (axi_to_dmi_dmi_handler_internal_req_access$EN) + axi_to_dmi_dmi_handler_internal_req_access <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_internal_req_access$D_IN; + if (axi_to_dmi_dmi_handler_internal_req_address$EN) + axi_to_dmi_dmi_handler_internal_req_address <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_internal_req_address$D_IN; + if (axi_to_dmi_dmi_handler_internal_req_data$EN) + axi_to_dmi_dmi_handler_internal_req_data <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_internal_req_data$D_IN; + if (axi_to_dmi_dmi_handler_internal_req_op$EN) + axi_to_dmi_dmi_handler_internal_req_op <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_internal_req_op$D_IN; + if (axi_to_dmi_dmi_handler_internal_rsp_data$EN) + axi_to_dmi_dmi_handler_internal_rsp_data <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_internal_rsp_data$D_IN; + if (axi_to_dmi_dmi_handler_internal_rsp_op$EN) + axi_to_dmi_dmi_handler_internal_rsp_op <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_internal_rsp_op$D_IN; + if (axi_to_dmi_dmi_handler_latency$EN) + axi_to_dmi_dmi_handler_latency <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_dmi_handler_latency$D_IN; + if (axi_to_dmi_internal_s_read_in_rv$EN) + axi_to_dmi_internal_s_read_in_rv <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_read_in_rv$D_IN; + if (axi_to_dmi_internal_s_read_out_rv$EN) + axi_to_dmi_internal_s_read_out_rv <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_read_out_rv$D_IN; + if (axi_to_dmi_internal_s_write_in_addr_rv$EN) + axi_to_dmi_internal_s_write_in_addr_rv <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_write_in_addr_rv$D_IN; + if (axi_to_dmi_internal_s_write_in_data_rv$EN) + axi_to_dmi_internal_s_write_in_data_rv <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_write_in_data_rv$D_IN; + if (axi_to_dmi_internal_s_write_out_rv$EN) + axi_to_dmi_internal_s_write_out_rv <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_write_out_rv$D_IN; + if (axi_to_dmi_read_id$EN) + axi_to_dmi_read_id <= `BSV_ASSIGNMENT_DELAY axi_to_dmi_read_id$D_IN; + if (axi_to_dmi_received_addr$EN) + axi_to_dmi_received_addr <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_received_addr$D_IN; + if (axi_to_dmi_received_data$EN) + axi_to_dmi_received_data <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_received_data$D_IN; + if (axi_to_dmi_strb$EN) + axi_to_dmi_strb <= `BSV_ASSIGNMENT_DELAY axi_to_dmi_strb$D_IN; + if (axi_to_dmi_write_counter$EN) + axi_to_dmi_write_counter <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_write_counter$D_IN; + if (axi_to_dmi_write_id$EN) + axi_to_dmi_write_id <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_write_id$D_IN; + end + end + + always@(posedge ACLK or `BSV_RESET_EDGE ARESETN) + if (ARESETN == `BSV_RESET_VALUE) + begin + axi_to_dmi_internal_s_read_isRst_isInReset <= `BSV_ASSIGNMENT_DELAY + 1'd1; + axi_to_dmi_internal_s_write_isRst_isInReset <= `BSV_ASSIGNMENT_DELAY + 1'd1; + end + else + begin + if (axi_to_dmi_internal_s_read_isRst_isInReset$EN) + axi_to_dmi_internal_s_read_isRst_isInReset <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_read_isRst_isInReset$D_IN; + if (axi_to_dmi_internal_s_write_isRst_isInReset$EN) + axi_to_dmi_internal_s_write_isRst_isInReset <= `BSV_ASSIGNMENT_DELAY + axi_to_dmi_internal_s_write_isRst_isInReset$D_IN; + end + + // synopsys translate_off + `ifdef BSV_NO_INITIAL_BLOCKS + `else // not BSV_NO_INITIAL_BLOCKS + initial + begin + axi_to_dmi_access_type = 1'h0; + axi_to_dmi_address = 32'hAAAAAAAA; + axi_to_dmi_address_pcie = 32'hAAAAAAAA; + axi_to_dmi_data = 32'hAAAAAAAA; + axi_to_dmi_data_pcie = 32'hAAAAAAAA; + axi_to_dmi_dmi_handler_dmi_busy = 1'h0; + axi_to_dmi_dmi_handler_internal_req_access = 1'h0; + axi_to_dmi_dmi_handler_internal_req_address = 7'h2A; + axi_to_dmi_dmi_handler_internal_req_data = 32'hAAAAAAAA; + axi_to_dmi_dmi_handler_internal_req_op = 2'h2; + axi_to_dmi_dmi_handler_internal_rsp_data = 32'hAAAAAAAA; + axi_to_dmi_dmi_handler_internal_rsp_op = 2'h2; + axi_to_dmi_dmi_handler_latency = 4'hA; + axi_to_dmi_internal_s_read_in_rv = 74'h2AAAAAAAAAAAAAAAAAA; + axi_to_dmi_internal_s_read_isRst_isInReset = 1'h0; + axi_to_dmi_internal_s_read_out_rv = 48'hAAAAAAAAAAAA; + axi_to_dmi_internal_s_write_in_addr_rv = 74'h2AAAAAAAAAAAAAAAAAA; + axi_to_dmi_internal_s_write_in_data_rv = 38'h2AAAAAAAAA; + axi_to_dmi_internal_s_write_isRst_isInReset = 1'h0; + axi_to_dmi_internal_s_write_out_rv = 15'h2AAA; + axi_to_dmi_read_id = 12'hAAA; + axi_to_dmi_received_addr = 1'h0; + axi_to_dmi_received_data = 1'h0; + axi_to_dmi_strb = 4'hA; + axi_to_dmi_write_counter = 5'h0A; + axi_to_dmi_write_id = 12'hAAA; + end + `endif // BSV_NO_INITIAL_BLOCKS + // synopsys translate_on +endmodule // mkAXI_to_Dmi + diff --git a/toolflow/vivado/common/ip/AXI_to_Dmi/xgui/AXI_to_Dmi_v1_0.tcl b/toolflow/vivado/common/ip/AXI_to_Dmi/xgui/AXI_to_Dmi_v1_0.tcl new file mode 100644 index 00000000..0db18e9a --- /dev/null +++ b/toolflow/vivado/common/ip/AXI_to_Dmi/xgui/AXI_to_Dmi_v1_0.tcl @@ -0,0 +1,10 @@ +# Definitional proc to organize widgets for parameters. +proc init_gui { IPINST } { + ipgui::add_param $IPINST -name "Component_Name" + #Adding Page + ipgui::add_page $IPINST -name "Page 0" + + +} + + diff --git a/toolflow/vivado/common/ip/AXI_to_Dmi/xgui/mkAXI_to_Dmi_v1_0.tcl b/toolflow/vivado/common/ip/AXI_to_Dmi/xgui/mkAXI_to_Dmi_v1_0.tcl new file mode 100644 index 00000000..0db18e9a --- /dev/null +++ b/toolflow/vivado/common/ip/AXI_to_Dmi/xgui/mkAXI_to_Dmi_v1_0.tcl @@ -0,0 +1,10 @@ +# Definitional proc to organize widgets for parameters. +proc init_gui { IPINST } { + ipgui::add_param $IPINST -name "Component_Name" + #Adding Page + ipgui::add_page $IPINST -name "Page 0" + + +} + + diff --git a/toolflow/vivado/common/ip/DMI/DMI.xml b/toolflow/vivado/common/ip/DMI/DMI.xml new file mode 100644 index 00000000..a5ed05d1 --- /dev/null +++ b/toolflow/vivado/common/ip/DMI/DMI.xml @@ -0,0 +1,12 @@ + + + esa.informatik.tu-darmstadt.de + user + DMI + 1.0 + false + false + 1 + 1 + RISC-V Debug Module Interface between DTM and DM see draft of the debug specification. + diff --git a/toolflow/vivado/common/ip/DMI/DMI_rtl.xml b/toolflow/vivado/common/ip/DMI/DMI_rtl.xml new file mode 100644 index 00000000..d5f15764 --- /dev/null +++ b/toolflow/vivado/common/ip/DMI/DMI_rtl.xml @@ -0,0 +1,212 @@ + + + esa.informatik.tu-darmstadt.de + user + DMI_rtl + 1.0 + + + + REQ_VALID + Indicates that a request is currently pending + + + 1 + + + 1 + in + + 1 + + + + REQ_READY + Indicates to the master that the slave is ready to accept a request + + + 1 + in + + + 1 + + 1 + + + + REQ_ADDRESS + The address in a request for either read or write + + + true + + + required + 7 + + + required + 7 + in + + 0 + + + + REQ_W_ADDRESS + The address in a request only for a write + + + true + + + 7 + + + 7 + in + + 0 + + + + REQ_DATA + The data that should be written with a request + + + true + + + required + 32 + + + required + 32 + in + + 0 + + + + REQ_OP + Corresponds to the meaning of the op field in the dmi register of the RISC-V DTM + + + required + 2 + + + 2 + in + + 0 + + + + REQ_READ + Indicates that a read request should be performed + + + 1 + + + 1 + in + + 0 + + + + REQ_WRITE + Indicates that a write request should be performed + + + 1 + + + 1 + in + + 0 + + + + REQ_ACCESS + Indicates that a request should be performed + + + required + 1 + + + 1 + in + + 0 + + + + RSP_VALID + Indicates to the master that a response is valid + + + 1 + in + + + 1 + + 1 + + + + RSP_READY + Indicates to the slave that the master can accept a response + + + 1 + + + 1 + in + + 1 + + + + RSP_DATA + The data from a successful read request + + + true + + + required + 32 + in + + + required + 32 + + 0 + + + + RSP_OP + Corresponds to the meaning of the op field in the dmi register of the RISC-V DTM + + + 2 + in + + + 2 + + 0 + + + + diff --git a/toolflow/vivado/platform/AU280/AU280.tcl b/toolflow/vivado/platform/AU280/AU280.tcl index 57f168a2..25179635 100644 --- a/toolflow/vivado/platform/AU280/AU280.tcl +++ b/toolflow/vivado/platform/AU280/AU280.tcl @@ -174,6 +174,7 @@ namespace eval platform { insert_regslice "host_dma" true "/host/M_DMA" "/memory/S_DMA" "/clocks_and_resets/host_clk" "/clocks_and_resets/host_interconnect_aresetn" "" insert_regslice "dma_host" true "/memory/M_HOST" "/host/S_HOST" "/clocks_and_resets/host_clk" "/clocks_and_resets/host_interconnect_aresetn" "" insert_regslice "host_arch" true "/host/M_ARCH" "/arch/S_ARCH" "/clocks_and_resets/design_clk" "/clocks_and_resets/design_interconnect_aresetn" "" + insert_regslice "l2_cache" [tapasco::is_feature_enabled "Cache"] "/memory/cache_l2_0/M0_AXI" "/memory/mig/C0_DDR4_S_AXI" "/clocks_and_resets/mem_clk" "/clocks_and_resets/mem_peripheral_aresetn" "/memory" if {[is_regslice_enabled "pe" false]} { set ips [get_bd_cells /arch/target_ip_*] diff --git a/toolflow/vivado/platform/AU280/plugins/hbm.tcl b/toolflow/vivado/platform/AU280/plugins/hbm.tcl index 6e4f98b5..423b28b3 100644 --- a/toolflow/vivado/platform/AU280/plugins/hbm.tcl +++ b/toolflow/vivado/platform/AU280/plugins/hbm.tcl @@ -17,7 +17,6 @@ # along with this program. If not, see . # - if {[tapasco::is_feature_enabled "HBM"]} { proc create_custom_subsystem_hbm {{args {}}} { @@ -245,17 +244,19 @@ namespace eval hbm { set hbm_index [format %02s $i] - # create smartconnect for clock domain conversion, protocol conversion (AXI4->AXI3) and data width conversion - set converter [create_bd_cell -type ip -vlnv xilinx.com:ip:smartconnect:1.0 smartconnect_${i}] - set_property -dict [list CONFIG.NUM_SI {1} CONFIG.NUM_CLKS {2} CONFIG.HAS_ARESETN {0}] $converter + # create interconnect for clock domain conversion, protocol conversion (AXI4->AXI3) and data width conversion + set converter [tapasco::ip::create_axi_ic converter_ic_${i} 1 1] + # set regslice to auto for correct protocol conversion + set_property -dict [list CONFIG.S00_HAS_REGSLICE {3}] $converter - # create connections between PE and smartconnect, and smartconnect and HBM - - connect_bd_net [get_bd_pins design_clk] [get_bd_pins $converter/aclk] - connect_bd_net [get_bd_pins $hbm/AXI_${hbm_index}_ACLK] [get_bd_pins $converter/aclk1] + # create connections between PE and interconnect, and interconnect and HBM + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $converter/S00_ACLK] + connect_bd_net [get_bd_pins design_interconnect_aresetn] [get_bd_pins $converter/S00_ARESETN] + connect_bd_net [get_bd_pins $hbm/AXI_${hbm_index}_ACLK] [get_bd_pins $converter/ACLK] [get_bd_pins $converter/M00_ACLK] + connect_bd_net [get_bd_pins $hbm/AXI_${hbm_index}_ARESET_N] [get_bd_pins $converter/ARESETN] [get_bd_pins $converter/M00_ARESETN] if {[platform::is_regslice_enabled "hbm_pe" false] || [platform::is_regslice_enabled [format "hbm_pe%s" $hbm_index] false]} { - # insert register slice between PE and smartconnect + # insert register slice between PE and interconnect set regslice_pre [create_bd_cell -type ip -vlnv xilinx.com:ip:axi_register_slice:2.1 regslice_pre_${i}] set_property -dict [list CONFIG.REG_AW {15} CONFIG.REG_AR {15} CONFIG.REG_W {15} CONFIG.REG_R {15} CONFIG.REG_B {15} CONFIG.USE_AUTOPIPELINING {1}] $regslice_pre @@ -269,7 +270,7 @@ namespace eval hbm { } if {[platform::is_regslice_enabled "hbm_hbm" false] || [platform::is_regslice_enabled [format "hbm_hbm%s" $hbm_index] false]} { - # insert register slice between smartconnect and HBM + # insert register slice between interconnect and HBM set regslice_post [create_bd_cell -type ip -vlnv xilinx.com:ip:axi_register_slice:2.1 regslice_post_${i}] set_property -dict [list CONFIG.REG_AW {15} CONFIG.REG_AR {15} CONFIG.REG_W {15} CONFIG.REG_R {15} CONFIG.REG_B {15} CONFIG.USE_AUTOPIPELINING {1}] $regslice_post @@ -289,8 +290,13 @@ namespace eval hbm { set masters [ldiff [lsort -dictionary [tapasco::get_aximm_interfaces [get_bd_cells /arch/target_ip_*]]] $hbmInterfaces] set arch_mem_ics [arch::arch_create_mem_interconnects $mgroups [llength $masters]] arch::arch_connect_mem $arch_mem_ics $masters - catch {arch::arch_connect_clocks} issue - catch {arch::arch_connect_resets} issue + + connect_bd_net [tapasco::subsystem::get_port "design" "clk"] \ + [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == clk && DIR == I"] + connect_bd_net -quiet [tapasco::subsystem::get_port "design" "rst" "interconnect"] \ + [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == rst && NAME =~ *interconnect_aresetn && DIR == I"] + connect_bd_net [tapasco::subsystem::get_port "design" "rst" "peripheral" "resetn"] \ + [get_bd_pins -of_objects [get_bd_cells -of_objects [current_bd_instance .]] -filter "TYPE == rst && NAME =~ *peripheral_aresetn && DIR == I"] # apply constraints for one or both stacks current_bd_instance /hbm @@ -350,5 +356,29 @@ namespace eval hbm { } +if {[tapasco::is_feature_enabled "HBM"]} { + namespace eval system_cache { + proc get_mem_connections {} { + set subsystem "/hbm" + # retrieve clk and rst port of /hbm subsystem + set instance [current_bd_instance] + current_bd_instance $subsystem + set clock [tapasco::subsystem::get_port "design" "clk"] + set reset [tapasco::subsystem::get_port "design" "rst" "peripheral" "resetn"] + current_bd_instance $instance + + # existing memory controller cache location + set cons [list [get_bd_intf_pins /memory/mig_ic/M00_AXI] [get_bd_intf_pins -regexp /memory/mig/(C0_DDR4_)?S_AXI] "/memory" [tapasco::subsystem::get_port "mem" "clk"] [tapasco::subsystem::get_port "mem" "rst" "peripheral" "resetn"]] + + # get all HBM AXI connections + foreach pin [get_bd_intf_pins -of_objects [get_bd_cells /hbm/converter_ic_*] -filter "VLNV == [tapasco::ip::get_vlnv aximm_intf] && MODE == Slave"] { + set pinA [lindex [get_bd_intf_pins -of [get_bd_intf_nets -of_objects $pin]] 1] + set pinB [lindex [get_bd_intf_pins -of [get_bd_intf_nets -of_objects $pin]] 0] + lappend cons $pinA $pinB "/hbm" $clock $reset + } + return $cons + } + } +} -tapasco::register_plugin "platform::hbm::addressmap" "post-address-map" \ No newline at end of file +tapasco::register_plugin "platform::hbm::addressmap" "post-address-map" diff --git a/toolflow/vivado/platform/AU280/plugins/sfpplus.tcl b/toolflow/vivado/platform/AU280/plugins/sfpplus.tcl new file mode 100644 index 00000000..148531b0 --- /dev/null +++ b/toolflow/vivado/platform/AU280/plugins/sfpplus.tcl @@ -0,0 +1,65 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + proc is_sfpplus_supported {} { + return true + } + + proc get_available_modes {} { + return {"10G" "100G" "Aurora"} + } + + proc num_available_ports {mode} { + if {$mode == "10G"} { + return [10g::num_available_ports] + } + if {$mode == "100G"} { + return [100g::num_available_ports] + } + if {$mode == "Aurora"} { + return [Aurora::num_available_ports] + } + puts "Invalid SFP+ mode: mode $mode is not supported by this platform. Available modes are: 10G, 100G, Aurora" + exit + } + + proc generate_cores {mode ports} { + if {$mode == "10G"} { + 10g::generate_cores $ports + } elseif {$mode == "100G"} { + 100g::generate_cores $ports + } elseif {$mode == "Aurora"} { + Aurora::generate_cores $ports + } else { + puts "Invalid SFP+ mode: mode $mode is not supported by this platform. Available modes are: 10G, 100G, Aurora" + exit + } + } + + proc addressmap {{args {}}} { + if {[tapasco::is_feature_enabled "SFPPLUS"]} { + set args [lappend args "M_NETWORK" [list 0x2500000 0 0 ""]] + } + return $args + } +} + +tapasco::register_plugin "platform::sfpplus::addressmap" "post-address-map" \ No newline at end of file diff --git a/toolflow/vivado/platform/AU280/plugins/sfpplus_100g.tcl b/toolflow/vivado/platform/AU280/plugins/sfpplus_100g.tcl new file mode 100644 index 00000000..1fd88f6e --- /dev/null +++ b/toolflow/vivado/platform/AU280/plugins/sfpplus_100g.tcl @@ -0,0 +1,150 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + namespace eval 100g { + + variable available_ports 2 + variable cmac_cores {"CMACE4_X0Y6" "CMACE4_X0Y7"} + variable gt_groups {"X0Y40~X0Y43" "X0Y44~X0Y47"} + variable refclk_pins {"T42" "P42"} + + proc num_available_ports {} { + variable available_ports + return $available_ports + } + + proc generate_cores {ports} { + + set num_streams [dict size $ports] + + puts "Generating $num_streams SFPPLUS cores" + set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" + set constraints_file [open $constraints_fn w+] + + # QSFP Ports + set const_one [tapasco::ip::create_constant const_one 1 1] + + # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core + set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] + set_property -dict [list \ + CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {false} \ + ] $dclk_wiz + + # Reset Generator for dclk reset + set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] + + connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] + connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] + + set first_port 0 + foreach port [dict keys $ports] { + set name [dict get $ports $port] + generate_core $port $name $first_port $constraints_file + incr first_port 1 + } + + close $constraints_file + read_xdc $constraints_fn + set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] + } + + # Generate a SFP+-Core to handle the ports of one physical cage + # @param physical_port the number of the physical cage + # @param name name of the port + # @param first_port the first free master on the AXI-Lite Config interconnect + # @param constraints_file the file used for constraints + proc generate_core {physical_port name first_port constraints_file} { + variable refclk_pins + variable cmac_cores + variable gt_groups + + # Create and configure core + set core [tapasco::ip::create_100g_ethernet ethernet_$physical_port] + + # Create and constrain refclk pin + set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 qsfp${physical_port}_156mhz] + set_property CONFIG.FREQ_HZ 156250000 $gt_refclk + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $physical_port] qsfp${physical_port}_156mhz_clk_p] + + set_property -dict [list \ + CONFIG.CMAC_CAUI4_MODE {1} \ + CONFIG.NUM_LANES {4x25} \ + CONFIG.USER_INTERFACE {AXIS} \ + CONFIG.GT_REF_CLK_FREQ {156.25} \ + CONFIG.TX_FLOW_CONTROL {0} \ + CONFIG.RX_FLOW_CONTROL {0} \ + CONFIG.INCLUDE_RS_FEC {1} \ + CONFIG.ENABLE_AXI_INTERFACE {0} \ + CONFIG.INCLUDE_STATISTICS_COUNTERS {0} \ + CONFIG.RX_MAX_PACKET_LEN {16383} \ + CONFIG.CMAC_CORE_SELECT [lindex $cmac_cores $physical_port] \ + CONFIG.GT_GROUP_SELECT [lindex $gt_groups $physical_port] \ + ] $core + + # Connect core + connect_bd_net [get_bd_pins $core/sys_reset] [get_bd_pins dclk_reset/peripheral_reset] + connect_bd_net [get_bd_pins $core/drp_clk] [get_bd_pins dclk_wiz/clk_out1] + connect_bd_net [get_bd_pins $core/init_clk] [get_bd_pins dclk_wiz/clk_out1] + + connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/gt_ref_clk] + make_bd_intf_pins_external [get_bd_intf_pins $core/gt_serial_port] + + connect_bd_intf_net [get_bd_intf_pins $core/axis_rx] [get_bd_intf_pins AXIS_RX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/axis_tx] [get_bd_intf_pins AXIS_TX_${name}] + connect_bd_net [get_bd_pins $core/gt_txusrclk2] [get_bd_pins $core/rx_clk] + + # clock and resets to AXIS interconnect + connect_bd_net [get_bd_pins $core/gt_txusrclk2] [get_bd_pins /Network/sfp_tx_clock_${name}] + connect_bd_net [get_bd_pins $core/gt_txusrclk2] [get_bd_pins /Network/sfp_rx_clock_${name}] + + set out_inv [create_inverter tx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/usr_tx_reset] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] + + set out_inv [create_inverter rx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/usr_rx_reset] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] + + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_enable] + connect_bd_net [get_bd_pins $core/stat_rx_aligned] [get_bd_pins $core/ctl_tx_enable] + + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_rsfec_enable] + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_rsfec_enable_correction] + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_rsfec_enable_indication] + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_tx_rsfec_enable] + + set aligned_inverter [tapasco::ip::create_logic_vector aligned_inverter] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] $aligned_inverter + connect_bd_net [get_bd_pins $core/stat_rx_aligned] [get_bd_pins $aligned_inverter/Op1] + connect_bd_net [get_bd_pins $aligned_inverter/Res] [get_bd_pins $core/ctl_tx_send_rfi] + } + + proc create_inverter {name} { + variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] + return $ret + } + } +} diff --git a/toolflow/vivado/platform/AU280/plugins/sfpplus_10g.tcl b/toolflow/vivado/platform/AU280/plugins/sfpplus_10g.tcl new file mode 100644 index 00000000..a2d2baed --- /dev/null +++ b/toolflow/vivado/platform/AU280/plugins/sfpplus_10g.tcl @@ -0,0 +1,188 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + namespace eval 10g { + + variable available_ports 8 + variable gt_lanes {"X0Y40" "X0Y41" "X0Y42" "X0Y43" "X0Y44" "X0Y45" "X0Y46" "X0Y47"} + variable gt_quad {"Quad_X0Y10" "Quad_X0Y11"} + variable refclk_pins {"T42" "P42"} + + proc num_available_ports {} { + variable available_ports + return $available_ports + } + + proc generate_cores {ports} { + + set num_streams [dict size $ports] + set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" + set constraints_file [open $constraints_fn w+] + + create_network_config_master + + # AXI Interconnect for Configuration + set axi_config [tapasco::ip::create_axi_ic axi_config 1 $num_streams] + + # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core + set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] + set_property -dict [list \ + CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {false} \ + ] $dclk_wiz + + # Reset Generator for dclk reset + set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] + + connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] + connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] + connect_bd_net [get_bd_pins $axi_config/M*_ACLK] [get_bd_pins $dclk_wiz/clk_out1] + connect_bd_net [get_bd_pins $axi_config/M*_ARESETN] [get_bd_pins $dclk_reset/peripheral_aresetn] + + connect_bd_intf_net [get_bd_intf_pins $axi_config/S00_AXI] [get_bd_intf_pins S_NETWORK] + connect_bd_net [get_bd_pins $axi_config/S00_ACLK] [get_bd_pins design_clk] + connect_bd_net [get_bd_pins $axi_config/S00_ARESETN] [get_bd_pins design_interconnect_aresetn] + connect_bd_net [get_bd_pins $axi_config/ACLK] [get_bd_pins design_clk] + connect_bd_net [get_bd_pins $axi_config/ARESETN] [get_bd_pins design_interconnect_aresetn] + + # Cores need constant clock select input + set const_clksel [tapasco::ip::create_constant const_clksel 3 5] + + # Generate SFP+-Cores + # Each core can handle (up to) all four ports of one physical cage + set first_port 0 + for {set i 0} {$i < 2} {incr i} { + set ports_created [generate_core $i $ports $first_port $constraints_file] + incr first_port $ports_created + } + + close $constraints_file + read_xdc $constraints_fn + set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] + } + + # Generate a SFP+-Core to handle the ports of one physical cage + # @param number the number of the physical cage + # @param physical_ports the numbers of all physical_ports which are required in the design + # @param first_port the first free master on the AXI-Lite Config interconnect + # @param constraints_file the file used for constraints + # @return the number of ports created with this core + proc generate_core {number physical_ports first_port constraints_file} { + variable gt_lanes + variable gt_quad + variable refclk_pins + + # Select physical_ports which will be handled by this core + set ports [list] + + for {set i 0} {$i < 4} {incr i} { + set port_number [expr ($number * 4) + $i] + if {[dict exists $physical_ports $port_number]} { + lappend ports $port_number + } + } + + set num_ports [llength $ports] + + # No ports for this core found -> abort + if {$num_ports == 0} { + return 0 + } + + # Create and configure core + set core [tapasco::ip::create_xxv_ethernet ethernet_$number] + + # Create and constrain refclk pin + set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 qsfp${number}_156mhz] + set_property CONFIG.FREQ_HZ 156250000 $gt_refclk + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $number] qsfp${number}_156mhz_clk_p] + + set_property -dict [list \ + CONFIG.LINE_RATE {10} \ + CONFIG.BASE_R_KR {BASE-R} \ + CONFIG.INCLUDE_AXI4_INTERFACE {1} \ + CONFIG.INCLUDE_STATISTICS_COUNTERS {0} \ + CONFIG.GT_REF_CLK_FREQ {156.25} \ + CONFIG.GT_GROUP_SELECT [lindex $gt_quad $number] \ + ] $core + + # Configure GT lanes based on required ports + set lanes [list] + for {set i 0} {$i < $num_ports} {incr i} { + set lane_index [format %01s [expr $i + 1]] + set gt_lane [lindex $gt_lanes [lindex $ports $i]] + lappend lanes CONFIG.LANE${lane_index}_GT_LOC $gt_lane + } + set_property -dict $lanes $core + + # Connect core + connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/gt_ref_clk] + make_bd_intf_pins_external [get_bd_intf_pins $core/gt_serial_port] + + connect_bd_net [get_bd_pins $core/sys_reset] [get_bd_pins dclk_reset/peripheral_reset] + connect_bd_net [get_bd_pins $core/dclk] [get_bd_pins dclk_wiz/clk_out1] + + # Connect ports of core + for {set i 0} {$i < $num_ports} {incr i} { + set name [dict get $physical_ports [lindex $ports $i]] + connect_bd_intf_net [get_bd_intf_pins $core/axis_rx_${i}] [get_bd_intf_pins AXIS_RX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/axis_tx_${i}] [get_bd_intf_pins AXIS_TX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/s_axi_${i}] [get_bd_intf_pins /Network/AXI_Config/M[format %02d [expr $first_port + $i]]_AXI] + connect_bd_net [get_bd_pins $core/s_axi_aclk_${i}] [get_bd_pins dclk_wiz/clk_out1] + connect_bd_net [get_bd_pins $core/s_axi_aresetn_${i}] [get_bd_pins dclk_reset/peripheral_aresetn] + connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins $core/rx_core_clk_${i}] + connect_bd_net [get_bd_pins $core/txoutclksel_in_${i}] [get_bd_pins const_clksel/dout] + connect_bd_net [get_bd_pins $core/rxoutclksel_in_${i}] [get_bd_pins const_clksel/dout] + + connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins /Network/sfp_tx_clock_${name}] + connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins /Network/sfp_rx_clock_${name}] + + set out_inv [create_inverter tx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/user_tx_reset_${i}] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] + + set out_inv [create_inverter rx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/user_rx_reset_${i}] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] + } + return $num_ports + } + + proc create_inverter {name} { + variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] + return $ret + } + + # Create AXI connection to Host interconnect for network configuration interfaces + proc create_network_config_master {} { + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_NETWORK + set m_si [create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 /host/M_NETWORK] + set num_mi_old [get_property CONFIG.NUM_MI [get_bd_cells /host/out_ic]] + set num_mi [expr "$num_mi_old + 1"] + set_property -dict [list CONFIG.NUM_MI $num_mi] [get_bd_cells /host/out_ic] + connect_bd_intf_net $m_si [get_bd_intf_pins /host/out_ic/[format "M%02d_AXI" $num_mi_old]] + } + } +} \ No newline at end of file diff --git a/toolflow/vivado/platform/AU280/plugins/sfpplus_aurora.tcl b/toolflow/vivado/platform/AU280/plugins/sfpplus_aurora.tcl new file mode 100644 index 00000000..a25b1c12 --- /dev/null +++ b/toolflow/vivado/platform/AU280/plugins/sfpplus_aurora.tcl @@ -0,0 +1,145 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + namespace eval Aurora { + + variable available_ports 2 + variable start_quad {"Quad_X0Y10" "Quad_X0Y11"} + variable start_lane {"X0Y40" "X0Y44"} + variable refclk_pins {"R40" "M42"} + variable refclk_en_n_pins {"H32" "H30"} + variable refclk_sel_pins {"G32" "G33"} + + proc num_available_ports {} { + variable available_ports + return $available_ports + } + + proc generate_cores {ports} { + + set num_streams [dict size $ports] + + puts "Generating $num_streams SFPPLUS cores" + set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" + set constraints_file [open $constraints_fn w+] + + # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core + set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] + set_property -dict [list CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {false} \ + ] $dclk_wiz + + # Reset Generator for dclk reset + set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] + + connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] + connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] + + set first_port 0 + foreach port [dict keys $ports] { + set name [dict get $ports $port] + generate_core $port $name $first_port $constraints_file + incr first_port 1 + } + + close $constraints_file + read_xdc $constraints_fn + set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] + } + + # Generate a SFP+-Core to handle the ports of one physical cage + # @param physical_port the number of the physical cage + # @param name name of the port + # @param first_port the first free master on the AXI-Lite Config interconnect + # @param constraints_file the file used for constraints + proc generate_core {physical_port name first_port constraints_file} { + variable start_quad + variable start_lane + variable refclk_pins + variable refclk_en_n_pins + variable refclk_sel_pins + + set const_zero [tapasco::ip::create_constant const_zero 1 0] + set const_one [tapasco::ip::create_constant const_one 1 1] + + # Create and constrain refclk pin + set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 qsfp${physical_port}_161mhz] + set_property CONFIG.FREQ_HZ 161132813 $gt_refclk + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $physical_port] qsfp${physical_port}_161mhz_clk_p] + + # Enable refclock + set refclk_en_n [create_bd_port -dir O reclk_en_n_$physical_port] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_en_n_pins $physical_port] reclk_en_n_$physical_port] + puts $constraints_file [format {set_property IOSTANDARD LVCMOS18 [get_ports %s]} reclk_en_n_$physical_port] + connect_bd_net [get_bd_pins $const_zero/dout] $refclk_en_n + + # Select refclock frequency (0 = 156.25 MHz, 1 = 161.132812 MHz) + set refclk_sel [create_bd_port -dir O reclk_sel_$physical_port] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_sel_pins $physical_port] reclk_sel_$physical_port] + puts $constraints_file [format {set_property IOSTANDARD LVCMOS18 [get_ports %s]} reclk_sel_$physical_port] + connect_bd_net [get_bd_pins $const_one/dout] $refclk_sel + + # Create and configure core + set core [tapasco::ip::create_aurora aurora_$physical_port] + + set_property -dict [list \ + CONFIG.C_AURORA_LANES {4} \ + CONFIG.C_LINE_RATE {25.78125} \ + CONFIG.C_USE_BYTESWAP {true} \ + CONFIG.C_REFCLK_FREQUENCY {161.1328125} \ + CONFIG.C_INIT_CLK {100} \ + CONFIG.SupportLevel {1} \ + CONFIG.RX_EQ_MODE {LPM} \ + CONFIG.C_UCOLUMN_USED {left} \ + CONFIG.C_START_QUAD [lindex $start_quad $physical_port] \ + CONFIG.C_START_LANE [lindex $start_lane $physical_port] \ + ] $core + + connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/GT_DIFF_REFCLK1] + connect_bd_net [get_bd_pins $core/reset_pb] [get_bd_pins dclk_reset/peripheral_reset] + connect_bd_net [get_bd_pins $core/pma_init] [get_bd_pins dclk_reset/peripheral_reset] + make_bd_intf_pins_external [get_bd_intf_pins $core/GT_SERIAL_RX] + make_bd_intf_pins_external [get_bd_intf_pins $core/GT_SERIAL_TX] + connect_bd_net [get_bd_pins $core/init_clk] [get_bd_pins dclk_wiz/clk_out1] + + # Connect core + connect_bd_intf_net [get_bd_intf_pins $core/USER_DATA_M_AXIS_RX] [get_bd_intf_pins AXIS_RX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/USER_DATA_S_AXIS_TX] [get_bd_intf_pins AXIS_TX_${name}] + + connect_bd_net [get_bd_pins $core/user_clk_out] [get_bd_pins /Network/sfp_tx_clock_${name}] + connect_bd_net [get_bd_pins $core/user_clk_out] [get_bd_pins /Network/sfp_rx_clock_${name}] + + set out_inv [create_inverter sys_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/sys_reset_out] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] + connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] + } + + proc create_inverter {name} { + variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] + return $ret + } + } +} diff --git a/toolflow/vivado/platform/common/addressmap.tcl b/toolflow/vivado/platform/common/addressmap.tcl index b1de01b1..4d64f0d0 100644 --- a/toolflow/vivado/platform/common/addressmap.tcl +++ b/toolflow/vivado/platform/common/addressmap.tcl @@ -163,6 +163,12 @@ namespace eval addressmap { puts " space: $space" puts " seg: $seg" if {[expr "(1 << 64) == $range"]} { set range "16E" } + if {[get_property NAME $seg] == "DmiDebugMem"} { + puts " Found Riscv Debug Memory" + set pe_id [scan [regsub {.*target_ip_.*([0-9][0-9][0-9])} $seg {\1}] %d] + ::tapasco::ip::add_debug_to_pe $pe_id "RiscvDebug" \ + [expr $offset - [::platform::get_pe_base_address]] $range + } create_bd_addr_seg \ -offset $offset \ -range $range \ diff --git a/toolflow/vivado/platform/common/plugins/sfpplus.tcl b/toolflow/vivado/platform/common/plugins/sfpplus.tcl index 9b372600..3ef3091d 100644 --- a/toolflow/vivado/platform/common/plugins/sfpplus.tcl +++ b/toolflow/vivado/platform/common/plugins/sfpplus.tcl @@ -43,7 +43,7 @@ if {[tapasco::is_feature_enabled "SFPPLUS"]} { sfpplus::create_network_pins $port_names # START platform specific puts "Creating Network Interfaces for Ports: $port_names" - sfpplus::generate_cores $physical_ports + sfpplus::generate_cores [sfpplus::parse_mode] $physical_ports # END platform specific sfpplus::connect_ports $ports @@ -57,7 +57,7 @@ namespace eval sfpplus { ###### START PLATFORM SPECIFIC ###### # To add SFP+-Support for a new platform, create a new plugin file for the platform. - # In the plugin file you need to source this file and overwrite these three functions. + # In the plugin file you need to source this file and overwrite these four functions. # Overwrite this function with "return true" to enable SPF+ for a new platform # @return whether SFP+ is supported on this platform @@ -66,10 +66,15 @@ namespace eval sfpplus { } # @return the number of physical ports available on this platform - proc num_available_ports {} { + proc num_available_ports {mode} { return 0 } + # @return a list of the available modes for this platform. the first item is the default mode + proc get_available_modes {} { + return {} + } + # Generate the required platform specific IP to use the SFP+Ports. # The following pins must be connected appropriately for each port with name port_name: # - AXIS_RX_port_name: the AXI Stream for the recieved packets of the port @@ -79,7 +84,7 @@ namespace eval sfpplus { # - sfp_rx_resetn_port_name: the reset for the recieving stream # - sfp_tx_resetn_port_name: the reset for the sending stream # @param physical_ports a dictionary mapping physical ports to the port_name. See Physical Port configuration at the top of this file - proc generate_cores {physical_ports} { + proc generate_cores {mode physical_ports} { } @@ -88,6 +93,18 @@ namespace eval sfpplus { ###### START PARSE CONFIGURATION ###### + # Retrieves the configured mode from the JSON configuration + # @return the configured mode; if no mode is given the default for this platform + proc parse_mode {} { + variable config [tapasco::get_feature "SFPPLUS"] + dict with config { + if {![info exists mode]} { + set mode [lindex [get_available_modes] 0] + } + return $mode + } + } + # Parses the JSON configuration # @param true if currently in the phase of validating the configuration # @return a dictionary containing the parsed configuration. See Internal configuration format at the top of this file @@ -167,7 +184,7 @@ namespace eval sfpplus { if {$validation} { dict set available_PEs $ip [lrepeat $count $ip] } else { - dict set available_PEs $ip [get_bd_cells /arch/target_ip_[format %02d $comp_index]_*] + dict set available_PEs $ip [get_bd_cells -filter "NAME =~ *target_ip_[format %02d $comp_index]_* && TYPE == ip" -of_objects [get_bd_cells /arch]] } } } @@ -202,7 +219,7 @@ namespace eval sfpplus { } set ports [parse_configuration true] set num_ports [dict size $ports] - set available_ports [num_available_ports] + set available_ports [num_available_ports [parse_mode]] if { $num_ports > $available_ports} { puts "Invalid SFP+ Configuration: Too many SFP-Ports specified (Max: $available_ports)" exit @@ -458,7 +475,7 @@ namespace eval sfpplus { current_bd_instance $transmitter_cell # Create Interconnect for transmitter synchronization set sync_ic_out [tapasco::ip::create_axis_ic transmitter_sync 1 1] - set_property -dict [list CONFIG.S00_FIFO_DEPTH {2048} CONFIG.M00_FIFO_DEPTH {2048} CONFIG.S00_FIFO_MODE {0} CONFIG.M00_FIFO_MODE {1}] $sync_ic_out + set_property -dict [list CONFIG.ARB_ON_TLAST {1} CONFIG.M00_FIFO_DEPTH {4096} CONFIG.S00_FIFO_DEPTH {4096} CONFIG.S00_FIFO_MODE {1} CONFIG.M00_FIFO_MODE {1}] $sync_ic_out connect_bd_net [get_bd_pins design_clk] [get_bd_pins $sync_ic_out/ACLK] [get_bd_pins $sync_ic_out/S*_ACLK] connect_bd_net [get_bd_pins design_interconnect_aresetn] [get_bd_pins $sync_ic_out/ARESETN] connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $sync_ic_out/S*_ARESETN] diff --git a/toolflow/vivado/platform/common/plugins/system_cache.tcl b/toolflow/vivado/platform/common/plugins/system_cache.tcl index 6f121f23..044e2e1b 100644 --- a/toolflow/vivado/platform/common/plugins/system_cache.tcl +++ b/toolflow/vivado/platform/common/plugins/system_cache.tcl @@ -22,49 +22,52 @@ namespace eval system_cache { proc create_system_cache {} { if {[tapasco::is_feature_enabled "Cache"]} { set instance [current_bd_instance] - current_bd_instance /memory set cf [tapasco::get_feature "Cache"] puts "Platform configured w/L2 Cache, implementing ..." - set cache [tapasco::ip::create_axi_cache "cache_l2" 1 \ - [tapasco::get_feature_option "Cache" "size" 32768] \ - [tapasco::get_feature_option "Cache" "associativity" 2]] - # set slave port width to 512bit, otherwise uses (not working) width conversion in SmartConnect - set_property CONFIG.C_S0_AXI_GEN_DATA_WIDTH {512} $cache - if {[tapasco::get_feature_option "Cache" "force_allocate_read"]} { - # force caching for master (otherwise relies on axi cache signals) - puts " Force allocate read" - set_property CONFIG.C_S0_AXI_GEN_FORCE_READ_ALLOCATE 1 $cache - set_property CONFIG.C_S0_AXI_GEN_FORCE_READ_BUFFER 1 $cache - } - if {[tapasco::get_feature_option "Cache" "force_allocate_write"]} { - puts " Force allocate write" - set_property CONFIG.C_S0_AXI_GEN_FORCE_WRITE_ALLOCATE 1 $cache - set_property CONFIG.C_S0_AXI_GEN_FORCE_WRITE_BUFFER 1 $cache - } + set i 0 + foreach {platform_port memory_port subsystem clock reset} [get_mem_connections] { + puts " Inserting cache between $platform_port and $memory_port in subsystem $subsystem" + current_bd_instance $subsystem + set cache [tapasco::ip::create_axi_cache "cache_l2_$i" 1 \ + [tapasco::get_feature_option "Cache" "size" 32768] \ + [tapasco::get_feature_option "Cache" "associativity" 2]] + if {[get_property CONFIG.DATA_WIDTH $platform_port] > 32} { + # set slave port width to 512bit, otherwise uses (not working) width conversion in SmartConnect + set_property CONFIG.C_S0_AXI_GEN_DATA_WIDTH [get_property CONFIG.DATA_WIDTH $platform_port] $cache + } + if {[tapasco::get_feature_option "Cache" "force_allocate_read"]} { + # force caching for master (otherwise relies on axi cache signals) + puts " Force allocate read" + set_property CONFIG.C_S0_AXI_GEN_FORCE_READ_ALLOCATE 1 $cache + set_property CONFIG.C_S0_AXI_GEN_FORCE_READ_BUFFER 1 $cache + } + if {[tapasco::get_feature_option "Cache" "force_allocate_write"]} { + puts " Force allocate write" + set_property CONFIG.C_S0_AXI_GEN_FORCE_WRITE_ALLOCATE 1 $cache + set_property CONFIG.C_S0_AXI_GEN_FORCE_WRITE_BUFFER 1 $cache + } - # remove existing connection - delete_bd_objs [get_bd_intf_nets -of_objects [get_memory_port]] - # connect mig_ic master to cache_l2 - connect_bd_intf_net [get_platform_port] [get_bd_intf_pins $cache/S0_AXI_GEN] - # connect cache_l2 to MIG - connect_bd_intf_net [get_bd_intf_pins $cache/M0_AXI] [get_memory_port] - - # connect clocks and reset - connect_bd_net [tapasco::subsystem::get_port "mem" "clk"] [get_bd_pins $cache/ACLK] - connect_bd_net [tapasco::subsystem::get_port "mem" "rst" "peripheral" "resetn"] [get_bd_pins $cache/ARESETN] + # remove existing connection + delete_bd_objs [get_bd_intf_nets -of_objects $memory_port] + # connect mig_ic master to cache_l2 + connect_bd_intf_net $platform_port [get_bd_intf_pins $cache/S0_AXI_GEN] + # connect cache_l2 to MIG + connect_bd_intf_net [get_bd_intf_pins $cache/M0_AXI] $memory_port + # connect clocks and reset + connect_bd_net $clock [get_bd_pins $cache/ACLK] + connect_bd_net $reset [get_bd_pins $cache/ARESETN] + incr i + } current_bd_instance $instance } return {} } - proc get_memory_port {} { - error "Cache feature not implemented for this platform" - } - - proc get_platform_port {} { + proc get_mem_connections {} { error "Cache feature not implemented for this platform" } } tapasco::register_plugin "platform::system_cache::create_system_cache" "post-platform" + diff --git a/toolflow/vivado/platform/netfpga_sume/plugins/sfpplus.tcl b/toolflow/vivado/platform/netfpga_sume/plugins/sfpplus.tcl index c03afa41..4a124a93 100644 --- a/toolflow/vivado/platform/netfpga_sume/plugins/sfpplus.tcl +++ b/toolflow/vivado/platform/netfpga_sume/plugins/sfpplus.tcl @@ -32,13 +32,17 @@ namespace eval sfpplus { variable signal_detect_pins {"N18" "L19" "J37" "H36"} variable locations {"GTHE2_CHANNEL_X1Y39" "GTHE2_CHANNEL_X1Y38" "GTHE2_CHANNEL_X1Y37" "GTHE2_CHANNEL_X1Y36"} - proc num_available_ports {} { + proc num_available_ports {mode} { variable available_ports return $available_ports } + proc get_available_modes {} { + return {"10G"} + } + - proc generate_cores {ports} { + proc generate_cores {mode ports} { set num_streams [dict size $ports] diff --git a/toolflow/vivado/platform/pcie/plugins/system_cache.tcl b/toolflow/vivado/platform/pcie/plugins/system_cache.tcl index 686055ab..00496780 100644 --- a/toolflow/vivado/platform/pcie/plugins/system_cache.tcl +++ b/toolflow/vivado/platform/pcie/plugins/system_cache.tcl @@ -18,11 +18,14 @@ # namespace eval system_cache { - proc get_platform_port {} { - return [get_bd_intf_pins mig_ic/M00_AXI] - } - proc get_memory_port {} { - return [get_bd_intf_pins -regexp mig/(C0_DDR4_)?S_AXI] + proc get_mem_connections {} { + set subsystem "/memory" + set instance [current_bd_instance] + current_bd_instance $subsystem + set clock [tapasco::subsystem::get_port "mem" "clk"] + set reset [tapasco::subsystem::get_port "mem" "rst" "peripheral" "resetn"] + current_bd_instance $instance + return [list [get_bd_intf_pins /memory/mig_ic/M00_AXI] [get_bd_intf_pins -regexp /memory/mig/(C0_DDR4_)?S_AXI] $subsystem $clock $reset] } } diff --git a/toolflow/vivado/platform/vc709/plugins/sfpplus.tcl b/toolflow/vivado/platform/vc709/plugins/sfpplus.tcl index 5dac8872..adeb04ff 100644 --- a/toolflow/vivado/platform/vc709/plugins/sfpplus.tcl +++ b/toolflow/vivado/platform/vc709/plugins/sfpplus.tcl @@ -55,12 +55,16 @@ namespace eval sfpplus { variable iic_rst {"AY42" "16" "SLOW" "LVCMOS18"} variable si5324_rst {"AT36" "16" "SLOW" "LVCMOS18"} - proc num_available_ports {} { + proc num_available_ports {mode} { variable available_ports return $available_ports } - proc generate_cores {ports} { + proc get_available_modes {} { + return {"10G"} + } + + proc generate_cores {mode ports} { variable refclk_pins set num_streams [dict size $ports] diff --git a/toolflow/vivado/platform/xupvvh/M386AAK40B40-CWD6Y.csv b/toolflow/vivado/platform/xupvvh/M386AAK40B40-CWD6Y.csv new file mode 100644 index 00000000..a119bcb4 --- /dev/null +++ b/toolflow/vivado/platform/xupvvh/M386AAK40B40-CWD6Y.csv @@ -0,0 +1,2 @@ +Part type,Part name,Rank,StackHeight,CA Mirror,Data mask,Address width,Row width,Column width,Bank width,Bank group width,CS width,CKE width,ODT width,CK width,Memory speed grade,Memory density,Component density,Memory device width,Memory component width,Data bits per strobe,IO Voltages,Data widths,Min period,Max period,tCKE,tFAW,tFAW_dlr,tMRD,tRAS,tRCD,tREFI,tRFC,tRFC_dlr,tRP,tRRD_S,tRRD_L,tRRD_dlr,tRTP,tWR,tWTR_S,tWTR_L,tXPR,tZQCS,tZQINIT,tCCD_3ds,cas latency,cas write latency,burst length,RTT (nominal) - ODT +LRDIMMs,M386AAK40B40-CWD6Y,2,4,1,0,18,17,10,2,2,2,2,2,1,3DS,128GB,8Gb,72,4,4,1.2V,72,833,1600,5000 ps,13000 ps,16 tck,8 tck,32000 ps,15000 ps,7800000 ps,350000 ps,120000 ps,15000 ps,3300 ps,4900 ps,4 tck,7500 ps,15000 ps,2500 ps,7500 ps,360 ns,128 tck,1024 tck,4 tck,20,16,8,RZQ/6 diff --git a/toolflow/vivado/platform/xupvvh/MTA18ADF2G72PZ-2G3.csv b/toolflow/vivado/platform/xupvvh/MTA18ADF2G72PZ-2G3.csv deleted file mode 100644 index f5027b28..00000000 --- a/toolflow/vivado/platform/xupvvh/MTA18ADF2G72PZ-2G3.csv +++ /dev/null @@ -1,2 +0,0 @@ -Part type,Part name,Rank,StackHeight,CA Mirror,Data mask,Address width,Row width,Column width,Bank width,Bank group width,CS width,CKE width,ODT width,CK width,Memory speed grade,Memory density,Component density,Memory device width,Memory component width,Data bits per strobe,IO Voltages,Data widths,Min period,Max period,tCKE,tFAW,tMRD,tRAS,tRCD,tREFI,tRFC,tRP,tRRD_S,tRRD_L,tRTP,tWR,tWTR_S,tWTR_L,tXPR,tZQCS,tZQINIT,cas latency,cas write latency,burst length,RTT (nominal) - ODT -RDIMMs,MTA18ADF2G72PZ-2G3,1,1,0,0,17,17,10,2,2,1,1,1,1,2G3,16GB,8Gb,72,4,4,1.2V,72,833,1600,5000 ps,13000 ps,8 tck,32000 ps,13320 ps,7800000 ps,350000 ps,13320 ps,3300 ps,4900 ps,7500 ps,15000 ps,2500 ps,7500 ps,360 ns,128 tck,1024 tck,18,16,8,RZQ/6 diff --git a/toolflow/vivado/platform/xupvvh/board.xdc b/toolflow/vivado/platform/xupvvh/board.xdc index 29408222..a0c92b3d 100644 --- a/toolflow/vivado/platform/xupvvh/board.xdc +++ b/toolflow/vivado/platform/xupvvh/board.xdc @@ -49,3 +49,7 @@ create_pblock pblock_axi_pcie resize_pblock pblock_axi_pcie -add SLR0 set_property IS_SOFT TRUE [get_pblocks pblock_axi_pcie] add_cells_to_pblock pblock_axi_pcie [get_cells [list system_i/host/axi_pcie3_0]] + + + +set_false_path -from [get_pins -hierarchical -filter { NAME =~ "*design_rst_gen*" && REF_PIN_NAME =~ "C" }] -to [get_pins -hierarchical -filter { NAME =~ "*network/dclk_wiz*" }] diff --git a/toolflow/vivado/platform/xupvvh/ddr4.xdc b/toolflow/vivado/platform/xupvvh/ddr4.xdc index aecf4f23..ca6ebb2b 100644 --- a/toolflow/vivado/platform/xupvvh/ddr4.xdc +++ b/toolflow/vivado/platform/xupvvh/ddr4.xdc @@ -42,7 +42,7 @@ set_property PACKAGE_PIN B35 [get_ports "C0_DDR4_0_adr[13]"] set_property PACKAGE_PIN A36 [get_ports "C0_DDR4_0_adr[14]"] set_property PACKAGE_PIN A34 [get_ports "C0_DDR4_0_adr[15]"] set_property PACKAGE_PIN A35 [get_ports "C0_DDR4_0_adr[16]"] -#set_property PACKAGE_PIN C38 [get_ports "C0_DDR4_0_adr[17]"] +set_property PACKAGE_PIN C38 [get_ports "C0_DDR4_0_adr[17]"] set_property PACKAGE_PIN F34 [get_ports "C0_DDR4_0_adr[2]"] set_property PACKAGE_PIN E34 [get_ports "C0_DDR4_0_adr[3]"] set_property PACKAGE_PIN E36 [get_ports "C0_DDR4_0_adr[4]"] @@ -56,17 +56,17 @@ set_property PACKAGE_PIN F35 [get_ports "C0_DDR4_0_ba[0]"] set_property PACKAGE_PIN F36 [get_ports "C0_DDR4_0_ba[1]"] set_property PACKAGE_PIN E37 [get_ports "C0_DDR4_0_bg[0]"] set_property PACKAGE_PIN E38 [get_ports "C0_DDR4_0_bg[1]"] -#set_property PACKAGE_PIN H39 [get_ports "C0_DDR4_0_c[0]"] -#set_property PACKAGE_PIN H37 [get_ports "C0_DDR4_0_c[1]"] +set_property PACKAGE_PIN H39 [get_ports "C0_DDR4_0_c_id[0]"] +set_property PACKAGE_PIN H37 [get_ports "C0_DDR4_0_c_id[1]"] #set_property PACKAGE_PIN A38 [get_ports "C0_DDR4_0_c[2]"] #set_property PACKAGE_PIN C33 [get_ports "C0_DDR4_0_c[3]"] #set_property PACKAGE_PIN B43 [get_ports "C0_DDR4_0_c[4]"] set_property PACKAGE_PIN D39 [get_ports "C0_DDR4_0_ck_c"] set_property PACKAGE_PIN H35 [get_ports "C0_DDR4_0_cke[0]"] -#set_property PACKAGE_PIN G38 [get_ports "C0_DDR4_0_cke[1]"] +set_property PACKAGE_PIN G38 [get_ports "C0_DDR4_0_cke[1]"] set_property PACKAGE_PIN E39 [get_ports "C0_DDR4_0_ck_t"] set_property PACKAGE_PIN H38 [get_ports "C0_DDR4_0_cs_n[0]"] -#set_property PACKAGE_PIN H34 [get_ports "C0_DDR4_0_cs_n[1]"] +set_property PACKAGE_PIN H34 [get_ports "C0_DDR4_0_cs_n[1]"] set_property PACKAGE_PIN A28 [get_ports "C0_DDR4_0_dq[0]"] set_property PACKAGE_PIN B28 [get_ports "C0_DDR4_0_dq[1]"] set_property PACKAGE_PIN C32 [get_ports "C0_DDR4_0_dq[10]"] @@ -176,7 +176,7 @@ set_property PACKAGE_PIN L33 [get_ports "C0_DDR4_0_dqs_t[7]"] set_property PACKAGE_PIN B40 [get_ports "C0_DDR4_0_dqs_t[8]"] set_property PACKAGE_PIN F40 [get_ports "C0_DDR4_0_dqs_t[9]"] set_property PACKAGE_PIN F39 [get_ports "C0_DDR4_0_odt[0]"] -#set_property PACKAGE_PIN G37 [get_ports "C0_DDR4_0_odt[1]"] +set_property PACKAGE_PIN G37 [get_ports "C0_DDR4_0_odt[1]"] set_property PACKAGE_PIN F38 [get_ports "C0_DDR4_0_par"] set_property PACKAGE_PIN J39 [get_ports "C0_DDR4_0_reset_n"] diff --git a/toolflow/vivado/platform/xupvvh/plugins/hbm.tcl b/toolflow/vivado/platform/xupvvh/plugins/hbm.tcl index 0f552ae7..07326dd2 100644 --- a/toolflow/vivado/platform/xupvvh/plugins/hbm.tcl +++ b/toolflow/vivado/platform/xupvvh/plugins/hbm.tcl @@ -308,9 +308,14 @@ namespace eval hbm { set masters [ldiff [lsort -dictionary [tapasco::get_aximm_interfaces [get_bd_cells /arch/target_ip_*]]] $hbmInterfaces] set arch_mem_ics [arch::arch_create_mem_interconnects $mgroups [llength $masters]] arch::arch_connect_mem $arch_mem_ics $masters - catch {arch::arch_connect_clocks} issue - catch {arch::arch_connect_resets} issue - + + connect_bd_net [tapasco::subsystem::get_port "design" "clk"] \ + [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == clk && DIR == I"] + connect_bd_net -quiet [tapasco::subsystem::get_port "design" "rst" "interconnect"] \ + [get_bd_pins -of_objects [get_bd_cells] -filter "TYPE == rst && NAME =~ *interconnect_aresetn && DIR == I"] + connect_bd_net [tapasco::subsystem::get_port "design" "rst" "peripheral" "resetn"] \ + [get_bd_pins -of_objects [get_bd_cells -of_objects [current_bd_instance .]] -filter "TYPE == rst && NAME =~ *peripheral_aresetn && DIR == I"] + # apply constraints for one or both stacks current_bd_instance /hbm set constraints_l "$::env(TAPASCO_HOME_TCL)/platform/xupvvh/plugins/hbm_l.xdc" diff --git a/toolflow/vivado/platform/xupvvh/plugins/sfpplus.tcl b/toolflow/vivado/platform/xupvvh/plugins/sfpplus.tcl index 57449c7d..af4574f7 100644 --- a/toolflow/vivado/platform/xupvvh/plugins/sfpplus.tcl +++ b/toolflow/vivado/platform/xupvvh/plugins/sfpplus.tcl @@ -23,176 +23,44 @@ namespace eval sfpplus { return true } - variable available_ports 16 - variable refclk_pins {"P13" "V13" "AD13" "AJ15"} - variable gt_quads {"Quad_X1Y11" "Quad_X1Y9" "Quad_X1Y6" "Quad_X1Y4"} - variable gt_lanes {"X1Y44" "X1Y45" "X1Y46" "X1Y47" "X1Y36" "X1Y37" "X1Y38" "X1Y39" "X1Y24" "X1Y25" "X1Y26" "X1Y27" "X1Y16" "X1Y17" "X1Y18" "X1Y19"} - - proc num_available_ports {} { - variable available_ports - return $available_ports + proc get_available_modes {} { + return {"10G" "100G" "Aurora"} } - proc generate_cores {ports} { - - set num_streams [dict size $ports] - - create_network_config_master - - puts "Generating $num_streams SFPPLUS cores" - set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" - set constraints_file [open $constraints_fn w+] - - # AXI Interconnect for Configuration - set axi_config [tapasco::ip::create_axi_ic axi_config 1 $num_streams] - - # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core - set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] - set_property -dict [list CONFIG.USE_SAFE_CLOCK_STARTUP {true} CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 CONFIG.USE_LOCKED {false} CONFIG.USE_RESET {false}] $dclk_wiz - - # Reset Generator for dclk reset - set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] - - connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] - connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] - connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] - connect_bd_net [get_bd_pins $axi_config/M*_ACLK] [get_bd_pins $dclk_wiz/clk_out1] - connect_bd_net [get_bd_pins $axi_config/M*_ARESETN] [get_bd_pins $dclk_reset/peripheral_aresetn] - - connect_bd_intf_net [get_bd_intf_pins $axi_config/S00_AXI] [get_bd_intf_pins S_NETWORK] - connect_bd_net [get_bd_pins $axi_config/S00_ACLK] [get_bd_pins design_clk] - connect_bd_net [get_bd_pins $axi_config/S00_ARESETN] [get_bd_pins design_interconnect_aresetn] - connect_bd_net [get_bd_pins $axi_config/ACLK] [get_bd_pins design_clk] - connect_bd_net [get_bd_pins $axi_config/ARESETN] [get_bd_pins design_interconnect_aresetn] - - # Cores need constant clock select input - set const_clksel [tapasco::ip::create_constant const_clksel 3 5] - - # Generate SFP+-Cores - # Each core can handle (up to) all four ports of one physical cage - set first_port 0 - for {set i 0} {$i < 4} {incr i} { - set ports_created [generate_core $i $ports $first_port $constraints_file] - incr first_port $ports_created - } - - close $constraints_file - read_xdc $constraints_fn - set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] - } - - # Generate a SFP+-Core to handle the ports of one physical cage - # @param number the number of the physical cage - # @param physical_ports the numbers of all physical_ports which are required in the design - # @param first_port the first free master on the AXI-Lite Config interconnect - # @param constraints_file git stthe file used for constraints - # @return the number of ports created with this core - proc generate_core {number physical_ports first_port constraints_file} { - variable refclk_pins - variable gt_quads - variable gt_lanes - - # Select physical_ports which will be handled by this core - set ports [list] - - for {set i 0} {$i < 4} {incr i} { - set port_number [expr ($number * 4) + $i] - if {[dict exists $physical_ports $port_number]} { - lappend ports $port_number - } + proc num_available_ports {mode} { + if {$mode == "10G"} { + return [10g::num_available_ports] } - - set num_ports [llength $ports] - - # No ports for this core found -> abort - if {$num_ports == 0} { - return 0 + if {$mode == "100G"} { + return [100g::num_available_ports] } - - # Create and constrain refclk pin - set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 gt_refclk_$number] - set_property CONFIG.FREQ_HZ 322265625 $gt_refclk - puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $number] gt_refclk_${number}_clk_p] - - - # Create and configure core - set core [tapasco::ip::create_xxv_ethernet ethernet_$number] - - set_property -dict [list \ - CONFIG.NUM_OF_CORES $num_ports \ - CONFIG.LINE_RATE {10} \ - CONFIG.BASE_R_KR {BASE-R} \ - CONFIG.INCLUDE_AXI4_INTERFACE {1} \ - CONFIG.INCLUDE_STATISTICS_COUNTERS {0} \ - CONFIG.GT_REF_CLK_FREQ {322.265625} \ - CONFIG.GT_GROUP_SELECT [lindex $gt_quads $number] - ] $core - - # Configure GT lanes based on required ports - set lanes [list] - for {set i 0} {$i < $num_ports} {incr i} { - set lane_index [format %01s [expr $i + 1]] - set gt_lane [lindex $gt_lanes [lindex $ports $i]] - lappend lanes CONFIG.LANE${lane_index}_GT_LOC $gt_lane + if {$mode == "Aurora"} { + return [Aurora::num_available_ports] } - set_property -dict $lanes $core - - connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/gt_ref_clk] - connect_bd_net [get_bd_pins $core/sys_reset] [get_bd_pins dclk_reset/peripheral_reset] - make_bd_intf_pins_external [get_bd_intf_pins $core/gt_rx] - make_bd_intf_pins_external [get_bd_intf_pins $core/gt_tx] - connect_bd_net [get_bd_pins $core/dclk] [get_bd_pins dclk_wiz/clk_out1] - - # Connect core - for {set i 0} {$i < $num_ports} {incr i} { - set name [dict get $physical_ports [lindex $ports $i]] - connect_bd_intf_net [get_bd_intf_pins $core/axis_rx_${i}] [get_bd_intf_pins AXIS_RX_${name}] - connect_bd_intf_net [get_bd_intf_pins $core/axis_tx_${i}] [get_bd_intf_pins AXIS_TX_${name}] - connect_bd_intf_net [get_bd_intf_pins $core/s_axi_${i}] [get_bd_intf_pins /Network/AXI_Config/M[format %02d [expr $first_port + $i]]_AXI] - connect_bd_net [get_bd_pins $core/s_axi_aclk_${i}] [get_bd_pins dclk_wiz/clk_out1] - connect_bd_net [get_bd_pins $core/s_axi_aresetn_${i}] [get_bd_pins dclk_reset/peripheral_aresetn] - connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins $core/rx_core_clk_${i}] - connect_bd_net [get_bd_pins $core/txoutclksel_in_${i}] [get_bd_pins const_clksel/dout] - connect_bd_net [get_bd_pins $core/rxoutclksel_in_${i}] [get_bd_pins const_clksel/dout] - - connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins /Network/sfp_tx_clock_${name}] - connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins /Network/sfp_rx_clock_${name}] - - set out_inv [create_inverter tx_reset_inverter_${name}] - connect_bd_net [get_bd_pins $core/user_tx_reset_${i}] [get_bd_pins $out_inv/Op1] - connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] - - set out_inv [create_inverter rx_reset_inverter_${name}] - connect_bd_net [get_bd_pins $core/user_rx_reset_${i}] [get_bd_pins $out_inv/Op1] - connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] - } - return $num_ports + puts "Invalid SFP+ mode: mode $mode is not supported by this platform. Available modes are: 10G, 100G, Aurora" + exit } - proc create_inverter {name} { - variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] - set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] - return $ret + proc generate_cores {mode ports} { + if {$mode == "10G"} { + 10g::generate_cores $ports + } elseif {$mode == "100G"} { + 100g::generate_cores $ports + } elseif {$mode == "Aurora"} { + Aurora::generate_cores $ports + } else { + puts "Invalid SFP+ mode: mode $mode is not supported by this platform. Available modes are: 10G, 100G, Aurora" + exit } - - # Create AXI connection to Host interconnect for network configuration interfaces - proc create_network_config_master {} { - create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_NETWORK - set m_si [create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 /host/M_NETWORK] - set num_mi_old [get_property CONFIG.NUM_MI [get_bd_cells /host/out_ic]] - set num_mi [expr "$num_mi_old + 1"] - set_property -dict [list CONFIG.NUM_MI $num_mi] [get_bd_cells /host/out_ic] - connect_bd_intf_net $m_si [get_bd_intf_pins /host/out_ic/[format "M%02d_AXI" $num_mi_old]] } - proc addressmap {{args {}}} { - if {[tapasco::is_feature_enabled "SFPPLUS"]} { - set args [lappend args "M_NETWORK" [list 0x2500000 0 0 ""]] - } - return $args - } - +proc addressmap {{args {}}} { + if {[tapasco::is_feature_enabled "SFPPLUS"]} { + set args [lappend args "M_NETWORK" [list 0x2500000 0 0 ""]] + } + return $args +} } diff --git a/toolflow/vivado/platform/xupvvh/plugins/sfpplus_100g.tcl b/toolflow/vivado/platform/xupvvh/plugins/sfpplus_100g.tcl new file mode 100644 index 00000000..2e07abe3 --- /dev/null +++ b/toolflow/vivado/platform/xupvvh/plugins/sfpplus_100g.tcl @@ -0,0 +1,175 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + namespace eval 100g { + + variable available_ports 4 + variable refclk_pins {"P13" "V13" "AD13" "AJ15"} + variable cmac_cores {"CMACE4_X0Y7" "CMACE4_X0Y6" "CMACE4_X0Y4" "CMACE4_X0Y2"} + variable gt_groups {"X1Y44~X1Y47" "X1Y36~X1Y39" "X1Y24~X1Y27" "X1Y16~X1Y19"} + variable fpga_i2c_master "E17" + variable qsfp_ctl_en "C18" + variable qsfp_rst {"A21" "A19" "B16" "C19"} + variable qsfp_lp "B18" + + proc num_available_ports {} { + variable available_ports + return $available_ports + } + + proc generate_cores {ports} { + + set num_streams [dict size $ports] + + puts "Generating $num_streams SFPPLUS cores" + set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" + set constraints_file [open $constraints_fn w+] + + # QSFP Ports + set const_zero [tapasco::ip::create_constant const_zero 1 0] + set const_one [tapasco::ip::create_constant const_one 1 1] + + variable fpga_i2c_master + variable qsfp_ctl_en + variable qsfp_lp + + set port_fpga_i2c_master [create_bd_port -dir O fpga_i2c_master] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports fpga_i2c_master]} $fpga_i2c_master] + puts $constraints_file {set_property IOSTANDARD LVCMOS18 [get_ports fpga_i2c_master]} + connect_bd_net [get_bd_pins $const_zero/dout] $port_fpga_i2c_master + + set port_qsfp_ctl_en [create_bd_port -dir O qsfp_ctl_en] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports qsfp_ctl_en]} $qsfp_ctl_en] + puts $constraints_file {set_property IOSTANDARD LVCMOS18 [get_ports qsfp_ctl_en]} + connect_bd_net [get_bd_pins $const_one/dout] $port_qsfp_ctl_en + + set port_qsfp_lp [create_bd_port -dir O qsfp_lp] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports qsfp_lp]} $qsfp_lp] + puts $constraints_file {set_property IOSTANDARD LVCMOS18 [get_ports qsfp_lp]} + connect_bd_net [get_bd_pins $const_zero/dout] $port_qsfp_lp + + # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core + set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] + set_property -dict [list CONFIG.USE_SAFE_CLOCK_STARTUP {true} CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 CONFIG.USE_LOCKED {false} CONFIG.USE_RESET {false}] $dclk_wiz + + # Reset Generator for dclk reset + set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] + + connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] + connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] + + set first_port 0 + foreach port [dict keys $ports] { + set name [dict get $ports $port] + generate_core $port $name $first_port $constraints_file + incr first_port 1 + } + + close $constraints_file + read_xdc $constraints_fn + set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] + } + + # Generate a SFP+-Core to handle the ports of one physical cage + # @param physical_port the number of the physical cage + # @param name name of the port + # @param first_port the first free master on the AXI-Lite Config interconnect + # @param constraints_file the file used for constraints + proc generate_core {physical_port name first_port constraints_file} { + variable refclk_pins + variable cmac_cores + variable gt_groups + variable qsfp_rst + + set port_qsfp_rst [create_bd_port -dir O qsfp_rst_l_$physical_port] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $qsfp_rst $physical_port] qsfp_rst_l_$physical_port] + puts $constraints_file [format {set_property IOSTANDARD LVCMOS18 [get_ports %s]} qsfp_rst_l_$physical_port] + + # Create and constrain refclk pin + set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 gt_refclk_$physical_port] + set_property CONFIG.FREQ_HZ 322265625 $gt_refclk + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $physical_port] gt_refclk_${physical_port}_clk_p] + + # Create and configure core + set core [tapasco::ip::create_100g_ethernet ethernet_$physical_port] + + set_property -dict [list \ + CONFIG.CMAC_CAUI4_MODE {1} \ + CONFIG.NUM_LANES {4x25} \ + CONFIG.USER_INTERFACE {AXIS} \ + CONFIG.GT_REF_CLK_FREQ {322.265625} \ + CONFIG.TX_FLOW_CONTROL {0} \ + CONFIG.RX_FLOW_CONTROL {0} \ + CONFIG.INCLUDE_RS_FEC {1} \ + CONFIG.ENABLE_AXI_INTERFACE {0} \ + CONFIG.INCLUDE_STATISTICS_COUNTERS {0} \ + CONFIG.RX_MAX_PACKET_LEN {16383} \ + CONFIG.CMAC_CORE_SELECT [lindex $cmac_cores $physical_port] \ + CONFIG.GT_GROUP_SELECT [lindex $gt_groups $physical_port] + ] $core + + connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/gt_ref_clk] + connect_bd_net [get_bd_pins $core/sys_reset] [get_bd_pins dclk_reset/peripheral_reset] + make_bd_intf_pins_external [get_bd_intf_pins $core/gt_rx] + make_bd_intf_pins_external [get_bd_intf_pins $core/gt_tx] + connect_bd_net [get_bd_pins $core/drp_clk] [get_bd_pins dclk_wiz/clk_out1] + connect_bd_net [get_bd_pins $core/init_clk] [get_bd_pins dclk_wiz/clk_out1] + + # Connect core + connect_bd_intf_net [get_bd_intf_pins $core/axis_rx] [get_bd_intf_pins AXIS_RX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/axis_tx] [get_bd_intf_pins AXIS_TX_${name}] + connect_bd_net [get_bd_pins $core/gt_txusrclk2] [get_bd_pins $core/rx_clk] + + connect_bd_net [get_bd_pins $core/gt_txusrclk2] [get_bd_pins /Network/sfp_tx_clock_${name}] + connect_bd_net [get_bd_pins $core/gt_txusrclk2] [get_bd_pins /Network/sfp_rx_clock_${name}] + + set out_inv [create_inverter tx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/usr_tx_reset] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] + + set out_inv [create_inverter rx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/usr_rx_reset] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] + + connect_bd_net [get_bd_pins dclk_reset/peripheral_aresetn] $port_qsfp_rst + + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_enable] + connect_bd_net [get_bd_pins $core/stat_rx_aligned] [get_bd_pins $core/ctl_tx_enable] + + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_rsfec_enable] + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_rsfec_enable_correction] + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_rx_rsfec_enable_indication] + connect_bd_net [get_bd_pins const_one/dout] [get_bd_pins $core/ctl_tx_rsfec_enable] + + set aligned_inverter [tapasco::ip::create_logic_vector aligned_inverter] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] $aligned_inverter + connect_bd_net [get_bd_pins $core/stat_rx_aligned] [get_bd_pins $aligned_inverter/Op1] + connect_bd_net [get_bd_pins $aligned_inverter/Res] [get_bd_pins $core/ctl_tx_send_rfi] + } + + proc create_inverter {name} { + variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] + return $ret + } + } +} \ No newline at end of file diff --git a/toolflow/vivado/platform/xupvvh/plugins/sfpplus_10g.tcl b/toolflow/vivado/platform/xupvvh/plugins/sfpplus_10g.tcl new file mode 100644 index 00000000..50f36efc --- /dev/null +++ b/toolflow/vivado/platform/xupvvh/plugins/sfpplus_10g.tcl @@ -0,0 +1,187 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + namespace eval 10g { + + variable available_ports 16 + variable refclk_pins {"P13" "V13" "AD13" "AJ15"} + variable gt_quads {"Quad_X1Y11" "Quad_X1Y9" "Quad_X1Y6" "Quad_X1Y4"} + variable gt_lanes {"X1Y44" "X1Y45" "X1Y46" "X1Y47" "X1Y36" "X1Y37" "X1Y38" "X1Y39" "X1Y24" "X1Y25" "X1Y26" "X1Y27" "X1Y16" "X1Y17" "X1Y18" "X1Y19"} + + proc num_available_ports {} { + variable available_ports + return $available_ports + } + + proc generate_cores {ports} { + + set num_streams [dict size $ports] + + create_network_config_master + + puts "Generating $num_streams SFPPLUS cores" + set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" + set constraints_file [open $constraints_fn w+] + + # AXI Interconnect for Configuration + set axi_config [tapasco::ip::create_axi_ic axi_config 1 $num_streams] + + # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core + set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] + set_property -dict [list CONFIG.USE_SAFE_CLOCK_STARTUP {true} CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 CONFIG.USE_LOCKED {false} CONFIG.USE_RESET {false}] $dclk_wiz + + # Reset Generator for dclk reset + set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] + + connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] + connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] + connect_bd_net [get_bd_pins $axi_config/M*_ACLK] [get_bd_pins $dclk_wiz/clk_out1] + connect_bd_net [get_bd_pins $axi_config/M*_ARESETN] [get_bd_pins $dclk_reset/peripheral_aresetn] + + connect_bd_intf_net [get_bd_intf_pins $axi_config/S00_AXI] [get_bd_intf_pins S_NETWORK] + connect_bd_net [get_bd_pins $axi_config/S00_ACLK] [get_bd_pins design_clk] + connect_bd_net [get_bd_pins $axi_config/S00_ARESETN] [get_bd_pins design_interconnect_aresetn] + connect_bd_net [get_bd_pins $axi_config/ACLK] [get_bd_pins design_clk] + connect_bd_net [get_bd_pins $axi_config/ARESETN] [get_bd_pins design_interconnect_aresetn] + + # Cores need constant clock select input + set const_clksel [tapasco::ip::create_constant const_clksel 3 5] + + # Generate SFP+-Cores + # Each core can handle (up to) all four ports of one physical cage + set first_port 0 + for {set i 0} {$i < 4} {incr i} { + set ports_created [generate_core $i $ports $first_port $constraints_file] + incr first_port $ports_created + } + + close $constraints_file + read_xdc $constraints_fn + set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] + } + + # Generate a SFP+-Core to handle the ports of one physical cage + # @param number the number of the physical cage + # @param physical_ports the numbers of all physical_ports which are required in the design + # @param first_port the first free master on the AXI-Lite Config interconnect + # @param constraints_file git stthe file used for constraints + # @return the number of ports created with this core + proc generate_core {number physical_ports first_port constraints_file} { + variable refclk_pins + variable gt_quads + variable gt_lanes + + # Select physical_ports which will be handled by this core + set ports [list] + + for {set i 0} {$i < 4} {incr i} { + set port_number [expr ($number * 4) + $i] + if {[dict exists $physical_ports $port_number]} { + lappend ports $port_number + } + } + + set num_ports [llength $ports] + + # No ports for this core found -> abort + if {$num_ports == 0} { + return 0 + } + + # Create and constrain refclk pin + set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 gt_refclk_$number] + set_property CONFIG.FREQ_HZ 322265625 $gt_refclk + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $number] gt_refclk_${number}_clk_p] + + + # Create and configure core + set core [tapasco::ip::create_xxv_ethernet ethernet_$number] + + set_property -dict [list \ + CONFIG.NUM_OF_CORES $num_ports \ + CONFIG.LINE_RATE {10} \ + CONFIG.BASE_R_KR {BASE-R} \ + CONFIG.INCLUDE_AXI4_INTERFACE {1} \ + CONFIG.INCLUDE_STATISTICS_COUNTERS {0} \ + CONFIG.GT_REF_CLK_FREQ {322.265625} \ + CONFIG.GT_GROUP_SELECT [lindex $gt_quads $number] + ] $core + + # Configure GT lanes based on required ports + set lanes [list] + for {set i 0} {$i < $num_ports} {incr i} { + set lane_index [format %01s [expr $i + 1]] + set gt_lane [lindex $gt_lanes [lindex $ports $i]] + lappend lanes CONFIG.LANE${lane_index}_GT_LOC $gt_lane + } + set_property -dict $lanes $core + + connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/gt_ref_clk] + connect_bd_net [get_bd_pins $core/sys_reset] [get_bd_pins dclk_reset/peripheral_reset] + make_bd_intf_pins_external [get_bd_intf_pins $core/gt_rx] + make_bd_intf_pins_external [get_bd_intf_pins $core/gt_tx] + connect_bd_net [get_bd_pins $core/dclk] [get_bd_pins dclk_wiz/clk_out1] + + # Connect core + for {set i 0} {$i < $num_ports} {incr i} { + set name [dict get $physical_ports [lindex $ports $i]] + connect_bd_intf_net [get_bd_intf_pins $core/axis_rx_${i}] [get_bd_intf_pins AXIS_RX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/axis_tx_${i}] [get_bd_intf_pins AXIS_TX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/s_axi_${i}] [get_bd_intf_pins /Network/AXI_Config/M[format %02d [expr $first_port + $i]]_AXI] + connect_bd_net [get_bd_pins $core/s_axi_aclk_${i}] [get_bd_pins dclk_wiz/clk_out1] + connect_bd_net [get_bd_pins $core/s_axi_aresetn_${i}] [get_bd_pins dclk_reset/peripheral_aresetn] + connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins $core/rx_core_clk_${i}] + connect_bd_net [get_bd_pins $core/txoutclksel_in_${i}] [get_bd_pins const_clksel/dout] + connect_bd_net [get_bd_pins $core/rxoutclksel_in_${i}] [get_bd_pins const_clksel/dout] + + connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins /Network/sfp_tx_clock_${name}] + connect_bd_net [get_bd_pins $core/tx_clk_out_${i}] [get_bd_pins /Network/sfp_rx_clock_${name}] + + set out_inv [create_inverter tx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/user_tx_reset_${i}] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] + + set out_inv [create_inverter rx_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/user_rx_reset_${i}] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] + } + return $num_ports + } + + proc create_inverter {name} { + variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] + return $ret + } + + # Create AXI connection to Host interconnect for network configuration interfaces + proc create_network_config_master {} { + create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_NETWORK + set m_si [create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 /host/M_NETWORK] + set num_mi_old [get_property CONFIG.NUM_MI [get_bd_cells /host/out_ic]] + set num_mi [expr "$num_mi_old + 1"] + set_property -dict [list CONFIG.NUM_MI $num_mi] [get_bd_cells /host/out_ic] + connect_bd_intf_net $m_si [get_bd_intf_pins /host/out_ic/[format "M%02d_AXI" $num_mi_old]] + } + + } +} \ No newline at end of file diff --git a/toolflow/vivado/platform/xupvvh/plugins/sfpplus_aurora.tcl b/toolflow/vivado/platform/xupvvh/plugins/sfpplus_aurora.tcl new file mode 100644 index 00000000..13842e4f --- /dev/null +++ b/toolflow/vivado/platform/xupvvh/plugins/sfpplus_aurora.tcl @@ -0,0 +1,156 @@ +# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt. +# +# This file is part of TaPaSCo +# (see https://github.com/esa-tu-darmstadt/tapasco). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +namespace eval sfpplus { + + namespace eval Aurora { + + variable available_ports 4 + variable refclk_pins {"P13" "V13" "AD13" "AJ15"} + variable start_quad {"Quad_X1Y11" "Quad_X1Y9" "Quad_X1Y6" "Quad_X1Y4"} + variable start_lane {"X1Y44" "X1Y36" "X1Y24" "X1Y16"} + variable fpga_i2c_master "E17" + variable qsfp_ctl_en "C18" + variable qsfp_rst {"A21" "A19" "B16" "C19"} + variable qsfp_lp "B18" + + proc num_available_ports {} { + variable available_ports + return $available_ports + } + + proc generate_cores {ports} { + + set num_streams [dict size $ports] + + puts "Generating $num_streams SFPPLUS cores" + set constraints_fn "[get_property DIRECTORY [current_project]]/sfpplus.xdc" + set constraints_file [open $constraints_fn w+] + + # QSFP Ports + set const_zero [tapasco::ip::create_constant const_zero 1 0] + set const_one [tapasco::ip::create_constant const_one 1 1] + + variable fpga_i2c_master + variable qsfp_ctl_en + variable qsfp_lp + + set port_fpga_i2c_master [create_bd_port -dir O fpga_i2c_master] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports fpga_i2c_master]} $fpga_i2c_master] + puts $constraints_file {set_property IOSTANDARD LVCMOS18 [get_ports fpga_i2c_master]} + connect_bd_net [get_bd_pins $const_zero/dout] $port_fpga_i2c_master + + set port_qsfp_ctl_en [create_bd_port -dir O qsfp_ctl_en] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports qsfp_ctl_en]} $qsfp_ctl_en] + puts $constraints_file {set_property IOSTANDARD LVCMOS18 [get_ports qsfp_ctl_en]} + connect_bd_net [get_bd_pins $const_one/dout] $port_qsfp_ctl_en + + set port_qsfp_lp [create_bd_port -dir O qsfp_lp] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports qsfp_lp]} $qsfp_lp] + puts $constraints_file {set_property IOSTANDARD LVCMOS18 [get_ports qsfp_lp]} + connect_bd_net [get_bd_pins $const_zero/dout] $port_qsfp_lp + + # Clocking wizard for creating clock dclk; Used for dclk and AXI-Lite clocks of core + set dclk_wiz [tapasco::ip::create_clk_wiz dclk_wiz] + set_property -dict [list CONFIG.USE_SAFE_CLOCK_STARTUP {true} CONFIG.CLKOUT1_REQUESTED_OUT_FREQ 100 CONFIG.USE_LOCKED {false} CONFIG.USE_RESET {false}] $dclk_wiz + + # Reset Generator for dclk reset + set dclk_reset [tapasco::ip::create_rst_gen dclk_reset] + + connect_bd_net [get_bd_pins $dclk_wiz/clk_out1] [get_bd_pins $dclk_reset/slowest_sync_clk] + connect_bd_net [get_bd_pins design_peripheral_aresetn] [get_bd_pins $dclk_reset/ext_reset_in] + connect_bd_net [get_bd_pins design_clk] [get_bd_pins $dclk_wiz/clk_in1] + + set first_port 0 + foreach port [dict keys $ports] { + set name [dict get $ports $port] + generate_core $port $name $first_port $constraints_file + incr first_port 1 + } + + close $constraints_file + read_xdc $constraints_fn + set_property PROCESSING_ORDER NORMAL [get_files $constraints_fn] + } + + # Generate a SFP+-Core to handle the ports of one physical cage + # @param physical_port the number of the physical cage + # @param name name of the port + # @param first_port the first free master on the AXI-Lite Config interconnect + # @param constraints_file the file used for constraints + proc generate_core {physical_port name first_port constraints_file} { + variable refclk_pins + variable start_quad + variable start_lane + variable qsfp_rst + + set port_qsfp_rst [create_bd_port -dir O qsfp_rst_l_$physical_port] + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $qsfp_rst $physical_port] qsfp_rst_l_$physical_port] + puts $constraints_file [format {set_property IOSTANDARD LVCMOS18 [get_ports %s]} qsfp_rst_l_$physical_port] + + # Create and constrain refclk pin + set gt_refclk [create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 gt_refclk_$physical_port] + set_property CONFIG.FREQ_HZ 322265625 $gt_refclk + puts $constraints_file [format {set_property PACKAGE_PIN %s [get_ports %s]} [lindex $refclk_pins $physical_port] gt_refclk_${physical_port}_clk_p] + + # Create and configure core + set core [tapasco::ip::create_aurora aurora_$physical_port] + + set_property -dict [list \ + CONFIG.C_AURORA_LANES {4} \ + CONFIG.C_LINE_RATE {25.78125} \ + CONFIG.C_USE_BYTESWAP {true} \ + CONFIG.C_REFCLK_FREQUENCY {322.265625} \ + CONFIG.C_INIT_CLK {100} \ + CONFIG.SupportLevel {1} \ + CONFIG.RX_EQ_MODE {LPM} \ + CONFIG.C_START_QUAD [lindex $start_quad $physical_port] \ + CONFIG.C_START_LANE [lindex $start_lane $physical_port] \ + ] $core + + # Connect core + connect_bd_intf_net $gt_refclk [get_bd_intf_pins $core/GT_DIFF_REFCLK1] + + connect_bd_net [get_bd_pins $core/reset_pb] [get_bd_pins dclk_reset/peripheral_reset] + connect_bd_net [get_bd_pins $core/pma_init] [get_bd_pins dclk_reset/peripheral_reset] + connect_bd_net [get_bd_pins dclk_reset/peripheral_aresetn] $port_qsfp_rst + + make_bd_intf_pins_external [get_bd_intf_pins $core/GT_SERIAL_RX] + make_bd_intf_pins_external [get_bd_intf_pins $core/GT_SERIAL_TX] + connect_bd_net [get_bd_pins $core/init_clk] [get_bd_pins dclk_wiz/clk_out1] + + connect_bd_intf_net [get_bd_intf_pins $core/USER_DATA_M_AXIS_RX] [get_bd_intf_pins AXIS_RX_${name}] + connect_bd_intf_net [get_bd_intf_pins $core/USER_DATA_S_AXIS_TX] [get_bd_intf_pins AXIS_TX_${name}] + + connect_bd_net [get_bd_pins $core/user_clk_out] [get_bd_pins /Network/sfp_tx_clock_${name}] + connect_bd_net [get_bd_pins $core/user_clk_out] [get_bd_pins /Network/sfp_rx_clock_${name}] + + set out_inv [create_inverter sys_reset_inverter_${name}] + connect_bd_net [get_bd_pins $core/sys_reset_out] [get_bd_pins $out_inv/Op1] + connect_bd_net [get_bd_pins /Network/sfp_tx_resetn_${name}] [get_bd_pins $out_inv/Res] + connect_bd_net [get_bd_pins /Network/sfp_rx_resetn_${name}] [get_bd_pins $out_inv/Res] + } + + proc create_inverter {name} { + variable ret [create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 $name] + set_property -dict [list CONFIG.C_SIZE {1} CONFIG.C_OPERATION {not} CONFIG.LOGO_FILE {data/sym_notgate.png}] [get_bd_cells $name] + return $ret + } + } +} diff --git a/toolflow/vivado/platform/xupvvh/xupvvh.tcl b/toolflow/vivado/platform/xupvvh/xupvvh.tcl index ed6e0fe5..402a9cae 100644 --- a/toolflow/vivado/platform/xupvvh/xupvvh.tcl +++ b/toolflow/vivado/platform/xupvvh/xupvvh.tcl @@ -67,32 +67,29 @@ namespace eval platform { set_property CONFIG.FREQ_HZ 100000000 $sys_clk # configure MIG core - set part_file "[get_property DIRECTORY [current_project]]/MTA18ADF2G72PZ-2G3.csv" + set part_file "[get_property DIRECTORY [current_project]]/M386AAK40B40-CWD6Y.csv" if { [file exists $part_file] == 1} { puts "Delete MIG configuration from project directory" file delete $part_file } puts "Copying MIG configuration to project directory" - file copy "$::env(TAPASCO_HOME_TCL)/platform/xupvvh/MTA18ADF2G72PZ-2G3.csv" $part_file + file copy "$::env(TAPASCO_HOME_TCL)/platform/xupvvh/M386AAK40B40-CWD6Y.csv" $part_file set properties [list CONFIG.C0.DDR4_TimePeriod {833} \ CONFIG.C0.DDR4_InputClockPeriod {9996} \ CONFIG.C0.DDR4_CLKOUT0_DIVIDE {5} \ - CONFIG.C0.DDR4_MemoryType {RDIMMs} \ - CONFIG.C0.DDR4_MemoryPart {MTA18ADF2G72PZ-2G3} \ + CONFIG.C0.DDR4_MemoryType {LRDIMMs} \ + CONFIG.C0.DDR4_MemoryPart {M386AAK40B40-CWD6Y} \ CONFIG.C0.DDR4_DataWidth {72} \ CONFIG.C0.DDR4_DataMask {NONE} \ - CONFIG.C0.DDR4_CasWriteLatency {16} \ CONFIG.C0.DDR4_AxiDataWidth {512} \ - CONFIG.C0.DDR4_AxiAddressWidth {34} \ + CONFIG.C0.DDR4_AxiAddressWidth {37} \ CONFIG.C0.DDR4_CustomParts $part_file \ CONFIG.C0.DDR4_isCustom {true} \ ] - set_property -dict $properties $mig - # connect MEM_CTRL interface (ECC configuration + status) set s_axi_mem_ctrl [create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_MEM_CTRL] @@ -232,7 +229,8 @@ namespace eval platform { insert_regslice "dma_host" true "/memory/M_HOST" "/host/S_HOST" "/clocks_and_resets/host_clk" "/clocks_and_resets/host_interconnect_aresetn" "" insert_regslice "host_arch" true "/host/M_ARCH" "/arch/S_ARCH" "/clocks_and_resets/design_clk" "/clocks_and_resets/design_interconnect_aresetn" "" - if {[tapasco::is_feature_enabled "SFPPLUS"]} { + # AXI control interface is only enabled in 10G mode + if {[get_bd_intf_pins "/network/S_NETWORK"] ne ""} { insert_regslice "host_network" true "/host/M_NETWORK" "/network/S_NETWORK" "/clocks_and_resets/design_clk" "/clocks_and_resets/design_interconnect_aresetn" "" } diff --git a/toolflow/vivado/platform/zc706/plugins/sfpplus.tcl b/toolflow/vivado/platform/zc706/plugins/sfpplus.tcl index af35d734..4550dadb 100644 --- a/toolflow/vivado/platform/zc706/plugins/sfpplus.tcl +++ b/toolflow/vivado/platform/zc706/plugins/sfpplus.tcl @@ -30,12 +30,16 @@ namespace eval sfpplus { variable refclk_pins {"AC8"} variable disable_pins_voltages {"LVCMOS25"} - proc num_available_ports {} { + proc num_available_ports {mode} { variable available_ports return $available_ports } - proc generate_cores {ports} { + proc get_available_modes {} { + return {"10G"} + } + + proc generate_cores {mode ports} { variable refclk_pins set num_streams [dict size $ports] diff --git a/toolflow/vivado/platform/zynqmp/zynqmp.tcl b/toolflow/vivado/platform/zynqmp/zynqmp.tcl index 9897bb00..088ae6fa 100644 --- a/toolflow/vivado/platform/zynqmp/zynqmp.tcl +++ b/toolflow/vivado/platform/zynqmp/zynqmp.tcl @@ -63,10 +63,10 @@ proc get_ignored_segments { } { set ignored [list] - lappend ignored "/host/zynqmp/SAXIGP2/HP0_DDR_LOW" - lappend ignored "/host/zynqmp/SAXIGP2/HP0_LPS_OCM" - lappend ignored "/host/zynqmp/SAXIGP2/HP0_PCIE_LOW" - lappend ignored "/host/zynqmp/SAXIGP2/HP0_QSPI" + lappend ignored "/host/zynqmp/SAXIGP0/HPC0_DDR_LOW" + lappend ignored "/host/zynqmp/SAXIGP0/HPC0_LPS_OCM" + lappend ignored "/host/zynqmp/SAXIGP0/HPC0_PCIE_LOW" + lappend ignored "/host/zynqmp/SAXIGP0/HPC0_QSPI" lappend ignored "/host/zynqmp/SAXIGP4/HP2_DDR_LOW" lappend ignored "/host/zynqmp/SAXIGP4/HP2_LPS_OCM" lappend ignored "/host/zynqmp/SAXIGP4/HP2_PCIE_LOW" @@ -179,7 +179,7 @@ set mem_slaves [list] set mem_masters [list] set arch_masters [::arch::get_masters] - set ps_slaves [list "HP0" "HP1"] + set ps_slaves [list "HPC0" "HP1"] puts "Creating memory slave ports for [llength $arch_masters] masters ..." if {[llength $arch_masters] > [llength $ps_slaves]} { error " trying to connect [llength $arch_masters] architecture masters, " \ @@ -317,7 +317,7 @@ } # create hierarchical ports - set hp_ports [list "HP0" "HP1"] + set hp_ports [list "HPC0" "HP1"] set mem_slaves [list] foreach s $hp_ports { lappend mem_slaves [create_bd_intf_pin -mode Slave -vlnv $aximm_vlnv "S_$s"] @@ -370,10 +370,11 @@ puts " PS generated..." puts " PS configuration ..." - # activate ACP, HP0, HP2 and GP0/1 (+ FCLK1 @10MHz) + # activate ACP, HPC0, HP2 and GP0/1 (+ FCLK1 @10MHz) set_property -dict [list \ CONFIG.PSU__FPGA_PL1_ENABLE {1} \ - CONFIG.PSU__USE__S_AXI_GP2 {1} \ + CONFIG.PSU__USE__S_AXI_GP0 {1} \ + CONFIG.PSU__USE__S_AXI_GP2 {0} \ CONFIG.PSU__USE__S_AXI_GP4 {1} \ CONFIG.PSU__CRL_APB__PL0_REF_CTRL__FREQMHZ [tapasco::get_design_frequency] \ CONFIG.PSU__CRL_APB__PL1_REF_CTRL__FREQMHZ {10} \ @@ -392,11 +393,19 @@ # connect slaves set ps_mem_slaves [list \ - [get_bd_intf_pins "$ps/S_AXI_HP0_FPD"] \ + [get_bd_intf_pins "$ps/S_AXI_HPC0_FPD"] \ [get_bd_intf_pins "$ps/S_AXI_HP2_FPD"] ] foreach ms $mem_offsets pms $ps_mem_slaves { connect_bd_intf_net $ms $pms } + # configure AxPROT + AxCACHE signals of HPC0 port for coherent memory accesses + set constant_HPC0_prot [tapasco::ip::create_constant constant_HPC0_prot 3 2] + connect_bd_net [get_bd_pins $ps/saxigp0_awprot] [get_bd_pins constant_HPC0_prot/dout] + connect_bd_net [get_bd_pins $ps/saxigp0_arprot] [get_bd_pins constant_HPC0_prot/dout] + set constant_HPC0_cache [tapasco::ip::create_constant constant_HPC0_cache 4 15] + connect_bd_net [get_bd_pins $ps/saxigp0_awcache] [get_bd_pins constant_HPC0_cache/dout] + connect_bd_net [get_bd_pins $ps/saxigp0_arcache] [get_bd_pins constant_HPC0_cache/dout] + # connect interrupt set irq_top [tapasco::ip::create_xlslice irq_top 16 0] set_property -dict [list CONFIG.DIN_FROM {7} CONFIG.DIN_WIDTH {16} CONFIG.DOUT_WIDTH {8} CONFIG.DIN_TO {0}] $irq_top diff --git a/toolflow/vivado/status/json_to_status/src/main.rs b/toolflow/vivado/status/json_to_status/src/main.rs index 40c2db4e..52b4bae0 100644 --- a/toolflow/vivado/status/json_to_status/src/main.rs +++ b/toolflow/vivado/status/json_to_status/src/main.rs @@ -282,7 +282,7 @@ fn run() -> Result<()> { let mut interrupts_pes: HashMap> = HashMap::new(); let mut interrupts_plat: HashMap> = HashMap::new(); - let pe_re = Regex::new(r"PE_(\d)_(\d)")?; + let pe_re = Regex::new(r"PE_(\d+)_(\d+)")?; let platform_re = Regex::new(r"(PLATFORM_COMPONENT_.*)_(.*)")?; for interrupt in json.Interrupts { @@ -325,6 +325,7 @@ fn run() -> Result<()> { } let mut pes: Vec = Vec::new(); + let mut peid = 0; for pe in json.Architecture.Composition { let addr = from_hex_str(&pe.Offset)?; let size = from_hex_str(&pe.Size)?; @@ -337,7 +338,7 @@ fn run() -> Result<()> { size: size, }); } else { - let int = match interrupts_pes.remove(&pe.SlotId) { + let int = match interrupts_pes.remove(&peid) { Some(x) => x, None => Vec::new(), }; @@ -350,6 +351,7 @@ fn run() -> Result<()> { debug: debugs.remove(&pe.SlotId), interrupts: int, }); + peid += 1; } }