├── .github ├── verible.waiver └── workflows │ ├── gitlab-ci.yml │ └── lint.yml ├── .gitignore ├── .gitlab-ci.yml ├── Bender.lock ├── Bender.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── bender-common.mk ├── bender-sim.mk ├── bender-synth.mk ├── doc ├── PULP_CLUSTER.drawio ├── PULP_CLUSTER.pdf └── PULP_CLUSTER.png ├── env ├── astral-env.sh ├── carfield-env.sh └── env.sh ├── include ├── cluster_bus_defines.sv ├── periph_bus_defines.sv ├── pulp_interfaces.sv └── pulp_soc_defines.sv ├── ips_list.yml ├── packages ├── apu_package.sv └── pulp_cluster_package.sv ├── regression.mk ├── rtl ├── axi2mem_wrap.sv ├── axi2per_wrap.sv ├── cluster_bus_wrap.sv ├── cluster_clock_gate.sv ├── cluster_event_map.sv ├── cluster_interconnect_wrap.sv ├── cluster_peripherals.sv ├── cluster_timer_wrap.sv ├── core_demux_wrap.sv ├── core_region.sv ├── data_periph_demux.sv ├── hwpe_subsystem.sv ├── idma_wrap.sv ├── instr_width_converter.sv ├── mchan_wrap.sv ├── obi_pulp_adapter.sv ├── per2axi_wrap.sv ├── per_demux_wrap.sv ├── periph_FIFO.sv ├── periph_demux.sv ├── pulp_cluster.sv ├── pulp_cluster_wrap.sv ├── tcdm_banks_wrap.sv └── xbar_pe_wrap.sv ├── scripts ├── fault_injection_utils │ └── pulp_extract_nets.tcl ├── run_and_exit.tcl ├── start.tcl ├── vsim.sh └── wave.tcl ├── src_files.yml ├── tb ├── dpi │ └── elfloader.cpp ├── mock_uart.sv ├── mock_uart_axi.sv └── pulp_cluster_tb.sv └── wave.do /.github/verible.waiver: -------------------------------------------------------------------------------- 1 | # Copyright 2022 ETH Zurich and University of Bologna. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # Auto-generated configuration registers are waived 6 | waive --rule=typedef-structs-unions --location="hw/regs/*" 7 | waive --rule=line-length --location="hw/regs/*" 8 | waive --rule=no-trailing-spaces --location="hw/regs/*" 9 | waive --rule=parameter-name-style --location="hw/regs/*" 10 | # Package contains long lines 11 | waive --rule=line-length --location="hw/cheshire_pkg.sv" 12 | -------------------------------------------------------------------------------- /.github/workflows/gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 ETH Zurich and University of Bologna. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # Author: Paul Scheffler 6 | 7 | name: gitlab-ci 8 | 9 | on: [ push, pull_request, workflow_dispatch ] 10 | 11 | jobs: 12 | 13 | check: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - 17 | name: Mirror and check 18 | uses: pulp-platform/pulp-actions/gitlab-ci@v2 19 | # Skip on forks or pull requests from forks due to missing secrets. 20 | if: > 21 | github.repository == 'pulp-platform/pulp_cluster' && 22 | (github.event_name != 'pull_request' || 23 | github.event.pull_request.head.repo.full_name == github.repository) 24 | with: 25 | domain: iis-git.ee.ethz.ch 26 | repo: github-mirror/pulp_cluster 27 | token: ${{ secrets.GITLAB_TOKEN }} 28 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 ETH Zurich and University of Bologna. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # Author: Paul Scheffler 6 | 7 | name: lint 8 | 9 | on: [ push, pull_request, workflow_dispatch ] 10 | 11 | jobs: 12 | 13 | # lint-license: 14 | # runs-on: ubuntu-latest 15 | # steps: 16 | # - 17 | # name: Checkout 18 | # uses: actions/checkout@v3 19 | # - 20 | # name: Check license 21 | # uses: pulp-platform/pulp-actions/lint-license@v2 22 | # with: 23 | # license: | 24 | # Copyright (\d{4}(-\d{4})?\s)?(ETH Zurich and University of Bologna|lowRISC contributors). 25 | # (Solderpad Hardware License, Version 0.51|Licensed under the Apache License, Version 2.0), see LICENSE for details. 26 | # SPDX-License-Identifier: (SHL-0.51|Apache-2.0) 27 | # # Exclude generated headers (no license checker support for optional lines) 28 | # exclude_paths: | 29 | # sw/include/regs/*.h 30 | 31 | lint-sv: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - 35 | name: Checkout 36 | uses: actions/checkout@v3 37 | - 38 | name: Run Verible 39 | uses: chipsalliance/verible-linter-action@main 40 | with: 41 | paths: hw 42 | extra_args: "--waiver_files .github/verible.waiver" 43 | github_token: ${{ secrets.GITHUB_TOKEN }} 44 | fail_on_error: true 45 | reviewdog_reporter: github-check 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bender/ 2 | work/ 3 | modelsim.ini 4 | transcript 5 | scripts/compile.tcl 6 | regression_tests/ 7 | pulp-runtime/ 8 | fault_injection_sim/ 9 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 ETH Zurich and University of Bologna. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | # Paul Scheffler 6 | 7 | # We initialize the nonfree repo, then spawn a sub-pipeline from it 8 | 9 | stages: 10 | - nonfree 11 | 12 | init: 13 | stage: nonfree 14 | script: make nonfree-init 15 | artifacts: 16 | paths: [ nonfree/ci.yml ] 17 | 18 | subpipe: 19 | stage: nonfree 20 | needs: [ init ] 21 | trigger: 22 | include: 23 | - artifact: nonfree/ci.yml 24 | job: init 25 | strategy: depend 26 | -------------------------------------------------------------------------------- /Bender.lock: -------------------------------------------------------------------------------- 1 | packages: 2 | apb: 3 | revision: 77ddf073f194d44b9119949d2421be59789e69ae 4 | version: 0.2.4 5 | source: 6 | Git: https://github.com/pulp-platform/apb.git 7 | dependencies: 8 | - common_cells 9 | axi: 10 | revision: 853ede23b2a9837951b74dbdc6d18c3eef5bac7d 11 | version: 0.39.5 12 | source: 13 | Git: https://github.com/pulp-platform/axi.git 14 | dependencies: 15 | - common_cells 16 | - common_verification 17 | - tech_cells_generic 18 | axi2mem: 19 | revision: b0e963433b2f6a61262b1448031e74eaec57c203 20 | version: null 21 | source: 22 | Git: https://github.com/pulp-platform/axi2mem.git 23 | dependencies: 24 | - axi_slice 25 | - common_cells 26 | axi2per: 27 | revision: 4932bd2b88a1c7b5f0bf95411fc512905ed32439 28 | version: null 29 | source: 30 | Git: https://github.com/pulp-platform/axi2per.git 31 | dependencies: 32 | - axi_slice 33 | axi_slice: 34 | revision: a4f72bc21ac4d7da631e8309d9f8d0c34b735c23 35 | version: 1.1.4 36 | source: 37 | Git: https://github.com/pulp-platform/axi_slice.git 38 | dependencies: 39 | - common_cells 40 | cluster_icache: 41 | revision: dd0e8f3497903a9ca99fc9f349d5a4f688ceb3ae 42 | version: null 43 | source: 44 | Git: https://github.com/pulp-platform/cluster_icache.git 45 | dependencies: 46 | - axi 47 | - common_cells 48 | - register_interface 49 | - scm 50 | - tech_cells_generic 51 | cluster_interconnect: 52 | revision: 1284def6c0b7f7e9355eb093d00883ad9dead1b7 53 | version: null 54 | source: 55 | Git: https://github.com/pulp-platform/cluster_interconnect.git 56 | dependencies: 57 | - common_cells 58 | cluster_peripherals: 59 | revision: 0b8e8ab9e6be3a5030a18256bb7e75cf6b6f6cac 60 | version: null 61 | source: 62 | Git: https://github.com/pulp-platform/cluster_peripherals.git 63 | dependencies: 64 | - hci 65 | common_cells: 66 | revision: c27bce39ebb2e6bae52f60960814a2afca7bd4cb 67 | version: 1.37.0 68 | source: 69 | Git: https://github.com/pulp-platform/common_cells.git 70 | dependencies: 71 | - common_verification 72 | - tech_cells_generic 73 | common_verification: 74 | revision: 9c07fa860593b2caabd9b5681740c25fac04b878 75 | version: 0.2.3 76 | source: 77 | Git: https://github.com/pulp-platform/common_verification.git 78 | dependencies: [] 79 | cv32e40p: 80 | revision: e863f576699815b38cc9d80dbdede8ed5efd5991 81 | version: null 82 | source: 83 | Git: https://github.com/pulp-platform/cv32e40p.git 84 | dependencies: 85 | - common_cells 86 | - fpnew 87 | - tech_cells_generic 88 | event_unit_flex: 89 | revision: 28e0499374117c7b0ef4c6ad81b60d7526af886f 90 | version: null 91 | source: 92 | Git: https://github.com/pulp-platform/event_unit_flex.git 93 | dependencies: 94 | - common_cells 95 | fpnew: 96 | revision: a8e0cba6dd50f357ece73c2c955d96efc3c6c315 97 | version: null 98 | source: 99 | Git: https://github.com/pulp-platform/cvfpu.git 100 | dependencies: 101 | - common_cells 102 | - fpu_div_sqrt_mvp 103 | fpu_div_sqrt_mvp: 104 | revision: 86e1f558b3c95e91577c41b2fc452c86b04e85ac 105 | version: 1.0.4 106 | source: 107 | Git: https://github.com/pulp-platform/fpu_div_sqrt_mvp.git 108 | dependencies: 109 | - common_cells 110 | hci: 111 | revision: aed9005c761827c6cbff2ea9a15f9cc37acd1169 112 | version: null 113 | source: 114 | Git: https://github.com/pulp-platform/hci.git 115 | dependencies: 116 | - cluster_interconnect 117 | - common_cells 118 | - hwpe-stream 119 | - l2_tcdm_hybrid_interco 120 | - redundancy_cells 121 | - register_interface 122 | hier-icache: 123 | revision: 2886cb2a46cea3e2bd2d979b505d88fadfbe150c 124 | version: null 125 | source: 126 | Git: https://github.com/pulp-platform/hier-icache.git 127 | dependencies: 128 | - axi 129 | - axi_slice 130 | - common_cells 131 | - icache-intc 132 | - scm 133 | - tech_cells_generic 134 | hwpe-ctrl: 135 | revision: a5966201aeeb988d607accdc55da933a53c6a56e 136 | version: null 137 | source: 138 | Git: https://github.com/pulp-platform/hwpe-ctrl.git 139 | dependencies: 140 | - tech_cells_generic 141 | hwpe-stream: 142 | revision: 65c99a4a2f37a79acee800ab0151f67dfb1edef1 143 | version: 1.8.0 144 | source: 145 | Git: https://github.com/pulp-platform/hwpe-stream.git 146 | dependencies: 147 | - tech_cells_generic 148 | ibex: 149 | revision: b18f7ef178ed07f5085051f96042c670a919fd5c 150 | version: null 151 | source: 152 | Git: https://github.com/pulp-platform/ibex.git 153 | dependencies: 154 | - tech_cells_generic 155 | icache-intc: 156 | revision: 663c3b6d3c2bf63ff25cda46f33c799c647b3985 157 | version: 1.0.1 158 | source: 159 | Git: https://github.com/pulp-platform/icache-intc.git 160 | dependencies: [] 161 | idma: 162 | revision: 437ffa9dac5dea0daccfd3e8ae604d4f6ae2cdf1 163 | version: null 164 | source: 165 | Git: https://github.com/pulp-platform/iDMA.git 166 | dependencies: 167 | - axi 168 | - common_cells 169 | - common_verification 170 | - register_interface 171 | l2_tcdm_hybrid_interco: 172 | revision: fa55e72859dcfb117a2788a77352193bef94ff2b 173 | version: 1.0.0 174 | source: 175 | Git: https://github.com/pulp-platform/L2_tcdm_hybrid_interco.git 176 | dependencies: [] 177 | mchan: 178 | revision: 7f064f205a3e0203e959b14773c4afecf56681ab 179 | version: null 180 | source: 181 | Git: https://github.com/pulp-platform/mchan.git 182 | dependencies: 183 | - common_cells 184 | neureka: 185 | revision: 94528df2bc6d5eedc0439bd403c2ad005f0a7519 186 | version: null 187 | source: 188 | Git: https://github.com/pulp-platform/neureka.git 189 | dependencies: 190 | - hci 191 | - hwpe-ctrl 192 | - hwpe-stream 193 | - register_interface 194 | - zeroriscy 195 | per2axi: 196 | revision: 95bf23119b47fc171d9ed3734c431f71cffd9350 197 | version: null 198 | source: 199 | Git: https://github.com/pulp-platform/per2axi.git 200 | dependencies: 201 | - axi_slice 202 | redmule: 203 | revision: 9223ccc932e21d0667e9c2d30831db41eec9299e 204 | version: 205 | source: 206 | Git: https://github.com/pulp-platform/redmule.git 207 | dependencies: 208 | - common_cells 209 | - cv32e40p 210 | - fpnew 211 | - hci 212 | - hwpe-ctrl 213 | - hwpe-stream 214 | - register_interface 215 | - tech_cells_generic 216 | redundancy_cells: 217 | revision: 49e714b97a19a7aaddf064ae2757c8f02d1f62dc 218 | version: null 219 | source: 220 | Git: https://github.com/pulp-platform/redundancy_cells.git 221 | dependencies: 222 | - common_cells 223 | - common_verification 224 | - register_interface 225 | - tech_cells_generic 226 | register_interface: 227 | revision: 5daa85d164cf6b54ad061ea1e4c6f3624556e467 228 | version: 0.4.5 229 | source: 230 | Git: https://github.com/pulp-platform/register_interface.git 231 | dependencies: 232 | - apb 233 | - axi 234 | - common_cells 235 | - common_verification 236 | riscv: 237 | revision: c760db14dbd6cc3ec3b8ae8274df2eac7225bcac 238 | version: null 239 | source: 240 | Git: https://github.com/AlSaqr-platform/riscv_nn.git 241 | dependencies: 242 | - fpnew 243 | - tech_cells_generic 244 | scm: 245 | revision: 74426dee36f28ae1c02f7635cf844a0156145320 246 | version: null 247 | source: 248 | Git: https://github.com/pulp-platform/scm.git 249 | dependencies: 250 | - tech_cells_generic 251 | softex: 252 | revision: 31e7534a3da3244f2f5c08bab430a560beee6ff2 253 | version: null 254 | source: 255 | Git: https://github.com/belanoa/softex.git 256 | dependencies: 257 | - common_cells 258 | - fpnew 259 | - hci 260 | - hwpe-ctrl 261 | - hwpe-stream 262 | - ibex 263 | tech_cells_generic: 264 | revision: 7968dd6e6180df2c644636bc6d2908a49f2190cf 265 | version: 0.2.13 266 | source: 267 | Git: https://github.com/pulp-platform/tech_cells_generic.git 268 | dependencies: 269 | - common_verification 270 | timer_unit: 271 | revision: 4c69615c89db9397a9747d6f6d6a36727854f0bc 272 | version: 1.0.3 273 | source: 274 | Git: https://github.com/pulp-platform/timer_unit.git 275 | dependencies: [] 276 | zeroriscy: 277 | revision: cc4068a0ccb7691cd062b809c34b2304e7fbfa36 278 | version: null 279 | source: 280 | Git: https://github.com/yvantor/ibex.git 281 | dependencies: [] 282 | -------------------------------------------------------------------------------- /Bender.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | package: 6 | name: pulp_cluster 7 | authors: 8 | - "Pirmin Vogel " 9 | - "Angelo Garofalo " 10 | - "Francesco Conti " 11 | - "Jie Chen " 12 | - "Michael Rogenmoser " 13 | 14 | dependencies: 15 | axi2mem: { git: "https://github.com/pulp-platform/axi2mem.git", rev: v1.0.2 } 16 | axi2per: { git: "https://github.com/pulp-platform/axi2per.git", rev: v1.0.2 } 17 | per2axi: { git: "https://github.com/pulp-platform/per2axi.git", rev: v1.0.5 } 18 | cluster_interconnect: { git: "https://github.com/pulp-platform/cluster_interconnect.git", rev: v1.3.0 } 19 | event_unit_flex: { git: "https://github.com/pulp-platform/event_unit_flex.git", rev: astral-v1.0 } 20 | mchan: { git: "https://github.com/pulp-platform/mchan.git", rev: v1.2.4 } 21 | idma: { git: "https://github.com/pulp-platform/iDMA.git", rev: v0.6.3 } 22 | hier-icache: { git: "https://github.com/pulp-platform/hier-icache.git", rev: v1.3.0 } 23 | cluster_icache: { git: "https://github.com/pulp-platform/cluster_icache.git", rev: v0.2.0 } 24 | cluster_peripherals: { git: "https://github.com/pulp-platform/cluster_peripherals.git", rev: v2.2.0 } 25 | axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.39.3 } 26 | timer_unit: { git: "https://github.com/pulp-platform/timer_unit.git", version: 1.0.2 } 27 | common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.35.0 } 28 | tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git", version: 0.2.3 } 29 | riscv: { git: "https://github.com/AlSaqr-platform/riscv_nn.git", rev: astral-v1.0 } 30 | cv32e40p: { git: "https://github.com/pulp-platform/cv32e40p.git", rev: astral-v1.0 } 31 | ibex: { git: "https://github.com/pulp-platform/ibex.git", rev: "pulpissimo-v6.1.2" } 32 | scm: { git: "https://github.com/pulp-platform/scm.git", rev: v1.2.0 } 33 | hci: { git: "https://github.com/pulp-platform/hci.git", rev: astral-v1.0 } 34 | register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.4 } 35 | redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: astral-v1.0 } 36 | redmule: { git: "https://github.com/pulp-platform/redmule.git", rev: astral-v1.0 } 37 | neureka: { git: "https://github.com/pulp-platform/neureka.git", rev: astral-v1.0 } 38 | softex: { git: "https://github.com/belanoa/softex.git" , rev: astral-v1.0 } 39 | 40 | export_include_dirs: 41 | - include 42 | 43 | sources: 44 | # Source files grouped in levels. Files in level 0 have no dependencies on files in this 45 | # package. Files in level 1 only depend on files in level 0, files in level 2 on files in 46 | # levels 1 and 0, etc. Files within a level are ordered alphabetically. 47 | # Level 0 48 | - packages/pulp_cluster_package.sv 49 | - rtl/axi2mem_wrap.sv 50 | - rtl/axi2per_wrap.sv 51 | - rtl/cluster_bus_wrap.sv 52 | - rtl/cluster_clock_gate.sv 53 | - rtl/cluster_event_map.sv 54 | - rtl/cluster_timer_wrap.sv 55 | - rtl/obi_pulp_adapter.sv 56 | - target: mchan 57 | files: 58 | - rtl/mchan_wrap.sv 59 | - target: not(mchan) 60 | files: 61 | - rtl/idma_wrap.sv 62 | - rtl/hwpe_subsystem.sv 63 | - rtl/instr_width_converter.sv 64 | - rtl/per2axi_wrap.sv 65 | - rtl/periph_demux.sv 66 | - rtl/per_demux_wrap.sv 67 | - rtl/periph_FIFO.sv 68 | - rtl/tcdm_banks_wrap.sv 69 | - rtl/xbar_pe_wrap.sv 70 | # Level 1 71 | - rtl/cluster_interconnect_wrap.sv 72 | - rtl/cluster_peripherals.sv 73 | - rtl/data_periph_demux.sv 74 | - rtl/core_demux_wrap.sv 75 | - rtl/core_region.sv 76 | - target: simulation 77 | files: 78 | defines: 79 | TRACE_EXECUTION: ~ 80 | # Level 3 81 | - rtl/pulp_cluster.sv 82 | - rtl/pulp_cluster_wrap.sv 83 | 84 | - target: test 85 | files: 86 | - tb/mock_uart.sv 87 | - tb/mock_uart_axi.sv 88 | - tb/pulp_cluster_tb.sv 89 | 90 | - target: cluster_standalone 91 | files: 92 | - include/pulp_interfaces.sv 93 | 94 | - target: pulp_standalone_synth 95 | files: 96 | - nonfree/gf12/sourcecode/tc_sram.sv 97 | - nonfree/gf12/sourcecode/tc_clk.sv 98 | 99 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ### Added 9 | - Added `CHANGELOG.md` 10 | 11 | ### Changed 12 | - Align `Bender.yml` IPs to `ips_list.yml` 13 | - Bump `fpu_interco` to unreleased version 14 | - Bump `riscv` to `cv32e40p` for `pulp_soc` v3.0.0 compatibility 15 | - Bump `axi` to v0.29.1 16 | - Updated schematic in `doc` 17 | - Changed tcdm_banks to `tc_sram` tech cell, remove explicit FPGA RAM instatiation. This is now supposed to be handled by tc_sram wrapping a Xilinx XPM. 18 | 19 | ### Removed 20 | ### Fixed 21 | - ibex implementation 22 | - ID compliance of tcdm_banks 23 | - Correct AXI ID width for icache bus 24 | 25 | ## [2.0.0] - 2021-05-20 26 | - Initial version prior to Changelog 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | SOLDERPAD HARDWARE LICENSE version 0.51 2 | 3 | This license is based closely on the Apache License Version 2.0, but is not 4 | approved or endorsed by the Apache Foundation. A copy of the non-modified 5 | Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0. 6 | 7 | As this license is not currently OSI or FSF approved, the Licensor permits any 8 | Work licensed under this License, at the option of the Licensee, to be treated 9 | as licensed under the Apache License Version 2.0 (which is so approved). 10 | 11 | This License is licensed under the terms of this License and in particular 12 | clause 7 below (Disclaimer of Warranties) applies in relation to its use. 13 | 14 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 15 | 16 | 1. Definitions. 17 | 18 | "License" shall mean the terms and conditions for use, reproduction, and 19 | distribution as defined by Sections 1 through 9 of this document. 20 | 21 | "Licensor" shall mean the Rights owner or entity authorized by the Rights owner 22 | that is granting the License. 23 | 24 | "Legal Entity" shall mean the union of the acting entity and all other entities 25 | that control, are controlled by, or are under common control with that entity. 26 | For the purposes of this definition, "control" means (i) the power, direct or 27 | indirect, to cause the direction or management of such entity, whether by 28 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 29 | outstanding shares, or (iii) beneficial ownership of such entity. 30 | 31 | "You" (or "Your") shall mean an individual or Legal Entity exercising 32 | permissions granted by this License. 33 | 34 | "Rights" means copyright and any similar right including design right (whether 35 | registered or unregistered), semiconductor topography (mask) rights and 36 | database rights (but excluding Patents and Trademarks). 37 | 38 | "Source" form shall mean the preferred form for making modifications, including 39 | but not limited to source code, net lists, board layouts, CAD files, 40 | documentation source, and configuration files. 41 | 42 | "Object" form shall mean any form resulting from mechanical transformation or 43 | translation of a Source form, including but not limited to compiled object 44 | code, generated documentation, the instantiation of a hardware design and 45 | conversions to other media types, including intermediate forms such as 46 | bytecodes, FPGA bitstreams, artwork and semiconductor topographies (mask 47 | works). 48 | 49 | "Work" shall mean the work of authorship, whether in Source form or other 50 | Object form, made available under the License, as indicated by a Rights notice 51 | that is included in or attached to the work (an example is provided in the 52 | Appendix below). 53 | 54 | "Derivative Works" shall mean any work, whether in Source or Object form, that 55 | is based on (or derived from) the Work and for which the editorial revisions, 56 | annotations, elaborations, or other modifications represent, as a whole, an 57 | original work of authorship. For the purposes of this License, Derivative Works 58 | shall not include works that remain separable from, or merely link (or bind by 59 | name) or physically connect to or interoperate with the interfaces of, the Work 60 | and Derivative Works thereof. 61 | 62 | "Contribution" shall mean any design or work of authorship, including the 63 | original version of the Work and any modifications or additions to that Work or 64 | Derivative Works thereof, that is intentionally submitted to Licensor for 65 | inclusion in the Work by the Rights owner or by an individual or Legal Entity 66 | authorized to submit on behalf of the Rights owner. For the purposes of this 67 | definition, "submitted" means any form of electronic, verbal, or written 68 | communication sent to the Licensor or its representatives, including but not 69 | limited to communication on electronic mailing lists, source code control 70 | systems, and issue tracking systems that are managed by, or on behalf of, the 71 | Licensor for the purpose of discussing and improving the Work, but excluding 72 | communication that is conspicuously marked or otherwise designated in writing 73 | by the Rights owner as "Not a Contribution." 74 | 75 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 76 | of whom a Contribution has been received by Licensor and subsequently 77 | incorporated within the Work. 78 | 79 | 2. Grant of License. Subject to the terms and conditions of this License, each 80 | Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 81 | no-charge, royalty-free, irrevocable license under the Rights to reproduce, 82 | prepare Derivative Works of, publicly display, publicly perform, sublicense, 83 | and distribute the Work and such Derivative Works in Source or Object form and 84 | do anything in relation to the Work as if the Rights did not exist. 85 | 86 | 3. Grant of Patent License. Subject to the terms and conditions of this 87 | License, each Contributor hereby grants to You a perpetual, worldwide, 88 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this 89 | section) patent license to make, have made, use, offer to sell, sell, import, 90 | and otherwise transfer the Work, where such license applies only to those 91 | patent claims licensable by such Contributor that are necessarily infringed by 92 | their Contribution(s) alone or by combination of their Contribution(s) with the 93 | Work to which such Contribution(s) was submitted. If You institute patent 94 | litigation against any entity (including a cross-claim or counterclaim in a 95 | lawsuit) alleging that the Work or a Contribution incorporated within the Work 96 | constitutes direct or contributory patent infringement, then any patent 97 | licenses granted to You under this License for that Work shall terminate as of 98 | the date such litigation is filed. 99 | 100 | 4. Redistribution. You may reproduce and distribute copies of the Work or 101 | Derivative Works thereof in any medium, with or without modifications, and in 102 | Source or Object form, provided that You meet the following conditions: 103 | 104 | You must give any other recipients of the Work or Derivative Works a copy 105 | of this License; and 106 | 107 | You must cause any modified files to carry prominent notices stating that 108 | You changed the files; and 109 | 110 | You must retain, in the Source form of any Derivative Works that You 111 | distribute, all copyright, patent, trademark, and attribution notices from 112 | the Source form of the Work, excluding those notices that do not pertain to 113 | any part of the Derivative Works; and 114 | 115 | If the Work includes a "NOTICE" text file as part of its distribution, then 116 | any Derivative Works that You distribute must include a readable copy of 117 | the attribution notices contained within such NOTICE file, excluding those 118 | notices that do not pertain to any part of the Derivative Works, in at 119 | least one of the following places: within a NOTICE text file distributed as 120 | part of the Derivative Works; within the Source form or documentation, if 121 | provided along with the Derivative Works; or, within a display generated by 122 | the Derivative Works, if and wherever such third-party notices normally 123 | appear. The contents of the NOTICE file are for informational purposes only 124 | and do not modify the License. You may add Your own attribution notices 125 | within Derivative Works that You distribute, alongside or as an addendum to 126 | the NOTICE text from the Work, provided that such additional attribution 127 | notices cannot be construed as modifying the License. You may add Your own 128 | copyright statement to Your modifications and may provide additional or 129 | different license terms and conditions for use, reproduction, or 130 | distribution of Your modifications, or for any such Derivative Works as a 131 | whole, provided Your use, reproduction, and distribution of the Work 132 | otherwise complies with the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 135 | Contribution intentionally submitted for inclusion in the Work by You to the 136 | Licensor shall be under the terms and conditions of this License, without any 137 | additional terms or conditions. Notwithstanding the above, nothing herein shall 138 | supersede or modify the terms of any separate license agreement you may have 139 | executed with Licensor regarding such Contributions. 140 | 141 | 6. Trademarks. This License does not grant permission to use the trade names, 142 | trademarks, service marks, or product names of the Licensor, except as required 143 | for reasonable and customary use in describing the origin of the Work and 144 | reproducing the content of the NOTICE file. 145 | 146 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in 147 | writing, Licensor provides the Work (and each Contributor provides its 148 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 149 | KIND, either express or implied, including, without limitation, any warranties 150 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any risks 153 | associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, whether in 156 | tort (including negligence), contract, or otherwise, unless required by 157 | applicable law (such as deliberate and grossly negligent acts) or agreed to in 158 | writing, shall any Contributor be liable to You for damages, including any 159 | direct, indirect, special, incidental, or consequential damages of any 160 | character arising as a result of this License or out of the use or inability to 161 | use the Work (including but not limited to damages for loss of goodwill, work 162 | stoppage, computer failure or malfunction, or any and all other commercial 163 | damages or losses), even if such Contributor has been advised of the 164 | possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or 167 | Derivative Works thereof, You may choose to offer, and charge a fee for, 168 | acceptance of support, warranty, indemnity, or other liability obligations 169 | and/or rights consistent with this License. However, in accepting such 170 | obligations, You may act only on Your own behalf and on Your sole 171 | responsibility, not on behalf of any other Contributor, and only if You agree 172 | to indemnify, defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason of your 174 | accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | ROOT_DIR = $(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))) 6 | 7 | HOSTNAME := $(shell hostname) 8 | ETH_HOST = $(shell echo $(HOSTNAME) | grep -q "\.ee\.ethz\.ch$$" && echo 1 || echo 0) 9 | ifeq ($(ETH_HOST),1) 10 | QUESTA ?= questa-2023.4-zr 11 | else 12 | QUESTA ?= 13 | endif 14 | 15 | BENDER ?= bender 16 | 17 | VSIM ?= $(QUESTA) vsim 18 | VOPT ?= $(QUESTA) vopt 19 | VLIB ?= $(QUESTA) vlib 20 | top_level ?= pulp_cluster_tb 21 | library ?= work 22 | elf-bin ?= stimuli.riscv 23 | bwruntest = $(ROOT_DIR)/pulp-runtime/scripts/bwruntests.py 24 | 25 | REGRESSIONS := $(ROOT_DIR)/regression_tests 26 | 27 | VLOG_ARGS += -suppress vlog-2583 -suppress vlog-13314 -suppress vlog-13233 -timescale \"1 ns / 1 ps\" \"+incdir+$(shell pwd)/include\" 28 | 29 | define generate_vsim 30 | echo 'set ROOT [file normalize [file dirname [info script]]/$3]' > $1 31 | $(BENDER) script vsim --vlog-arg="$(VLOG_ARGS)" $2 | grep -v "set ROOT" >> $1 32 | echo >> $1 33 | endef 34 | 35 | ###################### 36 | # Nonfree components # 37 | ###################### 38 | 39 | NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:pulp-restricted/pulp-cluster-nonfree.git 40 | NONFREE_COMMIT ?= 67079fe 41 | 42 | nonfree-init: 43 | git clone $(NONFREE_REMOTE) nonfree 44 | cd nonfree && git checkout $(NONFREE_COMMIT) 45 | 46 | ################ 47 | # Dependencies # 48 | ################ 49 | 50 | .PHONY: init 51 | 52 | init: checkout 53 | 54 | .PHONY: checkout 55 | ## Checkout/update dependencies using Bender 56 | checkout: 57 | $(BENDER) checkout 58 | touch Bender.lock 59 | make scripts/compile.tcl 60 | 61 | Bender.lock: 62 | $(BENDER) checkout 63 | touch Bender.lock 64 | 65 | 66 | ###### 67 | # SW # 68 | ###### 69 | 70 | .PHONY: sw-init sw-clean 71 | 72 | sw-init: pulp-runtime fault_injection_sim regression_tests 73 | sw-clean: 74 | @rm -rf pulp-runtime fault_injection_sim regression_test 75 | 76 | ## Clone pulp-runtime as SW stack 77 | PULP_RUNTIME_REMOTE ?= https://github.com/pulp-platform/pulp-runtime.git 78 | PULP_RUNTIME_COMMIT ?= b3c239c # branch: lg/upstream 79 | 80 | pulp-runtime: 81 | git clone $(PULP_RUNTIME_REMOTE) $@ 82 | cd $@ && git checkout $(PULP_RUNTIME_COMMIT) 83 | 84 | ## Clone fault injection scripts 85 | FAULT_SIM_REMOTE ?= https://github.com/pulp-platform/InjectaFault.git 86 | FAULT_SIM_COMMIT ?= 84ddcff # branch: rt/rename-var 87 | 88 | fault_injection_sim: 89 | git clone $(FAULT_SIM_REMOTE) $@ 90 | cd $@ && git checkout $(FAULT_SIM_COMMIT) 91 | 92 | ## Clone regression tests 93 | REGRESSION_TESTS_REMOTE ?= https://github.com/pulp-platform/regression_tests.git 94 | REGRESSION_TESTS_COMMIT ?= d43cb0d # branch: lg/upstream 95 | 96 | regression_tests: 97 | git clone $(REGRESSION_TESTS_REMOTE) $@ 98 | cd $@ && git checkout $(REGRESSION_TESTS_COMMIT) 99 | cd $@ && git submodule update --init --recursive 100 | 101 | ######################## 102 | # Build and simulation # 103 | ######################## 104 | 105 | .PHONY: sim-clean compile build run 106 | 107 | sim-clean: 108 | rm -rf scripts/compile.tcl 109 | rm -rf work 110 | 111 | include bender-common.mk 112 | include bender-sim.mk 113 | scripts/compile.tcl: | Bender.lock 114 | $(call generate_vsim, $@, $(common_defs) $(common_targs) $(sim_defs) $(sim_targs),..) 115 | echo 'vlog "$(realpath $(ROOT_DIR))/tb/dpi/elfloader.cpp" -ccflags "-std=c++11"' >> $@ 116 | 117 | include bender-synth.mk 118 | scripts/synth-compile.tcl: | Bender.lock 119 | $(BENDER) script synopsys $(common_targs) $(common_defs) $(synth_targs) $(synth_defs) > $@ 120 | 121 | $(library): 122 | $(QUESTA) vlib $(library) 123 | 124 | compile: $(library) 125 | @test -f Bender.lock || { echo "ERROR: Bender.lock file does not exist. Did you run make checkout in bender mode?"; exit 1; } 126 | @test -f scripts/compile.tcl || { echo "ERROR: scripts/compile.tcl file does not exist. Did you run make scripts in bender mode?"; exit 1; } 127 | $(VSIM) -c -do 'quit -code [source scripts/compile.tcl]' 128 | 129 | build: compile 130 | $(VOPT) $(compile_flag) -suppress 3053 -suppress 8885 -work $(library) $(top_level) -o $(top_level)_optimized +acc 131 | 132 | run: 133 | $(VSIM) +permissive -suppress 3053 -suppress 8885 -lib $(library) +MAX_CYCLES=$(max_cycles) +UVM_TESTNAME=$(test_case) +APP=$(elf-bin) +notimingchecks +nospecify -t 1ps \ 134 | ${top_level}_optimized +permissive-off ++$(elf-bin) ++$(target-options) ++$(cl-bin) | tee sim.log 135 | 136 | #################### 137 | # Regression tests # 138 | #################### 139 | 140 | include regression.mk 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PULP Cluster 2 | 3 | ![pulp_cluster schematic](doc/PULP_CLUSTER.png) 4 | 5 | The `pulp_cluster` repository contains the structure of the cluster subsystem 6 | used in PULP chips. For more details on the internal architecture, see the 7 | README.md in the [`pulp` repository](https://github.com/pulp-platform/pulp). 8 | 9 | The [`doc`](doc/) folder contains the draw.io schematic shown above, as well as 10 | the raw source to allow for updates, outlining the most important components in 11 | pulp_cluster, as well as the communication interfaces connecting these. While 12 | not a complete overview of all signals, this is meant as a slightly more 13 | detailed overview that can assist in development. Please be aware that the 14 | schematic may not be 100% accurate. 15 | 16 | ## Dependencies 17 | 18 | To *build* the cluster, you will need: 19 | 20 | - Bender `>= 0.24.0` 21 | - GNU Make `>= 3.82` 22 | - Python `>= 3.9` 23 | - RISCV GCC `>= 11.2.0` 24 | 25 | We use [Bender](https://github.com/pulp-platform/bender) for hardware IP and dependency management; for more information on using Bender, please see its documentation. You can install Bender directly through the Rust package manager Cargo: 26 | 27 | ``` 28 | cargo install bender 29 | ``` 30 | 31 | ## Simulation 32 | 33 | It is possible to run benchmarks on the cluster, either within 34 | [PULP](https://github.com/pulp-platform/pulp) or as a separate IP. For 35 | simulation within PULP, you can directly go to the PULP repo and follow the 36 | README. 37 | 38 | To simulate the cluster on its own, you can perform the following steps: 39 | 40 | Warning: requires QuestaSim 2022.3 or newer. 41 | 42 | 1. Make sure the PULP RV32 toolchain is in your `PATH`. Please refer to [PULP 43 | RISCV GCC toolchain](https://github.com/pulp-platform/pulp-riscv-gcc) to use 44 | a pre-built release. (At IIS, this is set up by the env script in step 4.) 45 | 46 | 2. Compile the hw: 47 | ``` 48 | make checkout 49 | make scripts/compile.tcl 50 | make build 51 | ``` 52 | 53 | 3. Download the sw stack and bare-metal tests: 54 | ``` 55 | make pulp-runtime 56 | make regression_tests 57 | ``` 58 | 59 | 4. Source the environment: 60 | ``` 61 | source env/env.sh 62 | ``` 63 | 64 | 5. Run the tests. Choose any test among the `parallel_bare_tests` and the 65 | `mchan_tests`, move into the related folder and do: 66 | 67 | ``` 68 | make clean all run 69 | ``` 70 | 71 | To use the GUI, add `gui=1` to the previous command. 72 | -------------------------------------------------------------------------------- /bender-common.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | common_defs += -D FEATURE_ICACHE_STAT 6 | common_defs += -D PRIVATE_ICACHE 7 | common_defs += -D HIERARCHY_ICACHE_32BIT 8 | common_defs += -D ICAHE_USE_FF 9 | bender_defs += -D TRACE_EXECUTION 10 | common_defs += -D CLUSTER_ALIAS 11 | common_defs += -D USE_PULP_PARAMETERS 12 | 13 | common_targs += -t rtl 14 | common_targs += -t mchan 15 | common_targs += -t cluster_standalone 16 | common_targs += -t scm_use_fpga_scm 17 | common_targs += -t cv32e40p_use_ff_regfile -------------------------------------------------------------------------------- /bender-sim.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | sim_defs += -D TRACE_EXECUTION 6 | 7 | sim_targs += -t test 8 | -------------------------------------------------------------------------------- /bender-synth.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | synth_defs := 6 | 7 | synth_targs := -t pulp_standalone_synth 8 | -------------------------------------------------------------------------------- /doc/PULP_CLUSTER.drawio: -------------------------------------------------------------------------------- 1 | 7V1pc5tIE/41rtr9YBX38dFWbCf7xllvTme/qBAaScRCaAHZcn79OxwjwcwAgxgOJXKlHIOGQ9PX0z093Rfy2N3d+dZmee/NwOpCEma7C/nNhSSJiiRdRP+E2WtyxjD15MTCd2bpoMOJT85PkJ4U0rNbZwaC3MDQ81ahs8mftL31Gthh7pzl+95LftjcW+WfurEWgDjxybZW5Nlvzixcpt9CFQ7n3wJnsURPFoX0E9dCg9MTwdKaeS+ZU/LNhTz2PS9M/nJ3Y7CKJg/NS3LdbcGn+xfzwTpkueB/ylz7ZyPeP37XjIf7qb35+rS6TO/ybK226Re2PR9MZq5lh/5qMt0GF+r1+kJ9k36H8BVNDJjBeUoPPT9cegtvba1uDmevfW+7noHo6QI8Oox573kbeFKEJ3+AMHxNiW5tQw+eWobuKv0U7JzwMbp8pKVH3+HRpTAS1PT4zS69e3zwig7Wof/6iG4SHXyP76Kiw8Nl8RG6LngCob3MPPwB+I4LQuCnA8gpT+cv8La+nU7Mq/t8s/nxw/x2r9t//QvefLGDyaWasq7lL0B66fZRcJ/kL/bdT+v71Hzcgo/Ox0stGRdNbuYBKUHvgAffxn+FA1L5gt/JUFIJ88HKCp3nPN9aKfsv9pfu7/bgOfBbHIZ483kA3y3DQvCPzEMPp2LGojPZ87/LD8vd4nEa/tD+enm/vLv/dnspE0xGctN6dhVJKzxae2uQ54Mg9L2nvfip+zNjb+X58fXy7a0Mf8pIVDmlLwfxRtK9zEg2OnfsNKcUU5B+SPWhbAj5WySslF6VFWf8RhJ2Iw27UcJrxI14EVU5E7WYFkcTFeeO9oh6dffw4e3z0z+h8lUI5/O7r28/P16Kxpmqe2JIZp4YinwkVWURu5HYMVXNM1WLiXEsVQn2aI+qVKggClI1WRcQhG1waJMcIPAGRyyWZYR7Bn4IdrlTKdq2pug5Ap2kO2yOkVrT0+MMyfeqLktzXP1lyZubz7qTR0ISe7UNINKbQGoBP/1+kxfo1FxImuVGc7ieBpt4ngSmU/gxRpk8On5ZOiH4tLFiEBk/NSeAc2e1ygjbTAXGTKGJoSFNZU07luAVfIbzQakId0tPkSTo0nZyxGxGgaHNNFJCal6yRFKw9h5plhBKa4QgceFuavmTDUiF6RckglhJA6NTEhAUCO2ZO5la66cAabQVfInrqQ//WoSJtur1DE/daAFjbtOYRbMNMJ3zNoaFXKFhToFoqgRfSDTZFAW1Jc5Ab4BpyeXLBlyo127vYR4dxXW+X2TCOtQYz8qagtW1ZT8t4ufnkGj0EzOA5YcYqI3P3TrRtKUBoD3stVdWEDh2cjIdQlU6QvwTcZ63DtNvJUoN+SobQaLSLtWrlREkZAlZQ0iXwmgfk20IrXXMGCmKwoSIIQWs18ywTTQgKHmOnn+Ohkc+sfGG0Gy8YpaP1+XS8fCP5Bu2GXgr45mMuL/99nDDVd3O50Czqep2pptTgQirtqZudcwKaxqbGdbbMsOkrnVsy16ChhCoejLrG0QO069g3rCO9FAWiUpdugQaMf8z1+p68oEIfTWdNvmmpsuWxmfyZRxqUHifOvl4nJLb5OvE5CP/eroNOHgCS893fkLzayFD3pGHXJs0Iu6gGSRpdJpY4GEpfnqJtAozK7Qmwcp6BhNN6QUCohU7YSTtV+m+Zz8sWLLrEAZWs8sByGZxLIK4dBzLBAipUV2TERCaZm1AGIdyeSBCzCartWOtXDESdRrJFQ8reF3bk4NMNBaIHOs0cpAkdsY6dhGciSGpjGaQDEmd8ZoOCvzWKKhUjxvruhUapqkVHeO3nlA8yaG349ZxTBPThyAgBYQoNASut2TpZImYudFoREwd/DphWZwxtRlZhJGeslbOYh3ZDLCOk0Suo8mBKH91lX7gOrNZrBBoBClREu0FpTA4oiokkWg0ktpCIzKJRqKQVATV1ev4dz8xqQMgyeERoUJ7FuORefyT0eZIfSdqWS9PaWo1tKQxIokjQkuyrhtd6G7c/SSS4arGa+XjNaHZeFmtF0LCxvdnfGTSjY4zBDfAdzbLwSQIsgeOM5Ktn66rwSTsjTIREeaqFPa2QZmaEwylQvBUPHarMQlSwdNUPKejwGHhJm1k3IQt/QBFVxKxBL61Cga5OscQD+sGCO1RDuITGlqlxYvbi5kpJBRy/P8me/06jun8NIn1L1gPQO/WgjAZxSuYWcUbJXQLw9G+8XPxzO9W8ZdMCeVQdTcr/moZa2HR5qrlMVU1ysZXqGR49UjRcK08Egzh8MO2zMhNSZPplOAZEn2yXTtNs4w60X0yg+6jqb72QtKk2Xs3nsQ7UKI5jVHmCao5iZPrOFR8SbdiAiPAVBmV2T4MKOvHxQG7jCaTuVfzaHqHYa6xBBvG+HHdJZkcdzXgI+mkjKJs5j0HtH5XaBR1uWx8lVHUpRHmqZiYcm7ZCCIxJ9IbDmq7feeiI3OJ4R1NNghz2W2SrUkuCYQQrvqTGIf0aiuxNSrWWEzOUGYUTm1beSO+UW90jraSOfuPSElo18yizdBVZlauv/wrSNqA7Gzp18cl4BT0CR560CUSftM2T7QGv5GppWTr/PLKnLYA1q0yVyh7keIIz3ZQW/CPUetY6kEDtT5UF6hRiJ1ZNbcLXVUDi8+kS3aMUNTQcSjacdBcITNtCVEZyD5IfPWdslXIpOgeHNvz0z3k6l5723xireaDheOtm1kKPAXdsAE9BX1qqNGU89wetme2WpshuyUqJfk2mvqeomhlSn0Mf3JWhj0+wUDSnK04WIKsuRDz5iI1KAdbQc+IK+WMauhutKL2KZHzvLJhCxDUth7Up1BtBzeFT7q/SdUi4G53v4VqQZ4EWy45j+QtKtChV4/6nSiAuXIqSRC5JYLQY+qUTUdrOHOTQbgQuipl1ftIEE3G8BCWqnNSSyl8C4mlziL/1RVBVI6K+tRO6BHz3oZWldBjCGXj62fGUd6I8GBwbNayB4OiPVgSbJSX3GsSLHX987z8WQbuVMouCF7JtKqqdiKiKp4ca1SIKDZerhBpHcuyk5uKNC85VCmbgXaO5AK3GabpKLSJk42S1kGLK7eGRtBewvwW3Eit9Z3RIeQ0mlSu0galmY7Wr8erNI0Vcxyx01Az0EWci/WJ+L7+AneXuNEl9uj2tI1GBv5de2k1DI71s4xCK3pEK+LX2hqWRqpuN92jEIcF0nUUqXcniD3CNVS9oxlyTvGMBEmqUD7UnNoGGol5xxLrJoaMRtLVLjCWguULyYZYqpYqxlcs0hBX46uZldqxA3VIrkVAAeYR1OtGJSqagLmRskABYGaHAEwn/Uo3s3Hr5FzKvNr59VaT6XKhMyo7rWbxeKjsRFVshr6K1UJthYjvmEx3bzOXyhY7WHnQyKW1yEHcnEbikYxPmSSR+qlLB1Enw9VJ6svQPETmmJdp5p2ykSKap6SmOAM1nbVq4RGuo6QoRymvuooJrwsip2GNwrrg2HikqArHi2rZ+P6iYToZvoGKLlJ4p6DsJCO/aUxGda96U3a0vb24gqMJMWMuRaorjt7fnqdhtarlB4EqtYPO6sZ11EIAr/eJe1PMLQTwGwlsblntzSmySH3hVrGSTkZkPj3cfJzcPH6evCODMMOowpNJ6je6w2UM7RE6VVUG6TcmpPt68+Hz5EtMPjy7jxhwLbZA4xWYhydIYclUchRWKZEBZK+6oTCZulNmjMiWMEyolWHrjNHI8gg4OC7O8mtC6IHYHQlLhdBx9mBuSFRlwDjZHfyFq4q3EO9VtjDMy04Z0oBEge5+Vm4571gemCtaDERwZJ3OV/UBG87QpswkONx4tWkrxfZ5taKO3QCYE213Gwpz4jvSjm5IhjGn2l7zQDpzkvGCBBT+PT4D/nI4SKnX3i3gJwOxMek+v7uHv8/EKwss7bPZeiMeuXAaE+/d+Gr89mYy/vzx/Zl+xcKnoepDfdHPJL3ts1E/tuzQUIw63nII5Sc1Neqait2oZaNukoEClFblWgNJqsonE3DO5jx+3yDXxmFEdZHjRaV2j3kRciEXqSCYmbFoUd24g4FtyxIrEtjx8UbFkh2eaV13vDaUBmEmGfuIocOb+6vJ7Rm1Yx3GVAz4oSBqb8CBjAbsqTd+f6ZeOfVQJl5v1CNhe9SIc2LPF70nv7SYpTwQe9oAadYzn1E9LbVpQS20U7HATnFvsInVKdGruh3gFa2GsqHLJHMuYg0ZtcE868ccn2pK3i3WUYHK3vQjWWbZ2jmTqJs4Qbd6FQZwbdF7i0AsbRylu1TMfHudM8loYNzDPcg1/Qg2fe+lqRGi4J9kSTdRbRqeuptZoCuc4yuRU2ijo8Vj3GmqyqMkxpclOXXaQocUp9CeuXEn1MC3XChL03n/fa54dcOpaHTVY58rkXUjK2vax17Q+MA7vO+4zFiGolNmJn3OqFRFnLYfcfUgCs3UaJPJwsfHlqHh5fd0LRNlRS3bLlqmSURlc7ycJC8np2ZnKU2Sy8a3k5wkot4mGXkbJ0UnHW8dRITz4K+IbaJqlH70nxX/doEVv338uQ82PghAfMImL7fiF1mntwiSVkPTbbi/WZx2CQ9e4hmeQxGBB9EYKJDR3ifBg3D32QEvhNxXeVTZQl5Fpb9a8q0ahwrqlAnL85ohkc6VQqs6zGO//PO/yw/L3eJxGv7Q/np5v7y7/3ZLKd2GUnqjGcrRUPtv66EPLoN47q7gAFHc7A4fojRgtL80dhgSR8FNHIXk7vBlkwcUlIwm+YWd+pB1nZ9pLdaI1qkGgPdVr6NXgPeCRiNIqc+m/HkQv6C3Y67kdFtl4qjEJ6P+pL2u2IlS0rx2Cq9NqSDmjFl8VIkDCmd8IEu75F56tSZKQzfCuqPLjCVLau+sxZ+TvnDd92rV0KmUplq7cIIcpX7xZPOOFr/JXnUUs6suT8haA/ewCG2igGS72z1FIy/eWPGzHrdjkiY7kpCBFHTAekudpYSHlKByAzUifpLSSfkaqbxaQ39Sohb0q07K4PYtJLlIGHsjwV+9UXVZBds2SgcoAtoD0G1X+qp1VFyqBrOOqpJRv5kVWhPXCkJK7ZNzJcdaFdXqGUG+dofaxbL2QpMiG0cJFIm+cN+DMfjXaY9PMl87FoZgZT2DiUzxpWuKQ455uq9hw7+sKHUaKYFn6rj66l2U0Uu0XMoc41VD71xbl80sljhhz+zJLAgJ7qyVO+F7oRWFjuFhtG8B49VCZmAIlu0FPpWfbHBMaikySp09Somv4HUN546jweMl4UdWZtfzFTzFkSAYFXJ+fGGoMgtTCe5qhwkURT0qV712mAAzVKLC1DStfeEn14uQ8Ae+PVThTz/F0g5pBcy71QX0FLTZy8T21vHXIlXB8aWwOEwgxpQKa3PL1iZQLGkwh9aAPmzdabyI6Kznnu+mLHaVWTGaFjeVS0YKa3QPb36xX8XEx7q0sVHONWXsdJ4MnlrrJ2e9gH/NLTuMFz7/yN8gSuEJ/iTvEGxoj4tBYkTmOGoHfGsVrcL+IQqUO7jUOyATRNyCcoeodwjlFvB0fInyJ8G+xetvVaV3aq++4UuxPBQItpeeokD2MpLlfxFPpOYnAByqviUr5t/S70CbuuiYlhjfCJcU0mMgC3HcyrDhmzUVfOGV3x5LKo9IpEOZ7OO5Gf99/9BOnrqfkOPk0tSJapmUxgNoXxbvtXQ68WgWDhfw1crZBEWzWlgakxR7kp6smgCnOwdSyBLWN1jWCFLoJCX05oSgJqhJ1XQYRhdgtccuwGU95c5NgClUL2W1QfQApr4h6QWeWwBzbQFcxhesDeLPDYCP5O6CsvGn0/+3oVbZLxeS9ralNELqC9OX2n8jAvTX/Zf6/gyu5jAQkC4MDAGRparPCKhUVPQCVhgOAiJDt2cE1D4C0hkREBL4MwQ6kr0pSQi/AgZi1ysDwUAimZV72iCoNgUGBoJEMpoRreFwJcjMAsacShDNNkC0dMR9ZU/Dgt20hqu0IhFGa/NMhhhOfY51LLbc/xyTju7Jz/Hg+Jj0Yn8FfaErnfEyPPS9aBPoAd/ACVneezMQjfg/ -------------------------------------------------------------------------------- /doc/PULP_CLUSTER.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulp-platform/pulp_cluster/a67e564cdad99b219ad6ae4c3a0ed7fab6325166/doc/PULP_CLUSTER.pdf -------------------------------------------------------------------------------- /doc/PULP_CLUSTER.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulp-platform/pulp_cluster/a67e564cdad99b219ad6ae4c3a0ed7fab6325166/doc/PULP_CLUSTER.png -------------------------------------------------------------------------------- /env/astral-env.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | # set up environment variables for rtl simulation, pulp-runtime and freertos 6 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 7 | 8 | if (hostname | grep -qE "\.ee\.ethz\.ch$") ; then 9 | export PULP_RUNTIME_GCC_TOOLCHAIN=/usr/pack/riscv-1.0-kgf/pulp-gcc-1.0.16 10 | end 11 | 12 | source "$ROOTD/pulp-runtime/configs/astral-cluster.sh" 13 | source "$ROOTD/scripts/vsim.sh" 14 | -------------------------------------------------------------------------------- /env/carfield-env.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | # set up environment variables for rtl simulation, pulp-runtime and freertos 6 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 7 | 8 | if (hostname | grep -qE "\.ee\.ethz\.ch$") ; then 9 | export PULP_RUNTIME_GCC_TOOLCHAIN=/usr/pack/riscv-1.0-kgf/pulp-gcc-1.0.16 10 | fi 11 | 12 | source "$ROOTD/pulp-runtime/configs/carfield-cluster.sh" 13 | source "$ROOTD/scripts/vsim.sh" 14 | -------------------------------------------------------------------------------- /env/env.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | # set up environment variables for rtl simulation, pulp-runtime and freertos 6 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 7 | 8 | if (hostname | grep -qE "\.ee\.ethz\.ch$") ; then 9 | export PULP_RUNTIME_GCC_TOOLCHAIN=/usr/pack/riscv-1.0-kgf/pulp-gcc-1.0.16 10 | fi 11 | 12 | source "$ROOTD/pulp-runtime/configs/pulp_cluster.sh" 13 | source "$ROOTD/scripts/vsim.sh" 14 | -------------------------------------------------------------------------------- /include/cluster_bus_defines.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2023 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * Collection of legacy pulp cluster defines. 13 | * 14 | */ 15 | 16 | `define NB_SLAVE 4 17 | `define NB_MASTER 3 18 | 19 | `define NB_REGION 1 20 | 21 | // MSTER PORT TO TCDM 22 | `define MASTER_0_START_ADDR 32'h1000_0000 23 | `define MASTER_0_END_ADDR 32'h101F_FFFF 24 | 25 | // MASTER PORT TO PERIPHERAL INTERCONNECT 26 | `define MASTER_1_START_ADDR 32'h1020_0000 27 | `define MASTER_1_END_ADDR 32'h103F_FFFF 28 | 29 | `define TCDM_ASSIGN_MASTER(lhs, rhs) \ 30 | assign lhs.req = rhs.req; \ 31 | assign lhs.add = rhs.add; \ 32 | assign lhs.wen = rhs.wen; \ 33 | assign lhs.wdata = rhs.wdata; \ 34 | assign lhs.be = rhs.be; \ 35 | \ 36 | assign rhs.gnt = lhs.gnt; \ 37 | assign rhs.r_valid = lhs.r_valid; \ 38 | assign rhs.r_opc = lhs.r_opc; \ 39 | assign rhs.r_rdata = lhs.r_rdata; 40 | 41 | `define TCDM_ASSIGN_SLAVE(lhs, rhs) `TCDM_ASSIGN_MASTER(rhs, lhs) 42 | -------------------------------------------------------------------------------- /include/periph_bus_defines.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2023 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | // SOC PERIPHERALS APB BUS PARAMETRES 12 | `define NB_MASTER 11 13 | 14 | // MASTER PORT TO FLL 15 | `define FLL_START_ADDR 32'h1A10_0000 16 | `define FLL_END_ADDR 32'h1A10_0FFF 17 | 18 | // MASTER PORT TO GPIO 19 | `define GPIO_START_ADDR 32'h1A10_1000 20 | `define GPIO_END_ADDR 32'h1A10_1FFF 21 | 22 | // MASTER PORT TO SPI MASTER 23 | `define UDMA_START_ADDR 32'h1A10_2000 24 | `define UDMA_END_ADDR 32'h1A10_3FFF 25 | 26 | // MASTER PORT TO SOC CONTROL 27 | `define SOC_CTRL_START_ADDR 32'h1A10_4000 28 | `define SOC_CTRL_END_ADDR 32'h1A10_4FFF 29 | 30 | // MASTER PORT TO ADV TIMER 31 | `define ADV_TIMER_START_ADDR 32'h1A10_5000 32 | `define ADV_TIMER_END_ADDR 32'h1A10_5FFF 33 | 34 | // MASTER PORT TO SOC EVENT GEN 35 | `define SOC_EVENT_GEN_START_ADDR 32'h1A10_6000 36 | `define SOC_EVENT_GEN_END_ADDR 32'h1A10_6FFF 37 | 38 | `define EU_START_ADDR 32'h1A10_9000 39 | `define EU_END_ADDR 32'h1A10_AFFF 40 | 41 | `define TIMER_START_ADDR 32'h1A10_B000 42 | `define TIMER_END_ADDR 32'h1A10_BFFF 43 | 44 | `define HWPE_START_ADDR 32'h1A10_C000 45 | `define HWPE_END_ADDR 32'h1A10_CFFF 46 | 47 | `define STDOUT_START_ADDR 32'h1A10_F000 48 | `define STDOUT_END_ADDR 32'h1A10_FFFF 49 | 50 | `define DEBUG_START_ADDR 32'h1A11_0000 51 | `define DEBUG_END_ADDR 32'h1A11_FFFF 52 | 53 | `define DUMMY_START_ADDR 32'h1A12_0000 54 | `define DUMMY_END_ADDR 32'h1A12_0008 55 | 56 | 57 | `define APB_ASSIGN_SLAVE(lhs, rhs) \ 58 | assign lhs.paddr = rhs.paddr; \ 59 | assign lhs.pwdata = rhs.pwdata; \ 60 | assign lhs.pwrite = rhs.pwrite; \ 61 | assign lhs.psel = rhs.psel; \ 62 | assign lhs.penable = rhs.penable; \ 63 | assign rhs.prdata = lhs.prdata; \ 64 | assign rhs.pready = lhs.pready; \ 65 | assign rhs.pslverr = lhs.pslverr 66 | 67 | `define APB_ASSIGN_MASTER(lhs, rhs) `APB_ASSIGN_SLAVE(rhs, lhs) 68 | -------------------------------------------------------------------------------- /include/pulp_soc_defines.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2023 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * Activate this define to exclude the cluster and speed up the FPGA deployement 13 | */ 14 | 15 | // `define EXCLUDE_CLUSTER 16 | 17 | /* 18 | * Collection of legacy pulp cluster defines. 19 | * 20 | */ 21 | 22 | `define CLUSTER_ALIAS 23 | `define PRIVATE_ICACHE 24 | `define HIERARCHY_ICACHE_32BIT 25 | `define FEATURE_ICACHE_STAT 26 | 27 | `define FC_FPU 1 28 | `define FC_FP_DIVSQRT 1 29 | 30 | // Remove the FPUs in the cluster for FPGA SYNTHESIS 31 | `ifdef FPGA_TARGET_XILINX 32 | `define CLUST_FPU 0 33 | `define CLUST_FP_DIVSQRT 0 34 | `define CLUST_SHARED_FP 0 35 | `define CLUST_SHARED_FP_DIVSQRT 0 36 | `elsif NO_FPU 37 | `define CLUST_FPU 0 38 | `define CLUST_FP_DIVSQRT 0 39 | `define CLUST_SHARED_FP 0 40 | `define CLUST_SHARED_FP_DIVSQRT 0 41 | `else 42 | `define CLUST_FPU 1 43 | `define CLUST_FP_DIVSQRT 1 44 | `define CLUST_SHARED_FP 2 45 | `define CLUST_SHARED_FP_DIVSQRT 2 46 | `endif 47 | 48 | //PARAMETRES 49 | `define NB_CLUSTERS 1 50 | `define NB_CORES 8 51 | `define NB_DMAS 4 52 | `define NB_MPERIPHS 1 53 | `define NB_SPERIPHS 12 54 | -------------------------------------------------------------------------------- /ips_list.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ETH Zurich and University of Bologna 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | 5 | # 6 | # List of IPs and relative branch/commit-hash/tag. 7 | # Uses the YAML syntax. 8 | # 9 | common_cells: 10 | commit: v1.21.0 11 | domain: [cluster, soc] 12 | axi/axi: 13 | commit: v0.29.1 14 | domain: [cluster, soc] 15 | axi/axi_slice: 16 | commit: v1.1.4 17 | domain: [cluster, soc] 18 | axi/axi2mem: 19 | commit: 6973e0434d26ba578cdb4aa69c26c1facd1a3f15 20 | domain: [soc, cluster] 21 | group: pulp-platform 22 | axi/axi2per: 23 | commit: tags/v1.0.1 24 | domain: [cluster] 25 | group: pulp-platform 26 | axi/per2axi: 27 | commit: v1.0.4 28 | domain: [soc, cluster] 29 | group: pulp-platform 30 | cluster_interconnect: 31 | commit: v1.1.1 32 | domain: [cluster] 33 | group: pulp-platform 34 | event_unit_flex: 35 | commit: 1.4.1 36 | domain: [cluster] 37 | group: pulp-platform 38 | mchan: 39 | commit: clusterv2 40 | domain: [cluster] 41 | group: pulp-platform 42 | hier-icache: 43 | commit: axi_node_dep 44 | domain: [cluster] 45 | group: pulp-platform 46 | icache-intc: 47 | commit: tags/v1.0.1 48 | domain: [cluster] 49 | group: pulp-platform 50 | icache_mp_128_pf: 51 | commit: 6f2e54102001230db9c82432bf9e011842419a48 52 | domain: [cluster] 53 | group: pulp-platform 54 | icache_private: 55 | commit: 1d4cdbcbec3ab454c09d378fc55631b60450fccd 56 | domain: [cluster] 57 | group: pulp-platform 58 | hwpe-ctrl: 59 | commit: v1.6.1 60 | group: pulp-platform 61 | domain: [soc, cluster, pulp] 62 | hwpe-stream: 63 | commit: v1.6.3 64 | group: pulp-platform 65 | domain: [soc, cluster, pulp] 66 | hci: 67 | commit: v1.0.8 68 | group: pulp-platform 69 | domain: [soc, cluster, pulp] 70 | cluster_peripherals: 71 | commit: v2.1.0 72 | domain: [cluster] 73 | group: pulp-platform 74 | fpu_interco: 75 | commit: 66b4084117546d5b748c30b5500769805f489d2f 76 | domain: [soc, cluster] 77 | group: pulp-platform 78 | hwpe-datamover-example: 79 | commit: v1.0 80 | group: pulp-platform 81 | domain: [cluster, pulp] 82 | -------------------------------------------------------------------------------- /packages/apu_package.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * apu_package.sv 13 | * Michael Gautschi 14 | */ 15 | 16 | package apu_package; 17 | 18 | parameter FPU = 1; 19 | 20 | parameter SHARED_FP = 1; 21 | parameter SHARED_DSP_MULT = SHARED_FP ? 1 : 0; // only available with shared FPU 22 | parameter SHARED_INT_DIV = SHARED_FP ? 0 : 0; // only available with shared FPU 23 | 24 | // Shared div/sqrt implementation 0=none, 1=pipelined version, 2=iterative shared unit 25 | parameter SHARED_FP_DIVSQRT = 2; 26 | 27 | //////////////////////////////////////////////////////////////////////////////////////// 28 | // IMPORTANT!! // 29 | //////////////////////////////////////////////////////////////////////////////////////// 30 | // THESE PARAMETERS HAVE TO MATCH THE ones in ips/riscv/includes/apu_core_package.sv // 31 | //////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | // by default set to 0 34 | parameter SHARED_INT_MULT = 0; 35 | 36 | // CPU side / general params 37 | parameter NARGS_CPU = 3; 38 | parameter WOP_CPU = 6; 39 | parameter NUSFLAGS_CPU = 5; 40 | parameter NDSFLAGS_CPU = 15; 41 | ///////////////////////////////////////////////////////////////////////////// 42 | // until here // 43 | ///////////////////////////////////////////////////////////////////////////// 44 | 45 | // FP-general 46 | parameter APUTYPE_FP = (SHARED_FP) ? SHARED_DSP_MULT + SHARED_INT_MULT + SHARED_INT_DIV : 0; 47 | parameter APU_FLAGS_FP = 2; 48 | 49 | // generated values 50 | parameter C_APUTYPES = (SHARED_FP) ? (SHARED_FP_DIVSQRT==1) ? APUTYPE_FP+6 : (SHARED_FP_DIVSQRT==2) ? APUTYPE_FP+5 : APUTYPE_FP+4 : SHARED_DSP_MULT + SHARED_INT_DIV + SHARED_INT_MULT; 51 | 52 | 53 | parameter WAPUTYPE = $clog2(C_APUTYPES); 54 | 55 | endpackage 56 | -------------------------------------------------------------------------------- /packages/pulp_cluster_package.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * pulp_cluster_package.sv 13 | * Davide Rossi 14 | * Michael Gautschi 15 | */ 16 | 17 | `include "pulp_soc_defines.sv" 18 | 19 | package pulp_cluster_package; 20 | 21 | import rapid_recovery_pkg::*; 22 | 23 | typedef bit [ 7:0] byte_t; 24 | typedef bit [12:0] alias_t; 25 | typedef bit [31:0] word_t; 26 | typedef bit [63:0] doub_t; 27 | 28 | // Core type 29 | typedef enum logic[1:0] { 30 | CV32, 31 | RI5CY, 32 | IBEX 33 | } core_type_e; 34 | 35 | // HWPE type 36 | typedef enum byte_t { 37 | REDMULE, 38 | NEUREKA, 39 | SOFTEX 40 | } hwpe_type_e; 41 | 42 | localparam int unsigned MAX_NUM_HWPES = 8; 43 | 44 | typedef struct { 45 | hwpe_type_e [MAX_NUM_HWPES-1:0] HwpeList; 46 | byte_t NumHwpes; 47 | } hwpe_subsystem_cfg_t; 48 | 49 | // PULP cluster configuration 50 | typedef struct { 51 | // Type of core in the cluster 52 | core_type_e CoreType; 53 | // Number of cores in the cluster 54 | byte_t NumCores; 55 | // Number of DMA TCDM plugs 56 | byte_t DmaNumPlugs; 57 | // Number of DMA outstanding transactions 58 | byte_t DmaNumOutstandingBursts; 59 | // DMA burst length in bits 60 | word_t DmaBurstLength; 61 | // Number of masters in crossbar peripherals 62 | byte_t NumMstPeriphs; 63 | // Number of slaves in crossbar peripherals 64 | byte_t NumSlvPeriphs; 65 | // Enable cluster aliasing 66 | bit ClusterAlias; 67 | // Base of the cluster alias 68 | alias_t ClusterAliasBase; 69 | // Number of internal synchronization stages 70 | byte_t NumSyncStages; 71 | // Enable HCI 72 | bit UseHci; 73 | // Size of the TCDM in bytes (power of two) 74 | word_t TcdmSize; 75 | // Number of TCDM banks (power of two) 76 | byte_t TcdmNumBank; 77 | // Enable HWPEs 78 | bit HwpePresent; 79 | // HWPEs selection and ID map 80 | hwpe_subsystem_cfg_t HwpeCfg; 81 | // Number of memory ports available for HWPEs 82 | byte_t HwpeNumPorts; 83 | // Enable the HMR Unit 84 | bit HMRPresent; 85 | // Enable double modular redundancy 86 | bit HMRDmrEnabled; 87 | // Enable triple modular redundancy 88 | bit HMRTmrEnabled; 89 | // Lock HMR into permanent DMR mode 90 | bit HMRDmrFIxed; 91 | // Lock HMR into permanent TMR mode 92 | bit HMRTmrFIxed; 93 | // Interleave DMR/TMR cores 94 | bit HMRInterleaveGrps; 95 | // Enable rapid recovery 96 | bit HMREnableRapidRecovery; 97 | // Separates voters and checkers for data 98 | bit HMRSeparateDataVoters; 99 | // Separates voters and checkers for AXI buses 100 | bit HMRSeparateAxiBus; 101 | // Number of separate voters/checkers for individual buses 102 | bit HMRNumBusVoters; 103 | // Enable ECC 104 | bit EnableECC; 105 | // Enable ECC on the hci interconnect 106 | bit ECCInterco; 107 | // Number if I$ banks 108 | byte_t iCacheNumBanks; 109 | // Number of I$ lines 110 | byte_t iCacheNumLines; 111 | // Number of I$ ways 112 | byte_t iCacheNumWays; // default is 4 113 | // Shared I$ size in bytes 114 | word_t iCacheSharedSize; // default is 4096 115 | // Private I$ size in bytes 116 | word_t iCachePrivateSize; // default is 521 117 | // Private I$ data width 118 | byte_t iCachePrivateDataWidth; 119 | // Enable reduced tag 120 | bit EnableReducedTag; 121 | // L2 size 122 | word_t L2Size; 123 | // Debug module base address 124 | doub_t DmBaseAddr; 125 | // BootROM base address 126 | doub_t BootRomBaseAddr; 127 | // Cores boot address 128 | doub_t BootAddr; 129 | // Enable private FPU 130 | bit EnablePrivateFpu; 131 | // Enable private FP division/sqrt 132 | bit EnablePrivateFpDivSqrt; 133 | // Enable shared FPUs 134 | bit EnableSharedFpu; 135 | // Enable shared FP division/sqrt 136 | bit EnableSharedFpDivSqrt; 137 | // Number of shared FPUs 138 | byte_t NumSharedFpu; 139 | // Number of AXI crossbar subordinate ports 140 | byte_t NumAxiIn; 141 | // Number of AXI crossbar manager ports 142 | byte_t NumAxiOut; 143 | // AXI ID width of crossbar subordinate ports 144 | byte_t AxiIdInWidth; 145 | // AXI ID width of crossbar manager ports 146 | byte_t AxiIdOutWidth; 147 | // AXI address width 148 | byte_t AxiAddrWidth; 149 | // AXI data width from external to cluster 150 | byte_t AxiDataInWidth; 151 | // AXI data width from cluster to external 152 | byte_t AxiDataOutWidth; 153 | // AXI user width 154 | byte_t AxiUserWidth; 155 | // AXI maximum subordinate transaction per ID 156 | byte_t AxiMaxInTrans; 157 | // AXI maximum manager transaction per ID 158 | byte_t AxiMaxOutTrans; 159 | // Log depth of AXI CDC FIFOs 160 | byte_t AxiCdcLogDepth; // old LOG_DEPTH 161 | // Sinchronization stages of AXI CDC FIFOs 162 | byte_t AxiCdcSyncStages; 163 | // Input synchronization stages 164 | byte_t SyncStages; 165 | // Cluster base address 166 | doub_t ClusterBaseAddr; 167 | // Cluster peripherals offset 168 | doub_t ClusterPeriphOffs; 169 | // Cluster base external offset 170 | doub_t ClusterExternalOffs; 171 | // Address remap for virtualization 172 | bit EnableRemapAddress; 173 | // Enable Snitch ICache 174 | bit SnitchICache; 175 | } pulp_cluster_cfg_t; 176 | 177 | localparam int unsigned NB_SPERIPH_PLUGS_EU = 2; 178 | 179 | // number of master and slave cluster periphs 180 | parameter int unsigned NB_MPERIPHS = `NB_MPERIPHS; 181 | parameter int unsigned NB_SPERIPHS = `NB_SPERIPHS; 182 | 183 | // position of peripherals on slave port of periph interconnect 184 | localparam int unsigned SPER_EOC_ID = 0; // 0x0000 - 0x0400 185 | localparam int unsigned SPER_TIMER_ID = 1; // 0x0400 - 0x0800 186 | localparam int unsigned SPER_EVENT_U_ID = 2; // 0x0800 - 0x1000 187 | // 3 also used for Event Unit 188 | localparam int unsigned SPER_HWPE_ID = 4; // 0x1000 - 0x1400 189 | localparam int unsigned SPER_ICACHE_CTRL = 5; // 0x1400 - 0x1800 190 | localparam int unsigned SPER_DMA_CL_ID = 6; // 0x1800 - 0x1C00 191 | localparam int unsigned SPER_DMA_FC_ID = 7; // 0x1C00 - 0x2000 192 | localparam int unsigned SPER_HMR_UNIT_ID = 8; // 0x2000 - 0x2400 193 | localparam int unsigned SPER_TCDM_SCRUBBER_ID = 9; // 0x2400 - 0x2800 194 | localparam int unsigned SPER_HWPE_HCI_ECC_ID = 10; // 0x2800 - 0x3200 195 | localparam int unsigned SPER_EXT_ID = 11; // -> unmapped, directed to error 196 | localparam int unsigned SPER_ERROR_ID = 12; // -> unmapped, directed to error 197 | 198 | // The following parameters refer to the cluster AXI crossbar 199 | localparam byte_t NumAxiSubordinatePorts = 4; 200 | localparam byte_t NumAxiManagerPorts = 3; 201 | localparam byte_t AxiSubordinateIdwidth = 4; 202 | localparam byte_t AxiManagerIdwidth = AxiSubordinateIdwidth + $clog2(NumAxiSubordinatePorts); 203 | localparam int unsigned NumCores = `NB_CORES; 204 | localparam int unsigned NumDmas = `NB_DMAS; 205 | 206 | localparam pulp_cluster_cfg_t PulpClusterDefaultCfg = '{ 207 | CoreType: RI5CY, 208 | NumCores: NumCores, 209 | DmaNumPlugs: NumDmas, 210 | DmaNumOutstandingBursts: 8, 211 | DmaBurstLength: 256, 212 | NumMstPeriphs: NB_MPERIPHS, 213 | NumSlvPeriphs: NB_SPERIPHS, 214 | ClusterAlias: 1, 215 | ClusterAliasBase: 'h0, 216 | NumSyncStages: 3, 217 | UseHci: 1, 218 | TcdmSize: 128*1024, 219 | TcdmNumBank: 16, 220 | HwpePresent: 1, 221 | HwpeCfg: '{NumHwpes: 3, HwpeList: {SOFTEX, NEUREKA, REDMULE}}, 222 | HwpeNumPorts: 9, 223 | HMRPresent: 1, 224 | HMRDmrEnabled: 1, 225 | HMRTmrEnabled: 1, 226 | HMRDmrFIxed: 0, 227 | HMRTmrFIxed: 0, 228 | HMRInterleaveGrps: 1, 229 | HMREnableRapidRecovery: 1, 230 | HMRSeparateDataVoters:1, 231 | HMRSeparateAxiBus:0, 232 | HMRNumBusVoters:1, 233 | EnableECC: 1, 234 | ECCInterco: 1, 235 | iCacheNumBanks: 2, 236 | iCacheNumLines: 1, 237 | iCacheNumWays: 4, 238 | iCacheSharedSize: 4*1024, 239 | iCachePrivateSize: 512, 240 | iCachePrivateDataWidth: 32, 241 | EnableReducedTag: 1, 242 | L2Size: 1000*1024, 243 | DmBaseAddr: 'h1A110000, 244 | BootRomBaseAddr: 'h1A000000, 245 | BootAddr: 'h1C000000, 246 | EnablePrivateFpu: 1, 247 | EnablePrivateFpDivSqrt: 0, 248 | EnableSharedFpu: 0, 249 | EnableSharedFpDivSqrt: 0, 250 | NumSharedFpu: 0, 251 | NumAxiIn: NumAxiSubordinatePorts, 252 | NumAxiOut: NumAxiManagerPorts, 253 | AxiIdInWidth: AxiSubordinateIdwidth, 254 | AxiIdOutWidth:AxiManagerIdwidth, 255 | AxiAddrWidth: 48, 256 | AxiDataInWidth: 64, 257 | AxiDataOutWidth: 64, 258 | AxiUserWidth: 10, 259 | AxiMaxInTrans: 64, 260 | AxiMaxOutTrans: 64, 261 | AxiCdcLogDepth: 3, 262 | AxiCdcSyncStages: 3, 263 | SyncStages: 3, 264 | ClusterBaseAddr: 'h10000000, 265 | ClusterPeriphOffs: 'h00200000, 266 | ClusterExternalOffs: 'h00400000, 267 | EnableRemapAddress: 0, 268 | SnitchICache: 0, 269 | default: '0 270 | }; 271 | 272 | typedef struct packed { 273 | logic gnt; 274 | logic [31:0] r_data; 275 | logic r_valid; 276 | } core_data_rsp_t; 277 | 278 | typedef struct packed { 279 | logic req; 280 | logic [31:0] add; 281 | logic we; 282 | logic [31:0] data; 283 | logic [3:0] be; 284 | } core_data_req_t; 285 | 286 | typedef struct packed { 287 | logic clock_en; 288 | logic [31:0] boot_addr; 289 | logic [3:0] core_id; 290 | logic [5:0] cluster_id; 291 | logic instr_gnt; 292 | logic instr_rvalid; 293 | logic [31:0] instr_rdata; 294 | logic data_gnt; 295 | logic data_rvalid; 296 | logic [31:0] data_rdata; 297 | logic irq_req; 298 | logic [4:0] irq_id; 299 | } core_inputs_t; 300 | 301 | typedef struct packed { 302 | logic instr_req; 303 | logic [31:0] instr_addr; 304 | logic data_req; 305 | logic data_we; 306 | logic [3:0] data_be; 307 | logic [31:0] data_add; 308 | logic [31:0] data_wdata; 309 | logic irq_ack; 310 | logic [4:0] irq_ack_id; 311 | logic debug_halted; 312 | logic core_busy; 313 | } core_outputs_t; 314 | 315 | typedef struct packed { 316 | rapid_recovery_pkg::regfile_write_t regfile_backup; 317 | rapid_recovery_pkg::csrs_intf_t csr_backup; 318 | rapid_recovery_pkg::pc_intf_t pc_backup; 319 | } core_backup_t; 320 | 321 | endpackage 322 | -------------------------------------------------------------------------------- /regression.mk: -------------------------------------------------------------------------------- 1 | ## Clone regression tests for bare-metal verification 2 | TARGET ?= pulp_cluster 3 | 4 | .PHONY: test-rt-par-bare 5 | ## Run only parallel tests on pulp-runtime 6 | test-rt-par-bare: pulp-runtime regression_tests 7 | cd $(REGRESSIONS) && $(bwruntest) --proc-verbose -v \ 8 | -t 3600 --yaml --max-procs 2 \ 9 | -o $(REGRESSIONS)/$(TARGET)/runtime-parallel.xml $(REGRESSIONS)/parallel-bare-tests.yaml 10 | 11 | .PHONY: test-rt-mchan 12 | ## Run mchan tests on pulp-runtime 13 | test-rt-mchan: pulp-runtime regression_tests 14 | cd $(REGRESSIONS) && $(bwruntest) --proc-verbose -v \ 15 | -t 7200 --yaml --max-procs 2 \ 16 | -o $(REGRESSIONS)/$(TARGET)/runtime-mchan.xml $(REGRESSIONS)/pulp_cluster-mchan-tests.yaml 17 | 18 | .PHONY: test-rt-$(TARGET) 19 | ## Run Carfield tests on pulp-runtime 20 | test-rt-$(TARGET): pulp-runtime regression_tests 21 | cd $(REGRESSIONS) && $(bwruntest) --proc-verbose -v \ 22 | -t 3600 --yaml --max-procs 2 \ 23 | -o $(REGRESSIONS)/$(TARGET)/runtime-mchan.xml $(REGRESSIONS)/$(TARGET).yaml 24 | -------------------------------------------------------------------------------- /rtl/axi2mem_wrap.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * axi2mem_wrap.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module axi2mem_wrap 20 | #( 21 | parameter int unsigned NB_DMAS = 4, 22 | parameter int unsigned AXI_ADDR_WIDTH = 32, 23 | parameter int unsigned AXI_DATA_WIDTH = 64, 24 | parameter int unsigned AXI_USER_WIDTH = 6, 25 | parameter int unsigned AXI_ID_WIDTH = 6, 26 | parameter type axi_req_t = logic, 27 | parameter type axi_resp_t = logic 28 | ) 29 | ( 30 | input logic clk_i, 31 | input logic rst_ni, 32 | input logic test_en_i, 33 | input axi_req_t axi_slave_req_i, 34 | output axi_resp_t axi_slave_resp_o, 35 | hci_core_intf.initiator tcdm_master[0:NB_DMAS-1], 36 | output logic busy_o 37 | ); 38 | 39 | logic [NB_DMAS-1:0][31:0] s_tcdm_bus_wdata; 40 | logic [NB_DMAS-1:0][31:0] s_tcdm_bus_add; 41 | logic [NB_DMAS-1:0] s_tcdm_bus_req; 42 | logic [NB_DMAS-1:0] s_tcdm_bus_wen; 43 | logic [NB_DMAS-1:0][3:0] s_tcdm_bus_be; 44 | logic [NB_DMAS-1:0] s_tcdm_bus_gnt; 45 | logic [NB_DMAS-1:0][31:0] s_tcdm_bus_r_rdata; 46 | logic [NB_DMAS-1:0] s_tcdm_bus_r_valid; 47 | 48 | generate 49 | for (genvar i=0; i 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module axi2per_wrap 20 | #( 21 | parameter int unsigned PER_ADDR_WIDTH = 32, 22 | parameter int unsigned PER_ID_WIDTH = 5, 23 | parameter int unsigned AXI_ADDR_WIDTH = 32, 24 | parameter int unsigned AXI_DATA_WIDTH = 64, 25 | parameter int unsigned AXI_USER_WIDTH = 6, 26 | parameter int unsigned AXI_ID_WIDTH = 6, 27 | parameter int unsigned BUFFER_DEPTH = 2, 28 | parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH/8, 29 | parameter type axi_req_t = logic, 30 | parameter type axi_resp_t = logic 31 | ) 32 | ( 33 | input logic clk_i, 34 | input logic rst_ni, 35 | input logic test_en_i, 36 | input axi_req_t axi_slave_req_i, 37 | output axi_resp_t axi_slave_resp_o, 38 | XBAR_TCDM_BUS.Master periph_master, 39 | output logic busy_o 40 | ); 41 | 42 | axi2per #( 43 | .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), 44 | .PER_ID_WIDTH ( PER_ID_WIDTH ), 45 | .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), 46 | .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), 47 | .AXI_USER_WIDTH ( AXI_USER_WIDTH ), 48 | .AXI_ID_WIDTH ( AXI_ID_WIDTH ), 49 | .BUFFER_DEPTH ( BUFFER_DEPTH ) 50 | ) axi2per_i ( 51 | .clk_i ( clk_i ), 52 | .rst_ni ( rst_ni ), 53 | .test_en_i ( test_en_i ), 54 | 55 | .axi_slave_aw_valid_i ( axi_slave_req_i.aw_valid ), 56 | .axi_slave_aw_addr_i ( axi_slave_req_i.aw.addr ), 57 | .axi_slave_aw_prot_i ( axi_slave_req_i.aw.prot ), 58 | .axi_slave_aw_region_i ( axi_slave_req_i.aw.region ), 59 | .axi_slave_aw_len_i ( axi_slave_req_i.aw.len ), 60 | .axi_slave_aw_size_i ( axi_slave_req_i.aw.size ), 61 | .axi_slave_aw_burst_i ( axi_slave_req_i.aw.burst ), 62 | .axi_slave_aw_lock_i ( axi_slave_req_i.aw.lock ), 63 | .axi_slave_aw_cache_i ( axi_slave_req_i.aw.cache ), 64 | .axi_slave_aw_qos_i ( axi_slave_req_i.aw.qos ), 65 | .axi_slave_aw_id_i ( axi_slave_req_i.aw.id ), 66 | .axi_slave_aw_user_i ( axi_slave_req_i.aw.user ), 67 | .axi_slave_aw_ready_o ( axi_slave_resp_o.aw_ready ), 68 | 69 | .axi_slave_ar_valid_i ( axi_slave_req_i.ar_valid ), 70 | .axi_slave_ar_addr_i ( axi_slave_req_i.ar.addr ), 71 | .axi_slave_ar_prot_i ( axi_slave_req_i.ar.prot ), 72 | .axi_slave_ar_region_i ( axi_slave_req_i.ar.region ), 73 | .axi_slave_ar_len_i ( axi_slave_req_i.ar.len ), 74 | .axi_slave_ar_size_i ( axi_slave_req_i.ar.size ), 75 | .axi_slave_ar_burst_i ( axi_slave_req_i.ar.burst ), 76 | .axi_slave_ar_lock_i ( axi_slave_req_i.ar.lock ), 77 | .axi_slave_ar_cache_i ( axi_slave_req_i.ar.cache ), 78 | .axi_slave_ar_qos_i ( axi_slave_req_i.ar.qos ), 79 | .axi_slave_ar_id_i ( axi_slave_req_i.ar.id ), 80 | .axi_slave_ar_user_i ( axi_slave_req_i.ar.user ), 81 | .axi_slave_ar_ready_o ( axi_slave_resp_o.ar_ready ), 82 | 83 | .axi_slave_w_valid_i ( axi_slave_req_i.w_valid ), 84 | .axi_slave_w_data_i ( axi_slave_req_i.w.data ), 85 | .axi_slave_w_strb_i ( axi_slave_req_i.w.strb ), 86 | .axi_slave_w_user_i ( axi_slave_req_i.w.user ), 87 | .axi_slave_w_last_i ( axi_slave_req_i.w.last ), 88 | .axi_slave_w_ready_o ( axi_slave_resp_o.w_ready ), 89 | 90 | .axi_slave_r_valid_o ( axi_slave_resp_o.r_valid ), 91 | .axi_slave_r_data_o ( axi_slave_resp_o.r.data ), 92 | .axi_slave_r_resp_o ( axi_slave_resp_o.r.resp ), 93 | .axi_slave_r_last_o ( axi_slave_resp_o.r.last ), 94 | .axi_slave_r_id_o ( axi_slave_resp_o.r.id ), 95 | .axi_slave_r_user_o ( axi_slave_resp_o.r.user ), 96 | .axi_slave_r_ready_i ( axi_slave_req_i.r_ready ), 97 | 98 | .axi_slave_b_valid_o ( axi_slave_resp_o.b_valid ), 99 | .axi_slave_b_resp_o ( axi_slave_resp_o.b.resp ), 100 | .axi_slave_b_id_o ( axi_slave_resp_o.b.id ), 101 | .axi_slave_b_user_o ( axi_slave_resp_o.b.user ), 102 | .axi_slave_b_ready_i ( axi_slave_req_i.b_ready ), 103 | 104 | .per_master_req_o ( periph_master.req ), 105 | .per_master_add_o ( periph_master.add ), 106 | .per_master_we_no ( periph_master.wen ), 107 | .per_master_wdata_o ( periph_master.wdata ), 108 | .per_master_be_o ( periph_master.be ), 109 | .per_master_gnt_i ( periph_master.gnt ), 110 | 111 | .per_master_r_valid_i ( periph_master.r_valid ), 112 | .per_master_r_opc_i ( periph_master.r_opc ), 113 | .per_master_r_rdata_i ( periph_master.r_rdata ), 114 | 115 | .busy_o(busy_o) 116 | ); 117 | 118 | endmodule 119 | -------------------------------------------------------------------------------- /rtl/cluster_bus_wrap.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * cluster_bus_wrap.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | 20 | `include "axi/assign.svh" 21 | `include "axi/typedef.svh" 22 | 23 | module cluster_bus_wrap 24 | import axi_pkg::xbar_cfg_t; 25 | #( 26 | parameter int unsigned NB_MASTER = 3 , 27 | parameter int unsigned NB_SLAVE = 4 , 28 | parameter int unsigned NB_CORES = 4 , 29 | parameter int unsigned AXI_ADDR_WIDTH = 32, 30 | parameter int unsigned AXI_DATA_WIDTH = 64, 31 | parameter int unsigned AXI_ID_IN_WIDTH = 4 , 32 | parameter int unsigned AXI_ID_OUT_WIDTH = 6 , 33 | parameter int unsigned AXI_USER_WIDTH = 6 , 34 | parameter int unsigned DMA_NB_OUTSND_BURSTS = 8 , 35 | parameter int unsigned TCDM_SIZE = 0, 36 | parameter logic [AXI_ADDR_WIDTH-1:0] BaseAddr = 'h10000000, 37 | parameter logic [AXI_ADDR_WIDTH-1:0] ClusterPeripheralsOffs = 'h00200000, 38 | parameter logic [AXI_ADDR_WIDTH-1:0] ClusterExternalOffs = 'h00400000, 39 | parameter type slave_req_t = logic, 40 | parameter type slave_resp_t = logic, 41 | parameter type master_req_t = logic, 42 | parameter type master_resp_t = logic, 43 | parameter type slave_aw_chan_t = logic, 44 | parameter type master_aw_chan_t = logic, 45 | parameter type w_chan_t = logic, 46 | parameter type slave_b_chan_t = logic, 47 | parameter type master_b_chan_t = logic, 48 | parameter type slave_ar_chan_t = logic, 49 | parameter type master_ar_chan_t = logic, 50 | parameter type slave_r_chan_t = logic, 51 | parameter type master_r_chan_t = logic 52 | ) 53 | ( 54 | input logic clk_i, 55 | input logic rst_ni, 56 | input logic test_en_i, 57 | input logic [5:0] cluster_id_i, 58 | input slave_req_t data_slave_req_i, 59 | output slave_resp_t data_slave_resp_o, 60 | input slave_req_t instr_slave_req_i, 61 | output slave_resp_t instr_slave_resp_o, 62 | input slave_req_t dma_slave_req_i, 63 | output slave_resp_t dma_slave_resp_o, 64 | input slave_req_t ext_slave_req_i, 65 | output slave_resp_t ext_slave_resp_o, 66 | //INITIATOR 67 | output master_req_t tcdm_master_req_o, 68 | input master_resp_t tcdm_master_resp_i, 69 | output master_req_t periph_master_req_o, 70 | input master_resp_t periph_master_resp_i, 71 | output master_req_t ext_master_req_o, 72 | input master_resp_t ext_master_resp_i 73 | ); 74 | 75 | //Ensure that AXI_ID out width has the correct size with an elaboration system task 76 | if (AXI_ID_OUT_WIDTH < AXI_ID_IN_WIDTH + $clog2(NB_SLAVE)) 77 | $error("ID width of AXI output ports is to small. The output id width must be input ID width + clog2() which is %d but it was %d", AXI_ID_IN_WIDTH + $clog2(NB_SLAVE), AXI_ID_OUT_WIDTH); 78 | else if (AXI_ID_OUT_WIDTH > AXI_ID_IN_WIDTH + $clog2(NB_SLAVE)) 79 | $warning("ID width of the AXI output port has the wrong length. It is larger than the required value. Trim it to the right length to get rid of this warning."); 80 | 81 | if (TCDM_SIZE == 0) 82 | $fatal(1,"TCDM size must be non-zero!"); 83 | if (TCDM_SIZE>ClusterPeripheralsOffs) // The TCDM must be entirely addressable 84 | $fatal(1,"TCDM size exceeds available address space in cluster bus!"); 85 | 86 | // Crossbar 87 | slave_req_t [NB_SLAVE-1:0] axi_slave_reqs; 88 | slave_resp_t [NB_SLAVE-1:0] axi_slave_resps; 89 | 90 | // assign here your axi slaves 91 | `AXI_ASSIGN_REQ_STRUCT(axi_slave_reqs[0], data_slave_req_i) 92 | `AXI_ASSIGN_RESP_STRUCT(data_slave_resp_o, axi_slave_resps[0]) 93 | `AXI_ASSIGN_REQ_STRUCT(axi_slave_reqs[1], instr_slave_req_i) 94 | `AXI_ASSIGN_RESP_STRUCT(instr_slave_resp_o, axi_slave_resps[1]) 95 | `AXI_ASSIGN_REQ_STRUCT(axi_slave_reqs[2], dma_slave_req_i) 96 | `AXI_ASSIGN_RESP_STRUCT(dma_slave_resp_o, axi_slave_resps[2]) 97 | `AXI_ASSIGN_REQ_STRUCT(axi_slave_reqs[3], ext_slave_req_i) 98 | `AXI_ASSIGN_RESP_STRUCT(ext_slave_resp_o, axi_slave_resps[3]) 99 | 100 | master_req_t [NB_MASTER-1:0] axi_master_reqs; 101 | master_resp_t [NB_MASTER-1:0] axi_master_resps; 102 | 103 | // assign here your axi masters 104 | `AXI_ASSIGN_REQ_STRUCT(tcdm_master_req_o, axi_master_reqs[0]) 105 | `AXI_ASSIGN_RESP_STRUCT(axi_master_resps[0], tcdm_master_resp_i) 106 | `AXI_ASSIGN_REQ_STRUCT(periph_master_req_o, axi_master_reqs[1]) 107 | `AXI_ASSIGN_RESP_STRUCT(axi_master_resps[1], periph_master_resp_i) 108 | `AXI_ASSIGN_REQ_STRUCT(ext_master_req_o, axi_master_reqs[2]) 109 | `AXI_ASSIGN_RESP_STRUCT(axi_master_resps[2], ext_master_resp_i) 110 | 111 | // Address Map Rule 112 | typedef struct packed { 113 | logic [AXI_ADDR_WIDTH-1:0] idx ; 114 | logic [AXI_ADDR_WIDTH-1:0] start_addr; 115 | logic [AXI_ADDR_WIDTH-1:0] end_addr ; 116 | } addr_map_rule_t; 117 | 118 | // address map 119 | logic [AXI_ADDR_WIDTH-1:0] cluster_base_addr; 120 | assign cluster_base_addr = BaseAddr + ( cluster_id_i << 22); 121 | localparam int unsigned N_RULES = 4; 122 | addr_map_rule_t [N_RULES-1:0] addr_map; 123 | 124 | assign addr_map[0] = '{ // TCDM 125 | idx: 0, 126 | start_addr: cluster_base_addr, 127 | end_addr: cluster_base_addr + TCDM_SIZE 128 | }; 129 | assign addr_map[1] = '{ // Peripherals 130 | idx: 1, 131 | start_addr: cluster_base_addr + ClusterPeripheralsOffs, 132 | end_addr: cluster_base_addr + ClusterExternalOffs 133 | }; 134 | assign addr_map[2] = '{ // everything above cluster to ext_slave 135 | idx: 2, 136 | start_addr: cluster_base_addr + ClusterExternalOffs, 137 | end_addr: 32'hFFFF_FFFF 138 | }; 139 | assign addr_map[3] = '{ // everything below cluster 140 | idx: 2, 141 | start_addr: 'h0, 142 | end_addr: cluster_base_addr 143 | }; 144 | 145 | localparam int unsigned MAX_TXNS_PER_SLV_PORT = (DMA_NB_OUTSND_BURSTS > NB_CORES) ? 146 | DMA_NB_OUTSND_BURSTS : NB_CORES; 147 | 148 | localparam xbar_cfg_t AXI_XBAR_CFG = '{ 149 | NoSlvPorts: NB_SLAVE, 150 | NoMstPorts: NB_MASTER, 151 | MaxMstTrans: MAX_TXNS_PER_SLV_PORT, //The TCDM ports do not support 152 | //outstanding transactiions anyways 153 | MaxSlvTrans: DMA_NB_OUTSND_BURSTS + NB_CORES, //Allow up to 4 in-flight transactions 154 | //per slave port 155 | FallThrough: 1'b0, //Use the reccomended default config 156 | LatencyMode: axi_pkg::NO_LATENCY, // CUT_ALL_AX | axi_pkg::DemuxW, 157 | PipelineStages: 0, 158 | AxiIdWidthSlvPorts: AXI_ID_IN_WIDTH, 159 | AxiIdUsedSlvPorts: AXI_ID_IN_WIDTH, 160 | UniqueIds: 1'b0, 161 | AxiAddrWidth: AXI_ADDR_WIDTH, 162 | AxiDataWidth: AXI_DATA_WIDTH, 163 | NoAddrRules: N_RULES 164 | }; 165 | 166 | 167 | axi_xbar #( 168 | .Cfg ( AXI_XBAR_CFG ), 169 | .ATOPs ( 1'b0 ), 170 | .Connectivity ( '1 ), 171 | .slv_aw_chan_t ( slave_aw_chan_t ), 172 | .mst_aw_chan_t ( master_aw_chan_t ), 173 | .w_chan_t ( w_chan_t ), 174 | .slv_b_chan_t ( slave_b_chan_t ), 175 | .mst_b_chan_t ( master_b_chan_t ), 176 | .slv_ar_chan_t ( slave_ar_chan_t ), 177 | .mst_ar_chan_t ( master_ar_chan_t ), 178 | .slv_r_chan_t ( slave_r_chan_t ), 179 | .mst_r_chan_t ( master_r_chan_t ), 180 | .slv_req_t ( slave_req_t ), 181 | .slv_resp_t ( slave_resp_t ), 182 | .mst_req_t ( master_req_t ), 183 | .mst_resp_t ( master_resp_t ), 184 | .rule_t ( addr_map_rule_t ) 185 | ) i_xbar ( 186 | .clk_i, 187 | .rst_ni, 188 | .test_i ( test_en_i ), 189 | .slv_ports_req_i ( axi_slave_reqs ), 190 | .slv_ports_resp_o ( axi_slave_resps ), 191 | .mst_ports_req_o ( axi_master_reqs ), 192 | .mst_ports_resp_i ( axi_master_resps ), 193 | .addr_map_i ( addr_map ), 194 | .en_default_mst_port_i ( '0 ), // disable default master port for all slave ports 195 | .default_mst_port_i ( '0 ) 196 | ); 197 | 198 | endmodule 199 | 200 | 201 | -------------------------------------------------------------------------------- /rtl/cluster_clock_gate.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * cluster_clock_gate.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module cluster_clock_gate 20 | #( 21 | parameter int unsigned NB_CORES = 4 22 | ) ( 23 | input logic clk_i, 24 | input logic rstn_i, 25 | input logic test_mode_i, 26 | input logic cluster_cg_en_i, 27 | input logic cluster_int_busy_i, 28 | input logic [NB_CORES-1:0] cores_busy_i, 29 | input logic events_i, 30 | input logic incoming_req_i, 31 | output logic isolate_cluster_o, 32 | output logic cluster_clk_o 33 | 34 | ); 35 | 36 | logic s_somebusy; 37 | logic [3:0] r_clockgate; 38 | logic s_clockenable; 39 | logic [1:0] r_events_sync; 40 | logic s_events_sync; 41 | 42 | assign isolate_cluster_o = r_clockgate; 43 | 44 | assign s_somebusy = cluster_int_busy_i | ( |cores_busy_i); 45 | 46 | assign s_clockenable = ~(&r_clockgate); 47 | 48 | always_ff @(posedge clk_i or negedge rstn_i) 49 | begin : proc_evnt_sync 50 | if(~rstn_i) begin 51 | r_events_sync <= 0; 52 | end else begin 53 | r_events_sync <= {r_events_sync[0],events_i}; 54 | end 55 | end 56 | 57 | always_ff @(posedge clk_i or negedge rstn_i) 58 | begin 59 | if(~rstn_i) begin 60 | r_clockgate <= 0; 61 | end 62 | else begin 63 | if(!s_somebusy && !incoming_req_i && !r_events_sync[1]) 64 | r_clockgate <= {r_clockgate[2:0],cluster_cg_en_i}; 65 | else 66 | r_clockgate <= {r_clockgate[2:0],1'b0}; 67 | end 68 | end 69 | 70 | tc_clk_gating u_clkgate_cluster ( 71 | .clk_o ( cluster_clk_o ), 72 | .clk_i ( clk_i ), 73 | .en_i ( s_clockenable ), 74 | .test_en_i ( test_mode_i ) 75 | ); 76 | 77 | endmodule 78 | -------------------------------------------------------------------------------- /rtl/cluster_event_map.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * cluster_event_map.sv 13 | * Florian Glaser 14 | */ 15 | 16 | module cluster_event_map 17 | #( 18 | parameter int unsigned NB_CORES = 4 19 | ) 20 | ( 21 | // events generated inside event unit 22 | input logic [NB_CORES-1:0][7:0] sw_events_i, 23 | input logic [NB_CORES-1:0] barrier_events_i, 24 | input logic [NB_CORES-1:0] mutex_events_i, 25 | input logic [NB_CORES-1:0] dispatch_events_i, 26 | input logic periph_fifo_event_i, 27 | 28 | // events from cluster blocks 29 | input logic [NB_CORES-1:0][3:0] acc_events_i, 30 | input logic [NB_CORES-1:0][1:0] dma_events_i, 31 | input logic [NB_CORES-1:0][1:0] timer_events_i, 32 | input logic [NB_CORES-1:0][31:0] cluster_events_i, 33 | 34 | output logic [NB_CORES-1:0][31:0] events_mapped_o 35 | ); 36 | 37 | genvar I; 38 | 39 | generate 40 | for ( I = 0; I < NB_CORES; I++ ) begin : CL_EVENT_MAP 41 | assign events_mapped_o[I][31:28] = '0; 42 | assign events_mapped_o[I][27] = periph_fifo_event_i; 43 | assign events_mapped_o[I][26:25] = '0; 44 | assign events_mapped_o[I][24] = '0; 45 | assign events_mapped_o[I][23:22] = cluster_events_i[I][1:0]; 46 | assign events_mapped_o[I][21:19] = '0; 47 | 48 | assign events_mapped_o[I][18] = dispatch_events_i[I]; 49 | assign events_mapped_o[I][17] = mutex_events_i[I]; 50 | assign events_mapped_o[I][16] = barrier_events_i[I]; 51 | 52 | assign events_mapped_o[I][15:12] = acc_events_i[I]; 53 | assign events_mapped_o[I][11:10] = timer_events_i[I]; 54 | assign events_mapped_o[I][9:8] = dma_events_i[I]; 55 | assign events_mapped_o[I][7:0] = sw_events_i[I]; 56 | end 57 | endgenerate 58 | 59 | endmodule 60 | -------------------------------------------------------------------------------- /rtl/cluster_interconnect_wrap.sv: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2017 ETH Zurich, University of Bologna 3 | * All rights reserved. 4 | * 5 | * This code is under development and not yet released to the public. 6 | * Until it is released, the code is under the copyright of ETH Zurich and 7 | * the University of Bologna, and may contain confidential and/or unpublished 8 | * work. Any reuse/redistribution is strictly forbidden without written 9 | * permission from ETH Zurich. 10 | * 11 | * Bug fixes and contributions will eventually be released under the 12 | * SolderPad open hardware license in the context of the PULP platform 13 | * (http://www.pulp-platform.org), under the copyright of ETH Zurich and the 14 | * University of Bologna. 15 | */ 16 | 17 | `include "hci_helpers.svh" 18 | 19 | import hci_package::*; 20 | 21 | module cluster_interconnect_wrap 22 | #( 23 | parameter int unsigned NB_CORES = 8, 24 | parameter int unsigned HWPE_PRESENT = 1, 25 | parameter int unsigned NB_HWPE_PORTS = 9, 26 | parameter int unsigned NB_DMAS = 4, 27 | parameter int unsigned NB_MPERIPHS = 1, 28 | parameter int unsigned NB_TCDM_BANKS = 16, 29 | parameter int unsigned NB_SPERIPHS = 10, //differ 30 | 31 | parameter int unsigned DATA_WIDTH = 32, 32 | parameter int unsigned ADDR_WIDTH = 32, 33 | parameter int unsigned BE_WIDTH = DATA_WIDTH/8, 34 | parameter logic [ADDR_WIDTH-1:0] ClusterBaseAddr = 'h10000000, 35 | parameter logic [ADDR_WIDTH-1:0] ClusterPeripheralsOffs = 'h00200000, 36 | parameter logic [ADDR_WIDTH-1:0] ClusterExternalOffs = 'h00400000, 37 | 38 | //TCDM PARAMETERS 39 | parameter int unsigned TEST_SET_BIT = 20, 40 | parameter int unsigned ADDR_MEM_WIDTH = 11, 41 | parameter int unsigned LOG_CLUSTER = 5, 42 | parameter int unsigned PE_ROUTING_LSB = 10, 43 | parameter int unsigned PE_ROUTING_MSB = PE_ROUTING_LSB+$clog2(NB_SPERIPHS)-1, //differ 44 | parameter int unsigned CLUSTER_ALIAS = 1, 45 | parameter int unsigned CLUSTER_ALIAS_BASE = 12'h000, 46 | 47 | parameter int unsigned USE_HETEROGENEOUS_INTERCONNECT = 1, 48 | parameter int unsigned USE_ECC_INTERCONNECT = 0, 49 | parameter hci_package::hci_size_parameter_t HCI_CORE_SIZE = '0, 50 | parameter hci_package::hci_size_parameter_t HCI_HWPE_SIZE = '0, 51 | parameter hci_package::hci_size_parameter_t HCI_MEM_SIZE = '0 52 | ) 53 | ( 54 | input logic clk_i, 55 | input logic rst_ni, 56 | input logic [5:0] cluster_id_i, 57 | XBAR_PERIPH_BUS.Slave hci_ecc_periph_slave, 58 | hci_core_intf.target core_tcdm_slave [0 : NB_CORES-1 ], 59 | hci_core_intf.target hwpe_tcdm_slave [0 : 0 ], 60 | XBAR_PERIPH_BUS.Slave core_periph_slave [NB_CORES-1 : 0 ], 61 | hci_core_intf.target ext_slave [0 : 3 ], 62 | hci_core_intf.target dma_slave [0 : NB_DMAS-1 ], 63 | XBAR_TCDM_BUS.Slave mperiph_slave [NB_MPERIPHS-1 : 0 ], 64 | hci_core_intf.initiator tcdm_sram_master [0 : NB_TCDM_BANKS-1], 65 | XBAR_PERIPH_BUS.Master speriph_master [NB_SPERIPHS-1 : 0 ], 66 | input hci_interconnect_ctrl_t hci_ctrl_i, 67 | input logic [1:0] TCDM_arb_policy_i 68 | ); 69 | 70 | localparam TCDM_ID_WIDTH = NB_CORES+NB_DMAS+4+NB_HWPE_PORTS; 71 | 72 | 73 | //-******************************************************** 74 | //-*********** HETEROGENEOUS INTERCONNECT TO TCDM ********* 75 | //-******************************************************** 76 | // Wraps the Logarithmic Interconnect + a HWPE Interconnect 77 | generate 78 | if( USE_HETEROGENEOUS_INTERCONNECT || !HWPE_PRESENT ) begin : hci_gen 79 | if (USE_ECC_INTERCONNECT) begin : gen_ecc_interco 80 | hci_ecc_interconnect #( 81 | .N_HWPE ( HWPE_PRESENT ), 82 | .N_CORE ( NB_CORES ), 83 | .N_DMA ( NB_DMAS ), 84 | .N_EXT ( 4 ), 85 | .N_MEM ( NB_TCDM_BANKS ), 86 | .IW ( TCDM_ID_WIDTH ), 87 | .TS_BIT ( TEST_SET_BIT ), 88 | //For an explanation of these macros refer to https://github.com/pulp-platform/hci/blob/v2.1.1/rtl/common/hci_helpers.svh 89 | .`HCI_SIZE_PARAM(cores) ( HCI_CORE_SIZE ), 90 | .`HCI_SIZE_PARAM(mems) ( HCI_MEM_SIZE ), 91 | .`HCI_SIZE_PARAM(hwpe) ( HCI_HWPE_SIZE ) 92 | `ifndef SYNTHESIS 93 | , 94 | .WAIVE_RQ3_ASSERT ( 1'b1 ), 95 | .WAIVE_RQ4_ASSERT ( 1'b1 ), 96 | .WAIVE_RSP3_ASSERT ( 1'b1 ), 97 | .WAIVE_RSP5_ASSERT ( 1'b1 ) 98 | `endif 99 | ) i_hci_interconnect ( 100 | .clk_i ( clk_i ), 101 | .rst_ni ( rst_ni ), 102 | .clear_i ( 1'b0 ), 103 | .ctrl_i ( hci_ctrl_i ), 104 | .periph_hci_ecc ( hci_ecc_periph_slave ), 105 | .cores ( core_tcdm_slave ), 106 | .hwpe ( hwpe_tcdm_slave [0] ), 107 | .dma ( dma_slave ), 108 | .ext ( ext_slave ), 109 | .mems ( tcdm_sram_master ) 110 | ); 111 | end else begin : gen_standard_interco 112 | hci_interconnect #( 113 | .N_HWPE ( HWPE_PRESENT ), 114 | .N_CORE ( NB_CORES ), 115 | .N_DMA ( NB_DMAS ), 116 | .N_EXT ( 4 ), 117 | .N_MEM ( NB_TCDM_BANKS ), 118 | .IW ( TCDM_ID_WIDTH ), 119 | .TS_BIT ( TEST_SET_BIT ), 120 | .`HCI_SIZE_PARAM(cores) ( HCI_CORE_SIZE ), 121 | .`HCI_SIZE_PARAM(mems) ( HCI_MEM_SIZE ), 122 | .`HCI_SIZE_PARAM(hwpe) ( HCI_HWPE_SIZE ) 123 | `ifndef SYNTHESIS 124 | , 125 | .WAIVE_RQ3_ASSERT ( 1'b1 ), 126 | .WAIVE_RQ4_ASSERT ( 1'b1 ), 127 | .WAIVE_RSP3_ASSERT ( 1'b1 ), 128 | .WAIVE_RSP5_ASSERT ( 1'b1 ) 129 | `endif 130 | ) i_hci_interconnect ( 131 | .clk_i ( clk_i ), 132 | .rst_ni ( rst_ni ), 133 | .clear_i ( 1'b0 ), 134 | .ctrl_i ( hci_ctrl_i ), 135 | .cores ( core_tcdm_slave ), 136 | .hwpe ( hwpe_tcdm_slave [0] ), 137 | .dma ( dma_slave ), 138 | .ext ( ext_slave ), 139 | .mems ( tcdm_sram_master ) 140 | ); 141 | 142 | assign hci_ecc_periph_slave.gnt = '0; 143 | assign hci_ecc_periph_slave.r_rdata = '0; 144 | assign hci_ecc_periph_slave.r_opc = '0; 145 | assign hci_ecc_periph_slave.r_id = '0; 146 | assign hci_ecc_periph_slave.r_valid = '0; 147 | end 148 | 149 | end else begin : no_hci_gen 150 | 151 | hci_core_intf #( 152 | .DW ( 32 ), 153 | .AW ( 32 ) 154 | ) core_hwpe_tcdm_slave [0:NB_CORES+NB_HWPE_PORTS-1] ( 155 | .clk ( clk_i ) 156 | ); 157 | 158 | hci_core_intf #( 159 | .DW ( NB_HWPE_PORTS*32 ), 160 | .AW ( 32 ) 161 | ) null_hwpe_tcdm_slave ( 162 | .clk ( clk_i ) 163 | ); 164 | 165 | hci_core_split #( 166 | .DW ( NB_HWPE_PORTS*32 ), 167 | .NB_OUT_CHAN ( NB_HWPE_PORTS ), 168 | .`HCI_SIZE_PARAM(tcdm_target) ( HCI_HWPE_SIZE ) 169 | ) i_hwpe_tcdm_splitter ( 170 | .clk_i ( clk_i ), 171 | .rst_ni ( rst_ni ), 172 | .clear_i ( clear_i ), 173 | .tcdm_target ( hwpe_tcdm_slave[0] ), 174 | .tcdm_initiator ( core_hwpe_tcdm_slave[NB_CORES:NB_CORES+NB_HWPE_PORTS-1] ) 175 | ); 176 | 177 | for(genvar ii=0; ii 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module cluster_timer_wrap 20 | #( 21 | parameter int unsigned ID_WIDTH = 2 22 | ) 23 | ( 24 | input logic clk_i, 25 | input logic rst_ni, 26 | input logic ref_clk_i, 27 | 28 | XBAR_PERIPH_BUS.Slave periph_slave, 29 | 30 | input logic event_lo_i, 31 | input logic event_hi_i, 32 | 33 | output logic irq_lo_o, 34 | output logic irq_hi_o, 35 | 36 | output logic busy_o 37 | ); 38 | 39 | timer_unit #( 40 | .ID_WIDTH ( ID_WIDTH ) 41 | ) timer_unit_i ( 42 | .clk_i ( clk_i ), 43 | .rst_ni ( rst_ni ), 44 | .ref_clk_i ( ref_clk_i ), 45 | 46 | .req_i ( periph_slave.req ), 47 | .addr_i ( periph_slave.add ), 48 | .wen_i ( periph_slave.wen ), 49 | .wdata_i ( periph_slave.wdata ), 50 | .be_i ( periph_slave.be ), 51 | .id_i ( periph_slave.id ), 52 | .gnt_o ( periph_slave.gnt ), 53 | 54 | .r_valid_o ( periph_slave.r_valid ), 55 | .r_opc_o ( periph_slave.r_opc ), 56 | .r_id_o ( periph_slave.r_id ), 57 | .r_rdata_o ( periph_slave.r_rdata ), 58 | 59 | .event_lo_i ( event_lo_i ), 60 | .event_hi_i ( event_hi_i ), 61 | 62 | .irq_lo_o ( irq_lo_o ), 63 | .irq_hi_o ( irq_hi_o ), 64 | 65 | .busy_o ( busy_o ) 66 | ); 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /rtl/core_demux_wrap.sv: -------------------------------------------------------------------------------- 1 | module core_demux_wrap #( 2 | parameter int unsigned AddrWidth = 32 , 3 | parameter int unsigned DataWidth = 32 , 4 | parameter int unsigned RemapAddress = 1 , 5 | parameter int unsigned ClustAlias = 1 , 6 | parameter int unsigned ClustAliasBase = 12'h000 , 7 | parameter int unsigned NumExtPerf = 5 , 8 | parameter type core_data_req_t = logic , 9 | parameter type core_data_rsp_t = logic , 10 | localparam int unsigned ByteEnable = DataWidth/8 11 | )( 12 | input logic clk_i , 13 | input logic rst_ni , 14 | input logic test_en_i , 15 | input logic clk_en_i , 16 | input logic [3:0] base_addr_i , 17 | input logic [5:0] cluster_id_i , 18 | output logic [NumExtPerf-1:0] ext_perf_o , 19 | input core_data_req_t core_data_req_i , 20 | output core_data_rsp_t core_data_rsp_o , 21 | hci_core_intf.initiator tcdm_bus_mst_o , 22 | hci_core_intf.initiator dma_ctrl_mst_o , 23 | XBAR_PERIPH_BUS.Master eventunit_bus_mst_o , 24 | XBAR_PERIPH_BUS.Master peripheral_bus_mst_o 25 | ); 26 | 27 | XBAR_PERIPH_BUS periph_demux_bus(); 28 | 29 | // bindings for tcdm_bus_mst 30 | logic tcdm_bus_mst_req; 31 | logic [AddrWidth - 1:0] tcdm_bus_mst_add; 32 | logic tcdm_bus_mst_wen; 33 | logic [DataWidth - 1:0] tcdm_bus_mst_wdata; 34 | logic [ByteEnable - 1:0] tcdm_bus_mst_be; 35 | logic tcdm_bus_mst_gnt; 36 | logic tcdm_bus_mst_r_valid; 37 | logic [DataWidth - 1:0] tcdm_bus_mst_r_rdata; 38 | 39 | // bindings initiator -> target 40 | assign tcdm_bus_mst_o.req = tcdm_bus_mst_req; 41 | assign tcdm_bus_mst_o.add = tcdm_bus_mst_add; 42 | assign tcdm_bus_mst_o.wen = tcdm_bus_mst_wen; 43 | assign tcdm_bus_mst_o.data = tcdm_bus_mst_wdata; 44 | assign tcdm_bus_mst_o.be = tcdm_bus_mst_be; 45 | // bidings target -> initiator 46 | assign tcdm_bus_mst_gnt = tcdm_bus_mst_o.gnt; 47 | assign tcdm_bus_mst_r_valid = tcdm_bus_mst_o.r_valid; 48 | assign tcdm_bus_mst_r_rdata = tcdm_bus_mst_o.r_data; 49 | 50 | // ties initiator -> target 51 | assign tcdm_bus_mst_o.r_ready = '1; 52 | assign tcdm_bus_mst_o.user = '0; 53 | assign tcdm_bus_mst_o.id = '0; 54 | assign tcdm_bus_mst_o.ecc = '0; 55 | assign tcdm_bus_mst_o.ereq = '0; 56 | assign tcdm_bus_mst_o.r_eready = '1; 57 | 58 | data_periph_demux #( 59 | .ADDR_WIDTH ( AddrWidth ), 60 | .DATA_WIDTH ( DataWidth ), 61 | .BYTE_ENABLE_BIT ( ByteEnable ), 62 | .REMAP_ADDRESS ( RemapAddress ), 63 | .CLUSTER_ALIAS ( ClustAlias ), 64 | .CLUSTER_ALIAS_BASE ( ClustAliasBase ) 65 | ) data_periph_demux_i ( 66 | .clk ( clk_i ), 67 | .rst_ni ( rst_ni ), 68 | .test_en_i ( test_en_i ), 69 | .base_addr_i ( base_addr_i ), 70 | .data_req_i ( core_data_req_i.req ), 71 | .data_add_i ( core_data_req_i.add ), 72 | .data_wen_i ( ~core_data_req_i.we ), //inverted when using OR10N 73 | .data_wdata_i ( core_data_req_i.data ), 74 | .data_be_i ( core_data_req_i.be ), 75 | .data_gnt_o ( core_data_rsp_o.gnt ), 76 | .data_r_valid_o ( core_data_rsp_o.r_valid ), 77 | .data_r_opc_o ( /* ucnconnected */ ), 78 | .data_r_rdata_o ( core_data_rsp_o.r_data ), 79 | 80 | .data_req_o_SH ( tcdm_bus_mst_req ), 81 | .data_add_o_SH ( tcdm_bus_mst_add ), 82 | .data_wen_o_SH ( tcdm_bus_mst_wen ), 83 | .data_wdata_o_SH ( tcdm_bus_mst_wdata ), 84 | .data_be_o_SH ( tcdm_bus_mst_be ), 85 | .data_gnt_i_SH ( tcdm_bus_mst_gnt ), 86 | .data_r_valid_i_SH ( tcdm_bus_mst_r_valid ), 87 | .data_r_rdata_i_SH ( tcdm_bus_mst_r_rdata ), 88 | 89 | .data_req_o_EXT ( periph_demux_bus.req ), 90 | .data_add_o_EXT ( periph_demux_bus.add ), 91 | .data_wen_o_EXT ( periph_demux_bus.wen ), 92 | .data_wdata_o_EXT ( periph_demux_bus.wdata ), 93 | .data_be_o_EXT ( periph_demux_bus.be ), 94 | .data_gnt_i_EXT ( periph_demux_bus.gnt ), 95 | .data_r_valid_i_EXT ( periph_demux_bus.r_valid ), 96 | .data_r_rdata_i_EXT ( periph_demux_bus.r_rdata ), 97 | .data_r_opc_i_EXT ( periph_demux_bus.r_opc ), 98 | 99 | .data_req_o_PE ( peripheral_bus_mst_o.req ), 100 | .data_add_o_PE ( peripheral_bus_mst_o.add ), 101 | .data_wen_o_PE ( peripheral_bus_mst_o.wen ), 102 | .data_wdata_o_PE ( peripheral_bus_mst_o.wdata ), 103 | .data_be_o_PE ( peripheral_bus_mst_o.be ), 104 | .data_gnt_i_PE ( peripheral_bus_mst_o.gnt ), 105 | .data_r_valid_i_PE ( peripheral_bus_mst_o.r_valid ), 106 | .data_r_rdata_i_PE ( peripheral_bus_mst_o.r_rdata ), 107 | .data_r_opc_i_PE ( peripheral_bus_mst_o.r_opc ), 108 | 109 | .perf_l2_ld_o ( ext_perf_o [0] ), 110 | .perf_l2_st_o ( ext_perf_o [1] ), 111 | .perf_l2_ld_cyc_o ( ext_perf_o [2] ), 112 | .perf_l2_st_cyc_o ( ext_perf_o [3] ), 113 | .CLUSTER_ID ( cluster_id_i ) 114 | ); 115 | 116 | assign ext_perf_o[4] = '0; 117 | 118 | assign periph_demux_bus.id = '0; 119 | 120 | assign dma_ctrl_mst_o.r_ready = '1; 121 | assign dma_ctrl_mst_o.user = '0; 122 | assign dma_ctrl_mst_o.id = '0; 123 | assign dma_ctrl_mst_o.ecc = '0; 124 | assign dma_ctrl_mst_o.ereq = '0; 125 | assign dma_ctrl_mst_o.r_eready = '1; 126 | 127 | periph_demux 128 | periph_demux_i ( 129 | .clk ( clk_i ), 130 | .rst_ni ( rst_ni ), 131 | 132 | .data_req_i ( periph_demux_bus.req ), 133 | .data_add_i ( periph_demux_bus.add ), 134 | .data_wen_i ( periph_demux_bus.wen ), 135 | .data_wdata_i ( periph_demux_bus.wdata ), 136 | .data_be_i ( periph_demux_bus.be ), 137 | .data_gnt_o ( periph_demux_bus.gnt ), 138 | .data_r_valid_o ( periph_demux_bus.r_valid ), 139 | .data_r_opc_o ( periph_demux_bus.r_opc ), 140 | .data_r_rdata_o ( periph_demux_bus.r_rdata ), 141 | 142 | .data_req_o_MH ( dma_ctrl_mst_o.req ), 143 | .data_add_o_MH ( dma_ctrl_mst_o.add ), 144 | .data_wen_o_MH ( dma_ctrl_mst_o.wen ), 145 | .data_wdata_o_MH ( dma_ctrl_mst_o.data ), 146 | .data_be_o_MH ( dma_ctrl_mst_o.be ), 147 | .data_gnt_i_MH ( dma_ctrl_mst_o.gnt ), 148 | .data_r_valid_i_MH ( dma_ctrl_mst_o.r_valid ), 149 | .data_r_rdata_i_MH ( dma_ctrl_mst_o.r_data ), 150 | .data_r_opc_i_MH ( dma_ctrl_mst_o.r_opc ), 151 | 152 | .data_req_o_EU ( eventunit_bus_mst_o.req ), 153 | .data_add_o_EU ( eventunit_bus_mst_o.add ), 154 | .data_wen_o_EU ( eventunit_bus_mst_o.wen ), 155 | .data_wdata_o_EU ( eventunit_bus_mst_o.wdata ), 156 | .data_be_o_EU ( eventunit_bus_mst_o.be ), 157 | .data_gnt_i_EU ( eventunit_bus_mst_o.gnt ), 158 | .data_r_valid_i_EU ( eventunit_bus_mst_o.r_valid ), 159 | .data_r_rdata_i_EU ( eventunit_bus_mst_o.r_rdata ), 160 | .data_r_opc_i_EU ( eventunit_bus_mst_o.r_opc ) 161 | ); 162 | 163 | endmodule: core_demux_wrap 164 | -------------------------------------------------------------------------------- /rtl/hwpe_subsystem.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * hwpe_subsystem.sv 13 | * Francesco Conti 14 | */ 15 | 16 | `include "hci_helpers.svh" 17 | 18 | module hwpe_subsystem 19 | import hci_package::*; 20 | import pulp_cluster_package::*; 21 | #( 22 | parameter hwpe_subsystem_cfg_t HWPE_CFG = hwpe_subsystem_cfg_t'{'0, '0}, 23 | parameter int unsigned N_CORES = 8, 24 | parameter int unsigned N_MASTER_PORT = 9, 25 | parameter int unsigned ID_WIDTH = 8, 26 | parameter hci_package::hci_size_parameter_t HCI_HWPE_SIZE = '0 27 | ) 28 | ( 29 | input logic clk, 30 | input logic rst_n, 31 | input logic test_mode, 32 | input logic hwpe_en_i, 33 | input logic [$clog2(MAX_NUM_HWPES)-1:0] hwpe_sel_i, 34 | 35 | hci_core_intf.initiator hwpe_xbar_master, 36 | XBAR_PERIPH_BUS.Slave hwpe_cfg_slave, 37 | 38 | output logic [N_CORES-1:0][1:0] evt_o, 39 | output logic busy_o 40 | ); 41 | 42 | localparam int unsigned DW = HCI_HWPE_SIZE.DW; 43 | localparam int unsigned AW = HCI_HWPE_SIZE.AW; 44 | localparam int unsigned EW = HCI_HWPE_SIZE.EW; 45 | localparam int unsigned EHW = HCI_HWPE_SIZE.EHW; 46 | 47 | localparam int unsigned N_HWPES = HWPE_CFG.NumHwpes; 48 | localparam int unsigned HWPE_SEL_BITS = (N_HWPES > 1) ? $clog2(N_HWPES) : 1; 49 | 50 | logic [N_HWPES-1:0] busy; 51 | logic [N_HWPES-1:0][N_CORES-1:0][1:0] evt; 52 | 53 | logic [N_HWPES-1:0] hwpe_clk; 54 | logic [N_HWPES-1:0] hwpe_en_int; 55 | 56 | logic [HWPE_SEL_BITS-1:0] hwpe_sel_int; 57 | 58 | assign hwpe_sel_int = hwpe_sel_i[HWPE_SEL_BITS-1:0]; 59 | 60 | hwpe_ctrl_intf_periph #( 61 | .ID_WIDTH ( ID_WIDTH ) 62 | ) periph [N_HWPES-1:0] (.clk(clk)); 63 | 64 | hci_core_intf #( 65 | .DW ( DW ), 66 | .AW ( AW ), 67 | .EW ( EW ), 68 | .EHW ( EHW ) 69 | ) tcdm [0:N_HWPES-1] (.clk(clk)); 70 | 71 | for (genvar i = 0; i < N_HWPES; i++) begin : gen_hwpe 72 | 73 | // HWPE specific enable 74 | assign hwpe_en_int[i] = hwpe_en_i && (hwpe_sel_int == i); 75 | 76 | // Clock gating cell 77 | tc_clk_gating i_hwpe_clock_gate ( 78 | .clk_i ( clk ), 79 | .en_i ( hwpe_en_int[i] ), 80 | .test_en_i ( test_mode ), 81 | .clk_o ( hwpe_clk[i] ) 82 | ); 83 | 84 | // Generate desired HWPEs 85 | if (HWPE_CFG.HwpeList[i] == REDMULE) begin : gen_redmule 86 | 87 | ///////////// 88 | // REDMULE // 89 | ///////////// 90 | 91 | redmule_top #( 92 | .ID_WIDTH ( ID_WIDTH ), 93 | .N_CORES ( N_CORES ), 94 | .DW ( N_MASTER_PORT*32 ), 95 | .`HCI_SIZE_PARAM(tcdm) ( HCI_HWPE_SIZE ) 96 | ) i_redmule ( 97 | .clk_i ( hwpe_clk[i] ), 98 | .rst_ni ( rst_n ), 99 | .test_mode_i ( test_mode ), 100 | .busy_o ( busy[i] ), 101 | .evt_o ( evt[i] ), 102 | .tcdm ( tcdm[i] ), 103 | .periph ( periph[i] ) 104 | ); 105 | 106 | end else if (HWPE_CFG.HwpeList[i] == NEUREKA) begin : gen_neureka 107 | 108 | ///////////// 109 | // NEUREKA // 110 | ///////////// 111 | 112 | neureka_top #( 113 | .PE_H ( 4 ), 114 | .PE_W ( 4 ), 115 | .ID ( ID_WIDTH ), 116 | .N_CORES ( N_CORES ), 117 | .`HCI_SIZE_PARAM(tcdm) ( HCI_HWPE_SIZE ) 118 | ) i_neureka ( 119 | // global signals 120 | .clk_i ( hwpe_clk[i] ), 121 | .rst_ni ( rst_n ), 122 | .test_mode_i ( test_mode ), 123 | // events 124 | .evt_o ( evt[i] ), 125 | .busy_o ( busy[i] ), 126 | // tcdm master ports 127 | .tcdm ( tcdm[i] ), 128 | // periph slave port 129 | .periph ( periph[i] ) 130 | ); 131 | 132 | end else if (HWPE_CFG.HwpeList[i] == SOFTEX) begin : gen_softex 133 | 134 | //////////// 135 | // SOFTEX // 136 | //////////// 137 | 138 | softex_top #( 139 | .N_CORES ( N_CORES ), 140 | .`HCI_SIZE_PARAM(Tcdm) ( HCI_HWPE_SIZE ) 141 | ) i_softex ( 142 | .clk_i ( hwpe_clk[i] ), 143 | .rst_ni ( rst_n ), 144 | .busy_o ( busy[i] ), 145 | .evt_o ( evt[i] ), 146 | .tcdm ( tcdm[i] ), 147 | .periph ( periph[i] ) 148 | ); 149 | 150 | end 151 | end 152 | 153 | ////////////////// 154 | // HWPE CFG BUS // 155 | ////////////////// 156 | 157 | // Target signals muxed according to `hwpe_sel_int` 158 | logic [N_HWPES-1:0] periph_gnt; 159 | logic [N_HWPES-1:0][31:0] periph_r_rdata; 160 | logic [N_HWPES-1:0] periph_r_valid; 161 | logic [N_HWPES-1:0][ID_WIDTH-1:0] periph_r_id; 162 | 163 | for (genvar i = 0; i < N_HWPES; i++) begin 164 | always_comb begin 165 | // Initiator signals decoded according to `hwpe_sel_int` 166 | periph[i].req = (hwpe_sel_int == i) ? hwpe_cfg_slave.req : '0; 167 | // No muxing needed 168 | periph[i].add = hwpe_cfg_slave.add; 169 | periph[i].wen = hwpe_cfg_slave.wen; 170 | periph[i].be = hwpe_cfg_slave.be; 171 | periph[i].data = hwpe_cfg_slave.wdata; 172 | periph[i].id = hwpe_cfg_slave.id; 173 | // Split interface signals into packed vectors 174 | periph_gnt [i] = periph[i].gnt; 175 | periph_r_rdata [i] = periph[i].r_data; 176 | periph_r_valid [i] = periph[i].r_valid; 177 | periph_r_id [i] = periph[i].r_id; 178 | end 179 | end 180 | 181 | always_comb begin 182 | // Config bus 183 | hwpe_cfg_slave.gnt = periph_gnt [0]; 184 | hwpe_cfg_slave.r_rdata = periph_r_rdata [0]; 185 | hwpe_cfg_slave.r_valid = periph_r_valid [0]; 186 | hwpe_cfg_slave.r_id = periph_r_id [0]; 187 | // evt and busy 188 | evt_o = evt[0]; 189 | busy_o = busy[0]; 190 | for (int i = 1; i < N_HWPES; i++) begin 191 | if (hwpe_sel_int == i) begin 192 | // Config bus 193 | hwpe_cfg_slave.gnt = periph_gnt [i]; 194 | hwpe_cfg_slave.r_rdata = periph_r_rdata [i]; 195 | hwpe_cfg_slave.r_valid = periph_r_valid [i]; 196 | hwpe_cfg_slave.r_id = periph_r_id [i]; 197 | // evt and busy 198 | evt_o = evt[i]; 199 | busy_o = busy[i]; 200 | end 201 | end 202 | end 203 | 204 | ////////////////////// 205 | // HWPE XBAR MASTER // 206 | ////////////////////// 207 | 208 | hci_core_mux_static #( 209 | .NB_CHAN ( N_HWPES ), 210 | .`HCI_SIZE_PARAM(in) ( HCI_HWPE_SIZE ) 211 | ) i_hwpe_hci_mux ( 212 | 213 | /* Internally unused */ 214 | .clk_i ( clk ), 215 | .rst_ni ( rst_n ), 216 | .clear_i ( '0 ), 217 | /*********************/ 218 | 219 | .sel_i ( hwpe_sel_int ), 220 | 221 | .in ( tcdm ), 222 | .out ( hwpe_xbar_master ) 223 | ); 224 | 225 | endmodule 226 | -------------------------------------------------------------------------------- /rtl/instr_width_converter.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2020 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | // 11 | // Converts 128-bit instruction data from cache to 32-bit instruction data for core. 12 | 13 | module instr_width_converter ( 14 | input logic clk_i, 15 | input logic rst_ni, 16 | 17 | output logic cache_req_o, 18 | input logic cache_gnt_i, 19 | output logic [31:0] cache_addr_o, 20 | input logic [127:0] cache_r_rdata_i, 21 | input logic cache_r_valid_i, 22 | 23 | input logic core_req_i, 24 | output logic core_gnt_o, 25 | input logic [31:0] core_addr_i, 26 | output logic [31:0] core_r_rdata_o, 27 | output logic core_r_valid_o 28 | ); 29 | 30 | logic busy_d, busy_q; 31 | logic cache_req_gnt; 32 | logic [1:0] word_sel_d, word_sel_q; 33 | logic [1:0] unused_addr; 34 | 35 | assign cache_req_gnt = cache_req_o && cache_gnt_i; 36 | assign core_gnt_o = cache_req_gnt; 37 | assign cache_req_o = cache_r_valid_i && busy_q ? core_req_i : // request passes if old instruction is available 38 | busy_q ? 1'b0 : core_req_i; // or not processing any new instructions 39 | 40 | assign cache_addr_o = {core_addr_i[31:4], 4'b0000}; 41 | assign unused_addr = core_addr_i[1:0]; 42 | 43 | assign busy_d = cache_req_gnt ? 1'b1 : 44 | cache_r_valid_i ? 1'b0 : busy_q; // Core will be busy if request is granted and not available yet 45 | 46 | assign word_sel_d = cache_req_gnt ? core_addr_i[3:2] : word_sel_q; // Select address portion based on previous request 47 | 48 | always_comb begin : mux_r_data 49 | unique case (word_sel_q) 50 | 2'b00 : core_r_rdata_o = cache_r_rdata_i[31:0]; 51 | 2'b01 : core_r_rdata_o = cache_r_rdata_i[63:32]; 52 | 2'b10 : core_r_rdata_o = cache_r_rdata_i[95:64]; 53 | 2'b11 : core_r_rdata_o = cache_r_rdata_i[127:96]; 54 | default : core_r_rdata_o = cache_r_rdata_i[31:0]; 55 | endcase // word_sel_q 56 | end 57 | 58 | assign core_r_valid_o = cache_r_valid_i; 59 | 60 | 61 | always_ff @(posedge clk_i or negedge rst_ni) begin : reg_control 62 | if(~rst_ni) begin 63 | busy_q <= 1'b0; 64 | word_sel_q <= '0; 65 | end else begin 66 | busy_q <= busy_d; 67 | word_sel_q <= word_sel_d; 68 | end 69 | end 70 | 71 | endmodule 72 | -------------------------------------------------------------------------------- /rtl/mchan_wrap.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * dmac_wrap.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module dmac_wrap 20 | #( 21 | parameter int unsigned NB_CTRLS = 2, 22 | parameter int unsigned NB_CORES = 8, 23 | parameter int unsigned NB_OUTSND_BURSTS = 8, 24 | parameter int unsigned MCHAN_BURST_LENGTH = 256, 25 | parameter int unsigned AXI_ADDR_WIDTH = 32, 26 | parameter int unsigned AXI_DATA_WIDTH = 64, 27 | parameter int unsigned AXI_USER_WIDTH = 6, 28 | parameter int unsigned AXI_ID_WIDTH = 4, 29 | parameter int unsigned PE_ID_WIDTH = 1, 30 | parameter int unsigned TCDM_ADD_WIDTH = 13, 31 | parameter int unsigned DATA_WIDTH = 32, 32 | parameter int unsigned ADDR_WIDTH = 32, 33 | parameter int unsigned BE_WIDTH = DATA_WIDTH/8, 34 | parameter type axi_req_t = logic, 35 | parameter type axi_resp_t = logic 36 | ) 37 | ( 38 | input logic clk_i, 39 | input logic rst_ni, 40 | input logic test_mode_i, 41 | 42 | hci_core_intf.target ctrl_slave[0:NB_CORES-1], 43 | XBAR_PERIPH_BUS.Slave pe_ctrl_slave[1:0], 44 | 45 | hci_core_intf.initiator tcdm_master[3:0], 46 | output axi_req_t ext_master_req_o, 47 | input axi_resp_t ext_master_resp_i, 48 | output logic [1:0] term_event_pe_o, 49 | output logic [1:0] term_irq_pe_o, 50 | output logic [NB_CORES-1:0] term_event_o, 51 | output logic [NB_CORES-1:0] term_irq_o, 52 | output logic busy_o 53 | ); 54 | 55 | // CORE --> MCHAN CTRL INTERFACE BUS SIGNALS 56 | logic [NB_CTRLS-1:0][DATA_WIDTH-1:0] s_ctrl_bus_wdata; 57 | logic [NB_CTRLS-1:0][ADDR_WIDTH-1:0] s_ctrl_bus_add; 58 | logic [NB_CTRLS-1:0] s_ctrl_bus_req; 59 | logic [NB_CTRLS-1:0] s_ctrl_bus_wen; 60 | logic [NB_CTRLS-1:0][BE_WIDTH-1:0] s_ctrl_bus_be; 61 | logic [NB_CTRLS-1:0][PE_ID_WIDTH-1:0] s_ctrl_bus_id; 62 | logic [NB_CTRLS-1:0] s_ctrl_bus_gnt; 63 | logic [NB_CTRLS-1:0][DATA_WIDTH-1:0] s_ctrl_bus_r_rdata; 64 | logic [NB_CTRLS-1:0] s_ctrl_bus_r_valid; 65 | logic [NB_CTRLS-1:0] s_ctrl_bus_r_opc; 66 | logic [NB_CTRLS-1:0][PE_ID_WIDTH-1:0] s_ctrl_bus_r_id; 67 | 68 | 69 | // MCHAN TCDM INIT --> TCDM MEMORY BUS SIGNALS 70 | logic [3:0][DATA_WIDTH-1:0] s_tcdm_bus_wdata; 71 | logic [3:0][ADDR_WIDTH-1:0] s_tcdm_bus_add; 72 | logic [3:0] s_tcdm_bus_req; 73 | logic [3:0] s_tcdm_bus_wen; 74 | logic [3:0][BE_WIDTH-1:0] s_tcdm_bus_be; 75 | logic [3:0] s_tcdm_bus_gnt; 76 | logic [3:0][DATA_WIDTH-1:0] s_tcdm_bus_r_rdata; 77 | logic [3:0] s_tcdm_bus_r_valid; 78 | 79 | // CLUSTER CORE PORT BINDING 80 | generate 81 | for (genvar i=0; i 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module per2axi_wrap 20 | #( 21 | parameter int unsigned NB_CORES = 4, 22 | parameter int unsigned PER_ADDR_WIDTH = 32, 23 | parameter int unsigned PER_ID_WIDTH = 5, 24 | parameter int unsigned AXI_ADDR_WIDTH = 32, 25 | parameter int unsigned AXI_DATA_WIDTH = 64, 26 | parameter int unsigned AXI_USER_WIDTH = 6, 27 | parameter int unsigned AXI_ID_WIDTH = 4, 28 | parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH/8, 29 | parameter int unsigned ID_WIDTH = PER_ID_WIDTH, // required for XBAR_PERIPH_BUS interface 30 | parameter type axi_req_t = logic, 31 | parameter type axi_resp_t = logic 32 | ) 33 | ( 34 | input logic clk_i, 35 | input logic rst_ni, 36 | input logic test_en_i, 37 | XBAR_PERIPH_BUS.Slave periph_slave, 38 | output axi_req_t axi_master_req_o, 39 | input axi_resp_t axi_master_resp_i, 40 | output logic busy_o 41 | ); 42 | 43 | per2axi #( 44 | .NB_CORES ( NB_CORES ), 45 | .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), 46 | .PER_ID_WIDTH ( PER_ID_WIDTH ), 47 | .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), 48 | .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), 49 | .AXI_USER_WIDTH ( AXI_USER_WIDTH ), 50 | .AXI_ID_WIDTH ( AXI_ID_WIDTH ) 51 | ) per2axi_i ( 52 | .clk_i ( clk_i ), 53 | .rst_ni ( rst_ni ), 54 | .test_en_i ( test_en_i ), 55 | 56 | .per_slave_req_i ( periph_slave.req ), 57 | .per_slave_add_i ( periph_slave.add ), 58 | .per_slave_we_i ( periph_slave.wen ), 59 | .per_slave_wdata_i ( periph_slave.wdata ), 60 | .per_slave_be_i ( periph_slave.be ), 61 | .per_slave_id_i ( periph_slave.id[PER_ID_WIDTH-1:0] ), 62 | .per_slave_gnt_o ( periph_slave.gnt ), 63 | 64 | .per_slave_r_valid_o ( periph_slave.r_valid ), 65 | .per_slave_r_opc_o ( periph_slave.r_opc ), 66 | .per_slave_r_id_o ( periph_slave.r_id[PER_ID_WIDTH-1:0] ), 67 | .per_slave_r_rdata_o ( periph_slave.r_rdata ), 68 | 69 | .axi_master_aw_valid_o ( axi_master_req_o.aw_valid ), 70 | .axi_master_aw_addr_o ( axi_master_req_o.aw.addr ), 71 | .axi_master_aw_prot_o ( axi_master_req_o.aw.prot ), 72 | .axi_master_aw_region_o ( axi_master_req_o.aw.region ), 73 | .axi_master_aw_len_o ( axi_master_req_o.aw.len ), 74 | .axi_master_aw_size_o ( axi_master_req_o.aw.size ), 75 | .axi_master_aw_burst_o ( axi_master_req_o.aw.burst ), 76 | .axi_master_aw_lock_o ( axi_master_req_o.aw.lock ), 77 | .axi_master_aw_cache_o ( axi_master_req_o.aw.cache ), 78 | .axi_master_aw_qos_o ( axi_master_req_o.aw.qos ), 79 | .axi_master_aw_id_o ( axi_master_req_o.aw.id[AXI_ID_WIDTH-1:0] ), 80 | .axi_master_aw_user_o ( axi_master_req_o.aw.user ), 81 | .axi_master_aw_ready_i ( axi_master_resp_i.aw_ready ), 82 | 83 | .axi_master_ar_valid_o ( axi_master_req_o.ar_valid ), 84 | .axi_master_ar_addr_o ( axi_master_req_o.ar.addr ), 85 | .axi_master_ar_prot_o ( axi_master_req_o.ar.prot ), 86 | .axi_master_ar_region_o ( axi_master_req_o.ar.region ), 87 | .axi_master_ar_len_o ( axi_master_req_o.ar.len ), 88 | .axi_master_ar_size_o ( axi_master_req_o.ar.size ), 89 | .axi_master_ar_burst_o ( axi_master_req_o.ar.burst ), 90 | .axi_master_ar_lock_o ( axi_master_req_o.ar.lock ), 91 | .axi_master_ar_cache_o ( axi_master_req_o.ar.cache ), 92 | .axi_master_ar_qos_o ( axi_master_req_o.ar.qos ), 93 | .axi_master_ar_id_o ( axi_master_req_o.ar.id[AXI_ID_WIDTH-1:0] ), 94 | .axi_master_ar_user_o ( axi_master_req_o.ar.user ), 95 | .axi_master_ar_ready_i ( axi_master_resp_i.ar_ready ), 96 | 97 | .axi_master_w_valid_o ( axi_master_req_o.w_valid ), 98 | .axi_master_w_data_o ( axi_master_req_o.w.data ), 99 | .axi_master_w_strb_o ( axi_master_req_o.w.strb ), 100 | .axi_master_w_user_o ( axi_master_req_o.w.user ), 101 | .axi_master_w_last_o ( axi_master_req_o.w.last ), 102 | .axi_master_w_ready_i ( axi_master_resp_i.w_ready ), 103 | 104 | .axi_master_r_valid_i ( axi_master_resp_i.r_valid ), 105 | .axi_master_r_data_i ( axi_master_resp_i.r.data ), 106 | .axi_master_r_resp_i ( axi_master_resp_i.r.resp ), 107 | .axi_master_r_last_i ( axi_master_resp_i.r.last ), 108 | .axi_master_r_id_i ( axi_master_resp_i.r.id[AXI_ID_WIDTH-1:0] ), 109 | .axi_master_r_user_i ( axi_master_resp_i.r.user ), 110 | .axi_master_r_ready_o ( axi_master_req_o.r_ready ), 111 | 112 | .axi_master_b_valid_i ( axi_master_resp_i.b_valid ), 113 | .axi_master_b_resp_i ( axi_master_resp_i.b.resp ), 114 | .axi_master_b_id_i ( axi_master_resp_i.b.id[AXI_ID_WIDTH-1:0] ), 115 | .axi_master_b_user_i ( axi_master_resp_i.b.user ), 116 | .axi_master_b_ready_o ( axi_master_req_o.b_ready ), 117 | 118 | .busy_o ( busy_o ) 119 | ); 120 | 121 | assign axi_master_req_o.aw.atop = '0; 122 | 123 | endmodule 124 | -------------------------------------------------------------------------------- /rtl/per_demux_wrap.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * per_demux_wrap.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module per_demux_wrap 20 | #( 21 | parameter int unsigned NB_MASTERS = 2, 22 | parameter int unsigned ADDR_OFFSET = 10 23 | ) 24 | ( 25 | input logic clk_i, 26 | input logic rst_ni, 27 | XBAR_TCDM_BUS.Slave slave, 28 | XBAR_TCDM_BUS.Master masters[NB_MASTERS-1:0] 29 | ); 30 | 31 | localparam NB_MASTERS_LOG = $clog2(NB_MASTERS); 32 | 33 | logic [NB_MASTERS_LOG-1:0] dest_q, dest_n; 34 | 35 | // need to explode the interfaces here because SystemVerilog does not allow 36 | // to use it directly...... 37 | logic [NB_MASTERS-1:0] masters_gnt; 38 | logic [NB_MASTERS-1:0] masters_r_valid; 39 | logic [NB_MASTERS-1:0] masters_r_opc; 40 | logic [NB_MASTERS-1:0][31:0] masters_r_data; 41 | 42 | generate 43 | for (genvar i = 0; i < NB_MASTERS; i++) begin 44 | assign masters[i].req = (dest_n == i) ? slave.req : 1'b0; 45 | assign masters[i].add = slave.add; 46 | assign masters[i].wen = slave.wen; 47 | assign masters[i].wdata = slave.wdata; 48 | assign masters[i].be = slave.be; 49 | 50 | // for exploded interface 51 | assign masters_gnt[i] = masters[i].gnt; 52 | assign masters_r_valid[i] = masters[i].r_valid; 53 | assign masters_r_opc[i] = masters[i].r_opc; 54 | assign masters_r_data[i] = masters[i].r_rdata; 55 | end 56 | endgenerate 57 | 58 | assign slave.gnt = masters_gnt[dest_n]; 59 | assign slave.r_valid = masters_r_valid[dest_q]; 60 | assign slave.r_opc = masters_r_opc[dest_q]; 61 | assign slave.r_rdata = masters_r_data[dest_q]; 62 | 63 | assign dest_n = slave.add[NB_MASTERS_LOG-1+ADDR_OFFSET:ADDR_OFFSET]; 64 | 65 | always_ff @(posedge clk_i, negedge rst_ni) 66 | begin 67 | if (~rst_ni) begin 68 | dest_q <= '0; 69 | end 70 | else begin 71 | dest_q <= dest_n; 72 | end 73 | end 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /rtl/periph_FIFO.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * periph_FIFO.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | module periph_FIFO 20 | #( 21 | parameter int unsigned ADDR_WIDTH=32, 22 | parameter int unsigned DATA_WIDTH=32, 23 | parameter int unsigned BYTE_ENABLE_BIT=DATA_WIDTH/8 24 | ) 25 | ( 26 | input logic clk_i, 27 | input logic rst_ni, 28 | input logic test_en_i, 29 | 30 | //Input SIde REQ 31 | input logic data_req_i, 32 | input logic [ADDR_WIDTH - 1:0] data_add_i, 33 | input logic data_wen_i, 34 | input logic [DATA_WIDTH - 1:0] data_wdata_i, 35 | input logic [BYTE_ENABLE_BIT - 1:0] data_be_i, 36 | output logic data_gnt_o, 37 | 38 | //Output side REQ 39 | output logic data_req_o, 40 | output logic [ADDR_WIDTH - 1:0] data_add_o, 41 | output logic data_wen_o, 42 | output logic [DATA_WIDTH - 1:0] data_wdata_o, 43 | output logic [BYTE_ENABLE_BIT - 1:0] data_be_o, 44 | input logic data_gnt_i, 45 | 46 | //Input SIde RESP 47 | input logic data_r_valid_i, 48 | input logic data_r_opc_i, 49 | input logic [DATA_WIDTH - 1:0] data_r_rdata_i, 50 | 51 | //Output SIde RESP 52 | output logic data_r_valid_o, 53 | output logic data_r_opc_o, 54 | output logic [DATA_WIDTH - 1:0] data_r_rdata_o 55 | ); 56 | 57 | localparam FIFO_DW = ADDR_WIDTH + 1 + DATA_WIDTH + BYTE_ENABLE_BIT; 58 | 59 | logic [FIFO_DW-1:0] DATA_IN; 60 | logic [FIFO_DW-1:0] DATA_OUT; 61 | 62 | assign DATA_IN = { data_add_i, data_wen_i, data_wdata_i, data_be_i }; 63 | assign { data_add_o, data_wen_o, data_wdata_o, data_be_o } = DATA_OUT; 64 | 65 | generic_fifo #( 66 | .DATA_WIDTH ( FIFO_DW ), 67 | .DATA_DEPTH ( 2 ) 68 | ) FIFO_REQ ( 69 | .clk ( clk_i ), 70 | .rst_n ( rst_ni ), 71 | .test_mode_i ( test_en_i ), 72 | .data_i ( DATA_IN ), 73 | .valid_i ( data_req_i ), 74 | .grant_o ( data_gnt_o ), 75 | .data_o ( DATA_OUT ), 76 | .valid_o ( data_req_o ), 77 | .grant_i ( data_gnt_i ) 78 | ); 79 | 80 | assign data_r_valid_o = data_r_valid_i; 81 | assign data_r_opc_o = data_r_opc_i; 82 | assign data_r_rdata_o = data_r_rdata_i; 83 | 84 | endmodule 85 | -------------------------------------------------------------------------------- /rtl/periph_demux.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * periph_demux.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | 20 | module periph_demux 21 | #( 22 | parameter int unsigned ADDR_WIDTH = 32, 23 | parameter int unsigned DATA_WIDTH = 32, 24 | parameter int unsigned BE_WIDTH = DATA_WIDTH/8 25 | ) 26 | ( 27 | input logic clk, 28 | input logic rst_ni, 29 | 30 | // CORE SIDE 31 | input logic data_req_i, 32 | input logic [ADDR_WIDTH - 1:0] data_add_i, 33 | input logic data_wen_i, 34 | input logic [DATA_WIDTH - 1:0] data_wdata_i, 35 | input logic [BE_WIDTH - 1:0] data_be_i, 36 | output logic data_gnt_o, 37 | 38 | output logic data_r_valid_o, // Data Response Valid (For LOAD/STORE commands) 39 | output logic [DATA_WIDTH - 1:0] data_r_rdata_o, // Data Response DATA (For LOAD commands) 40 | output logic data_r_opc_o, // Data Response Error 41 | 42 | // Low Latency log interconnect SIDE 43 | output logic data_req_o_MH, 44 | output logic [ADDR_WIDTH - 1:0] data_add_o_MH, 45 | output logic data_wen_o_MH, 46 | output logic [DATA_WIDTH - 1:0] data_wdata_o_MH, 47 | output logic [BE_WIDTH - 1:0] data_be_o_MH, 48 | input logic data_gnt_i_MH, 49 | input logic data_r_valid_i_MH, 50 | input logic [DATA_WIDTH - 1:0] data_r_rdata_i_MH, 51 | input logic data_r_opc_i_MH, 52 | 53 | //low latency event unit access, sleep_req,clear buffer_req 54 | output logic data_req_o_EU, 55 | output logic [ADDR_WIDTH - 1:0] data_add_o_EU, 56 | output logic data_wen_o_EU, 57 | output logic [DATA_WIDTH - 1:0] data_wdata_o_EU, 58 | output logic [BE_WIDTH - 1:0] data_be_o_EU, 59 | input logic data_gnt_i_EU, 60 | input logic data_r_valid_i_EU, 61 | input logic [DATA_WIDTH - 1:0] data_r_rdata_i_EU, 62 | input logic data_r_opc_i_EU 63 | ); 64 | 65 | enum logic [1:0] {MH, EU, UNMAPPED } request_destination; 66 | 67 | always_ff @(posedge clk, negedge rst_ni) begin : _UPDATE_RESPONSE_DESTINATION_ 68 | if(rst_ni == 1'b0) begin 69 | request_destination <= MH; 70 | end 71 | else begin 72 | if(data_req_i) begin 73 | `ifdef DEM_PER_BEFORE_TCDM_TS 74 | case(data_add_i[13:10]) 75 | 4'b1111 : begin : _EVENT_UNIT_REGS 76 | request_destination <= EU; 77 | end 78 | 4'b1110 : begin : _MCHAN_REGISTERS_ 79 | request_destination <= MH; 80 | end 81 | default: begin : _UNMAPPED_REGION_ 82 | request_destination <= UNMAPPED; 83 | end 84 | endcase // data_add_i[13:10] 85 | `else /* ! DEM_PER_BEFORE_TCDM_TS */ 86 | if( (data_add_i[19:14] == 6'b000001 ) ) begin // this means 0x1020_4000 to 1020_7FFF 87 | case(data_add_i[13:10]) 88 | 0 : begin : _EVENT_UNIT_REGS 89 | request_destination <= EU; 90 | end 91 | 1 : begin : _MCHAN_REGISTERS_ 92 | request_destination <= MH; 93 | end 94 | default : begin : _UNMAPPED_REGION_ 95 | request_destination <= UNMAPPED; 96 | end 97 | endcase // data_add_i[10:13] 98 | end 99 | `endif 100 | end 101 | end 102 | end 103 | 104 | assign data_add_o_MH = data_add_i; 105 | assign data_wen_o_MH = data_wen_i; 106 | assign data_wdata_o_MH = data_wdata_i; 107 | assign data_be_o_MH = data_be_i; 108 | 109 | assign data_add_o_EU = data_add_i; 110 | assign data_wen_o_EU = data_wen_i; 111 | assign data_wdata_o_EU = data_wdata_i; 112 | assign data_be_o_EU = data_be_i; 113 | 114 | always_comb 115 | begin : _HANDLE_REQ_ 116 | data_req_o_MH = 1'b0; 117 | data_req_o_EU = 1'b0; 118 | data_gnt_o = 1'b0; 119 | `ifdef DEM_PER_BEFORE_TCDM_TS 120 | case(data_add_i[13:10]) 121 | 4'b1111 : begin 122 | data_req_o_EU = data_req_i; 123 | data_gnt_o = data_gnt_i_EU; 124 | end 125 | 4'b1110 : begin 126 | data_req_o_MH = data_req_i; 127 | data_gnt_o = data_gnt_i_MH; 128 | end 129 | default : begin : _TO_UNMAPPED_REGION_ 130 | data_req_o_MH = 1'b0; 131 | data_req_o_EU = 1'b0; 132 | data_gnt_o = 1'b0; 133 | end 134 | endcase // data_add_i[13:10] 135 | `else /* ! DEM_PER_BEFORE_TCDM_TS */ 136 | if( (data_add_i[19:14] == 6'b000001 ) ) begin // this means 0x1020_4000 to 1020_7FFF 137 | case(data_add_i[13:10]) 138 | 0 : begin 139 | data_req_o_EU = data_req_i; 140 | data_gnt_o = data_gnt_i_EU; 141 | end 142 | 1 : begin 143 | data_req_o_MH = data_req_i; 144 | data_gnt_o = data_gnt_i_MH; 145 | end 146 | default : begin 147 | data_req_o_MH = 1'b0; 148 | data_req_o_EU = 1'b0; 149 | data_gnt_o = 1'b0; 150 | end 151 | endcase // data_add_i[10:13] 152 | end 153 | `endif 154 | end 155 | 156 | always_comb 157 | begin : _HANDLE_RESP_ 158 | case(request_destination) 159 | MH : begin : _RESP_FROM_MCHAN_ 160 | data_r_valid_o = data_r_valid_i_MH; 161 | data_r_rdata_o = data_r_rdata_i_MH; 162 | data_r_opc_o = 1'b0; 163 | end 164 | EU : begin : _RESP_FROM_EVENT_UNIT_ 165 | data_r_valid_o = data_r_valid_i_EU; 166 | data_r_rdata_o = data_r_rdata_i_EU; 167 | data_r_opc_o = 1'b0; 168 | end 169 | default : begin : _UNMAPPED_RESP_ 170 | data_r_valid_o = 1'b0; 171 | data_r_rdata_o = '0; 172 | data_r_opc_o = 1'b0; 173 | end 174 | endcase 175 | end 176 | 177 | endmodule 178 | -------------------------------------------------------------------------------- /rtl/pulp_cluster_wrap.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | // Yvan Tortorella 12 | 13 | import pulp_cluster_package::*; 14 | import axi_pkg::*; 15 | 16 | package pulp_cluster_wrap_package; 17 | localparam pulp_cluster_package::pulp_cluster_cfg_t Cfg = pulp_cluster_package::PulpClusterDefaultCfg; 18 | localparam int unsigned EventWidth = 8; 19 | 20 | localparam int unsigned AxiIdInWidth = pulp_cluster_package::AxiSubordinateIdwidth; 21 | localparam int unsigned AxiIdOutWidth = pulp_cluster_package::AxiManagerIdwidth; 22 | // CDC AXI parameters (external to cluster) 23 | localparam int unsigned AwInWidth = axi_pkg::aw_width(Cfg.AxiAddrWidth, 24 | Cfg.AxiIdInWidth, 25 | Cfg.AxiUserWidth); 26 | localparam int unsigned WInWidth = axi_pkg::w_width(Cfg.AxiDataInWidth, 27 | Cfg.AxiUserWidth); 28 | localparam int unsigned BInWidth = axi_pkg::b_width(Cfg.AxiIdInWidth, 29 | Cfg.AxiUserWidth); 30 | localparam int unsigned ArInWidth = axi_pkg::ar_width(Cfg.AxiAddrWidth, 31 | Cfg.AxiIdInWidth, 32 | Cfg.AxiUserWidth); 33 | localparam int unsigned RInWidth = axi_pkg::r_width(Cfg.AxiDataInWidth, 34 | Cfg.AxiIdInWidth, 35 | Cfg.AxiUserWidth); 36 | localparam int unsigned AsyncInAwDatawidth = (2**Cfg.AxiCdcLogDepth)*AwInWidth; 37 | localparam int unsigned AsyncInWDatawidth = (2**Cfg.AxiCdcLogDepth)*WInWidth; 38 | localparam int unsigned AsyncInBDataWidth = (2**Cfg.AxiCdcLogDepth)*BInWidth; 39 | localparam int unsigned AsyncInArDatawidth = (2**Cfg.AxiCdcLogDepth)*ArInWidth; 40 | localparam int unsigned AsyncInRDataWidth = (2**Cfg.AxiCdcLogDepth)*RInWidth; 41 | // CDC AXI parameters (cluster to external) 42 | localparam int unsigned AwOutWidth = axi_pkg::aw_width(Cfg.AxiAddrWidth, 43 | Cfg.AxiIdOutWidth, 44 | Cfg.AxiUserWidth); 45 | localparam int unsigned WOutWidth = axi_pkg::w_width(Cfg.AxiDataOutWidth, 46 | Cfg.AxiUserWidth); 47 | localparam int unsigned BOutWidth = axi_pkg::b_width(Cfg.AxiIdOutWidth, 48 | Cfg.AxiUserWidth); 49 | localparam int unsigned ArOutWidth = axi_pkg::ar_width(Cfg.AxiAddrWidth, 50 | Cfg.AxiIdOutWidth, 51 | Cfg.AxiUserWidth); 52 | localparam int unsigned ROutWidth = axi_pkg::r_width(Cfg.AxiDataOutWidth, 53 | Cfg.AxiIdOutWidth, 54 | Cfg.AxiUserWidth); 55 | localparam int unsigned AsyncOutAwDataWidth = (2**Cfg.AxiCdcLogDepth)*AwOutWidth; 56 | localparam int unsigned AsyncOutWDataWidth = (2**Cfg.AxiCdcLogDepth)*WOutWidth; 57 | localparam int unsigned AsyncOutBDataWidth = (2**Cfg.AxiCdcLogDepth)*BOutWidth; 58 | localparam int unsigned AsyncOutArDataWidth = (2**Cfg.AxiCdcLogDepth)*ArOutWidth; 59 | localparam int unsigned AsyncOutRDataWidth = (2**Cfg.AxiCdcLogDepth)*ROutWidth; 60 | localparam int unsigned AsyncEventDataWidth = (2**Cfg.AxiCdcLogDepth)*EventWidth; 61 | endpackage 62 | 63 | module pulp_cluster_wrap ( 64 | input logic clk_i, 65 | input logic rst_ni, 66 | input logic ref_clk_i, 67 | input logic pwr_on_rst_ni, 68 | input logic pmu_mem_pwdn_i, 69 | input logic [3:0] base_addr_i, 70 | input logic test_mode_i, 71 | input logic en_sa_boot_i, 72 | input logic [5:0] cluster_id_i, 73 | input logic fetch_en_i, 74 | output logic eoc_o, 75 | output logic busy_o, 76 | input logic axi_isolate_i, 77 | output logic axi_isolated_o, 78 | input logic dma_pe_evt_ack_i, 79 | output logic dma_pe_evt_valid_o, 80 | input logic dma_pe_irq_ack_i, 81 | output logic dma_pe_irq_valid_o, 82 | input logic pf_evt_ack_i, 83 | output logic pf_evt_valid_o, 84 | input logic [pulp_cluster_wrap_package::Cfg.NumCores-1:0] dbg_irq_valid_i, 85 | input logic mbox_irq_i, 86 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_cluster_events_wptr_i, 87 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_cluster_events_rptr_o, 88 | input logic [pulp_cluster_wrap_package::AsyncEventDataWidth-1:0] async_cluster_events_data_i, 89 | // AXI4 SLAVE 90 | //*************************************** 91 | // WRITE ADDRESS CHANNEL 92 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_aw_wptr_i, 93 | input logic [pulp_cluster_wrap_package::AsyncInAwDatawidth-1:0] async_data_slave_aw_data_i, 94 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_aw_rptr_o, 95 | // READ ADDRESS CHANNEL 96 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_ar_wptr_i, 97 | input logic [pulp_cluster_wrap_package::AsyncInArDatawidth-1:0] async_data_slave_ar_data_i, 98 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_ar_rptr_o, 99 | // WRITE DATA CHANNEL 100 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_w_wptr_i, 101 | input logic [pulp_cluster_wrap_package::AsyncInWDatawidth-1:0] async_data_slave_w_data_i, 102 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_w_rptr_o, 103 | // READ DATA CHANNEL 104 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_r_wptr_o, 105 | output logic [pulp_cluster_wrap_package::AsyncInRDataWidth-1:0] async_data_slave_r_data_o, 106 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_r_rptr_i, 107 | // WRITE RESPONSE CHANNEL 108 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_b_wptr_o, 109 | output logic [pulp_cluster_wrap_package::AsyncInBDataWidth-1:0] async_data_slave_b_data_o, 110 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_slave_b_rptr_i, 111 | // AXI4 MASTER 112 | //*************************************** 113 | // WRITE ADDRESS CHANNEL 114 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_aw_wptr_o, 115 | output logic [pulp_cluster_wrap_package::AsyncOutAwDataWidth-1:0] async_data_master_aw_data_o, 116 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_aw_rptr_i, 117 | // READ ADDRESS CHANNEL 118 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_ar_wptr_o, 119 | output logic [pulp_cluster_wrap_package::AsyncOutArDataWidth-1:0] async_data_master_ar_data_o, 120 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_ar_rptr_i, 121 | // WRITE DATA CHANNEL 122 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_w_wptr_o, 123 | output logic [pulp_cluster_wrap_package::AsyncOutWDataWidth-1:0] async_data_master_w_data_o, 124 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_w_rptr_i, 125 | // READ DATA CHANNEL 126 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_r_wptr_i, 127 | input logic [pulp_cluster_wrap_package::AsyncOutRDataWidth-1:0] async_data_master_r_data_i, 128 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_r_rptr_o, 129 | // WRITE RESPONSE CHANNEL 130 | input logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_b_wptr_i, 131 | input logic [pulp_cluster_wrap_package::AsyncOutBDataWidth-1:0] async_data_master_b_data_i, 132 | output logic [pulp_cluster_wrap_package::Cfg.AxiCdcLogDepth:0] async_data_master_b_rptr_o 133 | ); 134 | 135 | pulp_cluster #( .Cfg(pulp_cluster_wrap_package::Cfg) ) pulp_cluster_i ( 136 | .clk_i, 137 | .rst_ni, 138 | .pwr_on_rst_ni, 139 | .ref_clk_i, 140 | .axi_isolate_i ( '0 ), 141 | .axi_isolated_o, 142 | .pmu_mem_pwdn_i ( 1'b0 ), 143 | .base_addr_i, 144 | .dma_pe_evt_ack_i ( '1 ), 145 | .dma_pe_evt_valid_o, 146 | .dma_pe_irq_ack_i ( 1'b1 ), 147 | .dma_pe_irq_valid_o, 148 | .dbg_irq_valid_i ( '0 ), 149 | .mbox_irq_i ( '0 ), 150 | .pf_evt_ack_i ( 1'b1 ), 151 | .pf_evt_valid_o, 152 | .async_cluster_events_wptr_i ( '0 ), 153 | .async_cluster_events_rptr_o, 154 | .async_cluster_events_data_i ( '0 ), 155 | .en_sa_boot_i, 156 | .test_mode_i, 157 | .fetch_en_i, 158 | .eoc_o, 159 | .busy_o, 160 | .cluster_id_i, 161 | 162 | .async_data_master_aw_wptr_o, 163 | .async_data_master_aw_rptr_i, 164 | .async_data_master_aw_data_o, 165 | .async_data_master_ar_wptr_o, 166 | .async_data_master_ar_rptr_i, 167 | .async_data_master_ar_data_o, 168 | .async_data_master_w_data_o, 169 | .async_data_master_w_wptr_o, 170 | .async_data_master_w_rptr_i, 171 | .async_data_master_r_wptr_i, 172 | .async_data_master_r_rptr_o, 173 | .async_data_master_r_data_i, 174 | .async_data_master_b_wptr_i, 175 | .async_data_master_b_rptr_o, 176 | .async_data_master_b_data_i, 177 | 178 | .async_data_slave_aw_wptr_i, 179 | .async_data_slave_aw_rptr_o, 180 | .async_data_slave_aw_data_i, 181 | .async_data_slave_ar_wptr_i, 182 | .async_data_slave_ar_rptr_o, 183 | .async_data_slave_ar_data_i, 184 | .async_data_slave_w_data_i, 185 | .async_data_slave_w_wptr_i, 186 | .async_data_slave_w_rptr_o, 187 | .async_data_slave_r_wptr_o, 188 | .async_data_slave_r_rptr_i, 189 | .async_data_slave_r_data_o, 190 | .async_data_slave_b_wptr_o, 191 | .async_data_slave_b_rptr_i, 192 | .async_data_slave_b_data_o 193 | ); 194 | endmodule 195 | -------------------------------------------------------------------------------- /rtl/tcdm_banks_wrap.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /* 12 | * tcdm_banks_wrap.sv 13 | * Davide Rossi 14 | * Antonio Pullini 15 | * Igor Loi 16 | * Francesco Conti 17 | */ 18 | 19 | `include "hci_helpers.svh" 20 | 21 | module tcdm_banks_wrap #( 22 | parameter int unsigned BankSize = 256, //- -> OVERRIDE 23 | parameter int unsigned NbBanks = 1, // --> OVERRIDE 24 | parameter int unsigned DataWidth = 32, 25 | parameter int unsigned AddrWidth = 32, 26 | parameter int unsigned BeWidth = DataWidth/8, 27 | parameter int unsigned IdWidth = 1, 28 | parameter bit EnableEcc = 1, 29 | parameter bit EccInterco = 0, 30 | parameter int unsigned ProtectedWidth = DataWidth + 7, 31 | parameter hci_package::hci_size_parameter_t HCI_MEM_SIZE = '0 32 | ) ( 33 | input logic clk_i, 34 | input logic rst_ni, 35 | input logic test_mode_i, 36 | // Scrubber 37 | input logic [NbBanks-1:0] scrub_trigger_i, 38 | output logic [NbBanks-1:0] scrub_fix_o, 39 | output logic [NbBanks-1:0] scrub_uncorrectable_o, 40 | // ECC 41 | output logic [NbBanks-1:0] ecc_single_error_o, 42 | output logic [NbBanks-1:0] ecc_multiple_error_o, 43 | hci_core_intf.target tcdm_slave[0:NbBanks-1] 44 | ); 45 | 46 | for(genvar i=0; i= cluster_peripherals_base 103 | && addr <= cluster_peripherals_end) 104 | ) begin 105 | // decode peripheral to access 106 | pe_idx = addr[PE_ROUTING_MSB:PE_ROUTING_LSB]; 107 | if (addr[31:20] == cluster_peripherals_base[31:20] && 108 | addr[19:PE_ROUTING_MSB+1] == '0 && 109 | pe_idx < NB_SPERIPHS) 110 | begin 111 | if (pe_idx >= pulp_cluster_package::SPER_EVENT_U_ID && 112 | pe_idx < pulp_cluster_package::SPER_EVENT_U_ID 113 | + pulp_cluster_package::NB_SPERIPH_PLUGS_EU 114 | ) begin 115 | // Index is in event unit range, so return unified event unit port. 116 | return pulp_cluster_package::SPER_EVENT_U_ID; 117 | end else if (!HWPE_PRESENT && pe_idx == pulp_cluster_package::SPER_HWPE_ID) begin 118 | // Decode non-present HWPE to error slave. 119 | return PE_IDX_ERR; 120 | end else if (pe_idx == PE_IDX_EXT) begin 121 | // Decode direct accesses to external peripheral to error slave to break addressing 122 | // loop. 123 | return PE_IDX_ERR; 124 | end else begin 125 | // Return index of other peripheral. 126 | return pe_idx; 127 | end 128 | // .. or, if the address does not decode to a peripheral, decode to error slave 129 | end else begin 130 | return PE_IDX_ERR; 131 | end 132 | end else begin 133 | // otherwise decode to 'external' peripheral 134 | return PE_IDX_EXT; 135 | end 136 | end 137 | endfunction 138 | for (genvar i = 0; i < NB_CORES; i++) begin : gen_pe_xbar_bind_cores 139 | assign pe_inp_req[i] = core_periph_slave[i].req; 140 | assign pe_inp_idx[i] = addr_to_pe_idx(core_periph_slave[i].add, '0); 141 | assign pe_inp_wdata[i].addr = core_periph_slave[i].add; 142 | assign pe_inp_wdata[i].data = core_periph_slave[i].wdata; 143 | assign pe_inp_wdata[i].id = 1 << i; 144 | assign pe_inp_wdata[i].we_n = core_periph_slave[i].wen; 145 | assign pe_inp_wdata[i].be = core_periph_slave[i].be; 146 | assign core_periph_slave[i].gnt = pe_inp_gnt[i]; 147 | assign core_periph_slave[i].r_id = pe_inp_rdata[i].id; 148 | assign core_periph_slave[i].r_rdata = pe_inp_rdata[i].data; 149 | assign core_periph_slave[i].r_opc = pe_inp_rdata[i].opc; 150 | assign core_periph_slave[i].r_valid = pe_inp_rvalid[i]; 151 | end 152 | for (genvar i = 0; i < NB_MPERIPHS; i++) begin : gen_pe_xbar_bind_mperiphs 153 | assign pe_inp_req[i+NB_CORES] = mperiph_slave[i].req; 154 | assign pe_inp_idx[i+NB_CORES] = addr_to_pe_idx(mperiph_slave[i].add, '0); 155 | assign pe_inp_wdata[i+NB_CORES].addr = mperiph_slave[i].add; 156 | assign pe_inp_wdata[i+NB_CORES].data = mperiph_slave[i].wdata; 157 | assign pe_inp_wdata[i+NB_CORES].id = 1 << (i + NB_CORES); 158 | assign pe_inp_wdata[i+NB_CORES].we_n = mperiph_slave[i].wen; 159 | assign pe_inp_wdata[i+NB_CORES].be = mperiph_slave[i].be; 160 | assign mperiph_slave[i].gnt = pe_inp_gnt[i+NB_CORES]; 161 | assign mperiph_slave[i].r_rdata = pe_inp_rdata[i+NB_CORES].data; 162 | assign mperiph_slave[i].r_opc = pe_inp_rdata[i+NB_CORES].opc; 163 | assign mperiph_slave[i].r_valid = pe_inp_rvalid[i+NB_CORES]; 164 | end 165 | 166 | // Peripherals: Bind outputs. 167 | pe_req_t [PE_XBAR_N_OUPS-1:0] pe_oup_wdata; 168 | pe_resp_t [PE_XBAR_N_OUPS-1:0] pe_oup_rdata; 169 | logic [PE_XBAR_N_OUPS-1:0] pe_oup_req, 170 | pe_oup_gnt, 171 | pe_oup_rvalid; 172 | for (genvar i = 0; i < NB_SPERIPHS; i++) begin : gen_pe_xbar_bind_speriphs 173 | assign speriph_master[i].req = pe_oup_req[i]; 174 | assign pe_oup_gnt[i] = speriph_master[i].gnt; 175 | assign speriph_master[i].add = pe_oup_wdata[i].addr; 176 | assign speriph_master[i].wdata = pe_oup_wdata[i].data; 177 | assign speriph_master[i].id = pe_oup_wdata[i].id; 178 | assign speriph_master[i].wen = pe_oup_wdata[i].we_n; 179 | assign speriph_master[i].be = pe_oup_wdata[i].be; 180 | assign pe_oup_rdata[i].data = speriph_master[i].r_rdata; 181 | assign pe_oup_rdata[i].id = speriph_master[i].r_id; 182 | assign pe_oup_rdata[i].opc = speriph_master[i].r_opc; 183 | assign pe_oup_rvalid[i] = speriph_master[i].r_valid; 184 | end 185 | 186 | // Peripheral Interconnect 187 | logic [PE_XBAR_N_INPS-1:0][PE_XBAR_N_OUPS-1:0] pe_req, pe_gnt; 188 | // Demux requests of inputs and mux responses to inputs. 189 | for (genvar i = 0; i < PE_XBAR_N_INPS; i++) begin : gen_pe_xbar_inps 190 | stream_demux #( 191 | .N_OUP(PE_XBAR_N_OUPS) 192 | ) i_req_demux ( 193 | .inp_valid_i (pe_inp_req[i]), 194 | .inp_ready_o (pe_inp_gnt[i]), 195 | .oup_sel_i (pe_inp_idx[i]), 196 | .oup_valid_o (pe_req[i]), 197 | .oup_ready_i (pe_gnt[i]) 198 | ); 199 | logic [PE_XBAR_N_OUPS-1:0] pe_oup_reqs; 200 | for (genvar j = 0; j < PE_XBAR_N_OUPS; j++) begin : gen_pe_xbar_inps_oup_reqs 201 | assign pe_oup_reqs[j] = pe_oup_rvalid[j] & (pe_oup_rdata[j].id == 1 << i); 202 | end 203 | pe_idx_t oup_sel; 204 | onehot_to_bin #( 205 | .ONEHOT_WIDTH (PE_XBAR_N_OUPS) 206 | ) i_ohb ( 207 | .onehot (pe_oup_reqs), 208 | .bin (oup_sel) 209 | ); 210 | stream_mux #( 211 | .DATA_T (pe_resp_t), 212 | .N_INP (PE_XBAR_N_OUPS) 213 | ) i_resp_mux ( 214 | .inp_data_i (pe_oup_rdata), 215 | .inp_valid_i (pe_oup_reqs), 216 | .inp_ready_o (/* unused */), 217 | .inp_sel_i (oup_sel), 218 | .oup_data_o (pe_inp_rdata[i]), 219 | .oup_valid_o (pe_inp_rvalid[i]), 220 | .oup_ready_i (1'b1) 221 | ); 222 | end 223 | // Arbitrate requests to outputs. 224 | for (genvar i = 0; i < PE_XBAR_N_OUPS; i++) begin : gen_pe_xbar_oups 225 | logic [PE_XBAR_N_INPS-1:0] reqs, gnts; 226 | for (genvar j = 0; j < PE_XBAR_N_INPS; j++) begin : gen_pe_xbar_oup_arb_inps 227 | assign reqs[j] = pe_req[j][i]; 228 | assign pe_gnt[j][i] = gnts[j]; 229 | end 230 | rr_arb_tree #( 231 | .NumIn (PE_XBAR_N_INPS), 232 | .DataWidth ($bits(pe_req_t)), 233 | .ExtPrio (1'b0), 234 | .AxiVldRdy (1'b0), 235 | .LockIn (1'b0) 236 | ) i_arb ( 237 | .clk_i, 238 | .rst_ni, 239 | .flush_i (1'b0), 240 | .rr_i ('0), 241 | 242 | .req_i (reqs), 243 | .gnt_o (gnts), 244 | .data_i (pe_inp_wdata), 245 | 246 | .gnt_i (pe_oup_gnt[i]), 247 | .req_o (pe_oup_req[i]), 248 | .data_o (pe_oup_wdata[i]), 249 | .idx_o (/* unused */) 250 | ); 251 | end 252 | 253 | endmodule 254 | -------------------------------------------------------------------------------- /scripts/run_and_exit.tcl: -------------------------------------------------------------------------------- 1 | if {![info exists VSIM_PATH ]} { 2 | return -code error -errorinfo "[ERRORINFO] You must set the \"VSIM_PATH\" variable before sourcing the start script." 3 | set VSIM_PATH "" 4 | } 5 | 6 | if {![info exists APP]} { 7 | set APP "./build/test/test" 8 | } 9 | 10 | if {![info exists VSIM]} { 11 | set VSIM vsim 12 | } 13 | 14 | $VSIM +permissive -suppress 3053 -suppress 8885 -suppress 12130 -lib $VSIM_PATH/work +APP=./build/test/test +notimingchecks +nospecify -t 1ps pulp_cluster_tb_optimized +permissive-off ++./build/test/test 15 | 16 | add log -r /* 17 | 18 | proc run_and_exit {} { 19 | run -all 20 | quit -code [examine -radix decimal sim:/pulp_cluster_tb/ret_val(30:0)] 21 | } 22 | 23 | if {[info exists ::env(FAULT_INJECTION)]} { 24 | if {![info exists ::env(FAULT_INJECTION_SCRIPT)]} { 25 | error "Error: Missing FAULT_INJECTION_SCRIPT to source!" 26 | } 27 | source $::env(FAULT_INJECTION_SCRIPT) 28 | } 29 | 30 | run_and_exit 31 | -------------------------------------------------------------------------------- /scripts/start.tcl: -------------------------------------------------------------------------------- 1 | if {![info exists VSIM_PATH ]} { 2 | return -code error -errorinfo "[ERRORINFO] You must set the \"VSIM_PATH\" variable before sourcing the start script." 3 | set VSIM_PATH "" 4 | } 5 | 6 | if {![info exists VSIM]} { 7 | set VSIM vsim 8 | } 9 | 10 | $VSIM +permissive -suppress 3053 -suppress 8885 -suppress 12130 -lib $VSIM_PATH/work +APP=./build/test/test +notimingchecks +nospecify -t 1ps pulp_cluster_tb_optimized +permissive-off ++./build/test/test 11 | 12 | if {[info exists ::env(FAULT_INJECTION)]} { 13 | if {![info exists ::env(FAULT_INJECTION_SCRIPT)]} { 14 | error "Error: Missing FAULT_INJECTION_SCRIPT to source!" 15 | } 16 | source $::env(FAULT_INJECTION_SCRIPT) 17 | } 18 | 19 | source $VSIM_PATH/scripts/wave.tcl 20 | 21 | add log -r /* 22 | run -all 23 | -------------------------------------------------------------------------------- /scripts/vsim.sh: -------------------------------------------------------------------------------- 1 | ROOT=$(cd "$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}")/.." && pwd) 2 | export VSIM_PATH="$ROOT" 3 | -------------------------------------------------------------------------------- /scripts/wave.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2025 ETH Zurich and University of Bologna. 2 | # Solderpad Hardware License, Version 0.51, see LICENSE for details. 3 | # SPDX-License-Identifier: SHL-0.51 4 | # 5 | # Andrea Belano 6 | 7 | onerror {resume} 8 | quietly WaveActivateNextPane {} 0 9 | 10 | set CORE_TYPE [examine sim:/pulp_cluster_tb/PulpClusterCfg.CoreType] 11 | set NUM_CORES [examine -radix dec sim:/pulp_cluster_tb/PulpClusterCfg.NumCores] 12 | set HMR_PRESENT [examine sim:/pulp_cluster_tb/PulpClusterCfg.HMRPresent] 13 | set HWPE_PRESENT [examine sim:/pulp_cluster_tb/PulpClusterCfg.HwpePresent] 14 | set HWPE_LIST [examine sim:/pulp_cluster_tb/PulpClusterCfg.HwpeCfg.HwpeList] 15 | set NUM_HWPE [examine -radix dec sim:/pulp_cluster_tb/PulpClusterCfg.HwpeCfg.NumHwpes] 16 | 17 | # Cluster 18 | add wave -noupdate -group cluster /pulp_cluster_tb/cluster_i/* 19 | # HMR 20 | add wave -noupdate -group hmr /pulp_cluster_tb/cluster_i/gen_hmr_unit/i_hmr_unit/* 21 | # Peripherals 22 | add wave -noupdate -group cluster_peripherals /pulp_cluster_tb/cluster_i/cluster_peripherals_i/* 23 | # Control Unit 24 | add wave -noupdate -group cluster_control_unit /pulp_cluster_tb/cluster_i/cluster_peripherals_i/cluster_control_unit_i/* 25 | # HWPE Subsystem 26 | add wave -noupdate -group hwpe_subsystem /pulp_cluster_tb/cluster_i/hwpe_gen/hwpe_subsystem_i/* 27 | for {set i 0} {$i < $NUM_HWPE} {incr i} { 28 | #set HWPE_NAME [tolower $HWPE_LIST($i)] 29 | set HWPE_NAME [string tolower [examine sim:/pulp_cluster_tb/PulpClusterCfg.HwpeCfg.HwpeList[$i]]] 30 | add wave -noupdate -group hwpe_subsystem -group $HWPE_NAME /pulp_cluster_tb/cluster_i/hwpe_gen/hwpe_subsystem_i/gen_hwpe[$i]/gen_$HWPE_NAME/i_$HWPE_NAME/* 31 | } 32 | # Cores 33 | for {set i 0} {$i < $NUM_CORES} {incr i} { 34 | add wave -noupdate -group Core[$i] -group core_region /pulp_cluster_tb/cluster_i/CORE[$i]/core_region_i/* 35 | add wave -noupdate -group Core[$i] -group core_region -group core /pulp_cluster_tb/cluster_i/CORE[$i]/core_region_i/${CORE_TYPE}_CORE/${CORE_TYPE}_CORE/* 36 | } 37 | 38 | configure wave -timelineunits ns 39 | 40 | # Remove the hierarchial strip from signals 41 | config wave -signalnamewidth 1 -------------------------------------------------------------------------------- /src_files.yml: -------------------------------------------------------------------------------- 1 | pulp_cluster: 2 | vlog_opts: [ 3 | -L fpnew_lib, 4 | -L hci_lib, 5 | -L common_cells_lib, 6 | -L axi_lib, 7 | -L ibex_lib 8 | ] 9 | incdirs: [ 10 | ../../rtl/includes, 11 | packages, 12 | ../axi/axi/include, 13 | ../axi/axi/include/axi, 14 | ] 15 | files: [ 16 | ../axi/axi/include/axi/typedef.svh, 17 | packages/pulp_cluster_package.sv, 18 | rtl/instr_width_converter.sv, 19 | rtl/core_region.sv, 20 | rtl/core_demux.sv, 21 | rtl/periph_demux.sv, 22 | rtl/cluster_interconnect_wrap.sv, 23 | rtl/tcdm_banks_wrap.sv, 24 | rtl/per_demux_wrap.sv, 25 | rtl/periph_FIFO.sv, 26 | rtl/xbar_pe_wrap.sv, 27 | rtl/cluster_peripherals.sv, 28 | rtl/cluster_clock_gate.sv, 29 | rtl/cluster_timer_wrap.sv, 30 | rtl/cluster_event_map.sv, 31 | rtl/dmac_wrap.sv, 32 | rtl/hwpe_subsystem.sv, 33 | rtl/cluster_bus_wrap.sv, 34 | rtl/axi2mem_wrap.sv, 35 | rtl/axi2per_wrap.sv, 36 | rtl/per2axi_wrap.sv, 37 | rtl/pulp_cluster.sv, 38 | ../pulp_soc/rtl/components/pulp_interfaces.sv, 39 | ] 40 | -------------------------------------------------------------------------------- /tb/dpi/elfloader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2022 ETH Zurich and University of Bologna. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // 5 | // Modified version of the RISC-V Frontend Server 6 | // (https://github.com/riscvarchive/riscv-fesvr, e41cfc3001293b5625c25412bd9b26e6e4ab8f7e) 7 | // 8 | // Nicole Narr 9 | // Christopher Reinwardt 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define IS_ELF(hdr) \ 27 | ((hdr).e_ident[0] == 0x7f && (hdr).e_ident[1] == 'E' && \ 28 | (hdr).e_ident[2] == 'L' && (hdr).e_ident[3] == 'F') 29 | 30 | #define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1) 31 | #define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2) 32 | 33 | #define PT_LOAD 1 34 | #define SHT_NOBITS 8 35 | #define SHT_PROGBITS 0x1 36 | #define SHT_GROUP 0x11 37 | 38 | typedef struct { 39 | uint8_t e_ident[16]; 40 | uint16_t e_type; 41 | uint16_t e_machine; 42 | uint32_t e_version; 43 | uint32_t e_entry; 44 | uint32_t e_phoff; 45 | uint32_t e_shoff; 46 | uint32_t e_flags; 47 | uint16_t e_ehsize; 48 | uint16_t e_phentsize; 49 | uint16_t e_phnum; 50 | uint16_t e_shentsize; 51 | uint16_t e_shnum; 52 | uint16_t e_shstrndx; 53 | } Elf32_Ehdr; 54 | 55 | typedef struct { 56 | uint32_t sh_name; 57 | uint32_t sh_type; 58 | uint32_t sh_flags; 59 | uint32_t sh_addr; 60 | uint32_t sh_offset; 61 | uint32_t sh_size; 62 | uint32_t sh_link; 63 | uint32_t sh_info; 64 | uint32_t sh_addralign; 65 | uint32_t sh_entsize; 66 | } Elf32_Shdr; 67 | 68 | typedef struct 69 | { 70 | uint32_t p_type; 71 | uint32_t p_offset; 72 | uint32_t p_vaddr; 73 | uint32_t p_paddr; 74 | uint32_t p_filesz; 75 | uint32_t p_memsz; 76 | uint32_t p_flags; 77 | uint32_t p_align; 78 | } Elf32_Phdr; 79 | 80 | typedef struct 81 | { 82 | uint32_t st_name; 83 | uint32_t st_value; 84 | uint32_t st_size; 85 | uint8_t st_info; 86 | uint8_t st_other; 87 | uint16_t st_shndx; 88 | } Elf32_Sym; 89 | 90 | typedef struct { 91 | uint8_t e_ident[16]; 92 | uint16_t e_type; 93 | uint16_t e_machine; 94 | uint32_t e_version; 95 | uint64_t e_entry; 96 | uint64_t e_phoff; 97 | uint64_t e_shoff; 98 | uint32_t e_flags; 99 | uint16_t e_ehsize; 100 | uint16_t e_phentsize; 101 | uint16_t e_phnum; 102 | uint16_t e_shentsize; 103 | uint16_t e_shnum; 104 | uint16_t e_shstrndx; 105 | } Elf64_Ehdr; 106 | 107 | typedef struct { 108 | uint32_t sh_name; 109 | uint32_t sh_type; 110 | uint64_t sh_flags; 111 | uint64_t sh_addr; 112 | uint64_t sh_offset; 113 | uint64_t sh_size; 114 | uint32_t sh_link; 115 | uint32_t sh_info; 116 | uint64_t sh_addralign; 117 | uint64_t sh_entsize; 118 | } Elf64_Shdr; 119 | 120 | typedef struct { 121 | uint32_t p_type; 122 | uint32_t p_flags; 123 | uint64_t p_offset; 124 | uint64_t p_vaddr; 125 | uint64_t p_paddr; 126 | uint64_t p_filesz; 127 | uint64_t p_memsz; 128 | uint64_t p_align; 129 | } Elf64_Phdr; 130 | 131 | typedef struct { 132 | uint32_t st_name; 133 | uint8_t st_info; 134 | uint8_t st_other; 135 | uint16_t st_shndx; 136 | uint64_t st_value; 137 | uint64_t st_size; 138 | } Elf64_Sym; 139 | 140 | // address and size 141 | std::vector> sections; 142 | 143 | // memory based address and content 144 | std::map> mems; 145 | 146 | // Entrypoint 147 | uint64_t entry = 0; 148 | int section_index = 0; 149 | 150 | extern "C" { 151 | char get_entry(long long *entry_ret); 152 | char get_section(long long *address_ret, long long *len_ret); 153 | char read_section(long long address, const svOpenArrayHandle buffer, long long len); 154 | char read_elf(const char *filename); 155 | } 156 | 157 | static void write (uint64_t address, uint64_t len, uint8_t *buf) 158 | { 159 | std::vector mem; 160 | for (int i = 0; i < len; i++) { 161 | mem.push_back(buf[i]); 162 | } 163 | mems.insert(std::make_pair(address, mem)); 164 | } 165 | 166 | // Return the entry point reported by the ELF file 167 | // Must be called after reading the elf file obviously 168 | extern "C" char get_entry(long long *entry_ret) 169 | { 170 | *entry_ret = entry; 171 | return 0; 172 | } 173 | 174 | // Iterator over the section addresses and lengths 175 | // Returns: 176 | // 0 if there are no more sections 177 | // 1 if there are more sections to load 178 | extern "C" char get_section(long long *address_ret, long long *len_ret) 179 | { 180 | if (section_index < sections.size()) { 181 | *address_ret = sections[section_index].first; 182 | *len_ret = sections[section_index].second; 183 | section_index++; 184 | return 1; 185 | } else { 186 | return 0; 187 | } 188 | } 189 | 190 | extern "C" char read_section(long long address, const svOpenArrayHandle buffer, long long len) 191 | { 192 | // get actual pointer 193 | char *buf = (char *) svGetArrayPtr(buffer); 194 | 195 | // check that the address points to a section 196 | if (!mems.count(address)) { 197 | printf("[ELF] ERROR: No section found for address %p\n", address); 198 | return -1; 199 | } 200 | 201 | // copy array 202 | long long int len_tmp = len; 203 | for (auto &datum : mems.find(address)->second) { 204 | if(len_tmp-- == 0){ 205 | printf("[ELF] ERROR: Copied 0x%lx bytes. Buffer is full but there is still data available.\n", len); 206 | return -1; 207 | } 208 | 209 | *buf++ = datum; 210 | } 211 | 212 | return 0; 213 | } 214 | 215 | template 216 | static void load_elf(char *buf, size_t size) 217 | { 218 | E *eh = (E *) buf; 219 | P *ph = (P *) (buf + eh->e_phoff); 220 | Sh *sh = (Sh *) (buf + eh->e_shoff); 221 | 222 | char *shstrtab = NULL; 223 | 224 | if(size < eh->e_phoff + (eh->e_phnum * sizeof(P))){ 225 | printf("[ELF] ERROR: Filesize is smaller than advertised program headers (0x%lx vs 0x%lx)\n", size, eh->e_phoff + (eh->e_phnum * sizeof(P))); 226 | return; 227 | } 228 | 229 | entry = eh->e_entry; 230 | printf("[ELF] INFO: Entrypoint at %p\n", entry); 231 | 232 | // Iterate over all program header entries 233 | for (unsigned int i = 0; i < eh->e_phnum; i++) { 234 | // Check whether the current program header entry contains a loadable section of nonzero size 235 | if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { 236 | // Is this section something else than zeros? 237 | if (ph[i].p_filesz) { 238 | assert(size >= ph[i].p_offset + ph[i].p_filesz); 239 | sections.push_back(std::make_pair(ph[i].p_paddr, ph[i].p_memsz)); 240 | write(ph[i].p_paddr, ph[i].p_filesz, (uint8_t*)buf + ph[i].p_offset); 241 | } 242 | 243 | if(ph[i].p_memsz > ph[i].p_filesz){ 244 | printf("[ELF] WARNING: The section starting @ %p contains 0x%lx zero bytes which will NOT be preloaded!\n", 245 | ph[i].p_paddr, (ph[i].p_memsz - ph[i].p_filesz)); 246 | } 247 | } 248 | } 249 | 250 | if(size < eh->e_shoff + (eh->e_shnum * sizeof(Sh))){ 251 | printf("[ELF] ERROR: Filesize is smaller than advertised section headers (0x%lx vs 0x%lx)\n", 252 | size, eh->e_shoff + (eh->e_shnum * sizeof(Sh))); 253 | return; 254 | } 255 | 256 | if(eh->e_shstrndx >= eh->e_shnum){ 257 | printf("[ELF] ERROR: Malformed ELF file. The index of the section header strings is out of bounds (0x%lx vs max 0x%lx)", 258 | eh->e_shstrndx, eh->e_shnum); 259 | return; 260 | } 261 | 262 | if(size < sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size){ 263 | printf("[ELF] ERROR: Filesize is smaller than advertised size of section name table (0x%lx vs 0x%lx)\n", 264 | size, sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); 265 | return; 266 | } 267 | 268 | // Get a direct pointer to the section name section 269 | shstrtab = buf + sh[eh->e_shstrndx].sh_offset; 270 | unsigned int strtabidx = 0, symtabidx = 0; 271 | 272 | // Iterate over all section headers to find .strtab and .symtab 273 | for (unsigned int i = 0; i < eh->e_shnum; i++) { 274 | // Get an upper limit on how long the name can be (length of the section name section minus the offset of the name) 275 | unsigned int max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; 276 | 277 | // Is this the string table? 278 | if(strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0){ 279 | printf("[ELF] INFO: Found string table at offset 0x%lx\n", sh[i].sh_offset); 280 | strtabidx = i; 281 | continue; 282 | } 283 | 284 | // Is this the symbol table? 285 | if(strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0){ 286 | printf("[ELF] INFO: Found symbol table at offset 0x%lx\n", sh[i].sh_offset); 287 | symtabidx = i; 288 | continue; 289 | } 290 | } 291 | } 292 | 293 | extern "C" char read_elf(const char *filename) 294 | { 295 | char *buf = NULL; 296 | Elf64_Ehdr* eh64 = NULL; 297 | int fd = open(filename, O_RDONLY); 298 | char retval = 0; 299 | struct stat s; 300 | size_t size = 0; 301 | 302 | if(fd == -1){ 303 | printf("[ELF] ERROR: Unable to open file %s\n", filename); 304 | retval = -1; 305 | goto exit; 306 | } 307 | 308 | if(fstat(fd, &s) < 0) { 309 | printf("[ELF] ERROR: Unable to read stats for file %s\n", filename); 310 | retval = -1; 311 | goto exit_fd; 312 | } 313 | 314 | size = s.st_size; 315 | 316 | if(size < sizeof(Elf64_Ehdr)){ 317 | printf("[ELF] ERROR: File %s is too small to contain a valid ELF header (0x%lx vs 0x%lx)\n", filename, size, sizeof(Elf64_Ehdr)); 318 | retval = -1; 319 | goto exit_fd; 320 | } 321 | 322 | buf = (char *) mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 323 | if(buf == MAP_FAILED){ 324 | printf("[ELF] ERROR: Unable to memory map file %s\n", filename); 325 | retval = -1; 326 | goto exit_fd; 327 | } 328 | 329 | printf("[ELF] INFO: File %s was memory mapped to %p\n", filename, buf); 330 | 331 | eh64 = (Elf64_Ehdr *) buf; 332 | 333 | if(!(IS_ELF32(*eh64) || IS_ELF64(*eh64))){ 334 | printf("[ELF] ERROR: File %s does not contain a valid ELF signature\n", filename); 335 | retval = -1; 336 | goto exit_mmap; 337 | } 338 | 339 | if (IS_ELF32(*eh64)){ 340 | load_elf(buf, size); 341 | } else { 342 | load_elf(buf, size); 343 | } 344 | 345 | exit_mmap: 346 | munmap(buf, size); 347 | 348 | exit_fd: 349 | close(fd); 350 | 351 | exit: 352 | return retval; 353 | } 354 | -------------------------------------------------------------------------------- /tb/mock_uart.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | // 11 | // Author: Florian Zaruba, ETH Zurich 12 | // Date: 28/09/2018 13 | // Description: Mock replacement for UART in testbench (not synthesiesable!) 14 | 15 | module mock_uart #( 16 | parameter int UART_IDX = 0 17 | )( 18 | input logic clk_i, 19 | input logic rst_ni, 20 | input logic penable_i, 21 | input logic pwrite_i, 22 | input logic [31:0] paddr_i, 23 | input logic psel_i, 24 | input logic [31:0] pwdata_i, 25 | output logic [31:0] prdata_o, 26 | output logic pready_o, 27 | output logic pslverr_o 28 | ); 29 | localparam RBR = 0; 30 | localparam THR = 0; 31 | localparam IER = 1; 32 | localparam IIR = 2; 33 | localparam FCR = 2; 34 | localparam LCR = 3; 35 | localparam MCR = 4; 36 | localparam LSR = 5; 37 | localparam MSR = 6; 38 | localparam SCR = 7; 39 | localparam DLL = 0; 40 | localparam DLM = 1; 41 | 42 | localparam THRE = 5; // transmit holding register empty 43 | localparam TEMT = 6; // transmit holding register empty 44 | 45 | byte lcr = 0; 46 | byte dlm = 0; 47 | byte dll = 0; 48 | byte mcr = 0; 49 | byte lsr = 0; 50 | byte ier = 0; 51 | byte msr = 0; 52 | byte scr = 0; 53 | logic fifo_enabled = 1'b0; 54 | 55 | integer charnum = 0; 56 | logic [256*8-1:0] stringa = '0; 57 | 58 | assign pready_o = 1'b1; 59 | assign pslverr_o = 1'b0; 60 | 61 | function void uart_tx(byte ch); 62 | if(ch==8'h0A) begin 63 | $display("[TB UART %2d] %s", UART_IDX, stringa); 64 | charnum = 0; 65 | stringa = '0; 66 | end else begin 67 | stringa[(255-charnum)*8 +: 8] = ch; 68 | charnum = charnum + 1; 69 | end 70 | endfunction : uart_tx 71 | 72 | always_ff @(posedge clk_i or negedge rst_ni) begin 73 | if (rst_ni) begin 74 | if (psel_i & penable_i & pwrite_i) begin 75 | case ((paddr_i >> 'h2) & 'h7) 76 | THR: begin 77 | if (lcr & 'h80) dll <= byte'(pwdata_i[7:0]); 78 | else begin 79 | uart_tx(byte'(pwdata_i[7:0])); 80 | end 81 | end 82 | IER: begin 83 | if (lcr & 'h80) dlm <= byte'(pwdata_i[7:0]); 84 | else ier <= byte'(pwdata_i[7:0] & 'hF); 85 | end 86 | FCR: begin 87 | if (pwdata_i[0]) fifo_enabled <= 1'b1; 88 | else fifo_enabled <= 1'b0; 89 | end 90 | LCR: lcr <= byte'(pwdata_i[7:0]); 91 | MCR: mcr <= byte'(pwdata_i[7:0] & 'h1F); 92 | LSR: lsr <= byte'(pwdata_i[7:0]); 93 | MSR: msr <= byte'(pwdata_i[7:0]); 94 | SCR: scr <= byte'(pwdata_i[7:0]); 95 | default:; 96 | endcase 97 | end 98 | end 99 | end 100 | 101 | always_comb begin 102 | prdata_o = '0; 103 | if (psel_i & penable_i & ~pwrite_i) begin 104 | case ((paddr_i >> 'h2) & 'h7) 105 | THR: begin 106 | if (lcr & 'h80) prdata_o = {24'b0, dll}; 107 | end 108 | IER: begin 109 | if (lcr & 'h80) prdata_o = {24'b0, dlm}; 110 | else prdata_o = {24'b0, ier}; 111 | end 112 | IIR: begin 113 | if (fifo_enabled) prdata_o = {24'b0, 8'hc0}; 114 | else prdata_o = {24'b0, 8'b0}; 115 | end 116 | LCR: prdata_o = {24'b0, lcr}; 117 | MCR: prdata_o = {24'b0, mcr}; 118 | LSR: prdata_o = {24'b0, (lsr | (1 << THRE) | (1 << TEMT))}; 119 | MSR: prdata_o = {24'b0, msr}; 120 | SCR: prdata_o = {24'b0, scr}; 121 | default:; 122 | endcase 123 | end 124 | end 125 | endmodule 126 | -------------------------------------------------------------------------------- /tb/mock_uart_axi.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | // 11 | // Author: Florian Zaruba, ETH Zurich 12 | // Date: 28/09/2018 13 | // Description: Mock replacement for UART in testbench (not synthesiesable!) 14 | 15 | module mock_uart_axi #( 16 | parameter int unsigned AxiIw = 0, 17 | parameter int unsigned AxiAw = 0, 18 | parameter int unsigned AxiDw = 0, 19 | parameter int unsigned AxiUw = 0, 20 | parameter logic [AxiAw-1:0] BaseAddr = 0, 21 | parameter int unsigned N_CORES = 8 22 | 23 | )( 24 | input logic clk_i, 25 | input logic rst_ni, 26 | input logic test_i, 27 | AXI_BUS.Slave uart 28 | ); 29 | 30 | logic uart_penable; 31 | logic uart_pwrite; 32 | logic [AxiAw-1:0] uart_paddr; 33 | logic [N_CORES-1:0] uart_psel; 34 | logic [31:0] uart_pwdata; 35 | logic [N_CORES-1:0] [31:0] uart_prdata; 36 | logic [N_CORES-1:0] uart_pready; 37 | logic [N_CORES-1:0] uart_pslverr; 38 | 39 | AXI_LITE #( 40 | .AXI_DATA_WIDTH(AxiDw), 41 | .AXI_ADDR_WIDTH(AxiAw) 42 | ) uart_lite_wide(); 43 | 44 | AXI_LITE #( 45 | .AXI_DATA_WIDTH(32), 46 | .AXI_ADDR_WIDTH(AxiAw) 47 | ) uart_lite(); 48 | 49 | axi_to_axi_lite_intf #( 50 | .AXI_ADDR_WIDTH ( AxiAw ), 51 | .AXI_DATA_WIDTH ( AxiDw ), 52 | .AXI_ID_WIDTH ( AxiIw ), 53 | .AXI_USER_WIDTH ( AxiUw ), 54 | .AXI_MAX_WRITE_TXNS(1), 55 | .AXI_MAX_READ_TXNS (1), 56 | .FALL_THROUGH (1'b1), 57 | .FULL_BW (1'b1) 58 | ) i_axi_to_axi_lite_intf ( 59 | .clk_i, 60 | .rst_ni, 61 | .testmode_i(test_i), 62 | .slv (uart), 63 | .mst (uart_lite_wide) 64 | ); 65 | 66 | axi_lite_dw_converter_intf #( 67 | .AXI_ADDR_WIDTH (AxiAw), 68 | .AXI_SLV_PORT_DATA_WIDTH(AxiDw), 69 | .AXI_MST_PORT_DATA_WIDTH(32) 70 | ) i_axi_lite_dw_converter_intf ( 71 | .clk_i ( clk_i ), 72 | .rst_ni( rst_ni ), 73 | .slv ( uart_lite_wide ), 74 | .mst ( uart_lite ) 75 | ); 76 | 77 | typedef struct packed { 78 | int unsigned idx; 79 | logic [AxiAw-1:0] start_addr; 80 | logic [AxiAw-1:0] end_addr; 81 | } rule_t; 82 | 83 | rule_t [0:N_CORES-1] rule; 84 | // each mock UART only has 2 words of address space 85 | for (genvar g=0; g