├── .dir-locals.el ├── .github ├── verible.waiver └── workflows │ ├── gitlab-ci.yml │ ├── lint.yml │ └── publish-docs.yml ├── .gitignore ├── .gitlab-ci.yml ├── .gitmodules ├── Bender.local ├── Bender.lock ├── Bender.yml ├── CHANGELOG.md ├── CHANGELOG_WEEKLY.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── bender-common.mk ├── bender-safed.mk ├── bender-sim.mk ├── bender-synth.mk ├── bender-xilinx.mk ├── carfield.mk ├── docs ├── gs.md ├── img │ ├── arch.svg │ ├── clk_rst.svg │ └── isolation.svg ├── index.md ├── tg │ ├── index.md │ ├── integr.md │ ├── sim.md │ ├── synth.md │ └── xilinx.md └── um │ ├── arch.md │ ├── index.md │ └── sw.md ├── env ├── env-iis.sh ├── pulpd-env.sh ├── safed-env.sh └── spatzd-env.sh ├── hw ├── carfield.sv ├── carfield_pkg.sv ├── carfield_rstgen.sv ├── cheshire_wrap.sv ├── configs │ ├── carfield_l2dual_periph.sv │ ├── carfield_l2dual_pulp_periph.sv │ ├── carfield_l2dual_safe_periph.sv │ ├── carfield_l2dual_safe_pulp_periph.sv │ ├── carfield_l2dual_safe_pulp_spatz_periph.sv │ ├── carfield_l2dual_safe_secure_pulp_spatz_periph_can.sv │ ├── carfield_l2dual_safe_spatz_periph.sv │ ├── carfield_l2dual_secure_periph.sv │ └── carfield_l2dual_spatz_periph.sv ├── hyperbus_wrap.sv ├── l2_wrap.sv ├── regs │ ├── carfield_reg_pkg.sv │ ├── carfield_reg_top.sv │ ├── carfield_regs.csv │ ├── carfield_regs.hjson │ └── pcr.md └── spatz_cluster_wrapper.sv ├── mkdocs.yml ├── requirements.txt ├── scripts ├── csv_to_json.py ├── elf2header.py └── elf2slm.py ├── sw ├── .clang-format ├── .gitignore ├── benchmarks │ └── .gitkeep ├── boot │ ├── carfield.dtsi │ ├── carfield_bd_vcu118.dts │ ├── carfield_bd_vcu128.dts │ ├── carfield_pcie.dts │ ├── carfield_soc.dtsi │ ├── carfield_vanilla_vcu128.dts │ ├── mac_address.dtsi │ └── remote_boot.dtsi ├── include │ ├── bits.h │ ├── car_linux_mmap.h │ ├── car_memory_map.h │ ├── car_params.h │ ├── car_properties.h │ ├── car_util.h │ ├── csr.h │ ├── io.h │ └── regs │ │ ├── axi_llc_regs.h │ │ ├── clic.h │ │ ├── clicint.h │ │ ├── irq_router.h │ │ ├── safety_soc_ctrl.h │ │ ├── soc_ctrl.h │ │ ├── spatz_cluster_peripheral.h │ │ └── system_timer.h ├── lib │ └── .gitkeep ├── link │ └── l2.ld ├── sw.mk └── tests │ ├── bare-metal │ ├── hostd │ │ ├── addressability_test.c │ │ ├── axirt_budget.c │ │ ├── axirt_hello.c │ │ ├── cache_partitioning_basic.c │ │ ├── helloworld.c │ │ ├── irq_router_rw.c │ │ ├── mbox_test.c │ │ ├── minimal.c │ │ ├── pulp-offload-intf.c │ │ ├── pulpd_offloader_blocking.c │ │ ├── safed_offloader_blocking.c │ │ ├── spatz-offload.c.wip │ │ ├── sw_rst_seq.c │ │ ├── system_timer_test.c │ │ └── vclic_basic.c │ ├── pulpd │ │ └── sw.mk │ ├── safed │ │ └── sw.mk │ ├── secd │ │ └── sw.mk │ └── spatzd │ │ └── build │ └── linux │ └── addressability_test.c ├── target ├── .gitignore ├── sim │ ├── sim.mk │ ├── src │ │ ├── carfield_fix.sv │ │ ├── carfield_tb.sv │ │ └── vip_carfield_soc.sv │ └── vsim │ │ └── start.carfield_soc.tcl ├── synth │ └── src │ │ └── carfield_synth_wrap.sv └── xilinx │ ├── README.md │ ├── constraints │ ├── carfield.xdc │ └── carfield_islands.tcl │ ├── flavor_bd │ ├── .gitignore │ ├── constraints │ │ ├── vcu118.xdc │ │ ├── vcu118_ext_jtag.xdc │ │ ├── vcu128.xdc │ │ └── vcu128_ext_jtag.xdc │ ├── flavor_bd.mk │ └── scripts │ │ ├── carfield_bd_ext_jtag_vcu118.tcl │ │ ├── carfield_bd_ext_jtag_vcu128.tcl │ │ ├── carfield_bd_vcu118.tcl │ │ ├── carfield_bd_vcu128.tcl │ │ └── run.tcl │ ├── flavor_vanilla │ ├── .gitignore │ ├── constraints │ │ ├── carfield_top_xilinx.xdc │ │ ├── vcu128.xdc │ │ └── vcu128_ext_jtag.xdc │ ├── flavor_vanilla.mk │ ├── scripts │ │ └── run.tcl │ └── src │ │ ├── carfield_top_xilinx.sv │ │ ├── dram_wrapper_xilinx.sv │ │ ├── fan_ctrl.sv │ │ └── phy_definitions.svh │ ├── scripts │ ├── flash_spi.tcl │ ├── overrides.sh │ ├── program.tcl │ └── write_cfgmem.tcl │ ├── src │ ├── cdc_dst_axi_err.sv │ └── overrides │ │ └── tc_clk_xilinx.sv │ ├── xilinx.mk │ └── xilinx_ips │ ├── .gitignore │ ├── carfield_ip │ ├── carfield_ip.mk │ ├── constraints │ │ ├── carfield_xilinx_ip.xdc │ │ └── ooc_carfield_ip.xdc │ ├── src │ │ ├── carfield_xilinx.sv │ │ └── carfield_xilinx_ip.v │ └── tcl │ │ └── run.tcl │ ├── xilinx_ips.mk │ ├── xlnx_clk_wiz │ ├── tcl │ │ └── run.tcl │ └── xlnx_clk_wiz.mk │ ├── xlnx_mig_ddr4 │ ├── tcl │ │ └── run.tcl │ └── xlnx_mig_ddr4.mk │ └── xlnx_vio │ ├── tcl │ └── run.tcl │ └── xlnx_vio.mk └── utils ├── generate-makefile-help.sh ├── help.mk ├── lint ├── lint.mk └── spyglass │ ├── scripts │ └── run_lint.tcl │ └── sgdc │ └── func.sgdc ├── reggen ├── reggen │ ├── README.md │ ├── __init__.py │ ├── access.py │ ├── alert.py │ ├── bits.py │ ├── bus_interfaces.py │ ├── enum_entry.py │ ├── field.py │ ├── fpv_csr.sv.tpl │ ├── gen_cfg_html.py │ ├── gen_cfg_md.py │ ├── gen_cheader.py │ ├── gen_dv.py │ ├── gen_fpv.py │ ├── gen_html.py │ ├── gen_json.py │ ├── gen_md.py │ ├── gen_rtl.py │ ├── gen_selfdoc.py │ ├── html_helpers.py │ ├── inter_signal.py │ ├── ip_block.py │ ├── lib.py │ ├── md_helpers.py │ ├── multi_register.py │ ├── params.py │ ├── reg_base.py │ ├── reg_block.py │ ├── reg_html.css │ ├── reg_pkg.sv.tpl │ ├── reg_top.sv.tpl │ ├── register.py │ ├── signal.py │ ├── uvm_reg.sv.tpl │ ├── uvm_reg_base.sv.tpl │ ├── validate.py │ ├── version.py │ └── window.py ├── regtool.py └── topgen │ ├── __init__.py │ ├── c.py │ ├── gen_dv.py │ ├── intermodule.py │ ├── lib.py │ ├── merge.py │ ├── templates │ ├── README.md │ ├── chip_env_pkg__params.sv.tpl │ ├── chiplevel.sv.tpl │ ├── clang-format │ ├── tb__alert_handler_connect.sv.tpl │ ├── tb__xbar_connect.sv.tpl │ ├── toplevel.c.tpl │ ├── toplevel.h.tpl │ ├── toplevel.sv.tpl │ ├── toplevel_memory.h.tpl │ ├── toplevel_memory.ld.tpl │ ├── toplevel_pkg.sv.tpl │ ├── toplevel_rnd_cnst_pkg.sv.tpl │ └── xbar_env_pkg__params.sv.tpl │ ├── top.py │ ├── top_uvm_reg.sv.tpl │ └── validate.py └── venv.mk /.dir-locals.el: -------------------------------------------------------------------------------- 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 | ;; Robert Balas 6 | 7 | ;;; Directory Local Variables 8 | ;;; For more information see (info "(emacs) Directory Variables") 9 | 10 | ((nil . ((fill-column . 100))) 11 | (verilog-mode 12 | ;; (verilog-indent-lists quote nil) 13 | ;; (verilog-auto-lineup quote all) 14 | (verilog-cexp-indent . 2) 15 | (verilog-case-indent . 2) 16 | (verilog-indent-level-behavioral . 2) 17 | (verilog-indent-level-declaration . 2) 18 | (verilog-indent-level-module . 2) 19 | (verilog-indent-level . 2))) 20 | 21 | -------------------------------------------------------------------------------- /.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: Alessandro Ottaviano 6 | 7 | name: gitlab-ci 8 | 9 | on: [ push, pull_request, workflow_dispatch ] 10 | 11 | jobs: 12 | gitlab-ci: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Check Gitlab CI 16 | uses: pulp-platform/pulp-actions/gitlab-ci@v1 17 | with: 18 | domain: iis-git.ee.ethz.ch 19 | repo: github-mirror/carfield 20 | token: ${{ secrets.GITLAB_TOKEN }} 21 | poll-count: 2160 22 | -------------------------------------------------------------------------------- /.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)?.* 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 | .dir-locals.el 31 | utils/* 32 | scripts/* 33 | 34 | lint-sv: 35 | runs-on: ubuntu-latest 36 | steps: 37 | - 38 | name: Checkout 39 | uses: actions/checkout@v3 40 | - 41 | name: Run Verible 42 | uses: chipsalliance/verible-linter-action@main 43 | with: 44 | paths: hw 45 | exclude_paths: hw/configs 46 | extra_args: "--waiver_files .github/verible.waiver" 47 | github_token: ${{ secrets.GITHUB_TOKEN }} 48 | fail_on_error: true 49 | reviewdog_reporter: github-check 50 | 51 | # lint-cxx: 52 | # runs-on: ubuntu-latest 53 | # steps: 54 | # - 55 | # name: Checkout 56 | # uses: actions/checkout@v3 57 | # - 58 | # name: Run Clang-format 59 | # uses: DoozyX/clang-format-lint-action@v0.14 60 | # with: 61 | # extensions: 'c,h,cpp' 62 | # clangFormatVersion: 14 63 | # style: > 64 | # { 65 | # IndentWidth: 4, 66 | # ColumnLimit: 100, 67 | # AlignEscapedNewlines: DontAlign, 68 | # SortIncludes: false, 69 | # AllowShortFunctionsOnASingleLine: None, 70 | # AllowShortIfStatementsOnASingleLine: true, 71 | # AllowShortLoopsOnASingleLine: true 72 | # } 73 | # exclude: | 74 | # ./sw/include/regs/*.h 75 | # ./target/sim/src/elfloader.cpp 76 | -------------------------------------------------------------------------------- /.github/workflows/publish-docs.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 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: publish-docs 8 | 9 | on: 10 | push: 11 | branches: [ main ] 12 | workflow_dispatch: 13 | 14 | jobs: 15 | 16 | deploy: 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - 20 | name: Checkout 21 | uses: actions/checkout@v3 22 | with: 23 | submodules: recursive 24 | - 25 | name: Install Python 26 | uses: actions/setup-python@v2 27 | with: 28 | python-version: 3.9 29 | cache: pip 30 | - 31 | name: Install Python requirements 32 | run: pip install -r requirements.txt 33 | - 34 | name: Deploy Documentation 35 | run: mkdocs gh-deploy --force 36 | -------------------------------------------------------------------------------- /.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 car-nonfree-init 15 | artifacts: 16 | paths: [ nonfree/ci.yml ] 17 | 18 | subpipe: 19 | stage: nonfree 20 | needs: [ init ] 21 | variables: 22 | PARENT_PIPELINE_SOURCE: $CI_PIPELINE_SOURCE 23 | trigger: 24 | include: 25 | - artifact: nonfree/ci.yml 26 | job: init 27 | strategy: depend 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "sw/deps/cva6-sdk"] 2 | path = sw/deps/cva6-sdk 3 | url = https://github.com/pulp-platform/cva6-sdk.git 4 | -------------------------------------------------------------------------------- /Bender.local: -------------------------------------------------------------------------------- 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 | overrides: 6 | axi: { git: https://github.com/pulp-platform/axi.git , version: 0.39.1 } 7 | axi_riscv_atomics: { git: https://github.com/pulp-platform/axi_riscv_atomics.git , version: 0.8.2 } 8 | apb: { git: "https://github.com/pulp-platform/apb.git" , version: 0.2.3 } 9 | register_interface: { git: "https://github.com/pulp-platform/register_interface.git" , version: 0.4.1 } 10 | redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git" , rev: "5616a36f5e51d6f07f1c8bca15194077657e197d" } # branch: yt/rapidrecovery 11 | tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git" , version: =0.2.13 } 12 | riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git" , version: =0.8.0 } 13 | idma: { git: "https://github.com/pulp-platform/idma.git" , version: 0.5.1 } 14 | hier-icache: { git: "https://github.com/pulp-platform/hier-icache.git" , rev: a971e364bf8090cf77fafad995b480c1ac7ea4e0 } 15 | scm: { git: "https://github.com/pulp-platform/scm.git" , rev: 74426dee36f28ae1c02f7635cf844a0156145320 } 16 | cluster_interconnect: { git: "https://github.com/pulp-platform/cluster_interconnect.git", rev: 89e1019d64a86425211be6200770576cbdf3e8b3 } # branch: assertion-fix 17 | clic: { git: "https://github.com/pulp-platform/clic.git" , rev: 0ff9f07e0a492bff046dfe24399b1e1e82d557b7 } # branch: balasr/dev-2 18 | fpnew: { git: "https://github.com/pulp-platform/cvfpu.git" , rev: pulp-v0.1.3 } 19 | cv32e40p: { git: "https://github.com/pulp-platform/cv32e40p.git" , rev: e863f576699815b38cc9d80dbdede8ed5efd5991 } 20 | axi_rt: { git: "https://github.com/pulp-platform/axi_rt.git" , version: =0.0.0-alpha.4 } 21 | serial_link: { git: "https://github.com/pulp-platform/serial_link.git" , rev: 4024f01b1d67cdf1cf9486467d0f2e2f407aa372 } 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | All notable changes to this project will be documented in this file. 2 | 3 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). 4 | 5 | ## [Unreleased] 6 | 7 | ## [0.0.0] - 2023-03-05 8 | Copied the top level from [Iguana](https://github.com/pulp-platform/iguana) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Global owners 2 | * @alex96295 @CyrilKoe -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulp-platform/carfield/57d5f1e57d2e5f45ce0dc956e74618f6b5c737ad/CONTRIBUTING.md -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 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 | # Alessandro Ottaviano 6 | 7 | CAR_ROOT ?= $(shell pwd) 8 | BENDER ?= bender -d $(CAR_ROOT) 9 | 10 | include carfield.mk 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Carfield 2 | 3 | Carfield is an open-research heterogeneous platform for safety, resilient and time-predictable systems. Originally conceived as automotive-oriented SoC, the high configurability of the platform makes it tunable to target a broader class of mixed-criticality applications' domains, such as automotive, space or industry. 4 | 5 | Carfield is developed as part of the PULP project, a joint effort between ETH Zurich and the 6 | University of Bologna. 7 | 8 | ## Motivation 9 | 10 | The rapid evolution of AI algorithms and the massive amount of sensed data across 11 | application-domains such as Automotive, Space and Cyber-Physical embedded systems (CPSs), call for a 12 | *paradigm shift* in the design of **next generation of mixed-criticality systems (MCSs)**, from 13 | simple micro-controllers towards powerful and heterogeneous edge computers. 14 | 15 | These must not only deliver outstanding performance and energy efficiency but also ensure steadfast 16 | safety, resilience, and security. 17 | 18 | The Carfield platform aims to tackle these architectural challenges establishing itself as a 19 | pre-competitive heterogeneous platform for MCSs, underpinned by **fully open-source Intellectual 20 | Properties (IPs)**. 21 | 22 | Carfield showcases pioneering hardware solutions, addressing challenges related to time-predictable 23 | on/off-chip communication, robust fault recovery mechanisms, secure boot processes, cryptographic 24 | acceleration services, hardware-assisted virtualization, and accelerated computation for both 25 | floating-point and integer workloads. 26 | 27 | ## Quick Start 28 | 29 | * To learn how to build and use Carfield, see [Getting 30 | Started](https://pulp-platform.github.io/carfield/gs/). 31 | * To learn about available simulation, FPGA, and ASIC targets, see 32 | [Targets](https://pulp-platform.github.io/carfield/tg). 33 | * For detailed information on Carfield's inner workings, consult the [User 34 | Manual](https://pulp-platform.github.io/carfield/um/). 35 | 36 | If you are impatient and have all needed 37 | [dependencies](https://pulp-platform.github.io/carfield/gs/#dependencies), type: 38 | 39 | ``` 40 | make car-all 41 | ``` 42 | 43 | and then run a [simulation](https://pulp-platform.github.io/carfield/tg/sim) with Questasim by 44 | typing: 45 | 46 | ```tcl 47 | make car-vsim-sim-build 48 | make car-vsim-sim-run CHS_BINARY=./sw/tests/bare-metal/hostd/helloworld.car.l2.elf 49 | ``` 50 | 51 | --- 52 | 53 | To display the main *Make* build targets and their usage, from the root repository type: 54 | 55 | ```tcl 56 | make help 57 | ``` 58 | 59 | The Make files are autodocumented. 60 | 61 | ## License 62 | 63 | Unless specified otherwise in the respective file headers, all code checked into this repository is 64 | made available under a permissive license. All hardware sources and tool scripts are licensed under 65 | the Solderpad Hardware License 0.51 (see `LICENSE`) with the exception of generated register file 66 | code (e.g. `hw/regs/*.sv`), which is generated by a fork of lowRISC's 67 | [`regtool`](https://github.com/lowRISC/opentitan/blob/master/util/regtool.py) and licensed under 68 | Apache 2.0. All software sources are licensed under Apache 2.0. 69 | -------------------------------------------------------------------------------- /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 | # Author: Yvan Tortorella 6 | # Author: Matteo Perotti 7 | 8 | # Runtime-selectable Carfield configuration 9 | CARFIELD_CONFIG ?= carfield_l2dual_safe_secure_pulp_spatz_periph_can 10 | 11 | # bender targets 12 | common_targs += -t cva6 13 | common_targs += -t mchan 14 | common_targs += -t spatz 15 | common_targs += -t integer_cluster 16 | common_targs += -t cv32e40p_use_ff_regfile 17 | common_targs += -t scm_use_fpga_scm 18 | common_targs += -t cv64a6_imafdcsclic_sv39 19 | common_targs += -t rtl 20 | # Carfield config target. 21 | common_targs += -t $(CARFIELD_CONFIG) 22 | 23 | # bender defines 24 | common_defs += -D FEATURE_ICACHE_STAT 25 | common_defs += -D PRIVATE_ICACHE 26 | common_defs += -D HIERARCHY_ICACHE_32BIT 27 | common_defs += -D ICAHE_USE_FF 28 | common_defs += -D CLUSTER_ALIAS 29 | -------------------------------------------------------------------------------- /bender-safed.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 | # Author: Alessandro Ottaviano 6 | 7 | # bender defines 8 | safed_defs += -D TARGET_SIMULATION 9 | -------------------------------------------------------------------------------- /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 | # Author: Alessandro Ottaviano 6 | # Author: Michael Rogenmoser 7 | 8 | # bender targets 9 | sim_targs += -t sim 10 | sim_targs += -t test 11 | sim_targs += -t simulation 12 | sim_targs += -t hyper_test 13 | -------------------------------------------------------------------------------- /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 | # Author: Yvan Tortorella 6 | # Author: Matteo Perotti 7 | 8 | # bender targets 9 | synth_targs += -t asic 10 | synth_targs += -t synthesis 11 | synth_targs += -t top_level 12 | synth_targs += -t intel16 13 | synth_targs += -t cluster_standalone 14 | 15 | # bender defines 16 | synth_defs += -D SYNTHESIS 17 | synth_defs += -D EXCLUDE_PADFRAME 18 | synth_defs += -D TARGET_INTEL16_SIMPLE_DPM_RF 19 | -------------------------------------------------------------------------------- /bender-xilinx.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2021 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 | # Author: Cyril Koenig 6 | 7 | # bender targets 8 | xilinx_targs_common += -t fpga 9 | 10 | # bender defines 11 | xilinx_defs_common += -D PULP_FPGA_EMUL 12 | 13 | # Conditionally add GEN_{island} to bender define 14 | define check_enable_island 15 | ifeq ($($(1)),1) 16 | xilinx_defs_common += -D$(1)=1 17 | endif 18 | endef 19 | 20 | $(eval $(call check_enable_island,GEN_NO_HYPERBUS)) 21 | $(eval $(call check_enable_island,GEN_EXT_JTAG)) 22 | 23 | ifeq ($(GEN_EXT_JTAG),0) 24 | xilinx_targs_common += -t bscane 25 | endif 26 | 27 | # note : bender targets are later modified in xilinx.mk 28 | -------------------------------------------------------------------------------- /docs/gs.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | We first discuss the Carfield's project structure, its dependencies, and how to build it. 4 | 5 | ## Repository structure 6 | 7 | The project is structured as follows: 8 | 9 | | Directory | Description | Documentation | 10 | | --------- | ------------------------------------------ | --------------------- | 11 | | `doc` | Documentation | [Home](index.md) | 12 | | `hw` | Hardware sources as SystemVerilog RTL | [Architecture](um/arch.md) | 13 | | `sw` | Software stack, build setup, and tests | [Software Stack](um/sw.md) | 14 | | `target` | Simulation, FPGA, and ASIC target setups | [Targets](tg/index.md) | 15 | | `utils` | Utility scripts | | 16 | | `scripts` | Some helper scripts for env setup | | 17 | 18 | ## Dependencies 19 | 20 | To *build* Carfield, you will need: 21 | 22 | - GNU Make `>= 3.82` 23 | - Python `>= 3.6` 24 | - Bender `>= 0.27.1` 25 | - RISCV GCC `>= 11.2.0` 26 | - Python packages in `requirements.txt` 27 | 28 | We use [Bender](https://github.com/pulp-platform/bender) for hardware IP and dependency management; 29 | for more information on using Bender, please see its documentation. You can install Bender directly 30 | through the Rust package manager Cargo: 31 | 32 | ``` 33 | cargo install bender 34 | ``` 35 | 36 | Depending on your desired target, additional dependencies may be needed. 37 | 38 | ## Building Carfield 39 | 40 | To build different parts of Carfield, the `carfield.mk` run `make` followed by these targets: 41 | 42 | - `car-hw-init`: generated hardware, including IPs and boot ROM 43 | - `car-sim-init`(†): scripts and external models for simulation 44 | - `car-sw-build` (‡): bare-metal software running on the hardware 45 | 46 | † *`car-sim-init` will download externally provided peripheral simulation models, some proprietary 47 | and with non-free license terms, from their publically accessible sources. By running 48 | `car-sim-init`, you accept this.* 49 | 50 | ‡ *`car-sw-build` requires RV64 and RV32 toolchains. See the [Software Stack](um/sw.md) for more 51 | details.* 52 | 53 | To run all build targets above (†)(‡): 54 | 55 | ``` 56 | make car-init-all 57 | ``` 58 | 59 | Running `car-init-all` is *required* at least once to correctly configure IPs we depend on. On 60 | reconfiguring any generated hardware or changing IP versions, `car-init-all` should be rerun. 61 | 62 | The following additional targets are not invoked by the above, but also available: 63 | 64 | - `chs-bootrom-all` - rebuilds Cheshire's boot ROM. This is not done by default as reproducible 65 | builds (as checked by CI) can only be guaranteed for fixed compiler versions. 66 | - `car-nonfree-init` - clones our internal repository with nonfree resources we cannot release, 67 | including our internal CI or technology-specific standard cells, scripts and tools. *This is not 68 | necessary to use Carfield*. 69 | 70 | ### Note 71 | Carfield uses [`Cheshire`](https://github.com/pulp-platform/cheshire) as main dependency. Compared 72 | to the other dependencies, Cheshire provides most of the HW/SW infrastructure used by Carfield. All 73 | Cheshire's `make` targets, described in the dedicated documentation, are available in Carfield 74 | through the inclusion of the makefrag `cheshire.mk` in `carfield.mk`. 75 | 76 | ## Targets 77 | 78 | A *target* is an end use for Carfield. Each target requires different steps from here; read the page 79 | for your desired target in the following [Targets](tg/index.md) chapter. 80 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /docs/tg/index.md: -------------------------------------------------------------------------------- 1 | # Targets 2 | 3 | A *target* refers to an end use of Carfield. This could be a simulation setup, an FPGA or ASIC 4 | implementation, or the less common integration into other SoCs. 5 | 6 | Target setups can either be *included* in this repository or live in an *external* repository and 7 | use Carfield as a dependency. 8 | 9 | ## Included Targets 10 | 11 | Included target setups live in the `target` directory. Each included target has a *documentation 12 | page* in this chapter: 13 | 14 | - [Simulation](sim.md) 15 | - [Synthesis and physical implementation](synth.md) 16 | - [Xilinx FPGAs](xilinx.md) 17 | 18 | ## External Targets 19 | 20 | For ASIC implementation target, where an additional wrapper is needed for clock generation blocks, 21 | bidirectional pads or additional circuitry, or the less common integration into larger SoCs, 22 | Carfield may be included either as a Bender dependency or Git submodule. For further information and 23 | best pratices, see [Integration](integr.md). 24 | -------------------------------------------------------------------------------- /docs/tg/integr.md: -------------------------------------------------------------------------------- 1 | # Integration 2 | 3 | Carfield is a complex platform, therefore the case of it being integrated in larger SoCs is rare. A 4 | more common scenario is the use of Carfield in a ASIC wrapper that includes bidirectional pads, 5 | clock generation blocks (PLLs, FLLs...) or other circuitry. 6 | 7 | This page explain how to integrate Carfield to fulfill on of these needs. Since Carfield heavily 8 | relies on Cheshire, for better understanding we suggest to integrate this reading with its 9 | equivalent in the Cheshire's documentation. 10 | 11 | ## Using Carfield In Your Project 12 | 13 | As for internal targets, Carfield *must be built* before use in external projects. We aim to 14 | simplify this as much as possible with a portable *make fragment*, `carfield.mk`. 15 | 16 | If you use GNU Make to build your project and Bender to handle dependencies, you can include the 17 | Carfield build system into your own makefile with: 18 | 19 | ```make 20 | include $(shell bender path carfield)/carfield.mk 21 | ``` 22 | 23 | All of Carfield's build targets are available with the prefix `car-`. 24 | 25 | You can leverage this to ensure your Carfield build is up to date and rebuild hardware and software 26 | whenever necessary. You can change the default value of any build parameter, replace source files to 27 | adapt Carfield, or reuse parts of its build system, such as the software stack or the register and 28 | ROM generators. 29 | 30 | ## Instantiating Carfield 31 | 32 | A minimal clean instantiation would look as follows: 33 | 34 | ```systemverilog 35 | `include "cheshire/typedef.svh" 36 | 37 | // Define function to derive configuration from defaults. 38 | // This could also (preferrably) be done in a system package. 39 | function automatic cheshire_pkg::cheshire_cfg_t gen_cheshire_cfg(); 40 | cheshire_pkg::cheshire_cfg_t ret = cheshire_pkg::DefaultCfg; 41 | // Make overriding changes. Here, we add two AXI manager ports 42 | ret.AxiExtNumMst = 2; 43 | return ret; 44 | endfunction 45 | 46 | localparam cheshire_cfg_t CheshireCfg = gen_cheshire_cfg(); 47 | 48 | // Generate interface types prefixed by `csh_` from our configuration. 49 | `CHESHIRE_TYPEDEF_ALL(csh_, CheshireCfg) 50 | 51 | // Instantiate Cheshire with our configuration and interface types. 52 | carfield #( 53 | .Cfg ( DutCfg ), 54 | .HypNumPhys ( NumPhys ), 55 | .HypNumChips ( NumChips ), 56 | .reg_req_t ( reg_req_t ), 57 | .reg_rsp_t ( reg_rsp_t ) 58 | ) dut ( 59 | // ... IOs here ... 60 | ); 61 | ``` 62 | 63 | ## Verifying Carfield In-System 64 | 65 | To simplify the simulation and verification of Carfield in other systems or top-level wrappers 66 | (e.g., ASIC), we provide a monolithic block of verification IPs called `carfield_vip`. This is used 67 | along with the `X_vip` modules provided for other domains. Their description can be found in the 68 | dedicated domain's documentation. In particular, `carfield_vip` currently includes: 69 | 70 | * Preloadable Cypress HyperRAM models (used to simulate boot). 71 | 72 | Additionally, we provide a module `carfield_vip_tristate` which adapts the unidirectional IO of this 73 | module to bidirectional IOs which may be interfaced with pads where necessary. 74 | -------------------------------------------------------------------------------- /docs/tg/synth.md: -------------------------------------------------------------------------------- 1 | # Logic synthesis and physical implementation 2 | 3 | Currently, synthesis of Carfield is available with closed source tools, and hence its scripts are 4 | added in the `nonfree` repository mentioned in the [Getting Started](../gs.md) section. 5 | 6 | Once open-EDA and open-PDK flow is available, it will be updated in this page. 7 | 8 | For independent synthesis of carfield by external users, we provide a wrapper under 9 | `target/synth/carfield_synth_wrap.sv`. 10 | -------------------------------------------------------------------------------- /docs/um/index.md: -------------------------------------------------------------------------------- 1 | # User Manual 2 | 3 | The *user manual* provides detailed reference information on Carfield: 4 | 5 | - [Architecture](arch.md): Describes the hardware design, features, configuration and memory 6 | map of Carfield. 7 | - [Software Stack](sw.md): Describes how to run code on Carfield and its heterogeneous software 8 | stack. 9 | -------------------------------------------------------------------------------- /env/env-iis.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 | # set up environment variables for rtl simulation 7 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 8 | export PATH=/usr/pack/riscv-1.0-kgf/riscv64-gcc-11.2.0/bin:$PATH # RV64 GCC toolchain 9 | export SAFED_RISCV=/usr/pack/riscv-1.0-kgf/pulp-gcc-2.6.0/bin/riscv32-unknown-elf 10 | export PULPD_RISCV=/usr/pack/pulpsdk-1.0-kgf/artifactory/pulp-sdk-release/pkg/pulp_riscv_gcc/1.0.16/bin/riscv32-unknown-elf 11 | export QUESTA=questa-2023.4 12 | -------------------------------------------------------------------------------- /env/pulpd-env.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 | # set up environment variables for rtl simulation 7 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 8 | [[ -d "$ROOTD/pulp_cluster/pulp-runtime" ]] && source "$ROOTD/pulp_cluster/pulp-runtime/configs/carfield-cluster.sh" 9 | -------------------------------------------------------------------------------- /env/safed-env.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 | # set up environment variables for rtl simulation 7 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 8 | [[ -d "$ROOTD/safety_island/sw/pulp-freertos" ]] && source "$ROOTD/safety_island/sw/pulp-freertos/env/safety-island.sh" #TODO add carfield target in freertos 9 | [[ -d "$ROOTD/safety_island/sw/pulp-runtime" ]] && source "$ROOTD/safety_island/sw/pulp-runtime/configs/carfield.sh" 10 | -------------------------------------------------------------------------------- /env/spatzd-env.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 | # set up environment variables for rtl simulation 7 | ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) 8 | export LLVM_SPATZ_DIR=/usr/pack/riscv-1.0-kgf/spatz-llvm-2023.08.10 9 | export GCC_SPATZ_DIR=/usr/pack/riscv-1.0-kgf/spatz-gcc-7.1.1 10 | -------------------------------------------------------------------------------- /hw/carfield_rstgen.sv: -------------------------------------------------------------------------------- 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 | // Robert Balas 6 | 7 | `include "cheshire/typedef.svh" 8 | `include "apb/typedef.svh" 9 | 10 | /// Carfield reset handling 11 | /// Combine power-on and software reset 12 | /// 13 | /// The power-on reset will go through a reset synchronizer so there will be 14 | /// single cycle constraint from the syncrhonizer deassertion to all connected 15 | /// flops. This constraint can be relaxed with respect to the maximum runtime 16 | /// clock frequency since system runs with the external (slower clock) during 17 | /// power-on reset. 18 | /// 19 | /// The software reset on the other hand comes directly from a configuration 20 | /// register and is AND'd with the power-on reset withouth any reset 21 | /// synchronization. This reset can relaxed to a false path since we will only 22 | /// toggle it when we gate the clock of the domain receving the reset. 23 | 24 | module carfield_rstgen import carfield_pkg::*; #( 25 | parameter int unsigned NumRstDomains = 1 26 | ) ( 27 | input logic [NumRstDomains-1:0] clks_i, 28 | input logic pwr_on_rst_ni, 29 | input logic [NumRstDomains-1:0] sw_rsts_ni, 30 | input logic test_mode_i, 31 | 32 | output logic [NumRstDomains-1:0] rsts_no, 33 | output logic [NumRstDomains-1:0] pwr_on_rsts_no, 34 | output logic [NumRstDomains-1:0] inits_no 35 | ); 36 | 37 | logic [NumRstDomains-1:0] sync_rst_n; 38 | 39 | for (genvar k = 0; k < NumRstDomains; k++) begin : gen_rstgen_for_domains 40 | // synchronize the power-on reset 41 | rstgen i_rstgen ( 42 | .clk_i (clks_i[k]), 43 | .rst_ni (pwr_on_rst_ni), 44 | .test_mode_i, 45 | .rst_no (sync_rst_n[k]), 46 | .init_no (inits_no[k]) 47 | ); 48 | 49 | // synchronized power-on reset 50 | assign pwr_on_rsts_no[k] = sync_rst_n[k]; 51 | 52 | // synchronized power-on reset AND software reeset 53 | assign rsts_no[k] = sw_rsts_ni[k] & sync_rst_n[k]; 54 | end 55 | 56 | endmodule // carfield_rstgen 57 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 0; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 0; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 0; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_pulp_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 0; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 0; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 1; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_safe_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 1; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 0; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 0; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_safe_pulp_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 1; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 0; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 1; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_safe_pulp_spatz_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 1; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 1; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 1; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_safe_secure_pulp_spatz_periph_can.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 1; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 1; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 1; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 1; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | /********************* 50 | * APB Configuration * 51 | ********************/ 52 | // Can 53 | localparam bit CanEnable = 1; 54 | localparam doub_bt CanBase = 'h20001000; 55 | localparam doub_bt CanSize = 'h00001000; 56 | // System Timer 57 | localparam doub_bt SystemTimerBase = 'h20004000; 58 | localparam doub_bt SystemTimerSize = 'h00001000; 59 | // System Advanced Timer 60 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 61 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 62 | // System Watchdog 63 | localparam doub_bt SystemWatchdogBase = 'h20007000; 64 | localparam doub_bt SystemWatchdogSize = 'h00001000; 65 | // Hyperbus Config 66 | localparam doub_bt HyperBusBase = 'h20009000; 67 | localparam doub_bt HyperBusSize = 'h00001000; 68 | /************************ 69 | * RegBus Configuration * 70 | ***********************/ 71 | // Platform control registers 72 | localparam doub_bt PcrsBase = 'h20010000; 73 | localparam doub_bt PcrsSize = 'h00001000; 74 | // PLL 75 | localparam bit PllCfgEnable = 1; 76 | localparam doub_bt PllCfgBase = 'h20020000; 77 | localparam doub_bt PllCfgSize = 'h00001000; 78 | // Padframe 79 | localparam bit PadframeCfgEnable = 1; 80 | localparam doub_bt PadframeCfgBase = 'h200A0000; 81 | localparam doub_bt PadframeCfgSize = 'h00001000; 82 | // L2 ECC 83 | localparam bit L2EccCfgEnable = 1; 84 | localparam doub_bt L2EccCfgBase = 'h200B0000; 85 | localparam doub_bt L2EccCfgSize = 'h00001000; 86 | 87 | endpackage 88 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_safe_spatz_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 1; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 1; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 0; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_secure_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 0; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 0; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 0; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 1; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /hw/configs/carfield_l2dual_spatz_periph.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Yvan Tortorella 6 | 7 | package carfield_configuration; 8 | 9 | import cheshire_pkg::*; 10 | /********************* 11 | * AXI Configuration * 12 | ********************/ 13 | //L2, port 0 14 | localparam bit L2Port0Enable = 1; 15 | localparam doub_bt L2Port0Base = 'h78000000; 16 | localparam doub_bt L2Port0Size = 'h00200000; 17 | // L2, port 1 18 | localparam bit L2Port1Enable = 1; 19 | localparam doub_bt L2Port1Base = L2Port0Base + L2Port0Size; 20 | localparam doub_bt L2Port1Size = L2Port0Size; 21 | // Safety Island 22 | localparam bit SafetyIslandEnable = 0; 23 | localparam doub_bt SafetyIslandBase = 'h60000000; 24 | localparam doub_bt SafetyIslandSize = 'h00800000; 25 | // Ethernet 26 | localparam bit EthernetEnable = 0; 27 | localparam doub_bt EthernetBase = 'h20000000; 28 | localparam doub_bt EthernetSize = 'h00001000; 29 | // Peripherals 30 | localparam bit PeriphEnable = 1; 31 | localparam doub_bt PeriphBase = 'h20001000; 32 | localparam doub_bt PeriphSize = 'h00009000; 33 | // Spatz cluster 34 | localparam bit SpatzClusterEnable = 1; 35 | localparam doub_bt SpatzClusterBase = 'h51000000; 36 | localparam doub_bt SpatzClusterSize = 'h00800000; 37 | // PULP cluster 38 | localparam bit PulpClusterEnable = 0; 39 | localparam doub_bt PulpClusterBase = 'h50000000; 40 | localparam doub_bt PulpClusterSize = 'h00800000; 41 | // Security Island 42 | localparam bit SecurityIslandEnable = 0; 43 | localparam doub_bt SecurityIslandBase = 'h0; 44 | localparam doub_bt SecurityIslandSize = 'h0; 45 | // Mailbox 46 | localparam bit MailboxEnable = 1; 47 | localparam doub_bt MailboxBase = 'h40000000; 48 | localparam doub_bt MailboxSize = 'h00001000; 49 | // Can 50 | localparam bit CanEnable = 0; 51 | localparam doub_bt CanBase = 'h20001000; 52 | localparam doub_bt CanSize = 'h00001000; 53 | // System Timer 54 | localparam doub_bt SystemTimerBase = 'h20004000; 55 | localparam doub_bt SystemTimerSize = 'h00001000; 56 | // System Advanced Timer 57 | localparam doub_bt SystemAdvancedTimerBase = 'h20005000; 58 | localparam doub_bt SystemAdvancedTimerSize = 'h00001000; 59 | // System Watchdog 60 | localparam doub_bt SystemWatchdogBase = 'h20007000; 61 | localparam doub_bt SystemWatchdogSize = 'h00001000; 62 | // Hyperbus Config 63 | localparam doub_bt HyperBusBase = 'h20009000; 64 | localparam doub_bt HyperBusSize = 'h00001000; 65 | /************************ 66 | * RegBus Configuration * 67 | ***********************/ 68 | // Platform control registers 69 | localparam doub_bt PcrsBase = 'h20010000; 70 | localparam doub_bt PcrsSize = 'h00001000; 71 | // PLL 72 | localparam bit PllCfgEnable = 1; 73 | localparam doub_bt PllCfgBase = 'h20020000; 74 | localparam doub_bt PllCfgSize = 'h00001000; 75 | // Padframe 76 | localparam bit PadframeCfgEnable = 1; 77 | localparam doub_bt PadframeCfgBase = 'h200A0000; 78 | localparam doub_bt PadframeCfgSize = 'h00001000; 79 | // L2 ECC 80 | localparam bit L2EccCfgEnable = 1; 81 | localparam doub_bt L2EccCfgBase = 'h200B0000; 82 | localparam doub_bt L2EccCfgSize = 'h00001000; 83 | 84 | endpackage 85 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 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 | site_name: Carfield 6 | theme: 7 | name: material 8 | icon: 9 | repo: fontawesome/brands/github 10 | features: 11 | - navigation.expand 12 | - navigation.tracking 13 | - navigation.sections 14 | - navigation.indexes 15 | - navigation.footer 16 | 17 | plugins: 18 | - glightbox: 19 | touchNavigation: true 20 | loop: false 21 | effect: zoom 22 | slide_effect: slide 23 | width: 100% 24 | height: auto 25 | zoomable: true 26 | draggable: true 27 | skip_classes: 28 | - custom-skip-class-name 29 | auto_caption: false 30 | caption_position: bottom 31 | 32 | repo_url: https://github.com/pulp-platform/carfield 33 | repo_name: pulp-platform/carfield 34 | 35 | nav: 36 | - Home: 37 | - index.md 38 | - Getting Started: gs.md 39 | - Targets: 40 | - tg/index.md 41 | - Simulation: tg/sim.md 42 | - Synthesis and physical implementation: tg/synth.md 43 | - Xilinx FPGAs: tg/xilinx.md 44 | - Integration: tg/integr.md 45 | - User Manual: 46 | - um/index.md 47 | - Architecture: um/arch.md 48 | - Software Stack: um/sw.md 49 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | hjson 2 | jsonref 3 | jsonschema 4 | Mako==1.1.6 5 | PyYAML==6.0 6 | pyelftools==0.29 7 | requests 8 | mako 9 | pyyaml 10 | tabulate 11 | yapf 12 | mkdocs 13 | mkdocs-material 14 | mkdocs-glightbox 15 | dataclasses 16 | -------------------------------------------------------------------------------- /scripts/csv_to_json.py: -------------------------------------------------------------------------------- 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 | # Luca Valente 6 | 7 | import pandas as pd 8 | import re 9 | import argparse 10 | from string import Template 11 | 12 | 13 | header = """// Copyright 2023 ETH Zurich and University of Bologna. 14 | // Solderpad Hardware License, Version 0.51, see LICENSE for details. 15 | // SPDX-License-Identifier: SHL-0.51 16 | // Robert Balas 17 | // Luca Valente 18 | { 19 | name: "carfield", 20 | clock_primary: "clk_i", 21 | bus_interfaces: [ 22 | { protocol: "reg_iface", direction: "device" } 23 | ], 24 | regwidth: "32", 25 | registers :[ 26 | """ 27 | 28 | reg_tlp = """ 29 | { name: "$name", 30 | desc: "$comment", 31 | swaccess: "$swa", 32 | hwaccess: "$hwa", 33 | resval: "$rv", 34 | hwqe: "$hwqe", 35 | fields: [ 36 | { bits: "$bw:0" } 37 | ], 38 | } 39 | """ 40 | 41 | parser = argparse.ArgumentParser(description='generate your hex from slm') 42 | 43 | parser.add_argument("--input", dest="input_file", default=None, help="Specify input file") 44 | parser.add_argument("--output", dest="output_file", default=None, help="Specify output file") 45 | 46 | args = parser.parse_args() 47 | 48 | if args.input_file is None: 49 | raise Exception('Specify the input file!') 50 | if args.output_file is None: 51 | raise Exception('Specify the output file!') 52 | 53 | 54 | f = open(args.output_file, "w") 55 | f.write(header) 56 | 57 | df = pd.read_csv(args.input_file, sep=',' ) 58 | 59 | outer_ports = "" 60 | de_assign = "" 61 | pll_intf = "" 62 | first_pin = 1 63 | for index, row in df.iterrows(): 64 | name = row['Name'] 65 | num_bits = row['Bits'] 66 | swa = row['SW Access'] 67 | hwa = row['HW Access'] 68 | hwqe = row['HWQE Access'] 69 | defv = row['Default Value'] 70 | desc = row['Comment'] 71 | s = Template(reg_tlp) 72 | f.write(s.substitute(name=name,swa=swa,hwa=hwa,hwqe=hwqe,rv=defv,bw=num_bits-1,comment=desc)) 73 | 74 | f.write(' ],\n') 75 | f.write('}\n') 76 | f.close() 77 | -------------------------------------------------------------------------------- /sw/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | IndentWidth: 4 4 | UseTab: Never 5 | BreakBeforeBraces: Linux 6 | AlwaysBreakBeforeMultilineStrings: true 7 | AllowShortIfStatementsOnASingleLine: false 8 | AllowShortLoopsOnASingleLine: false 9 | AllowShortFunctionsOnASingleLine: false 10 | IndentCaseLabels: false 11 | AlignEscapedNewlinesLeft: false 12 | AlignTrailingComments: true 13 | AlignOperands: true 14 | AllowAllParametersOfDeclarationOnNextLine: false 15 | AlignAfterOpenBracket: true 16 | SpaceAfterCStyleCast: false 17 | MaxEmptyLinesToKeep: 2 18 | BreakBeforeBinaryOperators: NonAssignment 19 | BreakStringLiterals: false 20 | SortIncludes: false 21 | ContinuationIndentWidth: 4 22 | ColumnLimit: 120 23 | IndentPPDirectives: AfterHash 24 | BinPackArguments: true 25 | BinPackParameters: true 26 | ForEachMacros: 27 | - 'TAILQ_FOREACH' 28 | - 'TAILQ_FOREACH_REVERSE' 29 | BreakBeforeBinaryOperators: None 30 | MaxEmptyLinesToKeep: 1 31 | AlwaysBreakAfterDefinitionReturnType: None 32 | AlwaysBreakAfterReturnType: None 33 | AlwaysBreakBeforeMultilineStrings: false 34 | AlignConsecutiveAssignments: true 35 | ... 36 | -------------------------------------------------------------------------------- /sw/.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.dump 3 | *.elf 4 | *.memh 5 | *.slm 6 | benchmarks/ 7 | -------------------------------------------------------------------------------- /sw/benchmarks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulp-platform/carfield/57d5f1e57d2e5f45ce0dc956e74618f6b5c737ad/sw/benchmarks/.gitkeep -------------------------------------------------------------------------------- /sw/boot/carfield.dtsi: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Cyril Koenig 6 | 7 | /dts-v1/; 8 | / { 9 | #address-cells = <2>; 10 | #size-cells = <2>; 11 | compatible = "eth,carfield-dev"; 12 | model = "eth,carfield"; 13 | chosen { 14 | stdout-path = "/soc/serial@3002000:38400"; 15 | }; 16 | memory@80000000 { 17 | // Give 1GiB to Linux management 18 | device_type = "memory"; 19 | reg = <0x0 0x80000000 0x0 0x40000000>; 20 | }; 21 | 22 | /include/ "carfield_soc.dtsi" 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /sw/boot/carfield_bd_vcu118.dts: -------------------------------------------------------------------------------- 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 | // Cyril Koenig 6 | 7 | 8 | /include/ "carfield.dtsi" 9 | -------------------------------------------------------------------------------- /sw/boot/carfield_bd_vcu128.dts: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Cyril Koenig 6 | 7 | 8 | /include/ "carfield.dtsi" 9 | 10 | &soc { 11 | eth_dma0: eth_dma@141e00000 { 12 | #dma-cells = <1>; 13 | #address-cells = <1>; 14 | #size-cells = <1>; 15 | compatible = "xlnx,axi-dma-1.00.a"; 16 | reg = <0x1 0x41e00000 0x0 0x10000>; 17 | interrupts-extended = <&PLIC0 21 &PLIC0 22>; 18 | xlnx,addrwidth = <0x40>; 19 | xlnx,include-sg; 20 | dma-channel@141e00000 { 21 | compatible = "xlnx,axi-dma-mm2s-channel"; 22 | reg = <0 0>; 23 | dma-channels = <0x1>; 24 | interrupts-extended = <&PLIC0 21>; 25 | xlnx,datawidth = <0x20>; 26 | xlnx,device-id = <0x0>; 27 | xlnx,include-dre ; 28 | }; 29 | dma-channel@141e00030 { 30 | compatible = "xlnx,axi-dma-s2mm-channel"; 31 | reg = <0 0>; 32 | dma-channels = <0x1>; 33 | interrupts-extended = <&PLIC0 22>; 34 | xlnx,datawidth = <0x20>; 35 | xlnx,device-id = <0x0>; 36 | xlnx,include-dre ; 37 | }; 38 | }; 39 | eth0: eth0@140c00000 { 40 | compatible = "xlnx,axi-ethernet-1.00.a"; 41 | reg = <0x1 0x40c00000 0x0 0x40000>; 42 | // attacked to system clock, provide name for matching 43 | clocks = <&sysclk>, <&sysclk>; 44 | clock-names = "s_axi_lite_clk", "axis_clk"; 45 | // interrupt and mac_irq 46 | interrupts-extended = <&PLIC0 19 &PLIC0 24>; 47 | /include/ "mac_address.dtsi" 48 | /include/ "remote_boot.dtsi" 49 | device_type = "network"; 50 | axistream-connected = <ð_dma0>; 51 | axistream-control-connected = <ð_dma0>; 52 | phy-handle = <&dp83867_0>; 53 | // xlnx,phy-type = <0x4>; // XAE_PHY_TYPE_SGMII. linux: deprecated, use phy-mode 54 | phy-mode = "sgmii"; 55 | xlnx,phyaddr = <0x0>; 56 | xlnx,rxcsum = <0x2>; // 0, 1, 2 for no/partial/full offloading 57 | xlnx,rxmem = <0x1000>; 58 | xlnx,txcsum = <0x2>; // 0, 1, 2 for no/partial/full offloading 59 | xlnx,txmem = <0x1000>; 60 | 61 | mdio: mdio { 62 | #address-cells = <1>; 63 | #size-cells = <0>; 64 | // reset-gpios = <&tca6416a 6 GPIO_ACTIVE_LOW>; 65 | // reset-delay-us = <2>; 66 | // PCS/PMA PHY 67 | xilinx_phy: ethernet-phy@0 { 68 | #phy-cells = <1>; 69 | device_type = "ethernet-phy"; 70 | reg = <0>; 71 | }; 72 | // External PHY 73 | dp83867_0: ethernet-phy@3 { 74 | compatible = "ethernet-phy-ieee802.3-c22"; 75 | reg = <3>; 76 | #phy-cells = <1>; 77 | device_type = "ethernet-phy"; 78 | ti,sgmii-ref-clock-output-enable; 79 | ti,dp83867-rxctrl-strap-quirk; 80 | }; 81 | }; 82 | }; 83 | }; 84 | -------------------------------------------------------------------------------- /sw/boot/carfield_pcie.dts: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Cyril Koenig 6 | 7 | /dts-v1/; 8 | /plugin/; 9 | &{/dev@0,0} { 10 | axi-bus { 11 | #address-cells = <2>; 12 | #size-cells = <2>; 13 | compatible = "simple-bus"; 14 | ranges; 15 | 16 | /include/ "carfield_soc.dtsi" 17 | 18 | }; 19 | }; 20 | 21 | &soc { 22 | pcie-axi-bar@180000000 { 23 | compatible = "xlnx,pcie-axi-bar"; 24 | reg = <0x1 0x80000000 0x0 0x80000000>; 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /sw/boot/carfield_vanilla_vcu128.dts: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // Cyril Koenig 6 | 7 | 8 | /include/ "carfield.dtsi" 9 | -------------------------------------------------------------------------------- /sw/boot/mac_address.dtsi: -------------------------------------------------------------------------------- 1 | local-mac-address = [ 00 00 00 00 00 00 ]; 2 | mac-address = [ 00 00 00 00 00 00 ]; 3 | -------------------------------------------------------------------------------- /sw/boot/remote_boot.dtsi: -------------------------------------------------------------------------------- 1 | // Uncomment below for remote boot 2 | // remote-boot = "0.0.0.0:vcu128-01/carfield/uImage-ci"; 3 | -------------------------------------------------------------------------------- /sw/include/bits.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2014, Wind River Systems, Inc. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // Copyright 2023 ETH Zurich 5 | // Author: Robert Balas (balasr@iis.ee.ethz.ch) 6 | 7 | #ifndef __BITS_H 8 | #define __BITS_H 9 | 10 | #include 11 | 12 | /* Helper to pass a int as a pointer or vice-versa. */ 13 | #define POINTER_TO_UINT(x) ((uintptr_t) (x)) 14 | #define UINT_TO_POINTER(x) ((void *) (uintptr_t) (x)) 15 | #define POINTER_TO_INT(x) ((intptr_t) (x)) 16 | #define INT_TO_POINTER(x) ((void *) (intptr_t) (x)) 17 | 18 | #if !(defined (__CHAR_BIT__) && defined (__SIZEOF_LONG__)) 19 | # error Missing required predefined macros for BITS_PER_LONG calculation 20 | #endif 21 | 22 | #define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) 23 | /* Create a contiguous bitmask starting at bit position @l and ending at 24 | * position @h. 25 | */ 26 | #define GENMASK(h, l) \ 27 | (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) 28 | 29 | /* KB, MB, GB */ 30 | #define KB(x) ((x) << 10) 31 | #define MB(x) (KB(x) << 10) 32 | #define GB(x) (MB(x) << 10) 33 | 34 | /* KHZ, MHZ */ 35 | #define KHZ(x) ((x) * 1000) 36 | #define MHZ(x) (KHZ(x) * 1000) 37 | 38 | #ifndef BIT 39 | #if defined(_ASMLANGUAGE) 40 | #define BIT(n) (1 << (n)) 41 | #else 42 | #define BIT(n) (1UL << (n)) 43 | #endif 44 | #endif 45 | 46 | /** 47 | * @brief Macro sets or clears bit depending on boolean value 48 | * 49 | * @param var Variable to be altered 50 | * @param bit Bit number 51 | * @param set Value 0 clears bit, any other value sets bit 52 | */ 53 | #define WRITE_BIT(var, bit, set) \ 54 | ((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit))) 55 | 56 | #define BIT_MASK(n) (BIT(n) - 1) 57 | 58 | 59 | /** 60 | * @brief Convenience macro reads or sets register fields 61 | * 62 | * @param FIELD Register name 63 | * @param v value of bits 64 | */ 65 | #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) 66 | #define REG_GET(FIELD, v) (((v) & FIELD##_MASK) >> FIELD##_SHIFT) 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /sw/include/car_linux_mmap.h: -------------------------------------------------------------------------------- 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 | // Cyril Koenig 6 | // 7 | // This file wraps mmap calls to the Carfield driver 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include // mmap 18 | 19 | #include "car_params.h" // car_soc_ctrl, ... 20 | 21 | int carfield_mmap(int device_fd, unsigned int page_offset, size_t length, 22 | void **res) { 23 | *res = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, 24 | page_offset * getpagesize()); 25 | 26 | if (*res == MAP_FAILED) { 27 | printf("mmap() failed %s for offset: %x length: %x\n", strerror(errno), 28 | page_offset, length); 29 | *res = NULL; 30 | return -EIO; 31 | } 32 | return 0; 33 | } 34 | 35 | int carfield_platform_init(int fd) { 36 | if (carfield_mmap(fd, 0, 0x1000, &car_soc_ctrl)) { 37 | printf("mmap() failed for car_soc_ctrl\n"); 38 | } 39 | if (carfield_mmap(fd, 10, 0x100000, &car_l2_intl_0)) { 40 | printf("mmap() failed for car_l2_intl_0\n"); 41 | } 42 | if (carfield_mmap(fd, 11, 0x100000, &car_l2_cont_0)) { 43 | printf("mmap() failed for car_l2_cont_0\n"); 44 | } 45 | if (carfield_mmap(fd, 12, 0x100000, &car_l2_intl_1)) { 46 | printf("mmap() failed for car_l2_intl_1\n"); 47 | } 48 | if (carfield_mmap(fd, 13, 0x100000, &car_l2_cont_1)) { 49 | printf("mmap() failed for car_l2_cont_1\n"); 50 | } 51 | if (carfield_mmap(fd, 100, 0x800000, &car_safety_island)) { 52 | printf("mmap() failed for car_safety_island\n"); 53 | } 54 | if (carfield_mmap(fd, 200, 0x800000, &car_integer_cluster)) { 55 | printf("mmap() failed for car_integer_cluster\n"); 56 | } 57 | if (carfield_mmap(fd, 300, 0x800000, &car_spatz_cluster)) { 58 | printf("mmap() failed for car_spatz_cluster\n"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sw/include/car_params.h: -------------------------------------------------------------------------------- 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 | // Cyril Koenig 6 | // 7 | // This file resolves the pointers used in car_memory_map.h 8 | // In the linux case these pointers are attributed by calling carfield_mmap() 9 | 10 | #pragma once 11 | 12 | #ifndef LINUX_APP // Hardcoded const pointers 13 | const void* car_soc_ctrl = 0x20010000; 14 | const void* car_safety_island = 0x60000000; 15 | const void* car_integer_cluster = 0x50000000; 16 | const void* car_spatz_cluster = 0x51000000; 17 | const void* car_l2_intl_0 = 0x78000000; 18 | const void* car_l2_cont_0 = 0x78100000; 19 | const void* car_l2_intl_1 = 0x78200000; 20 | const void* car_l2_cont_1 = 0x78300000; 21 | 22 | #else // Pointers to be mapped by the driver 23 | void* car_soc_ctrl; 24 | void* car_safety_island; 25 | void* car_integer_cluster; 26 | void* car_spatz_cluster; 27 | void* car_l2_intl_0; 28 | void* car_l2_cont_0; 29 | void* car_l2_intl_1; 30 | void* car_l2_cont_1; 31 | #endif 32 | -------------------------------------------------------------------------------- /sw/include/car_properties.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | #define IntClustNumCores 12 6 | -------------------------------------------------------------------------------- /sw/include/csr.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | // 7 | 8 | /* Description: CSR access macros 9 | * Authors: Robert Balas (balasr@iis.ee.ethz.ch) 10 | */ 11 | 12 | #ifndef __CSR_H 13 | #define __CSR_H 14 | 15 | /* TODO: complete this */ 16 | #define CSR_MSTATUS 0x300 17 | #define CSR_MISA 0x301 18 | #define CSR_MIE 0x304 19 | #define CSR_MTVEC 0x305 20 | #define CSR_MSCRATCH 0x340 21 | #define CSR_MEPC 0x341 22 | #define CSR_MCAUSE 0x342 23 | #define CSR_MTVAL 0x343 24 | #define CSR_MIP 0x344 25 | #define CSR_MNXTI 0x345 26 | #define CSR_PMPCFG0 0x3a0 27 | #define CSR_PMPADDR0 0x3b0 28 | #define CSR_MHARTID 0xf14 29 | #define CSR_MINTSTATUS 0x346 30 | #define CSR_MINTTHRESH 0x347 31 | #define CSR_MCLICBASE 0x350 32 | #define MIE 8 33 | 34 | #define __CSR_EXPAND(x) #x 35 | 36 | #define csr_read(csr) \ 37 | ({ \ 38 | register unsigned long __val; \ 39 | asm volatile("csrr %0, " __CSR_EXPAND(csr) \ 40 | : "=r"(__val) \ 41 | : \ 42 | : "memory"); \ 43 | __val; \ 44 | }) 45 | 46 | #define csr_write(csr, val) \ 47 | ({ \ 48 | unsigned long __val = (unsigned long)(val); \ 49 | asm volatile("csrw " __CSR_EXPAND(csr) ", %0" \ 50 | : \ 51 | : "rK"(__val) \ 52 | : "memory"); \ 53 | }) 54 | 55 | /* I hope this properly does a memory barrier with the "memory" hint */ 56 | #define csr_read_clear(csr, val) \ 57 | ({ \ 58 | unsigned long __val = (unsigned long)(val); \ 59 | asm volatile("csrrc %0, " __CSR_EXPAND(csr) ", %1" \ 60 | : "=r"(__val) \ 61 | : "rK"(__val) \ 62 | : "memory"); \ 63 | __val; \ 64 | }) 65 | 66 | #define csr_read_set(csr, val) \ 67 | ({ \ 68 | unsigned long __val = (unsigned long)(val); \ 69 | asm volatile("csrrs %0, " __CSR_EXPAND(csr) ", %1" \ 70 | : "=r"(__val) \ 71 | : "rK"(__val) \ 72 | : "memory"); \ 73 | __val; \ 74 | }) 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /sw/include/io.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | // 7 | 8 | /* Description: Memory mapped register I/O access 9 | */ 10 | 11 | #ifndef __IO_H 12 | #define __IO_H 13 | 14 | #include 15 | 16 | 17 | /* generic I/O write */ 18 | static inline void writeb(uint8_t val, uintptr_t addr) 19 | { 20 | asm volatile("sb %0, 0(%1)" 21 | : 22 | : "r"(val), "r"((volatile uint8_t *)addr) 23 | : "memory"); 24 | } 25 | 26 | static inline void writeh(uint16_t val, uintptr_t addr) 27 | { 28 | asm volatile("sh %0, 0(%1)" 29 | : 30 | : "r"(val), "r"((volatile uint16_t *)addr) 31 | : "memory"); 32 | } 33 | 34 | static inline void writew(uint32_t val, uintptr_t addr) 35 | { 36 | asm volatile("sw %0, 0(%1)" 37 | : 38 | : "r"(val), "r"((volatile uint32_t *)addr) 39 | : "memory"); 40 | } 41 | 42 | static inline void writed(uint64_t val, uintptr_t addr) 43 | { 44 | asm volatile("sd %0, 0(%1)" 45 | : 46 | : "r"(val), "r"((volatile uint64_t *)addr) 47 | : "memory"); 48 | } 49 | 50 | /* generic I/O read */ 51 | static inline uint8_t readb(const uintptr_t addr) 52 | { 53 | uint8_t val; 54 | 55 | asm volatile("lb %0, 0(%1)" 56 | : "=r"(val) 57 | : "r"((const volatile uint8_t *)addr) 58 | : "memory"); 59 | return val; 60 | } 61 | 62 | static inline uint16_t readh(const uintptr_t addr) 63 | { 64 | uint16_t val; 65 | 66 | asm volatile("lh %0, 0(%1)" 67 | : "=r"(val) 68 | : "r"((const volatile uint16_t *)addr) 69 | : "memory"); 70 | return val; 71 | } 72 | 73 | static inline uint32_t readw(const uintptr_t addr) 74 | { 75 | uint32_t val; 76 | 77 | asm volatile("lw %0, 0(%1)" 78 | : "=r"(val) 79 | : "r"((const volatile uint32_t *)addr) 80 | : "memory"); 81 | return val; 82 | } 83 | 84 | static inline uint64_t readd(const uintptr_t addr) 85 | { 86 | uint64_t val; 87 | 88 | asm volatile("ld %0, 0(%1)" 89 | : "=r"(val) 90 | : "r"((const volatile uint64_t *)addr) 91 | : "memory"); 92 | return val; 93 | } 94 | #endif 95 | -------------------------------------------------------------------------------- /sw/include/regs/clic.h: -------------------------------------------------------------------------------- 1 | // Generated register defines for MCLIC 2 | 3 | // Copyright information found in source file: 4 | // Copyright 2022 ETH Zurich and University of Bologna.Copyright and related rights are licensed under the Solderpad Hardware 5 | 6 | // Licensing information found in source file: 7 | // licensed under the Solderpad Hardware 8 | // SPDX-License-Identifier: Apache-2.0 9 | 10 | #ifndef _MCLIC_REG_DEFS_ 11 | #define _MCLIC_REG_DEFS_ 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | // Register width 17 | #define MCLIC_PARAM_REG_WIDTH 32 18 | 19 | // CLIC configuration 20 | #define MCLIC_MCLICCFG_REG_OFFSET 0x0 21 | #define MCLIC_MCLICCFG_MNLBITS_MASK 0xf 22 | #define MCLIC_MCLICCFG_MNLBITS_OFFSET 0 23 | #define MCLIC_MCLICCFG_MNLBITS_FIELD \ 24 | ((bitfield_field32_t) { .mask = MCLIC_MCLICCFG_MNLBITS_MASK, .index = MCLIC_MCLICCFG_MNLBITS_OFFSET }) 25 | #define MCLIC_MCLICCFG_NMBITS_MASK 0x3 26 | #define MCLIC_MCLICCFG_NMBITS_OFFSET 4 27 | #define MCLIC_MCLICCFG_NMBITS_FIELD \ 28 | ((bitfield_field32_t) { .mask = MCLIC_MCLICCFG_NMBITS_MASK, .index = MCLIC_MCLICCFG_NMBITS_OFFSET }) 29 | #define MCLIC_MCLICCFG_SNLBITS_MASK 0xf 30 | #define MCLIC_MCLICCFG_SNLBITS_OFFSET 16 31 | #define MCLIC_MCLICCFG_SNLBITS_FIELD \ 32 | ((bitfield_field32_t) { .mask = MCLIC_MCLICCFG_SNLBITS_MASK, .index = MCLIC_MCLICCFG_SNLBITS_OFFSET }) 33 | #define MCLIC_MCLICCFG_UNLBITS_MASK 0xf 34 | #define MCLIC_MCLICCFG_UNLBITS_OFFSET 24 35 | #define MCLIC_MCLICCFG_UNLBITS_FIELD \ 36 | ((bitfield_field32_t) { .mask = MCLIC_MCLICCFG_UNLBITS_MASK, .index = MCLIC_MCLICCFG_UNLBITS_OFFSET }) 37 | #define MCLIC_MCLICCFG_RESERVED_MASK 0xf 38 | #define MCLIC_MCLICCFG_RESERVED_OFFSET 28 39 | #define MCLIC_MCLICCFG_RESERVED_FIELD \ 40 | ((bitfield_field32_t) { .mask = MCLIC_MCLICCFG_RESERVED_MASK, .index = MCLIC_MCLICCFG_RESERVED_OFFSET }) 41 | 42 | // CLIC enable mnxti irq forwarding logic 43 | #define MCLIC_CLICMNXTICONF_REG_OFFSET 0x4 44 | #define MCLIC_CLICMNXTICONF_CLICMNXTICONF_BIT 0 45 | 46 | #ifdef __cplusplus 47 | } // extern "C" 48 | #endif 49 | #endif // _MCLIC_REG_DEFS_ 50 | // End generated register defines for MCLIC 51 | -------------------------------------------------------------------------------- /sw/include/regs/clicint.h: -------------------------------------------------------------------------------- 1 | // Generated register defines for CLICINT 2 | 3 | // Copyright information found in source file: 4 | // Copyright 2022 ETH Zurich and University of Bologna.Copyright and related rights are licensed under the Solderpad Hardware 5 | 6 | // Licensing information found in source file: 7 | // licensed under the Solderpad Hardware 8 | // SPDX-License-Identifier: Apache-2.0 9 | 10 | #ifndef _CLICINT_REG_DEFS_ 11 | #define _CLICINT_REG_DEFS_ 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | // Register width 17 | #define CLICINT_PARAM_REG_WIDTH 32 18 | 19 | // CLIC interrupt pending, enable, attribute and control 20 | #define CLICINT_CLICINT_REG_OFFSET(id) (0x1000 + 0x4 * id) 21 | //#define CLICINT_CLICINT_REG_OFFSET 0x0 22 | #define CLICINT_CLICINT_IP_BIT 0 23 | #define CLICINT_CLICINT_IE_BIT 8 24 | #define CLICINT_CLICINT_ATTR_SHV_BIT 16 25 | #define CLICINT_CLICINT_ATTR_TRIG_MASK 0x3 26 | #define CLICINT_CLICINT_ATTR_TRIG_OFFSET 17 27 | #define CLICINT_CLICINT_ATTR_TRIG_FIELD \ 28 | ((bitfield_field32_t) { .mask = CLICINT_CLICINT_ATTR_TRIG_MASK, .index = CLICINT_CLICINT_ATTR_TRIG_OFFSET }) 29 | #define CLICINT_CLICINT_ATTR_MODE_MASK 0x3 30 | #define CLICINT_CLICINT_ATTR_MODE_OFFSET 22 31 | #define CLICINT_CLICINT_ATTR_MODE_FIELD \ 32 | ((bitfield_field32_t) { .mask = CLICINT_CLICINT_ATTR_MODE_MASK, .index = CLICINT_CLICINT_ATTR_MODE_OFFSET }) 33 | #define CLICINT_CLICINT_CTL_MASK 0xff 34 | #define CLICINT_CLICINT_CTL_OFFSET 24 35 | #define CLICINT_CLICINT_CTL_FIELD \ 36 | ((bitfield_field32_t) { .mask = CLICINT_CLICINT_CTL_MASK, .index = CLICINT_CLICINT_CTL_OFFSET }) 37 | 38 | #ifdef __cplusplus 39 | } // extern "C" 40 | #endif 41 | #endif // _CLICINT_REG_DEFS_ 42 | // End generated register defines for CLICINT 43 | -------------------------------------------------------------------------------- /sw/include/regs/irq_router.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | // Alessandro Ottaviano 7 | 8 | // Header definition for irq_router 9 | // Note that this is not auto-generated due to limitations of reggen 10 | 11 | #ifndef _IRQ_ROUTER_REG_DEFS_ 12 | #define _IRQ_ROUTER_REG_DEFS_ 13 | 14 | // Register width 15 | #define IRQ_ROUTER_PARAM_REG_WIDTH 32 16 | 17 | // Target selection bitmask control register 18 | #define IRQ_ROUTER_IRQ_TARGET_MASK_REG_OFFSET(i) (0x0 + 0x4 * i) 19 | 20 | #define IRQ_ROUTER_NUM_IRQ_SRCS 59 21 | #define IRQ_ROUTER_NUM_TARGETS 4 22 | 23 | enum car_irq_router_target { 24 | IRQ_ROUTER_TARGET_NONE = 0, 25 | IRQ_ROUTER_TARGET_PLIC = 1, 26 | IRQ_ROUTER_TARGET_CVA6_CLIC0 = 1 << 1, 27 | IRQ_ROUTER_TARGET_CVA6_CLIC1 = 1 << 2, 28 | IRQ_ROUTER_TARGET_SAFETY_ISLAND = 1 << 3, 29 | }; 30 | 31 | #endif // _IRQ_ROUTER_REG_DEFS_ 32 | -------------------------------------------------------------------------------- /sw/include/regs/safety_soc_ctrl.h: -------------------------------------------------------------------------------- 1 | // Generated register defines for safety_soc_ctrl 2 | 3 | // Copyright information found in source file: 4 | // Copyright 2023 ETH Zurich and University of Bologna 5 | 6 | // Licensing information found in source file: 7 | // 8 | // SPDX-License-Identifier: SHL-0.51 9 | 10 | #ifndef _SAFETY_SOC_CTRL_REG_DEFS_ 11 | #define _SAFETY_SOC_CTRL_REG_DEFS_ 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | // Register width 17 | #define SAFETY_SOC_CTRL_PARAM_REG_WIDTH 32 18 | 19 | // Core Boot Address 20 | #define SAFETY_SOC_CTRL_BOOTADDR_REG_OFFSET 0x0 21 | 22 | // Core Fetch Enable 23 | #define SAFETY_SOC_CTRL_FETCHEN_REG_OFFSET 0x4 24 | #define SAFETY_SOC_CTRL_FETCHEN_FETCHEN_BIT 0 25 | 26 | // Core Return Status (return value, EOC) 27 | #define SAFETY_SOC_CTRL_CORESTATUS_REG_OFFSET 0x8 28 | 29 | // Core Boot Mode 30 | #define SAFETY_SOC_CTRL_BOOTMODE_REG_OFFSET 0xc 31 | #define SAFETY_SOC_CTRL_BOOTMODE_BOOTMODE_MASK 0x3 32 | #define SAFETY_SOC_CTRL_BOOTMODE_BOOTMODE_OFFSET 0 33 | #define SAFETY_SOC_CTRL_BOOTMODE_BOOTMODE_FIELD \ 34 | ((bitfield_field32_t) { .mask = SAFETY_SOC_CTRL_BOOTMODE_BOOTMODE_MASK, .index = SAFETY_SOC_CTRL_BOOTMODE_BOOTMODE_OFFSET }) 35 | 36 | #ifdef __cplusplus 37 | } // extern "C" 38 | #endif 39 | #endif // _SAFETY_SOC_CTRL_REG_DEFS_ 40 | // End generated register defines for safety_soc_ctrl -------------------------------------------------------------------------------- /sw/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulp-platform/carfield/57d5f1e57d2e5f45ce0dc956e74618f6b5c737ad/sw/lib/.gitkeep -------------------------------------------------------------------------------- /sw/link/l2.ld: -------------------------------------------------------------------------------- 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 | /* Nicole Narr */ 6 | /* Christopher Reinwardt */ 7 | /* Paul Scheffler */ 8 | /* Alessandro Ottaviano */ 9 | 10 | INCLUDE common.ldh 11 | 12 | MEMORY { 13 | l2 (rwx) : ORIGIN = 0x78000000, LENGTH = 1M 14 | } 15 | 16 | SECTIONS { 17 | /* Keep binaries lean */ 18 | /* /DISCARD/ : { *(.riscv.attributes) *(.comment) } */ 19 | 20 | /* Global and stack pointer */ 21 | /* By default, keep the calling context (boot ROM) stack pointer */ 22 | /* __global_pointer$ = ADDR(.misc) + SIZEOF(.misc) / 2; 23 | __stack_pointer$ = 0; */ 24 | 25 | __base_l2 = ORIGIN(l2); 26 | } 27 | 28 | SECTIONS { 29 | __stack_pointer$ = ORIGIN(l2) + LENGTH(l2) - 8; 30 | 31 | .text : { 32 | *(.text._start) 33 | *(.text) 34 | *(.text.*) 35 | } > l2 36 | 37 | .misc : ALIGN(16) { 38 | *(.rodata) 39 | *(.rodata.*) 40 | *(.data) 41 | *(.data.*) 42 | *(.srodata) 43 | *(.srodata.*) 44 | *(.sdata) 45 | *(.sdata.*) 46 | } > l2 47 | 48 | . = ALIGN(32); 49 | __bss_start = .; 50 | .bss : { 51 | *(.bss) 52 | *(.bss.*) 53 | *(.sbss) 54 | *(.sbss.*) 55 | } > l2 56 | . = ALIGN(32); 57 | __bss_end = .; 58 | 59 | .bulk : ALIGN(16) { 60 | *(.bulk) 61 | *(.bulk.*) 62 | } > l2 63 | } 64 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/axirt_budget.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Thomas Benz 6 | // 7 | // Validate the budget functionality of AXI RT 8 | 9 | #include "axirt.h" 10 | #include "dif/dma.h" 11 | #include "regs/axi_rt.h" 12 | #include "params.h" 13 | #include "util.h" 14 | #include "car_util.h" 15 | 16 | // transfer 17 | #define SIZE_BYTES 256 18 | #define SRC_STRIDE 0 19 | #define DST_STRIDE 0 20 | #define NUM_REPS 8 21 | #define SRC_ADDR 0x0000000010000000 // LLC SPM 22 | #define DST_ADDR 0x0000000080000000 // DRAM 23 | 24 | #define TOTAL_SIZE (SIZE_BYTES * NUM_REPS) 25 | 26 | int main(void) { 27 | 28 | // enable and configure axi rt with fragmentation of 8 beats 29 | __axirt_claim(1, 1); 30 | __axirt_set_len_limit_group(7, 0); 31 | 32 | // configure CVA6 33 | __axirt_set_region(0, 0xffffffff, 0, 0); 34 | __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 0); 35 | __axirt_set_budget(0x10000000, 0, 0); 36 | __axirt_set_budget(0x10000000, 1, 0); 37 | __axirt_set_period(0x10000000, 0, 0); 38 | __axirt_set_period(0x10000000, 1, 0); 39 | 40 | // configure DMA 41 | __axirt_set_region(0, 0xffffffff, 0, 2); 42 | __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 2); 43 | __axirt_set_budget(0x10000000, 0, 2); 44 | __axirt_set_budget(0x10000000, 1, 2); 45 | __axirt_set_period(0x10000000, 0, 2); 46 | __axirt_set_period(0x10000000, 1, 2); 47 | 48 | // enable RT unit for DMA and CVA6 49 | __axirt_enable(0x5); 50 | 51 | // launch DMA transfer 52 | sys_dma_2d_blk_memcpy(DST_ADDR, SRC_ADDR, SIZE_BYTES, DST_STRIDE, SRC_STRIDE, NUM_REPS); 53 | 54 | // read budget registers and compare 55 | volatile uint32_t read_budget = *reg32(&__base_axirt, AXI_RT_READ_BUDGET_LEFT_2_REG_OFFSET); 56 | volatile uint32_t write_budget = *reg32(&__base_axirt, AXI_RT_WRITE_BUDGET_LEFT_2_REG_OFFSET); 57 | 58 | // check 59 | volatile uint8_t difference = (TOTAL_SIZE - read_budget) + (TOTAL_SIZE - write_budget); 60 | volatile uint8_t mismatch = read_budget != write_budget; 61 | 62 | return mismatch | (difference << 1); 63 | } 64 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/axirt_hello.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Nicole Narr 6 | // Christopher Reinwardt 7 | // Thomas Benz 8 | // 9 | // Simple payload to test AXI-RT 10 | 11 | #include "regs/cheshire.h" 12 | #include "dif/clint.h" 13 | #include "dif/uart.h" 14 | #include "axirt.h" 15 | #include "regs/axi_rt.h" 16 | #include "params.h" 17 | #include "util.h" 18 | #include "car_util.h" 19 | 20 | int main(void) { 21 | 22 | // Init the HW 23 | car_init_start(); 24 | 25 | char str[] = "Hello AXI-RT!\r\n"; 26 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 27 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 28 | 29 | // enable and configure axi rt 30 | __axirt_claim(1, 1); 31 | __axirt_set_len_limit_group(2, 0); 32 | 33 | // configure CVA6 34 | __axirt_set_region(0, 0xffffffff, 0, 0); 35 | __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 0); 36 | __axirt_set_budget(8, 0, 0); 37 | __axirt_set_budget(8, 1, 0); 38 | __axirt_set_period(100, 0, 0); 39 | __axirt_set_period(100, 1, 0); 40 | 41 | // configure DMA 42 | __axirt_set_region(0, 0xffffffff, 0, 2); 43 | __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 2); 44 | __axirt_set_budget(0x10000000, 0, 2); 45 | __axirt_set_budget(0x10000000, 1, 2); 46 | __axirt_set_period(0x10000000, 0, 2); 47 | __axirt_set_period(0x10000000, 1, 2); 48 | 49 | // enable RT unit for DMA and CVA6 50 | __axirt_enable(0x5); 51 | 52 | // configure uart and write msg 53 | uart_init(&__base_uart, reset_freq, 115200); 54 | uart_write_str(&__base_uart, str, sizeof(str)); 55 | uart_write_flush(&__base_uart); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/cache_partitioning_basic.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | 7 | // Basic testing of the cache partitioning's configuration registers 8 | 9 | #include 10 | #include 11 | #include "dif/uart.h" 12 | #include "params.h" 13 | #include "regs/cheshire.h" 14 | #include "regs/axi_llc_regs.h" 15 | #include "util.h" 16 | #include "car_util.h" 17 | #include "car_memory_map.h" 18 | #include "printf.h" 19 | 20 | static int probe_rw(uint64_t addr, uint32_t val) 21 | { 22 | writew(val, addr); 23 | uint32_t ret = readw(addr); 24 | return !(ret == val); 25 | } 26 | 27 | #define LLC_RW_TEST_REG(NAME, VAL) \ 28 | err = probe_rw(CAR_LLC_CFG_BASE_ADDR + NAME, VAL); \ 29 | if (err) { \ 30 | printf("error: rw " #NAME "\n"); \ 31 | uart_write_flush(&__base_uart); \ 32 | return 1; \ 33 | } 34 | 35 | int main(void) 36 | { 37 | int err = 0; 38 | 39 | // Init UART 40 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 41 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 42 | uart_init(&__base_uart, reset_freq, 115200); 43 | 44 | // Read LLC version register 45 | uint32_t low = readw(CAR_LLC_CFG_BASE_ADDR + AXI_LLC_VERSION_LOW_REG_OFFSET); 46 | uint32_t high = readw(CAR_LLC_CFG_BASE_ADDR + AXI_LLC_VERSION_HIGH_REG_OFFSET); 47 | uint64_t version = ((uint64_t)high << 32) | ((uint64_t)low); 48 | 49 | // Run basic register rw tests 50 | LLC_RW_TEST_REG(AXI_LLC_CFG_FLUSH_PARTITION_LOW_REG_OFFSET, 0xcafedead); 51 | LLC_RW_TEST_REG(AXI_LLC_CFG_FLUSH_PARTITION_HIGH_REG_OFFSET, 0xcafedead); 52 | 53 | LLC_RW_TEST_REG(AXI_LLC_CFG_SET_PARTITION_LOW_0_REG_OFFSET, 0xdefec8ed); 54 | LLC_RW_TEST_REG(AXI_LLC_CFG_SET_PARTITION_LOW_1_REG_OFFSET, 0xdefec8ed); 55 | 56 | LLC_RW_TEST_REG(AXI_LLC_CFG_SET_PARTITION_HIGH_0_REG_OFFSET, 0xdeadc0de); 57 | LLC_RW_TEST_REG(AXI_LLC_CFG_SET_PARTITION_HIGH_1_REG_OFFSET, 0xdeadc0de); 58 | 59 | printf("llc ver = 0x%016" PRIx64 "\n", version); 60 | uart_write_flush(&__base_uart); 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/helloworld.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Nicole Narr 6 | // Christopher Reinwardt 7 | // 8 | // Simple payload to test bootmodes 9 | 10 | #include "regs/cheshire.h" 11 | #include "dif/clint.h" 12 | #include "dif/uart.h" 13 | #include "params.h" 14 | #include "util.h" 15 | #include "car_util.h" 16 | 17 | int main(void) { 18 | 19 | // Init the HW 20 | car_init_start(); 21 | 22 | char str[] = "Hello World!\r\n"; 23 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 24 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 25 | uart_init(&__base_uart, reset_freq, 115200); 26 | uart_write_str(&__base_uart, str, sizeof(str)); 27 | uart_write_flush(&__base_uart); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/mbox_test.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Maicol Ciani 6 | // 7 | 8 | #include "car_memory_map.h" 9 | #include "io.h" 10 | #include "regs/cheshire.h" 11 | #include "sw/device/lib/dif/dif_rv_plic.h" // to be changed accoridng to correct hash 12 | #include "dif/clint.h" 13 | #include "dif/uart.h" 14 | #include "params.h" 15 | #include "util.h" 16 | #include 17 | #include 18 | 19 | static dif_rv_plic_t plic0; 20 | 21 | int main(int argc, char const *argv[]) { 22 | int mbox_id = 60; // index of mbox irq in the irq vector input to the PLIC 23 | int prio = 0x1; 24 | int a,b,c,d,e; 25 | bool t; 26 | unsigned global_irq_en = 0x00001808; 27 | unsigned external_irq_en = 0x00000800; 28 | 29 | // Uart setup 30 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 31 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 32 | uart_init(&__base_uart, reset_freq, 115200); 33 | 34 | asm volatile("csrw mstatus, %0\n" : : "r"(global_irq_en )); // Set global interrupt enable in CVA6 csr 35 | asm volatile("csrw mie, %0\n" : : "r"(external_irq_en)); // Set external interrupt enable in CVA6 csr 36 | // PLIC setup 37 | mmio_region_t plic_base_addr = mmio_region_from_addr(0x04000000); 38 | t = dif_rv_plic_init(plic_base_addr, &plic0); 39 | t = dif_rv_plic_irq_set_priority(&plic0, mbox_id, prio); 40 | t = dif_rv_plic_irq_set_enabled(&plic0, mbox_id, 0, kDifToggleEnabled); 41 | writew(0xBAADC0DE, 0x40000880); 42 | a = readw(0x40000880); 43 | if( a == 0xBAADC0DE ) 44 | writew(0x00000001, 0x40000804); // ring doorbell if mailbox is accessible 45 | writew(0x00000001, 0x4000080c); 46 | wfi(); 47 | return 0; 48 | } 49 | 50 | void trap_vector (void){ 51 | int * claim_irq; 52 | int mbox_id = 60; 53 | dif_rv_plic_irq_claim(&plic0, 0, &claim_irq); 54 | dif_rv_plic_irq_complete(&plic0, 0, *claim_irq); 55 | writew(0x0, 0x40000C04); 56 | writew(0x0, 0x40000C0C); 57 | writew(0x1, 0x40000C08); 58 | return; 59 | } 60 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/minimal.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | 7 | // Minimal test, mainly useful to see whether the return value gets properly read out 8 | 9 | int main(void) 10 | { 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/pulp-offload-intf.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Luca Valente 6 | // 7 | // Bare-metal offload test for the PULP cluster with interference 8 | 9 | #include 10 | #include 11 | 12 | #include "car_memory_map.h" 13 | #include "car_util.h" 14 | #include "dif/clint.h" 15 | #include "dif/uart.h" 16 | #include "params.h" 17 | #include "regs/cheshire.h" 18 | #include "csr.h" 19 | #include "util.h" 20 | #include "payload.h" 21 | #include "printf.h" 22 | 23 | #define LCL 24 | 25 | long int buffer[128]; 26 | 27 | void read_from_cache(int l1_way_size, int stride) { 28 | asm volatile("": : :"memory"); 29 | for(volatile int j = 0; j < l1_way_size; j++) 30 | { 31 | * ( ( volatile long int * ) &buffer[j] ); 32 | } 33 | asm volatile("": : :"memory"); 34 | for(volatile int j = 0; j < l1_way_size; j++) 35 | { 36 | * ( ( volatile long int * ) &buffer[j*stride]); 37 | } 38 | asm volatile("": : :"memory"); 39 | } 40 | 41 | long unsigned sweep(int stride) 42 | { 43 | 44 | int l1_way_size = 4 * 1024 / 8; 45 | int working_set = l1_way_size * stride * 8; 46 | 47 | volatile long unsigned cycle_start; 48 | 49 | for(int i = 0; i < 10; i++) 50 | { 51 | if(i==1) 52 | { 53 | cycle_start = get_mcycle(); 54 | } 55 | read_from_cache(l1_way_size, stride); 56 | } 57 | 58 | volatile long unsigned cycles = get_mcycle() - cycle_start; 59 | 60 | #ifdef VERBOSE 61 | printf("%3dKB , %6d \r\n", 62 | working_set / 1024, (int)cycles); 63 | #endif 64 | 65 | return cycles; 66 | } 67 | 68 | int main(void) 69 | { 70 | // Set the LLC as LLC 71 | axi_llc_reg32_all_cache(&__base_llc); 72 | writew(0x18,CAR_HYPERBUS_CFG_BASE_ADDR+0x18); 73 | volatile uint32_t pulp_ret_val = 0; 74 | // Init the HW 75 | // PULP Island 76 | #ifdef LCL 77 | car_enable_domain(CAR_PULP_RST); 78 | char str[] = "Cluster boot.\r\n"; 79 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 80 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 81 | 82 | load_binary(); 83 | 84 | volatile uint32_t pulp_boot_default = ELF_BOOT_ADDR; 85 | 86 | pulp_cluster_set_bootaddress(pulp_boot_default); 87 | 88 | uart_init(&__base_uart, reset_freq, 115200); 89 | uart_write_str(&__base_uart, str, sizeof(str)); 90 | uart_write_flush(&__base_uart); 91 | 92 | pulp_cluster_start(); 93 | #endif 94 | 95 | #ifdef VERBOSE 96 | printf("Buffer: %x\n", buffer); 97 | #endif 98 | 99 | volatile long unsigned cycles[5]; 100 | int j=0; 101 | for( int i = 4; i<128; i=i*2){ 102 | cycles[j] = sweep(i); 103 | j++; 104 | } 105 | 106 | #ifdef LCL 107 | pulp_cluster_wait_eoc(); 108 | 109 | pulp_ret_val = pulp_cluster_get_return(); 110 | #endif 111 | 112 | 113 | for(int i=0;i<5;i++) 114 | printf("%d\r\n",cycles[i]); 115 | 116 | printf("Done\n"); 117 | 118 | return pulp_ret_val; 119 | 120 | } 121 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/pulpd_offloader_blocking.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Yvan Tortorella 6 | // 7 | // Bare-metal offload test for the PULP cluster 8 | 9 | #include 10 | #include 11 | 12 | #include "car_memory_map.h" 13 | #include "car_util.h" 14 | #include "dif/clint.h" 15 | #include "dif/uart.h" 16 | #include "params.h" 17 | #include "regs/cheshire.h" 18 | #include "util.h" 19 | #include "payload.h" 20 | 21 | int main(void) 22 | { 23 | // Init the HW 24 | // PULP Island 25 | car_enable_domain(CAR_PULP_RST); 26 | 27 | char str[] = "Cluster boot.\r\n"; 28 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 29 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 30 | 31 | load_binary(); 32 | 33 | volatile uint32_t pulp_boot_default = ELF_BOOT_ADDR; 34 | volatile uint32_t pulp_ret_val = 0; 35 | 36 | pulp_cluster_set_bootaddress(pulp_boot_default); 37 | 38 | uart_init(&__base_uart, reset_freq, 115200); 39 | uart_write_str(&__base_uart, str, sizeof(str)); 40 | uart_write_flush(&__base_uart); 41 | 42 | pulp_cluster_start(); 43 | 44 | pulp_cluster_wait_eoc(); 45 | 46 | pulp_ret_val = pulp_cluster_get_return(); 47 | 48 | return pulp_ret_val; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/safed_offloader_blocking.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Alessandro Ottaviano 6 | // 7 | 8 | #include 9 | #include 10 | 11 | #include "car_memory_map.h" 12 | #include "io.h" 13 | #include "dif/clint.h" 14 | #include "dif/uart.h" 15 | #include "params.h" 16 | #include "regs/cheshire.h" 17 | #include "util.h" 18 | #include "payload.h" 19 | #include "car_util.h" 20 | 21 | extern int load_safed_payload (); 22 | 23 | int main(void) 24 | { 25 | // Init the HW 26 | // Safety Island 27 | car_enable_domain(CAR_SAFETY_RST); 28 | 29 | // Here we assume that the offloader has to poll a status register to catch the end of 30 | // computation of the Safety Island. Therefore, the offloading is blocking. 31 | uint32_t ret = safed_offloader_blocking(); 32 | 33 | return ret; 34 | } 35 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/spatz-offload.c.wip: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Mattia Sinigaglia 6 | // 7 | 8 | #include "car_memory_map.h" 9 | #include "io.h" 10 | #include "regs/cheshire.h" 11 | #include "sw/device/lib/dif/dif_rv_plic.h" // to be changed accoridng to correct hash 12 | #include "dif/clint.h" 13 | #include "dif/uart.h" 14 | #include "params.h" 15 | #include "util.h" 16 | #include 17 | #include 18 | 19 | 20 | 21 | int main(void) { 22 | 23 | // Init the HW 24 | car_init_start(); 25 | 26 | char str[] = "FP Cluster boot.\r\n"; 27 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 28 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 29 | 30 | load_binary(); 31 | 32 | writew(0x78003EE0, SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_REG_OFFSET); 33 | 34 | // Mailbox base addr CAR_MBOX_BASE_ADDR 35 | for (int id = 0; id < 2; id++){ 36 | // Set Spatz id Interrupt 37 | writew(0x00000001, MBOX_CAR_INT_SND_SET(id)); 38 | 39 | // Enable Spatz id Interrupt 40 | writew(0x00000001, MBOX_CAR_INT_SND_EN(id)); 41 | 42 | } 43 | wfi(); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/sw_rst_seq.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | // Alessandro Ottaviano 7 | 8 | // Basic testing of warm resets. This test is executed only from LLC/SPM since it tests SW reset on 9 | // shared L2 and hyperbus memory controller. 10 | 11 | #include 12 | #include "params.h" 13 | #include "regs/cheshire.h" 14 | #include "regs/soc_ctrl.h" 15 | #include "regs/safety_soc_ctrl.h" 16 | #include "regs/spatz_cluster_peripheral.h" 17 | #include "util.h" 18 | #include "car_util.h" 19 | #include "car_memory_map.h" 20 | 21 | int main(void) 22 | { 23 | // Safety Island 24 | car_enable_domain(CAR_SAFETY_RST); 25 | 26 | // Security Island 27 | // car_enable_domain(CAR_SECURITY_RST); 28 | 29 | // PULP Island 30 | car_enable_domain(CAR_PULP_RST); 31 | 32 | // Spatz Island 33 | car_enable_domain(CAR_SPATZ_RST); 34 | 35 | // Safety Island 36 | 37 | // We write a bunch of bytes to the safety island's boot register and check 38 | // that it reads the reset value after a warm reset. Note that we can't use 39 | // the safety island's scratchpad for that since it is not resetable 40 | uint64_t magic = 0xcafebeef; 41 | 42 | // Write a pattern to safety island boot addr 43 | writew(magic, CAR_SAFETY_ISLAND_PERIPHS_BASE_ADDR(car_safety_island) + 44 | SAFETY_SOC_CTRL_BOOTADDR_REG_OFFSET); 45 | 46 | // Double check 47 | if (readw(CAR_SAFETY_ISLAND_PERIPHS_BASE_ADDR(car_safety_island) + 48 | SAFETY_SOC_CTRL_BOOTADDR_REG_OFFSET) != magic) 49 | return ESAFEDNOACCES; 50 | 51 | // engage reset sequence for safety island 52 | car_reset_domain(CAR_SAFETY_RST); 53 | 54 | // After the reset we should only see zeros 55 | if (readw(CAR_SAFETY_ISLAND_PERIPHS_BASE_ADDR(car_safety_island) + 56 | SAFETY_SOC_CTRL_BOOTADDR_REG_OFFSET) != 57 | SAFETY_ISLAND_BOOT_ADDR_RSVAL) 58 | return ESAFEDNOACCES; 59 | 60 | // Spatz 61 | writew(magic, CAR_FP_CLUSTER_PERIPHS_BASE_ADDR(car_spatz_cluster) + 62 | SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_REG_OFFSET); 63 | if (readw(CAR_FP_CLUSTER_PERIPHS_BASE_ADDR(car_spatz_cluster) + 64 | SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_REG_OFFSET) != 65 | magic) 66 | return EFPCLNOACCES; 67 | 68 | car_reset_domain(CAR_SPATZ_RST); 69 | if (readw(CAR_FP_CLUSTER_PERIPHS_BASE_ADDR(car_spatz_cluster) + 70 | SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_REG_OFFSET) != 0) 71 | return EFPCLNOACCES; 72 | 73 | // PULP Reset 74 | writew(magic, CAR_INT_CLUSTER_BOOT_ADDR_REG(car_integer_cluster)); 75 | if (readw(CAR_INT_CLUSTER_BOOT_ADDR_REG(car_integer_cluster)) != magic) 76 | return EINTCLNOACCES; 77 | 78 | volatile uint32_t pulp_boot_addr_rst_value = 0x78008080; 79 | car_reset_domain(CAR_PULP_RST); 80 | if (readw(CAR_INT_CLUSTER_BOOT_ADDR_REG(car_integer_cluster)) != pulp_boot_addr_rst_value) 81 | return EINTCLNOACCES; 82 | 83 | // L2 Reset 84 | // Memory doesn't have a reset so this needs to be checked manually 85 | car_reset_domain(CAR_L2_RST); 86 | 87 | // Security Island 88 | // We can't access anything so this needs to be checked manually In secure boot mode, the 89 | // security island can't be software resetted, which is why we disable this for now 90 | // car_reset_domain(CAR_SECURITY_RST); 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/system_timer_test.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Alessandro Ottaviano 6 | // 7 | 8 | #include "car_memory_map.h" 9 | #include "io.h" 10 | #include "dif/clint.h" 11 | #include "dif/uart.h" 12 | #include "params.h" 13 | #include "regs/cheshire.h" 14 | #include "regs/system_timer.h" 15 | #include "util.h" 16 | #include "car_util.h" 17 | 18 | // TODO: This test is really brittle. Its only purpose is to test timer accesses when the timer is 19 | // configured in freerunning mode and check if the value is within a sensible range. A better test 20 | // uses a periodic timer and checks if the periodic interrupts are taken. It will replace the 21 | // current test when interrupts are tested in the SoC. 22 | 23 | #define assert(expression) \ 24 | do { \ 25 | if (!expression) { \ 26 | return 1; \ 27 | } \ 28 | } while (0) 29 | 30 | #define DUMMY_TIMER_CNT_GOLDEN_MIN 8000 31 | #define DUMMY_TIMER_CNT_GOLDEN_MAX 9000 32 | 33 | int main(void) { 34 | 35 | // Reset system timer 36 | writed(1, CAR_SYSTEM_TIMER_BASE_ADDR + TIMER_RESET_LO_OFFSET); 37 | 38 | // Start system timer 39 | writed(1, CAR_SYSTEM_TIMER_BASE_ADDR + TIMER_START_LO_OFFSET); 40 | 41 | for (volatile int i = 0; i < 500; i++) 42 | ; 43 | 44 | // Stop system timer 45 | writed(0, CAR_SYSTEM_TIMER_BASE_ADDR + TIMER_CFG_LO_OFFSET); 46 | 47 | // Get system timer count 48 | volatile int time = readd(CAR_SYSTEM_TIMER_BASE_ADDR + TIMER_CNT_LO_OFFSET); 49 | 50 | // Note: the result is checked against a golden value that is probed from 51 | // the waveforms, to check if the value is correctly read from sw. 52 | if (time <= DUMMY_TIMER_CNT_GOLDEN_MIN || time >= DUMMY_TIMER_CNT_GOLDEN_MAX) { 53 | return 1; 54 | } 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/hostd/vclic_basic.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // Robert Balas 6 | 7 | // Basic testing of the virtualized clic's registers 8 | 9 | #include 10 | #include 11 | #include "dif/uart.h" 12 | #include "params.h" 13 | #include "regs/cheshire.h" 14 | #include "regs/clic.h" 15 | #include "regs/clicint.h" 16 | #include "util.h" 17 | #include "car_util.h" 18 | #include "car_memory_map.h" 19 | #include "printf.h" 20 | 21 | static int probe_rw(uint64_t addr, uint32_t val) 22 | { 23 | writew(val, addr); 24 | uint32_t ret = readw(addr); 25 | return !(ret == val); 26 | } 27 | 28 | #define VCLIC_RW_TEST_REG(NAME, VAL) \ 29 | err = probe_rw(CAR_CLIC_CFG_BASE_ADDR(0) + NAME, VAL); \ 30 | if (err) { \ 31 | printf("error: rw " #NAME "\n"); \ 32 | uart_write_flush(&__base_uart); \ 33 | return 1; \ 34 | } 35 | 36 | int main(void) 37 | { 38 | int err = 0; 39 | 40 | // Init UART 41 | uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); 42 | uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); 43 | uart_init(&__base_uart, reset_freq, 115200); 44 | 45 | uint32_t mclicconf = readw(CAR_CLIC_CFG_BASE_ADDR(0) + MCLIC_MCLICCFG_REG_OFFSET); 46 | 47 | // Run basic register rw tests 48 | VCLIC_RW_TEST_REG(MCLIC_MCLICCFG_REG_OFFSET, mclicconf | 0x3); 49 | VCLIC_RW_TEST_REG(CLICINT_CLICINT_REG_OFFSET(1), 0x100); 50 | VCLIC_RW_TEST_REG(CLICINT_CLICINT_REG_OFFSET(75), 0x100); 51 | 52 | // supervisor 53 | VCLIC_RW_TEST_REG(0x08000, 1); 54 | 55 | // VCLIC regs 56 | VCLIC_RW_TEST_REG(0x0e000, 1); 57 | 58 | uart_write_flush(&__base_uart); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/pulpd/sw.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 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 | # Alessandro Ottaviano 6 | # Yvan Tortorella 7 | 8 | .PHONY: all clean 9 | 10 | # Make fragment for integer cluster bare-metal tests compiled with pulp-runtime. 11 | 12 | # List all the directories in the 'tests' folder 13 | CAR_PULPD_SW := $(CAR_SW_DIR)/tests/bare-metal/pulpd 14 | PULPD_SW_DIR := $(PULPD_ROOT)/regression-tests/carfield 15 | PULPD_TEST_DIRS := $(wildcard $(PULPD_ROOT)/regression-tests/carfield/*) 16 | 17 | # We remove unneded TCDM sections directly from the binary we want to generate. This speeds up the standalone 18 | # simulation when preloading the L2 memory using JTAG and Serial Link. 19 | remove_sections := --remove-section .l1cluster_g --remove-section .bss_l1 20 | 21 | # Generate the list of build targets based on the directories 22 | PULPD_BUILD_TARGETS := $(addsuffix /build,$(PULPD_TEST_DIRS)) 23 | 24 | # We have a target per test. The target (1) compiles the binary and (2) generates the needed stimuli 25 | # file format, if any is required. 26 | $(PULPD_SW_DIR)/%/build: $(PULPD_ROOT) | venv 27 | # Compile 28 | $(MAKE) -C $(PULPD_SW_DIR)/$* all 29 | cp $@/test/test $(CAR_PULPD_SW)/$*.elf 30 | $(PULPD_RISCV)-objcopy $(remove_sections) $(CAR_PULPD_SW)/$*.elf 31 | cp $(CAR_PULPD_SW)/$*.elf $@/test/test.elf 32 | @echo $(PULPD_SW_DIR) 33 | 34 | # Convert compiled binaries to header files 35 | PULPD_HEADER_TARGETS := $(patsubst $(PULPD_SW_DIR)/%, $(CAR_SW_DIR)/tests/bare-metal/pulpd/%.h, $(PULPD_TEST_DIRS)) 36 | 37 | $(CAR_SW_DIR)/tests/bare-metal/pulpd/%.h: $(PULPD_SW_DIR)/%/build/test/test | venv 38 | $(VENV)/python $(CAR_ROOT)/scripts/elf2header.py --binary $< --vectors $@ 39 | 40 | # Convert compiled binaries to slm for hyperram 41 | PULPD_SLM_TARGETS := $(patsubst $(PULPD_SW_DIR)/%, $(CAR_SW_DIR)/tests/bare-metal/pulpd/%.hyperram0.slm, $(PULPD_TEST_DIRS)) 42 | PULPD_SLM_TARGETS += $(patsubst $(PULPD_SW_DIR)/%, $(CAR_SW_DIR)/tests/bare-metal/pulpd/%.hyperram1.slm, $(PULPD_TEST_DIRS)) 43 | 44 | $(CAR_SW_DIR)/tests/bare-metal/pulpd/%.hyperram0.slm $(CAR_SW_DIR)/tests/bare-metal/pulpd/%.hyperram1.slm: $(PULPD_SW_DIR)/%/build/test/test.elf | venv 45 | $(VENV)/python $(CAR_ROOT)/scripts/elf2slm.py --binary=$< --vectors=$(CAR_SW_DIR)/tests/bare-metal/pulpd/$*.hyperram 46 | 47 | # Global targets 48 | pulpd-sw-all: $(PULPD_BUILD_TARGETS) $(PULPD_HEADER_TARGETS) $(PULPD_SLM_TARGETS) 49 | 50 | pulpd-sw-clean: 51 | # Clean all the directories in 'tests' 52 | $(foreach dir, $(PULPD_TEST_DIRS), $(MAKE) -C $(dir) clean;) 53 | $(RM) $(CAR_SW_DIR)/tests/bare-metal/pulpd/*.h 54 | -------------------------------------------------------------------------------- /sw/tests/bare-metal/safed/sw.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 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 | # Alessandro Ottaviano 6 | 7 | .PHONY: all clean 8 | 9 | # Make fragment for safety island bare-metal tests compiled with pulp-runtime. 10 | 11 | # List all the directories in the 'tests' folder 12 | SAFED_TEST_DIRS := $(wildcard $(SAFED_SW_DIR)/tests/*) 13 | SAFED_TEST_DIRS := $(filter-out $(SAFED_SW_DIR)/tests/runtime_shared,$(SAFED_TEST_DIRS)) 14 | SAFED_TEST_DIRS := $(filter-out $(wildcard $(SAFED_SW_DIR)/tests/freertos*),$(SAFED_TEST_DIRS)) 15 | 16 | # Generate the list of build targets based on the directories 17 | SAFED_BUILD_TARGETS := $(addsuffix /build,$(SAFED_TEST_DIRS)) 18 | 19 | # We have a target per test. The target (1) compiles the binary and (2) generates the needed stimuli 20 | # file format, if any is required. 21 | $(SAFED_SW_DIR)/tests/%/build: $(SAFED_ROOT) | venv 22 | # Compile 23 | $(MAKE) -C $(SAFED_SW_DIR)/tests/$* all || true 24 | # Make sure we don't have intermediate files in case of errors 25 | @if [ ! -f $@/$*/$* ]; then echo "Error: Did you source env/safed-env.sh?"; $(RM) -r $@; exit 1; fi 26 | 27 | # Convert compiled binaries to header files 28 | SAFED_HEADER_TARGETS := $(patsubst $(SAFED_SW_DIR)/tests/%, $(CAR_SW_DIR)/tests/bare-metal/safed/%.h, $(SAFED_TEST_DIRS)) 29 | 30 | $(CAR_SW_DIR)/tests/bare-metal/safed/%.h: $(SAFED_SW_DIR)/tests/%/build | venv 31 | $(VENV)/python $(CAR_ROOT)/scripts/elf2header.py --binary $ 6 | # Christopher Reinwardt 7 | # Alessandro Ottaviano 8 | # Paul Scheffler 9 | 10 | set flags "" 11 | if {[info exists VSIM_FLAGS]} { append flags "${VSIM_FLAGS}" } 12 | 13 | set pargs "" 14 | if {[info exists HYP_USER_PRELOAD]} { append pargs "+HYP_USER_PRELOAD=${HYP_USER_PRELOAD} " } 15 | if {[info exists SECURE_BOOT]} { append pargs "+SECURE_BOOT=${SECURE_BOOT} " } 16 | if {[info exists CHS_BOOTMODE]} { append pargs "+CHS_BOOTMODE=${CHS_BOOTMODE} " } 17 | if {[info exists CHS_PRELMODE]} { append pargs "+CHS_PRELMODE=${CHS_PRELMODE} " } 18 | if {[info exists CHS_BINARY]} { append pargs "+CHS_BINARY=${CHS_BINARY} " } 19 | if {[info exists SECD_BINARY]} { append pargs "+SECD_BINARY=${SECD_BINARY} " } 20 | if {[info exists SECD_BOOTMODE]} { append pargs "+SECD_BOOTMODE=${SECD_BOOTMODE} " } 21 | if {[info exists SECD_IMAGE]} { append pargs "+SECD_IMAGE=${SECD_IMAGE} " } 22 | if {[info exists PULPD_BOOTMODE]} { append pargs "+PULPD_BOOTMODE=${PULPD_BOOTMODE} " } 23 | if {[info exists PULPD_BINARY]} { append pargs "+PULPD_BINARY=${PULPD_BINARY} " } 24 | if {[info exists SAFED_BOOTMODE]} { append pargs "+SAFED_BOOTMODE=${SAFED_BOOTMODE} " } 25 | if {[info exists SAFED_BINARY]} { append pargs "+SAFED_BINARY=${SAFED_BINARY} " } 26 | if {[info exists SPATZD_BOOTMODE]} { append pargs "+SPATZD_BOOTMODE=${SPATZD_BOOTMODE} " } 27 | if {[info exists SPATZD_BINARY] } { append pargs "+SPATZD_BINARY=${SPATZD_BINARY} " } 28 | if {[info exists CHS_IMAGE]} { append pargs "+CHS_IMAGE=${CHS_IMAGE} " } 29 | 30 | eval "vsim ${TESTBENCH}_opt -t 1ps" ${flags} ${pargs} 31 | 32 | set StdArithNoWarnings 1 33 | set NumericStdNoWarnings 1 34 | -------------------------------------------------------------------------------- /target/xilinx/README.md: -------------------------------------------------------------------------------- 1 | ## Xilinx compile flow 2 | 3 | The Xilinx compile flow is divided in flavors: 4 | - vanilla : A pure-verilog compile flow which does not use block design but pre-generates IPs source code. 5 | - bd : A block design based compile flow which pre-packages a Carfield IP and builds a bitstream out of it. 6 | 7 | User inputs variables are defined in xilinx.mk and written in capital letters (ex: XILINX_BOARD), while derived variables are writted in lower case (ex: xilinx_bit). 8 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/.gitignore: -------------------------------------------------------------------------------- 1 | # Makefile 2 | /out/ 3 | # Bender 4 | /scripts/add_sources.tcl* 5 | /scripts/add_includes.tcl 6 | # Vivado 7 | /.Xil 8 | /carfield_* 9 | /probes.ltx 10 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/constraints/vcu118.xdc: -------------------------------------------------------------------------------- 1 | # Copyright 2024 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 | # Cyril Koenig 6 | 7 | # VIOs are asynchronous 8 | set_false_path -through [get_pins -of_objects [get_cells design_1_i/vio_0] -filter {NAME =~ *probe*}] 9 | 10 | # Create system clocks 11 | create_clock -period 4 -name sys_clk [get_pins design_1_i/util_ds_buf_0/IBUF_OUT] 12 | set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_pins design_1_i/util_ds_buf_0/IBUF_OUT] 13 | create_clock -period 10 -name pcie_clk [get_nets design_1_i/util_ds_buf_1/U0/IBUF_OUT[0]] 14 | create_clock -period 10 -name pcie_clk_div [get_nets design_1_i/util_ds_buf_1/U0/IBUF_DS_ODIV2[0]] 15 | set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets design_1_i/util_ds_buf_1/U0/IBUF_DS_ODIV2[0]] 16 | set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets design_1_i/util_ds_buf_1/U0/IBUF_OUT[0]] 17 | 18 | # PCIe clock LOC 19 | #set_property LOC [get_package_pins -of_objects [get_bels [get_sites -filter {NAME =~ *COMMON*} -of_objects [get_iobanks -of_objects [get_sites GTYE4_CHANNEL_X1Y15]]]/REFCLK0P]] [get_ports pcie_refclk_clk_p[0]] 20 | #set_property LOC [get_package_pins -of_objects [get_bels [get_sites -filter {NAME =~ *COMMON*} -of_objects [get_iobanks -of_objects [get_sites GTYE4_CHANNEL_X1Y15]]]/REFCLK0N]] [get_ports pcie_refclk_clk_n[0]] 21 | 22 | set_property PACKAGE_PIN AW25 [get_ports "uart_rx_i"] ;# Bank 64 VCCO - VCC1V8_FPGA - IO_L9P_T1L_N4_AD12P_64 23 | set_property IOSTANDARD LVCMOS18 [get_ports "uart_rx_i"] ;# Bank 64 VCCO - VCC1V8_FPGA - IO_L9P_T1L_N4_AD12P_64 24 | set_property PACKAGE_PIN BB21 [get_ports "uart_tx_o"] ;# Bank 64 VCCO - VCC1V8_FPGA - IO_L8N_T1L_N3_AD5N_64 25 | set_property IOSTANDARD LVCMOS18 [get_ports "uart_tx_o"] ;# Bank 64 VCCO - VCC1V8_FPGA - IO_L8N_T1L_N3_AD5N_64 26 | #set_property PACKAGE_PIN BB22 [get_ports "uart_rts_o"] ; 27 | #set_property IOSTANDARD LVCMOS18 [get_ports "uart_rts_o"] ; 28 | #set_property PACKAGE_PIN AY25 [get_ports "uart_cts_i"] ; 29 | #set_property IOSTANDARD LVCMOS18 [get_ports "uart_cts_i"] ; 30 | 31 | set_property PACKAGE_PIN L19 [get_ports cpu_reset] ;# Bank 73 VCCO - VCC1V2_FPGA - IO_T1U_N12_73 32 | set_property IOSTANDARD LVCMOS12 [get_ports cpu_reset] ;# Bank 73 VCCO - VCC1V2_FPGA - IO_T1U_N12_73 33 | 34 | set_property BOARD_PART_PIN default_250mhz_clk1_n [get_ports default_250mhz_clk1_clk_n] 35 | set_property BOARD_PART_PIN default_250mhz_clk1_p [get_ports default_250mhz_clk1_clk_p] 36 | 37 | set_property PACKAGE_PIN D12 [get_ports default_250mhz_clk1_clk_n] ; # Bank 71 VCCO - VCC1V2_FPGA - IO_L13N_T2L_N1_GC_QBC_71 38 | set_property IOSTANDARD DIFF_SSTL12 [get_ports default_250mhz_clk1_clk_n] ; # Bank 71 VCCO - VCC1V2_FPGA - IO_L13N_T2L_N1_GC_QBC_71 39 | set_property PACKAGE_PIN E12 [get_ports default_250mhz_clk1_clk_p] ; # Bank 71 VCCO - VCC1V2_FPGA - IO_L13P_T2L_N0_GC_QBC_71 40 | set_property IOSTANDARD DIFF_SSTL12 [get_ports default_250mhz_clk1_clk_p] ; # Bank 71 VCCO - VCC1V2_FPGA - IO_L13P_T2L_N0_GC_QBC_71 41 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/constraints/vcu118_ext_jtag.xdc: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | # 7 | set_property PACKAGE_PIN N30 [get_ports jtag_tdo_o] 8 | set_property IOSTANDARD LVCMOS12 [get_ports jtag_tdo_o] 9 | 10 | set_property PACKAGE_PIN P30 [get_ports jtag_tck_i] 11 | set_property IOSTANDARD LVCMOS12 [get_ports jtag_tck_i] 12 | 13 | set_property PACKAGE_PIN N28 [get_ports jtag_tms_i] 14 | set_property IOSTANDARD LVCMOS12 [get_ports jtag_tms_i] 15 | 16 | set_property PACKAGE_PIN M30 [get_ports jtag_tdi_i] 17 | set_property IOSTANDARD LVCMOS12 [get_ports jtag_tdi_i] 18 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/constraints/vcu128_ext_jtag.xdc: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | set_property PACKAGE_PIN A23 [get_ports jtag_gnd_o] ;# A23 - C15 (FMCP_HSPC_LA10_N) - J1.04 - GND 8 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_gnd_o] ; 9 | 10 | set_property PACKAGE_PIN B23 [get_ports jtag_vdd_o] ;# B23 - C14 (FMCP_HSPC_LA10_P) - J1.02 - VDD 11 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_vdd_o] ; 12 | 13 | set_property PACKAGE_PIN B25 [get_ports jtag_tdo_o] ;# B25 - H17 (FMCP_HSPC_LA11_N) - J1.08 - TDO 14 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tdo_o] 15 | 16 | set_property PACKAGE_PIN B26 [get_ports jtag_tck_i] ;# B26 - H16 (FMCP_HSPC_LA11_P) - J1.06 - TCK 17 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tck_i] ; 18 | 19 | set_property PACKAGE_PIN H22 [get_ports jtag_tms_i] ;# H22 - G16 (FMCP_HSPC_LA12_N) - J1.12 - TNS 20 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tms_i] ; 21 | 22 | set_property PACKAGE_PIN J22 [get_ports jtag_tdi_i] ;# J22 - G15 (FMCP_HSPC_LA12_P) - J1.10 - TDI 23 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tdi_i] 24 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/flavor_bd.mk: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | # Output bitstream 8 | xilinx_bit_bd = $(CAR_XIL_DIR)/flavor_bd/out/design_1_wrapper.bit 9 | 10 | # This flavor requires pre-compiled Xilinx IPs 11 | xilinx_ips_names_bd := carfield_ip 12 | # Path to compiled ips 13 | xilinx_ips_paths_bd := $(foreach ip-name,$(xilinx_ips_names_bd),$(xilinx_ip_dir)/$(ip-name)/$(ip-name).srcs/sources_1/ip/$(ip-name)/$(ip-name).xci) 14 | 15 | # Vivado variables 16 | vivado_env_bd := \ 17 | XILINX_PROJECT=$(XILINX_PROJECT) \ 18 | XILINX_BOARD=$(XILINX_BOARD) \ 19 | XILINX_PART=$(xilinx_part) \ 20 | XILINX_BOARD_LONG=$(xilinx_board_long) \ 21 | XILINX_PORT=$(XILINX_PORT) \ 22 | XILINX_HOST=$(XILINX_HOST) \ 23 | XILINX_FPGA_PATH=$(XILINX_FPGA_PATH) \ 24 | XILINX_BIT=$(xilinx_bit) \ 25 | GEN_NO_HYPERBUS=$(GEN_NO_HYPERBUS) \ 26 | GEN_EXT_JTAG=$(GEN_EXT_JTAG) \ 27 | XILINX_ROUTED_DCP=$(XILINX_ROUTED_DCP) \ 28 | XILINX_CHECK_TIMING=$(XILINX_CHECK_TIMING) \ 29 | XILINX_ELABORATION_ONLY=$(XILINX_ELABORATION_ONLY) 30 | 31 | # Flavor specific bender args 32 | xilinx_targs_bd := $(common_targs) $(xilinx_targs_common) -t xilinx_bd -t $(XILINX_BOARD) 33 | xilinx_defs_bd := $(common_defs) $(xilinx_defs_common) 34 | 35 | # Add includes files for block design 36 | $(CAR_XIL_DIR)/flavor_bd/scripts/add_includes.tcl: 37 | ${BENDER} script vivado --only-defines --only-includes $(xilinx_targs_bd) $(xilinx_defs_bd) > $@.bak 38 | # Remove ibex's vendored prim includes as they conflict with opentitan's vendored prim includes 39 | grep -v -P "lowrisc_ip/ip/prim/rtl" $@.bak > $@ 40 | # Override system verilog files 41 | $(CAR_XIL_DIR)/scripts/overrides.sh $@ 42 | echo "" >> $@ 43 | 44 | # Build block design bitstream 45 | $(CAR_XIL_DIR)/flavor_bd/out/%.bit: $(xilinx_ips_paths_bd) $(CAR_XIL_DIR)/flavor_bd/scripts/add_includes.tcl 46 | mkdir -p $(CAR_XIL_DIR)/flavor_bd/out 47 | cd $(CAR_XIL_DIR)/flavor_bd && $(vivado_env_bd) $(VIVADO) $(VIVADO_FLAGS) -source scripts/run.tcl 48 | find $(CAR_XIL_DIR)/flavor_bd/carfield* -name "*.ltx" -o -name "*.bit" -o -name "*routed.rpt" | xargs -I {} cp {} $(CAR_XIL_DIR)/flavor_bd/out 49 | .PRECIOUS: $(CAR_XIL_DIR)/flavor_bd/out/%.bit 50 | 51 | car-xil-clean-bd: 52 | cd $(CAR_XIL_DIR)/flavor_bd && rm -rf scripts/add_includes.tcl* *.log *.jou *.str *.mif carfield_* .Xil/ 53 | 54 | .PHONY: car-xil-clean-bd 55 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/scripts/carfield_bd_ext_jtag_vcu118.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2024 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 | # Cyril Koenig 6 | 7 | set jtag_tck_i [ create_bd_port -dir I jtag_tck_i ] 8 | set jtag_tdi_i [ create_bd_port -dir I jtag_tdi_i ] 9 | set jtag_tdo_o [ create_bd_port -dir O jtag_tdo_o ] 10 | set jtag_tms_i [ create_bd_port -dir I jtag_tms_i ] 11 | connect_bd_net -net carfield_xilinx_ip_0_jtag_tdo_o [get_bd_ports jtag_tdo_o] [get_bd_pins carfield_xilinx_ip_0/jtag_tdo_o] 12 | connect_bd_net -net jtag_tck_i_1 [get_bd_ports jtag_tck_i] [get_bd_pins carfield_xilinx_ip_0/jtag_tck_i] 13 | connect_bd_net -net jtag_tdi_i_1 [get_bd_ports jtag_tdi_i] [get_bd_pins carfield_xilinx_ip_0/jtag_tdi_i] 14 | connect_bd_net -net jtag_tms_i_1 [get_bd_ports jtag_tms_i] [get_bd_pins carfield_xilinx_ip_0/jtag_tms_i] 15 | -------------------------------------------------------------------------------- /target/xilinx/flavor_bd/scripts/carfield_bd_ext_jtag_vcu128.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2024 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 | # Cyril Koenig 6 | 7 | set jtag_gnd_o [ create_bd_port -dir O jtag_gnd_o ] 8 | set jtag_tck_i [ create_bd_port -dir I jtag_tck_i ] 9 | set jtag_tdi_i [ create_bd_port -dir I jtag_tdi_i ] 10 | set jtag_tdo_o [ create_bd_port -dir O jtag_tdo_o ] 11 | set jtag_tms_i [ create_bd_port -dir I jtag_tms_i ] 12 | set jtag_vdd_o [ create_bd_port -dir O jtag_vdd_o ] 13 | connect_bd_net -net carfield_xilinx_ip_0_jtag_gnd_o [get_bd_ports jtag_gnd_o] [get_bd_pins carfield_xilinx_ip_0/jtag_gnd_o] 14 | connect_bd_net -net carfield_xilinx_ip_0_jtag_vdd_o [get_bd_ports jtag_vdd_o] [get_bd_pins carfield_xilinx_ip_0/jtag_vdd_o] 15 | connect_bd_net -net carfield_xilinx_ip_0_jtag_tdo_o [get_bd_ports jtag_tdo_o] [get_bd_pins carfield_xilinx_ip_0/jtag_tdo_o] 16 | connect_bd_net -net jtag_tck_i_1 [get_bd_ports jtag_tck_i] [get_bd_pins carfield_xilinx_ip_0/jtag_tck_i] 17 | connect_bd_net -net jtag_tdi_i_1 [get_bd_ports jtag_tdi_i] [get_bd_pins carfield_xilinx_ip_0/jtag_tdi_i] 18 | connect_bd_net -net jtag_tms_i_1 [get_bd_ports jtag_tms_i] [get_bd_pins carfield_xilinx_ip_0/jtag_tms_i] 19 | -------------------------------------------------------------------------------- /target/xilinx/flavor_vanilla/.gitignore: -------------------------------------------------------------------------------- 1 | .Xil 2 | carfield.cache 3 | carfield.ip_user_files 4 | carfield.hw 5 | carfield.sim 6 | carfield.srcs 7 | scripts/add_sources.tcl* 8 | scripts/add_includes.tcl 9 | out/ 10 | probes.ltx -------------------------------------------------------------------------------- /target/xilinx/flavor_vanilla/constraints/carfield_top_xilinx.xdc: -------------------------------------------------------------------------------- 1 | # Copyright 2024 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 | # Cyril Koenig 6 | 7 | set SOC_TCK 20 8 | set JTAG_TCK 100.0 9 | set UART_IO_SPEED 200.0 10 | 11 | ################### 12 | # Top level reset # 13 | ################### 14 | 15 | # The output of the top level reset synchronizer 16 | set SOC_RST_SRC [get_pins -filter {DIRECTION == OUT} -leaf -of_objects [get_nets rst_n]] 17 | set_max_delay -through $SOC_RST_SRC $SOC_TCK 18 | set_false_path -hold -through $SOC_RST_SRC 19 | 20 | ########## 21 | # Clocks # 22 | ########## 23 | 24 | # Rtc clock is asynchronous 25 | create_generated_clock -source [get_pins -filter {DIRECTION == OUT} -leaf -of_objects [get_nets clk_10]] -divide_by 10 -name rtc_clk [get_pins rtc_clk_q_reg/Q] 26 | set_clock_groups -asynchronous -group {rtc_clk} 27 | 28 | # System Clock 29 | # [see in $XILINX_BOARD.xdc] 30 | 31 | # JTAG Clock 32 | create_clock -period $JTAG_TCK -name clk_jtag [get_ports jtag_tck_i] 33 | set_input_jitter clk_jtag 1.000 34 | set_clock_groups -name jtag_grp -asynchronous -group {clk_jtag} 35 | 36 | ########## 37 | # BUFG # 38 | ########## 39 | 40 | # JTAG are on non clock capable GPIOs (if not using BSCANE) 41 | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports jtag_tck_i]] 42 | set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports jtag_tck_i]] 43 | 44 | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports cpu_reset]] 45 | set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports cpu_reset]] 46 | 47 | ######## 48 | # JTAG # 49 | ######## 50 | 51 | set_input_delay -min -clock clk_jtag [expr 0.10 * $JTAG_TCK] [get_ports {jtag_tdi_i jtag_tms_i}] 52 | set_input_delay -max -clock clk_jtag [expr 0.20 * $JTAG_TCK] [get_ports {jtag_tdi_i jtag_tms_i}] 53 | 54 | set_output_delay -min -clock clk_jtag [expr 0.10 * $JTAG_TCK] [get_ports jtag_tdo_o] 55 | set_output_delay -max -clock clk_jtag [expr 0.20 * $JTAG_TCK] [get_ports jtag_tdo_o] 56 | 57 | set_max_delay -from [get_ports jtag_trst_ni] $JTAG_TCK 58 | set_false_path -hold -from [get_ports jtag_trst_ni] 59 | 60 | ######## 61 | # UART # 62 | ######## 63 | 64 | set_max_delay [expr $UART_IO_SPEED * 0.35] -from [get_ports uart_rx_i] 65 | set_false_path -hold -from [get_ports uart_rx_i] 66 | 67 | set_max_delay [expr $UART_IO_SPEED * 0.35] -to [get_ports uart_tx_o] 68 | set_false_path -hold -to [get_ports uart_tx_o] 69 | 70 | ######## 71 | # VIOs # 72 | ######## 73 | 74 | set_false_path -through [get_pins -of_object [get_cells -hier -filter {REF_NAME =~ xlnx_vio || ORIG_REF_NAME =~ xlnx_vio}] -filter {NAME =~ *probe*}] 75 | 76 | ################# 77 | # Carfield CDCs # 78 | ################# 79 | 80 | # Hyper 81 | ################### 82 | 83 | # i_hyper_cdc_dst 84 | set_max_delay -datapath \ 85 | -from [get_pins i_hyper_cdc_dst/i_cdc_fifo_gray_*/*reg*/C] \ 86 | -to [get_pins i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/i_spill_register/spill_register_flushable_i/*reg*/D] \ 87 | $SOC_TCK 88 | set_max_delay -datapath \ 89 | -from [get_pins i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/*reg*/C] \ 90 | -to [get_pins i_hyper_cdc_dst/i_cdc_fifo_gray_*/i_spill_register/spill_register_flushable_i/*reg*/D] \ 91 | $SOC_TCK 92 | set_max_delay -datapath \ 93 | -from [get_pins i_hyper_cdc_dst/i_cdc_fifo_gray_*/*reg*/C] \ 94 | -to [get_pins i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/*i_sync/*reg*/D] \ 95 | $SOC_TCK 96 | set_max_delay -datapath \ 97 | -from [get_pins i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/*reg*/C] \ 98 | -to [get_pins i_hyper_cdc_dst/i_cdc_fifo_gray_*/*i_sync/*reg*/D] \ 99 | $SOC_TCK 100 | -------------------------------------------------------------------------------- /target/xilinx/flavor_vanilla/constraints/vcu128_ext_jtag.xdc: -------------------------------------------------------------------------------- 1 | # Copyright 2020 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 | # Cyril Koenig 6 | 7 | set_property PACKAGE_PIN A23 [get_ports jtag_gnd_o] ;# A23 - C15 (FMCP_HSPC_LA10_N) - J1.04 - GND 8 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_gnd_o] ; 9 | 10 | set_property PACKAGE_PIN B23 [get_ports jtag_vdd_o] ;# B23 - C14 (FMCP_HSPC_LA10_P) - J1.02 - VDD 11 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_vdd_o] ; 12 | 13 | set_property PACKAGE_PIN B25 [get_ports jtag_tdo_o] ;# B25 - H17 (FMCP_HSPC_LA11_N) - J1.08 - TDO 14 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tdo_o] 15 | 16 | set_property PACKAGE_PIN B26 [get_ports jtag_tck_i] ;# B26 - H16 (FMCP_HSPC_LA11_P) - J1.06 - TCK 17 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tck_i] ; 18 | 19 | set_property PACKAGE_PIN H22 [get_ports jtag_tms_i] ;# H22 - G16 (FMCP_HSPC_LA12_N) - J1.12 - TNS 20 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tms_i] ; 21 | 22 | set_property PACKAGE_PIN J22 [get_ports jtag_tdi_i] ;# J22 - G15 (FMCP_HSPC_LA12_P) - J1.10 - TDI 23 | set_property IOSTANDARD LVCMOS18 [get_ports jtag_tdi_i] 24 | -------------------------------------------------------------------------------- /target/xilinx/flavor_vanilla/flavor_vanilla.mk: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | # Output bitstream 8 | xilinx_bit_vanilla := $(CAR_XIL_DIR)/flavor_vanilla/out/carfield_top_xilinx.bit 9 | 10 | # This flavor requires pre-compiled Xilinx IPs (which may depend on the board) 11 | xilinx_ips_names_vanilla_vcu128 := xlnx_mig_ddr4 xlnx_clk_wiz xlnx_vio 12 | xilinx_ips_names_vanilla := $(xilinx_ips_names_vanilla_${XILINX_BOARD}) 13 | # Path to compiled ips 14 | xilinx_ips_paths_vanilla = $(foreach ip-name,$(xilinx_ips_names_vanilla),$(xilinx_ip_dir)/$(ip-name)/$(ip-name).srcs/sources_1/ip/$(ip-name)/$(ip-name).xci) 15 | 16 | # Flavor specific bender args 17 | # (added enabled ips in bender args, used by phy_definitions.svh) 18 | xilinx_targs_vanilla = $(xilinx_targs_common) $(foreach ip-name,$(xilinx_ips_names_vanilla),$(addprefix -t ,$(ip-name))) 19 | xilinx_targs_vanilla += -t xilinx_vanilla $(addprefix -t ,$(XILINX_BOARD)) 20 | xilinx_defs_vanilla := $(common_defs) $(xilinx_defs_common) 21 | 22 | # Vivado variables 23 | vivado_env_vanilla := \ 24 | XILINX_PROJECT=$(XILINX_PROJECT) \ 25 | XILINX_BOARD=$(XILINX_BOARD) \ 26 | XILINX_PART=$(xilinx_part) \ 27 | XILINX_BOARD_LONG=$(xilinx_board_long) \ 28 | XILINX_PORT=$(XILINX_PORT) \ 29 | XILINX_HOST=$(XILINX_HOST) \ 30 | XILINX_FPGA_PATH=$(XILINX_FPGA_PATH) \ 31 | XILINX_BIT=$(xilinx_bit) \ 32 | XILINX_IP_PATHS="$(xilinx_ips_paths_vanilla)" \ 33 | ROUTED_DCP=$(ROUTED_DCP) \ 34 | XILINX_CHECK_TIMING=$(XILINX_CHECK_TIMING) \ 35 | XILINX_ELABORATION_ONLY=$(XILINX_ELABORATION_ONLY) 36 | 37 | # Generate bender scripts (! attention ! modified on the fly) 38 | $(CAR_XIL_DIR)/flavor_vanilla/scripts/add_sources.tcl: Bender.yml 39 | $(BENDER) script vivado $(common_targs) $(xilinx_targs_vanilla) $(common_defs) $(xilinx_defs_vanilla) > $@.bak 40 | # Remove ibex's vendored prim includes as they conflict with opentitan's vendored prim includes 41 | grep -v -P "lowrisc_ip/ip/prim/rtl" $@.bak > $@ 42 | # Override system verilog files 43 | $(CAR_XIL_DIR)/scripts/overrides.sh $@ 44 | echo "" >> $@ 45 | 46 | 47 | # Compile bitstream 48 | $(CAR_XIL_DIR)/flavor_vanilla/out/%.bit: $(xilinx_ips_paths_vanilla) $(CAR_XIL_DIR)/flavor_vanilla/scripts/add_sources.tcl 49 | @if [ "$(GEN_NO_HYPERBUS)" != "1" ] && [ "$(XILINX_ELABORATION_ONLY)" != "1" ]; then echo "Support for the Hyperbus FMC card is not yet available."; fi; 50 | @mkdir -p $(CAR_XIL_DIR)/flavor_vanilla/out 51 | cd $(CAR_XIL_DIR)/flavor_vanilla && $(vivado_env) $(VIVADO) $(VIVADO_FLAGS) -source scripts/run.tcl 52 | find $(CAR_XIL_DIR)/flavor_vanilla/carfield* -name "*.ltx" -o -name "*.bit" -o -name "*routed.rpt" | xargs -I {} cp {} $(CAR_XIL_DIR)/flavor_vanilla/out 53 | .PRECIOUS: $(CAR_XIL_DIR)/flavor_vanilla/out/%.bit 54 | 55 | car-xil-clean-vanilla: 56 | cd $(CAR_XIL_DIR)/flavor_vanilla && rm -rf scripts/add_sources.tcl* *.log *.jou *.str *.mif carfield.* .Xil/ 57 | 58 | .PHONY: car-xil-clean-vanilla 59 | -------------------------------------------------------------------------------- /target/xilinx/flavor_vanilla/src/fan_ctrl.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | // Author: Florian Zaruba, zarubaf@iis.ee.ethz.ch 6 | // Description: PWM Fan Control for Genesys II board 7 | 8 | module fan_ctrl ( 9 | input logic clk_i, 10 | input logic rst_ni, 11 | input logic [3:0] pwm_setting_i, 12 | output logic fan_pwm_o 13 | ); 14 | logic [3:0] ms_clock_d, ms_clock_q; 15 | logic [11:0] cycle_counter_d, cycle_counter_q; 16 | 17 | // clock divider 18 | always_comb begin 19 | cycle_counter_d = cycle_counter_q + 1; 20 | ms_clock_d = ms_clock_q; 21 | 22 | // divide clock by 49 23 | // At 50 MHz input clock this results in a 62.5 kHz 24 | // PWM Signal 25 | if (cycle_counter_q == 49) begin 26 | cycle_counter_d = 0; 27 | ms_clock_d = ms_clock_q + 1; 28 | end 29 | 30 | if (ms_clock_q == 15) begin 31 | ms_clock_d = 0; 32 | end 33 | end 34 | 35 | // duty cycle 36 | always_comb begin 37 | if (ms_clock_q < pwm_setting_i) begin 38 | fan_pwm_o = 1'b1; 39 | end else begin 40 | fan_pwm_o = 1'b0; 41 | end 42 | end 43 | 44 | always_ff @(posedge clk_i or negedge rst_ni) begin 45 | if (~rst_ni) begin 46 | ms_clock_q <= '0; 47 | cycle_counter_q <= '0; 48 | end else begin 49 | ms_clock_q <= ms_clock_d; 50 | cycle_counter_q <= cycle_counter_d; 51 | end 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /target/xilinx/flavor_vanilla/src/phy_definitions.svh: -------------------------------------------------------------------------------- 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 | // Cyril Koenig 6 | 7 | `ifdef TARGET_VCU128 8 | `define USE_RESET 9 | `ifdef GEN_EXT_JTAG 10 | `define USE_JTAG 11 | `define USE_JTAG_VDDGND 12 | `endif 13 | `define USE_QSPI 14 | `define USE_STARTUPE3 15 | `define USE_VIO 16 | `define HypNumChips 1 17 | `define HypNumPhys 1 18 | `ifdef GEN_NO_HYPERBUS 19 | `define USE_DDR4 20 | `endif 21 | `endif 22 | 23 | ///////////////////// 24 | // DRAM INTERFACES // 25 | ///////////////////// 26 | 27 | `ifdef USE_DDR4 28 | `define USE_DDR 29 | `endif 30 | `ifdef USE_DDR3 31 | `define USE_DDR 32 | `endif 33 | 34 | `define DDR4_INTF \ 35 | /* DDR4 intf */ \ 36 | output c0_ddr4_reset_n, \ 37 | output [0:0] c0_ddr4_ck_t, \ 38 | output [0:0] c0_ddr4_ck_c, \ 39 | output c0_ddr4_act_n, \ 40 | output [16:0] c0_ddr4_adr, \ 41 | output [1:0] c0_ddr4_ba, \ 42 | output [0:0] c0_ddr4_bg, \ 43 | output [0:0] c0_ddr4_cke, \ 44 | output [0:0] c0_ddr4_odt, \ 45 | `ifdef TARGET_VCU128 \ 46 | output [1:0] c0_ddr4_cs_n, \ 47 | inout [8:0] c0_ddr4_dm_dbi_n, \ 48 | inout [71:0] c0_ddr4_dq, \ 49 | inout [8:0] c0_ddr4_dqs_c, \ 50 | inout [8:0] c0_ddr4_dqs_t, \ 51 | `endif \ 52 | `ifdef TARGET_ZCU102 \ 53 | output [0:0] c0_ddr4_cs_n, \ 54 | inout [1:0] c0_ddr4_dm_dbi_n, \ 55 | inout [15:0] c0_ddr4_dq, \ 56 | inout [1:0] c0_ddr4_dqs_c, \ 57 | inout [1:0] c0_ddr4_dqs_t, \ 58 | `endif 59 | 60 | `define DDR3_INTF \ 61 | output ddr3_ck_p, \ 62 | output ddr3_ck_n, \ 63 | inout [31:0] ddr3_dq, \ 64 | inout [3:0] ddr3_dqs_n, \ 65 | inout [3:0] ddr3_dqs_p, \ 66 | output [14:0] ddr3_addr, \ 67 | output [2:0] ddr3_ba, \ 68 | output ddr3_ras_n, \ 69 | output ddr3_cas_n, \ 70 | output ddr3_we_n, \ 71 | output ddr3_reset_n, \ 72 | output [0:0] ddr3_cke, \ 73 | output [0:0] ddr3_cs_n, \ 74 | output [3:0] ddr3_dm, \ 75 | output [0:0] ddr3_odt, 76 | 77 | `define ila(__name, __signal) \ 78 | (* dont_touch = "yes" *) (* mark_debug = "true" *) logic [$bits(__signal)-1:0] __name; \ 79 | assign __name = __signal; 80 | -------------------------------------------------------------------------------- /target/xilinx/scripts/flash_spi.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2024 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 | # Nils Wistoff 6 | # Noah Huetter 7 | 8 | open_hw_manager 9 | 10 | connect_hw_server -url $::env(XILINX_HOST):$::env(XILINX_PORT) 11 | open_hw_target [get_hw_targets $::env(XILINX_FPGA_PATH)] 12 | 13 | set file $::env(FILE) 14 | set offset $::env(OFFSET) 15 | set mcs_file image.mcs 16 | 17 | if {$::env(XILINX_BOARD) eq "vcu118"} { 18 | set hw_device [get_hw_devices xcvu9p_0] 19 | set hw_mem_device [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0] 20 | } 21 | 22 | if {$::env(XILINX_BOARD) eq "vcu128"} { 23 | set hw_device [get_hw_devices xcvu37p_0] 24 | set hw_mem_device [lindex [get_cfgmem_parts {mt25qu02g-spi-x1_x2_x4}] 0] 25 | } 26 | 27 | write_cfgmem -force -format mcs -size 256 -interface SPIx4 \ 28 | -loaddata "up $offset $file" \ 29 | -checksum \ 30 | -file $mcs_file 31 | 32 | set_property PARAM.FREQUENCY 15000000 [get_hw_targets *] 33 | 34 | create_hw_cfgmem -hw_device $hw_device $hw_mem_device 35 | set hw_cfgmem [get_property PROGRAM.HW_CFGMEM $hw_device] 36 | set_property PROGRAM.FILES [list $mcs_file ] $hw_cfgmem 37 | set_property PROGRAM.ADDRESS_RANGE {use_file} $hw_cfgmem 38 | set_property PROGRAM.PRM_FILE {} $hw_cfgmem 39 | set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} $hw_cfgmem 40 | set_property PROGRAM.BLANK_CHECK 0 $hw_cfgmem 41 | set_property PROGRAM.ERASE 1 $hw_cfgmem 42 | set_property PROGRAM.CFG_PROGRAM 1 $hw_cfgmem 43 | set_property PROGRAM.VERIFY 1 $hw_cfgmem 44 | set_property PROGRAM.CHECKSUM 0 $hw_cfgmem 45 | 46 | # Create bitstream to access SPI flash 47 | create_hw_bitstream -hw_device $hw_device [get_property PROGRAM.HW_CFGMEM_BITFILE $hw_device]; 48 | program_hw_devices $hw_device; 49 | refresh_hw_device $hw_device; 50 | 51 | # Program SPI flash 52 | program_hw_cfgmem -hw_cfgmem $hw_cfgmem 53 | -------------------------------------------------------------------------------- /target/xilinx/scripts/overrides.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2023 ETH Zurich and University of Bologna. 3 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | # Cyril Koenig 7 | # 8 | # Replace files in a bender script with override version 9 | 10 | SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" 11 | 12 | for f in `find $SCRIPT_DIR/../src/overrides -not -type d -printf "%f\n"`; do 13 | echo "Removing $f $1.tmp" 14 | grep -v -P "(? $1.tmp 15 | mv $1.tmp $1 16 | done 17 | 18 | 19 | #for f in `find $SCRIPT_DIR/../src/overrides -not -type d -printf "%f\n"`; do 20 | # echo "Removing $f $1.tmp" 21 | # grep -v -P "(? $1.tmp 22 | # diff $1.tmp $@ | grep ">\|<" 23 | # mv $1.tmp $1 24 | #done 25 | -------------------------------------------------------------------------------- /target/xilinx/scripts/program.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2018 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 | # Author: Florian Zaruba 6 | 7 | puts $::env(XILINX_BIT) 8 | 9 | open_hw_manager 10 | 11 | connect_hw_server -url $::env(XILINX_HOST):$::env(XILINX_PORT) 12 | open_hw_target [get_hw_targets $::env(XILINX_FPGA_PATH)] 13 | 14 | if {$::env(XILINX_BOARD) eq "genesys2"} { 15 | set hw_device [get_hw_devices xc7k325t_0] 16 | } 17 | if {$::env(XILINX_BOARD) eq "vcu118"} { 18 | set hw_device [get_hw_devices xcvu9p_0] 19 | } 20 | if {$::env(XILINX_BOARD) eq "vcu128"} { 21 | set hw_device [get_hw_devices xcvu37p_0] 22 | } 23 | 24 | set_property PARAM.FREQUENCY 15000000 [get_hw_targets *] 25 | 26 | current_hw_device $hw_device 27 | set_property PROGRAM.FILE $::env(XILINX_BIT) $hw_device 28 | 29 | set xilinx_ltx [file rootname $::env(XILINX_BIT)].ltx 30 | set_property PROBES.FILE $xilinx_ltx $hw_device 31 | set_property FULL_PROBES.FILE $xilinx_ltx $hw_device 32 | 33 | program_hw_devices $hw_device 34 | refresh_hw_device [lindex $hw_device 0] 35 | 36 | # Force reset 37 | get_hw_vios * 38 | set_property OUTPUT_VALUE 1 [get_hw_probes [list *aux_reset* probe_out0 *probe_out2_1] -of_objects [get_hw_vios *]] 39 | commit_hw_vio [get_hw_vios *] 40 | set_property OUTPUT_VALUE 0 [get_hw_probes [list *aux_reset* probe_out0 *probe_out2_1] -of_objects [get_hw_vios *]] 41 | commit_hw_vio [get_hw_vios *] 42 | -------------------------------------------------------------------------------- /target/xilinx/scripts/write_cfgmem.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2018 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 | # Author: Florian Zaruba 6 | # Description: Generate a memory configuration file from a bitstream (Genesys II only right now) 7 | 8 | if {$argc < 2 || $argc > 4} { 9 | puts $argc 10 | puts {Error: Invalid number of arguments} 11 | puts {Usage: write_cfgmem.tcl mcsfile bitfile [datafile]} 12 | exit 1 13 | } 14 | 15 | lassign $argv mcsfile bitfile 16 | 17 | # https://scholar.princeton.edu/jbalkind/blog/programming-genesys-2-qspi-spi-x4-flash 18 | # https://scholar.princeton.edu/jbalkind/blog/programming-vc707-virtex-7-bpi-flash 19 | if {$::env(BOARD) eq "genesys2"} { 20 | #write_cfgmem -format mcs -interface SPIx4 -size 256 -loadbit "up 0x0 $bitfile" -file $mcsfile -force 21 | write_cfgmem -format mcs -interface SPIx1 -size 256 -loadbit "up 0x0 $bitfile" -file $mcsfile -force 22 | } elseif {$::env(BOARD) eq "vc707"} { 23 | write_cfgmem -format mcs -interface bpix16 -size 128 -loadbit "up 0x0 $bitfile" -file $mcsfile -force 24 | } elseif {$::env(BOARD) eq "kc705"} { 25 | write_cfgmem -format mcs -interface SPIx4 -size 128 -loadbit "up 0x0 $bitfile" -file $mcsfile -force 26 | } else { 27 | exit 1 28 | } 29 | -------------------------------------------------------------------------------- /target/xilinx/src/overrides/tc_clk_xilinx.sv: -------------------------------------------------------------------------------- 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 | // Cells to be used for Xilinx FPGA mappings 6 | 7 | module tc_clk_and2 ( 8 | input logic clk0_i, 9 | input logic clk1_i, 10 | output logic clk_o 11 | ); 12 | 13 | assign clk_o = clk0_i & clk1_i; 14 | 15 | endmodule 16 | 17 | module tc_clk_buffer ( 18 | input logic clk_i, 19 | output logic clk_o 20 | ); 21 | 22 | assign clk_o = clk_i; 23 | 24 | endmodule 25 | 26 | // Disable clock gating on FPGA as it behaves differently than expected 27 | module tc_clk_gating #( 28 | /// This paramaeter is a hint for tool/technology specific mappings of this 29 | /// tech_cell. It indicates wether this particular clk gate instance is 30 | /// required for functional correctness or just instantiated for power 31 | /// savings. If IS_FUNCTIONAL == 0, technology specific mappings might 32 | /// replace this cell with a feedthrough connection without any gating. 33 | parameter bit IS_FUNCTIONAL = 1'b1 34 | )( 35 | input logic clk_i, 36 | input logic en_i, 37 | input logic test_en_i, 38 | output logic clk_o 39 | ); 40 | 41 | assign clk_o = clk_i; 42 | 43 | endmodule 44 | 45 | module tc_clk_inverter ( 46 | input logic clk_i, 47 | output logic clk_o 48 | ); 49 | 50 | assign clk_o = ~clk_i; 51 | 52 | endmodule 53 | 54 | module tc_clk_mux2 ( 55 | input logic clk0_i, 56 | input logic clk1_i, 57 | input logic clk_sel_i, 58 | output logic clk_o 59 | ); 60 | 61 | assign clk_o = clk_sel_i ? clk1_i : clk0_i; 62 | 63 | endmodule 64 | 65 | module tc_clk_xor2 ( 66 | input logic clk0_i, 67 | input logic clk1_i, 68 | output logic clk_o 69 | ); 70 | 71 | assign clk_o = clk0_i ^ clk1_i; 72 | 73 | endmodule 74 | 75 | module tc_clk_or2 ( 76 | input logic clk0_i, 77 | input logic clk1_i, 78 | output logic clk_o 79 | ); 80 | 81 | assign clk_o = clk0_i | clk1_i; 82 | 83 | endmodule 84 | 85 | 86 | -------------------------------------------------------------------------------- /target/xilinx/xilinx.mk: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | ## @section Carfield emulation 8 | 9 | # 10 | # Makefile variables (user inputs are in capital letters) 11 | # 12 | 13 | VIVADO ?= vitis-2020.2 vivado 14 | 15 | XILINX_PROJECT ?= carfield 16 | # XILINX_FLAVOR in {vanilla,bd} see carfield_bd.mk 17 | XILINX_FLAVOR ?= bd 18 | # Board in {vcu128, vcu118} 19 | XILINX_BOARD ?= vcu128 20 | 21 | XILINX_PORT ?= 3121 22 | XILINX_FPGA_PATH ?= xilinx_tcf/Xilinx/* 23 | XILINX_HOST ?= localhost 24 | XILINX_BOOT_ETH ?= 0 25 | 26 | ifeq ($(XILINX_BOARD),vcu128) 27 | xilinx_part := xcvu37p-fsvh2892-2L-e 28 | xilinx_board_long := xilinx.com:vcu128:part0:1.0 29 | endif 30 | 31 | ifeq ($(XILINX_BOARD),vcu118) 32 | xilinx_part := xcvu9p-flga2104-2L-e 33 | xilinx_board_long := xilinx.com:vcu118:part0:2.4 34 | endif 35 | 36 | XILINX_USE_ARTIFACTS ?= 0 37 | XILINX_ARTIFACTS_ROOT ?= 38 | XILINX_ELABORATION_ONLY ?= 0 39 | XILINX_CHECK_TIMING ?= 0 40 | 41 | VIVADO_MODE ?= batch 42 | VIVADO_FLAGS ?= -nojournal -mode $(VIVADO_MODE) 43 | 44 | xilinx_ip_dir := $(CAR_XIL_DIR)/xilinx_ips 45 | xilinx_bit := $(CAR_XIL_DIR)/out/$(XILINX_PROJECT)_$(XILINX_FLAVOR)_$(XILINX_BOARD)_$(CARFIELD_CONFIG).bit 46 | 47 | # 48 | # Include other makefiles flavors 49 | # 50 | 51 | include $(CAR_XIL_DIR)/flavor_vanilla/flavor_vanilla.mk 52 | include $(CAR_XIL_DIR)/flavor_bd/flavor_bd.mk 53 | 54 | # 55 | # Flavor dependant variables 56 | # 57 | 58 | vivado_env := $(vivado_env_$(XILINX_FLAVOR)) 59 | xilinx_targs := $(xilinx_targs_$(XILINX_FLAVOR)) 60 | xilinx_defs := $(xilinx_defs_$(XILINX_FLAVOR)) 61 | 62 | # 63 | # IPs compile rules 64 | # 65 | 66 | # Note: at the moment xilinx_ips uses vivado_env defined above, 67 | # but it could re-define its own vivado_env and xilinx_targs 68 | include $(CAR_XIL_DIR)/xilinx_ips/xilinx_ips.mk 69 | 70 | # 71 | # Top level compile rules 72 | # 73 | 74 | # Copy bitstream and probe file to final output location (/target/xilinx/out) 75 | $(CAR_XIL_DIR)/out/%.bit: $(xilinx_bit_$(XILINX_FLAVOR)) 76 | mkdir -p $(CAR_XIL_DIR)/out/ 77 | if [ "$(XILINX_ELABORATION_ONLY)" -eq "0" ]; then \ 78 | cp $< $@; \ 79 | cp $(patsubst %.bit,%.ltx,$< $@); \ 80 | fi 81 | 82 | ## Build bitstream for Carfield 83 | ## @param XILINX_PROJECT The name of the Xilinx project 84 | ## @param XILINX_FLAVOR= The flavor of the implementation 85 | ## @param XILINX_BOARD The target Xilinx board 86 | ## @param CARFIELD_CONFIG The SoC configuration to be used 87 | car-xil-all: $(xilinx_bit) 88 | 89 | ## Program last bitstream for Carfield 90 | ## @param VIVADO The Vivado version in use 91 | ## @param XILINX_BOARD The target Xilinx board to be programmed 92 | ## @param VIVADO_FLAGS Some flags for Vivado, such as batch or gui mode 93 | car-xil-program: 94 | @echo "Programming board $(XILINX_BOARD) ($(xilinx_part))" 95 | $(vivado_env) $(VIVADO) $(VIVADO_FLAGS) -source $(CAR_XIL_DIR)/scripts/program.tcl 96 | 97 | ## Flash Linux image on Cheshire 98 | ## @param VIVADO The Vivado version in use 99 | ## @param XILINX_BOARD The target Xilinx board to be programmed 100 | ## @param XILINX_FLAVOR= The flavor of the implementation. 101 | ## @param VIVADO_FLAGS Some flags for Vivado, such as batch or gui mode 102 | car-xil-flash: $(CAR_SW_DIR)/boot/linux_carfield_$(XILINX_FLAVOR)_$(XILINX_BOARD).gpt.bin 103 | $(vivado_env) FILE=$< OFFSET=0 $(VIVADO) $(VIVADO_FLAGS) -source $(CAR_XIL_DIR)/scripts/flash_spi.tcl 104 | 105 | ## Clean Xilinx artifacts for all implementations 106 | car-xil-clean: car-xil-clean-vanilla car-xil-clean-bd xilinx-ip-clean-all 107 | 108 | .PHONY: car-xil-program car-xil-flash car-xil-clean car-xil-all 109 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/.gitignore: -------------------------------------------------------------------------------- 1 | *.cache 2 | *.gen 3 | *.hw 4 | *.srcs 5 | *.xpr 6 | component.xml 7 | xgui 8 | *.jou 9 | *.log 10 | add_sources.* -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/carfield_ip/carfield_ip.mk: -------------------------------------------------------------------------------- 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 | ROOT_carfield_ip := $(CAR_XIL_DIR)/xilinx_ips/carfield_ip 6 | XILINX_USE_ARTIFACTS_carfield_ip := 0 7 | 8 | # Add additional requirements for this ip 9 | IP_DEP_carfield_ip := $(CAR_XIL_DIR)/xilinx_ips/carfield_ip/tcl/add_sources.tcl 10 | 11 | # Generate the bender script for the ip 12 | $(CAR_XIL_DIR)/xilinx_ips/carfield_ip/tcl/add_sources.tcl: Bender.yml 13 | # Add source files for ip 14 | $(BENDER) script vivado $(xilinx_targs) $(common_defs) $(xilinx_defs_bd) > $@ 15 | mv $@ $@.bak 16 | # Remove ibex's vendored prim includes as they conflict with opentitan's vendored prim includes 17 | grep -v -P "lowrisc_ip/ip/prim/rtl" $@.bak > $@ 18 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/carfield_ip/constraints/carfield_xilinx_ip.xdc: -------------------------------------------------------------------------------- 1 | # Copyright 2024 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 | # Cyril Koenig 6 | 7 | set SOC_TCK 20 8 | set JTAG_TCK 100.0 9 | set UART_IO_SPEED 200.0 10 | 11 | ################### 12 | # Global Settings # 13 | ################### 14 | 15 | # The output of the reset synchronizer 16 | set_false_path -from [get_ports cpu_reset*] 17 | 18 | ########## 19 | # Clocks # 20 | ########## 21 | 22 | # Rtc clock is asynchronous 23 | create_generated_clock -source [get_ports clk_10] -divide_by 10 -name rtc_clk [get_pins i_carfield_xilinx/rtc_clk_q_reg/Q] 24 | set_clock_groups -asynchronous -group {rtc_clk} 25 | set_max_delay -from [get_pin i_carfield_xilinx/rtc_clk_q_reg/Q] $SOC_TCK 26 | 27 | # System Clock 28 | # [see in board.xdc] 29 | 30 | # JTAG Clock 31 | create_clock -period $JTAG_TCK -name clk_jtag [get_ports jtag_tck_i] 32 | set_clock_groups -name jtag_grp -asynchronous -group {clk_jtag} 33 | 34 | ########## 35 | # BUFG # 36 | ########## 37 | 38 | # JTAG are on non clock capable GPIOs (if not using BSCANE) 39 | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports jtag_tck_i]] 40 | set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports jtag_tck_i]] 41 | 42 | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports cpu_reset]] 43 | set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports cpu_reset]] 44 | 45 | set all_in_mux [get_nets -of [ get_pins -filter { DIRECTION == IN } -of [get_cells -hier -filter { ORIG_REF_NAME == tc_clk_mux2 || REF_NAME == tc_clk_mux2 }]]] 46 | set_property CLOCK_DEDICATED_ROUTE FALSE $all_in_mux 47 | set_property CLOCK_BUFFER_TYPE NONE $all_in_mux 48 | 49 | ################# 50 | # Carfield CDCs # 51 | ################# 52 | 53 | # Hyper 54 | ################ 55 | 56 | #i_hyper_cdc_dst 57 | set_max_delay -datapath \ 58 | -from [get_pins i_carfield_xilinx/i_hyper_cdc_dst/i_cdc_fifo_gray_*/*reg*/C] \ 59 | -to [get_pins i_carfield_xilinx/i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/i_spill_register/spill_register_flushable_i/*reg*/D] \ 60 | $SOC_TCK 61 | set_max_delay -datapath \ 62 | -from [get_pins i_carfield_xilinx/i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/*reg*/C] \ 63 | -to [get_pins i_carfield_xilinx/i_hyper_cdc_dst/i_cdc_fifo_gray_*/i_spill_register/spill_register_flushable_i/*reg*/D] \ 64 | $SOC_TCK 65 | set_max_delay -datapath \ 66 | -from [get_pins i_carfield_xilinx/i_hyper_cdc_dst/i_cdc_fifo_gray_*/*reg*/C] \ 67 | -to [get_pins i_carfield_xilinx/i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/*i_sync/*reg*/D] \ 68 | $SOC_TCK 69 | set_max_delay -datapath \ 70 | -from [get_pins i_carfield_xilinx/i_carfield/i_cheshire_wrap/i_cheshire_ext_llc_cdc_src/i_cdc_fifo_gray_*/*reg*/C] \ 71 | -to [get_pins i_carfield_xilinx/i_hyper_cdc_dst/i_cdc_fifo_gray_*/*i_sync/*reg*/D] \ 72 | $SOC_TCK 73 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/carfield_ip/constraints/ooc_carfield_ip.xdc: -------------------------------------------------------------------------------- 1 | create_clock -name carfield_ooc_synth_clk_100 -period 100 [get_ports clk_100] 2 | create_clock -name carfield_ooc_synth_clk_50 -period 50 [get_ports clk_50] 3 | create_clock -name carfield_ooc_synth_clk_20 -period 20 [get_ports clk_20] 4 | create_clock -name carfield_ooc_synth_clk_10 -period 10 [get_ports clk_10] 5 | set_case_analysis 0 [get_ports testmode_i] 6 | 7 | set_clock_groups -name async_clks -asynchronous \ 8 | -group [get_clocks -include_generated_clocks carfield_ooc_synth_clk_100] \ 9 | -group [get_clocks -include_generated_clocks carfield_ooc_synth_clk_50] \ 10 | -group [get_clocks -include_generated_clocks carfield_ooc_synth_clk_20] \ 11 | -group [get_clocks -include_generated_clocks carfield_ooc_synth_clk_10] 12 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/carfield_ip/tcl/run.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2020 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 | # Cyril Koenig 6 | 7 | # Create project 8 | set project carfield_ip 9 | 10 | create_project $project . -force -part $::env(XILINX_PART) 11 | set_property XPM_LIBRARIES XPM_MEMORY [current_project] 12 | 13 | # set number of threads to 8 (maximum, unfortunately) 14 | set_param general.maxThreads 8 15 | 16 | # Define sources 17 | source tcl/add_sources.tcl 18 | 19 | # Add constraints 20 | add_files -fileset constrs_1 constraints/ooc_carfield_ip.xdc 21 | set_property USED_IN {synthesis out_of_context} [get_files ooc_carfield_ip.xdc] 22 | import_files -fileset constrs_1 -norecurse constraints/carfield_xilinx_ip.xdc 23 | # General constraints 24 | import_files -fileset constrs_1 -norecurse ../../constraints/carfield.xdc 25 | set_property SCOPED_TO_REF carfield [get_files carfield.xdc] 26 | set_property processing_order LATE [get_files carfield.xdc] 27 | 28 | # Package IP 29 | set_property top carfield_xilinx_ip [current_fileset] 30 | 31 | # Attention SFCU is only used because of Carfield's structure 32 | update_compile_order -fileset sources_1 33 | synth_design -rtl -name rtl_1 -sfcu 34 | 35 | ipx::package_project -root_dir . -vendor ethz.ch -library user -taxonomy /UserIP -set_current false 36 | 37 | # If we don't reopen project, Vivado does not find the newly created ip_repo 38 | close_project 39 | open_project $project.xpr 40 | # Export this IP as a .xci too for coherence with Xilinx IPs 41 | set_property ip_repo_paths . [current_project] 42 | create_ip -verbose -module_name $project -vlnv ethz.ch:user:carfield_xilinx_ip 43 | 44 | exit 45 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/xilinx_ips.mk: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | # List available IPs 8 | xilinx_available_ips = xlnx_clk_wiz xlnx_mig_ddr4 xlnx_vio carfield_ip 9 | 10 | # Include IP and add top level building rule (%.xci) and enable artifacts management 11 | define xlnx_ips_vars_and_deps = 12 | include $(CAR_XIL_DIR)/xilinx_ips/$(1)/$(1).mk 13 | ARTIFACTS_PATHS_$(1) := $$(addprefix $$(ROOT_$(1))/, $$(ARTIFACTS_FILES_$(1))) 14 | ARTIFACTS_VALS_$(1) := $$(foreach var, $$(ARTIFACTS_VARS_$(1)), $$(var)=$$($$(var))) 15 | 16 | ifeq ($(XILINX_USE_ARTIFACTS)$$(XILINX_USE_ARTIFACTS_$(1)),11) 17 | $(CAR_XIL_DIR)/xilinx_ips/$(1)/%.xci: xilinx-ip-load-artifacts-$(1) $$(IP_DEP_$(1)) $(CAR_XIL_DIR)/xilinx_ips/$(1)/$(1).xpr xilinx-ip-save-artifacts-$(1) 18 | else 19 | $(CAR_XIL_DIR)/xilinx_ips/$(1)/%.xci: $$(IP_DEP_$(1)) $(CAR_XIL_DIR)/xilinx_ips/$(1)/$(1).xpr 20 | endif 21 | @echo "IP $(1) : Done" 22 | 23 | $(CAR_XIL_DIR)/xilinx_ips/$(1)/$(1).xpr: 24 | cd $$(ROOT_$(1)) && $(vivado_env) $(VIVADO) -mode batch -source tcl/run.tcl 25 | 26 | .PRECIOUS: $(CAR_XIL_DIR)/xilinx_ips/$(1)/$(1).xpr $(CAR_XIL_DIR)/xilinx_ips/$(1)/%.xci 27 | endef 28 | 29 | # Call xlnx_ips_vars_and_deps 30 | $(foreach ip, $(xilinx_available_ips), $(eval $(call xlnx_ips_vars_and_deps,$(ip)))) 31 | 32 | # Define inputs used to differentiate artifacts 33 | $(CAR_XIL_DIR)/xilinx_ips/%/.generated_env: 34 | echo $(VIVADO) $(XILINX_PROJECT) > $@ 35 | echo $(ARTIFACTS_VALS_$*) >> $@ 36 | echo $(ARTIFACTS_FILES_$*) >> $@ 37 | sha256sum $(ARTIFACTS_PATHS_$*) | awk '{print $$1}' >> $@ 38 | 39 | # Define artifact hash 40 | $(CAR_XIL_DIR)/xilinx_ips/%/.generated_sha256: $(CAR_XIL_DIR)/xilinx_ips/%/.generated_env 41 | sha256sum $< | awk '{print $$1}' > $@ 42 | 43 | # Phonies can not use wildcards 44 | define xlnx_ips_phonies = 45 | # Load artifact based on hash 46 | xilinx-ip-load-artifacts-$(1): $(CAR_XIL_DIR)/xilinx_ips/$(1)/.generated_sha256 47 | @if [ -z "$(XILINX_ARTIFACTS_ROOT)" ]; then \ 48 | echo "Error: XILINX_ARTIFACTS_ROOT missing"; \ 49 | exit 1; \ 50 | fi 51 | @if [ -d "$(XILINX_ARTIFACTS_ROOT)/`cat $$<`" ]; then \ 52 | echo -e $(TERM_GREEN)"Fetching $(1) from $(XILINX_ARTIFACTS_ROOT)/`cat $$<`"$(TERM_NC); \ 53 | cp -r $(XILINX_ARTIFACTS_ROOT)/`cat $$<`/* $(ROOT_$(1)); \ 54 | else \ 55 | echo -e "$(1) not found in $(XILINX_ARTIFACTS_ROOT)/`cat $$<`"; \ 56 | fi 57 | 58 | # Save artifact based on hash 59 | xilinx-ip-save-artifacts-$(1): $(CAR_XIL_DIR)/xilinx_ips/$(1)/.generated_sha256 $(CAR_XIL_DIR)/xilinx_ips/$(1)/$(1).xpr 60 | @if [ ! -d "$(XILINX_ARTIFACTS_ROOT)/`cat $$<`" ]; then \ 61 | cp -r $(ROOT_$(1)) $(XILINX_ARTIFACTS_ROOT)/`cat $$<`; \ 62 | chmod -R g+rw $(XILINX_ARTIFACTS_ROOT)/`cat $$<`; \ 63 | fi 64 | 65 | # Delete all the project.* generated folders 66 | xilinx-ip-clean-$(1): 67 | @if [ -z "$$(ROOT_$(1))" ]; then echo "Error: Cannot find ROOT_$(1)" exit 1; fi; 68 | find $$(ROOT_$(1)) -mindepth 1 -type d -name "$(1).*" -exec rm -r {} + 69 | cd $$(ROOT_$(1)) && rm -rf $(1) .generated_env .generated_sha256 vivado* .Xil *.xpr tcl/add_sources* xgui component.xml 70 | .PHONY: xilinx-ip-load-artifacts-$(1) xilinx-ip-save-artifacts-$(1) xilinx-ip-clean-$(1) 71 | endef 72 | 73 | # Call xlnx_ips_phonies 74 | $(foreach ip, $(xilinx_available_ips), $(eval $(call xlnx_ips_phonies,$(ip)))) 75 | 76 | xilinx-ip-clean-all: $(addprefix xilinx-ip-clean-,$(xilinx_available_ips)) 77 | 78 | # Note: We do not PHONY the three rules above for lisibility since 79 | # PHONY rules cannot use wildcards... but these files won't exist anyways 80 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/xlnx_clk_wiz/xlnx_clk_wiz.mk: -------------------------------------------------------------------------------- 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 | ROOT_xlnx_clk_wiz := $(CAR_XIL_DIR)/xilinx_ips/xlnx_clk_wiz 6 | ARTIFACTS_FILES_xlnx_clk_wiz := xlnx_clk_wiz.mk tcl/run.tcl 7 | ARTIFACTS_VARS_xlnx_clk_wiz := xilinx_part XILINX_BOARD xilinx_board_long 8 | XILINX_USE_ARTIFACTS_xlnx_clk_wiz := 1 9 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/xlnx_mig_ddr4/tcl/run.tcl: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | set partNumber $::env(XILINX_PART) 8 | set boardName $::env(XILINX_BOARD_LONG) 9 | 10 | set ipName xlnx_mig_ddr4 11 | 12 | create_project $ipName . -force -part $partNumber 13 | set_property board_part $boardName [current_project] 14 | 15 | create_ip -name ddr4 -vendor xilinx.com -library ip -version 2.2 -module_name $ipName 16 | 17 | 18 | if {$::env(XILINX_BOARD) eq "vcu128"} { 19 | set_property -dict [list CONFIG.C0.DDR4_Clamshell {true} \ 20 | CONFIG.C0_DDR4_BOARD_INTERFACE {ddr4_sdram} \ 21 | CONFIG.System_Clock {No_Buffer} \ 22 | CONFIG.Reference_Clock {No_Buffer} \ 23 | CONFIG.C0.DDR4_InputClockPeriod {10000} \ 24 | CONFIG.C0.DDR4_CLKOUT0_DIVIDE {3} \ 25 | CONFIG.C0.DDR4_MemoryPart {MT40A512M16HA-075E} \ 26 | CONFIG.C0.DDR4_DataWidth {72} \ 27 | CONFIG.C0.DDR4_DataMask {NO_DM_NO_DBI} \ 28 | CONFIG.C0.DDR4_Ecc {true} \ 29 | CONFIG.C0.DDR4_AxiDataWidth {512} \ 30 | CONFIG.C0.DDR4_AxiAddressWidth {32} \ 31 | CONFIG.C0.DDR4_AxiIDWidth {8} \ 32 | CONFIG.ADDN_UI_CLKOUT1_FREQ_HZ {100} \ 33 | CONFIG.C0.BANK_GROUP_WIDTH {1} \ 34 | CONFIG.C0.CS_WIDTH {2} \ 35 | CONFIG.C0.DDR4_AxiSelection {true} \ 36 | ] [get_ips $ipName] 37 | 38 | } elseif {$::env(XILINX_BOARD) eq "zcu102"} { 39 | set_property -dict [list CONFIG.C0_DDR4_BOARD_INTERFACE {ddr4_sdram_062} \ 40 | CONFIG.C0.DDR4_TimePeriod {833} \ 41 | CONFIG.C0.DDR4_InputClockPeriod {3332} \ 42 | CONFIG.C0.DDR4_CLKOUT0_DIVIDE {5} \ 43 | CONFIG.C0.DDR4_MemoryPart {MT40A256M16LY-062E} \ 44 | CONFIG.C0.DDR4_DataWidth {16} \ 45 | CONFIG.C0.DDR4_CasWriteLatency {12} \ 46 | CONFIG.C0.DDR4_AxiDataWidth {128} \ 47 | CONFIG.C0.DDR4_AxiAddressWidth {29} \ 48 | CONFIG.C0.DDR4_AxiIDWidth {8} \ 49 | CONFIG.ADDN_UI_CLKOUT1_FREQ_HZ {100} \ 50 | CONFIG.System_Clock {No_Buffer} \ 51 | CONFIG.Reference_Clock {No_Buffer} \ 52 | CONFIG.C0.BANK_GROUP_WIDTH {1} \ 53 | CONFIG.C0.DDR4_AxiSelection {true} \ 54 | ] [get_ips $ipName] 55 | } 56 | 57 | 58 | generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] 59 | generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] 60 | create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] 61 | launch_run -jobs 8 ${ipName}_synth_1 62 | wait_on_run ${ipName}_synth_1 63 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/xlnx_mig_ddr4/xlnx_mig_ddr4.mk: -------------------------------------------------------------------------------- 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 | ROOT_xlnx_mig_ddr4 := $(CAR_XIL_DIR)/xilinx_ips/xlnx_mig_ddr4 6 | ARTIFACTS_FILES_xlnx_mig_ddr4 := xlnx_mig_ddr4.mk tcl/run.tcl 7 | ARTIFACTS_VARS_xlnx_mig_ddr4 := xilinx_part XILINX_BOARD xilinx_board_long 8 | XILINX_USE_ARTIFACTS_xlnx_mig_ddr4 := 1 9 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/xlnx_vio/tcl/run.tcl: -------------------------------------------------------------------------------- 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 | # Cyril Koenig 6 | 7 | set partNumber $::env(XILINX_PART) 8 | set boardName $::env(XILINX_BOARD_LONG) 9 | 10 | set ipName xlnx_vio 11 | 12 | create_project $ipName . -force -part $partNumber 13 | set_property board_part $boardName [current_project] 14 | 15 | create_ip -name vio -vendor xilinx.com -library ip -version 3.0 -module_name $ipName 16 | set_property -dict [list CONFIG.C_NUM_PROBE_OUT {3} \ 17 | CONFIG.C_PROBE_OUT0_INIT_VAL {0x0} \ 18 | CONFIG.C_PROBE_OUT0_WIDTH {1} \ 19 | CONFIG.C_PROBE_OUT1_INIT_VAL {0x2} \ 20 | CONFIG.C_PROBE_OUT1_WIDTH {2} \ 21 | CONFIG.C_PROBE_OUT2_INIT_VAL {0x1} \ 22 | CONFIG.C_PROBE_OUT2_WIDTH {2} \ 23 | CONFIG.C_EN_PROBE_IN_ACTIVITY {0} \ 24 | CONFIG.C_NUM_PROBE_IN {0} \ 25 | ] [get_ips $ipName] 26 | 27 | generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] 28 | generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] 29 | create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] 30 | launch_run -jobs 8 ${ipName}_synth_1 31 | wait_on_run ${ipName}_synth_1 32 | -------------------------------------------------------------------------------- /target/xilinx/xilinx_ips/xlnx_vio/xlnx_vio.mk: -------------------------------------------------------------------------------- 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 | ROOT_xlnx_vio := $(CAR_XIL_DIR)/xilinx_ips/xlnx_vio 6 | ARTIFACTS_FILES_xlnx_vio := xlnx_vio.mk tcl/run.tcl 7 | ARTIFACTS_VARS_xlnx_vio := xilinx_part XILINX_BOARD xilinx_board_long 8 | XILINX_USE_ARTIFACTS_xlnx_vio := 1 9 | -------------------------------------------------------------------------------- /utils/generate-makefile-help.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Slightly modified versoin of hilnius excellent bash script for 4 | # self-documenting makefiles 5 | # (https://gist.github.com/klmr/575726c7e05d8780505a). This version of his 6 | # script supports multiple makefiles (i.e. mk files that include other files). 7 | # The bash script expects a MAKEFILES variable with a list of all makefiles to 8 | # process. This list can obtained easily by passing the current content of the 9 | # makefile specila variable $(MAKEFILE_LIST) at the very end of your file to be 10 | # docummented. See the accompanying utils.mk how to properly use this bash script. 11 | 12 | RULE_COLOR="$(tput setaf 6)" 13 | SECTION_COLOR="$(tput setaf 3)" 14 | VARIABLE_COLOR="$(tput setaf 2)" 15 | VALUE_COLOR="$(tput setaf 1)" 16 | CLEAR_STYLE="$(tput sgr0)" 17 | TARGET_STYLED_HELP_NAME="${RULE_COLOR}TARGET${CLEAR_STYLE}" 18 | ARGUMENTS_HELP_NAME="${VARIABLE_COLOR}ARGUMENT${CLEAR_STYLE}=${VALUE_COLOR}VALUE${CLEAR_STYLE}" 19 | 20 | echo "Usage: make [$TARGET_STYLED_HELP_NAME [$TARGET_STYLED_HELP_NAME ...]] [$ARGUMENTS_HELP_NAME [$ARGUMENTS_HELP_NAME ...]]" 21 | echo "${SECTION_COLOR}Targets:${CLEAR_STYLE}" 22 | echo " ${RULE_COLOR}help${CLEAR_STYLE}" 23 | echo " Get help for commands in this folder" 24 | echo "" 25 | 26 | TARGET_REGEX="^[a-zA-Z0-9%_\/%-]+:" 27 | SECTION_REGEX="^##\s*@section\s*(.*)$" 28 | DOCBLOCK_REGEX="^##\s+(.+)$" 29 | PARAM_REGEX="@param\s+([a-zA-Z_]+)(=([^\s]+))?\s*(.*$)?" 30 | 31 | COMMENT="" 32 | PARAMS="" 33 | PARAMS_DOC="" 34 | 35 | for FILE in $MAKEFILES 36 | do 37 | cat $FILE | while read line 38 | do 39 | # do something with $line here 40 | if [[ ! -z $line ]] 41 | then 42 | if [[ $line =~ $SECTION_REGEX ]] 43 | then 44 | SECTION_NAME=$(echo $line | sed -e "s/^##\s*@section\s*\(.*\)$/\1/g") 45 | echo "$SECTION_COLOR$SECTION_NAME$CLEAR_STYLE:" 46 | elif [[ $line =~ $TARGET_REGEX ]] 47 | then 48 | # if there is no comment for this target, we don't display it in the docs to keep private targets hidden 49 | if [[ ! -z $COMMENT ]] 50 | then 51 | TARGET=$(echo $line | sed -e "s/^\([a-zA-Z0-9%_\/%-]\+\):.*/\1/g") 52 | echo " $RULE_COLOR$TARGET$CLEAR_STYLE $PARAMS" 53 | echo -e "$COMMENT" 54 | if [[ ! -z $PARAMS_DOC ]] 55 | then 56 | echo " Params:" 57 | echo -e "$PARAMS_DOC" 58 | fi 59 | fi 60 | COMMENT="" 61 | PARAMS="" 62 | PARAMS_DOC="" 63 | elif [[ $line =~ $PARAM_REGEX ]] 64 | then 65 | PARAM=$(echo $line | sed -e "s/##\s*@param\s\+\([a-zA-Z_]\+\)\(=\([^[:space:]]\+\)\)\?\s*\(.*\)\?$/${VARIABLE_COLOR}\1${CLEAR_STYLE}=${VALUE_COLOR}\3${CLEAR_STYLE}/g") 66 | PARAM_DOC=$(echo $line | sed -e "s/##\s*@param\s\+\([a-zA-Z_]\+\)\(=\([^[:space:]]\+\)\)\?\s*\(.*\)\?$/- \1 (example: \3) \4/g") 67 | PARAMS="${PARAMS}${PARAM} " 68 | PARAMS_DOC="${PARAMS_DOC} ${PARAM_DOC}\n" 69 | elif [[ $line =~ $DOCBLOCK_REGEX ]] 70 | then 71 | # echo "doc : $line" 72 | # echo $line | sed -e "s/^##\s*\(.*\)$/\1/g" 73 | LINE_CLEANED=$(echo $line | sed -e "s/^##\+\s*\(.*\)$/\1/g") 74 | COMMENT="${COMMENT} $LINE_CLEANED\n" 75 | fi 76 | fi 77 | done 78 | done 79 | -------------------------------------------------------------------------------- /utils/lint/lint.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2021 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 | # Author: Matteo Perotti 6 | 7 | ROOT := $(patsubst %/,%, $(dir $(abspath $(lastword $(MAKEFILE_LIST))/../))) 8 | 9 | SNPS_SG ?= spyglass-2022.06 10 | 11 | bender_defs ?= -D SYNTHESIS \ 12 | -D EXCLUDE_PADFRAME 13 | 14 | bender_targs ?= -t asic \ 15 | -t cva6_test \ 16 | -t synthesis \ 17 | -t top_level \ 18 | -t intel16 \ 19 | -t scm_use_latch_scm \ 20 | -t cluster_standalone \ 21 | -t cv64a6_imafdc_sv39 22 | 23 | # PHONY since these targets are all pretty fast compared to spyglass 24 | .PHONY: lint gen_script update 25 | 26 | lint: update gen_script spyglass/sgdc/func.sgdc spyglass/scripts/run_lint.tcl 27 | cd spyglass; $(SNPS_SG) sg_shell -tcl scripts/run_lint.tcl 28 | 29 | gen_script: update 30 | mkdir -p spyglass/tmp 31 | bender script verilator -t spyglass $(bender_targs) -D SPYGLASS $(bender_defs) > spyglass/tmp/files 32 | 33 | update: 34 | bender update 35 | make -C $(ROOT) chs-hw-all 36 | make -C $(ROOT) spatz-init 37 | -------------------------------------------------------------------------------- /utils/lint/spyglass/scripts/run_lint.tcl: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 PROJECT carfield 6 | set TIMESTAMP [exec date +%Y%m%d_%H%M%S] 7 | 8 | # Add ignored files to this list 9 | set IgnoredFiles [list [exec bender path cva6]/core/include/axi_intf.sv] 10 | 11 | new_project sg_projects/${PROJECT}_${TIMESTAMP} 12 | current_methodology $env(SPYGLASS_HOME)/GuideWare/latest/block/rtl_handoff 13 | 14 | # Ignore re-defined files 15 | foreach file $IgnoredFiles { 16 | set_option ignorefile $file 17 | } 18 | 19 | # Read the RTL 20 | read_file -type sourcelist tmp/files 21 | 22 | # Read constraints 23 | read_file -type sgdc sgdc/func.sgdc 24 | 25 | # Set options 26 | set_option enableSV12 yes 27 | set_option language_mode mixed 28 | set_option designread_disable_flatten no 29 | set_option mthresh 32768 30 | set_option top carfield_wrap 31 | 32 | # Link Design 33 | current_design carfield_wrap 34 | compile_design 35 | 36 | # Set lint_rtl goal and run 37 | current_goal lint/lint_rtl 38 | run_goal 39 | 40 | # Create a link to the results 41 | exec rm -rf sg_projects/${PROJECT} 42 | exec ln -sf ${PROJECT}_${TIMESTAMP} sg_projects/${PROJECT} 43 | 44 | # Ciao! 45 | exit -save 46 | -------------------------------------------------------------------------------- /utils/lint/spyglass/sgdc/func.sgdc: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 | current_design carfield_wrap 6 | test_mode -name "carfield_wrap.test_mode_i" -value "1" 7 | reset -name "rst_ni" -async -value 0 8 | reset -name "jtag_trst_ni" -async -value 0 9 | clock -name "clk_i" -tag sys_clk -domain sys_clk_domain 10 | clock -name "jtag_tck_i" -tag jtag_clk -domain jtag_clk_domain 11 | clock -name "rtc_i" -tag rt_clk -domain rt_clk_domain 12 | -------------------------------------------------------------------------------- /utils/reggen/reggen/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulp-platform/carfield/57d5f1e57d2e5f45ce0dc956e74618f6b5c737ad/utils/reggen/reggen/__init__.py -------------------------------------------------------------------------------- /utils/reggen/reggen/alert.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | from typing import Dict, List 6 | 7 | from .bits import Bits 8 | from .signal import Signal 9 | from .lib import check_keys, check_name, check_str, check_list 10 | 11 | 12 | class Alert(Signal): 13 | def __init__(self, name: str, desc: str, bit: int, fatal: bool): 14 | super().__init__(name, desc, Bits(bit, bit)) 15 | self.bit = bit 16 | self.fatal = fatal 17 | 18 | @staticmethod 19 | def from_raw(what: str, 20 | lsb: int, 21 | raw: object) -> 'Alert': 22 | rd = check_keys(raw, what, ['name', 'desc'], []) 23 | 24 | name = check_name(rd['name'], 'name field of ' + what) 25 | desc = check_str(rd['desc'], 'desc field of ' + what) 26 | 27 | # Make sense of the alert name, which should be prefixed with recov_ or 28 | # fatal_. 29 | pfx = name.split('_')[0] 30 | if pfx == 'recov': 31 | fatal = False 32 | elif pfx == 'fatal': 33 | fatal = True 34 | else: 35 | raise ValueError('Invalid name field of {}: alert names must be ' 36 | 'prefixed with "recov_" or "fatal_". Saw {!r}.' 37 | .format(what, name)) 38 | 39 | return Alert(name, desc, lsb, fatal) 40 | 41 | @staticmethod 42 | def from_raw_list(what: str, raw: object) -> List['Alert']: 43 | ret = [] 44 | for idx, entry in enumerate(check_list(raw, what)): 45 | entry_what = 'entry {} of {}'.format(idx, what) 46 | alert = Alert.from_raw(entry_what, idx, entry) 47 | ret.append(alert) 48 | return ret 49 | 50 | def _asdict(self) -> Dict[str, object]: 51 | return { 52 | 'name': self.name, 53 | 'desc': self.desc, 54 | } 55 | -------------------------------------------------------------------------------- /utils/reggen/reggen/bits.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | '''Support code for bit ranges in reggen''' 6 | 7 | from typing import Tuple 8 | 9 | from .lib import check_str 10 | from .params import ReggenParams 11 | 12 | 13 | class Bits: 14 | def __init__(self, msb: int, lsb: int): 15 | assert 0 <= lsb <= msb 16 | self.msb = msb 17 | self.lsb = lsb 18 | 19 | def bitmask(self) -> int: 20 | return (1 << (self.msb + 1)) - (1 << self.lsb) 21 | 22 | def width(self) -> int: 23 | return 1 + self.msb - self.lsb 24 | 25 | def max_value(self) -> int: 26 | return (1 << self.width()) - 1 27 | 28 | def extract_field(self, reg_val: int) -> int: 29 | return (reg_val & self.bitmask()) >> self.lsb 30 | 31 | @staticmethod 32 | def from_raw(where: str, 33 | reg_width: int, 34 | params: ReggenParams, 35 | raw: object) -> 'Bits': 36 | # Bits should be specified as msb:lsb or as just a single bit index. 37 | if isinstance(raw, int): 38 | msb = raw 39 | lsb = raw 40 | else: 41 | str_val = check_str(raw, 'bits field for {}'.format(where)) 42 | msb, lsb = Bits._parse_str(where, params, str_val) 43 | 44 | # Check that the bit indices look sensible 45 | if msb < lsb: 46 | raise ValueError('msb for {} is {}: less than {}, the msb.' 47 | .format(where, msb, lsb)) 48 | if lsb < 0: 49 | raise ValueError('lsb for {} is {}, which is negative.' 50 | .format(where, lsb)) 51 | if msb >= reg_width: 52 | raise ValueError("msb for {} is {}, which doesn't fit in {} bits." 53 | .format(where, msb, reg_width)) 54 | 55 | return Bits(msb, lsb) 56 | 57 | @staticmethod 58 | def _parse_str(where: str, 59 | params: ReggenParams, 60 | str_val: str) -> Tuple[int, int]: 61 | try: 62 | idx = int(str_val) 63 | return (idx, idx) 64 | except ValueError: 65 | # Doesn't look like an integer. Never mind: try msb:lsb 66 | pass 67 | 68 | parts = str_val.split(':') 69 | if len(parts) != 2: 70 | raise ValueError('bits field for {} is not an ' 71 | 'integer or of the form msb:lsb. Saw {!r}.' 72 | .format(where, str_val)) 73 | return (params.expand(parts[0], 74 | 'msb of bits field for {}'.format(where)), 75 | params.expand(parts[1], 76 | 'lsb of bits field for {}'.format(where))) 77 | 78 | def make_translated(self, bit_offset: int) -> 'Bits': 79 | assert 0 <= bit_offset 80 | return Bits(self.msb + bit_offset, self.lsb + bit_offset) 81 | 82 | def as_str(self) -> str: 83 | if self.lsb == self.msb: 84 | return str(self.lsb) 85 | else: 86 | assert self.lsb < self.msb 87 | return '{}:{}'.format(self.msb, self.lsb) 88 | -------------------------------------------------------------------------------- /utils/reggen/reggen/enum_entry.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | from typing import Dict 6 | 7 | from .lib import check_keys, check_str, check_int 8 | 9 | REQUIRED_FIELDS = { 10 | 'name': ['s', "name of the member of the enum"], 11 | 'desc': ['t', "description when field has this value"], 12 | 'value': ['d', "value of this member of the enum"] 13 | } 14 | 15 | 16 | class EnumEntry: 17 | def __init__(self, where: str, max_val: int, raw: object): 18 | rd = check_keys(raw, where, 19 | list(REQUIRED_FIELDS.keys()), 20 | []) 21 | 22 | self.name = check_str(rd['name'], 'name field of {}'.format(where)) 23 | self.desc = check_str(rd['desc'], 'desc field of {}'.format(where)) 24 | self.value = check_int(rd['value'], 'value field of {}'.format(where)) 25 | if not (0 <= self.value <= max_val): 26 | raise ValueError("value for {} is {}, which isn't representable " 27 | "in the field (representable range: 0 .. {})." 28 | .format(where, self.value, max_val)) 29 | 30 | def _asdict(self) -> Dict[str, object]: 31 | return { 32 | 'name': self.name, 33 | 'desc': self.desc, 34 | 'value': str(self.value) 35 | } 36 | -------------------------------------------------------------------------------- /utils/reggen/reggen/gen_fpv.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | # # Lint as: python3 5 | # 6 | """Generate FPV CSR read and write assertions from IpBlock 7 | """ 8 | 9 | import logging as log 10 | import os.path 11 | 12 | import yaml 13 | from mako import exceptions 14 | from mako.template import Template 15 | from pkg_resources import resource_filename 16 | 17 | from .ip_block import IpBlock 18 | 19 | 20 | def gen_fpv(block: IpBlock, outdir): 21 | # Read Register templates 22 | fpv_csr_tpl = Template( 23 | filename=resource_filename('reggen', 'fpv_csr.sv.tpl')) 24 | 25 | # Generate a module with CSR assertions for each device interface. For a 26 | # device interface with no name, we generate _csr_assert_fpv. For a 27 | # named interface, we generate __csr_assert_fpv. 28 | lblock = block.name.lower() 29 | generated = [] 30 | for if_name, rb in block.reg_blocks.items(): 31 | if not rb.flat_regs: 32 | # No registers to check! 33 | continue 34 | 35 | if if_name is None: 36 | mod_base = lblock 37 | else: 38 | mod_base = lblock + '_' + if_name.lower() 39 | 40 | mod_name = mod_base + '_csr_assert_fpv' 41 | filename = mod_name + '.sv' 42 | generated.append(filename) 43 | reg_top_path = os.path.join(outdir, filename) 44 | with open(reg_top_path, 'w', encoding='UTF-8') as fout: 45 | try: 46 | fout.write(fpv_csr_tpl.render(block=block, 47 | mod_base=mod_base, 48 | if_name=if_name, 49 | rb=rb)) 50 | except: # noqa F722 for template Exception handling 51 | log.error(exceptions.text_error_template().render()) 52 | return 1 53 | 54 | # Generate a fusesoc core file that points at the files we've just 55 | # generated. 56 | core_data = { 57 | 'name': "lowrisc:fpv:{}_csr_assert".format(lblock), 58 | 'filesets': { 59 | 'files_dv': { 60 | 'depend': [ 61 | "lowrisc:tlul:headers", 62 | "lowrisc:prim:assert", 63 | ], 64 | 'files': generated, 65 | 'file_type': 'systemVerilogSource' 66 | }, 67 | }, 68 | 'targets': { 69 | 'default': { 70 | 'filesets': [ 71 | 'files_dv', 72 | ], 73 | }, 74 | }, 75 | } 76 | core_file_path = os.path.join(outdir, lblock + '_csr_assert_fpv.core') 77 | with open(core_file_path, 'w') as core_file: 78 | core_file.write('CAPI=2:\n') 79 | yaml.dump(core_data, core_file, encoding='utf-8') 80 | 81 | return 0 82 | -------------------------------------------------------------------------------- /utils/reggen/reggen/gen_json.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | """Generate JSON/compact JSON/Hjson from register JSON tree 5 | """ 6 | 7 | import hjson 8 | 9 | 10 | def gen_json(obj, outfile, format): 11 | if format == 'json': 12 | hjson.dumpJSON(obj, 13 | outfile, 14 | ensure_ascii=False, 15 | use_decimal=True, 16 | indent=' ', 17 | for_json=True) 18 | elif format == 'compact': 19 | hjson.dumpJSON(obj, 20 | outfile, 21 | ensure_ascii=False, 22 | for_json=True, 23 | use_decimal=True, 24 | separators=(',', ':')) 25 | elif format == 'hjson': 26 | hjson.dump(obj, 27 | outfile, 28 | ensure_ascii=False, 29 | for_json=True, 30 | use_decimal=True) 31 | else: 32 | raise ValueError('Invalid JSON format ' + format) 33 | 34 | return 0 35 | -------------------------------------------------------------------------------- /utils/reggen/reggen/html_helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | import logging as log 6 | import re 7 | from typing import List, Match, Optional, Set 8 | 9 | 10 | def expand_paras(s: str, rnames: Set[str]) -> List[str]: 11 | '''Expand a description field to HTML. 12 | 13 | This supports a sort of simple pseudo-markdown. Supported Markdown 14 | features: 15 | 16 | - Separate paragraphs on a blank line 17 | - **bold** and *italicised* text 18 | - Back-ticks for pre-formatted text 19 | 20 | We also generate links to registers when a name is prefixed with a double 21 | exclamation mark. For example, if there is a register FOO then !!FOO or 22 | !!FOO.field will generate a link to that register. 23 | 24 | Returns a list of rendered paragraphs 25 | 26 | ''' 27 | # Start by splitting into paragraphs. The regex matches a newline followed 28 | # by one or more lines that just contain whitespace. Then render each 29 | # paragraph with the _expand_paragraph worker function. 30 | paras = [_expand_paragraph(paragraph.strip(), rnames) 31 | for paragraph in re.split(r'\n(?:\s*\n)+', s)] 32 | 33 | # There will always be at least one paragraph (splitting an empty string 34 | # gives ['']) 35 | assert paras 36 | return paras 37 | 38 | 39 | def _expand_paragraph(s: str, rnames: Set[str]) -> str: 40 | '''Expand a single paragraph, as described in _get_desc_paras''' 41 | def fieldsub(match: Match[str]) -> str: 42 | base = match.group(1).partition('.')[0].lower() 43 | if base in rnames: 44 | if match.group(1)[-1] == ".": 45 | return ('' + 46 | match.group(1)[:-1] + '.') 47 | else: 48 | return ('' + 49 | match.group(1) + '') 50 | log.warn('!!' + match.group(1).partition('.')[0] + 51 | ' not found in register list.') 52 | return match.group(0) 53 | 54 | # Split out pre-formatted text. Because the call to re.split has a capture 55 | # group in the regex, we get an odd number of results. Elements with even 56 | # indices are "normal text". Those with odd indices are the captured text 57 | # between the back-ticks. 58 | code_split = re.split(r'`([^`]+)`', s) 59 | expanded_parts = [] 60 | 61 | for idx, part in enumerate(code_split): 62 | if idx & 1: 63 | # Text contained in back ticks 64 | expanded_parts.append('{}'.format(part)) 65 | continue 66 | 67 | part = re.sub(r"!!([A-Za-z0-9_.]+)", fieldsub, part) 68 | part = re.sub(r"(?s)\*\*(.+?)\*\*", r'\1', part) 69 | part = re.sub(r"\*([^*]+?)\*", r'\1', part) 70 | expanded_parts.append(part) 71 | 72 | return '

{}

'.format(''.join(expanded_parts)) 73 | 74 | 75 | def render_td(s: str, rnames: Set[str], td_class: Optional[str]) -> str: 76 | '''Expand a description field and put it in a . 77 | 78 | Returns a string. See _get_desc_paras for the format that gets expanded. 79 | 80 | ''' 81 | desc_paras = expand_paras(s, rnames) 82 | class_attr = '' if td_class is None else ' class="{}"'.format(td_class) 83 | return '{}'.format(class_attr, ''.join(desc_paras)) 84 | -------------------------------------------------------------------------------- /utils/reggen/reggen/inter_signal.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | from typing import Dict, Optional 6 | 7 | from .lib import (check_keys, check_name, 8 | check_str, check_optional_str, check_int) 9 | 10 | 11 | class InterSignal: 12 | def __init__(self, 13 | name: str, 14 | desc: Optional[str], 15 | struct: str, 16 | package: Optional[str], 17 | signal_type: str, 18 | act: str, 19 | width: int, 20 | default: Optional[str]): 21 | assert 0 < width 22 | self.name = name 23 | self.desc = desc 24 | self.struct = struct 25 | self.package = package 26 | self.signal_type = signal_type 27 | self.act = act 28 | self.width = width 29 | self.default = default 30 | 31 | @staticmethod 32 | def from_raw(what: str, raw: object) -> 'InterSignal': 33 | rd = check_keys(raw, what, 34 | ['name', 'struct', 'type', 'act'], 35 | ['desc', 'package', 'width', 'default']) 36 | 37 | name = check_name(rd['name'], 'name field of ' + what) 38 | 39 | r_desc = rd.get('desc') 40 | if r_desc is None: 41 | desc = None 42 | else: 43 | desc = check_str(r_desc, 'desc field of ' + what) 44 | 45 | struct = check_str(rd['struct'], 'struct field of ' + what) 46 | 47 | r_package = rd.get('package') 48 | if r_package is None or r_package == '': 49 | package = None 50 | else: 51 | package = check_name(r_package, 'package field of ' + what) 52 | 53 | signal_type = check_name(rd['type'], 'type field of ' + what) 54 | act = check_name(rd['act'], 'act field of ' + what) 55 | width = check_int(rd.get('width', 1), 'width field of ' + what) 56 | if width <= 0: 57 | raise ValueError('width field of {} is not positive.'.format(what)) 58 | 59 | default = check_optional_str(rd.get('default'), 60 | 'default field of ' + what) 61 | 62 | return InterSignal(name, desc, struct, package, 63 | signal_type, act, width, default) 64 | 65 | def _asdict(self) -> Dict[str, object]: 66 | ret = {'name': self.name} # type: Dict[str, object] 67 | if self.desc is not None: 68 | ret['desc'] = self.desc 69 | ret['struct'] = self.struct 70 | if self.package is not None: 71 | ret['package'] = self.package 72 | ret['type'] = self.signal_type 73 | ret['act'] = self.act 74 | ret['width'] = self.width 75 | if self.default is not None: 76 | ret['default'] = self.default 77 | 78 | return ret 79 | 80 | def as_dict(self) -> Dict[str, object]: 81 | return self._asdict() 82 | -------------------------------------------------------------------------------- /utils/reggen/reggen/reg_base.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | from typing import List 6 | 7 | from .field import Field 8 | 9 | 10 | class RegBase: 11 | '''An abstract class inherited by Register and MultiRegister 12 | 13 | This represents a block of one or more registers with a base address. 14 | 15 | ''' 16 | def __init__(self, offset: int): 17 | self.offset = offset 18 | 19 | def get_n_bits(self, bittype: List[str]) -> int: 20 | '''Get the size of this register / these registers in bits 21 | 22 | See Field.get_n_bits() for the precise meaning of bittype. 23 | 24 | ''' 25 | raise NotImplementedError() 26 | 27 | def get_field_list(self) -> List[Field]: 28 | '''Get an ordered list of the fields in the register(s) 29 | 30 | Registers are ordered from low to high address. Within a register, 31 | fields are ordered as Register.fields: from LSB to MSB. 32 | 33 | ''' 34 | raise NotImplementedError() 35 | 36 | def is_homogeneous(self) -> bool: 37 | '''True if every field in the block is identical 38 | 39 | For a single register, this is true if it only has one field. For a 40 | multireg, it is true if the generating register has just one field. 41 | Note that if the compact flag is set, the generated registers might 42 | have multiple (replicated) fields. 43 | 44 | ''' 45 | raise NotImplementedError() 46 | -------------------------------------------------------------------------------- /utils/reggen/reggen/reg_html.css: -------------------------------------------------------------------------------- 1 | /* Stylesheet for reggen HTML register output */ 2 | /* Copyright lowRISC contributors. */ 3 | /* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ 4 | /* SPDX-License-Identifier: Apache-2.0 */ 5 | 6 | table.regpic { 7 | width: 95%; 8 | border-collapse: collapse; 9 | margin-left:auto; 10 | margin-right:auto; 11 | table-layout:fixed; 12 | } 13 | 14 | table.regdef { 15 | border: 1px solid black; 16 | width: 80%; 17 | border-collapse: collapse; 18 | margin-left:auto; 19 | margin-right:auto; 20 | table-layout:auto; 21 | } 22 | 23 | table.regdef th { 24 | border: 1px solid black; 25 | font-family: sans-serif; 26 | 27 | } 28 | 29 | td.bitnum { 30 | font-size: 60%; 31 | text-align: center; 32 | } 33 | 34 | td.unused { 35 | border: 1px solid black; 36 | background-color: gray; 37 | } 38 | 39 | td.fname { 40 | border: 1px solid black; 41 | text-align: center; 42 | font-family: sans-serif; 43 | } 44 | 45 | 46 | td.regbits, td.regperm, td.regrv { 47 | border: 1px solid black; 48 | text-align: center; 49 | font-family: sans-serif; 50 | } 51 | 52 | td.regde, td.regfn { 53 | border: 1px solid black; 54 | } 55 | 56 | table.cfgtable { 57 | border: 1px solid black; 58 | width: 80%; 59 | border-collapse: collapse; 60 | margin-left:auto; 61 | margin-right:auto; 62 | table-layout:auto; 63 | } 64 | 65 | table.cfgtable th { 66 | border: 1px solid black; 67 | font-family: sans-serif; 68 | font-weight: bold; 69 | } 70 | 71 | table.cfgtable td { 72 | border: 1px solid black; 73 | font-family: sans-serif; 74 | } 75 | -------------------------------------------------------------------------------- /utils/reggen/reggen/signal.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | from typing import Dict, Sequence 6 | 7 | from .bits import Bits 8 | from .lib import check_keys, check_name, check_str, check_int, check_list 9 | 10 | 11 | class Signal: 12 | def __init__(self, name: str, desc: str, bits: Bits): 13 | self.name = name 14 | self.desc = desc 15 | self.bits = bits 16 | 17 | @staticmethod 18 | def from_raw(what: str, lsb: int, raw: object) -> 'Signal': 19 | rd = check_keys(raw, what, 20 | ['name', 'desc'], 21 | ['width']) 22 | 23 | name = check_name(rd['name'], 'name field of ' + what) 24 | desc = check_str(rd['desc'], 'desc field of ' + what) 25 | width = check_int(rd.get('width', 1), 'width field of ' + what) 26 | if width <= 0: 27 | raise ValueError('The width field of signal {} ({}) ' 28 | 'has value {}, but should be positive.' 29 | .format(name, what, width)) 30 | 31 | bits = Bits(lsb + width - 1, lsb) 32 | 33 | return Signal(name, desc, bits) 34 | 35 | @staticmethod 36 | def from_raw_list(what: str, raw: object) -> Sequence['Signal']: 37 | lsb = 0 38 | ret = [] 39 | for idx, entry in enumerate(check_list(raw, what)): 40 | entry_what = 'entry {} of {}'.format(idx, what) 41 | interrupt = Signal.from_raw(entry_what, lsb, entry) 42 | ret.append(interrupt) 43 | lsb += interrupt.bits.width() 44 | return ret 45 | 46 | def _asdict(self) -> Dict[str, object]: 47 | return { 48 | 'name': self.name, 49 | 'desc': self.desc, 50 | 'width': str(self.bits.width()) 51 | } 52 | 53 | def as_nwt_dict(self, type_field: str) -> Dict[str, object]: 54 | '''Return a view of the signal as a dictionary 55 | 56 | The dictionary has fields "name", "width" and "type", the last 57 | of which comes from the type_field argument. Used for topgen 58 | integration. 59 | 60 | ''' 61 | return {'name': self.name, 62 | 'width': self.bits.width(), 63 | 'type': type_field} 64 | -------------------------------------------------------------------------------- /utils/reggen/reggen/uvm_reg.sv.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // UVM Registers auto-generated by `reggen` containing data structure 6 | ## 7 | ## 8 | ## We use functions from uvm_reg_base.sv.tpl to define 9 | ## per-device-interface code. 10 | ## 11 | <%namespace file="uvm_reg_base.sv.tpl" import="*"/>\ 12 | ## 13 | ## 14 | ${make_ral_pkg(dv_base_prefix, block.regwidth, reg_block_path, rb, esc_if_name)} 15 | -------------------------------------------------------------------------------- /utils/reggen/reggen/version.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | r"""Standard version printing 5 | """ 6 | import os 7 | import subprocess 8 | import sys 9 | 10 | import pkg_resources # part of setuptools 11 | 12 | 13 | def show_and_exit(clitool, packages): 14 | util_path = os.path.dirname(os.path.realpath(clitool)) 15 | os.chdir(util_path) 16 | ver = subprocess.run( 17 | ["git", "describe", "--always", "--dirty", "--broken"], 18 | stdout=subprocess.PIPE).stdout.strip().decode('ascii') 19 | if (ver == ''): 20 | ver = 'not found (not in Git repository?)' 21 | sys.stderr.write(clitool + " Git version " + ver + '\n') 22 | for p in packages: 23 | sys.stderr.write(p + ' ' + pkg_resources.require(p)[0].version + '\n') 24 | exit(0) 25 | -------------------------------------------------------------------------------- /utils/reggen/topgen/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | from .lib import get_hjsonobj_xbars, search_ips # noqa: F401 6 | # noqa: F401 These functions are used in topgen.py 7 | from .merge import amend_clocks, merge_top # noqa: F401 8 | from .validate import validate_top, check_flash # noqa: F401 9 | -------------------------------------------------------------------------------- /utils/reggen/topgen/gen_dv.py: -------------------------------------------------------------------------------- 1 | # Copyright lowRISC contributors. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | import logging as log 6 | from typing import Optional, Tuple 7 | 8 | from mako import exceptions # type: ignore 9 | from mako.lookup import TemplateLookup # type: ignore 10 | from pkg_resources import resource_filename 11 | 12 | from reggen.gen_dv import gen_core_file 13 | 14 | from .top import Top 15 | 16 | 17 | def sv_base_addr(top: Top, if_name: Tuple[str, Optional[str]]) -> str: 18 | '''Get the base address of a device interface in SV syntax''' 19 | return "{}'h{:x}".format(top.regwidth, top.if_addrs[if_name]) 20 | 21 | 22 | def gen_dv(top: Top, 23 | dv_base_prefix: str, 24 | outdir: str) -> int: 25 | '''Generate DV RAL model for a Top''' 26 | # Read template 27 | lookup = TemplateLookup(directories=[resource_filename('topgen', '.'), 28 | resource_filename('reggen', '.')]) 29 | uvm_reg_tpl = lookup.get_template('top_uvm_reg.sv.tpl') 30 | 31 | # Expand template 32 | try: 33 | to_write = uvm_reg_tpl.render(top=top, 34 | dv_base_prefix=dv_base_prefix) 35 | except: # noqa: E722 36 | log.error(exceptions.text_error_template().render()) 37 | return 1 38 | 39 | # Dump to output file 40 | dest_path = '{}/chip_ral_pkg.sv'.format(outdir) 41 | with open(dest_path, 'w') as fout: 42 | fout.write(to_write) 43 | 44 | gen_core_file(outdir, 'chip', dv_base_prefix, ['chip_ral_pkg.sv']) 45 | 46 | return 0 47 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/README.md: -------------------------------------------------------------------------------- 1 | # OpenTitan topgen templates 2 | 3 | This directory contains templates used by topgen to assembly a chip toplevel. 4 | 5 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/chip_env_pkg__params.sv.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Generated by topgen.py 6 | 7 | parameter string LIST_OF_ALERTS[] = { 8 | % for alert in top["alert"]: 9 | % if loop.last: 10 | "${alert["name"]}" 11 | % else: 12 | "${alert["name"]}", 13 | % endif 14 | % endfor 15 | }; 16 | 17 | parameter uint NUM_ALERTS = ${len(top["alert"])}; 18 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/clang-format: -------------------------------------------------------------------------------- 1 | # This disables clang-format on all files in the sw/autogen directory. 2 | # This is needed so that git-clang-format and similar scripts work. 3 | DisableFormat: true 4 | SortIncludes: false 5 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/tb__alert_handler_connect.sv.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // 5 | // tb__alert_handler_connect.sv is auto-generated by `topgen.py` tool 6 | 7 | <% 8 | index = 0 9 | module_name = "" 10 | %>\ 11 | % for alert in top["alert"]: 12 | % if alert["module_name"] == module_name: 13 | <% index = index + 1 %>\ 14 | % else: 15 | <% 16 | module_name = alert["module_name"] 17 | index = 0 18 | %>\ 19 | % endif 20 | assign alert_if[${loop.index}].alert_tx = `CHIP_HIER.u_${module_name}.alert_tx_o[${index}]; 21 | % endfor 22 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/toplevel.c.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "${helper.header_path}" 6 | 7 | /** 8 | * PLIC Interrupt Source to Peripheral Map 9 | * 10 | * This array is a mapping from `${helper.plic_interrupts.name.as_c_type()}` to 11 | * `${helper.plic_sources.name.as_c_type()}`. 12 | */ 13 | ${helper.plic_mapping.render_definition()} 14 | 15 | /** 16 | * Alert Handler Alert Source to Peripheral Map 17 | * 18 | * This array is a mapping from `${helper.alert_alerts.name.as_c_type()}` to 19 | * `${helper.alert_sources.name.as_c_type()}`. 20 | */ 21 | ${helper.alert_mapping.render_definition()} 22 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/toplevel_memory.h.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #ifndef _TOP_${top["name"].upper()}_MEMORY_H_ 6 | #define _TOP_${top["name"].upper()}_MEMORY_H_ 7 | 8 | /** 9 | * @file 10 | * @brief Assembler-only Top-Specific Definitions. 11 | * 12 | * This file contains preprocessor definitions for use within assembly code. 13 | * 14 | * These are not shared with C/C++ code because these are only allowed to be 15 | * preprocessor definitions, no data or type declarations are allowed. The 16 | * assembler is also stricter about literals (not allowing suffixes for 17 | * signed/unsigned which are sensible to use for unsigned values in C/C++). 18 | */ 19 | 20 | // Include guard for assembler 21 | #ifdef __ASSEMBLER__ 22 | 23 | /** 24 | * Memory base address for rom in top earlgrey. 25 | */ 26 | #define TOP_EARLGREY_ROM_BASE_ADDR 0x00008000 27 | 28 | /** 29 | * Memory size for rom in top earlgrey. 30 | */ 31 | #define TOP_EARLGREY_ROM_SIZE_BYTES 0x4000 32 | 33 | % for m in top["memory"]: 34 | /** 35 | * Memory base address for ${m["name"]} in top ${top["name"]}. 36 | */ 37 | #define TOP_${top["name"].upper()}_${m["name"].upper()}_BASE_ADDR ${m["base_addr"]} 38 | 39 | /** 40 | * Memory size for ${m["name"]} in top ${top["name"]}. 41 | */ 42 | #define TOP_${top["name"].upper()}_${m["name"].upper()}_SIZE_BYTES ${m["size"]} 43 | 44 | % endfor 45 | 46 | % for (inst_name, if_name), region in helper.devices(): 47 | <% 48 | if_desc = inst_name if if_name is None else '{} device on {}'.format(if_name, inst_name) 49 | hex_base_addr = "0x{:X}".format(region.base_addr) 50 | base_addr_name = region.base_addr_name().as_c_define() 51 | %>\ 52 | /** 53 | * Peripheral base address for ${if_desc} in top ${top["name"]}. 54 | * 55 | * This should be used with #mmio_region_from_addr to access the memory-mapped 56 | * registers associated with the peripheral (usually via a DIF). 57 | */ 58 | #define ${base_addr_name} ${hex_base_addr} 59 | % endfor 60 | #endif // __ASSEMBLER__ 61 | 62 | #endif // _TOP_${top["name"].upper()}_MEMORY_H_ 63 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/toplevel_memory.ld.tpl: -------------------------------------------------------------------------------- 1 | /* Copyright lowRISC contributors. */ 2 | /* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ 3 | /* SPDX-License-Identifier: Apache-2.0 */ 4 | <%! 5 | def memory_to_flags(memory): 6 | memory_type = memory["type"] 7 | memory_access = memory.get("swaccess", "rw") 8 | assert memory_access in ["ro", "rw"] 9 | 10 | flags_str = "" 11 | if memory_access == "ro": 12 | flags_str += "r" 13 | else: 14 | flags_str += "rw" 15 | 16 | if memory_type in ["rom", "eflash"]: 17 | flags_str += "x" 18 | 19 | return flags_str 20 | %>\ 21 | 22 | /** 23 | * Partial linker script for chip memory configuration. 24 | */ 25 | MEMORY { 26 | rom(rx) : ORIGIN = 0x00008000, LENGTH = 0x4000 27 | % for m in top["memory"]: 28 | ${m["name"]}(${memory_to_flags(m)}) : ORIGIN = ${m["base_addr"]}, LENGTH = ${m["size"]} 29 | % endfor 30 | } 31 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/toplevel_rnd_cnst_pkg.sv.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | ${gencmd} 5 | <% 6 | def make_blocked_sv_literal(hexstr, randwidth): 7 | """This chops the random hexstring into manageable blocks of 64 chars such that the 8 | lines do not get too long. 9 | """ 10 | # Make all-caps and drop '0x' preamble 11 | hexstr = str(hexstr[2:]).upper() 12 | # Block width in hex chars 13 | blockwidth = 64 14 | remainder = randwidth % (4*blockwidth) 15 | numbits = remainder if remainder else 4*blockwidth 16 | idx = 0 17 | hexblocks = [] 18 | while randwidth > 0: 19 | hexstr = hexstr[idx:] 20 | randwidth -= numbits 21 | idx = (numbits + 3) // 4 22 | hexblocks.append(str(numbits) + "'h" + hexstr[0:idx]) 23 | numbits = 4*blockwidth 24 | return hexblocks 25 | %> 26 | package top_${top["name"]}_rnd_cnst_pkg; 27 | 28 | % for m in top["module"]: 29 | % for p in filter(lambda p: p.get("randtype") in ["data", "perm"], m["param_list"]): 30 | % if loop.first: 31 | //////////////////////////////////////////// 32 | // ${m['name']} 33 | //////////////////////////////////////////// 34 | % endif 35 | // ${p['desc']} 36 | parameter ${p["type"]} ${p["name_top"]} = { 37 | % for block in make_blocked_sv_literal(p["default"], p["randwidth"]): 38 | ${block}${"" if loop.last else ","} 39 | % endfor 40 | }; 41 | 42 | % endfor 43 | % endfor 44 | endpackage : top_${top["name"]}_rnd_cnst_pkg 45 | -------------------------------------------------------------------------------- /utils/reggen/topgen/templates/xbar_env_pkg__params.sv.tpl: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // 5 | // xbar_env_pkg__params generated by `topgen.py` tool 6 | 7 | <% 8 | from collections import OrderedDict 9 | 10 | def is_device_a_xbar(dev_name): 11 | for xbar in top["xbar"]: 12 | if xbar["name"] == dev_name: 13 | return 1 14 | return 0 15 | 16 | # recursively find all non-xbar devices under this xbar 17 | def get_xbar_edge_nodes(xbar_name): 18 | edge_devices = [] 19 | for xbar in top["xbar"]: 20 | if xbar["name"] == xbar_name: 21 | for host, devices in xbar["connections"].items(): 22 | for dev_name in devices: 23 | if is_device_a_xbar(dev_name): 24 | edge_devices.extend(get_xbar_edge_nodes()) 25 | else: 26 | edge_devices.append(dev_name) 27 | 28 | return edge_devices 29 | 30 | # find device xbar and assign all its device nodes to it: "peri" -> "uart, gpio, ..." 31 | xbar_device_dict = OrderedDict() 32 | 33 | for xbar in top["xbar"]: 34 | for n in xbar["nodes"]: 35 | if n["type"] == "device" and n["xbar"]: 36 | xbar_device_dict[n["name"]] = get_xbar_edge_nodes(n["name"]) 37 | 38 | # create the mapping: host with the corresponding devices map 39 | host_dev_map = OrderedDict() 40 | for host, devices in top["xbar"][0]["connections"].items(): 41 | dev_list = [] 42 | for dev in devices: 43 | if dev not in xbar_device_dict.keys(): 44 | dev_list.append(dev) 45 | else: 46 | dev_list.extend(xbar_device_dict[dev]) 47 | host_dev_map[host] = dev_list 48 | 49 | %>\ 50 | 51 | // List of Xbar device memory map 52 | tl_device_t xbar_devices[$] = '{ 53 | % for xbar in top["xbar"]: 54 | % for device in xbar["nodes"]: 55 | % if device["type"] == "device" and not device["xbar"]: 56 | '{"${device["name"].replace('.', '__')}", '{ 57 | % for addr in device["addr_range"]: 58 | <% 59 | start_addr = int(addr["base_addr"], 0) 60 | end_addr = start_addr + int(addr["size_byte"], 0) - 1 61 | %>\ 62 | '{32'h${"%08x" % start_addr}, 32'h${"%08x" % end_addr}}${"," if not loop.last else ""} 63 | % endfor 64 | }}${"," if not loop.last or xbar != top["xbar"][-1] else "};"} 65 | % endif 66 | % endfor 67 | % endfor 68 | 69 | // List of Xbar hosts 70 | tl_host_t xbar_hosts[$] = '{ 71 | % for host in host_dev_map.keys(): 72 | '{"${host}", ${loop.index}, '{ 73 | <% 74 | host_devices = host_dev_map[host]; 75 | %>\ 76 | % for device in host_devices: 77 | % if loop.last: 78 | "${device}"}} 79 | % else: 80 | "${device}", 81 | % endif 82 | % endfor 83 | % if loop.last: 84 | }; 85 | % else: 86 | , 87 | % endif 88 | % endfor 89 | --------------------------------------------------------------------------------