From cf060ebb31173fabfb65219621042733367be9fb Mon Sep 17 00:00:00 2001 From: mbelda <11842513+mbelda@users.noreply.github.com> Date: Fri, 15 Mar 2024 07:08:39 +0100 Subject: [PATCH] Update esl_epfl_x_heep to esl-epfl/x-heep@76d58ef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update code from upstream repository https://github.com/esl- epfl/x-heep.git to revision 76d58efe7b9dec0723c1cb9aaf8ad76ad6c85373 * Update ci (esl-epfl/x-heep#454) (Luigi Giuffrida) * fix num of FPGAs in README (Davide Schiavone) * Porting Ultrascale ZCU104 board (esl-epfl/x-heep#435) (jmiranda) * Add absolute path to `CMakeLists.txt` match statements (esl- epfl/x-heep#469) (Michele Caon) * add SystemC example (esl-epfl/x-heep#443) (Davide Schiavone) * Structs multireg fix (esl-epfl/x-heep#466) (Stefano Albini) * add Coremark and update cv32e40p (esl-epfl/x-heep#465) (Davide Schiavone) * add tiled matmul (esl-epfl/x-heep#464) (Davide Schiavone) * fix software errors/warnings (esl-epfl/x-heep#462) (Davide Schiavone) * add xcelium support (esl-epfl/x-heep#452) (Davide Schiavone) * Add matmul example (esl-epfl/x-heep#461) (Davide Schiavone) * fix typo in debug_ss (esl-epfl/x-heep#460) (Luigi Giuffrida) * update riscv_dbg (esl-epfl/x-heep#230) (Davide Schiavone) * Fix esl-epfl/x-heep#430 (esl-epfl/x-heep#459) (David Mallasén Quintana) * fix esl-epfl/x-heep#447 (esl-epfl/x-heep#453) (Davide Schiavone) * fix typo (esl-epfl/x-heep#458) (Luigi Giuffrida) * add OpenOCD BSCAN configuration file (esl-epfl/x-heep#457) (Luis Waucquez) * Removed repeated code in dma hal (esl-epfl/x-heep#456) (Juan-n-only) * Fix linker script generation (esl-epfl/x-heep#451) (Luigi Giuffrida) * Add a target to the Makefile to directly program the FPGA (esl- epfl/x-heep#450) (Luigi Giuffrida) * [hw/sw] update flash load linker script, data_interleaved and data_flash_only sections (esl-epfl/x-heep#399) (Davide Schiavone) * add simple accelerator example (esl-epfl/x-heep#446) (Davide Schiavone) * change python format for Bootrom (esl-epfl/x-heep#442) (Davide Schiavone) * fix memset bug (esl-epfl/x-heep#439) (Mattia Consani) * update cv32e40px with dual-read support (esl-epfl/x-heep#441) (Davide Schiavone) * Added X-HEEP Reference. (esl-epfl/x-heep#440) (Simone Machetti) * add w25q128 flash BSP (esl-epfl/x-heep#433) (Mattia Consani) * removed FEMU (esl-epfl/x-heep#437) (Simone Machetti) * update cve2 (esl-epfl/x-heep#284) (Davide Schiavone) * porting X-HEEP to the nexys FPGA (esl-epfl/x-heep#432) (Davide Schiavone) * Add standard and quad write functionality to flash model (esl- epfl/x-heep#426) (Mattia Consani) * revert :bug: introduced in last revendor of iceprog (davide schiavone) * Add `example_spi_host_quadIO` (esl-epfl/x-heep#401) (Mattia Consani) * fix minimal cfg with stack and heap size (esl-epfl/x-heep#431) (Davide Schiavone) * Update verible url (esl-epfl/x-heep#428) (David Mallasén Quintana) * expose DMA slots externally + external FIFO example (esl- epfl/x-heep#417) (grinningmosfet) * Updated the documentation on how to add external interrupts (esl- epfl/x-heep#427) (Juan-n-only) * add citation in readme (Davide Schiavone) * Fix run-blinky-freertos command (esl-epfl/x-heep#424) (jmiranda) * Compilation fix (esl-epfl/x-heep#422) (jmiranda) * add stack and heap size as parameters to mcu-gen (esl- epfl/x-heep#419) (Luigi Giuffrida) Signed-off-by: mbelda <11842513+mbelda@users.noreply.github.com> --- hw/vendor/esl_epfl_x_heep/.gitignore | 6 +- hw/vendor/esl_epfl_x_heep/Makefile | 71 +- hw/vendor/esl_epfl_x_heep/README.md | 167 +- .../esl_epfl_x_heep/core-v-mini-mcu.core | 117 +- .../docs/source/How_to/CompileMakefile | 34 +- .../docs/source/How_to/Debug.md | 82 +- .../docs/source/How_to/ExternalDevices.md | 52 + .../docs/source/How_to/ProgramFlash.md | 18 +- .../docs/source/How_to/SystemC.md | 16 + .../ao_peripheral_subsystem.sv | 9 +- .../hw/core-v-mini-mcu/core_v_mini_mcu.sv | 21 +- .../hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl | 21 +- .../hw/core-v-mini-mcu/cpu_subsystem.sv | 82 +- .../hw/core-v-mini-mcu/debug_subsystem.sv | 7 +- ..._epfl_nexys-a7-100t_board_files.lock.hjson | 14 + ...pfl_nexys-a7-100t_board_files.vendor.hjson | 17 + .../board.xml | 1301 +++++++++++++++ .../mig.prj | 157 ++ .../part0_pins.xml | 153 ++ .../preset.xml | 398 +++++ .../esl_epfl_zcu104_board_files.lock.hjson | 14 + .../esl_epfl_zcu104_board_files.vendor.hjson | 16 + .../esl_epfl_zcu104_board_files/board.xml | 657 ++++++++ .../part0_pins.xml | 228 +++ .../esl_epfl_zcu104_board_files/preset.xml | 446 +++++ .../hw/fpga/constraints/nexys/constraints.xdc | 2 +- .../hw/fpga/constraints/nexys/pin_assign.xdc | 258 +-- .../fpga/constraints/pynq-z2/constraints.xdc | 2 +- .../fpga/constraints/pynq-z2/pin_assign.xdc | 135 +- .../hw/fpga/constraints/zcu104/pin_assign.xdc | 99 ++ .../hw/fpga/prim_xilinx_clk.sv | 9 + .../hw/fpga/scripts/nexys/set_board.tcl | 3 + .../nexys/xilinx_generate_clk_wizard.tcl | 43 + .../hw/fpga/scripts/pynq-z2/set_board.tcl | 3 + .../xilinx_generate_clk_wizard.tcl | 3 - .../hw/fpga/scripts/zcu104/set_board.tcl | 3 + .../zcu104/xilinx_generate_clk_wizard.tcl | 40 + .../hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv | 56 +- .../esl_epfl_x_heep/hw/ip/boot_rom/README.md | 28 - .../esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S | 2 +- .../hw/ip/boot_rom/boot_rom.dump | 83 +- .../esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h | 46 +- .../hw/ip/boot_rom/boot_rom.sv | 46 +- .../hw/ip/boot_rom/environment.yml | 6 - .../esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py | 5 +- .../esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv | 4 +- .../hw/ip/i2s/rtl/i2s_ws_gen.sv | 2 +- .../hw/ip_examples/iffifo/data/iffifo.hjson | 76 + .../hw/ip_examples/iffifo/iffifo.core | 26 + .../hw/ip_examples/iffifo/iffifo.vlt | 15 + .../hw/ip_examples/iffifo/iffifo_gen.sh | 8 + .../hw/ip_examples/iffifo/rtl/iffifo.sv | 115 ++ .../ip_examples/iffifo/rtl/iffifo_reg_pkg.sv | 106 ++ .../ip_examples/iffifo/rtl/iffifo_reg_top.sv | 451 +++++ .../simple_accelerator.core | 22 + .../simple_accelerator/simple_accelerator.sv | 421 +++++ .../simple_accelerator/simple_accelerator.vlt | 10 + .../slow_memory/rtl/slow_memory.sv | 35 +- .../hw/system/x_heep_system.sv.tpl | 7 +- .../hw/vendor/esl_epfl_cv32e40px.core | 1 + .../hw/vendor/esl_epfl_cv32e40px.lock.hjson | 2 +- .../hw/vendor/esl_epfl_cv32e40px.vendor.hjson | 4 +- .../bhv/cv32e40px_instr_trace.svh | 12 +- .../esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv | 275 ++-- .../bhv/cv32e40px_tb_wrapper.sv | 30 +- .../bhv/include/cv32e40px_tracer_pkg.sv | 12 +- .../esl_epfl_cv32e40px/bhv/insn_trace.sv | 201 +-- .../bhv/pipe_freeze_trace.sv | 47 +- .../rtl/cv32e40px_controller.sv | 10 +- .../esl_epfl_cv32e40px/rtl/cv32e40px_core.sv | 54 +- .../rtl/cv32e40px_cs_registers.sv | 8 +- .../rtl/cv32e40px_ex_stage.sv | 76 +- .../rtl/cv32e40px_fp_wrapper.sv | 2 +- .../rtl/cv32e40px_id_stage.sv | 179 +- .../rtl/cv32e40px_register_file_ff.sv | 66 +- .../rtl/cv32e40px_register_file_latch.sv | 53 +- .../rtl/cv32e40px_x_disp.sv | 115 +- .../rtl/include/cv32e40px_core_v_xif_pkg.sv | 7 +- .../hw/dv/dpi/uartdpi/uartdpi.sv | 2 + .../openhwgroup_cv32e20/.readthedocs.yaml | 23 + .../bhv/cve2_sim_clock_gate.sv | 2 +- .../cv32e20_manifest.flist | 63 + .../openhwgroup_cv32e20/cve2_configs.yaml | 94 ++ .../vendor/openhwgroup_cv32e20/cve2_core.core | 115 ++ .../openhwgroup_cv32e20/cve2_icache.core | 22 + .../openhwgroup_cv32e20/cve2_multdiv.core | 28 + .../{ibex_pkg.core => cve2_pkg.core} | 6 +- .../vendor/openhwgroup_cv32e20/cve2_top.core | 115 ++ .../{cve2.core => cve2_top_tracing.core} | 111 +- .../openhwgroup_cv32e20/cve2_tracer.core | 20 + .../lint/verilator_waiver.vlt | 30 +- .../rtl/{ibex_alu.sv => cve2_alu.sv} | 8 +- ...anch_predict.sv => cve2_branch_predict.sv} | 4 +- ..._decoder.sv => cve2_compressed_decoder.sv} | 4 +- ...{ibex_controller.sv => cve2_controller.sv} | 182 +-- .../openhwgroup_cv32e20/rtl/cve2_core.f | 17 + .../rtl/{ibex_core.sv => cve2_core.sv} | 475 +----- .../rtl/{ibex_counter.sv => cve2_counter.sv} | 2 +- ...x_cs_registers.sv => cve2_cs_registers.sv} | 295 +--- .../rtl/{ibex_csr.sv => cve2_csr.sv} | 2 +- .../rtl/{ibex_decoder.sv => cve2_decoder.sv} | 73 +- .../{ibex_ex_block.sv => cve2_ex_block.sv} | 50 +- ...{ibex_fetch_fifo.sv => cve2_fetch_fifo.sv} | 32 +- .../{ibex_id_stage.sv => cve2_id_stage.sv} | 475 +----- .../openhwgroup_cv32e20/rtl/cve2_if_stage.sv | 278 ++++ ..._store_unit.sv => cve2_load_store_unit.sv} | 14 +- ...x_multdiv_fast.sv => cve2_multdiv_fast.sv} | 27 +- ...x_multdiv_slow.sv => cve2_multdiv_slow.sv} | 15 +- .../rtl/{ibex_pkg.sv => cve2_pkg.sv} | 126 +- .../rtl/{ibex_pmp.sv => cve2_pmp.sv} | 14 +- ...default.svh => cve2_pmp_reset_default.svh} | 0 ...etch_buffer.sv => cve2_prefetch_buffer.sv} | 68 +- ...er_file_ff.sv => cve2_register_file_ff.sv} | 34 +- .../rtl/cve2_sleep_unit.sv | 118 -- .../openhwgroup_cv32e20/rtl/cve2_top.sv | 272 ++++ ...bex_top_tracing.sv => cve2_top_tracing.sv} | 75 +- .../rtl/{ibex_tracer.sv => cve2_tracer.sv} | 14 +- ...{ibex_tracer_pkg.sv => cve2_tracer_pkg.sv} | 4 +- .../vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv | 69 + .../openhwgroup_cv32e20/rtl/ibex_core.f | 17 - .../rtl/ibex_dummy_instr.sv | 150 -- .../openhwgroup_cv32e20/rtl/ibex_icache.sv | 1165 ------------- .../openhwgroup_cv32e20/rtl/ibex_if_stage.sv | 750 --------- .../openhwgroup_cv32e20/rtl/ibex_lockstep.sv | 491 ------ .../rtl/ibex_register_file_fpga.sv | 83 - .../rtl/ibex_register_file_latch.sv | 164 -- .../openhwgroup_cv32e20/rtl/ibex_top.sv | 978 ----------- .../openhwgroup_cv32e20/rtl/ibex_wb_stage.sv | 214 --- .../lowrisc_ip/dv/sv/dv_utils/README.md | 0 .../dv/sv/dv_utils/dv_fcov_macros.core | 17 + .../dv/sv/dv_utils/dv_fcov_macros.svh | 112 ++ .../lowrisc_ip/dv/sv/dv_utils/dv_macros.core | 17 + .../lowrisc_ip/dv/sv/dv_utils/dv_macros.svh | 536 ++++++ .../dv/sv/dv_utils/dv_report_catcher.sv | 46 + .../dv/sv/dv_utils/dv_report_server.sv | 65 + .../dv/sv/dv_utils/dv_test_status.core | 17 + .../dv/sv/dv_utils/dv_test_status_pkg.sv | 31 + .../lowrisc_ip/dv/sv/dv_utils/dv_utils.core | 28 + .../lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv | 223 +++ .../lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv | 96 ++ .../hw/vendor/openhwgroup_cv32e40p.core | 1 + .../hw/vendor/openhwgroup_cv32e40p.lock.hjson | 2 +- .../vendor/openhwgroup_cv32e40p.vendor.hjson | 2 +- .../hw/vendor/openhwgroup_cv32e40p/.gitignore | 6 + .../bhv/cv32e40p_instr_trace.svh | 12 +- .../openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv | 333 ++-- .../bhv/cv32e40p_tb_wrapper.sv | 16 +- .../bhv/include/cv32e40p_tracer_pkg.sv | 12 +- .../openhwgroup_cv32e40p/bhv/insn_trace.sv | 205 +-- .../bhv/pipe_freeze_trace.sv | 47 +- .../rtl/cv32e40p_controller.sv | 12 +- .../openhwgroup_cv32e40p/rtl/cv32e40p_core.sv | 54 +- .../rtl/cv32e40p_cs_registers.sv | 10 +- .../rtl/cv32e40p_ex_stage.sv | 67 +- .../rtl/cv32e40p_fp_wrapper.sv | 2 +- .../rtl/cv32e40p_id_stage.sv | 14 +- .../hw/vendor/openhwgroup_cv32e40x.core | 1 + .../hw/vendor/openhwgroup_cve2.lock.hjson | 4 +- .../hw/vendor/openhwgroup_cve2.vendor.hjson | 29 +- .../0001-vendor-cv32e40px-Re-vendor.patch | 44 - .../patches/lowrisc_opentitan/uartdpi.patch | 8 +- .../openhwgroup_cv32e20/cv32e20_assert.patch | 12 + .../openhwgroup_cv32e20/cv32e20_core.patch | 12 + .../clk_mux_glitch_free.patch | 13 + .../0002-spiflash_valueargs.patch | 20 - .../patches/yosyshq_picorv32/spiflash.patch | 113 ++ ....-lowactive-reset.patch => spimemio.patch} | 0 .../src/clk_mux_glitch_free.sv | 2 +- .../hw/vendor/pulp_platform_fpnew.lock.hjson | 2 +- .../vendor/pulp_platform_fpnew.vendor.hjson | 2 +- .../hw/vendor/pulp_platform_gpio.core | 2 + .../vendor/pulp_platform_riscv_dbg.lock.hjson | 2 +- .../pulp_platform_riscv_dbg.vendor.hjson | 2 +- .../pulp_platform_riscv_dbg/CHANGELOG.md | 35 +- .../debug_rom/Makefile | 2 +- .../debug_rom/debug_rom.S | 9 +- .../debug_rom/debug_rom.h | 24 +- .../debug_rom/debug_rom.sv | 52 +- .../debug_rom/debug_rom_one_scratch.h | 24 +- .../debug_rom/debug_rom_one_scratch.sv | 44 +- .../debug_rom/gen_rom.py | 20 +- .../doc/debug-system.md | 10 +- .../pulp_platform_riscv_dbg/src/dm_csrs.sv | 110 +- .../pulp_platform_riscv_dbg/src/dm_mem.sv | 49 +- .../pulp_platform_riscv_dbg/src/dm_pkg.sv | 12 +- .../pulp_platform_riscv_dbg/src/dm_top.sv | 5 +- .../pulp_platform_riscv_dbg/src/dmi_jtag.sv | 33 +- .../src/dmi_jtag_tap.sv | 13 +- .../pulp_platform_tech_cells_generic.core | 1 + .../hw/vendor/waiver/lint/cv32e40p.vlt | 1 + .../hw/vendor/waiver/lint/cve2.vlt | 3 + .../hw/vendor/waiver/lint/riscv_dbg.vlt | 1 + .../yosyshq_picorv32/picosoc/spiflash.v | 53 +- .../esl_epfl_x_heep/linux_femu/README.md | 171 -- .../linux_femu/arm/openocd_cfg/README.md | 80 - .../arm/openocd_cfg/gpio_bitbang.cfg | 58 - .../linux_femu/arm/uart_enable/README.md | 57 - .../arm/uart_enable/uart_enable.dtbo | Bin 344 -> 0 bytes .../arm/uart_enable/uart_enable.dtsi | 18 - .../linux_femu/arm/uart_enable/uart_enable.sh | 5 - .../linux_femu/arm/virtual_flash/Makefile | 7 - .../arm/virtual_flash/OverlayControl.c | 103 -- .../arm/virtual_flash/OverlayControl.h | 27 - .../arm/virtual_flash/virtual_flash.cpp | 100 -- .../linux_femu/constraints/constraints.xdc | 1 - .../linux_femu/constraints/pin_assign.xdc | 73 - .../esl_epfl_x_heep/linux_femu/pad_cfg.hjson | 208 --- .../linux_femu/rtl/axi_address_hijacker.v | 331 ---- .../linux_femu/rtl/linux_femu.sv.tpl | 533 ------ .../xilinx_generate_processing_system.tcl | 118 -- hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson | 2 + .../esl_epfl_x_heep/mcu_cfg_minimal.hjson | 2 + hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt | 49 +- hw/vendor/esl_epfl_x_heep/sw/Makefile | 9 +- .../sw/applications/coremark/core_list_join.c | 612 +++++++ .../sw/applications/coremark/core_matrix.c | 376 +++++ .../sw/applications/coremark/core_portme.c | 104 ++ .../sw/applications/coremark/core_portme.h | 93 ++ .../sw/applications/coremark/core_state.c | 347 ++++ .../sw/applications/coremark/core_util.c | 266 +++ .../sw/applications/coremark/coremark.h | 211 +++ .../sw/applications/coremark/main.c | 459 ++++++ .../sw/applications/example_dma/main.c | 4 +- .../sw/applications/example_ext_memory/main.c | 128 ++ .../sw/applications/example_iffifo/main.c | 206 +++ .../example_matadd_interleaved/main.c | 84 + .../example_matadd_interleaved/matrixAdd32.h | 64 + .../example_matmul/gen_stimuly.py | 52 + .../sw/applications/example_matmul/main.c | 126 ++ .../applications/example_matmul/matrixMul8.h | 62 + .../example_simple_accelerator/main.c | 85 + .../example_spi_flash_write/main.c | 490 ------ .../sw/applications/example_spi_host/main.c | 265 --- .../applications/example_spi_host_dma/main.c | 312 ---- .../example_spi_host_dma_power_gate/main.c | 9 +- .../sw/applications/example_spi_read/buffer.h | 35 + .../sw/applications/example_spi_read/main.c | 300 ++++ .../sw/applications/example_spi_write/main.c | 351 ++++ .../applications/example_virtual_flash/main.c | 222 --- .../sw/applications/minver/arch.cfg | 67 + .../sw/applications/minver/beebsc.c | 177 ++ .../sw/applications/minver/beebsc.h | 65 + .../sw/applications/minver/board.c | 22 + .../sw/applications/minver/boardsupport.c | 21 + .../sw/applications/minver/boardsupport.h | 21 + .../sw/applications/minver/chip.c | 32 + .../sw/applications/minver/chipsupport.c | 73 + .../sw/applications/minver/chipsupport.h | 25 + .../sw/applications/minver/libminver.c | 292 ++++ .../sw/applications/minver/main.c | 50 + .../sw/applications/minver/support.h | 72 + .../esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c | 1449 +++++++++++++++++ .../sw/device/bsp/w25q/w25q128jw.h | 433 +++++ .../esl_epfl_x_heep/sw/device/lib/crt/crt0.S | 208 +-- .../sw/device/lib/drivers/dma/dma.c | 38 +- .../sw/device/lib/drivers/dma/dma.h | 4 +- .../sw/device/lib/drivers/gpio/gpio.c | 4 +- .../sw/device/lib/drivers/iffifo/iffifo.h | 56 + .../device/lib/drivers/iffifo/iffifo_regs.h | 47 + .../sw/device/lib/drivers/rv_plic/rv_plic.c | 2 +- .../sw/device/lib/drivers/spi_host/spi_host.h | 9 + .../sw/device/lib/runtime/core_v_mini_mcu.c | 37 + .../device/lib/runtime/core_v_mini_mcu.h.tpl | 4 + .../sw/device/lib/runtime/handler.c | 2 +- .../sw/device/lib/runtime/syscalls.c | 36 +- .../sw/device/target/nexys-a7-100t/x-heep.h | 30 + .../sw/device/target/systemc/x-heep.h | 30 + .../sw/device/target/zcu104/x-heep.h | 28 + .../esl_epfl_x_heep/sw/linker/link.ld.tpl | 55 +- .../sw/linker/link_flash_exec.ld.tpl | 6 +- .../sw/linker/link_flash_load.ld.tpl | 99 +- ...er-iceprog-custom-for-heep-with-gpio.patch | 136 +- .../vendor/yosyshq_icestorm/iceprog/iceprog.c | 64 +- .../tb/XHEEP_CmdLineOptions.cpp | 100 ++ .../tb/XHEEP_CmdLineOptions.hh | 24 + .../tb/core-v-mini-mcu-pynq-z2-bscan.cfg | 44 + .../esl_epfl_x_heep/tb/systemc_tb/Cache.h | 221 +++ .../tb/systemc_tb/MainMemory.h | 68 + .../tb/systemc_tb/MemoryRequest.h | 241 +++ hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp | 342 ++++ hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp | 81 +- hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl | 2 +- hw/vendor/esl_epfl_x_heep/tb/testharness.sv | 98 +- .../esl_epfl_x_heep/tb/testharness_pkg.sv | 27 +- hw/vendor/esl_epfl_x_heep/util/mcu_gen.py | 27 + hw/vendor/esl_epfl_x_heep/util/structs_gen.py | 3 +- .../esl_epfl_x_heep/x-heep-tb-utils.core | 13 + hw/vendor/eslepfl_x_heep.lock.hjson | 2 +- 288 files changed, 18886 insertions(+), 10886 deletions(-) create mode 100644 hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/set_board.tcl create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/set_board.tcl rename hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/{ => pynq-z2}/xilinx_generate_clk_wizard.tcl (86%) create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/set_board.tcl create mode 100644 hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt create mode 100755 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/{ibex_pkg.core => cve2_pkg.core} (73%) create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/{cve2.core => cve2_top_tracing.core} (52%) create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_alu.sv => cve2_alu.sv} (99%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_branch_predict.sv => cve2_branch_predict.sv} (98%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_compressed_decoder.sv => cve2_compressed_decoder.sv} (99%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_controller.sv => cve2_controller.sv} (82%) create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_core.sv => cve2_core.sv} (73%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_counter.sv => cve2_counter.sv} (99%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_cs_registers.sv => cve2_cs_registers.sv} (86%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_csr.sv => cve2_csr.sv} (98%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_decoder.sv => cve2_decoder.sv} (94%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_ex_block.sv => cve2_ex_block.sv} (80%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_fetch_fifo.sv => cve2_fetch_fifo.sv} (92%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_id_stage.sv => cve2_id_stage.sv} (60%) create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_load_store_unit.sv => cve2_load_store_unit.sv} (96%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_multdiv_fast.sv => cve2_multdiv_fast.sv} (96%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_multdiv_slow.sv => cve2_multdiv_slow.sv} (96%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_pkg.sv => cve2_pkg.sv} (74%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_pmp.sv => cve2_pmp.sv} (95%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_pmp_reset_default.svh => cve2_pmp_reset_default.svh} (100%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_prefetch_buffer.sv => cve2_prefetch_buffer.sv} (81%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_register_file_ff.sv => cve2_register_file_ff.sv} (66%) delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_top_tracing.sv => cve2_top_tracing.sv} (66%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_tracer.sv => cve2_tracer.sv} (98%) rename hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/{ibex_tracer_pkg.sv => cve2_tracer_pkg.sv} (99%) create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch delete mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch create mode 100644 hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch rename hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/{0001-async.-lowactive-reset.patch => spimemio.patch} (100%) delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/README.md delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtbo delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h delete mode 100755 hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl delete mode 100644 hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_iffifo/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c delete mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c delete mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host/main.c delete mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_read/buffer.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_read/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c delete mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h create mode 100644 hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h create mode 100644 hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp create mode 100644 hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.hh create mode 100644 hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg create mode 100644 hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h create mode 100644 hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h create mode 100644 hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h create mode 100644 hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp diff --git a/hw/vendor/esl_epfl_x_heep/.gitignore b/hw/vendor/esl_epfl_x_heep/.gitignore index a9a6e8c0..f2b85af8 100644 --- a/hw/vendor/esl_epfl_x_heep/.gitignore +++ b/hw/vendor/esl_epfl_x_heep/.gitignore @@ -7,16 +7,12 @@ build/ *.dis *.map *.do -.venv/* +.venv/ util/__pycache__/* # ignore apps output file run_verif_rtl_log.txt -#ignore femu generated hw -linux_femu/rtl/linux_femu.sv -.venv/ - # ignore the following hw automatically generated files environment.yml core-v-mini-mcu.upf diff --git a/hw/vendor/esl_epfl_x_heep/Makefile b/hw/vendor/esl_epfl_x_heep/Makefile index fa6e81ef..2d67386a 100644 --- a/hw/vendor/esl_epfl_x_heep/Makefile +++ b/hw/vendor/esl_epfl_x_heep/Makefile @@ -6,6 +6,7 @@ MAKE = make # Get the absolute path mkfile_path := $(shell dirname "$(realpath $(firstword $(MAKEFILE_LIST)))") +$(info $$You are executing from: $(mkfile_path)) # Include the self-documenting tool FILE=$(mkfile_path)/Makefile @@ -33,7 +34,7 @@ PROJECT ?= hello_world # Linker options are 'on_chip' (default),'flash_load','flash_exec','freertos' LINKER ?= on_chip -# Target options are 'sim' (default) and 'pynq-z2' +# Target options are 'sim' (default) and 'pynq-z2' and 'nexys-a7-100t' TARGET ?= sim MCU_CFG ?= mcu_cfg.hjson PAD_CFG ?= pad_cfg.hjson @@ -49,7 +50,7 @@ COMPILER_PREFIX ?= riscv32-unknown- ARCH ?= rv32imc # Path relative from the location of sw/Makefile from which to fetch source files. The directory of that file is the default value. -SOURCE ?= "." +SOURCE ?= $(".") # Simulation engines options are verilator (default) and questasim SIMULATOR ?= verilator @@ -57,6 +58,31 @@ SIMULATOR ?= verilator # Timeout for simulation, default 120 TIMEOUT ?= 120 +# Flash read address for testing, in hexadecimal format 0x0000 +FLASHREAD_ADDR ?= 0x0 +FLASHREAD_FILE ?= $(mkfile_path)/flashcontent.hex +FLASHREAD_BYTES ?= 256 + +#max address in the hex file, used to program the flash +ifeq ($(wildcard sw/build/main.hex),) + MAX_HEX_ADDRESS = 0 + MAX_HEX_ADDRESS_DEC = 0 + BYTES_AFTER_MAX_HEX_ADDRESS = 0 + FLASHRWITE_BYTES = 0 +else + MAX_HEX_ADDRESS = $(shell cat sw/build/main.hex | grep "@" | tail -1 | cut -c2-) + MAX_HEX_ADDRESS_DEC = $(shell printf "%d" 0x$(MAX_HEX_ADDRESS)) + BYTES_AFTER_MAX_HEX_ADDRESS = $(shell tac sw/build/main.hex | awk 'BEGIN {count=0} /@/ {print count; exit} {count++}') + FLASHRWITE_BYTES = $(shell echo $(MAX_HEX_ADDRESS_DEC) + $(BYTES_AFTER_MAX_HEX_ADDRESS)*16 | bc) +endif + + +#binary to store in flash memory +FLASHWRITE_FILE = $(mkfile_path)/sw/build/main.hex + +# Export variables to sub-makefiles +export + ## @section Conda conda: environment.yml conda env create -f environment.yml @@ -64,13 +90,6 @@ conda: environment.yml environment.yml: python-requirements.txt util/python-requirements2conda.sh -## @section Linux-Emulation - -## Generates FEMU -linux-femu-gen: mcu-gen - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir linux_femu/rtl/ --tpl-sv linux_femu/rtl/linux_femu.sv.tpl - $(MAKE) verible - ## @section Installation ## Generates mcu files core-v-mini-mcu files and build the design with fusesoc @@ -115,7 +134,7 @@ verible: ## Generates the build folder in sw using CMake to build (compile and linking) ## @param PROJECT= -## @param TARGET=sim(default),pynq-z2 +## @param TARGET=sim(default),systemc,pynq-z2,nexys-a7-100t,zcu104 ## @param LINKER=on_chip(default),flash_load,flash_exec ## @param COMPILER=gcc(default), clang ## @param COMPILER_PREFIX=riscv32-unknown-(default) @@ -134,10 +153,14 @@ app-compile-all: ## @section Simulation -## Verilator simulation +## Verilator simulation with C++ verilator-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --tool=verilator $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log +## Verilator simulation with SystemC +verilator-sim-sc: + $(FUSESOC) --cores-root . run --no-export --target=sim_sc --tool=verilator $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log + ## Questasim simulation questasim-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --tool=modelsim $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log @@ -161,6 +184,10 @@ vcs-sim: vcs-ams-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --flag "ams_sim" --tool=vcs $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log +## xcelium simulation +xcelium-sim: + $(FUSESOC) --cores-root . run --no-export --target=sim --tool=xcelium $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log + ## Generates the build output for helloworld application ## Uses verilator to simulate the HW model and run the FW ## UART Dumping in uart0.log to show recollected results @@ -175,7 +202,7 @@ run-helloworld: mcu-gen verilator-sim ## Uses verilator to simulate the HW model and run the FW ## UART Dumping in uart0.log to show recollected results run-blinkyfreertos: mcu-gen verilator-sim - $(MAKE) -C sw PROJECT=blinky_freertos TARGET=$(TARGET) LINKER=$(LINKER) COMPILER=$(COMPILER) COMPILER_PREFIX=$(COMPILER_PREFIX) ARCH=$(ARCH); + $(MAKE) -C sw PROJECT=example_freertos_blinky TARGET=$(TARGET) LINKER=$(LINKER) COMPILER=$(COMPILER) COMPILER_PREFIX=$(COMPILER_PREFIX) ARCH=$(ARCH); cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator; \ ./Vtestharness +firmware=../../../sw/build/main.hex; \ cat uart0.log; \ @@ -196,7 +223,7 @@ app-simulate-all: ## @section Vivado ## Builds (synthesis and implementation) the bitstream for the FPGA version using Vivado -## @param FPGA_BOARD=nexys-a7-100t,pynq-z2 +## @param FPGA_BOARD=nexys-a7-100t,pynq-z2,zcu104 ## @param FUSESOC_FLAGS=--flag= vivado-fpga: $(FUSESOC) --cores-root . run --no-export --target=$(FPGA_BOARD) $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildvivado.log @@ -204,6 +231,9 @@ vivado-fpga: vivado-fpga-nobuild: $(FUSESOC) --cores-root . run --no-export --target=$(FPGA_BOARD) $(FUSESOC_FLAGS) --setup openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildvivado.log +vivado-fpga-pgm: + $(MAKE) -C build/openhwgroup.org_systems_core-v-mini-mcu_0/$(FPGA_BOARD)-vivado pgm + ## @section ASIC ## Note that for this step you need to provide technology-dependent files (e.g., libs, constraints) asic: @@ -220,18 +250,27 @@ openroad-sky130: ## Read the id from the EPFL_Programmer flash flash-readid: - cd sw/vendor/yosyshq_icestorm/iceprog; \ + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ ./iceprog -d i:0x0403:0x6011 -I B -t; ## Loads the obtained binary to the EPFL_Programmer flash flash-prog: - cd sw/vendor/yosyshq_icestorm/iceprog; \ - ./iceprog -d i:0x0403:0x6011 -I B $(mkfile_path)/sw/build/main.hex; + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ + ./iceprog -a $(FLASHRWITE_BYTES) -d i:0x0403:0x6011 -I B $(FLASHWRITE_FILE); + +## Read the EPFL_Programmer flash +flash-read: + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ + ./iceprog -d i:0x0403:0x6011 -I B -o $(shell printf "%d" $(FLASHREAD_ADDR)) -R $(FLASHREAD_BYTES) $(FLASHREAD_FILE); ## Run openOCD w/ EPFL_Programmer openOCD_epflp: xterm -e openocd -f ./tb/core-v-mini-mcu-pynq-z2-esl-programmer.cfg; +## Run openOCD w/ BSCAN of the Pynq-Z2 board +openOCD_bscan: + xterm -e openocd -f ./tb/core-v-mini-mcu-pynq-z2-bscan.cfg; + ## Start GDB gdb_connect: $(MAKE) -C sw gdb_connect diff --git a/hw/vendor/esl_epfl_x_heep/README.md b/hw/vendor/esl_epfl_x_heep/README.md index 0e0130b7..c9705474 100644 --- a/hw/vendor/esl_epfl_x_heep/README.md +++ b/hw/vendor/esl_epfl_x_heep/README.md @@ -39,6 +39,21 @@ The block diagram below shows the `X-HEEP` MCU

+# Reference + +If you use X-HEEP in your academic work you can cite us: [X-HEEP Paper](https://arxiv.org/abs/2401.05548) + +``` +@misc{machetti2024xheep, + title={X-HEEP: An Open-Source, Configurable and Extendible RISC-V Microcontroller for the Exploration of Ultra-Low-Power Edge Accelerators}, + author={Simone Machetti and Pasquale Davide Schiavone and Thomas Christoph Müller and Miguel Peón-Quirós and David Atienza}, + year={2024}, + eprint={2401.05548}, + archivePrefix={arXiv}, + primaryClass={cs.AR} +} +``` + # Self-documented Makefile Note that under `util` folder, the file `generate-makefile-help` is employed to generate a self-documented helping output. In case of including any other target or command under the main `Makefile`, follow the same general and parameter descriptions as already provided for every target. Check the `help` output by doing `make` or `make help`. Moreover, **note that some of the parameters required for some of the targets are initiated with _default values_** @@ -59,7 +74,6 @@ It has been tested only on `Ubuntu 20`, and we know it does NOT WORK on `Ubuntu ## 2. Python - We rely on either (a) `miniconda`, or (b) `virtual environment` enviroment. Choose between `2.a` or `2.b` to setup your enviroment. @@ -79,7 +93,6 @@ You need to do it only the first time, then just activate the environment everyt conda activate core-v-mini-mcu ``` - ### 2.b Virtual Environment Install the python virtual environment just as: @@ -153,13 +166,36 @@ sudo apt-get install -y gtkwave We use version v0.0-1824-ga3b5bedf -See: [Install Verible](https://opentitan.org/guides/getting_started/index.html#step-6a-install-verible-optional) +See: [Install Verible](https://opentitan.org/guides/getting_started/index.html#step-7a-install-verible-optional) To format your RTL code type: ``` make verible ``` + +## Docker alternative + +A docker image containing all the required software dependancies is available on [github-packages](https://github.com/orgs/esl-epfl/packages/container/package/x-heep-toolchain). + +It is only required to install [`docker`](https://docs.docker.com/get-docker/) and pull the image. + +```bash +docker pull ghcr.io/esl-epfl/x-heep-toolchain:latest +``` + +Assuming that X-HEEP has been cloned to `X-HEEP-DIR=\absolute\path\to\x-HEEP\folder`, it is possible to directly run the docker mounting `X-HEEP-DIR` to the path `\workspace\x-heep` in the docker. + +```bash +docker run -it -v ${X-HEEP-DIR}:/workspace/x-heep ghcr.io/esl-epfl/x-heep-toolchain +``` + +Take care to indicate the absolute path to the local clone of X-HEEP, otherwise `docker` will not be able to properly nount the local folder in the container. + +All the command listed in the README can be execute in the docker container, except for: +- Simulation with Questasim and VCS, synthesis with Design Compiler (licenses are required to use these tools, so they are not installed in the container) +- OpenRoad flow is not installed in the container, so it is not possible to run the related make commands + ## Compilation Flow and Package Manager We use [FuseSoC](https://github.com/olofk/fusesoc) for all the tools we use. @@ -168,7 +204,7 @@ The `fusesoc` commands are inside the Makefile. # Adding external IPs -This repository relies on [Vendor](https://opentitan.org/book/util/doc/vendor.html) to add new IPs. The `vendor.py` script in the [`./util`](./util/) folder implements what is describeb above, while [this](./ExternalDevices.md) file contains additional information on how to connect external devices to the system. +This repository relies on [Vendor](https://opentitan.org/book/util/doc/vendor.html) to add new IPs. The `vendor.py` script in the [`./util`](./util/) folder implements what is described above, while [this](./docs/source/How_to/ExternalDevices.md) file contains additional information on how to connect external devices to the system. # Compiling with Makefile @@ -206,7 +242,6 @@ make mcu-gen MCU_CFG=mcu_cfg_minimal.hjson The `minimal` configuration is a work-in-progress, thus not all the APPs have been tested. - ## Compiling Software Don't forget to set the `RISCV` env variable to the compiler folder (without the `/bin` included). @@ -219,11 +254,11 @@ make app To run any other application, please use the following command with appropiate parameters: ``` -app PROJECT= TARGET=sim(default),pynq-z2 LINKER=on_chip(default),flash_load,flash_exec COMPILER=gcc(default),clang COMPILER_PREFIX=riscv32-unknown-(default) ARCH=rv32imc(default), +app PROJECT= TARGET=sim(default),systemc,pynq-z2,nexys-a7-100t,zcu104 LINKER=on_chip(default),flash_load,flash_exec COMPILER=gcc(default),clang COMPILER_PREFIX=riscv32-unknown-(default) ARCH=rv32imc(default), Params: - PROJECT (ex: , hello_world(default)) -- TARGET (ex: sim(default),pynq-z2) +- TARGET (ex: sim(default),systemc,pynq-z2,nexys-a7-100t,zcu104) - LINKER (ex: on_chip(default),flash_load,flash_exec) - COMPILER (ex: gcc(default),clang) - COMPILER_PREFIX (ex: riscv32-unknown-(default)) @@ -238,9 +273,8 @@ make app TARGET=pynq-z2 Or, if you use the OpenHW Group [GCC](https://www.embecosm.com/resources/tool-chain-downloads/#corev) compiler with CORE_PULP extensions, make sure to point the `RISCV` env variable to the OpenHW Group compiler, then just run: - ``` -make app COMPILER_PREFIX=riscv32-corev- ARCH=rv32imc_zicsr_zifencei_xcvhwlp1p0_xcvmem1p0_xcvmac1p0_xcvbi1p0_xcvalu1p0_xcvsimd1p0_xcvbitmanip1p0 +make app COMPILER_PREFIX=riscv32-corev- ARCH=rv32imc_zicsr_zifencei_xcvhwlp_xcvmem_xcvmac_xcvbi_xcvalu_xcvsimd_xcvbitmanip ``` This will create the executable file to be loaded into your target system (ASIC, FPGA, Simulation). @@ -264,13 +298,13 @@ Moreover, FreeRTOS is being fetch from 'https://github.com/FreeRTOS/FreeRTOS-Ker ## Simulating -This project supports simulation with Verilator, Synopsys VCS, and Siemens Questasim. +This project supports simulation with Verilator, Synopsys VCS, Siemens Questasim and Cadence Xcelium. It relies on `fusesoc` to handle multiple EDA tools and parameters. For example, if you want to set the `FPU` and `COREV_PULP` parameters of the `cv32e40p` CPU, you need to add next to your compilation command `FUSESOC_PARAM="--COREV_PULP=1 --FPU=1"` Below the different EDA examples commands. -### Compiling for Verilator +### Compiling for Verilator (C++ testbench) To simulate your application with Verilator, first compile the HDL: @@ -296,6 +330,38 @@ or to execute all these three steps type: make run-helloworld ``` +### Compiling for Verilator (SystemC testbench) + +To simulate your application with Verilator using `SystemC`, + +make sure you have `SystemC 2.3.3` installed, if not, find it [here](https://www.accellera.org/downloads/standards/systemc). + +Make sure to have the following env variables set: + +``` +export SYSTEMC_INCLUDE=/your_path_to_systemc/systemc/include/ +export SYSTEMC_LIBDIR=/your_path_to_systemc/systemc/lib-linux64/ +``` + +Compile the HDL: + +``` +make verilator-sim-sc +``` + +then, go to your target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim_sc-verilator +``` + +and type to run your compiled software: + +``` +./Vtestharness +firmware=../../../sw/build/main.hex +``` + +If you want to know what is special about the SystemC testbench, have a look [here](./docs/source/How_to/SystemC.md) ### Compiling for VCS @@ -337,7 +403,7 @@ cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs and running the same executable as for the digital simulation. Note that with Verdi you can view both the digital and the analog waveforms. -Additional instructions on how to run an analog / mixed-signal simulation of X-HEEP can be found [here](AnalogMixedSignal.md). To try out the simulation, we provide an example SPICE netlist of an simple 1-bit ADC created by us and exported from [xschem](https://xschem.sourceforge.io/stefan/index.html) and which uses the PTM 65nm bulk CMOS model from [https://ptm.asu.edu](https://ptm.asu.edu/). +Additional instructions on how to run an analog / mixed-signal simulation of X-HEEP can be found [here](./docs/source/How_to/AnalogMixedSignal.md). To try out the simulation, we provide an example SPICE netlist of an simple 1-bit ADC created by us and exported from [xschem](https://xschem.sourceforge.io/stefan/index.html) and which uses the PTM 65nm bulk CMOS model from [https://ptm.asu.edu](https://ptm.asu.edu/). ### Compiling for Questasim @@ -390,6 +456,26 @@ make run RUN_OPT=1 RUN_UPF=1 PLUSARGS="c firmware=../../../sw/build/main.hex" Questasim version must be >= Questasim 2020.4 +### Compiling for Xcelium + +To simulate your application with Xcelium, first compile the HDL: + +``` +make xcelium-sim +``` + +then, go to your target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-xcelium/ +``` + +and type to run your compiled software: + +``` +make run PLUSARGS="c firmware=../../../sw/build/main.hex" +``` + ### UART DPI To simulate the UART, we use the LowRISC OpenTitan [UART DPI](https://github.com/lowRISC/opentitan/tree/master/hw/dv/dpi/uartdpi). @@ -427,7 +513,6 @@ The available parameters are: * LINKER: `on_chip`(default), `flash_load` or `flash_exec` (can provide more than one) * TIMEOUT: Integer number of seconds (default 120) - #### Usage ##### Comands @@ -440,7 +525,7 @@ make app-simulate-all ``` Note that both commands allow the previous parameters to specify compiling or simulation options. E.g.: ``` -make app-simulate-all LINKER=on_chip SIMULATOR=questasim COMPILER=clang TIMEOUT=150 +make app-simulate-all LINKER=on_chip SIMULATOR=questasim COMPILER=clang TIMEOUT=150 ``` ##### Manually @@ -467,25 +552,27 @@ The success of the script is not required for merging of a PR. ## Debug -Follow the [Debug](./Debug.md) guide to debug core-v-mini-mcu. +Follow the [Debug](./docs/source/How_to/Debug.md) guide to debug core-v-mini-mcu. Alternatively, in case you are used to developing using Integrated Development Environments (IDEs), please check [the IDE readme](./IDEs.md). ## Execute From Flash -Follow the [ExecuteFromFlash](./ExecuteFromFlash.md) guide to exxecute code directly from the FLASH with modelsim, FPGA, or ASIC. +Follow the [ExecuteFromFlash](./docs/source/How_to/ExecuteFromFlash.md) guide to exxecute code directly from the FLASH with modelsim, FPGA, or ASIC. ## Emulation on Xilinx FPGAs -This project offers two different X-HEEP implementetions on the Xilinx FPGAs, called Standalone-FEMU and Linux-FEMU. +This project offers two different X-HEEP implementetions on Xilinx FPGAs, called Standalone and FEMU. -### Standalone-FEMU (Standalone Fpga EMUlation) +### Standalone In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA, and its input/output are connected to the available headers on the FPGA board. +Three FPGA boards are supported: the Xilinx Pynq-z2, Nexys-A7-100t, Zynq Ultrascale+ ZCU104. + Make sure you have the FPGA board files installed in your Vivado. -For example, for the Xilinx Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them: +For example, for the Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them: To build and program the bitstream for your FPGA with vivado, type: @@ -493,6 +580,18 @@ To build and program the bitstream for your FPGA with vivado, type: make vivado-fpga FPGA_BOARD=pynq-z2 ``` +or + +``` +make vivado-fpga FPGA_BOARD=nexys-a7-100t +``` + +or + +``` +make vivado-fpga FPGA_BOARD=zcu104 +``` + or add the flag `use_bscane_xilinx` to use the native Xilinx scanchain: ``` @@ -507,11 +606,23 @@ To program the bitstream, open Vivado, open --> Hardware Manager --> Open Target --> Autoconnect --> Program Device ``` -and choose the file `openhwgroup.org_systems_core-v-mini-mcu_0.bit` +and choose the file `openhwgroup.org_systems_core-v-mini-mcu_0.bit`. -To run SW, follow the [Debug](./Debug.md) guide +Or simply type: + +``` +bash vivado-fpga-pgm FPGA_BOARD=pynq-z2 +``` + +or + +``` +make vivado-fpga-pgm FPGA_BOARD=nexys-a7-100t +``` + +To run SW, follow the [Debug](./docs/source/How_to/Debug.md) guide to load the binaries with the HS2 cable over JTAG, -or follow the [ExecuteFromFlash](./ExecuteFromFlash.md) +or follow the [ExecuteFromFlash](./docs/source/How_to/ExecuteFromFlash.md) guide if you have a FLASH attached to the FPGA. Do not forget that the `pynq-z2` board requires you to have the ethernet cable attached to the board while running. @@ -520,7 +631,7 @@ For example, if you want to run your application using flash_exec, do as follow: compile your application, e.g. `make app PROJECT=example_matfadd TARGET=pynq-z2 ARCH=rv32imfc LINKER=flash_exec` -and then follow the [ExecuteFromFlash](./ExecuteFromFlash.md) to program the flash and set the boot buttons on the FPGA correctly. +and then follow the [ExecuteFromFlash](./docs/source/How_to/ExecuteFromFlash.md) to program the flash and set the boot buttons on the FPGA correctly. To look at the output of your printf, run in another terminal: @@ -528,13 +639,11 @@ To look at the output of your printf, run in another terminal: Please be sure to use the right `ttyUSB` number (you can discover it with `dmesg --time-format iso | grep FTDI` for example). +### FPGA EMUlation Platform (FEMU) -### Linux-FEMU (Linux Fpga EMUlation) - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA and Linux is run on the ARM-based processing system (PS) side of the same chip. - -Read the [following](./linux_femu/README.md) documentation to have more information about this implementation. +In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the Xilinx Zynq-7020 chip on the Pynq-Z2 board and Linux is run on the ARM-based processing system (PS) side of the same chip. +NOTE: This platform is not part of this repository, but you can access it with the following link: [FEMU](https://github.com/esl-epfl/x-heep-femu-sdk). # ASIC Implementation @@ -555,6 +664,6 @@ make asic ## OpenRoad support for SkyWater 130nm We are working on supporting OpenRoad and SkyWater 130nm PDK, please refer to the -[OpenRoadFlow](./OpenRoadFlow.md) page. This is not ready yet, it has not been tested. +[Implement on ASIC](./docs/source/How_to/ImplementASIC.md) page. This is not ready yet, it has not been tested. This relies on a fork of [edalize](https://github.com/davideschiavone/edalize) that contains templates for Design Compiler and OpenRoad. diff --git a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core index 7bebad44..dd439888 100644 --- a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core +++ b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core @@ -13,7 +13,7 @@ filesets: - x-heep::packages - openhwgroup.org:ip:cv32e40p - openhwgroup.org:ip:cv32e40x - - openhwgroup.org:ip:cve2 + - openhwgroup:cve2:cve2_top - esl_epfl:ip:cv32e40px - pulp-platform.org:ip:gpio - pulp-platform.org::common_cells @@ -102,7 +102,6 @@ filesets: ip-fpga: files: - - hw/fpga/scripts/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - hw/fpga/scripts/generate_sram.tcl: { file_type: tclSource } - hw/fpga/prim_xilinx_clk.sv: { file_type: systemVerilogSource } - hw/fpga/cv32e40p_xilinx_clock_gate.sv: { file_type: systemVerilogSource } @@ -115,15 +114,20 @@ filesets: - hw/fpga/pad_cell_bypass_input_xilinx.sv: { file_type: systemVerilogSource } - hw/fpga/pad_cell_bypass_output_xilinx.sv: { file_type: systemVerilogSource } - fpga-arm-emulation: - depend: - - pulp-platform.org::axi_spi_slave + ip-fpga-pynq-z2: + files: + - hw/fpga/scripts/pynq-z2/set_board.tcl: { file_type: tclSource } + - hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + + ip-fpga-nexys: files: - - linux_femu/scripts/xilinx_generate_processing_system.tcl: {file_type: tclSource} - - linux_femu/rtl/axi_address_hijacker.v: {file_type: verilogSource} - - linux_femu/rtl/linux_femu.sv: {file_type: systemVerilogSource} - - linux_femu/constraints/pin_assign.xdc: {file_type: xdc} - - linux_femu/constraints/constraints.xdc: {file_type: xdc} + - hw/fpga/scripts/nexys/set_board.tcl: { file_type: tclSource } + - hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + + ip-fpga-zcu104: + files: + - hw/fpga/scripts/zcu104/set_board.tcl: { file_type: tclSource } + - hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } ip-asic: depend: @@ -155,6 +159,11 @@ filesets: - hw/fpga/constraints/pynq-z2/constraints.xdc file_type: xdc + xdc-fpga-zcu104: + files: + - hw/fpga/constraints/zcu104/pin_assign.xdc + file_type: xdc + netlist-fpga: files: - build/openhwgroup.org_systems_core-v-mini-mcu_0/nexys-a7-100t-vivado/core_v_mini_mcu_xiling_postsynth.v @@ -194,6 +203,8 @@ filesets: tb-verilator: files: + - tb/XHEEP_CmdLineOptions.hh: { is_include_file: true } + - tb/XHEEP_CmdLineOptions.cpp - tb/tb_top.cpp file_type: cppSource @@ -202,6 +213,14 @@ filesets: - tb/tb_top.sv file_type: systemVerilogSource + tb-sc-verilator: + files: + - tb/XHEEP_CmdLineOptions.hh: { is_include_file: true } + - tb/XHEEP_CmdLineOptions.cpp + - tb/tb_sc_top.cpp + file_type: cppSource + + openroad_base_files: files: - flow/OpenROAD-flow-scripts/flow/Makefile : {file_type: Makefile} @@ -262,7 +281,15 @@ parameters: datatype: bool paramtype: vlogdefine default: false - FPGA_NETLIST: + SIM_SYSTEMC: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_NEXYS: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_ZCU104: datatype: bool paramtype: vlogdefine default: false @@ -302,6 +329,8 @@ targets: - files_rtl_generic - target_sim ? (rtl-simulation) - target_sim ? (tool_verilator? (files_verilator_waiver)) + - target_sim_sc ? (rtl-simulation) + - target_sim_sc ? (tool_verilator? (files_verilator_waiver)) toplevel: [core_v_mini_mcu] sim: @@ -314,13 +343,17 @@ targets: - tool_modelsim? (pre_patch_modelsim_Makefile) - tool_vcs? (cfile_uartdpi) - tool_vcs? (pre_build_remote_bitbang) + - tool_xcelium? (pre_build_remote_bitbang) + - tool_xcelium? (pre_build_uartdpi) - tool_verilator? (tb-verilator) - tool_modelsim? (tb-sv) - tool_vcs? (tb-sv) + - tool_xcelium? (tb-sv) - "!integrated_heep? (x_heep_system)" toplevel: - tool_modelsim? (tb_top) - tool_vcs? (tb_top) + - tool_xcelium? (tb_top) - tool_verilator? (testharness) hooks: pre_build: @@ -328,6 +361,8 @@ targets: - tool_modelsim? (pre_build_remote_bitbang) - tool_modelsim? (pre_patch_modelsim_Makefile) # this is required by Questa 2020 on - ams_sim? (pre_patch_vcs_ams_Makefile) + - tool_xcelium? (pre_build_uartdpi) + - tool_xcelium? (pre_build_remote_bitbang) parameters: - COREV_PULP - FPU @@ -342,6 +377,7 @@ targets: - -override_timescale 1ns/1ps - -suppress vlog-2583 - -suppress vlog-2577 + - -suppress vlog-2720 - -pedanticerrors - -define MODELSIM vsim_options: @@ -364,6 +400,12 @@ targets: - -LDFLAGS "-pthread -lutil" - +lint=TFIPC-L - -V + xcelium: + xrun_options: + - -vtimescale 1ns/10ps + - -sv_lib ../../../hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.so + - -sv_lib ../../../hw/vendor/pulp_platform_pulpissimo/rtl/tb/remote_bitbang/librbs.so + - -define XCELIUM verilator: mode: cc verilator_options: @@ -380,12 +422,48 @@ targets: - '-LDFLAGS "-pthread -lutil -lelf"' - "-Wall" + sim_sc: + <<: *default_target + default_tool: modelsim + filesets_append: + - tb-utils + - tool_verilator? (tb-sc-verilator) + - "!integrated_heep? (x_heep_system)" + toplevel: + - tool_verilator? (testharness) + parameters: + - COREV_PULP + - FPU + - JTAG_DPI + - X_EXT + - USE_EXTERNAL_DEVICE_EXAMPLE + - USE_UPF + - REMOVE_OBI_FIFO + - SIM_SYSTEMC=true + tools: + verilator: + mode: sc + verilator_options: + - '--sc' + - '--trace' + - '--trace-structs' + - '--trace-params' + - '--trace-max-array 1024' + - '--x-assign unique' + - '--x-initial unique' + - '--exe tb_sc_top.cpp' + - '-CFLAGS "-std=c++11 -Wall -g -fpermissive"' + - '-LDFLAGS "-pthread -lutil -lelf $(SYSTEMC_LIBDIR)/libsystemc.a"' + - "-Wall" + nexys-a7-100t: <<: *default_target default_tool: vivado description: Digilent Nexys-A7-100T Board filesets_append: + - x_heep_system - rtl-fpga + - ip-fpga-nexys - ip-fpga - xdc-fpga-nexys parameters: @@ -394,6 +472,7 @@ targets: - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO + - FPGA_NEXYS=true tools: vivado: part: xc7a100tcsg324-1 @@ -406,6 +485,7 @@ targets: filesets_append: - x_heep_system - rtl-fpga + - ip-fpga-pynq-z2 - ip-fpga - xdc-fpga-pynq-z2 parameters: @@ -419,27 +499,28 @@ targets: part: xc7z020clg400-1 toplevel: [xilinx_core_v_mini_mcu_wrapper] - pynq-z2-arm-emulation: + zcu104: <<: *default_target default_tool: vivado - description: TUL Pynq-Z2 Board + description: ZCU104 Evaluation Board filesets_append: - x_heep_system - rtl-fpga + - ip-fpga-zcu104 - ip-fpga - - fpga-arm-emulation + - xdc-fpga-zcu104 parameters: - COREV_PULP - FPU - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO + - FPGA_ZCU104=true tools: vivado: - part: xc7z020clg400-1 - jobs: 4 - toplevel: [linux_femu] - + part: xczu7ev-ffvc1156-2-e + toplevel: [xilinx_core_v_mini_mcu_wrapper] + asic_synthesis: <<: *default_target default_tool: design_compiler diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile index c0aab16c..2db8a17d 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile @@ -107,7 +107,6 @@ or to execute all these three steps type: make run-helloworld ``` - ### Compiling for VCS To simulate your application with VCS, first compile the HDL: @@ -238,7 +237,6 @@ The available parameters are: * LINKER: `on_chip`(default), `flash_load` or `flash_exec` (can provide more than one) * TIMEOUT: Integer number of seconds (default 120) - #### Usage ##### Comands @@ -286,15 +284,17 @@ Follow the [ExecuteFromFlash](./ExecuteFromFlash.md) guide to exxecute code dire ## Emulation on Xilinx FPGAs -This project offers two different X-HEEP implementetions on the Xilinx FPGAs, called Standalone-FEMU and Linux-FEMU. +This project offers two different X-HEEP implementetions on Xilinx FPGAs, called Standalone and FEMU. -### Standalone-FEMU (Standalone Fpga EMUlation) +### Standalone In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA, and its input/output are connected to the available headers on the FPGA board. +Two FPGA boards are supported: the Xilinx Pynq-z2 and Nexys-A7-100t. + Make sure you have the FPGA board files installed in your Vivado. -For example, for the Xilinx Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them: +For example, for the Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them: To build and program the bitstream for your FPGA with vivado, type: @@ -302,6 +302,12 @@ To build and program the bitstream for your FPGA with vivado, type: make vivado-fpga FPGA_BOARD=pynq-z2 ``` +or + +``` +make vivado-fpga FPGA_BOARD=nexys-a7-100t +``` + or add the flag `use_bscane_xilinx` to use the native Xilinx scanchain: ``` @@ -323,12 +329,22 @@ to load the binaries with the HS2 cable over JTAG, or follow the [ExecuteFromFlash](./ExecuteFromFlash.md) guide if you have a FLASH attached to the FPGA. - Do not forget that the `pynq-z2` board requires you to have the ethernet cable attached to the board while running. +For example, if you want to run your application using flash_exec, do as follow: + +compile your application, e.g. `make app PROJECT=example_matfadd TARGET=pynq-z2 ARCH=rv32imfc LINKER=flash_exec` + +and then follow the [ExecuteFromFlash](./ExecuteFromFlash.md) to program the flash and set the boot buttons on the FPGA correctly. + +To look at the output of your printf, run in another terminal: + +`picocom -b 9600 -r -l --imap lfcrlf /dev/ttyUSB2` + +Please be sure to use the right `ttyUSB` number (you can discover it with `dmesg --time-format iso | grep FTDI` for example). -### Linux-FEMU (Linux Fpga EMUlation) +### FPGA EMUlation Platform (FEMU) -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA and Linux is run on the ARM-based processing system (PS) side of the same chip. +In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the Xilinx Zynq-7020 chip on the Pynq-Z2 board and Linux is run on the ARM-based processing system (PS) side of the same chip. -Read the [following](./linux_femu/README.md) documentation to have more information about this implementation. +NOTE: This platform is not part of this repository, but you can access it with the following link: [FEMU](https://github.com/esl-epfl/x-heep-femu-sdk). diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md index 4ec743f3..2a5882f6 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md @@ -40,7 +40,7 @@ Now we are going to Simulate debugging with core-v-mini-mcu. In this setup, OpenOCD communicates with the remote bitbang server by means of DPIs. The remote bitbang server is simplemented in the folder ./hw/vendor/pulp_platform_pulpissimo/rtl/tb/remote_bitbang and it will be compiled using fusesoc. -### Verilator +### Verilator (C++ only) To simulate your application with Questasim using the remote_bitbang server, you need to compile you system adding the `JTAG DPI` functions: @@ -130,24 +130,86 @@ Transfer rate: 67 bytes/sec, 798 bytes/write. `gdb` automatically set the `program counter` to start from `_start`, check with: +Anytime you want to check the `disassemble`, just do: + + +``` +(gdb) disassemble +``` + +and get an output that look like: + ``` -(gdb) i r pc +Dump of assembler code for function _start: +=> 0x00000180 <+0>: auipc gp,0xd + 0x00000184 <+4>: addi gp,gp,964 # 0xd544 + 0x00000188 <+8>: auipc sp,0xf + 0x0000018c <+12>: addi sp,sp,-1080 # 0xed50 + 0x00000190 <+16>: lui a0,0x20000 + ... ``` -It should give you `0x180`. + +``` +(gdb) info reg pc +``` +Gives you the program counter. Now you can play with `gdb` e.g: Ask for the content of register `a0` ``` -(gdb) i r a0 +(gdb) info reg a0 ``` -or just run the entire execution with the continue command and then check the `uart0.log` to see the printed hello world string: + +or set it to `15` as: + +``` +(gdb) set $a0=15 +``` + +or just run the entire execution with the and then check the `uart0.log` to see the printed hello world string: ``` (gdb) continue ``` +If you want to reset the non-debug modules (as the CPU): + +``` +(gdb) monitor reset halt +``` + +Set a breakpoint to a specific instruction address: + +``` +(gdb) b *0x0000019c +Breakpoint 1 at 0x19c: file /x-heep/sw/device/lib/crt/crt0.S, line 38. +``` + +and continue the execution untill the breakpoint as: + +``` +(gdb) continue +``` + +Then check the breakpoint status: + +``` +(gdb) info b +Num Type Disp Enb Address What +1 breakpoint keep y 0x0000019c /x-heep/sw/device/lib/crt/crt0.S:38 + breakpoint already hit 1 time +``` + +and finally delete it: + +``` +(gdb) delete 1 +(gdb) info b +No breakpoints or watchpoints. +``` + You can also run all the gdb steps by running: ``` make gdb_connect MAINFILE= @@ -202,6 +264,16 @@ or with the EPFL Programmer also using this other command (**strongly recommende make openOCD_epflp ``` +or with the BSCAN of the Pynq-Z2 board using this command: +``` +openocd -f ./tb/core-v-mini-mcu-pynq-z2-bscan.cfg +``` + +or with the BSCAN of the Pynq-Z2 board also using this other command (**strongly recommended**): + +``` +make openOCD_bscan +``` If you get this error: diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md index 530b9817..bbc89bd3 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md @@ -97,3 +97,55 @@ For example, launching the script [`memcopy_periph_gen.sh`](./../../../hw/ip_exa 1. `memcopy_periph_reg_top.sv`: the register file module. It can be directly instantiated inside your peripheral RTL code (e.g., [`memcopy_periph.sv`](./../../../hw/ip_examples/memcopy_periph/rtl/memcopy_periph.sv)) and connected to the peripheral device controller(s). 2. `memcopy_periph_reg_pkg.sv`: SystemVerilog package containing the definitions used in the SystemVerilog module above. 3. `memcopy_periph_regs.h`: C/C++ header file defining the address offset of the peripheral configuration registers. Take a look at the C code [here](./../../../sw/applications/example_external_peripheral/memcopy_periph.c) for a usage example. + +## External Interrupts + +X-HEEP includes several empty external interrupts slots that can be assigned both in HW and SW. + +Firstly, connect your external device's interrupt to one of the slots of the `external_interrupt_vector` of X-HEEP: + +```systemverilog + +logic [core_v_mini_mcu_pkg::NEXT_INT-1:0] ext_intr_vector; + +always_comb begin +for (int i = 0; i < core_v_mini_mcu_pkg::NEXT_INT; i++) begin + ext_intr_vector[i] = 1'b0; // All interrupt lines set to zero by default +end +ext_intr_vector[0] = my_device_int; // Re-assign the interrupt lines used here +end + +x_heep_system #( + . . . +) x_heep_system_i ( + .intr_vector_ext_i(ext_intr_vector), + . . . +) + +``` + +Then, when initializing the PLIC system in software, do not forget to assign the corresponding interrupt ID to your custom handler. + +```C +#define MY_DEVICE_INTR EXT_INTR_0 + +void handler_irq_my_device(uint32_t id) { + my_device_intr_flag = 1; + // Do whatever you need here +} + +void main() { + plic_Init(); // Init the PLIC, this will clear all external interrupts assigned previously. + plic_irq_set_priority(MY_DEVICE_INTR, 1); // Set the priority of the external device's interrupt. + plic_irq_set_enabled(MY_DEVICE_INTR, kPlicToggleEnabled); // Enable the external device's interrupt. + plic_assign_external_irq_handler( MY_DEVICE_INTR, (void *) &handler_irq_my_device); // Assign a handler taht will be called when this interrupt is triggered. + + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level external interrupts + const uint32_t mask = 1 << 11;//IRQ_EXT_ENABLE_OFFSET; + CSR_SET_BITS(CSR_REG_MIE, mask); + + . . . +} +``` \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md index 98c09221..7ed89d24 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md @@ -92,30 +92,28 @@ Generate the C program you want to execute as described in the [ExecuteFromFlash then program the FLASH as: ``` -./iceprog -d i:0x0403:0x6011 -I B ../../../build/main.hex +make flash-prog ``` -You can also program the FLASH by running: +You can read the content of the FLASH as: ``` -make flash-prog MAINFILE= +make flash-read FLASHREAD_ADDR=0x10000 FLASHREAD_BYTES=16; xxd flashcontent.hex ``` -You can read the content of the FLASH as: +In this example, we are reading `16` bytes from the flash address `0x10000`. -``` -./iceprog -d i:0x0403:0x6011 -I B -r flash_content.txt -xxd flash_content.txt > flash_content.dump.txt -``` Now program the FPGA with the x-heep bitstream: ``` -cd build/openhwgroup.org_systems_core-v-mini-mcu_0/pynq-z2-vivado +make vivado-fpga-pgm FPGA_BOARD=pynq-z2 ``` -Remember to set the `boot_sel_i` and `execute_from_flash_i` switches to 1. +Remember to set the `boot_sel_i` and `execute_from_flash_i` switches to `1` if you `execute from flash`, +or just `boot_sel_i` to `1` and `execute_from_flash_i` to `0` if you `load from flash`. + Reset the logic (so the x-heep reset and not the bitstream reset) and enjoy. Additional note: To use the flash directly from X-HEEP, you first need to execute from the PC any iceprog command targeting the Flash. On the exit of any iceprog program, the FTDI pins will be set to high impedance. If this is not performed, the pins from the FTDI won't be on high impedance and the SPI signals cannot be driven from X-HEEP (or any other device). diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md new file mode 100644 index 00000000..1a1aad57 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md @@ -0,0 +1,16 @@ +# SystemC model + +Supporting SystemC model in `X-HEEP` is still a work-in-progress. +However, a simple example is provided in the SystemC testbench available in `tb/tb_sc_top.cpp`. + +When compiling the `X-HEEP` with Verilator using SystemC, the above testbench is used for simulation. +The testbench gets an `X-HEEP` external-memory `obi` master port to communicate with a SystemC memory model. + +Such model is very simple as meant to be an example and is provided in `tb/systemc_tb`. +For those who want to extend the functionality of `X-HEEP` with SystemC, such examples can be used as starting point. + +The SystemC modules leverages `TLM-2.0` as well as baseline SystemC functionalities. + +The `X-HEEP` `obi` port is connected to a `C++` direct-mapped cache who handles `hit` and `miss` with pre-defined latencies. +It uses `TLM-2.0` to communicate with the external SystemC memory on `miss` cache-transactions. +A module in SystemC then communicates with the RTL SystemC model compiled by Verilator to provides read/write data. \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv index 4a3073b8..504fed22 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv @@ -118,7 +118,10 @@ module ao_peripheral_subsystem // EXTERNAL PERIPH output reg_req_t ext_peripheral_slave_req_o, - input reg_rsp_t ext_peripheral_slave_resp_i + input reg_rsp_t ext_peripheral_slave_resp_i, + + input logic ext_dma_slot_tx_i, + input logic ext_dma_slot_rx_i ); import core_v_mini_mcu_pkg::*; @@ -364,13 +367,15 @@ module ao_peripheral_subsystem .intr_timer_expired_1_0_o(rv_timer_1_intr_o) ); - parameter DMA_TRIGGER_SLOT_NUM = 5; + parameter DMA_TRIGGER_SLOT_NUM = 7; logic [DMA_TRIGGER_SLOT_NUM-1:0] dma_trigger_slots; assign dma_trigger_slots[0] = spi_rx_valid; assign dma_trigger_slots[1] = spi_tx_ready; assign dma_trigger_slots[2] = spi_flash_rx_valid; assign dma_trigger_slots[3] = spi_flash_tx_ready; assign dma_trigger_slots[4] = i2s_rx_valid_i; + assign dma_trigger_slots[5] = ext_dma_slot_tx_i; + assign dma_trigger_slots[6] = ext_dma_slot_rx_i; dma #( .reg_req_t (reg_pkg::reg_req_t), diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv index 4a1ef2e9..45f21d2c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv @@ -315,7 +315,10 @@ module core_v_mini_mcu output logic [EXT_DOMAINS_RND-1:0] external_ram_banks_set_retentive_no, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_clkgate_en_no, - output logic [31:0] exit_value_o + output logic [31:0] exit_value_o, + + input logic ext_dma_slot_tx_i, + input logic ext_dma_slot_rx_i ); import core_v_mini_mcu_pkg::*; @@ -365,6 +368,7 @@ module core_v_mini_mcu // signals to debug unit logic debug_core_req; + logic debug_reset_n; // core logic core_sleep; @@ -456,7 +460,7 @@ module core_v_mini_mcu ) cpu_subsystem_i ( // Clock and Reset .clk_i, - .rst_ni(cpu_subsystem_rst_n), + .rst_ni(cpu_subsystem_rst_n && debug_reset_n), .core_instr_req_o(core_instr_req), .core_instr_resp_i(core_instr_resp), .core_data_req_o(core_data_req), @@ -485,6 +489,7 @@ module core_v_mini_mcu .jtag_tdi_i, .jtag_tdo_o, .debug_core_req_o(debug_core_req), + .debug_ndmreset_no(debug_reset_n), .debug_slave_req_i(debug_slave_req), .debug_slave_resp_o(debug_slave_resp), .debug_master_req_o(debug_master_req), @@ -496,7 +501,7 @@ module core_v_mini_mcu .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) ) system_bus_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .core_instr_req_i(core_instr_req), .core_instr_resp_o(core_instr_resp), .core_data_req_i(core_data_req), @@ -539,7 +544,7 @@ module core_v_mini_mcu .NUM_BANKS(core_v_mini_mcu_pkg::NUM_BANKS) ) memory_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .clk_gate_en_ni(memory_subsystem_clkgate_en_n), .ram_req_i(ram_slave_req), .ram_resp_o(ram_slave_resp), @@ -548,7 +553,7 @@ module core_v_mini_mcu ao_peripheral_subsystem ao_peripheral_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .slave_req_i(ao_peripheral_slave_req), .slave_resp_o(ao_peripheral_slave_resp), .boot_select_i, @@ -628,12 +633,14 @@ module core_v_mini_mcu .uart_intr_rx_parity_err_o(uart_intr_rx_parity_err), .i2s_rx_valid_i(i2s_rx_valid), .ext_peripheral_slave_req_o, - .ext_peripheral_slave_resp_i + .ext_peripheral_slave_resp_i, + .ext_dma_slot_tx_i, + .ext_dma_slot_rx_i ); peripheral_subsystem peripheral_subsystem_i ( .clk_i, - .rst_ni(peripheral_subsystem_rst_n), + .rst_ni(peripheral_subsystem_rst_n && debug_reset_n), .clk_gate_en_ni(peripheral_subsystem_clkgate_en_n), .slave_req_i(peripheral_slave_req), .slave_resp_o(peripheral_slave_resp), diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl index b4935df4..84255ec1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl @@ -69,7 +69,10 @@ ${pad.core_v_mini_mcu_interface} output logic [EXT_DOMAINS_RND-1:0] external_ram_banks_set_retentive_no, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_clkgate_en_no, - output logic [31:0] exit_value_o + output logic [31:0] exit_value_o, + + input logic ext_dma_slot_tx_i, + input logic ext_dma_slot_rx_i ); import core_v_mini_mcu_pkg::*; @@ -119,6 +122,7 @@ ${pad.core_v_mini_mcu_interface} // signals to debug unit logic debug_core_req; + logic debug_reset_n; // core logic core_sleep; @@ -210,7 +214,7 @@ ${pad.core_v_mini_mcu_interface} ) cpu_subsystem_i ( // Clock and Reset .clk_i, - .rst_ni(cpu_subsystem_rst_n), + .rst_ni(cpu_subsystem_rst_n && debug_reset_n), .core_instr_req_o(core_instr_req), .core_instr_resp_i(core_instr_resp), .core_data_req_o(core_data_req), @@ -239,6 +243,7 @@ ${pad.core_v_mini_mcu_interface} .jtag_tdi_i, .jtag_tdo_o, .debug_core_req_o(debug_core_req), + .debug_ndmreset_no(debug_reset_n), .debug_slave_req_i(debug_slave_req), .debug_slave_resp_o(debug_slave_resp), .debug_master_req_o(debug_master_req), @@ -250,7 +255,7 @@ ${pad.core_v_mini_mcu_interface} .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) ) system_bus_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .core_instr_req_i(core_instr_req), .core_instr_resp_o(core_instr_resp), .core_data_req_i(core_data_req), @@ -293,7 +298,7 @@ ${pad.core_v_mini_mcu_interface} .NUM_BANKS(core_v_mini_mcu_pkg::NUM_BANKS) ) memory_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .clk_gate_en_ni(memory_subsystem_clkgate_en_n), .ram_req_i(ram_slave_req), .ram_resp_o(ram_slave_resp), @@ -302,7 +307,7 @@ ${pad.core_v_mini_mcu_interface} ao_peripheral_subsystem ao_peripheral_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .slave_req_i(ao_peripheral_slave_req), .slave_resp_o(ao_peripheral_slave_resp), .boot_select_i, @@ -380,12 +385,14 @@ ${pad.core_v_mini_mcu_interface} .uart_intr_rx_parity_err_o(uart_intr_rx_parity_err), .i2s_rx_valid_i(i2s_rx_valid), .ext_peripheral_slave_req_o, - .ext_peripheral_slave_resp_i + .ext_peripheral_slave_resp_i, + .ext_dma_slot_tx_i, + .ext_dma_slot_rx_i ); peripheral_subsystem peripheral_subsystem_i ( .clk_i, - .rst_ni(peripheral_subsystem_rst_n), + .rst_ni(peripheral_subsystem_rst_n && debug_reset_n), .clk_gate_en_ni(peripheral_subsystem_clkgate_en_n), .slave_req_i(peripheral_slave_req), .slave_resp_o(peripheral_slave_resp), diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv index bbb62d75..256723f6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv @@ -59,21 +59,16 @@ module cpu_subsystem if (CPU_TYPE == cv32e20) begin : gen_cv32e20 - logic [4:0] rf_raddr_a, rf_raddr_b, rf_waddr_wb; - logic [31:0] rf_rdata_a, rf_rdata_b, rf_wdata_wb; - logic rf_we_wb; - - import ibex_pkg::*; - - ibex_core #( + cve2_top #( .DmHaltAddr(DM_HALTADDRESS), - .DmExceptionAddr(32'h0), - .DbgTriggerEn(1'b1), - .ResetAll(1'b1) + .DmExceptionAddr('0) ) cv32e20_i ( .clk_i (clk_i), .rst_ni(rst_ni), + .test_en_i(1'b0), + .ram_cfg_i('0), + .hart_id_i (32'h0), .boot_addr_i(BOOT_ADDR), @@ -94,79 +89,20 @@ module cpu_subsystem .data_rvalid_i(core_data_resp_i.rvalid), .data_err_i (1'b0), - .dummy_instr_id_o (), - .rf_raddr_a_o (rf_raddr_a), - .rf_raddr_b_o (rf_raddr_b), - .rf_waddr_wb_o (rf_waddr_wb), - .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb), - .rf_rdata_a_ecc_i (rf_rdata_a), - .rf_rdata_b_ecc_i (rf_rdata_b), - - .ic_tag_req_o (), - .ic_tag_write_o (), - .ic_tag_addr_o (), - .ic_tag_wdata_o (), - .ic_tag_rdata_i (), - .ic_data_req_o (), - .ic_data_write_o (), - .ic_data_addr_o (), - .ic_data_wdata_o (), - .ic_data_rdata_i (), - .ic_scr_key_valid_i(), - .irq_software_i(irq_i[3]), .irq_timer_i (irq_i[7]), .irq_external_i(irq_i[11]), - .irq_fast_i (irq_i[30:16]), - .irq_nm_i (irq_i[31]), - .irq_pending_o (), + .irq_fast_i (irq_i[31:16]), + .irq_nm_i (1'b0), - .debug_req_i(debug_req_i), + .debug_req_i (debug_req_i), .crash_dump_o(), - .double_fault_seen_o(), .fetch_enable_i(fetch_enable), - .alert_minor_o (), - .alert_major_o (), - .icache_inval_o(), - .core_sleep_o - ); - - cv32e40p_register_file #( - .ADDR_WIDTH(6) - ) cv32e20_register_file_i ( - // Clock and Reset - .clk (clk_i), - .rst_n(rst_ni), - - .scan_cg_en_i(1'b0), - - //Read port R1 - .raddr_a_i({1'b0, rf_raddr_a}), - .rdata_a_o(rf_rdata_a), - - //Read port R2 - .raddr_b_i({1'b0, rf_raddr_b}), - .rdata_b_o(rf_rdata_b), - - //Read port R3 - .raddr_c_i('0), - .rdata_c_o(), - // Write port W1 - .waddr_a_i({1'b0, rf_waddr_wb}), - .wdata_a_i(rf_wdata_wb), - .we_a_i(rf_we_wb), - - // Write port W2 - .waddr_b_i('0), - .wdata_b_i('0), - .we_b_i('0) + .core_sleep_o ); - - assign irq_ack_o = '0; assign irq_id_o = '0; diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv index 392c12ad..673c1b31 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv @@ -16,6 +16,7 @@ module debug_subsystem input logic jtag_tdi_i, output logic jtag_tdo_o, + output logic debug_ndmreset_no, output logic debug_core_req_o, input obi_req_t debug_slave_req_i, @@ -42,7 +43,9 @@ module debug_subsystem dm::dmi_resp_t dmi_resp; logic dmi_resp_ready; logic dmi_resp_valid; + logic ndmreset; + assign debug_ndmreset_no = ~ndmreset; dmi_jtag #( .IdcodeValue(JTAG_IDCODE) @@ -69,10 +72,10 @@ module debug_subsystem .clk_i (clk_i), .rst_ni (rst_ni), .testmode_i (1'b0), - .ndmreset_o (), + .ndmreset_o (ndmreset), .dmactive_o (), .debug_req_o (debug_core_req_o), - .unavailable_i(~(1'b01)), + .unavailable_i(~(1'b1)), .hartinfo_i (hartinfo), .slave_req_i (debug_slave_req_i.req), diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson new file mode 100644 index 00000000..3a3e601c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson @@ -0,0 +1,14 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This file is generated by the util/vendor script. Please do not modify it +// manually. + +{ + upstream: + { + url: https://github.com/esl-epfl/nexys-a7-100t_board_files.git + rev: 19e19ad6bd3b5a405d3e0ef98fee94e7e19e3bab + } +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson new file mode 100644 index 00000000..af1e9c40 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson @@ -0,0 +1,17 @@ +// Copyright 2022 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +{ + name: "esl_epfl_nexys_a7_100t_board_files", + target_dir: "esl_epfl_nexys_a7_100t_board_files", + + upstream: { + url: "https://github.com/esl-epfl/nexys-a7-100t_board_files.git", + rev: "19e19ad6bd3b5a405d3e0ef98fee94e7e19e3bab", + }, + + exclude_from_upstream: [ + "README.md" + ] +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml new file mode 100644 index 00000000..1ce62873 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml @@ -0,0 +1,1301 @@ + + + + + D.0 + +1.3 +Nexys A7-100T + + + + + Accelerometer control through SPI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DDR2 board interface, it can use MIG IP for connection. + + + + + + 16 DIP Switches + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dual 7 Seg LED Segments + + + + + + + + + + + + + + + + + + + + 16 LEDs + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 Push Buttons + + + + + + + + + + + + + + + + + Quad SPI Flash + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 RGB LEDs + + + + + + + + + + + + + + + + + + 7 Segment Display Anodes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Temperature Sensor connected to I2C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + USB-to-UART Bridge, which allows a connection to a host computer with a USB port + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Accelerometer controlled through SPI + + + 256 MB Onboard DDR Memory + + + + + + + 16 Switches + + + 7 Segment Display Segment Control + + + 16 LEDs + + + Push Buttons 5 to 0 {Down Right Left Up Center} + + + QSPI Flash + + + Onboard Reset Button + + + 2 RGB LEDs + + + 7 Segment Display Anodes + + + 100 MHz Single-Ended System Clock + + + SPI Controlled Temperature Sensor + + + USB-to-UART Bridge, which allows a connection to a host computer with a USB port + + + Pmod Connector JA + + + Pmod Connector JB + + + Pmod Connector JC + + + Pmod Connector JD + + + Pmod Connector JXADC + + + + + + + + + + + + + + + + + + + + + Onboard MicroSD Card Slot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj new file mode 100644 index 00000000..301f5834 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj @@ -0,0 +1,157 @@ + + + + + + + + design_1_mig_7series_0_0 + + 1 + + 1 + + OFF + + 1024 + + ON + + Enabled + + xc7a100t-csg324/-1 + + 4.2 + + Single-Ended + + No Buffer + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + 7a/xc7a50t-csg324 + + + + DDR2_SDRAM/Components/MT47H64M16HR-25E + 3077 + 1.8V + 4:1 + 99.997 + 1 + 1200 + 6.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Strict + 4 + FALSE + + 13 + 10 + 3 + 134217728 + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + Sequential + 5 + Normal + No + Fast exit + 5 + Enable-Normal + Fullstrength + Enable + 1 + 50ohms + 0 + OCD Exit + Enable + Disable + Enable + AXI + + RD_PRI_REG + 27 + 128 + 4 + 0 + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml new file mode 100644 index 00000000..43f20b5e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml new file mode 100644 index 00000000..7128ccee --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson new file mode 100644 index 00000000..a05740cc --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson @@ -0,0 +1,14 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This file is generated by the util/vendor script. Please do not modify it +// manually. + +{ + upstream: + { + url: https://github.com/esl-epfl/zcu104_board_files.git + rev: 53e4affbaeec73809304940be8f5351ae147227a + } +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson new file mode 100644 index 00000000..69028826 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson @@ -0,0 +1,16 @@ +// Copyright 2023 David Mallasén Quintana +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +{ + name: "esl_epfl_zcu104_board_files", + target_dir: "esl_epfl_zcu104_board_files", + + upstream: { + url: "https://github.com/esl-epfl/zcu104_board_files.git", + rev: "53e4affbaeec73809304940be8f5351ae147227a", + }, + + exclude_from_upstream: [ + "README.md" + ] +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml new file mode 100644 index 00000000..2206a918 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml @@ -0,0 +1,657 @@ + + + + + + ZCU104 Board File Image + + + + + RevA + RevB + RevC + + + 1.0 + + Zynq UltraScale+ ZCU104 Evaluation Board + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FPGA part on the board + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DDR4 board interface, it can use DDR4 controller IP for connection. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4-Position User DIP Switch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SI570 based User programmable differential 300 MHz Clock. Can be used for DDR4 input system clock + + + + + + + PL UART + + + + + + + + PL I2C + + + + + 2GB DDR4 SDRAM memory SODIMM + + + + + + + + CPU Reset Push Button, Active High + + + + DIP Switches 3 to 0 + + + + LEDs, 3 to 0, Active High + + + + Push Buttons, 3 to 0, Active High + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml new file mode 100644 index 00000000..e5d6301c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml new file mode 100644 index 00000000..b8d89084 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml @@ -0,0 +1,446 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc index 5a3c1c4b..ed3a6e89 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc @@ -1 +1 @@ -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets x_heep_system_i/pad_ring_i/pad_clk_i/xilinx_iobuf_i/O] +create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk_i}]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc index 53e0eb8f..be620356 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc @@ -1,213 +1,83 @@ -## This file is a general .xdc for the Nexys A7-100T -## To use it in a project: -## - uncomment the lines corresponding to used pins -## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 ## Clock signal -set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk_i }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz -#create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}]; +set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports {clk_i}]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz -##Switches -set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { jtag_trst_ni }]; #IO_L24N_T3_RS0_15 Sch=sw[0] -set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { execute_from_flash_i }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1] -set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { boot_select_i }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2] -#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { SW[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3] -#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { SW[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4] -#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { SW[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5] -#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { SW[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6] -#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { SW[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7] -#set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { SW[8] }]; #IO_L24N_T3_34 Sch=sw[8] -#set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { SW[9] }]; #IO_25_34 Sch=sw[9] -#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { SW[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10] -#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { SW[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11] -#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { SW[12] }]; #IO_L24P_T3_35 Sch=sw[12] -#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { SW[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13] -#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { SW[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14] -#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { SW[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15] +set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports {rst_i}]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn ## LEDs -set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { rst_led }]; #IO_L18P_T2_A24_15 Sch=led[0] -set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { clk_led }]; #IO_L24P_T3_RS1_15 Sch=led[1] -set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { exit_value_o }]; #IO_L17N_T2_A25_15 Sch=led[2] -set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { exit_valid_o }]; #IO_L8P_T1_D11_14 Sch=led[3] -set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[29] }]; #IO_L7P_T1_D09_14 Sch=led[4] -#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[30] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5] -#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[31] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6] -#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7] -#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { LED[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8] -#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { LED[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9] -#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { LED[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10] -#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11] -#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12] -#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { LED[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13] -#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { LED[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14] -#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { LED[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15] - -## RGB LEDs -#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { LED16_B }]; #IO_L5P_T0_D06_14 Sch=led16_b -#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { LED16_G }]; #IO_L10P_T1_D14_14 Sch=led16_g -#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { LED16_R }]; #IO_L11P_T1_SRCC_14 Sch=led16_r -#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { LED17_B }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led17_b -#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { LED17_G }]; #IO_0_14 Sch=led17_g -#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { LED17_R }]; #IO_L11N_T1_SRCC_14 Sch=led17_r - -##7 segment display -set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[8] }]; #IO_L24N_T3_A00_D16_14 Sch=ca -set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[9] }]; #IO_25_14 Sch=cb -set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[10] }]; #IO_25_15 Sch=cc -set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[11] }]; #IO_L17P_T2_A26_15 Sch=cd -set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[12] }]; #IO_L13P_T2_MRCC_14 Sch=ce -set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[13] }]; #IO_L19P_T3_A10_D26_14 Sch=cf -set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[14] }]; #IO_L4P_T0_D04_14 Sch=cg -set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[15] }]; #IO_L19N_T3_A21_VREF_15 Sch=dp -set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[16] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0] -set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[17] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1] -set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[18] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2] -set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[19] }]; #IO_L19P_T3_A22_15 Sch=an[3] -set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[20] }]; #IO_L8N_T1_D12_14 Sch=an[4] -set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[21] }]; #IO_L14P_T2_SRCC_14 Sch=an[5] -set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[22] }]; #IO_L23P_T3_35 Sch=an[6] -set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[23] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7] +set_property -dict {PACKAGE_PIN V11 IOSTANDARD LVCMOS33} [get_ports {rst_led_o}]; +set_property -dict {PACKAGE_PIN J13 IOSTANDARD LVCMOS33} [get_ports {clk_led_o}]; +set_property -dict {PACKAGE_PIN N14 IOSTANDARD LVCMOS33} [get_ports {exit_valid_o}]; +set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports {exit_value_o}]; +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_led_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_out_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_led_OBUF] -##CPU Reset Button -set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { rst_i }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn - -##Buttons -set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[24] }]; #IO_L9P_T1_DQS_14 Sch=btnc -set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[25] }]; #IO_L4N_T0_D05_14 Sch=btnu -set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[26] }]; #IO_L12P_T1_MRCC_14 Sch=btnl -set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[27] }]; #IO_L10N_T1_D15_14 Sch=btnr -set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[28] }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd +##Switches +set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports {execute_from_flash_i}]; #Sch=sw[1] +set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS33} [get_ports {boot_select_i}]; #Sch=sw[2] +##Switches +set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {jtag_trst_ni}]; #IO_L24N_T3_RS0_15 Sch=sw[0] ##Pmod Headers ##Pmod Header JA -set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[0] }]; #IO_L20N_T3_A19_15 Sch=ja[1] -set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[1] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] -set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[2] }]; #IO_L21P_T3_DQS_15 Sch=ja[3] -set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[3] }]; #IO_L18N_T2_A23_15 Sch=ja[4] -set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[4] }]; #IO_L16N_T2_A27_15 Sch=ja[7] -set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[5] }]; #IO_L16P_T2_A28_15 Sch=ja[8] -set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[6] }]; #IO_L22N_T3_A16_15 Sch=ja[9] -set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[7] }]; #IO_L22P_T3_A17_15 Sch=ja[10] - -##Pmod Header JB -#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { JB[1] }]; #IO_L1P_T0_AD0P_15 Sch=jb[1] -#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { JB[2] }]; #IO_L14N_T2_SRCC_15 Sch=jb[2] -#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { JB[3] }]; #IO_L13N_T2_MRCC_15 Sch=jb[3] -set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { clk_out }]; #IO_L15P_T2_DQS_15 Sch=jb[4] -set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { jtag_tms_i }]; #IO_L11N_T1_SRCC_15 Sch=jb[7] -set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdi_i }]; #IO_L5P_T0_AD9P_15 Sch=jb[8] -set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdo_o }]; #IO_0_15 Sch=jb[9] -set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { jtag_tck_i }]; #IO_L13P_T2_MRCC_15 Sch=jb[10] +set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_csb_o}]; #IO_L20N_T3_A19_15 Sch=ja[1] +set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sck_o}]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] +set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}]; #IO_L21P_T3_DQS_15 Sch=ja[3] +set_property -dict {PACKAGE_PIN G17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}]; #IO_L18N_T2_A23_15 Sch=ja[4] +set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}]; #IO_L16N_T2_A27_15 Sch=ja[7] +set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}]; #IO_L16P_T2_A28_15 Sch=ja[8] +#set_property -dict {PACKAGE_PIN F18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}]; #IO_L22N_T3_A16_15 Sch=ja[9] +#set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}]; #IO_L22P_T3_A17_15 Sch=ja[10] ##Pmod Header JC -#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { JC[1] }]; #IO_L23N_T3_35 Sch=jc[1] -#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { JC[2] }]; #IO_L19N_T3_VREF_35 Sch=jc[2] -set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { i2c_scl_io }]; #IO_L22N_T3_35 Sch=jc[3] -set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { i2c_sda_io }]; #IO_L19P_T3_35 Sch=jc[4] -#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { JC[7] }]; #IO_L6P_T0_35 Sch=jc[7] -set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { spi_csb_o }]; #IO_L22P_T3_35 Sch=jc[8] -#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { JC[9] }]; #IO_L21P_T3_DQS_35 Sch=jc[9] -#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { JC[10] }]; #IO_L5P_T0_AD13P_35 Sch=jc[10] - -##Pmod Header JD -#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { JD[1] }]; #IO_L21N_T3_DQS_35 Sch=jd[1] -#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { JD[2] }]; #IO_L17P_T2_35 Sch=jd[2] -#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { JD[3] }]; #IO_L17N_T2_35 Sch=jd[3] -#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { JD[4] }]; #IO_L20N_T3_35 Sch=jd[4] -#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { JD[7] }]; #IO_L15P_T2_DQS_35 Sch=jd[7] -#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { JD[8] }]; #IO_L20P_T3_35 Sch=jd[8] -#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { JD[9] }]; #IO_L15N_T2_DQS_35 Sch=jd[9] -#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { JD[10] }]; #IO_L13N_T2_MRCC_35 Sch=jd[10] +set_property -dict {PACKAGE_PIN K1 IOSTANDARD LVCMOS33} [get_ports {spi_csb_o}]; #IO_L23N_T3_35 Sch=jc[1] +set_property -dict {PACKAGE_PIN F6 IOSTANDARD LVCMOS33} [get_ports {spi_sck_o}]; #IO_L19N_T3_VREF_35 Sch=jc[2] +set_property -dict {PACKAGE_PIN J2 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}]; #IO_L22N_T3_35 Sch=jc[3] +set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}]; #IO_L19P_T3_35 Sch=jc[4] +set_property -dict {PACKAGE_PIN E7 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}]; #IO_L6P_T0_35 Sch=jc[7] +set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}]; #IO_L22P_T3_35 Sch=jc[8] +#set_property -dict {PACKAGE_PIN J4 IOSTANDARD LVCMOS33} [get_ports {clk_out}]; #IO_L21P_T3_DQS_35 Sch=jc[9] +#set_property -dict {PACKAGE_PIN E6 IOSTANDARD LVCMOS33} [get_ports {JC[10]}]; #IO_L5P_T0_AD13P_35 Sch=jc[10] -##Pmod Header JXADC -#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { XA_N[1] }]; #IO_L9N_T1_DQS_AD3N_15 Sch=xa_n[1] -#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { XA_P[1] }]; #IO_L9P_T1_DQS_AD3P_15 Sch=xa_p[1] -set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[2] }]; #IO_L8N_T1_AD10N_15 Sch=xa_n[2] -set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[0] }]; #IO_L8P_T1_AD10P_15 Sch=xa_p[2] -#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { XA_N[3] }]; #IO_L7N_T1_AD2N_15 Sch=xa_n[3] -set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[1] }]; #IO_L7P_T1_AD2P_15 Sch=xa_p[3] -set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[3] }]; #IO_L10N_T1_AD11N_15 Sch=xa_n[4] -set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { spi_sck_o }]; #IO_L10P_T1_AD11P_15 Sch=xa_p[4] - -##VGA Connector -#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0] -#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1] -#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2] -#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3] -#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0] -#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1] -#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2] -#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3] -#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0] -#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[1] }]; #IO_L4N_T0_35 Sch=vga_b[1] -#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2] -#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[3] }]; #IO_L4P_T0_35 Sch=vga_b[3] -#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { VGA_HS }]; #IO_L4P_T0_15 Sch=vga_hs -#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { VGA_VS }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs - -##Micro SD Connector -#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { SD_RESET }]; #IO_L14P_T2_SRCC_35 Sch=sd_reset -#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { SD_CD }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd -#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { SD_SCK }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sd_sck -#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { SD_CMD }]; #IO_L16N_T2_35 Sch=sd_cmd -#set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[0] }]; #IO_L16P_T2_35 Sch=sd_dat[0] -#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[1] }]; #IO_L18N_T2_35 Sch=sd_dat[1] -#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[2] }]; #IO_L18P_T2_35 Sch=sd_dat[2] -#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[3] }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3] - -##Accelerometer -#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { ACL_MISO }]; #IO_L11P_T1_SRCC_15 Sch=acl_miso -#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { ACL_MOSI }]; #IO_L5N_T0_AD9N_15 Sch=acl_mosi -#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { ACL_SCLK }]; #IO_L14P_T2_SRCC_15 Sch=acl_sclk -#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { ACL_CSN }]; #IO_L12P_T1_MRCC_15 Sch=acl_csn -#set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports { ACL_INT[1] }]; #IO_L2P_T0_AD8P_15 Sch=acl_int[1] -#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { ACL_INT[2] }]; #IO_L20P_T3_A20_15 Sch=acl_int[2] - -##Temperature Sensor -#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { TMP_SCL }]; #IO_L1N_T0_AD0N_15 Sch=tmp_scl -#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { TMP_SDA }]; #IO_L12N_T1_MRCC_15 Sch=tmp_sda -#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { TMP_INT }]; #IO_L6N_T0_VREF_15 Sch=tmp_int -#set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { TMP_CT }]; #IO_L2N_T0_AD8N_15 Sch=tmp_ct - -##Omnidirectional Microphone -#set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { M_CLK }]; #IO_25_35 Sch=m_clk -#set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { M_DATA }]; #IO_L24N_T3_35 Sch=m_data -#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { M_LRSEL }]; #IO_0_35 Sch=m_lrsel +##USB-RS232 Interface +set_property -dict {PACKAGE_PIN C4 IOSTANDARD LVCMOS33} [get_ports {uart_rx_i}]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {uart_tx_o}]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out -##PWM Audio Amplifier -#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { AUD_PWM }]; #IO_L4N_T0_15 Sch=aud_pwm -#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { AUD_SD }]; #IO_L6P_T0_15 Sch=aud_sd +##Pmod Header JB +#set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS33} [get_ports {JB[1]}]; #IO_L1P_T0_AD0P_15 Sch=jb[1] +#set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports {JB[2]}]; #IO_L14N_T2_SRCC_15 Sch=jb[2] +#set_property -dict {PACKAGE_PIN G16 IOSTANDARD LVCMOS33} [get_ports {uart_tx_o}]; #IO_L13N_T2_MRCC_15 Sch=jb[3] +#set_property -dict {PACKAGE_PIN H14 IOSTANDARD LVCMOS33} [get_ports {uart_rx_i}]; #IO_L15P_T2_DQS_15 Sch=jb[4] +set_property -dict {PACKAGE_PIN E16 IOSTANDARD LVCMOS33} [get_ports {jtag_tms_i}]; #IO_L11N_T1_SRCC_15 Sch=jb[7] +set_property -dict {PACKAGE_PIN F13 IOSTANDARD LVCMOS33} [get_ports {jtag_tdi_i}]; #IO_L5P_T0_AD9P_15 Sch=jb[8] +set_property -dict {PACKAGE_PIN G13 IOSTANDARD LVCMOS33} [get_ports {jtag_tdo_o}]; #IO_0_15 Sch=jb[9] +set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports {jtag_tck_i}]; #IO_L13P_T2_MRCC_15 Sch=jb[10] -##USB-RS232 Interface -set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_rx_i }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in -set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_tx_o }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out -#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { UART_CTS }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts -#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { UART_RTS }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts +## LEDs +set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[1]}]; +set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[2]}]; +set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[3]}]; +set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}]; +set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}]; +set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}]; +set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}]; +set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}]; +set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}]; +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}]; +set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}]; -##USB HID (PS/2) -#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { PS2_CLK }]; #IO_L13P_T2_MRCC_35 Sch=ps2_clk -#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { PS2_DATA }]; #IO_L10N_T1_AD15N_35 Sch=ps2_data +##Buttons +set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}]; #IO_L9P_T1_DQS_14 Sch=btnc +set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}]; #IO_L4N_T0_D05_14 Sch=btnu +set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}]; #IO_L12P_T1_MRCC_14 Sch=btnl +set_property -dict {PACKAGE_PIN M17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}]; #IO_L10N_T1_D15_14 Sch=btnr +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}]; #IO_L9N_T1_DQS_D13_14 Sch=btnd -##SMSC Ethernet PHY -#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { ETH_MDC }]; #IO_L11P_T1_SRCC_16 Sch=eth_mdc -#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { ETH_MDIO }]; #IO_L14N_T2_SRCC_16 Sch=eth_mdio -#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { ETH_RSTN }]; #IO_L10P_T1_AD15P_35 Sch=eth_rstn -#set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { ETH_CRSDV }]; #IO_L6N_T0_VREF_16 Sch=eth_crsdv -#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXERR }]; #IO_L13N_T2_MRCC_16 Sch=eth_rxerr -#set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXD[0] }]; #IO_L13P_T2_MRCC_16 Sch=eth_rxd[0] -#set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXD[1] }]; #IO_L19N_T3_VREF_16 Sch=eth_rxd[1] -#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXEN }]; #IO_L11N_T1_SRCC_16 Sch=eth_txen -#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXD[0] }]; #IO_L14P_T2_SRCC_16 Sch=eth_txd[0] -#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXD[1] }]; #IO_L12N_T1_MRCC_16 Sch=eth_txd[1] -#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { ETH_REFCLK }]; #IO_L11P_T1_SRCC_35 Sch=eth_refclk -#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { ETH_INTN }]; #IO_L12P_T1_MRCC_16 Sch=eth_intn +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] -##Quad SPI Flash -#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] -#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] -#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] -#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] -#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { QSPI_CSN }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc index 5a3c1c4b..ed3a6e89 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc @@ -1 +1 @@ -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets x_heep_system_i/pad_ring_i/pad_clk_i/xilinx_iobuf_i/O] +create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk_i}]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc index 116323f2..9f8f7ded 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc @@ -2,84 +2,97 @@ # Solderpad Hardware License, Version 2.1, see LICENSE.md for details. # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Clock signal set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports clk_i] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] + set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports rst_i] -set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports rst_led] -set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports clk_led] -set_property -dict {PACKAGE_PIN W9 IOSTANDARD LVCMOS33} [get_ports clk_out] + +# LEDs +set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports rst_led_o] +set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports clk_led_o] set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports exit_value_o] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_led_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_out_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_led_OBUF] + +# Switches set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports boot_select_i] -## Pmoda -## RPi GPIO 7-0 are shared with pmoda_rpi_gpio_tri_io[7:0] - +# FLASH # QSPI # Q0 / MOSI # Q1 / MISO # Q2 / nWP # Q3 / nHLD +set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] ; # Pmoda[4] +set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] ; # Pmoda[0] +set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] ; # Pmoda[5] +set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] ; # Pmoda[1] +set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] ; # Pmoda[6] +set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] ; # Pmoda[2] -set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] -set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] -set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] -set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] -set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] -set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] -#set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports {crst}] -set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] +# UART +set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] ; # Pmodb[0] +set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] ; # Pmodb[4] -set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_o] -set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_o] -set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}] -set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}] -set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}] -set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}] +# JTAG +set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] ; # Pmob[1] +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] ; # Pmodb[6] +set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] ; # Pmodb[2] +set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] ; # Pmodb[5] +set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] ; # Pmoda[7] -## Pmodb -set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] -set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] -set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] -set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] -set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] -set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] +# I2C +set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}] ; # Pmodb[7] +set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}] ; # Pmodb[3] -set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}] -set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}] -set_property -dict {PACKAGE_PIN W8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}] -set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}] -set_property -dict {PACKAGE_PIN Y6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}] -set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}] -set_property -dict {PACKAGE_PIN W10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}] -set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}] -set_property -dict {PACKAGE_PIN V8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}] -set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}] -set_property -dict {PACKAGE_PIN V7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}] -set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[11]}] -set_property -dict {PACKAGE_PIN V6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[12]}] -set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[13]}] -set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[14]}] -set_property -dict {PACKAGE_PIN Y9 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_clk_io}] -set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_pdm_io}] -set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {i2s_sck_io}] -set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {i2s_ws_io}] -set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {i2s_sd_io}] +# SPI SD +set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_o] ; # arduino_direct_spi_ss_io +set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_o] ; # arduino_direct_spi_sck_io +set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}] ; # arduino_direct_spi_io0_io +set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}] ; # arduino_direct_spi_io1_io +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}] ; # arduino_gpio_tri_io[12] +set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}] ; # arduino_gpio_tri_io[13] -## Tri-color LD5 for TARGET_PYNQ_Z2 -set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[15]}] -set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[16]}] -set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[17]}] +# GPIOs +set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}] ; # arduino_gpio_tri_io[0] +set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}] ; # rpi_gpio_tri_io[11] +set_property -dict {PACKAGE_PIN W8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}] ; # rpi_gpio_tri_io[5] +set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}] ; # rpi_gpio_tri_io[16] +set_property -dict {PACKAGE_PIN Y6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}] ; # rpi_gpio_tri_io[7] +set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}] ; # arduino_gpio_tri_io[1] +set_property -dict {PACKAGE_PIN W10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}] ; # rpi_gpio_tri_io[3] +set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}] ; # rpi_gpio_tri_io[1] +set_property -dict {PACKAGE_PIN V8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}] ; # rpi_gpio_tri_io[2] +set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}] ; # rpi_gpio_tri_io[14] +set_property -dict {PACKAGE_PIN V7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}] ; # rpi_gpio_tri_io[19] +set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[11]}] ; # rpi_gpio_tri_io[9] +set_property -dict {PACKAGE_PIN V6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[12]}] ; # rpi_gpio_tri_io[6] +set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[13]}] ; # arduino_gpio_tri_io[2] +set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[14]}] ; # arduino_gpio_tri_io[3] -set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[0]}] -set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[1]}] -set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_o}] -set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_0_io}] -set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_1_io}] -set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_2_io}] -set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_3_io}] -set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}] -set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}] +# PDM2PCM +set_property -dict {PACKAGE_PIN Y9 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_clk_io}] ; # rpi_gpio_tri_io[13] +set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_pdm_io}] ; # rpi_gpio_tri_io[12] -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] +# I2S +set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {i2s_sck_io}] ; # rpi_gpio_tri_io[8] +set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {i2s_ws_io}] ; # rpi_gpio_tri_io[4] +set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {i2s_sd_io}] ; # arduino_direct_iic_scl_io + +# SPI2 +set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[0]}] ; # rpi_gpio_tri_io[15] +set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[1]}] ; # arduino_gpio_tri_io[5] +set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_o}] ; # rpi_gpio_tri_io[10] +set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[0]}] ; # arduino__gpio_tri_io[8] +set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[1]}] ; # arduino_gpio_tri_io[9] +set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[2]}] ; # arduino_gpio_tri_io[10] +set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[3]}] ; # arduino_gpio_tri_io[11] +# Tri-color LEDs for TARGET_PYNQ_Z2 +set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[15]}] ; # rgbleds_6bits_tri_o[5] +set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[16]}] ; # rgbled_6bits_tri_o[3] +set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[17]}] ; # rgbleds_6bits_tri_o[4] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc new file mode 100644 index 00000000..4b523cdf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc @@ -0,0 +1,99 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# CLOCK +set_property -dict {PACKAGE_PIN AH18 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_p] +set_property -dict {PACKAGE_PIN AH17 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_n] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i] + +# RESET +set_property -dict {PACKAGE_PIN M11 IOSTANDARD LVCMOS33} [get_ports rst_i] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_i] + +# LEDS +set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports rst_led_o] +set_property -dict {PACKAGE_PIN D6 IOSTANDARD LVCMOS33} [get_ports clk_led_o] +set_property -dict {PACKAGE_PIN A5 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] +set_property -dict {PACKAGE_PIN B5 IOSTANDARD LVCMOS33} [get_ports exit_value_o] + +# SWITCHES +set_property -dict {PACKAGE_PIN E4 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports boot_select_i] + +# FLASH +# QSPI +# Q0 / MOSI +# Q1 / MISO +# Q2 / nWP +# Q3 / nHLD +set_property -dict {PACKAGE_PIN L10 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] +set_property -dict {PACKAGE_PIN J9 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] +set_property -dict {PACKAGE_PIN M10 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] +set_property -dict {PACKAGE_PIN K9 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] +set_property -dict {PACKAGE_PIN M8 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] +set_property -dict {PACKAGE_PIN K8 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] + +# UART +set_property -dict {PACKAGE_PIN G8 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] +set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] + +# JTAG +set_property -dict {PACKAGE_PIN H8 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] +set_property -dict {PACKAGE_PIN J6 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] +set_property -dict {PACKAGE_PIN G7 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] +set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] +set_property -dict {PACKAGE_PIN M9 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] + +# I2C +set_property -dict {PACKAGE_PIN J7 IOSTANDARD LVCMOS33} [get_ports i2c_scl_io] +set_property -dict {PACKAGE_PIN H7 IOSTANDARD LVCMOS33} [get_ports i2c_sda_io] + +## The following pins are sent to the FMC connector, using the LA pins as single-ended. +## The bank only supports up to 1.8 V. + +# SPI SD +set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS18} [get_ports spi_csb_o] +set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS18} [get_ports spi_sck_o] +set_property -dict {PACKAGE_PIN L15 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[0]}] +set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[1]}] +set_property -dict {PACKAGE_PIN C13 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[2]}] +set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[3]}] + +# GPIOs +set_property -dict {PACKAGE_PIN D11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[0]}] +set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS18} [get_ports {gpio_io[1]}] +set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS18} [get_ports {gpio_io[2]}] +set_property -dict {PACKAGE_PIN A7 IOSTANDARD LVCMOS18} [get_ports {gpio_io[3]}] +set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS18} [get_ports {gpio_io[4]}] +set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[5]}] +set_property -dict {PACKAGE_PIN K17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[6]}] +set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[7]}] +set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS18} [get_ports {gpio_io[8]}] +set_property -dict {PACKAGE_PIN G16 IOSTANDARD LVCMOS18} [get_ports {gpio_io[9]}] +set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS18} [get_ports {gpio_io[10]}] +set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS18} [get_ports {gpio_io[11]}] +set_property -dict {PACKAGE_PIN F11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[12]}] +set_property -dict {PACKAGE_PIN E10 IOSTANDARD LVCMOS18} [get_ports {gpio_io[13]}] +set_property -dict {PACKAGE_PIN B11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[14]}] +set_property -dict {PACKAGE_PIN A11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[15]}] +set_property -dict {PACKAGE_PIN B9 IOSTANDARD LVCMOS18} [get_ports {gpio_io[16]}] +set_property -dict {PACKAGE_PIN B8 IOSTANDARD LVCMOS18} [get_ports {gpio_io[17]}] + +# PDM2PCM +set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS18} [get_ports pdm2pcm_clk_io] +set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS18} [get_ports pdm2pcm_pdm_io] + +# I2S +set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS18} [get_ports i2s_sck_io] +set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS18} [get_ports i2s_ws_io] +set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS18} [get_ports i2s_sd_io] + +# SPI2 +set_property -dict {PACKAGE_PIN F18 IOSTANDARD LVCMOS18} [get_ports {spi2_csb_o[0]}] +set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS18} [get_ports {spi2_csb_o[1]}] +set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS18} [get_ports spi2_sck_o] +set_property -dict {PACKAGE_PIN F12 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[0]}] +set_property -dict {PACKAGE_PIN E12 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[1]}] +set_property -dict {PACKAGE_PIN H13 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[2]}] +set_property -dict {PACKAGE_PIN H12 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[3]}] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv index 349920c1..35165b88 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv @@ -158,3 +158,12 @@ module tc_clk_xor2 ( assign clk_o = clk0_i ^ clk1_i; endmodule + +module tc_clk_inverter ( + input logic clk_i, + output logic clk_o +); + + xilinx_clk_inverter clk_inv_i (.*); + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/set_board.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/set_board.tcl new file mode 100644 index 00000000..544cd11b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/set_board.tcl @@ -0,0 +1,3 @@ +# Select board +set_property -name "board_part_repo_paths" -value "[file normalize "../../../hw/fpga/board_files/"]" -objects [current_project] +set_property -name "board_part" -value "digilentinc.com:nexys-a7-100t:part0:1.3" -objects [current_project] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl new file mode 100644 index 00000000..69dff9c3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl @@ -0,0 +1,43 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Define design macros + +set design_name xilinx_clk_wizard +set in_clk_freq_MHz 100 +set out_clk_freq_MHz 15 + + +# Create block design +create_bd_design $design_name + +# Create ports +set clk_100MHz [ create_bd_port -dir I -type clk -freq_hz [ expr $in_clk_freq_MHz * 1000000 ] clk_100MHz ] +set clk_out1_0 [ create_bd_port -dir O -type clk clk_out1_0 ] +set_property -dict [ list CONFIG.FREQ_HZ [ expr $out_clk_freq_MHz * 1000000 ] ] $clk_out1_0 + +# Create instance and set properties +set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] +set_property -dict [ list \ + CONFIG.CLKOUT1_JITTER {333.843} \ + CONFIG.CLKOUT1_PHASE_ERROR {293.793} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {15} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {49.875} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {66.500} \ + CONFIG.PRIM_IN_FREQ $in_clk_freq_MHz \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {false} \ +] $clk_wiz_0 + +# Create port connections +connect_bd_net -net clk_in1_0_1 [ get_bd_ports clk_100MHz ] [ get_bd_pins clk_wiz_0/clk_in1 ] +connect_bd_net -net clk_wiz_0_clk_out1 [ get_bd_ports clk_out1_0 ] [ get_bd_pins clk_wiz_0/clk_out1 ] + +# Save and close block design +save_bd_design +close_bd_design $design_name + +# create wrapper +set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse xilinx_clk_wizard.bd ] -top ] +add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/set_board.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/set_board.tcl new file mode 100644 index 00000000..f16f754f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/set_board.tcl @@ -0,0 +1,3 @@ +# Select board +set_property -name "board_part_repo_paths" -value "[file normalize "../../../hw/fpga/board_files/"]" -objects [current_project] +set_property -name "board_part" -value "tul.com.tw:pynq-z2:part0:1.0" -objects [current_project] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/xilinx_generate_clk_wizard.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl similarity index 86% rename from hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/xilinx_generate_clk_wizard.tcl rename to hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl index 1c2a41a0..e61c5832 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/xilinx_generate_clk_wizard.tcl +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl @@ -7,9 +7,6 @@ set design_name xilinx_clk_wizard set in_clk_freq_MHz 125 set out_clk_freq_MHz 15 -# Select board -set_property -name "board_part_repo_paths" -value "[file normalize "../../../hw/fpga/board_files/"]" -objects [current_project] -set_property -name "board_part" -value "tul.com.tw:pynq-z2:part0:1.0" -objects [current_project] # Create block design create_bd_design $design_name diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/set_board.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/set_board.tcl new file mode 100644 index 00000000..0108a4c8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/set_board.tcl @@ -0,0 +1,3 @@ +# Select board +set_property -name "board_part_repo_paths" -value "[file normalize "../../../hw/fpga/board_files/"]" -objects [current_project] +set_property -name "board_part" -value "xilinx.com:zcu104:part0:1.0" -objects [current_project] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl new file mode 100644 index 00000000..d67e4054 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl @@ -0,0 +1,40 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Define design macros + +set design_name xilinx_clk_wizard + +# Create block design +create_bd_design $design_name + +# Create instance and set properties +create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 +set_property -dict [list \ + CONFIG.CLKIN1_JITTER_PS {33.330000000000005} \ + CONFIG.CLKOUT1_JITTER {282.792} \ + CONFIG.CLKOUT1_PHASE_ERROR {207.545} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {15} \ + CONFIG.CLK_IN1_BOARD_INTERFACE {clk_300mhz} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {32.875} \ + CONFIG.MMCM_CLKIN1_PERIOD {3.333} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {65.750} \ + CONFIG.MMCM_DIVCLK_DIVIDE {10} \ + CONFIG.OPTIMIZE_CLOCKING_STRUCTURE_EN {true} \ + CONFIG.PRIM_SOURCE {Differential_clock_capable_pin} \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {true} \ +] [get_bd_cells clk_wiz_0] + +# Create ports +make_bd_pins_external [get_bd_cells clk_wiz_0] +make_bd_intf_pins_external [get_bd_cells clk_wiz_0] + +# Save and close block design +save_bd_design +close_bd_design $design_name + +# Create wrapper +set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse xilinx_clk_wizard.bd ] -top ] +add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv index 1324bfb1..fc9c53fb 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv @@ -13,13 +13,16 @@ module xilinx_core_v_mini_mcu_wrapper parameter CLK_LED_COUNT_LENGTH = 27 ) ( +`ifdef FPGA_ZCU104 + inout logic clk_300mhz_n, + inout logic clk_300mhz_p, +`else inout logic clk_i, +`endif inout logic rst_i, - //visibility signals - output logic rst_led, - output logic clk_led, - output logic clk_out, + output logic rst_led_o, + output logic clk_led_o, inout logic boot_select_i, inout logic execute_from_flash_i, @@ -33,7 +36,7 @@ module xilinx_core_v_mini_mcu_wrapper inout logic uart_rx_i, inout logic uart_tx_o, - inout logic [19:0] gpio_io, + inout logic [17:0] gpio_io, output logic exit_value_o, inout logic exit_valid_o, @@ -46,10 +49,7 @@ module xilinx_core_v_mini_mcu_wrapper inout logic spi_csb_o, inout logic spi_sck_o, - inout logic spi2_sd_0_io, - inout logic spi2_sd_1_io, - inout logic spi2_sd_2_io, - inout logic spi2_sd_3_io, + inout logic [3:0] spi2_sd_io, inout logic [1:0] spi2_csb_o, inout logic spi2_sck_o, @@ -71,13 +71,17 @@ module xilinx_core_v_mini_mcu_wrapper logic [CLK_LED_COUNT_LENGTH - 1:0] clk_count; // low active reset - assign rst_n = !rst_i; +`ifdef FPGA_NEXYS + assign rst_n = rst_i; +`else + assign rst_n = !rst_i; +`endif // reset LED for debugging - assign rst_led = rst_n; + assign rst_led_o = rst_n; // counter to blink an LED - assign clk_led = clk_count[CLK_LED_COUNT_LENGTH-1]; + assign clk_led_o = clk_count[CLK_LED_COUNT_LENGTH-1]; always_ff @(posedge clk_gen or negedge rst_n) begin : clk_count_process if (!rst_n) begin @@ -90,13 +94,23 @@ module xilinx_core_v_mini_mcu_wrapper // eXtension Interface if_xif #() ext_if (); - // clock output for debugging - assign clk_out = clk_gen; - +`ifdef FPGA_ZCU104 + xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( + .CLK_IN1_D_0_clk_n(clk_300mhz_n), + .CLK_IN1_D_0_clk_p(clk_300mhz_p), + .clk_out1_0(clk_gen) + ); +`elsif FPGA_NEXYS + xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( + .clk_100MHz(clk_i), + .clk_out1_0(clk_gen) + ); +`else // FPGA PYNQ-Z2 xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( .clk_125MHz(clk_i), .clk_out1_0(clk_gen) ); +`endif x_heep_system #( .X_EXT(X_EXT), @@ -180,10 +194,10 @@ module xilinx_core_v_mini_mcu_wrapper .spi_sck_io(spi_sck_o), .i2c_scl_io, .i2c_sda_io, - .spi2_sd_0_io(spi2_sd_0_io), - .spi2_sd_1_io(spi2_sd_1_io), - .spi2_sd_2_io(spi2_sd_2_io), - .spi2_sd_3_io(spi2_sd_3_io), + .spi2_sd_0_io(spi2_sd_io[0]), + .spi2_sd_1_io(spi2_sd_io[1]), + .spi2_sd_2_io(spi2_sd_io[2]), + .spi2_sd_3_io(spi2_sd_io[3]), .spi2_cs_0_io(spi2_csb_o[0]), .spi2_cs_1_io(spi2_csb_o[1]), .spi2_sck_io(spi2_sck_o), @@ -191,7 +205,9 @@ module xilinx_core_v_mini_mcu_wrapper .pdm2pcm_pdm_io, .i2s_sck_io(i2s_sck_io), .i2s_ws_io(i2s_ws_io), - .i2s_sd_io(i2s_sd_io) + .i2s_sd_io(i2s_sd_io), + .ext_dma_slot_tx_i('0), + .ext_dma_slot_rx_i('0) ); assign exit_value_o = exit_value[0]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md index dc07aef1..65b4b051 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md @@ -1,33 +1,5 @@ ## boot_rom -1. If you haven't done it yet, install [Conda](https://phoenixnap.com/kb/how-to-install-anaconda-ubuntu-18-04-or-20-04) as described in the link, -and create the Conda enviroment with python 2.7: - -```bash -conda update conda -conda env create -f environment.yml -``` - -Activate the environment with - -```bash -conda activate boot_rom -``` - -If you are already in the core-v-mini-mcu conda env, deactivate it first: - -```bash -conda deactivate -``` - -2. Install the required Python tools: - -``` -pip install --user -r python-requirements.txt -``` - -3. Generate the boot_rom: - If you modified the `boot_rom.S` file, generate it as: ``` diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S index f154eec4..7b0fab66 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S @@ -99,7 +99,7 @@ _wait_spi_ready_tx_init: _wait_spi_ready_read_prog: lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) bgez a5, _wait_spi_ready_read_prog - li a3, 1024 # 1KB copy size + li a3, 2048 # 2KB copy size li s1, 0 # dst ptr (ram) // For loop until the 1KB copy from flash to ram is done diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump index c4a74476..025800d8 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump @@ -6,14 +6,14 @@ Disassembly of section .text: 00000000 : 0: 200405b7 lui a1,0x20040 - 4: 0005c503 lbu a0,0(a1) # 20040000 <_end+0x2003ff16> + 4: 0005c503 lbu a0,0(a1) # 20040000 <_end+0x2003ff14> 8: c119 beqz a0,e a: 41c8 lw a0,4(a1) c: 9502 jalr a0 0000000e : e: 200005b7 lui a1,0x20000 - 12: 0085c503 lbu a0,8(a1) # 20000008 <_end+0x1fffff1e> + 12: 0085c503 lbu a0,8(a1) # 20000008 <_end+0x1fffff1c> 16: e511 bnez a0,22 <_jump_to_flash> 00000018 <_jump_to_debug_rom>: @@ -31,7 +31,7 @@ Disassembly of section .text: 2c: 4505 li a0,1 2e: c188 sw a0,0(a1) 30: 400005b7 lui a1,0x40000 - 34: 18058593 addi a1,a1,384 # 40000180 <_end+0x40000096> + 34: 18058593 addi a1,a1,384 # 40000180 <_end+0x40000094> 38: 9582 jalr a1 0000003a <_copy_from_flash>: @@ -73,41 +73,42 @@ Disassembly of section .text: 0000008a <_wait_spi_ready_read_prog>: 8a: 49dc lw a5,20(a1) 8c: fe07dfe3 bgez a5,8a <_wait_spi_ready_read_prog> - 90: 40000693 li a3,1024 - 94: 4481 li s1,0 - 96: 10000b13 li s6,256 - 9a: 09000437 lui s0,0x9000 - 9e: 0ff40a93 addi s5,s0,255 # 90000ff <_end+0x9000015> - -000000a2 <_32B_chunk_loop>: - a2: 00db4663 blt s6,a3,ae <_read_32B_chunk> - a6: 08000437 lui s0,0x8000 - aa: 0ff40a93 addi s5,s0,255 # 80000ff <_end+0x8000015> - -000000ae <_read_32B_chunk>: - ae: 0355a223 sw s5,36(a1) # 20020024 <_end+0x2001ff3a> - b2: 0001 nop - -000000b4 <_wait_spi_ready_read_32B_chunk>: - b4: 49dc lw a5,20(a1) - b6: fe07dfe3 bgez a5,b4 <_wait_spi_ready_read_32B_chunk> - ba: 10048b93 addi s7,s1,256 - -000000be <_wait_spi_rxwm_8_words>: - be: 49dc lw a5,20(a1) - c0: 83d1 srli a5,a5,0x14 - c2: 8b85 andi a5,a5,1 - c4: dfed beqz a5,be <_wait_spi_rxwm_8_words> - c6: 02048613 addi a2,s1,32 - -000000ca <_spi_fifo_read_8_words>: - ca: 0285a883 lw a7,40(a1) - ce: 0114a023 sw a7,0(s1) - d2: 0491 addi s1,s1,4 - d4: fec49be3 bne s1,a2,ca <_spi_fifo_read_8_words> - d8: ff7493e3 bne s1,s7,be <_wait_spi_rxwm_8_words> - dc: f0068693 addi a3,a3,-256 - e0: f2e9 bnez a3,a2 <_32B_chunk_loop> - e2: 200005b7 lui a1,0x20000 - e6: 4990 lw a2,16(a1) - e8: 9602 jalr a2 + 90: 6685 lui a3,0x1 + 92: 80068693 addi a3,a3,-2048 # 800 <_end+0x714> + 96: 4481 li s1,0 + 98: 10000b13 li s6,256 + 9c: 09000437 lui s0,0x9000 + a0: 0ff40a93 addi s5,s0,255 # 90000ff <_end+0x9000013> + +000000a4 <_32B_chunk_loop>: + a4: 00db4663 blt s6,a3,b0 <_read_32B_chunk> + a8: 08000437 lui s0,0x8000 + ac: 0ff40a93 addi s5,s0,255 # 80000ff <_end+0x8000013> + +000000b0 <_read_32B_chunk>: + b0: 0355a223 sw s5,36(a1) # 20020024 <_end+0x2001ff38> + b4: 0001 nop + +000000b6 <_wait_spi_ready_read_32B_chunk>: + b6: 49dc lw a5,20(a1) + b8: fe07dfe3 bgez a5,b6 <_wait_spi_ready_read_32B_chunk> + bc: 10048b93 addi s7,s1,256 + +000000c0 <_wait_spi_rxwm_8_words>: + c0: 49dc lw a5,20(a1) + c2: 83d1 srli a5,a5,0x14 + c4: 8b85 andi a5,a5,1 + c6: dfed beqz a5,c0 <_wait_spi_rxwm_8_words> + c8: 02048613 addi a2,s1,32 + +000000cc <_spi_fifo_read_8_words>: + cc: 0285a883 lw a7,40(a1) + d0: 0114a023 sw a7,0(s1) + d4: 0491 addi s1,s1,4 + d6: fec49be3 bne s1,a2,cc <_spi_fifo_read_8_words> + da: ff7493e3 bne s1,s7,c0 <_wait_spi_rxwm_8_words> + de: f0068693 addi a3,a3,-256 + e2: f2e9 bnez a3,a4 <_32B_chunk_loop> + e4: 200005b7 lui a1,0x20000 + e8: 4990 lw a2,16(a1) + ea: 9602 jalr a2 diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h index 8f0e3d2b..bbb8198a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h @@ -39,27 +39,27 @@ uint32_t reset_vec[reset_vec_size] = { 0xd1d8070d, 0x49dc0001, 0xfe07dfe3, - 0x40000693, - 0x0b134481, - 0x04371000, - 0x0a930900, - 0x46630ff4, - 0x043700db, - 0x0a930800, - 0xa2230ff4, - 0x00010355, - 0xdfe349dc, - 0x8b93fe07, - 0x49dc1004, - 0x8b8583d1, - 0x8613dfed, - 0xa8830204, - 0xa0230285, - 0x04910114, - 0xfec49be3, - 0xff7493e3, - 0xf0068693, - 0x05b7f2e9, - 0x49902000, - 0x00009602 + 0x86936685, + 0x44818006, + 0x10000b13, + 0x09000437, + 0x0ff40a93, + 0x00db4663, + 0x08000437, + 0x0ff40a93, + 0x0355a223, + 0x49dc0001, + 0xfe07dfe3, + 0x10048b93, + 0x83d149dc, + 0xdfed8b85, + 0x02048613, + 0x0285a883, + 0x0114a023, + 0x9be30491, + 0x93e3fec4, + 0x8693ff74, + 0xf2e9f006, + 0x200005b7, + 0x96024990 }; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv index 07c74e3a..93983a15 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv @@ -26,29 +26,29 @@ module boot_rom logic [RomSize-1:0][31:0] mem; assign mem = { - 32'h00009602, - 32'h49902000, - 32'h05b7f2e9, - 32'hf0068693, - 32'hff7493e3, - 32'hfec49be3, - 32'h04910114, - 32'ha0230285, - 32'ha8830204, - 32'h8613dfed, - 32'h8b8583d1, - 32'h49dc1004, - 32'h8b93fe07, - 32'hdfe349dc, - 32'h00010355, - 32'ha2230ff4, - 32'h0a930800, - 32'h043700db, - 32'h46630ff4, - 32'h0a930900, - 32'h04371000, - 32'h0b134481, - 32'h40000693, + 32'h96024990, + 32'h200005b7, + 32'hf2e9f006, + 32'h8693ff74, + 32'h93e3fec4, + 32'h9be30491, + 32'h0114a023, + 32'h0285a883, + 32'h02048613, + 32'hdfed8b85, + 32'h83d149dc, + 32'h10048b93, + 32'hfe07dfe3, + 32'h49dc0001, + 32'h0355a223, + 32'h0ff40a93, + 32'h08000437, + 32'h00db4663, + 32'h0ff40a93, + 32'h09000437, + 32'h10000b13, + 32'h44818006, + 32'h86936685, 32'hfe07dfe3, 32'h49dc0001, 32'hd1d8070d, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml deleted file mode 100644 index 260ecf9a..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: boot_rom -channels: - - defaults -dependencies: - - python=2.7.18 - diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py index b52e22bd..b1a79b57 100755 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py @@ -89,9 +89,8 @@ def read_bin(): with open(filename + ".img", 'rb') as f: - rom = binascii.hexlify(f.read()) - rom = map(''.join, zip(rom[::2], rom[1::2])) - + rom = bytes.hex(f.read()) + rom = list(map(''.join, zip(rom[::2], rom[1::2]))) # align to 32 bit align = (int((len(rom) + 3) / 4 )) * 4; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv index fb155575..2195a075 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv @@ -7,8 +7,8 @@ // Description: I2s core logic module i2s_core #( - parameter MaxWordWidth, - parameter ClkDividerWidth + parameter MaxWordWidth = 32, + parameter ClkDividerWidth = 8 ) ( input logic clk_i, input logic rst_ni, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv index ed85b649..a6ebeca2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv @@ -10,7 +10,7 @@ // by Antonio Pullini (pullinia@iis.ee.ethz.ch) module i2s_ws_gen #( - parameter MaxWordWidth, + parameter MaxWordWidth = 32, localparam int unsigned CounterWidth = $clog2(MaxWordWidth) ) ( input logic sck_i, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson new file mode 100644 index 00000000..919cceaf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson @@ -0,0 +1,76 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +{ name: "iffifo" + clock_primary: "clk_i" + bus_interfaces: [ + { protocol: "reg_iface", direction: "device" } + ], + regwidth: 32 + registers: [ + + { name: "FIFO_OUT" + desc: "Data coming from the FIFO (Fifo Output/Software RX)" + swaccess: "ro" + hwaccess: "hrw" # required for RE signal + hwext: "true" # required for RE signal + hwre: "true" # Used to emulate a window behaviour + fields: [ + { bits: "31:0" } + ] + } + + { name: "FIFO_IN" + desc: "Data sent to the FIFO (Fifo Input/Software TX)" + hwaccess: "hro" + swaccess: "rw" # required for QE signal + hwqe: "true" # Used to emulate a window behaviour + fields: [ + { bits: "31:0" } + ] + } + + { name: "STATUS" + desc: "General purpose status register" + swaccess: "ro" + hwaccess: "hwo" + fields: [ + { bits: "0", name: "EMPTY", desc: "Asserted when FIFO empty." } + { bits: "1", name: "AVAILABLE", desc: "Asserted when data is available in FIFO." } + { bits: "2", name: "REACHED", desc: "Asserted when occupied data slots count greater than threshold." } + { bits: "3", name: "FULL", desc: "Asserted when all FIFO slots are occupied." } + ] + } + + { name: "OCCUPANCY" + desc: "Current number of occupied FIFO slots" + swaccess: "ro" + hwaccess: "hwo" + fields: [ + { bits: "31:0" } + ] + } + + { name: "WATERMARK" + desc: "FIFO occupancy at which the STATUS:REACHED bit is asserted" + swaccess: "rw" + hwaccess: "hro" + fields: [ + { bits: "31:0" } + ] + } + + { name: "INTERRUPTS" + desc: "Write any value to assert an interrupt. Write 0 or 1 to disable or enable an interrupt." + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" # Used to catch software writes + fields: [ + { bits: "0", name: "REACHED", desc: "Watermark reached interrupt" } + ] + } + + ] +} + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core new file mode 100644 index 00000000..f0e23463 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core @@ -0,0 +1,26 @@ +CAPI=2: + +name: "example:ip:iffifo" +description: "core-v-mini-mcu iffifo peripheral" + +# Copyright 2023 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# +# Author: Pierre Guillod , EPFL, STI-SEL +# Date: 18.10.2023 + +filesets: + files_rtl: + depend: + - pulp-platform.org::common_cells + files: + - rtl/iffifo_reg_pkg.sv + - rtl/iffifo_reg_top.sv + - rtl/iffifo.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt new file mode 100644 index 00000000..9820d038 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt @@ -0,0 +1,15 @@ +// Copyright 2023 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Author: Pierre Guillod , EPFL, STI-SEL +// Date: 18.10.2023 + +`verilator_config + +lint_off -rule DECLFILENAME -file "*/iffifo/rtl/iffifo_reg_top.sv" -match "Filename 'iffifo_reg_top' does not match MODULE name: 'iffifo_reg_top_intf'*" +lint_off -rule WIDTH -file "*/iffifo/rtl/iffifo_reg_top.sv" -match "Operator ASSIGNW expects 3 bits on the Assign RHS, but Assign RHS's SEL generates 32*" +lint_off -rule UNUSED -file "*/iffifo/rtl/iffifo.sv" -match "Bits of signal are not used: 'reg2hw'[0]*" + +lint_off -rule UNUSED -file "*/iffifo/rtl/iffifo_window.sv" -match "Bits of signal are not used: 'rx_win_i'[67:64,31:0]" +lint_off -rule WIDTH -file "*/iffifo/rtl/iffifo_*.sv" -match "Operator ASSIGNW expects*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh new file mode 100755 index 00000000..45cc8f1c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh @@ -0,0 +1,8 @@ +# Copyright EPFL contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +echo "Generating RTL" +${PYTHON} ../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py -r -t rtl data/iffifo.hjson +echo "Generating SW" +${PYTHON} ../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py --cdefines -o ../../../sw/device/lib/drivers/iffifo/iffifo_regs.h data/iffifo.hjson diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv new file mode 100644 index 00000000..35a6b008 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv @@ -0,0 +1,115 @@ +// Copyright 2023 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Author: Pierre Guillod , EPFL, STI-SEL +// Date: 18.10.2023 + +module iffifo #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + localparam int WIDTH = 32, + localparam int DEPTH = 4, + localparam int DEPTHw = $clog2(DEPTH + 1) +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + // DMA slots + output logic iffifo_in_ready_o, + output logic iffifo_out_valid_o, + + // Interrupt lines + output logic iffifo_int_o +); + + import iffifo_reg_pkg::*; + + iffifo_reg2hw_t reg2hw; + iffifo_hw2reg_t hw2reg; + + logic [WIDTH-1:0] fifout; + logic [DEPTHw-1:0] occupancy; + logic empty, full, reached, available; + + assign hw2reg.fifo_out.d = fifout + 1; + + // Status (full/empty/watermark) reporting circuitry + assign empty = (occupancy == 0); + assign available = !empty; + assign hw2reg.status.empty.de = 1; + assign hw2reg.status.empty.d = empty; + assign hw2reg.status.available.de = 1; + assign hw2reg.status.available.d = available; + assign hw2reg.status.full.de = 1; + assign hw2reg.status.full.d = full; + assign hw2reg.status.reached.de = 1; + assign hw2reg.status.reached.d = reached; + assign hw2reg.occupancy.de = 1; + assign hw2reg.occupancy.d = {{32 - DEPTHw{1'b0}}, occupancy}; + assign reached = ({{32 - DEPTHw{1'b0}}, occupancy} >= reg2hw.watermark.q); + + // Interrupts circuitry + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + + iffifo_int_o <= 0; + + end else begin + + // Interrupts firing + if (reached & reg2hw.interrupts.q) begin + iffifo_int_o <= 1; + end + + // Interrupts assertion + if (reg2hw.interrupts.qe) begin + iffifo_int_o <= 0; + end + + end + end + + iffifo_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) iffifo_reg_top_i ( + .clk_i, + .rst_ni, + .reg2hw, + .hw2reg, + .reg_req_i, + .reg_rsp_o, + .devmode_i(1'b0) + ); + + prim_fifo_sync #( + .Width(WIDTH), + .Depth(DEPTH), + .Pass(1'b0), + .OutputZeroIfEmpty(1'b0) + ) iffifo_fifo_i ( + + .clk_i, + .rst_ni, + .clr_i(1'b0), + + // From DMA (output) to FIFO (input, TX) + .wvalid_i(reg2hw.fifo_in.qe), + .wready_o(iffifo_in_ready_o), + .wdata_i (reg2hw.fifo_in.q), + + // From FIFO (output) to DMA (input, RX) + .rvalid_o(iffifo_out_valid_o), + .rready_i(reg2hw.fifo_out.re), + .rdata_o (fifout), + + .full_o (full), + .depth_o(occupancy) + + ); + +endmodule : iffifo + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv new file mode 100644 index 00000000..e362798d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv @@ -0,0 +1,106 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package iffifo_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 5; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic [31:0] q; + logic re; + } iffifo_reg2hw_fifo_out_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } iffifo_reg2hw_fifo_in_reg_t; + + typedef struct packed {logic [31:0] q;} iffifo_reg2hw_watermark_reg_t; + + typedef struct packed { + logic q; + logic qe; + } iffifo_reg2hw_interrupts_reg_t; + + typedef struct packed {logic [31:0] d;} iffifo_hw2reg_fifo_out_reg_t; + + typedef struct packed { + struct packed { + logic d; + logic de; + } empty; + struct packed { + logic d; + logic de; + } available; + struct packed { + logic d; + logic de; + } reached; + struct packed { + logic d; + logic de; + } full; + } iffifo_hw2reg_status_reg_t; + + typedef struct packed { + logic [31:0] d; + logic de; + } iffifo_hw2reg_occupancy_reg_t; + + // Register -> HW type + typedef struct packed { + iffifo_reg2hw_fifo_out_reg_t fifo_out; // [99:67] + iffifo_reg2hw_fifo_in_reg_t fifo_in; // [66:34] + iffifo_reg2hw_watermark_reg_t watermark; // [33:2] + iffifo_reg2hw_interrupts_reg_t interrupts; // [1:0] + } iffifo_reg2hw_t; + + // HW -> register type + typedef struct packed { + iffifo_hw2reg_fifo_out_reg_t fifo_out; // [72:41] + iffifo_hw2reg_status_reg_t status; // [40:33] + iffifo_hw2reg_occupancy_reg_t occupancy; // [32:0] + } iffifo_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IFFIFO_FIFO_OUT_OFFSET = 5'h0; + parameter logic [BlockAw-1:0] IFFIFO_FIFO_IN_OFFSET = 5'h4; + parameter logic [BlockAw-1:0] IFFIFO_STATUS_OFFSET = 5'h8; + parameter logic [BlockAw-1:0] IFFIFO_OCCUPANCY_OFFSET = 5'hc; + parameter logic [BlockAw-1:0] IFFIFO_WATERMARK_OFFSET = 5'h10; + parameter logic [BlockAw-1:0] IFFIFO_INTERRUPTS_OFFSET = 5'h14; + + // Reset values for hwext registers and their fields + parameter logic [31:0] IFFIFO_FIFO_OUT_RESVAL = 32'h0; + + // Register index + typedef enum int { + IFFIFO_FIFO_OUT, + IFFIFO_FIFO_IN, + IFFIFO_STATUS, + IFFIFO_OCCUPANCY, + IFFIFO_WATERMARK, + IFFIFO_INTERRUPTS + } iffifo_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IFFIFO_PERMIT[6] = '{ + 4'b1111, // index[0] IFFIFO_FIFO_OUT + 4'b1111, // index[1] IFFIFO_FIFO_IN + 4'b0001, // index[2] IFFIFO_STATUS + 4'b1111, // index[3] IFFIFO_OCCUPANCY + 4'b1111, // index[4] IFFIFO_WATERMARK + 4'b0001 // index[5] IFFIFO_INTERRUPTS + }; + +endpackage + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv new file mode 100644 index 00000000..cd8d2f56 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv @@ -0,0 +1,451 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module iffifo_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 5 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output iffifo_reg_pkg::iffifo_reg2hw_t reg2hw, // Write + input iffifo_reg_pkg::iffifo_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import iffifo_reg_pkg::*; + + localparam int DW = 32; + localparam int DBW = DW / 8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [ AW-1:0] reg_addr; + logic [ DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [ DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic [31:0] fifo_out_qs; + logic fifo_out_re; + logic [31:0] fifo_in_qs; + logic [31:0] fifo_in_wd; + logic fifo_in_we; + logic status_empty_qs; + logic status_available_qs; + logic status_reached_qs; + logic status_full_qs; + logic [31:0] occupancy_qs; + logic [31:0] watermark_qs; + logic [31:0] watermark_wd; + logic watermark_we; + logic interrupts_qs; + logic interrupts_wd; + logic interrupts_we; + + // Register instances + // R[fifo_out]: V(True) + + prim_subreg_ext #( + .DW(32) + ) u_fifo_out ( + .re (fifo_out_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.fifo_out.d), + .qre(reg2hw.fifo_out.re), + .qe (), + .q (reg2hw.fifo_out.q), + .qs (fifo_out_qs) + ); + + + // R[fifo_in]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_fifo_in ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(fifo_in_we), + .wd(fifo_in_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.fifo_in.qe), + .q (reg2hw.fifo_in.q), + + // to register interface (read) + .qs(fifo_in_qs) + ); + + + // R[status]: V(False) + + // F[empty]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_empty ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.empty.de), + .d (hw2reg.status.empty.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_empty_qs) + ); + + + // F[available]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_available ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.available.de), + .d (hw2reg.status.available.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_available_qs) + ); + + + // F[reached]: 2:2 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_reached ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.reached.de), + .d (hw2reg.status.reached.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_reached_qs) + ); + + + // F[full]: 3:3 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_full ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.full.de), + .d (hw2reg.status.full.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_full_qs) + ); + + + // R[occupancy]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RO"), + .RESVAL (32'h0) + ) u_occupancy ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.occupancy.de), + .d (hw2reg.occupancy.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(occupancy_qs) + ); + + + // R[watermark]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_watermark ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(watermark_we), + .wd(watermark_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.watermark.q), + + // to register interface (read) + .qs(watermark_qs) + ); + + + // R[interrupts]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_interrupts ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(interrupts_we), + .wd(interrupts_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.interrupts.qe), + .q (reg2hw.interrupts.q), + + // to register interface (read) + .qs(interrupts_qs) + ); + + + + + logic [5:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == IFFIFO_FIFO_OUT_OFFSET); + addr_hit[1] = (reg_addr == IFFIFO_FIFO_IN_OFFSET); + addr_hit[2] = (reg_addr == IFFIFO_STATUS_OFFSET); + addr_hit[3] = (reg_addr == IFFIFO_OCCUPANCY_OFFSET); + addr_hit[4] = (reg_addr == IFFIFO_WATERMARK_OFFSET); + addr_hit[5] = (reg_addr == IFFIFO_INTERRUPTS_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[0] & (|(IFFIFO_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(IFFIFO_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(IFFIFO_PERMIT[2] & ~reg_be))) | + (addr_hit[3] & (|(IFFIFO_PERMIT[3] & ~reg_be))) | + (addr_hit[4] & (|(IFFIFO_PERMIT[4] & ~reg_be))) | + (addr_hit[5] & (|(IFFIFO_PERMIT[5] & ~reg_be))))); + end + + assign fifo_out_re = addr_hit[0] & reg_re & !reg_error; + + assign fifo_in_we = addr_hit[1] & reg_we & !reg_error; + assign fifo_in_wd = reg_wdata[31:0]; + + assign watermark_we = addr_hit[4] & reg_we & !reg_error; + assign watermark_wd = reg_wdata[31:0]; + + assign interrupts_we = addr_hit[5] & reg_we & !reg_error; + assign interrupts_wd = reg_wdata[0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[31:0] = fifo_out_qs; + end + + addr_hit[1]: begin + reg_rdata_next[31:0] = fifo_in_qs; + end + + addr_hit[2]: begin + reg_rdata_next[0] = status_empty_qs; + reg_rdata_next[1] = status_available_qs; + reg_rdata_next[2] = status_reached_qs; + reg_rdata_next[3] = status_full_qs; + end + + addr_hit[3]: begin + reg_rdata_next[31:0] = occupancy_qs; + end + + addr_hit[4]: begin + reg_rdata_next[31:0] = watermark_qs; + end + + addr_hit[5]: begin + reg_rdata_next[0] = interrupts_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module iffifo_reg_top_intf #( + parameter int AW = 5, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output iffifo_reg_pkg::iffifo_reg2hw_t reg2hw, // Write + input iffifo_reg_pkg::iffifo_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW / 8; + + `include "register_interface/typedef.svh" + `include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + iffifo_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core new file mode 100644 index 00000000..2ef913ea --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core @@ -0,0 +1,22 @@ +CAPI=2: + +name: "example:ip:simple_accelerator" +description: "core-v-mini-mcu iffifo peripheral" + +# Copyright 2024 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# +# Author: Davide Schiavone , EPFL, STI-SEL +# Date: 12.02.2024 + +filesets: + files_rtl: + files: + - simple_accelerator.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv new file mode 100644 index 00000000..846775af --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv @@ -0,0 +1,421 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +module simple_accelerator #( + parameter int unsigned FIFO_DEPTH = 4, + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter type obi_req_t = logic, + parameter type obi_resp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + output obi_req_t acc_read_ch0_req_o, + input obi_resp_t acc_read_ch0_resp_i, + + output obi_req_t acc_write_ch0_req_o, + input obi_resp_t acc_write_ch0_resp_i + +); + + + + logic status_ready_d, status_ready_q, status_start_q; + logic [31:0] address_read_q, address_write_q; + logic [31:0] threshold_q; + logic [ 9:0] size_q; + + localparam int unsigned LastFifoUsage = FIFO_DEPTH - 1; + localparam int unsigned Addr_Fifo_Depth = (FIFO_DEPTH > 1) ? $clog2(FIFO_DEPTH) : 1; + + + logic [ 31:0] read_ptr_reg; + logic [ 31:0] read_ptr_valid_reg; + logic [ 31:0] write_ptr_reg; + logic [ 31:0] write_address; + logic [ 9:0] dma_cnt; + logic dma_start; + logic dma_done; + + + logic [Addr_Fifo_Depth-1:0] fifo_usage; + logic fifo_alm_full; + + logic data_in_req; + logic data_in_we; + logic [ 3:0] data_in_be; + logic [ 31:0] data_in_addr; + logic data_in_gnt; + logic data_in_rvalid; + logic [ 31:0] data_in_rdata; + + logic data_out_req; + logic data_out_we; + logic [ 3:0] data_out_be; + logic [ 31:0] data_out_addr; + logic [ 31:0] data_out_wdata; + logic data_out_gnt; + + logic fifo_flush; + logic fifo_full; + logic fifo_empty; + + + logic [ 31:0] fifo_input; + logic [ 31:0] fifo_output; + + logic [ 3:0] byte_enable_out; + + logic dma_start_pending; + + enum { + DMA_READY, + DMA_STARTING, + DMA_RUNNING + } + dma_state_q, dma_state_d; + + logic [Addr_Fifo_Depth-1:0] outstanding_req; + + enum logic { + DMA_READ_FSM_IDLE, + DMA_READ_FSM_ON + } + dma_read_fsm_state, dma_read_fsm_n_state; + + enum logic { + DMA_WRITE_FSM_IDLE, + DMA_WRITE_FSM_ON + } + dma_write_fsm_state, dma_write_fsm_n_state; + + assign acc_read_ch0_req_o.req = data_in_req; + assign acc_read_ch0_req_o.we = data_in_we; + assign acc_read_ch0_req_o.be = data_in_be; + assign acc_read_ch0_req_o.addr = data_in_addr; + assign acc_read_ch0_req_o.wdata = 32'h0; + + assign data_in_gnt = acc_read_ch0_resp_i.gnt; + assign data_in_rvalid = acc_read_ch0_resp_i.rvalid; + assign data_in_rdata = acc_read_ch0_resp_i.rdata; + + assign acc_write_ch0_req_o.req = data_out_req; + assign acc_write_ch0_req_o.we = data_out_we; + assign acc_write_ch0_req_o.be = data_out_be; + assign acc_write_ch0_req_o.addr = data_out_addr; + + //complete the function + assign acc_write_ch0_req_o.wdata = data_out_wdata > threshold_q ? data_out_wdata : threshold_q; + //assign acc_write_ch0_req_o.wdata = data_out_wdata; + + assign data_out_gnt = acc_write_ch0_resp_i.gnt; + + assign status_ready_d = (dma_state_q == DMA_READY); + + assign write_address = write_ptr_reg; + + assign fifo_alm_full = (fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); + + assign dma_start = (dma_state_q == DMA_STARTING); + + //decoder + + //0 READ ADDRESS + //4 WRITE ADDRESS + //8 THRESHOLD + //C READY + //10 SIZE + //14 START + always_comb begin + reg_rsp_o.rdata = '0; + reg_rsp_o.error = 1'b0; + reg_rsp_o.ready = 1'b1; + + if (reg_req_i.valid) begin + if (reg_req_i.addr[7:0] == 8'h14) begin + reg_rsp_o.rdata = {31'h0, status_start_q}; + end + if (reg_req_i.addr[7:0] == 8'h10) begin + reg_rsp_o.rdata = {22'h0, size_q}; + end + if (reg_req_i.addr[7:0] == 8'hC) begin + reg_rsp_o.rdata = {31'h0, status_ready_q}; + end + if (reg_req_i.addr[7:0] == 8'h8) begin + reg_rsp_o.rdata = threshold_q; + end + if (reg_req_i.addr[7:0] == 8'h4) begin + reg_rsp_o.rdata = address_write_q; + end + if (reg_req_i.addr[7:0] == 8'h0) begin + reg_rsp_o.rdata = address_read_q; + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + status_start_q <= '0; + size_q <= '0; + status_ready_q <= '0; + threshold_q <= '0; + address_write_q <= '0; + address_read_q <= '0; + end else begin + if (reg_req_i.valid && reg_req_i.write) begin + if (reg_req_i.addr[7:0] == 8'h14) begin + status_start_q <= reg_req_i.wdata[0]; + end + if (reg_req_i.addr[7:0] == 8'h10) begin + size_q <= reg_req_i.wdata[9:0]; + end + if (reg_req_i.addr[7:0] == 8'hC) begin + status_ready_q <= reg_req_i.wdata[0]; + end + if (reg_req_i.addr[7:0] == 8'h8) begin + threshold_q <= reg_req_i.wdata; + end + if (reg_req_i.addr[7:0] == 8'h4) begin + address_write_q <= reg_req_i.wdata; + end + if (reg_req_i.addr[7:0] == 8'h0) begin + address_read_q <= reg_req_i.wdata; + end + end else begin + if (dma_done) status_ready_q <= 1'b1; + status_start_q <= '0; + end + end + end + + + // + // Main DMA state machine + // + // READY : idle, waiting for a write pulse to size registered in `dma_start_pending` + // STARTING: load transaction data + // RUNNING : waiting for transaction finish + // when `dma_done` rises either enter ready or restart in circular mode + // + always_comb begin + dma_state_d = dma_state_q; + case (dma_state_q) + DMA_READY: begin + if (dma_start_pending) begin + dma_state_d = DMA_STARTING; + end + end + DMA_STARTING: begin + dma_state_d = DMA_RUNNING; + end + DMA_RUNNING: begin + if (dma_done) begin + dma_state_d = DMA_READY; + end + end + endcase + end + + // update state + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + dma_state_q <= DMA_READY; + end else begin + dma_state_q <= dma_state_d; + end + end + + + // DMA pulse start when dma_start register is written + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_start + if (~rst_ni) begin + dma_start_pending <= 1'b0; + end else begin + if (dma_start == 1'b1) begin + dma_start_pending <= 1'b0; + end else if (status_start_q && size_q != '0) begin + dma_start_pending <= 1'b1; + end + end + end + + // Store input data pointer and increment everytime read request is granted + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_in_reg + if (~rst_ni) begin + read_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + read_ptr_reg <= address_read_q; + end else if (data_in_gnt == 1'b1) begin + read_ptr_reg <= read_ptr_reg + 32'h4; + end + end + end + + // Only update read_ptr_valid_reg when the data is stored in the fifo + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_valid_in_reg + if (~rst_ni) begin + read_ptr_valid_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + read_ptr_valid_reg <= address_read_q; + end else if (data_in_rvalid == 1'b1) begin + read_ptr_valid_reg <= read_ptr_valid_reg + 32'h4; + end + end + end + + // Store output data pointer and increment everytime write request is granted + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_out_reg + if (~rst_ni) begin + write_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + write_ptr_reg <= address_write_q; + end else if (data_out_gnt == 1'b1) begin + write_ptr_reg <= write_ptr_reg + 32'h4; + end + end + end + + // Store dma transfer size and decrement it everytime input data rvalid is asserted + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_cnt_reg + if (~rst_ni) begin + dma_cnt <= '0; + end else begin + if (dma_start == 1'b1) begin + dma_cnt <= size_q; + end else if (data_in_gnt == 1'b1) begin + dma_cnt <= dma_cnt - 10'h1; + end + end + end + + assign byte_enable_out = 4'b1111; + + assign data_out_wdata = fifo_output; + + assign fifo_input = data_in_rdata; + + // FSM state update + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_fsm_state + if (~rst_ni) begin + dma_read_fsm_state <= DMA_READ_FSM_IDLE; + dma_write_fsm_state <= DMA_WRITE_FSM_IDLE; + outstanding_req <= '0; + end else begin + dma_read_fsm_state <= dma_read_fsm_n_state; + dma_write_fsm_state <= dma_write_fsm_n_state; + outstanding_req <= outstanding_req + (data_in_req && data_in_gnt) - data_in_rvalid; + end + end + + // Read master FSM + always_comb begin : proc_dma_read_fsm_logic + + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + + data_in_req = '0; + data_in_we = '0; + data_in_be = '0; + data_in_addr = '0; + + fifo_flush = 1'b0; + + unique case (dma_read_fsm_state) + + DMA_READ_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1) begin + dma_read_fsm_n_state = DMA_READ_FSM_ON; + fifo_flush = 1'b1; + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end + end + // Read one word + DMA_READ_FSM_ON: begin + // If all input data read exit + if (|dma_cnt == 1'b0) begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is full, almost full (last data) + if (fifo_full == 1'b0 && fifo_alm_full == 1'b0) begin + data_in_req = 1'b1; + data_in_we = 1'b0; + data_in_be = 4'b1111; // always read all bytes + data_in_addr = read_ptr_reg; + end + end + end + endcase + end + + // Write master FSM + always_comb begin : proc_dma_write_fsm_logic + + dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; + dma_done = 1'b0; + + data_out_req = '0; + data_out_we = '0; + data_out_be = '0; + data_out_addr = '0; + + unique case (dma_write_fsm_state) + + DMA_WRITE_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1) begin + dma_write_fsm_n_state = DMA_WRITE_FSM_ON; + end else begin + dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; + end + end + // Read one word + DMA_WRITE_FSM_ON: begin + // If all input data read exit + if (fifo_empty == 1'b1 && dma_read_fsm_state == DMA_READ_FSM_IDLE) begin + dma_done = outstanding_req == '0; + dma_write_fsm_n_state = dma_done ? DMA_WRITE_FSM_IDLE : DMA_WRITE_FSM_ON; + end else begin + dma_write_fsm_n_state = DMA_WRITE_FSM_ON; + // Wait if fifo is empty + if (fifo_empty == 1'b0) begin + data_out_req = 1'b1; + data_out_we = 1'b1; + data_out_be = byte_enable_out; + data_out_addr = write_address; + end + end + end + endcase + end + + fifo_v3 #( + .DEPTH(FIFO_DEPTH) + ) dma_fifo_i ( + .clk_i, + .rst_ni, + .flush_i(fifo_flush), + .testmode_i(1'b0), + // status flags + .full_o(fifo_full), + .empty_o(fifo_empty), + .usage_o(fifo_usage), + // as long as the queue is not full we can push new data + .data_i(fifo_input), + .push_i(data_in_rvalid), + // as long as the queue is not empty we can pop new elements + .data_o(fifo_output), + .pop_i(data_out_gnt) + ); + + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt new file mode 100644 index 00000000..ac1ea03e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt @@ -0,0 +1,10 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Author: Davide Schiavone , EPFL, STI-SEL +// Date: 12.02.2024 + +`verilator_config + +lint_off -rule UNUSED -file "*/simple_accelerator/simple_accelerator.sv" -match "*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv index 785ddd46..6cedd80a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv @@ -79,12 +79,21 @@ module slow_memory #( always_comb begin - gnt_o = 1'b0; - rvalid_o = rvalid_q; - state_n = state_q; - counter_n = counter_q - 1; - rvalid_n = rvalid_q; - + gnt_o = 1'b0; + rvalid_o = rvalid_q; + state_n = state_q; + counter_n = counter_q - 1; + rvalid_n = rvalid_q; + mem_req = '0; + mem_we = '0; + mem_addr = '0; + mem_wdata = '0; + mem_be = '0; + mem_req_n = mem_req_q; + mem_we_n = mem_we_q; + mem_addr_n = mem_addr_q; + mem_wdata_n = mem_wdata_q; + mem_be_n = mem_be_q; unique case (state_q) READY: begin @@ -92,13 +101,13 @@ module slow_memory #( if (req_i) begin gnt_o = random1[0]; if (gnt_o) begin - state_n = WAIT_RVALID; - counter_n = random2[4:0] + 1; - mem_req_n <= req_i; - mem_we_n <= we_i; - mem_addr_n <= addr_i; - mem_wdata_n <= wdata_i; - mem_be_n <= be_i; + state_n = WAIT_RVALID; + counter_n = random2[4:0] + 1; + mem_req_n = req_i; + mem_we_n = we_i; + mem_addr_n = addr_i; + mem_wdata_n = wdata_i; + mem_be_n = be_i; end end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl index 7d58ed79..c88bdaca 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl @@ -48,6 +48,9 @@ module x_heep_system output logic [31:0] exit_value_o, + input logic ext_dma_slot_tx_i, + input logic ext_dma_slot_rx_i, + // eXtension interface if_xif.cpu_compressed xif_compressed_if, if_xif.cpu_issue xif_issue_if, @@ -137,7 +140,9 @@ ${pad.core_v_mini_mcu_bonding} .external_subsystem_rst_no, .external_ram_banks_set_retentive_no, .external_subsystem_clkgate_en_no, - .exit_value_o + .exit_value_o, + .ext_dma_slot_tx_i, + .ext_dma_slot_rx_i ); pad_ring pad_ring_i ( diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core index 56a485a4..a31337d1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core @@ -60,3 +60,4 @@ targets: - files_rtl - ff_regfile - target_sim? (files_clk_gate) + - target_sim_sc? (files_clk_gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson index 39f77e7a..7248758f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/esl-epfl/cv32e40px.git - rev: acf3442b414725191fb7a2027facd0b5b4123c1c + rev: 49770e7dd5d569f440810866f4f33ce6a4f7ef1f } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson index b261db04..547959fe 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson @@ -7,11 +7,9 @@ upstream: { url: "https://github.com/esl-epfl/cv32e40px.git", - rev: "acf3442b414725191fb7a2027facd0b5b4123c1c", + rev: "49770e7dd5d569f440810866f4f33ce6a4f7ef1f", }, - patch_dir: "patches/esl_epfl_cv32e40px", - exclude_from_upstream: [ "ci", ".github", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh index 8c4ae99f..a89ed4e4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh @@ -679,22 +679,22 @@ class instr_trace_t; // decode and print instruction case (instr[11:8]) // cv.starti, cv.endi - 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, rd[0], imm_iz_type); + 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, instr[7], imm_iz_type); // cv.counti - 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, rd[0], imm_iz_type); + 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, instr[7], imm_iz_type); // cv.start, cv.end, cv.count 4'b0001, 4'b0011, 4'b0101: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s", mnemonic, rd[0], regAddrToStr(rs1)); + str = $sformatf("%-16s %d, %s", mnemonic, instr[7], regAddrToStr(rs1)); end // cv.setupi 4'b0110: begin - str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, rd[0], imm_iz_type, rs1); + str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, instr[7], imm_iz_type, rs1); end // cv.setup 4'b0111: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, rd[0], regAddrToStr(rs1), imm_iz_type); + str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, instr[7], regAddrToStr(rs1), imm_iz_type); end endcase end @@ -861,7 +861,7 @@ class instr_trace_t; endcase str_sci = ""; end - + // shuffle/pack 6'b110000: begin if (instr[14:12] == 3'b111) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv index 868de33c..4effb2b8 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv @@ -73,6 +73,10 @@ module cv32e40px_rvfi input logic is_compressed_id_i, input logic ebrk_insn_dec_i, + input logic ecall_insn_dec_i, + + input logic mret_insn_dec_i, + input logic mret_dec_i, input logic [5:0] csr_cause_i, @@ -126,6 +130,9 @@ module cv32e40px_rvfi input logic [31:0] data_wdata_ex_i, input logic lsu_split_q_ex_i, + input logic mult_ready_i, + input logic alu_ready_i, + //// WB probes //// input logic [31:0] pc_wb_i, input logic wb_ready_i, @@ -202,6 +209,7 @@ module cv32e40px_rvfi input logic csr_we_i, input logic [31:0] csr_wdata_int_i, + input logic csr_fregs_we_i, input logic csr_jvt_we_i, input Status_t csr_mstatus_n_i, input Status_t csr_mstatus_q_i, @@ -617,6 +625,8 @@ module cv32e40px_rvfi logic pc_mux_interrupt; logic pc_mux_nmi; + localparam logic [31:0] MSTATUS_WRITE_MASK = 32'h0000_6088; + `include "pipe_freeze_trace.sv" `include "insn_trace.sv" @@ -633,6 +643,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; logic [2:0] saved_debug_cause; integer next_send; + event e_empty_queue; function void empty_fifo(); integer i, trace_q_size; trace_q_size = wb_bypass_trace_q.size(); @@ -648,6 +659,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; new_rvfi_trace.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; rvfi_trace_q.push_back(new_rvfi_trace); next_send = next_send + 1; + ->e_empty_queue; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); end @@ -658,6 +670,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; /* * Function used to alocate a new insn and send it to the rvfi driver */ + event e_add_to_bypass; function void send_rvfi(insn_trace_t m_wb_insn); insn_trace_t new_rvfi_trace; new_rvfi_trace = new(); @@ -667,6 +680,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; next_send = next_send + 1; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); + ->e_add_to_bypass; end empty_fifo(); endfunction @@ -837,7 +851,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; //CSR rvfi_csr_mstatus_rmask = new_rvfi_trace.m_csr.mstatus_rmask | new_rvfi_trace.m_csr.mstatus_fs_rmask; - rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask; + rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask & MSTATUS_WRITE_MASK; rvfi_csr_mstatus_wmask[31] = new_rvfi_trace.m_csr.mstatus_fs_wmask[31]; rvfi_csr_mstatus_wmask[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wmask[14:13]; @@ -870,7 +884,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end rvfi_csr_mstatus_wdata[30:18] = '0; // MPRV is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[17] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.mprv; + rvfi_csr_mstatus_wdata[17] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.mprv; rvfi_csr_mstatus_wdata[16:15] = '0; if (FPU == 1 && ZFINX == 0) begin rvfi_csr_mstatus_wdata[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wdata; @@ -882,11 +896,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; rvfi_csr_mstatus_wdata[7] = new_rvfi_trace.m_csr.mstatus_wdata.mpie; rvfi_csr_mstatus_wdata[6:5] = '0; // UPIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[4] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.upie; + rvfi_csr_mstatus_wdata[4] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.upie; rvfi_csr_mstatus_wdata[3] = new_rvfi_trace.m_csr.mstatus_wdata.mie; rvfi_csr_mstatus_wdata[2:1] = '0; // UIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[0] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.uie; + rvfi_csr_mstatus_wdata[0] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.uie; `SET_RVFI_CSR_FROM_INSN(misa) `SET_RVFI_CSR_FROM_INSN(mie) @@ -1111,6 +1125,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; * The third updates the rvfi interface */ `define CSR_FROM_PIPE(TRACE_NAME, CSR_NAME) \ + if(!trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we) begin \ + trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ + end\ if (r_pipe_freeze_trace.csr.``CSR_NAME``_we) begin \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we = r_pipe_freeze_trace.csr.``CSR_NAME``_we; \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ @@ -1120,9 +1137,14 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_``TRACE_NAME``.m_csr.``CSR_NAME``_rmask = '1; event e_mstatus_to_id; + event e_fregs_dirty_1, e_fregs_dirty_2, e_fregs_dirty_3; function void mstatus_to_id(); `CSR_FROM_PIPE(id, mstatus) `CSR_FROM_PIPE(id, mstatus_fs) + if(r_pipe_freeze_trace.csr.fregs_we && !r_pipe_freeze_trace.csr.mstatus_fs_we && !(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we)) begin //writes happening in ex that needs to be reported to id + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + ->e_fregs_dirty_2; + end ->e_mstatus_to_id; endfunction //those event are for debug purpose @@ -1133,10 +1155,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; e_dev_commit_rf_to_ex_3, e_dev_commit_rf_to_ex_4, e_dev_commit_rf_to_ex_5; - event e_if_2_id_1, e_if_2_id_2; + event e_if_2_id_1, e_if_2_id_2, e_if_2_id_3; event e_ex_to_wb_1, e_ex_to_wb_2; event e_id_to_ex_1, e_id_to_ex_2; event e_commit_dpc; + event e_csr_in_ex, e_csr_irq; event e_send_rvfi_trace_apu_resp; event @@ -1160,12 +1183,17 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(apu_resp, fcsr) `CSR_FROM_PIPE(apu_resp, fflags) - // `CSR_FROM_PIPE(apu_resp, mstatus) `CSR_FROM_PIPE(apu_resp, mstatus_fs) - if (r_pipe_freeze_trace.csr.mstatus_we) begin + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_id.m_order > trace_apu_resp.m_order)) begin + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_ex.m_order > trace_apu_resp.m_order)) begin trace_ex.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_wb.m_order > trace_apu_resp.m_order)) begin + trace_wb.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end endfunction function void csr_to_apu_req(); @@ -1243,6 +1271,15 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_is_irq_start; bit s_id_done; function void if_to_id(); + if (trace_id.m_valid) begin + minstret_to_id(); + `CSR_FROM_PIPE(id, misa) + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + tinfo_to_id(); + `CSR_FROM_PIPE(id, mip) + send_rvfi(trace_id); + end trace_id.init(trace_if); trace_id.m_trap = ~r_pipe_freeze_trace.minstret; trace_id.m_is_illegal = r_pipe_freeze_trace.is_illegal; @@ -1280,34 +1317,40 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_core_is_decoding; // For readability, ctrl_fsm is DECODE or DECODE_HWLOOP - trace_if = new(); - trace_id = new(); - trace_ex = new(); - trace_wb = new(); - s_new_valid_insn = 1'b0; - s_ex_valid_adjusted = 1'b0; + bit s_ex_reg_we_adjusted; //ex_reg_we + bit s_rf_we_wb_adjusted; // + + trace_if = new(); + trace_id = new(); + trace_ex = new(); + trace_wb = new(); + s_new_valid_insn = 1'b0; + s_ex_valid_adjusted = 1'b0; - s_id_done = 1'b0; - s_apu_wb_ok = 1'b0; - s_apu_0_cycle_reps = 1'b0; + s_id_done = 1'b0; + s_apu_wb_ok = 1'b0; + s_apu_0_cycle_reps = 1'b0; - next_send = 1; - cnt_data_req = 0; - cnt_data_resp = 0; - cnt_apu_req = 0; - cnt_apu_resp = 0; - csr_is_irq = '0; - is_dbg_taken = '0; - s_was_flush = 1'b0; + next_send = 1; + cnt_data_req = 0; + cnt_data_resp = 0; + cnt_apu_req = 0; + cnt_apu_resp = 0; + csr_is_irq = '0; + is_dbg_taken = '0; + s_was_flush = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; - s_skip_wb = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; + s_skip_wb = 1'b0; - s_core_is_decoding = 1'b0; + s_core_is_decoding = 1'b0; + + s_ex_reg_we_adjusted = 1'b0; + s_rf_we_wb_adjusted = 1'b0; forever begin wait(e_pipe_monitor_ok.triggered); // event triggered @@ -1387,7 +1430,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_new_valid_insn = r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.is_decoding;// && !r_pipe_freeze_trace.apu_rvalid; - s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX));// && !r_pipe_freeze_trace.apu_rvalid;; + s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_WB) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF));// && !r_pipe_freeze_trace.apu_rvalid;; + s_ex_reg_we_adjusted = r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.mult_ready && r_pipe_freeze_trace.alu_ready && r_pipe_freeze_trace.lsu_ready_ex && !s_apu_to_alu_port; + s_rf_we_wb_adjusted = r_pipe_freeze_trace.rf_we_wb && (~r_pipe_freeze_trace.data_misaligned_ex && r_pipe_freeze_trace.wb_ready) && (!s_apu_to_lsu_port || r_pipe_freeze_trace.wb_contention_lsu); s_fflags_we_non_apu = 1'b0; if (r_pipe_freeze_trace.csr.fflags_we) begin @@ -1418,40 +1463,34 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_skip_wb = 1'b1; end end - if (trace_wb.m_valid && !s_skip_wb) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if((trace_wb.m_rd_addr[0] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[0]) && trace_wb.m_mem_req_id_valid[0]) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[0] = 1'b0; - end else if (trace_wb.m_2_rd_insn && (trace_wb.m_rd_addr[1] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[1]) && trace_wb.m_mem_req_id_valid[1]) begin - trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[1] = 1'b0; - end - end - if (!trace_wb.m_data_missaligned) begin - send_rvfi(trace_wb); - ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; - trace_wb.m_valid = 1'b0; + if (trace_wb.m_valid && !s_skip_wb && s_rf_we_wb_adjusted) begin + if (trace_wb.m_2_rd_insn) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + end else if (trace_wb.m_ex_fw) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + trace_wb.m_2_rd_insn = 1'b1; end else begin - if (s_wb_valid_adjusted) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if (!trace_wb.m_ex_fw) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end - if (trace_wb.m_data_missaligned && !trace_wb.m_got_first_data) begin - trace_wb.m_got_first_data = 1'b1; - end else begin - send_rvfi(trace_wb); - ->e_dev_send_wb_2; ->e_send_rvfi_trace_wb_3; - trace_wb.m_valid = 1'b0; - end - end // rf_we_wb + trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; + end + + if (r_pipe_freeze_trace.csr.fregs_we) begin + `CSR_FROM_PIPE(wb, mstatus_fs) + trace_wb.m_csr.mstatus_fs_we = 1'b1; + trace_wb.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_wb.m_csr.mstatus_fs_wdata = FS_DIRTY; end + ->e_fregs_dirty_1; end + + send_rvfi(trace_wb); + ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; + trace_wb.m_valid = 1'b0; + end if (trace_ex.m_valid) begin @@ -1464,14 +1503,14 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(ex, tdata2) tinfo_to_ex(); - if (r_pipe_freeze_trace.regfile_we_lsu) begin + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_4; - if ((cnt_data_resp == trace_ex.m_mem_req_id[0]) && !(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin + if (!(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; trace_ex.m_mem_req_id_valid[0] = 1'b0; - end else if ((cnt_data_resp == trace_ex.m_mem_req_id[1]) && trace_ex.m_mem_req_id_valid[1]) begin + end else if (trace_ex.m_mem_req_id_valid[1]) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; @@ -1485,7 +1524,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_valid = 1'b0; ->e_send_rvfi_trace_ex_2; end else begin - if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port) begin + if (!s_ex_valid_adjusted & !trace_ex.m_csr.got_minstret) begin + minstret_to_ex(); + end + + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_1; if (trace_ex.m_got_ex_reg) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; @@ -1497,24 +1540,35 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; end - end - if (!s_ex_valid_adjusted & !trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end - if (trace_ex.m_is_load) begin // only move relevant instr in wb stage - ->e_ex_to_wb_1; - trace_wb.move_down_pipe(trace_ex); - end else begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); + if (r_pipe_freeze_trace.csr.fregs_we) begin + `CSR_FROM_PIPE(ex, mstatus_fs) + trace_ex.m_csr.mstatus_fs_we = 1'b1; + trace_ex.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_ex.m_csr.mstatus_fs_wdata = FS_DIRTY; + end + ->e_fregs_dirty_3; end + send_rvfi(trace_ex); - ->e_send_rvfi_trace_ex_6; + trace_ex.m_valid = 1'b0; + + end else begin + if (trace_ex.m_is_load) begin // only move relevant instr in wb stage + ->e_ex_to_wb_1; + trace_wb.move_down_pipe(trace_ex); + end else begin + if (!trace_ex.m_csr.got_minstret) begin + minstret_to_ex(); + end + send_rvfi(trace_ex); + ->e_send_rvfi_trace_ex_6; + end + trace_ex.m_valid = 1'b0; end - trace_ex.m_valid = 1'b0; end - end else if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port && !s_was_flush) begin + end else if (s_rf_we_wb_adjusted && !s_was_flush) begin ->e_dev_commit_rf_to_ex_2; if (trace_ex.m_got_ex_reg) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; @@ -1529,22 +1583,29 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end end - s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF)) && (!r_pipe_freeze_trace.apu_rvalid || r_pipe_freeze_trace.data_req_ex); + // If mret, we need to keep the instruction in Id during flush_ex because mstatus update happens at that time + s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || ((r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) && !r_pipe_freeze_trace.mret_insn_dec)) && (!r_pipe_freeze_trace.apu_rvalid || r_pipe_freeze_trace.data_req_ex); //EX_STAGE if (trace_id.m_valid) begin + + if(trace_id.m_sample_csr_write_in_ex && !csr_is_irq && !s_is_irq_start) begin //First cycle after id_ready, csr write is asserted in this cycle + `CSR_FROM_PIPE(id, mstatus) + `CSR_FROM_PIPE(id, mstatus_fs) + `CSR_FROM_PIPE(id, mepc) + `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, dscratch0) + `CSR_FROM_PIPE(id, dscratch1) + ->e_csr_in_ex; + end + + if(r_pipe_freeze_trace.is_decoding) begin + trace_id.m_sample_csr_write_in_ex = 1'b0; + end mtvec_to_id(); `CSR_FROM_PIPE(id, mip) `CSR_FROM_PIPE(id, misa) - if (!csr_is_irq && !s_is_irq_start) begin - mstatus_to_id(); - `CSR_FROM_PIPE(id, mepc) - if (trace_id.m_csr.mcause_we == '0) begin //for debug purpose - `CSR_FROM_PIPE(id, mcause) - end - end - `CSR_FROM_PIPE(id, mcountinhibit) `CSR_FROM_PIPE(id, mscratch) `CSR_FROM_PIPE(id, mie) @@ -1603,10 +1664,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_rd_addr[0] = r_pipe_freeze_trace.ex_reg_addr; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.ex_reg_wdata; trace_id.m_got_ex_reg = 1'b1; - end else if (!trace_ex.m_valid & r_pipe_freeze_trace.rf_we_wb & !trace_id.m_ex_fw) begin + end else if (!trace_ex.m_valid & s_rf_we_wb_adjusted & !trace_id.m_ex_fw) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end else if (r_pipe_freeze_trace.rf_we_wb) begin + end else if (s_rf_we_wb_adjusted) begin trace_id.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_id.m_2_rd_insn = 1'b1; @@ -1621,19 +1682,16 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end + if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; trace_id.m_mem.wmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end else begin trace_id.m_mem.rmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; end + if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; trace_id.m_mem_req_id[0] = 0; @@ -1692,15 +1750,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; @@ -1708,7 +1761,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem_req_id_valid[0] = 1'b0; trace_id.m_mem_req_id_valid[1] = 1'b1; end - end else if (r_pipe_freeze_trace.rf_we_wb && !r_pipe_freeze_trace.ex_reg_we) begin + end else if (s_rf_we_wb_adjusted && !r_pipe_freeze_trace.ex_reg_we) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; end @@ -1734,12 +1787,21 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; //IF_STAGE if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready) begin - if(trace_if.m_valid && r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin - if_to_id(); - trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; - ->e_if_2_id_2; + if (trace_if.m_valid) begin + if (r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin + if_to_id(); + trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; + ->e_if_2_id_2; + end else if (r_pipe_freeze_trace.is_illegal) begin + if_to_id(); + trace_id.m_is_illegal = 1'b1; + ->e_if_2_id_3; + end else if (r_pipe_freeze_trace.ecall_insn_dec) begin + if_to_id(); + end end + trace_if.m_insn = r_pipe_freeze_trace.instr_if; //Instr comes from if, buffer for one cycle trace_if.m_pc_rdata = r_pipe_freeze_trace.pc_if; trace_if.m_dbg_taken = is_dbg_taken; @@ -1754,6 +1816,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; mstatus_to_id(); `CSR_FROM_PIPE(id, mepc) `CSR_FROM_PIPE(id, mcause) + ->e_csr_irq; end if (!s_id_done && r_pipe_freeze_trace.is_decoding) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv index 1b40b80e..d4aa94dc 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv @@ -272,13 +272,19 @@ module cv32e40px_tb_wrapper .rs1_addr_id_i (cv32e40px_top_i.core_i.id_stage_i.regfile_addr_ra_id), .rs2_addr_id_i (cv32e40px_top_i.core_i.id_stage_i.regfile_addr_rb_id), + .rs3_addr_id_i (cv32e40px_top_i.core_i.id_stage_i.regfile_addr_rc_id), .operand_a_fw_id_i (cv32e40px_top_i.core_i.id_stage_i.operand_a_fw_id), .operand_b_fw_id_i (cv32e40px_top_i.core_i.id_stage_i.operand_b_fw_id), + .operand_c_fw_id_i (cv32e40px_top_i.core_i.id_stage_i.operand_c_fw_id), // .instr (cv32e40px_top_i.core_i.id_stage_i.instr ), .is_compressed_id_i(cv32e40px_top_i.core_i.id_stage_i.is_compressed_i), .ebrk_insn_dec_i (cv32e40px_top_i.core_i.id_stage_i.ebrk_insn_dec), - .csr_cause_i (cv32e40px_top_i.core_i.csr_cause), - .debug_csr_save_i (cv32e40px_top_i.core_i.debug_csr_save), + .ecall_insn_dec_i (cv32e40px_top_i.core_i.id_stage_i.ecall_insn_dec), + .mret_insn_dec_i (cv32e40px_top_i.core_i.id_stage_i.mret_insn_dec), + .mret_dec_i (cv32e40px_top_i.core_i.id_stage_i.mret_dec), + + .csr_cause_i (cv32e40px_top_i.core_i.csr_cause), + .debug_csr_save_i(cv32e40px_top_i.core_i.debug_csr_save), // HWLOOP regs .hwlp_start_q_i (hwlp_start_q), @@ -298,14 +304,16 @@ module cv32e40px_tb_wrapper .apu_multicycle_i (cv32e40px_top_i.core_i.ex_stage_i.apu_multicycle), .wb_contention_lsu_i(cv32e40px_top_i.core_i.ex_stage_i.wb_contention_lsu), .wb_contention_i (cv32e40px_top_i.core_i.ex_stage_i.wb_contention), - + .regfile_we_lsu_i (cv32e40px_top_i.core_i.ex_stage_i.regfile_we_lsu), // .rf_we_alu_i (cv32e40px_top_i.core_i.id_stage_i.regfile_alu_we_fw_i), // .rf_addr_alu_i (cv32e40px_top_i.core_i.id_stage_i.regfile_alu_waddr_fw_i), // .rf_wdata_alu_i (cv32e40px_top_i.core_i.id_stage_i.regfile_alu_wdata_fw_i), + .mult_ready_i (cv32e40px_top_i.core_i.ex_stage_i.mult_ready), + .alu_ready_i (cv32e40px_top_i.core_i.ex_stage_i.alu_ready), //// WB probes //// - .wb_valid_i(cv32e40px_top_i.core_i.wb_valid), - + .wb_valid_i (cv32e40px_top_i.core_i.wb_valid), + .wb_ready_i (cv32e40px_top_i.core_i.lsu_ready_wb), //// LSU probes //// .data_we_ex_i (cv32e40px_top_i.core_i.data_we_ex), .data_atop_ex_i (cv32e40px_top_i.core_i.data_atop_ex), @@ -325,6 +333,8 @@ module cv32e40px_tb_wrapper .lsu_ready_ex_i (cv32e40px_top_i.core_i.lsu_ready_ex), .lsu_ready_wb_i (cv32e40px_top_i.core_i.lsu_ready_wb), + .lsu_data_be_i(cv32e40px_top_i.core_i.load_store_unit_i.data_be), + .data_req_pmp_i(cv32e40px_top_i.core_i.data_req_pmp), .data_gnt_pmp_i(cv32e40px_top_i.core_i.data_gnt_pmp), .data_rvalid_i(cv32e40px_top_i.core_i.data_rvalid_i), @@ -339,11 +349,12 @@ module cv32e40px_tb_wrapper .rf_we_wb_i(cv32e40px_top_i.core_i.id_stage_i.regfile_we_wb_i), .rf_addr_wb_i(cv32e40px_top_i.core_i.id_stage_i.regfile_waddr_wb_i), .rf_wdata_wb_i(cv32e40px_top_i.core_i.id_stage_i.regfile_wdata_wb_i), + .regfile_alu_we_ex_i(cv32e40px_top_i.core_i.id_stage_i.regfile_alu_we_ex_o), // APU .apu_req_i (cv32e40px_top_i.core_i.apu_req_o), .apu_gnt_i (cv32e40px_top_i.core_i.apu_gnt_i), - .apu_rvalid_i(cv32e40px_top_i.core_i.apu_rvalid_i), + .apu_rvalid_i(cv32e40px_top_i.core_i.ex_stage_i.apu_valid), // Controller FSM probes .ctrl_fsm_cs_i(cv32e40px_top_i.core_i.id_stage_i.controller_i.ctrl_fsm_cs), @@ -355,6 +366,8 @@ module cv32e40px_tb_wrapper .csr_we_i (cv32e40px_top_i.core_i.cs_registers_i.csr_we_int), .csr_wdata_int_i(cv32e40px_top_i.core_i.cs_registers_i.csr_wdata_int), + .csr_fregs_we_i(cv32e40px_top_i.core_i.cs_registers_i.fregs_we_i), + .csr_mstatus_n_i (cv32e40px_top_i.core_i.cs_registers_i.mstatus_n), .csr_mstatus_q_i (cv32e40px_top_i.core_i.cs_registers_i.mstatus_q), .csr_mstatus_fs_n_i(cv32e40px_top_i.core_i.cs_registers_i.mstatus_fs_n), @@ -367,6 +380,10 @@ module cv32e40px_tb_wrapper .csr_tdata1_q_i (cv32e40px_top_i.core_i.cs_registers_i.tmatch_control_rdata),//gen_trigger_regs.tmatch_control_exec_q ), .csr_tdata1_we_i(cv32e40px_top_i.core_i.cs_registers_i.gen_trigger_regs.tmatch_control_we), + .csr_tdata2_n_i (cv32e40px_top_i.core_i.cs_registers_i.tmatch_value_rdata),//csr_wdata_int ), + .csr_tdata2_q_i (cv32e40px_top_i.core_i.cs_registers_i.tmatch_value_rdata),//gen_trigger_regs.tmatch_control_exec_q ), + .csr_tdata2_we_i(cv32e40px_top_i.core_i.cs_registers_i.gen_trigger_regs.tmatch_value_we), + .csr_tinfo_n_i({16'h0, cv32e40px_top_i.core_i.cs_registers_i.tinfo_types}), .csr_tinfo_q_i({16'h0, cv32e40px_top_i.core_i.cs_registers_i.tinfo_types}), @@ -424,6 +441,7 @@ module cv32e40px_tb_wrapper ); `endif + `ifdef CV32E40P_RVFI_TRACE_EXECUTION bind cv32e40px_rvfi: rvfi_i cv32e40px_rvfi_trace #( .FPU (FPU), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv index 40edce03..90ee5be9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv @@ -196,8 +196,8 @@ package cv32e40px_tracer_pkg; parameter INSTR_CVEND0 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI0 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT0 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI0 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP0 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI0 = {17'b?, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP0 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVSTARTI1 = {12'b?, 5'b00000, 3'b100, 4'b0000, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVSTART1 = {12'b000000000000, 5'b?, 3'b100, 4'b0001, 1'b1, OPCODE_CUSTOM_1}; @@ -205,8 +205,8 @@ package cv32e40px_tracer_pkg; parameter INSTR_CVEND1 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI1 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT1 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI1 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP1 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI1 = {17'b?, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP1 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_FF1 = {7'b0100001, 5'b0, 5'b?, 3'b011, 5'b?, OPCODE_CUSTOM_1}; @@ -449,8 +449,8 @@ package cv32e40px_tracer_pkg; parameter INSTR_CVSHUFFLE2H = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVSHUFFLE2B = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACK = {5'b11101, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACKH = {5'b11101, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACK = {5'b11110, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACKH = {5'b11110, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKHIB = {5'b11111, 1'b0, 1'b1, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKLOB = {5'b11111, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv index 3db2a7ee..3fe7c184 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv @@ -66,6 +66,8 @@ int m_instret_cnt; + bit m_sample_csr_write_in_ex; + struct { logic [31:0] addr ; logic [ 3:0] rmask; @@ -145,32 +147,33 @@ function new(); - this.m_order = 0; - this.m_skip_order = 1'b0; - this.m_valid = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_intr = '0; - this.m_dbg_taken = 1'b0; - this.m_dbg_cause = '0; - this.m_is_ebreak = '0; - this.m_is_illegal = '0; - this.m_is_irq = '0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; - this.m_instret_cnt = 0; + this.m_order = 0; + this.m_skip_order = 1'b0; + this.m_valid = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_intr = '0; + this.m_dbg_taken = 1'b0; + this.m_dbg_cause = '0; + this.m_is_ebreak = '0; + this.m_is_illegal = '0; + this.m_is_irq = '0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; + this.m_instret_cnt = 0; + this.m_sample_csr_write_in_ex = 1'b1; endfunction function void get_mnemonic(); @@ -875,37 +878,38 @@ if(this.m_skip_order) begin this.m_order = this.m_order + 64'h1; end - this.m_skip_order = 1'b0; - this.m_pc_rdata = r_pipe_freeze_trace.pc_id; - this.m_is_illegal = 1'b0; - this.m_is_irq = 1'b0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_got_regs_write = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_instret_cnt = 0; - this.m_rd_addr[0] = '0; - this.m_rd_addr[1] = '0; - this.m_2_rd_insn = 1'b0; - this.m_rs1_addr = '0; - this.m_rs2_addr = '0; - this.m_rs3_addr = '0; - this.m_ex_fw = '0; - this.m_csr.got_minstret = '0; - this.m_dbg_taken = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; + this.m_skip_order = 1'b0; + this.m_pc_rdata = r_pipe_freeze_trace.pc_id; + this.m_is_illegal = 1'b0; + this.m_is_irq = 1'b0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_got_regs_write = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_instret_cnt = 0; + this.m_sample_csr_write_in_ex = 1'b1; + this.m_rd_addr[0] = '0; + this.m_rd_addr[1] = '0; + this.m_2_rd_insn = 1'b0; + this.m_rs1_addr = '0; + this.m_rs2_addr = '0; + this.m_rs3_addr = '0; + this.m_ex_fw = '0; + this.m_csr.got_minstret = '0; + this.m_dbg_taken = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; this.m_csr.mcause_we = '0; if (is_compressed_id_i) begin this.m_insn[31:16] = '0; @@ -944,47 +948,48 @@ endfunction function void copy_full(insn_trace_t m_source); - this.m_valid = m_source.m_valid; - this.m_stage = m_source.m_stage; - this.m_order = m_source.m_order; - this.m_pc_rdata = m_source.m_pc_rdata; - this.m_insn = m_source.m_insn; - this.m_mnemonic = m_source.m_mnemonic; - this.m_is_memory = m_source.m_is_memory; - this.m_is_load = m_source.m_is_load; - this.m_is_apu = m_source.m_is_apu; - this.m_is_apu_ok = m_source.m_is_apu_ok; - this.m_apu_req_id = m_source.m_apu_req_id; - this.m_mem_req_id = m_source.m_mem_req_id; - this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; - this.m_data_missaligned = m_source.m_data_missaligned; - this.m_got_first_data = m_source.m_got_first_data; - this.m_got_ex_reg = m_source.m_got_ex_reg; - this.m_dbg_taken = m_source.m_dbg_taken; - this.m_dbg_cause = m_source.m_dbg_cause; - this.m_is_ebreak = m_source.m_is_ebreak; - this.m_is_illegal = m_source.m_is_illegal; - this.m_is_irq = m_source.m_is_irq; - this.m_instret_cnt = m_source.m_instret_cnt; - this.m_rs1_addr = m_source.m_rs1_addr; - this.m_rs2_addr = m_source.m_rs2_addr; - this.m_rs3_addr = m_source.m_rs3_addr; - this.m_rs1_rdata = m_source.m_rs1_rdata; - this.m_rs2_rdata = m_source.m_rs2_rdata; - this.m_rs3_rdata = m_source.m_rs3_rdata; - - this.m_ex_fw = m_source.m_ex_fw; - this.m_rd_addr = m_source.m_rd_addr; - this.m_2_rd_insn = m_source.m_2_rd_insn; - this.m_rd_wdata = m_source.m_rd_wdata; - - this.m_intr = m_source.m_intr; - this.m_trap = m_source.m_trap; - this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; - this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; - this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; - - this.m_mem = m_source.m_mem; + this.m_valid = m_source.m_valid; + this.m_stage = m_source.m_stage; + this.m_order = m_source.m_order; + this.m_pc_rdata = m_source.m_pc_rdata; + this.m_insn = m_source.m_insn; + this.m_mnemonic = m_source.m_mnemonic; + this.m_is_memory = m_source.m_is_memory; + this.m_is_load = m_source.m_is_load; + this.m_is_apu = m_source.m_is_apu; + this.m_is_apu_ok = m_source.m_is_apu_ok; + this.m_apu_req_id = m_source.m_apu_req_id; + this.m_mem_req_id = m_source.m_mem_req_id; + this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; + this.m_data_missaligned = m_source.m_data_missaligned; + this.m_got_first_data = m_source.m_got_first_data; + this.m_got_ex_reg = m_source.m_got_ex_reg; + this.m_dbg_taken = m_source.m_dbg_taken; + this.m_dbg_cause = m_source.m_dbg_cause; + this.m_is_ebreak = m_source.m_is_ebreak; + this.m_is_illegal = m_source.m_is_illegal; + this.m_is_irq = m_source.m_is_irq; + this.m_instret_cnt = m_source.m_instret_cnt; + this.m_sample_csr_write_in_ex = m_source.m_sample_csr_write_in_ex; + this.m_rs1_addr = m_source.m_rs1_addr; + this.m_rs2_addr = m_source.m_rs2_addr; + this.m_rs3_addr = m_source.m_rs3_addr; + this.m_rs1_rdata = m_source.m_rs1_rdata; + this.m_rs2_rdata = m_source.m_rs2_rdata; + this.m_rs3_rdata = m_source.m_rs3_rdata; + + this.m_ex_fw = m_source.m_ex_fw; + this.m_rd_addr = m_source.m_rd_addr; + this.m_2_rd_insn = m_source.m_2_rd_insn; + this.m_rd_wdata = m_source.m_rd_wdata; + + this.m_intr = m_source.m_intr; + this.m_trap = m_source.m_trap; + this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; + this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; + this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; + + this.m_mem = m_source.m_mem; //CRS `ASSIGN_CSR(mstatus) `ASSIGN_CSR(mstatus_fs) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv index 58051ab8..88d65d0b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv @@ -64,6 +64,9 @@ typedef struct { logic is_compressed_id; logic ebrk_insn_dec; + logic ecall_insn_dec; + logic mret_insn_dec; + logic mret_dec; logic [5:0] csr_cause; @@ -112,6 +115,9 @@ typedef struct { logic [31:0] data_wdata_ex; logic lsu_split_q_ex; + logic mult_ready; + logic alu_ready; + //// WB probes //// logic [31:0] pc_wb; logic wb_ready; @@ -198,6 +204,8 @@ typedef struct { logic mcause_we; logic dcsr_we; + logic fregs_we; + logic jvt_we; Status_t mstatus_n; Status_t mstatus_q; @@ -348,16 +356,24 @@ function compute_csr_we(); r_pipe_freeze_trace.csr.mstatus_we = 1'b1; r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; end - CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; - CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; - CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; - CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; - CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; - CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; - CSR_FFLAGS: r_pipe_freeze_trace.csr.fflags_we = 1'b1; - CSR_FRM: r_pipe_freeze_trace.csr.frm_we = 1'b1; - CSR_FCSR: r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; + CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; + CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; + CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; + CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; + CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; + CSR_FFLAGS: begin + r_pipe_freeze_trace.csr.fflags_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_FRM: r_pipe_freeze_trace.csr.frm_we = 1'b1; + CSR_FCSR: begin + r_pipe_freeze_trace.csr.fcsr_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_DSCRATCH0: r_pipe_freeze_trace.csr.dscratch0_we = 1'b1; + CSR_DSCRATCH1: r_pipe_freeze_trace.csr.dscratch1_we = 1'b1; endcase end // CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = r_pipe_freeze_trace.csr.mcause_n != r_pipe_freeze_trace.csr.mcause_q; //for debug purpose @@ -416,6 +432,9 @@ task monitor_pipeline(); r_pipe_freeze_trace.jump_target_id = jump_target_id_i; r_pipe_freeze_trace.is_compressed_id = is_compressed_id_i; r_pipe_freeze_trace.ebrk_insn_dec = ebrk_insn_dec_i; + r_pipe_freeze_trace.ecall_insn_dec = ecall_insn_dec_i; + r_pipe_freeze_trace.mret_insn_dec = mret_insn_dec_i; + r_pipe_freeze_trace.mret_dec = mret_dec_i; r_pipe_freeze_trace.csr_cause = csr_cause_i; r_pipe_freeze_trace.debug_csr_save = debug_csr_save_i; r_pipe_freeze_trace.minstret = minstret_i; @@ -462,6 +481,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.data_wdata_ex = data_wdata_ex_i; r_pipe_freeze_trace.lsu_split_q_ex = lsu_split_q_ex_i; + r_pipe_freeze_trace.mult_ready = mult_ready_i; + r_pipe_freeze_trace.alu_ready = alu_ready_i; //// WB probes //// r_pipe_freeze_trace.pc_wb = pc_wb_i; r_pipe_freeze_trace.wb_ready = wb_ready_i; @@ -526,6 +547,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.csr.we = csr_we_i; r_pipe_freeze_trace.csr.wdata_int = csr_wdata_int_i; + r_pipe_freeze_trace.csr.fregs_we = csr_fregs_we_i; + r_pipe_freeze_trace.csr.jvt_we = csr_jvt_we_i; r_pipe_freeze_trace.csr.mstatus_n = csr_mstatus_n_i; r_pipe_freeze_trace.csr.mstatus_q = csr_mstatus_q_i; @@ -650,10 +673,6 @@ task monitor_pipeline(); if (r_pipe_freeze_trace.csr.fcsr_we) begin r_pipe_freeze_trace.csr.fflags_we = 1'b1; r_pipe_freeze_trace.csr.frm_we = 1'b1; - end else begin - if (r_pipe_freeze_trace.csr.fflags_we || r_pipe_freeze_trace.csr.frm_we) begin - r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - end end if (csr_fcsr_fflags_we_i) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv index 6516f932..a3e3bac9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv @@ -491,6 +491,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; @@ -712,6 +713,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; @@ -764,7 +766,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; ebrk_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; + halt_id_o = 1'b0; if (debug_mode_q) // we got back to the park loop in the debug rom @@ -776,15 +778,15 @@ module cv32e40px_controller import cv32e40px_pkg::*; else begin // otherwise just a normal ebreak exception - ctrl_fsm_ns = FLUSH_EX; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end end ecall_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = FLUSH_EX; + halt_id_o = 1'b0; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end csr_status_i: begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv index fc301b91..25aa6cc9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv @@ -194,6 +194,7 @@ module cv32e40px_core logic [31:0] jump_target_id, jump_target_ex; logic branch_in_ex; logic branch_decision; + logic [ 1:0] ctrl_transfer_insn_in_dec; logic ctrl_busy; logic if_busy; @@ -237,6 +238,7 @@ module cv32e40px_core logic [ C_RM-1:0] frm_csr; logic [ C_FFLAG-1:0] fflags_csr; logic fflags_we; + logic fregs_we; // APU logic apu_en_ex; @@ -272,6 +274,7 @@ module cv32e40px_core logic regfile_we_ex; logic [ 5:0] regfile_waddr_fw_wb_o; // From WB to ID logic regfile_we_wb; + logic regfile_we_wb_power; logic [ 31:0] regfile_wdata; logic [ 5:0] regfile_alu_waddr_ex; @@ -279,6 +282,7 @@ module cv32e40px_core logic [ 5:0] regfile_alu_waddr_fw; logic regfile_alu_we_fw; + logic regfile_alu_we_fw_power; logic [ 31:0] regfile_alu_wdata_fw; // CSR control @@ -596,9 +600,10 @@ module cv32e40px_core .instr_req_o (instr_req_int), // Jumps and branches - .branch_in_ex_o (branch_in_ex), - .branch_decision_i(branch_decision), - .jump_target_o (jump_target_id), + .branch_in_ex_o (branch_in_ex), + .branch_decision_i (branch_decision), + .jump_target_o (jump_target_id), + .ctrl_transfer_insn_in_dec_o(ctrl_transfer_insn_in_dec), // IF and ID control signals .clear_instr_valid_o(clear_instr_valid), @@ -790,13 +795,15 @@ module cv32e40px_core .wake_from_sleep_o(wake_from_sleep), // Forward Signals - .regfile_waddr_wb_i(regfile_waddr_fw_wb_o), // Write address ex-wb pipeline - .regfile_we_wb_i (regfile_we_wb), // write enable for the register file - .regfile_wdata_wb_i(regfile_wdata), // write data to commit in the register file + .regfile_waddr_wb_i (regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i (regfile_we_wb), // write enable for the register file + .regfile_we_wb_power_i(regfile_we_wb_power), + .regfile_wdata_wb_i (regfile_wdata), // write data to commit in the register file - .regfile_alu_waddr_fw_i(regfile_alu_waddr_fw), - .regfile_alu_we_fw_i (regfile_alu_we_fw), - .regfile_alu_wdata_fw_i(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_i (regfile_alu_waddr_fw), + .regfile_alu_we_fw_i (regfile_alu_we_fw), + .regfile_alu_we_fw_power_i(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_i (regfile_alu_wdata_fw), // from ALU .mult_multicycle_i(mult_multicycle), @@ -828,6 +835,7 @@ module cv32e40px_core // // ///////////////////////////////////////////////////// cv32e40px_ex_stage #( + .COREV_PULP (COREV_PULP), .FPU (FPU), .APU_NARGS_CPU (APU_NARGS_CPU), .APU_WOP_CPU (APU_WOP_CPU), @@ -876,6 +884,8 @@ module cv32e40px_core .data_misaligned_ex_i(data_misaligned_ex), // from ID/EX pipeline .data_misaligned_i (data_misaligned), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + // FPU .fpu_fflags_we_o(fflags_we), .fpu_fflags_o (fflags_csr), @@ -941,18 +951,20 @@ module cv32e40px_core .regfile_we_i (regfile_we_ex), // Output of ex stage pipeline - .regfile_waddr_wb_o(regfile_waddr_fw_wb_o), - .regfile_we_wb_o (regfile_we_wb), - .regfile_wdata_wb_o(regfile_wdata), + .regfile_waddr_wb_o (regfile_waddr_fw_wb_o), + .regfile_we_wb_o (regfile_we_wb), + .regfile_we_wb_power_o(regfile_we_wb_power), + .regfile_wdata_wb_o (regfile_wdata), // To IF: Jump and branch target and decision .jump_target_o (jump_target_ex), .branch_decision_o(branch_decision), // To ID stage: Forwarding signals - .regfile_alu_waddr_fw_o(regfile_alu_waddr_fw), - .regfile_alu_we_fw_o (regfile_alu_we_fw), - .regfile_alu_wdata_fw_o(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_o (regfile_alu_waddr_fw), + .regfile_alu_we_fw_o (regfile_alu_we_fw), + .regfile_alu_we_fw_power_o(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_o (regfile_alu_wdata_fw), // stall control .is_decoding_i (is_decoding), @@ -1072,6 +1084,7 @@ module cv32e40px_core .frm_o (frm_csr), .fflags_i (fflags_csr), .fflags_we_i(fflags_we), + .fregs_we_i (fregs_we), // Interrupt related control signals .mie_bypass_o (mie_bypass), @@ -1140,13 +1153,16 @@ module cv32e40px_core ); // CSR access - assign csr_addr = csr_addr_int; - assign csr_wdata = alu_operand_a_ex; - assign csr_op = csr_op_ex; + assign csr_addr = csr_addr_int; + assign csr_wdata = alu_operand_a_ex; + assign csr_op = csr_op_ex; assign csr_addr_int = csr_num_e'(csr_access_ex ? alu_operand_b_ex[11:0] : '0); - + // Floating-Point registers write + assign fregs_we = (FPU & !ZFINX) ? ((regfile_alu_we_fw && regfile_alu_waddr_fw[5]) || + (regfile_we_wb && regfile_waddr_fw_wb_o[5])) + : 1'b0; /////////////////////////// // ____ __ __ ____ // diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv index 2d873452..f24b3bf9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv @@ -68,6 +68,7 @@ module cv32e40px_cs_registers output logic [ 2:0] frm_o, input logic [C_FFLAG-1:0] fflags_i, input logic fflags_we_i, + input logic fregs_we_i, // Interrupts output logic [31:0] mie_bypass_o, @@ -212,6 +213,7 @@ module cv32e40px_cs_registers logic [31:0] exception_pc; Status_t mstatus_q, mstatus_n; + logic mstatus_we_int; FS_t mstatus_fs_q, mstatus_fs_n; logic [5:0] mcause_q, mcause_n; logic [5:0] ucause_q, ucause_n; @@ -897,6 +899,7 @@ module cv32e40px_cs_registers dscratch0_n = dscratch0_q; dscratch1_n = dscratch1_q; + mstatus_we_int = 1'b0; mstatus_n = mstatus_q; mcause_n = mcause_q; ucause_n = '0; // Not used if PULP_SECURE == 0 @@ -957,7 +960,8 @@ module cv32e40px_cs_registers mprv: csr_wdata_int[MSTATUS_MPRV_BIT] }; if (FPU == 1 && ZFINX == 0) begin - mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); + mstatus_we_int = 1'b1; + mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); end end // mie: machine interrupt enable @@ -1027,7 +1031,7 @@ module cv32e40px_cs_registers if (ZFINX == 0) begin // FPU Register File/Flags implicit update or modified by CSR instructions - if (fflags_we_i || fcsr_update) begin + if ((fregs_we_i && !(mstatus_we_int && mstatus_fs_n != FS_DIRTY)) || fflags_we_i || fcsr_update) begin mstatus_fs_n = FS_DIRTY; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv index 6ab1b01b..3beaf022 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv @@ -34,6 +34,7 @@ module cv32e40px_ex_stage import cv32e40px_apu_core_pkg::*; import cv32e40px_core_v_xif_pkg::*; #( + parameter COREV_PULP = 0, parameter FPU = 0, parameter APU_NARGS_CPU = 3, parameter APU_WOP_CPU = 6, @@ -82,6 +83,8 @@ module cv32e40px_ex_stage input logic data_misaligned_ex_i, input logic data_misaligned_i, + input logic [1:0] ctrl_transfer_insn_in_dec_i, + // FPU signals output logic fpu_fflags_we_o, output logic [APU_NUSFLAGS_CPU-1:0] fpu_fflags_o, @@ -152,11 +155,13 @@ module cv32e40px_ex_stage // Output of EX stage pipeline output logic [ 5:0] regfile_waddr_wb_o, output logic regfile_we_wb_o, + output logic regfile_we_wb_power_o, output logic [31:0] regfile_wdata_wb_o, // Forwarding ports : to ID stage output logic [ 5:0] regfile_alu_waddr_fw_o, output logic regfile_alu_we_fw_o, + output logic regfile_alu_we_fw_power_o, output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL // To IF: Jump and branch target and decision @@ -204,30 +209,36 @@ module cv32e40px_ex_stage // ALU write port mux always_comb begin - regfile_alu_wdata_fw_o = '0; - regfile_alu_waddr_fw_o = '0; - regfile_alu_we_fw_o = '0; - wb_contention = 1'b0; - result_fw_to_x_o = '0; + regfile_alu_wdata_fw_o = '0; + regfile_alu_waddr_fw_o = '0; + regfile_alu_we_fw_o = '0; + wb_contention = 1'b0; + result_fw_to_x_o = '0; + regfile_alu_we_fw_power_o = 1'b0; if (x_result_valid_assigned_i & x_result_we_i & (x_result_rd_i != 5'b00000)) begin - regfile_alu_we_fw_o = 1'b1; - regfile_alu_waddr_fw_o = {1'b0, x_result_rd_i}; - regfile_alu_wdata_fw_o = x_result_data_i; + regfile_alu_we_fw_o = 1'b1; + regfile_alu_we_fw_power_o = 1'b1; + regfile_alu_waddr_fw_o = {1'b0, x_result_rd_i}; + regfile_alu_wdata_fw_o = x_result_data_i; if (regfile_alu_we_i) begin wb_contention = 1'b1; end end else begin // APU single cycle operations, and multicycle operations (>2cycles) are written back on ALU port if (apu_valid & (apu_singlecycle | apu_multicycle)) begin - regfile_alu_we_fw_o = 1'b1; - regfile_alu_waddr_fw_o = apu_waddr; - regfile_alu_wdata_fw_o = apu_result; - result_fw_to_x_o = apu_result; + regfile_alu_we_fw_o = 1'b1; + regfile_alu_we_fw_power_o = 1'b1; + regfile_alu_waddr_fw_o = apu_waddr; + regfile_alu_wdata_fw_o = apu_result; + result_fw_to_x_o = apu_result; if (regfile_alu_we_i & ~apu_en_i) begin wb_contention = 1'b1; end end else begin - regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_we_fw_power_o = !COREV_PULP ? regfile_alu_we_i & ~apu_en_i : + regfile_alu_we_i & ~apu_en_i & + mult_ready & alu_ready & lsu_ready_ex_i; regfile_alu_waddr_fw_o = regfile_alu_waddr_i; if (alu_en_i) begin regfile_alu_wdata_fw_o = alu_result; @@ -247,21 +258,24 @@ module cv32e40px_ex_stage // LSU write port mux always_comb begin - regfile_we_wb_o = 1'b0; - regfile_waddr_wb_o = regfile_waddr_lsu; - regfile_wdata_wb_o = lsu_rdata_i; - wb_contention_lsu = 1'b0; + regfile_we_wb_o = 1'b0; + regfile_we_wb_power_o = 1'b0; + regfile_waddr_wb_o = regfile_waddr_lsu; + regfile_wdata_wb_o = lsu_rdata_i; + wb_contention_lsu = 1'b0; if (regfile_we_lsu) begin - regfile_we_wb_o = 1'b1; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = !COREV_PULP ? 1'b1 : ~data_misaligned_ex_i & wb_ready_i; if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin wb_contention_lsu = 1'b1; end // APU two-cycle operations are written back on LSU port end else if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin - regfile_we_wb_o = 1'b1; - regfile_waddr_wb_o = apu_waddr; - regfile_wdata_wb_o = apu_result; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = 1'b1; + regfile_waddr_wb_o = apu_waddr; + regfile_wdata_wb_o = apu_result; end end @@ -406,11 +420,20 @@ module cv32e40px_ex_stage apu_result_q <= 'b0; apu_flags_q <= 'b0; end else begin - if (apu_rvalid_i && apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || (data_req_i && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + if (apu_rvalid_i && apu_multicycle && + (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b1; apu_result_q <= apu_result_i; apu_flags_q <= apu_flags_i; - end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b0; end end @@ -418,7 +441,12 @@ module cv32e40px_ex_stage assign apu_req_o = apu_req; assign apu_gnt = apu_gnt_i; - assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); + assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) + ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); assign apu_operands_o = apu_operands_i; assign apu_op_o = apu_op_i; assign apu_result = apu_rvalid_q ? apu_result_q : apu_result_i; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv index 8502e341..54add99d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv @@ -111,7 +111,7 @@ module cv32e40px_fp_wrapper .int_fmt_i (fpnew_pkg::int_format_e'(fpu_int_fmt)), .vectorial_op_i(fpu_vec_op), .tag_i (1'b0), - .simd_mask_i ('b0), + .simd_mask_i (1'b0), .in_valid_i (apu_req_i), .in_ready_o (apu_gnt_o), .flush_i (1'b0), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv index 4c513d27..6e996c32 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv @@ -72,6 +72,7 @@ module cv32e40px_id_stage output logic branch_in_ex_o, input logic branch_decision_i, output logic [31:0] jump_target_o, + output logic [ 1:0] ctrl_transfer_insn_in_dec_o, // IF and ID stage signals output logic clear_instr_valid_o, @@ -263,10 +264,12 @@ module cv32e40px_id_stage // Forward Signals input logic [5:0] regfile_waddr_wb_i, input logic regfile_we_wb_i, + input logic regfile_we_wb_power_i, input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata input logic [ 5:0] regfile_alu_waddr_fw_i, input logic regfile_alu_we_fw_i, + input logic regfile_alu_we_fw_power_i, input logic [31:0] regfile_alu_wdata_fw_i, // from ALU @@ -302,6 +305,9 @@ module cv32e40px_id_stage localparam REG_D_MSB = 11; localparam REG_D_LSB = 7; + + localparam REGFILE_NUM_READ_PORTS = ((COREV_X_IF == 1) & (X_DUALREAD == 1)) ? 2 : 1; + logic [31:0] instr; @@ -381,9 +387,9 @@ module cv32e40px_id_stage logic [ 5:0] regfile_alu_waddr_id; logic regfile_alu_we_id, regfile_alu_we_dec_id; - logic [31:0] regfile_data_ra_id; - logic [31:0] regfile_data_rb_id; - logic [31:0] regfile_data_rc_id; + logic [REGFILE_NUM_READ_PORTS-1:0][31:0] regfile_data_ra_id; + logic [REGFILE_NUM_READ_PORTS-1:0][31:0] regfile_data_rb_id; + logic [REGFILE_NUM_READ_PORTS-1:0][31:0] regfile_data_rc_id; // ALU Control logic alu_en; @@ -438,8 +444,8 @@ module cv32e40px_id_stage logic [2:0][4:0] x_rs_addr; logic x_mem_data_req; logic x_mem_valid; - logic [2:0] x_ex_fwd; - logic [2:0] x_wb_fwd; + logic [RF_READ_PORTS-1:0] x_ex_fwd; + logic [RF_READ_PORTS-1:0] x_wb_fwd; // Register Write Control logic regfile_we_id; @@ -622,17 +628,18 @@ module cv32e40px_id_stage // \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| // // |_| |___/ // ////////////////////////////////////////////////////////////////// - - always_comb begin : jump_target_mux - unique case (ctrl_transfer_target_mux_sel) - JT_JAL: jump_target = pc_id_i + imm_uj_type; - JT_COND: jump_target = pc_id_i + imm_sb_type; - - // JALR: Cannot forward RS1, since the path is too long - JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; - default: jump_target = regfile_data_ra_id + imm_i_type; - endcase - end + generate + always_comb begin : jump_target_mux + unique case (ctrl_transfer_target_mux_sel) + JT_JAL: jump_target = pc_id_i + imm_uj_type; + JT_COND: jump_target = pc_id_i + imm_sb_type; + + // JALR: Cannot forward RS1, since the path is too long + JT_JALR: jump_target = regfile_data_ra_id[0] + imm_i_type; + default: jump_target = regfile_data_ra_id[0] + imm_i_type; + endcase + end + endgenerate assign jump_target_o = jump_target; @@ -666,16 +673,18 @@ module cv32e40px_id_stage endcase end - // Operand a forwarding mux - always_comb begin : operand_a_fw_mux - case (operand_a_fw_mux_sel) - SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; - SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; - SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; - default: operand_a_fw_id = regfile_data_ra_id; - endcase - ; // case (operand_a_fw_mux_sel) - end + generate + // Operand a forwarding mux + always_comb begin : operand_a_fw_mux + case (operand_a_fw_mux_sel) + SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id[0]; + default: operand_a_fw_id = regfile_data_ra_id[0]; + endcase + ; // case (operand_a_fw_mux_sel) + end + endgenerate ////////////////////////////////////////////////////// // ___ _ ____ // @@ -732,16 +741,31 @@ module cv32e40px_id_stage assign alu_operand_b = (scalar_replication == 1'b1) ? operand_b_vec : operand_b; - // Operand b forwarding mux - always_comb begin : operand_b_fw_mux - case (operand_b_fw_mux_sel) - SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; - SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; - SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; - default: operand_b_fw_id = regfile_data_rb_id; - endcase - ; // case (operand_b_fw_mux_sel) - end + generate + if (X_DUALREAD == 0) begin : no_dualread_fw_b + // Operand b forwarding mux + always_comb begin : operand_b_fw_mux + case (operand_b_fw_mux_sel) + SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; + default: operand_b_fw_id = regfile_data_rb_id; + endcase + ; // case (operand_b_fw_mux_sel) + end + end else begin : dualread_fw_b + // Operand b forwarding mux + always_comb begin : operand_b_fw_mux + case (operand_b_fw_mux_sel) + SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id[0]; + default: operand_b_fw_id = regfile_data_rb_id[0]; + endcase + ; // case (operand_b_fw_mux_sel) + end + end + endgenerate ////////////////////////////////////////////////////// @@ -777,17 +801,31 @@ module cv32e40px_id_stage assign alu_operand_c = (scalar_replication_c == 1'b1) ? operand_c_vec : operand_c; - // Operand c forwarding mux - always_comb begin : operand_c_fw_mux - case (operand_c_fw_mux_sel) - SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; - SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; - SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id; - default: operand_c_fw_id = regfile_data_rc_id; - endcase - ; // case (operand_c_fw_mux_sel) - end - + generate + if (X_DUALREAD == 0) begin : no_dualread_fw_c + // Operand c forwarding mux + always_comb begin : operand_c_fw_mux + case (operand_c_fw_mux_sel) + SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id; + default: operand_c_fw_id = regfile_data_rc_id; + endcase + ; // case (operand_c_fw_mux_sel) + end + end else begin : dualread_fw_c + // Operand c forwarding mux + always_comb begin : operand_c_fw_mux + case (operand_c_fw_mux_sel) + SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id[0]; + default: operand_c_fw_id = regfile_data_rc_id[0]; + endcase + ; // case (operand_c_fw_mux_sel) + end + end + endgenerate /////////////////////////////////////////////////////////////////////////// // ___ _ _ _ ___ ____ // @@ -865,6 +903,9 @@ module cv32e40px_id_stage if (ctrl_transfer_target_mux_sel == JT_JALR) begin apu_read_regs[0] = regfile_addr_ra_id; apu_read_regs_valid[0] = 1'b1; + end else begin + apu_read_regs[0] = regfile_addr_ra_id; + apu_read_regs_valid[0] = 1'b0; end end // OP_A_CURRPC: OP_A_REGA_OR_FWD: begin @@ -982,13 +1023,17 @@ module cv32e40px_id_stage .ADDR_WIDTH(6), .DATA_WIDTH(32), .FPU (FPU), - .ZFINX (ZFINX) + .ZFINX (ZFINX), + .COREV_X_IF(COREV_X_IF), + .X_DUALREAD(X_DUALREAD) ) register_file_i ( .clk (clk), .rst_n(rst_n), .scan_cg_en_i(scan_cg_en_i), + .dualread_i(x_issue_resp_i.dualread), + // Read port a .raddr_a_i(regfile_addr_ra_id), .rdata_a_o(regfile_data_ra_id), @@ -1004,12 +1049,12 @@ module cv32e40px_id_stage // Write port a .waddr_a_i(regfile_waddr_wb_i), .wdata_a_i(regfile_wdata_wb_i), - .we_a_i (regfile_we_wb_i), + .we_a_i (regfile_we_wb_power_i), // Write port b .waddr_b_i(regfile_alu_waddr_fw_i), .wdata_b_i(regfile_alu_wdata_fw_i), - .we_b_i (regfile_alu_we_fw_i) + .we_b_i (regfile_alu_we_fw_power_i) ); logic [1:0] x_mem_data_type_id; @@ -1037,6 +1082,7 @@ module cv32e40px_id_stage .x_issue_valid_o (x_issue_valid_o), .x_issue_ready_i (x_issue_ready_i), .x_issue_resp_writeback_i(x_issue_resp_i.writeback), + .x_issue_resp_dualread_i (x_issue_resp_i.dualread), .x_issue_resp_accept_i (x_issue_resp_i.accept), .x_issue_resp_loadstore_i(x_issue_resp_i.loadstore), .x_issue_req_rs_valid_o (x_issue_req_o.rs_valid), @@ -1118,22 +1164,25 @@ module cv32e40px_id_stage assign x_mem_valid = x_mem_valid_i; // xif integer souce operand selection - for (genvar i = 0; i < 3; i++) begin : xif_operand_assignment - always_comb begin - if (i == 0) begin - x_issue_req_o.rs[i] = regfile_data_ra_id; - end else if (i == 1) begin - x_issue_req_o.rs[i] = regfile_data_rb_id; - end else begin - x_issue_req_o.rs[i] = regfile_data_rc_id; - end - if (x_ex_fwd[i]) begin - x_issue_req_o.rs[i] = result_fw_to_x_i; - end else if (x_wb_fwd[i]) begin - x_issue_req_o.rs[i] = regfile_wdata_wb_i; + for (genvar j = 0; j < REGFILE_NUM_READ_PORTS; j++) begin : xif_operand_assignment_dualread + for (genvar i = 0; i < 3; i++) begin : xif_operand_assignment + always_comb begin + if (i == 0) begin + x_issue_req_o.rs[i+3*j] = regfile_data_ra_id[j]; + end else if (i == 1) begin + x_issue_req_o.rs[i+3*j] = regfile_data_rb_id[j]; + end else begin + x_issue_req_o.rs[i+3*j] = regfile_data_rc_id[j]; + end + if (x_ex_fwd[i+3*j]) begin + x_issue_req_o.rs[i+3*j] = result_fw_to_x_i; + end else if (x_wb_fwd[i+3*j]) begin + x_issue_req_o.rs[i+3*j] = regfile_wdata_wb_i; + end end end end + // LSU signal assignment/MUX always_comb begin x_mem_data_type_id = 2'b00; @@ -1300,7 +1349,7 @@ module cv32e40px_id_stage .debug_wfi_no_sleep_i(debug_wfi_no_sleep), // jump/branches - .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec_o), .ctrl_transfer_insn_in_id_o (ctrl_transfer_insn_in_id), .ctrl_transfer_target_mux_sel_o(ctrl_transfer_target_mux_sel), @@ -1400,7 +1449,7 @@ module cv32e40px_id_stage // jump/branch control .branch_taken_ex_i (branch_taken_ex), .ctrl_transfer_insn_in_id_i (ctrl_transfer_insn_in_id), - .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec_o), // Interrupt signals .irq_wu_ctrl_i (irq_wu_ctrl), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv index 1543f6e9..d0aad583 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv @@ -31,7 +31,9 @@ module cv32e40px_register_file #( parameter ADDR_WIDTH = 5, parameter DATA_WIDTH = 32, parameter FPU = 0, - parameter ZFINX = 0 + parameter ZFINX = 0, + parameter COREV_X_IF = 0, + parameter X_DUALREAD = 0 ) ( // Clock and Reset input logic clk, @@ -39,17 +41,19 @@ module cv32e40px_register_file #( input logic scan_cg_en_i, + input logic [2:0] dualread_i, + //Read port R1 - input logic [ADDR_WIDTH-1:0] raddr_a_i, - output logic [DATA_WIDTH-1:0] rdata_a_o, + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_a_o, //Read port R2 - input logic [ADDR_WIDTH-1:0] raddr_b_i, - output logic [DATA_WIDTH-1:0] rdata_b_o, + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_b_o, //Read port R3 - input logic [ADDR_WIDTH-1:0] raddr_c_i, - output logic [DATA_WIDTH-1:0] rdata_c_o, + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_c_o, // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, @@ -86,17 +90,53 @@ module cv32e40px_register_file #( //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- - assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; - assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; - assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; - + generate + if (COREV_X_IF != 0) begin + if (X_DUALREAD) begin + always_comb begin + rdata_a_o[0] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + rdata_b_o[0] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + rdata_c_o[0] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + if (dualread_i[0] == 1) + rdata_a_o[1] = raddr_a_i[5] ? (mem_fp[{ + raddr_a_i[4:1], raddr_a_i[0]|1'b1 + }]) : (mem[{ + raddr_a_i[4:1], raddr_a_i[0]|1'b1 + }]); + else rdata_a_o[1] = '0; + if (dualread_i[1] == 1) + rdata_b_o[1] = raddr_b_i[5] ? (mem_fp[{ + raddr_b_i[4:1], raddr_b_i[0]|1'b1 + }]) : (mem[{ + raddr_b_i[4:1], raddr_b_i[0]|1'b1 + }]); + else rdata_b_o[1] = '0; + if (dualread_i[2] == 1) + rdata_c_o[1] = raddr_c_i[5] ? (mem_fp[{ + raddr_c_i[4:1], raddr_c_i[0]|1'b1 + }]) : (mem[{ + raddr_c_i[4:1], raddr_c_i[0]|1'b1 + }]); + else rdata_c_o[1] = '0; + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + endgenerate //----------------------------------------------------------------------------- //-- WRITE : Write Address Decoder (WAD), combinatorial process //----------------------------------------------------------------------------- // Mask top bit of write address to disable fp regfile - assign waddr_a = waddr_a_i; - assign waddr_b = waddr_b_i; + assign waddr_a = waddr_a_i; + assign waddr_b = waddr_b_i; genvar gidx; generate diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv index 037db7c4..217150c0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv @@ -33,7 +33,9 @@ module cv32e40px_register_file #( parameter ADDR_WIDTH = 5, parameter DATA_WIDTH = 32, parameter FPU = 0, - parameter ZFINX = 0 + parameter ZFINX = 0, + parameter COREV_X_IF = 0, + parameter X_DUALREAD = 0 ) ( // Clock and Reset input logic clk, @@ -41,17 +43,19 @@ module cv32e40px_register_file #( input logic scan_cg_en_i, + input logic dualread_i, + //Read port R1 - input logic [ADDR_WIDTH-1:0] raddr_a_i, - output logic [DATA_WIDTH-1:0] rdata_a_o, + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_a_o, //Read port R2 - input logic [ADDR_WIDTH-1:0] raddr_b_i, - output logic [DATA_WIDTH-1:0] rdata_b_o, + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_b_o, //Read port R3 - input logic [ADDR_WIDTH-1:0] raddr_c_i, - output logic [DATA_WIDTH-1:0] rdata_c_o, + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_c_o, // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, @@ -98,10 +102,37 @@ module cv32e40px_register_file #( //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- - assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; - assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; - assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; - + generate + if (COREV_X_IF != 0) begin + if (X_DUALREAD) begin + always_comb begin + if (dualread_i) begin + rdata_a_o[0] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + rdata_b_o[0] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + rdata_c_o[0] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + rdata_a_o[1] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0] | 5'b00001] : mem[raddr_a_i[4:0] | 5'b00001]; + rdata_b_o[1] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0] | 5'b00001] : mem[raddr_b_i[4:0] | 5'b00001]; + rdata_c_o[1] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0] | 5'b00001] : mem[raddr_c_i[4:0] | 5'b00001]; + end else begin + rdata_a_o[0] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + rdata_b_o[0] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + rdata_c_o[0] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + rdata_b_o[1] = '0; + rdata_a_o[1] = '0; + rdata_c_o[1] = '0; + end + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + endgenerate //----------------------------------------------------------------------------- // WRITE : SAMPLE INPUT DATA //--------------------------------------------------------------------------- diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv index 71bbf665..fe147124 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv @@ -33,11 +33,13 @@ module cv32e40px_x_disp input logic x_issue_ready_i, input logic x_issue_resp_accept_i, input logic x_issue_resp_writeback_i, - input logic x_issue_resp_loadstore_i, // unused - output logic [2:0] x_issue_req_rs_valid_o, - output logic [3:0] x_issue_req_id_o, - output logic [1:0] x_issue_req_mode_o, - output logic x_issue_req_ecs_valid, + + input logic [ 2:0] x_issue_resp_dualread_i, + input logic x_issue_resp_loadstore_i, // unused + output logic [RF_READ_PORTS-1:0] x_issue_req_rs_valid_o, + output logic [ 3:0] x_issue_req_id_o, + output logic [ 1:0] x_issue_req_mode_o, + output logic x_issue_req_ecs_valid, // commit interface output logic x_commit_valid_o, @@ -65,19 +67,19 @@ module cv32e40px_x_disp input logic x_result_we_i, // scoreboard, dependency check, stall, forwarding - input logic [4:0] waddr_id_i, - input logic [4:0] waddr_ex_i, - input logic [4:0] waddr_wb_i, - input logic we_ex_i, - input logic we_wb_i, - input logic [4:0] mem_instr_waddr_ex_i, - input logic mem_instr_we_ex_i, - input logic [2:0] regs_used_i, - input logic branch_or_jump_i, - input logic instr_valid_i, - input logic [2:0][4:0] x_rs_addr_i, - output logic [2:0] x_ex_fwd_o, - output logic [2:0] x_wb_fwd_o, + input logic [ 4:0] waddr_id_i, + input logic [ 4:0] waddr_ex_i, + input logic [ 4:0] waddr_wb_i, + input logic we_ex_i, + input logic we_wb_i, + input logic [ 4:0] mem_instr_waddr_ex_i, + input logic mem_instr_we_ex_i, + input logic [ 2:0] regs_used_i, + input logic branch_or_jump_i, + input logic instr_valid_i, + input logic [ 2:0][4:0] x_rs_addr_i, + output logic [RF_READ_PORTS-1:0] x_ex_fwd_o, + output logic [RF_READ_PORTS-1:0] x_wb_fwd_o, // memory request core-internal status signals output logic x_mem_data_req_o, @@ -109,14 +111,31 @@ module cv32e40px_x_disp // issue interface assign x_issue_valid_o = x_illegal_insn_dec_i & ~branch_or_jump_i & ~instr_offloaded_q & instr_valid_i & ~illegal_forwarding_prevention; assign x_issue_req_id_o = id_q; - assign x_issue_req_rs_valid_o[0] = (~scoreboard_q[x_rs_addr_i[0]] | x_ex_fwd_o[0] | x_wb_fwd_o[0]) - & ~(x_rs_addr_i[0] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[0] == waddr_wb_i & ~ex_valid_i); - assign x_issue_req_rs_valid_o[1] = (~scoreboard_q[x_rs_addr_i[1]] | x_ex_fwd_o[1] | x_wb_fwd_o[1]) - & ~(x_rs_addr_i[1] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[1] == waddr_wb_i & ~ex_valid_i); - assign x_issue_req_rs_valid_o[2] = (~scoreboard_q[x_rs_addr_i[2]] | x_ex_fwd_o[2] | x_wb_fwd_o[2]) - & ~(x_rs_addr_i[2] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[2] == waddr_wb_i & ~ex_valid_i); - assign x_issue_req_ecs_valid = 1'b1; // extension context status is not implemented in cv32e40px - + generate + if (X_DUALREAD != 0) begin + assign x_issue_req_rs_valid_o[0] = (~scoreboard_q[x_rs_addr_i[0]] | x_ex_fwd_o[0] | x_wb_fwd_o[0]) + & ~(x_rs_addr_i[0] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[0] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[1] = (~scoreboard_q[x_rs_addr_i[1]] | x_ex_fwd_o[1] | x_wb_fwd_o[1]) + & ~(x_rs_addr_i[1] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[1] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[2] = (~scoreboard_q[x_rs_addr_i[2]] | x_ex_fwd_o[2] | x_wb_fwd_o[2]) + & ~(x_rs_addr_i[2] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[2] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[3] = (~scoreboard_q[x_rs_addr_i[0] | 5'b00001] | x_ex_fwd_o[3] | x_wb_fwd_o[3]) + & ~((x_rs_addr_i[0] | 5'b00001) == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~((x_rs_addr_i[0] | 5'b00001) == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[4] = (~scoreboard_q[x_rs_addr_i[1] | 5'b00001] | x_ex_fwd_o[4] | x_wb_fwd_o[4]) + & ~((x_rs_addr_i[1] | 5'b00001) == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~((x_rs_addr_i[1] | 5'b00001) == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[5] = (~scoreboard_q[x_rs_addr_i[2] | 5'b00001] | x_ex_fwd_o[5] | x_wb_fwd_o[5]) + & ~((x_rs_addr_i[2] | 5'b00001) == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~((x_rs_addr_i[2] | 5'b00001) == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_ecs_valid = 1'b1; // extension context status is not implemented in cv32e40px + end else begin + assign x_issue_req_rs_valid_o[0] = (~scoreboard_q[x_rs_addr_i[0]] | x_ex_fwd_o[0] | x_wb_fwd_o[0]) + & ~(x_rs_addr_i[0] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[0] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[1] = (~scoreboard_q[x_rs_addr_i[1]] | x_ex_fwd_o[1] | x_wb_fwd_o[1]) + & ~(x_rs_addr_i[1] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[1] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[2] = (~scoreboard_q[x_rs_addr_i[2]] | x_ex_fwd_o[2] | x_wb_fwd_o[2]) + & ~(x_rs_addr_i[2] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[2] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_ecs_valid = 1'b1; // extension context status is not implemented in cv32e40px + end + endgenerate // commit interface assign x_commit_valid_o = x_issue_valid_o; assign x_commit_id_o = id_q; @@ -140,22 +159,46 @@ module cv32e40px_x_disp // core stall signal assign x_stall_o = dep | outstanding_mem | x_if_not_ready | x_if_memory_instr | illegal_forwarding_prevention; - assign dep = ~x_illegal_insn_o & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) - | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) - | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2]))); + assign outstanding_mem = data_req_dec_i & (mem_counter_q != '0); assign x_if_memory_instr = x_mem_data_req_o & ~(x_issue_valid_o & x_issue_ready_i); assign x_if_not_ready = x_issue_valid_o & ~x_issue_ready_i; - assign illegal_forwarding_prevention = x_result_valid_i & (x_ex_fwd_o[0] | x_ex_fwd_o[1] | x_ex_fwd_o[2]); + assign illegal_forwarding_prevention = x_result_valid_i & (|x_ex_fwd_o); // forwarding - assign x_ex_fwd_o[0] = x_rs_addr_i[0] == waddr_ex_i & we_ex_i & ex_valid_i; - assign x_ex_fwd_o[1] = x_rs_addr_i[1] == waddr_ex_i & we_ex_i & ex_valid_i; - assign x_ex_fwd_o[2] = x_rs_addr_i[2] == waddr_ex_i & we_ex_i & ex_valid_i; - assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; - assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; - assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; + generate + if (X_DUALREAD != 0) begin + assign x_ex_fwd_o[0] = x_rs_addr_i[0] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[1] = x_rs_addr_i[1] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[2] = x_rs_addr_i[2] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[3] = (x_rs_addr_i[0] | 5'b00001) == waddr_ex_i & we_ex_i & ex_valid_i & x_issue_resp_dualread_i[0]; + assign x_ex_fwd_o[4] = (x_rs_addr_i[1] | 5'b00001) == waddr_ex_i & we_ex_i & ex_valid_i & x_issue_resp_dualread_i[1]; + assign x_ex_fwd_o[5] = (x_rs_addr_i[2] | 5'b00001) == waddr_ex_i & we_ex_i & ex_valid_i & x_issue_resp_dualread_i[2]; + assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[3] = (x_rs_addr_i[0] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[0]; + assign x_wb_fwd_o[4] = (x_rs_addr_i[1] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[1]; + assign x_wb_fwd_o[5] = (x_rs_addr_i[2] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[2]; + assign dep = ~x_illegal_insn_o & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) + | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) + | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2])) + | (((regs_used_i[0] & x_issue_resp_dualread_i[0]) & scoreboard_q[x_rs_addr_i[0] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[0] | 5'b00001))) & x_issue_resp_dualread_i[0]) + | (((regs_used_i[1] & x_issue_resp_dualread_i[1]) & scoreboard_q[x_rs_addr_i[1] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[1] | 5'b00001))) & x_issue_resp_dualread_i[1]) + | (((regs_used_i[2] & x_issue_resp_dualread_i[2]) & scoreboard_q[x_rs_addr_i[2] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[2] | 5'b00001))) & x_issue_resp_dualread_i[2])); + end else begin + assign x_ex_fwd_o[0] = x_rs_addr_i[0] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[1] = x_rs_addr_i[1] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[2] = x_rs_addr_i[2] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; + assign dep = ~x_illegal_insn_o & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) + | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) + | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2]))); + end + endgenerate // id generation assign x_compressed_id_o = id_d; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv index 499fec31..678635d0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv @@ -15,6 +15,7 @@ package cv32e40px_core_v_xif_pkg; // cv-x-if parameters parameter int X_NUM_RS = 3; + parameter int X_DUALREAD = 0; // 0: single read, 1: dual read parameter int X_ID_WIDTH = 4; parameter int X_MEM_WIDTH = 32; parameter int X_RFR_WIDTH = 32; @@ -23,6 +24,8 @@ package cv32e40px_core_v_xif_pkg; parameter logic [1:0] X_ECS_XS = '0; localparam int XLEN = 32; + localparam int RF_READ_PORTS = (X_DUALREAD == 1) ? 2 * X_NUM_RS : X_NUM_RS; + typedef struct packed { logic [15:0] instr; // Offloaded compressed instruction @@ -39,8 +42,8 @@ package cv32e40px_core_v_xif_pkg; logic [31:0] instr; // Offloaded instruction logic [1:0] mode; // Privilege level logic [X_ID_WIDTH-1:0] id; // Identification of the offloaded instruction - logic [X_NUM_RS -1:0][X_RFR_WIDTH-1:0] rs; // Register file source operands for the offloaded instruction - logic [X_NUM_RS -1:0] rs_valid; // Validity of the register file source operand(s) + logic [RF_READ_PORTS-1:0][X_RFR_WIDTH-1:0] rs; // Register file source operands for the offloaded instruction + logic [RF_READ_PORTS-1:0] rs_valid; // Validity of the register file source operand(s) logic [5:0] ecs; // Extension Context Status ({mstatus.xs, mstatus.fs, mstatus.vs}) logic ecs_valid; // Validity of the Extension Context Status } x_issue_req_t; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv index 07c75cf8..2be4df54 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv @@ -84,11 +84,13 @@ module uartdpi #( `ifndef VCS `ifndef MODELSIM +`ifndef XCELIUM initial begin // Prevent falling edges of rx_i before reset causing spurious characters seen_reset = 0; end `endif +`endif `endif // RX diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml new file mode 100644 index 00000000..00178f19 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml @@ -0,0 +1,23 @@ +# Copyright 2023 OpenHW Group +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "3.9" + +# Build from the docs directory with Sphinx +sphinx: + configuration: doc/conf.py + +# Explicitly set the Python requirements +python: + install: + - requirements: doc/requirements.txt \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv index 8cc81dd3..7974cf92 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv @@ -27,4 +27,4 @@ module cve2_clock_gate ( assign clk_o = clk_i & clk_en; -endmodule // cv32e40p_clock_gate +endmodule // cve2_clock_gate diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist new file mode 100644 index 00000000..4a0142d8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2022 OpenHW Group +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +/////////////////////////////////////////////////////////////////////////////// +// +// Manifest for the CV32E20 RTL model. +// - Format based on manifest used by other CORE-V cores. +// - Intended to be used by both synthesis and simulation. +// - Relevent synthesis and simulation scripts/Makefiles must set the shell +// ENV variable DESIGN_RTL_DIR as required. +// +// TODO: Replace once-and-for-all with unified manifest (FuseSoc?) +// +/////////////////////////////////////////////////////////////////////////////// + ++incdir+${DESIGN_RTL_DIR}/../shared/rtl/ ++incdir+${DESIGN_RTL_DIR}/../rtl ++incdir+${DESIGN_RTL_DIR}/../shared/rtl/sim ++incdir+${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl ++incdir+${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/dv/sv/dv_utils + +${DESIGN_RTL_DIR}/cve2_pkg.sv +${DESIGN_RTL_DIR}/cve2_tracer_pkg.sv +${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl/prim_secded_pkg.sv +${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv +${DESIGN_RTL_DIR}/cve2_alu.sv +${DESIGN_RTL_DIR}/cve2_compressed_decoder.sv +${DESIGN_RTL_DIR}/cve2_controller.sv +${DESIGN_RTL_DIR}/cve2_cs_registers.sv +${DESIGN_RTL_DIR}/cve2_csr.sv +${DESIGN_RTL_DIR}/cve2_counter.sv +${DESIGN_RTL_DIR}/cve2_decoder.sv +${DESIGN_RTL_DIR}/cve2_ex_block.sv +${DESIGN_RTL_DIR}/cve2_fetch_fifo.sv +${DESIGN_RTL_DIR}/cve2_id_stage.sv +${DESIGN_RTL_DIR}/cve2_if_stage.sv +${DESIGN_RTL_DIR}/cve2_load_store_unit.sv +${DESIGN_RTL_DIR}/cve2_multdiv_fast.sv +${DESIGN_RTL_DIR}/cve2_multdiv_slow.sv +${DESIGN_RTL_DIR}/cve2_prefetch_buffer.sv +${DESIGN_RTL_DIR}/cve2_pmp.sv +${DESIGN_RTL_DIR}/cve2_register_file_ff.sv +${DESIGN_RTL_DIR}/cve2_wb.sv +${DESIGN_RTL_DIR}/cve2_core.sv +${DESIGN_RTL_DIR}/cve2_top.sv +${DESIGN_RTL_DIR}/cve2_top_tracing.sv +${DESIGN_RTL_DIR}/cve2_tracer.sv + +${DESIGN_RTL_DIR}/../bhv/cve2_sim_clock_gate.sv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml new file mode 100644 index 00000000..1dba358d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml @@ -0,0 +1,94 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Ibex configurations files, holds the parameter sets that are tested under CI. +# Each configuration must specify the same set of parameters + +# Two-stage pipeline without additional branch target ALU and 3 cycle multiplier +# (4 cycles for mulh), resulting in 2 stall cycles for mul (3 for mulh) +small: + RV32E : 0 + RV32M : "cve2_pkg::RV32MFast" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 0 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + +# Configuration to match that used in the OpenTitan project +opentitan: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BOTEarlGrey" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# =============================== +# * EXPERIMENTAL CONFIGURATIONS * +# =============================== + +# Three-stage pipeline with additional branch traget ALU and 1 cycle multiplier +# (2 cycles for mulh) so mul does not stall (mulh stall 1 cycles). This is the +# maximum performance configuration. +experimental-maxperf: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + +# experimental-maxperf config above plus PMP enabled with 16 regions. +experimental-maxperf-pmp: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf-pmp config above with balanced bitmanip extension +experimental-maxperf-pmp-bmbalanced: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BBalanced" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf-pmp config above with full bitmanip extension +experimental-maxperf-pmp-bmfull: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BFull" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf with branch predictor switched on. This exists to allow +# easy use of Ibex with the branch predictor in particular for CI runs. The +# branch predictor will be enabled in all the 'maxperf' configs after further +# development. +experimental-branch-predictor: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core new file mode 100644 index 00000000..6d621a43 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core @@ -0,0 +1,115 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "openhwgroup:cve2:cve2_core:0.1" +description: "Ibex CPU Core Components" + +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - openhwgroup:cve2:cve2_pkg + - lowrisc:dv:dv_fcov_macros + files: + - rtl/cve2_alu.sv + - rtl/cve2_branch_predict.sv + - rtl/cve2_compressed_decoder.sv + - rtl/cve2_controller.sv + - rtl/cve2_cs_registers.sv + - rtl/cve2_csr.sv + - rtl/cve2_counter.sv + - rtl/cve2_decoder.sv + - rtl/cve2_ex_block.sv + - rtl/cve2_fetch_fifo.sv + - rtl/cve2_id_stage.sv + - rtl/cve2_if_stage.sv + - rtl/cve2_load_store_unit.sv + - rtl/cve2_multdiv_fast.sv + - rtl/cve2_multdiv_slow.sv + - rtl/cve2_prefetch_buffer.sv + - rtl/cve2_pmp.sv + - rtl/cve2_wb.sv + - rtl/cve2_core.sv + - rtl/cve2_pmp_reset_default.svh: {is_include_file: true} + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + FPGA_XILINX: + datatype: bool + description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. + default: false + paramtype: vlogdefine + + RV32E: + datatype: int + default: 0 + paramtype: vlogparam + + RV32M: + datatype: str + default: cve2_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." + + RV32B: + datatype: str + default: cve2_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + toplevel: cve2_core + parameters: + - tool_vivado ? (FPGA_XILINX=true) + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: cve2_core + tools: + veribleformat: + verible_format_args: + - "--inplace" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core new file mode 100644 index 00000000..ad2c2617 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core @@ -0,0 +1,22 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_icache:0.1" +description: "Ibex instruction cache" +filesets: + files_rtl: + depend: + - lowrisc:prim:secded + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_icache.sv + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_rtl + toplevel: cve2_icache + default_tool: vcs diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core new file mode 100644 index 00000000..700e6c9e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core @@ -0,0 +1,28 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_multdiv:0.1" +description: "Multiplier and divider" + +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_multdiv_fast.sv + - rtl/cve2_multdiv_slow.sv + file_type: systemVerilogSource + +parameters: + RV32M: + datatype: int + default: 2 + paramtype: vlogparam + description: "Selection of multiplication implementation. Switch to enable single cycle multiplications." + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core similarity index 73% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core index 17f47e08..a89c9e12 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core @@ -2,13 +2,13 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:ibex:ibex_pkg:0.1" -description: "Header package for Ibex" +name: "openhwgroup:cve2:cve2_pkg:0.1" +description: "Header package for CVE2" filesets: files_rtl: files: - - rtl/ibex_pkg.sv + - rtl/cve2_pkg.sv file_type: systemVerilogSource targets: diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core new file mode 100644 index 00000000..0d9d2c5c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core @@ -0,0 +1,115 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "openhwgroup:cve2:cve2_top:0.1" +description: "Ibex, a small RV32 CPU core" + +filesets: + files_rtl: + depend: + - openhwgroup:cve2:cve2_pkg + - openhwgroup:cve2:cve2_core + - lowrisc:prim:buf + - lowrisc:prim:clock_mux2 + - lowrisc:prim:flop + - lowrisc:prim:ram_1p_scr + files: + - rtl/cve2_register_file_ff.sv # generic FF-based + - rtl/cve2_top.sv + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + + files_clk_gate: + files: + - bhv/cve2_sim_clock_gate.sv + file_type: systemVerilogSource + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + FPGA_XILINX: + datatype: bool + description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. + default: false + paramtype: vlogdefine + + RV32E: + datatype: int + default: 0 + paramtype: vlogparam + + RV32M: + datatype: str + default: cve2_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." + + RV32B: + datatype: str + default: cve2_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + - target_sim ? (files_clk_gate) + - target_sim_sc ? (files_clk_gate) + toplevel: cve2_top + parameters: + - tool_vivado ? (FPGA_XILINX=true) + + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + filesets_append: + - files_clk_gate + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: cve2_top + tools: + veribleformat: + verible_format_args: + - "--inplace" + - "--formal_parameters_indentation=indent" + - "--named_parameter_indentation=indent" + - "--named_port_indentation=indent" + - "--port_declarations_indentation=indent" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core similarity index 52% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2.core rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core index ec43f9cb..65d2b5b7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core @@ -2,68 +2,28 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 - -name: "openhwgroup.org:ip:cve2" -description: "OpenHW Group RISC-V Core CVE2" - +name: "lowrisc:cve2:cve2_top_tracing:0.1" +description: "Ibex, a small RV32 CPU core with tracing enabled" filesets: files_rtl: depend: - - lowrisc:prim:assert - - lowrisc:ibex:ibex_pkg - files: - - rtl/ibex_alu.sv - - rtl/ibex_branch_predict.sv - - rtl/ibex_compressed_decoder.sv - - rtl/ibex_controller.sv - - rtl/ibex_cs_registers.sv - - rtl/ibex_csr.sv - - rtl/ibex_counter.sv - - rtl/ibex_decoder.sv - - rtl/ibex_ex_block.sv - - rtl/ibex_fetch_fifo.sv - - rtl/ibex_id_stage.sv - - rtl/ibex_if_stage.sv - - rtl/ibex_load_store_unit.sv - - rtl/ibex_multdiv_fast.sv - - rtl/ibex_multdiv_slow.sv - - rtl/ibex_prefetch_buffer.sv - - rtl/ibex_pmp.sv - - rtl/ibex_wb_stage.sv - - rtl/ibex_dummy_instr.sv - - rtl/ibex_core.sv - - rtl/cve2_sleep_unit.sv - - rtl/ibex_pmp_reset_default.svh: {is_include_file: true} - file_type: systemVerilogSource - - files_lint_verilator: - files: - - lint/verilator_waiver.vlt: {file_type: vlt} - - files_lint_verible: - files: - - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} - - files_clk_gate: + - lowrisc:cve2:cve2_top + - lowrisc:cve2:cve2_tracer files: - - bhv/cve2_sim_clock_gate.sv + - rtl/cve2_top_tracing.sv file_type: systemVerilogSource parameters: + # The tracer uses the RISC-V Formal Interface (RVFI) to collect trace signals. RVFI: datatype: bool paramtype: vlogdefine + default: true SYNTHESIS: datatype: bool paramtype: vlogdefine - FPGA_XILINX: - datatype: bool - description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. - default: false - paramtype: vlogdefine - RV32E: datatype: int default: 0 @@ -71,21 +31,21 @@ parameters: RV32M: datatype: str - default: ibex_pkg::RV32MFast + default: cve2_pkg::RV32MFast paramtype: vlogdefine - description: "RV32M implementation parameter enum. See the ibex_pkg::rv32m_e enum in ibex_pkg.sv for permitted values." + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." RV32B: datatype: str - default: ibex_pkg::RV32BNone + default: cve2_pkg::RV32BNone paramtype: vlogdefine - description: "Bitmanip implementation parameter enum. See the ibex_pkg::rv32b_e enum in ibex_pkg.sv for permitted values." + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." RegFile: datatype: str - default: ibex_pkg::RegFileFF + default: cve2_pkg::RegFileFF paramtype: vlogdefine - description: "Register file implementation parameter enum. See the ibex_pkg::regfile_e enum in ibex_pkg.sv for permitted values." + description: "Register file implementation parameter enum. See the cve2_pkg::regfile_e enum in cve2_pkg.sv for permitted values." ICache: datatype: int @@ -99,29 +59,23 @@ parameters: paramtype: vlogparam description: "Enable ECC protection in instruction cache" - BranchTargetALU: - datatype: int - default: 0 - paramtype: vlogparam - description: "Enables separate branch target ALU (increasing branch performance EXPERIMENTAL) [0/1]" - WritebackStage: datatype: int default: 0 paramtype: vlogparam description: "Enables third pipeline stage (EXPERIMENTAL) [0/1]" - BranchPredictor: + SecureCVE2: datatype: int - paramtype: vlogparam default: 0 - description: "Enables static branch prediction (EXPERIMENTAL)" + paramtype: vlogparam + description: "Enables security hardening features (EXPERIMENTAL) [0/1]" - SecureIbex: + ICacheScramble: datatype: int default: 0 paramtype: vlogparam - description: "Enables security hardening features (EXPERIMENTAL) [0/1]" + description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]" PMPEnable: datatype: int @@ -144,19 +98,28 @@ parameters: targets: default: &default_target filesets: - - tool_verilator ? (files_lint_verilator) - - tool_veriblelint ? (files_lint_verible) - files_rtl - - target_sim? (files_clk_gate) - - target_sim-opt? (files_clk_gate) - toplevel: ibex_core parameters: - - tool_vivado ? (FPGA_XILINX=true) + - RVFI=true + toplevel: cve2_top_tracing + lint: <<: *default_target parameters: - - SYNTHESIS=true - RVFI=true + - SYNTHESIS=true + - RV32E + - RV32M + - RV32B + - RegFile + - ICache + - ICacheECC + - WritebackStage + - SecureCVE2 + - ICacheScramble + - PMPEnable + - PMPGranularity + - PMPNumRegions default_tool: verilator tools: verilator: @@ -173,8 +136,12 @@ targets: - SYNTHESIS=true - RVFI=true default_tool: veribleformat - toplevel: ibex_core + toplevel: cve2_top_tracing tools: veribleformat: verible_format_args: - "--inplace" + - "--formal_parameters_indentation=indent" + - "--named_parameter_indentation=indent" + - "--named_port_indentation=indent" + - "--port_declarations_indentation=indent" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core new file mode 100644 index 00000000..0e43a806 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core @@ -0,0 +1,20 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_tracer:0.1" +description: "Tracer for use with Ibex using the RVFI interface" +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_tracer_pkg.sv + - rtl/cve2_tracer.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt index b7c952ca..bac40c20 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt @@ -12,7 +12,7 @@ `verilator_config lint_off -rule PINCONNECTEMPTY -// We have some boolean top-level parameters in e.g. ibex_core_tracing.sv. +// We have some boolean top-level parameters in e.g. cve2_core_tracing.sv. // When building with fusesoc, these get set with defines like // -GRV32M=1 (rather than -GRV32M=1'b1), leading to warnings like: // @@ -23,13 +23,13 @@ lint_off -rule PINCONNECTEMPTY // matches when you set a 1-bit value to a literal 1, so it won't hide // silly mistakes like setting it to 2. // -lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" +lint_off -rule WIDTH -file "*/rtl/cve2_top_tracing.sv" -match "*expects 1 bits*Initial value's CONST '32'h1'*" // Operator expects 1 bit on initial value but initial value's CONST generates // 32 bits, need a specific RV32B waiver as it uses enums so the above catch-all // waiver doesn't work. -lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*'RV32B'*" +lint_off -rule WIDTH -file "*/rtl/cve2_top_tracing.sv" -match "*'RV32B'*" // Bits of signal are not used: be_i[3:1] // Bits of signal are not used: addr_i[31:10,1:0] @@ -52,21 +52,25 @@ lint_off -rule UNUSED -file "*/rtl/timer.sv" -match "*'timer_addr_i'[31:10]*" // Signal is not used: clk_i // leaving clk and reset connected in-case we want to add assertions -lint_off -rule UNUSED -file "*/rtl/ibex_pmp.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_branch_predict.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_pmp.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_compressed_decoder.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_decoder.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_branch_predict.sv" -match "*clk_i*" // Signal is not used: rst_ni // leaving clk and reset connected in-case we want to add assertions -lint_off -rule UNUSED -file "*/rtl/ibex_pmp.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_branch_predict.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_pmp.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_compressed_decoder.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_decoder.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_branch_predict.sv" -match "*rst_ni*" // Temporary waivers until OpenTitan primitives are lint-clean // https://github.com/lowRISC/opentitan/issues/2313 lint_off -file "*/lowrisc_prim_*/rtl/*.sv" -lint_off -rule UNUSED -file "*/rtl/ibex_top_tracing.sv" -match "*RndCnstLfsrSeed*" -lint_off -rule UNUSED -file "*/rtl/ibex_top_tracing.sv" -match "*RndCnstLfsrPerm*" +lint_off -rule UNUSED -file "*/rtl/cve2_top_tracing.sv" -match "*RndCnstLfsrSeed*" +lint_off -rule UNUSED -file "*/rtl/cve2_top_tracing.sv" -match "*RndCnstLfsrPerm*" +lint_off -rule DECLFILENAME -file "*/bhv/cve2_sim_clock_gate.sv" -match "Filename 'cve2_sim_clock_gate' does not match MODULE name: 'cve2_clock_gate'" +lint_off -rule UNOPTFLAT -file "*/rtl/cve2_core.sv" -match "Signal unoptimizable: Feedback to clock or circular logic: 'cve2_top.u_cve2_core.irqs'" +lint_off -rule UNUSED -file "*/rtl/cve2_wb.sv" -match "Signal is not used: 'clk_i'*" +lint_off -rule UNUSED -file "*/rtl/cve2_wb.sv" -match "Signal is not used: 'rst_ni'*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv index eb6afcae..2471c621 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv @@ -6,10 +6,10 @@ /** * Arithmetic logic unit */ -module ibex_alu #( - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone +module cve2_alu #( + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( - input ibex_pkg::alu_op_e operator_i, + input cve2_pkg::alu_op_e operator_i, input logic [31:0] operand_a_i, input logic [31:0] operand_b_i, @@ -31,7 +31,7 @@ module ibex_alu #( output logic comparison_result_o, output logic is_equal_result_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] operand_a_rev; logic [32:0] operand_b_neg; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv similarity index 98% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv index 87f83836..e49c7007 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv @@ -17,7 +17,7 @@ `include "prim_assert.sv" -module ibex_branch_predict ( +module cve2_branch_predict ( input logic clk_i, input logic rst_ni, @@ -30,7 +30,7 @@ module ibex_branch_predict ( output logic predict_branch_taken_o, output logic [31:0] predict_branch_pc_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] imm_j_type; logic [31:0] imm_b_type; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv index e3c6aa52..1b5b17ff 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv @@ -13,7 +13,7 @@ `include "prim_assert.sv" -module ibex_compressed_decoder ( +module cve2_compressed_decoder ( input logic clk_i, input logic rst_ni, input logic valid_i, @@ -22,7 +22,7 @@ module ibex_compressed_decoder ( output logic is_compressed_o, output logic illegal_instr_o ); - import ibex_pkg::*; + import cve2_pkg::*; // valid_i indicates if instr_i is valid and is used for assertions only. // The following signal is used to avoid possible lint errors. diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv similarity index 82% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 0f2ae7bc..fba4352f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -8,15 +8,14 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_controller #( - parameter bit WritebackStage = 0, - parameter bit BranchPredictor = 0 +module cve2_controller #( ) ( input logic clk_i, input logic rst_ni, + input logic fetch_enable_i, // core can fetch instructions leave RESET state output logic ctrl_busy_o, // core is busy processing instrs // decoder related signals @@ -33,7 +32,6 @@ module ibex_controller #( input logic [31:0] instr_i, // uncompressed instr data for mtval input logic [15:0] instr_compressed_i, // instr compressed data for mtval input logic instr_is_compressed_i, // instr is compressed - input logic instr_bp_taken_i, // instr was predicted taken branch input logic instr_fetch_err_i, // instr has error input logic instr_fetch_err_plus2_i, // instr error is x32 input logic [31:0] pc_id_i, // instr address @@ -47,37 +45,32 @@ module ibex_controller #( // to prefetcher output logic instr_req_o, // start fetching instructions output logic pc_set_o, // jump to address set by pc_mux - output ibex_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector + output cve2_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector // (boot, normal, exception...) - output logic nt_branch_mispredict_o, // Not-taken branch in ID/EX was - // mispredicted (predicted taken) - output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC - output ibex_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs + output cve2_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC + output cve2_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs // LSU input logic [31:0] lsu_addr_last_i, // for mtval input logic load_err_i, input logic store_err_i, - output logic wb_exception_o, // Instruction in WB taking an exception - output logic id_exception_o, // Instruction in ID taking an exception // jump/branch signals input logic branch_set_i, // branch set signal (branch definitely // taken) - input logic branch_not_set_i, // branch is definitely not taken input logic jump_set_i, // jump taken set signal // interrupt signals input logic csr_mstatus_mie_i, // M-mode interrupt enable bit input logic irq_pending_i, // interrupt request pending - input ibex_pkg::irqs_t irqs_i, // interrupt requests qualified with + input cve2_pkg::irqs_t irqs_i, // interrupt requests qualified with // mie CSR input logic irq_nm_i, // non-maskeable interrupt output logic nmi_mode_o, // core executing NMI handler // debug signals input logic debug_req_i, - output ibex_pkg::dbg_cause_e debug_cause_o, + output cve2_pkg::dbg_cause_e debug_cause_o, output logic debug_csr_save_o, output logic debug_mode_o, input logic debug_single_step_i, @@ -85,24 +78,18 @@ module ibex_controller #( input logic debug_ebreaku_i, input logic trigger_match_i, - // Wakeup Signal - output logic wake_from_sleep_o, - output logic csr_save_if_o, output logic csr_save_id_o, - output logic csr_save_wb_o, output logic csr_restore_mret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, - input ibex_pkg::priv_lvl_e priv_mode_i, + input cve2_pkg::priv_lvl_e priv_mode_i, input logic csr_mstatus_tw_i, // stall & flush signals input logic stall_id_i, - input logic stall_wb_i, output logic flush_id_o, - input logic ready_wb_i, // performance monitors output logic perf_jump_o, // we are executing a jump @@ -110,7 +97,7 @@ module ibex_controller #( output logic perf_tbranch_o // we are executing a taken branch // instruction ); - import ibex_pkg::*; + import cve2_pkg::*; // FSM state encoding typedef enum logic [3:0] { @@ -153,8 +140,6 @@ module ibex_controller #( logic enter_debug_mode; logic ebreak_into_debug; logic handle_irq; - logic id_wb_pending; - logic [3:0] mfip_id; logic unused_irq_timer; @@ -173,8 +158,8 @@ module ibex_controller #( always_ff @(negedge clk_i) begin // print warning in case of decoding errors if ((ctrl_fsm_cs == DECODE) && instr_valid_i && !instr_fetch_err_i && illegal_insn_d) begin - $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, ibex_core.hart_id_i, - ibex_id_stage.pc_id_i, ibex_id_stage.instr_rdata_i); + $display("%m @ %t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, cve2_core.hart_id_i, + cve2_id_stage.pc_id_i, cve2_id_stage.instr_rdata_i); end end // synopsys translate_on @@ -206,7 +191,7 @@ module ibex_controller #( (mret_insn | (csr_mstatus_tw_i & wfi_insn)); // This is recorded in the illegal_insn_q flop to help timing. Specifically - // it is needed to break the path from ibex_cs_registers/illegal_csr_insn_o + // it is needed to break the path from cve2_cs_registers/illegal_csr_insn_o // to pc_set_o. Clear when controller is in FLUSH so it won't remain set // once illegal instruction is handled. // All terms in this expression are qualified by instr_valid_i @@ -223,8 +208,6 @@ module ibex_controller #( // LSU exception requests assign exc_req_lsu = store_err_i | load_err_i; - assign id_exception_o = exc_req_d; - // special requests: special instructions, pipeline flushes, exceptions... // All terms in these expressions are qualified by instr_valid_i except exc_req_lsu which can come // from the Writeback stage with no instr_valid_i from the ID stage @@ -239,40 +222,7 @@ module ibex_controller #( // generic special request signal, applies to all instructions assign special_req = special_req_pc_change | special_req_flush_only; - // Is there an instruction in ID or WB that has yet to complete? - assign id_wb_pending = instr_valid_i | ~ready_wb_i; - // Exception/fault prioritisation is taken from Table 3.7 of Priviledged Spec v1.11 - if (WritebackStage) begin : g_wb_exceptions - always_comb begin - instr_fetch_err_prio = 0; - illegal_insn_prio = 0; - ecall_insn_prio = 0; - ebrk_insn_prio = 0; - store_err_prio = 0; - load_err_prio = 0; - - // Note that with the writeback stage store/load errors occur on the instruction in writeback, - // all other exception/faults occur on the instruction in ID/EX. The faults from writeback - // must take priority as that instruction is architecurally ordered before the one in ID/EX. - if (store_err_q) begin - store_err_prio = 1'b1; - end else if (load_err_q) begin - load_err_prio = 1'b1; - end else if (instr_fetch_err) begin - instr_fetch_err_prio = 1'b1; - end else if (illegal_insn_q) begin - illegal_insn_prio = 1'b1; - end else if (ecall_insn) begin - ecall_insn_prio = 1'b1; - end else if (ebrk_insn) begin - ebrk_insn_prio = 1'b1; - end - end - - // Instruction in writeback is generating an exception so instruction in ID must not execute - assign wb_exception_o = load_err_q | store_err_q | load_err_i | store_err_i; - end else begin : g_no_wb_exceptions always_comb begin instr_fetch_err_prio = 0; illegal_insn_prio = 0; @@ -295,8 +245,6 @@ module ibex_controller #( load_err_prio = 1'b1; end end - assign wb_exception_o = 1'b0; - end `ASSERT_IF(IbexExceptionPrioOnehot, $onehot({instr_fetch_err_prio, @@ -346,6 +294,7 @@ module ibex_controller #( // - while in debug mode [Debug Spec v0.13.2, p.39], // - while in NMI mode (nested NMIs are not supported, NMI has highest priority and // cannot be interrupted by regular interrupts). + // - while single stepping. assign handle_irq = ~debug_mode_q & ~nmi_mode_q & (irq_nm_i | (irq_pending_i & csr_mstatus_mie_i)); @@ -353,7 +302,7 @@ module ibex_controller #( always_comb begin : gen_mfip_id mfip_id = 4'd0; - for (int i = 14; i >= 0; i--) begin + for (int i = 15; i >= 0; i--) begin if (irqs_i.irq_fast[i]) begin mfip_id = i[3:0]; end @@ -372,7 +321,6 @@ module ibex_controller #( csr_save_if_o = 1'b0; csr_save_id_o = 1'b0; - csr_save_wb_o = 1'b0; csr_restore_mret_id_o = 1'b0; csr_restore_dret_id_o = 1'b0; csr_save_cause_o = 1'b0; @@ -384,7 +332,6 @@ module ibex_controller #( // helping timing. pc_mux_o = PC_BOOT; pc_set_o = 1'b0; - nt_branch_mispredict_o = 1'b0; exc_pc_mux_o = EXC_PC_IRQ; exc_cause_o = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00 @@ -412,9 +359,11 @@ module ibex_controller #( instr_req_o = 1'b0; pc_mux_o = PC_BOOT; pc_set_o = 1'b1; - ctrl_fsm_ns = BOOT_SET; + if (fetch_enable_i == 1'b1) + begin + ctrl_fsm_ns = BOOT_SET; + end end - BOOT_SET: begin // copy boot address to instr fetch address instr_req_o = 1'b1; @@ -441,13 +390,12 @@ module ibex_controller #( // normal execution flow // in debug mode or single step mode we leave immediately (wfi=nop) - if (wake_from_sleep_o) begin - ctrl_fsm_ns = FIRST_FETCH; + if (irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i) begin + ctrl_fsm_ns = FIRST_FETCH; end else begin // Make sure clock remains disabled. ctrl_busy_o = 1'b0; end - end FIRST_FETCH: begin @@ -497,40 +445,25 @@ module ibex_controller #( // FLUSH state. retain_id = 1'b1; - // Wait for the writeback stage to either be ready for a new instruction or raise its own - // exception before going to FLUSH. If the instruction in writeback raises an exception it - // must take priority over any exception from an instruction in ID/EX. Only once the - // writeback stage is ready can we be certain that won't happen. Without a writeback - // stage ready_wb_i == 1 so the FSM will always go directly to FLUSH. + // The FSM will always go directly to FLUSH. - if (ready_wb_i | wb_exception_o) begin - ctrl_fsm_ns = FLUSH; - end + ctrl_fsm_ns = FLUSH; end if (branch_set_i || jump_set_i) begin - // Only set the PC if the branch predictor hasn't already done the branch for us - pc_set_o = BranchPredictor ? ~instr_bp_taken_i : 1'b1; + pc_set_o = 1'b1; perf_tbranch_o = branch_set_i; perf_jump_o = jump_set_i; end - if (BranchPredictor) begin - if (instr_bp_taken_i & branch_not_set_i) begin - // If the instruction is a branch that was predicted to be taken but was not taken - // signal a mispredict. - nt_branch_mispredict_o = 1'b1; - end - end - // If entering debug mode or handling an IRQ the core needs to wait until any instruction in - // ID or WB has finished executing. Stall IF during that time. - if ((enter_debug_mode || handle_irq) && (stall || id_wb_pending)) begin + // ID has finished executing. Stall IF during that time. + if ((enter_debug_mode || handle_irq) && (stall || instr_valid_i)) begin halt_if = 1'b1; end - if (!stall && !special_req && !id_wb_pending) begin + if (!stall && !special_req && !instr_valid_i) begin if (enter_debug_mode) begin // enter debug mode ctrl_fsm_ns = DBG_TAKEN_IF; @@ -565,12 +498,13 @@ module ibex_controller #( if (irq_nm_i && !nmi_mode_q) begin exc_cause_o = EXC_CAUSE_IRQ_NM; nmi_mode_d = 1'b1; // enter NMI mode - end else if (irqs_i.irq_fast != 15'b0) begin + end else if (irqs_i.irq_fast != 16'b0) begin // generate exception cause ID from fast interrupt ID: // - first bit distinguishes interrupts from exceptions, - // - second bit adds 16 to fast interrupt ID - // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16} - exc_cause_o = exc_cause_e'({2'b11, mfip_id}); + // - third bit adds 16 to fast interrupt ID so that the interrup 0 becomes 16 and the interrupt 15 becomes 31 (hence 5bits) + // - second bit is always 0 as the FAST interrupts are represented in the first 5bits, the 6th is always 0 cause is used by the NMI (in that case is 1 as represented by the number 32) + // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 6'd16} + exc_cause_o = exc_cause_e'({3'b101, mfip_id}); end else if (irqs_i.irq_external) begin exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M; end else if (irqs_i.irq_software) begin @@ -597,11 +531,11 @@ module ibex_controller #( csr_save_cause_o = 1'b1; if (trigger_match_i) begin - debug_cause_o = DBG_CAUSE_TRIGGER; - end else if (debug_single_step_i) begin - debug_cause_o = DBG_CAUSE_STEP; + debug_cause_o = DBG_CAUSE_TRIGGER; // (priority 4) + end else if (debug_req_i) begin + debug_cause_o = DBG_CAUSE_HALTREQ; // (priority 1) end else begin - debug_cause_o = DBG_CAUSE_HALTREQ; + debug_cause_o = DBG_CAUSE_STEP; // (priority 0, lowest) end // enter debug mode @@ -657,13 +591,7 @@ module ibex_controller #( pc_mux_o = PC_EXC; exc_pc_mux_o = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC; - if (WritebackStage) begin : g_writeback_mepc_save - // With the writeback stage present whether an instruction accessing memory will cause - // an exception is only known when it is in writeback. So when taking such an exception - // epc must come from writeback. - csr_save_id_o = ~(store_err_q | load_err_q); - csr_save_wb_o = store_err_q | load_err_q; - end else begin : g_no_writeback_mepc_save + begin : g_no_writeback_mepc_save csr_save_id_o = 1'b0; end @@ -742,9 +670,6 @@ module ibex_controller #( csr_restore_dret_id_o = 1'b1; end else if (wfi_insn) begin ctrl_fsm_ns = WAIT_SLEEP; - end else if (csr_pipe_flush && handle_irq) begin - // start handling IRQs when doing CSR-related pipeline flushes - ctrl_fsm_ns = IRQ_TAKEN; end end // exc_req_q @@ -754,9 +679,14 @@ module ibex_controller #( // Leave all other signals as is to ensure CSRs and PC get set as if // core was entering exception handler, entry to debug mode will then // see the appropriate state and setup dpc correctly. + // If an EBREAK instruction is causing us to enter debug mode on the // same cycle as a debug_req or single step, honor the EBREAK and - // proceed to DBG_TAKEN_ID. + // proceed to DBG_TAKEN_ID, as it has the highest priority. + // [Debug Spec v1.0.0-STABLE, p.53] + // cause==EBREAK -> prio 3 (highest) + // cause==debug_req -> prio 2 + // cause==step -> prio 1 (lowest) if (enter_debug_mode_prio_q && !(ebrk_insn_prio && ebreak_into_debug)) begin ctrl_fsm_ns = DBG_TAKEN_IF; end @@ -782,9 +712,8 @@ module ibex_controller #( /////////////////// // If high current instruction cannot complete this cycle. Either because it needs more cycles to - // finish (stall_id_i) or because the writeback stage cannot accept it yet (stall_wb_i). If there - // is no writeback stage stall_wb_i is a constant 0. - assign stall = stall_id_i | stall_wb_i; + // finish (stall_id_i) + assign stall = stall_id_i; // signal to IF stage that ID stage is ready for next instr assign id_in_ready_o = ~stall & ~halt_if & ~retain_id; @@ -821,27 +750,22 @@ module ibex_controller #( end end - assign wake_from_sleep_o = irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i; - - ////////// // FCOV // ////////// - //`DV_FCOV_SIGNAL(logic, interrupt_taken, (ctrl_fsm_cs != IRQ_TAKEN) & (ctrl_fsm_ns == IRQ_TAKEN)) - //`DV_FCOV_SIGNAL(logic, debug_entry_if, - // (ctrl_fsm_cs != DBG_TAKEN_IF) & (ctrl_fsm_ns == DBG_TAKEN_IF)) - //`DV_FCOV_SIGNAL(logic, debug_entry_id, - // (ctrl_fsm_cs != DBG_TAKEN_ID) & (ctrl_fsm_ns == DBG_TAKEN_ID)) - //`DV_FCOV_SIGNAL(logic, pipe_flush, (ctrl_fsm_cs != FLUSH) & (ctrl_fsm_ns == FLUSH)) - //`DV_FCOV_SIGNAL(logic, debug_req, debug_req_i & ~debug_mode_q) + `DV_FCOV_SIGNAL(logic, interrupt_taken, (ctrl_fsm_cs != IRQ_TAKEN) & (ctrl_fsm_ns == IRQ_TAKEN)) + `DV_FCOV_SIGNAL(logic, debug_entry_if, + (ctrl_fsm_cs != DBG_TAKEN_IF) & (ctrl_fsm_ns == DBG_TAKEN_IF)) + `DV_FCOV_SIGNAL(logic, debug_entry_id, + (ctrl_fsm_cs != DBG_TAKEN_ID) & (ctrl_fsm_ns == DBG_TAKEN_ID)) + `DV_FCOV_SIGNAL(logic, pipe_flush, (ctrl_fsm_cs != FLUSH) & (ctrl_fsm_ns == FLUSH)) + `DV_FCOV_SIGNAL(logic, debug_req, debug_req_i & ~debug_mode_q) //////////////// // Assertions // //////////////// - `ASSERT(AlwaysInstrClearOnMispredict, nt_branch_mispredict_o |-> instr_valid_clear_o) - // Selectors must be known/valid. `ASSERT(IbexCtrlStateValid, ctrl_fsm_cs inside { RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH, @@ -923,7 +847,7 @@ module ibex_controller #( `ifdef RVFI // Workaround for internal verilator error when using hierarchical refers to calcuate this - // directly in ibex_core + // directly in cve2_core logic rvfi_flush_next; assign rvfi_flush_next = ctrl_fsm_ns == FLUSH; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f new file mode 100644 index 00000000..3250f707 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f @@ -0,0 +1,17 @@ +cve2_pkg.sv +cve2_alu.sv +cve2_compressed_decoder.sv +cve2_controller.sv +cve2_counter.sv +cve2_cs_registers.sv +cve2_decoder.sv +cve2_ex_block.sv +cve2_id_stage.sv +cve2_if_stage.sv +cve2_load_store_unit.sv +cve2_multdiv_slow.sv +cve2_multdiv_fast.sv +cve2_prefetch_buffer.sv +cve2_fetch_fifo.sv +cve2_register_file_ff.sv +cve2_core.sv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv similarity index 73% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index f57c87d9..4f79b67f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -12,7 +12,7 @@ /** * Top level module of the ibex RISC-V core */ -module ibex_core import ibex_pkg::*; #( +module cve2_core import cve2_pkg::*; #( parameter bit PMPEnable = 1'b0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, @@ -21,23 +21,8 @@ module ibex_core import ibex_pkg::*; #( parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, parameter rv32b_e RV32B = RV32BNone, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit BranchPredictor = 1'b0, parameter bit DbgTriggerEn = 1'b0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit SecureIbex = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit RegFileECC = 1'b0, - parameter int unsigned RegFileDataWidth = 32, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -45,6 +30,8 @@ module ibex_core import ibex_pkg::*; #( input logic clk_i, input logic rst_ni, + input logic test_en_i, + input logic [31:0] hart_id_i, input logic [31:0] boot_addr_i, @@ -67,34 +54,11 @@ module ibex_core import ibex_pkg::*; #( input logic [31:0] data_rdata_i, input logic data_err_i, - // Register file interface - output logic dummy_instr_id_o, - output logic [4:0] rf_raddr_a_o, - output logic [4:0] rf_raddr_b_o, - output logic [4:0] rf_waddr_wb_o, - output logic rf_we_wb_o, - output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, - - // RAMs interface - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - // Interrupt inputs input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt output logic irq_pending_o, @@ -103,7 +67,6 @@ module ibex_core import ibex_pkg::*; #( output crash_dump_t crash_dump_o, // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - output logic double_fault_seen_o, // RISC-V Formal Interface // Does not comply with the coding standards of _i/_o suffixes, but follows @@ -139,22 +102,14 @@ module ibex_core import ibex_pkg::*; #( `endif // CPU Control Signals - // SEC_CM: FETCH.CTRL.LC_GATED input logic fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_o, - output logic icache_inval_o, - output logic core_sleep_o + output logic core_busy_o ); localparam int unsigned PMP_NUM_CHAN = 3; // SEC_CM: CORE.DATA_REG_SW.SCA - localparam bit DataIndTiming = SecureIbex; - localparam bit PCIncrCheck = SecureIbex; - localparam bit ShadowCSR = 1'b0; // IF/ID signals - logic dummy_instr_id; logic instr_valid_id; logic instr_new_id; logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage @@ -163,33 +118,18 @@ module ibex_core import ibex_pkg::*; #( logic [15:0] instr_rdata_c_id; // Compressed instruction sampled inside IF stage logic instr_is_compressed_id; logic instr_perf_count_id; - logic instr_bp_taken_id; logic instr_fetch_err; // Bus error on instr fetch logic instr_fetch_err_plus2; // Instruction error is misaligned logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage logic [31:0] pc_if; // Program counter in IF stage logic [31:0] pc_id; // Program counter in ID stage - logic [31:0] pc_wb; // Program counter in WB stage logic [33:0] imd_val_d_ex[2]; // Intermediate register for multicycle Ops logic [33:0] imd_val_q_ex[2]; // Intermediate register for multicycle Ops logic [1:0] imd_val_we_ex; - logic data_ind_timing; - logic dummy_instr_en; - logic [2:0] dummy_instr_mask; - logic dummy_instr_seed_en; - logic [31:0] dummy_instr_seed; - logic icache_enable; - logic icache_inval; - logic icache_ecc_error; - logic pc_mismatch_alert; - logic csr_shadow_err; - logic instr_first_cycle_id; logic instr_valid_clear; logic pc_set; - logic nt_branch_mispredict; - logic [31:0] nt_branch_addr; pc_sel_e pc_mux_id; // Mux selector for next PC exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC exc_cause_e exc_cause; // Exception cause @@ -221,26 +161,19 @@ module ibex_core import ibex_pkg::*; #( logic [31:0] rf_wdata_wb; // Writeback register write data that can be used on the forwarding path (doesn't factor in memory // read data as this is too late for the forwarding path) - logic [31:0] rf_wdata_fwd_wb; logic [31:0] rf_wdata_lsu; logic rf_we_wb; logic rf_we_lsu; - logic rf_ecc_err_comb; logic [4:0] rf_waddr_id; logic [31:0] rf_wdata_id; logic rf_we_id; - logic rf_rd_a_wb_match; - logic rf_rd_b_wb_match; // ALU Control alu_op_e alu_operator_ex; logic [31:0] alu_operand_a_ex; logic [31:0] alu_operand_b_ex; - logic [31:0] bt_a_operand; - logic [31:0] bt_b_operand; - logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU logic [31:0] result_ex; @@ -253,7 +186,6 @@ module ibex_core import ibex_pkg::*; #( logic [1:0] multdiv_signed_mode_ex; logic [31:0] multdiv_operand_a_ex; logic [31:0] multdiv_operand_b_ex; - logic multdiv_ready_id; // CSR control logic csr_access; @@ -272,7 +204,6 @@ module ibex_core import ibex_pkg::*; #( logic lsu_sign_ext; logic lsu_req; logic [31:0] lsu_wdata; - logic lsu_req_done; // stall control logic id_in_ready; @@ -285,13 +216,8 @@ module ibex_core import ibex_pkg::*; #( logic instr_req_int; // Id stage asserts a req to instruction core interface logic instr_req_gated; - // Writeback stage - logic en_wb; - wb_instr_type_e instr_type_wb; - logic ready_wb; - logic rf_write_wb; - logic outstanding_load_wb; - logic outstanding_store_wb; + // Writeback + logic en_wb; // Interrupts logic nmi_mode; @@ -308,7 +234,6 @@ module ibex_core import ibex_pkg::*; #( logic csr_save_if; logic csr_save_id; - logic csr_save_wb; logic csr_restore_mret_id; logic csr_restore_dret_id; logic csr_save_cause; @@ -331,15 +256,12 @@ module ibex_core import ibex_pkg::*; #( // signals relating to instruction movements between pipeline stages // used by performance counters and RVFI logic instr_id_done; - logic instr_done_wb; logic perf_instr_ret_wb; logic perf_instr_ret_compressed_wb; - logic perf_instr_ret_wb_spec; - logic perf_instr_ret_compressed_wb_spec; logic perf_iside_wait; logic perf_dside_wait; - logic perf_mul_wait; + logic perf_wfi_wait; logic perf_div_wait; logic perf_jump; logic perf_branch; @@ -350,63 +272,23 @@ module ibex_core import ibex_pkg::*; #( // for RVFI logic illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction - ////////////////////////////////////////////////////////////////////////////////////////////// - // ____ _ _ __ __ _ // - // / ___| | ___ ___| | __ | \/ | __ _ _ __ __ _ __ _ ___ _ __ ___ ___ _ __ | |_ // - // | | | |/ _ \ / __| |/ / | |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '_ ` _ \ / _ \ '_ \| __| // - // | |___| | (_) | (__| < | | | | (_| | | | | (_| | (_| | __/ | | | | | __/ | | | |_ // - // \____|_|\___/ \___|_|\_\ |_| |_|\__,_|_| |_|\__,_|\__, |\___|_| |_| |_|\___|_| |_|\__| // - // |___/ // - ////////////////////////////////////////////////////////////////////////////////////////////// - - logic clk; - logic fetch_enable; - logic wake_from_sleep; - - cve2_sleep_unit sleep_unit_i ( - // Clock, reset interface - .clk_ungated_i(clk_i), // Ungated clock - .rst_n (rst_ni), - .clk_gated_o (clk), // Gated clock - .scan_cg_en_i (1'b0), - - // Core sleep - .core_sleep_o(core_sleep_o), - - // Fetch enable - .fetch_enable_i(fetch_enable_i), - .fetch_enable_o(fetch_enable), - - // Core status - .if_busy_i (if_busy), - .ctrl_busy_i(ctrl_busy), - .lsu_busy_i (lsu_busy), - - // WFI wake - .wake_from_sleep_i(wake_from_sleep) - ); + ////////////////////// + // Clock management // + ////////////////////// + // Before going to sleep, wait for I- and D-side + // interfaces to finish ongoing operations. + assign core_busy_o = ctrl_busy | if_busy | lsu_busy; ////////////// // IF stage // ////////////// - ibex_if_stage #( + cve2_if_stage #( .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr), - .DummyInstructions(DummyInstructions), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .PCIncrCheck (PCIncrCheck), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), - .BranchPredictor (BranchPredictor) + .DmExceptionAddr (DmExceptionAddr) ) if_stage_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), .boot_addr_i(boot_addr_i), @@ -420,18 +302,6 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_i (instr_rdata_i), .instr_err_i (instr_err_i), - .ic_tag_req_o (ic_tag_req_o), - .ic_tag_write_o (ic_tag_write_o), - .ic_tag_addr_o (ic_tag_addr_o), - .ic_tag_wdata_o (ic_tag_wdata_o), - .ic_tag_rdata_i (ic_tag_rdata_i), - .ic_data_req_o (ic_data_req_o), - .ic_data_write_o (ic_data_write_o), - .ic_data_addr_o (ic_data_addr_o), - .ic_data_wdata_o (ic_data_wdata_o), - .ic_data_rdata_i (ic_data_rdata_i), - .ic_scr_key_valid_i(ic_scr_key_valid_i), - // outputs to ID stage .instr_valid_id_o (instr_valid_id), .instr_new_id_o (instr_new_id), @@ -439,11 +309,9 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_alu_id_o (instr_rdata_alu_id), .instr_rdata_c_id_o (instr_rdata_c_id), .instr_is_compressed_id_o(instr_is_compressed_id), - .instr_bp_taken_o (instr_bp_taken_id), .instr_fetch_err_o (instr_fetch_err), .instr_fetch_err_plus2_o (instr_fetch_err_plus2), .illegal_c_insn_id_o (illegal_c_insn_id), - .dummy_instr_id_o (dummy_instr_id), .pc_if_o (pc_if), .pc_id_o (pc_id), .pmp_err_if_i (pmp_req_err[PMP_I]), @@ -453,20 +321,11 @@ module ibex_core import ibex_pkg::*; #( .instr_valid_clear_i (instr_valid_clear), .pc_set_i (pc_set), .pc_mux_i (pc_mux_id), - .nt_branch_mispredict_i(nt_branch_mispredict), .exc_pc_mux_i (exc_pc_mux_id), .exc_cause (exc_cause), - .dummy_instr_en_i (dummy_instr_en), - .dummy_instr_mask_i (dummy_instr_mask), - .dummy_instr_seed_en_i (dummy_instr_seed_en), - .dummy_instr_seed_i (dummy_instr_seed), - .icache_enable_i (icache_enable), - .icache_inval_i (icache_inval), - .icache_ecc_error_o (icache_ecc_error), // branch targets .branch_target_ex_i(branch_target_ex), - .nt_branch_addr_i (nt_branch_addr), // CSRs .csr_mepc_i (csr_mepc), // exception return address @@ -477,7 +336,6 @@ module ibex_core import ibex_pkg::*; #( // pipeline stalls .id_in_ready_i(id_in_ready), - .pc_mismatch_alert_o(pc_mismatch_alert), .if_busy_o (if_busy) ); @@ -485,27 +343,23 @@ module ibex_core import ibex_pkg::*; #( // available assign perf_iside_wait = id_in_ready & ~instr_valid_id; - // fetch_enable_i can be used to stop the core fetching new instructions - assign instr_req_gated = instr_req_int & fetch_enable; + // For non secure Ibex only the bottom bit of fetch enable is considered + assign instr_req_gated = instr_req_int; ////////////// // ID stage // ////////////// - ibex_id_stage #( + cve2_id_stage #( .RV32E (RV32E), .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU), - .DataIndTiming (DataIndTiming), - .WritebackStage (WritebackStage), - .BranchPredictor(BranchPredictor) + .RV32B (RV32B) ) id_stage_i ( - - .clk_i(clk), + .clk_i (clk_i), .rst_ni(rst_ni), // Processor Enable + .fetch_enable_i(fetch_enable_i), .ctrl_busy_o (ctrl_busy), .illegal_insn_o(illegal_insn_id), @@ -515,7 +369,6 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_alu_i (instr_rdata_alu_id), .instr_rdata_c_i (instr_rdata_c_id), .instr_is_compressed_i(instr_is_compressed_id), - .instr_bp_taken_i (instr_bp_taken_id), // Jumps and branches .branch_decision_i(branch_decision), @@ -527,11 +380,8 @@ module ibex_core import ibex_pkg::*; #( .instr_req_o (instr_req_int), .pc_set_o (pc_set), .pc_mux_o (pc_mux_id), - .nt_branch_mispredict_o(nt_branch_mispredict), - .nt_branch_addr_o (nt_branch_addr), .exc_pc_mux_o (exc_pc_mux_id), .exc_cause_o (exc_cause), - .icache_inval_o (icache_inval), .instr_fetch_err_i (instr_fetch_err), .instr_fetch_err_plus2_i(instr_fetch_err_plus2), @@ -551,9 +401,6 @@ module ibex_core import ibex_pkg::*; #( .imd_val_d_ex_i (imd_val_d_ex), .imd_val_we_ex_i(imd_val_we_ex), - .bt_a_operand_o(bt_a_operand), - .bt_b_operand_o(bt_b_operand), - .mult_en_ex_o (mult_en_ex), .div_en_ex_o (div_en_ex), .mult_sel_ex_o (mult_sel_ex), @@ -562,7 +409,6 @@ module ibex_core import ibex_pkg::*; #( .multdiv_signed_mode_ex_o(multdiv_signed_mode_ex), .multdiv_operand_a_ex_o (multdiv_operand_a_ex), .multdiv_operand_b_ex_o (multdiv_operand_b_ex), - .multdiv_ready_id_o (multdiv_ready_id), // CSR ID/EX .csr_access_o (csr_access), @@ -570,7 +416,6 @@ module ibex_core import ibex_pkg::*; #( .csr_op_en_o (csr_op_en), .csr_save_if_o (csr_save_if), // control signal to save PC .csr_save_id_o (csr_save_id), // control signal to save PC - .csr_save_wb_o (csr_save_wb), // control signal to save PC .csr_restore_mret_id_o(csr_restore_mret_id), // restore mstatus upon MRET .csr_restore_dret_id_o(csr_restore_dret_id), // restore mstatus upon MRET .csr_save_cause_o (csr_save_cause), @@ -578,7 +423,6 @@ module ibex_core import ibex_pkg::*; #( .priv_mode_i (priv_mode_id), .csr_mstatus_tw_i (csr_mstatus_tw), .illegal_csr_insn_i (illegal_csr_insn_id), - .data_ind_timing_i (data_ind_timing), // LSU .lsu_req_o (lsu_req), // to load store unit @@ -586,7 +430,6 @@ module ibex_core import ibex_pkg::*; #( .lsu_type_o (lsu_type), // to load store unit .lsu_sign_ext_o(lsu_sign_ext), // to load store unit .lsu_wdata_o (lsu_wdata), // to load store unit - .lsu_req_done_i(lsu_req_done), // from load store unit .lsu_addr_incr_req_i(lsu_addr_incr_req), .lsu_addr_last_i (lsu_addr_last), @@ -611,9 +454,6 @@ module ibex_core import ibex_pkg::*; #( .debug_ebreaku_i (debug_ebreaku), .trigger_match_i (trigger_match), - // Wakeup Signal - .wake_from_sleep_o(wake_from_sleep), - // write data to commit in the register file .result_ex_i(result_ex), .csr_rdata_i(csr_rdata), @@ -627,40 +467,28 @@ module ibex_core import ibex_pkg::*; #( .rf_waddr_id_o (rf_waddr_id), .rf_wdata_id_o (rf_wdata_id), .rf_we_id_o (rf_we_id), - .rf_rd_a_wb_match_o(rf_rd_a_wb_match), - .rf_rd_b_wb_match_o(rf_rd_b_wb_match), - - .rf_waddr_wb_i (rf_waddr_wb), - .rf_wdata_fwd_wb_i(rf_wdata_fwd_wb), - .rf_write_wb_i (rf_write_wb), - .en_wb_o (en_wb), - .instr_type_wb_o (instr_type_wb), + .en_wb_o (en_wb), .instr_perf_count_id_o (instr_perf_count_id), - .ready_wb_i (ready_wb), - .outstanding_load_wb_i (outstanding_load_wb), - .outstanding_store_wb_i(outstanding_store_wb), // Performance Counters .perf_jump_o (perf_jump), .perf_branch_o (perf_branch), .perf_tbranch_o (perf_tbranch), .perf_dside_wait_o(perf_dside_wait), - .perf_mul_wait_o (perf_mul_wait), + .perf_wfi_wait_o (perf_wfi_wait), .perf_div_wait_o (perf_div_wait), .instr_id_done_o (instr_id_done) ); - assign icache_inval_o = icache_inval; // for RVFI only assign unused_illegal_insn_id = illegal_insn_id; - ibex_ex_block #( + cve2_ex_block #( .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU) + .RV32B (RV32B) ) ex_block_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), // ALU signal from ID stage @@ -669,10 +497,6 @@ module ibex_core import ibex_pkg::*; #( .alu_operand_b_i (alu_operand_b_ex), .alu_instr_first_cycle_i(instr_first_cycle_id), - // Branch target ALU signal from ID stage - .bt_a_operand_i(bt_a_operand), - .bt_b_operand_i(bt_b_operand), - // Multipler/Divider signal from ID stage .multdiv_operator_i (multdiv_operator_ex), .mult_en_i (mult_en_ex), @@ -682,8 +506,6 @@ module ibex_core import ibex_pkg::*; #( .multdiv_signed_mode_i(multdiv_signed_mode_ex), .multdiv_operand_a_i (multdiv_operand_a_ex), .multdiv_operand_b_i (multdiv_operand_b_ex), - .multdiv_ready_id_i (multdiv_ready_id), - .data_ind_timing_i (data_ind_timing), // Intermediate value register .imd_val_we_o(imd_val_we_ex), @@ -707,8 +529,8 @@ module ibex_core import ibex_pkg::*; #( assign data_req_o = data_req_out & ~pmp_req_err[PMP_D]; assign lsu_resp_err = lsu_load_err | lsu_store_err; - ibex_load_store_unit load_store_unit_i ( - .clk_i (clk), + cve2_load_store_unit load_store_unit_i ( + .clk_i (clk_i), .rst_ni(rst_ni), // data interface @@ -733,7 +555,6 @@ module ibex_core import ibex_pkg::*; #( .lsu_rdata_o (rf_wdata_lsu), .lsu_rdata_valid_o(rf_we_lsu), .lsu_req_i (lsu_req), - .lsu_req_done_o (lsu_req_done), .adder_result_ex_i(alu_adder_result_ex), @@ -753,27 +574,17 @@ module ibex_core import ibex_pkg::*; #( .perf_store_o(perf_store) ); - ibex_wb_stage #( - .ResetAll ( ResetAll ), - .WritebackStage(WritebackStage) - ) wb_stage_i ( - .clk_i (clk), - .rst_ni (rst_ni), - .en_wb_i (en_wb), - .instr_type_wb_i (instr_type_wb), - .pc_id_i (pc_id), + cve2_wb #( + ) wb_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .en_wb_i (en_wb), + .instr_is_compressed_id_i(instr_is_compressed_id), .instr_perf_count_id_i (instr_perf_count_id), - .ready_wb_o (ready_wb), - .rf_write_wb_o (rf_write_wb), - .outstanding_load_wb_o (outstanding_load_wb), - .outstanding_store_wb_o (outstanding_store_wb), - .pc_wb_o (pc_wb), .perf_instr_ret_wb_o (perf_instr_ret_wb), .perf_instr_ret_compressed_wb_o (perf_instr_ret_compressed_wb), - .perf_instr_ret_wb_spec_o (perf_instr_ret_wb_spec), - .perf_instr_ret_compressed_wb_spec_o(perf_instr_ret_compressed_wb_spec), .rf_waddr_id_i(rf_waddr_id), .rf_wdata_id_i(rf_wdata_id), @@ -782,79 +593,14 @@ module ibex_core import ibex_pkg::*; #( .rf_wdata_lsu_i(rf_wdata_lsu), .rf_we_lsu_i (rf_we_lsu), - .rf_wdata_fwd_wb_o(rf_wdata_fwd_wb), - .rf_waddr_wb_o(rf_waddr_wb), .rf_wdata_wb_o(rf_wdata_wb), .rf_we_wb_o (rf_we_wb), .lsu_resp_valid_i(lsu_resp_valid), - .lsu_resp_err_i (lsu_resp_err), - - .instr_done_wb_o(instr_done_wb) + .lsu_resp_err_i (lsu_resp_err) ); - ///////////////////////////// - // Register file interface // - ///////////////////////////// - - assign dummy_instr_id_o = dummy_instr_id; - assign rf_raddr_a_o = rf_raddr_a; - assign rf_waddr_wb_o = rf_waddr_wb; - assign rf_we_wb_o = rf_we_wb; - assign rf_raddr_b_o = rf_raddr_b; - - if (RegFileECC) begin : gen_regfile_ecc - - // SEC_CM: DATA_REG_SW.INTEGRITY - logic [1:0] rf_ecc_err_a, rf_ecc_err_b; - logic rf_ecc_err_a_id, rf_ecc_err_b_id; - - // ECC checkbit generation for regiter file wdata - prim_secded_inv_39_32_enc regfile_ecc_enc ( - .data_i(rf_wdata_wb), - .data_o(rf_wdata_wb_ecc_o) - ); - - // ECC checking on register file rdata - prim_secded_inv_39_32_dec regfile_ecc_dec_a ( - .data_i (rf_rdata_a_ecc_i), - .data_o (), - .syndrome_o(), - .err_o (rf_ecc_err_a) - ); - prim_secded_inv_39_32_dec regfile_ecc_dec_b ( - .data_i (rf_rdata_b_ecc_i), - .data_o (), - .syndrome_o(), - .err_o (rf_ecc_err_b) - ); - - // Assign read outputs - no error correction, just trigger an alert - assign rf_rdata_a = rf_rdata_a_ecc_i[31:0]; - assign rf_rdata_b = rf_rdata_b_ecc_i[31:0]; - - // Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal - assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match; - assign rf_ecc_err_b_id = |rf_ecc_err_b & rf_ren_b & ~rf_rd_b_wb_match; - - // Combined error - assign rf_ecc_err_comb = instr_valid_id & (rf_ecc_err_a_id | rf_ecc_err_b_id); - - end else begin : gen_no_regfile_ecc - logic unused_rf_ren_a, unused_rf_ren_b; - logic unused_rf_rd_a_wb_match, unused_rf_rd_b_wb_match; - - assign unused_rf_ren_a = rf_ren_a; - assign unused_rf_ren_b = rf_ren_b; - assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match; - assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match; - assign rf_wdata_wb_ecc_o = rf_wdata_wb; - assign rf_rdata_a = rf_rdata_a_ecc_i; - assign rf_rdata_b = rf_rdata_b_ecc_i; - assign rf_ecc_err_comb = 1'b0; - end - /////////////////////// // Crash dump output // /////////////////////// @@ -864,15 +610,6 @@ module ibex_core import ibex_pkg::*; #( assign crash_dump_o.last_data_addr = lsu_addr_last; assign crash_dump_o.exception_addr = csr_mepc; - /////////////////// - // Alert outputs // - /////////////////// - - // Minor alert - core is in a recoverable state - assign alert_minor_o = icache_ecc_error; - - // Major alert - core is unrecoverable - assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err; // Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included `ifdef INC_ASSERT @@ -888,19 +625,7 @@ module ibex_core import ibex_pkg::*; #( assign outstanding_store_id = id_stage_i.instr_executing & id_stage_i.lsu_req_dec & id_stage_i.lsu_we; - if (WritebackStage) begin : gen_wb_stage - // When the writeback stage is present a load/store could be in ID or WB. A Load/store in ID can - // see a response before it moves to WB when it is unaligned otherwise we should only see - // a response when load/store is in WB. - assign outstanding_load_resp = outstanding_load_wb | - (outstanding_load_id & load_store_unit_i.split_misaligned_access); - - assign outstanding_store_resp = outstanding_store_wb | - (outstanding_store_id & load_store_unit_i.split_misaligned_access); - - // When writing back the result of a load, the load must have made it to writeback - `ASSERT(NoMemRFWriteWithoutPendingLoad, rf_we_lsu |-> outstanding_load_wb, clk_i, !rst_ni) - end else begin : gen_no_wb_stage + begin : gen_no_wb_stage // Without writeback stage only look into whether load or store is in ID to determine if // a response is expected. assign outstanding_load_resp = outstanding_load_id; @@ -916,8 +641,24 @@ module ibex_core import ibex_pkg::*; #( //////////////////////// // RF (Register File) // //////////////////////// -`ifdef RVFI -`endif + cve2_register_file_ff #( + .RV32E (RV32E), + .DataWidth (32), + .WordZeroVal (32'h0) + ) register_file_i ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .test_en_i(test_en_i), + + .raddr_a_i(rf_raddr_a), + .rdata_a_o(rf_rdata_a), + .raddr_b_i(rf_raddr_b), + .rdata_b_o(rf_rdata_b), + .waddr_a_i(rf_waddr_wb), + .wdata_a_i(rf_wdata_wb), + .we_a_i (rf_we_wb) + ); ///////////////////////////////////////// @@ -927,13 +668,9 @@ module ibex_core import ibex_pkg::*; #( assign csr_wdata = alu_operand_a_ex; assign csr_addr = csr_num_e'(csr_access ? alu_operand_b_ex[11:0] : 12'b0); - ibex_cs_registers #( + cve2_cs_registers #( .DbgTriggerEn (DbgTriggerEn), .DbgHwBreakNum (DbgHwBreakNum), - .DataIndTiming (DataIndTiming), - .DummyInstructions(DummyInstructions), - .ShadowCSR (ShadowCSR), - .ICache (ICache), .MHPMCounterNum (MHPMCounterNum), .MHPMCounterWidth (MHPMCounterWidth), .PMPEnable (PMPEnable), @@ -943,7 +680,7 @@ module ibex_core import ibex_pkg::*; #( .RV32M (RV32M), .RV32B (RV32B) ) cs_registers_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), // Hart ID from outside @@ -993,19 +730,9 @@ module ibex_core import ibex_pkg::*; #( .pc_if_i(pc_if), .pc_id_i(pc_id), - .pc_wb_i(pc_wb), - - .data_ind_timing_o (data_ind_timing), - .dummy_instr_en_o (dummy_instr_en), - .dummy_instr_mask_o (dummy_instr_mask), - .dummy_instr_seed_en_o(dummy_instr_seed_en), - .dummy_instr_seed_o (dummy_instr_seed), - .icache_enable_o (icache_enable), - .csr_shadow_err_o (csr_shadow_err), .csr_save_if_i (csr_save_if), .csr_save_id_i (csr_save_id), - .csr_save_wb_i (csr_save_wb), .csr_restore_mret_i(csr_restore_mret_id), .csr_restore_dret_i(csr_restore_dret_id), .csr_save_cause_i (csr_save_cause), @@ -1013,13 +740,9 @@ module ibex_core import ibex_pkg::*; #( .csr_mtval_i (csr_mtval), .illegal_csr_insn_o(illegal_csr_insn_id), - .double_fault_seen_o, - // performance counter related signals .instr_ret_i (perf_instr_ret_wb), .instr_ret_compressed_i (perf_instr_ret_compressed_wb), - .instr_ret_spec_i (perf_instr_ret_wb_spec), - .instr_ret_compressed_spec_i(perf_instr_ret_compressed_wb_spec), .iside_wait_i (perf_iside_wait), .jump_i (perf_jump), .branch_i (perf_branch), @@ -1027,7 +750,7 @@ module ibex_core import ibex_pkg::*; #( .mem_load_i (perf_load), .mem_store_i (perf_store), .dside_wait_i (perf_dside_wait), - .mul_wait_i (perf_mul_wait), + .wfi_wait_i (perf_wfi_wait), .div_wait_i (perf_div_wait) ); @@ -1055,7 +778,7 @@ module ibex_core import ibex_pkg::*; #( assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ; assign pmp_priv_lvl[PMP_D] = priv_mode_lsu; - ibex_pmp #( + cve2_pmp #( .PMPGranularity(PMPGranularity), .PMPNumChan (PMP_NUM_CHAN), .PMPNumRegions (PMPNumRegions) @@ -1096,7 +819,7 @@ module ibex_core import ibex_pkg::*; #( // second stage. RVFI outputs are all straight from flops. So 2 stage pipeline requires a single // set of flops (instr_info => RVFI_out), 3 stage pipeline requires two sets (instr_info => wb // => RVFI_out) - localparam int RVFI_STAGES = WritebackStage ? 2 : 1; + localparam int RVFI_STAGES = 1; logic rvfi_stage_valid [RVFI_STAGES]; logic [63:0] rvfi_stage_order [RVFI_STAGES]; @@ -1153,22 +876,20 @@ module ibex_core import ibex_pkg::*; #( logic [31:0] rvfi_mem_addr_d; logic [31:0] rvfi_mem_addr_q; logic rvfi_trap_id; - logic rvfi_trap_wb; logic [63:0] rvfi_stage_order_d; logic rvfi_id_done; - logic rvfi_wb_done; logic new_debug_req; logic new_nmi; logic new_irq; - ibex_pkg::irqs_t captured_mip; + cve2_pkg::irqs_t captured_mip; logic captured_nmi; logic captured_debug_req; logic captured_valid; // RVFI extension for co-simulation support // debug_req and MIP captured at IF -> ID transition so one extra stage - ibex_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1]; + cve2_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1]; logic rvfi_ext_stage_nmi [RVFI_STAGES+1]; logic rvfi_ext_stage_debug_req [RVFI_STAGES+1]; logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES]; @@ -1226,56 +947,20 @@ module ibex_core import ibex_pkg::*; #( // Factor in exceptions taken in ID so RVFI tracking picks up flushed instructions that took // a trap - assign rvfi_id_done = instr_id_done | (id_stage_i.controller_i.rvfi_flush_next & - id_stage_i.controller_i.id_exception_o); - - if (WritebackStage) begin : gen_rvfi_wb_stage - logic unused_instr_new_id; + // MRET causes MSTATUS to get written one clock later. Fix rvfi_valid when executing MRET + assign rvfi_id_done = (instr_id_done & !id_stage_i.controller_i.mret_insn)| + id_stage_i.csr_restore_mret_id_o | + (id_stage_i.controller_i.rvfi_flush_next & id_stage_i.controller_i.exc_req_d); - assign unused_instr_new_id = instr_new_id; + // Without writeback stage first RVFI stage is output stage so simply valid the cycle after + // instruction leaves ID/EX (and so has retired) + assign rvfi_stage_valid_d[0] = rvfi_id_done; + // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly + // setup register write signals + assign rvfi_instr_new_wb = instr_new_id; + assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu; - // With writeback stage first RVFI stage buffers instruction information captured in ID/EX - // awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB - // So first stage becomes valid when instruction leaves ID/EX stage and remains valid until - // instruction leaves WB - assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) | - (rvfi_stage_valid[0] & ~rvfi_wb_done); - // Second stage is output stage so simple valid cycle after instruction leaves WB (and so has - // retired) - assign rvfi_stage_valid_d[1] = rvfi_wb_done; - - // Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB) - logic rvfi_instr_new_wb_q; - - // Signal new instruction in WB either when one has just entered or when a trap is progressing - // through the tracking pipeline - assign rvfi_instr_new_wb = rvfi_instr_new_wb_q | (rvfi_stage_valid[0] & rvfi_stage_trap[0]); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rvfi_instr_new_wb_q <= 0; - end else begin - rvfi_instr_new_wb_q <= rvfi_id_done; - end - end - - assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o; - assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu; - // WB is instantly done in the tracking pipeline when a trap is progress through the pipeline - assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]); - end else begin : gen_rvfi_no_wb_stage - // Without writeback stage first RVFI stage is output stage so simply valid the cycle after - // instruction leaves ID/EX (and so has retired) - assign rvfi_stage_valid_d[0] = rvfi_id_done & ~dummy_instr_id; - // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly - // setup register write signals - assign rvfi_instr_new_wb = instr_new_id; - assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu; - assign rvfi_trap_wb = 1'b0; - assign rvfi_wb_done = instr_done_wb; - end - - assign rvfi_stage_order_d = dummy_instr_id ? rvfi_stage_order[0] : rvfi_stage_order[0] + 64'd1; + assign rvfi_stage_order_d = rvfi_stage_order[0] + 64'd1; // For interrupts and debug Ibex will take the relevant trap as soon as whatever instruction in ID // finishes or immediately if the ID stage is empty. The rvfi_ext interface provides the DV @@ -1410,9 +1095,8 @@ module ibex_core import ibex_pkg::*; #( rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o; end end else begin - if (rvfi_wb_done) begin rvfi_stage_halt[i] <= rvfi_stage_halt[i-1]; - rvfi_stage_trap[i] <= rvfi_stage_trap[i-1] | rvfi_trap_wb; + rvfi_stage_trap[i] <= rvfi_stage_trap[i-1]; rvfi_stage_intr[i] <= rvfi_stage_intr[i-1]; rvfi_stage_order[i] <= rvfi_stage_order[i-1]; rvfi_stage_insn[i] <= rvfi_stage_insn[i-1]; @@ -1443,7 +1127,6 @@ module ibex_core import ibex_pkg::*; #( rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i]; rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i]; rvfi_ext_stage_mcycle[i] <= rvfi_ext_stage_mcycle[i-1]; - end end end end @@ -1596,13 +1279,9 @@ module ibex_core import ibex_pkg::*; #( end `else - logic unused_instr_new_id, unused_instr_id_done, unused_instr_done_wb; + logic unused_instr_new_id, unused_instr_id_done; assign unused_instr_id_done = instr_id_done; assign unused_instr_new_id = instr_new_id; - assign unused_instr_done_wb = instr_done_wb; `endif - // Certain parameter combinations are not supported - `ASSERT_INIT(IllegalParamSecure, !(SecureIbex && (RV32M == RV32MNone))) - endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv index a6187b78..417614b1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv @@ -1,4 +1,4 @@ -module ibex_counter #( +module cve2_counter #( parameter int CounterWidth = 32, // When set `counter_val_upd_o` provides an incremented version of the counter value, otherwise // the output is hard-wired to 0. This is required to allow Xilinx DSP inference to work diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv similarity index 86% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index aa328205..dfce0985 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -12,21 +12,17 @@ `include "prim_assert.sv" -module ibex_cs_registers #( +module cve2_cs_registers #( parameter bit DbgTriggerEn = 0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit DataIndTiming = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit ShadowCSR = 1'b0, - parameter bit ICache = 1'b0, parameter int unsigned MHPMCounterNum = 10, parameter int unsigned MHPMCounterWidth = 40, parameter bit PMPEnable = 0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( // Clock and Reset input logic clk_i, @@ -36,8 +32,8 @@ module ibex_cs_registers #( input logic [31:0] hart_id_i, // Privilege mode - output ibex_pkg::priv_lvl_e priv_mode_id_o, - output ibex_pkg::priv_lvl_e priv_mode_lsu_o, + output cve2_pkg::priv_lvl_e priv_mode_id_o, + output cve2_pkg::priv_lvl_e priv_mode_lsu_o, output logic csr_mstatus_tw_o, // mtvec @@ -47,9 +43,9 @@ module ibex_cs_registers #( // Interface to registers (SRAM like) input logic csr_access_i, - input ibex_pkg::csr_num_e csr_addr_i, + input cve2_pkg::csr_num_e csr_addr_i, input logic [31:0] csr_wdata_i, - input ibex_pkg::csr_op_e csr_op_i, + input cve2_pkg::csr_op_e csr_op_i, input csr_op_en_i, output logic [31:0] csr_rdata_o, @@ -57,21 +53,21 @@ module ibex_cs_registers #( input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic nmi_mode_i, output logic irq_pending_o, // interrupt request pending - output ibex_pkg::irqs_t irqs_o, // interrupt requests qualified with mie + output cve2_pkg::irqs_t irqs_o, // interrupt requests qualified with mie output logic csr_mstatus_mie_o, output logic [31:0] csr_mepc_o, // PMP - output ibex_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], + output cve2_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], output logic [33:0] csr_pmp_addr_o [PMPNumRegions], - output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o, + output cve2_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o, // debug input logic debug_mode_i, - input ibex_pkg::dbg_cause_e debug_cause_i, + input cve2_pkg::dbg_cause_e debug_cause_i, input logic debug_csr_save_i, output logic [31:0] csr_depc_o, output logic debug_single_step_o, @@ -81,35 +77,21 @@ module ibex_cs_registers #( input logic [31:0] pc_if_i, input logic [31:0] pc_id_i, - input logic [31:0] pc_wb_i, - - // CPU control bits - output logic data_ind_timing_o, - output logic dummy_instr_en_o, - output logic [2:0] dummy_instr_mask_o, - output logic dummy_instr_seed_en_o, - output logic [31:0] dummy_instr_seed_o, - output logic icache_enable_o, - output logic csr_shadow_err_o, // Exception save/restore input logic csr_save_if_i, input logic csr_save_id_i, - input logic csr_save_wb_i, input logic csr_restore_mret_i, input logic csr_restore_dret_i, input logic csr_save_cause_i, - input ibex_pkg::exc_cause_e csr_mcause_i, + input cve2_pkg::exc_cause_e csr_mcause_i, input logic [31:0] csr_mtval_i, output logic illegal_csr_insn_o, // access to non-existent CSR, // with wrong priviledge level, or // missing write permissions - output logic double_fault_seen_o, // Performance Counters input logic instr_ret_i, // instr retired in ID/EX stage input logic instr_ret_compressed_i, // compressed instr retired - input logic instr_ret_spec_i, // speculative instr_ret_i - input logic instr_ret_compressed_spec_i, // speculative instr_ret_compressed_i input logic iside_wait_i, // core waiting for the iside input logic jump_i, // jump instr seen (j, jr, jal, jalr) input logic branch_i, // branch instr seen (bf, bnf) @@ -117,11 +99,11 @@ module ibex_cs_registers #( input logic mem_load_i, // load from memory in this cycle input logic mem_store_i, // store to memory in this cycle input logic dside_wait_i, // core waiting for the dside - input logic mul_wait_i, // core waiting for multiply + input logic wfi_wait_i, // core waiting for interrupt input logic div_wait_i // core waiting for divide ); - import ibex_pkg::*; + import cve2_pkg::*; localparam int unsigned RV32BEnabled = (RV32B == RV32BNone) ? 0 : 1; localparam int unsigned RV32MEnabled = (RV32M == RV32MNone) ? 0 : 1; @@ -174,23 +156,12 @@ module ibex_cs_registers #( priv_lvl_e prv; } dcsr_t; - // CPU control register fields - typedef struct packed { - logic double_fault_seen; - logic sync_exc_seen; - logic [2:0] dummy_instr_mask; - logic dummy_instr_en; - logic data_ind_timing; - logic icache_enable; - } cpu_ctrl_t; - // Interrupt and exception control signals logic [31:0] exception_pc; // CSRs priv_lvl_e priv_lvl_q, priv_lvl_d; status_t mstatus_q, mstatus_d; - logic mstatus_err; logic mstatus_en; irqs_t mie_q, mie_d; logic mie_en; @@ -198,12 +169,11 @@ module ibex_cs_registers #( logic mscratch_en; logic [31:0] mepc_q, mepc_d; logic mepc_en; - logic [5:0] mcause_q, mcause_d; + logic [6:0] mcause_q, mcause_d; logic mcause_en; logic [31:0] mtval_q, mtval_d; logic mtval_en; logic [31:0] mtvec_q, mtvec_d; - logic mtvec_err; logic mtvec_en; irqs_t mip; dcsr_t dcsr_q, dcsr_d; @@ -219,12 +189,11 @@ module ibex_cs_registers #( status_stk_t mstack_q, mstack_d; logic mstack_en; logic [31:0] mstack_epc_q, mstack_epc_d; - logic [5:0] mstack_cause_q, mstack_cause_d; + logic [6:0] mstack_cause_q, mstack_cause_d; // PMP Signals logic [31:0] pmp_addr_rdata [PMP_MAX_REGIONS]; logic [PMP_CFG_W-1:0] pmp_cfg_rdata [PMP_MAX_REGIONS]; - logic pmp_csr_err; pmp_mseccfg_t pmp_mseccfg; // Hardware performance monitor signals @@ -246,18 +215,13 @@ module ibex_cs_registers #( logic unused_mhpmcounterh_we_1; logic unused_mhpmcounter_incr_1; - logic [63:0] minstret_next, minstret_raw; + logic [63:0] minstret_raw; // Debug / trigger registers logic [31:0] tselect_rdata; logic [31:0] tmatch_control_rdata; logic [31:0] tmatch_value_rdata; - // CPU control bits - cpu_ctrl_t cpuctrl_q, cpuctrl_d, cpuctrl_wdata_raw, cpuctrl_wdata; - logic cpuctrl_we; - logic cpuctrl_err; - // CSR update logic logic [31:0] csr_wdata_int; logic [31:0] csr_rdata_int; @@ -308,6 +272,8 @@ module ibex_cs_registers #( CSR_MIMPID: csr_rdata_int = CSR_MIMPID_VALUE; // mhartid: unique hardware thread id CSR_MHARTID: csr_rdata_int = hart_id_i; + // mconfigptr: pointer to configuration data structre + CSR_MCONFIGPTR: csr_rdata_int = CSR_MCONFIGPTR_VALUE; // mstatus: always M-mode, contains IE bit CSR_MSTATUS: begin @@ -319,6 +285,13 @@ module ibex_cs_registers #( csr_rdata_int[CSR_MSTATUS_TW_BIT] = mstatus_q.tw; end + // mstatush: All zeros for Ibex (fixed little endian and all other bits reserved) + CSR_MSTATUSH: csr_rdata_int = '0; + + // menvcfg: machine environment configuration, all zeros for Ibex (none of the relevant + // features are implemented) + CSR_MENVCFG, CSR_MENVCFGH: csr_rdata_int = '0; + // misa CSR_MISA: csr_rdata_int = MISA_VALUE; @@ -345,7 +318,7 @@ module ibex_cs_registers #( CSR_MEPC: csr_rdata_int = mepc_q; // mcause: exception cause - CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]}; + CSR_MCAUSE: csr_rdata_int = {mcause_q[6], 25'b0, mcause_q[5:0]}; // mtval: trap value CSR_MTVAL: csr_rdata_int = mtval_q; @@ -486,11 +459,6 @@ module ibex_cs_registers #( illegal_csr = ~DbgTriggerEn; end - // Custom CSR for controlling CPU features - CSR_CPUCTRL: begin - csr_rdata_int = {{32 - $bits(cpu_ctrl_t) {1'b0}}, cpuctrl_q}; - end - // Custom CSR for LFSR re-seeding (cannot be read) CSR_SECURESEED: begin csr_rdata_int = '0; @@ -500,6 +468,16 @@ module ibex_cs_registers #( illegal_csr = 1'b1; end endcase + + if (!PMPEnable) begin + if (csr_addr inside {CSR_PMPCFG0, CSR_PMPCFG1, CSR_PMPCFG2, CSR_PMPCFG3, + CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR2, CSR_PMPADDR3, + CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, + CSR_PMPADDR8, CSR_PMPADDR9, CSR_PMPADDR10, CSR_PMPADDR11, + CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15}) begin + illegal_csr = 1'b1; + end + end end // write logic @@ -514,7 +492,7 @@ module ibex_cs_registers #( mepc_en = 1'b0; mepc_d = {csr_wdata_int[31:1], 1'b0}; mcause_en = 1'b0; - mcause_d = {csr_wdata_int[31], csr_wdata_int[4:0]}; + mcause_d = {csr_wdata_int[31], csr_wdata_int[5:0]}; mtval_en = 1'b0; mtval_d = csr_wdata_int; mtvec_en = csr_mtvec_init_i; @@ -539,11 +517,6 @@ module ibex_cs_registers #( mhpmcounter_we = '0; mhpmcounterh_we = '0; - cpuctrl_we = 1'b0; - cpuctrl_d = cpuctrl_q; - - double_fault_seen_o = 1'b0; - if (csr_we_int) begin unique case (csr_addr_i) // mstatus: IE bit @@ -641,11 +614,6 @@ module ibex_cs_registers #( mhpmcounterh_we[mhpmcounter_idx] = 1'b1; end - CSR_CPUCTRL: begin - cpuctrl_d = cpuctrl_wdata; - cpuctrl_we = 1'b1; - end - default:; endcase end @@ -661,9 +629,6 @@ module ibex_cs_registers #( csr_save_id_i: begin exception_pc = pc_id_i; end - csr_save_wb_i: begin - exception_pc = pc_wb_i; - end default:; endcase @@ -695,17 +660,6 @@ module ibex_cs_registers #( // save previous status for recoverable NMI mstack_en = 1'b1; - if (!mcause_d[5]) begin - // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC - // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - cpuctrl_we = 1'b1; - - cpuctrl_d.sync_exc_seen = 1'b1; - if (cpuctrl_q.sync_exc_seen) begin - double_fault_seen_o = 1'b1; - cpuctrl_d.double_fault_seen = 1'b1; - end - end end end // csr_save_cause_i @@ -718,10 +672,12 @@ module ibex_cs_registers #( mstatus_en = 1'b1; mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts + if (mstatus_q.mpp != PRIV_LVL_M) begin + mstatus_d.mprv = 1'b0; + end + // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - cpuctrl_we = 1'b1; - cpuctrl_d.sync_exc_seen = 1'b0; if (nmi_mode_i) begin // when returning from an NMI restore state from mstack CSR @@ -797,13 +753,12 @@ module ibex_cs_registers #( // MSTATUS localparam status_t MSTATUS_RST_VAL = '{mie: 1'b0, - mpie: 1'b1, - mpp: PRIV_LVL_U, + mpie: 1'b0, + mpp: PRIV_LVL_M, mprv: 1'b0, tw: 1'b0}; - ibex_csr #( + cve2_csr #( .Width ($bits(status_t)), - .ShadowCopy(ShadowCSR), .ResetValue({MSTATUS_RST_VAL}) ) u_mstatus_csr ( .clk_i (clk_i), @@ -811,11 +766,11 @@ module ibex_cs_registers #( .wr_data_i ({mstatus_d}), .wr_en_i (mstatus_en), .rd_data_o (mstatus_q), - .rd_error_o(mstatus_err) + .rd_error_o() ); // MEPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -833,7 +788,7 @@ module ibex_cs_registers #( assign mie_d.irq_timer = csr_wdata_int[CSR_MTIX_BIT]; assign mie_d.irq_external = csr_wdata_int[CSR_MEIX_BIT]; assign mie_d.irq_fast = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW]; - ibex_csr #( + cve2_csr #( .Width ($bits(irqs_t)), .ShadowCopy(1'b0), .ResetValue('0) @@ -847,7 +802,7 @@ module ibex_cs_registers #( ); // MSCRATCH - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -861,8 +816,8 @@ module ibex_cs_registers #( ); // MCAUSE - ibex_csr #( - .Width (6), + cve2_csr #( + .Width (7), .ShadowCopy(1'b0), .ResetValue('0) ) u_mcause_csr ( @@ -875,7 +830,7 @@ module ibex_cs_registers #( ); // MTVAL - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -889,9 +844,8 @@ module ibex_cs_registers #( ); // MTVEC - ibex_csr #( + cve2_csr #( .Width (32), - .ShadowCopy(ShadowCSR), .ResetValue(32'd1) ) u_mtvec_csr ( .clk_i (clk_i), @@ -899,7 +853,7 @@ module ibex_cs_registers #( .wr_data_i (mtvec_d), .wr_en_i (mtvec_en), .rd_data_o (mtvec_q), - .rd_error_o(mtvec_err) + .rd_error_o() ); // DCSR @@ -909,7 +863,7 @@ module ibex_cs_registers #( prv: PRIV_LVL_M, default: '0 }; - ibex_csr #( + cve2_csr #( .Width ($bits(dcsr_t)), .ShadowCopy(1'b0), .ResetValue({DCSR_RESET_VAL}) @@ -923,7 +877,7 @@ module ibex_cs_registers #( ); // DEPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -937,7 +891,7 @@ module ibex_cs_registers #( ); // DSCRATCH0 - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -951,7 +905,7 @@ module ibex_cs_registers #( ); // DSCRATCH1 - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -966,7 +920,7 @@ module ibex_cs_registers #( // MSTACK localparam status_stk_t MSTACK_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U}; - ibex_csr #( + cve2_csr #( .Width ($bits(status_stk_t)), .ShadowCopy(1'b0), .ResetValue({MSTACK_RESET_VAL}) @@ -980,7 +934,7 @@ module ibex_cs_registers #( ); // MSTACK_EPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -994,8 +948,8 @@ module ibex_cs_registers #( ); // MSTACK_CAUSE - ibex_csr #( - .Width (6), + cve2_csr #( + .Width (7), .ShadowCopy(1'b0), .ResetValue('0) ) u_mstack_cause_csr ( @@ -1013,10 +967,10 @@ module ibex_cs_registers #( if (PMPEnable) begin : g_pmp_registers // PMP reset values - `ifdef IBEX_CUSTOM_PMP_RESET_VALUES - `include "ibex_pmp_reset.svh" + `ifdef CVE2_CUSTOM_PMP_RESET_VALUES + `include "cve2_pmp_reset.svh" `else - `include "ibex_pmp_reset_default.svh" + `include "cve2_pmp_reset_default.svh" `endif pmp_mseccfg_t pmp_mseccfg_q, pmp_mseccfg_d; @@ -1102,9 +1056,8 @@ module ibex_cs_registers #( &csr_wdata_int[(i%4)*PMP_CFG_W+:2]; assign pmp_cfg_wdata[i].read = csr_wdata_int[(i%4)*PMP_CFG_W]; - ibex_csr #( + cve2_csr #( .Width ($bits(pmp_cfg_t)), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_cfg_rst[i]) ) u_pmp_cfg_csr ( .clk_i (clk_i), @@ -1131,9 +1084,8 @@ module ibex_cs_registers #( (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0])); end - ibex_csr #( + cve2_csr #( .Width (PMPAddrWidth), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_addr_rst[i][33-:PMPAddrWidth]) ) u_pmp_addr_csr ( .clk_i (clk_i), @@ -1164,9 +1116,8 @@ module ibex_cs_registers #( // MSECCFG.RLB cannot be set again assign pmp_mseccfg_d.rlb = any_pmp_entry_locked ? 1'b0 : csr_wdata_int[CSR_MSECCFG_RLB_BIT]; - ibex_csr #( + cve2_csr #( .Width ($bits(pmp_mseccfg_t)), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_mseccfg_rst) ) u_pmp_mseccfg ( .clk_i (clk_i), @@ -1177,7 +1128,6 @@ module ibex_cs_registers #( .rd_error_o(pmp_mseccfg_err) ); - assign pmp_csr_err = (|pmp_cfg_err) | (|pmp_addr_err) | pmp_mseccfg_err; assign pmp_mseccfg = pmp_mseccfg_q; end else begin : g_no_pmp_tieoffs @@ -1190,7 +1140,6 @@ module ibex_cs_registers #( assign csr_pmp_cfg_o[i] = pmp_cfg_t'(1'b0); assign csr_pmp_addr_o[i] = '0; end - assign pmp_csr_err = 1'b0; assign pmp_mseccfg = '0; end @@ -1219,7 +1168,7 @@ module ibex_cs_registers #( end // When adding or altering performance counter meanings and default - // mappings please update dv/verilator/pcount/cpp/ibex_pcounts.cc + // mappings please update dv/verilator/pcount/cpp/cve2_pcounts.cc // appropriately. // // active counters @@ -1234,7 +1183,7 @@ module ibex_cs_registers #( mhpmcounter_incr[8] = branch_i; // num of branches (conditional) mhpmcounter_incr[9] = branch_taken_i; // num of taken branches (conditional) mhpmcounter_incr[10] = instr_ret_compressed_i; // num of compressed instr - mhpmcounter_incr[11] = mul_wait_i; // cycles waiting for multiply + mhpmcounter_incr[11] = wfi_wait_i; // cycles waiting for multiply mhpmcounter_incr[12] = div_wait_i; // cycles waiting for divide end @@ -1255,7 +1204,7 @@ module ibex_cs_registers #( end // mcycle - ibex_counter #( + cve2_counter #( .CounterWidth(64) ) mcycle_counter_i ( .clk_i(clk_i), @@ -1270,7 +1219,7 @@ module ibex_cs_registers #( // minstret - ibex_counter #( + cve2_counter #( .CounterWidth(64), .ProvideValUpd(1) ) minstret_counter_i ( @@ -1281,7 +1230,7 @@ module ibex_cs_registers #( .counter_we_i(mhpmcounter_we[2]), .counter_val_i(csr_wdata_int), .counter_val_o(minstret_raw), - .counter_val_upd_o(minstret_next) + .counter_val_upd_o() ); // Where the writeback stage is present instruction in ID observing value of minstret must take @@ -1291,7 +1240,7 @@ module ibex_cs_registers #( // so the incorrect value doesn't matter. A similar behaviour is required for the compressed // instruction retired counter below. When the writeback stage isn't present the speculative // signals are always 0. - assign mhpmcounter[2] = instr_ret_spec_i & ~mcountinhibit[2] ? minstret_next : minstret_raw; + assign mhpmcounter[2] = minstret_raw; // reserved: assign mhpmcounter[1] = '0; @@ -1306,7 +1255,7 @@ module ibex_cs_registers #( if (i < MHPMCounterNum) begin : gen_imp logic [63:0] mhpmcounter_raw, mhpmcounter_next; - ibex_counter #( + cve2_counter #( .CounterWidth(MHPMCounterWidth), .ProvideValUpd(Cnt == 10) ) mcounters_variable_i ( @@ -1324,7 +1273,6 @@ module ibex_cs_registers #( // Special behaviour for reading compressed instruction retired counter, see comment on // `mhpmcounter[2]` above for further information. assign mhpmcounter[Cnt] = - instr_ret_compressed_spec_i & ~mcountinhibit[Cnt] ? mhpmcounter_next: mhpmcounter_raw; end else begin : gen_other_cnts logic [63:0] unused_mhpmcounter_next; @@ -1334,11 +1282,6 @@ module ibex_cs_registers #( end end else begin : gen_unimp assign mhpmcounter[Cnt] = '0; - - if (Cnt == 10) begin : gen_no_compressed_instr_cnt - logic unused_instr_ret_compressed_spec_i; - assign unused_instr_ret_compressed_spec_i = instr_ret_compressed_spec_i; - end end end @@ -1407,7 +1350,7 @@ module ibex_cs_registers #( assign tmatch_value_d = csr_wdata_int[31:0]; // Registers - ibex_csr #( + cve2_csr #( .Width (DbgHwNumLen), .ShadowCopy(1'b0), .ResetValue('0) @@ -1421,7 +1364,7 @@ module ibex_cs_registers #( ); for (genvar i = 0; i < DbgHwBreakNum; i++) begin : g_dbg_tmatch_reg - ibex_csr #( + cve2_csr #( .Width (1), .ShadowCopy(1'b0), .ResetValue('0) @@ -1434,7 +1377,7 @@ module ibex_cs_registers #( .rd_error_o() ); - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -1501,88 +1444,12 @@ module ibex_cs_registers #( // CPU control register // ////////////////////////// - // Cast register write data - assign cpuctrl_wdata_raw = cpu_ctrl_t'(csr_wdata_int[$bits(cpu_ctrl_t)-1:0]); - - // Generate fixed time execution bit - if (DataIndTiming) begin : gen_dit - // SEC_CM: CORE.DATA_REG_SW.SCA - assign cpuctrl_wdata.data_ind_timing = cpuctrl_wdata_raw.data_ind_timing; - - end else begin : gen_no_dit - // tieoff for the unused bit - logic unused_dit; - assign unused_dit = cpuctrl_wdata_raw.data_ind_timing; - - // field will always read as zero if not configured - assign cpuctrl_wdata.data_ind_timing = 1'b0; - end - - assign data_ind_timing_o = cpuctrl_q.data_ind_timing; - - // Generate dummy instruction signals - if (DummyInstructions) begin : gen_dummy - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - assign cpuctrl_wdata.dummy_instr_en = cpuctrl_wdata_raw.dummy_instr_en; - assign cpuctrl_wdata.dummy_instr_mask = cpuctrl_wdata_raw.dummy_instr_mask; - - // Signal a write to the seed register - assign dummy_instr_seed_en_o = csr_we_int && (csr_addr == CSR_SECURESEED); - assign dummy_instr_seed_o = csr_wdata_int; - - end else begin : gen_no_dummy - // tieoff for the unused bit - logic unused_dummy_en; - logic [2:0] unused_dummy_mask; - assign unused_dummy_en = cpuctrl_wdata_raw.dummy_instr_en; - assign unused_dummy_mask = cpuctrl_wdata_raw.dummy_instr_mask; - - // field will always read as zero if not configured - assign cpuctrl_wdata.dummy_instr_en = 1'b0; - assign cpuctrl_wdata.dummy_instr_mask = 3'b000; - assign dummy_instr_seed_en_o = 1'b0; - assign dummy_instr_seed_o = '0; - end - - assign dummy_instr_en_o = cpuctrl_q.dummy_instr_en; - assign dummy_instr_mask_o = cpuctrl_q.dummy_instr_mask; - - // Generate icache enable bit - if (ICache) begin : gen_icache_enable - assign cpuctrl_wdata.icache_enable = cpuctrl_wdata_raw.icache_enable; - end else begin : gen_no_icache - // tieoff for the unused icen bit - logic unused_icen; - assign unused_icen = cpuctrl_wdata_raw.icache_enable; - - // icen field will always read as zero if ICache not configured - assign cpuctrl_wdata.icache_enable = 1'b0; - end - - assign cpuctrl_wdata.double_fault_seen = cpuctrl_wdata_raw.double_fault_seen; - assign cpuctrl_wdata.sync_exc_seen = cpuctrl_wdata_raw.sync_exc_seen; - - assign icache_enable_o = cpuctrl_q.icache_enable; - - ibex_csr #( - .Width ($bits(cpu_ctrl_t)), - .ShadowCopy(ShadowCSR), - .ResetValue('0) - ) u_cpuctrl_csr ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .wr_data_i ({cpuctrl_d}), - .wr_en_i (cpuctrl_we), - .rd_data_o (cpuctrl_q), - .rd_error_o(cpuctrl_err) - ); - - assign csr_shadow_err_o = mstatus_err | mtvec_err | pmp_csr_err | cpuctrl_err; + // Removed //////////////// // Assertions // //////////////// - `ASSERT(IbexCsrOpEnRequiresAccess, csr_op_en_i |-> csr_access_i) + `ASSERT(CVE2CsrOpEnRequiresAccess, csr_op_en_i |-> csr_access_i) endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv similarity index 98% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv index 309a325f..b464bcce 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv @@ -8,7 +8,7 @@ `include "prim_assert.sv" -module ibex_csr #( +module cve2_csr #( parameter int unsigned Width = 32, parameter bit ShadowCopy = 1'b0, parameter bit [Width-1:0] ResetValue = '0 diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv similarity index 94% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv index 4b019593..5b9cbca1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv @@ -13,11 +13,10 @@ `include "prim_assert.sv" -module ibex_decoder #( +module cve2_decoder #( parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit BranchTargetALU = 0 + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, @@ -31,8 +30,6 @@ module ibex_decoder #( output logic ecall_insn_o, // syscall instr encountered output logic wfi_insn_o, // wait for interrupt instr encountered output logic jump_set_o, // jump taken set signal - input logic branch_taken_i, // registered branch decision - output logic icache_inval_o, // from IF-ID pipeline register input logic instr_first_cycle_i, // instruction read is in its first cycle @@ -43,10 +40,8 @@ module ibex_decoder #( input logic illegal_c_insn_i, // compressed instruction decode failed // immediates - output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a - output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b - output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a - output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b + output cve2_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a + output cve2_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b output logic [31:0] imm_i_type_o, output logic [31:0] imm_s_type_o, output logic [31:0] imm_b_type_o, @@ -55,7 +50,7 @@ module ibex_decoder #( output logic [31:0] zimm_rs1_type_o, // register file - output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection + output cve2_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection output logic rf_we_o, // write enable for regfile output logic [4:0] rf_raddr_a_o, output logic [4:0] rf_raddr_b_o, @@ -64,10 +59,10 @@ module ibex_decoder #( output logic rf_ren_b_o, // Instruction reads from RF addr B // ALU - output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection - output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC, + output cve2_pkg::alu_op_e alu_operator_o, // ALU operation selection + output cve2_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC, // immediate or zero - output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or + output cve2_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or // immediate output logic alu_multicycle_o, // ternary bitmanip instruction @@ -77,12 +72,12 @@ module ibex_decoder #( output logic mult_sel_o, // as above but static, for data muxes output logic div_sel_o, // as above but static, for data muxes - output ibex_pkg::md_op_e multdiv_operator_o, + output cve2_pkg::md_op_e multdiv_operator_o, output logic [1:0] multdiv_signed_mode_o, // CSRs output logic csr_access_o, // access to CSR - output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR + output cve2_pkg::csr_op_e csr_op_o, // operation to perform on CSR // LSU output logic data_req_o, // start transaction to data memory @@ -97,7 +92,7 @@ module ibex_decoder #( output logic branch_in_dec_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic illegal_insn; logic illegal_reg_rv32e; @@ -206,7 +201,6 @@ module ibex_decoder #( jump_in_dec_o = 1'b0; jump_set_o = 1'b0; branch_in_dec_o = 1'b0; - icache_inval_o = 1'b0; multdiv_operator_o = MD_OP_MULL; multdiv_signed_mode_o = 2'b00; @@ -244,8 +238,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) - rf_we = BranchTargetALU; + // Calculate jump target (and store PC) + rf_we = 1'b0; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -257,8 +251,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) - rf_we = BranchTargetALU; + // Calculate jump target (and store PC) + rf_we = 1'b0; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -572,14 +566,12 @@ module ibex_decoder #( // FENCE.I is implemented as a jump to the next PC, this gives the required flushing // behaviour (iside prefetch buffer flushed and response to any outstanding iside // requests will be ignored). - // If present, the ICache will also be flushed. jump_in_dec_o = 1'b1; rf_we = 1'b0; if (instr_first_cycle_i) begin jump_set_o = 1'b1; - icache_inval_o = 1'b1; end end default: begin @@ -676,10 +668,6 @@ module ibex_decoder #( imm_a_mux_sel_o = IMM_A_ZERO; imm_b_mux_sel_o = IMM_B_I; - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_I; - - opcode_alu = opcode_e'(instr_alu[6:0]); use_rs3_d = 1'b0; @@ -694,13 +682,8 @@ module ibex_decoder #( /////////// OPCODE_JAL: begin // Jump and Link - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_J; - end - // Jumps take two cycles without the BTALU - if (instr_first_cycle_i && !BranchTargetALU) begin + if (instr_first_cycle_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; @@ -716,13 +699,8 @@ module ibex_decoder #( end OPCODE_JALR: begin // Jump and Link Register - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_REG_A; - bt_b_mux_sel_o = IMM_B_I; - end - // Jumps take two cycles without the BTALU - if (instr_first_cycle_i && !BranchTargetALU) begin + if (instr_first_cycle_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_IMM; @@ -749,24 +727,18 @@ module ibex_decoder #( default: ; endcase - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - // Not-taken branch will jump to next instruction (used in secure mode) - bt_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC; - end - // Without branch target ALU, a branch is a two-stage operation using the Main ALU in both // stages if (instr_first_cycle_i) begin // First evaluate the branch condition alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_REG_B; - end else if (!BranchTargetALU) begin + end else begin // Then calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; // Not-taken branch will jump to next instruction (used in secure mode) - imm_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC; + imm_b_mux_sel_o = IMM_B_B; alu_operator_o = ALU_ADD; end end @@ -1147,15 +1119,10 @@ module ibex_decoder #( end 3'b001: begin // FENCE.I will flush the IF stage, prefetch buffer and ICache if present. - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_INCR_PC; - end else begin alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMM_B_INCR_PC; alu_operator_o = ALU_ADD; - end end default: ; endcase diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv similarity index 80% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv index ee900164..98713a3d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv @@ -8,27 +8,21 @@ * * Execution block: Hosts ALU and MUL/DIV unit */ -module ibex_ex_block #( - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit BranchTargetALU = 0 +module cve2_ex_block #( + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, // ALU - input ibex_pkg::alu_op_e alu_operator_i, + input cve2_pkg::alu_op_e alu_operator_i, input logic [31:0] alu_operand_a_i, input logic [31:0] alu_operand_b_i, input logic alu_instr_first_cycle_i, - // Branch Target ALU - // All of these signals are unusued when BranchTargetALU == 0 - input logic [31:0] bt_a_operand_i, - input logic [31:0] bt_b_operand_i, - // Multiplier/Divider - input ibex_pkg::md_op_e multdiv_operator_i, + input cve2_pkg::md_op_e multdiv_operator_i, input logic mult_en_i, // dynamic enable signal, for FSM control input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes @@ -36,8 +30,6 @@ module ibex_ex_block #( input logic [1:0] multdiv_signed_mode_i, input logic [31:0] multdiv_operand_a_i, input logic [31:0] multdiv_operand_b_i, - input logic multdiv_ready_id_i, - input logic data_ind_timing_i, // intermediate val reg output logic [1:0] imd_val_we_o, @@ -53,7 +45,7 @@ module ibex_ex_block #( output logic ex_valid_o // EX has valid output ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] alu_result, multdiv_result; @@ -91,29 +83,16 @@ module ibex_ex_block #( // branch handling assign branch_decision_o = alu_cmp_result; - if (BranchTargetALU) begin : g_branch_target_alu - logic [32:0] bt_alu_result; - logic unused_bt_carry; - - assign bt_alu_result = bt_a_operand_i + bt_b_operand_i; - - assign unused_bt_carry = bt_alu_result[32]; - assign branch_target_o = bt_alu_result[31:0]; - end else begin : g_no_branch_target_alu - // Unused bt_operand signals cause lint errors, this avoids them - logic [31:0] unused_bt_a_operand, unused_bt_b_operand; + // Unused bt_operand signals cause lint errors, this avoids them + //logic [31:0] unused_bt_a_operand, unused_bt_b_operand; - assign unused_bt_a_operand = bt_a_operand_i; - assign unused_bt_b_operand = bt_b_operand_i; - - assign branch_target_o = alu_adder_result_ex_o; - end + assign branch_target_o = alu_adder_result_ex_o; ///////// // ALU // ///////// - ibex_alu #( + cve2_alu #( .RV32B(RV32B) ) alu_i ( .operator_i (alu_operator_i), @@ -138,7 +117,7 @@ module ibex_ex_block #( //////////////// if (RV32M == RV32MSlow) begin : gen_multdiv_slow - ibex_multdiv_slow multdiv_i ( + cve2_multdiv_slow multdiv_i ( .clk_i (clk_i), .rst_ni (rst_ni), .mult_en_i (mult_en_i), @@ -152,18 +131,17 @@ module ibex_ex_block #( .alu_adder_ext_i (alu_adder_result_ext), .alu_adder_i (alu_adder_result_ex_o), .equal_to_zero_i (alu_is_equal_result), - .data_ind_timing_i (data_ind_timing_i), .valid_o (multdiv_valid), .alu_operand_a_o (multdiv_alu_operand_a), .alu_operand_b_o (multdiv_alu_operand_b), .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), - .multdiv_ready_id_i(multdiv_ready_id_i), + .multdiv_ready_id_i(1'b1), .multdiv_result_o (multdiv_result) ); end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast - ibex_multdiv_fast #( + cve2_multdiv_fast #( .RV32M(RV32M) ) multdiv_i ( .clk_i (clk_i), @@ -181,11 +159,9 @@ module ibex_ex_block #( .alu_adder_ext_i (alu_adder_result_ext), .alu_adder_i (alu_adder_result_ex_o), .equal_to_zero_i (alu_is_equal_result), - .data_ind_timing_i (data_ind_timing_i), .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), - .multdiv_ready_id_i(multdiv_ready_id_i), .valid_o (multdiv_valid), .multdiv_result_o (multdiv_result) ); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv similarity index 92% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv index 61179ed0..20b2b62b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv @@ -12,9 +12,8 @@ `include "prim_assert.sv" -module ibex_fetch_fifo #( - parameter int unsigned NUM_REQS = 2, - parameter bit ResetAll = 1'b0 +module cve2_fetch_fifo #( + parameter int unsigned NUM_REQS = 2 ) ( input logic clk_i, input logic rst_ni, @@ -149,19 +148,11 @@ module ibex_fetch_fifo #( assign instr_addr_d = clear_i ? in_addr_i[31:1] : instr_addr_next; - if (ResetAll) begin : g_instr_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_addr_q <= '0; - end else if (instr_addr_en) begin - instr_addr_q <= instr_addr_d; - end - end - end else begin : g_instr_addr_nr - always_ff @(posedge clk_i) begin - if (instr_addr_en) begin - instr_addr_q <= instr_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_addr_q <= '0; + end else if (instr_addr_en) begin + instr_addr_q <= instr_addr_d; end end @@ -234,7 +225,7 @@ module ibex_fetch_fifo #( end for (genvar i = 0; i < DEPTH; i++) begin : g_fifo_regs - if (ResetAll) begin : g_rdata_ra + begin : g_rdata always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rdata_q[i] <= '0; @@ -244,13 +235,6 @@ module ibex_fetch_fifo #( err_q[i] <= err_d[i]; end end - end else begin : g_rdata_nr - always_ff @(posedge clk_i) begin - if (entry_en[i]) begin - rdata_q[i] <= rdata_d[i]; - err_q[i] <= err_d[i]; - end - end end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv similarity index 60% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv index 1644d072..e989ff29 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv @@ -15,20 +15,17 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_id_stage #( +module cve2_id_stage #( parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit DataIndTiming = 1'b0, - parameter bit BranchTargetALU = 0, - parameter bit WritebackStage = 0, - parameter bit BranchPredictor = 0 + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, + input logic fetch_enable_i, output logic ctrl_busy_o, output logic illegal_insn_o, @@ -38,23 +35,19 @@ module ibex_id_stage #( input logic [31:0] instr_rdata_alu_i, // from IF-ID pipeline registers input logic [15:0] instr_rdata_c_i, // from IF-ID pipeline registers input logic instr_is_compressed_i, - input logic instr_bp_taken_i, output logic instr_req_o, output logic instr_first_cycle_id_o, output logic instr_valid_clear_o, // kill instr in IF-ID reg output logic id_in_ready_o, // ID stage is ready for next instr - output logic icache_inval_o, // Jumps and branches input logic branch_decision_i, // IF and ID stage signals output logic pc_set_o, - output ibex_pkg::pc_sel_e pc_mux_o, - output logic nt_branch_mispredict_o, - output logic [31:0] nt_branch_addr_o, - output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, - output ibex_pkg::exc_cause_e exc_cause_o, + output cve2_pkg::pc_sel_e pc_mux_o, + output cve2_pkg::exc_pc_sel_e exc_pc_mux_o, + output cve2_pkg::exc_cause_e exc_cause_o, input logic illegal_c_insn_i, input logic instr_fetch_err_i, @@ -66,7 +59,7 @@ module ibex_id_stage #( input logic ex_valid_i, // EX stage has valid output input logic lsu_resp_valid_i, // LSU has valid output, or is done // ALU - output ibex_pkg::alu_op_e alu_operator_ex_o, + output cve2_pkg::alu_op_e alu_operator_ex_o, output logic [31:0] alu_operand_a_ex_o, output logic [31:0] alu_operand_b_ex_o, @@ -75,36 +68,29 @@ module ibex_id_stage #( input logic [33:0] imd_val_d_ex_i[2], output logic [33:0] imd_val_q_ex_o[2], - // Branch target ALU - output logic [31:0] bt_a_operand_o, - output logic [31:0] bt_b_operand_o, - // MUL, DIV output logic mult_en_ex_o, output logic div_en_ex_o, output logic mult_sel_ex_o, output logic div_sel_ex_o, - output ibex_pkg::md_op_e multdiv_operator_ex_o, + output cve2_pkg::md_op_e multdiv_operator_ex_o, output logic [1:0] multdiv_signed_mode_ex_o, output logic [31:0] multdiv_operand_a_ex_o, output logic [31:0] multdiv_operand_b_ex_o, - output logic multdiv_ready_id_o, // CSR output logic csr_access_o, - output ibex_pkg::csr_op_e csr_op_o, + output cve2_pkg::csr_op_e csr_op_o, output logic csr_op_en_o, output logic csr_save_if_o, output logic csr_save_id_o, - output logic csr_save_wb_o, output logic csr_restore_mret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, - input ibex_pkg::priv_lvl_e priv_mode_i, + input cve2_pkg::priv_lvl_e priv_mode_i, input logic csr_mstatus_tw_i, input logic illegal_csr_insn_i, - input logic data_ind_timing_i, // Interface to load store unit output logic lsu_req_o, @@ -113,18 +99,13 @@ module ibex_id_stage #( output logic lsu_sign_ext_o, output logic [31:0] lsu_wdata_o, - input logic lsu_req_done_i, // Data req to LSU is complete and - // instruction can move to writeback - // (only relevant where writeback stage is - // present) - input logic lsu_addr_incr_req_i, input logic [31:0] lsu_addr_last_i, // Interrupt signals input logic csr_mstatus_mie_i, input logic irq_pending_i, - input ibex_pkg::irqs_t irqs_i, + input cve2_pkg::irqs_t irqs_i, input logic irq_nm_i, output logic nmi_mode_o, @@ -133,7 +114,7 @@ module ibex_id_stage #( // Debug Signal output logic debug_mode_o, - output ibex_pkg::dbg_cause_e debug_cause_o, + output cve2_pkg::dbg_cause_e debug_cause_o, output logic debug_csr_save_o, input logic debug_req_i, input logic debug_single_step_i, @@ -141,9 +122,6 @@ module ibex_id_stage #( input logic debug_ebreaku_i, input logic trigger_match_i, - // Wakeup Signal - output logic wake_from_sleep_o, - // Write back signal input logic [31:0] result_ex_i, input logic [31:0] csr_rdata_i, @@ -160,20 +138,9 @@ module ibex_id_stage #( output logic [4:0] rf_waddr_id_o, output logic [31:0] rf_wdata_id_o, output logic rf_we_id_o, - output logic rf_rd_a_wb_match_o, - output logic rf_rd_b_wb_match_o, - - // Register write information from writeback (for resolving data hazards) - input logic [4:0] rf_waddr_wb_i, - input logic [31:0] rf_wdata_fwd_wb_i, - input logic rf_write_wb_i, output logic en_wb_o, - output ibex_pkg::wb_instr_type_e instr_type_wb_o, output logic instr_perf_count_id_o, - input logic ready_wb_i, - input logic outstanding_load_wb_i, - input logic outstanding_store_wb_i, // Performance Counters output logic perf_jump_o, // executing a jump instr @@ -181,12 +148,12 @@ module ibex_id_stage #( output logic perf_tbranch_o, // executing a taken branch instr output logic perf_dside_wait_o, // instruction in ID/EX is awaiting memory // access to finish before proceeding - output logic perf_mul_wait_o, + output logic perf_wfi_wait_o, output logic perf_div_wait_o, output logic instr_id_done_o ); - import ibex_pkg::*; + import cve2_pkg::*; // Decoder/Controller, ID stage internal signals logic illegal_insn_dec; @@ -196,14 +163,9 @@ module ibex_id_stage #( logic ecall_insn_dec; logic wfi_insn_dec; - logic wb_exception; - logic id_exception; - logic branch_in_dec; logic branch_set, branch_set_raw, branch_set_raw_d; logic branch_jump_set_done_q, branch_jump_set_done_d; - logic branch_not_set; - logic branch_taken; logic jump_in_dec; logic jump_set_dec; logic jump_set, jump_set_raw; @@ -213,13 +175,11 @@ module ibex_id_stage #( logic instr_executing; logic instr_done; logic controller_run; - logic stall_ld_hz; logic stall_mem; logic stall_multdiv; logic stall_branch; logic stall_jump; logic stall_id; - logic stall_wb; logic flush_id; logic multicycle_done; @@ -260,9 +220,6 @@ module ibex_id_stage #( logic [33:0] imd_val_q[2]; - op_a_sel_e bt_a_mux_sel; - imm_b_sel_e bt_b_mux_sel; - imm_a_sel_e imm_a_mux_sel; imm_b_sel_e imm_b_mux_sel, imm_b_mux_sel_dec; @@ -313,75 +270,30 @@ module ibex_id_stage #( endcase end - if (BranchTargetALU) begin : g_btalu_muxes - // Branch target ALU operand A mux - always_comb begin : bt_operand_a_mux - unique case (bt_a_mux_sel) - OP_A_REG_A: bt_a_operand_o = rf_rdata_a_fwd; - OP_A_CURRPC: bt_a_operand_o = pc_id_i; - default: bt_a_operand_o = pc_id_i; - endcase - end - - // Branch target ALU operand B mux - always_comb begin : bt_immediate_b_mux - unique case (bt_b_mux_sel) - IMM_B_I: bt_b_operand_o = imm_i_type; - IMM_B_B: bt_b_operand_o = imm_b_type; - IMM_B_J: bt_b_operand_o = imm_j_type; - IMM_B_INCR_PC: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; - default: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; - endcase - end - - // Reduced main ALU immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase - end - `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { - IMM_B_I, - IMM_B_S, - IMM_B_U, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) - end else begin : g_nobtalu - op_a_sel_e unused_a_mux_sel; - imm_b_sel_e unused_b_mux_sel; - - assign unused_a_mux_sel = bt_a_mux_sel; - assign unused_b_mux_sel = bt_b_mux_sel; - assign bt_a_operand_o = '0; - assign bt_b_operand_o = '0; - - // Full main ALU immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_B: imm_b = imm_b_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_J: imm_b = imm_j_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase - end - `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { - IMM_B_I, - IMM_B_S, - IMM_B_B, - IMM_B_U, - IMM_B_J, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) + op_a_sel_e unused_a_mux_sel; + imm_b_sel_e unused_b_mux_sel; + + // Full main ALU immediate MUX for Operand B + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMM_B_I: imm_b = imm_i_type; + IMM_B_S: imm_b = imm_s_type; + IMM_B_B: imm_b = imm_b_type; + IMM_B_U: imm_b = imm_u_type; + IMM_B_J: imm_b = imm_j_type; + IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; + IMM_B_INCR_ADDR: imm_b = 32'h4; + default: imm_b = 32'h4; + endcase end + `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { + IMM_B_I, + IMM_B_S, + IMM_B_B, + IMM_B_U, + IMM_B_J, + IMM_B_INCR_PC, + IMM_B_INCR_ADDR}) // ALU MUX for Operand B assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : rf_rdata_b_fwd; @@ -422,11 +334,10 @@ module ibex_id_stage #( // Decoder // ///////////// - ibex_decoder #( + cve2_decoder #( .RV32E (RV32E), .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU) + .RV32B (RV32B) ) decoder_i ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -439,8 +350,6 @@ module ibex_id_stage #( .ecall_insn_o (ecall_insn_dec), .wfi_insn_o (wfi_insn_dec), .jump_set_o (jump_set_dec), - .branch_taken_i(branch_taken), - .icache_inval_o(icache_inval_o), // from IF-ID pipeline register .instr_first_cycle_i(instr_first_cycle), @@ -451,8 +360,6 @@ module ibex_id_stage #( // immediates .imm_a_mux_sel_o(imm_a_mux_sel), .imm_b_mux_sel_o(imm_b_mux_sel_dec), - .bt_a_mux_sel_o (bt_a_mux_sel), - .bt_b_mux_sel_o (bt_b_mux_sel), .imm_i_type_o (imm_i_type), .imm_s_type_o (imm_s_type), @@ -501,7 +408,7 @@ module ibex_id_stage #( ); ///////////////////////////////// - // CSR-related pipline flushes // + // CSR-related pipeline flushes // ///////////////////////////////// always_comb begin : csr_pipeline_flushes csr_pipe_flush = 1'b0; @@ -510,10 +417,15 @@ module ibex_id_stage #( // - When enabling interrupts, pending IRQs become visible to the controller only during // the next cycle. If during that cycle the core disables interrupts again, it does not // see any pending IRQs and consequently does not start to handle interrupts. + // - When modifying any PMP CSR, PMP check of the next instruction might get invalidated. + // Hence, a pipeline flush is needed to instantiate another PMP check with the updated CSRs. // - When modifying debug CSRs - TODO: Check if this is really needed if (csr_op_en_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin - if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS || - csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE) begin + if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS || + csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE || + csr_num_e'(instr_rdata_i[31:20]) == CSR_MSECCFG || + // To catch all PMPCFG/PMPADDR registers, get the shared top most 7 bits. + instr_rdata_i[31:25] == 7'h1D) begin csr_pipe_flush = 1'b1; end end else if (csr_op_en_o == 1'b1 && csr_op_o != CSR_OP_READ) begin @@ -532,13 +444,12 @@ module ibex_id_stage #( assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i); - ibex_controller #( - .WritebackStage (WritebackStage), - .BranchPredictor(BranchPredictor) + cve2_controller #( ) controller_i ( .clk_i (clk_i), .rst_ni(rst_ni), + .fetch_enable_i(fetch_enable_i), .ctrl_busy_o(ctrl_busy_o), // decoder related signals @@ -555,7 +466,6 @@ module ibex_id_stage #( .instr_i (instr_rdata_i), .instr_compressed_i (instr_rdata_c_i), .instr_is_compressed_i (instr_is_compressed_i), - .instr_bp_taken_i (instr_bp_taken_i), .instr_fetch_err_i (instr_fetch_err_i), .instr_fetch_err_plus2_i(instr_fetch_err_plus2_i), .pc_id_i (pc_id_i), @@ -569,7 +479,6 @@ module ibex_id_stage #( .instr_req_o (instr_req_o), .pc_set_o (pc_set_o), .pc_mux_o (pc_mux_o), - .nt_branch_mispredict_o(nt_branch_mispredict_o), .exc_pc_mux_o (exc_pc_mux_o), .exc_cause_o (exc_cause_o), @@ -577,12 +486,8 @@ module ibex_id_stage #( .lsu_addr_last_i(lsu_addr_last_i), .load_err_i (lsu_load_err_i), .store_err_i (lsu_store_err_i), - .wb_exception_o (wb_exception), - .id_exception_o (id_exception), - // jump/branch control .branch_set_i (branch_set), - .branch_not_set_i (branch_not_set), .jump_set_i (jump_set), // interrupt signals @@ -595,7 +500,6 @@ module ibex_id_stage #( // CSR Controller Signals .csr_save_if_o (csr_save_if_o), .csr_save_id_o (csr_save_id_o), - .csr_save_wb_o (csr_save_wb_o), .csr_restore_mret_id_o(csr_restore_mret_id_o), .csr_restore_dret_id_o(csr_restore_dret_id_o), .csr_save_cause_o (csr_save_cause_o), @@ -613,13 +517,8 @@ module ibex_id_stage #( .debug_ebreaku_i (debug_ebreaku_i), .trigger_match_i (trigger_match_i), - // Wakeup Signal - .wake_from_sleep_o(wake_from_sleep_o), - .stall_id_i(stall_id), - .stall_wb_i(stall_wb), .flush_id_o(flush_id), - .ready_wb_i(ready_wb_i), // Performance Counters .perf_jump_o (perf_jump_o), @@ -659,31 +558,24 @@ module ibex_id_stage #( // Branch set control // //////////////////////// - if (BranchTargetALU && !DataIndTiming) begin : g_branch_set_direct - // Branch set fed straight to controller with branch target ALU - // (condition pass/fail used same cycle as generated instruction request) - assign branch_set_raw = branch_set_raw_d; - end else begin : g_branch_set_flop - // SEC_CM: CORE.DATA_REG_SW.SCA - // Branch set flopped without branch target ALU, or in fixed time execution mode - // (condition pass/fail used next cycle where branch target is calculated) - logic branch_set_raw_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - branch_set_raw_q <= 1'b0; - end else begin - branch_set_raw_q <= branch_set_raw_d; - end + // SEC_CM: CORE.DATA_REG_SW.SCA + // Branch set flopped without branch target ALU, or in fixed time execution mode + // (condition pass/fail used next cycle where branch target is calculated) + logic branch_set_raw_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + branch_set_raw_q <= 1'b0; + end else begin + branch_set_raw_q <= branch_set_raw_d; end + end - // Branches always take two cycles in fixed time execution mode, with or without the branch - // target ALU (to avoid a path from the branch decision into the branch target ALU operand - // muxing). - assign branch_set_raw = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d : - branch_set_raw_q; + // Branches always take two cycles in fixed time execution mode, with or without the branch + // target ALU (to avoid a path from the branch decision into the branch target ALU operand + // muxing). + assign branch_set_raw = branch_set_raw_q; - end // Track whether the current instruction in ID/EX has done a branch or jump set. assign branch_jump_set_done_d = (branch_set_raw | jump_set_raw | branch_jump_set_done_q) & @@ -707,46 +599,6 @@ module ibex_id_stage #( assign jump_set = jump_set_raw & ~branch_jump_set_done_q; assign branch_set = branch_set_raw & ~branch_jump_set_done_q; - // Branch condition is calculated in the first cycle and flopped for use in the second cycle - // (only used in fixed time execution mode to determine branch destination). - if (DataIndTiming) begin : g_sec_branch_taken - // SEC_CM: CORE.DATA_REG_SW.SCA - logic branch_taken_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - branch_taken_q <= 1'b0; - end else begin - branch_taken_q <= branch_decision_i; - end - end - - assign branch_taken = ~data_ind_timing_i | branch_taken_q; - - end else begin : g_nosec_branch_taken - - // Signal unused without fixed time execution mode - only taken branches will trigger - // branch_set_raw - assign branch_taken = 1'b1; - - end - - // Holding branch_set/jump_set high for more than one cycle should not cause a functional issue. - // However it could generate needless prefetch buffer flushes and instruction fetches. The ID/EX - // designs ensures that this never happens for non-predicted branches. - `ASSERT(NeverDoubleBranch, branch_set & ~instr_bp_taken_i |=> ~branch_set) - `ASSERT(NeverDoubleJump, jump_set & ~instr_bp_taken_i |=> ~jump_set) - - ////////////////////////////// - // Branch not-taken address // - ////////////////////////////// - - if (BranchPredictor) begin : g_calc_nt_addr - assign nt_branch_addr_o = pc_id_i + (instr_is_compressed_i ? 32'd2 : 32'd4); - end else begin : g_n_calc_nt_addr - assign nt_branch_addr_o = 32'd0; - end - /////////////// // ID-EX FSM // /////////////// @@ -775,7 +627,6 @@ module ibex_id_stage #( stall_branch = 1'b0; stall_alu = 1'b0; branch_set_raw_d = 1'b0; - branch_not_set = 1'b0; jump_set_raw = 1'b0; perf_branch_o = 1'b0; @@ -784,13 +635,9 @@ module ibex_id_stage #( FIRST_CYCLE: begin unique case (1'b1) lsu_req_dec: begin - if (!WritebackStage) begin + begin // LSU operation id_fsm_d = MULTI_CYCLE; - end else begin - if(~lsu_req_done_i) begin - id_fsm_d = MULTI_CYCLE; - end end end multdiv_en_dec: begin @@ -808,22 +655,17 @@ module ibex_id_stage #( // All branches take two cycles in fixed time execution mode, regardless of branch // condition. // SEC_CM: CORE.DATA_REG_SW.SCA - id_fsm_d = (data_ind_timing_i || (!BranchTargetALU && branch_decision_i)) ? + id_fsm_d = (branch_decision_i) ? MULTI_CYCLE : FIRST_CYCLE; - stall_branch = (~BranchTargetALU & branch_decision_i) | data_ind_timing_i; - branch_set_raw_d = (branch_decision_i | data_ind_timing_i); - - if (BranchPredictor) begin - branch_not_set = ~branch_decision_i; - end + stall_branch = branch_decision_i; + branch_set_raw_d = branch_decision_i; perf_branch_o = 1'b1; end jump_in_dec: begin // uncond branch operation - // BTALU means jumps only need one cycle - id_fsm_d = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE; - stall_jump = ~BranchTargetALU; + id_fsm_d = MULTI_CYCLE; + stall_jump = 1'b1; jump_set_raw = jump_set_dec; end alu_multicycle_dec: begin @@ -842,7 +684,7 @@ module ibex_id_stage #( rf_we_raw = rf_we_dec & ex_valid_i; end - if (multicycle_done & ready_wb_i) begin + if (multicycle_done) begin id_fsm_d = FIRST_CYCLE; end else begin stall_multdiv = multdiv_en_dec; @@ -858,22 +700,19 @@ module ibex_id_stage #( end end - // Note for the two-stage configuration ready_wb_i is always set - assign multdiv_ready_id_o = ready_wb_i; - `ASSERT(StallIDIfMulticycle, (id_fsm_q == FIRST_CYCLE) & (id_fsm_d == MULTI_CYCLE) |-> stall_id) // Stall ID/EX stage for reason that relates to instruction in ID/EX, update assertion below if // modifying this. - assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch | + assign stall_id = stall_mem | stall_multdiv | stall_jump | stall_branch | stall_alu; // Generally illegal instructions have no reason to stall, however they must still stall waiting // for outstanding memory requests so exceptions related to them take priority over the illegal // instruction exception. `ASSERT(IllegalInsnStallMustBeMemStall, illegal_insn_o & stall_id |-> stall_mem & - ~(stall_ld_hz | stall_multdiv | stall_jump | stall_branch | stall_alu)) + ~(stall_multdiv | stall_jump | stall_branch | stall_alu)) assign instr_done = ~stall_id & ~flush_id & instr_executing; @@ -884,119 +723,6 @@ module ibex_id_stage #( // Used by ALU to access RS3 if ternary instruction. assign instr_first_cycle_id_o = instr_first_cycle; - if (WritebackStage) begin : gen_stall_mem - // Register read address matches write address in WB - logic rf_rd_a_wb_match; - logic rf_rd_b_wb_match; - // Hazard between registers being read and written - logic rf_rd_a_hz; - logic rf_rd_b_hz; - - logic outstanding_memory_access; - - logic instr_kill; - - assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i; - - // Is a memory access ongoing that isn't finishing this cycle - assign outstanding_memory_access = (outstanding_load_wb_i | outstanding_store_wb_i) & - ~lsu_resp_valid_i; - - // Can start a new memory access if any previous one has finished or is finishing - assign data_req_allowed = ~outstanding_memory_access; - - // Instruction won't execute because: - // - There is a pending exception in writeback - // The instruction in ID/EX will be flushed and the core will jump to an exception handler - // - The controller isn't running instructions - // This either happens in preparation for a flush and jump to an exception handler e.g. in - // response to an IRQ or debug request or whilst the core is sleeping or resetting/fetching - // first instruction in which case any valid instruction in ID/EX should be ignored. - // - There was an error on instruction fetch - assign instr_kill = instr_fetch_err_i | - wb_exception | - id_exception | - ~controller_run; - - // With writeback stage instructions must be prevented from executing if there is: - // - A load hazard - // - A pending memory access - // If it receives an error response this results in a precise exception from WB so ID/EX - // instruction must not execute until error response is known). - // - A load/store error - // This will cause a precise exception for the instruction in WB so ID/EX instruction must not - // execute - // - // instr_executing_spec is a speculative signal. It indicates an instruction can execute - // assuming there are no exceptions from writeback and any outstanding memory access won't - // receive an error. It is required so branch and jump requests don't factor in an incoming dmem - // error (that in turn would factor directly into imem requests leading to a feedthrough path). - // - // instr_executing is the full signal, it will only allow execution once any potential - // exceptions from writeback have been resolved. - assign instr_executing_spec = instr_valid_i & - ~instr_fetch_err_i & - controller_run & - ~stall_ld_hz; - - assign instr_executing = instr_valid_i & - ~instr_kill & - ~stall_ld_hz & - ~outstanding_memory_access; - - `ASSERT(IbexExecutingSpecIfExecuting, instr_executing |-> instr_executing_spec) - - `ASSERT(IbexStallIfValidInstrNotExecuting, - instr_valid_i & ~instr_kill & ~instr_executing |-> stall_id) - - `ASSERT(IbexCannotRetireWithPendingExceptions, - instr_done |-> ~(wb_exception | outstanding_memory_access)) - - // Stall for reasons related to memory: - // * There is an outstanding memory access that won't resolve this cycle (need to wait to allow - // precise exceptions) - // * There is a load/store request not being granted or which is unaligned and waiting to issue - // a second request (needs to stay in ID for the address calculation) - assign stall_mem = instr_valid_i & - (outstanding_memory_access | (lsu_req_dec & ~lsu_req_done_i)); - - // If we stall a load in ID for any reason, it must not make an LSU request - // (otherwide we might issue two requests for the same instruction) - `ASSERT(IbexStallMemNoRequest, - instr_valid_i & lsu_req_dec & ~instr_done |-> ~lsu_req_done_i) - - assign rf_rd_a_wb_match = (rf_waddr_wb_i == rf_raddr_a_o) & |rf_raddr_a_o; - assign rf_rd_b_wb_match = (rf_waddr_wb_i == rf_raddr_b_o) & |rf_raddr_b_o; - - assign rf_rd_a_wb_match_o = rf_rd_a_wb_match; - assign rf_rd_b_wb_match_o = rf_rd_b_wb_match; - - // If instruction is reading register that load will be writing stall in - // ID until load is complete. No need to stall when reading zero register. - assign rf_rd_a_hz = rf_rd_a_wb_match & rf_ren_a; - assign rf_rd_b_hz = rf_rd_b_wb_match & rf_ren_b; - - // If instruction is read register that writeback is writing forward writeback data to read - // data. Note this doesn't factor in load data as it arrives too late, such hazards are - // resolved via a stall (see above). - assign rf_rdata_a_fwd = rf_rd_a_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_a_i; - assign rf_rdata_b_fwd = rf_rd_b_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_b_i; - - assign stall_ld_hz = outstanding_load_wb_i & (rf_rd_a_hz | rf_rd_b_hz); - - assign instr_type_wb_o = ~lsu_req_dec ? WB_INSTR_OTHER : - lsu_we ? WB_INSTR_STORE : - WB_INSTR_LOAD; - - assign instr_id_done_o = en_wb_o & ready_wb_i; - - // Stall ID/EX as instruction in ID/EX cannot proceed to writeback yet - assign stall_wb = en_wb_o & ~ready_wb_i; - - assign perf_dside_wait_o = instr_valid_i & ~instr_kill & - (outstanding_memory_access | stall_ld_hz); - end else begin : gen_no_stall_mem - assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i; assign data_req_allowed = instr_first_cycle; @@ -1005,9 +731,6 @@ module ibex_id_stage #( // Then stall until it is complete assign stall_mem = instr_valid_i & (lsu_req_dec & (~lsu_resp_valid_i | instr_first_cycle)); - // No load hazards without Writeback Stage - assign stall_ld_hz = 1'b0; - // Without writeback stage any valid instruction that hasn't seen an error will execute assign instr_executing_spec = instr_valid_i & ~instr_fetch_err_i & controller_run; assign instr_executing = instr_executing_spec; @@ -1020,60 +743,34 @@ module ibex_id_stage #( assign rf_rdata_a_fwd = rf_rdata_a_i; assign rf_rdata_b_fwd = rf_rdata_b_i; - assign rf_rd_a_wb_match_o = 1'b0; - assign rf_rd_b_wb_match_o = 1'b0; - // Unused Writeback stage only IO & wiring // Assign inputs and internal wiring to unused signals to satisfy lint checks // Tie-off outputs to constant values logic unused_data_req_done_ex; - logic [4:0] unused_rf_waddr_wb; - logic unused_rf_write_wb; - logic unused_outstanding_load_wb; - logic unused_outstanding_store_wb; - logic unused_wb_exception; - logic [31:0] unused_rf_wdata_fwd_wb; - logic unused_id_exception; - - assign unused_data_req_done_ex = lsu_req_done_i; - assign unused_rf_waddr_wb = rf_waddr_wb_i; - assign unused_rf_write_wb = rf_write_wb_i; - assign unused_outstanding_load_wb = outstanding_load_wb_i; - assign unused_outstanding_store_wb = outstanding_store_wb_i; - assign unused_wb_exception = wb_exception; - assign unused_rf_wdata_fwd_wb = rf_wdata_fwd_wb_i; - assign unused_id_exception = id_exception; - - assign instr_type_wb_o = WB_INSTR_OTHER; - assign stall_wb = 1'b0; assign perf_dside_wait_o = instr_executing & lsu_req_dec & ~lsu_resp_valid_i; assign instr_id_done_o = instr_done; - end // Signal which instructions to count as retired in minstret, all traps along with ebrk and // ecall instructions are not counted. assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec & ~illegal_csr_insn_i & ~instr_fetch_err_i; - // An instruction is ready to move to the writeback stage (or retire if there is no writeback - // stage) + // An instruction is ready to move to the writeback assign en_wb_o = instr_done; - assign perf_mul_wait_o = stall_multdiv & mult_en_dec; + assign perf_wfi_wait_o = wfi_insn_dec; assign perf_div_wait_o = stall_multdiv & div_en_dec; ////////// // FCOV // ////////// - //`DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz, - // (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage) - //`DV_FCOV_SIGNAL(logic, branch_taken, - // instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i) - //`DV_FCOV_SIGNAL(logic, branch_not_taken, - // instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) + `DV_FCOV_SIGNAL(logic, branch_taken, + instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i) + `DV_FCOV_SIGNAL(logic, branch_not_taken, + instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) //////////////// // Assertions // @@ -1086,16 +783,6 @@ module ibex_id_stage #( OP_A_FWD, OP_A_CURRPC, OP_A_IMM}) - `ASSERT_KNOWN_IF(IbexBTAluAOpMuxSelKnown, bt_a_mux_sel, instr_valid_i) - `ASSERT(IbexBTAluAOpMuxSelValid, instr_valid_i |-> bt_a_mux_sel inside { - OP_A_REG_A, - OP_A_CURRPC}) - `ASSERT_KNOWN_IF(IbexBTAluBOpMuxSelKnown, bt_b_mux_sel, instr_valid_i) - `ASSERT(IbexBTAluBOpMuxSelValid, instr_valid_i |-> bt_b_mux_sel inside { - IMM_B_I, - IMM_B_B, - IMM_B_J, - IMM_B_INCR_PC}) `ASSERT(IbexRegfileWdataSelValid, instr_valid_i |-> rf_wdata_sel inside { RF_WD_EX, RF_WD_CSR}) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv new file mode 100644 index 00000000..cbb05054 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv @@ -0,0 +1,278 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Instruction Fetch Stage + * + * Instruction fetch unit: Selection of the next PC, and buffering (sampling) of + * the read instruction. + */ + +`include "prim_assert.sv" + +module cve2_if_stage import cve2_pkg::*; #( + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 +) ( + input logic clk_i, + input logic rst_ni, + + input logic [31:0] boot_addr_i, // also used for mtvec + input logic req_i, // instruction request control + + // instruction cache interface + output logic instr_req_o, + output logic [31:0] instr_addr_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + input logic [31:0] instr_rdata_i, + input logic instr_err_i, + + // output of ID stage + output logic instr_valid_id_o, // instr in IF-ID is valid + output logic instr_new_id_o, // instr in IF-ID is new + output logic [31:0] instr_rdata_id_o, // instr for ID stage + output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage + // to reduce fan-out + output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage + // (mtval), meaningful only if + // instr_is_compressed_id_o = 1'b1 + output logic instr_is_compressed_id_o, // compressed decoder thinks this + // is a compressed instr + output logic instr_fetch_err_o, // bus error on fetch + output logic instr_fetch_err_plus2_o, // bus error misaligned + output logic illegal_c_insn_id_o, // compressed decoder thinks this + // is an invalid instr + output logic [31:0] pc_if_o, + output logic [31:0] pc_id_o, + input logic pmp_err_if_i, + input logic pmp_err_if_plus2_i, + + // control signals + input logic instr_valid_clear_i, // clear instr valid bit in IF-ID + input logic pc_set_i, // set the PC to a new value + input pc_sel_e pc_mux_i, // selector for PC multiplexer + input exc_pc_sel_e exc_pc_mux_i, // selects ISR address + input exc_cause_e exc_cause, // selects ISR address for + // vectorized interrupt lines + // jump and branch target + input logic [31:0] branch_target_ex_i, // branch/jump target address + + // CSRs + input logic [31:0] csr_mepc_i, // PC to restore after handling + // the interrupt/exception + input logic [31:0] csr_depc_i, // PC to restore after handling + // the debug request + input logic [31:0] csr_mtvec_i, // base PC to jump to on exception + output logic csr_mtvec_init_o, // tell CS regfile to init mtvec + + // pipeline stall + input logic id_in_ready_i, // ID stage is ready for new instr + + // misc signals + output logic if_busy_o // IF stage is busy fetching instr +); + + logic instr_valid_id_d, instr_valid_id_q; + logic instr_new_id_d, instr_new_id_q; + + // prefetch buffer related signals + logic prefetch_busy; + logic branch_req; + logic [31:0] fetch_addr_n; + logic unused_fetch_addr_n0; + + logic fetch_valid; + logic fetch_ready; + logic [31:0] fetch_rdata; + logic [31:0] fetch_addr; + logic fetch_err; + logic fetch_err_plus2; + + logic [31:0] instr_decompressed; + logic illegal_c_insn; + logic instr_is_compressed; + + logic if_instr_pmp_err; + logic if_instr_err; + logic if_instr_err_plus2; + + logic [31:0] exc_pc; + + logic [6:0] irq_id; + logic unused_irq_bit; + + logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable + + cve2_pkg::pc_sel_e pc_mux_internal; + + logic [7:0] unused_boot_addr; + logic [7:0] unused_csr_mtvec; + + assign unused_boot_addr = boot_addr_i[7:0]; + assign unused_csr_mtvec = csr_mtvec_i[7:0]; + + // extract interrupt ID from exception cause + assign irq_id = {exc_cause}; + assign unused_irq_bit = irq_id[6]; // MSB distinguishes interrupts from exceptions + + // exception PC selection mux + always_comb begin : exc_pc_mux + unique case (exc_pc_mux_i) + EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; + EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], irq_id[5:0], 2'b00 }; + EXC_PC_DBD: exc_pc = DmHaltAddr; + EXC_PC_DBG_EXC: exc_pc = DmExceptionAddr; + default: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; + endcase + end + + assign pc_mux_internal = + pc_mux_i; + + // fetch address selection mux + always_comb begin : fetch_addr_mux + unique case (pc_mux_internal) + PC_BOOT: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; + PC_JUMP: fetch_addr_n = branch_target_ex_i; + PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler + PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC + PC_DRET: fetch_addr_n = csr_depc_i; + default: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; + endcase + end + + // tell CS register file to initialize mtvec on boot + assign csr_mtvec_init_o = (pc_mux_i == PC_BOOT) & pc_set_i; + + // prefetch buffer, caches a fixed number of instructions + cve2_prefetch_buffer #( + ) prefetch_buffer_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .req_i ( req_i ), + + .branch_i ( branch_req ), + .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + .err_o ( fetch_err ), + .err_plus2_o ( fetch_err_plus2 ), + + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + .instr_err_i ( instr_err_i ), + + .busy_o ( prefetch_busy ) + ); + + assign unused_fetch_addr_n0 = fetch_addr_n[0]; + + assign branch_req = pc_set_i; + + assign pc_if_o = fetch_addr; + assign if_busy_o = prefetch_busy; + + // PMP errors + // An error can come from the instruction address, or the next instruction address for unaligned, + // uncompressed instructions. + assign if_instr_pmp_err = pmp_err_if_i | + (fetch_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i); + + // Combine bus errors and pmp errors + assign if_instr_err = fetch_err | if_instr_pmp_err; + + // Capture the second half of the address for errors on the second part of an instruction + assign if_instr_err_plus2 = ((fetch_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i) | + fetch_err_plus2) & ~pmp_err_if_i; + + // compressed instruction decoding, or more precisely compressed instruction + // expander + // + // since it does not matter where we decompress instructions, we do it here + // to ease timing closure + cve2_compressed_decoder compressed_decoder_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .valid_i (fetch_valid & ~fetch_err), + .instr_i (fetch_rdata), + .instr_o (instr_decompressed), + .is_compressed_o(instr_is_compressed), + .illegal_instr_o(illegal_c_insn) + ); + + // The ID stage becomes valid as soon as any instruction is registered in the ID stage flops. + // Note that the current instruction is squashed by the incoming pc_set_i signal. + // Valid is held until it is explicitly cleared (due to an instruction completing or an exception) + assign instr_valid_id_d = (fetch_valid & id_in_ready_i & ~pc_set_i) | + (instr_valid_id_q & ~instr_valid_clear_i); + assign instr_new_id_d = fetch_valid & id_in_ready_i; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_valid_id_q <= 1'b0; + instr_new_id_q <= 1'b0; + end else begin + instr_valid_id_q <= instr_valid_id_d; + instr_new_id_q <= instr_new_id_d; + end + end + + assign instr_valid_id_o = instr_valid_id_q; + // Signal when a new instruction enters the ID stage (only used for RVFI signalling). + assign instr_new_id_o = instr_new_id_q; + + // IF-ID pipeline registers, frozen when the ID stage is stalled + assign if_id_pipe_reg_we = instr_new_id_d; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_rdata_id_o <= '0; + instr_rdata_alu_id_o <= '0; + instr_fetch_err_o <= '0; + instr_fetch_err_plus2_o <= '0; + instr_rdata_c_id_o <= '0; + instr_is_compressed_id_o <= '0; + illegal_c_insn_id_o <= '0; + pc_id_o <= '0; + end else if (if_id_pipe_reg_we) begin + instr_rdata_id_o <= instr_decompressed; + // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. + instr_rdata_alu_id_o <= instr_decompressed; + instr_fetch_err_o <= if_instr_err; + instr_fetch_err_plus2_o <= if_instr_err_plus2; + instr_rdata_c_id_o <= fetch_rdata[15:0]; //if_instr_rdata[15:0]; + instr_is_compressed_id_o <= instr_is_compressed; + illegal_c_insn_id_o <= illegal_c_insn; + pc_id_o <= pc_if_o; + end + end + + assign fetch_ready = id_in_ready_i; + + //////////////// + // Assertions // + //////////////// + + // Selectors must be known/valid. + `ASSERT_KNOWN(IbexExcPcMuxKnown, exc_pc_mux_i) + + // Boot address must be aligned to 256 bytes. + `ASSERT(IbexBootAddrUnaligned, boot_addr_i[7:0] == 8'h00) + + // Address must not contain X when request is sent. + `ASSERT(IbexInstrAddrUnknown, instr_req_o |-> !$isunknown(instr_addr_o)) + + // Address must be word aligned when request is sent. + `ASSERT(IbexInstrAddrUnaligned, instr_req_o |-> (instr_addr_o[1:0] == 2'b00)) + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv similarity index 96% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv index 6ec55b07..3575fadf 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv @@ -12,9 +12,9 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_load_store_unit +module cve2_load_store_unit ( input logic clk_i, input logic rst_ni, @@ -50,10 +50,6 @@ module ibex_load_store_unit // -> mtval // -> AGU for misaligned accesses - output logic lsu_req_done_o, // Signals that data request is complete - // (only need to await final data - // response) -> to ID/EX - output logic lsu_resp_valid_o, // LSU has response from transaction -> to ID/EX // exception signals @@ -453,8 +449,6 @@ module ibex_load_store_unit endcase end - assign lsu_req_done_o = (lsu_req_i | (ls_fsm_cs != IDLE)) & (ls_fsm_ns == IDLE); - // registers for FSM always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin @@ -503,8 +497,8 @@ module ibex_load_store_unit // FCOV // ////////// - //`DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q) - //`DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q) + `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q) + `DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q) //////////////// // Assertions // diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv similarity index 96% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv index 3f0d27ac..d1d400a3 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv @@ -14,8 +14,8 @@ `include "prim_assert.sv" -module ibex_multdiv_fast #( - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast +module cve2_multdiv_fast #( + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast ) ( input logic clk_i, input logic rst_ni, @@ -23,14 +23,13 @@ module ibex_multdiv_fast #( input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes input logic div_sel_i, // static decoder output, for data muxes - input ibex_pkg::md_op_e operator_i, + input cve2_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, input logic [31:0] op_b_i, input logic [33:0] alu_adder_ext_i, input logic [31:0] alu_adder_i, input logic equal_to_zero_i, - input logic data_ind_timing_i, output logic [32:0] alu_operand_a_o, output logic [32:0] alu_operand_b_o, @@ -39,13 +38,11 @@ module ibex_multdiv_fast #( output logic [33:0] imd_val_d_o[2], output logic [1:0] imd_val_we_o, - input logic multdiv_ready_id_i, - output logic [31:0] multdiv_result_o, output logic valid_o ); - import ibex_pkg::*; + import cve2_pkg::*; // Both multiplier variants logic signed [34:0] mac_res_signed; @@ -210,7 +207,7 @@ module ibex_multdiv_fast #( mult_valid = 1'b0; mult_state_d = MULH; end else begin - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end end @@ -229,7 +226,7 @@ module ibex_multdiv_fast #( mult_state_d = MULL; mult_valid = 1'b1; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end default: begin @@ -328,7 +325,7 @@ module ibex_multdiv_fast #( // Note no state transition will occur if mult_hold is set mult_state_d = ALBL; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end else begin accum = imd_val_q_i[0]; mac_res_d = mac_res; @@ -351,7 +348,7 @@ module ibex_multdiv_fast #( // Note no state transition will occur if mult_hold is set mult_state_d = ALBL; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end default: begin mult_state_d = ALBL; @@ -424,7 +421,7 @@ module ibex_multdiv_fast #( // normal and will naturally return -1 op_remainder_d = '1; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; // Record that this is a div by zero to stop the sign change at the end of the // division (in data_ind_timing mode). div_by_zero_d = equal_to_zero_i; @@ -435,7 +432,7 @@ module ibex_multdiv_fast #( // normal and will naturally return operand a op_remainder_d = {2'b0, op_a_i}; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; end // 0 - B = 0 iff B == 0 alu_operand_a_o = {32'h0 , 1'b1}; @@ -508,7 +505,7 @@ module ibex_multdiv_fast #( // Hold result until ID stage is ready to accept it // Note no state transition will occur if div_hold is set md_state_d = MD_IDLE; - div_hold = ~multdiv_ready_id_i; + div_hold = 1'b0; div_valid = 1'b1; end @@ -530,4 +527,4 @@ module ibex_multdiv_fast #( `endif `endif -endmodule // ibex_mult +endmodule // cve2_mult diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv similarity index 96% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv index 214d3f59..70732cc6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv @@ -11,7 +11,7 @@ `include "prim_assert.sv" -module ibex_multdiv_slow +module cve2_multdiv_slow ( input logic clk_i, input logic rst_ni, @@ -19,14 +19,13 @@ module ibex_multdiv_slow input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes input logic div_sel_i, // static decoder output, for data muxes - input ibex_pkg::md_op_e operator_i, + input cve2_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, input logic [31:0] op_b_i, input logic [33:0] alu_adder_ext_i, input logic [31:0] alu_adder_i, input logic equal_to_zero_i, - input logic data_ind_timing_i, output logic [32:0] alu_operand_a_o, output logic [32:0] alu_operand_b_o, @@ -42,7 +41,7 @@ module ibex_multdiv_slow output logic valid_o ); - import ibex_pkg::*; + import cve2_pkg::*; typedef enum logic [2:0] { MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH @@ -191,7 +190,7 @@ module ibex_multdiv_slow op_b_shift_d = op_b_ext >> 1; // Proceed with multiplication by 0/1 in data-independent time mode // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && ((op_b_ext >> 1) == 0)) ? MD_LAST : MD_COMP; + md_state_d = ((op_b_ext >> 1) == 0) ? MD_LAST : MD_COMP; end MD_OP_MULH: begin op_a_shift_d = op_a_ext; @@ -207,7 +206,7 @@ module ibex_multdiv_slow // normal and will naturally return -1 accum_window_d = {33{1'b1}}; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; // Record that this is a div by zero to stop the sign change at the end of the // division (in data_ind_timing mode). div_by_zero_d = equal_to_zero_i; @@ -219,7 +218,7 @@ module ibex_multdiv_slow // normal and will naturally return operand a accum_window_d = op_a_ext; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; end default:; endcase @@ -252,7 +251,7 @@ module ibex_multdiv_slow // Multiplication is complete once op_b is zero, unless in data_ind_timing mode where // the maximum possible shift-add operations will be completed regardless of op_b // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = ((!data_ind_timing_i && (op_b_shift_d == 0)) || + md_state_d = ((op_b_shift_d == 0) || (multdiv_count_q == 5'd1)) ? MD_LAST : MD_COMP; end MD_OP_MULH: begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv similarity index 74% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv index fec80fdf..6cd8f4b1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv @@ -6,7 +6,7 @@ /** * Package with constants used by Ibex */ -package ibex_pkg; +package cve2_pkg; //////////////// // IO Structs // @@ -31,12 +31,6 @@ package ibex_pkg; // Parameter Enums // ///////////////////// - typedef enum integer { - RegFileFF = 0, - RegFileFPGA = 1, - RegFileLatch = 2 - } regfile_e; - typedef enum integer { RV32MNone = 0, RV32MSlow = 1, @@ -298,26 +292,25 @@ package ibex_pkg; logic irq_software; logic irq_timer; logic irq_external; - logic [14:0] irq_fast; // 15 fast interrupts, - // one interrupt is reserved for NMI (not visible through mip/mie) + logic [15:0] irq_fast; // 16 fast interrupts } irqs_t; // Exception cause - typedef enum logic [5:0] { - EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03}, - EXC_CAUSE_IRQ_TIMER_M = {1'b1, 5'd07}, - EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11}, - // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16}, - // EXC_CAUSE_IRQ_FAST_14 = {1'b1, 5'd30}, - EXC_CAUSE_IRQ_NM = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15 - EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00}, - EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01}, - EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd02}, - EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03}, - EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05}, - EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07}, - EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08}, - EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11} + typedef enum logic [6:0] { + EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 6'd03}, + EXC_CAUSE_IRQ_TIMER_M = {1'b1, 6'd07}, + EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 6'd11}, + // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 6'd16}, + // EXC_CAUSE_IRQ_FAST_15 = {1'b1, 6'd31}, + EXC_CAUSE_IRQ_NM = {1'b1, 6'd32}, + EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 6'd00}, + EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 6'd01}, + EXC_CAUSE_ILLEGAL_INSN = {1'b0, 6'd02}, + EXC_CAUSE_BREAKPOINT = {1'b0, 6'd03}, + EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 6'd05}, + EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 6'd07}, + EXC_CAUSE_ECALL_UMODE = {1'b0, 6'd08}, + EXC_CAUSE_ECALL_MMODE = {1'b0, 6'd11} } exc_cause_e; // Debug cause @@ -329,27 +322,6 @@ package ibex_pkg; DBG_CAUSE_STEP = 3'h4 } dbg_cause_e; - // ICache constants - parameter int unsigned ADDR_W = 32; - parameter int unsigned BUS_SIZE = 32; - parameter int unsigned BUS_BYTES = BUS_SIZE/8; - parameter int unsigned BUS_W = $clog2(BUS_BYTES); - parameter int unsigned IC_SIZE_BYTES = 4096; - parameter int unsigned IC_NUM_WAYS = 2; - parameter int unsigned IC_LINE_SIZE = 64; - parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8; - parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES); - parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES; - parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES; - parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS); - parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES); - parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1; - parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit - parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords - // ICache Scrambling Parameters - parameter int unsigned SCRAMBLE_KEY_W = 128; - parameter int unsigned SCRAMBLE_NONCE_W = 64; - // PMP constants parameter int unsigned PMP_MAX_REGIONS = 16; parameter int unsigned PMP_CFG_W = 8; @@ -391,10 +363,11 @@ package ibex_pkg; // CSRs typedef enum logic[11:0] { // Machine information - CSR_MVENDORID = 12'hF11, - CSR_MARCHID = 12'hF12, - CSR_MIMPID = 12'hF13, - CSR_MHARTID = 12'hF14, + CSR_MVENDORID = 12'hF11, + CSR_MARCHID = 12'hF12, + CSR_MIMPID = 12'hF13, + CSR_MHARTID = 12'hF14, + CSR_MCONFIGPTR = 12'hF15, // Machine trap setup CSR_MSTATUS = 12'h300, @@ -402,6 +375,10 @@ package ibex_pkg; CSR_MIE = 12'h304, CSR_MTVEC = 12'h305, CSR_MCOUNTEREN= 12'h306, + CSR_MSTATUSH = 12'h310, + + CSR_MENVCFG = 12'h30A, + CSR_MENVCFGH = 12'h31A, // Machine trap handling CSR_MSCRATCH = 12'h340, @@ -569,52 +546,33 @@ package ibex_pkg; parameter int unsigned CSR_MTIX_BIT = 7; parameter int unsigned CSR_MEIX_BIT = 11; parameter int unsigned CSR_MFIX_BIT_LOW = 16; - parameter int unsigned CSR_MFIX_BIT_HIGH = 30; + parameter int unsigned CSR_MFIX_BIT_HIGH = 31; // CSR Machine Security Configuration bits parameter int unsigned CSR_MSECCFG_MML_BIT = 0; parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1; parameter int unsigned CSR_MSECCFG_RLB_BIT = 2; - // Vendor ID - // No JEDEC ID has been allocated to lowRISC so the value is 0 to indicate the field is not - // implemented - localparam logic [31:0] CSR_MVENDORID_VALUE = 32'b0; + // Machine Vendor ID - OpenHW JEDEC ID is '2 decimal (bank 13)' + parameter MVENDORID_OFFSET = 7'h2; // Final byte without parity bit + parameter MVENDORID_BANK = 25'hC; // Number of continuation codes + + // Machine Architecture ID (https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md) + parameter MARCHID = 32'd35; - // Architecture ID - // Top bit is unset to indicate an open source project. The lower bits are an ID allocated by the - // RISC-V Foundation. Note this is allocated specifically to Ibex, should significant changes be - // made a different architecture ID should be supplied. - localparam logic [31:0] CSR_MARCHID_VALUE = {1'b0, 31'd22}; + localparam logic [31:0] CSR_MVENDORID_VALUE = {MVENDORID_BANK, MVENDORID_OFFSET}; + localparam logic [31:0] CSR_MARCHID_VALUE = MARCHID; // Implementation ID - // 0 indicates this field is not implemeted. Ibex implementors may wish to indicate an RTL/netlist + // 0 indicates this field is not implemeted. cve2 implementors may wish to indicate an RTL/netlist // version here using their own unique encoding (e.g. 32 bits of the git hash of the implemented // commit). localparam logic [31:0] CSR_MIMPID_VALUE = 32'b0; - // These LFSR parameters have been generated with - // $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix "" - parameter int LfsrWidth = 32; - typedef logic [LfsrWidth-1:0] lfsr_seed_t; - typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t; - parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4; - parameter lfsr_perm_t RndCnstLfsrPermDefault = { - 160'h1e35ecba467fd1b12e958152c04fa43878a8daed - }; - parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKeyDefault = - 128'h14e8cecae3040d5e12286bb3cc113298; - parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonceDefault = - 64'hf79780bc735f3843; - - // Fetch enable. Mult-bit signal used for security hardening. For non-secure implementation all - // bits other than the bottom bit are ignored. - typedef logic [3:0] fetch_enable_t; - - // Note that if adjusting these parameters it is assumed the bottom bit is set for On and unset - // for Off. This allows the use of FetchEnableOn/FetchEnableOff to work for both secure and - // non-secure Ibex. If this assumption is broken the RTL that uses the fetch_enable signal within - // `ibex_core` may need adjusting. - parameter fetch_enable_t FetchEnableOn = 4'b1001; - parameter fetch_enable_t FetchEnableOff = 4'b0110; + // Machine Configuration Pointer + // 0 indicates the configuration data structure does not eixst. cve2 implementors may wish to + // alter this to point to their system specific configuration data structure. + localparam logic [31:0] CSR_MCONFIGPTR_VALUE = 32'b0; + endpackage + diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv similarity index 95% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv index 16e806a2..b531eefd 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -module ibex_pmp #( +module cve2_pmp #( // Granularity of NAPOT access, // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc. parameter int unsigned PMPGranularity = 0, @@ -16,19 +16,19 @@ module ibex_pmp #( input logic rst_ni, // Interface to CSRs - input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], + input cve2_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], input logic [33:0] csr_pmp_addr_i [PMPNumRegions], - input ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, + input cve2_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, - input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan], + input cve2_pkg::priv_lvl_e priv_mode_i [PMPNumChan], // Access checking channels input logic [33:0] pmp_req_addr_i [PMPNumChan], - input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], + input cve2_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], output logic pmp_req_err_o [PMPNumChan] ); - import ibex_pkg::*; + import cve2_pkg::*; // Access Checking Signals logic [33:0] region_start_addr [PMPNumRegions]; @@ -177,7 +177,7 @@ module ibex_pmp #( assign pmp_req_err_o[c] = access_fault[c]; end - // RLB, rule locking bypass, is only relevant to ibex_cs_registers which controls writes to the + // RLB, rule locking bypass, is only relevant to cve2_cs_registers which controls writes to the // PMP CSRs. Tie to unused signal here to prevent lint warnings. logic unused_csr_pmp_mseccfg_rlb; assign unused_csr_pmp_mseccfg_rlb = csr_pmp_mseccfg_i.rlb; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp_reset_default.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp_reset_default.svh similarity index 100% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp_reset_default.svh rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp_reset_default.svh diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv similarity index 81% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv index 5b834ce2..51b1195c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv @@ -9,8 +9,7 @@ * Prefetch Buffer that caches instructions. This cuts overly long critical * paths to the instruction cache. */ -module ibex_prefetch_buffer #( - parameter bit ResetAll = 1'b0 +module cve2_prefetch_buffer #( ) ( input logic clk_i, input logic rst_ni, @@ -18,8 +17,6 @@ module ibex_prefetch_buffer #( input logic req_i, input logic branch_i, - input logic branch_mispredict_i, - input logic [31:0] mispredict_addr_i, input logic [31:0] addr_i, @@ -65,16 +62,12 @@ module ibex_prefetch_buffer #( logic valid_raw; - logic branch_or_mispredict; - //////////////////////////// // Prefetch buffer status // //////////////////////////// assign busy_o = (|rdata_outstanding_q) | instr_req_o; - assign branch_or_mispredict = branch_i | branch_mispredict_i; - ////////////////////////////////////////////// // Fetch fifo - consumes addresses and data // ////////////////////////////////////////////// @@ -82,7 +75,7 @@ module ibex_prefetch_buffer #( // A branch will invalidate any previously fetched instructions. // Note that the FENCE.I instruction relies on this flushing behaviour on branch. If it is // altered the FENCE.I implementation may require changes. - assign fifo_clear = branch_or_mispredict; + assign fifo_clear = branch_i; // Reversed version of rdata_outstanding_q which can be overlaid with fifo fill state for (genvar i = 0; i < NUM_REQS; i++) begin : gen_rd_rev @@ -94,9 +87,8 @@ module ibex_prefetch_buffer #( // Overlay the fifo fill state with the outstanding requests to see if there is space. assign fifo_ready = ~&(fifo_busy | rdata_outstanding_rev); - ibex_fetch_fifo #( - .NUM_REQS (NUM_REQS), - .ResetAll (ResetAll) + cve2_fetch_fifo #( + .NUM_REQS (NUM_REQS) ) fifo_i ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -122,7 +114,7 @@ module ibex_prefetch_buffer #( ////////////// // Make a new request any time there is space in the FIFO, and space in the request queue - assign valid_new_req = req_i & (fifo_ready | branch_or_mispredict) & + assign valid_new_req = req_i & (fifo_ready | branch_i) & ~rdata_outstanding_q[NUM_REQS-1]; assign valid_req = valid_req_q | valid_new_req; @@ -131,7 +123,7 @@ module ibex_prefetch_buffer #( assign valid_req_d = valid_req & ~instr_gnt_i; // Record whether an outstanding bus request is cancelled by a branch - assign discard_req_d = valid_req_q & (branch_or_mispredict | discard_req_q); + assign discard_req_d = valid_req_q & (branch_i | discard_req_q); //////////////// // Fetch addr // @@ -156,52 +148,34 @@ module ibex_prefetch_buffer #( assign stored_addr_d = instr_addr; // CPU resets with a branch, so no need to reset these addresses - if (ResetAll) begin : g_stored_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - stored_addr_q <= '0; - end else if (stored_addr_en) begin - stored_addr_q <= stored_addr_d; - end - end - end else begin : g_stored_addr_nr - always_ff @(posedge clk_i) begin - if (stored_addr_en) begin - stored_addr_q <= stored_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + stored_addr_q <= '0; + end else if (stored_addr_en) begin + stored_addr_q <= stored_addr_d; end end // 2. fetch_addr_q // Update on a branch or as soon as a request is issued - assign fetch_addr_en = branch_or_mispredict | (valid_new_req & ~valid_req_q); + assign fetch_addr_en = branch_i | (valid_new_req & ~valid_req_q); assign fetch_addr_d = (branch_i ? addr_i : - branch_mispredict_i ? {mispredict_addr_i[31:2], 2'b00} : {fetch_addr_q[31:2], 2'b00}) + // Current address + 4 {{29{1'b0}},(valid_new_req & ~valid_req_q),2'b00}; - if (ResetAll) begin : g_fetch_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fetch_addr_q <= '0; - end else if (fetch_addr_en) begin - fetch_addr_q <= fetch_addr_d; - end - end - end else begin : g_fetch_addr_nr - always_ff @(posedge clk_i) begin - if (fetch_addr_en) begin - fetch_addr_q <= fetch_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + fetch_addr_q <= '0; + end else if (fetch_addr_en) begin + fetch_addr_q <= fetch_addr_d; end end // Address mux assign instr_addr = valid_req_q ? stored_addr_q : branch_i ? addr_i : - branch_mispredict_i ? mispredict_addr_i : fetch_addr_q; assign instr_addr_w_aligned = {instr_addr[31:2], 2'b00}; @@ -220,7 +194,7 @@ module ibex_prefetch_buffer #( // If a branch is received at any point while a request is outstanding, it must be tracked // to ensure we discard the data once received assign branch_discard_n[i] = (valid_req & instr_gnt_i & discard_req_d) | - (branch_or_mispredict & rdata_outstanding_q[i]) | + (branch_i & rdata_outstanding_q[i]) | branch_discard_q[i]; end else begin : g_reqtop @@ -232,7 +206,7 @@ module ibex_prefetch_buffer #( rdata_outstanding_q[i]; assign branch_discard_n[i] = (valid_req & instr_gnt_i & discard_req_d & rdata_outstanding_q[i-1]) | - (branch_or_mispredict & rdata_outstanding_q[i]) | + (branch_i & rdata_outstanding_q[i]) | branch_discard_q[i]; end end @@ -246,7 +220,7 @@ module ibex_prefetch_buffer #( // Push a new entry to the FIFO once complete (and not cancelled by a branch) assign fifo_valid = instr_rvalid_i & ~branch_discard_q[0]; - assign fifo_addr = branch_i ? addr_i : mispredict_addr_i; + assign fifo_addr = addr_i; /////////////// // Registers // @@ -273,6 +247,6 @@ module ibex_prefetch_buffer #( assign instr_req_o = valid_req; assign instr_addr_o = instr_addr_w_aligned; - assign valid_o = valid_raw & ~branch_mispredict_i; + assign valid_o = valid_raw; endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv similarity index 66% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv index 90b0c719..148ba225 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv @@ -10,10 +10,9 @@ * This register file is based on flip flops. Use this register file when * targeting FPGA synthesis or Verilator simulation. */ -module ibex_register_file_ff #( +module cve2_register_file_ff #( parameter bit RV32E = 0, parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset @@ -21,7 +20,6 @@ module ibex_register_file_ff #( input logic rst_ni, input logic test_en_i, - input logic dummy_instr_id_i, //Read port R1 input logic [4:0] raddr_a_i, @@ -63,34 +61,8 @@ module ibex_register_file_ff #( end end - // With dummy instructions enabled, R0 behaves as a real register but will always return 0 for - // real instructions. - if (DummyInstructions) begin : g_dummy_r0 - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic we_r0_dummy; - logic [DataWidth-1:0] rf_r0_q; - - // Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions) - assign we_r0_dummy = we_a_i & dummy_instr_id_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rf_r0_q <= WordZeroVal; - end else if (we_r0_dummy) begin - rf_r0_q <= wdata_a_i; - end - end - - // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal; - - end else begin : g_normal_r0 - logic unused_dummy_instr_id; - assign unused_dummy_instr_id = dummy_instr_id_i; - - // R0 is nil - assign rf_reg[0] = WordZeroVal; - end + // R0 is nil + assign rf_reg[0] = WordZeroVal; assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv deleted file mode 100644 index 80388031..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2020 Silicon Labs, Inc. -// -// This file, and derivatives thereof are licensed under the -// Solderpad License, Version 2.0 (the "License"). -// -// Use of this file means you agree to the terms and conditions -// of the license and are in full compliance with the License. -// -// You may obtain a copy of the License at: -// -// https://solderpad.org/licenses/SHL-2.0/ -// -// Unless required by applicable law or agreed to in writing, software -// and hardware implementations thereof distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED. -// -// See the License for the specific language governing permissions and -// limitations under the License. - -//////////////////////////////////////////////////////////////////////////////// -// Engineer: Arjan Bink - arjan.bink@silabs.com // -// // -// Design Name: Sleep Unit // -// Project Name: CVE2 // -// Language: SystemVerilog // -// // -// Description: Sleep unit containing the instantiated clock gate which // -// provides the gated clock (clk_gated_o) for the rest // -// of the design. Forked version of cv32e40p // -// // -// The clock is gated for the following scenarios: // -// // -// - While waiting for fetch to become enabled // -// - While blocked on a WFI (PULP_CLUSTER = 0) // -// - While clock_en_i = 0 during a p.elw (PULP_CLUSTER = 1) // -// // -// Sleep is signaled via core_sleep_o when: // -// - During a WFI (except in debug) // -// // -// // -//////////////////////////////////////////////////////////////////////////////// - -module cve2_sleep_unit ( - // Clock, reset interface - input logic clk_ungated_i, // Free running clock - input logic rst_n, - output logic clk_gated_o, // Gated clock - input logic scan_cg_en_i, // Enable all clock gates for testing - - // Core sleep - output logic core_sleep_o, - - // Fetch enable - input logic fetch_enable_i, - output logic fetch_enable_o, - - // Core status - input logic if_busy_i, - input logic ctrl_busy_i, - input logic lsu_busy_i, - - // WFI wake - input logic wake_from_sleep_i -); - - logic fetch_enable_q; // Sticky version of fetch_enable_i - logic fetch_enable_d; - logic core_busy_q; // Is core still busy (and requires a clock) with what needs to finish before entering sleep? - logic core_busy_d; - logic clock_en; // Final clock enable - - ////////////////////////////////////////////////////////////////////////////// - // Sleep FSM - ////////////////////////////////////////////////////////////////////////////// - - // Make sticky version of fetch_enable_i - assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q; - - - // Busy when any of the sub units is busy (typically wait for the instruction buffer to fill up) - assign core_busy_d = if_busy_i || ctrl_busy_i || lsu_busy_i; - - // Enable the clock only after the initial fetch enable while busy or waking up to become busy - assign clock_en = fetch_enable_q && (wake_from_sleep_i || core_busy_q); - - // Sleep only in response to WFI which leads to clock disable; debug_wfi_no_sleep_o in - // cv32e40p_controller determines the scenarios for which WFI can(not) cause sleep. - assign core_sleep_o = fetch_enable_q && !clock_en; - - - always_ff @(posedge clk_ungated_i, negedge rst_n) begin - if (rst_n == 1'b0) begin - core_busy_q <= 1'b0; - fetch_enable_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - fetch_enable_q <= fetch_enable_d; - end - end - - // Fetch enable for Controller - assign fetch_enable_o = fetch_enable_q; - - // Main clock gate of CV32E40P - cve2_clock_gate core_clock_gate_i ( - .clk_i (clk_ungated_i), - .en_i (clock_en), - .scan_cg_en_i(scan_cg_en_i), - .clk_o (clk_gated_o) - ); - - //---------------------------------------------------------------------------- - // Assertions - TODO - //---------------------------------------------------------------------------- - - -endmodule // cve2_sleep_unit diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv new file mode 100644 index 00000000..00c38a4a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -0,0 +1,272 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef RISCV_FORMAL + `define RVFI +`endif + +`include "prim_assert.sv" + +/** + * Top level module of the ibex RISC-V core + */ +module cve2_top import cve2_pkg::*; #( + parameter int unsigned MHPMCounterNum = 0, + parameter int unsigned MHPMCounterWidth = 40, + parameter bit RV32E = 1'b0, + parameter rv32m_e RV32M = RV32MFast, + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, // enable all clock gates for testing + input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, + + input logic [31:0] hart_id_i, + input logic [31:0] boot_addr_i, + + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, + input logic instr_err_i, + + // Data memory interface + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + input logic data_err_i, + + // Interrupt inputs + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [15:0] irq_fast_i, + input logic irq_nm_i, // non-maskeable interrupt + + // Debug Interface + input logic debug_req_i, + output crash_dump_t crash_dump_o, + + // RISC-V Formal Interface + // Does not comply with the coding standards of _i/_o suffixes, but follows + // the convention of RISC-V Formal Interface Specification. +`ifdef RVFI + output logic rvfi_valid, + output logic [63:0] rvfi_order, + output logic [31:0] rvfi_insn, + output logic rvfi_trap, + output logic rvfi_halt, + output logic rvfi_intr, + output logic [ 1:0] rvfi_mode, + output logic [ 1:0] rvfi_ixl, + output logic [ 4:0] rvfi_rs1_addr, + output logic [ 4:0] rvfi_rs2_addr, + output logic [ 4:0] rvfi_rs3_addr, + output logic [31:0] rvfi_rs1_rdata, + output logic [31:0] rvfi_rs2_rdata, + output logic [31:0] rvfi_rs3_rdata, + output logic [ 4:0] rvfi_rd_addr, + output logic [31:0] rvfi_rd_wdata, + output logic [31:0] rvfi_pc_rdata, + output logic [31:0] rvfi_pc_wdata, + output logic [31:0] rvfi_mem_addr, + output logic [ 3:0] rvfi_mem_rmask, + output logic [ 3:0] rvfi_mem_wmask, + output logic [31:0] rvfi_mem_rdata, + output logic [31:0] rvfi_mem_wdata, + output logic [31:0] rvfi_ext_mip, + output logic rvfi_ext_nmi, + output logic rvfi_ext_debug_req, + output logic [63:0] rvfi_ext_mcycle, +`endif + + // CPU Control Signals + input logic fetch_enable_i, + output logic core_sleep_o +); + + // Scrambling Parameter + localparam int unsigned NumAddrScrRounds = 0; + + // Physical Memory Protection + localparam bit PMPEnable = 1'b0; + localparam int unsigned PMPGranularity = 0; + localparam int unsigned PMPNumRegions = 4; + + // Trigger support + localparam bit DbgTriggerEn = 1'b1; + localparam int unsigned DbgHwBreakNum = 1; + + // Bit manipulation extension + localparam rv32b_e RV32B = RV32BNone; + + // Clock signals + logic clk; + logic core_busy_d, core_busy_q; + logic clock_en; + logic fetch_enable_d, fetch_enable_q; + logic irq_pending; + + ///////////////////// + // Main clock gate // + ///////////////////// + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + core_busy_q <= 1'b0; + fetch_enable_q <= 1'b0; + end else begin + core_busy_q <= core_busy_d; + fetch_enable_q <= fetch_enable_d; + end + end + + assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i); + assign core_sleep_o = fetch_enable_q & !clock_en; + assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q; + + cve2_clock_gate core_clock_gate_i ( + .clk_i (clk_i), + .en_i (clock_en), + .scan_cg_en_i(test_en_i), + .clk_o (clk) + ); + + //////////////////////// + // Core instantiation // + //////////////////////// + + cve2_core #( + .PMPEnable (PMPEnable), + .PMPGranularity (PMPGranularity), + .PMPNumRegions (PMPNumRegions), + .MHPMCounterNum (MHPMCounterNum), + .MHPMCounterWidth (MHPMCounterWidth), + .RV32E (RV32E), + .RV32M (RV32M), + .RV32B (RV32B), + .DbgTriggerEn (DbgTriggerEn), + .DbgHwBreakNum (DbgHwBreakNum), + .DmHaltAddr (DmHaltAddr), + .DmExceptionAddr (DmExceptionAddr) + ) u_cve2_core ( + .clk_i(clk), + .rst_ni, + .test_en_i, + + .hart_id_i, + .boot_addr_i, + + .instr_req_o, + .instr_gnt_i, + .instr_rvalid_i, + .instr_addr_o, + .instr_rdata_i, + .instr_err_i, + + .data_req_o, + .data_gnt_i, + .data_rvalid_i, + .data_we_o, + .data_be_o, + .data_addr_o, + .data_wdata_o, + .data_rdata_i, + .data_err_i, + + .irq_software_i, + .irq_timer_i, + .irq_external_i, + .irq_fast_i, + .irq_nm_i, + .irq_pending_o(irq_pending), + + .debug_req_i, + .crash_dump_o, + +`ifdef RVFI + .rvfi_valid, + .rvfi_order, + .rvfi_insn, + .rvfi_trap, + .rvfi_halt, + .rvfi_intr, + .rvfi_mode, + .rvfi_ixl, + .rvfi_rs1_addr, + .rvfi_rs2_addr, + .rvfi_rs3_addr, + .rvfi_rs1_rdata, + .rvfi_rs2_rdata, + .rvfi_rs3_rdata, + .rvfi_rd_addr, + .rvfi_rd_wdata, + .rvfi_pc_rdata, + .rvfi_pc_wdata, + .rvfi_mem_addr, + .rvfi_mem_rmask, + .rvfi_mem_wmask, + .rvfi_mem_rdata, + .rvfi_mem_wdata, + .rvfi_ext_mip, + .rvfi_ext_nmi, + .rvfi_ext_debug_req, + .rvfi_ext_mcycle, +`endif + + .fetch_enable_i (fetch_enable_q), + .core_busy_o (core_busy_d) + ); + + //////////////////////// + // Rams Instantiation // + //////////////////////// + + prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; + logic unused_ram_inputs; + + assign unused_ram_cfg = ram_cfg_i; + assign unused_ram_inputs = (|NumAddrScrRounds); + + + // X checks for top-level outputs + `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) + `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) + + `ASSERT_KNOWN(IbexDataReqX, data_req_o) + `ASSERT_KNOWN_IF(IbexDataReqPayloadX, + {data_we_o, data_be_o, data_addr_o, data_wdata_o}, data_req_o) + + `ASSERT_KNOWN(IbexCoreSleepX, core_sleep_o) + + // X check for top-level inputs + `ASSERT_KNOWN(IbexTestEnX, test_en_i) + `ASSERT_KNOWN(IbexRamCfgX, ram_cfg_i) + `ASSERT_KNOWN(IbexHartIdX, hart_id_i) + `ASSERT_KNOWN(IbexBootAddrX, boot_addr_i) + + `ASSERT_KNOWN(IbexInstrGntX, instr_gnt_i) + `ASSERT_KNOWN(IbexInstrRValidX, instr_rvalid_i) + `ASSERT_KNOWN_IF(IbexInstrRPayloadX, + {instr_rdata_i, instr_err_i}, instr_rvalid_i) + + `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) + `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) + + `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) + + `ASSERT_KNOWN(IbexDebugReqX, debug_req_i) +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv similarity index 66% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv index f4384653..989e83d7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv @@ -3,30 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 /** - * Top level module of the ibex RISC-V core with tracing enabled + * Top level module of the cve2 RISC-V core with tracing enabled */ -module ibex_top_tracing import ibex_pkg::*; #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, +module cve2_top_tracing import cve2_pkg::*; #( parameter int unsigned MHPMCounterNum = 0, parameter int unsigned MHPMCounterWidth = 40, parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter regfile_e RegFile = RegFileFF, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter bit ICacheScramble = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -35,7 +20,6 @@ module ibex_top_tracing import ibex_pkg::*; #( input logic rst_ni, input logic test_en_i, // enable all clock gates for testing - input logic scan_rst_ni, input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, @@ -48,7 +32,6 @@ module ibex_top_tracing import ibex_pkg::*; #( input logic instr_rvalid_i, output logic [31:0] instr_addr_o, input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, input logic instr_err_i, // Data memory interface @@ -59,39 +42,27 @@ module ibex_top_tracing import ibex_pkg::*; #( output logic [3:0] data_be_o, output logic [31:0] data_addr_o, output logic [31:0] data_wdata_o, - output logic [6:0] data_wdata_intg_o, input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, input logic data_err_i, // Interrupt inputs input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt - // Scrambling Interface - input logic scramble_key_valid_i, - input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, - input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, - output logic scramble_req_o, - // Debug Interface input logic debug_req_i, output crash_dump_t crash_dump_o, - output logic double_fault_seen_o, // CPU Control Signals - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, + input logic fetch_enable_i, output logic core_sleep_o ); - // ibex_tracer relies on the signals from the RISC-V Formal Interface + // cve2_tracer relies on the signals from the RISC-V Formal Interface `ifndef RVFI $fatal("Fatal error: RVFI needs to be defined globally."); `endif @@ -136,35 +107,19 @@ module ibex_top_tracing import ibex_pkg::*; #( assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req; assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle; - ibex_top #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), + cve2_top #( .MHPMCounterNum ( MHPMCounterNum ), .MHPMCounterWidth ( MHPMCounterWidth ), .RV32E ( RV32E ), .RV32M ( RV32M ), - .RV32B ( RV32B ), - .RegFile ( RegFile ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), .BranchPredictor ( BranchPredictor ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), - .SecureIbex ( SecureIbex ), - .ICacheScramble ( ICacheScramble ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) - ) u_ibex_top ( + ) u_cve2_top ( .clk_i, .rst_ni, .test_en_i, - .scan_rst_ni, .ram_cfg_i, .hart_id_i, @@ -175,7 +130,6 @@ module ibex_top_tracing import ibex_pkg::*; #( .instr_rvalid_i, .instr_addr_o, .instr_rdata_i, - .instr_rdata_intg_i, .instr_err_i, .data_req_o, @@ -185,9 +139,7 @@ module ibex_top_tracing import ibex_pkg::*; #( .data_be_o, .data_addr_o, .data_wdata_o, - .data_wdata_intg_o, .data_rdata_i, - .data_rdata_intg_i, .data_err_i, .irq_software_i, @@ -196,14 +148,8 @@ module ibex_top_tracing import ibex_pkg::*; #( .irq_fast_i, .irq_nm_i, - .scramble_key_valid_i, - .scramble_key_i, - .scramble_nonce_i, - .scramble_req_o, - .debug_req_i, .crash_dump_o, - .double_fault_seen_o, .rvfi_valid, .rvfi_order, @@ -234,14 +180,11 @@ module ibex_top_tracing import ibex_pkg::*; #( .rvfi_ext_mcycle, .fetch_enable_i, - .alert_minor_o, - .alert_major_internal_o, - .alert_major_bus_o, .core_sleep_o ); - ibex_tracer - u_ibex_tracer ( + cve2_tracer + u_cve2_tracer ( .clk_i, .rst_ni, diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv similarity index 98% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv index bd36a214..707419e4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv @@ -12,12 +12,12 @@ * All traced instructions are written to a log file. By default, the log file is named * trace_core_.log, with being the 8 digit hart ID of the core being traced. * - * The file name base, defaulting to "trace_core" can be set using the "ibex_tracer_file_base" - * plusarg passed to the simulation, e.g. "+ibex_tracer_file_base=ibex_my_trace". The exact syntax + * The file name base, defaulting to "trace_core" can be set using the "cve2_tracer_file_base" + * plusarg passed to the simulation, e.g. "+cve2_tracer_file_base=cve2_my_trace". The exact syntax * of passing plusargs to a simulation depends on the simulator. * * The creation of the instruction trace is enabled by default but can be disabled for a simulation. - * This behaviour is controlled by the plusarg "ibex_tracer_enable". Use "ibex_tracer_enable=0" to + * This behaviour is controlled by the plusarg "cve2_tracer_enable". Use "cve2_tracer_enable=0" to * disable the tracer. * * The trace contains six columns, separated by tabs: @@ -34,7 +34,7 @@ * to the one produced by objdump. This simplifies the correlation between the static program * information from the objdump-generated disassembly, and the runtime information from this tracer. */ -module ibex_tracer ( +module cve2_tracer ( input logic clk_i, input logic rst_ni, @@ -79,7 +79,7 @@ module ibex_tracer ( logic [ 1:0] unused_rvfi_mode = rvfi_mode; logic [ 1:0] unused_rvfi_ixl = rvfi_ixl; - import ibex_tracer_pkg::*; + import cve2_tracer_pkg::*; int file_handle; string file_name; @@ -98,7 +98,7 @@ module ibex_tracer ( logic trace_log_enable; initial begin - if ($value$plusargs("ibex_tracer_enable=%b", trace_log_enable)) begin + if ($value$plusargs("cve2_tracer_enable=%b", trace_log_enable)) begin if (trace_log_enable == 1'b0) begin $display("%m: Instruction trace disabled."); end @@ -112,7 +112,7 @@ module ibex_tracer ( if (file_handle == 32'h0) begin string file_name_base = "trace_core"; - void'($value$plusargs("ibex_tracer_file_base=%s", file_name_base)); + void'($value$plusargs("cve2_tracer_file_base=%s", file_name_base)); $sformat(file_name, "%s_%h.log", file_name_base, hart_id_i); $display("%m: Writing execution trace to %s", file_name); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv index 6dbbfc90..700dd37b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv @@ -3,8 +3,8 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -package ibex_tracer_pkg; - import ibex_pkg::*; +package cve2_tracer_pkg; + import cve2_pkg::*; parameter logic [1:0] OPCODE_C0 = 2'b00; parameter logic [1:0] OPCODE_C1 = 2'b01; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv new file mode 100644 index 00000000..dee73f74 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv @@ -0,0 +1,69 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Writeback passthrough + * + * The writeback stage is not present therefore this module acts as + * a simple passthrough to write data direct to the register file. + */ + +`include "prim_assert.sv" +`include "dv_fcov_macros.svh" + +module cve2_wb #( +) ( + input logic clk_i, + input logic rst_ni, + input logic en_wb_i, + + input logic instr_is_compressed_id_i, + input logic instr_perf_count_id_i, + + output logic perf_instr_ret_wb_o, + output logic perf_instr_ret_compressed_wb_o, + + input logic [4:0] rf_waddr_id_i, + input logic [31:0] rf_wdata_id_i, + input logic rf_we_id_i, + + input logic [31:0] rf_wdata_lsu_i, + input logic rf_we_lsu_i, + + output logic [4:0] rf_waddr_wb_o, + output logic [31:0] rf_wdata_wb_o, + output logic rf_we_wb_o, + + input logic lsu_resp_valid_i, + input logic lsu_resp_err_i +); + + import cve2_pkg::*; + + // 0 == RF write from ID + // 1 == RF write from LSU + logic [31:0] rf_wdata_wb_mux [2]; + logic [1:0] rf_wdata_wb_mux_we; + + // without writeback stage just pass through register write signals + assign rf_waddr_wb_o = rf_waddr_id_i; + assign rf_wdata_wb_mux[0] = rf_wdata_id_i; + assign rf_wdata_wb_mux_we[0] = rf_we_id_i; + + // Increment instruction retire counters for valid instructions which are not lsu errors. + assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i & + ~(lsu_resp_valid_i & lsu_resp_err_i); + assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i; + + assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i; + assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; + + // RF write data can come from ID results (all RF writes that aren't because of loads will come + // from here) or the LSU (RF writes for load data) + assign rf_wdata_wb_o = ({32{rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | + ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); + assign rf_we_wb_o = |rf_wdata_wb_mux_we; + + `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f deleted file mode 100644 index 83e8396b..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f +++ /dev/null @@ -1,17 +0,0 @@ -ibex_pkg.sv -ibex_alu.sv -ibex_compressed_decoder.sv -ibex_controller.sv -ibex_counter.sv -ibex_cs_registers.sv -ibex_decoder.sv -ibex_ex_block.sv -ibex_id_stage.sv -ibex_if_stage.sv -ibex_load_store_unit.sv -ibex_multdiv_slow.sv -ibex_multdiv_fast.sv -ibex_prefetch_buffer.sv -ibex_fetch_fifo.sv -ibex_register_file_ff.sv -ibex_core.sv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv deleted file mode 100644 index ba33adc4..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Dummy instruction module - * - * Provides pseudo-randomly inserted fake instructions for secure code obfuscation - */ - -// SEC_CM: CTRL_FLOW.UNPREDICTABLE -module ibex_dummy_instr import ibex_pkg::*; #( - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - - // Interface to CSRs - input logic dummy_instr_en_i, - input logic [2:0] dummy_instr_mask_i, - input logic dummy_instr_seed_en_i, - input logic [31:0] dummy_instr_seed_i, - - // Interface to IF stage - input logic fetch_valid_i, - input logic id_in_ready_i, - output logic insert_dummy_instr_o, - output logic [31:0] dummy_instr_data_o -); - - localparam int unsigned TIMEOUT_CNT_W = 5; - localparam int unsigned OP_W = 5; - - typedef enum logic [1:0] { - DUMMY_ADD = 2'b00, - DUMMY_MUL = 2'b01, - DUMMY_DIV = 2'b10, - DUMMY_AND = 2'b11 - } dummy_instr_e; - - typedef struct packed { - dummy_instr_e instr_type; - logic [OP_W-1:0] op_b; - logic [OP_W-1:0] op_a; - logic [TIMEOUT_CNT_W-1:0] cnt; - } lfsr_data_t; - localparam int unsigned LFSR_OUT_W = $bits(lfsr_data_t); - - lfsr_data_t lfsr_data; - logic [TIMEOUT_CNT_W-1:0] dummy_cnt_incr, dummy_cnt_threshold; - logic [TIMEOUT_CNT_W-1:0] dummy_cnt_d, dummy_cnt_q; - logic dummy_cnt_en; - logic lfsr_en; - logic [LFSR_OUT_W-1:0] lfsr_state; - logic insert_dummy_instr; - logic [6:0] dummy_set; - logic [2:0] dummy_opcode; - logic [31:0] dummy_instr; - logic [31:0] dummy_instr_seed_q, dummy_instr_seed_d; - - // Shift the LFSR every time we insert an instruction - assign lfsr_en = insert_dummy_instr & id_in_ready_i; - - assign dummy_instr_seed_d = dummy_instr_seed_q ^ dummy_instr_seed_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_instr_seed_q <= '0; - end else if (dummy_instr_seed_en_i) begin - dummy_instr_seed_q <= dummy_instr_seed_d; - end - end - - prim_lfsr #( - .LfsrDw ( LfsrWidth ), - .StateOutDw ( LFSR_OUT_W ), - .DefaultSeed ( RndCnstLfsrSeed ), - .StatePermEn ( 1'b1 ), - .StatePerm ( RndCnstLfsrPerm ) - ) lfsr_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .seed_en_i ( dummy_instr_seed_en_i ), - .seed_i ( dummy_instr_seed_d ), - .lfsr_en_i ( lfsr_en ), - .entropy_i ( '0 ), - .state_o ( lfsr_state ) - ); - - // Extract fields from LFSR - assign lfsr_data = lfsr_data_t'(lfsr_state); - - // Set count threshold for inserting a new instruction. This is the pseudo-random value from the - // LFSR with a mask applied (based on CSR config data) to shorten the period if required. - assign dummy_cnt_threshold = lfsr_data.cnt & {dummy_instr_mask_i,{TIMEOUT_CNT_W-3{1'b1}}}; - assign dummy_cnt_incr = dummy_cnt_q + {{TIMEOUT_CNT_W-1{1'b0}},1'b1}; - // Clear the counter everytime a new instruction is inserted - assign dummy_cnt_d = insert_dummy_instr ? '0 : dummy_cnt_incr; - // Increment the counter for each executed instruction while dummy instuctions are - // enabled. - assign dummy_cnt_en = dummy_instr_en_i & id_in_ready_i & - (fetch_valid_i | insert_dummy_instr); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_cnt_q <= '0; - end else if (dummy_cnt_en) begin - dummy_cnt_q <= dummy_cnt_d; - end - end - - // Insert a dummy instruction each time the counter hits the threshold - assign insert_dummy_instr = dummy_instr_en_i & (dummy_cnt_q == dummy_cnt_threshold); - - // Encode instruction - always_comb begin - unique case (lfsr_data.instr_type) - DUMMY_ADD: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b000; - end - DUMMY_MUL: begin - dummy_set = 7'b0000001; - dummy_opcode = 3'b000; - end - DUMMY_DIV: begin - dummy_set = 7'b0000001; - dummy_opcode = 3'b100; - end - DUMMY_AND: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b111; - end - default: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b000; - end - endcase - end - - // SET RS2 RS1 OP RD - assign dummy_instr = {dummy_set, lfsr_data.op_b, lfsr_data.op_a, dummy_opcode, 5'h00, 7'h33}; - - // Assign outputs - assign insert_dummy_instr_o = insert_dummy_instr; - assign dummy_instr_data_o = dummy_instr; - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv deleted file mode 100644 index c15a29b5..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv +++ /dev/null @@ -1,1165 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Instruction cache - * - * Provides an instruction cache along with cache management, instruction buffering and prefetching - */ - -`include "prim_assert.sv" - -module ibex_icache import ibex_pkg::*; #( - parameter bit ICacheECC = 1'b0, - parameter bit ResetAll = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - // Only cache branch targets - parameter bit BranchCache = 1'b0 -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - - // Signal that the core would like instructions - input logic req_i, - - // Set the cache's address counter - input logic branch_i, - input logic branch_mispredict_i, - input logic [31:0] mispredict_addr_i, - input logic [31:0] addr_i, - - // IF stage interface: Pass fetched instructions to the core - input logic ready_i, - output logic valid_o, - output logic [31:0] rdata_o, - output logic [31:0] addr_o, - output logic err_o, - output logic err_plus2_o, - - // Instruction memory / interconnect interface: Fetch instruction data from memory - output logic instr_req_o, - input logic instr_gnt_i, - output logic [31:0] instr_addr_o, - input logic [BUS_SIZE-1:0] instr_rdata_i, - input logic instr_err_i, - input logic instr_rvalid_i, - - // RAM IO - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - // Cache status - input logic icache_enable_i, - input logic icache_inval_i, - output logic busy_o, - output logic ecc_error_o -); - - // Number of fill buffers (must be >= 2) - localparam int unsigned NUM_FB = 4; - // Request throttling threshold - localparam int unsigned FB_THRESHOLD = NUM_FB - 2; - - // Prefetch signals - logic [ADDR_W-1:0] lookup_addr_aligned; - logic [ADDR_W-1:0] prefetch_addr_d, prefetch_addr_q; - logic prefetch_addr_en; - logic branch_or_mispredict; - // Cache pipelipe IC0 signals - logic lookup_throttle; - logic lookup_req_ic0; - logic [ADDR_W-1:0] lookup_addr_ic0; - logic [IC_INDEX_W-1:0] lookup_index_ic0; - logic fill_req_ic0; - logic [IC_INDEX_W-1:0] fill_index_ic0; - logic [IC_TAG_SIZE-1:0] fill_tag_ic0; - logic [IC_LINE_SIZE-1:0] fill_wdata_ic0; - logic lookup_grant_ic0; - logic lookup_actual_ic0; - logic fill_grant_ic0; - logic tag_req_ic0; - logic [IC_INDEX_W-1:0] tag_index_ic0; - logic [IC_NUM_WAYS-1:0] tag_banks_ic0; - logic tag_write_ic0; - logic [TagSizeECC-1:0] tag_wdata_ic0; - logic data_req_ic0; - logic [IC_INDEX_W-1:0] data_index_ic0; - logic [IC_NUM_WAYS-1:0] data_banks_ic0; - logic data_write_ic0; - logic [LineSizeECC-1:0] data_wdata_ic0; - // Cache pipelipe IC1 signals - logic [TagSizeECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] data_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] hit_data_ecc_ic1; - logic [IC_LINE_SIZE-1:0] hit_data_ic1; - logic lookup_valid_ic1; - logic [ADDR_W-1:IC_INDEX_HI+1] lookup_addr_ic1; - logic [IC_NUM_WAYS-1:0] tag_match_ic1; - logic tag_hit_ic1; - logic [IC_NUM_WAYS-1:0] tag_invalid_ic1; - logic [IC_NUM_WAYS-1:0] lowest_invalid_way_ic1; - logic [IC_NUM_WAYS-1:0] round_robin_way_ic1, round_robin_way_q; - logic [IC_NUM_WAYS-1:0] sel_way_ic1; - logic ecc_err_ic1; - logic ecc_write_req; - logic [IC_NUM_WAYS-1:0] ecc_write_ways; - logic [IC_INDEX_W-1:0] ecc_write_index; - // Fill buffer signals - logic [$clog2(NUM_FB)-1:0] fb_fill_level; - logic fill_cache_new; - logic fill_new_alloc; - logic fill_spec_req, fill_spec_done, fill_spec_hold; - logic [NUM_FB-1:0][NUM_FB-1:0] fill_older_d, fill_older_q; - logic [NUM_FB-1:0] fill_alloc_sel, fill_alloc; - logic [NUM_FB-1:0] fill_busy_d, fill_busy_q; - logic [NUM_FB-1:0] fill_done; - logic [NUM_FB-1:0] fill_in_ic1; - logic [NUM_FB-1:0] fill_stale_d, fill_stale_q; - logic [NUM_FB-1:0] fill_cache_d, fill_cache_q; - logic [NUM_FB-1:0] fill_hit_ic1, fill_hit_d, fill_hit_q; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_cnt_d, fill_ext_cnt_q; - logic [NUM_FB-1:0] fill_ext_hold_d, fill_ext_hold_q; - logic [NUM_FB-1:0] fill_ext_done_d, fill_ext_done_q; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_rvd_cnt_d, fill_rvd_cnt_q; - logic [NUM_FB-1:0] fill_rvd_done; - logic [NUM_FB-1:0] fill_ram_done_d, fill_ram_done_q; - logic [NUM_FB-1:0] fill_out_grant; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_out_cnt_d, fill_out_cnt_q; - logic [NUM_FB-1:0] fill_out_done; - logic [NUM_FB-1:0] fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req; - logic [NUM_FB-1:0] fill_data_sel, fill_data_reg; - logic [NUM_FB-1:0] fill_data_hit, fill_data_rvd; - logic [NUM_FB-1:0][IC_LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_beat, fill_rvd_beat; - logic [NUM_FB-1:0] fill_ext_arb, fill_ram_arb, fill_out_arb; - logic [NUM_FB-1:0] fill_rvd_arb; - logic [NUM_FB-1:0] fill_entry_en; - logic [NUM_FB-1:0] fill_addr_en; - logic [NUM_FB-1:0] fill_way_en; - logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_data_en; - logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_err_d, fill_err_q; - logic [ADDR_W-1:0] fill_addr_q [NUM_FB]; - logic [IC_NUM_WAYS-1:0] fill_way_q [NUM_FB]; - logic [IC_LINE_SIZE-1:0] fill_data_d [NUM_FB]; - logic [IC_LINE_SIZE-1:0] fill_data_q [NUM_FB]; - logic [ADDR_W-1:BUS_W] fill_ext_req_addr; - logic [ADDR_W-1:0] fill_ram_req_addr; - logic [IC_NUM_WAYS-1:0] fill_ram_req_way; - logic [IC_LINE_SIZE-1:0] fill_ram_req_data; - logic [IC_LINE_SIZE-1:0] fill_out_data; - logic [IC_LINE_BEATS-1:0] fill_out_err; - // External req signals - logic instr_req; - logic [ADDR_W-1:BUS_W] instr_addr; - // Data output signals - logic skid_complete_instr; - logic skid_ready; - logic output_compressed; - logic skid_valid_d, skid_valid_q, skid_en; - logic [15:0] skid_data_d, skid_data_q; - logic skid_err_q; - logic output_valid; - logic addr_incr_two; - logic output_addr_en; - logic [ADDR_W-1:1] output_addr_incr; - logic [ADDR_W-1:1] output_addr_d, output_addr_q; - logic [15:0] output_data_lo, output_data_hi; - logic data_valid, output_ready; - logic [IC_LINE_SIZE-1:0] line_data; - logic [IC_LINE_BEATS-1:0] line_err; - logic [31:0] line_data_muxed; - logic line_err_muxed; - logic [31:0] output_data; - logic output_err; - // Invalidations - logic start_inval, inval_done; - logic inval_lock, inval_req_d, inval_req_q; - logic reset_inval_q; - logic inval_prog_d, inval_prog_q; - logic [IC_INDEX_W-1:0] inval_index_d, inval_index_q; - - ////////////////////////// - // Instruction prefetch // - ////////////////////////// - - assign branch_or_mispredict = branch_i | branch_mispredict_i; - - assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}}; - - // The prefetch address increments by one cache line for each granted request. - // This address is also updated if there is a branch that is not granted, since the target - // address (addr_i) is only valid for one cycle while branch_i is high. - - // The captured branch target address is not forced to be aligned since the offset in the cache - // line must also be recorded for later use by the fill buffers. - assign prefetch_addr_d = - lookup_grant_ic0 ? (lookup_addr_aligned + - {{ADDR_W-IC_LINE_W-1{1'b0}}, 1'b1, {IC_LINE_W{1'b0}}}) : - branch_i ? addr_i : - mispredict_addr_i; - - assign prefetch_addr_en = branch_or_mispredict | lookup_grant_ic0; - - if (ResetAll) begin : g_prefetch_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - prefetch_addr_q <= '0; - end else if (prefetch_addr_en) begin - prefetch_addr_q <= prefetch_addr_d; - end - end - end else begin : g_prefetch_addr_nr - always_ff @(posedge clk_i) begin - if (prefetch_addr_en) begin - prefetch_addr_q <= prefetch_addr_d; - end - end - end - - //////////////////////// - // Pipeline stage IC0 // - //////////////////////// - - // Cache lookup - assign lookup_throttle = (fb_fill_level > FB_THRESHOLD[$clog2(NUM_FB)-1:0]); - - assign lookup_req_ic0 = req_i & ~&fill_busy_q & (branch_or_mispredict | ~lookup_throttle) & - ~ecc_write_req; - assign lookup_addr_ic0 = branch_i ? addr_i : - branch_mispredict_i ? mispredict_addr_i : - prefetch_addr_q; - assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W]; - - // Cache write - assign fill_req_ic0 = (|fill_ram_req); - assign fill_index_ic0 = fill_ram_req_addr[IC_INDEX_HI:IC_LINE_W]; - assign fill_tag_ic0 = {(~inval_prog_q & ~ecc_write_req), - fill_ram_req_addr[ADDR_W-1:IC_INDEX_HI+1]}; - assign fill_wdata_ic0 = fill_ram_req_data; - - // Arbitrated signals - lookups have highest priority - assign lookup_grant_ic0 = lookup_req_ic0; - assign fill_grant_ic0 = fill_req_ic0 & ~lookup_req_ic0 & ~inval_prog_q & - ~ecc_write_req; - // Qualified lookup grant to mask ram signals in IC1 if access was not made - assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q & - ~icache_inval_i & ~inval_lock & ~start_inval; - - // Tagram - assign tag_req_ic0 = lookup_req_ic0 | fill_req_ic0 | inval_prog_q | ecc_write_req; - assign tag_index_ic0 = inval_prog_q ? inval_index_q : - ecc_write_req ? ecc_write_index : - fill_grant_ic0 ? fill_index_ic0 : - lookup_index_ic0; - assign tag_banks_ic0 = ecc_write_req ? ecc_write_ways : - fill_grant_ic0 ? fill_ram_req_way : - {IC_NUM_WAYS{1'b1}}; - assign tag_write_ic0 = fill_grant_ic0 | inval_prog_q | ecc_write_req; - - // Dataram - assign data_req_ic0 = lookup_req_ic0 | fill_req_ic0; - assign data_index_ic0 = tag_index_ic0; - assign data_banks_ic0 = tag_banks_ic0; - assign data_write_ic0 = tag_write_ic0; - - // Append ECC checkbits to write data if required - if (ICacheECC) begin : gen_ecc_wdata - // SEC_CM: ICACHE.MEM.INTEGRITY - // Tagram ECC - // Reuse the same ecc encoding module for larger cache sizes by padding with zeros - logic [21:0] tag_ecc_input_padded; - logic [27:0] tag_ecc_output_padded; - logic [22-IC_TAG_SIZE:0] unused_tag_ecc_output; - - assign tag_ecc_input_padded = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0}; - assign unused_tag_ecc_output = tag_ecc_output_padded[21:IC_TAG_SIZE-1]; - - prim_secded_inv_28_22_enc tag_ecc_enc ( - .data_i (tag_ecc_input_padded), - .data_o (tag_ecc_output_padded) - ); - - assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[IC_TAG_SIZE-1:0]}; - - // Dataram ECC - for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_inv_39_32_enc data_ecc_enc ( - .data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]), - .data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC]) - ); - end - - end else begin : gen_noecc_wdata - assign tag_wdata_ic0 = fill_tag_ic0; - assign data_wdata_ic0 = fill_wdata_ic0; - end - - //////////////// - // IC0 -> IC1 // - //////////////// - - // Tag RAMs outputs - assign ic_tag_req_o = {IC_NUM_WAYS{tag_req_ic0}} & tag_banks_ic0; - assign ic_tag_write_o = tag_write_ic0; - assign ic_tag_addr_o = tag_index_ic0; - assign ic_tag_wdata_o = tag_wdata_ic0; - - // Tag RAMs inputs - assign tag_rdata_ic1 = ic_tag_rdata_i; - - // Data RAMs outputs - assign ic_data_req_o = {IC_NUM_WAYS{data_req_ic0}} & data_banks_ic0; - assign ic_data_write_o = data_write_ic0; - assign ic_data_addr_o = data_index_ic0; - assign ic_data_wdata_o = data_wdata_ic0; - - // Data RAMs inputs - assign data_rdata_ic1 = ic_data_rdata_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_valid_ic1 <= 1'b0; - end else begin - lookup_valid_ic1 <= lookup_actual_ic0; - end - end - - if (ResetAll) begin : g_lookup_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_addr_ic1 <= '0; - fill_in_ic1 <= '0; - end else if (lookup_grant_ic0) begin - lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1]; - fill_in_ic1 <= fill_alloc_sel; - end - end - end else begin : g_lookup_addr_nr - always_ff @(posedge clk_i) begin - if (lookup_grant_ic0) begin - lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1]; - fill_in_ic1 <= fill_alloc_sel; - end - end - end - - //////////////////////// - // Pipeline stage IC1 // - //////////////////////// - - // Tag matching - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_match - assign tag_match_ic1[way] = (tag_rdata_ic1[way][IC_TAG_SIZE-1:0] == - {1'b1,lookup_addr_ic1[ADDR_W-1:IC_INDEX_HI+1]}); - assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][IC_TAG_SIZE-1]; - end - - assign tag_hit_ic1 = |tag_match_ic1; - - // Hit data mux - always_comb begin - hit_data_ecc_ic1 = 'b0; - for (int way = 0; way < IC_NUM_WAYS; way++) begin - if (tag_match_ic1[way]) begin - hit_data_ecc_ic1 |= data_rdata_ic1[way]; - end - end - end - - // Way selection for allocations to the cache (onehot signals) - // 1 first invalid way - // 2 global round-robin (pseudorandom) way - assign lowest_invalid_way_ic1[0] = tag_invalid_ic1[0]; - assign round_robin_way_ic1[0] = round_robin_way_q[IC_NUM_WAYS-1]; - for (genvar way = 1; way < IC_NUM_WAYS; way++) begin : gen_lowest_way - assign lowest_invalid_way_ic1[way] = tag_invalid_ic1[way] & ~|tag_invalid_ic1[way-1:0]; - assign round_robin_way_ic1[way] = round_robin_way_q[way-1]; - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - round_robin_way_q <= {{IC_NUM_WAYS-1{1'b0}}, 1'b1}; - end else if (lookup_valid_ic1) begin - round_robin_way_q <= round_robin_way_ic1; - end - end - - assign sel_way_ic1 = |tag_invalid_ic1 ? lowest_invalid_way_ic1 : - round_robin_way_q; - - // ECC checking logic - if (ICacheECC) begin : gen_data_ecc_checking - // SEC_CM: ICACHE.MEM.INTEGRITY - logic [IC_NUM_WAYS-1:0] tag_err_ic1; - logic [IC_LINE_BEATS*2-1:0] data_err_ic1; - logic ecc_correction_write_d, ecc_correction_write_q; - logic [IC_NUM_WAYS-1:0] ecc_correction_ways_d, ecc_correction_ways_q; - logic [IC_INDEX_W-1:0] lookup_index_ic1, ecc_correction_index_q; - - // Tag ECC checking - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_ecc - logic [1:0] tag_err_bank_ic1; - logic [27:0] tag_rdata_padded_ic1; - - // Expand the tag rdata with extra padding if the tag size is less than the maximum - assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TagSizeECC-1-:6], - {22-IC_TAG_SIZE{1'b0}}, - tag_rdata_ic1[way][IC_TAG_SIZE-1:0]}; - - prim_secded_inv_28_22_dec data_ecc_dec ( - .data_i (tag_rdata_padded_ic1), - .data_o (), - .syndrome_o (), - .err_o (tag_err_bank_ic1) - ); - assign tag_err_ic1[way] = |tag_err_bank_ic1; - end - - // Data ECC checking - // Note - could generate for all ways and mux after - for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_inv_39_32_dec data_ecc_dec ( - .data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]), - .data_o (), - .syndrome_o (), - .err_o (data_err_ic1[bank*2+:2]) - ); - - assign hit_data_ic1[bank*BUS_SIZE+:BUS_SIZE] = - hit_data_ecc_ic1[bank*BusSizeECC+:BUS_SIZE]; - - end - - // Tag ECC across all ways is always expected to be correct so the check does not need to be - // qualified by hit or tag valid. Initial (invalid with correct ECC) tags are written on reset - // and all further tag writes produce correct ECC. For data ECC no initialisation is done on - // reset so unused data (in particular those ways that don't have a valid tag) may have - // incorrect ECC. We only check data ECC where tags indicate it is valid and we have hit on it. - assign ecc_err_ic1 = lookup_valid_ic1 & (((|data_err_ic1) & tag_hit_ic1) | (|tag_err_ic1)); - - // Error correction - // All ways will be invalidated on a tag error to prevent X-propagation from data_err_ic1 on - // spurious hits. Also prevents the same line being allocated twice when there was a true - // hit and a spurious hit. - assign ecc_correction_ways_d = {IC_NUM_WAYS{|tag_err_ic1}} | - (tag_match_ic1 & {IC_NUM_WAYS{|data_err_ic1}}); - assign ecc_correction_write_d = ecc_err_ic1; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - ecc_correction_write_q <= 1'b0; - end else begin - ecc_correction_write_q <= ecc_correction_write_d; - end - end - - // The index is required in IC1 only when ECC is configured so is registered here - if (ResetAll) begin : g_lookup_ind_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_index_ic1 <= '0; - end else if (lookup_grant_ic0) begin - lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W]; - end - end - end else begin : g_lookup_ind_nr - always_ff @(posedge clk_i) begin - if (lookup_grant_ic0) begin - lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W]; - end - end - end - - // Store the ways with errors to be invalidated - if (ResetAll) begin : g_ecc_correction_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - ecc_correction_ways_q <= '0; - ecc_correction_index_q <= '0; - end else if (ecc_err_ic1) begin - ecc_correction_ways_q <= ecc_correction_ways_d; - ecc_correction_index_q <= lookup_index_ic1; - end - end - end else begin : g_ecc_correction_nr - always_ff @(posedge clk_i) begin - if (ecc_err_ic1) begin - ecc_correction_ways_q <= ecc_correction_ways_d; - ecc_correction_index_q <= lookup_index_ic1; - end - end - end - - assign ecc_write_req = ecc_correction_write_q; - assign ecc_write_ways = ecc_correction_ways_q; - assign ecc_write_index = ecc_correction_index_q; - - assign ecc_error_o = ecc_err_ic1; - end else begin : gen_no_data_ecc - assign ecc_err_ic1 = 1'b0; - assign ecc_write_req = 1'b0; - assign ecc_write_ways = '0; - assign ecc_write_index = '0; - assign hit_data_ic1 = hit_data_ecc_ic1; - - assign ecc_error_o = 1'b0; - end - - /////////////////////////////// - // Cache allocation decision // - /////////////////////////////// - - if (BranchCache) begin : gen_caching_logic - - // Cache branch target + a number of subsequent lines - localparam int unsigned CACHE_AHEAD = 2; - localparam int unsigned CACHE_CNT_W = (CACHE_AHEAD == 1) ? 1 : $clog2(CACHE_AHEAD) + 1; - logic cache_cnt_dec; - logic [CACHE_CNT_W-1:0] cache_cnt_d, cache_cnt_q; - - assign cache_cnt_dec = lookup_grant_ic0 & (|cache_cnt_q); - assign cache_cnt_d = branch_i ? CACHE_AHEAD[CACHE_CNT_W-1:0] : - (cache_cnt_q - {{CACHE_CNT_W-1{1'b0}},cache_cnt_dec}); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - cache_cnt_q <= '0; - end else begin - cache_cnt_q <= cache_cnt_d; - end - end - - assign fill_cache_new = (branch_i | (|cache_cnt_q)) & icache_enable_i & - ~icache_inval_i & ~inval_lock & ~inval_prog_q; - - end else begin : gen_cache_all - - // Cache all missing fetches - assign fill_cache_new = icache_enable_i & ~start_inval & ~inval_prog_q; - end - - ////////////////////////// - // Fill buffer tracking // - ////////////////////////// - - always_comb begin - fb_fill_level = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_busy_q[i] & ~fill_stale_q[i]) begin - fb_fill_level += {{$clog2(NUM_FB) - 1{1'b0}}, 1'b1}; - end - end - end - - // Allocate a new buffer for every granted lookup - assign fill_new_alloc = lookup_grant_ic0; - // Track whether a speculative external request was made from IC0, and whether it was granted - // Speculative requests are only made for branches, or if the cache is disabled - assign fill_spec_req = (~icache_enable_i | branch_or_mispredict) & ~|fill_ext_req; - assign fill_spec_done = fill_spec_req & instr_gnt_i; - assign fill_spec_hold = fill_spec_req & ~instr_gnt_i; - - for (genvar fb = 0; fb < NUM_FB; fb++) begin : gen_fbs - - ///////////////////////////// - // Fill buffer allocations // - ///////////////////////////// - - // Allocate the lowest available buffer - if (fb == 0) begin : gen_fb_zero - assign fill_alloc_sel[fb] = ~fill_busy_q[fb]; - end else begin : gen_fb_rest - assign fill_alloc_sel[fb] = ~fill_busy_q[fb] & (&fill_busy_q[fb-1:0]); - end - - assign fill_alloc[fb] = fill_alloc_sel[fb] & fill_new_alloc; - assign fill_busy_d[fb] = fill_alloc[fb] | (fill_busy_q[fb] & ~fill_done[fb]); - - // Track which other fill buffers are older than this one (for age-based arbitration) - // TODO sparsify - assign fill_older_d[fb] = (fill_alloc[fb] ? fill_busy_q : fill_older_q[fb]) & ~fill_done; - - // A fill buffer can release once all its actions are completed - // all data written to the cache (unless hit or error) - assign fill_done[fb] = (fill_ram_done_q[fb] | fill_hit_q[fb] | ~fill_cache_q[fb] | - (|fill_err_q[fb])) & - // all data output unless stale due to intervening branch - (fill_out_done[fb] | fill_stale_q[fb] | branch_or_mispredict) & - // all external requests completed - fill_rvd_done[fb]; - - ///////////////////////////////// - // Fill buffer status tracking // - ///////////////////////////////// - - // Track staleness (requests become stale when a branch intervenes) - assign fill_stale_d[fb] = fill_busy_q[fb] & (branch_or_mispredict | fill_stale_q[fb]); - // Track whether or not this request should allocate to the cache - // Any invalidation or disabling of the cache while the buffer is busy will stop allocation - assign fill_cache_d[fb] = (fill_alloc[fb] & fill_cache_new) | - (fill_cache_q[fb] & fill_busy_q[fb] & - icache_enable_i & ~icache_inval_i & ~inval_lock); - // Record whether the request hit in the cache - assign fill_hit_ic1[fb] = lookup_valid_ic1 & fill_in_ic1[fb] & tag_hit_ic1 & ~ecc_err_ic1; - assign fill_hit_d[fb] = fill_hit_ic1[fb] | (fill_hit_q[fb] & fill_busy_q[fb]); - - /////////////////////////////////////////// - // Fill buffer external request tracking // - /////////////////////////////////////////// - - // Make an external request - assign fill_ext_req[fb] = fill_busy_q[fb] & ~fill_ext_done_d[fb]; - - // Count the number of completed external requests (each line requires IC_LINE_BEATS requests) - assign fill_ext_cnt_d[fb] = fill_alloc[fb] ? - {{IC_LINE_BEATS_W{1'b0}},fill_spec_done} : - (fill_ext_cnt_q[fb] + {{IC_LINE_BEATS_W{1'b0}}, - fill_ext_arb[fb] & instr_gnt_i}); - // External request must be held until granted - assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) | - (fill_ext_arb[fb] & ~instr_gnt_i); - // External requests are completed when the counter is filled or when the request is cancelled - assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][IC_LINE_BEATS_W] | - // external requests are considered complete if the request hit - fill_hit_ic1[fb] | fill_hit_q[fb] | - // cancel if the line won't be cached and, it is stale - (~fill_cache_q[fb] & (branch_or_mispredict | fill_stale_q[fb] | - // or we're already at the end of the line - fill_ext_beat[fb][IC_LINE_BEATS_W]))) & - // can't cancel while we are waiting for a grant on the bus - ~fill_ext_hold_q[fb] & fill_busy_q[fb]; - // Track whether this fill buffer expects to receive beats of data - assign fill_rvd_exp[fb] = fill_busy_q[fb] & ~fill_rvd_done[fb]; - // Count the number of rvalid beats received - assign fill_rvd_cnt_d[fb] = fill_alloc[fb] ? '0 : - (fill_rvd_cnt_q[fb] + - {{IC_LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]}); - // External data is complete when all issued external requests have received their data - assign fill_rvd_done[fb] = (fill_ext_done_q[fb] & ~fill_ext_hold_q[fb]) & - (fill_rvd_cnt_q[fb] == fill_ext_cnt_q[fb]); - - ////////////////////////////////////// - // Fill buffer data output tracking // - ////////////////////////////////////// - - // Send data to the IF stage for requests that are not stale, have not completed their - // data output, and have data available to send. - // Data is available if: - // - The request hit in the cache - // - Buffered data is available (fill_rvd_cnt_q is ahead of fill_out_cnt_q) - // - Data is available from the bus this cycle (fill_rvd_arb) - assign fill_out_req[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] & - (fill_hit_ic1[fb] | fill_hit_q[fb] | - (fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]); - - // Calculate when a beat of data is output. Any ECC error squashes the output that cycle. - assign fill_out_grant[fb] = fill_out_arb[fb] & output_ready; - - // Count the beats of data output to the IF stage - assign fill_out_cnt_d[fb] = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[IC_LINE_W-1:BUS_W]} : - (fill_out_cnt_q[fb] + - {{IC_LINE_BEATS_W{1'b0}},fill_out_grant[fb]}); - // Data output complete when the counter fills - assign fill_out_done[fb] = fill_out_cnt_q[fb][IC_LINE_BEATS_W]; - - ////////////////////////////////////// - // Fill buffer ram request tracking // - ////////////////////////////////////// - - // make a fill request once all data beats received - assign fill_ram_req[fb] = fill_busy_q[fb] & fill_rvd_cnt_q[fb][IC_LINE_BEATS_W] & - // unless the request hit, was non-allocating or got an error - ~fill_hit_q[fb] & fill_cache_q[fb] & ~|fill_err_q[fb] & - // or the request was already completed - ~fill_ram_done_q[fb]; - - // Record when a cache allocation request has been completed - assign fill_ram_done_d[fb] = fill_ram_arb[fb] | (fill_ram_done_q[fb] & fill_busy_q[fb]); - - ////////////////////////////// - // Fill buffer line offsets // - ////////////////////////////// - - // When we branch into the middle of a line, the output count will not start from zero. This - // beat count is used to know which incoming rdata beats are relevant. - assign fill_ext_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} + - fill_ext_cnt_q[fb][IC_LINE_BEATS_W:0]; - assign fill_ext_off[fb] = fill_ext_beat[fb][IC_LINE_BEATS_W-1:0]; - assign fill_rvd_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} + - fill_rvd_cnt_q[fb][IC_LINE_BEATS_W:0]; - assign fill_rvd_off[fb] = fill_rvd_beat[fb][IC_LINE_BEATS_W-1:0]; - - ///////////////////////////// - // Fill buffer arbitration // - ///////////////////////////// - - // Age based arbitration - all these signals are one-hot - assign fill_ext_arb[fb] = fill_ext_req[fb] & ~|(fill_ext_req & fill_older_q[fb]); - assign fill_ram_arb[fb] = fill_ram_req[fb] & fill_grant_ic0 & - ~|(fill_ram_req & fill_older_q[fb]); - // Calculate which fill buffer is the oldest one which still needs to output data to IF - assign fill_data_sel[fb] = ~|(fill_busy_q & ~fill_out_done & ~fill_stale_q & - fill_older_q[fb]); - // Arbitrate the request which has data available to send, and is the oldest outstanding - assign fill_out_arb[fb] = fill_out_req[fb] & fill_data_sel[fb]; - // Assign incoming rvalid data to the oldest fill buffer expecting it - assign fill_rvd_arb[fb] = instr_rvalid_i & fill_rvd_exp[fb] & - ~|(fill_rvd_exp & fill_older_q[fb]); - - ///////////////////////////// - // Fill buffer data muxing // - ///////////////////////////// - - // Output data muxing controls - // 1. Select data from the fill buffer data register - assign fill_data_reg[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & - ~fill_out_done[fb] & fill_data_sel[fb] & - // The incoming data is already ahead of the output count - ((fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_hit_q[fb] | - (|fill_err_q[fb])); - // 2. Select IC1 hit data - assign fill_data_hit[fb] = fill_busy_q[fb] & fill_hit_ic1[fb] & fill_data_sel[fb]; - // 3. Select incoming instr_rdata_i - assign fill_data_rvd[fb] = fill_busy_q[fb] & fill_rvd_arb[fb] & ~fill_hit_q[fb] & - ~fill_hit_ic1[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] & - // The incoming data lines up with the output count - (fill_rvd_beat[fb] == fill_out_cnt_q[fb]) & fill_data_sel[fb]; - - - /////////////////////////// - // Fill buffer registers // - /////////////////////////// - - // Fill buffer general enable - assign fill_entry_en[fb] = fill_alloc[fb] | fill_busy_q[fb]; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_busy_q[fb] <= 1'b0; - fill_older_q[fb] <= '0; - fill_stale_q[fb] <= 1'b0; - fill_cache_q[fb] <= 1'b0; - fill_hit_q[fb] <= 1'b0; - fill_ext_cnt_q[fb] <= '0; - fill_ext_hold_q[fb] <= 1'b0; - fill_ext_done_q[fb] <= 1'b0; - fill_rvd_cnt_q[fb] <= '0; - fill_ram_done_q[fb] <= 1'b0; - fill_out_cnt_q[fb] <= '0; - end else if (fill_entry_en[fb]) begin - fill_busy_q[fb] <= fill_busy_d[fb]; - fill_older_q[fb] <= fill_older_d[fb]; - fill_stale_q[fb] <= fill_stale_d[fb]; - fill_cache_q[fb] <= fill_cache_d[fb]; - fill_hit_q[fb] <= fill_hit_d[fb]; - fill_ext_cnt_q[fb] <= fill_ext_cnt_d[fb]; - fill_ext_hold_q[fb] <= fill_ext_hold_d[fb]; - fill_ext_done_q[fb] <= fill_ext_done_d[fb]; - fill_rvd_cnt_q[fb] <= fill_rvd_cnt_d[fb]; - fill_ram_done_q[fb] <= fill_ram_done_d[fb]; - fill_out_cnt_q[fb] <= fill_out_cnt_d[fb]; - end - end - - //////////////////////////////////////// - // Fill buffer address / data storage // - //////////////////////////////////////// - - assign fill_addr_en[fb] = fill_alloc[fb]; - assign fill_way_en[fb] = (lookup_valid_ic1 & fill_in_ic1[fb]); - - if (ResetAll) begin : g_fill_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_addr_q[fb] <= '0; - end else if (fill_addr_en[fb]) begin - fill_addr_q[fb] <= lookup_addr_ic0; - end - end - end else begin : g_fill_addr_nr - always_ff @(posedge clk_i) begin - if (fill_addr_en[fb]) begin - fill_addr_q[fb] <= lookup_addr_ic0; - end - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_way_q[fb] <= '0; - end else if (fill_way_en[fb]) begin - fill_way_q[fb] <= sel_way_ic1; - end - end - - // Data either comes from the cache or the bus. If there was an ECC error, we must take - // the incoming bus data since the cache hit data is corrupted. - assign fill_data_d[fb] = fill_hit_ic1[fb] ? hit_data_ic1 : - {IC_LINE_BEATS{instr_rdata_i}}; - - for (genvar b = 0; b < IC_LINE_BEATS; b++) begin : gen_data_buf - // Error tracking (per beat) - assign fill_err_d[fb][b] = (fill_rvd_arb[fb] & instr_err_i & - (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])) | - // Hold the error once recorded - (fill_busy_q[fb] & fill_err_q[fb][b]); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_err_q[fb][b] <= '0; - end else if (fill_entry_en[fb]) begin - fill_err_q[fb][b] <= fill_err_d[fb][b]; - end - end - - // Enable the relevant part of the data register (or all for cache hits) - // Ignore incoming rvalid data when we already have cache hit data - assign fill_data_en[fb][b] = fill_hit_ic1[fb] | - (fill_rvd_arb[fb] & ~fill_hit_q[fb] & - (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])); - - if (ResetAll) begin : g_fill_data_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= '0; - end else if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; - end - end - end else begin : g_fill_data_nr - always_ff @(posedge clk_i) begin - if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; - end - end - end - - end - end - - //////////////////////////////// - // Fill buffer one-hot muxing // - //////////////////////////////// - - // External req info - always_comb begin - fill_ext_req_addr = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_ext_arb[i]) begin - fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:IC_LINE_W], fill_ext_off[i]}; - end - end - end - - // Cache req info - always_comb begin - fill_ram_req_addr = '0; - fill_ram_req_way = '0; - fill_ram_req_data = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_ram_arb[i]) begin - fill_ram_req_addr |= fill_addr_q[i]; - fill_ram_req_way |= fill_way_q[i]; - fill_ram_req_data |= fill_data_q[i]; - end - end - end - - // IF stage output data - always_comb begin - fill_out_data = '0; - fill_out_err = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_data_reg[i]) begin - fill_out_data |= fill_data_q[i]; - // Ignore any speculative errors accumulated on cache hits - fill_out_err |= (fill_err_q[i] & ~{IC_LINE_BEATS{fill_hit_q[i]}}); - end - end - end - - /////////////////////// - // External requests // - /////////////////////// - - assign instr_req = ((~icache_enable_i | branch_or_mispredict) & lookup_grant_ic0) | - (|fill_ext_req); - - assign instr_addr = |fill_ext_req ? fill_ext_req_addr : - lookup_addr_ic0[ADDR_W-1:BUS_W]; - - assign instr_req_o = instr_req; - assign instr_addr_o = {instr_addr[ADDR_W-1:BUS_W],{BUS_W{1'b0}}}; - - //////////////////////// - // Output data muxing // - //////////////////////// - - // Mux between line-width data sources - assign line_data = |fill_data_hit ? hit_data_ic1 : fill_out_data; - assign line_err = |fill_data_hit ? {IC_LINE_BEATS{1'b0}} : fill_out_err; - - // Mux the relevant beat of line data, based on the output address - always_comb begin - line_data_muxed = '0; - line_err_muxed = 1'b0; - for (int unsigned i = 0; i < IC_LINE_BEATS; i++) begin - // When data has been skidded, the output address is behind by one - if ((output_addr_q[IC_LINE_W-1:BUS_W] + {{IC_LINE_BEATS_W-1{1'b0}},skid_valid_q}) == - i[IC_LINE_BEATS_W-1:0]) begin - line_data_muxed |= line_data[i*32+:32]; - line_err_muxed |= line_err[i]; - end - end - end - - // Mux between incoming rdata and the muxed line data - assign output_data = |fill_data_rvd ? instr_rdata_i : line_data_muxed; - assign output_err = |fill_data_rvd ? instr_err_i : line_err_muxed; - - // Output data is valid (from any of the three possible sources). Note that fill_out_arb - // must be used here rather than fill_out_req because data can become valid out of order - // (e.g. cache hit data can become available ahead of an older outstanding miss). - assign data_valid = |fill_out_arb; - - // Skid buffer data - assign skid_data_d = output_data[31:16]; - - assign skid_en = data_valid & (ready_i | skid_ready); - - if (ResetAll) begin : g_skid_data_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - skid_data_q <= '0; - skid_err_q <= '0; - end else if (skid_en) begin - skid_data_q <= skid_data_d; - skid_err_q <= output_err; - end - end - end else begin : g_skid_data_nr - always_ff @(posedge clk_i) begin - if (skid_en) begin - skid_data_q <= skid_data_d; - skid_err_q <= output_err; - end - end - end - - // The data in the skid buffer is ready if it's a complete compressed instruction or if there's - // an error (no need to wait for the second half) - assign skid_complete_instr = skid_valid_q & ((skid_data_q[1:0] != 2'b11) | skid_err_q); - - // Data can be loaded into the skid buffer for an unaligned uncompressed instruction - assign skid_ready = output_addr_q[1] & ~skid_valid_q & (~output_compressed | output_err); - - assign output_ready = (ready_i | skid_ready) & ~skid_complete_instr; - - assign output_compressed = (rdata_o[1:0] != 2'b11); - - assign skid_valid_d = - // Branches invalidate the skid buffer - branch_or_mispredict ? 1'b0 : - // Once valid, the skid buffer stays valid until a compressed instruction realigns the stream - (skid_valid_q ? ~(ready_i & ((skid_data_q[1:0] != 2'b11) | skid_err_q)) : - // The skid buffer becomes valid when: - // - we branch to an unaligned uncompressed instruction - (data_valid & - (((output_addr_q[1] & (~output_compressed | output_err)) | - // - a compressed instruction misaligns the stream - (~output_addr_q[1] & output_compressed & ~output_err & ready_i))))); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - skid_valid_q <= 1'b0; - end else begin - skid_valid_q <= skid_valid_d; - end - end - - // Signal that valid data is available to the IF stage - // Note that if the first half of an unaligned instruction reports an error, we do not need - // to wait for the second half - // Compressed instruction completely satisfied by skid buffer - assign output_valid = skid_complete_instr | - // Output data available and, output stream aligned, or skid data available, - (data_valid & (~output_addr_q[1] | skid_valid_q | - // or this is an error or an unaligned compressed instruction - output_err | (output_data[17:16] != 2'b11))); - - // Update the address on branches and every time an instruction is driven - assign output_addr_en = branch_or_mispredict | (ready_i & valid_o); - - // Increment the address by two every time a compressed instruction is popped - assign addr_incr_two = output_compressed & ~err_o; - - // Next IF stage PC - assign output_addr_incr = (output_addr_q[31:1] + - // Increment address by 4 or 2 - {29'd0, ~addr_incr_two, addr_incr_two}); - - // Redirect the address on branches or mispredicts - assign output_addr_d = branch_i ? addr_i[31:1] : - branch_mispredict_i ? mispredict_addr_i[31:1] : - output_addr_incr; - - if (ResetAll) begin : g_output_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - output_addr_q <= '0; - end else if (output_addr_en) begin - output_addr_q <= output_addr_d; - end - end - end else begin : g_output_addr_nr - always_ff @(posedge clk_i) begin - if (output_addr_en) begin - output_addr_q <= output_addr_d; - end - end - end - - // Mux the data from BUS_SIZE to halfword - // This muxing realigns data when instruction words are split across BUS_W e.g. - // word 1 |----|*h1*| - // word 0 |*h0*|----| --> |*h1*|*h0*| - // 31 15 0 31 15 0 - always_comb begin - output_data_lo = '0; - for (int unsigned i = 0; i < IC_OUTPUT_BEATS; i++) begin - if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin - output_data_lo |= output_data[i*16+:16]; - end - end - end - - always_comb begin - output_data_hi = '0; - for (int unsigned i = 0; i < IC_OUTPUT_BEATS - 1; i++) begin - if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin - output_data_hi |= output_data[(i+1)*16+:16]; - end - end - if (&output_addr_q[BUS_W-1:1]) begin - output_data_hi |= output_data[15:0]; - end - end - - assign valid_o = output_valid & ~branch_mispredict_i; - assign rdata_o = {output_data_hi, (skid_valid_q ? skid_data_q : output_data_lo)}; - assign addr_o = {output_addr_q, 1'b0}; - assign err_o = (skid_valid_q & skid_err_q) | (~skid_complete_instr & output_err); - // Error caused by the second half of a misaligned uncompressed instruction - // (only relevant when err_o is set) - assign err_plus2_o = skid_valid_q & ~skid_err_q; - - /////////////////// - // Invalidations // - /////////////////// - - - // We need to save the invalidation request inside a register. That way we can wait - // until we have a valid scrambling key to do it. Since the key itself is needed for - // starting to fill in the RAMs and read from them, ICache also needs to stop operating. - assign inval_req_d = (inval_req_q | icache_inval_i) & ~(inval_done & inval_prog_q); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_req_q <= 1'b0; - end else begin - inval_req_q <= inval_req_d; - end - end - - // This will act like a lock mechanism. - // Main idea is to lock the invalidation request until we got a valid scrambling key. - assign inval_lock = inval_req_d & ~ic_scr_key_valid_i; - - // Invalidate on reset, or when instructed. If an invalidation request is received while a - // previous invalidation is ongoing, it does not need to be restarted. Do not start - // this process until inval lock is removed meaning the scrambling key is valid. - assign start_inval = ~inval_lock & (~reset_inval_q | inval_req_q) & ~inval_prog_q ; - assign inval_prog_d = ~inval_lock & (start_inval | (inval_prog_q & ~inval_done)); - assign inval_done = &inval_index_q; - assign inval_index_d = start_inval ? '0 : (inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1}); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_prog_q <= 1'b0; - reset_inval_q <= 1'b0; - end else begin - inval_prog_q <= inval_prog_d; - reset_inval_q <= 1'b1; - end - end - - if (ResetAll) begin : g_inval_index_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_index_q <= '0; - end else if (inval_prog_d) begin - inval_index_q <= inval_index_d; - end - end - end else begin : g_inval_index_nr - always_ff @(posedge clk_i) begin - if (inval_prog_d) begin - inval_index_q <= inval_index_d; - end - end - end - - ///////////////// - // Busy status // - ///////////////// - - // Only busy (for WFI purposes) while an invalidation is in-progress, or external requests are - // outstanding. - assign busy_o = inval_req_q | (|(fill_busy_q & ~fill_rvd_done)); - - //////////////// - // Assertions // - //////////////// - - `ASSERT_INIT(size_param_legal, (IC_LINE_SIZE > 32)) - - // ECC primitives will need to be changed for different sizes - `ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27)) - `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_SIZE == 32)) - - // Lookups in the tag ram should always give a known result - `ASSERT_KNOWN(TagHitKnown, lookup_valid_ic1 & tag_hit_ic1) - `ASSERT_KNOWN(TagInvalidKnown, lookup_valid_ic1 & tag_invalid_ic1) - - // This is only used for the Yosys-based formal flow. Once we have working bind support, we can - // get rid of it. -`ifdef FORMAL - `ifdef YOSYS - // Unfortunately, Yosys doesn't support passing unpacked arrays as ports. Explicitly pack up the - // signals we need. - logic [NUM_FB-1:0][ADDR_W-1:0] packed_fill_addr_q; - always_comb begin - for (int i = 0; i < NUM_FB; i++) begin - packed_fill_addr_q[i][ADDR_W-1:0] = fill_addr_q[i]; - end - end - - `include "formal_tb_frag.svh" - `endif -`endif - - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv deleted file mode 100644 index c430b669..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv +++ /dev/null @@ -1,750 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Instruction Fetch Stage - * - * Instruction fetch unit: Selection of the next PC, and buffering (sampling) of - * the read instruction. - */ - -`include "prim_assert.sv" - -module ibex_if_stage import ibex_pkg::*; #( - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808, - parameter bit DummyInstructions = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit PCIncrCheck = 1'b0, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit BranchPredictor = 1'b0 -) ( - input logic clk_i, - input logic rst_ni, - - input logic [31:0] boot_addr_i, // also used for mtvec - input logic req_i, // instruction request control - - // instruction cache interface - output logic instr_req_o, - output logic [31:0] instr_addr_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - input logic [31:0] instr_rdata_i, - input logic instr_err_i, - - // ICache RAM IO - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - // output of ID stage - output logic instr_valid_id_o, // instr in IF-ID is valid - output logic instr_new_id_o, // instr in IF-ID is new - output logic [31:0] instr_rdata_id_o, // instr for ID stage - output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage - // to reduce fan-out - output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage - // (mtval), meaningful only if - // instr_is_compressed_id_o = 1'b1 - output logic instr_is_compressed_id_o, // compressed decoder thinks this - // is a compressed instr - output logic instr_bp_taken_o, // instruction was predicted to be - // a taken branch - output logic instr_fetch_err_o, // bus error on fetch - output logic instr_fetch_err_plus2_o, // bus error misaligned - output logic illegal_c_insn_id_o, // compressed decoder thinks this - // is an invalid instr - output logic dummy_instr_id_o, // Instruction is a dummy - output logic [31:0] pc_if_o, - output logic [31:0] pc_id_o, - input logic pmp_err_if_i, - input logic pmp_err_if_plus2_i, - - // control signals - input logic instr_valid_clear_i, // clear instr valid bit in IF-ID - input logic pc_set_i, // set the PC to a new value - input pc_sel_e pc_mux_i, // selector for PC multiplexer - input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was - // mispredicted (predicted taken) - input logic [31:0] nt_branch_addr_i, // Not-taken branch address in ID/EX - input exc_pc_sel_e exc_pc_mux_i, // selects ISR address - input exc_cause_e exc_cause, // selects ISR address for - // vectorized interrupt lines - input logic dummy_instr_en_i, - input logic [2:0] dummy_instr_mask_i, - input logic dummy_instr_seed_en_i, - input logic [31:0] dummy_instr_seed_i, - input logic icache_enable_i, - input logic icache_inval_i, - output logic icache_ecc_error_o, - - // jump and branch target - input logic [31:0] branch_target_ex_i, // branch/jump target address - - // CSRs - input logic [31:0] csr_mepc_i, // PC to restore after handling - // the interrupt/exception - input logic [31:0] csr_depc_i, // PC to restore after handling - // the debug request - input logic [31:0] csr_mtvec_i, // base PC to jump to on exception - output logic csr_mtvec_init_o, // tell CS regfile to init mtvec - - // pipeline stall - input logic id_in_ready_i, // ID stage is ready for new instr - - // misc signals - output logic pc_mismatch_alert_o, - output logic if_busy_o // IF stage is busy fetching instr -); - - logic instr_valid_id_d, instr_valid_id_q; - logic instr_new_id_d, instr_new_id_q; - - // prefetch buffer related signals - logic prefetch_busy; - logic branch_req; - logic [31:0] fetch_addr_n; - logic unused_fetch_addr_n0; - - logic fetch_valid; - logic fetch_ready; - logic [31:0] fetch_rdata; - logic [31:0] fetch_addr; - logic fetch_err; - logic fetch_err_plus2; - - logic [31:0] instr_decompressed; - logic illegal_c_insn; - logic instr_is_compressed; - - logic if_instr_valid; - logic [31:0] if_instr_rdata; - logic [31:0] if_instr_addr; - logic if_instr_bus_err; - logic if_instr_pmp_err; - logic if_instr_err; - logic if_instr_err_plus2; - - logic [31:0] exc_pc; - - logic [5:0] irq_id; - logic unused_irq_bit; - - logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable - - // Dummy instruction signals - logic stall_dummy_instr; - logic [31:0] instr_out; - logic instr_is_compressed_out; - logic illegal_c_instr_out; - logic instr_err_out; - - logic predict_branch_taken; - logic [31:0] predict_branch_pc; - - ibex_pkg::pc_sel_e pc_mux_internal; - - logic [7:0] unused_boot_addr; - logic [7:0] unused_csr_mtvec; - - assign unused_boot_addr = boot_addr_i[7:0]; - assign unused_csr_mtvec = csr_mtvec_i[7:0]; - - // extract interrupt ID from exception cause - assign irq_id = {exc_cause}; - assign unused_irq_bit = irq_id[5]; // MSB distinguishes interrupts from exceptions - - // exception PC selection mux - always_comb begin : exc_pc_mux - unique case (exc_pc_mux_i) - EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; - EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], 1'b0, irq_id[4:0], 2'b00 }; - EXC_PC_DBD: exc_pc = DmHaltAddr; - EXC_PC_DBG_EXC: exc_pc = DmExceptionAddr; - default: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; - endcase - end - - // The Branch predictor can provide a new PC which is internal to if_stage. Only override the mux - // select to choose this if the core isn't already trying to set a PC. - assign pc_mux_internal = - (BranchPredictor && predict_branch_taken && !pc_set_i) ? PC_BP : pc_mux_i; - - // fetch address selection mux - always_comb begin : fetch_addr_mux - unique case (pc_mux_internal) - PC_BOOT: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; - PC_JUMP: fetch_addr_n = branch_target_ex_i; - PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler - PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC - PC_DRET: fetch_addr_n = csr_depc_i; - // Without branch predictor will never get pc_mux_internal == PC_BP. We still handle no branch - // predictor case here to ensure redundant mux logic isn't synthesised. - PC_BP: fetch_addr_n = BranchPredictor ? predict_branch_pc : { boot_addr_i[31:8], 8'h00 }; - default: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; - endcase - end - - // tell CS register file to initialize mtvec on boot - assign csr_mtvec_init_o = (pc_mux_i == PC_BOOT) & pc_set_i; - - if (ICache) begin : gen_icache - // Full I-Cache option - ibex_icache #( - .ICacheECC (ICacheECC), - .ResetAll (ResetAll), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC) - ) icache_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .req_i ( req_i ), - - .branch_i ( branch_req ), - .branch_mispredict_i ( nt_branch_mispredict_i ), - .mispredict_addr_i ( nt_branch_addr_i ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), - - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), - .err_o ( fetch_err ), - .err_plus2_o ( fetch_err_plus2 ), - - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - .instr_err_i ( instr_err_i ), - - .ic_tag_req_o ( ic_tag_req_o ), - .ic_tag_write_o ( ic_tag_write_o ), - .ic_tag_addr_o ( ic_tag_addr_o ), - .ic_tag_wdata_o ( ic_tag_wdata_o ), - .ic_tag_rdata_i ( ic_tag_rdata_i ), - .ic_data_req_o ( ic_data_req_o ), - .ic_data_write_o ( ic_data_write_o ), - .ic_data_addr_o ( ic_data_addr_o ), - .ic_data_wdata_o ( ic_data_wdata_o ), - .ic_data_rdata_i ( ic_data_rdata_i ), - .ic_scr_key_valid_i ( ic_scr_key_valid_i ), - - .icache_enable_i ( icache_enable_i ), - .icache_inval_i ( icache_inval_i ), - .busy_o ( prefetch_busy ), - .ecc_error_o ( icache_ecc_error_o ) - ); - end else begin : gen_prefetch_buffer - // prefetch buffer, caches a fixed number of instructions - ibex_prefetch_buffer #( - .ResetAll (ResetAll) - ) prefetch_buffer_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .req_i ( req_i ), - - .branch_i ( branch_req ), - .branch_mispredict_i ( nt_branch_mispredict_i ), - .mispredict_addr_i ( nt_branch_addr_i ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), - - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), - .err_o ( fetch_err ), - .err_plus2_o ( fetch_err_plus2 ), - - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - .instr_err_i ( instr_err_i ), - - .busy_o ( prefetch_busy ) - ); - // ICache tieoffs - logic unused_icen, unused_icinv, unused_scr_key_valid; - logic [TagSizeECC-1:0] unused_tag_ram_input [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS]; - assign unused_icen = icache_enable_i; - assign unused_icinv = icache_inval_i; - assign unused_tag_ram_input = ic_tag_rdata_i; - assign unused_data_ram_input = ic_data_rdata_i; - assign unused_scr_key_valid = ic_scr_key_valid_i; - assign ic_tag_req_o = 'b0; - assign ic_tag_write_o = 'b0; - assign ic_tag_addr_o = 'b0; - assign ic_tag_wdata_o = 'b0; - assign ic_data_req_o = 'b0; - assign ic_data_write_o = 'b0; - assign ic_data_addr_o = 'b0; - assign ic_data_wdata_o = 'b0; - assign icache_ecc_error_o = 'b0; - -`ifndef SYNTHESIS - // If we don't instantiate an icache and this is a simulation then we have a problem because the - // simulator might discard the icache module entirely, including some DPI exports that it - // implies. This then causes problems for linking against C++ testbench code that expected them. - // As a slightly ugly hack, let's define the DPI functions here (the real versions are defined - // in prim_util_get_scramble_params.svh) - export "DPI-C" function simutil_get_scramble_key; - export "DPI-C" function simutil_get_scramble_nonce; - function automatic int simutil_get_scramble_key(output bit [127:0] val); - return 0; - endfunction - function automatic int simutil_get_scramble_nonce(output bit [319:0] nonce); - return 0; - endfunction -`endif - end - - assign unused_fetch_addr_n0 = fetch_addr_n[0]; - - assign branch_req = pc_set_i | predict_branch_taken; - - assign pc_if_o = if_instr_addr; - assign if_busy_o = prefetch_busy; - - // PMP errors - // An error can come from the instruction address, or the next instruction address for unaligned, - // uncompressed instructions. - assign if_instr_pmp_err = pmp_err_if_i | - (if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i); - - // Combine bus errors and pmp errors - assign if_instr_err = if_instr_bus_err | if_instr_pmp_err; - - // Capture the second half of the address for errors on the second part of an instruction - assign if_instr_err_plus2 = ((if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i) | - fetch_err_plus2) & ~pmp_err_if_i; - - // compressed instruction decoding, or more precisely compressed instruction - // expander - // - // since it does not matter where we decompress instructions, we do it here - // to ease timing closure - ibex_compressed_decoder compressed_decoder_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .valid_i (fetch_valid & ~fetch_err), - .instr_i (if_instr_rdata), - .instr_o (instr_decompressed), - .is_compressed_o(instr_is_compressed), - .illegal_instr_o(illegal_c_insn) - ); - - // Dummy instruction insertion - if (DummyInstructions) begin : gen_dummy_instr - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic insert_dummy_instr; - logic [31:0] dummy_instr_data; - - ibex_dummy_instr #( - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm) - ) dummy_instr_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .dummy_instr_en_i (dummy_instr_en_i), - .dummy_instr_mask_i (dummy_instr_mask_i), - .dummy_instr_seed_en_i(dummy_instr_seed_en_i), - .dummy_instr_seed_i (dummy_instr_seed_i), - .fetch_valid_i (fetch_valid), - .id_in_ready_i (id_in_ready_i), - .insert_dummy_instr_o (insert_dummy_instr), - .dummy_instr_data_o (dummy_instr_data) - ); - - // Mux between actual instructions and dummy instructions - assign instr_out = insert_dummy_instr ? dummy_instr_data : instr_decompressed; - assign instr_is_compressed_out = insert_dummy_instr ? 1'b0 : instr_is_compressed; - assign illegal_c_instr_out = insert_dummy_instr ? 1'b0 : illegal_c_insn; - assign instr_err_out = insert_dummy_instr ? 1'b0 : if_instr_err; - - // Stall the IF stage if we insert a dummy instruction. The dummy will execute between whatever - // is currently in the ID stage and whatever is valid from the prefetch buffer this cycle. The - // PC of the dummy instruction will match whatever is next from the prefetch buffer. - assign stall_dummy_instr = insert_dummy_instr; - - // Register the dummy instruction indication into the ID stage - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_instr_id_o <= 1'b0; - end else if (if_id_pipe_reg_we) begin - dummy_instr_id_o <= insert_dummy_instr; - end - end - - end else begin : gen_no_dummy_instr - logic unused_dummy_en; - logic [2:0] unused_dummy_mask; - logic unused_dummy_seed_en; - logic [31:0] unused_dummy_seed; - - assign unused_dummy_en = dummy_instr_en_i; - assign unused_dummy_mask = dummy_instr_mask_i; - assign unused_dummy_seed_en = dummy_instr_seed_en_i; - assign unused_dummy_seed = dummy_instr_seed_i; - assign instr_out = instr_decompressed; - assign instr_is_compressed_out = instr_is_compressed; - assign illegal_c_instr_out = illegal_c_insn; - assign instr_err_out = if_instr_err; - assign stall_dummy_instr = 1'b0; - assign dummy_instr_id_o = 1'b0; - end - - // The ID stage becomes valid as soon as any instruction is registered in the ID stage flops. - // Note that the current instruction is squashed by the incoming pc_set_i signal. - // Valid is held until it is explicitly cleared (due to an instruction completing or an exception) - assign instr_valid_id_d = (if_instr_valid & id_in_ready_i & ~pc_set_i) | - (instr_valid_id_q & ~instr_valid_clear_i); - assign instr_new_id_d = if_instr_valid & id_in_ready_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_valid_id_q <= 1'b0; - instr_new_id_q <= 1'b0; - end else begin - instr_valid_id_q <= instr_valid_id_d; - instr_new_id_q <= instr_new_id_d; - end - end - - assign instr_valid_id_o = instr_valid_id_q; - // Signal when a new instruction enters the ID stage (only used for RVFI signalling). - assign instr_new_id_o = instr_new_id_q; - - // IF-ID pipeline registers, frozen when the ID stage is stalled - assign if_id_pipe_reg_we = instr_new_id_d; - - if (ResetAll) begin : g_instr_rdata_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_rdata_id_o <= '0; - instr_rdata_alu_id_o <= '0; - instr_fetch_err_o <= '0; - instr_fetch_err_plus2_o <= '0; - instr_rdata_c_id_o <= '0; - instr_is_compressed_id_o <= '0; - illegal_c_insn_id_o <= '0; - pc_id_o <= '0; - end else if (if_id_pipe_reg_we) begin - instr_rdata_id_o <= instr_out; - // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. - instr_rdata_alu_id_o <= instr_out; - instr_fetch_err_o <= instr_err_out; - instr_fetch_err_plus2_o <= if_instr_err_plus2; - instr_rdata_c_id_o <= if_instr_rdata[15:0]; - instr_is_compressed_id_o <= instr_is_compressed_out; - illegal_c_insn_id_o <= illegal_c_instr_out; - pc_id_o <= pc_if_o; - end - end - end else begin : g_instr_rdata_nr - always_ff @(posedge clk_i) begin - if (if_id_pipe_reg_we) begin - instr_rdata_id_o <= instr_out; - // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. - instr_rdata_alu_id_o <= instr_out; - instr_fetch_err_o <= instr_err_out; - instr_fetch_err_plus2_o <= if_instr_err_plus2; - instr_rdata_c_id_o <= if_instr_rdata[15:0]; - instr_is_compressed_id_o <= instr_is_compressed_out; - illegal_c_insn_id_o <= illegal_c_instr_out; - pc_id_o <= pc_if_o; - end - end - end - - // Check for expected increments of the PC when security hardening enabled - if (PCIncrCheck) begin : g_secure_pc - // SEC_CM: PC.CTRL_FLOW.CONSISTENCY - logic [31:0] prev_instr_addr_incr, prev_instr_addr_incr_buf; - logic prev_instr_seq_q, prev_instr_seq_d; - - // Do not check for sequential increase after a branch, jump, exception, interrupt or debug - // request, all of which will set branch_req. Also do not check after reset or for dummys. - assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) & - ~branch_req & ~if_instr_err & ~stall_dummy_instr; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - prev_instr_seq_q <= 1'b0; - end else begin - prev_instr_seq_q <= prev_instr_seq_d; - end - end - - assign prev_instr_addr_incr = pc_id_o + (instr_is_compressed_id_o ? 32'd2 : 32'd4); - - // Buffer anticipated next PC address to ensure optimiser cannot remove the check. - prim_buf #(.Width(32)) u_prev_instr_addr_incr_buf ( - .in_i (prev_instr_addr_incr), - .out_o(prev_instr_addr_incr_buf) - ); - - // Check that the address equals the previous address +2/+4 - assign pc_mismatch_alert_o = prev_instr_seq_q & (pc_if_o != prev_instr_addr_incr_buf); - - end else begin : g_no_secure_pc - assign pc_mismatch_alert_o = 1'b0; - end - - if (BranchPredictor) begin : g_branch_predictor - logic [31:0] instr_skid_data_q; - logic [31:0] instr_skid_addr_q; - logic instr_skid_bp_taken_q; - logic instr_skid_valid_q, instr_skid_valid_d; - logic instr_skid_en; - logic instr_bp_taken_q, instr_bp_taken_d; - - logic predict_branch_taken_raw; - - // ID stages needs to know if branch was predicted taken so it can signal mispredicts - if (ResetAll) begin : g_bp_taken_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_bp_taken_q <= '0; - end else if (if_id_pipe_reg_we) begin - instr_bp_taken_q <= instr_bp_taken_d; - end - end - end else begin : g_bp_taken_nr - always_ff @(posedge clk_i) begin - if (if_id_pipe_reg_we) begin - instr_bp_taken_q <= instr_bp_taken_d; - end - end - end - - // When branch prediction is enabled a skid buffer between the IF and ID/EX stage is introduced. - // If an instruction in IF is predicted to be a taken branch and ID/EX is not ready the - // instruction in IF is moved to the skid buffer which becomes the output of the IF stage until - // the ID/EX stage accepts the instruction. The skid buffer is required as otherwise the ID/EX - // ready signal is coupled to the instr_req_o output which produces a feedthrough path from - // data_gnt_i -> instr_req_o (which needs to be avoided as for some interconnects this will - // result in a combinational loop). - - assign instr_skid_en = predict_branch_taken & ~pc_set_i & ~id_in_ready_i & ~instr_skid_valid_q; - - assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i & ~stall_dummy_instr) | - instr_skid_en; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_skid_valid_q <= 1'b0; - end else begin - instr_skid_valid_q <= instr_skid_valid_d; - end - end - - if (ResetAll) begin : g_instr_skid_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_skid_bp_taken_q <= '0; - instr_skid_data_q <= '0; - instr_skid_addr_q <= '0; - end else if (instr_skid_en) begin - instr_skid_bp_taken_q <= predict_branch_taken; - instr_skid_data_q <= fetch_rdata; - instr_skid_addr_q <= fetch_addr; - end - end - end else begin : g_instr_skid_nr - always_ff @(posedge clk_i) begin - if (instr_skid_en) begin - instr_skid_bp_taken_q <= predict_branch_taken; - instr_skid_data_q <= fetch_rdata; - instr_skid_addr_q <= fetch_addr; - end - end - end - - ibex_branch_predict branch_predict_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .fetch_rdata_i(fetch_rdata), - .fetch_pc_i (fetch_addr), - .fetch_valid_i(fetch_valid), - - .predict_branch_taken_o(predict_branch_taken_raw), - .predict_branch_pc_o (predict_branch_pc) - ); - - // If there is an instruction in the skid buffer there must be no branch prediction. - // Instructions are only placed in the skid after they have been predicted to be a taken branch - // so with the skid valid any prediction has already occurred. - // Do not branch predict on instruction errors. - assign predict_branch_taken = predict_branch_taken_raw & ~instr_skid_valid_q & ~fetch_err; - - assign if_instr_valid = fetch_valid | (instr_skid_valid_q & ~nt_branch_mispredict_i); - assign if_instr_rdata = instr_skid_valid_q ? instr_skid_data_q : fetch_rdata; - assign if_instr_addr = instr_skid_valid_q ? instr_skid_addr_q : fetch_addr; - - // Don't branch predict on instruction error so only instructions without errors end up in the - // skid buffer. - assign if_instr_bus_err = ~instr_skid_valid_q & fetch_err; - assign instr_bp_taken_d = instr_skid_valid_q ? instr_skid_bp_taken_q : predict_branch_taken; - - assign fetch_ready = id_in_ready_i & ~stall_dummy_instr & ~instr_skid_valid_q; - - assign instr_bp_taken_o = instr_bp_taken_q; - - `ASSERT(NoPredictSkid, instr_skid_valid_q |-> ~predict_branch_taken) - `ASSERT(NoPredictIllegal, predict_branch_taken |-> ~illegal_c_insn) - end else begin : g_no_branch_predictor - assign instr_bp_taken_o = 1'b0; - assign predict_branch_taken = 1'b0; - assign predict_branch_pc = 32'b0; - - assign if_instr_valid = fetch_valid; - assign if_instr_rdata = fetch_rdata; - assign if_instr_addr = fetch_addr; - assign if_instr_bus_err = fetch_err; - assign fetch_ready = id_in_ready_i & ~stall_dummy_instr; - end - - //////////////// - // Assertions // - //////////////// - - // Selectors must be known/valid. - `ASSERT_KNOWN(IbexExcPcMuxKnown, exc_pc_mux_i) - - if (BranchPredictor) begin : g_branch_predictor_asserts - `ASSERT_IF(IbexPcMuxValid, pc_mux_internal inside { - PC_BOOT, - PC_JUMP, - PC_EXC, - PC_ERET, - PC_DRET, - PC_BP}, - pc_set_i) - -`ifdef INC_ASSERT - /** - * Checks for branch prediction interface to fetch_fifo/icache - * - * The interface has two signals: - * - predicted_branch_i: When set with a branch (branch_i) indicates the branch is a predicted - * one, it should be ignored when a branch_i isn't set. - * - branch_mispredict_i: Indicates the previously predicted branch was mis-predicted and - * execution should resume with the not-taken side of the branch (i.e. continue with the PC - * that followed the predicted branch). This must be raised before the instruction that is - * made available following a predicted branch is accepted (Following a cycle with branch_i - * & predicted_branch_i, branch_mispredict_i can only be asserted before or on the same cycle - * as seeing fetch_valid & fetch_ready). When branch_mispredict_i is asserted, fetch_valid may - * be asserted in response. If fetch_valid is asserted on the same cycle as - * branch_mispredict_i this indicates the fetch_fifo/icache has the not-taken side of the - * branch immediately ready for use - */ - logic predicted_branch_live_q, predicted_branch_live_d; - logic [31:0] predicted_branch_nt_pc_q, predicted_branch_nt_pc_d; - logic [31:0] awaiting_instr_after_mispredict_q, awaiting_instr_after_mispredict_d; - logic [31:0] next_pc; - - logic mispredicted, mispredicted_d, mispredicted_q; - - assign next_pc = fetch_addr + (instr_is_compressed_out ? 32'd2 : 32'd4); - - logic predicted_branch; - - // pc_set_i takes precendence over branch prediction - assign predicted_branch = predict_branch_taken & ~pc_set_i; - - always_comb begin - predicted_branch_live_d = predicted_branch_live_q; - mispredicted_d = mispredicted_q; - - if (branch_req & predicted_branch) begin - predicted_branch_live_d = 1'b1; - mispredicted_d = 1'b0; - end else if (predicted_branch_live_q) begin - if (fetch_valid & fetch_ready) begin - predicted_branch_live_d = 1'b0; - end else if (nt_branch_mispredict_i) begin - mispredicted_d = 1'b1; - end - end - end - - always @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - predicted_branch_live_q <= 1'b0; - mispredicted_q <= 1'b0; - end else begin - predicted_branch_live_q <= predicted_branch_live_d; - mispredicted_q <= mispredicted_d; - end - end - - always @(posedge clk_i) begin - if (branch_req & predicted_branch) begin - predicted_branch_nt_pc_q <= next_pc; - end - end - - // Must only see mispredict after we've performed a predicted branch but before we've accepted - // any instruction (with fetch_ready & fetch_valid) that follows that predicted branch. - `ASSERT(MispredictOnlyImmediatelyAfterPredictedBranch, - nt_branch_mispredict_i |-> predicted_branch_live_q) - // Check that on mispredict we get the correct PC for the non-taken side of the branch when - // prefetch buffer/icache makes that PC available. - `ASSERT(CorrectPCOnMispredict, - predicted_branch_live_q & mispredicted_d & fetch_valid |-> - fetch_addr == predicted_branch_nt_pc_q) - // Must not signal mispredict over multiple cycles but it's possible to have back to back - // mispredicts for different branches (core signals mispredict, prefetch buffer/icache immediate - // has not-taken side of the mispredicted branch ready, which itself is a predicted branch, - // following cycle core signal that that branch has mispredicted). - `ASSERT(MispredictSingleCycle, - nt_branch_mispredict_i & ~(fetch_valid & fetch_ready) |=> ~nt_branch_mispredict_i) - // Note that we should never see a mispredict and an incoming branch on the same cycle. - // The mispredict also cancels any predicted branch so overall branch_req must be low. - `ASSERT(NoMispredBranch, nt_branch_mispredict_i |-> ~branch_req) -`endif - - end else begin : g_no_branch_predictor_asserts - `ASSERT_IF(IbexPcMuxValid, pc_mux_internal inside { - PC_BOOT, - PC_JUMP, - PC_EXC, - PC_ERET, - PC_DRET}, - pc_set_i) - end - - // Boot address must be aligned to 256 bytes. - `ASSERT(IbexBootAddrUnaligned, boot_addr_i[7:0] == 8'h00) - - // Address must not contain X when request is sent. - `ASSERT(IbexInstrAddrUnknown, instr_req_o |-> !$isunknown(instr_addr_o)) - - // Address must be word aligned when request is sent. - `ASSERT(IbexInstrAddrUnaligned, instr_req_o |-> (instr_addr_o[1:0] == 2'b00)) - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv deleted file mode 100644 index 4f986d0c..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -// Ibex lockstep module -// This module instantiates a second copy of the core logic, and compares it's outputs against -// those from the main core. The second core runs synchronously with the main core, delayed by -// LockstepOffset cycles. - -// SEC_CM: LOGIC.SHADOW -module ibex_lockstep import ibex_pkg::*; #( - parameter int unsigned LockstepOffset = 2, - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit SecureIbex = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit RegFileECC = 1'b0, - parameter int unsigned RegFileDataWidth = 32, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808 -) ( - input logic clk_i, - input logic rst_ni, - - input logic [31:0] hart_id_i, - input logic [31:0] boot_addr_i, - - input logic instr_req_i, - input logic instr_gnt_i, - input logic instr_rvalid_i, - input logic [31:0] instr_addr_i, - input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, - input logic instr_err_i, - - input logic data_req_i, - input logic data_gnt_i, - input logic data_rvalid_i, - input logic data_we_i, - input logic [3:0] data_be_i, - input logic [31:0] data_addr_i, - input logic [31:0] data_wdata_i, - output logic [6:0] data_wdata_intg_o, - input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, - input logic data_err_i, - - input logic dummy_instr_id_i, - input logic [4:0] rf_raddr_a_i, - input logic [4:0] rf_raddr_b_i, - input logic [4:0] rf_waddr_wb_i, - input logic rf_we_wb_i, - input logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, - - input logic [IC_NUM_WAYS-1:0] ic_tag_req_i, - input logic ic_tag_write_i, - input logic [IC_INDEX_W-1:0] ic_tag_addr_i, - input logic [TagSizeECC-1:0] ic_tag_wdata_i, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - input logic [IC_NUM_WAYS-1:0] ic_data_req_i, - input logic ic_data_write_i, - input logic [IC_INDEX_W-1:0] ic_data_addr_i, - input logic [LineSizeECC-1:0] ic_data_wdata_i, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - input logic irq_software_i, - input logic irq_timer_i, - input logic irq_external_i, - input logic [14:0] irq_fast_i, - input logic irq_nm_i, - input logic irq_pending_i, - - input logic debug_req_i, - input crash_dump_t crash_dump_i, - input logic double_fault_seen_i, - - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, - input logic icache_inval_i, - input logic core_busy_i, - input logic test_en_i, - input logic scan_rst_ni -); - - localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset); - // Core outputs are delayed for an extra cycle due to shadow output registers - localparam int unsigned OutputsOffset = LockstepOffset + 1; - - ////////////////////// - // Reset generation // - ////////////////////// - - // Upon reset, the comparison is stopped and the shadow core is reset, both immediately. A - // counter is started. After LockstepOffset clock cycles: - // - The counter is stopped. - // - The reset of the shadow core is synchronously released. - // The comparison is started in the following clock cycle. - - logic [LockstepOffsetW-1:0] rst_shadow_cnt_d, rst_shadow_cnt_q, rst_shadow_cnt_incr; - // Internally generated resets cause IMPERFECTSCH warnings - /* verilator lint_off IMPERFECTSCH */ - logic rst_shadow_set_d, rst_shadow_set_q; - logic rst_shadow_n, enable_cmp_q; - /* verilator lint_on IMPERFECTSCH */ - - assign rst_shadow_cnt_incr = rst_shadow_cnt_q + LockstepOffsetW'(1); - - assign rst_shadow_set_d = (rst_shadow_cnt_q == LockstepOffsetW'(LockstepOffset - 1)); - assign rst_shadow_cnt_d = rst_shadow_set_d ? rst_shadow_cnt_q : rst_shadow_cnt_incr; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rst_shadow_cnt_q <= '0; - enable_cmp_q <= '0; - end else begin - rst_shadow_cnt_q <= rst_shadow_cnt_d; - enable_cmp_q <= rst_shadow_set_q; - end - end - - // The primitives below are used to place size-only constraints in order to prevent - // synthesis optimizations and preserve anchor points for constraining backend tools. - prim_flop #( - .Width(1), - .ResetValue(1'b0) - ) u_prim_rst_shadow_set_flop ( - .clk_i (clk_i), - .rst_ni(rst_ni), - .d_i (rst_shadow_set_d), - .q_o (rst_shadow_set_q) - ); - - prim_clock_mux2 #( - .NoFpgaBufG(1'b1) - ) u_prim_rst_shadow_n_mux2 ( - .clk0_i(rst_shadow_set_q), - .clk1_i(scan_rst_ni), - .sel_i (test_en_i), - .clk_o (rst_shadow_n) - ); - - ////////////////// - // Input delays // - ////////////////// - - typedef struct packed { - logic instr_gnt; - logic instr_rvalid; - logic [31:0] instr_rdata; - logic instr_err; - logic data_gnt; - logic data_rvalid; - logic [31:0] data_rdata; - logic data_err; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; - logic irq_software; - logic irq_timer; - logic irq_external; - logic [14:0] irq_fast; - logic irq_nm; - logic debug_req; - fetch_enable_t fetch_enable; - logic ic_scr_key_valid; - } delayed_inputs_t; - - delayed_inputs_t [LockstepOffset-1:0] shadow_inputs_q; - delayed_inputs_t shadow_inputs_in; - logic [6:0] instr_rdata_intg_q, data_rdata_intg_q; - // Packed arrays must be dealt with separately - logic [TagSizeECC-1:0] shadow_tag_rdata_q [IC_NUM_WAYS][LockstepOffset]; - logic [LineSizeECC-1:0] shadow_data_rdata_q [IC_NUM_WAYS][LockstepOffset]; - - // Assign the inputs to the delay structure - assign shadow_inputs_in.instr_gnt = instr_gnt_i; - assign shadow_inputs_in.instr_rvalid = instr_rvalid_i; - assign shadow_inputs_in.instr_rdata = instr_rdata_i; - assign shadow_inputs_in.instr_err = instr_err_i; - assign shadow_inputs_in.data_gnt = data_gnt_i; - assign shadow_inputs_in.data_rvalid = data_rvalid_i; - assign shadow_inputs_in.data_rdata = data_rdata_i; - assign shadow_inputs_in.data_err = data_err_i; - assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i; - assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i; - assign shadow_inputs_in.irq_software = irq_software_i; - assign shadow_inputs_in.irq_timer = irq_timer_i; - assign shadow_inputs_in.irq_external = irq_external_i; - assign shadow_inputs_in.irq_fast = irq_fast_i; - assign shadow_inputs_in.irq_nm = irq_nm_i; - assign shadow_inputs_in.debug_req = debug_req_i; - assign shadow_inputs_in.fetch_enable = fetch_enable_i; - assign shadow_inputs_in.ic_scr_key_valid = ic_scr_key_valid_i; - - // Delay the inputs - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_rdata_intg_q <= '0; - data_rdata_intg_q <= '0; - for (int unsigned i = 0; i < LockstepOffset; i++) begin - shadow_inputs_q[i] <= delayed_inputs_t'('0); - shadow_tag_rdata_q[i] <= '{default: 0}; - shadow_data_rdata_q[i] <= '{default: 0}; - end - end else begin - instr_rdata_intg_q <= instr_rdata_intg_i; - data_rdata_intg_q <= data_rdata_intg_i; - for (int unsigned i = 0; i < LockstepOffset - 1; i++) begin - shadow_inputs_q[i] <= shadow_inputs_q[i+1]; - shadow_tag_rdata_q[i] <= shadow_tag_rdata_q[i+1]; - shadow_data_rdata_q[i] <= shadow_data_rdata_q[i+1]; - end - shadow_inputs_q[LockstepOffset-1] <= shadow_inputs_in; - shadow_tag_rdata_q[LockstepOffset-1] <= ic_tag_rdata_i; - shadow_data_rdata_q[LockstepOffset-1] <= ic_data_rdata_i; - end - end - - //////////////////////////// - // Bus integrity checking // - //////////////////////////// - - // SEC_CM: BUS.INTEGRITY - logic bus_intg_err; - logic [1:0] instr_intg_err, data_intg_err; - logic [31:0] unused_wdata; - - // Checks on incoming data - prim_secded_inv_39_32_dec u_instr_intg_dec ( - .data_i ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}), - .data_o (), - .syndrome_o (), - .err_o (instr_intg_err) - ); - - prim_secded_inv_39_32_dec u_data_intg_dec ( - .data_i ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}), - .data_o (), - .syndrome_o (), - .err_o (data_intg_err) - ); - - assign bus_intg_err = (shadow_inputs_q[LockstepOffset-1].instr_rvalid & |instr_intg_err) | - (shadow_inputs_q[LockstepOffset-1].data_rvalid & |data_intg_err); - - // Generate integrity bits - prim_secded_inv_39_32_enc u_data_gen ( - .data_i (data_wdata_i), - .data_o ({data_wdata_intg_o, unused_wdata}) - ); - - /////////////////// - // Output delays // - /////////////////// - - typedef struct packed { - logic instr_req; - logic [31:0] instr_addr; - logic data_req; - logic data_we; - logic [3:0] data_be; - logic [31:0] data_addr; - logic [31:0] data_wdata; - logic dummy_instr_id; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic irq_pending; - crash_dump_t crash_dump; - logic double_fault_seen; - logic icache_inval; - logic core_busy; - } delayed_outputs_t; - - delayed_outputs_t [OutputsOffset-1:0] core_outputs_q; - delayed_outputs_t core_outputs_in; - delayed_outputs_t shadow_outputs_d, shadow_outputs_q; - - // Assign core outputs to the structure - assign core_outputs_in.instr_req = instr_req_i; - assign core_outputs_in.instr_addr = instr_addr_i; - assign core_outputs_in.data_req = data_req_i; - assign core_outputs_in.data_we = data_we_i; - assign core_outputs_in.data_be = data_be_i; - assign core_outputs_in.data_addr = data_addr_i; - assign core_outputs_in.data_wdata = data_wdata_i; - assign core_outputs_in.dummy_instr_id = dummy_instr_id_i; - assign core_outputs_in.rf_raddr_a = rf_raddr_a_i; - assign core_outputs_in.rf_raddr_b = rf_raddr_b_i; - assign core_outputs_in.rf_waddr_wb = rf_waddr_wb_i; - assign core_outputs_in.rf_we_wb = rf_we_wb_i; - assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i; - assign core_outputs_in.ic_tag_req = ic_tag_req_i; - assign core_outputs_in.ic_tag_write = ic_tag_write_i; - assign core_outputs_in.ic_tag_addr = ic_tag_addr_i; - assign core_outputs_in.ic_tag_wdata = ic_tag_wdata_i; - assign core_outputs_in.ic_data_req = ic_data_req_i; - assign core_outputs_in.ic_data_write = ic_data_write_i; - assign core_outputs_in.ic_data_addr = ic_data_addr_i; - assign core_outputs_in.ic_data_wdata = ic_data_wdata_i; - assign core_outputs_in.irq_pending = irq_pending_i; - assign core_outputs_in.crash_dump = crash_dump_i; - assign core_outputs_in.double_fault_seen = double_fault_seen_i; - assign core_outputs_in.icache_inval = icache_inval_i; - assign core_outputs_in.core_busy = core_busy_i; - - // Delay the outputs - always_ff @(posedge clk_i) begin - for (int unsigned i = 0; i < OutputsOffset - 1; i++) begin - core_outputs_q[i] <= core_outputs_q[i+1]; - end - core_outputs_q[OutputsOffset-1] <= core_outputs_in; - end - - /////////////////////////////// - // Shadow core instantiation // - /////////////////////////////// - - logic shadow_alert_minor, shadow_alert_major; - - ibex_core #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), - .MHPMCounterNum ( MHPMCounterNum ), - .MHPMCounterWidth ( MHPMCounterWidth ), - .RV32E ( RV32E ), - .RV32M ( RV32M ), - .RV32B ( RV32B ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), - .BusSizeECC ( BusSizeECC ), - .TagSizeECC ( TagSizeECC ), - .LineSizeECC ( LineSizeECC ), - .BranchPredictor ( BranchPredictor ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), - .SecureIbex ( SecureIbex ), - .DummyInstructions ( DummyInstructions ), - .RegFileECC ( RegFileECC ), - .RegFileDataWidth ( RegFileDataWidth ), - .DmHaltAddr ( DmHaltAddr ), - .DmExceptionAddr ( DmExceptionAddr ) - ) u_shadow_core ( - .clk_i (clk_i), - .rst_ni (rst_shadow_n), - - .hart_id_i (hart_id_i), - .boot_addr_i (boot_addr_i), - - .instr_req_o (shadow_outputs_d.instr_req), - .instr_gnt_i (shadow_inputs_q[0].instr_gnt), - .instr_rvalid_i (shadow_inputs_q[0].instr_rvalid), - .instr_addr_o (shadow_outputs_d.instr_addr), - .instr_rdata_i (shadow_inputs_q[0].instr_rdata), - .instr_err_i (shadow_inputs_q[0].instr_err), - - .data_req_o (shadow_outputs_d.data_req), - .data_gnt_i (shadow_inputs_q[0].data_gnt), - .data_rvalid_i (shadow_inputs_q[0].data_rvalid), - .data_we_o (shadow_outputs_d.data_we), - .data_be_o (shadow_outputs_d.data_be), - .data_addr_o (shadow_outputs_d.data_addr), - .data_wdata_o (shadow_outputs_d.data_wdata), - .data_rdata_i (shadow_inputs_q[0].data_rdata), - .data_err_i (shadow_inputs_q[0].data_err), - - .dummy_instr_id_o (shadow_outputs_d.dummy_instr_id), - .rf_raddr_a_o (shadow_outputs_d.rf_raddr_a), - .rf_raddr_b_o (shadow_outputs_d.rf_raddr_b), - .rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb), - .rf_we_wb_o (shadow_outputs_d.rf_we_wb), - .rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (shadow_inputs_q[0].rf_rdata_a_ecc), - .rf_rdata_b_ecc_i (shadow_inputs_q[0].rf_rdata_b_ecc), - - .ic_tag_req_o (shadow_outputs_d.ic_tag_req), - .ic_tag_write_o (shadow_outputs_d.ic_tag_write), - .ic_tag_addr_o (shadow_outputs_d.ic_tag_addr), - .ic_tag_wdata_o (shadow_outputs_d.ic_tag_wdata), - .ic_tag_rdata_i (shadow_tag_rdata_q[0]), - .ic_data_req_o (shadow_outputs_d.ic_data_req), - .ic_data_write_o (shadow_outputs_d.ic_data_write), - .ic_data_addr_o (shadow_outputs_d.ic_data_addr), - .ic_data_wdata_o (shadow_outputs_d.ic_data_wdata), - .ic_data_rdata_i (shadow_data_rdata_q[0]), - .ic_scr_key_valid_i (shadow_inputs_q[0].ic_scr_key_valid), - - .irq_software_i (shadow_inputs_q[0].irq_software), - .irq_timer_i (shadow_inputs_q[0].irq_timer), - .irq_external_i (shadow_inputs_q[0].irq_external), - .irq_fast_i (shadow_inputs_q[0].irq_fast), - .irq_nm_i (shadow_inputs_q[0].irq_nm), - .irq_pending_o (shadow_outputs_d.irq_pending), - - .debug_req_i (shadow_inputs_q[0].debug_req), - .crash_dump_o (shadow_outputs_d.crash_dump), - .double_fault_seen_o (shadow_outputs_d.double_fault_seen), - -`ifdef RVFI - .rvfi_valid (), - .rvfi_order (), - .rvfi_insn (), - .rvfi_trap (), - .rvfi_halt (), - .rvfi_intr (), - .rvfi_mode (), - .rvfi_ixl (), - .rvfi_rs1_addr (), - .rvfi_rs2_addr (), - .rvfi_rs3_addr (), - .rvfi_rs1_rdata (), - .rvfi_rs2_rdata (), - .rvfi_rs3_rdata (), - .rvfi_rd_addr (), - .rvfi_rd_wdata (), - .rvfi_pc_rdata (), - .rvfi_pc_wdata (), - .rvfi_mem_addr (), - .rvfi_mem_rmask (), - .rvfi_mem_wmask (), - .rvfi_mem_rdata (), - .rvfi_mem_wdata (), - .rvfi_ext_mip (), - .rvfi_ext_nmi (), - .rvfi_ext_debug_req (), - .rvfi_ext_mcycle (), -`endif - - .fetch_enable_i (shadow_inputs_q[0].fetch_enable), - .alert_minor_o (shadow_alert_minor), - .alert_major_o (shadow_alert_major), - .icache_inval_o (shadow_outputs_d.icache_inval), - .core_busy_o (shadow_outputs_d.core_busy) - ); - - // Register the shadow core outputs - always_ff @(posedge clk_i) begin - shadow_outputs_q <= shadow_outputs_d; - end - - ///////////////////////// - // Compare the outputs // - ///////////////////////// - - logic outputs_mismatch; - - assign outputs_mismatch = enable_cmp_q & (shadow_outputs_q != core_outputs_q[0]); - assign alert_major_internal_o = outputs_mismatch | shadow_alert_major; - assign alert_major_bus_o = bus_intg_err; - assign alert_minor_o = shadow_alert_minor; - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv deleted file mode 100644 index 678549ab..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * RISC-V register file - * - * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. - * - * This register file is designed to make FPGA synthesis tools infer RAM primitives. For Xilinx - * FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested. - */ -module ibex_register_file_fpga #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, - parameter logic [DataWidth-1:0] WordZeroVal = '0 -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, - input logic dummy_instr_id_i, - - //Read port R1 - input logic [ 4:0] raddr_a_i, - output logic [DataWidth-1:0] rdata_a_o, - //Read port R2 - input logic [ 4:0] raddr_b_i, - output logic [DataWidth-1:0] rdata_b_o, - // Write port W1 - input logic [ 4:0] waddr_a_i, - input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i -); - - localparam int ADDR_WIDTH = RV32E ? 4 : 5; - localparam int NUM_WORDS = 2 ** ADDR_WIDTH; - - logic [DataWidth-1:0] mem[NUM_WORDS]; - logic we; // write enable if writing to any register other than R0 - - // async_read a - assign rdata_a_o = (raddr_a_i == '0) ? '0 : mem[raddr_a_i]; - - // async_read b - assign rdata_b_o = (raddr_b_i == '0) ? '0 : mem[raddr_b_i]; - - // we select - assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i; - - // Note that the SystemVerilog LRM requires variables on the LHS of assignments within - // "always_ff" to not be written to by any other process. However, to enable the initialization - // of the inferred RAM32M primitives with non-zero values, below "initial" procedure is needed. - // Therefore, we use "always" instead of the generally preferred "always_ff" for the synchronous - // write procedure. - always @(posedge clk_i) begin : sync_write - if (we == 1'b1) begin - mem[waddr_a_i] <= wdata_a_i; - end - end : sync_write - - // Make sure we initialize the BRAM with the correct register reset value. - initial begin - for (int k = 0; k < NUM_WORDS; k++) begin - mem[k] = WordZeroVal; - end - end - - // Reset not used in this register file version - logic unused_rst_ni; - assign unused_rst_ni = rst_ni; - - // Dummy instruction changes not relevant for FPGA implementation - logic unused_dummy_instr; - assign unused_dummy_instr = dummy_instr_id_i; - // Test enable signal not used in FPGA implementation - logic unused_test_en; - assign unused_test_en = test_en_i; - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv deleted file mode 100644 index f1e4df75..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * RISC-V register file - * - * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. - * This register file is based on latches and is thus smaller than the flip-flop - * based RF. It requires a target technology-specific clock gating cell. Use this - * register file when targeting ASIC synthesis or event-based simulators. - */ -module ibex_register_file_latch #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, - parameter logic [DataWidth-1:0] WordZeroVal = '0 -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, - input logic dummy_instr_id_i, - - //Read port R1 - input logic [4:0] raddr_a_i, - output logic [DataWidth-1:0] rdata_a_o, - - //Read port R2 - input logic [4:0] raddr_b_i, - output logic [DataWidth-1:0] rdata_b_o, - - // Write port W1 - input logic [4:0] waddr_a_i, - input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i - -); - - localparam int unsigned ADDR_WIDTH = RV32E ? 4 : 5; - localparam int unsigned NUM_WORDS = 2**ADDR_WIDTH; - - logic [DataWidth-1:0] mem[NUM_WORDS]; - - logic [NUM_WORDS-1:1] waddr_onehot_a; - - logic [NUM_WORDS-1:1] mem_clocks; - logic [DataWidth-1:0] wdata_a_q; - - // internal addresses - logic [ADDR_WIDTH-1:0] raddr_a_int, raddr_b_int, waddr_a_int; - - assign raddr_a_int = raddr_a_i[ADDR_WIDTH-1:0]; - assign raddr_b_int = raddr_b_i[ADDR_WIDTH-1:0]; - assign waddr_a_int = waddr_a_i[ADDR_WIDTH-1:0]; - - logic clk_int; - - ////////// - // READ // - ////////// - assign rdata_a_o = mem[raddr_a_int]; - assign rdata_b_o = mem[raddr_b_int]; - - /////////// - // WRITE // - /////////// - // Global clock gating - prim_clock_gating cg_we_global ( - .clk_i ( clk_i ), - .en_i ( we_a_i ), - .test_en_i ( test_en_i ), - .clk_o ( clk_int ) - ); - - // Sample input data - // Use clk_int here, since otherwise we don't want to write anything anyway. - always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata - if (!rst_ni) begin - wdata_a_q <= WordZeroVal; - end else begin - if (we_a_i) begin - wdata_a_q <= wdata_a_i; - end - end - end - - // Write address decoding - always_comb begin : wad - for (int i = 1; i < NUM_WORDS; i++) begin : wad_word_iter - if (we_a_i && (waddr_a_int == 5'(i))) begin - waddr_onehot_a[i] = 1'b1; - end else begin - waddr_onehot_a[i] = 1'b0; - end - end - end - - // Individual clock gating (if integrated clock-gating cells are available) - for (genvar x = 1; x < NUM_WORDS; x++) begin : gen_cg_word_iter - prim_clock_gating cg_i ( - .clk_i ( clk_int ), - .en_i ( waddr_onehot_a[x] ), - .test_en_i ( test_en_i ), - .clk_o ( mem_clocks[x] ) - ); - end - - // Actual write operation: - // Generate the sequential process for the NUM_WORDS words of the memory. - // The process is synchronized with the clocks mem_clocks[i], i = 1, ..., NUM_WORDS-1. - for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_latches - always_latch begin - if (mem_clocks[i]) begin - mem[i] = wdata_a_q; - end - end - end - - // With dummy instructions enabled, R0 behaves as a real register but will always return 0 for - // real instructions. - if (DummyInstructions) begin : g_dummy_r0 - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic we_r0_dummy; - logic r0_clock; - logic [DataWidth-1:0] mem_r0; - - // Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions) - assign we_r0_dummy = we_a_i & dummy_instr_id_i; - - // R0 clock gate - prim_clock_gating cg_i ( - .clk_i ( clk_int ), - .en_i ( we_r0_dummy ), - .test_en_i ( test_en_i ), - .clk_o ( r0_clock ) - ); - - always_latch begin : latch_wdata - if (r0_clock) begin - mem_r0 = wdata_a_q; - end - end - - // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal; - - end else begin : g_normal_r0 - logic unused_dummy_instr_id; - assign unused_dummy_instr_id = dummy_instr_id_i; - - assign mem[0] = WordZeroVal; - end - -`ifdef VERILATOR - initial begin - $display("Latch-based register file not supported for Verilator simulation"); - $fatal; - end -`endif - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv deleted file mode 100644 index b566bb17..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -`ifdef RISCV_FORMAL - `define RVFI -`endif - -`include "prim_assert.sv" - -/** - * Top level module of the ibex RISC-V core - */ -module ibex_top import ibex_pkg::*; #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter regfile_e RegFile = RegFileFF, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter bit ICacheScramble = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808, - // Default seed and nonce for scrambling - parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKey = RndCnstIbexKeyDefault, - parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonce = RndCnstIbexNonceDefault -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, // enable all clock gates for testing - input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, - - input logic [31:0] hart_id_i, - input logic [31:0] boot_addr_i, - - // Instruction memory interface - output logic instr_req_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - output logic [31:0] instr_addr_o, - input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, - input logic instr_err_i, - - // Data memory interface - output logic data_req_o, - input logic data_gnt_i, - input logic data_rvalid_i, - output logic data_we_o, - output logic [3:0] data_be_o, - output logic [31:0] data_addr_o, - output logic [31:0] data_wdata_o, - output logic [6:0] data_wdata_intg_o, - input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, - input logic data_err_i, - - // Interrupt inputs - input logic irq_software_i, - input logic irq_timer_i, - input logic irq_external_i, - input logic [14:0] irq_fast_i, - input logic irq_nm_i, // non-maskeable interrupt - - // Scrambling Interface - input logic scramble_key_valid_i, - input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, - input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, - output logic scramble_req_o, - - // Debug Interface - input logic debug_req_i, - output crash_dump_t crash_dump_o, - output logic double_fault_seen_o, - - // RISC-V Formal Interface - // Does not comply with the coding standards of _i/_o suffixes, but follows - // the convention of RISC-V Formal Interface Specification. -`ifdef RVFI - output logic rvfi_valid, - output logic [63:0] rvfi_order, - output logic [31:0] rvfi_insn, - output logic rvfi_trap, - output logic rvfi_halt, - output logic rvfi_intr, - output logic [ 1:0] rvfi_mode, - output logic [ 1:0] rvfi_ixl, - output logic [ 4:0] rvfi_rs1_addr, - output logic [ 4:0] rvfi_rs2_addr, - output logic [ 4:0] rvfi_rs3_addr, - output logic [31:0] rvfi_rs1_rdata, - output logic [31:0] rvfi_rs2_rdata, - output logic [31:0] rvfi_rs3_rdata, - output logic [ 4:0] rvfi_rd_addr, - output logic [31:0] rvfi_rd_wdata, - output logic [31:0] rvfi_pc_rdata, - output logic [31:0] rvfi_pc_wdata, - output logic [31:0] rvfi_mem_addr, - output logic [ 3:0] rvfi_mem_rmask, - output logic [ 3:0] rvfi_mem_wmask, - output logic [31:0] rvfi_mem_rdata, - output logic [31:0] rvfi_mem_wdata, - output logic [31:0] rvfi_ext_mip, - output logic rvfi_ext_nmi, - output logic rvfi_ext_debug_req, - output logic [63:0] rvfi_ext_mcycle, -`endif - - // CPU Control Signals - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, - output logic core_sleep_o, - - // DFT bypass controls - input logic scan_rst_ni -); - - localparam bit Lockstep = SecureIbex; - localparam bit ResetAll = Lockstep; - localparam bit DummyInstructions = SecureIbex; - localparam bit RegFileECC = SecureIbex; - localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; - // Icache parameters - localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE; - localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS; - localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE; - // Scrambling Parameter - localparam int unsigned NumAddrScrRounds = ICacheScramble ? 2 : 0; - localparam int unsigned NumDiffRounds = NumAddrScrRounds; - - // Clock signals - logic clk; - logic core_busy_d, core_busy_q; - logic clock_en; - logic irq_pending; - // Core <-> Register file signals - logic dummy_instr_id; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc, rf_rdata_a_ecc_buf; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc, rf_rdata_b_ecc_buf; - // Core <-> RAMs signals - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS]; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS]; - // Alert signals - logic core_alert_major, core_alert_minor; - logic lockstep_alert_major_internal, lockstep_alert_major_bus; - logic lockstep_alert_minor; - // Scramble signals - logic icache_inval; - logic [SCRAMBLE_KEY_W-1:0] scramble_key_q; - logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_q; - logic scramble_key_valid_d, scramble_key_valid_q; - logic scramble_req_d, scramble_req_q; - - fetch_enable_t fetch_enable_buf; - - ///////////////////// - // Main clock gate // - ///////////////////// - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - core_busy_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - end - end - - assign clock_en = core_busy_q | debug_req_i | irq_pending | irq_nm_i; - assign core_sleep_o = ~clock_en; - - prim_clock_gating core_clock_gate_i ( - .clk_i (clk_i), - .en_i (clock_en), - .test_en_i(test_en_i), - .clk_o (clk) - ); - - //////////////////////// - // Core instantiation // - //////////////////////// - - // Buffer security critical signals to prevent synthesis optimisation removing them - prim_buf #(.Width($bits(fetch_enable_t))) u_fetch_enable_buf ( - .in_i (fetch_enable_i), - .out_o(fetch_enable_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_a_ecc_buf ( - .in_i (rf_rdata_a_ecc), - .out_o(rf_rdata_a_ecc_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_b_ecc_buf ( - .in_i (rf_rdata_b_ecc), - .out_o(rf_rdata_b_ecc_buf) - ); - - ibex_core #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr) - ) u_ibex_core ( - .clk_i(clk), - .rst_ni, - - .hart_id_i, - .boot_addr_i, - - .instr_req_o, - .instr_gnt_i, - .instr_rvalid_i, - .instr_addr_o, - .instr_rdata_i, - .instr_err_i, - - .data_req_o, - .data_gnt_i, - .data_rvalid_i, - .data_we_o, - .data_be_o, - .data_addr_o, - .data_wdata_o, - .data_rdata_i, - .data_err_i, - - .dummy_instr_id_o (dummy_instr_id), - .rf_raddr_a_o (rf_raddr_a), - .rf_raddr_b_o (rf_raddr_b), - .rf_waddr_wb_o (rf_waddr_wb), - .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_buf), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_buf), - - .ic_tag_req_o (ic_tag_req), - .ic_tag_write_o (ic_tag_write), - .ic_tag_addr_o (ic_tag_addr), - .ic_tag_wdata_o (ic_tag_wdata), - .ic_tag_rdata_i (ic_tag_rdata), - .ic_data_req_o (ic_data_req), - .ic_data_write_o (ic_data_write), - .ic_data_addr_o (ic_data_addr), - .ic_data_wdata_o (ic_data_wdata), - .ic_data_rdata_i (ic_data_rdata), - .ic_scr_key_valid_i(scramble_key_valid_q), - - .irq_software_i, - .irq_timer_i, - .irq_external_i, - .irq_fast_i, - .irq_nm_i, - .irq_pending_o(irq_pending), - - .debug_req_i, - .crash_dump_o, - .double_fault_seen_o, - -`ifdef RVFI - .rvfi_valid, - .rvfi_order, - .rvfi_insn, - .rvfi_trap, - .rvfi_halt, - .rvfi_intr, - .rvfi_mode, - .rvfi_ixl, - .rvfi_rs1_addr, - .rvfi_rs2_addr, - .rvfi_rs3_addr, - .rvfi_rs1_rdata, - .rvfi_rs2_rdata, - .rvfi_rs3_rdata, - .rvfi_rd_addr, - .rvfi_rd_wdata, - .rvfi_pc_rdata, - .rvfi_pc_wdata, - .rvfi_mem_addr, - .rvfi_mem_rmask, - .rvfi_mem_wmask, - .rvfi_mem_rdata, - .rvfi_mem_wdata, - .rvfi_ext_mip, - .rvfi_ext_nmi, - .rvfi_ext_debug_req, - .rvfi_ext_mcycle, -`endif - - .fetch_enable_i(fetch_enable_buf), - .alert_minor_o (core_alert_minor), - .alert_major_o (core_alert_major), - .icache_inval_o(icache_inval), - .core_busy_o (core_busy_d) - ); - - ///////////////////////////////// - // Register file Instantiation // - ///////////////////////////////// - - if (RegFile == RegFileFF) begin : gen_regfile_ff - ibex_register_file_ff #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga - ibex_register_file_fpga #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end else if (RegFile == RegFileLatch) begin : gen_regfile_latch - ibex_register_file_latch #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end - - /////////////////////////////// - // Scrambling Infrastructure // - /////////////////////////////// - - if (ICacheScramble) begin : gen_scramble - - // SEC_CM: ICACHE.MEM.SCRAMBLE - // Scramble key valid starts with OTP returning new valid key and stays high - // until we request a new valid key. - assign scramble_key_valid_d = scramble_req_q ? scramble_key_valid_i : - icache_inval ? 1'b0 : - scramble_key_valid_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - scramble_key_q <= RndCnstIbexKey; - scramble_nonce_q <= RndCnstIbexNonce; - end else if (scramble_key_valid_i) begin - scramble_key_q <= scramble_key_i; - scramble_nonce_q <= scramble_nonce_i; - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - scramble_key_valid_q <= 1'b1; - scramble_req_q <= '0; - end else begin - scramble_key_valid_q <= scramble_key_valid_d; - scramble_req_q <= scramble_req_d; - end - end - - // Scramble key request starts with invalidate signal from ICache and stays high - // until we got a valid key. - assign scramble_req_d = scramble_req_q ? ~scramble_key_valid_i : icache_inval; - assign scramble_req_o = scramble_req_q; - - end else begin : gen_noscramble - - logic unused_scramble_inputs = scramble_key_valid_i & (|scramble_key_i) & (|RndCnstIbexKey) & - (|scramble_nonce_i) & (|RndCnstIbexNonce) & scramble_req_q & - icache_inval & scramble_key_valid_d & scramble_req_d; - - assign scramble_req_d = 1'b0; - assign scramble_req_q = 1'b0; - assign scramble_req_o = 1'b0; - assign scramble_key_q = '0; - assign scramble_nonce_q = '0; - assign scramble_key_valid_q = 1'b1; - assign scramble_key_valid_d = 1'b1; - end - - //////////////////////// - // Rams Instantiation // - //////////////////////// - - if (ICache) begin : gen_rams - - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner - - // SEC_CM: ICACHE.MEM.SCRAMBLE - // Tag RAM instantiation - prim_ram_1p_scr #( - .Width (TagSizeECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (TagSizeECC), - .EnableParity (0), - .DiffWidth (TagSizeECC), - .NumAddrScrRounds (NumAddrScrRounds), - .NumDiffRounds (NumDiffRounds) - ) tag_bank ( - .clk_i, - .rst_ni, - - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_tag_req[way]), - - .gnt_o (), - .write_i (ic_tag_write), - .addr_i (ic_tag_addr), - .wdata_i (ic_tag_wdata), - .wmask_i ({TagSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_tag_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) - ); - - // Data RAM instantiation - prim_ram_1p_scr #( - .Width (LineSizeECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (LineSizeECC), - .ReplicateKeyStream (1), - .EnableParity (0), - .DiffWidth (LineSizeECC), - .NumAddrScrRounds (NumAddrScrRounds), - .NumDiffRounds (NumDiffRounds) - ) data_bank ( - .clk_i, - .rst_ni, - - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_data_req[way]), - - .gnt_o (), - .write_i (ic_data_write), - .addr_i (ic_data_addr), - .wdata_i (ic_data_wdata), - .wmask_i ({LineSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_data_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) - ); - end - - end else begin : gen_norams - - prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; - logic unused_ram_inputs; - - assign unused_ram_cfg = ram_cfg_i; - assign unused_ram_inputs = (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) & (|ic_tag_wdata) & - (|ic_data_req) & ic_data_write & (|ic_data_addr) & (|ic_data_wdata) & - (|scramble_key_q) & (|scramble_nonce_q) & scramble_key_valid_q & - scramble_key_valid_d & (|scramble_nonce_q) & - (|NumAddrScrRounds); - - assign ic_tag_rdata = '{default:'b0}; - assign ic_data_rdata = '{default:'b0}; - - end - - // Redundant lockstep core implementation - if (Lockstep) begin : gen_lockstep - // SEC_CM: LOGIC.SHADOW - // Note: certain synthesis tools like DC are very smart at optimizing away redundant logic. - // Hence, we have to insert an optimization barrier at the IOs of the lockstep Ibex. - // This is achieved by manually buffering each bit using prim_buf. - // Our Xilinx and DC synthesis flows make sure that these buffers cannot be optimized away - // using keep attributes (Vivado) and size_only constraints (DC). - - localparam int NumBufferBits = $bits({ - hart_id_i, - boot_addr_i, - instr_req_o, - instr_gnt_i, - instr_rvalid_i, - instr_addr_o, - instr_rdata_i, - instr_rdata_intg_i, - instr_err_i, - data_req_o, - data_gnt_i, - data_rvalid_i, - data_we_o, - data_be_o, - data_addr_o, - data_wdata_o, - data_rdata_i, - data_rdata_intg_i, - data_err_i, - dummy_instr_id, - rf_raddr_a, - rf_raddr_b, - rf_waddr_wb, - rf_we_wb, - rf_wdata_wb_ecc, - rf_rdata_a_ecc, - rf_rdata_b_ecc, - ic_tag_req, - ic_tag_write, - ic_tag_addr, - ic_tag_wdata, - ic_data_req, - ic_data_write, - ic_data_addr, - ic_data_wdata, - scramble_key_valid_i, - irq_software_i, - irq_timer_i, - irq_external_i, - irq_fast_i, - irq_nm_i, - irq_pending, - debug_req_i, - crash_dump_o, - double_fault_seen_o, - fetch_enable_i, - icache_inval, - core_busy_d - }); - - logic [NumBufferBits-1:0] buf_in, buf_out; - - logic [31:0] hart_id_local; - logic [31:0] boot_addr_local; - - logic instr_req_local; - logic instr_gnt_local; - logic instr_rvalid_local; - logic [31:0] instr_addr_local; - logic [31:0] instr_rdata_local; - logic [6:0] instr_rdata_intg_local; - logic instr_err_local; - - logic data_req_local; - logic data_gnt_local; - logic data_rvalid_local; - logic data_we_local; - logic [3:0] data_be_local; - logic [31:0] data_addr_local; - logic [31:0] data_wdata_local; - logic [6:0] data_wdata_intg_local; - logic [31:0] data_rdata_local; - logic [6:0] data_rdata_intg_local; - logic data_err_local; - - logic dummy_instr_id_local; - logic [4:0] rf_raddr_a_local; - logic [4:0] rf_raddr_b_local; - logic [4:0] rf_waddr_wb_local; - logic rf_we_wb_local; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_local; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_local; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_local; - - logic [IC_NUM_WAYS-1:0] ic_tag_req_local; - logic ic_tag_write_local; - logic [IC_INDEX_W-1:0] ic_tag_addr_local; - logic [TagSizeECC-1:0] ic_tag_wdata_local; - logic [IC_NUM_WAYS-1:0] ic_data_req_local; - logic ic_data_write_local; - logic [IC_INDEX_W-1:0] ic_data_addr_local; - logic [LineSizeECC-1:0] ic_data_wdata_local; - logic scramble_key_valid_local; - - logic irq_software_local; - logic irq_timer_local; - logic irq_external_local; - logic [14:0] irq_fast_local; - logic irq_nm_local; - logic irq_pending_local; - - logic debug_req_local; - crash_dump_t crash_dump_local; - logic double_fault_seen_local; - fetch_enable_t fetch_enable_local; - - logic icache_inval_local; - logic core_busy_local; - - assign buf_in = { - hart_id_i, - boot_addr_i, - instr_req_o, - instr_gnt_i, - instr_rvalid_i, - instr_addr_o, - instr_rdata_i, - instr_rdata_intg_i, - instr_err_i, - data_req_o, - data_gnt_i, - data_rvalid_i, - data_we_o, - data_be_o, - data_addr_o, - data_wdata_o, - data_rdata_i, - data_rdata_intg_i, - data_err_i, - dummy_instr_id, - rf_raddr_a, - rf_raddr_b, - rf_waddr_wb, - rf_we_wb, - rf_wdata_wb_ecc, - rf_rdata_a_ecc, - rf_rdata_b_ecc, - ic_tag_req, - ic_tag_write, - ic_tag_addr, - ic_tag_wdata, - ic_data_req, - ic_data_write, - ic_data_addr, - ic_data_wdata, - scramble_key_valid_q, - irq_software_i, - irq_timer_i, - irq_external_i, - irq_fast_i, - irq_nm_i, - irq_pending, - debug_req_i, - crash_dump_o, - double_fault_seen_o, - fetch_enable_i, - icache_inval, - core_busy_d - }; - - assign { - hart_id_local, - boot_addr_local, - instr_req_local, - instr_gnt_local, - instr_rvalid_local, - instr_addr_local, - instr_rdata_local, - instr_rdata_intg_local, - instr_err_local, - data_req_local, - data_gnt_local, - data_rvalid_local, - data_we_local, - data_be_local, - data_addr_local, - data_wdata_local, - data_rdata_local, - data_rdata_intg_local, - data_err_local, - dummy_instr_id_local, - rf_raddr_a_local, - rf_raddr_b_local, - rf_waddr_wb_local, - rf_we_wb_local, - rf_wdata_wb_ecc_local, - rf_rdata_a_ecc_local, - rf_rdata_b_ecc_local, - ic_tag_req_local, - ic_tag_write_local, - ic_tag_addr_local, - ic_tag_wdata_local, - ic_data_req_local, - ic_data_write_local, - ic_data_addr_local, - ic_data_wdata_local, - scramble_key_valid_local, - irq_software_local, - irq_timer_local, - irq_external_local, - irq_fast_local, - irq_nm_local, - irq_pending_local, - debug_req_local, - crash_dump_local, - double_fault_seen_local, - fetch_enable_local, - icache_inval_local, - core_busy_local - } = buf_out; - - // Manually buffer all input signals. - prim_buf #(.Width(NumBufferBits)) u_signals_prim_buf ( - .in_i(buf_in), - .out_o(buf_out) - ); - - logic [TagSizeECC-1:0] ic_tag_rdata_local [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] ic_data_rdata_local [IC_NUM_WAYS]; - for (genvar k = 0; k < IC_NUM_WAYS; k++) begin : gen_ways - prim_buf #(.Width(TagSizeECC)) u_tag_prim_buf ( - .in_i(ic_tag_rdata[k]), - .out_o(ic_tag_rdata_local[k]) - ); - prim_buf #(.Width(LineSizeECC)) u_data_prim_buf ( - .in_i(ic_data_rdata[k]), - .out_o(ic_data_rdata_local[k]) - ); - end - - logic lockstep_alert_minor_local, lockstep_alert_major_internal_local; - logic lockstep_alert_major_bus_local; - - ibex_lockstep #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr) - ) u_ibex_lockstep ( - .clk_i (clk), - .rst_ni (rst_ni), - - .hart_id_i (hart_id_local), - .boot_addr_i (boot_addr_local), - - .instr_req_i (instr_req_local), - .instr_gnt_i (instr_gnt_local), - .instr_rvalid_i (instr_rvalid_local), - .instr_addr_i (instr_addr_local), - .instr_rdata_i (instr_rdata_local), - .instr_rdata_intg_i (instr_rdata_intg_local), - .instr_err_i (instr_err_local), - - .data_req_i (data_req_local), - .data_gnt_i (data_gnt_local), - .data_rvalid_i (data_rvalid_local), - .data_we_i (data_we_local), - .data_be_i (data_be_local), - .data_addr_i (data_addr_local), - .data_wdata_i (data_wdata_local), - .data_wdata_intg_o (data_wdata_intg_local), - .data_rdata_i (data_rdata_local), - .data_rdata_intg_i (data_rdata_intg_local), - .data_err_i (data_err_local), - - .dummy_instr_id_i (dummy_instr_id_local), - .rf_raddr_a_i (rf_raddr_a_local), - .rf_raddr_b_i (rf_raddr_b_local), - .rf_waddr_wb_i (rf_waddr_wb_local), - .rf_we_wb_i (rf_we_wb_local), - .rf_wdata_wb_ecc_i (rf_wdata_wb_ecc_local), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_local), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_local), - - .ic_tag_req_i (ic_tag_req_local), - .ic_tag_write_i (ic_tag_write_local), - .ic_tag_addr_i (ic_tag_addr_local), - .ic_tag_wdata_i (ic_tag_wdata_local), - .ic_tag_rdata_i (ic_tag_rdata_local), - .ic_data_req_i (ic_data_req_local), - .ic_data_write_i (ic_data_write_local), - .ic_data_addr_i (ic_data_addr_local), - .ic_data_wdata_i (ic_data_wdata_local), - .ic_data_rdata_i (ic_data_rdata_local), - .ic_scr_key_valid_i (scramble_key_valid_local), - - .irq_software_i (irq_software_local), - .irq_timer_i (irq_timer_local), - .irq_external_i (irq_external_local), - .irq_fast_i (irq_fast_local), - .irq_nm_i (irq_nm_local), - .irq_pending_i (irq_pending_local), - - .debug_req_i (debug_req_local), - .crash_dump_i (crash_dump_local), - .double_fault_seen_i (double_fault_seen_local), - - .fetch_enable_i (fetch_enable_local), - .alert_minor_o (lockstep_alert_minor_local), - .alert_major_internal_o (lockstep_alert_major_internal_local), - .alert_major_bus_o (lockstep_alert_major_bus_local), - .icache_inval_i (icache_inval_local), - .core_busy_i (core_busy_local), - .test_en_i (test_en_i), - .scan_rst_ni (scan_rst_ni) - ); - - // Manually buffer the output signals. - prim_buf #(.Width (7)) u_prim_buf_wdata_intg ( - .in_i(data_wdata_intg_local), - .out_o(data_wdata_intg_o) - ); - - prim_buf u_prim_buf_alert_minor ( - .in_i (lockstep_alert_minor_local), - .out_o(lockstep_alert_minor) - ); - - prim_buf u_prim_buf_alert_major_internal ( - .in_i (lockstep_alert_major_internal_local), - .out_o(lockstep_alert_major_internal) - ); - - prim_buf u_prim_buf_alert_major_bus ( - .in_i (lockstep_alert_major_bus_local), - .out_o(lockstep_alert_major_bus) - ); - - end else begin : gen_no_lockstep - assign lockstep_alert_major_internal = 1'b0; - assign lockstep_alert_major_bus = 1'b0; - assign lockstep_alert_minor = 1'b0; - assign data_wdata_intg_o = 'b0; - logic unused_scan, unused_intg; - assign unused_scan = scan_rst_ni; - assign unused_intg = |{instr_rdata_intg_i, data_rdata_intg_i}; - end - - assign alert_major_internal_o = core_alert_major | lockstep_alert_major_internal; - assign alert_major_bus_o = lockstep_alert_major_bus; - assign alert_minor_o = core_alert_minor | lockstep_alert_minor; - - // X checks for top-level outputs - `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) - `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) - - `ASSERT_KNOWN(IbexDataReqX, data_req_o) - `ASSERT_KNOWN_IF(IbexDataReqPayloadX, - {data_we_o, data_be_o, data_addr_o, data_wdata_o, data_wdata_intg_o}, data_req_o) - - `ASSERT_KNOWN(IbexScrambleReqX, scramble_req_o) - `ASSERT_KNOWN(IbexDoubleFaultSeenX, double_fault_seen_o) - `ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o) - `ASSERT_KNOWN(IbexAlertMajorInternalX, alert_major_internal_o) - `ASSERT_KNOWN(IbexAlertMajorBusX, alert_major_bus_o) - `ASSERT_KNOWN(IbexCoreSleepX, core_sleep_o) - - // X check for top-level inputs - `ASSERT_KNOWN(IbexTestEnX, test_en_i) - `ASSERT_KNOWN(IbexRamCfgX, ram_cfg_i) - `ASSERT_KNOWN(IbexHartIdX, hart_id_i) - `ASSERT_KNOWN(IbexBootAddrX, boot_addr_i) - - `ASSERT_KNOWN(IbexInstrGntX, instr_gnt_i) - `ASSERT_KNOWN(IbexInstrRValidX, instr_rvalid_i) - `ASSERT_KNOWN_IF(IbexInstrRPayloadX, - {instr_rdata_i, instr_rdata_intg_i, instr_err_i}, instr_rvalid_i) - - `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) - `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) - `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_rdata_intg_i, data_err_i}, data_rvalid_i) - - `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) - - `ASSERT_KNOWN(IbexScrambleKeyValidX, scramble_key_valid_i) - `ASSERT_KNOWN_IF(IbexScramblePayloadX, {scramble_key_i, scramble_nonce_i}, scramble_key_valid_i) - - `ASSERT_KNOWN(IbexDebugReqX, debug_req_i) - `ASSERT_KNOWN(IbexFetchEnableX, fetch_enable_i) -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv deleted file mode 100644 index 14364c57..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Writeback Stage - * - * Writeback is an optional third pipeline stage. It writes data back to the register file that was - * produced in the ID/EX stage or awaits a response to a load/store (LSU writes direct to register - * file for load data). If the writeback stage is not present (WritebackStage == 0) this acts as - * a simple passthrough to write data direct to the register file. - */ - -`include "prim_assert.sv" -//`include "dv_fcov_macros.svh" - -module ibex_wb_stage #( - parameter bit ResetAll = 1'b0, - parameter bit WritebackStage = 1'b0 -) ( - input logic clk_i, - input logic rst_ni, - - input logic en_wb_i, - input ibex_pkg::wb_instr_type_e instr_type_wb_i, - input logic [31:0] pc_id_i, - input logic instr_is_compressed_id_i, - input logic instr_perf_count_id_i, - - output logic ready_wb_o, - output logic rf_write_wb_o, - output logic outstanding_load_wb_o, - output logic outstanding_store_wb_o, - output logic [31:0] pc_wb_o, - output logic perf_instr_ret_wb_o, - output logic perf_instr_ret_compressed_wb_o, - output logic perf_instr_ret_wb_spec_o, - output logic perf_instr_ret_compressed_wb_spec_o, - - input logic [4:0] rf_waddr_id_i, - input logic [31:0] rf_wdata_id_i, - input logic rf_we_id_i, - - input logic [31:0] rf_wdata_lsu_i, - input logic rf_we_lsu_i, - - output logic [31:0] rf_wdata_fwd_wb_o, - - output logic [4:0] rf_waddr_wb_o, - output logic [31:0] rf_wdata_wb_o, - output logic rf_we_wb_o, - - input logic lsu_resp_valid_i, - input logic lsu_resp_err_i, - - output logic instr_done_wb_o -); - - import ibex_pkg::*; - - // 0 == RF write from ID - // 1 == RF write from LSU - logic [31:0] rf_wdata_wb_mux [2]; - logic [1:0] rf_wdata_wb_mux_we; - - if (WritebackStage) begin : g_writeback_stage - logic [31:0] rf_wdata_wb_q; - logic rf_we_wb_q; - logic [4:0] rf_waddr_wb_q; - - logic wb_done; - - logic wb_valid_q; - logic [31:0] wb_pc_q; - logic wb_compressed_q; - logic wb_count_q; - wb_instr_type_e wb_instr_type_q; - - logic wb_valid_d; - - // Stage becomes valid if an instruction enters for ID/EX and valid is cleared when instruction - // is done - assign wb_valid_d = (en_wb_i & ready_wb_o) | (wb_valid_q & ~wb_done); - - // Writeback for non load/store instructions always completes in a cycle (so instantly done) - // Writeback for load/store must wait for response to be received by the LSU - // Signal only relevant if wb_valid_q set - assign wb_done = (wb_instr_type_q == WB_INSTR_OTHER) | lsu_resp_valid_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - wb_valid_q <= 1'b0; - end else begin - wb_valid_q <= wb_valid_d; - end - end - - if (ResetAll) begin : g_wb_regs_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rf_we_wb_q <= '0; - rf_waddr_wb_q <= '0; - rf_wdata_wb_q <= '0; - wb_instr_type_q <= wb_instr_type_e'(0); - wb_pc_q <= '0; - wb_compressed_q <= '0; - wb_count_q <= '0; - end else if (en_wb_i) begin - rf_we_wb_q <= rf_we_id_i; - rf_waddr_wb_q <= rf_waddr_id_i; - rf_wdata_wb_q <= rf_wdata_id_i; - wb_instr_type_q <= instr_type_wb_i; - wb_pc_q <= pc_id_i; - wb_compressed_q <= instr_is_compressed_id_i; - wb_count_q <= instr_perf_count_id_i; - end - end - end else begin : g_wb_regs_nr - always_ff @(posedge clk_i) begin - if (en_wb_i) begin - rf_we_wb_q <= rf_we_id_i; - rf_waddr_wb_q <= rf_waddr_id_i; - rf_wdata_wb_q <= rf_wdata_id_i; - wb_instr_type_q <= instr_type_wb_i; - wb_pc_q <= pc_id_i; - wb_compressed_q <= instr_is_compressed_id_i; - wb_count_q <= instr_perf_count_id_i; - end - end - end - - assign rf_waddr_wb_o = rf_waddr_wb_q; - assign rf_wdata_wb_mux[0] = rf_wdata_wb_q; - assign rf_wdata_wb_mux_we[0] = rf_we_wb_q & wb_valid_q; - - assign ready_wb_o = ~wb_valid_q | wb_done; - - // Instruction in writeback will be writing to register file if either rf_we is set or writeback - // is awaiting load data. This is used for determining RF read hazards in ID/EX - assign rf_write_wb_o = wb_valid_q & (rf_we_wb_q | (wb_instr_type_q == WB_INSTR_LOAD)); - - assign outstanding_load_wb_o = wb_valid_q & (wb_instr_type_q == WB_INSTR_LOAD); - assign outstanding_store_wb_o = wb_valid_q & (wb_instr_type_q == WB_INSTR_STORE); - - assign pc_wb_o = wb_pc_q; - - assign instr_done_wb_o = wb_valid_q & wb_done; - - // Increment instruction retire counters for valid instructions which are not lsu errors. - // Speculative versions of the signals do not factor in exceptions and whether the instruction - // is done yet. These are used to get correct values for instructions reading the relevant - // performance counters in the ID stage. - assign perf_instr_ret_wb_spec_o = wb_count_q; - assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q; - assign perf_instr_ret_wb_o = instr_done_wb_o & wb_count_q & - ~(lsu_resp_valid_i & lsu_resp_err_i); - assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q; - - // Forward data that will be written to the RF back to ID to resolve data hazards. The flopped - // rf_wdata_wb_q is used rather than rf_wdata_wb_o as the latter includes read data from memory - // that returns too late to be used on the forwarding path. - assign rf_wdata_fwd_wb_o = rf_wdata_wb_q; - end else begin : g_bypass_wb - // without writeback stage just pass through register write signals - assign rf_waddr_wb_o = rf_waddr_id_i; - assign rf_wdata_wb_mux[0] = rf_wdata_id_i; - assign rf_wdata_wb_mux_we[0] = rf_we_id_i; - - // Increment instruction retire counters for valid instructions which are not lsu errors. - // The speculative signals are always 0 when no writeback stage is present as the raw counter - // values will be correct. - assign perf_instr_ret_wb_spec_o = 1'b0; - assign perf_instr_ret_compressed_wb_spec_o = 1'b0; - assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i & - ~(lsu_resp_valid_i & lsu_resp_err_i); - assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i; - - // ready needs to be constant 1 without writeback stage (otherwise ID/EX stage will stall) - assign ready_wb_o = 1'b1; - - // Unused Writeback stage only IO & wiring - // Assign inputs and internal wiring to unused signals to satisfy lint checks - // Tie-off outputs to constant values - logic unused_clk; - logic unused_rst; - wb_instr_type_e unused_instr_type_wb; - logic [31:0] unused_pc_id; - - assign unused_clk = clk_i; - assign unused_rst = rst_ni; - assign unused_instr_type_wb = instr_type_wb_i; - assign unused_pc_id = pc_id_i; - - assign outstanding_load_wb_o = 1'b0; - assign outstanding_store_wb_o = 1'b0; - assign pc_wb_o = '0; - assign rf_write_wb_o = 1'b0; - assign rf_wdata_fwd_wb_o = 32'b0; - assign instr_done_wb_o = 1'b0; - end - - assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i; - assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; - - // RF write data can come from ID results (all RF writes that aren't because of loads will come - // from here) or the LSU (RF writes for load data) - assign rf_wdata_wb_o = ({32{rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | - ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); - assign rf_we_wb_o = |rf_wdata_wb_mux_we; - - //`DV_FCOV_SIGNAL_GEN_IF(logic, wb_valid, g_writeback_stage.wb_valid_q, WritebackStage) - - `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md new file mode 100644 index 00000000..e69de29b diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core new file mode 100644 index 00000000..02c03356 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_fcov_macros" +description: "DV FCOV macros" + +filesets: + files_fcov: + files: + - dv_fcov_macros.svh: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_fcov diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh new file mode 100644 index 00000000..8ca12cdc --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh @@ -0,0 +1,112 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Include FCOV RTL by default. Disable it for synthesis and where explicitly requested (by defining +// DV_FCOV_DISABLE). +`ifdef SYNTHESIS + `define DV_FCOV_DISABLE +`elsif YOSYS + `define DV_FCOV_DISABLE +`endif + +// Disable instantiations of FCOV coverpoints or covergroups. +`ifdef VERILATOR + `define DV_FCOV_DISABLE_CP +`elsif DV_FCOV_DISABLE + `define DV_FCOV_DISABLE_CP +`endif + +// Instantiates a covergroup in an interface or module. +// +// This macro assumes that a covergroup of the same name as the NAME_ arg is defined in the +// interface or module. It just adds some extra signals and logic to control the creation of the +// covergroup instance with ~bit en_~. This defaults to 0. It is ORed with the external +// COND_ signal. The testbench can modify it at t = 0 based on the test being run. +// NOTE: This is not meant to be invoked inside a class. +// +// NAME_ : Name of the covergroup. +// COND_ : External condition / expr that controls the creation of the covergroup. +// ARGS_ : Arguments to covergroup instance, if any. Args MUST BE wrapped in (..). +`ifndef DV_FCOV_INSTANTIATE_CG +`ifdef DV_FCOV_DISABLE_CP + `define DV_FCOV_INSTANTIATE_CG(NAME_, COND_ = 1'b1, ARGS_ = ()) +`else + `define DV_FCOV_INSTANTIATE_CG(NAME_, COND_ = 1'b1, ARGS_ = ()) \ + bit en_``NAME_ = 1'b0; \ + NAME_ NAME_``_inst; \ + initial begin \ + /* The #1 delay below allows any part of the tb to control the conditions first at t = 0. */ \ + #1; \ + if ((en_``NAME_) || (COND_)) begin \ + $display("%0t: (%0s:%0d) [%m] %0s", $time, `__FILE__, `__LINE__, \ + {"Creating covergroup ", `"NAME_`"}); \ + NAME_``_inst = new``ARGS_; \ + end \ + end +`endif +`endif + +// Creates a coverpoint for an expression where only the expression true case is of interest for +// coverage (e.g. where the expression indicates an event has occured). +`ifndef DV_FCOV_EXPR_SEEN +`ifdef DV_FCOV_DISABLE_CP + `define DV_FCOV_EXPR_SEEN(NAME_, EXPR_) +`else + `define DV_FCOV_EXPR_SEEN(NAME_, EXPR_) cp_``NAME_: coverpoint EXPR_ { bins seen = {1}; } +`endif +`endif + +// Creates a SVA cover that can be used in a covergroup. +// +// This macro creates an unnamed SVA cover from the property (or an expression) `PROP_` and an event +// with the name `EV_NAME_`. When the SVA cover is hit, the event is triggered. A coverpoint can +// cover the `triggered` property of the event. +`ifndef DV_FCOV_SVA +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SVA(EV_NAME_, PROP_, CLK_ = clk_i, RST_ = rst_ni) +`else + `define DV_FCOV_SVA(EV_NAME_, PROP_, CLK_ = clk_i, RST_ = rst_ni) \ + event EV_NAME_; \ + cover property (@(posedge CLK_) disable iff (RST_ == 0) (PROP_)) begin \ + -> EV_NAME_; \ + end +`endif +`endif + +// Coverage support is not always available but it's useful to include extra fcov signals for +// linting purposes. They need to be marked as unused to avoid warnings. +`ifndef DV_FCOV_MARK_UNUSED + `define DV_FCOV_MARK_UNUSED(TYPE_, NAME_) \ + TYPE_ unused_fcov_``NAME_; \ + assign unused_fcov_``NAME_ = fcov_``NAME_; +`endif + +// Define a signal and expression in the design for capture in functional coverage +`ifndef DV_FCOV_SIGNAL +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SIGNAL(TYPE_, NAME_, EXPR_) +`else + `define DV_FCOV_SIGNAL(TYPE_, NAME_, EXPR_) \ + TYPE_ fcov_``NAME_; \ + assign fcov_``NAME_ = EXPR_; \ + `DV_FCOV_MARK_UNUSED(TYPE_, NAME_) +`endif +`endif + +// Define a signal and expression in the design for capture in functional coverage depending on +// design configuration. The input GEN_COND_ must be a constant or parameter. +`ifndef DV_FCOV_SIGNAL_GEN_IF +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SIGNAL_GEN_IF(TYPE_, NAME_, EXPR_, GEN_COND_, DEFAULT_ = '0) +`else + `define DV_FCOV_SIGNAL_GEN_IF(TYPE_, NAME_, EXPR_, GEN_COND_, DEFAULT_ = '0) \ + TYPE_ fcov_``NAME_; \ + if (GEN_COND_) begin : g_fcov_``NAME_ \ + assign fcov_``NAME_ = EXPR_; \ + end else begin : g_no_fcov_``NAME_ \ + assign fcov_``NAME_ = DEFAULT_; \ + end \ + `DV_FCOV_MARK_UNUSED(TYPE_, NAME_) +`endif +`endif diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core new file mode 100644 index 00000000..5f2fb800 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_macros" +description: "A collection of macros used in DV." + +filesets: + files_dv: + files: + - dv_macros.svh: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_dv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh new file mode 100644 index 00000000..2e5e1375 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh @@ -0,0 +1,536 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef UVM + `include "uvm_macros.svh" +`endif + +// UVM speficic macros +`ifndef gfn +`ifdef UVM + // verilog_lint: waive macro-name-style + `define gfn get_full_name() +`else + // verilog_lint: waive macro-name-style + `define gfn $sformatf("%m") +`endif +`endif + +`ifndef gtn + // verilog_lint: waive macro-name-style + `define gtn get_type_name() +`endif + +`ifndef gn + // verilog_lint: waive macro-name-style + `define gn get_name() +`endif + +`ifndef gmv + // verilog_lint: waive macro-name-style + `define gmv(csr) csr.get_mirrored_value() +`endif + +// cast base class obj holding extended class handle to extended class handle; +// throw error if cast fails +`ifndef downcast + // verilog_lint: waive macro-name-style + `define downcast(EXT_, BASE_, MSG_="", SEV_=fatal, ID_=`gfn) \ + begin \ + if (!$cast(EXT_, BASE_)) begin \ + `dv_``SEV_($sformatf({"Cast failed: base class variable %0s ", \ + "does not hold extended class %0s handle %s"}, \ + `"BASE_`", `"EXT_`", MSG_), ID_) \ + end \ + end +`endif + +// Note, UVM provides a macro `uvm_new_func -- which only applies to uvm_components +`ifndef uvm_object_new + `define uvm_object_new \ + function new (string name=""); \ + super.new(name); \ + endfunction : new +`endif + +`ifndef uvm_create_obj + `define uvm_create_obj(_type_name_, _inst_name_) \ + _inst_name_ = _type_name_::type_id::create(`"_inst_name_`"); +`endif + +`ifndef uvm_component_new + `define uvm_component_new \ + function new (string name="", uvm_component parent=null); \ + super.new(name, parent); \ + endfunction : new +`endif + +`ifndef uvm_create_comp + `define uvm_create_comp(_type_name_, _inst_name_) \ + _inst_name_ = _type_name_::type_id::create(`"_inst_name_`", this); +`endif + +// Convert arbitrary text / expression to string. +`ifndef DV_STRINGIFY + `define DV_STRINGIFY(I_) `"I_`" +`endif + +`ifndef DUT_HIER_STR + `define DUT_HIER_STR `DV_STRINGIFY(`DUT_HIER) +`endif + +// Common check macros used by DV_CHECK error and fatal macros. +// Note: Should not be called by user code +`ifndef DV_CHECK + `define DV_CHECK(T_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!(T_)) begin \ + `dv_``SEV_($sformatf("Check failed (%s) %s ", `"T_`", MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_EQ + `define DV_CHECK_EQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) == (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s == %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_NE + `define DV_CHECK_NE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) != (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s != %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_CASE_EQ + `define DV_CHECK_CASE_EQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) === (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s === %s (0x%0h [%0b] vs 0x%0h [%0b]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_CASE_NE + `define DV_CHECK_CASE_NE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) !== (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s !== %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_LT + `define DV_CHECK_LT(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) < (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s < %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_GT + `define DV_CHECK_GT(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) > (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s > %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_LE + `define DV_CHECK_LE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) <= (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s <= %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_GE + `define DV_CHECK_GE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) >= (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s >= %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_STREQ + `define DV_CHECK_STREQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + if (!((ACT_) == (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed \"%s\" == \"%s\" %s", ACT_, EXP_, MSG_), ID_) \ + end +`endif + +`ifndef DV_CHECK_STRNE + `define DV_CHECK_STRNE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + if (!((ACT_) != (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed \"%s\" != \"%s\" %s", ACT_, EXP_, MSG_), ID_) \ + end +`endif + +// Fatal version of the checks +`ifndef DV_CHECK_FATAL + `define DV_CHECK_FATAL(T_, MSG_="", ID_=`gfn) \ + `DV_CHECK(T_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_EQ_FATAL + `define DV_CHECK_EQ_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_EQ(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_NE_FATAL + `define DV_CHECK_NE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_NE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_LT_FATAL + `define DV_CHECK_LT_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_LT(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_GT_FATAL + `define DV_CHECK_GT_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_GT(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_LE_FATAL + `define DV_CHECK_LE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_LE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_GE_FATAL + `define DV_CHECK_GE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_GE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_STREQ_FATAL + `define DV_CHECK_STREQ_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_STREQ(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_STRNE_FATAL + `define DV_CHECK_STRNE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_STRNE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +// Shorthand for common foo.randomize() + fatal check +`ifndef DV_CHECK_RANDOMIZE_FATAL + `define DV_CHECK_RANDOMIZE_FATAL(VAR_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(VAR_.randomize(), MSG_, ID_) +`endif + +// Shorthand for common foo.randomize() with { } + fatal check +`ifndef DV_CHECK_RANDOMIZE_WITH_FATAL + `define DV_CHECK_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(VAR_.randomize() with {WITH_C_}, MSG_, ID_) +`endif + +// Shorthand for common std::randomize(foo) + fatal check +`ifndef DV_CHECK_STD_RANDOMIZE_FATAL + `define DV_CHECK_STD_RANDOMIZE_FATAL(VAR_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(std::randomize(VAR_), MSG_, ID_) +`endif + +// Shorthand for common std::randomize(foo) with { } + fatal check +`ifndef DV_CHECK_STD_RANDOMIZE_WITH_FATAL + `define DV_CHECK_STD_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!",ID_=`gfn) \ + `DV_CHECK_FATAL(std::randomize(VAR_) with {WITH_C_}, MSG_, ID_) +`endif + +// Shorthand for common cls_inst.randomize(member) + fatal check +// Randomizes a specific member of a class instance. +`ifndef DV_CHECK_MEMBER_RANDOMIZE_FATAL + `define DV_CHECK_MEMBER_RANDOMIZE_FATAL(VAR_, CLS_INST_=this, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(CLS_INST_.randomize(VAR_), MSG_, ID_) +`endif + +// Shorthand for common cls_inst.randomize(member) with { } + fatal check +// Randomizes a specific member of a class instance with inline constraints. +`ifndef DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL + `define DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(VAR_, C_, CLS_INST_=this, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(CLS_INST_.randomize(VAR_) with {C_}, MSG_, ID_) +`endif + +// print static/dynamic 1d array or queue +`ifndef DV_PRINT_ARR_CONTENTS +`define DV_PRINT_ARR_CONTENTS(ARR_, V_=uvm_pkg::UVM_MEDIUM, ID_=`gfn) \ + begin \ + foreach (ARR_[i]) begin \ + `dv_info($sformatf("%s[%0d] = %0d (0x%0h)", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_TLM_FIFO_CONTENTS +`define DV_EOT_PRINT_TLM_FIFO_CONTENTS(TYP_, FIFO_, SEV_=error, ID_=`gfn) \ + begin \ + while (!FIFO_.is_empty()) begin \ + TYP_ item; \ + void'(FIFO_.try_get(item)); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"FIFO_`", item.sprint()), ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_TLM_FIFO_ARR_CONTENTS +`define DV_EOT_PRINT_TLM_FIFO_ARR_CONTENTS(TYP_, FIFO_, SEV_=error, ID_=`gfn) \ + begin \ + foreach (FIFO_[i]) begin \ + while (!FIFO_[i].is_empty()) begin \ + TYP_ item; \ + void'(FIFO_[i].try_get(item)); \ + `dv_``SEV_($sformatf("%s[%0d] item uncompared:\n%s", `"FIFO_`", i, item.sprint()), ID_) \ + end \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_Q_CONTENTS +`define DV_EOT_PRINT_Q_CONTENTS(TYP_, Q_, SEV_=error, ID_=`gfn) \ + begin \ + while (Q_.size() != 0) begin \ + TYP_ item = Q_.pop_front(); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"Q_`", item.sprint()), ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_Q_ARR_CONTENTS +`define DV_EOT_PRINT_Q_ARR_CONTENTS(TYP_, Q_, SEV_=error, ID_=`gfn) \ + begin \ + foreach (Q_[i]) begin \ + while (Q_[i].size() != 0) begin \ + TYP_ item = Q_[i].pop_front(); \ + `dv_``SEV_($sformatf("%s[%0d] item uncompared:\n%s", `"Q_`", i, item.sprint()), ID_) \ + end \ + end \ + end +`endif + +// check for non-empty mailbox and print items that were uncompared at end of test +`ifndef DV_EOT_PRINT_MAILBOX_CONTENTS +`define DV_EOT_PRINT_MAILBOX_CONTENTS(TYP_, MAILBOX_, SEV_=error, ID_=`gfn) \ + begin \ + while (MAILBOX_.num() != 0) begin \ + TYP_ item; \ + void'(MAILBOX_.try_get(item)); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"MAILBOX_`", item.sprint()), ID_) \ + end \ + end +`endif + +// get parity - implemented as a macro so that it can be invoked in constraints as well +`ifndef GET_PARITY + `define GET_PARITY(val, odd=0) (^val ^ odd) +`endif + +// Wait a task or statement with exit condition +// Kill the thread when either the wait statement is completed or exit condition occurs +// input WAIT_ need to be a statement. Here are some examples +// `DV_SPINWAIT(wait(...);, "Wait for ...") +// `DV_SPINWAIT( +// while (1) begin +// ... +// end) +`ifndef DV_SPINWAIT_EXIT +`define DV_SPINWAIT_EXIT(WAIT_, EXIT_, MSG_ = "exit condition occurred!", ID_ =`gfn) \ + begin \ + fork begin \ + fork \ + begin \ + WAIT_ \ + end \ + begin \ + EXIT_ \ + if (MSG_ != "") begin \ + `dv_info(MSG_, uvm_pkg::UVM_HIGH, ID_) \ + end \ + end \ + join_any \ + disable fork; \ + end join \ + end +`endif + +// wait a task or statement with timer watchdog +`ifndef DV_SPINWAIT +`define DV_SPINWAIT(WAIT_, MSG_ = "timeout occurred!", TIMEOUT_NS_ = default_spinwait_timeout_ns, ID_ =`gfn) \ + `DV_SPINWAIT_EXIT(WAIT_, wait_timeout(TIMEOUT_NS_, ID_, MSG_);, "", ID_) +`endif + +// Control assertions in the DUT. +// +// This macro is invoked in top level testbench that instantiates the DUT. It spawns off an initial +// block that forever waits for a resource of type bit named by the string arg ~LABEL_~ that +// can be set by any entity in the testbench. Based on the value set, it enables or disables the +// assertions at the hierarchy of the provided path. The entity setting the resource value invokes +// uvm_config_db#(bit)::set(...) and this macro calls the corresponding get. +// +// LABEL_ : Name of the assertion control resource bit (string). +// HIER_ : Path to the module within which the assertion is controlled. +// LEVELS_: Number of levels within the module to control the assertions. +// SCOPE_ : Hierarchical string path to the testbench where this macro is invoked, example: %m. +// ID_ : Identifier string used for UVM logs. +`ifndef DV_ASSERT_CTRL +`define DV_ASSERT_CTRL(LABEL_, HIER_, LEVELS_ = 0, SCOPE_ = "", ID_ = $sformatf("%m")) \ + initial begin \ + bit assert_en; \ + forever begin \ + uvm_config_db#(bit)::wait_modified(null, SCOPE_, LABEL_); \ + if (!uvm_config_db#(bit)::get(null, SCOPE_, LABEL_, assert_en)) begin \ + `uvm_fatal(ID_, $sformatf("Failed to get \"%0s\" from uvm_config_db", LABEL_)) \ + end \ + if (assert_en) begin \ + `uvm_info(ID_, $sformatf("Enabling assertions: %0s", `DV_STRINGIFY(HIER_)), UVM_LOW) \ + $asserton(LEVELS_, HIER_); \ + end else begin \ + `uvm_info(ID_, $sformatf("Disabling assertions: %0s", `DV_STRINGIFY(HIER_)), UVM_LOW) \ + $assertoff(LEVELS_, HIER_); \ + end \ + end \ + end +`endif + +// Retrieves a plusarg value representing an enum literal. +// +// The plusarg is parsed as a string, which needs to be converted into the enum literal whose name +// matches the string. This functionality is provided by the UVM helper function below. +// +// ENUM_: The enum type. +// VAR_: The enum variable to which the plusarg value will be set (must be declared already). +// PLUSARG_: the name of the plusarg (as raw text). This is typically the same as the enum variable. +// CHECK_EXISTS_: Throws a fatal error if the plusarg is not set. +`ifndef DV_GET_ENUM_PLUSARG +`define DV_GET_ENUM_PLUSARG(ENUM_, VAR_, PLUSARG_ = VAR_, CHECK_EXISTS_ = 0, ID_ = `gfn) \ + begin \ + string str; \ + if ($value$plusargs("``PLUSARG_``=%0s", str)) begin \ + if (!uvm_enum_wrapper#(ENUM_)::from_name(str, VAR_)) begin \ + `uvm_fatal(ID_, $sformatf("Cannot find %s from enum ``ENUM_``", VAR_.name())) \ + end \ + end else if (CHECK_EXISTS_) begin \ + `uvm_fatal(ID_, "Please pass the plusarg +``PLUSARG_``=<``ENUM_``-literal>") \ + end \ + end +`endif + +// Enable / disable assertions at a module hierarchy identified by LABEL_. +// +// This goes in conjunction with `DV_ASSERT_CTRL() macro above, but is invoked in the entity that is +// sending the req to turn on / off the assertions. Note that that piece of code invoking this macro +// does not have the information on the actual hierarchical path to the module or the levels - this +// is 'wrapped' into the LABEL_ instead. DV user needs to uniquify the label sufficienly enough to +// reflect it. +// +// LABEL_ : Name of the assertion control resource bit (string). +// VALUE_ : Value of the control bit - 1 - enable assertions, 0 - disable assertions. +// SCOPE_ : Hierarchical string path to the testbench where this macro is invoked, example: %m. +`ifndef DV_ASSERT_CTRL_REQ +`define DV_ASSERT_CTRL_REQ(LABEL_, VALUE_, SCOPE_="") \ + begin \ + uvm_config_db#(bit)::set(null, SCOPE_, LABEL_, VALUE_); \ + end +`endif + +// Macros for logging (info, warning, error and fatal severities). +// +// These are meant to be invoked in modules and interfaces that are shared between DV and Verilator +// testbenches. We waive the lint requirement for these to be in uppercase, since they are +// UVM-adjacent. +`ifdef UVM +`ifndef dv_info + // verilog_lint: waive macro-name-style + `define dv_info(MSG_, VERBOSITY_ = uvm_pkg::UVM_LOW, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(VERBOSITY_, uvm_pkg::UVM_INFO, ID_)) begin \ + uvm_pkg::uvm_report_info(ID_, MSG_, VERBOSITY_, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_warning + // verilog_lint: waive macro-name-style + `define dv_warning(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_WARNING, ID_)) begin \ + uvm_pkg::uvm_report_warning(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_error + // verilog_lint: waive macro-name-style + `define dv_error(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_ERROR, ID_)) begin \ + uvm_pkg::uvm_report_error(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_fatal + // verilog_lint: waive macro-name-style + `define dv_fatal(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_FATAL, ID_)) begin \ + uvm_pkg::uvm_report_fatal(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`else // UVM + +`ifndef dv_info + // verilog_lint: waive macro-name-style + `define dv_info(MSG_, VERBOSITY = DUMMY_, ID_ = $sformatf("%m")) \ + $display("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_warning + // verilog_lint: waive macro-name-style + `define dv_warning(MSG_, ID_ = $sformatf("%m")) \ + $warning("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_error + // verilog_lint: waive macro-name-style + `define dv_error(MSG_, ID_ = $sformatf("%m")) \ + $error("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_fatal + // verilog_lint: waive macro-name-style + `define dv_fatal(MSG_, ID_ = $sformatf("%m")) \ + $fatal("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`endif // UVM + +// Macros for constrain clk with common frequencies +// constrain clock to run at 24Mhz - 100Mhz and use higher weights on 24, 25, 48, 50, 100 +`ifndef DV_COMMON_CLK_CONSTRAINT +`define DV_COMMON_CLK_CONSTRAINT(FREQ_) \ + FREQ_ dist { \ + [24:25] :/ 2, \ + [26:47] :/ 1, \ + [48:50] :/ 2, \ + [51:95] :/ 1, \ + 96 :/ 1, \ + [97:99] :/ 1, \ + 100 :/ 1 \ + }; +`endif diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv new file mode 100644 index 00000000..91e3337e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv @@ -0,0 +1,46 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// Report catcher/demoter +class dv_report_catcher extends uvm_report_catcher; + + // Stores a new severity indexed by the ID and + // the regular expression to match the message + protected uvm_severity m_changed_sev[string][string]; + + `uvm_object_utils(dv_report_catcher) + `uvm_object_new + + // Called for all report messages - defined in uvm_report_catcher + virtual function action_e catch(); + string id = get_id(); + if (m_changed_sev.exists(id)) begin + string report_msg = get_message(); + foreach (m_changed_sev[id][msg]) begin + if (uvm_re_match(msg, report_msg)) begin + set_severity(m_changed_sev[id][msg]); + end + end + end + return THROW; + endfunction + + // Change severity of a message with ID == id and message text + // matching msg which is treated as a regular expression + virtual function void add_change_sev(string id, string msg, uvm_severity sev); + m_changed_sev[id][msg] = sev; + endfunction + + // Remove a change entry + // If msg == "" then remove all changes for a given id + virtual function void remove_change_sev(string id, string msg = ""); + if (m_changed_sev.exists(id)) + if (msg == "") begin + // Delete all with id if message is blank + m_changed_sev.delete(id); + end else if (m_changed_sev[id].exists(msg)) begin + m_changed_sev[id].delete(msg); + end + endfunction + +endclass diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv new file mode 100644 index 00000000..a5d7440e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv @@ -0,0 +1,65 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Standardize look & feel of report phase and uvm logging messages. +class dv_report_server extends uvm_default_report_server; + + bit show_file_line = 1'b1; + // if enabled, show the relative path of the file. By default only show file name + bit show_file_path = 1'b0; + bit use_default_uvm_report_message_format = 1'b0; + + function new (string name = ""); + super.new(name); + // provide ability to override these knobs over cli + void'($value$plusargs("show_file_line=%0b", show_file_line)); + void'($value$plusargs("show_file_path=%0b", show_file_path)); + void'($value$plusargs("use_default_uvm_report_message_format=%0b", + use_default_uvm_report_message_format)); + endfunction + + function void report_summarize(UVM_FILE file = 0); + int num_uvm_warning; + int num_uvm_error; + int num_uvm_fatal; + + num_uvm_warning = get_severity_count(UVM_WARNING); + num_uvm_error = get_severity_count(UVM_ERROR); + num_uvm_fatal = get_severity_count(UVM_FATAL); + + // Print default summary report + super.report_summarize(file); + + // Print final test pass-fail - external tool can use this signature for test status + // Treat UVM_WARNINGs as a sign of test failure since it could silently result in false pass + dv_test_status_pkg::dv_test_status((num_uvm_warning + num_uvm_error + num_uvm_fatal) == 0); + endfunction + + // Override default messaging format to standard "pretty" format for all testbenches + virtual function string compose_report_message(uvm_report_message report_message, + string report_object_name = ""); + + if (use_default_uvm_report_message_format) begin + return (super.compose_report_message(report_message, report_object_name)); + end else begin + uvm_severity severity = report_message.get_severity(); + string filename = report_message.get_filename(); + int line = report_message.get_line(); + string obj_name = report_message.get_report_object().get_full_name(); + string id = report_message.get_id(); + string message = report_message.get_message(); + string file_line; + + if (show_file_line && filename != "") begin + if (!show_file_path) filename = str_utils_pkg::str_path_basename(filename); + file_line = $sformatf("(%0s:%0d) ", filename, line); + end + obj_name = {obj_name, ((obj_name != "") ? " " : "")}; + compose_report_message = $sformatf({"%0s @ %t: ", file_line, obj_name, "[%0s] %0s"}, + severity.name(), $realtime, id, message); + return compose_report_message; + end + endfunction + +endclass diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core new file mode 100644 index 00000000..bbec1b05 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_test_status" +description: "DV test status reporting utilities" + +filesets: + files_dv: + files: + - dv_test_status_pkg.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv new file mode 100644 index 00000000..3a81ddfc --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv @@ -0,0 +1,31 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package dv_test_status_pkg; + + // Prints the test status signature & banner. + // + // This function takes a boolean arg indicating whether the test passed or failed and prints the + // signature along with a banner. The signature can be used by external scripts to determine if + // the test passed or failed. + function automatic void dv_test_status(bit passed); + if (passed) begin + $display("\nTEST PASSED CHECKS"); + $display(" _____ _ _ _ "); + $display("|_ _|__ ___| |_ _ __ __ _ ___ ___ ___ __| | |"); + $display(" | |/ _ \\/ __| __| | '_ \\ / _` / __/ __|/ _ \\/ _` | |"); + $display(" | | __/\\__ \\ |_ | |_) | (_| \\__ \\__ \\ __/ (_| |_|"); + $display(" |_|\\___||___/\\__| | .__/ \\__,_|___/___/\\___|\\__,_(_)"); + $display(" |_| \n"); + end else begin + $display("\nTEST FAILED CHECKS"); + $display(" _____ _ __ _ _ _ _ "); + $display("|_ _|__ ___| |_ / _| __ _(_) | ___ __| | |"); + $display(" | |/ _ \\/ __| __| | |_ / _` | | |/ _ \\/ _` | |"); + $display(" | | __/\\__ \\ |_ | _| (_| | | | __/ (_| |_|"); + $display(" |_|\\___||___/\\__| |_| \\__,_|_|_|\\___|\\__,_(_)\n"); + end + endfunction + +endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core new file mode 100644 index 00000000..1e405236 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core @@ -0,0 +1,28 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_utils" +description: "DV utilities" + +filesets: + files_dv: + depend: + - lowrisc:dv:dv_macros + - lowrisc:dv:dv_fcov_macros + - lowrisc:dv:common_ifs + - lowrisc:prim:assert:0.1 + - lowrisc:cve2:bus_params_pkg + - lowrisc:dv:str_utils + - lowrisc:dv:dv_test_status + files: + - dv_utils_pkg.sv + - dv_report_catcher.sv: {is_include_file: true} + - dv_report_server.sv: {is_include_file: true} + - dv_vif_wrap.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv new file mode 100644 index 00000000..62f3b765 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv @@ -0,0 +1,223 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package dv_utils_pkg; + // dep packages + import uvm_pkg::*; + import bus_params_pkg::*; + + // macro includes + `include "dv_macros.svh" +`ifdef UVM + `include "uvm_macros.svh" +`endif + + // common parameters used across all benches + parameter int NUM_MAX_INTERRUPTS = 32; + typedef logic [NUM_MAX_INTERRUPTS-1:0] interrupt_t; + + parameter int NUM_MAX_ALERTS = 32; + typedef logic [NUM_MAX_ALERTS-1:0] alert_t; + + // types & variables + typedef bit [31:0] uint; + typedef bit [7:0] uint8; + typedef bit [15:0] uint16; + typedef bit [31:0] uint32; + typedef bit [63:0] uint64; + + // TODO: The above typedefs violate the name rule, which is fixed below. Cleanup the codebase to + // use the typedefs below and remove the ones above. + typedef bit [7:0] uint8_t; + typedef bit [15:0] uint16_t; + typedef bit [31:0] uint32_t; + typedef bit [63:0] uint64_t; + + // typedef parameterized pins_if for ease of implementation for interrupts and alerts + typedef virtual pins_if #(NUM_MAX_INTERRUPTS) intr_vif; + typedef virtual pins_if #(1) devmode_vif; + + // interface direction / mode - Host or Device + typedef enum bit { + Host, + Device + } if_mode_e; + + // compare operator types + typedef enum { + CompareOpEq, + CompareOpCaseEq, + CompareOpNe, + CompareOpCaseNe, + CompareOpGt, + CompareOpGe, + CompareOpLt, + CompareOpLe + } compare_op_e; + + // mem address struct + typedef struct { + uvm_reg_addr_t start_addr; + uvm_reg_addr_t end_addr; + } addr_range_t; + + // Enum representing a bus operation type - read or write. + typedef enum bit { + BusOpWrite = 1'b0, + BusOpRead = 1'b1 + } bus_op_e; + + // Enum representing a type of host requests - read only, write only or random read & write + typedef enum int { + HostReqNone = 0, + HostReqReadOnly = 1, + HostReqWriteOnly = 2, + HostReqReadWrite = 3 + } host_req_type_e; + + // Enum representing clock frequency difference on 2 clocks + typedef enum bit [1:0] { + ClkFreqDiffNone, + ClkFreqDiffSmall, + ClkFreqDiffBig, + ClkFreqDiffAny + } clk_freq_diff_e; + + string msg_id = "dv_utils_pkg"; + + // return the smaller value of 2 inputs + function automatic int min2(int a, int b); + return (a < b) ? a : b; + endfunction + + // return the bigger value of 2 inputs + function automatic int max2(int a, int b); + return (a > b) ? a : b; + endfunction + + // return the biggest value within the given queue of integers. + function automatic int max(const ref int int_q[$]); + `DV_CHECK_GT_FATAL(int_q.size(), 0, "max function cannot accept an empty queue of integers!", + msg_id) + // Assign the first value from the queue in case of negative integers. + max = int_q[0]; + foreach (int_q[i]) max = max2(max, int_q[i]); + return max; + endfunction + + // get absolute value of the input. Usage: absolute(val) or absolute(a - b) + function automatic uint absolute(int val); + return val >= 0 ? val : -val; + endfunction + + // endian swaps a 32-bit data word + function automatic logic [31:0] endian_swap(logic [31:0] data); + return {<<8{data}}; + endfunction + + // endian swaps bytes at a word granularity, while preserving overall word ordering. + // + // e.g. if `arr[] = '{'h0, 'h1, 'h2, 'h3, 'h4, 'h5, 'h6, 'h7}`, this function will produce: + // `'{'h3, 'h2, 'h1, 'h0, 'h7, 'h6, 'h5, 'h4}` + function automatic void endian_swap_byte_arr(ref bit [7:0] arr[]); + arr = {<< byte {arr}}; + arr = {<< 32 {arr}}; + endfunction + +`ifdef UVM + // Simple function to set max errors before quitting sim + function automatic void set_max_quit_count(int n); + uvm_report_server report_server = uvm_report_server::get_server(); + report_server.set_max_quit_count(n); + endfunction + + // return if uvm_fatal occurred + function automatic bit has_uvm_fatal_occurred(); + uvm_report_server report_server = uvm_report_server::get_server(); + return report_server.get_severity_count(UVM_FATAL) > 0; + endfunction + + // task that waits for the specfied timeout + task automatic wait_timeout(input uint timeout_ns, + input string error_msg_id = msg_id, + input string error_msg = "timeout occurred!", + input bit report_fatal = 1); + #(timeout_ns * 1ns); + if (report_fatal) `uvm_fatal(error_msg_id, error_msg) + else `uvm_error(error_msg_id, error_msg) + endtask : wait_timeout + + // get masked data based on provided byte mask; if csr reg handle is provided (optional) then + // masked bytes from csr's mirrored value are returned, else masked bytes are 0's + function automatic bit [bus_params_pkg::BUS_DW-1:0] + get_masked_data(bit [bus_params_pkg::BUS_DW-1:0] data, + bit [bus_params_pkg::BUS_DBW-1:0] mask, + uvm_reg csr = null); + bit [bus_params_pkg::BUS_DW-1:0] csr_data; + csr_data = (csr != null) ? csr.get_mirrored_value() : '0; + get_masked_data = data; + foreach (mask[i]) begin + if (~mask[i]) get_masked_data[i * 8 +: 8] = csr_data[i * 8 +: 8]; + end + endfunction + + // create a sequence by name and return the handle of uvm_sequence + function automatic uvm_sequence create_seq_by_name(string seq_name); + uvm_object obj; + uvm_factory factory; + uvm_sequence seq; + + factory = uvm_factory::get(); + obj = factory.create_object_by_name(seq_name, "", seq_name); + if (obj == null) begin + // print factory overrides to help debug + factory.print(1); + `uvm_fatal(msg_id, $sformatf("could not create %0s seq", seq_name)) + end + if (!$cast(seq, obj)) begin + `uvm_fatal(msg_id, $sformatf("cast failed - %0s is not a uvm_sequence", seq_name)) + end + return seq; + endfunction +`endif + + // Returns the hierarchical path to the interface / module N levels up. + // + // Meant to be invoked inside a module or interface. + // hier: String input of the interface / module, typically $sformatf("%m"). + // n_levels_up: Integer number of levels up the hierarchy to omit. + // Example: if (hier = tb.dut.foo.bar, n_levels_up = 2), then return tb.dut + function automatic string get_parent_hier(string hier, int n_levels_up = 1); + int idx; + int level; + if (n_levels_up <= 0) return hier; + for (idx = hier.len() - 1; idx >= 0; idx--) begin + if (hier[idx] == ".") level++; + if (level == n_levels_up) break; + end + return (hier.substr(0, idx - 1)); + endfunction + + // Periodically check for the existence of a magic file (dv.stop). Exit if it exists. This + // provides a mechanism to gracefully kill a simulation without direct access to the process. + task automatic poll_for_stop(uint interval_ns = 10_000, string filename = "dv.stop"); + fork + while (1) begin + #(interval_ns * 1ns); + if (!$system($sformatf("test -f %0s", filename))) begin + $system($sformatf("rm %0s", filename)); + `dv_fatal($sformatf("Found %0s file. Exiting!", filename), "poll_for_stop") + end + end + join_none + endtask : poll_for_stop + + // sources +`ifdef UVM + `include "dv_report_catcher.sv" + `include "dv_report_server.sv" + `include "dv_vif_wrap.sv" +`endif + +endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv new file mode 100644 index 00000000..61d99479 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv @@ -0,0 +1,96 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Abstract class meant to hold arbitrary virtual interface handles. +// +// Written primarily for an interface which implements functional coverage, this could be used +// for other purposes as well. This abstract class provides utilities & macros to retrieve +// virtual interface handles that are bound to a DUT's sub-modules. These sub-module interfaces must +// self-register using the `DV_VIF_WRAP_SET_VIF()` macro (see details below). The extended class +// then implements the `get_vifs()` method using the `DV_VIF_WRAP_GET_VIF*` macros below to retrieve +// the sub-module interface handles it maintains. +virtual class dv_vif_wrap; + string hier; // Represents the hierarchy of the parent module or interface. + string name; // Name of the class instance. + + function new(string hier, string name = ""); + this.hier = hier; + this.name = name; + endfunction + + // Abstract method implemented by the extended class. It is recommended to invoke the helper + // macros below rather than manually define it. + pure virtual task get_vifs(); + +endclass + +// Helper macros. +// +// These are defined in the file itself since they are tightly coupled to the class definition +// above. These are scoped globally so that extended classes can invoke them. + +// Enable an interface to register itself (set its handle into the config db). +// +// Meant to be invoked from an interface. The macros invocation causes the interface to register +// itself into the uvm_resource_db pool. The derived class of dv_vif_wrap retrieves the handle to +// that interface handle from the uvm_resource db pool. +// +// SV LRM does not yet allow referencing the instance of an interface within itself as one +// would in case of a class using the ~this~ keyword. However, most major simulators actually +// support this in their own custom way. On VCS, a reference to self within the interface can be set +// using `interface::self()` construct. On Xcelium, this is achieved by simply referencing the +// interface name. +// +// _IF: The SV interface +// _VIF: The corresponding virtual interface handle name +// _LEVEL: # of hierarchical levels the module to which the SV interface is bound, starting at the +// top level DUT instance. +`define DV_VIF_WRAP_SET_VIF(_IF, _VIF, _LEVEL = 0) \ + import uvm_pkg::*; \ + function automatic void self_register(); \ + string path; \ + virtual _IF vif; \ + /* Initial block adds another level in the path hierarchy which needs to be split out. */ \ + /* Add one more to go one level up the interface instance. */ \ + /* Example: tb.dut.core.u_foo_if.self_register -> tb.dut.core. */ \ + path = dv_utils_pkg::get_parent_hier(.hier($sformatf("%m")), .n_levels_up(2 + _LEVEL)); \ +`ifdef VCS \ + vif = interface::self(); \ +`elsif XCELIUM \ + vif = _IF; \ +`else \ + vif = _IF; \ +`endif \ + uvm_pkg::uvm_resource_db#(virtual _IF)::set(path, `"_VIF`", vif); \ + endfunction \ + initial self_register(); + +// Enables the retrieval of individual vifs. +// +// The three macros below go together to define the _get_vifs() task in the extended class. +`define DV_VIF_WRAP_GET_VIFS_BEGIN \ + task get_vifs(); \ + fork \ + +// To avoid race condition between the instant when an interface handle is set into the config db +// and the instant when it is retrieved (in the same time step, at t = 0), the macro below invokes +// uvm_config_db#(..)::wait_modified() to ensure that the retrieval is done only after the set. +`define DV_VIF_WRAP_GET_VIF(_IF, _VIF) \ + begin \ + bit vif_found; \ + /* At most 2 retries. */ \ + repeat (2) begin \ + /* Force the evaluation at the end of the time step. */ \ + #0; \ + if (uvm_pkg::uvm_resource_db#(virtual _IF)::read_by_name(hier, `"_VIF`", _VIF)) begin \ + vif_found = 1'b1; \ + break; \ + end \ + end \ + `DV_CHECK_FATAL(vif_found, {`"_VIF`", " not found in the resource db"}, hier) \ + end + +`define DV_VIF_WRAP_GET_VIFS_END \ + join \ + endtask diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core index f11d35c1..1d8a39f7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core @@ -64,3 +64,4 @@ targets: - files_rtl - ff_regfile - target_sim? (files_clk_gate) + - target_sim_sc? (files_clk_gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson index 00ea518e..b122083e 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/openhwgroup/cv32e40p.git - rev: c8d65849ec060c6f7bc62325b46ba0ab7eae8805 + rev: 370cf19b3b60cbdc847ff102551392dd501029a2 } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson index 462a2848..5b2ce889 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/openhwgroup/cv32e40p.git", - rev: "c8d65849ec060c6f7bc62325b46ba0ab7eae8805", + rev: "370cf19b3b60cbdc847ff102551392dd501029a2", }, patch_dir: "patches/openhwgroup_cv32e40p", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore index ef351b19..66eb251a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore @@ -18,3 +18,9 @@ TAGS /build /Bender.lock /Bender.local +golden_reference_design +golden.src +revised.src +cadence_conformal +synopsys_formality +questa_autocheck diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh index 8c4ae99f..a89ed4e4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh @@ -679,22 +679,22 @@ class instr_trace_t; // decode and print instruction case (instr[11:8]) // cv.starti, cv.endi - 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, rd[0], imm_iz_type); + 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, instr[7], imm_iz_type); // cv.counti - 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, rd[0], imm_iz_type); + 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, instr[7], imm_iz_type); // cv.start, cv.end, cv.count 4'b0001, 4'b0011, 4'b0101: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s", mnemonic, rd[0], regAddrToStr(rs1)); + str = $sformatf("%-16s %d, %s", mnemonic, instr[7], regAddrToStr(rs1)); end // cv.setupi 4'b0110: begin - str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, rd[0], imm_iz_type, rs1); + str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, instr[7], imm_iz_type, rs1); end // cv.setup 4'b0111: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, rd[0], regAddrToStr(rs1), imm_iz_type); + str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, instr[7], regAddrToStr(rs1), imm_iz_type); end endcase end @@ -861,7 +861,7 @@ class instr_trace_t; endcase str_sci = ""; end - + // shuffle/pack 6'b110000: begin if (instr[14:12] == 3'b111) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv index ca158f96..13a5beb0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv @@ -73,6 +73,10 @@ module cv32e40p_rvfi input logic is_compressed_id_i, input logic ebrk_insn_dec_i, + input logic ecall_insn_dec_i, + + input logic mret_insn_dec_i, + input logic mret_dec_i, input logic [5:0] csr_cause_i, @@ -126,6 +130,9 @@ module cv32e40p_rvfi input logic [31:0] data_wdata_ex_i, input logic lsu_split_q_ex_i, + input logic mult_ready_i, + input logic alu_ready_i, + //// WB probes //// input logic [31:0] pc_wb_i, input logic wb_ready_i, @@ -202,6 +209,7 @@ module cv32e40p_rvfi input logic csr_we_i, input logic [31:0] csr_wdata_int_i, + input logic csr_fregs_we_i, input logic csr_jvt_we_i, input Status_t csr_mstatus_n_i, input Status_t csr_mstatus_q_i, @@ -617,6 +625,8 @@ module cv32e40p_rvfi logic pc_mux_interrupt; logic pc_mux_nmi; + localparam logic [31:0] MSTATUS_WRITE_MASK = 32'h0000_6088; + `include "pipe_freeze_trace.sv" `include "insn_trace.sv" @@ -633,6 +643,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; logic [2:0] saved_debug_cause; integer next_send; + event e_empty_queue; function void empty_fifo(); integer i, trace_q_size; trace_q_size = wb_bypass_trace_q.size(); @@ -648,6 +659,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; new_rvfi_trace.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; rvfi_trace_q.push_back(new_rvfi_trace); next_send = next_send + 1; + ->e_empty_queue; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); end @@ -658,6 +670,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; /* * Function used to alocate a new insn and send it to the rvfi driver */ + event e_add_to_bypass; function void send_rvfi(insn_trace_t m_wb_insn); insn_trace_t new_rvfi_trace; new_rvfi_trace = new(); @@ -667,6 +680,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; next_send = next_send + 1; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); + ->e_add_to_bypass; end empty_fifo(); endfunction @@ -837,7 +851,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; //CSR rvfi_csr_mstatus_rmask = new_rvfi_trace.m_csr.mstatus_rmask | new_rvfi_trace.m_csr.mstatus_fs_rmask; - rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask; + rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask & MSTATUS_WRITE_MASK; rvfi_csr_mstatus_wmask[31] = new_rvfi_trace.m_csr.mstatus_fs_wmask[31]; rvfi_csr_mstatus_wmask[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wmask[14:13]; @@ -870,7 +884,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end rvfi_csr_mstatus_wdata[30:18] = '0; // MPRV is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[17] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.mprv; + rvfi_csr_mstatus_wdata[17] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.mprv; rvfi_csr_mstatus_wdata[16:15] = '0; if (FPU == 1 && ZFINX == 0) begin rvfi_csr_mstatus_wdata[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wdata; @@ -882,11 +896,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; rvfi_csr_mstatus_wdata[7] = new_rvfi_trace.m_csr.mstatus_wdata.mpie; rvfi_csr_mstatus_wdata[6:5] = '0; // UPIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[4] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.upie; + rvfi_csr_mstatus_wdata[4] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.upie; rvfi_csr_mstatus_wdata[3] = new_rvfi_trace.m_csr.mstatus_wdata.mie; rvfi_csr_mstatus_wdata[2:1] = '0; // UIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[0] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.uie; + rvfi_csr_mstatus_wdata[0] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.uie; `SET_RVFI_CSR_FROM_INSN(misa) `SET_RVFI_CSR_FROM_INSN(mie) @@ -1111,6 +1125,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; * The third updates the rvfi interface */ `define CSR_FROM_PIPE(TRACE_NAME, CSR_NAME) \ + if(!trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we) begin \ + trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ + end\ if (r_pipe_freeze_trace.csr.``CSR_NAME``_we) begin \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we = r_pipe_freeze_trace.csr.``CSR_NAME``_we; \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ @@ -1120,9 +1137,14 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_``TRACE_NAME``.m_csr.``CSR_NAME``_rmask = '1; event e_mstatus_to_id; + event e_fregs_dirty_1, e_fregs_dirty_2, e_fregs_dirty_3; function void mstatus_to_id(); `CSR_FROM_PIPE(id, mstatus) `CSR_FROM_PIPE(id, mstatus_fs) + if(r_pipe_freeze_trace.csr.fregs_we && !r_pipe_freeze_trace.csr.mstatus_fs_we && !(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we)) begin //writes happening in ex that needs to be reported to id + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + ->e_fregs_dirty_2; + end ->e_mstatus_to_id; endfunction //those event are for debug purpose @@ -1133,10 +1155,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; e_dev_commit_rf_to_ex_3, e_dev_commit_rf_to_ex_4, e_dev_commit_rf_to_ex_5; - event e_if_2_id_1, e_if_2_id_2; + event e_if_2_id_1, e_if_2_id_2, e_if_2_id_3, e_if_2_id_4; event e_ex_to_wb_1, e_ex_to_wb_2; event e_id_to_ex_1, e_id_to_ex_2; event e_commit_dpc; + event e_csr_in_ex, e_csr_irq; event e_send_rvfi_trace_apu_resp; event @@ -1160,12 +1183,17 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(apu_resp, fcsr) `CSR_FROM_PIPE(apu_resp, fflags) - // `CSR_FROM_PIPE(apu_resp, mstatus) `CSR_FROM_PIPE(apu_resp, mstatus_fs) - if (r_pipe_freeze_trace.csr.mstatus_we) begin + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_id.m_order > trace_apu_resp.m_order)) begin + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_ex.m_order > trace_apu_resp.m_order)) begin trace_ex.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_wb.m_order > trace_apu_resp.m_order)) begin + trace_wb.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end endfunction function void csr_to_apu_req(); @@ -1243,14 +1271,22 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_is_irq_start; bit s_id_done; function void if_to_id(); + if (trace_id.m_valid) begin + `CSR_FROM_PIPE(id, misa) + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + tinfo_to_id(); + `CSR_FROM_PIPE(id, mip) + send_rvfi(trace_id); + end trace_id.init(trace_if); trace_id.m_trap = ~r_pipe_freeze_trace.minstret; - trace_id.m_is_illegal = r_pipe_freeze_trace.is_illegal; + trace_id.m_is_illegal = trace_id.m_is_illegal | r_pipe_freeze_trace.is_illegal; + `CSR_FROM_PIPE(id, dpc) s_is_pc_set = 1'b0; s_is_irq_start = 1'b0; trace_if.m_valid = 1'b0; s_id_done = 1'b0; - `CSR_FROM_PIPE(id, dpc) endfunction function logic [31:0] be_to_mask(logic [3:0] be); @@ -1280,34 +1316,44 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_core_is_decoding; // For readability, ctrl_fsm is DECODE or DECODE_HWLOOP - trace_if = new(); - trace_id = new(); - trace_ex = new(); - trace_wb = new(); - s_new_valid_insn = 1'b0; - s_ex_valid_adjusted = 1'b0; + bit s_ex_reg_we_adjusted; //ex_reg_we + bit s_rf_we_wb_adjusted; // + + bit s_dont_override_mstatus_fs_id; + + trace_if = new(); + trace_id = new(); + trace_ex = new(); + trace_wb = new(); + s_new_valid_insn = 1'b0; + s_ex_valid_adjusted = 1'b0; + + s_id_done = 1'b0; + s_apu_wb_ok = 1'b0; + s_apu_0_cycle_reps = 1'b0; + + next_send = 1; + cnt_data_req = 0; + cnt_data_resp = 0; + cnt_apu_req = 0; + cnt_apu_resp = 0; + csr_is_irq = '0; + is_dbg_taken = '0; + s_was_flush = 1'b0; - s_id_done = 1'b0; - s_apu_wb_ok = 1'b0; - s_apu_0_cycle_reps = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; - next_send = 1; - cnt_data_req = 0; - cnt_data_resp = 0; - cnt_apu_req = 0; - cnt_apu_resp = 0; - csr_is_irq = '0; - is_dbg_taken = '0; - s_was_flush = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; + s_skip_wb = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; + s_core_is_decoding = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; - s_skip_wb = 1'b0; + s_ex_reg_we_adjusted = 1'b0; + s_rf_we_wb_adjusted = 1'b0; - s_core_is_decoding = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; forever begin wait(e_pipe_monitor_ok.triggered); // event triggered @@ -1325,19 +1371,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end if (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID && r_pipe_freeze_trace.ebrk_insn_dec) begin - if (trace_wb.m_valid) begin - send_rvfi(trace_wb); - trace_wb.m_valid = 1'b0; - ->e_send_rvfi_trace_wb_1; - end - if (trace_ex.m_valid) begin - send_rvfi(trace_ex); - trace_ex.m_valid = 1'b0; - ->e_send_rvfi_trace_ex_1; - end if (trace_id.m_valid) begin - - minstret_to_id(); `CSR_FROM_PIPE(id, misa) `CSR_FROM_PIPE(id, tdata1) `CSR_FROM_PIPE(id, tdata2) @@ -1387,7 +1421,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_new_valid_insn = r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.is_decoding;// && !r_pipe_freeze_trace.apu_rvalid; - s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX));// && !r_pipe_freeze_trace.apu_rvalid;; + s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_WB) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF));// && !r_pipe_freeze_trace.apu_rvalid;; + s_ex_reg_we_adjusted = r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.mult_ready && r_pipe_freeze_trace.alu_ready && r_pipe_freeze_trace.lsu_ready_ex && !s_apu_to_alu_port; + s_rf_we_wb_adjusted = r_pipe_freeze_trace.rf_we_wb && (~r_pipe_freeze_trace.data_misaligned_ex && r_pipe_freeze_trace.wb_ready) && (!s_apu_to_lsu_port || r_pipe_freeze_trace.wb_contention_lsu); s_fflags_we_non_apu = 1'b0; if (r_pipe_freeze_trace.csr.fflags_we) begin @@ -1418,60 +1454,55 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_skip_wb = 1'b1; end end - if (trace_wb.m_valid && !s_skip_wb) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if((trace_wb.m_rd_addr[0] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[0]) && trace_wb.m_mem_req_id_valid[0]) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[0] = 1'b0; - end else if (trace_wb.m_2_rd_insn && (trace_wb.m_rd_addr[1] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[1]) && trace_wb.m_mem_req_id_valid[1]) begin - trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[1] = 1'b0; - end - end - if (!trace_wb.m_data_missaligned) begin - send_rvfi(trace_wb); - ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; - trace_wb.m_valid = 1'b0; + if (trace_wb.m_valid && !s_skip_wb && s_rf_we_wb_adjusted) begin + if (trace_wb.m_2_rd_insn) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + end else if (trace_wb.m_ex_fw) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + trace_wb.m_2_rd_insn = 1'b1; end else begin - if (s_wb_valid_adjusted) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if (!trace_wb.m_ex_fw) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end - if (trace_wb.m_data_missaligned && !trace_wb.m_got_first_data) begin - trace_wb.m_got_first_data = 1'b1; - end else begin - send_rvfi(trace_wb); - ->e_dev_send_wb_2; ->e_send_rvfi_trace_wb_3; - trace_wb.m_valid = 1'b0; - end - end // rf_we_wb + trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; + end + + if (r_pipe_freeze_trace.csr.fregs_we) begin + `CSR_FROM_PIPE(wb, mstatus_fs) + trace_wb.m_csr.mstatus_fs_we = 1'b1; + trace_wb.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_wb.m_csr.mstatus_fs_wdata = FS_DIRTY; end + ->e_fregs_dirty_1; end + + send_rvfi(trace_wb); + ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; + trace_wb.m_valid = 1'b0; + end if (trace_ex.m_valid) begin - - if (!trace_ex.m_csr.got_minstret) begin + if(trace_ex.m_instret_smaple_trigger == 1) begin //time to sample instret minstret_to_ex(); end + trace_ex.m_instret_smaple_trigger = trace_ex.m_instret_smaple_trigger + 1; + `CSR_FROM_PIPE(ex, misa) `CSR_FROM_PIPE(ex, tdata1) `CSR_FROM_PIPE(ex, tdata2) tinfo_to_ex(); - if (r_pipe_freeze_trace.regfile_we_lsu) begin + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_4; - if ((cnt_data_resp == trace_ex.m_mem_req_id[0]) && !(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin + if (!(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; trace_ex.m_mem_req_id_valid[0] = 1'b0; - end else if ((cnt_data_resp == trace_ex.m_mem_req_id[1]) && trace_ex.m_mem_req_id_valid[1]) begin + end else if (trace_ex.m_mem_req_id_valid[1]) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; @@ -1485,7 +1516,8 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_valid = 1'b0; ->e_send_rvfi_trace_ex_2; end else begin - if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port) begin + + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_1; if (trace_ex.m_got_ex_reg) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; @@ -1497,24 +1529,35 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; end - end - if (!s_ex_valid_adjusted & !trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end - if (trace_ex.m_is_load) begin // only move relevant instr in wb stage - ->e_ex_to_wb_1; - trace_wb.move_down_pipe(trace_ex); - end else begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); + if (r_pipe_freeze_trace.csr.fregs_we && !r_pipe_freeze_trace.apu_rvalid) begin //Catching mstatus_fs updates caused by flw + `CSR_FROM_PIPE(ex, mstatus_fs) + trace_ex.m_csr.mstatus_fs_we = 1'b1; + trace_ex.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_ex.m_csr.mstatus_fs_wdata = FS_DIRTY; + end else begin + trace_id.m_csr.mstatus_fs_rdata = trace_ex.m_csr.mstatus_fs_wdata; + s_dont_override_mstatus_fs_id = 1'b1; + end + ->e_fregs_dirty_3; end + send_rvfi(trace_ex); - ->e_send_rvfi_trace_ex_6; + trace_ex.m_valid = 1'b0; + + end else begin + if (trace_ex.m_is_load) begin // only move relevant instr in wb stage + ->e_ex_to_wb_1; + trace_wb.move_down_pipe(trace_ex); + end else begin + send_rvfi(trace_ex); + ->e_send_rvfi_trace_ex_6; + end + trace_ex.m_valid = 1'b0; end - trace_ex.m_valid = 1'b0; end - end else if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port && !s_was_flush) begin + end else if (s_rf_we_wb_adjusted && !s_was_flush) begin ->e_dev_commit_rf_to_ex_2; if (trace_ex.m_got_ex_reg) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; @@ -1529,21 +1572,38 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end end - s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF)) && (!r_pipe_freeze_trace.apu_rvalid || r_pipe_freeze_trace.data_req_ex); + // If mret, we need to keep the instruction in Id during flush_ex because mstatus update happens at that time + s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || ((r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) && !r_pipe_freeze_trace.mret_insn_dec)); //EX_STAGE - if (trace_id.m_valid) begin - mtvec_to_id(); - `CSR_FROM_PIPE(id, mip) - `CSR_FROM_PIPE(id, misa) + if (trace_id.m_valid) begin + if(trace_id.m_instret_smaple_trigger == 1) begin //time to sample instret + minstret_to_id(); + end + trace_id.m_instret_smaple_trigger = trace_id.m_instret_smaple_trigger + 1; - if (!csr_is_irq && !s_is_irq_start) begin - mstatus_to_id(); + if(trace_id.m_sample_csr_write_in_ex && !csr_is_irq && !s_is_irq_start) begin //First cycle after id_ready, csr write is asserted in this cycle + `CSR_FROM_PIPE(id, mstatus) + if(!s_dont_override_mstatus_fs_id) begin + `CSR_FROM_PIPE(id, mstatus_fs) + end `CSR_FROM_PIPE(id, mepc) - if (trace_id.m_csr.mcause_we == '0) begin //for debug purpose - `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, dscratch0) + `CSR_FROM_PIPE(id, dscratch1) + if(r_pipe_freeze_trace.csr.we && (r_pipe_freeze_trace.csr.addr == CSR_DPC)) begin + `CSR_FROM_PIPE(id, dpc) end + ->e_csr_in_ex; + end + + if(r_pipe_freeze_trace.is_decoding) begin + trace_id.m_sample_csr_write_in_ex = 1'b0; end + mtvec_to_id(); + + `CSR_FROM_PIPE(id, mip) + `CSR_FROM_PIPE(id, misa) `CSR_FROM_PIPE(id, mcountinhibit) `CSR_FROM_PIPE(id, mscratch) @@ -1553,10 +1613,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(id, frm) `CSR_FROM_PIPE(id, fcsr) - if (r_pipe_freeze_trace.csr.we) begin - `CSR_FROM_PIPE(id, dpc) - end - if (r_pipe_freeze_trace.csr.dcsr_we) begin dcsr_to_id(); end @@ -1577,6 +1633,15 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_csr.frm_wmask = '0; trace_ex.m_csr.fcsr_wmask = '0; + if(r_pipe_freeze_trace.ctrl_fsm_cs == XRET_JUMP) begin //xret exit pipeline + tinfo_to_id(); + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + send_rvfi(trace_id); + trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; + end + if (r_pipe_freeze_trace.apu_req && r_pipe_freeze_trace.apu_gnt) begin trace_id.m_is_apu = 1'b1; trace_id.m_apu_req_id = cnt_apu_req; @@ -1586,6 +1651,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_apu_req.set_to_apu(); apu_trace_q.push_back(trace_apu_req); trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; if(r_pipe_freeze_trace.apu_rvalid && (cnt_apu_req == cnt_apu_resp)) begin//APU return in the same cycle apu_resp(); @@ -1603,10 +1669,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_rd_addr[0] = r_pipe_freeze_trace.ex_reg_addr; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.ex_reg_wdata; trace_id.m_got_ex_reg = 1'b1; - end else if (!trace_ex.m_valid & r_pipe_freeze_trace.rf_we_wb & !trace_id.m_ex_fw) begin + end else if (!trace_ex.m_valid & s_rf_we_wb_adjusted & !trace_id.m_ex_fw) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end else if (r_pipe_freeze_trace.rf_we_wb) begin + end else if (s_rf_we_wb_adjusted) begin trace_id.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_id.m_2_rd_insn = 1'b1; @@ -1621,19 +1687,16 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end + if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; trace_id.m_mem.wmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end else begin trace_id.m_mem.rmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; end + if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; trace_id.m_mem_req_id[0] = 0; @@ -1644,6 +1707,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; hwloop_to_id(); trace_ex.move_down_pipe(trace_id); // The instruction moves forward from ID to EX trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; ->e_id_to_ex_1; end else if (r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.rf_alu_we_ex) begin @@ -1667,9 +1731,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; if (s_new_valid_insn) begin // There is a new valid instruction if (trace_id.m_valid) begin if (trace_ex.m_valid) begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end if (trace_wb.m_valid) begin send_rvfi(trace_ex); ->e_send_rvfi_trace_ex_4; @@ -1692,15 +1753,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; @@ -1708,7 +1764,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem_req_id_valid[0] = 1'b0; trace_id.m_mem_req_id_valid[1] = 1'b1; end - end else if (r_pipe_freeze_trace.rf_we_wb && !r_pipe_freeze_trace.ex_reg_we) begin + end else if (s_rf_we_wb_adjusted && !r_pipe_freeze_trace.ex_reg_we) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; end @@ -1716,6 +1772,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; hwloop_to_id(); trace_ex.move_down_pipe(trace_id); trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; ->e_id_to_ex_2; end if_to_id(); @@ -1733,12 +1790,27 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end //IF_STAGE - if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready) begin - if(trace_if.m_valid && r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin - if_to_id(); - trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; - ->e_if_2_id_2; + if(trace_if.m_valid) begin + if(r_pipe_freeze_trace.is_illegal && r_pipe_freeze_trace.is_decoding) begin + trace_if.m_is_illegal = 1'b1; end + end + + if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready && r_pipe_freeze_trace.instr_valid_if) begin + if (trace_if.m_valid) begin + if (r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin + if_to_id(); + trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; + ->e_if_2_id_2; + end else if (trace_if.m_is_illegal) begin + if_to_id(); + ->e_if_2_id_3; + end else if (r_pipe_freeze_trace.ecall_insn_dec) begin + if_to_id(); + ->e_if_2_id_4; + end + end + trace_if.m_insn = r_pipe_freeze_trace.instr_if; //Instr comes from if, buffer for one cycle trace_if.m_pc_rdata = r_pipe_freeze_trace.pc_if; @@ -1754,6 +1826,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; mstatus_to_id(); `CSR_FROM_PIPE(id, mepc) `CSR_FROM_PIPE(id, mcause) + ->e_csr_irq; end if (!s_id_done && r_pipe_freeze_trace.is_decoding) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv index 725ed4f0..ca703682 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv @@ -279,8 +279,12 @@ module cv32e40p_tb_wrapper // .instr (cv32e40p_top_i.core_i.id_stage_i.instr ), .is_compressed_id_i(cv32e40p_top_i.core_i.id_stage_i.is_compressed_i), .ebrk_insn_dec_i (cv32e40p_top_i.core_i.id_stage_i.ebrk_insn_dec), - .csr_cause_i (cv32e40p_top_i.core_i.csr_cause), - .debug_csr_save_i (cv32e40p_top_i.core_i.debug_csr_save), + .ecall_insn_dec_i (cv32e40p_top_i.core_i.id_stage_i.ecall_insn_dec), + .mret_insn_dec_i (cv32e40p_top_i.core_i.id_stage_i.mret_insn_dec), + .mret_dec_i (cv32e40p_top_i.core_i.id_stage_i.mret_dec), + + .csr_cause_i (cv32e40p_top_i.core_i.csr_cause), + .debug_csr_save_i(cv32e40p_top_i.core_i.debug_csr_save), // HWLOOP regs .hwlp_start_q_i (hwlp_start_q), @@ -305,9 +309,11 @@ module cv32e40p_tb_wrapper // .rf_addr_alu_i (cv32e40p_top_i.core_i.id_stage_i.regfile_alu_waddr_fw_i), // .rf_wdata_alu_i (cv32e40p_top_i.core_i.id_stage_i.regfile_alu_wdata_fw_i), + .mult_ready_i (cv32e40p_top_i.core_i.ex_stage_i.mult_ready), + .alu_ready_i (cv32e40p_top_i.core_i.ex_stage_i.alu_ready), //// WB probes //// - .wb_valid_i(cv32e40p_top_i.core_i.wb_valid), - + .wb_valid_i (cv32e40p_top_i.core_i.wb_valid), + .wb_ready_i (cv32e40p_top_i.core_i.lsu_ready_wb), //// LSU probes //// .data_we_ex_i (cv32e40p_top_i.core_i.data_we_ex), .data_atop_ex_i (cv32e40p_top_i.core_i.data_atop_ex), @@ -360,6 +366,8 @@ module cv32e40p_tb_wrapper .csr_we_i (cv32e40p_top_i.core_i.cs_registers_i.csr_we_int), .csr_wdata_int_i(cv32e40p_top_i.core_i.cs_registers_i.csr_wdata_int), + .csr_fregs_we_i(cv32e40p_top_i.core_i.cs_registers_i.fregs_we_i), + .csr_mstatus_n_i (cv32e40p_top_i.core_i.cs_registers_i.mstatus_n), .csr_mstatus_q_i (cv32e40p_top_i.core_i.cs_registers_i.mstatus_q), .csr_mstatus_fs_n_i(cv32e40p_top_i.core_i.cs_registers_i.mstatus_fs_n), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv index c099ff4f..d026c4aa 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv @@ -196,8 +196,8 @@ package cv32e40p_tracer_pkg; parameter INSTR_CVEND0 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI0 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT0 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI0 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP0 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI0 = {17'b?, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP0 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVSTARTI1 = {12'b?, 5'b00000, 3'b100, 4'b0000, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVSTART1 = {12'b000000000000, 5'b?, 3'b100, 4'b0001, 1'b1, OPCODE_CUSTOM_1}; @@ -205,8 +205,8 @@ package cv32e40p_tracer_pkg; parameter INSTR_CVEND1 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI1 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT1 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI1 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP1 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI1 = {17'b?, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP1 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_FF1 = {7'b0100001, 5'b0, 5'b?, 3'b011, 5'b?, OPCODE_CUSTOM_1}; @@ -449,8 +449,8 @@ package cv32e40p_tracer_pkg; parameter INSTR_CVSHUFFLE2H = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVSHUFFLE2B = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACK = {5'b11101, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACKH = {5'b11101, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACK = {5'b11110, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACKH = {5'b11110, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKHIB = {5'b11111, 1'b0, 1'b1, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKLOB = {5'b11111, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv index 3db2a7ee..71cbaaff 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv @@ -65,6 +65,9 @@ bit m_move_down_pipe; int m_instret_cnt; + int m_instret_smaple_trigger; //We need to sample minstret from csr 2 cycle after id is doen + + bit m_sample_csr_write_in_ex; struct { logic [31:0] addr ; @@ -145,32 +148,34 @@ function new(); - this.m_order = 0; - this.m_skip_order = 1'b0; - this.m_valid = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_intr = '0; - this.m_dbg_taken = 1'b0; - this.m_dbg_cause = '0; - this.m_is_ebreak = '0; - this.m_is_illegal = '0; - this.m_is_irq = '0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; - this.m_instret_cnt = 0; + this.m_order = 0; + this.m_skip_order = 1'b0; + this.m_valid = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_intr = '0; + this.m_dbg_taken = 1'b0; + this.m_dbg_cause = '0; + this.m_is_ebreak = '0; + this.m_is_illegal = '0; + this.m_is_irq = '0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; + this.m_instret_cnt = 0; + this.m_instret_smaple_trigger = 0; + this.m_sample_csr_write_in_ex = 1'b1; endfunction function void get_mnemonic(); @@ -875,37 +880,39 @@ if(this.m_skip_order) begin this.m_order = this.m_order + 64'h1; end - this.m_skip_order = 1'b0; - this.m_pc_rdata = r_pipe_freeze_trace.pc_id; - this.m_is_illegal = 1'b0; - this.m_is_irq = 1'b0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_got_regs_write = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_instret_cnt = 0; - this.m_rd_addr[0] = '0; - this.m_rd_addr[1] = '0; - this.m_2_rd_insn = 1'b0; - this.m_rs1_addr = '0; - this.m_rs2_addr = '0; - this.m_rs3_addr = '0; - this.m_ex_fw = '0; - this.m_csr.got_minstret = '0; - this.m_dbg_taken = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; + this.m_skip_order = 1'b0; + this.m_pc_rdata = r_pipe_freeze_trace.pc_id; + this.m_is_illegal = 1'b0; + this.m_is_irq = 1'b0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_got_regs_write = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_instret_cnt = 0; + this.m_instret_smaple_trigger = 0; + this.m_sample_csr_write_in_ex = 1'b1; + this.m_rd_addr[0] = '0; + this.m_rd_addr[1] = '0; + this.m_2_rd_insn = 1'b0; + this.m_rs1_addr = '0; + this.m_rs2_addr = '0; + this.m_rs3_addr = '0; + this.m_ex_fw = '0; + this.m_csr.got_minstret = '0; + this.m_dbg_taken = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; this.m_csr.mcause_we = '0; if (is_compressed_id_i) begin this.m_insn[31:16] = '0; @@ -944,47 +951,49 @@ endfunction function void copy_full(insn_trace_t m_source); - this.m_valid = m_source.m_valid; - this.m_stage = m_source.m_stage; - this.m_order = m_source.m_order; - this.m_pc_rdata = m_source.m_pc_rdata; - this.m_insn = m_source.m_insn; - this.m_mnemonic = m_source.m_mnemonic; - this.m_is_memory = m_source.m_is_memory; - this.m_is_load = m_source.m_is_load; - this.m_is_apu = m_source.m_is_apu; - this.m_is_apu_ok = m_source.m_is_apu_ok; - this.m_apu_req_id = m_source.m_apu_req_id; - this.m_mem_req_id = m_source.m_mem_req_id; - this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; - this.m_data_missaligned = m_source.m_data_missaligned; - this.m_got_first_data = m_source.m_got_first_data; - this.m_got_ex_reg = m_source.m_got_ex_reg; - this.m_dbg_taken = m_source.m_dbg_taken; - this.m_dbg_cause = m_source.m_dbg_cause; - this.m_is_ebreak = m_source.m_is_ebreak; - this.m_is_illegal = m_source.m_is_illegal; - this.m_is_irq = m_source.m_is_irq; - this.m_instret_cnt = m_source.m_instret_cnt; - this.m_rs1_addr = m_source.m_rs1_addr; - this.m_rs2_addr = m_source.m_rs2_addr; - this.m_rs3_addr = m_source.m_rs3_addr; - this.m_rs1_rdata = m_source.m_rs1_rdata; - this.m_rs2_rdata = m_source.m_rs2_rdata; - this.m_rs3_rdata = m_source.m_rs3_rdata; - - this.m_ex_fw = m_source.m_ex_fw; - this.m_rd_addr = m_source.m_rd_addr; - this.m_2_rd_insn = m_source.m_2_rd_insn; - this.m_rd_wdata = m_source.m_rd_wdata; - - this.m_intr = m_source.m_intr; - this.m_trap = m_source.m_trap; - this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; - this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; - this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; - - this.m_mem = m_source.m_mem; + this.m_valid = m_source.m_valid; + this.m_stage = m_source.m_stage; + this.m_order = m_source.m_order; + this.m_pc_rdata = m_source.m_pc_rdata; + this.m_insn = m_source.m_insn; + this.m_mnemonic = m_source.m_mnemonic; + this.m_is_memory = m_source.m_is_memory; + this.m_is_load = m_source.m_is_load; + this.m_is_apu = m_source.m_is_apu; + this.m_is_apu_ok = m_source.m_is_apu_ok; + this.m_apu_req_id = m_source.m_apu_req_id; + this.m_mem_req_id = m_source.m_mem_req_id; + this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; + this.m_data_missaligned = m_source.m_data_missaligned; + this.m_got_first_data = m_source.m_got_first_data; + this.m_got_ex_reg = m_source.m_got_ex_reg; + this.m_dbg_taken = m_source.m_dbg_taken; + this.m_dbg_cause = m_source.m_dbg_cause; + this.m_is_ebreak = m_source.m_is_ebreak; + this.m_is_illegal = m_source.m_is_illegal; + this.m_is_irq = m_source.m_is_irq; + this.m_instret_cnt = m_source.m_instret_cnt; + this.m_instret_smaple_trigger = m_source.m_instret_smaple_trigger; + this.m_sample_csr_write_in_ex = m_source.m_sample_csr_write_in_ex; + this.m_rs1_addr = m_source.m_rs1_addr; + this.m_rs2_addr = m_source.m_rs2_addr; + this.m_rs3_addr = m_source.m_rs3_addr; + this.m_rs1_rdata = m_source.m_rs1_rdata; + this.m_rs2_rdata = m_source.m_rs2_rdata; + this.m_rs3_rdata = m_source.m_rs3_rdata; + + this.m_ex_fw = m_source.m_ex_fw; + this.m_rd_addr = m_source.m_rd_addr; + this.m_2_rd_insn = m_source.m_2_rd_insn; + this.m_rd_wdata = m_source.m_rd_wdata; + + this.m_intr = m_source.m_intr; + this.m_trap = m_source.m_trap; + this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; + this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; + this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; + + this.m_mem = m_source.m_mem; //CRS `ASSIGN_CSR(mstatus) `ASSIGN_CSR(mstatus_fs) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv index 58051ab8..88d65d0b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv @@ -64,6 +64,9 @@ typedef struct { logic is_compressed_id; logic ebrk_insn_dec; + logic ecall_insn_dec; + logic mret_insn_dec; + logic mret_dec; logic [5:0] csr_cause; @@ -112,6 +115,9 @@ typedef struct { logic [31:0] data_wdata_ex; logic lsu_split_q_ex; + logic mult_ready; + logic alu_ready; + //// WB probes //// logic [31:0] pc_wb; logic wb_ready; @@ -198,6 +204,8 @@ typedef struct { logic mcause_we; logic dcsr_we; + logic fregs_we; + logic jvt_we; Status_t mstatus_n; Status_t mstatus_q; @@ -348,16 +356,24 @@ function compute_csr_we(); r_pipe_freeze_trace.csr.mstatus_we = 1'b1; r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; end - CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; - CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; - CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; - CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; - CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; - CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; - CSR_FFLAGS: r_pipe_freeze_trace.csr.fflags_we = 1'b1; - CSR_FRM: r_pipe_freeze_trace.csr.frm_we = 1'b1; - CSR_FCSR: r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; + CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; + CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; + CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; + CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; + CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; + CSR_FFLAGS: begin + r_pipe_freeze_trace.csr.fflags_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_FRM: r_pipe_freeze_trace.csr.frm_we = 1'b1; + CSR_FCSR: begin + r_pipe_freeze_trace.csr.fcsr_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_DSCRATCH0: r_pipe_freeze_trace.csr.dscratch0_we = 1'b1; + CSR_DSCRATCH1: r_pipe_freeze_trace.csr.dscratch1_we = 1'b1; endcase end // CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = r_pipe_freeze_trace.csr.mcause_n != r_pipe_freeze_trace.csr.mcause_q; //for debug purpose @@ -416,6 +432,9 @@ task monitor_pipeline(); r_pipe_freeze_trace.jump_target_id = jump_target_id_i; r_pipe_freeze_trace.is_compressed_id = is_compressed_id_i; r_pipe_freeze_trace.ebrk_insn_dec = ebrk_insn_dec_i; + r_pipe_freeze_trace.ecall_insn_dec = ecall_insn_dec_i; + r_pipe_freeze_trace.mret_insn_dec = mret_insn_dec_i; + r_pipe_freeze_trace.mret_dec = mret_dec_i; r_pipe_freeze_trace.csr_cause = csr_cause_i; r_pipe_freeze_trace.debug_csr_save = debug_csr_save_i; r_pipe_freeze_trace.minstret = minstret_i; @@ -462,6 +481,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.data_wdata_ex = data_wdata_ex_i; r_pipe_freeze_trace.lsu_split_q_ex = lsu_split_q_ex_i; + r_pipe_freeze_trace.mult_ready = mult_ready_i; + r_pipe_freeze_trace.alu_ready = alu_ready_i; //// WB probes //// r_pipe_freeze_trace.pc_wb = pc_wb_i; r_pipe_freeze_trace.wb_ready = wb_ready_i; @@ -526,6 +547,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.csr.we = csr_we_i; r_pipe_freeze_trace.csr.wdata_int = csr_wdata_int_i; + r_pipe_freeze_trace.csr.fregs_we = csr_fregs_we_i; + r_pipe_freeze_trace.csr.jvt_we = csr_jvt_we_i; r_pipe_freeze_trace.csr.mstatus_n = csr_mstatus_n_i; r_pipe_freeze_trace.csr.mstatus_q = csr_mstatus_q_i; @@ -650,10 +673,6 @@ task monitor_pipeline(); if (r_pipe_freeze_trace.csr.fcsr_we) begin r_pipe_freeze_trace.csr.fflags_we = 1'b1; r_pipe_freeze_trace.csr.frm_we = 1'b1; - end else begin - if (r_pipe_freeze_trace.csr.fflags_we || r_pipe_freeze_trace.csr.frm_we) begin - r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - end end if (csr_fcsr_fflags_we_i) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv index 54980269..a41e345d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv @@ -491,6 +491,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; @@ -712,6 +713,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; @@ -764,7 +766,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; ebrk_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; + halt_id_o = 1'b0; if (debug_mode_q) // we got back to the park loop in the debug rom @@ -776,15 +778,15 @@ module cv32e40p_controller import cv32e40p_pkg::*; else begin // otherwise just a normal ebreak exception - ctrl_fsm_ns = FLUSH_EX; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end end ecall_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = FLUSH_EX; + halt_id_o = 1'b0; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end csr_status_i: begin @@ -1559,7 +1561,7 @@ endgenerate // HWLoop 0 and 1 having target address constraints property p_hwlp_same_target_address; - @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1) |-> ( hwlp_end_addr_i[1] - 4 >= hwlp_end_addr_i[0] - 4 + 8 ); + @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1 && pc_id_i >= hwlp_start_addr_i[0] && pc_id_i <= hwlp_end_addr_i[0] - 4) |-> ( hwlp_end_addr_i[1] - 4 >= hwlp_end_addr_i[0] - 4 + 8 ); endproperty a_hwlp_same_target_address : assert property(p_hwlp_same_target_address) else $warning("%t, HWLoops target address do not respect constraints", $time); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv index e6f9f709..d72fae9e 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv @@ -158,6 +158,7 @@ module cv32e40p_core logic [31:0] jump_target_id, jump_target_ex; logic branch_in_ex; logic branch_decision; + logic [ 1:0] ctrl_transfer_insn_in_dec; logic ctrl_busy; logic if_busy; @@ -201,6 +202,7 @@ module cv32e40p_core logic [ C_RM-1:0] frm_csr; logic [ C_FFLAG-1:0] fflags_csr; logic fflags_we; + logic fregs_we; // APU logic apu_en_ex; @@ -228,6 +230,7 @@ module cv32e40p_core logic regfile_we_ex; logic [ 5:0] regfile_waddr_fw_wb_o; // From WB to ID logic regfile_we_wb; + logic regfile_we_wb_power; logic [ 31:0] regfile_wdata; logic [ 5:0] regfile_alu_waddr_ex; @@ -235,6 +238,7 @@ module cv32e40p_core logic [ 5:0] regfile_alu_waddr_fw; logic regfile_alu_we_fw; + logic regfile_alu_we_fw_power; logic [ 31:0] regfile_alu_wdata_fw; // CSR control @@ -540,9 +544,10 @@ module cv32e40p_core .instr_req_o (instr_req_int), // Jumps and branches - .branch_in_ex_o (branch_in_ex), - .branch_decision_i(branch_decision), - .jump_target_o (jump_target_id), + .branch_in_ex_o (branch_in_ex), + .branch_decision_i (branch_decision), + .jump_target_o (jump_target_id), + .ctrl_transfer_insn_in_dec_o(ctrl_transfer_insn_in_dec), // IF and ID control signals .clear_instr_valid_o(clear_instr_valid), @@ -699,13 +704,15 @@ module cv32e40p_core .wake_from_sleep_o(wake_from_sleep), // Forward Signals - .regfile_waddr_wb_i(regfile_waddr_fw_wb_o), // Write address ex-wb pipeline - .regfile_we_wb_i (regfile_we_wb), // write enable for the register file - .regfile_wdata_wb_i(regfile_wdata), // write data to commit in the register file + .regfile_waddr_wb_i (regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i (regfile_we_wb), // write enable for the register file + .regfile_we_wb_power_i(regfile_we_wb_power), + .regfile_wdata_wb_i (regfile_wdata), // write data to commit in the register file - .regfile_alu_waddr_fw_i(regfile_alu_waddr_fw), - .regfile_alu_we_fw_i (regfile_alu_we_fw), - .regfile_alu_wdata_fw_i(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_i (regfile_alu_waddr_fw), + .regfile_alu_we_fw_i (regfile_alu_we_fw), + .regfile_alu_we_fw_power_i(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_i (regfile_alu_wdata_fw), // from ALU .mult_multicycle_i(mult_multicycle), @@ -737,6 +744,7 @@ module cv32e40p_core // // ///////////////////////////////////////////////////// cv32e40p_ex_stage #( + .COREV_PULP (COREV_PULP), .FPU (FPU), .APU_NARGS_CPU (APU_NARGS_CPU), .APU_WOP_CPU (APU_WOP_CPU), @@ -785,6 +793,8 @@ module cv32e40p_core .data_misaligned_ex_i(data_misaligned_ex), // from ID/EX pipeline .data_misaligned_i (data_misaligned), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + // FPU .fpu_fflags_we_o(fflags_we), .fpu_fflags_o (fflags_csr), @@ -838,18 +848,20 @@ module cv32e40p_core .regfile_we_i (regfile_we_ex), // Output of ex stage pipeline - .regfile_waddr_wb_o(regfile_waddr_fw_wb_o), - .regfile_we_wb_o (regfile_we_wb), - .regfile_wdata_wb_o(regfile_wdata), + .regfile_waddr_wb_o (regfile_waddr_fw_wb_o), + .regfile_we_wb_o (regfile_we_wb), + .regfile_we_wb_power_o(regfile_we_wb_power), + .regfile_wdata_wb_o (regfile_wdata), // To IF: Jump and branch target and decision .jump_target_o (jump_target_ex), .branch_decision_o(branch_decision), // To ID stage: Forwarding signals - .regfile_alu_waddr_fw_o(regfile_alu_waddr_fw), - .regfile_alu_we_fw_o (regfile_alu_we_fw), - .regfile_alu_wdata_fw_o(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_o (regfile_alu_waddr_fw), + .regfile_alu_we_fw_o (regfile_alu_we_fw), + .regfile_alu_we_fw_power_o(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_o (regfile_alu_wdata_fw), // stall control .is_decoding_i (is_decoding), @@ -969,6 +981,7 @@ module cv32e40p_core .frm_o (frm_csr), .fflags_i (fflags_csr), .fflags_we_i(fflags_we), + .fregs_we_i (fregs_we), // Interrupt related control signals .mie_bypass_o (mie_bypass), @@ -1037,13 +1050,16 @@ module cv32e40p_core ); // CSR access - assign csr_addr = csr_addr_int; - assign csr_wdata = alu_operand_a_ex; - assign csr_op = csr_op_ex; + assign csr_addr = csr_addr_int; + assign csr_wdata = alu_operand_a_ex; + assign csr_op = csr_op_ex; assign csr_addr_int = csr_num_e'(csr_access_ex ? alu_operand_b_ex[11:0] : '0); - + // Floating-Point registers write + assign fregs_we = (FPU == 1 & ZFINX == 0) ? ((regfile_alu_we_fw && regfile_alu_waddr_fw[5]) || + (regfile_we_wb && regfile_waddr_fw_wb_o[5])) + : 1'b0; /////////////////////////// // ____ __ __ ____ // diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv index 25c777e2..920305c8 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv @@ -68,6 +68,7 @@ module cv32e40p_cs_registers output logic [ 2:0] frm_o, input logic [C_FFLAG-1:0] fflags_i, input logic fflags_we_i, + input logic fregs_we_i, // Interrupts output logic [31:0] mie_bypass_o, @@ -212,6 +213,7 @@ module cv32e40p_cs_registers logic [31:0] exception_pc; Status_t mstatus_q, mstatus_n; + logic mstatus_we_int; FS_t mstatus_fs_q, mstatus_fs_n; logic [5:0] mcause_q, mcause_n; logic [5:0] ucause_q, ucause_n; @@ -507,7 +509,7 @@ module cv32e40p_cs_registers // mimpid, Machine Implementation ID CSR_MIMPID: begin - csr_rdata_int = (FPU || COREV_PULP || COREV_CLUSTER) ? 32'h1 : 'b0; + csr_rdata_int = (FPU == 1 || COREV_PULP == 1 || COREV_CLUSTER == 1) ? 32'h1 : 'b0; end // unimplemented, read 0 CSRs @@ -897,6 +899,7 @@ module cv32e40p_cs_registers dscratch0_n = dscratch0_q; dscratch1_n = dscratch1_q; + mstatus_we_int = 1'b0; mstatus_n = mstatus_q; mcause_n = mcause_q; ucause_n = '0; // Not used if PULP_SECURE == 0 @@ -957,7 +960,8 @@ module cv32e40p_cs_registers mprv: csr_wdata_int[MSTATUS_MPRV_BIT] }; if (FPU == 1 && ZFINX == 0) begin - mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); + mstatus_we_int = 1'b1; + mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); end end // mie: machine interrupt enable @@ -1027,7 +1031,7 @@ module cv32e40p_cs_registers if (ZFINX == 0) begin // FPU Register File/Flags implicit update or modified by CSR instructions - if (fflags_we_i || fcsr_update) begin + if ((fregs_we_i && !(mstatus_we_int && mstatus_fs_n != FS_DIRTY)) || fflags_we_i || fcsr_update) begin mstatus_fs_n = FS_DIRTY; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv index c51ef7f8..488a83dc 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv @@ -33,6 +33,7 @@ module cv32e40p_ex_stage import cv32e40p_pkg::*; import cv32e40p_apu_core_pkg::*; #( + parameter COREV_PULP = 0, parameter FPU = 0, parameter APU_NARGS_CPU = 3, parameter APU_WOP_CPU = 6, @@ -81,6 +82,8 @@ module cv32e40p_ex_stage input logic data_misaligned_ex_i, input logic data_misaligned_i, + input logic [1:0] ctrl_transfer_insn_in_dec_i, + // FPU signals output logic fpu_fflags_we_o, output logic [APU_NUSFLAGS_CPU-1:0] fpu_fflags_o, @@ -138,11 +141,13 @@ module cv32e40p_ex_stage // Output of EX stage pipeline output logic [ 5:0] regfile_waddr_wb_o, output logic regfile_we_wb_o, + output logic regfile_we_wb_power_o, output logic [31:0] regfile_wdata_wb_o, // Forwarding ports : to ID stage output logic [ 5:0] regfile_alu_waddr_fw_o, output logic regfile_alu_we_fw_o, + output logic regfile_alu_we_fw_power_o, output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL // To IF: Jump and branch target and decision @@ -190,22 +195,27 @@ module cv32e40p_ex_stage // ALU write port mux always_comb begin - regfile_alu_wdata_fw_o = '0; - regfile_alu_waddr_fw_o = '0; - regfile_alu_we_fw_o = '0; - wb_contention = 1'b0; + regfile_alu_wdata_fw_o = '0; + regfile_alu_waddr_fw_o = '0; + regfile_alu_we_fw_o = 1'b0; + regfile_alu_we_fw_power_o = 1'b0; + wb_contention = 1'b0; - // APU single cycle operations, and multicycle operations (>2cycles) are written back on ALU port + // APU single cycle operations, and multicycle operations (> 2cycles) are written back on ALU port if (apu_valid & (apu_singlecycle | apu_multicycle)) begin - regfile_alu_we_fw_o = 1'b1; - regfile_alu_waddr_fw_o = apu_waddr; - regfile_alu_wdata_fw_o = apu_result; + regfile_alu_we_fw_o = 1'b1; + regfile_alu_we_fw_power_o = 1'b1; + regfile_alu_waddr_fw_o = apu_waddr; + regfile_alu_wdata_fw_o = apu_result; if (regfile_alu_we_i & ~apu_en_i) begin wb_contention = 1'b1; end end else begin - regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; + regfile_alu_we_fw_power_o = (COREV_PULP == 0) ? regfile_alu_we_i & ~apu_en_i : + regfile_alu_we_i & ~apu_en_i & + mult_ready & alu_ready & lsu_ready_ex_i; regfile_alu_waddr_fw_o = regfile_alu_waddr_i; if (alu_en_i) regfile_alu_wdata_fw_o = alu_result; if (mult_en_i) regfile_alu_wdata_fw_o = mult_result; @@ -215,21 +225,24 @@ module cv32e40p_ex_stage // LSU write port mux always_comb begin - regfile_we_wb_o = 1'b0; - regfile_waddr_wb_o = regfile_waddr_lsu; - regfile_wdata_wb_o = lsu_rdata_i; - wb_contention_lsu = 1'b0; + regfile_we_wb_o = 1'b0; + regfile_we_wb_power_o = 1'b0; + regfile_waddr_wb_o = regfile_waddr_lsu; + regfile_wdata_wb_o = lsu_rdata_i; + wb_contention_lsu = 1'b0; if (regfile_we_lsu) begin - regfile_we_wb_o = 1'b1; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = (COREV_PULP == 0) ? 1'b1 : ~data_misaligned_ex_i & wb_ready_i; if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin wb_contention_lsu = 1'b1; end // APU two-cycle operations are written back on LSU port end else if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin - regfile_we_wb_o = 1'b1; - regfile_waddr_wb_o = apu_waddr; - regfile_wdata_wb_o = apu_result; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = 1'b1; + regfile_waddr_wb_o = apu_waddr; + regfile_wdata_wb_o = apu_result; end end @@ -371,11 +384,20 @@ module cv32e40p_ex_stage apu_result_q <= 'b0; apu_flags_q <= 'b0; end else begin - if (apu_rvalid_i && apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || (data_req_i && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + if (apu_rvalid_i && apu_multicycle && + (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b1; apu_result_q <= apu_result_i; apu_flags_q <= apu_flags_i; - end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b0; end end @@ -383,7 +405,12 @@ module cv32e40p_ex_stage assign apu_req_o = apu_req; assign apu_gnt = apu_gnt_i; - assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); + assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) + ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); assign apu_operands_o = apu_operands_i; assign apu_op_o = apu_op_i; assign apu_result = apu_rvalid_q ? apu_result_q : apu_result_i; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv index 042fa0f2..62ec46c2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv @@ -111,7 +111,7 @@ module cv32e40p_fp_wrapper .int_fmt_i (fpnew_pkg::int_format_e'(fpu_int_fmt)), .vectorial_op_i(fpu_vec_op), .tag_i (1'b0), - .simd_mask_i ('b0), + .simd_mask_i (1'b0), .in_valid_i (apu_req_i), .in_ready_o (apu_gnt_o), .flush_i (1'b0), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv index 7811eabf..93bb1380 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv @@ -70,6 +70,7 @@ module cv32e40p_id_stage output logic branch_in_ex_o, input logic branch_decision_i, output logic [31:0] jump_target_o, + output logic [ 1:0] ctrl_transfer_insn_in_dec_o, // IF and ID stage signals output logic clear_instr_valid_o, @@ -225,10 +226,12 @@ module cv32e40p_id_stage // Forward Signals input logic [5:0] regfile_waddr_wb_i, input logic regfile_we_wb_i, + input logic regfile_we_wb_power_i, input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata input logic [ 5:0] regfile_alu_waddr_fw_i, input logic regfile_alu_we_fw_i, + input logic regfile_alu_we_fw_power_i, input logic [31:0] regfile_alu_wdata_fw_i, // from ALU @@ -809,6 +812,9 @@ module cv32e40p_id_stage if (ctrl_transfer_target_mux_sel == JT_JALR) begin apu_read_regs[0] = regfile_addr_ra_id; apu_read_regs_valid[0] = 1'b1; + end else begin + apu_read_regs[0] = regfile_addr_ra_id; + apu_read_regs_valid[0] = 1'b0; end end // OP_A_CURRPC: OP_A_REGA_OR_FWD: begin @@ -948,12 +954,12 @@ module cv32e40p_id_stage // Write port a .waddr_a_i(regfile_waddr_wb_i), .wdata_a_i(regfile_wdata_wb_i), - .we_a_i (regfile_we_wb_i), + .we_a_i (regfile_we_wb_power_i), // Write port b .waddr_b_i(regfile_alu_waddr_fw_i), .wdata_b_i(regfile_alu_wdata_fw_i), - .we_b_i (regfile_alu_we_fw_i) + .we_b_i (regfile_alu_we_fw_power_i) ); @@ -1087,7 +1093,7 @@ module cv32e40p_id_stage .debug_wfi_no_sleep_i(debug_wfi_no_sleep), // jump/branches - .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec_o), .ctrl_transfer_insn_in_id_o (ctrl_transfer_insn_in_id), .ctrl_transfer_target_mux_sel_o(ctrl_transfer_target_mux_sel), @@ -1187,7 +1193,7 @@ module cv32e40p_id_stage // jump/branch control .branch_taken_ex_i (branch_taken_ex), .ctrl_transfer_insn_in_id_i (ctrl_transfer_insn_in_id), - .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec_o), // Interrupt signals .irq_wu_ctrl_i (irq_wu_ctrl), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core index 70a248de..7a12b181 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core @@ -67,3 +67,4 @@ targets: filesets: - files_rtl - target_sim? (files_clk_gate) + - target_sim_sc? (files_clk_gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson index d1cc1ce7..a9251111 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/davideschiavone/cve2.git - rev: 5039e60cdea6a76282576ca7e93a35ee9a3ff2e9 + url: https://github.com/openhwgroup/cve2.git + rev: f5b21e71c9b511477b04ef81d1292858c51ac20c } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson index 8c860069..d398c1eb 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,22 +6,43 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/davideschiavone/cve2.git", - rev: "5039e60cdea6a76282576ca7e93a35ee9a3ff2e9", + url: "https://github.com/openhwgroup/cve2.git", + rev: "f5b21e71c9b511477b04ef81d1292858c51ac20c", }, + patch_dir: "patches/openhwgroup_cv32e20", + exclude_from_upstream: [ "ci", "dv", "examples", "formal", ".dir-locals.el", - "cv32e40p_manifest.flist", "doc", "shared", "syn", "util", - "vendor", + "scripts", + "vendor/eembc_coremark", + "vendor/eembc_coremark.lock.hjson", + "vendor/google_riscv-dv", + "vendor/google_riscv-dv.lock.hjson", + "vendor/google_riscv-dv.vendor.hjson", + "vendor/lowrisc_ip.lock.hjson", + "vendor/lowrisc_ip.vendor.hjson", + "vendor/patches", + "vendor/lowrisc_ip/ip" + "vendor/lowrisc_ip/lint" + "vendor/lowrisc_ip/util" + "vendor/lowrisc_ip/dv/tools", + "vendor/lowrisc_ip/dv/verilator", + "vendor/lowrisc_ip/dv/sv/common_ifs", + "vendor/lowrisc_ip/dv/sv/csr_utils", + "vendor/lowrisc_ip/dv/sv/dv_base_reg", + "vendor/lowrisc_ip/dv/sv/dv_lib", + "vendor/lowrisc_ip/dv/sv/mem_bkdr_util", + "vendor/lowrisc_ip/dv/sv/mem_model", + "vendor/lowrisc_ip/dv/sv/str_utils", ".github", "azure-pipelines.yml", "check_tool_requirements.core", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch deleted file mode 100644 index 28ab47b1..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/rtl/cv32e40px_cs_registers.sv b/rtl/cv32e40px_cs_registers.sv -index 1f1d56b..cdc6433 100644 ---- a/rtl/cv32e40px_cs_registers.sv -+++ b/rtl/cv32e40px_cs_registers.sv -@@ -1450,7 +1450,7 @@ module cv32e40px_cs_registers - // minstret is located at index 2 - // Programable HPM counters start at index 3 - if ((cnt_gidx == 1) || (cnt_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented -- assign mhpmcounter_q[cnt_gidx] = 'b0; -+ always_ff @(posedge clk) mhpmcounter_q[cnt_gidx] <= 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) begin -@@ -1478,10 +1478,10 @@ module cv32e40px_cs_registers - for (evt_gidx = 0; evt_gidx < 32; evt_gidx++) begin : gen_mhpmevent - // programable HPM events start at index3 - if ((evt_gidx < 3) || (evt_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented -- assign mhpmevent_q[evt_gidx] = 'b0; -+ always_ff @(posedge clk) mhpmevent_q[evt_gidx] <= 'b0; - end else begin : gen_implemented - if (NUM_HPM_EVENTS < 32) begin : gen_tie_off -- assign mhpmevent_q[evt_gidx][31:NUM_HPM_EVENTS] = 'b0; -+ always_ff @(posedge clk) mhpmevent_q[evt_gidx][31:NUM_HPM_EVENTS] <= 'b0; - end - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mhpmevent_q[evt_gidx][NUM_HPM_EVENTS-1:0] <= 'b0; -@@ -1499,7 +1499,7 @@ module cv32e40px_cs_registers - (en_gidx == 1) || - (en_gidx >= (NUM_MHPMCOUNTERS+3) ) ) - begin : gen_non_implemented -- assign mcounteren_q[en_gidx] = 'b0; -+ always_ff @(posedge clk) mcounteren_q[en_gidx] <= 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mcounteren_q[en_gidx] <= 'b0; // default disable -@@ -1514,7 +1514,7 @@ module cv32e40px_cs_registers - generate - for (inh_gidx = 0; inh_gidx < 32; inh_gidx++) begin : gen_mcountinhibit - if ((inh_gidx == 1) || (inh_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented -- assign mcountinhibit_q[inh_gidx] = 'b0; -+ always_ff @(posedge clk) mcountinhibit_q[inh_gidx] <= 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mcountinhibit_q[inh_gidx] <= 'b1; // default disable diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch index 94b7d2b8..54c13229 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch @@ -1,5 +1,5 @@ diff --git a/hw/dv/dpi/uartdpi/uartdpi.h b/hw/dv/dpi/uartdpi/uartdpi.h -index 29d50a5a2..2149fb115 100644 +index 29d50a5a28..2149fb1155 100644 --- a/hw/dv/dpi/uartdpi/uartdpi.h +++ b/hw/dv/dpi/uartdpi/uartdpi.h @@ -5,7 +5,9 @@ @@ -21,21 +21,23 @@ index 29d50a5a2..2149fb115 100644 +#endif #endif // OPENTITAN_HW_DV_DPI_UARTDPI_UARTDPI_H_ diff --git a/hw/dv/dpi/uartdpi/uartdpi.sv b/hw/dv/dpi/uartdpi/uartdpi.sv -index 97fae4767..07c75cf8e 100644 +index 97fae47674..2be4df54ff 100644 --- a/hw/dv/dpi/uartdpi/uartdpi.sv +++ b/hw/dv/dpi/uartdpi/uartdpi.sv -@@ -82,11 +82,14 @@ module uartdpi #( +@@ -82,11 +82,16 @@ module uartdpi #( end end - +`ifndef VCS +`ifndef MODELSIM ++`ifndef XCELIUM initial begin // Prevent falling edges of rx_i before reset causing spurious characters seen_reset = 0; end +`endif ++`endif +`endif // RX diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch new file mode 100644 index 00000000..4ac84c15 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch @@ -0,0 +1,12 @@ +diff --git a/rtl/cve2_top.sv b/rtl/cve2_top.sv +index 34af60b7..00c38a4a 100644 +--- a/rtl/cve2_top.sv ++++ b/rtl/cve2_top.sv +@@ -265,7 +265,6 @@ module cve2_top import cve2_pkg::*; #( + + `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) + `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) +- `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) + + `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) + diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch new file mode 100644 index 00000000..9727dec1 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch @@ -0,0 +1,12 @@ +diff --git a/cve2_top.core b/cve2_top.core +index cb4e23b4..0d9d2c5c 100644 +--- a/cve2_top.core ++++ b/cve2_top.core +@@ -75,6 +75,7 @@ targets: + - tool_veriblelint ? (files_lint_verible) + - files_rtl + - target_sim ? (files_clk_gate) ++ - target_sim_sc ? (files_clk_gate) + toplevel: cve2_top + parameters: + - tool_vivado ? (FPGA_XILINX=true) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch new file mode 100644 index 00000000..3e5ccb84 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch @@ -0,0 +1,13 @@ +diff --git a/src/clk_mux_glitch_free.sv b/src/clk_mux_glitch_free.sv +index e0eb5cd..5193742 100644 +--- a/src/clk_mux_glitch_free.sv ++++ b/src/clk_mux_glitch_free.sv +@@ -191,7 +191,7 @@ endmodule + + // Helper Module to generate an N-input clock OR-gate from a tree of tc_clk_or2 cells. + module clk_or_tree #( +- parameter int unsigned NUM_INPUTS ++ parameter int unsigned NUM_INPUTS = 1 + ) ( + input logic [NUM_INPUTS-1:0] clks_i, + output logic clk_o diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch deleted file mode 100644 index 5b525705..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v -index 22b337b..e0eef9f 100644 ---- a/picosoc/spiflash.v -+++ b/picosoc/spiflash.v -@@ -102,8 +102,14 @@ module spiflash ( - reg [7:0] memory [0:16*1024*1024-1]; - - reg [1023:0] firmware_file; -+ reg result; -+ integer i; -+ - initial begin -- if (!$value$plusargs("firmware=%s", firmware_file)) -+ for (i=0;i<=16*1024*1024;i=i+1) -+ memory[i] = '0; -+ result = $value$plusargs("firmware=%s", firmware_file); -+ if (!result) - firmware_file = "firmware.hex"; - $readmemh(firmware_file, memory); - end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch new file mode 100644 index 00000000..3583151d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch @@ -0,0 +1,113 @@ +diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v +index 22b337b..55342b5 100644 +--- a/picosoc/spiflash.v ++++ b/picosoc/spiflash.v +@@ -26,7 +26,7 @@ + // updates output signals 1ns after the SPI clock edge. + // + // Supported commands: +-// AB, B9, FF, 03, BB, EB, ED ++// AB, B9, FF, 03, BB, EB, ED, 06, 02, 32 + // + // Well written SPI flash data sheets: + // Cypress S25FL064L http://www.cypress.com/file/316661/download +@@ -61,6 +61,8 @@ module spiflash ( + reg spi_io_vld; + + reg powered_up = 0; ++ reg write_enable = 0; ++ reg write_enable_reset = 0; + + localparam [3:0] mode_spi = 1; + localparam [3:0] mode_dspi_rd = 2; +@@ -102,8 +104,14 @@ module spiflash ( + reg [7:0] memory [0:16*1024*1024-1]; + + reg [1023:0] firmware_file; ++ reg result; ++ integer i; ++ + initial begin +- if (!$value$plusargs("firmware=%s", firmware_file)) ++ for (i=0;i<=16*1024*1024;i=i+1) ++ memory[i] = 8'h00; ++ result = $value$plusargs("firmware=%s", firmware_file); ++ if (!result) + firmware_file = "firmware.hex"; + $readmemh(firmware_file, memory); + end +@@ -123,6 +131,9 @@ module spiflash ( + + if (spi_cmd == 8'h ff) + xip_cmd = 0; ++ ++ if (spi_cmd == 8'h 06) ++ write_enable = 1; + end + + if (powered_up && spi_cmd == 'h 03) begin +@@ -141,6 +152,25 @@ module spiflash ( + end + end + ++ if (powered_up && write_enable && spi_cmd == 'h 02) begin ++ if (bytecount == 1) ++ write_enable_reset = 1; ++ ++ if (bytecount == 2) ++ spi_addr[23:16] = buffer; ++ ++ if (bytecount == 3) ++ spi_addr[15:8] = buffer; ++ ++ if (bytecount == 4) ++ spi_addr[7:0] = buffer; ++ ++ if (bytecount >= 5 && bytecount <= 260) begin ++ memory[spi_addr] = buffer; ++ spi_addr = spi_addr + 1; ++ end ++ end ++ + if (powered_up && spi_cmd == 'h bb) begin + if (bytecount == 1) + mode = mode_dspi_rd; +@@ -191,6 +221,27 @@ module spiflash ( + end + end + ++ if (powered_up && write_enable && spi_cmd == 'h 32) begin ++ if (bytecount == 1) ++ write_enable_reset = 1; ++ ++ if (bytecount == 2) ++ spi_addr[23:16] = buffer; ++ ++ if (bytecount == 3) ++ spi_addr[15:8] = buffer; ++ ++ if (bytecount == 4) begin ++ spi_addr[7:0] = buffer; ++ mode = mode_qspi_rd; ++ end ++ ++ if (bytecount >= 5 && bytecount <= 260) begin ++ memory[spi_addr] = buffer; ++ spi_addr = spi_addr + 1; ++ end ++ end ++ + if (powered_up && spi_cmd == 'h ed) begin + if (bytecount == 1) + next_mode = mode_qspi_ddr_rd; +@@ -268,6 +319,10 @@ module spiflash ( + $display(""); + $fflush; + end ++ if (write_enable_reset) begin ++ write_enable = 0; ++ write_enable_reset = 0; ++ end + buffer = 0; + bitcount = 0; + bytecount = 0; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0001-async.-lowactive-reset.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spimemio.patch similarity index 100% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0001-async.-lowactive-reset.patch rename to hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spimemio.patch diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv index e0eb5cdc..51937424 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv @@ -191,7 +191,7 @@ endmodule // Helper Module to generate an N-input clock OR-gate from a tree of tc_clk_or2 cells. module clk_or_tree #( - parameter int unsigned NUM_INPUTS + parameter int unsigned NUM_INPUTS = 1 ) ( input logic [NUM_INPUTS-1:0] clks_i, output logic clk_o diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson index bc1ec555..de40549d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/pulp-platform/fpnew.git - rev: d6e581628f3517a1fb1257507d3214e599f7859d + rev: 79e453139072df42c9ec8f697132ba485d74e23d } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson index 7ae0d55c..1fe09cca 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/pulp-platform/fpnew.git", - rev: "d6e581628f3517a1fb1257507d3214e599f7859d", + rev: "79e453139072df42c9ec8f697132ba485d74e23d", }, exclude_from_upstream: [ diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core index 630f318a..2d79c611 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core @@ -39,8 +39,10 @@ targets: - rtl - "gpio-test? (testbench)" - target_sim? (clock-gate) + - target_sim_sc? (clock-gate) - target_asic_synthesis? (clock-gate) - target_asic_yosys_synthesis? (clock-gate) - target_nexys-a7-100t? (no-clock-gate) - target_pynq-z2? (no-clock-gate) - target_pynq-z2-arm-emulation? (no-clock-gate) + - target_zcu104? (no-clock-gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson index 3f13125e..f74356a1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/pulp-platform/riscv-dbg.git - rev: 69be5ddc03ea1688c0eab47d6ed9d0e8725beda1 + rev: 358f90110220adf7a083f8b65d157e836d706236 } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson index 2ec8e7e9..1c13cb43 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/pulp-platform/riscv-dbg.git", - rev: "69be5ddc03ea1688c0eab47d6ed9d0e8725beda1", + rev: "358f90110220adf7a083f8b65d157e836d706236", }, exclude_from_upstream: [ diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md index 35db8983..99dab605 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md @@ -4,7 +4,40 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## Unreleased + +## [0.8.1] - 2023-10-01 +### Changed +- debug_rom: Add rst + +## [0.8.0] - 2023-04-05 +### Fixed +- dm_csrs: Fix W1C behavior of `sberror` (#155) [@andreaskurth](https://github.com/andreaskurth) +- gen_rom.py: Port to python3 (#152) [@andreaskurth](https://github.com/andreaskurth) + +### Added +- `xprop_off` to Xprop-incompatible processes (#151) [@andreaskurth](https://github.com/andreaskurth) + +## [0.7.0] - 2022-11-02 +### Fixed +- 64-bit unaligned accesses (#145) [@creinwar](https://github.com/creinwar) +- Various minor testbench fixes (#146) + +### Changed +- Halted, Resume and Exception addresses are now aligned to 8 bytes + +## [0.6.0] - 2022-10-11 +### Fixed +- Testbench build (#141, #142) +- remote_bitbang tb build for newer GCC versions (#133) [@epsilon537](https://github.com/noytzach) +- 32-bit access to abstract data (#27) [@Silabs-ArjanB](https://github.com/Silabs-ArjanB) +- `dm_mem`: Clear state of hart upon ndmreset (#140) [@andreaskurth](https://github.com/andreaskurth) +- `dmi_jtag_tap`: Bring all state to initial value in test-logic-reset (#139) [@andreaskurth](https://github.com/andreaskurth) +- Fix DMI response when command or SBA are busy (#138) [@andreaskurth](https://github.com/andreaskurth) + +### Changed +- Add expontential backoff to read_dmi in tb (#134) [@colluca](https://github.com/colluca) + ## [0.5.1] - 2022-04-12 ### Fixed - Fixed dmi_bscane_tap top-level signals diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile index b23370aa..931e2532 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile @@ -5,7 +5,7 @@ debug_rom = debug_rom.sv debug_rom_one_scratch.sv GCC?=riscv64-unknown-elf-gcc OBJCOPY?=riscv64-unknown-elf-objcopy OBJDUMP?=riscv64-unknown-elf-objdump -PYTHON?=python +PYTHON?=python3 all: $(debug_rom) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S index 2989c7e8..7126ae46 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S @@ -6,9 +6,9 @@ // # define SND_SCRATCH 1 // These are implementation-specific addresses in the Debug Module #define HALTED 0x100 -#define GOING 0x104 -#define RESUMING 0x108 -#define EXCEPTION 0x10C +#define GOING 0x108 +#define RESUMING 0x110 +#define EXCEPTION 0x118 // Region of memory where each hart has 1 // byte to read. @@ -26,10 +26,13 @@ entry: jal zero, _entry + nop resume: jal zero, _resume + nop exception: jal zero, _exception + nop diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h index b4f2d35a..9e1d73d2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h @@ -1,11 +1,14 @@ // Auto-generated code -const int reset_vec_size = 38; +const int reset_vec_size = 40; uint32_t reset_vec[reset_vec_size] = { - 0x00c0006f, - 0x07c0006f, - 0x04c0006f, + 0x0180006f, + 0x00000013, + 0x0840006f, + 0x00000013, + 0x0500006f, + 0x00000013, 0x0ff0000f, 0x7b241073, 0x7b351073, @@ -22,23 +25,22 @@ uint32_t reset_vec[reset_vec_size] = { 0x00a40433, 0x40044403, 0x00247413, - 0xfa041ce3, + 0xfa0418e3, 0xfd5ff06f, 0x00000517, 0x00c55513, 0x00c51513, - 0x10052623, + 0x10052c23, 0x7b302573, 0x7b202473, 0x00100073, - 0x10052223, + 0x10052423, 0x7b302573, 0x7b202473, - 0xa85ff06f, + 0xa79ff06f, 0xf1402473, - 0x10852423, + 0x10852823, 0x7b302573, 0x7b202473, - 0x7b200073, - 0x00000000 + 0x7b200073 }; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv index 0299db6b..ac10eeea 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv @@ -16,41 +16,47 @@ // Auto-generated code module debug_rom ( input logic clk_i, + input logic rst_ni, input logic req_i, input logic [63:0] addr_i, output logic [63:0] rdata_o ); - localparam int unsigned RomSize = 19; + localparam int unsigned RomSize = 20; logic [RomSize-1:0][63:0] mem; assign mem = { - 64'h00000000_7b200073, + 64'h7b200073_7b202473, + 64'h7b302573_10852823, + 64'hf1402473_a79ff06f, 64'h7b202473_7b302573, - 64'h10852423_f1402473, - 64'ha85ff06f_7b202473, - 64'h7b302573_10052223, - 64'h00100073_7b202473, - 64'h7b302573_10052623, - 64'h00c51513_00c55513, - 64'h00000517_fd5ff06f, - 64'hfa041ce3_00247413, - 64'h40044403_00a40433, - 64'hf1402473_02041c63, - 64'h00147413_40044403, - 64'h00a40433_10852023, - 64'hf1402473_00c51513, + 64'h10052423_00100073, + 64'h7b202473_7b302573, + 64'h10052c23_00c51513, 64'h00c55513_00000517, - 64'h7b351073_7b241073, - 64'h0ff0000f_04c0006f, - 64'h07c0006f_00c0006f + 64'hfd5ff06f_fa0418e3, + 64'h00247413_40044403, + 64'h00a40433_f1402473, + 64'h02041c63_00147413, + 64'h40044403_00a40433, + 64'h10852023_f1402473, + 64'h00c51513_00c55513, + 64'h00000517_7b351073, + 64'h7b241073_0ff0000f, + 64'h00000013_0500006f, + 64'h00000013_0840006f, + 64'h00000013_0180006f }; - logic [$clog2(RomSize)-1:0] addr_q; + logic [$clog2(RomSize)-1:0] addr_d, addr_q; + + assign addr_d = req_i ? addr_i[$clog2(RomSize)-1+3:3] : addr_q; - always_ff @(posedge clk_i) begin - if (req_i) begin - addr_q <= addr_i[$clog2(RomSize)-1+3:3]; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + addr_q <= '0; + end else begin + addr_q <= addr_d; end end @@ -59,7 +65,7 @@ module debug_rom ( always_comb begin : p_outmux rdata_o = '0; if (addr_q < $clog2(RomSize)'(RomSize)) begin - rdata_o = mem[addr_q]; + rdata_o = mem[addr_q]; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h index 625d66a0..d4539714 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h @@ -1,11 +1,14 @@ // Auto-generated code -const int reset_vec_size = 26; +const int reset_vec_size = 28; uint32_t reset_vec[reset_vec_size] = { - 0x00c0006f, - 0x0500006f, - 0x0340006f, + 0x0180006f, + 0x00000013, + 0x0580006f, + 0x00000013, + 0x0380006f, + 0x00000013, 0x0ff0000f, 0x7b241073, 0xf1402473, @@ -16,17 +19,16 @@ uint32_t reset_vec[reset_vec_size] = { 0xf1402473, 0x40044403, 0x00247413, - 0xfc0418e3, + 0xfc0414e3, 0xfddff06f, - 0x10002623, + 0x10002c23, 0x7b202473, 0x00100073, - 0x10002223, + 0x10002423, 0x7b202473, - 0xab1ff06f, + 0xaa5ff06f, 0xf1402473, - 0x10802423, + 0x10802823, 0x7b202473, - 0x7b200073, - 0x00000000 + 0x7b200073 }; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv index af7e67c7..3cd2d9e2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv @@ -16,35 +16,41 @@ // Auto-generated code module debug_rom_one_scratch ( input logic clk_i, + input logic rst_ni, input logic req_i, input logic [63:0] addr_i, output logic [63:0] rdata_o ); - localparam int unsigned RomSize = 13; + localparam int unsigned RomSize = 14; logic [RomSize-1:0][63:0] mem; assign mem = { - 64'h00000000_7b200073, - 64'h7b202473_10802423, - 64'hf1402473_ab1ff06f, - 64'h7b202473_10002223, - 64'h00100073_7b202473, - 64'h10002623_fddff06f, - 64'hfc0418e3_00247413, - 64'h40044403_f1402473, - 64'h02041263_00147413, - 64'h40044403_10802023, - 64'hf1402473_7b241073, - 64'h0ff0000f_0340006f, - 64'h0500006f_00c0006f + 64'h7b200073_7b202473, + 64'h10802823_f1402473, + 64'haa5ff06f_7b202473, + 64'h10002423_00100073, + 64'h7b202473_10002c23, + 64'hfddff06f_fc0414e3, + 64'h00247413_40044403, + 64'hf1402473_02041263, + 64'h00147413_40044403, + 64'h10802023_f1402473, + 64'h7b241073_0ff0000f, + 64'h00000013_0380006f, + 64'h00000013_0580006f, + 64'h00000013_0180006f }; - logic [$clog2(RomSize)-1:0] addr_q; + logic [$clog2(RomSize)-1:0] addr_d, addr_q; - always_ff @(posedge clk_i) begin - if (req_i) begin - addr_q <= addr_i[$clog2(RomSize)-1+3:3]; + assign addr_d = req_i ? addr_i[$clog2(RomSize)-1+3:3] : addr_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + addr_q <= '0; + end else begin + addr_q <= addr_d; end end @@ -53,7 +59,7 @@ module debug_rom_one_scratch ( always_comb begin : p_outmux rdata_o = '0; if (addr_q < $clog2(RomSize)'(RomSize)) begin - rdata_o = mem[addr_q]; + rdata_o = mem[addr_q]; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py index b8cb60bc..a34efc5d 100755 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py @@ -43,6 +43,7 @@ module = """\ module $filename ( input logic clk_i, + input logic rst_ni, input logic req_i, input logic [63:0] addr_i, output logic [63:0] rdata_o @@ -55,11 +56,15 @@ $content }; - logic [$$clog2(RomSize)-1:0] addr_q; + logic [$$clog2(RomSize)-1:0] addr_d, addr_q; - always_ff @(posedge clk_i) begin - if (req_i) begin - addr_q <= addr_i[$$clog2(RomSize)-1+3:3]; + assign addr_d = req_i ? addr_i[$$clog2(RomSize)-1+3:3] : addr_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + addr_q <= '0; + end else begin + addr_q <= addr_d; end end @@ -68,7 +73,7 @@ always_comb begin : p_outmux rdata_o = '0; if (addr_q < $$clog2(RomSize)'(RomSize)) begin - rdata_o = mem[addr_q]; + rdata_o = mem[addr_q]; end end @@ -88,9 +93,8 @@ def read_bin(): with open(filename + ".img", 'rb') as f: - rom = binascii.hexlify(f.read()) - rom = map(''.join, zip(rom[::2], rom[1::2])) - + rom = bytes.hex(f.read()) + rom = list(map(''.join, zip(rom[::2], rom[1::2]))) # align to 64 bit align = (int((len(rom) + 7) / 8 )) * 8; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md index 1beca7df..5fbfbe18 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md @@ -439,9 +439,9 @@ Address | Description --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ 0x0 to 0x0ff | _unused_ 0x100 | Halted. Write to this address to acknowledge that the core is halted. -0x104 | Going. Write to this address to acknowledge that the core is executing. -0x108 | Resuming. Write to this address to acknowledge that the core is resuming non-debug operation. -0x10c | Exception. An exception was triggered while the core was in debug mode. +0x108 | Going. Write to this address to acknowledge that the core is executing. +0x110 | Resuming. Write to this address to acknowledge that the core is resuming non-debug operation. +0x118 | Exception. An exception was triggered while the core was in debug mode. 0x300 | WhereTo 0x338 to 0x35f | AbstractCmd 0x360 to 0x37f | Program Buffer (8 words) @@ -449,8 +449,8 @@ Address | Description 0x400 to 0x7ff | Flags 0x800 to 0x1000 | Debug ROM 0x800 | HaltAddress. Entry point into the Debug Module. The core must jump to this address when it was requested to halt. -0x804 | ResumeAddress. Entry point into the Debug Module. Jumping to this address instructs the debug module to bring the core out of debug mode and back into normal operation mode. -0x808 | ExceptionAddress. Entry point into the Debug Module. The core must jump to this address when it receives an exception while being in debug mode. +0x808 | ResumeAddress. Entry point into the Debug Module. Jumping to this address instructs the debug module to bring the core out of debug mode and back into normal operation mode. +0x810 | ExceptionAddress. Entry point into the Debug Module. The core must jump to this address when it receives an exception while being in debug mode. (Note: The debug memory addressing scheme is adopted from the Rocket Chip Generator.) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv index 350c6c5f..59d1c90a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv @@ -90,7 +90,6 @@ module dm_csrs #( logic resp_queue_empty; logic resp_queue_push; logic resp_queue_pop; - logic [31:0] resp_queue_data; localparam dm::dm_csr_e DataEnd = dm::dm_csr_e'(dm::Data0 + {4'h0, dm::DataCount} - 8'h1); localparam dm::dm_csr_e ProgBufEnd = dm::dm_csr_e'(dm::ProgBuf0 + {4'h0, dm::ProgBufSize} - 8'h1); @@ -179,8 +178,8 @@ module dm_csrs #( logic [HartSelLen-1:0] selected_hart; - // a successful response returns zero - assign dmi_resp_o.resp = dm::DTM_SUCCESS; + dm::dmi_resp_t resp_queue_inp; + assign dmi_resp_valid_o = ~resp_queue_empty; assign dmi_req_ready_o = ~resp_queue_full; assign resp_queue_push = dmi_req_valid_i & dmi_req_ready_o; @@ -223,7 +222,7 @@ module dm_csrs #( // types instead. assign autoexecdata_idx = 4'({dm_csr_addr} - {dm::Data0}); - always_comb begin : csr_read_write + always_comb (*xprop_off *) begin : csr_read_write // -------------------- // Static Values (R/O) // -------------------- @@ -279,7 +278,8 @@ module dm_csrs #( sbaddr_d = 64'(sbaddress_i); sbdata_d = sbdata_q; - resp_queue_data = 32'h0; + resp_queue_inp.data = 32'h0; + resp_queue_inp.resp = dm::DTM_SUCCESS; cmd_valid_d = 1'b0; sbaddress_write_valid_o = 1'b0; sbdata_read_valid_o = 1'b0; @@ -294,62 +294,70 @@ module dm_csrs #( if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_READ) begin unique case (dm_csr_addr) inside [(dm::Data0):DataEnd]: begin - resp_queue_data = data_q[$clog2(dm::DataCount)'(autoexecdata_idx)]; + resp_queue_inp.data = data_q[$clog2(dm::DataCount)'(autoexecdata_idx)]; if (!cmdbusy_i) begin // check whether we need to re-execute the command (just give a cmd_valid) cmd_valid_d = abstractauto_q.autoexecdata[autoexecdata_idx]; // An abstract command was executing while one of the data registers was read - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end - dm::DMControl: resp_queue_data = dmcontrol_q; - dm::DMStatus: resp_queue_data = dmstatus; - dm::Hartinfo: resp_queue_data = hartinfo_aligned[selected_hart]; - dm::AbstractCS: resp_queue_data = abstractcs; - dm::AbstractAuto: resp_queue_data = abstractauto_q; + dm::DMControl: resp_queue_inp.data = dmcontrol_q; + dm::DMStatus: resp_queue_inp.data = dmstatus; + dm::Hartinfo: resp_queue_inp.data = hartinfo_aligned[selected_hart]; + dm::AbstractCS: resp_queue_inp.data = abstractcs; + dm::AbstractAuto: resp_queue_inp.data = abstractauto_q; // command is read-only - dm::Command: resp_queue_data = '0; + dm::Command: resp_queue_inp.data = '0; [(dm::ProgBuf0):ProgBufEnd]: begin - resp_queue_data = progbuf_q[dmi_req_i.addr[$clog2(dm::ProgBufSize)-1:0]]; + resp_queue_inp.data = progbuf_q[dmi_req_i.addr[$clog2(dm::ProgBufSize)-1:0]]; if (!cmdbusy_i) begin // check whether we need to re-execute the command (just give a cmd_valid) // range of autoexecprogbuf is 31:16 cmd_valid_d = abstractauto_q.autoexecprogbuf[{1'b1, dmi_req_i.addr[3:0]}]; // An abstract command was executing while one of the progbuf registers was read - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end - dm::HaltSum0: resp_queue_data = haltsum0; - dm::HaltSum1: resp_queue_data = haltsum1; - dm::HaltSum2: resp_queue_data = haltsum2; - dm::HaltSum3: resp_queue_data = haltsum3; + dm::HaltSum0: resp_queue_inp.data = haltsum0; + dm::HaltSum1: resp_queue_inp.data = haltsum1; + dm::HaltSum2: resp_queue_inp.data = haltsum2; + dm::HaltSum3: resp_queue_inp.data = haltsum3; dm::SBCS: begin - resp_queue_data = sbcs_q; + resp_queue_inp.data = sbcs_q; end dm::SBAddress0: begin - resp_queue_data = sbaddr_q[31:0]; + resp_queue_inp.data = sbaddr_q[31:0]; end dm::SBAddress1: begin - resp_queue_data = sbaddr_q[63:32]; + resp_queue_inp.data = sbaddr_q[63:32]; end dm::SBData0: begin // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbdata_read_valid_o = (sbcs_q.sberror == '0); - resp_queue_data = sbdata_q[31:0]; + resp_queue_inp.data = sbdata_q[31:0]; end end dm::SBData1: begin // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin - resp_queue_data = sbdata_q[63:32]; + resp_queue_inp.data = sbdata_q[63:32]; end end default:; @@ -367,8 +375,11 @@ module dm_csrs #( // check whether we need to re-execute the command (just give a cmd_valid) cmd_valid_d = abstractauto_q.autoexecdata[autoexecdata_idx]; //An abstract command was executing while one of the data registers was written - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end end @@ -391,8 +402,11 @@ module dm_csrs #( // reads during abstract command execution are not allowed if (!cmdbusy_i) begin cmderr_d = dm::cmderr_e'(~a_abstractcs.cmderr & cmderr_q); - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end dm::Command: begin @@ -402,8 +416,11 @@ module dm_csrs #( command_d = dm::command_t'(dmi_req_i.data); // if there was an attempted to write during a busy execution // and the cmderror field is zero set the busy error - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end dm::AbstractAuto: begin @@ -412,8 +429,11 @@ module dm_csrs #( abstractauto_d = 32'h0; abstractauto_d.autoexecdata = 12'(dmi_req_i.data[dm::DataCount-1:0]); abstractauto_d.autoexecprogbuf = 16'(dmi_req_i.data[dm::ProgBufSize-1+16:16]); - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end [(dm::ProgBuf0):ProgBufEnd]: begin @@ -426,26 +446,31 @@ module dm_csrs #( // range of autoexecprogbuf is 31:16 cmd_valid_d = abstractauto_q.autoexecprogbuf[{1'b1, dmi_req_i.addr[3:0]}]; //An abstract command was executing while one of the progbuf registers was written - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end dm::SBCS: begin // access while the SBA was busy if (sbbusy_i) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbcs = dm::sbcs_t'(dmi_req_i.data); sbcs_d = sbcs; // R/W1C sbcs_d.sbbusyerror = sbcs_q.sbbusyerror & (~sbcs.sbbusyerror); - sbcs_d.sberror = sbcs_q.sberror & {3{~(sbcs.sberror == 3'd1)}}; + sbcs_d.sberror = (|sbcs.sberror) ? 3'b0 : sbcs_q.sberror; end end dm::SBAddress0: begin // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbaddr_d[31:0] = dmi_req_i.data; sbaddress_write_valid_o = (sbcs_q.sberror == '0); @@ -455,6 +480,7 @@ module dm_csrs #( // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbaddr_d[63:32] = dmi_req_i.data; end @@ -463,6 +489,7 @@ module dm_csrs #( // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbdata_d[31:0] = dmi_req_i.data; sbdata_write_valid_o = (sbcs_q.sberror == '0); @@ -472,6 +499,7 @@ module dm_csrs #( // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbdata_d[63:32] = dmi_req_i.data; end @@ -557,8 +585,8 @@ module dm_csrs #( // response FIFO fifo_v2 #( - .dtype ( logic [31:0] ), - .DEPTH ( 2 ) + .dtype ( logic [$bits(dmi_resp_o)-1:0] ), + .DEPTH ( 2 ) ) i_fifo ( .clk_i, .rst_ni, @@ -569,9 +597,9 @@ module dm_csrs #( .empty_o ( resp_queue_empty ), .alm_full_o ( ), .alm_empty_o ( ), - .data_i ( resp_queue_data ), + .data_i ( resp_queue_inp ), .push_i ( resp_queue_push ), - .data_o ( dmi_resp_o.data ), + .data_o ( dmi_resp_o ), .pop_i ( resp_queue_pop ) ); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv index 178259f6..9ff3c86a 100755 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv @@ -26,6 +26,7 @@ module dm_mem #( input logic rst_ni, // debug module reset output logic [NrHarts-1:0] debug_req_o, + input logic ndmreset_i, input logic [19:0] hartsel_i, // from Ctrl and Status register input logic [NrHarts-1:0] haltreq_i, @@ -77,9 +78,9 @@ module dm_mem #( localparam logic [DbgAddressBits-1:0] FlagsEndAddr = 'h7FF; localparam logic [DbgAddressBits-1:0] HaltedAddr = 'h100; - localparam logic [DbgAddressBits-1:0] GoingAddr = 'h104; - localparam logic [DbgAddressBits-1:0] ResumingAddr = 'h108; - localparam logic [DbgAddressBits-1:0] ExceptionAddr = 'h10C; + localparam logic [DbgAddressBits-1:0] GoingAddr = 'h108; + localparam logic [DbgAddressBits-1:0] ResumingAddr = 'h110; + localparam logic [DbgAddressBits-1:0] ExceptionAddr = 'h118; logic [dm::ProgBufSize/2-1:0][63:0] progbuf; logic [7:0][63:0] abstract_cmd; @@ -201,6 +202,13 @@ module dm_mem #( cmderror_valid_o = 1'b1; cmderror_o = dm::CmdErrorException; end + + if (ndmreset_i) begin + // Clear state of hart and its control signals when it is being reset. + state_d = Idle; + go = 1'b0; + resume = 1'b0; + end end // word mux for 32bit and 64bit buses @@ -214,14 +222,13 @@ module dm_mem #( end // read/write logic - logic [63:0] data_bits; + logic [dm::DataCount-1:0][31:0] data_bits; logic [7:0][7:0] rdata; - always_comb begin : p_rw_logic + always_comb (* xprop_off *) begin : p_rw_logic halted_d_aligned = NrHartsAligned'(halted_q); resuming_d_aligned = NrHartsAligned'(resuming_q); rdata_d = rdata_q; - // convert the data in bits representation data_bits = data_i; rdata = '0; @@ -258,9 +265,19 @@ module dm_mem #( // core can write data registers [DataBaseAddr:DataEndAddr]: begin data_valid_o = 1'b1; - for (int i = 0; i < $bits(be_i); i++) begin - if (be_i[i]) begin - data_bits[i*8+:8] = wdata_i[i*8+:8]; + for (int dc = 0; dc < dm::DataCount; dc++) begin + if ((addr_i[DbgAddressBits-1:2] - DataBaseAddr[DbgAddressBits-1:2]) == dc) begin + for (int i = 0; i < $bits(be_i); i++) begin + if (be_i[i]) begin + if (i>3) begin // for upper 32bit data write (only used for BusWidth == 64) + if ((dc+1) < dm::DataCount) begin // ensure we write to an implemented data register + data_bits[dc+1][(i-4)*8+:8] = wdata_i[i*8+:8]; + end + end else begin // for lower 32bit data write + data_bits[dc][i*8+:8] = wdata_i[i*8+:8]; + end + end + end end end end @@ -293,10 +310,8 @@ module dm_mem #( [DataBaseAddr:DataEndAddr]: begin rdata_d = { - data_i[$clog2(dm::ProgBufSize)'(addr_i[DbgAddressBits-1:3] - - DataBaseAddr[DbgAddressBits-1:3] + 1'b1)], - data_i[$clog2(dm::ProgBufSize)'(addr_i[DbgAddressBits-1:3] - - DataBaseAddr[DbgAddressBits-1:3])] + data_i[$clog2(dm::DataCount)'(((addr_i[DbgAddressBits-1:3] - DataBaseAddr[DbgAddressBits-1:3]) << 1) + 1'b1)], + data_i[$clog2(dm::DataCount)'(((addr_i[DbgAddressBits-1:3] - DataBaseAddr[DbgAddressBits-1:3]) << 1))] }; end @@ -325,6 +340,12 @@ module dm_mem #( end end + if (ndmreset_i) begin + // When harts are reset, they are neither halted nor resuming. + halted_d_aligned = '0; + resuming_d_aligned = '0; + end + data_o = data_bits; end @@ -476,6 +497,7 @@ module dm_mem #( if (HasSndScratch) begin : gen_rom_snd_scratch debug_rom i_debug_rom ( .clk_i, + .rst_ni, .req_i, .addr_i ( rom_addr ), .rdata_o ( rom_rdata ) @@ -486,6 +508,7 @@ module dm_mem #( // be saved. debug_rom_one_scratch i_debug_rom ( .clk_i, + .rst_ni, .req_i, .addr_i ( rom_addr ), .rdata_o ( rom_rdata ) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv index 1c2b6195..cc2e1ebc 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv @@ -26,8 +26,8 @@ package dm; // address to which a hart should jump when it was requested to halt localparam logic [63:0] HaltAddress = 64'h800; - localparam logic [63:0] ResumeAddress = HaltAddress + 4; - localparam logic [63:0] ExceptionAddress = HaltAddress + 8; + localparam logic [63:0] ResumeAddress = HaltAddress + 8; + localparam logic [63:0] ExceptionAddress = HaltAddress + 16; // address where data0-15 is shadowed or if shadowed in a CSR // address of the first CSR used for shadowing the data @@ -197,6 +197,12 @@ package dm; DTM_WRITE = 2'h2 } dtm_op_e; + typedef enum logic [1:0] { + DTM_SUCCESS = 2'h0, + DTM_ERR = 2'h2, + DTM_BUSY = 2'h3 + } dtm_op_status_e; + typedef struct packed { logic [31:29] sbversion; logic [28:23] zero0; @@ -215,8 +221,6 @@ package dm; logic sbaccess8; } sbcs_t; - localparam logic [1:0] DTM_SUCCESS = 2'h0; - typedef struct packed { logic [6:0] addr; dtm_op_e op; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv index 3c9c4451..c21e58d9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv @@ -86,6 +86,7 @@ module dm_top #( logic [dm::DataCount-1:0][31:0] data_csrs_mem; logic [dm::DataCount-1:0][31:0] data_mem_csrs; logic data_valid; + logic ndmreset; logic [19:0] hartsel; // System Bus Access Module logic [BusWidth-1:0] sbaddress_csrs_sba; @@ -104,6 +105,7 @@ module dm_top #( logic sberror_valid; logic [2:0] sberror; + assign ndmreset_o = ndmreset; dm_csrs #( .NrHarts(NrHarts), @@ -120,7 +122,7 @@ module dm_top #( .dmi_resp_valid_o, .dmi_resp_ready_i, .dmi_resp_o, - .ndmreset_o, + .ndmreset_o ( ndmreset ), .dmactive_o, .hartsel_o ( hartsel ), .hartinfo_i, @@ -201,6 +203,7 @@ module dm_top #( .clk_i, .rst_ni, .debug_req_o, + .ndmreset_i ( ndmreset ), .hartsel_i ( hartsel ), .haltreq_i ( haltreq ), .resumereq_i ( resumereq ), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv index 0712f8c6..577c3fd0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv @@ -17,7 +17,7 @@ */ module dmi_jtag #( - parameter logic [31:0] IdcodeValue = 32'h00000001 + parameter logic [31:0] IdcodeValue = 32'h00000DB3 ) ( input logic clk_i, // DMI Clock input logic rst_ni, // Asynchronous reset active low @@ -134,9 +134,11 @@ module dmi_jtag #( assign dmi_resp_ready = 1'b1; logic error_dmi_busy; + logic error_dmi_op_failed; always_comb begin : p_fsm error_dmi_busy = 1'b0; + error_dmi_op_failed = 1'b0; // default assignments state_d = state_q; address_d = address_q; @@ -177,7 +179,22 @@ module dmi_jtag #( WaitReadValid: begin // load data into register and shift out if (dmi_resp_valid) begin - data_d = dmi_resp.data; + unique case (dmi_resp.resp) + dm::DTM_SUCCESS: begin + data_d = dmi_resp.data; + end + dm::DTM_ERR: begin + data_d = 32'hDEAD_BEEF; + error_dmi_op_failed = 1'b1; + end + dm::DTM_BUSY: begin + data_d = 32'hB051_B051; + error_dmi_busy = 1'b1; + end + default: begin + data_d = 32'hBAAD_C0DE; + end + endcase state_d = Idle; end end @@ -193,6 +210,11 @@ module dmi_jtag #( WaitWriteValid: begin // got a valid answer go back to idle if (dmi_resp_valid) begin + unique case (dmi_resp.resp) + dm::DTM_ERR: error_dmi_op_failed = 1'b1; + dm::DTM_BUSY: error_dmi_busy = 1'b1; + default: ; + endcase state_d = Idle; end end @@ -218,9 +240,14 @@ module dmi_jtag #( error_dmi_busy = 1'b1; end - if (error_dmi_busy) begin + if (error_dmi_busy && error_q == DMINoError) begin error_d = DMIBusy; end + + if (error_dmi_op_failed && error_q == DMINoError) begin + error_d = DMIOPFailed; + end + // clear sticky error flag if (update && dtmcs_q.dmireset && dtmcs_select) begin error_d = DMINoError; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv index 0c188c05..53f0fa9d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv @@ -94,8 +94,9 @@ module dmi_jtag_tap #( jtag_ir_d = ir_reg_e'(jtag_ir_shift_q); end - // According to JTAG spec we have to reset the IR to IDCODE in test_logic_reset if (test_logic_reset) begin + // Bring all TAP state to the initial value. + jtag_ir_shift_d = '0; jtag_ir_d = IDCODE; end end @@ -135,6 +136,12 @@ module dmi_jtag_tap #( if (idcode_select) idcode_d = {td_i, 31'(idcode_q >> 1)}; if (bypass_select) bypass_d = td_i; end + + if (test_logic_reset) begin + // Bring all TAP state to the initial value. + idcode_d = IdcodeValue; + bypass_d = 1'b0; + end end // ---------------- @@ -180,12 +187,12 @@ module dmi_jtag_tap #( // ---------------- logic tck_n, tck_ni; - cluster_clock_inverter i_tck_inv ( + tc_clk_inverter i_tck_inv ( .clk_i ( tck_i ), .clk_o ( tck_ni ) ); - pulp_clock_mux2 i_dft_tck_mux ( + tc_clk_mux2 i_dft_tck_mux ( .clk0_i ( tck_ni ), .clk1_i ( tck_i ), // bypass the inverted clock for testing .clk_sel_i ( testmode_i ), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core index 6a70b8e2..02d8b12c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core @@ -20,3 +20,4 @@ targets: default: filesets: - target_sim? (rtl_sim) + - target_sim_sc? (rtl_sim) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt index 65542b42..4be49e61 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt @@ -114,3 +114,4 @@ lint_off -rule WIDTH -file "*/rtl/cv32e40p_decoder.sv" -match "Logical operator lint_off -rule WIDTH -file "*/rtl/cv32e40p_controller.sv" -match "Logical operator LOGAND expects 1 bit on the LHS, but LHS's VARREF 'FPU' generates 32 bits.*" lint_off -rule WIDTH -file "*/rtl/cv32e40p_cs_registers.sv" -match "Logical operator LOGOR expects 1 bit on the LHS, but LHS's VARREF 'FPU' generates 32 bits.*" lint_off -rule LATCH -file "*/rtl/cv32e40p_id_stage.sv" -match "Latch inferred for signal*apu_read_regs*" +lint_off -rule WIDTH -file "*/rtl/cv32e40p_cs_registers.sv" -match "Logical operator LOGOR expects 1 bit on the RHS, but RHS's VARREF 'COREV_PULP' generates 32 bits.*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt index ac5b0076..7b3fc6bb 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt @@ -6,3 +6,6 @@ lint_off -rule DECLFILENAME -file "*bhv/cve2_sim_clock_gate.sv" -match "*Filename 'cve2_sim_clock_gate' does not match MODULE name: 'cve2_clock_gate'*" lint_off -rule UNOPTFLAT -file "*rtl/*.sv" -match "*" +lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_a'*" +lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_b'*" +lint_off -rule UNUSED -file "*rtl/cve2_wb.sv" -match "Signal is not used:*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt index 460f3c6b..6a33f058 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt @@ -11,3 +11,4 @@ lint_off -rule DECLFILENAME -file "*/src/cdc_reset_ctrlr.sv" -match "Filename 'c lint_off -rule DECLFILENAME -file "*/src/cdc_fifo_gray_clearable.sv" -match "Filename 'cdc_fifo_gray_clearable' does not match MODULE name: 'cdc_fifo_gray_src_clearable'*" lint_off -rule WIDTH -file "*/src/cdc_2phase_clearable.sv" -match "Logical operator GENIF expects 1 bit on the If, but If's VARREF 'CLEAR_ON_ASYNC_RESET' generates 32 bits.*" lint_off -rule UNOPTFLAT -file "*/src/cdc_4phase.sv" -match "Signal unoptimizable*" +lint_off -rule WIDTH -file "*/src/dm_mem.sv" -match "*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v b/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v index e0eef9f7..55342b5f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v @@ -26,7 +26,7 @@ // updates output signals 1ns after the SPI clock edge. // // Supported commands: -// AB, B9, FF, 03, BB, EB, ED +// AB, B9, FF, 03, BB, EB, ED, 06, 02, 32 // // Well written SPI flash data sheets: // Cypress S25FL064L http://www.cypress.com/file/316661/download @@ -61,6 +61,8 @@ module spiflash ( reg spi_io_vld; reg powered_up = 0; + reg write_enable = 0; + reg write_enable_reset = 0; localparam [3:0] mode_spi = 1; localparam [3:0] mode_dspi_rd = 2; @@ -107,7 +109,7 @@ module spiflash ( initial begin for (i=0;i<=16*1024*1024;i=i+1) - memory[i] = '0; + memory[i] = 8'h00; result = $value$plusargs("firmware=%s", firmware_file); if (!result) firmware_file = "firmware.hex"; @@ -129,6 +131,9 @@ module spiflash ( if (spi_cmd == 8'h ff) xip_cmd = 0; + + if (spi_cmd == 8'h 06) + write_enable = 1; end if (powered_up && spi_cmd == 'h 03) begin @@ -147,6 +152,25 @@ module spiflash ( end end + if (powered_up && write_enable && spi_cmd == 'h 02) begin + if (bytecount == 1) + write_enable_reset = 1; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) + spi_addr[7:0] = buffer; + + if (bytecount >= 5 && bytecount <= 260) begin + memory[spi_addr] = buffer; + spi_addr = spi_addr + 1; + end + end + if (powered_up && spi_cmd == 'h bb) begin if (bytecount == 1) mode = mode_dspi_rd; @@ -197,6 +221,27 @@ module spiflash ( end end + if (powered_up && write_enable && spi_cmd == 'h 32) begin + if (bytecount == 1) + write_enable_reset = 1; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) begin + spi_addr[7:0] = buffer; + mode = mode_qspi_rd; + end + + if (bytecount >= 5 && bytecount <= 260) begin + memory[spi_addr] = buffer; + spi_addr = spi_addr + 1; + end + end + if (powered_up && spi_cmd == 'h ed) begin if (bytecount == 1) next_mode = mode_qspi_ddr_rd; @@ -274,6 +319,10 @@ module spiflash ( $display(""); $fflush; end + if (write_enable_reset) begin + write_enable = 0; + write_enable_reset = 0; + end buffer = 0; bitcount = 0; bytecount = 0; diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/README.md b/hw/vendor/esl_epfl_x_heep/linux_femu/README.md deleted file mode 100644 index 45764e74..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/README.md +++ /dev/null @@ -1,171 +0,0 @@ -# Linux-FEMU - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the Zynq 7020 chip and Linux is run on the ARM-based processing system (PS) side of the same chip. The X-HEEP JTAG signals are driven by the PS GPIO peripheral and are used to program and debug the architecture, while the X-HEEP UART is connected to the PS UART peripheral and is used to get the stdout of the program running on the architecture. Moreover, the X-HEEP flash SPI is connected to the ARM AXI bus passing through an SPI to AXI bridge: this allows virtualising the flash memory into the on-board DDR RAM memory. In this way, the program running on the architecture can read the external virtualised flash as it was a real flash memory, i.e., this virtualisation is totally transparent to the X-HEEP code. - -Go through the following steps to build and use our Linux-FEMU version. - -## Build the platform - -Start in the x-heep main folder. - -## Generate the files - -1. Activate the conda environment with: - -``` -conda activate core-v-mini-mcu -``` - -2. Generate the hdl files by calling: - -``` -make linux-femu-gen PAD_CFG=linux_femu/pad_cfg.hjson -``` - -__NOTE__: you can customize the mcu-gen process by providing the MEMORY_BANKS - CPU - BUS parameters to the above command. - -## Flash the SD card with a Linux image - -1. Download the Linux image (version v3.0.1) using the following link: - -`http://www.pynq.io/board.html` - -2. Follow the procedure explained in the following linked page to flash the downloaded image to the SD card: - -`https://pynq.readthedocs.io/en/v2.2.1/appendix.html#writing-the-sd-card` - -3. Insert the SD into the Pynq-Z2 board and make sure the booting bridge is on the SD position. - -4. Power-on the board and wait for Linux to boot (a row of 4 leds should turn on). - -## Create the Vivado project and generate the bitstream - -1. Starting in the x-heep main folder, run the following command to create the Vivado project and generate the bitstream: - -``` -make vivado-fpga FPGA_BOARD=pynq-z2-arm-emulation -``` - -2. Open the project x-heep/build/openhwgroup.org_systems_core-v-mini-mcu_0/pynq-z2-arm-emulation-vivado/openhwgroup.org_systems_core-v-mini-mcu_0.xpr with Vivado and use the Hardware Manager to program the bitstream to the Zynq 7020 of the Pynq-Z2 board. - -## Connect to Linux running on the Pynq-Z2 board - -Connect your Linux-based PC to the Pynq-Z2 board through Ethernet and run the following command: - -``` -ssh -X xilinx@board_ip -``` - -The default password is: xilinx - -If you need additional documentation on how to connect your PC to the Pynq-Z2 board, use the following link: - -`https://pynq.readthedocs.io/en/v2.6.1/getting_started/pynq_z2_setup.html` - -## Install OpenOCD on the Pynq-Z2 board - -1. Clone the OpenOCD repository usign the following link: - -`https://github.com/openocd-org/openocd` - -2. Run the following commands from the OpneOCD main folder to install it: - -``` -sudo ./bootstrap -sudo ./configure --enable-sysfsgpio -sudo make -sudo make install -``` - -## Copy the x-heep folder to the Pynq-Z2 baord - -Copy the x-heep/linux_femu/arm/ folder from your PC to the home directory of the Pynq-Z2 board with the following command: - -``` -sudo scp -r x-heep/linux_femu/arm/ xilinx@board_ip:~ -``` - -## Enable UART1 on Linux on the Pynq-Z2 baord - -Enter the arm/uart_enable/ folder and run the following commands: - -``` -sudo su -mkdir -p /configfs -./uart_enable.sh -exit -``` - -These commands enable the UART1 on the ARM system side of the Zynq 7020 on the Pynq-Z2 board. UART1 is used to receive the stdout of the code running on the HEEP architecture implemented on the PL side of the chip. - -## Prepare the needed shells - -You need to use 5 shells (the first, second and third shells will run on the Pynq-Z2 board, while the fourth and fifth shells will run on your PC): - -1. First shell - run virtual flash app on the Pynq-Z2 board - browse to the arm/virtual_flash/ folder and execute the following commands to compile and run the required application: - -``` -sudo make clean -sudo make -sudo ./virtual_flash -``` - -This app allocates a buffer into the off-chip DDR memory of the Pynq-Z2 board and stores its physical base address to the hijacker PL peripheral. - -2. Second shell - run the following commands on the Pynq-Z2 board to get the stdout from the app running on x-heep: - -``` -sudo apt-get install screen -sudo screen /dev/ttyPS1 115200 -``` - -3. Third shell - run openocd on the Pynq-Z2 board - browse to the arm/openocd_cfg/ folder and run the following command: - -``` -sudo openocd -f ./gpio_bitbang.cfg -``` - -4. Fourth shell - compile HEEP app on your PC - browse to the x-heep/sw/ folder and run the following command: - -``` -make clean applications/example_virtual_flash/example_virtual_flash.hex TARGET=pynq-z2 -``` - -With this command you compile a sample RISC-V based application that uses the allocated DDR-based virtual memory. You may want to change this command with the name of your own application. - -5. Fifth shell - run GDB on your PC - browse to the x-heep/sw/applications/example_virtual_flash/ folder and run the following command to connect GDB: - -``` -sudo /path_to_your_riscv_toolchain/bin/riscv32-unknown-elf-gdb -``` - -Use the following GDB commands to connect to OpenOCD running on the Pynq-Z2 board and run your application: - -``` -(gdb) target remote board_ip:3333 -(gdb) load example_virtual_flash.elf -(gdb) cont -``` - -Go back to the first shell and press ENTER to end the application and dump the content of the virtual flash to a file. Then, run the following commands: - -``` -xxd dump.txt dump -nano dump -``` - -Check if your result corresponds to the following lines: - -``` -00000000: 0000 0000 0000 0001 0000 0002 0000 0003 ................ -00000010: 0000 0004 0000 0005 0000 0006 0000 0007 ................ -00000020: 0000 0008 0000 0009 0000 000a 0000 000b ................ -00000030: 0000 000c 0000 000d 0000 000e 0000 000f ................ -00000040: 0000 0010 0000 0011 0000 0012 0000 0013 ................ -00000050: 0000 0014 0000 0015 0000 0016 0000 0017 ................ -00000060: 0000 0018 0000 0019 0000 001a 0000 001b ................ -00000070: 0000 001c 0000 001d 0000 001e 0000 001f ................ -00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ -``` - -__NOTE__: to run other applications, press the hard reset button on the Pynq-Z2 board (BTN3) and re-connect OpneOCD and GDB. diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md deleted file mode 100644 index 38dfdbce..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md +++ /dev/null @@ -1,80 +0,0 @@ -### Hardware Configurations - -On the hardware side, we must configure the ZYNQ processing system to use the EMIO and export them externally so that they can be attached to x-heep. They are then routed outwards from the wrapper to x-heep JTAG signals. - -### Software Configurations - -## Target adapter configuration __gpio_bitbang.cfg__: - -``` -# SPDX-License-Identifier: GPL-2.0-or-later - -# -# Config for using RaspberryPi's expansion header -# -# This is best used with a fast enough buffer but also -# is suitable for direct connection if the target voltage -# matches RPi's 3.3V -# -# Do not forget the GND connection, pin 6 of the expansion header. -# - -adapter driver sysfsgpio -transport select jtag - -bindto 0.0.0.0 - -set _CHIPNAME riscv -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10001c05 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000 -echo "Target created" - -riscv set_reset_timeout_sec 2000 -riscv set_command_timeout_sec 2000 -# riscv set_prefer_sba off - -echo "Setting preferences" - -# Each of the JTAG lines need a gpio number set: tck tms tdi tdo -# Header pin numbers: 23 22 19 21 -sysfsgpio jtag_nums 964 961 963 962 - -# Each of the SWD lines need a gpio number set: swclk swdio -# Header pin numbers: 23 22 -# sysfsgpio swd_nums 11 25 - -# If you define trst or srst, use appropriate reset_config -# Header pin numbers: TRST - 26, SRST - 18 - -sysfsgpio trst_num 960 -reset_config trst_only - -# sysfsgpio srst_num 24 -# reset_config srst_only srst_push_pull - -# or if you have both connected, -# reset_config trst_and_srst srst_push_pull - -scan_chain - -init - -echo "Init routine started" - -halt -echo "Ready for connections" -``` - -This instructs openocd to use the riscv HART and jtag module but instead of transmitting the commands over the usual FTDI usb adapter, it bitbangs the GPIOs by using the SYSFS framework. - -In order to understand the pin numbering used in the script we have to know how the JTAG has been ported to the PYNQ without using external adapters. The ZYNQ 7000 offers several banks of GPIO lines used for different purposes. The first 54 are MIO (multiplexed I/O) and are configured for different purposes but are PS-side only. After those, we have 64 EMIO (extended MIO) which are lines that can be routed to the PL). The idea is therefore to expose 5 EMIO GPIOS (5 jtag signals) and route them to the PL and to x-heep directly. Those can be controlled as normal GPIO lines and allow interfacing directly from ARM. - -Therefore, the pin numbers used in the configuration file are derived as follows: - -1. Find the GPIO starting numbers that linux uses by running ``` sudo cat /sys/kernel/debug/gpio ``` -> in this case it was __906__ - -2. Add 54 (the first 54 GPIOS are the MIOs). - -3. Add the gpio_n assigned to the specific signal (depends on the HDL connections). diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg deleted file mode 100755 index 11c5519d..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg +++ /dev/null @@ -1,58 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later - -# -# Config for using RaspberryPi's expansion header -# -# This is best used with a fast enough buffer but also -# is suitable for direct connection if the target voltage -# matches RPi's 3.3V -# -# Do not forget the GND connection, pin 6 of the expansion header. -# - -adapter driver sysfsgpio -transport select jtag - -bindto 0.0.0.0 - -set _CHIPNAME riscv -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10001c05 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000 -echo "Target created" - -riscv set_reset_timeout_sec 2000 -riscv set_command_timeout_sec 2000 -# riscv set_prefer_sba off - -echo "Setting preferences" - -# Each of the JTAG lines need a gpio number set: tck tms tdi tdo -# Header pin numbers: 23 22 19 21 -sysfsgpio jtag_nums 964 961 963 962 - -# Each of the SWD lines need a gpio number set: swclk swdio -# Header pin numbers: 23 22 -# sysfsgpio swd_nums 11 25 - -# If you define trst or srst, use appropriate reset_config -# Header pin numbers: TRST - 26, SRST - 18 - -sysfsgpio trst_num 960 -reset_config trst_only - -# sysfsgpio srst_num 24 -# reset_config srst_only srst_push_pull - -# or if you have both connected, -# reset_config trst_and_srst srst_push_pull - -scan_chain - -init - -echo "Init routine started" - -halt -echo "Ready for connections" diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md deleted file mode 100644 index 15f4fac9..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md +++ /dev/null @@ -1,57 +0,0 @@ -### Hardware Configurations - -On the hardware side, we must configure the ZYNQ processing system to enable UART1 and route tx and rx to the EMIO pins so that they can be attached to x-heep. They are then routed outwards from the wrapper to x-heep UART signals. - -__NOTE__: remembed to connect tx to rx and viceversa. - -### Software Configurations - -## Enable UART1 - -In order to ask Linux to use that as a normal serial port, we need to modify the DEVICE TREE to expose this new hardware piece. In theory, the UART1 peripheral is already defined in the tree but is disabled. Instead of rebuilding the device tree, we can add an overlay at runtime to add and change configuration properties of the tree. In particular, we need to extend the device tree with the following: - -``` -/dts-v1/; -/plugin/; - -/{ - fragment@0{ - target-path = "/aliases"; - __overlay__ { - serial1 = "/axi/serial@e0001000"; - }; - }; - - fragment@1{ - target = <&uart1>; - __overlay__ { - status = "okay"; - }; - }; -}; - -``` - -This first makes an alias to make sure that the uart1 (/axi/serial@e0001000) is called serial1, and then enables it by setting the status as "okay". Aliasing is important to avoid a problem that could arise if the kernel decides to swap the ttyPS1 and ttyPS0 (uart0 and the one used to connect to ARM through serial), because we'd have no access to the board over serial. - -1. DTSI file must be compiled into binary format as follows: - -``` -dtc -O dtb -o uart_enable.dtbo -b 0 -@ uart_enable.dtsi -``` -2. We mount the configfs, which is a RAM-based configuration file-system exposed to add overlays. - -``` -sudo mount configfs configfs /configfs -sudo mkdir configfs/device-tree/overlays/uart_enable -``` - -3. Concatenate the dtbo binary file to insert into the kernel device tree. - -``` -sudo su -cat uart_enable.dtbo >/configfs/device-tree/overlays/uart_enable/dtbo -exit -``` - -4. Make sure with dmesg that no errors were thrown and that /dev/ttySP1 has appeared -> that is x-heep's serial. diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtbo b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtbo deleted file mode 100755 index 896a0f34f64bdb7390b4dc181001e74076428956..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 344 zcmZusJqyAx5WV;@2nq^1xjDH=n@u|PXSjtM(ps#xB&oFj(m&$vq~0~9qWIwD-97G- zm)q=l2M`AU*pr5&TjGK^Co;HywAJ?^x>h6x)3d&~n709j#0eJx<{4UTxh4puimNs` zHcD~Nb1ULBz&Z=8HW}uz4#Q9qd4MqJ_<2LNKJSi*%NK$4-`!*K*To4NQbvE5Qb|@< orS&oT9Gjs3h>RSXRJ-Um$He=)65SDeWC`8_>(EseDl|^Q8(n`scK`qY diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi deleted file mode 100755 index 21804e30..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi +++ /dev/null @@ -1,18 +0,0 @@ -/dts-v1/; -/plugin/; - -/{ - fragment@0{ - target-path = "/aliases"; - __overlay__ { - serial1 = "/axi/serial@e0001000"; - }; - }; - - fragment@1{ - target = <&uart1>; - __overlay__ { - status = "okay"; - }; - }; -}; diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh deleted file mode 100755 index ec02611c..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -mount -t configfs configfs /configfs -mkdir /configfs/device-tree/overlays/uart_enable -cat ./uart_enable.dtbo >/configfs/device-tree/overlays/uart_enable/dtbo diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile deleted file mode 100755 index e9c11b69..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: virtual_flash - -virtual_flash: virtual_flash.cpp OverlayControl.c OverlayControl.h - g++ -O0 -g -Wall virtual_flash.cpp OverlayControl.c -o virtual_flash -lpthread -lm -lcma - -clean: - rm -f virtual_flash diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c deleted file mode 100755 index 68f2a857..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c +++ /dev/null @@ -1,103 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -// 1 --> Basic logging, 2 --> Debugging -#define LOGGING 2 - -#include "OverlayControl.h" -extern "C" { -#include -} - -static volatile uint32_t * memMapAddr = NULL; -static int memMapFileDesc = -1; -static uint32_t memMapSize = 0; - -volatile uint32_t * MapMemIO(uint32_t baseAddr, uint32_t mapSize) -{ - bool res = true; - - res = ( (memMapFileDesc = open("/dev/mem", O_RDWR | O_SYNC )) != -1); - - if (!res) { - #ifdef LOGGING - printf("Error opening file.\n"); - #endif - } - else { - #if LOGGING == 2 - printf("File opened.\n"); - #endif - memMapAddr = (volatile unsigned int *)mmap(NULL, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, memMapFileDesc, baseAddr); - res = (memMapAddr != MAP_FAILED); - if (!res) { - #ifdef LOGGING - printf("Memory mapping failed.\n"); - #endif - close(memMapFileDesc); - memMapFileDesc = -1; - memMapAddr = NULL; - } - } - - if (res) { - #ifdef LOGGING - printf("Memory mapped.\n"); - #endif - memMapSize = mapSize; - } - - return memMapAddr; -} - -bool UnmapMemIO() -{ - bool res = true; - - if ((memMapAddr != NULL) && (memMapAddr != MAP_FAILED)) { - if ( munmap((void*)memMapAddr, memMapSize) ) { - #ifdef LOGGING - printf("Memory unmapping failed.\n"); - #endif - res = false; - } - else { - #ifdef LOGGING - printf("Memory unmapped.\n"); - #endif - } - } - - if (memMapFileDesc != -1) { - close(memMapFileDesc); - memMapFileDesc = -1; - } - - return res; -} - -// Reference of functions to (de)allocate DMA memory. -// extern "C" { -// #include -// } -/* * Allocate a physically contiguos chunk of CMA memory and map it into - * virtual memory space. Return this Virtual pointer. Returns -1 on failure. -void *cma_alloc(uint32_t len, uint32_t cacheable); - * Return a physical memory address corresponding to a given Virtual address - * pointer. Returns NULL on failure. -unsigned long cma_get_phy_addr(void *buf); - * Free a previously allocated CMA memory chunk. -void cma_free(void *buf); - * Returns the number of available CMA memiry pages which can be allocated. -uint32_t cma_pages_available(); - * Extra functions in case user needs to flush or invalidate Cache. -void cma_flush_cache(void *buf, unsigned int phys_addr, int size); -void cma_invalidate_cache(void *buf, unsigned int phys_addr, int size); -*/ diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h deleted file mode 100755 index 92807321..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef OVERLAYCONTROL_H -#define OVERLAYCONTROL_H - -volatile uint32_t * MapMemIO(uint32_t baseAddr, uint32_t mapSize); -bool UnmapMemIO(); - -// Reference of functions to (de)allocate DMA memory. -// extern "C" { -// #include -// } -/* * Allocate a physically contiguos chunk of CMA memory and map it into - * virtual memory space. Return this Virtual pointer. Returns -1 on failure. -void *cma_alloc(uint32_t len, uint32_t cacheable); - * Return a physical memory address corresponding to a given Virtual address - * pointer. Returns NULL on failure. -unsigned long cma_get_phy_addr(void *buf); - * Free a previously allocated CMA memory chunk. -void cma_free(void *buf); - * Returns the number of available CMA memiry pages which can be allocated. -uint32_t cma_pages_available(); - * Extra functions in case user needs to flush or invalidate Cache. -void cma_flush_cache(void *buf, unsigned int phys_addr, int size); -void cma_invalidate_cache(void *buf, unsigned int phys_addr, int size); -*/ - -#endif // OVERLAYCONTROL_H diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp deleted file mode 100755 index 8de7bc7c..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp +++ /dev/null @@ -1,100 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include "OverlayControl.h" - -extern "C" { -#include -} - -const uint32_t MEM_IS_CACHEABLE = 0; -const uint32_t MAP_SIZE = 64*1024; -const uint32_t BASE_ADDR = 0x43C00000; -const uint32_t ALLOC_SIZE_BYTE = 64*1024*128; -const uint32_t FIXED_VALUE = 0x1c; - -uint32_t *virtual_flash_buffer, *virtual_flash_buffer_phy; - -static void stop(int) -{ - signal(SIGTERM, SIG_DFL); - signal(SIGINT, SIG_DFL); - - if(virtual_flash_buffer != NULL){ - FILE* dump = fopen("./dump.txt", "wb"); - fwrite(virtual_flash_buffer, ALLOC_SIZE_BYTE, 1, dump); - fclose(dump); - } -} - -int main(int argc, char **argv) -{ - signal(SIGTERM, stop); - signal(SIGINT, stop); - volatile uint8_t *pl_peripherals = NULL; - volatile uint32_t* hijacker = NULL; - - printf("Press ENTER to confirm that the bitstream is loaded (proceeding without it can crash the board).\n"); - getchar(); - - // Get the virtual address corresponding to the physical base address of the PL peripherals - if ((pl_peripherals = (uint8_t *) MapMemIO(BASE_ADDR, MAP_SIZE)) == NULL) { - printf("Error getting address!\n"); - return -1; - } - printf("PL peripherals mapped at 0x%08X.\n", (uint32_t)pl_peripherals); - fflush(stdout); - - // Map hijacker PL peripheral - hijacker = (uint32_t *)pl_peripherals; - printf("hijacker mapped at 0x%08X.\n", (uint32_t)hijacker); - - // Allocate DDR memory buffer to virtualize a Flash memory and get its physical address - fflush(stdout); - virtual_flash_buffer = (uint32_t *)cma_alloc(ALLOC_SIZE_BYTE, MEM_IS_CACHEABLE); - virtual_flash_buffer_phy = (uint32_t *)((uint32_t)cma_get_phy_addr(virtual_flash_buffer)); - printf("DDR memory buffer allocated.\n"); - fflush(stdout); - printf("Virtual address: 0x%.8X.\n", (uint32_t)virtual_flash_buffer); - fflush(stdout); - printf("Physical address: Phys: 0x%.8X.\n\n", (uint32_t)virtual_flash_buffer_phy); - fflush(stdout); - if (virtual_flash_buffer == NULL) { - printf("Error allocating DDR memory for %u bytes!\n", ALLOC_SIZE_BYTE); - return -1; - } - - // Initialize DDR memory buffer - for (uint32_t i = 0; i < ALLOC_SIZE_BYTE / sizeof(uint32_t); i++) - virtual_flash_buffer[0] = i; - - // Copy the physical address of the DDR memory buffer to hijacker PL peripheral - *hijacker = (uint32_t)virtual_flash_buffer_phy; - - // Press ENTER to end the application - printf("Press ENTER to end the application.\n"); - getchar(); - - printf("Virtual flash read and content stored in file dump.txt.\n\n"); - - // Read content of the DDR memory buffer and store it to a file - FILE *dump = fopen("./dump.txt", "wb"); - fwrite(virtual_flash_buffer, ALLOC_SIZE_BYTE, 1, dump); - fclose(dump); - - /////////////////////////////////////////////////////////////////////////////////////// - // DDR memory is a global variable. In this Linux version, it is allocated - // by a pl_peripherals driver provided by Xilinx. This means that it is not freed - // automatically when our process exits. We MUST free it or the board will - // run out of DMA memory!!! - /////////////////////////////////////////////////////////////////////////////////////// - if (virtual_flash_buffer != NULL) - cma_free(virtual_flash_buffer); - UnmapMemIO(); - - return 0; -} diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc b/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc deleted file mode 100644 index ca9babe2..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc +++ /dev/null @@ -1 +0,0 @@ -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets linux_femu/pad_ring_i/pad_clk_i/xilinx_iobuf_i/O] diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc deleted file mode 100644 index d6be7e83..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2022 EPFL -# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports clk_in] -set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports rst_i] -set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports rst_led] -set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports clk_led] -set_property -dict {PACKAGE_PIN W9 IOSTANDARD LVCMOS33} [get_ports clk_out] -set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] -set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports exit_value_o] -set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] -set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports boot_select_i] - -## Pmoda -## RPi GPIO 7-0 are shared with pmoda_rpi_gpio_tri_io[7:0] - -# QSPI - -set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_io] -set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_io] -set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_0_io}] -set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_1_io}] -set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_2_io}] -set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_3_io}] - -## Pmodb - -set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}] -set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}] -set_property -dict {PACKAGE_PIN W8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}] -set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}] -set_property -dict {PACKAGE_PIN Y6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}] -set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}] -set_property -dict {PACKAGE_PIN W10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}] -set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}] -set_property -dict {PACKAGE_PIN V8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}] -set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}] -set_property -dict {PACKAGE_PIN V7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}] -set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[11]}] -set_property -dict {PACKAGE_PIN V6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[12]}] -set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[13]}] -set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[14]}] -set_property -dict {PACKAGE_PIN Y9 IOSTANDARD LVCMOS33} [get_ports {gpio_io[15]}] -set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[16]}] -set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {gpio_io[17]}] -set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[18]}] -set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[19]}] -set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[20]}] -set_property -dict {PACKAGE_PIN F19 IOSTANDARD LVCMOS33} [get_ports {gpio_io[21]}] -set_property -dict {PACKAGE_PIN P16 IOSTANDARD LVCMOS33} [get_ports {gpio_io[22]}] -set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_io[0]}] -set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_io[1]}] -set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_io}] -set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_0_io}] -set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_1_io}] -set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_2_io}] -set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_3_io}] -#set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[24]}] -#set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[25]}] -#set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[26]}] -#set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[27]}] -#set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {gpio_io[28]}] -#set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[29]}] -#set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[30]}] -#set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {gpio_io[31]}] - -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] - -set_property PACKAGE_PIN W13 [get_ports i2c_scl_io] -set_property PACKAGE_PIN T10 [get_ports i2c_sda_io] -set_property IOSTANDARD LVCMOS33 [get_ports i2c_scl_io] -set_property IOSTANDARD LVCMOS33 [get_ports i2c_sda_io] diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson b/hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson deleted file mode 100644 index 235ee13f..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// Derived from Occamy: https://github.com/pulp-platform/snitch/blob/master/hw/system/occamy/src/occamy_cfg.hjson -// Peripherals configuration for core-v-mini-mcu. -{ - pads: { - - clk: { - num: 1, - type: input - }, - rst: { - num: 1, - active: low, - driven_manually: True - type: input - }, - boot_select: { - num: 1, - type: input - }, - execute_from_flash: { - num: 1, - type: input - }, - jtag_tck: { - num: 1, - keep_internal: True - type: input - }, - jtag_tms: { - num: 1, - keep_internal: True - type: input - }, - jtag_trst: { - num: 1, - keep_internal: True - active: low, - type: input - }, - jtag_tdi: { - num: 1, - keep_internal: True - type: input - }, - jtag_tdo: { - num: 1, - keep_internal: True - type: output - }, - uart_rx: { - num: 1, - keep_internal: True - type: input - }, - uart_tx: { - num: 1, - keep_internal: True - type: output - }, - exit_valid: { - num: 1, - type: output - }, - gpio: { - num: 23, - num_offset: 0, #first gpio is gpio0 - type: inout - }, - spi_flash_sck: { - num: 1, - keep_internal: True - type: inout - }, - spi_flash_cs: { - num: 2, #carefull, the x-heep uses the CS from the spi pkg, change it - keep_internal: True - type: inout - }, - spi_flash_sd: { - num: 4, - keep_internal: True - type: inout - }, - spi_sck: { - num: 1, - type: inout - }, - spi_cs: { - num: 2, - type: inout - }, - spi_sd: { - num: 4, - type: inout - }, - spi2_cs_0: { - num: 1, - type: inout - mux: { - spi2_cs_0: { - type: inout - }, - gpio_23: { - type: inout - }, - } - }, - spi2_cs_1: { - num: 1, - type: inout - mux: { - spi2_cs_1: { - type: inout - }, - gpio_24: { - type: inout - }, - }, - }, - spi2_sck: { - num: 1, - type: inout - mux: { - spi2_sck: { - type: inout - }, - gpio_25: { - type: inout - }, - } - }, - spi2_sd_0: { - num: 1, - type: inout - mux: { - spi2_sd_0: { - type: inout - }, - gpio_26: { - type: inout - }, - } - }, - spi2_sd_1: { - num: 1, - type: inout - mux: { - spi2_sd_1: { - type: inout - }, - gpio_27: { - type: inout - }, - } - }, - spi2_sd_2: { - num: 1, - type: inout - mux: { - spi2_sd_2: { - type: inout - }, - gpio_28: { - type: inout - }, - } - }, - spi2_sd_3: { - num: 1, - type: inout - mux: { - spi2_sd_3: { - type: inout - }, - gpio_29: { - type: inout - }, - } - }, - i2c_scl: { - num: 1, - type: inout - mux: { - i2c_scl: { - type: inout - }, - gpio_31: { - type: inout - }, - } - }, - i2c_sda: { - num: 1, - type: inout - mux: { - i2c_sda: { - type: inout - }, - gpio_30: { - type: inout - }, - } - } - } -} diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v b/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v deleted file mode 100644 index e99c60e8..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2022 EPFL -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -module axi_address_hijacker # -( - parameter integer AXI_ADDR_WIDTH = 32, - parameter integer C_S_AXI_DATA_WIDTH = 32, - parameter integer C_S_AXI_ADDR_WIDTH = 4 -)( - input wire [AXI_ADDR_WIDTH-1:0] axi_master_awaddr_in, - input wire [AXI_ADDR_WIDTH-1:0] axi_master_araddr_in, - - output wire [AXI_ADDR_WIDTH-1:0] axi_master_araddr_out, - output wire [AXI_ADDR_WIDTH-1:0] axi_master_awaddr_out, - - ///////////////////////////////////////// - // AXI-Lite slave interface - ///////////////////////////////////////// - - // clock and reset - input wire S_AXI_ACLK, - input wire S_AXI_ARESETN, - - // write address - input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, - input wire [2 : 0] S_AXI_AWPROT, - input wire S_AXI_AWVALID, - output wire S_AXI_AWREADY, - - // write data - input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, - input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, - input wire S_AXI_WVALID, - output wire S_AXI_WREADY, - - // write response - output wire [1 : 0] S_AXI_BRESP, - output wire S_AXI_BVALID, - input wire S_AXI_BREADY, - - // read address - input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, - input wire [2 : 0] S_AXI_ARPROT, - input wire S_AXI_ARVALID, - output wire S_AXI_ARREADY, - - // read data - output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, - output wire [1 : 0] S_AXI_RRESP, - output wire S_AXI_RVALID, - input wire S_AXI_RREADY -); - - reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; - reg axi_awready; - reg axi_wready; - reg [1 : 0] axi_bresp; - reg axi_bvalid; - reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; - reg axi_arready; - reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; - reg [1 : 0] axi_rresp; - reg axi_rvalid; - - localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1; - localparam integer OPT_MEM_ADDR_BITS = 1; - - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0; - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1; - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2; - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3; - wire slv_reg_rden; - wire slv_reg_wren; - reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; - integer byte_index; - reg aw_en; - - assign S_AXI_AWREADY = axi_awready; - assign S_AXI_WREADY = axi_wready; - assign S_AXI_BRESP = axi_bresp; - assign S_AXI_BVALID = axi_bvalid; - assign S_AXI_ARREADY = axi_arready; - assign S_AXI_RDATA = axi_rdata; - assign S_AXI_RRESP = axi_rresp; - assign S_AXI_RVALID = axi_rvalid; - - // Implement axi_awready generation - // axi_awready is asserted for one S_AXI_ACLK clock cycle when both - // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is - // de-asserted when reset is low. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_awready <= 1'b0; - aw_en <= 1'b1; - end - else - begin - if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) - begin - axi_awready <= 1'b1; - aw_en <= 1'b0; - end - else if (S_AXI_BREADY && axi_bvalid) - begin - aw_en <= 1'b1; - axi_awready <= 1'b0; - end - else - begin - axi_awready <= 1'b0; - end - end - end - - // Implement axi_awaddr latching - // This process is used to latch the address when both - // S_AXI_AWVALID and S_AXI_WVALID are valid. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_awaddr <= 0; - end - else - begin - if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) - begin - axi_awaddr <= S_AXI_AWADDR; - end - end - end - - // Implement axi_wready generation - // axi_wready is asserted for one S_AXI_ACLK clock cycle when both - // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is - // de-asserted when reset is low. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_wready <= 1'b0; - end - else - begin - if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en ) - begin - axi_wready <= 1'b1; - end - else - begin - axi_wready <= 1'b0; - end - end - end - - // Implement memory mapped register select and write logic generation - // The write data is accepted and written to memory mapped registers when - // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to - // select byte enables of slave registers while writing. - // These registers are cleared when reset (active low) is applied. - // Slave register write enable is asserted when valid address and data are available - // and the slave is ready to accept the write address and write data. - assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; - - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - slv_reg0 <= 0; - slv_reg1 <= 0; - slv_reg2 <= 0; - slv_reg3 <= 0; - end - else begin - if (slv_reg_wren) - begin - case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) - 2'h0: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - 2'h1: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - 2'h2: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - 2'h3: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - default : begin - slv_reg0 <= slv_reg0; - slv_reg1 <= slv_reg1; - slv_reg2 <= slv_reg2; - slv_reg3 <= slv_reg3; - end - endcase - end - end - end - - // Implement write response logic generation - // The write response and response valid signals are asserted by the slave - // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. - // This marks the acceptance of address and indicates the status of - // write transaction. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_bvalid <= 0; - axi_bresp <= 2'b0; - end - else - begin - if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) - begin - axi_bvalid <= 1'b1; - axi_bresp <= 2'b0; - end - else - begin - if (S_AXI_BREADY && axi_bvalid) - begin - axi_bvalid <= 1'b0; - end - end - end - end - - // Implement axi_arready generation - // axi_arready is asserted for one S_AXI_ACLK clock cycle when - // S_AXI_ARVALID is asserted. axi_awready is - // de-asserted when reset (active low) is asserted. - // The read address is also latched when S_AXI_ARVALID is - // asserted. axi_araddr is reset to zero on reset assertion. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_arready <= 1'b0; - axi_araddr <= 32'b0; - end - else - begin - if (~axi_arready && S_AXI_ARVALID) - begin - axi_arready <= 1'b1; - axi_araddr <= S_AXI_ARADDR; - end - else - begin - axi_arready <= 1'b0; - end - end - end - - // Implement axi_arvalid generation - // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both - // S_AXI_ARVALID and axi_arready are asserted. The slave registers - // data are available on the axi_rdata bus at this instance. The - // assertion of axi_rvalid marks the validity of read data on the - // bus and axi_rresp indicates the status of read transaction.axi_rvalid - // is deasserted on reset (active low). axi_rresp and axi_rdata are - // cleared to zero on reset (active low). - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_rvalid <= 0; - axi_rresp <= 0; - end - else - begin - if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) - begin - axi_rvalid <= 1'b1; - axi_rresp <= 2'b0; - end - else if (axi_rvalid && S_AXI_RREADY) - begin - axi_rvalid <= 1'b0; - end - end - end - - // Implement memory mapped register select and read logic generation - // Slave register read enable is asserted when valid address is available - // and the slave is ready to accept the read address. - assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; - always @(*) - begin - case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) - 2'h0 : reg_data_out <= slv_reg0; - 2'h1 : reg_data_out <= slv_reg1; - 2'h2 : reg_data_out <= slv_reg2; - 2'h3 : reg_data_out <= slv_reg3; - default : reg_data_out <= 0; - endcase - end - - // Output register or memory read data - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_rdata <= 0; - end - else - begin - if (slv_reg_rden) - begin - axi_rdata <= reg_data_out; - end - end - end - - assign axi_master_araddr_out = axi_master_araddr_in + slv_reg0; - assign axi_master_awaddr_out = axi_master_awaddr_in + slv_reg0; - - endmodule diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl b/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl deleted file mode 100644 index ef5dad9b..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright 2022 EPFL -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -module linux_femu - import obi_pkg::*; - import reg_pkg::*; -#( - parameter COREV_PULP = 0, - parameter FPU = 0, - parameter ZFINX = 0, - parameter EXT_XBAR_NMASTER = 0, - parameter CLK_LED_COUNT_LENGTH = 27 -) ( - inout logic clk_in, - inout logic rst_i, - - output logic rst_led, - output logic clk_led, - output logic clk_out, - - inout logic boot_select_i, - inout logic execute_from_flash_i, - - inout logic [29:0] gpio_io, - - output logic exit_value_o, - inout logic exit_valid_o, - - inout logic spi_sd_0_io, - inout logic spi_sd_1_io, - inout logic spi_sd_2_io, - inout logic spi_sd_3_io, - inout logic spi_csb_io, - inout logic spi_sck_io, - - inout logic spi2_sd_0_io, - inout logic spi2_sd_1_io, - inout logic spi2_sd_2_io, - inout logic spi2_sd_3_io, - inout logic [1:0] spi2_csb_io, - inout logic spi2_sck_io, - - inout logic i2c_scl_io, - inout logic i2c_sda_io, - - inout wire [14:0] DDR_addr, - inout wire [2:0] DDR_ba, - inout wire DDR_cas_n, - inout wire DDR_ck_n, - inout wire DDR_ck_p, - inout wire DDR_cke, - inout wire DDR_cs_n, - inout wire [3:0] DDR_dm, - inout wire [31:0] DDR_dq, - inout wire [3:0] DDR_dqs_n, - inout wire [3:0] DDR_dqs_p, - inout wire DDR_odt, - inout wire DDR_ras_n, - inout wire DDR_reset_n, - inout wire DDR_we_n, - inout wire FIXED_IO_ddr_vrn, - inout wire FIXED_IO_ddr_vrp, - inout wire [53:0] FIXED_IO_mio, - inout wire FIXED_IO_ps_clk, - inout wire FIXED_IO_ps_porb, - inout wire FIXED_IO_ps_srstb -); - - import core_v_mini_mcu_pkg::*; - - parameter AXI_ADDR_WIDTH = 32; - parameter AXI_ADDR_WIDTH_SLAVE = 4; - parameter AXI_DATA_WIDTH = 32; - - // PM signals - logic cpu_subsystem_powergate_switch; - logic cpu_subsystem_powergate_switch_ack; - logic cpu_subsystem_powergate_iso; - logic cpu_subsystem_rst_n; - logic peripheral_subsystem_powergate_switch; - logic peripheral_subsystem_powergate_switch_ack; - logic peripheral_subsystem_powergate_iso; - logic peripheral_subsystem_rst_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_set_retentive; - - // PS SIDE PORTS - logic AXI_HP_ACLK; - logic AXI_HP_ARESETN; - logic [AXI_ADDR_WIDTH - 1:0] AXI_HP_araddr_sig; - logic [1:0] AXI_HP_arburst_sig; - logic [3:0] AXI_HP_arcache_sig; - logic [5:0] AXI_HP_arid_sig; - logic [3:0] AXI_HP_arlen_sig; - logic [1:0] AXI_HP_arlock_sig; - logic [2:0] AXI_HP_arprot_sig; - logic [3:0] AXI_HP_arqos_sig; - logic AXI_HP_arready_sig; - logic [2:0] AXI_HP_arsize_sig; - logic AXI_HP_arvalid_sig; - logic [AXI_ADDR_WIDTH - 1:0] AXI_HP_awaddr_sig; - logic [1:0] AXI_HP_awburst_sig; - logic [3:0] AXI_HP_awcache_sig; - logic [5:0] AXI_HP_awid_sig; - logic [3:0] AXI_HP_awlen_sig; - logic [1:0] AXI_HP_awlock_sig; - logic [2:0] AXI_HP_awprot_sig; - logic [3:0] AXI_HP_awqos_sig; - logic AXI_HP_awready_sig; - logic [2:0] AXI_HP_awsize_sig; - logic AXI_HP_awvalid_sig; - logic [5:0] AXI_HP_bid_sig; - logic AXI_HP_bready_sig; - logic [1:0] AXI_HP_bresp_sig; - logic AXI_HP_bvalid_sig; - logic [AXI_DATA_WIDTH - 1:0] AXI_HP_rdata_sig; - logic [5:0] AXI_HP_rid_sig; - logic AXI_HP_rlast_sig; - logic AXI_HP_rready_sig; - logic [1:0] AXI_HP_rresp_sig; - logic AXI_HP_rvalid_sig; - logic [AXI_DATA_WIDTH - 1:0] AXI_HP_wdata_sig; - logic [5:0] AXI_HP_wid_sig; - logic AXI_HP_wlast_sig; - logic AXI_HP_wready_sig; - logic [3:0] AXI_HP_wstrb_sig; - logic AXI_HP_wvalid_sig; - - logic spi_test_clk_sig; - logic spi_test_cs_sig; - logic [3:0] spi_test_data_sig; - - // ADDRESS HIJACKER PORTS - logic [AXI_ADDR_WIDTH-1:0] axi_master_awaddr_in_sig; - logic [AXI_ADDR_WIDTH-1:0] axi_master_araddr_in_sig; - - logic [AXI_ADDR_WIDTH_SLAVE - 1 : 0] s00_axi_awaddr_sig; - logic s00_axi_awvalid_sig; - logic s00_axi_awready_sig; - logic [AXI_DATA_WIDTH - 1 : 0] s00_axi_wdata_sig; - logic s00_axi_wvalid_sig; - logic s00_axi_wready_sig; - logic s00_axi_bvalid_sig; - logic s00_axi_bready_sig; - logic [(AXI_DATA_WIDTH / 8)-1 : 0] s00_axi_wstrb_sig; - logic [2 : 0] s00_axi_arprot_sig; - logic [2 : 0] s00_axi_awprot_sig; - logic [AXI_ADDR_WIDTH_SLAVE - 1 : 0] s00_axi_araddr_sig; - logic s00_axi_arvalid_sig; - logic s00_axi_arready_sig; - logic [AXI_DATA_WIDTH - 1 : 0] s00_axi_rdata_sig; - logic s00_axi_rvalid_sig; - logic s00_axi_rready_sig; - logic [1:0] s00_axi_rresp_sig; - logic [1:0] s00_axi_bresp_sig; - - // PAD controller - reg_req_t pad_req; - reg_rsp_t pad_resp; - logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][7:0] pad_attributes; - logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][3:0] pad_muxes; - - logic rst_ngen; - - // input, output pins from core_v_mini_mcu -% for pad in total_pad_list: -${pad.internal_signals} -% endfor - - wire clk_gen; - logic [ 31:0] exit_value; - wire rst_n; - logic [CLK_LED_COUNT_LENGTH - 1:0] clk_count; - - // low active reset - assign rst_n = !rst_i; - - // reset LED for debugging - assign rst_led = rst_n; - - // counter to blink an LED - assign clk_led = clk_count[CLK_LED_COUNT_LENGTH-1]; - - always_ff @(posedge clk_gen or negedge rst_n) begin : clk_count_process - if (!rst_n) begin - clk_count <= '0; - end else begin - clk_count <= clk_count + 1; - end - end - - // clock output for debugging - assign clk_out = clk_gen; - - xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( - .clk_125MHz(clk_in), - .clk_out1_0(clk_gen) - ); - - // eXtension Interface - if_xif #() ext_if (); - - logic clk_i; - assign clk_i = clk_gen; - - core_v_mini_mcu #( - .COREV_PULP(COREV_PULP), - .FPU(FPU), - .ZFINX(ZFINX), - .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) - ) core_v_mini_mcu_i ( - - .rst_ni(rst_ngen), -% for pad in pad_list: -${pad.core_v_mini_mcu_bonding} -% endfor - .intr_vector_ext_i('0), - .xif_compressed_if(ext_if), - .xif_issue_if(ext_if), - .xif_commit_if(ext_if), - .xif_mem_if(ext_if), - .xif_mem_result_if(ext_if), - .xif_result_if(ext_if), - .ext_xbar_master_req_i('0), - .ext_xbar_master_resp_o(), - .ext_core_instr_req_o(), - .ext_core_instr_resp_i('0), - .ext_core_data_req_o(), - .ext_core_data_resp_i('0), - .ext_debug_master_req_o(), - .ext_debug_master_resp_i('0), - .ext_dma_read_ch0_req_o(), - .ext_dma_read_ch0_resp_i('0), - .ext_dma_write_ch0_req_o(), - .ext_dma_write_ch0_resp_i('0), - .ext_dma_addr_ch0_req_o(), - .ext_dma_addr_ch0_resp_i('0), - .ext_peripheral_slave_req_o(), - .ext_peripheral_slave_resp_i('0), - .external_subsystem_powergate_switch_o(), - .external_subsystem_powergate_switch_ack_i(), - .external_subsystem_powergate_iso_o(), - .external_subsystem_rst_no(), - .external_ram_banks_set_retentive_o(), - .exit_value_o(exit_value), - .pad_req_o(pad_req), - .pad_resp_i(pad_resp), - .cpu_subsystem_powergate_switch_o(cpu_subsystem_powergate_switch), - .cpu_subsystem_powergate_switch_ack_i(cpu_subsystem_powergate_switch_ack), - .peripheral_subsystem_powergate_switch_o(peripheral_subsystem_powergate_switch), - .peripheral_subsystem_powergate_switch_ack_i(peripheral_subsystem_powergate_switch_ack), - .memory_subsystem_banks_powergate_switch_o(memory_subsystem_banks_powergate_switch), - .memory_subsystem_banks_powergate_switch_ack_i(memory_subsystem_banks_powergate_switch_ack) - ); - - logic gpio_0_io; - logic gpio_1_io; - logic gpio_2_io; - logic gpio_3_io; - logic gpio_4_io; - logic gpio_5_io; - logic gpio_6_io; - logic gpio_7_io; - logic gpio_8_io; - logic gpio_9_io; - logic gpio_10_io; - logic gpio_11_io; - logic gpio_12_io; - logic gpio_13_io; - logic gpio_14_io; - logic gpio_15_io; - logic gpio_16_io; - logic gpio_17_io; - logic gpio_18_io; - logic gpio_19_io; - logic gpio_20_io; - logic gpio_21_io; - logic gpio_22_io; - - assign spi_flash_sck_o_sig = spi_flash_sck_out_x; - assign spi_flash_csb_o_sig = spi_flash_cs_0_out_x; - assign spi_sdi1_sig = spi_flash_sd_1_in_x; - assign spi_sdo0_sig = spi_flash_sd_0_out_x; - assign spi_sdo2_sig = spi_sd_2_out_x; - assign spi_sdo3_sig = spi_sd_3_out_x; - - assign spi2_csb_io[0] = spi2_cs_0_io; - assign spi2_csb_io[1] = spi2_cs_1_io; - - assign gpio_io[0] = gpio_0_io; - assign gpio_io[1] = gpio_1_io; - assign gpio_io[2] = gpio_2_io; - assign gpio_io[3] = gpio_3_io; - assign gpio_io[4] = gpio_4_io; - assign gpio_io[5] = gpio_5_io; - assign gpio_io[6] = gpio_6_io; - assign gpio_io[7] = gpio_7_io; - assign gpio_io[8] = gpio_8_io; - assign gpio_io[9] = gpio_9_io; - assign gpio_io[10] = gpio_10_io; - assign gpio_io[11] = gpio_11_io; - assign gpio_io[12] = gpio_12_io; - assign gpio_io[13] = gpio_13_io; - assign gpio_io[14] = gpio_14_io; - assign gpio_io[15] = gpio_15_io; - assign gpio_io[16] = gpio_16_io; - assign gpio_io[17] = gpio_17_io; - assign gpio_io[18] = gpio_18_io; - assign gpio_io[19] = gpio_19_io; - assign gpio_io[20] = gpio_20_io; - assign gpio_io[21] = gpio_21_io; - assign gpio_io[22] = gpio_22_io; - - processing_system_wrapper processing_system_wrapper_i ( - .DDR_addr(DDR_addr), - .DDR_ba(DDR_ba), - .DDR_cas_n(DDR_cas_n), - .DDR_ck_n(DDR_ck_n), - .DDR_ck_p(DDR_ck_p), - .DDR_cke(DDR_cke), - .DDR_cs_n(DDR_cs_n), - .DDR_dm(DDR_dm), - .DDR_dq(DDR_dq), - .DDR_dqs_n(DDR_dqs_n), - .DDR_dqs_p(DDR_dqs_p), - .DDR_odt(DDR_odt), - .DDR_ras_n(DDR_ras_n), - .DDR_reset_n(DDR_reset_n), - .DDR_we_n(DDR_we_n), - .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn), - .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp), - .FIXED_IO_mio(FIXED_IO_mio), - .FIXED_IO_ps_clk(FIXED_IO_ps_clk), - .FIXED_IO_ps_porb(FIXED_IO_ps_porb), - .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb), - .UART_rxd(uart_tx_out_x), - .UART_txd(uart_rx_in_x), - .gpio_jtag_tck_i(jtag_tck_in_x), - .gpio_jtag_tms_i(jtag_tms_in_x), - .gpio_jtag_trst_ni(jtag_trst_nin_x), - .gpio_jtag_tdi_i(jtag_tdi_in_x), - .gpio_jtag_tdo_o(jtag_tdo_out_x), - .AXI_HP_ACLK(AXI_HP_ACLK), - .AXI_HP_ARESETN(AXI_HP_ARESETN), - .AXI_HP_araddr(AXI_HP_araddr_sig), - .AXI_HP_arburst(AXI_HP_arburst_sig), - .AXI_HP_arcache(AXI_HP_arcache_sig), - .AXI_HP_arlen(AXI_HP_arlen_sig), - .AXI_HP_arlock(AXI_HP_arlock_sig), - .AXI_HP_arprot(AXI_HP_arprot_sig), - .AXI_HP_arqos(AXI_HP_arqos_sig), - .AXI_HP_arready(AXI_HP_arready_sig), - .AXI_HP_arsize(AXI_HP_arsize_sig), - .AXI_HP_arvalid(AXI_HP_arvalid_sig), - .AXI_HP_awaddr(AXI_HP_awaddr_sig), - .AXI_HP_awburst(AXI_HP_awburst_sig), - .AXI_HP_awcache(AXI_HP_awcache_sig), - .AXI_HP_awlen(AXI_HP_awlen_sig), - .AXI_HP_awlock(AXI_HP_awlock_sig), - .AXI_HP_awprot(AXI_HP_awprot_sig), - .AXI_HP_awqos(AXI_HP_awqos_sig), - .AXI_HP_awready(AXI_HP_awready_sig), - .AXI_HP_awsize(AXI_HP_awsize_sig), - .AXI_HP_awvalid(AXI_HP_awvalid_sig), - .AXI_HP_bready(AXI_HP_bready_sig), - .AXI_HP_bresp(AXI_HP_bresp_sig), - .AXI_HP_bvalid(AXI_HP_bvalid_sig), - .AXI_HP_rdata(AXI_HP_rdata_sig), - .AXI_HP_rlast(AXI_HP_rlast_sig), - .AXI_HP_rready(AXI_HP_rready_sig), - .AXI_HP_rresp(AXI_HP_rresp_sig), - .AXI_HP_rvalid(AXI_HP_rvalid_sig), - .AXI_HP_wdata(AXI_HP_wdata_sig), - .AXI_HP_wlast(AXI_HP_wlast_sig), - .AXI_HP_wready(AXI_HP_wready_sig), - .AXI_HP_wstrb(AXI_HP_wstrb_sig), - .AXI_HP_wvalid(AXI_HP_wvalid_sig), - .M_AXI_araddr(s00_axi_araddr_sig), - .M_AXI_arready(s00_axi_arready_sig), - .M_AXI_arvalid(s00_axi_arvalid_sig), - .M_AXI_awaddr(s00_axi_awaddr_sig), - .M_AXI_awready(s00_axi_awready_sig), - .M_AXI_awvalid(s00_axi_awvalid_sig), - .M_AXI_bready(s00_axi_bready_sig), - .M_AXI_bresp(s00_axi_bresp_sig), - .M_AXI_bvalid(s00_axi_bvalid_sig), - .M_AXI_rdata(s00_axi_rdata_sig), - .M_AXI_rready(s00_axi_rready_sig), - .M_AXI_rresp(s00_axi_rresp_sig), - .M_AXI_rvalid(s00_axi_rvalid_sig), - .M_AXI_wdata(s00_axi_wdata_sig), - .M_AXI_wready(s00_axi_wready_sig), - .M_AXI_wvalid(s00_axi_wvalid_sig), - .M_AXI_awprot(s00_axi_awprot_sig), - .M_AXI_arprot(s00_axi_arprot_sig), - .M_AXI_wstrb(s00_axi_wstrb_sig) - ); - - axi_address_hijacker #( - .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), - .C_S_AXI_DATA_WIDTH(AXI_DATA_WIDTH) - ) add_hij ( - .axi_master_awaddr_in(axi_master_awaddr_in_sig), - .axi_master_araddr_in(axi_master_araddr_in_sig), - - // output write and read address by adding fixed offset - .axi_master_araddr_out(AXI_HP_araddr_sig), - .axi_master_awaddr_out(AXI_HP_awaddr_sig), - - .S_AXI_ACLK(AXI_HP_ACLK), - .S_AXI_ARESETN(AXI_HP_ARESETN), - - .S_AXI_AWADDR (s00_axi_awaddr_sig), - .S_AXI_AWPROT (s00_axi_awprot_sig), - .S_AXI_AWVALID(s00_axi_awvalid_sig), - .S_AXI_AWREADY(s00_axi_awready_sig), - .S_AXI_WDATA (s00_axi_wdata_sig), - .S_AXI_WSTRB (s00_axi_wstrb_sig), - .S_AXI_WVALID (s00_axi_wvalid_sig), - .S_AXI_WREADY (s00_axi_wready_sig), - .S_AXI_BRESP (s00_axi_bresp_sig), - .S_AXI_BVALID (s00_axi_bvalid_sig), - .S_AXI_BREADY (s00_axi_bready_sig), - .S_AXI_ARADDR (s00_axi_araddr_sig), - .S_AXI_ARPROT (s00_axi_arprot_sig), - .S_AXI_ARVALID(s00_axi_arvalid_sig), - .S_AXI_ARREADY(s00_axi_arready_sig), - .S_AXI_RDATA (s00_axi_rdata_sig), - .S_AXI_RRESP (s00_axi_rresp_sig), - .S_AXI_RVALID (s00_axi_rvalid_sig), - .S_AXI_RREADY (s00_axi_rready_sig) - ); - - axi_spi_slave #( - .AXI_DATA_WIDTH(AXI_DATA_WIDTH) - ) fake_flash ( - .axi_aclk(AXI_HP_ACLK), - .axi_aresetn(AXI_HP_ARESETN), - - .test_mode('0), - - .axi_master_aw_valid(AXI_HP_awvalid_sig), - .axi_master_aw_id(AXI_HP_awid_sig), - .axi_master_aw_prot(AXI_HP_awprot_sig), - .axi_master_aw_qos(AXI_HP_awqos_sig), - .axi_master_aw_cache(AXI_HP_awcache_sig), - .axi_master_aw_lock(AXI_HP_awlock_sig), - .axi_master_aw_burst(AXI_HP_awburst_sig), - .axi_master_aw_size(AXI_HP_awsize_sig), - .axi_master_aw_len(AXI_HP_awlen_sig), - .axi_master_aw_addr(axi_master_awaddr_in_sig), - .axi_master_aw_ready(AXI_HP_awready_sig), - - .axi_master_w_valid(AXI_HP_wvalid_sig), - .axi_master_w_data (AXI_HP_wdata_sig), - .axi_master_w_strb (AXI_HP_wstrb_sig), - .axi_master_w_last (AXI_HP_wlast_sig), - .axi_master_w_ready(AXI_HP_wready_sig), - - .axi_master_b_valid(AXI_HP_bvalid_sig), - .axi_master_b_id(AXI_HP_bid_sig), - .axi_master_b_resp(AXI_HP_bresp_sig), - .axi_master_b_ready(AXI_HP_bready_sig), - - .axi_master_ar_valid(AXI_HP_arvalid_sig), - .axi_master_ar_id(AXI_HP_arid_sig), - .axi_master_ar_prot(AXI_HP_arprot_sig), - .axi_master_ar_qos(AXI_HP_arqos_sig), - .axi_master_ar_cache(AXI_HP_arcache_sig), - .axi_master_ar_lock(AXI_HP_arlock_sig), - .axi_master_ar_burst(AXI_HP_arburst_sig), - .axi_master_ar_size(AXI_HP_arsize_sig), - .axi_master_ar_len(AXI_HP_arlen_sig), - .axi_master_ar_addr(axi_master_araddr_in_sig), - .axi_master_ar_ready(AXI_HP_arready_sig), - - .axi_master_r_valid(AXI_HP_rvalid_sig), - .axi_master_r_id(AXI_HP_rid_sig), - .axi_master_r_data(AXI_HP_rdata_sig), - .axi_master_r_resp(AXI_HP_rresp_sig), - .axi_master_r_last(AXI_HP_rlast_sig), - .axi_master_r_ready(AXI_HP_rready_sig), - - .spi_sclk(spi_flash_sck_o_sig), - .spi_cs (spi_flash_csb_o_sig), - .spi_sdo1(spi_sdi1_sig), - .spi_sdi0(spi_sdo0_sig), - .spi_sdi2(spi_sdo2_sig), - .spi_sdi3(spi_sdo3_sig) - ); - - // TESTING PURPOSES -> THEY WILL BE INPUT TO PS AND READ BY SYSTEM ILA - assign spi_test_clk_sig = spi_flash_sck_o_sig; - assign spi_test_cs_sig = spi_flash_csb_o_sig; - assign spi_test_data_sig = {spi_sdo0_sig, spi_sdi1_sig, spi_sdo2_sig, spi_sdo3_sig}; - - pad_ring pad_ring_i ( -% for pad in total_pad_list: -${pad.pad_ring_bonding_bonding} -% endfor - .pad_attributes_i(pad_attributes) - ); - -${pad_constant_driver_assign} - -${pad_mux_process} - - pad_control #( - .reg_req_t(reg_pkg::reg_req_t), - .reg_rsp_t(reg_pkg::reg_rsp_t), - .NUM_PAD (core_v_mini_mcu_pkg::NUM_PAD) - ) pad_control_i ( - .clk_i(clk_in_x), - .rst_ni(rst_ngen), - .reg_req_i(pad_req), - .reg_rsp_o(pad_resp), - .pad_attributes_o(pad_attributes), - .pad_muxes_o(pad_muxes) - ); - - rstgen rstgen_i ( - .clk_i(clk_in_x), - .rst_ni(rst_n), - .test_mode_i(1'b0), - .rst_no(rst_ngen), - .init_no() - ); - - assign exit_value_o = exit_value[0]; -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl b/hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl deleted file mode 100644 index a4628c5b..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2022 EPFL -# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# Define design macros - -# Select board -set_property board_part tul.com.tw:pynq-z2:part0:1.0 [current_project] - -# Create block design -create_bd_design "processing_system" - -# Add Zynq Processing System -create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 -apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {make_external "FIXED_IO, DDR" apply_board_preset "1" Master "Disable" Slave "Disable" } [get_bd_cells processing_system7_0] -set_property -dict [list CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {20} CONFIG.PCW_USE_S_AXI_HP0 {1} CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {0} CONFIG.PCW_SD0_PERIPHERAL_ENABLE {0} CONFIG.PCW_UART0_PERIPHERAL_ENABLE {0} CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} CONFIG.PCW_UART1_UART1_IO {EMIO} CONFIG.PCW_USB0_PERIPHERAL_ENABLE {0} CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {0} CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} CONFIG.PCW_GPIO_EMIO_GPIO_IO {5}] [get_bd_cells processing_system7_0] - -# Add AXI Interconnect -create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_interconnect_0 -set_property -dict [list CONFIG.NUM_SI {2} CONFIG.NUM_MI {2}] [get_bd_cells axi_interconnect_0] - -# Add Constant -create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 -set_property -dict [list CONFIG.CONST_WIDTH {2} CONFIG.CONST_VAL {0b11}] [get_bd_cells xlconstant_0] - -# Add Concatenation -create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 -set_property -dict [list CONFIG.IN0_WIDTH.VALUE_SRC USER CONFIG.IN1_WIDTH.VALUE_SRC USER CONFIG.IN2_WIDTH.VALUE_SRC USER] [get_bd_cells xlconcat_0] -set_property -dict [list CONFIG.NUM_PORTS {3} CONFIG.IN0_WIDTH {2} CONFIG.IN2_WIDTH {2}] [get_bd_cells xlconcat_0] - -# Add Slices -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0 -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_1 -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_2 -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_3 -set_property -dict [list CONFIG.DIN_TO {3} CONFIG.DIN_FROM {3} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_0] -set_property -dict [list CONFIG.DIN_TO {4} CONFIG.DIN_FROM {4} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_1] -set_property -dict [list CONFIG.DIN_TO {1} CONFIG.DIN_FROM {1} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_2] -set_property -dict [list CONFIG.DIN_TO {0} CONFIG.DIN_FROM {0} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_3] - -# Create port AXI_HP -make_bd_intf_pins_external [get_bd_intf_pins axi_interconnect_0/S00_AXI] -set_property name AXI_HP [get_bd_intf_ports S00_AXI_0] -set_property -dict [list CONFIG.FREQ_HZ {20000000}] [get_bd_intf_ports AXI_HP] - -# Create port M_AXI -make_bd_intf_pins_external [get_bd_intf_pins axi_interconnect_0/M01_AXI] -set_property name M_AXI [get_bd_intf_ports M01_AXI_0] -set_property -dict [list CONFIG.FREQ_HZ {20000000}] [get_bd_intf_ports M_AXI] - -# Connect AXI Interconnect and Zynq Processing System -connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect_0/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP0] -connect_bd_intf_net [get_bd_intf_pins processing_system7_0/M_AXI_GP0] -boundary_type upper [get_bd_intf_pins axi_interconnect_0/S01_AXI] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/M00_ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/M01_ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/S00_ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/S01_ACLK] - -# Create port AXI_HP_ACLK -create_bd_port -dir O -type clk AXI_HP_ACLK - -# Create port AXI_HP_ARESETN -create_bd_port -dir O -type rst AXI_HP_ARESETN - -# Connect AXI_HP_ACLK and AXI_HP_ARESETN -connect_bd_net [get_bd_ports AXI_HP_ACLK] [get_bd_pins processing_system7_0/FCLK_CLK0] -connect_bd_net [get_bd_ports AXI_HP_ARESETN] [get_bd_pins rst_ps7_0_20M/peripheral_aresetn] - -# Create port gpio_jtag_tdo_o -make_bd_pins_external [get_bd_pins xlconcat_0/In1] -set_property name gpio_jtag_tdo_o [get_bd_ports In1_0] - -# Connect Constant and Concatenation -connect_bd_net [get_bd_pins xlconstant_0/dout] [get_bd_pins xlconcat_0/In0] -connect_bd_net [get_bd_pins xlconcat_0/In2] [get_bd_pins xlconstant_0/dout] -connect_bd_net [get_bd_pins xlconcat_0/dout] [get_bd_pins processing_system7_0/GPIO_I] - -# Create port gpio_jtag_tdi_i -make_bd_pins_external [get_bd_pins xlslice_0/Dout] -set_property name gpio_jtag_tdi_i [get_bd_ports Dout_0] - -# Create port gpio_jtag_tck_i -make_bd_pins_external [get_bd_pins xlslice_1/Dout] -set_property name gpio_jtag_tck_i [get_bd_ports Dout_0] - -# Create port gpio_jtag_tms_i -make_bd_pins_external [get_bd_pins xlslice_2/Dout] -set_property name gpio_jtag_tms_i [get_bd_ports Dout_0] - -# Create port gpio_jtag_trst_ni -make_bd_pins_external [get_bd_pins xlslice_3/Dout] -set_property name gpio_jtag_trst_ni [get_bd_ports Dout_0] - -# Connect Slices -connect_bd_net [get_bd_pins xlslice_0/Din] [get_bd_pins processing_system7_0/GPIO_O] -connect_bd_net [get_bd_pins xlslice_1/Din] [get_bd_pins processing_system7_0/GPIO_O] -connect_bd_net [get_bd_pins xlslice_2/Din] [get_bd_pins processing_system7_0/GPIO_O] -connect_bd_net [get_bd_pins xlslice_3/Din] [get_bd_pins processing_system7_0/GPIO_O] - -# Create port UART -make_bd_intf_pins_external [get_bd_intf_pins processing_system7_0/UART_1] -set_property name UART [get_bd_intf_ports UART_1_0] - -# Assign addresses -assign_bd_address - -# Validate design -validate_bd_design - -# Save design -save_bd_design - -# Close design -close_bd_design [get_bd_designs processing_system] - -# Make wrapper -set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse processing_system.bd ] -top ] -add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson b/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson index 4bc1e1df..f1d435df 100644 --- a/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson +++ b/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson @@ -27,6 +27,8 @@ lenght: whatisleft, #keyword used to calculate the size as: ram.length - code.lenght } }, + stack_size: 0x800, + heap_size: 0x800, } debug: { diff --git a/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson b/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson index 98440522..ed74849a 100644 --- a/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson +++ b/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson @@ -27,6 +27,8 @@ lenght: whatisleft, #keyword used to calculate the size as: ram.length - code.lenght } }, + stack_size: 0x800, + heap_size: 0x800, } debug: { diff --git a/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt b/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt index d857d792..9639d6cf 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt +++ b/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt @@ -63,9 +63,9 @@ FILE(GLOB_RECURSE new_list FOLLOW_SYMLINKS ${SOURCE_PATH}*.h) SET(dir_list_str "") FOREACH(file_path ${new_list}) SET(add 0) # This variable is set to 1 if the file_pth needs to be added to the list - if(${file_path} MATCHES "/device/") - if(${file_path} MATCHES "/target/") # Add it if its not in target, or if its in target/${TARGET} - if(${file_path} MATCHES ${TARGET}) + if(${file_path} MATCHES "${ROOT_PROJECT}device/") + if(${file_path} MATCHES "${ROOT_PROJECT}device/target/") # Add it if its not in target, or if its in target/${TARGET} + if(${file_path} MATCHES "${ROOT_PROJECT}device/target/${TARGET}") SET(add 1) endif() else() @@ -73,9 +73,9 @@ FOREACH(file_path ${new_list}) endif() elseif(${file_path} MATCHES ${PROJECT}) SET(add 1) - elseif( ( ${file_path} MATCHES "/freertos/" ) AND ( ${PROJECT} MATCHES "freertos" ) ) + elseif( ( ${file_path} MATCHES "${ROOT_PROJECT}freertos/" ) AND ( ${PROJECT} MATCHES "freertos" ) ) SET(add 1) - elseif( ${file_path} MATCHES "/external/" ) + elseif( ${file_path} MATCHES "${ROOT_PROJECT}external/" ) SET(add 1) endif() @@ -124,9 +124,9 @@ SET( c_dir_list "" ) SET( app_found 0 ) FOREACH(file_path IN LISTS new_list) SET(add 0) # This variable is set to 1 if the file_pth needs to be added to the list - if(${file_path} MATCHES "/device/") + if(${file_path} MATCHES "${ROOT_PROJECT}device/") SET(add 1) - elseif( ${file_path} MATCHES "/external/" ) + elseif( ${file_path} MATCHES "${ROOT_PROJECT}external/" ) SET(add 1) elseif( ( ${file_path} MATCHES "/${PROJECT}/" ) AND ( NOT ${file_path} MATCHES ${MAINFILE} ) ) SET(add 1) @@ -153,7 +153,7 @@ if( app_found EQUAL 0 ) SET(c_dir_list "") FOREACH(file_path IN LISTS new_list) SET(add 0) # This variable is set to 1 if the file_pth needs to be added to the list - if(${file_path} MATCHES "/device/") + if(${file_path} MATCHES "${ROOT_PROJECT}device/") SET(add 1) elseif( ( ${file_path} MATCHES "/${PROJECT}/" ) AND ( NOT ${file_path} MATCHES ${MAINFILE} ) ) SET(add 1) @@ -303,14 +303,27 @@ endif() # Set CMAKE flags # specify the C standard -set(COMPILER_LINKER_FLAGS "\ - -march=${CMAKE_SYSTEM_PROCESSOR} \ - -w -Os -g -nostdlib \ - -DHOST_BUILD \ - -D${CRT_TYPE} \ - -D${CRTO} \ - -DportasmHANDLE_INTERRUPT=vSystemIrqHandler\ -") +if(NOT ${PROJECT} MATCHES "coremark") + set(COMPILER_LINKER_FLAGS "\ + -march=${CMAKE_SYSTEM_PROCESSOR} \ + -w -O2 -g -nostdlib \ + -ffunction-sections \ + -DHOST_BUILD \ + -D${CRT_TYPE} \ + -D${CRTO} \ + -DportasmHANDLE_INTERRUPT=vSystemIrqHandler\ + ") +else() + set(COMPILER_LINKER_FLAGS "\ + -march=${CMAKE_SYSTEM_PROCESSOR} \ + -w -O3 -g -nostdlib -falign-functions=16 -funroll-all-loops -falign-jumps=4 -finline-functions -Wall -static -pedantic -DPERFORMANCE_RUN=1 -DITERATIONS=1 -DHAS_STDIO=1 -DHAS_PRINTF=1 \ + -ffunction-sections \ + -DHOST_BUILD \ + -D${CRT_TYPE} \ + -D${CRTO} \ + -DportasmHANDLE_INTERRUPT=vSystemIrqHandler\ + ") +endif() set(CMAKE_C_FLAGS ${COMPILER_LINKER_FLAGS}) if (${COMPILER} MATCHES "clang") @@ -401,7 +414,7 @@ endif() # Post processing command to create a disassembly file add_custom_command(TARGET ${MAINFILE}.elf POST_BUILD - COMMAND ${CMAKE_OBJDUMP} -S ${MAINFILE}.elf > ${MAINFILE}.disasm + COMMAND ${CMAKE_OBJDUMP} -S ${MAINFILE}.elf > ${MAINFILE}.S COMMENT "Invoking: Disassemble") # Post processing command to create a hex file @@ -434,4 +447,4 @@ endforeach() SET(DCMAKE_EXPORT_COMPILE_COMMANDS ON) -#message( FATAL_ERROR "You can not do this at all, CMake will exit." ) \ No newline at end of file +#message( FATAL_ERROR "You can not do this at all, CMake will exit." ) diff --git a/hw/vendor/esl_epfl_x_heep/sw/Makefile b/hw/vendor/esl_epfl_x_heep/sw/Makefile index 3582fb25..a36f5ead 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/Makefile +++ b/hw/vendor/esl_epfl_x_heep/sw/Makefile @@ -25,7 +25,7 @@ PROJECT ?= hello_world # Linker options are 'on_chip' (default),'flash_load','flash_exec' LINKER ?= on_chip -# Target options are 'sim' (default) and 'pynq-z2' +# Target options are 'sim' (default), 'pynq-z2', and 'nexys-a7-100t' TARGET ?= sim # Compiler options are 'gcc' (default) and 'clang' @@ -38,7 +38,7 @@ COMPILER_PREFIX ?= riscv32-unknown- ARCH ?= rv32imc # Path relative from the location of sw/Makefile from which to fetch source files. The directory of that file is the default value. -SOURCE ?= "." +SOURCE ?= $(".") # riscv toolchain install path RISCV ?= ~/.riscv @@ -56,7 +56,7 @@ source_path := $(realpath $(mkfile_path)/$(SOURCE)) $(info $$You are fetching sources from $(source_path) ) -SOURCE_PATH = $(source_path)/ +SOURCE_PATH = $(source_path)/ ROOT_PROJECT = $(mkfile_path)/ INC_FOLDERS = $(mkfile_path)/device/target/$(TARGET)/ LINK_FOLDER = $(mkfile_path)/linker @@ -70,6 +70,9 @@ else CMAKE=cmake3 endif +# Export variables to sub-makefiles +export + # Let's CMake! include cmake/targets.mak diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c new file mode 100644 index 00000000..64527aa5 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c @@ -0,0 +1,612 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* +Topic: Description + Benchmark using a linked list. + + Linked list is a common data structure used in many applications. + + For our purposes, this will excercise the memory units of the processor. + In particular, usage of the list pointers to find and alter data. + + We are not using Malloc since some platforms do not support this +library. + + Instead, the memory block being passed in is used to create a list, + and the benchmark takes care not to add more items then can be + accomodated by the memory block. The porting layer will make sure + that we have a valid memory block. + + All operations are done in place, without using any extra memory. + + The list itself contains list pointers and pointers to data items. + Data items contain the following: + + idx - An index that captures the initial order of the list. + data - Variable data initialized based on the input parameters. The 16b +are divided as follows: o Upper 8b are backup of original data. o Bit 7 +indicates if the lower 7 bits are to be used as is or calculated. o Bits 0-2 +indicate type of operation to perform to get a 7b value. o Bits 3-6 provide +input for the operation. + +*/ + +/* local functions */ + +list_head *core_list_find(list_head *list, list_data *info); +list_head *core_list_reverse(list_head *list); +list_head *core_list_remove(list_head *item); +list_head *core_list_undo_remove(list_head *item_removed, + list_head *item_modified); +list_head *core_list_insert_new(list_head * insert_point, + list_data * info, + list_head **memblock, + list_data **datablock, + list_head * memblock_end, + list_data * datablock_end); +typedef ee_s32 (*list_cmp)(list_data *a, list_data *b, core_results *res); +list_head *core_list_mergesort(list_head * list, + list_cmp cmp, + core_results *res); + +ee_s16 +calc_func(ee_s16 *pdata, core_results *res) +{ + ee_s16 data = *pdata; + ee_s16 retval; + ee_u8 optype + = (data >> 7) + & 1; /* bit 7 indicates if the function result has been cached */ + if (optype) /* if cached, use cache */ + return (data & 0x007f); + else + { /* otherwise calculate and cache the result */ + ee_s16 flag = data & 0x7; /* bits 0-2 is type of function to perform */ + ee_s16 dtype + = ((data >> 3) + & 0xf); /* bits 3-6 is specific data for the operation */ + dtype |= dtype << 4; /* replicate the lower 4 bits to get an 8b value */ + switch (flag) + { + case 0: + if (dtype < 0x22) /* set min period for bit corruption */ + dtype = 0x22; + retval = core_bench_state(res->size, + res->memblock[3], + res->seed1, + res->seed2, + dtype, + res->crc); + if (res->crcstate == 0) + res->crcstate = retval; + break; + case 1: + retval = core_bench_matrix(&(res->mat), dtype, res->crc); + if (res->crcmatrix == 0) + res->crcmatrix = retval; + break; + default: + retval = data; + break; + } + res->crc = crcu16(retval, res->crc); + retval &= 0x007f; + *pdata = (data & 0xff00) | 0x0080 | retval; /* cache the result */ + return retval; + } +} +/* Function: cmp_complex + Compare the data item in a list cell. + + Can be used by mergesort. +*/ +ee_s32 +cmp_complex(list_data *a, list_data *b, core_results *res) +{ + ee_s16 val1 = calc_func(&(a->data16), res); + ee_s16 val2 = calc_func(&(b->data16), res); + return val1 - val2; +} + +/* Function: cmp_idx + Compare the idx item in a list cell, and regen the data. + + Can be used by mergesort. +*/ +ee_s32 +cmp_idx(list_data *a, list_data *b, core_results *res) +{ + if (res == NULL) + { + a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16 >> 8)); + b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16 >> 8)); + } + return a->idx - b->idx; +} + +void +copy_info(list_data *to, list_data *from) +{ + to->data16 = from->data16; + to->idx = from->idx; +} + +/* Benchmark for linked list: + - Try to find multiple data items. + - List sort + - Operate on data from list (crc) + - Single remove/reinsert + * At the end of this function, the list is back to original state +*/ +ee_u16 +core_bench_list(core_results *res, ee_s16 finder_idx) +{ + ee_u16 retval = 0; + ee_u16 found = 0, missed = 0; + list_head *list = res->list; + ee_s16 find_num = res->seed3; + list_head *this_find; + list_head *finder, *remover; + list_data info; + ee_s16 i; + + info.idx = finder_idx; + /* find values in the list, and change the list each time + * (reverse and cache if value found) */ + for (i = 0; i < find_num; i++) + { + info.data16 = (i & 0xff); + this_find = core_list_find(list, &info); + list = core_list_reverse(list); + if (this_find == NULL) + { + missed++; + retval += (list->next->info->data16 >> 8) & 1; + } + else + { + found++; + if (this_find->info->data16 & 0x1) /* use found value */ + retval += (this_find->info->data16 >> 9) & 1; + /* and cache next item at the head of the list (if any) */ + if (this_find->next != NULL) + { + finder = this_find->next; + this_find->next = finder->next; + finder->next = list->next; + list->next = finder; + } + } + if (info.idx >= 0) + info.idx++; +#if CORE_DEBUG + ee_printf("List find %d: [%d,%d,%d]\n", i, retval, missed, found); +#endif + } + retval += found * 4 - missed; + /* sort the list by data content and remove one item*/ + if (finder_idx > 0) + list = core_list_mergesort(list, cmp_complex, res); + remover = core_list_remove(list->next); + /* CRC data content of list from location of index N forward, and then undo + * remove */ + finder = core_list_find(list, &info); + if (!finder) + finder = list->next; + while (finder) + { + retval = crc16(list->info->data16, retval); + finder = finder->next; + } +#if CORE_DEBUG + ee_printf("List sort 1: %04x\n", retval); +#endif + remover = core_list_undo_remove(remover, list->next); + /* sort the list by index, in effect returning the list to original state */ + list = core_list_mergesort(list, cmp_idx, NULL); + /* CRC data content of list */ + finder = list->next; + while (finder) + { + retval = crc16(list->info->data16, retval); + finder = finder->next; + } +#if CORE_DEBUG + ee_printf("List sort 2: %04x\n", retval); +#endif + return retval; +} +/* Function: core_list_init + Initialize list with data. + + Parameters: + blksize - Size of memory to be initialized. + memblock - Pointer to memory block. + seed - Actual values chosen depend on the seed parameter. + The seed parameter MUST be supplied from a source that cannot be + determined at compile time + + Returns: + Pointer to the head of the list. + +*/ +list_head * +core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) +{ + /* calculated pointers for the list */ + ee_u32 per_item = 16 + sizeof(struct list_data_s); + ee_u32 size = (blksize / per_item) + - 2; /* to accomodate systems with 64b pointers, and make sure + same code is executed, set max list elements */ + list_head *memblock_end = memblock + size; + list_data *datablock = (list_data *)(memblock_end); + list_data *datablock_end = datablock + size; + /* some useful variables */ + ee_u32 i; + list_head *finder, *list = memblock; + list_data info; + + /* create a fake items for the list head and tail */ + list->next = NULL; + list->info = datablock; + list->info->idx = 0x0000; + list->info->data16 = (ee_s16)0x8080; + memblock++; + datablock++; + info.idx = 0x7fff; + info.data16 = (ee_s16)0xffff; + core_list_insert_new( + list, &info, &memblock, &datablock, memblock_end, datablock_end); + + /* then insert size items */ + for (i = 0; i < size; i++) + { + ee_u16 datpat = ((ee_u16)(seed ^ i) & 0xf); + ee_u16 dat + = (datpat << 3) | (i & 0x7); /* alternate between algorithms */ + info.data16 = (dat << 8) | dat; /* fill the data with actual data and + upper bits with rebuild value */ + core_list_insert_new( + list, &info, &memblock, &datablock, memblock_end, datablock_end); + } + /* and now index the list so we know initial seed order of the list */ + finder = list->next; + i = 1; + while (finder->next != NULL) + { + if (i < size / 5) /* first 20% of the list in order */ + finder->info->idx = i++; + else + { + ee_u16 pat = (ee_u16)(i++ ^ seed); /* get a pseudo random number */ + finder->info->idx = 0x3fff + & (((i & 0x07) << 8) + | pat); /* make sure the mixed items end up + after the ones in sequence */ + } + finder = finder->next; + } + list = core_list_mergesort(list, cmp_idx, NULL); +#if CORE_DEBUG + ee_printf("Initialized list:\n"); + finder = list; + while (finder) + { + ee_printf( + "[%04x,%04x]", finder->info->idx, (ee_u16)finder->info->data16); + finder = finder->next; + } + ee_printf("\n"); +#endif + return list; +} + +/* Function: core_list_insert + Insert an item to the list + + Parameters: + insert_point - where to insert the item. + info - data for the cell. + memblock - pointer for the list header + datablock - pointer for the list data + memblock_end - end of region for list headers + datablock_end - end of region for list data + + Returns: + Pointer to new item. +*/ +list_head * +core_list_insert_new(list_head * insert_point, + list_data * info, + list_head **memblock, + list_data **datablock, + list_head * memblock_end, + list_data * datablock_end) +{ + list_head *newitem; + + if ((*memblock + 1) >= memblock_end) + return NULL; + if ((*datablock + 1) >= datablock_end) + return NULL; + + newitem = *memblock; + (*memblock)++; + newitem->next = insert_point->next; + insert_point->next = newitem; + + newitem->info = *datablock; + (*datablock)++; + copy_info(newitem->info, info); + + return newitem; +} + +/* Function: core_list_remove + Remove an item from the list. + + Operation: + For a singly linked list, remove by copying the data from the next item + over to the current cell, and unlinking the next item. + + Note: + since there is always a fake item at the end of the list, no need to + check for NULL. + + Returns: + Removed item. +*/ +list_head * +core_list_remove(list_head *item) +{ + list_data *tmp; + list_head *ret = item->next; + /* swap data pointers */ + tmp = item->info; + item->info = ret->info; + ret->info = tmp; + /* and eliminate item */ + item->next = item->next->next; + ret->next = NULL; + return ret; +} + +/* Function: core_list_undo_remove + Undo a remove operation. + + Operation: + Since we want each iteration of the benchmark to be exactly the same, + we need to be able to undo a remove. + Link the removed item back into the list, and switch the info items. + + Parameters: + item_removed - Return value from the + item_modified - List item that was modified during + + Returns: + The item that was linked back to the list. + +*/ +list_head * +core_list_undo_remove(list_head *item_removed, list_head *item_modified) +{ + list_data *tmp; + /* swap data pointers */ + tmp = item_removed->info; + item_removed->info = item_modified->info; + item_modified->info = tmp; + /* and insert item */ + item_removed->next = item_modified->next; + item_modified->next = item_removed; + return item_removed; +} + +/* Function: core_list_find + Find an item in the list + + Operation: + Find an item by idx (if not 0) or specific data value + + Parameters: + list - list head + info - idx or data to find + + Returns: + Found item, or NULL if not found. +*/ +list_head * +core_list_find(list_head *list, list_data *info) +{ + if (info->idx >= 0) + { + while (list && (list->info->idx != info->idx)) + list = list->next; + return list; + } + else + { + while (list && ((list->info->data16 & 0xff) != info->data16)) + list = list->next; + return list; + } +} +/* Function: core_list_reverse + Reverse a list + + Operation: + Rearrange the pointers so the list is reversed. + + Parameters: + list - list head + info - idx or data to find + + Returns: + Found item, or NULL if not found. +*/ + +list_head * +core_list_reverse(list_head *list) +{ + list_head *next = NULL, *tmp; + while (list) + { + tmp = list->next; + list->next = next; + next = list; + list = tmp; + } + return next; +} +/* Function: core_list_mergesort + Sort the list in place without recursion. + + Description: + Use mergesort, as for linked list this is a realistic solution. + Also, since this is aimed at embedded, care was taken to use iterative + rather then recursive algorithm. The sort can either return the list to + original order (by idx) , or use the data item to invoke other other + algorithms and change the order of the list. + + Parameters: + list - list to be sorted. + cmp - cmp function to use + + Returns: + New head of the list. + + Note: + We have a special header for the list that will always be first, + but the algorithm could theoretically modify where the list starts. + + */ +list_head * +core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) +{ + list_head *p, *q, *e, *tail; + ee_s32 insize, nmerges, psize, qsize, i; + + insize = 1; + + while (1) + { + p = list; + list = NULL; + tail = NULL; + + nmerges = 0; /* count number of merges we do in this pass */ + + while (p) + { + nmerges++; /* there exists a merge to be done */ + /* step `insize' places along from p */ + q = p; + psize = 0; + for (i = 0; i < insize; i++) + { + psize++; + q = q->next; + if (!q) + break; + } + + /* if q hasn't fallen off end, we have two lists to merge */ + qsize = insize; + + /* now we have two lists; merge them */ + while (psize > 0 || (qsize > 0 && q)) + { + + /* decide whether next element of merge comes from p or q */ + if (psize == 0) + { + /* p is empty; e must come from q. */ + e = q; + q = q->next; + qsize--; + } + else if (qsize == 0 || !q) + { + /* q is empty; e must come from p. */ + e = p; + p = p->next; + psize--; + } + else if (cmp(p->info, q->info, res) <= 0) + { + /* First element of p is lower (or same); e must come from + * p. */ + e = p; + p = p->next; + psize--; + } + else + { + /* First element of q is lower; e must come from q. */ + e = q; + q = q->next; + qsize--; + } + + /* add the next element to the merged list */ + if (tail) + { + tail->next = e; + } + else + { + list = e; + } + tail = e; + } + + /* now p has stepped `insize' places along, and q has too */ + p = q; + } + + tail->next = NULL; + + /* If we have done only one merge, we're finished. */ + if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ + return list; + + /* Otherwise repeat, merging lists twice the size */ + insize *= 2; + } +#if COMPILER_REQUIRES_SORT_RETURN + return list; +#endif +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c new file mode 100644 index 00000000..9c7901c3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c @@ -0,0 +1,376 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* +Topic: Description + Matrix manipulation benchmark + + This very simple algorithm forms the basis of many more complex +algorithms. + + The tight inner loop is the focus of many optimizations (compiler as +well as hardware based) and is thus relevant for embedded processing. + + The total available data space will be divided to 3 parts: + NxN Matrix A - initialized with small values (upper 3/4 of the bits all +zero). NxN Matrix B - initialized with medium values (upper half of the bits all +zero). NxN Matrix C - used for the result. + + The actual values for A and B must be derived based on input that is not +available at compile time. +*/ +ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val); +ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval); +void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val); +void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); +void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); +void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); +void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val); + +#define matrix_test_next(x) (x + 1) +#define matrix_clip(x, y) ((y) ? (x)&0x0ff : (x)&0x0ffff) +#define matrix_big(x) (0xf000 | (x)) +#define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to)))) + +#if CORE_DEBUG +void +printmat(MATDAT *A, ee_u32 N, char *name) +{ + ee_u32 i, j; + ee_printf("Matrix %s [%dx%d]:\n", name, N, N); + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + if (j != 0) + ee_printf(","); + ee_printf("%d", A[i * N + j]); + } + ee_printf("\n"); + } +} +void +printmatC(MATRES *C, ee_u32 N, char *name) +{ + ee_u32 i, j; + ee_printf("Matrix %s [%dx%d]:\n", name, N, N); + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + if (j != 0) + ee_printf(","); + ee_printf("%d", C[i * N + j]); + } + ee_printf("\n"); + } +} +#endif +/* Function: core_bench_matrix + Benchmark function + + Iterate N times, + changing the matrix values slightly by a constant amount each time. +*/ +ee_u16 +core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) +{ + ee_u32 N = p->N; + MATRES *C = p->C; + MATDAT *A = p->A; + MATDAT *B = p->B; + MATDAT val = (MATDAT)seed; + + crc = crc16(matrix_test(N, C, A, B, val), crc); + + return crc; +} + +/* Function: matrix_test + Perform matrix manipulation. + + Parameters: + N - Dimensions of the matrix. + C - memory for result matrix. + A - input matrix + B - operator matrix (not changed during operations) + + Returns: + A CRC value that captures all results calculated in the function. + In particular, crc of the value calculated on the result matrix + after each step by . + + Operation: + + 1 - Add a constant value to all elements of a matrix. + 2 - Multiply a matrix by a constant. + 3 - Multiply a matrix by a vector. + 4 - Multiply a matrix by a matrix. + 5 - Add a constant value to all elements of a matrix. + + After the last step, matrix A is back to original contents. +*/ +ee_s16 +matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) +{ + ee_u16 crc = 0; + MATDAT clipval = matrix_big(val); + + matrix_add_const(N, A, val); /* make sure data changes */ +#if CORE_DEBUG + printmat(A, N, "matrix_add_const"); +#endif + matrix_mul_const(N, C, A, val); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_const"); +#endif + matrix_mul_vect(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_vect"); +#endif + matrix_mul_matrix(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_matrix"); +#endif + matrix_mul_matrix_bitextract(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_matrix_bitextract"); +#endif + + matrix_add_const(N, A, -val); /* return matrix to initial value */ + return crc; +} + +/* Function : matrix_init + Initialize the memory block for matrix benchmarking. + + Parameters: + blksize - Size of memory to be initialized. + memblk - Pointer to memory block. + seed - Actual values chosen depend on the seed parameter. + p - pointers to containing initialized matrixes. + + Returns: + Matrix dimensions. + + Note: + The seed parameter MUST be supplied from a source that cannot be + determined at compile time +*/ +ee_u32 +core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) +{ + ee_u32 N = 0; + MATDAT *A; + MATDAT *B; + ee_s32 order = 1; + MATDAT val; + ee_u32 i = 0, j = 0; + if (seed == 0) + seed = 1; + while (j < blksize) + { + i++; + j = i * i * 2 * 4; + } + N = i - 1; + A = (MATDAT *)align_mem(memblk); + B = A + N * N; + + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + seed = ((order * seed) % 65536); + val = (seed + order); + val = matrix_clip(val, 0); + B[i * N + j] = val; + val = (val + order); + val = matrix_clip(val, 1); + A[i * N + j] = val; + order++; + } + } + + p->A = A; + p->B = B; + p->C = (MATRES *)align_mem(B + N * N); + p->N = N; +#if CORE_DEBUG + printmat(A, N, "A"); + printmat(B, N, "B"); +#endif + return N; +} + +/* Function: matrix_sum + Calculate a function that depends on the values of elements in the + matrix. + + For each element, accumulate into a temporary variable. + + As long as this value is under the parameter clipval, + add 1 to the result if the element is bigger then the previous. + + Otherwise, reset the accumulator and add 10 to the result. +*/ +ee_s16 +matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) +{ + MATRES tmp = 0, prev = 0, cur = 0; + ee_s16 ret = 0; + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + cur = C[i * N + j]; + tmp += cur; + if (tmp > clipval) + { + ret += 10; + tmp = 0; + } + else + { + ret += (cur > prev) ? 1 : 0; + } + prev = cur; + } + } + return ret; +} + +/* Function: matrix_mul_const + Multiply a matrix by a constant. + This could be used as a scaler for instance. +*/ +void +matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) +{ + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val; + } + } +} + +/* Function: matrix_add_const + Add a constant value to all elements of a matrix. +*/ +void +matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val) +{ + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + A[i * N + j] += val; + } + } +} + +/* Function: matrix_mul_vect + Multiply a matrix by a vector. + This is common in many simple filters (e.g. fir where a vector of + coefficients is applied to the matrix.) +*/ +void +matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) +{ + ee_u32 i, j; + for (i = 0; i < N; i++) + { + C[i] = 0; + for (j = 0; j < N; j++) + { + C[i] += (MATRES)A[i * N + j] * (MATRES)B[j]; + } + } +} + +/* Function: matrix_mul_matrix + Multiply a matrix by a matrix. + Basic code is used in many algorithms, mostly with minor changes such as + scaling. +*/ +void +matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) +{ + ee_u32 i, j, k; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + C[i * N + j] = 0; + for (k = 0; k < N; k++) + { + C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j]; + } + } + } +} + +/* Function: matrix_mul_matrix_bitextract + Multiply a matrix by a matrix, and extract some bits from the result. + Basic code is used in many algorithms, mostly with minor changes such as + scaling. +*/ +void +matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) +{ + ee_u32 i, j, k; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + C[i * N + j] = 0; + for (k = 0; k < N; k++) + { + MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j]; + C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7); + } + } + } +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c new file mode 100644 index 00000000..3b40763c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c @@ -0,0 +1,104 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "csr.h" +#include "x-heep.h" + +#include "coremark.h" + +ee_u32 default_num_contexts = 1; + +static CORETIMETYPE start_time_val, stop_time_val; + +#if VALIDATION_RUN +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PERFORMANCE_RUN +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PROFILE_RUN +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; +#endif +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; + +void +portable_init(core_portable *p, int *argc, char *argv[]) +{ + // Don't need to do anything here atm. + (void)p; + (void)argc; + (void)argv; +} + +void +portable_fini(core_portable *p) +{ + // Don't need to do anything here atm. + (void)p; +} + +void +start_time(void) +{ + // Enable mcycle counter and read value + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + + CSR_READ(CSR_REG_MCYCLE, &start_time_val); +} + +void +stop_time(void) +{ + CSR_READ(CSR_REG_MCYCLE, &stop_time_val); +} + +CORE_TICKS +get_time(void) +{ + return (stop_time_val - start_time_val); +} + +secs_ret +time_in_secs(CORE_TICKS ticks) +{ + return ticks*1E-6; // Normalized to 1 MHz clock period +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h new file mode 100644 index 00000000..5a15066a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h @@ -0,0 +1,93 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include +#include + +typedef signed short ee_s16; +typedef unsigned short ee_u16; +typedef signed int ee_s32; +typedef double ee_f32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef ee_u32 ee_ptr_int; +typedef size_t ee_size_t; + +typedef ee_u32 CORE_TICKS; + +typedef struct CORE_PORTABLE_S +{ + ee_u8 portable_id; +} core_portable; + +#ifndef MULTITHREAD +#define MULTITHREAD 1 // 1 means single-core +#define USE_PTHREAD 0 +#define USE_FORK 0 +#define USE_SOCKET 0 +#endif + +#ifndef COMPILER_VERSION +#ifdef __GNUC__ +#define COMPILER_VERSION "GCC"__VERSION__ +#else +#define COMPILER_VERSION "Undefined non-gcc compiler used" +#endif +#endif + +#ifndef COMPILER_FLAGS +#define COMPILER_FLAGS FLAGS_STR +#endif + +#ifndef MEM_LOCATION +#define MEM_LOCATION "" +#endif + +#ifndef SEED_METHOD +#define SEED_METHOD SEED_VOLATILE +#endif + +#ifndef HAS_PRINTF +#define HAS_PRINTF 1 +#endif + +#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) + +#define CORETIMETYPE ee_u32 + +extern ee_u32 default_num_contexts; + +void portable_init(core_portable *p, int *argc, char *argv[]); +void portable_fini(core_portable *p); diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c new file mode 100644 index 00000000..b5c3d461 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c @@ -0,0 +1,347 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* local functions */ +enum CORE_STATE core_state_transition(ee_u8 **instr, ee_u32 *transition_count); + +/* +Topic: Description + Simple state machines like this one are used in many embedded products. + + For more complex state machines, sometimes a state transition table +implementation is used instead, trading speed of direct coding for ease of +maintenance. + + Since the main goal of using a state machine in CoreMark is to excercise +the switch/if behaviour, we are using a small moore machine. + + In particular, this machine tests type of string input, + trying to determine whether the input is a number or something else. + (see core_state.png). +*/ + +/* Function: core_bench_state + Benchmark function + + Go over the input twice, once direct, and once after introducing some + corruption. +*/ +ee_u16 +core_bench_state(ee_u32 blksize, + ee_u8 *memblock, + ee_s16 seed1, + ee_s16 seed2, + ee_s16 step, + ee_u16 crc) +{ + ee_u32 final_counts[NUM_CORE_STATES]; + ee_u32 track_counts[NUM_CORE_STATES]; + ee_u8 *p = memblock; + ee_u32 i; + +#if CORE_DEBUG + ee_printf("State Bench: %d,%d,%d,%04x\n", seed1, seed2, step, crc); +#endif + for (i = 0; i < NUM_CORE_STATES; i++) + { + final_counts[i] = track_counts[i] = 0; + } + /* run the state machine over the input */ + while (*p != 0) + { + enum CORE_STATE fstate = core_state_transition(&p, track_counts); + final_counts[fstate]++; +#if CORE_DEBUG + ee_printf("%d,", fstate); + } + ee_printf("\n"); +#else + } +#endif + p = memblock; + while (p < (memblock + blksize)) + { /* insert some corruption */ + if (*p != ',') + *p ^= (ee_u8)seed1; + p += step; + } + p = memblock; + /* run the state machine over the input again */ + while (*p != 0) + { + enum CORE_STATE fstate = core_state_transition(&p, track_counts); + final_counts[fstate]++; +#if CORE_DEBUG + ee_printf("%d,", fstate); + } + ee_printf("\n"); +#else + } +#endif + p = memblock; + while (p < (memblock + blksize)) + { /* undo corruption is seed1 and seed2 are equal */ + if (*p != ',') + *p ^= (ee_u8)seed2; + p += step; + } + /* end timing */ + for (i = 0; i < NUM_CORE_STATES; i++) + { + crc = crcu32(final_counts[i], crc); + crc = crcu32(track_counts[i], crc); + } + return crc; +} + +/* Default initialization patterns */ +static ee_u8 *intpat[4] + = { (ee_u8 *)"5012", (ee_u8 *)"1234", (ee_u8 *)"-874", (ee_u8 *)"+122" }; +static ee_u8 *floatpat[4] = { (ee_u8 *)"35.54400", + (ee_u8 *)".1234500", + (ee_u8 *)"-110.700", + (ee_u8 *)"+0.64400" }; +static ee_u8 *scipat[4] = { (ee_u8 *)"5.500e+3", + (ee_u8 *)"-.123e-2", + (ee_u8 *)"-87e+832", + (ee_u8 *)"+0.6e-12" }; +static ee_u8 *errpat[4] = { (ee_u8 *)"T0.3e-1F", + (ee_u8 *)"-T.T++Tq", + (ee_u8 *)"1T3.4e4z", + (ee_u8 *)"34.0e-T^" }; + +/* Function: core_init_state + Initialize the input data for the state machine. + + Populate the input with several predetermined strings, interspersed. + Actual patterns chosen depend on the seed parameter. + + Note: + The seed parameter MUST be supplied from a source that cannot be + determined at compile time +*/ +void +core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p) +{ + ee_u32 total = 0, next = 0, i; + ee_u8 *buf = 0; +#if CORE_DEBUG + ee_u8 *start = p; + ee_printf("State: %d,%d\n", size, seed); +#endif + size--; + next = 0; + while ((total + next + 1) < size) + { + if (next > 0) + { + for (i = 0; i < next; i++) + *(p + total + i) = buf[i]; + *(p + total + i) = ','; + total += next + 1; + } + seed++; + switch (seed & 0x7) + { + case 0: /* int */ + case 1: /* int */ + case 2: /* int */ + buf = intpat[(seed >> 3) & 0x3]; + next = 4; + break; + case 3: /* float */ + case 4: /* float */ + buf = floatpat[(seed >> 3) & 0x3]; + next = 8; + break; + case 5: /* scientific */ + case 6: /* scientific */ + buf = scipat[(seed >> 3) & 0x3]; + next = 8; + break; + case 7: /* invalid */ + buf = errpat[(seed >> 3) & 0x3]; + next = 8; + break; + default: /* Never happen, just to make some compilers happy */ + break; + } + } + size++; + while (total < size) + { /* fill the rest with 0 */ + *(p + total) = 0; + total++; + } +#if CORE_DEBUG + ee_printf("State Input: %s\n", start); +#endif +} + +static ee_u8 +ee_isdigit(ee_u8 c) +{ + ee_u8 retval; + retval = ((c >= '0') & (c <= '9')) ? 1 : 0; + return retval; +} + +/* Function: core_state_transition + Actual state machine. + + The state machine will continue scanning until either: + 1 - an invalid input is detcted. + 2 - a valid number has been detected. + + The input pointer is updated to point to the end of the token, and the + end state is returned (either specific format determined or invalid). +*/ + +enum CORE_STATE +core_state_transition(ee_u8 **instr, ee_u32 *transition_count) +{ + ee_u8 * str = *instr; + ee_u8 NEXT_SYMBOL; + enum CORE_STATE state = CORE_START; + for (; *str && state != CORE_INVALID; str++) + { + NEXT_SYMBOL = *str; + if (NEXT_SYMBOL == ',') /* end of this input */ + { + str++; + break; + } + switch (state) + { + case CORE_START: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INT; + } + else if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') + { + state = CORE_S1; + } + else if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + } + else + { + state = CORE_INVALID; + transition_count[CORE_INVALID]++; + } + transition_count[CORE_START]++; + break; + case CORE_S1: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INT; + transition_count[CORE_S1]++; + } + else if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + transition_count[CORE_S1]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_S1]++; + } + break; + case CORE_INT: + if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + transition_count[CORE_INT]++; + } + else if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_INT]++; + } + break; + case CORE_FLOAT: + if (NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e') + { + state = CORE_S2; + transition_count[CORE_FLOAT]++; + } + else if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_FLOAT]++; + } + break; + case CORE_S2: + if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') + { + state = CORE_EXPONENT; + transition_count[CORE_S2]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_S2]++; + } + break; + case CORE_EXPONENT: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_SCIENTIFIC; + transition_count[CORE_EXPONENT]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_EXPONENT]++; + } + break; + case CORE_SCIENTIFIC: + if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_INVALID]++; + } + break; + default: + break; + } + } + *instr = str; + return state; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c new file mode 100644 index 00000000..0544e621 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c @@ -0,0 +1,266 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* Function: get_seed + Get a values that cannot be determined at compile time. + + Since different embedded systems and compilers are used, 3 different + methods are provided: 1 - Using a volatile variable. This method is only + valid if the compiler is forced to generate code that reads the value of a + volatile variable from memory at run time. Please note, if using this method, + you would need to modify core_portme.c to generate training profile. 2 - + Command line arguments. This is the preferred method if command line + arguments are supported. 3 - System function. If none of the first 2 methods + is available on the platform, a system function which is not a stub can be + used. + + e.g. read the value on GPIO pins connected to switches, or invoke + special simulator functions. +*/ +#if (SEED_METHOD == SEED_VOLATILE) +extern volatile ee_s32 seed1_volatile; +extern volatile ee_s32 seed2_volatile; +extern volatile ee_s32 seed3_volatile; +extern volatile ee_s32 seed4_volatile; +extern volatile ee_s32 seed5_volatile; +ee_s32 +get_seed_32(int i) +{ + ee_s32 retval; + switch (i) + { + case 1: + retval = seed1_volatile; + break; + case 2: + retval = seed2_volatile; + break; + case 3: + retval = seed3_volatile; + break; + case 4: + retval = seed4_volatile; + break; + case 5: + retval = seed5_volatile; + break; + default: + retval = 0; + break; + } + return retval; +} +#elif (SEED_METHOD == SEED_ARG) +ee_s32 +parseval(char *valstring) +{ + ee_s32 retval = 0; + ee_s32 neg = 1; + int hexmode = 0; + if (*valstring == '-') + { + neg = -1; + valstring++; + } + if ((valstring[0] == '0') && (valstring[1] == 'x')) + { + hexmode = 1; + valstring += 2; + } + /* first look for digits */ + if (hexmode) + { + while (((*valstring >= '0') && (*valstring <= '9')) + || ((*valstring >= 'a') && (*valstring <= 'f'))) + { + ee_s32 digit = *valstring - '0'; + if (digit > 9) + digit = 10 + *valstring - 'a'; + retval *= 16; + retval += digit; + valstring++; + } + } + else + { + while ((*valstring >= '0') && (*valstring <= '9')) + { + ee_s32 digit = *valstring - '0'; + retval *= 10; + retval += digit; + valstring++; + } + } + /* now add qualifiers */ + if (*valstring == 'K') + retval *= 1024; + if (*valstring == 'M') + retval *= 1024 * 1024; + + retval *= neg; + return retval; +} + +ee_s32 +get_seed_args(int i, int argc, char *argv[]) +{ + if (argc > i) + return parseval(argv[i]); + return 0; +} + +#elif (SEED_METHOD == SEED_FUNC) +/* If using OS based function, you must define and implement the functions below + * in core_portme.h and core_portme.c ! */ +ee_s32 +get_seed_32(int i) +{ + ee_s32 retval; + switch (i) + { + case 1: + retval = portme_sys1(); + break; + case 2: + retval = portme_sys2(); + break; + case 3: + retval = portme_sys3(); + break; + case 4: + retval = portme_sys4(); + break; + case 5: + retval = portme_sys5(); + break; + default: + retval = 0; + break; + } + return retval; +} +#endif + +/* Function: crc* + Service functions to calculate 16b CRC code. + +*/ +ee_u16 +crcu8(ee_u8 data, ee_u16 crc) +{ + ee_u8 i = 0, x16 = 0, carry = 0; + + for (i = 0; i < 8; i++) + { + x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1)); + data >>= 1; + + if (x16 == 1) + { + crc ^= 0x4002; + carry = 1; + } + else + carry = 0; + crc >>= 1; + if (carry) + crc |= 0x8000; + else + crc &= 0x7fff; + } + return crc; +} +ee_u16 +crcu16(ee_u16 newval, ee_u16 crc) +{ + crc = crcu8((ee_u8)(newval), crc); + crc = crcu8((ee_u8)((newval) >> 8), crc); + return crc; +} +ee_u16 +crcu32(ee_u32 newval, ee_u16 crc) +{ + crc = crc16((ee_s16)newval, crc); + crc = crc16((ee_s16)(newval >> 16), crc); + return crc; +} +ee_u16 +crc16(ee_s16 newval, ee_u16 crc) +{ + return crcu16((ee_u16)newval, crc); +} + +ee_u8 +check_data_types() +{ + ee_u8 retval = 0; + if (sizeof(ee_u8) != 1) + { + ee_printf("ERROR: ee_u8 is not an 8b datatype!\n"); + retval++; + } + if (sizeof(ee_u16) != 2) + { + ee_printf("ERROR: ee_u16 is not a 16b datatype!\n"); + retval++; + } + if (sizeof(ee_s16) != 2) + { + ee_printf("ERROR: ee_s16 is not a 16b datatype!\n"); + retval++; + } + if (sizeof(ee_s32) != 4) + { + ee_printf("ERROR: ee_s32 is not a 32b datatype!\n"); + retval++; + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR: ee_u32 is not a 32b datatype!\n"); + retval++; + } + if (sizeof(ee_ptr_int) != sizeof(int *)) + { + ee_printf( + "ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n"); + retval++; + } + if (retval > 0) + { + ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n"); + } + return retval; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h new file mode 100644 index 00000000..1501da49 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h @@ -0,0 +1,211 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +/* Topic: Description + This file contains declarations of the various benchmark functions. +*/ + +/* Configuration: TOTAL_DATA_SIZE + Define total size for data algorithms will operate on +*/ +#ifndef TOTAL_DATA_SIZE +#define TOTAL_DATA_SIZE 2 * 1000 +#endif + +#define SEED_ARG 0 +#define SEED_FUNC 1 +#define SEED_VOLATILE 2 + +#define MEM_STATIC 0 +#define MEM_MALLOC 1 +#define MEM_STACK 2 + +#include "core_portme.h" + +#if HAS_STDIO +#include +#endif +#if HAS_PRINTF +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define ee_printf(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define ee_printf(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define ee_printf printf +#endif + +#endif + +/* Actual benchmark execution in iterate */ +void *iterate(void *pres); + +/* Typedef: secs_ret + For machines that have floating point support, get number of seconds as + a double. Otherwise an unsigned int. +*/ +#if HAS_FLOAT +typedef double secs_ret; +#else +typedef ee_u32 secs_ret; +#endif + +#if MAIN_HAS_NORETURN +#define MAIN_RETURN_VAL +#define MAIN_RETURN_TYPE void +#else +#define MAIN_RETURN_VAL 0 +#define MAIN_RETURN_TYPE int +#endif + +void start_time(void); +void stop_time(void); +CORE_TICKS get_time(void); +secs_ret time_in_secs(CORE_TICKS ticks); + +/* Misc useful functions */ +ee_u16 crcu8(ee_u8 data, ee_u16 crc); +ee_u16 crc16(ee_s16 newval, ee_u16 crc); +ee_u16 crcu16(ee_u16 newval, ee_u16 crc); +ee_u16 crcu32(ee_u32 newval, ee_u16 crc); +ee_u8 check_data_types(void); +void * portable_malloc(ee_size_t size); +void portable_free(void *p); +ee_s32 parseval(char *valstring); + +/* Algorithm IDS */ +#define ID_LIST (1 << 0) +#define ID_MATRIX (1 << 1) +#define ID_STATE (1 << 2) +#define ALL_ALGORITHMS_MASK (ID_LIST | ID_MATRIX | ID_STATE) +#define NUM_ALGORITHMS 3 + +/* list data structures */ +typedef struct list_data_s +{ + ee_s16 data16; + ee_s16 idx; +} list_data; + +typedef struct list_head_s +{ + struct list_head_s *next; + struct list_data_s *info; +} list_head; + +/*matrix benchmark related stuff */ +#define MATDAT_INT 1 +#if MATDAT_INT +typedef ee_s16 MATDAT; +typedef ee_s32 MATRES; +#else +typedef ee_f16 MATDAT; +typedef ee_f32 MATRES; +#endif + +typedef struct MAT_PARAMS_S +{ + int N; + MATDAT *A; + MATDAT *B; + MATRES *C; +} mat_params; + +/* state machine related stuff */ +/* List of all the possible states for the FSM */ +typedef enum CORE_STATE +{ + CORE_START = 0, + CORE_INVALID, + CORE_S1, + CORE_S2, + CORE_INT, + CORE_FLOAT, + CORE_EXPONENT, + CORE_SCIENTIFIC, + NUM_CORE_STATES +} core_state_e; + +/* Helper structure to hold results */ +typedef struct RESULTS_S +{ + /* inputs */ + ee_s16 seed1; /* Initializing seed */ + ee_s16 seed2; /* Initializing seed */ + ee_s16 seed3; /* Initializing seed */ + void * memblock[4]; /* Pointer to safe memory location */ + ee_u32 size; /* Size of the data */ + ee_u32 iterations; /* Number of iterations to execute */ + ee_u32 execs; /* Bitmask of operations to execute */ + struct list_head_s *list; + mat_params mat; + /* outputs */ + ee_u16 crc; + ee_u16 crclist; + ee_u16 crcmatrix; + ee_u16 crcstate; + ee_s16 err; + /* ultithread specific */ + core_portable port; +} core_results; + +/* Multicore execution handling */ +#if (MULTITHREAD > 1) +ee_u8 core_start_parallel(core_results *res); +ee_u8 core_stop_parallel(core_results *res); +#endif + +/* list benchmark functions */ +list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed); +ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx); + +/* state benchmark functions */ +void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p); +ee_u16 core_bench_state(ee_u32 blksize, + ee_u8 *memblock, + ee_s16 seed1, + ee_s16 seed2, + ee_s16 step, + ee_u16 crc); + +/* matrix benchmark functions */ +ee_u32 core_init_matrix(ee_u32 blksize, + void * memblk, + ee_s32 seed, + mat_params *p); +ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc); diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c new file mode 100644 index 00000000..12136ada --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c @@ -0,0 +1,459 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +/* File: core_main.c + This file contains the framework to acquire a block of memory, seed + initial parameters, tun t he benchmark and report the results. +*/ +#include "coremark.h" + +/* Function: iterate + Run the benchmark for a specified number of iterations. + + Operation: + For each type of benchmarked algorithm: + a - Initialize the data block for the algorithm. + b - Execute the algorithm N times. + + Returns: + NULL. +*/ +static ee_u16 list_known_crc[] = { (ee_u16)0xd4b0, + (ee_u16)0x3340, + (ee_u16)0x6a79, + (ee_u16)0xe714, + (ee_u16)0xe3c1 }; +static ee_u16 matrix_known_crc[] = { (ee_u16)0xbe52, + (ee_u16)0x1199, + (ee_u16)0x5608, + (ee_u16)0x1fd7, + (ee_u16)0x0747 }; +static ee_u16 state_known_crc[] = { (ee_u16)0x5e47, + (ee_u16)0x39bf, + (ee_u16)0xe5a4, + (ee_u16)0x8e3a, + (ee_u16)0x8d84 }; +void * +iterate(void *pres) +{ + ee_u32 i; + ee_u16 crc; + core_results *res = (core_results *)pres; + ee_u32 iterations = res->iterations; + res->crc = 0; + res->crclist = 0; + res->crcmatrix = 0; + res->crcstate = 0; + + for (i = 0; i < iterations; i++) + { + crc = core_bench_list(res, 1); + res->crc = crcu16(crc, res->crc); + crc = core_bench_list(res, -1); + res->crc = crcu16(crc, res->crc); + if (i == 0) + res->crclist = res->crc; + } + return NULL; +} + +#if (SEED_METHOD == SEED_ARG) +ee_s32 get_seed_args(int i, int argc, char *argv[]); +#define get_seed(x) (ee_s16) get_seed_args(x, argc, argv) +#define get_seed_32(x) get_seed_args(x, argc, argv) +#else /* via function or volatile */ +ee_s32 get_seed_32(int i); +#define get_seed(x) (ee_s16) get_seed_32(x) +#endif + +#if (MEM_METHOD == MEM_STATIC) +ee_u8 static_memblk[TOTAL_DATA_SIZE]; +#endif +char *mem_name[3] = { "Static", "Heap", "Stack" }; +/* Function: main + Main entry routine for the benchmark. + This function is responsible for the following steps: + + 1 - Initialize input seeds from a source that cannot be determined at + compile time. 2 - Initialize memory block for use. 3 - Run and time the + benchmark. 4 - Report results, testing the validity of the output if the + seeds are known. + + Arguments: + 1 - first seed : Any value + 2 - second seed : Must be identical to first for iterations to be + identical 3 - third seed : Any value, should be at least an order of + magnitude less then the input size, but bigger then 32. 4 - Iterations : + Special, if set to 0, iterations will be automatically determined such that + the benchmark will run between 10 to 100 secs + +*/ + +#if MAIN_HAS_NOARGC +MAIN_RETURN_TYPE +main(void) +{ + int argc = 0; + char *argv[1]; +#else +MAIN_RETURN_TYPE +main(int argc, char *argv[]) +{ +#endif + ee_u16 i, j = 0, num_algorithms = 0; + ee_s16 known_id = -1, total_errors = 0; + ee_u16 seedcrc = 0; + CORE_TICKS total_time; + core_results results[MULTITHREAD]; +#if (MEM_METHOD == MEM_STACK) + ee_u8 stack_memblock[TOTAL_DATA_SIZE * MULTITHREAD]; +#endif + /* first call any initializations needed */ + portable_init(&(results[0].port), &argc, argv); + /* First some checks to make sure benchmark will run ok */ + if (sizeof(struct list_head_s) > 128) + { + ee_printf("list_head structure too big for comparable data!\n"); + return MAIN_RETURN_VAL; + } + results[0].seed1 = get_seed(1); + results[0].seed2 = get_seed(2); + results[0].seed3 = get_seed(3); + results[0].iterations = get_seed_32(4); +#if CORE_DEBUG + results[0].iterations = 1; +#endif + results[0].execs = get_seed_32(5); + if (results[0].execs == 0) + { /* if not supplied, execute all algorithms */ + results[0].execs = ALL_ALGORITHMS_MASK; + } + /* put in some default values based on one seed only for easy testing */ + if ((results[0].seed1 == 0) && (results[0].seed2 == 0) + && (results[0].seed3 == 0)) + { /* perfromance run */ + results[0].seed1 = 0; + results[0].seed2 = 0; + results[0].seed3 = 0x66; + } + if ((results[0].seed1 == 1) && (results[0].seed2 == 0) + && (results[0].seed3 == 0)) + { /* validation run */ + results[0].seed1 = 0x3415; + results[0].seed2 = 0x3415; + results[0].seed3 = 0x66; + } +#if (MEM_METHOD == MEM_STATIC) + results[0].memblock[0] = (void *)static_memblk; + results[0].size = TOTAL_DATA_SIZE; + results[0].err = 0; +#if (MULTITHREAD > 1) +#error "Cannot use a static data area with multiple contexts!" +#endif +#elif (MEM_METHOD == MEM_MALLOC) + for (i = 0; i < MULTITHREAD; i++) + { + ee_s32 malloc_override = get_seed(7); + if (malloc_override != 0) + results[i].size = malloc_override; + else + results[i].size = TOTAL_DATA_SIZE; + results[i].memblock[0] = portable_malloc(results[i].size); + results[i].seed1 = results[0].seed1; + results[i].seed2 = results[0].seed2; + results[i].seed3 = results[0].seed3; + results[i].err = 0; + results[i].execs = results[0].execs; + } +#elif (MEM_METHOD == MEM_STACK) +for (i = 0; i < MULTITHREAD; i++) +{ + results[i].memblock[0] = stack_memblock + i * TOTAL_DATA_SIZE; + results[i].size = TOTAL_DATA_SIZE; + results[i].seed1 = results[0].seed1; + results[i].seed2 = results[0].seed2; + results[i].seed3 = results[0].seed3; + results[i].err = 0; + results[i].execs = results[0].execs; +} +#else +#error "Please define a way to initialize a memory block." +#endif + /* Data init */ + /* Find out how space much we have based on number of algorithms */ + for (i = 0; i < NUM_ALGORITHMS; i++) + { + if ((1 << (ee_u32)i) & results[0].execs) + num_algorithms++; + } + for (i = 0; i < MULTITHREAD; i++) + results[i].size = results[i].size / num_algorithms; + /* Assign pointers */ + for (i = 0; i < NUM_ALGORITHMS; i++) + { + ee_u32 ctx; + if ((1 << (ee_u32)i) & results[0].execs) + { + for (ctx = 0; ctx < MULTITHREAD; ctx++) + results[ctx].memblock[i + 1] + = (char *)(results[ctx].memblock[0]) + results[0].size * j; + j++; + } + } + /* call inits */ + for (i = 0; i < MULTITHREAD; i++) + { + if (results[i].execs & ID_LIST) + { + results[i].list = core_list_init( + results[0].size, results[i].memblock[1], results[i].seed1); + } + if (results[i].execs & ID_MATRIX) + { + core_init_matrix(results[0].size, + results[i].memblock[2], + (ee_s32)results[i].seed1 + | (((ee_s32)results[i].seed2) << 16), + &(results[i].mat)); + } + if (results[i].execs & ID_STATE) + { + core_init_state( + results[0].size, results[i].seed1, results[i].memblock[3]); + } + } + + /* automatically determine number of iterations if not set */ + if (results[0].iterations == 0) + { + secs_ret secs_passed = 0; + ee_u32 divisor; + results[0].iterations = 1; + while (secs_passed < (secs_ret)1) + { + results[0].iterations *= 10; + start_time(); + iterate(&results[0]); + stop_time(); + secs_passed = time_in_secs(get_time()); + } + /* now we know it executes for at least 1 sec, set actual run time at + * about 10 secs */ + divisor = (ee_u32)secs_passed; + if (divisor == 0) /* some machines cast float to int as 0 since this + conversion is not defined by ANSI, but we know at + least one second passed */ + divisor = 1; + results[0].iterations *= 1 + 10 / divisor; + } + /* perform actual benchmark */ + start_time(); +#if (MULTITHREAD > 1) + if (default_num_contexts > MULTITHREAD) + { + default_num_contexts = MULTITHREAD; + } + for (i = 0; i < default_num_contexts; i++) + { + results[i].iterations = results[0].iterations; + results[i].execs = results[0].execs; + core_start_parallel(&results[i]); + } + for (i = 0; i < default_num_contexts; i++) + { + core_stop_parallel(&results[i]); + } +#else + iterate(&results[0]); +#endif + stop_time(); + total_time = get_time(); + /* get a function of the input to report */ + seedcrc = crc16(results[0].seed1, seedcrc); + seedcrc = crc16(results[0].seed2, seedcrc); + seedcrc = crc16(results[0].seed3, seedcrc); + seedcrc = crc16(results[0].size, seedcrc); + + switch (seedcrc) + { /* test known output for common seeds */ + case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */ + known_id = 0; + ee_printf("6k performance run parameters for coremark.\n"); + break; + case 0x7b05: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per + algorithm */ + known_id = 1; + ee_printf("6k validation run parameters for coremark.\n"); + break; + case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm + */ + known_id = 2; + ee_printf("Profile generation run parameters for coremark.\n"); + break; + case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */ + known_id = 3; + ee_printf("2K performance run parameters for coremark.\n"); + break; + case 0x18f2: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per + algorithm */ + known_id = 4; + ee_printf("2K validation run parameters for coremark.\n"); + break; + default: + total_errors = -1; + break; + } + if (known_id >= 0) + { + for (i = 0; i < default_num_contexts; i++) + { + results[i].err = 0; + if ((results[i].execs & ID_LIST) + && (results[i].crclist != list_known_crc[known_id])) + { + ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n", + i, + results[i].crclist, + list_known_crc[known_id]); + results[i].err++; + } + if ((results[i].execs & ID_MATRIX) + && (results[i].crcmatrix != matrix_known_crc[known_id])) + { + ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n", + i, + results[i].crcmatrix, + matrix_known_crc[known_id]); + results[i].err++; + } + if ((results[i].execs & ID_STATE) + && (results[i].crcstate != state_known_crc[known_id])) + { + ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n", + i, + results[i].crcstate, + state_known_crc[known_id]); + results[i].err++; + } + total_errors += results[i].err; + } + } + total_errors += check_data_types(); + /* and report results */ + ee_printf("CoreMark Size : %lu\n", (long unsigned)results[0].size); + ee_printf("Total ticks : %lu\n", (long unsigned)total_time); +#if HAS_FLOAT + ee_printf("Total time (secs): %f\n", time_in_secs(total_time)); + if (time_in_secs(total_time) > 0) + ee_printf("Iterations/Sec : %f\n", + default_num_contexts * results[0].iterations + / time_in_secs(total_time)); +#else + ee_printf("Total time (secs): %d\n", time_in_secs(total_time)); + if (time_in_secs(total_time) > 0) + ee_printf("Iterations/Sec : %d\n", + default_num_contexts * results[0].iterations + / time_in_secs(total_time)); +#endif +/* if (time_in_secs(total_time) < 10) + { + ee_printf( + "ERROR! Must execute for at least 10 secs for a valid result!\n"); + total_errors++; + } +*/ + + ee_printf("Iterations : %lu\n", + (long unsigned)default_num_contexts * results[0].iterations); +#if (MULTITHREAD > 1) + ee_printf("Parallel %s : %d\n", PARALLEL_METHOD, default_num_contexts); +#endif + ee_printf("Memory location : %s\n", MEM_LOCATION); + /* output for verification */ + ee_printf("seedcrc : 0x%04x\n", seedcrc); + if (results[0].execs & ID_LIST) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crclist : 0x%04x\n", i, results[i].crclist); + if (results[0].execs & ID_MATRIX) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcmatrix : 0x%04x\n", i, results[i].crcmatrix); + if (results[0].execs & ID_STATE) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcstate : 0x%04x\n", i, results[i].crcstate); + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcfinal : 0x%04x\n", i, results[i].crc); + if (total_errors == 0) + { + ee_printf( + "Correct operation validated. See README.md for run and reporting " + "rules.\n"); +#if HAS_FLOAT + if (known_id == 3) + { + ee_printf("CoreMark 1.0 : %f / %s", + default_num_contexts * results[0].iterations + / time_in_secs(total_time), + COMPILER_VERSION); +// COMPILER_VERSION, +// COMPILER_FLAGS); +#if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC) + ee_printf(" / %s", MEM_LOCATION); +#else + ee_printf(" / %s", mem_name[MEM_METHOD]); +#endif + +#if (MULTITHREAD > 1) + ee_printf(" / %d:%s", default_num_contexts, PARALLEL_METHOD); +#endif + ee_printf("\n"); + } +#endif + } + if (total_errors > 0) + ee_printf("Errors detected\n"); + if (total_errors < 0) + ee_printf( + "Cannot validate operation for these seed values, please compare " + "with results on a known platform.\n"); + +#if (MEM_METHOD == MEM_MALLOC) + for (i = 0; i < MULTITHREAD; i++) + portable_free(results[i].memblock[0]); +#endif + /* And last call any target specific code for finalizing */ + portable_fini(&(results[0].port)); + + return MAIN_RETURN_VAL; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c index bbab3698..ea842d8a 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c @@ -208,7 +208,7 @@ int main(int argc, char *argv[]) #endif // TEST_ADDRESS_MODE -#ifndef TARGET_PYNQ_Z2 +#if defined(TARGET_SIM) || defined(TARGET_SYSTEMC) #ifdef TEST_ADDRESS_MODE_EXTERNAL_DEVICE @@ -275,7 +275,7 @@ int main(int argc, char *argv[]) #endif //TEST_ADDRESS_MODE_EXTERNAL_DEVICE #else - #pragma message( "TEST_ADDRESS_MODE_EXTERNAL_DEVICE is not executed on PYNQ Z2" ) + #pragma message( "TEST_ADDRESS_MODE_EXTERNAL_DEVICE is not executed on target different than TARGET_SIM" ) #endif #ifdef TEST_PENDING_TRANSACTION diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c new file mode 100644 index 00000000..8af03ad4 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c @@ -0,0 +1,128 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#define BUFF_LEN 100 + +uint32_t buffer_rnd_index[BUFF_LEN]; + +#ifdef TARGET_SYSTEMC +//make app PROJECT=example_ext_memory TARGET=systemc +#define CACHE_FLUSH 1 +#define CACHE_BYPASS 2 +#define CACHE_SIZE 4*1024 +#endif + +#define MEMORY_SIZE 32*1024 +#define MEMORY_ADDR_MASK 0x7FFF +#define MEMORY_MAX_WORD_INDEX (MEMORY_SIZE/4) + +int is_in_array(uint32_t number, uint32_t* array, int N ) { + + for (int i=0;i + */ + +#include +#include + +#include "core_v_mini_mcu.h" + +#include "x-heep.h" +#include "iffifo_regs.h" + +#include "mmio.h" +#include "handler.h" +#include "csr.h" +#include "hart.h" + +#include "rv_plic.h" + +#include "dma.h" +#include "dma_regs.h" +#include "fast_intr_ctrl.h" + + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +unsigned int IFFIFO_START_ADDRESS = EXT_PERIPHERAL_START_ADDRESS + 0x2000; + +int32_t to_fifo [6] __attribute__ ((aligned (4))) = { 1, 2, 3, 4, 5, 6 }; +int32_t from_fifo[4] __attribute__ ((aligned (4))) = { 0, 0, 0, 0 }; + +int8_t dma_intr_flag = 0; +void dma_intr_handler_trans_done() +{ + dma_intr_flag = 1; +} + +void protected_wait_for_dma_interrupt(void) +{ + while(!dma_is_ready()) { + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (!dma_is_ready()) { + wait_for_interrupt(); + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } +} + +iffifo_intr_flag = 0; +static void handler_irq_iffifo( uint32_t int_id ) +{ + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b0); + iffifo_intr_flag = 1; + PRINTF(" ** REACH intr. fired.\n"); +} + +static dma_target_t tgt_src; +static dma_target_t tgt_dst; +static dma_trans_t trans; + +int compare_print_fifo_array(void) { + int errors = 0; + PRINTF("from_fifo = {"); + for (int i = 0; i < 4; i+=1) { + PRINTF("%d",from_fifo[i]); + if(i != 4-1) {PRINTF(", ");}; + if (to_fifo[i]+1 != from_fifo[i]) {++errors;} + } + PRINTF("}\n"); + return errors; +} + +void print_status_register(void) +{ + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + int32_t status = mmio_region_read32(iffifo_base_addr, IFFIFO_STATUS_REG_OFFSET); + PRINTF("STATUS = "); + PRINTF(status & (1 << IFFIFO_STATUS_EMPTY_BIT) ? "E" : "-"); // FIFO empty + PRINTF(status & (1 << IFFIFO_STATUS_AVAILABLE_BIT) ? "A" : "-"); // Data available in FIFO + PRINTF(status & (1 << IFFIFO_STATUS_REACHED_BIT) ? "R" : "-"); // Watermark reached + PRINTF(status & (1 << IFFIFO_STATUS_FULL_BIT) ? "F" : "-"); // FIFO full + PRINTF("\n"); +} + +int is_iffifo_full(void) +{ + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + int32_t status = mmio_region_read32(iffifo_base_addr, IFFIFO_STATUS_REG_OFFSET); + return status & (1 << IFFIFO_STATUS_FULL_BIT); +} + +int main(int argc, char *argv[]) { + + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + + // Enable interrupt on processor side + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level external interrupts + const uint32_t mask = 1 << 11; + CSR_SET_BITS(CSR_REG_MIE, mask); + + if(plic_Init()) {return EXIT_FAILURE;}; + if(plic_irq_set_priority(EXT_INTR_1, 1)) {return EXIT_FAILURE;}; + if(plic_irq_set_enabled(EXT_INTR_1, kPlicToggleEnabled)) {return EXIT_FAILURE;}; + + plic_assign_external_irq_handler(EXT_INTR_1, &handler_irq_iffifo); + + mmio_region_write32(iffifo_base_addr, IFFIFO_WATERMARK_REG_OFFSET, 2); + mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b1); + + dma_config_flags_t ret; + + // -- DMA CONFIGURATION -- + + dma_init(NULL); + tgt_src.ptr = to_fifo; + tgt_src.inc_du = 1; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + tgt_src.size_du = 6; + + tgt_dst.ptr = IFFIFO_START_ADDRESS + IFFIFO_FIFO_IN_REG_OFFSET; + tgt_dst.inc_du = 0; + tgt_dst.trig = DMA_TRIG_SLOT_EXT_TX; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.end = DMA_TRANS_END_INTR; + + ret = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + if (ret != 0) {return EXIT_FAILURE;} + ret = dma_load_transaction(&trans); + if (ret != 0) {return EXIT_FAILURE;} + + if (compare_print_fifo_array() != 4) {return EXIT_FAILURE;} + + print_status_register(); + + PRINTF("Launch MM -> Stream DMA\n"); + // Launch a 6-word TX DMA transaction to a 4-word FIFO. The FIFO will be full. + dma_launch( &trans ); + + // To terminate the DMA transaction, 2 words must be manually popped from the FIFO. + while(!is_iffifo_full()); + int32_t read0 = mmio_region_read32(iffifo_base_addr, IFFIFO_FIFO_OUT_REG_OFFSET); + while(!is_iffifo_full()); + int32_t read1 = mmio_region_read32(iffifo_base_addr, IFFIFO_FIFO_OUT_REG_OFFSET); + + print_status_register(); + + PRINTF("Manual readings: {%d, %d}\n", read0, read1); + + protected_wait_for_dma_interrupt(); + + dma_init(NULL); + tgt_src.ptr = IFFIFO_START_ADDRESS + IFFIFO_FIFO_OUT_REG_OFFSET; + tgt_src.inc_du = 0; + tgt_src.trig = DMA_TRIG_SLOT_EXT_RX; + tgt_src.type = DMA_DATA_TYPE_WORD; + tgt_src.size_du = 4; + + tgt_dst.ptr = from_fifo; + tgt_dst.inc_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.end = DMA_TRANS_END_INTR; + + ret = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + if (ret != 0) {return EXIT_FAILURE;} + ret = dma_load_transaction(&trans); + if (ret != 0) {return EXIT_FAILURE;} + PRINTF("Launch Stream -> MM DMA\n"); + dma_launch( &trans ); + + protected_wait_for_dma_interrupt(); + + print_status_register(); + + if (compare_print_fifo_array() == 0) {return EXIT_FAILURE;}; + + if (!iffifo_intr_flag) {return EXIT_FAILURE;}; + + return EXIT_SUCCESS; + +} + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c new file mode 100644 index 00000000..86f69972 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c @@ -0,0 +1,84 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include +#include +#include "csr.h" +#include "matrixAdd32.h" +#include "x-heep.h" +#include "core_v_mini_mcu.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +void __attribute__ ((noinline)) matrixAdd(int32_t * A, int32_t * B, int32_t * C, int N, int M); +uint32_t check_results(int32_t * C, int N, int M); + +int32_t __attribute__((section(".xheep_data_interleaved"))) m_c[16*16]; + + +int main() +{ + +#ifndef HAS_MEMORY_BANKS_IL + PRINTF("This application is only meant to be tested when there are interleaved memory banks\n"); + return EXIT_SUCCESS; +#endif + + + int N = WIDTH; + int M = HEIGHT; + uint32_t errors = 0; + unsigned int instr, cycles, ldstall, jrstall, imstall; + + CSR_WRITE(CSR_REG_MCYCLE, 0); + + //execute the kernel + matrixAdd(m_a, m_b, m_c, N, M); + + CSR_READ(CSR_REG_MCYCLE, &cycles) ; + + //stop the HW counter used for monitoring + + errors = check_results(m_c, N, M); + + PRINTF("program finished with %d errors and %d cycles\n\r", errors, cycles); + return errors; +} + +void __attribute__ ((noinline)) matrixAdd(int32_t * A, int32_t * B, int32_t * C, int N, int M) +{ + for(int i = 0; i < N; i++) { + for(int j = 0; j < M; j++) { + C[i*N+j] = A[i*WIDTH+j] + B[i*WIDTH+j]; + } + } +} + +uint32_t check_results(int32_t * C, int N, int M) +{ + // check + int i, j; + uint32_t err = 0; + + for(i = 0; i < N; i++) { + for(j = 0; j < M; j++) { + if(C[i*N+j] != m_exp[i*WIDTH+j]) { + err++; + PRINTF("Error at index %d, %d, expected %d, got %d\n\r", i, j, m_exp[i*WIDTH+j], C[i*N+j]); + } + } + } + + return err; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h new file mode 100644 index 00000000..8b9bace3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h @@ -0,0 +1,64 @@ +#ifndef MatrixAdd32_H_ +#define MatrixAdd32_H_ + +int32_t __attribute__((section(".xheep_data_interleaved"))) m_a[16*16] = { +-267220638, -815694637, -357240193, 52586566, 471263969, -752743258, -54811671, -330483534, -895389047, 476606065, -261687046, -301494394, 101299356, 1064594637, 876939884, 673598893, +510087407, 21095419, -66273695, 200819447, 230905645, -522677817, 466985617, -42864608, 925345137, -985253526, 963426323, 34126990, -894741205, -944572242, -62503253, -88084923, +-40863508, 775424478, -977993934, -563294903, 240810335, -950840151, 841082377, 814816122, 1010825869, 626595210, -30466653, 32965586, -1009681585, -398274647, 209852250, -680997577, +831825297, 371554642, 209565266, -173321792, 130553499, -846489230, -837855833, -291296547, -656131005, -1008649794, -644660179, -559832327, -957317256, 414035806, 238077607, -417354312, +691270381, 167236288, -370338394, 264811381, -740211299, -502137446, -216028919, -576761164, -1005576983, -300300576, -51567714, 742968985, -713639053, 81381137, -254911471, -456085969, +-657637814, 212880558, 164912940, 975706502, -558175870, -522438623, 219649600, -149341108, -761491992, -324770181, -905679666, -1066241764, 852450941, -105770862, -706293797, 965826475, +605386582, 397282251, -510180840, 322039481, 906789344, 577829424, -244909961, -6565162, -10463653, -275962613, 1045813592, 287658995, 202626085, -913131320, -953473425, 7501200, +44568419, 631042458, -962343731, 389765403, 510986448, 615528098, 854389577, 873031590, 291656555, 717742724, 139337062, 1014134612, 37179482, 156110030, 549532436, -211305424, +146967397, -910154681, 306466943, 809719463, 990862734, -321035009, -503247368, -434011427, -184327001, -460285290, -695885128, 745541667, 549735829, 972687164, 81845219, 626415449, +-869892524, 7650305, -668932203, 612640394, -533618868, -767284692, 263874653, -505082478, -333082894, -170998598, 351985173, 539903843, 161284779, -223326011, -386924128, -894616525, +-205913216, 983230715, 184759813, 3745004, -421392253, 311771810, 809133901, 541639735, 1029270115, 390582486, 1059667793, -308077038, -345200733, 661937983, -69729012, -313649214, +-457079064, 660862401, -419895058, -352985806, 748622990, 789128492, 57857836, 123409871, 367565501, 714681971, 90478156, 401194382, -25590123, 808922190, 231668089, 365978441, +-168791957, 500701111, 966566283, -619646012, 410934777, -567381204, 405170082, -954683259, -176892010, 205925886, 1035377376, 91289957, 478111519, 220727997, -859802080, -155168848, +723982461, -833318195, -445511314, -903460885, 167471780, 423323222, -640855013, 480396600, -268314639, -850542572, 257027787, -315635254, 560711756, -717798753, -372060287, -544448897, +-103077323, -640041517, 577573751, 1039664378, -546538923, 739571966, 680289428, 412799378, 987282320, -378880850, 588647906, -965191092, -829907433, 739600408, -33720223, 56361300, +-1068334620, -399957948, -960664907, -540542510, 280786542, -752129362, -10289650, 1029788294, -636639267, 1029706817, -892387611, 191199904, -965464658, -1048403025, -734580512, 872029387, +}; + +int32_t __attribute__((section(".xheep_data_interleaved"))) m_b[16*16] = { +-451882475, -777460700, 909169980, -96074001, -300818508, 814405880, -568048006, -83472456, 402440048, 810240641, -180564453, 216877888, -140613462, 620727378, -909318526, 765805622, +-231722067, -336894715, -1073684733, -121460761, -23888211, 438175722, -904262018, 145258576, -356787314, 372900212, -358591099, 140421444, -928238022, -99914115, 968352616, -71902672, +-7354035, -831973999, 233305822, -392287490, -729923194, -828467700, -323283176, -788941348, -111739211, -199056442, -476803416, 465916744, 443852965, -376815395, 148885406, 124331090, +-998134941, -490161461, 607731285, 887008149, 683830004, -186741406, -241303958, 456378716, 536730595, 967225269, 1037796891, -802215107, 382626188, 791688228, 538691527, -19673298, +251682349, 598278365, 984763713, 698038628, 821027888, -495782484, -798473539, -424505599, 310436971, 361824506, -130460722, -847926918, 926418138, 637997507, 565305015, 901041052, +236841072, 748341019, 851219634, 437917539, 979456559, 834327011, -191800443, 415161968, -687346999, -41616108, 226338567, 671381489, -248505365, -991524242, 465050274, 673573191, +-432551530, 1057245412, 714468280, -650829182, -850172935, 408331778, 846612827, 884618062, -1025138869, 389044228, 241552082, 1038961376, -425996140, -770151901, -59811946, 433319347, +420324744, -41895865, -626338369, -617719112, -398763632, 40560785, 608712418, 270292226, 276772130, 713936878, -39616963, 852564869, 651061789, -1069752389, 942487510, -212496210, +-884568730, -614540093, 940597970, 963278316, 500604546, -89930534, -362276438, 800923761, 799305363, 67728257, -935053727, -507421158, 453168328, -270267180, 767962559, 540805, +-178905319, 755067965, -132287841, -8637376, 608185815, 427835026, 103464976, -203264205, 80225884, 539643001, -362743073, -487778248, 792077066, 697184933, 827496823, 790812604, +249285726, 359686773, 419021969, 454726313, 124358246, 47824230, -619837186, -913155286, -381944316, 783327309, 572077053, -225060553, 787746239, 671339856, 730167112, 870184696, +319311551, 932192632, -376845525, -288051918, 713264893, -102198441, -315559203, -635483087, -76253988, -427900440, -508626018, -847322511, -717023663, 649773356, -751674700, -363502823, +896873064, -967112426, -607994984, 346538028, -403535863, -456242519, -865446025, -238823125, 568667781, -1008745310, -517236588, -90482335, -769550983, -553756781, -473911347, -317302102, +308779302, 610106502, -99323447, -610238668, 176302035, 320291710, 22124485, 927846370, -961507070, 1046393978, 623269088, -385024596, -636139940, -661255126, -1024580190, -710776275, +874358552, -978379641, 484825057, -177908522, -643611415, -197553591, 406358020, 460342548, 408235584, -809119385, 1047128507, -592130753, -50891763, 786819419, 314046385, 461621105, +-328939806, 375494681, 558517164, 640788713, -419567316, -499867631, 629778826, 201608525, 1006046604, 259505742, 994398852, 338082134, -444011788, 128878595, -672831452, 18560178, +}; + +int32_t m_exp[16*16] = { +-719103113, -1593155337, 551929787, -43487435, 170445461, 61662622, -622859677, -413955990, -492948999, 1286846706, -442251499, -84616506, -39314106, 1685322015, -32378642, 1439404515, +278365340, -315799296, -1139958428, 79358686, 207017434, -84502095, -437276401, 102393968, 568557823, -612353314, 604835224, 174548434, -1822979227, -1044486357, 905849363, -159987595, +-48217543, -56549521, -744688112, -955582393, -489112859, -1779307851, 517799201, 25874774, 899086658, 427538768, -507270069, 498882330, -565828620, -775090042, 358737656, -556666487, +-166309644, -118606819, 817296551, 713686357, 814383503, -1033230636, -1079159791, 165082169, -119400410, -41424525, 393136712, -1362047434, -574691068, 1205724034, 776769134, -437027610, +942952730, 765514653, 614425319, 962850009, 80816589, -997919930, -1014502458, -1001266763, -695140012, 61523930, -182028436, -104957933, 212779085, 719378644, 310393544, 444955083, +-420796742, 961221577, 1016132574, 1413624041, 421280689, 311888388, 27849157, 265820860, -1448838991, -366386289, -679341099, -394860275, 603945576, -1097295104, -241243523, 1639399666, +172835052, 1454527663, 204287440, -328789701, 56616409, 986161202, 601702866, 878052900, -1035602522, 113081615, 1287365674, 1326620371, -223370055, -1683283221, -1013285371, 440820547, +464893163, 589146593, -1588682100, -227953709, 112222816, 656088883, 1463101995, 1143323816, 568428685, 1431679602, 99720099, 1866699481, 688241271, -913642359, 1492019946, -423801634, +-737601333, -1524694774, 1247064913, 1772997779, 1491467280, -410965543, -865523806, 366912334, 614978362, -392557033, -1630938855, 238120509, 1002904157, 702419984, 849807778, 626956254, +-1048797843, 762718270, -801220044, 604003018, 74566947, -339449666, 367339629, -708346683, -252857010, 368644403, -10757900, 52125595, 953361845, 473858922, 440572695, -103803921, +43372510, 1342917488, 603781782, 458471317, -297034007, 359596040, 189296715, -371515551, 647325799, 1173909795, 1631744846, -533137591, 442545506, 1333277839, 660438100, 556535482, +-137767513, 1593055033, -796740583, -641037724, 1461887883, 686930051, -257701367, -512073216, 291311513, 286781531, -418147862, -446128129, -742613786, 1458695546, -520006611, 2475618, +728081107, -466411315, 358571299, -273107984, 7398914, -1023623723, -460275943, -1193506384, 391775771, -802819424, 518140788, 807622, -291439464, -333028784, -1333713427, -472470950, +1032761763, -223211693, -544834761, -1513699553, 343773815, 743614932, -618730528, 1408242970, -1229821709, 195851406, 880296875, -700659850, -75428184, -1379053879, -1396640477, -1255225172, +771281229, -1618421158, 1062398808, 861755856, -1190150338, 542018375, 1086647448, 873141926, 1395517904, -1188000235, 1635776413, -1557321845, -880799196, 1526419827, 280326162, 517982405, +-1397274426, -24463267, -402147743, 100246203, -138780774, -1251996993, 619489176, 1231396819, 369407337, 1289212559, 102011241, 529282038, -1409476446, -919524430, -1407411964, 890589565, +}; + +#define WIDTH 16 +#define HEIGHT 16 + +#endif // MatrixAdd32_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py new file mode 100644 index 00000000..cdf55503 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +## Copyright 2024 EPFL +## Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +import sys +import random +import numpy as np + +def write_arr(f, name, arr, ctype, size): + f.write("const " + ctype + " " + name + "[] = {\n") + + for row in arr: + for elem in row[:-1]: + f.write('%d,' % (elem)) + f.write('%d,\n' % (row[-1])) + + f.write('};\n\n') + return + + +################################################################################ +f = open('matrixMul8.h', 'w') +f.write('#ifndef _MATMUL8_\n') +f.write('#define _MATMUL8_\n') +f.write('// This file is automatically generated\n') + + +SIZE = 16 +RANGE = 4 + +m_a = [] +m_b = [] +m_exp = [] + +# Generate random 8 bit integers from -RANGE to RANGE for A and B +m_a = np.random.randint(-RANGE, RANGE, size=(SIZE, SIZE), dtype=np.int32) +m_b = np.random.randint(-RANGE, RANGE, size=(SIZE, SIZE), dtype=np.int32) +m_exp = np.zeros((SIZE, SIZE), dtype=np.int32) + +# Test the function with A and B +m_exp = np.matmul(m_a,m_b) + +write_arr(f, 'm_a', m_a, 'int8_t', SIZE) +write_arr(f, 'm_b', m_b, 'int8_t', SIZE) +write_arr(f, 'm_exp', m_exp, 'int32_t', SIZE) + +f.write('#define SIZE %d\n' % SIZE) + + +f.write('#endif') diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c new file mode 100644 index 00000000..aec6ca4e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c @@ -0,0 +1,126 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include +#include +#include "csr.h" +#include "matrixMul8.h" +#include "x-heep.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +void __attribute__ ((noinline)) matrixMul8_blocksize(int8_t * A, int8_t * B, int32_t * C, int N); + +void __attribute__ ((noinline)) matrixMul8_tiled(int8_t * A, int8_t * B, int32_t * C, int N); + +uint32_t check_results(int32_t * C, int N); + +int32_t m_c[SIZE*SIZE]; + +#define BLOCK_SIZE 4 + +// Define a macro for accessing matrix elements +#define A(i,j) &A[i*SIZE+j] +#define B(i,j) &B[i*SIZE+j] +#define C(i,j) &C[i*SIZE+j] + +#define HIGHEST_PERF + +int main() +{ + + uint32_t errors = 0; + unsigned int instr, cycles; + + for(int i =0;i> 1; // Half the size + // Multiply the blocks and add them to the corresponding blocks of C + matrixMul8_tiled(A(0, 0), B(0, 0), C(0, 0), N); // C_00 += A_00 * B_00 + matrixMul8_tiled(A(0, N), B(N, 0), C(0, 0), N); // C_00 += A_01 * B_10 + matrixMul8_tiled(A(0, 0), B(0, N), C(0, N), N); // C_01 += A_00 * B_01 + matrixMul8_tiled(A(0, N), B(N, N), C(0, N), N); // C_01 += A_01 * B_11 + matrixMul8_tiled(A(N, 0), B(0, 0), C(N, 0), N); // C_10 += A_10 * B_00 + matrixMul8_tiled(A(N, N), B(N, 0), C(N, 0), N); // C_10 += A_11 * B_10 + matrixMul8_tiled(A(N, 0), B(0, N), C(N, N), N); // C_11 += A_10 * B_01 + matrixMul8_tiled(A(N, N), B(N, N), C(N, N), N); // C_11 += A_11 * B_11 + } +} + + +uint32_t check_results(int32_t * C, int N) +{ + // check + int i, j; + uint32_t err = 0; + + for(i = 0; i < N; i++) { + for(j = 0; j < N; j++) { + if(C[i*N+j] != m_exp[i*N+j]) { + err++; + PRINTF("Error at index %d, %d, expected %d, got %d\n\r", i, j, m_exp[i*N+j], C[i*N+j]); + } + } + } + + return err; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h new file mode 100644 index 00000000..bc2be3e0 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h @@ -0,0 +1,62 @@ +#ifndef _MATMUL8_ +#define _MATMUL8_ +// This file is automatically generated +const int8_t m_a[] = { +-4,-2,-3,3,3,-1,-4,-3,1,-2,-2,2,-2,-4,-2,-1, +0,2,0,-2,-3,3,-2,3,-1,3,0,2,3,1,-3,-2, +0,2,2,3,-2,-2,-3,-2,0,-3,0,-4,2,-3,-3,1, +3,-4,1,1,-1,0,-3,0,1,3,-1,-2,2,3,-4,0, +3,-1,2,-4,-1,-2,0,-3,-3,0,-2,-4,-2,1,0,-2, +-3,0,-2,2,-1,2,2,2,3,1,0,-2,-1,-4,3,-3, +1,3,2,-3,-4,-3,-2,-1,-2,3,1,-3,2,-4,0,0, +-2,0,3,-1,3,-4,0,-2,2,3,-2,-2,-1,-4,-3,1, +-4,-2,-4,-1,-2,-4,-4,-2,-4,-4,-3,0,-2,-4,2,-4, +1,-1,-3,-2,-1,-2,-4,0,2,3,1,-3,-3,1,3,1, +-3,0,1,3,-3,1,3,2,0,-2,1,-4,-3,0,1,-4, +3,0,-1,-3,2,-1,-1,1,-1,3,2,-4,2,2,0,-2, +-4,2,2,-2,2,-4,-3,-3,-3,-3,-2,-3,3,0,3,0, +2,3,-2,0,3,1,1,-3,3,0,1,-4,-4,-1,0,1, +0,0,1,3,-3,3,3,1,-3,1,1,2,1,-2,-2,2, +-1,2,-2,1,0,-2,-3,-1,0,0,2,0,3,3,-4,-4, +}; + +const int8_t m_b[] = { +2,1,2,1,0,3,-1,-1,3,3,3,-2,0,-3,-1,3, +-3,0,-3,0,2,-2,3,0,-2,-1,2,-3,2,-2,0,-2, +-4,0,1,3,-3,-3,-2,2,3,0,-1,2,3,2,-2,-4, +3,3,-2,3,2,2,-2,-1,-3,-3,-1,-3,3,-2,2,-2, +0,1,0,-3,-1,-3,-1,0,-1,3,3,1,-1,-1,2,2, +-2,-4,-1,-1,1,1,2,-1,2,3,0,3,2,0,-4,3, +-1,-1,-3,2,-4,3,3,-1,3,1,-3,-2,1,1,2,3, +0,2,0,1,1,-3,-4,-4,2,-2,1,0,3,2,0,-1, +0,1,1,-1,2,-1,0,2,-1,-3,3,0,-2,-4,2,3, +1,-4,2,-4,0,1,3,-4,-2,-3,-2,-2,-1,3,-2,-3, +1,0,2,3,0,1,1,-1,-3,-1,3,-3,-3,-2,1,-4, +-3,2,-4,1,3,2,3,-2,1,1,3,0,-2,-2,-1,-1, +1,-3,-1,1,-2,2,-1,-4,3,0,-3,-4,-3,1,-1,2, +-1,-2,3,-4,0,1,1,1,-2,1,-4,3,0,1,2,1, +1,3,-1,-4,2,0,-1,-1,-4,-3,-2,-4,-1,-4,3,2, +0,1,0,1,3,-4,-1,2,1,-1,3,-2,-2,-2,-1,-1, +}; + +const int32_t m_exp[] = { +15,30,-21,1,25,-11,-8,24,-29,-1,32,23,-10,-15,9,-4, +-20,-44,1,-1,3,12,19,-41,25,4,-10,11,7,36,-44,-17, +13,10,3,50,-5,-17,-31,28,5,-12,9,-14,14,-3,-8,-28, +23,-31,50,-6,-12,14,-20,-5,19,6,-17,24,-4,29,-22,-1, +0,-17,35,-16,-40,5,-2,28,15,29,-28,27,10,27,-7,8, +15,8,-21,-5,6,6,0,-18,-23,-38,-11,-19,16,-8,16,14, +3,-18,14,16,-15,-9,1,-8,6,-23,-5,-36,-6,20,-27,-43, +-4,-1,9,3,-23,-39,-5,24,5,-13,15,6,-4,21,-3,-26, +20,35,-18,-6,6,3,-17,18,-28,-4,-14,16,-2,8,15,-4, +31,7,45,-49,28,-14,-8,10,-49,-31,11,-6,-24,-17,14,-3, +3,8,-5,21,-19,8,-10,8,-17,-23,-39,10,49,16,22,-9, +21,-30,44,-32,-25,5,-5,-22,-5,10,-12,-8,-15,19,1,8, +-7,8,-2,-18,-18,-38,-23,28,-20,-3,-29,-4,-9,9,17,-11, +10,4,11,-18,8,-13,16,34,-29,6,36,-5,0,-37,18,22, +-7,-13,-29,48,-2,22,13,-26,31,1,-8,-18,20,16,-30,-23, +8,-20,13,0,-5,20,10,-10,-22,2,-9,4,-12,14,6,-18, +}; + +#define SIZE 16 +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c new file mode 100644 index 00000000..71de642f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c @@ -0,0 +1,85 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#define TEST_DATA_SIZE 16 + +#define PRINTF_IN_SIM 1 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + + +int32_t errors = 0; + +//defined in the testharness_pkg.sv +#define SIMPLE_ACC_START_ADDRESS EXT_PERIPHERAL_START_ADDRESS + 0x3000; + +// Simple accelerator Decoder (address for bytes) +//0 READ ADDRESS +#define SIMPLE_ACC_READ_OFFSET 0 +//4 WRITE ADDRESS +#define SIMPLE_ACC_WRITE_OFFSET 1 +//8 THRESHOLD +#define SIMPLE_ACC_THRESHOLD_OFFSET 2 +//C READY +#define SIMPLE_ACC_READY_OFFSET 3 +//10 SIZE +#define SIMPLE_ACC_SIZE_OFFSET 4 +//14 START +#define SIMPLE_ACC_START_OFFSET 5 + + + +int main(int argc, char *argv[]) +{ + + static uint32_t source_data[TEST_DATA_SIZE] __attribute__ ((aligned (4))); + static uint32_t copied_data[TEST_DATA_SIZE] __attribute__ ((aligned (4))); + uint32_t threshold_value = 20; + volatile static uint32_t *simple_acc = SIMPLE_ACC_START_ADDRESS; + + + for(int i=0;i threshold_value ? source_data[i] : threshold_value; + if(copied_data[i] != expected_data){ + errors++; + PRINTF("copied_data[%d] is %d, expected %d\n\r",i,copied_data[i], expected_data); + } + } + + if (errors == 0) { + PRINTF("Simple Accelerator Successful\n\r"); + return EXIT_SUCCESS; + } else { + PRINTF("Simple Accelerator failure: %d errors out of %d data checked\n\r", errors, TEST_DATA_SIZE ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c deleted file mode 100644 index a3d273e7..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif -/* Test Configurations */ -#define TEST_CIRCULAR -#define TEST_MEM_2_SPI -#define TEST_SPI_2_MEM - -// These defines are used only to easily change the data types. -// If not needed, the proper way is using the dma_data_type_t enum. -#define TEST_DATA_TYPE DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD - -#if TEST_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD -#define DATA_TYPE uint8_t -#elif TEST_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD -#define DATA_TYPE uint16_t -#else -#define DATA_TYPE uint32_t -#endif - - -#ifdef TEST_CIRCULAR -// WARNING: When using circular mode the amount of WORDS of each cycle needs to be 32 <= x <= 128 - #define CIRCULAR_CYCLES 4 - #define COPY_DATA_UNITS 256 - #define COPY_DATA_PER_CYCLE ( COPY_DATA_UNITS / CIRCULAR_CYCLES )// Flash page size = 256 Bytes -#else - #define COPY_DATA_UNITS 64 - #define COPY_DATA_PER_CYCLE COPY_DATA_UNITS -#endif //TEST_CIRCULAR - -#define REVERT_24b_ADDR(addr) ((((uint32_t)addr & 0xff0000) >> 16) | ((uint32_t)addr & 0xff00) | (((uint32_t)addr & 0xff) << 16)) - -#define FLASH_ADDR 0x00008500 // 256B data alignment - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -int8_t spi_intr_flag; -spi_host_t spi_host; -int8_t cycles; - -// Reserve memory array -DATA_TYPE flash_data[COPY_DATA_UNITS] __attribute__ ((aligned (DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)))) = { 0 }; -DATA_TYPE copy_data [COPY_DATA_UNITS] __attribute__ ((aligned (DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)))) = { 0 }; - -DATA_TYPE *fifo_ptr_tx; -DATA_TYPE *fifo_ptr_rx; - -#ifndef USE_SPI_FLASH -void fic_irq_spi(void) -{ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#else -void fic_irq_spi_flash(void) -{ - // Disable SPI interrupts - // PRINTF("&"); - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#endif //USE_SPI_FLASH - -#ifdef TEST_CIRCULAR -void dma_intr_handler_trans_done(void) -{ - PRINTF("#"); - cycles++; - if( cycles >= CIRCULAR_CYCLES -1 ) dma_stop_circular(); -} -#else -void dma_intr_handler_trans_done(void) -{ - PRINTF("#"); -} -#endif - -static inline __attribute__((always_inline)) void spi_config() -{ - -/* -* SPI CONFIGURATIONS -*/ -#ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); -#else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); -#endif //USE_SPI_FLASH - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level fast spi interrupt - - -#ifndef USE_SPI_FLASH - const uint32_t mask = 1 << 20; -#else - const uint32_t mask = 1 << 21; -#endif - CSR_SET_BITS(CSR_REG_MIE, mask); - spi_intr_flag = 0; - -#ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); -#endif // USE_SPI_FLASH - - - CSR_SET_BITS(CSR_REG_MIE, mask); - - // Enable SPI host device - spi_set_enable(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // SPI and SPI_FLASH are the same IP so same register map - fifo_ptr_tx = spi_host.base_addr.base + SPI_HOST_TXDATA_REG_OFFSET; - fifo_ptr_rx = spi_host.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Reset - const uint32_t reset_cmd = 0xFFFFFFFF; - spi_write_word(&spi_host, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_reset); - spi_wait_for_ready(&spi_host); - spi_set_rx_watermark(&spi_host,1); - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - // Write enable - const uint32_t write_enable_cmd = 0x06; - spi_write_word(&spi_host, write_enable_cmd); - const uint32_t cmd_write_en = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_write_en); - spi_wait_for_ready(&spi_host); - - // Write command - const uint32_t write_byte_cmd = ((FLASH_ADDR << 8) | 0x02); // Program Page + addr - spi_write_word(&spi_host, write_byte_cmd); - const uint32_t cmd_write = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_write); - spi_wait_for_ready(&spi_host); - -} - - -static inline __attribute__((always_inline)) void spi_wait_4_resp() -{ - // Check status register status waiting for ready - bool flash_busy = true; - uint8_t flash_resp[4] = {0xff,0xff,0xff,0xff}; - while(flash_busy){ - uint32_t flash_cmd = 0x00000005; // [CMD] Read status register - spi_write_word(&spi_host, flash_cmd); // Push TX buffer - uint32_t spi_status_cmd = spi_create_command((spi_command_t){ - .len = 0, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - uint32_t spi_status_read_cmd = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_set_command(&spi_host, spi_status_cmd); - spi_wait_for_ready(&spi_host); - spi_set_command(&spi_host, spi_status_read_cmd); - spi_wait_for_ready(&spi_host); - spi_wait_for_rx_watermark(&spi_host); - spi_read_word(&spi_host, &flash_resp[0]); - if ((flash_resp[0] & 0x01) == 0) flash_busy = false; - } -} - -int main(int argc, char *argv[]) -{ - -#ifdef TARGET_SIM - #pragma message("This app does not allow Flash write operations in simulation!") - PRINTF("Flash writes are not permitted during Simulation, only on FPGA\n"); - return EXIT_SUCCESS; -#endif - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - -#ifdef USE_SPI_FLASH - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; - } -#endif - spi_config(); - dma_init(NULL); - - dma_config_flags_t res; - - for( DATA_TYPE i = 0; i < COPY_DATA_PER_CYCLE; i ++ ) - { - ((DATA_TYPE*)flash_data)[i] = (DATA_TYPE) i; - } - -#ifdef TEST_MEM_2_SPI - - PRINTF("\n\n\r======================================\n\n\r"); - PRINTF(" MEM -> -> DMA -> -> SPI -> -> FLASH "); - PRINTF("\n\n\r======================================\n\n\r"); - -#ifndef USE_SPI_FLASH - const uint8_t slot = DMA_TRIG_SLOT_SPI_TX; // The DMA will wait for the SPI TX FIFO ready signal -#else - const uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_TX; // The DMA will wait for the SPI FLASH TX FIFO ready signal -#endif //USE_SPI_FLASH - - static dma_target_t tgt1= { - .ptr = flash_data, - .inc_du = 1, - .size_du = COPY_DATA_PER_CYCLE, - .trig = DMA_TRIG_MEMORY, - .type = TEST_DATA_TYPE, - }; - - static dma_target_t tgt2= { - .inc_du = 0, - .size_du = COPY_DATA_PER_CYCLE, - .trig = slot, - .type = TEST_DATA_TYPE, - }; - - tgt2.ptr = fifo_ptr_tx; // This is necessary because fifo_ptr_tx is not a constant, and therefore cannot be used as initializer element. - - static dma_trans_t trans = { - .src = &tgt1, - .dst = &tgt2, - .mode = DMA_TRANS_MODE_SINGLE, - .win_du = 0, - .end = DMA_TRANS_END_INTR, - }; - -#ifdef TEST_CIRCULAR - trans.mode = DMA_TRANS_MODE_CIRCULAR; - cycles = 0; -#endif // TEST_CIRCULAR - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \n\r", res); - - res = dma_load_transaction(&trans); - PRINTF("load: %u \n\r", res); - - res = dma_launch(&trans); - - spi_intr_flag = 0; - // Wait for the first data to arrive to the TX FIFO before enabling interrupt - spi_wait_for_tx_not_empty(&spi_host); - // Enable event interrupt - spi_enable_evt_intr(&spi_host, true); - // Enable TX empty interrupt - spi_enable_txempty_intr(&spi_host, true); - - const uint32_t cmd_write_tx = spi_create_command((spi_command_t){ - .len = COPY_DATA_UNITS*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE) - 1, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_write_tx); - spi_wait_for_ready(&spi_host); - - // Wait for SPI interrupt - while(spi_intr_flag == 0) { - wait_for_interrupt(); - } - PRINTF("triggered\n\r"); - - spi_wait_4_resp(); - - PRINTF("%d Bytes written in Flash at @ 0x%08x \n\r", COPY_DATA_UNITS*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE), FLASH_ADDR); - - -#endif //TEST_SPI_2_MEM - -#ifdef TEST_SPI_2_MEM - - PRINTF("\n\n\r======================================\n\n\r"); - PRINTF(" MEM <- <- DMA <- <- SPI <- <- FLASH "); - PRINTF("\n\n\r======================================\n\n\r"); - -#ifndef USE_SPI_FLASH - const uint8_t slot2 = DMA_TRIG_SLOT_SPI_RX; // The DMA will wait for the SPI TX FIFO ready signal -#else - const uint8_t slot2 = DMA_TRIG_SLOT_SPI_FLASH_RX; // The DMA will wait for the SPI FLASH TX FIFO ready signal - #endif - - static dma_target_t tgt3= { - .ptr = copy_data, - .inc_du = 1, - // Because the data type needs to be WORD the size needs to be normalized. - .size_du = COPY_DATA_PER_CYCLE*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)/DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE_WORD), - .trig = DMA_TRIG_MEMORY, - .type = DMA_DATA_TYPE_WORD, // Only possible to read word-wise from SPI - }; - - static dma_target_t tgt4= { - .inc_du = 0, - // Because the data type needs to be WORD the size needs to be normalized. - .size_du = COPY_DATA_PER_CYCLE*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)/DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE_WORD), - .trig = slot2, - .type = DMA_DATA_TYPE_WORD, - }; - tgt4.ptr = fifo_ptr_rx; - - static dma_trans_t trans2 = { - .src = &tgt4, - .dst = &tgt3, - .end = DMA_TRANS_END_INTR, - }; - - res = dma_validate_transaction( &trans2, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \n\r", res); - - res = dma_load_transaction(&trans2); - PRINTF("load: %u \n\r", res); - - // The address bytes sent through the SPI to the Flash are in reverse order - const int32_t read_byte_cmd = ((REVERT_24b_ADDR(FLASH_ADDR) << 8) | 0x03); - - // Fill TX FIFO with TX data (read command + 3B address) - spi_write_word(&spi_host, read_byte_cmd); - // Wait for readiness to process commands - spi_wait_for_ready(&spi_host); - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_read); - spi_wait_for_ready(&spi_host); - - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ - .len = COPY_DATA_UNITS*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE) - 1, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_set_command(&spi_host, cmd_read_rx); - spi_wait_for_ready(&spi_host); - - res = dma_launch(&trans2); - - while( ! dma_is_ready() ){ - /* wait_for_interrupt(); For small buffer sizes the interrupt arrives before going to wfi(); */ - }; - - PRINTF("triggered!\n\r"); - - // Power down flash - const uint32_t powerdown_byte_cmd = 0xb9; - spi_write_word(&spi_host, powerdown_byte_cmd); - const uint32_t cmd_powerdown = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerdown); - spi_wait_for_ready(&spi_host); - - // The data is already in memory -- Check results - PRINTF("ram vs flash...\n\r"); - - int i; - uint32_t errors = 0; - uint32_t count = 0; - for (i = 0; i -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "fast_intr_ctrl.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Simple example to check the SPI host peripheral is working. It checks the ram and flash have the same content -#define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - -volatile int8_t spi_intr_flag; -spi_host_t spi_host; -uint32_t flash_data[8]; -uint32_t flash_original[8] = {1}; - -#ifndef USE_SPI_FLASH -void fic_irq_spi(void) -{ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#else -void fic_irq_spi_flash(void) -{ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#endif - -int main(int argc, char *argv[]) -{ - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t read_byte_cmd = ((REVERT_24b_ADDR(flash_original) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { -#ifdef USE_SPI_FLASH - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; -#else - /* - if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different - as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH - */ - uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; - for(int i =0; i < 8 ; i++){ - flash_original[i] = ptr_flash[i]; - } - // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS - read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - -#endif - - } - - - // spi_host_t spi_host; - #ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - #else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); - #endif - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level fast spi interrupt - #ifndef USE_SPI_FLASH - const uint32_t mask = 1 << 20; - #else - const uint32_t mask = 1 << 21; - #endif - CSR_SET_BITS(CSR_REG_MIE, mask); - spi_intr_flag = 0; - - #ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); - #endif - - // Enable SPI host device - spi_set_enable(&spi_host, true); - - // Enable event interrupt - spi_enable_evt_intr(&spi_host, true); - // Enable RX watermark interrupt - spi_enable_rxwm_intr(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Set RX watermark to 8 word - spi_set_rx_watermark(&spi_host, 8); - - uint32_t *flash_data_ptr = flash_data[0]; - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - // Load command FIFO with command (1 Byte at single speed) - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - volatile uint32_t data_addr = flash_original; - - - // Fill TX FIFO with TX data (read command + 3B address) - spi_write_word(&spi_host, read_byte_cmd); - // Wait for readiness to process commands - spi_wait_for_ready(&spi_host); - - //////////////////////////////////////////////////////////////// - - // // Load command FIFO with read command (1 Byte at single speed) - // const uint32_t cmd_read = spi_create_command((spi_command_t){ - // .len = 0, - // .csaat = true, - // .speed = kSpiSpeedStandard, - // .direction = kSpiDirTxOnly - // }); - // spi_set_command(&spi_host, cmd_read); - // spi_wait_for_ready(&spi_host); - // // Load command FIFO with read address (3 Byte at single speed) - // const uint32_t cmd_addr = spi_create_command((spi_command_t){ - // .len = 2, - // .csaat = true, - // .speed = kSpiSpeedStandard, - // .direction = kSpiDirTxOnly - // }); - // spi_set_command(&spi_host, cmd_addr); - // spi_wait_for_ready(&spi_host); - - // OR - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_read); - spi_wait_for_ready(&spi_host); - - //////////////////////////////////////////////////////////////// - - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ - .len = 31, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_set_command(&spi_host, cmd_read_rx); - spi_wait_for_ready(&spi_host); - - // Wait transaction is finished (polling register) - // spi_wait_for_rx_watermark(&spi_host); - // or wait for SPI interrupt - PRINTF("Waiting for SPI...\n\r"); - - while( spi_intr_flag == 0 ) { - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - - if( spi_intr_flag == 0 ) - wait_for_interrupt(); - - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - } - - // Enable event interrupt - spi_enable_evt_intr(&spi_host, true); - // Enable RX watermark interrupt - spi_enable_rxwm_intr(&spi_host, true); - - // Read data from SPI RX FIFO - for (int i=0; i<8; i++) { - spi_read_word(&spi_host, &flash_data[i]); - } - - PRINTF("flash vs ram...\n\r"); - - uint32_t errors = 0; - uint32_t* ram_ptr = flash_original; - for (int i=0; i<8; i++) { - if(flash_data[i] != *ram_ptr) { - PRINTF("@%x : %x != %x\n\r", ram_ptr, flash_data[i], *ram_ptr); - errors++; - } - ram_ptr++; - } - - if (errors == 0) { - PRINTF("success!\n\r"); - } else { - PRINTF("failure, %d errors!\n\r", errors); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c deleted file mode 100644 index de6ab165..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Type of data frome the SPI. For types different than words the SPI data is requested in separate transactions -// word(0), half-word(1), byte(2,3) -#define SPI_DATA_TYPE DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD - -// Number of elements to copy -#define COPY_DATA_NUM 16 - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - -#define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) - -volatile int8_t dma_intr_flag; -spi_host_t spi_host; - -void dma_intr_handler_trans_done(void) -{ - PRINTF("Non-weak implementation of a DMA interrupt\n\r"); - dma_intr_flag = 1; -} - -// Reserve memory array -uint32_t flash_data[COPY_DATA_NUM] __attribute__ ((aligned (4))) = {0x76543210,0xfedcba98,0x579a6f90,0x657d5bee,0x758ee41f,0x01234567,0xfedbca98,0x89abcdef,0x679852fe,0xff8252bb,0x763b4521,0x6875adaa,0x09ac65bb,0x666ba334,0x44556677,0x0000ba98}; -uint32_t copy_data[COPY_DATA_NUM] __attribute__ ((aligned (4))) = { 0 }; - -#if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - #define DATA_TYPE uint32_t -#elif SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD - #define DATA_TYPE uint16_t -#else - #define DATA_TYPE uint8_t -#endif - -#define COPY_DATA_TYPE (COPY_DATA_NUM/(sizeof(uint32_t)/sizeof(DATA_TYPE))) - - -int main(int argc, char *argv[]) -{ - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t read_byte_cmd; - - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { -#ifdef USE_SPI_FLASH - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; -#else - /* - if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different - as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH - */ - uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; - for(int i =0; i < COPY_DATA_NUM ; i++){ - flash_data[i] = ptr_flash[i]; - } -#endif - - } - - - #ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - #else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); - #endif - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - #ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); - #endif - - // Enable SPI host device - spi_set_enable(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // SPI and SPI_FLASH are the same IP so same register map - uint32_t *fifo_ptr_rx = spi_host.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; - - - // DMA CONFIGURATION - PRINTF("---- TEST ---- \n\r"); - dma_init(NULL); - - - #ifndef USE_SPI_FLASH - uint8_t slot = DMA_TRIG_SLOT_SPI_RX; // The DMA will wait for the SPI RX FIFO valid signal - #else - uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; // The DMA will wait for the SPI FLASH RX FIFO valid signal - #endif - - static dma_target_t tgt_src = { - .inc_du = 0, - .size_du = COPY_DATA_NUM, - .type = SPI_DATA_TYPE, - }; - tgt_src.ptr = fifo_ptr_rx; // Necessary outside 'cause its not a const. - tgt_src.trig = slot;// Necessary outside 'cause its not a const. - - static dma_target_t tgt_dst = { - .ptr = copy_data, - .inc_du = 1, - .type = SPI_DATA_TYPE, - .trig = DMA_TRIG_MEMORY, - }; - static dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - .end = DMA_TRANS_END_INTR, - }; - - dma_config_flags_t res; - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("Result - tgt trans: %u\n\r", res ); - res = dma_load_transaction(&trans); - PRINTF("Result - tgt load: %u\n\r", res ); - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Reset - const uint32_t reset_cmd = 0xFFFFFFFF; - spi_write_word(&spi_host, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_reset); - spi_wait_for_ready(&spi_host); - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - - dma_intr_flag = 0; - res = dma_launch(&trans); - PRINTF("launched!\n\r"); - - #if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - - if(get_spi_flash_mode(&soc_ctrl) != SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO) - read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - else - // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS - read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Single transaction - .len = COPY_DATA_NUM*sizeof(DATA_TYPE) - 1, // In bytes - 1 - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_write_word(&spi_host, read_byte_cmd); // Fill TX FIFO with TX data (read command + 3B address) - spi_wait_for_ready(&spi_host); // Wait for readiness to process commands - spi_set_command(&spi_host, cmd_read); // Send read command to the external device through SPI - spi_wait_for_ready(&spi_host); - spi_set_command(&spi_host, cmd_read_rx); // Receive data in RX - spi_wait_for_ready(&spi_host); - #else - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Multiple transactions of the data type - .len = (sizeof(DATA_TYPE) - 1), - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - DATA_TYPE* flash_ptr = (DATA_TYPE *)flash_data; - for (int i = 0; i +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" + +/* By default, PRINTFs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#ifdef TARGET_PYNQ_Z2 + #define USE_SPI_FLASH +#endif + + +// Start buffers (the original data) +#include "buffer.h" +// End buffer (where what is read is stored) +uint32_t flash_data[256]; + +/* + * Assign the test buffer to the buffer to write to flash. + * The buffer is defined in the file buffer.h. As multiple buffers can + * be defined, this is userful to pick the right one. + * Also the length is specified, to test different length cases. In any case + * length <= test_buffer length. +*/ +#define TEST_BUFFER flash_original_1024B +#define LENGTH 1024 + +#ifndef ON_CHIP +#define FLASH_ONLY_WORDS 32 +#define FLASH_ONLY_BYTES (FLASH_ONLY_WORDS*4) + +int32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16))) flash_only_buffer[FLASH_ONLY_WORDS] = { + 0xABCDEF00, + 0xABCDEF01, + 0xABCDEF02, + 0xABCDEF03, + 0xABCDEF04, + 0xABCDEF05, + 0xABCDEF06, + 0xABCDEF07, + 0xABCDEF08, + 0xABCDEF09, + 0xABCDEF0A, + 0xABCDEF0B, + 0xABCDEF0C, + 0xABCDEF0D, + 0xABCDEF0E, + 0xABCDEF0F, + 0xABCDEF10, + 0xABCDEF11, + 0xABCDEF12, + 0xABCDEF13, + 0xABCDEF14, + 0xABCDEF15, + 0xABCDEF16, + 0xABCDEF17, + 0xABCDEF18, + 0xABCDEF19, + 0xABCDEF1A, + 0xABCDEF1B, + 0xABCDEF1C, + 0xABCDEF1D, + 0xABCDEF1E, + 0xABCDEF1F, +}; + +int32_t __attribute__ ((aligned (16))) flash_only_buffer_golden_value[FLASH_ONLY_WORDS] = { + 0xABCDEF00, + 0xABCDEF01, + 0xABCDEF02, + 0xABCDEF03, + 0xABCDEF04, + 0xABCDEF05, + 0xABCDEF06, + 0xABCDEF07, + 0xABCDEF08, + 0xABCDEF09, + 0xABCDEF0A, + 0xABCDEF0B, + 0xABCDEF0C, + 0xABCDEF0D, + 0xABCDEF0E, + 0xABCDEF0F, + 0xABCDEF10, + 0xABCDEF11, + 0xABCDEF12, + 0xABCDEF13, + 0xABCDEF14, + 0xABCDEF15, + 0xABCDEF16, + 0xABCDEF17, + 0xABCDEF18, + 0xABCDEF19, + 0xABCDEF1A, + 0xABCDEF1B, + 0xABCDEF1C, + 0xABCDEF1D, + 0xABCDEF1E, + 0xABCDEF1F, +}; +#endif + +// Test functions +uint32_t test_read(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_flash_only(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_dma(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_quad(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_quad_dma(uint32_t *test_buffer, uint32_t len); + +// Check function +uint32_t check_result(uint8_t *test_buffer, uint32_t len); + +// Define global status variable +w25q_error_codes_t global_status; + +int main(int argc, char *argv[]) { + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + PRINTF("BSP read test\n", LENGTH); + + // Pick the correct spi device based on simulation type + spi_host_t spi; + #ifndef USE_SPI_FLASH + spi.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); + #else + spi.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); + #endif + + // Define status variable + int32_t errors = 0; + + // Init SPI host and SPI<->Flash bridge parameters + if (w25q128jw_init(spi) != FLASH_OK) return EXIT_FAILURE; + + // Test simple read + PRINTF("Testing simple read...\n"); + errors += test_read(TEST_BUFFER, LENGTH); + +#ifndef ON_CHIP + PRINTF("Testing simple read on flash only data...\n"); + errors += test_read_flash_only(flash_only_buffer, FLASH_ONLY_BYTES); +#endif + + // Test simple read with DMA + PRINTF("Testing simple read with DMA...\n"); + errors += test_read_dma(TEST_BUFFER, LENGTH); + + // Test quad read + PRINTF("Testing quad read...\n"); + errors += test_read_quad(TEST_BUFFER, LENGTH); + + // Test quad read with DMA + PRINTF("Testing quad read with DMA...\n"); + errors += test_read_quad_dma(TEST_BUFFER, LENGTH); + + PRINTF("\n--------TEST FINISHED--------\n"); + if (errors == 0) { + PRINTF("All tests passed!\n"); + return EXIT_SUCCESS; + } else { + PRINTF("Some tests failed!\n"); + return EXIT_FAILURE; + } + +} + +uint32_t test_read(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} +#ifndef ON_CHIP +uint32_t test_read_flash_only(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = heep_get_flash_address_offset(test_buffer); + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + printf("Checking Results \n"); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(flash_only_buffer_golden_value, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} +#endif +uint32_t test_read_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard_dma(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} + +uint32_t test_read_quad(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_quad(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} + +uint32_t test_read_quad_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_quad_dma(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} + +uint32_t check_result(uint8_t *test_buffer, uint32_t len) { + uint32_t errors = 0; + uint8_t *flash_data_char = (uint8_t *)flash_data; + + for (uint32_t i = 0; i < len; i++) { + if (test_buffer[i] != flash_data_char[i]) { + PRINTF("Error at position %d: expected %x, got %x\n", i, test_buffer[i], flash_data_char[i]); + errors++; + } + } + + if (errors == 0) { + PRINTF("success!\n"); + } else { + PRINTF("failure, %d errors!\n", errors); + } + + return errors; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c new file mode 100644 index 00000000..2b1a362b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c @@ -0,0 +1,351 @@ +/** + * @file main.c + * @brief Simple spi write example using BSP + * + * Simple example that writes a 1kB buffer to flash memory at a specific address + * and then read it back to check if the data was written correctly. + * For buffers bigger than 4kB (or even smaller buffers that are not aligned to 4kB), + * the erase operation must be tweeked to erase all the sectors that contain the + * buffer. + * + * @note The application assume the correct functioning of the read operation. + * +*/ + +#include +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" + +/* By default, PRINTFs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#ifdef TARGET_PYNQ_Z2 + #define USE_SPI_FLASH +#endif + + +// what to write in flash +uint32_t flash_original_1024B[256] = { + 0x76543211, 0xfedcba99, 0x579a6f91, 0x657d5bef, 0x758ee420, 0x01234568, 0xfedbca97, 0x89abde00, + 0x76543212, 0xfedcba9a, 0x579a6f92, 0x657d5bf0, 0x758ee421, 0x01234569, 0xfedbca98, 0x89abde01, + 0x76543213, 0xfedcba9b, 0x579a6f93, 0x657d5bf1, 0x758ee422, 0x0123456a, 0xfedbca99, 0x89abde02, + 0x76543214, 0xfedcba9c, 0x579a6f94, 0x657d5bf2, 0x758ee423, 0x0123456b, 0xfedbca9a, 0x89abde03, + 0x76543215, 0xfedcba9d, 0x579a6f95, 0x657d5bf3, 0x758ee424, 0x0123456c, 0xfedbca9b, 0x89abde04, + 0x76543216, 0xfedcba9e, 0x579a6f96, 0x657d5bf4, 0x758ee425, 0x0123456d, 0xfedbca9c, 0x89abde05, + 0x76543217, 0xfedcba9f, 0x579a6f97, 0x657d5bf5, 0x758ee426, 0x0123456e, 0xfedbca9d, 0x89abde06, + 0x76543218, 0xfedcbaa0, 0x579a6f98, 0x657d5bf6, 0x758ee427, 0x0123456f, 0xfedbca9e, 0x89abde07, + 0x76543219, 0xfedcbaa1, 0x579a6f99, 0x657d5bf7, 0x758ee428, 0x01234570, 0xfedbca9f, 0x89abde08, + 0x7654321a, 0xfedcbaa2, 0x579a6f9a, 0x657d5bf8, 0x758ee429, 0x01234571, 0xfedbcaa0, 0x89abde09, + 0x7654321b, 0xfedcbaa3, 0x579a6f9b, 0x657d5bf9, 0x758ee42a, 0x01234572, 0xfedbcaa1, 0x89abde0a, + 0x7654321c, 0xfedcbaa4, 0x579a6f9c, 0x657d5bfa, 0x758ee42b, 0x01234573, 0xfedbcaa2, 0x89abde0b, + 0x7654321d, 0xfedcbaa5, 0x579a6f9d, 0x657d5bfb, 0x758ee42c, 0x01234574, 0xfedbcaa3, 0x89abde0c, + 0x7654321e, 0xfedcbaa6, 0x579a6f9e, 0x657d5bfc, 0x758ee42d, 0x01234575, 0xfedbcaa4, 0x89abde0d, + 0x7654321f, 0xfedcbaa7, 0x579a6f9f, 0x657d5bfd, 0x758ee42e, 0x01234576, 0xfedbcaa5, 0x89abde0e, + 0x76543220, 0xfedcbaa8, 0x579a6fa0, 0x657d5bfe, 0x758ee42f, 0x01234577, 0xfedbcaa6, 0x89abde0f, + 0x76543221, 0xfedcbaa9, 0x579a6fa1, 0x657d5bff, 0x758ee430, 0x01234578, 0xfadbcaa7, 0x89abde10, + 0x76543222, 0xfedcbaaa, 0x579a6fa2, 0x657d5c00, 0x758ee431, 0x01234579, 0xfadbcaa8, 0x89abde11, + 0x76543223, 0xfedcbaab, 0x579a6fa3, 0x657d5c01, 0x758ee432, 0x0123457a, 0xfadbcaa9, 0x89abde12, + 0x76543224, 0xfedcbaac, 0x579a6fa4, 0x657d5c02, 0x758ee433, 0x0123457b, 0xfadbcaaa, 0x89abde13, + 0x76543225, 0xfedcbaad, 0x579a6fa5, 0x657d5c03, 0x758ee434, 0x0123457c, 0xfadbcaab, 0x89abde14, + 0x76543226, 0xfedcbaae, 0x579a6fa6, 0x657d5c04, 0x758ee435, 0x0123457d, 0xfadbcaac, 0x89abde15, + 0x76543227, 0xfedcbaaf, 0x579a6fa7, 0x657d5c05, 0x758ee436, 0x0123457e, 0xfadbcaad, 0x89abde16, + 0x76543228, 0xfedcbab0, 0x579a6fa8, 0x657d5c06, 0x758ee437, 0x0123457f, 0xfadbcaae, 0x89abde17, + 0x76543220, 0xfedcbaa8, 0x579a6fa0, 0x657d5bfe, 0x758ee42f, 0x01234577, 0xfedbcaa6, 0x89abde0f, + 0x76543221, 0xfedcbaa9, 0x579a6fa1, 0x657d5bff, 0x758ee430, 0x01234578, 0xfadbcaa7, 0x89abde10, + 0x76543222, 0xfedcbaaa, 0x579a6fa2, 0x657d5c00, 0x758ee431, 0x01234579, 0xfadbcaa8, 0x89abde11, + 0x76543223, 0xfedcbaab, 0x579a6fa3, 0x657d5c01, 0x758ee432, 0x0123457a, 0xfadbcaa9, 0x89abde12, + 0x76543224, 0xfedcbaac, 0x579a6fa4, 0x657d5c02, 0x758ee433, 0x0123457b, 0xfadbcaaa, 0x89abde13, + 0x76543225, 0xfedcbaad, 0x579a6fa5, 0x657d5c03, 0x758ee434, 0x0123457c, 0xfadbcaab, 0x89abde14, + 0x76543226, 0xfedcbaae, 0x579a6fa6, 0x657d5c04, 0x758ee435, 0x0123457d, 0xfadbcaac, 0x89abde15, + 0x76543227, 0xfedcbaaf, 0x579a6fa7, 0x657d5c05, 0x758ee436, 0x0123457e, 0xfadbcaad, 0x89abde16, + 0x76543228, 0xfedcbab0, 0x579a6fa8, 0x657d5c06, 0x758ee437, 0x0123457f, 0xfadbcaae, 0x89abde17 +}; + +// End buffer (where what is read is stored) +uint32_t flash_read_data[256]; + +#define BYTES_TO_WRITE 533 //in bytes, must be less than 256*4=1024 + +// address to which we write in FLASH, we do not initiliaze it to 0 as we do not want into the BSS +// otherwise the compilers/linker won't allocate this to the .data section, thus not written in flash +// If not written in flash, after erasing the block this array would be all '0xFF', and this would loose +// generality of the testing as without erasing, the write operation in flash can bring 1->0 but not viceversa +// by initializing to another number, we are sure it goes to .data section and written in flash +uint32_t __attribute__ ((aligned (16))) flash_write_buffer[256] = { + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA +}; + +#ifndef ON_CHIP +int32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16))) flash_only_write_buffer[256]; +#endif + +// Test functions +uint32_t test_write(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_dma(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_quad(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_quad_dma(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_flash_only(uint32_t *test_buffer, uint32_t len); + +// Check function +uint32_t check_result(uint8_t *test_buffer, uint32_t len); + +// Erase memory function +void erase_memory(uint32_t addr); + +// Define global status variable +w25q_error_codes_t global_status; + +int main(int argc, char *argv[]) { + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + PRINTF("BSP write test\n"); + + // Pick the correct spi device + spi_host_t spi; + #ifndef USE_SPI_FLASH + spi.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); + #else + spi.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); + #endif + + // Define status variable + int32_t errors = 0; + + // Init SPI host and SPI<->Flash bridge parameters + if (w25q128jw_init(spi) != FLASH_OK) return EXIT_FAILURE; + + // Test simple write + PRINTF("Testing simple write...\n"); + errors += test_write(flash_original_1024B, BYTES_TO_WRITE); + +#ifndef ON_CHIP + // Test simple write on flash_only data + PRINTF("Testing simple write. on flash only data..\n"); + errors += test_write_flash_only(flash_original_1024B, BYTES_TO_WRITE); +#endif + + + // Test simple write with DMA + PRINTF("Testing simple write with DMA...\n"); + errors += test_write_dma(flash_original_1024B, BYTES_TO_WRITE); + + // Test quad write + PRINTF("Testing quad write...\n"); + errors += test_write_quad(flash_original_1024B, BYTES_TO_WRITE); + + // Test quad write with DMA + PRINTF("Testing quad write with DMA...\n"); + errors += test_write_quad_dma(flash_original_1024B, BYTES_TO_WRITE); + + PRINTF("\n--------TEST FINISHED--------\n"); + if (errors == 0) { + PRINTF("All tests passed!\n"); + return EXIT_SUCCESS; + } else { + PRINTF("Some tests failed!\n"); + return EXIT_FAILURE; + } +} + + +uint32_t test_write(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_standard(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} + +uint32_t test_write_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_standard_dma(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} + +uint32_t test_write_quad(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_quad(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} + +uint32_t test_write_quad_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_quad_dma(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} +#ifndef ON_CHIP +uint32_t test_write_flash_only(uint32_t *test_buffer, uint32_t len) { + + //remove FLASH offset as required by the BSP, flash_only_write_buffer is only mapped to the LMA + uint32_t *test_buffer_flash = heep_get_flash_address_offset(flash_only_write_buffer); + + // Clean memory + erase_memory(test_buffer_flash); + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_standard(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} +#endif +uint32_t check_result(uint8_t *test_buffer, uint32_t len) { + uint32_t errors = 0; + uint8_t *flash_read_data_char = (uint8_t *)flash_read_data; + + for (uint32_t i = 0; i < len; i++) { + if (test_buffer[i] != flash_read_data_char[i]) { + PRINTF("Error at position %d: expected %x, got %x\n", i, test_buffer[i], flash_read_data_char[i]); + errors++; + } + } + + if (errors == 0) { + PRINTF("success!\n"); + } else { + PRINTF("failure, %d errors!\n", errors); + } + + return errors; +} + +// Erase the memory only if FPGA is used +void erase_memory(uint32_t addr) { + #ifdef USE_SPI_FLASH + w25q128jw_4k_erase(addr); + #endif +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c deleted file mode 100644 index e1e16f56..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c +++ /dev/null @@ -1,222 +0,0 @@ - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "rv_timer.h" -#include "rv_timer_regs.h" -#include "soc_ctrl.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" -#include "spi_host.h" -#include "spi_host_regs.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "gpio.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - -#define REVERT_24b_ADDR(addr) ((((uint32_t)addr & 0xff0000) >> 16) | ((uint32_t)addr & 0xff00) | (((uint32_t)addr & 0xff) << 16)) -#define FLASH_ADDR 0x00000000 -#define FLASH_SIZE 64 * 1024 * 1024 -#define FLASH_CLK_MAX_HZ (133 * 1000 * 1000) - - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Interrupt controller variables -plic_result_t plic_res; -uint32_t intr_num; - -//volatile int8_t timer_flag; -volatile int8_t spi_intr_flag; - -spi_host_t spi_host_flash; - -void dma_intr_handler_trans_done(){ - PRINTF("#\n\r"); -} - -void fic_irq_spi_flash(){ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host_flash, false); - spi_enable_rxwm_intr(&spi_host_flash, false); - spi_intr_flag = 1; - PRINTF("@\n\r"); -} - - -void write_to_flash(spi_host_t *SPI, uint16_t *data, uint32_t byte_count, uint32_t addr) -{ - uint32_t write_to_mem = 0x02; - spi_write_word(SPI, write_to_mem); - uint32_t cmd_write_to_mem = spi_create_command((spi_command_t){ - .len = 0, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(SPI, cmd_write_to_mem); - spi_wait_for_ready(SPI); - - uint32_t addr_cmd = __builtin_bswap32(addr); - spi_write_word(SPI, addr_cmd); - uint32_t cmd_address = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(SPI, cmd_address); - spi_wait_for_ready(SPI); - - uint32_t *fifo_ptr_tx = SPI->base_addr.base + SPI_HOST_TXDATA_REG_OFFSET; - - // -- DMA CONFIGURATION -- - dma_init(NULL); - - dma_target_t tgt_src = { - .ptr = data, - .inc_du = 1, - .size_du = 64, - .type = DMA_DATA_TYPE_HALF_WORD, - .trig = DMA_TRIG_MEMORY, - }; - dma_target_t tgt_dst = { - .ptr = fifo_ptr_tx, - .inc_du = 0, - .size_du = 0, - .type = DMA_DATA_TYPE_HALF_WORD, - .trig = DMA_TRIG_SLOT_SPI_FLASH_TX, - }; - dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - .end = DMA_TRANS_END_INTR, - }; - - dma_config_flags_t res; - - spi_intr_flag = 0; - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("trans: %u\n\r", res ); - res = dma_load_transaction(&trans); - PRINTF("load: %u\n\r", res ); - res = dma_launch(&trans); - - // Wait for the first data to arrive to the TX FIFO before enabling interrupt - spi_wait_for_tx_not_empty(SPI); - // Enable event interrupt - spi_enable_evt_intr(SPI, true); - // Enable TX empty interrupt - spi_enable_txempty_intr(SPI, true); - - const uint32_t cmd_write_tx = spi_create_command((spi_command_t){ - .len = byte_count - 1, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(SPI, cmd_write_tx); - spi_wait_for_ready(SPI); - - // Wait for SPI interrupt - while(spi_intr_flag == 0) { - wait_for_interrupt(); - } - - PRINTF("%d words written to flash.\n\n\r", byte_count/4); -} - -int main(int argc, char *argv[]) -{ - // Get current Frequency - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - soc_ctrl_select_spi_host(&soc_ctrl); - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - uint32_t mask = 1 << 21; - CSR_SET_BITS(CSR_REG_MIE, mask); - spi_intr_flag = 0; - // Set mie.MEIE bit to one to enable timer interrupt - mask = 1 << 7; - CSR_SET_BITS(CSR_REG_MIE, mask); - - spi_host_flash.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - spi_set_enable(&spi_host_flash, true); - spi_output_enable(&spi_host_flash, true); - - uint16_t clk_div = 0; - if (FLASH_CLK_MAX_HZ < core_clk / 2) - { - clk_div = (core_clk / (FLASH_CLK_MAX_HZ)-2) / 2; // The value is truncated - if (core_clk / (2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) - clk_div += 1; // Adjust if the truncation was not 0 - } - - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg_flash = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0}); - spi_set_configopts(&spi_host_flash, 0, chip_cfg_flash); - spi_set_csid(&spi_host_flash, 0); - - // To set the number of dummy cycles we have to send command 0x11 and then a 1B value - const uint32_t reset_cmd = 0x11; - spi_write_word(&spi_host_flash, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 0, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host_flash, cmd_reset); - spi_wait_for_ready(&spi_host_flash); - - const uint32_t set_dummy_cycle = 0x07; - spi_write_word(&spi_host_flash, set_dummy_cycle); - const uint32_t cmd_set_dummy = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - - spi_set_command(&spi_host_flash, cmd_set_dummy); - spi_wait_for_ready(&spi_host_flash); - - uint32_t results[32]; - for(uint32_t i = 0; i < 32; i++){ - results[i] = i; - } - - write_to_flash(&spi_host_flash, results, sizeof(*results) * 32, FLASH_ADDR); - - PRINTF("Success.\n\r"); - - return EXIT_SUCCESS; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg new file mode 100644 index 00000000..0583bdfe --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg @@ -0,0 +1,67 @@ +############################################################################### +# +# Copyright 2020 OpenHW Group +# +# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://solderpad.org/licenses/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +# +############################################################################### + +# This is a python setting of parameters for the architecture. The following +# parameters may be set (other keys are silently ignored). Defaults are shown +# in brackets +# - cc ('cc') +# - ld (same value as for cc) +# - cflags ([]) +# - ldflags ([]) +# - cc_define_pattern ('-D{0}') +# - cc_incdir_pattern ('-I{0}') +# - cc_input_pattern ('{0}') +# - cc_output_pattern ('-o {0}') +# - ld_input_pattern ('{0}') +# - ld_output_pattern ('-o {0}') +# - user_libs ([]) +# - dummy_libs ([]) +# - cpu_mhz (1) +# - warmup_heat (1) + +# The "flags" and "libs" parameters (cflags, ldflags, user_libs, dummy_libs) +# should be lists of arguments to be passed to the compile or link line as +# appropriate. Patterns are Python format patterns used to create arguments. +# Thus for GCC or Clang/LLVM defined constants can be passed using the prefix +# '-D', and the pattern '-D{0}' would be appropriate (which happens to be the +# default). + +# "user_libs" may be absolute file names or arguments to the linker. In the +# latter case corresponding arguments in ldflags may be needed. For example +# with GCC or Clang/LLVM is "-l" flags are used in "user_libs", the "-L" flags +# may be needed in "ldflags". + +# Dummy libs have their source in the "support" subdirectory. Thus if 'crt0' +# is specified, there should be a source file 'dummy-crt0.c' in the support +# directory. + +# There is no need to set an unused parameter, and this file may be empty to +# set no flags. + +# Parameter values which are duplicated in architecture, board, chip or +# command line are used in the following order of priority +# - default value +# - architecture specific value +# - chip specific value +# - board specific value +# - command line value + +# For flags, this priority is applied to individual flags, not the complete +# list of flags. diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c new file mode 100644 index 00000000..5e55329f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c @@ -0,0 +1,177 @@ +/* BEEBS local library variants + + Copyright (C) 2019 Embecosm Limited. + + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +/* These are very simple local versions of library routines, to ensure the + code is compiled with the flags used for the benchmark. Not all library + routines are here, just ones that cause a lot of unecessary load, or where + there is variation between platforms and architectures. */ + +#include +#include +#include "beebsc.h" + +/* Seed for the random number generator */ + +static long int seed = 0; + +/* Heap records and sane initial values */ + +static void *heap_ptr = NULL; +static void *heap_end = NULL; +static size_t heap_requested = 0; + + +/* Yield a sequence of random numbers in the range [0, 2^15-1]. + + long int is guaranteed to be at least 32 bits. The seed only ever uses 31 + bits (so is positive). + + For BEEBS this gets round different operating systems using different + multipliers and offsets and RAND_MAX variations. */ + +int +rand_beebs (void) +{ + seed = (seed * 1103515245L + 12345) & ((1UL << 31) - 1); + return (int) (seed >> 16); +} + + +/* Initialize the random number generator */ + +void +srand_beebs (unsigned int new_seed) +{ + seed = (long int) new_seed; +} + + +/* Initialize the BEEBS heap pointers. Note that the actual memory block is + in the caller code. */ + +void +init_heap_beebs (void *heap, size_t heap_size) +{ + heap_ptr = (void *) heap; + heap_end = (void *) ((char *) heap_ptr + heap_size); + heap_requested = 0; +} + + +/* Report if malloc ever failed. + + Return non-zero (TRUE) if malloc did not reqest more than was available + since the last call to init_heap_beebs, zero (FALSE) otherwise. */ + +int +check_heap_beebs (void *heap) +{ + return ((void *) ((char *) heap + heap_requested) <= heap_end); +} + + +/* BEEBS version of malloc. + + This is primarily to reduce library and OS dependencies. Malloc is + generally not used in embedded code, or if it is, only in well defined + contexts to pre-allocate a fixed amount of memory. So this simplistic + implementation is just fine. + + Note in particular the assumption that memory will never be freed! */ + +void * +malloc_beebs (size_t size) +{ + void *new_ptr = heap_ptr; + + heap_requested += size; + + if (((void *) ((char *) heap_ptr + size) > heap_end) || (0 == size)) + return NULL; + else + { + heap_ptr = (void *) ((char *) heap_ptr + size); + return new_ptr; + } +} + + +/* BEEBS version of calloc. + + Implement as wrapper for malloc */ + +void * +calloc_beebs (size_t nmemb, size_t size) +{ + void *new_ptr = malloc_beebs (nmemb * size); + + /* Calloc is defined to zero the memory. OK to use a function here, because + it will be handled specially by the compiler anyway. */ + + if (NULL != new_ptr) + memset (new_ptr, 0, nmemb * size); + + return new_ptr; +} + + +/* BEEBS version of realloc. + + This is primarily to reduce library and OS dependencies. We just have to + allocate new memory and copy stuff across. */ + +void * +realloc_beebs (void *ptr, size_t size) +{ + void *new_ptr = heap_ptr; + + heap_requested += size; + + if (((void *) ((char *) heap_ptr + size) > heap_end) || (0 == size)) + return NULL; + else + { + heap_ptr = (void *) ((char *) heap_ptr + size); + + /* This is clunky, since we don't know the size of the original + pointer. However it is a read only action and we know it must + be big enough if we right off the end, or we couldn't have + allocated here. If the size is smaller, it doesn't matter. */ + + if (NULL != ptr) + { + size_t i; + + for (i = 0; i < size; i++) + ((char *) new_ptr)[i] = ((char *) ptr)[i]; + } + + return new_ptr; + } +} + + +/* BEEBS version of free. + + For our simplified version of memory handling, free can just do nothing. */ + +void +free_beebs (void *ptr __attribute__ ((unused))) +{ +} + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h new file mode 100644 index 00000000..4a108959 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h @@ -0,0 +1,65 @@ +/* BEEBS local library variants header + + Copyright (C) 2019 Embecosm Limited. + + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef BEEBSC_H +#define BEEBSC_H + +#include + +/* BEEBS fixes RAND_MAX to its lowest permitted value, 2^15-1 */ + +#ifdef RAND_MAX +#undef RAND_MAX +#endif +#define RAND_MAX ((1U << 15) - 1) + +/* Common understanding of a "small value" (epsilon) for floating point + comparisons. */ + +#define VERIFY_DOUBLE_EPS 1.0e-13 +#define VERIFY_FLOAT_EPS 1.0e-5 + +/* Simplified assert. + + The full complexity of assert is not needed for a benchmark. See the + discussion at: + + https://lists.librecores.org/pipermail/embench/2019-August/000007.html + + This function just*/ + +#define assert_beebs(expr) { if (!(expr)) exit (1); } + +#define float_eq_beebs(exp, actual) (fabsf(exp - actual) < VERIFY_FLOAT_EPS) +#define float_neq_beebs(exp, actual) !float_eq_beebs(exp, actual) +#define double_eq_beebs(exp, actual) (fabs(exp - actual) < VERIFY_DOUBLE_EPS) +#define double_neq_beebs(exp, actual) !double_eq_beebs(exp, actual) + +/* Local simplified versions of library functions */ + +int rand_beebs (void); +void srand_beebs (unsigned int new_seed); + +void init_heap_beebs (void *heap, const size_t heap_size); +int check_heap_beebs (void *heap); +void *malloc_beebs (size_t size); +void *calloc_beebs (size_t nmemb, size_t size); +void *realloc_beebs (void *ptr, size_t size); +void free_beebs (void *ptr); +#endif /* BEEBSC_H */ + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c new file mode 100644 index 00000000..db8fafa8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c @@ -0,0 +1,22 @@ +/* Common board.c for the benchmarks + + Copyright (C) 2018-2019 Embecosm Limited + + Contributor: Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +/* This is just a wrapper for the board specific support file. */ + +#include "boardsupport.c" + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c new file mode 100644 index 00000000..f2e674de --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c @@ -0,0 +1,21 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + +#include "boardsupport.h" + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h new file mode 100644 index 00000000..6223cd68 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h @@ -0,0 +1,21 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + + + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c new file mode 100644 index 00000000..37ac28fe --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c @@ -0,0 +1,32 @@ +/* Common board.c for the benchmarks + + Copyright (C) 2018-2019 Embecosm Limited + + Contributor: Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +/* This is just a wrapper for the chip specific support file if there is one. */ + +/*#include "config.h"*/ + +#ifdef HAVE_CHIPSUPPORT_H +#include "chipsupport.c" +#endif + +/* Standard C does not permit empty translation units, so provide one. */ + +static void +empty_func () +{ +} + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c new file mode 100644 index 00000000..3228651d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c @@ -0,0 +1,73 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + +#include +#include +#include +#include "chipsupport.h" + +#include "csr.h" +#include "x-heep.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#define FS_INITIAL 0x01 + +void +initialise_board () +{ + PRINTF("Initialize board corev32 \n"); + + //enable FP operations + CSR_SET_BITS(CSR_REG_MSTATUS, (FS_INITIAL << 13)); + +} + +void __attribute__ ((noinline)) __attribute__ ((externally_visible)) +start_trigger () +{ + PRINTF("start of test \n"); + + // Enable mcycle counter and read value + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + +} + +void __attribute__ ((noinline)) __attribute__ ((externally_visible)) +stop_trigger () +{ + uint32_t cycle_cnt; + CSR_READ(CSR_REG_MCYCLE, &cycle_cnt); + PRINTF("end of test \n"); + PRINTF("Result is given in CPU cycles \n"); + PRINTF("RES: %d \n", cycle_cnt); + +} + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h new file mode 100644 index 00000000..bd174c31 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h @@ -0,0 +1,25 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + +#ifndef CHIPSUPPORT_H +#define CHIPSUPPORT_H + +#define CPU_MHZ 1 + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c new file mode 100644 index 00000000..0cabd55b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c @@ -0,0 +1,292 @@ +/* BEEBS minver benchmark + + This version, copyright (C) 2014-2019 Embecosm Limited and University of + Bristol + + Contributor Pierre Langlois + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later + + ************************************************************************* + * * + * SNU-RT Benchmark Suite for Worst Case Timing Analysis * + * ===================================================== * + * Collected and Modified by S.-S. Lim * + * sslim@archi.snu.ac.kr * + * Real-Time Research Group * + * Seoul National University * + * * + * * + * < Features > - restrictions for our experimental environment * + * * + * 1. Completely structured. * + * - There are no unconditional jumps. * + * - There are no exit from loop bodies. * + * (There are no 'break' or 'return' in loop bodies) * + * 2. No 'switch' statements. * + * 3. No 'do..while' statements. * + * 4. Expressions are restricted. * + * - There are no multiple expressions joined by 'or', * + * 'and' operations. * + * 5. No library calls. * + * - All the functions needed are implemented in the * + * source file. * + * * + * * + ************************************************************************* + * * + * FILE: minver.c * + * SOURCE : Turbo C Programming for Engineering by Hyun Soo Ahn * + * * + * DESCRIPTION : * + * * + * Matrix inversion for 3x3 floating point matrix. * + * * + * REMARK : * + * * + * EXECUTION TIME : * + * * + * * + ************************************************************************* + +*/ + +#include +#include +#include "support.h" + +/* This scale factor will be changed to equalise the runtime of the + benchmarks. */ +#define LOCAL_SCALE_FACTOR 555 + +int minver (int row, int col, float eps); +int mmul (int row_a, int col_a, int row_b, int col_b); + +static float a_ref[3][3] = { + {3.0, -6.0, 7.0}, + {9.0, 0.0, -5.0}, + {5.0, -8.0, 6.0}, +}; + +static float b[3][3] = { + {-3.0, 0.0, 2.0}, + {3.0, -2.0, 0.0}, + {0.0, 2.0, -3.0}, +}; + +static float a[3][3], c[3][3], d[3][3], det; + +static float +minver_fabs (float n) +{ + float f; + + if (n >= 0) + f = n; + else + f = -n; + return f; +} + +int +mmul (int row_a, int col_a, int row_b, int col_b) +{ + int i, j, k, row_c, col_c; + float w; + + row_c = row_a; + col_c = col_b; + + if (row_c < 1 || row_b < 1 || col_c < 1 || col_a != row_b) + return (999); + for (i = 0; i < row_c; i++) + { + for (j = 0; j < col_c; j++) + { + w = 0.0; + for (k = 0; k < row_b; k++) + w += a[i][k] * b[k][j]; + c[i][j] = w; + } + } + + return (0); +} + + +int +minver (int row, int col, float eps) +{ + int work[500], i, j, k, r, iw, u, v; + float w, wmax, pivot, api, w1; + + r = w = 0; + if (row < 2 || row > 500 || eps <= 0.0) + return (999); + w1 = 1.0; + for (i = 0; i < row; i++) + work[i] = i; + for (k = 0; k < row; k++) + { + wmax = 0.0; + for (i = k; i < row; i++) + { + w = minver_fabs (a[i][k]); + if (w > wmax) + { + wmax = w; + r = i; + } + } + pivot = a[r][k]; + api = minver_fabs (pivot); + if (api <= eps) + { + det = w1; + return (1); + } + w1 *= pivot; + u = k * col; + v = r * col; + if (r != k) + { + w1 = -w; + iw = work[k]; + work[k] = work[r]; + work[r] = iw; + for (j = 0; j < row; j++) + { + w = a[k][j]; + a[k][j] = a[r][j]; + a[r][j] = w; + } + } + for (i = 0; i < row; i++) + a[k][i] /= pivot; + for (i = 0; i < row; i++) + { + if (i != k) + { + v = i * col; + w = a[i][k]; + if (w != 0.0) + { + for (j = 0; j < row; j++) + if (j != k) + a[i][j] -= w * a[k][j]; + a[i][k] = -w / pivot; + } + } + } + a[k][k] = 1.0 / pivot; + } + + for (i = 0; i < row; i++) + { + while (1) + { + k = work[i]; + if (k == i) + break; + iw = work[k]; + work[k] = work[i]; + work[i] = iw; + for (j = 0; j < row; j++) + { + u = j * col; + w = a[k][i]; + a[k][i] = a[k][k]; + a[k][k] = w; + } + } + } + + det = w1; + + return (0); +} + + +int +verify_benchmark (int res __attribute ((unused))) +{ + int i, j; + float eps = 1.0e-6; + + static float c_exp[3][3] = { + {-27.0, 26.0, -15.0}, + {-27.0, -10.0, 33.0}, + {-39.0, 28.0, -8.0} + }; + + static float d_exp[3][3] = { + {0.133333325, -0.199999958, 0.2666665910}, + {-0.519999862, 0.113333330, 0.5266665220}, + {0.479999840, -0.359999895, 0.0399999917} + }; + + /* Allow small errors in floating point */ + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + if (float_neq_beebs(c[i][j], c_exp[i][j]) || float_neq_beebs(d[i][j], d_exp[i][j])) + return 0; + + return float_eq_beebs(det, -16.6666718); +} + + +void +initialise_benchmark (void) +{ +} + + +static int benchmark_body (int rpt); + +void +warm_caches (int heat) +{ + int res = benchmark_body (heat); + + return; +} + + +int +benchmark (void) +{ + return benchmark_body (LOCAL_SCALE_FACTOR * 1); +} + + +static int __attribute__ ((noinline)) +benchmark_body (int rpt) +{ + int i; + + for (i = 0; i < rpt; i++) + { + float eps = 1.0e-6; + + memcpy (a, a_ref, 3 * 3 * sizeof (a[0][0])); + minver (3, 3, eps); + memcpy (d, a, 3 * 3 * sizeof (a[0][0])); + memcpy (a, a_ref, 3 * 3 * sizeof (a[0][0])); + mmul (3, 3, 3, 3); + } + + return 0; +} + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c new file mode 100644 index 00000000..64566101 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c @@ -0,0 +1,50 @@ +/* Common main.c for the benchmarks + + Copyright (C) 2014 Embecosm Limited and University of Bristol + Copyright (C) 2018-2019 Embecosm Limited + + Contributor: James Pallister + Contributor: Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +#include "csr.h" +#include "x-heep.h" + +#include "support.h" + + +int __attribute__ ((used)) +main (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + int i; + volatile int result; + int correct; + + initialise_board (); + initialise_benchmark (); + warm_caches (1); + + start_trigger (); + result = benchmark (); + stop_trigger (); + + /* bmarks that use arrays will check a global array rather than int result */ + + correct = verify_benchmark (result); + + return (!correct); + +} /* main () */ + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h new file mode 100644 index 00000000..b68b81e6 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h @@ -0,0 +1,72 @@ +/* Support header for BEEBS. + + Copyright (C) 2014 Embecosm Limited and the University of Bristol + Copyright (C) 2019 Embecosm Limited + + Contributor James Pallister + + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef SUPPORT_H +#define SUPPORT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Include board support header if we have one */ + +#ifdef HAVE_BOARDSUPPORT_H +#include "boardsupport.h" +#endif + +/* Benchmarks must implement verify_benchmark, which must return -1 if no + verification is done. */ + +int verify_benchmark (int result); + +/* Standard functions implemented for each board */ + +void initialise_board (void); +void start_trigger (void); +void stop_trigger (void); + +/* Every benchmark implements this for one-off data initialization. This is + only used for initialization that is independent of how often benchmark () + is called. */ + +void initialise_benchmark (void); + +/* Every benchmark implements this for cache warm up, typically calling + benchmark several times. The argument controls how much warming up is + done, with 0 meaning no warming. */ + +void warm_caches (int temperature); + +/* Every benchmark implements this as its entry point. Don't allow it to be + inlined! */ + +int benchmark (void) __attribute__ ((noinline)); + +/* Every benchmark must implement this to validate the result of the + benchmark. */ + +int verify_benchmark (int res); + +/* Local simplified versions of library functions */ + +#include "beebsc.h" + +#endif /* SUPPORT_H */ + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c new file mode 100644 index 00000000..5c7763f5 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c @@ -0,0 +1,1449 @@ +/* + ******************* +******************************* C SOURCE FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : w25q.c +** version : 1 +** date : 1/11/2023 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ +/** +* @file w25q.c +* @date 1/11/2023 +* @brief Source file of the W25Q-family flash memory driver. +*/ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ +#include "string.h" + +#include "w25q128jw.h" + +/* To manage addresses. */ +#include "mmio.h" + +/* To manage interrupts. */ +#include "fast_intr_ctrl.h" +#include "csr.h" +#include "stdasm.h" + +/* To manage DMA. */ +#include "dma.h" + +/* To get TX and RX FIFO depth */ +#include "spi_host_regs.h" + +/* To get the target of the compilation (sim or pynq) */ +#include "x-heep.h" + +/* To get the soc_ctrl base address */ +#include "soc_ctrl_structs.h" + +/* For word swap operations*/ +#include "bitfield.h" + +/****************************************************************************/ +/** **/ +/* DEFINITIONS AND MACROS */ +/** **/ +/****************************************************************************/ + +/** + * The flash is expecting the address in Big endian format, so a swap is needed + * in order to provide the MSB first. + * Shift is needed as the byteswap is performed on 32-bit words. +*/ +#define REVERT_24b_ADDR(addr) (bitfield_byteswap32(addr) >> 8) + +/** + * @bref If the target is the FPGA, use the SPI FLASH. +*/ +#ifdef TARGET_PYNQ_Z2 +#define USE_SPI_FLASH +#endif + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +/** + * @brief Power up the flash. +*/ +static void flash_power_up(void); + +/** + * @brief Set the QE bit in the flash status register. + * + * @return FLASH_OK if the QE bit is set, @ref error_codes otherwise. +*/ +static w25q_error_codes_t set_QE_bit(void); + +/** + * @brief Configure the SPI<->Flash connection paramethers. +*/ +static void configure_spi(void); + +/** + * @brief Wait for the flash to be ready. + * + * It pools the BUSY bit in the flash status register. + * It is not checking the SUS bit status. +*/ +static void flash_wait(void); + +/** + * @brief Reset the flash. +*/ +static void flash_reset(void); + +/** + * @brief Erase the flash and write the data. + * + * It read 4k (a sector) at a time, erase it and write the data back. + * Befor writing the data back, it modifies the buffer in order to + * add the new data without modifing the other bytes. All the bytes + * that are not going to be modified will be copied back as is. + * + * @param addr 24-bit address to write to. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +static w25q_error_codes_t erase_and_write(uint32_t addr, uint8_t *data ,uint32_t length); + +/** + * @brief Wrapper for page write. + * + * It performs the sanity checks and calls the page_write function with + * the correct speed paramether. A wrapper is necessary as it is not possible + * to program more than a page (256 bytes) at a time. So multiple calls + * to page_write can be needed. + * + * @param addr 24-bit address to write to. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @param quad if 1, the write is performed at quad speed. + * @param dma if 1, the write is performed using DMA. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +static w25q_error_codes_t page_write_wrapper(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma); + +/** + * @brief Write (up to) a page to the flash. + * + * @param addr 24-bit address to write to. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @param quad if 1, the write is performed at quad speed. + * @param dma if 1, the write is performed using DMA. +*/ +static w25q_error_codes_t page_write(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma); + +/** + * @brief Copy length bytes from data to the SPI TX FIFO, using DMA. + * + * @param data pointer to the data buffer. + * @param length number of bytes to copy. + + * @return FLASH_OK if the operation is successful, @ref error_codes otherwise. +*/ +static w25q_error_codes_t dma_send_toflash(uint8_t *data, uint32_t length); + +/** + * @brief Enable flash write. + * + * It sets the WEL bit in the flash status register. + * Every action that require the WEL to be set is goig to automatically + * clear it. +*/ +static void flash_write_enable(void); + +/** + * @brief Performs sanity checks on the input parameters. + * + * Checks if the address is valid, the data pointer is not NULL + * and the length is not 0. + * + * @param addr 24-bit address. + * @param data pointer to the data buffer. + * @param length number of bytes to read/write. + * @return FLASH_OK if the sanity checks are passed, @ref error_codes otherwise. +*/ +static w25q_error_codes_t w25q128jw_sanity_checks(uint32_t addr, uint8_t *data, uint32_t length); + +/** + * @brief Return the minimum between two numbers. + * + * The function uses signed integers in order to handle also negative numbers. + * + * @param a first number. + * @param b second number. + * @return the minimum between a and b. +*/ +static int32_t MIN(int32_t a, int32_t b) { + return (a < b) ? a : b; +} + + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +/** + * @brief SPI structure. +*/ +spi_host_t __attribute__((section(".xheep_init_data_crt0"))) spi; //this variable is also used by the crt0, thus keep it in this section + +/** + * @brief Static vector used in the erase_and_write function. + * + * It is used to store the data of a sector (4k) of the flash. Given the dimensions + * of the vector, is not possible to allocate it dinamically as it would cause a stack + * or heap overflow. +*/ +uint8_t sector_data[FLASH_SECTOR_SIZE]; + + +/****************************************************************************/ +/** **/ +/* EXPORTED FUNCTIONS */ +/** **/ +/****************************************************************************/ + + +void w25q128jw_init_crt0() { + //make sure spi variable is into the xheep_init_data_crt0 section + spi.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); + return; +} + +w25q_error_codes_t w25q128jw_init(spi_host_t spi_host) { + /* + * Check if memory mapped SPI is enabled. Current version of the bsp + * does not support memory mapped SPI. + */ + if (soc_ctrl_peri->USE_SPIMEMIO == 1) { + return FLASH_ERROR; // Error + } + + // Set the global spi variable to the one passed as argument. + spi = spi_host; + + #ifdef USE_SPI_FLASH + // Select SPI host as SPI output + soc_ctrl_select_spi_host((soc_ctrl_t*)soc_ctrl_peri); + #endif // USE_SPI_FLASH + + // Enable SPI host device + spi_set_enable(&spi, true); + + // Enable SPI output + spi_output_enable(&spi, true); + + // Configure SPI<->Flash connection on CSID 0 + configure_spi(); + + // Set CSID + spi_set_csid(&spi, 0); + + // Power up flash + flash_power_up(); + + // Set QE bit (only FPGA, simulation do not support status registers at all) + #ifdef TARGET_PYNQ_Z2 + if (set_QE_bit() == FLASH_ERROR) return FLASH_ERROR; // Error occurred while setting QE bit + #endif // TARGET_PYNQ_Z2 + + return FLASH_OK; // Success +} + +w25q_error_codes_t w25q128jw_read(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Define the status variable + w25q_error_codes_t status; + + if (length < RX_DMA_THRESHOLD) { + status = w25q128jw_read_quad(addr, data, length); + if (status != FLASH_OK) return status; + } else { + // Wait DMA to be free + while(!dma_is_ready()); + status = w25q128jw_read_quad_dma(addr, data, length); + if (status != FLASH_OK) return status; + } + + return FLASH_OK; +} + +w25q_error_codes_t w25q128jw_write(uint32_t addr, void *data, uint32_t length, uint8_t erase_before_write) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Define the status variable + w25q_error_codes_t status = FLASH_OK; + + if (erase_before_write == 1) { + status = erase_and_write(addr, data, length); + } else { + // Wait DMA to be free + while(!dma_is_ready()); + status = w25q128jw_write_quad_dma(addr, data, length); + } + + return status; +} + +w25q_error_codes_t w25q128jw_read_standard(uint32_t addr, void* data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Address + Read command + uint32_t read_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_RD); + // Load command to TX FIFO + spi_write_word(&spi, read_byte_cmd); + spi_wait_for_ready(&spi); + + // Set up segment parameters -> send command and address + const uint32_t cmd_read_1 = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = true, // Command not finished + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + // Load segment parameters to COMMAND register + spi_set_command(&spi, cmd_read_1); + spi_wait_for_ready(&spi); + + // Set up segment parameters -> read length bytes + const uint32_t cmd_read_2 = spi_create_command((spi_command_t){ + .len = length-1, // len bytes + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirRxOnly // Read only + }); + spi_set_command(&spi, cmd_read_2); + spi_wait_for_ready(&spi); + + /* + * Set RX watermark to length. The watermark is in words. + * If the length is not a multiple of 4, the RX watermark is set to length/4+1 + * to take into account the extra bytes. + * If the length is higher then the RX FIFO depth, the RX watermark is set to + * RX FIFO depth. In this case the flag is not set to 0, so the loop will + * continue until all the data is read. + */ + int flag = 1; + int to_read = 0; + int i_start = 0; + int length_original = length; + uint32_t *data_32bit = (uint32_t *)data; + while (flag) { + if (length >= SPI_HOST_PARAM_RX_DEPTH) { + spi_set_rx_watermark(&spi, SPI_HOST_PARAM_RX_DEPTH>>2); + length -= SPI_HOST_PARAM_RX_DEPTH; + to_read += SPI_HOST_PARAM_RX_DEPTH; + } + else { + spi_set_rx_watermark(&spi, (length%4==0 ? length>>2 : (length>>2)+1)); + to_read += length; + flag = 0; + } + // Wait till SPI RX FIFO is full (or I read all the data) + spi_wait_for_rx_watermark(&spi); + // Read data from SPI RX FIFO + for (int i = i_start; i < to_read>>2; i++) { + spi_read_word(&spi, &data_32bit[i]); // Writes a full word + } + // Update the starting index + i_start += SPI_HOST_PARAM_RX_DEPTH>>2; + } + // Take into account the extra bytes (if any) + if (length_original % 4 != 0) { + uint32_t last_word = 0; + spi_read_word(&spi, &last_word); + memcpy(&data_32bit[length_original>>2], &last_word, length%4); + } + + return FLASH_OK; // Success +} + +w25q_error_codes_t w25q128jw_write_standard(uint32_t addr, void* data, uint32_t length) { + // Call the wrapper with quad = 0, dma = 0 + return page_write_wrapper(addr, data, length, 0, 0); +} + + +w25q_error_codes_t w25q128jw_erase_and_write_standard(uint32_t addr, void* data, uint32_t length){ + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_standard(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifdef TARGET_PYNQ_Z2 + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_PYNQ_Z2 + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_standard(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + + + +w25q_error_codes_t w25q128jw_read_standard_dma(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + /* + * SET UP DMA + */ + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_rx = spi.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; + + // Init DMA, the integrated DMA is used (peri == NULL) + dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH RX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_RX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_du = 0, // Target is peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + // Size is in data units (words in this case) + tgt_src.size_du = length>>2; + // Target is SPI RX FIFO + tgt_src.ptr = (uint8_t*)fifo_ptr_rx; + // Trigger to control the data flow + tgt_src.trig = slot; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is byte + .trig = DMA_TRIG_MEMORY, // Read-write operation to memory + }; + tgt_dst.ptr = (uint8_t*)data; // Target is the data buffer + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .end = DMA_TRANS_END_POLLING, + }; + + // Validate, load and launch DMA transaction + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + res = dma_load_transaction(&trans); + res = dma_launch(&trans); + + // Address + Read command + uint32_t read_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_RD); + // Load command to TX FIFO + spi_write_word(&spi, read_byte_cmd); + spi_wait_for_ready(&spi); + + // Set up segment parameters -> send command and address + const uint32_t cmd_read_1 = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = true, // Command not finished + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + // Load segment parameters to COMMAND register + spi_set_command(&spi, cmd_read_1); + spi_wait_for_ready(&spi); + + // Set up segment parameters -> read length bytes + const uint32_t cmd_read_2 = spi_create_command((spi_command_t){ + .len = length-1, // len bytes + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirRxOnly // Read only + }); + spi_set_command(&spi, cmd_read_2); + spi_wait_for_ready(&spi); + + // Wait for DMA to finish transaction + while(!dma_is_ready()); + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + uint32_t last_word = 0; + spi_read_word(&spi, &last_word); + memcpy(&data[length - length%4], &last_word, length%4); + } + + return FLASH_OK; +} + +w25q_error_codes_t w25q128jw_write_standard_dma(uint32_t addr, void *data, uint32_t length) { + // Call the wrapper with quad = 0, dma = 1 + return page_write_wrapper(addr, data, length, 0, 1); +} + +w25q_error_codes_t w25q128jw_erase_and_write_standard_dma(uint32_t addr, void* data, uint32_t length){ + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_standard_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifdef TARGET_PYNQ_Z2 + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_PYNQ_Z2 + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_standard_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + + +w25q_error_codes_t w25q128jw_read_quad(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Send quad read command at standard speed + uint32_t cmd_read_quadIO = FC_RDQIO; + spi_write_word(&spi, cmd_read_quadIO); + const uint32_t cmd_read = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_read); + spi_wait_for_ready(&spi); + + /* + * Send address at quad speed. + * Last byte is Fxh (here FFh) required by W25Q128JW + */ + uint32_t read_byte_cmd = (REVERT_24b_ADDR(addr) | (0xFF << 24)); + spi_write_word(&spi, read_byte_cmd); + const uint32_t cmd_address = spi_create_command((spi_command_t){ + .len = 3, // 3 Byte + .csaat = true, // Command not finished + .speed = kSpiSpeedQuad, // Quad speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_address); + spi_wait_for_ready(&spi); + + // Quad read requires dummy clocks + const uint32_t dummy_clocks_cmd = spi_create_command((spi_command_t){ + #ifdef TARGET_PYNQ_Z2 + .len = DUMMY_CLOCKS_FAST_READ_QUAD_IO-1, + #else + .len = DUMMY_CLOCKS_SIM-1, + #endif + .csaat = true, // Command not finished + .speed = kSpiSpeedQuad, // Quad speed + .direction = kSpiDirDummy // Dummy + }); + spi_set_command(&spi, dummy_clocks_cmd); + spi_wait_for_ready(&spi); + + // Read back the requested data at quad speed + const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ + .len = length-1, // 32 Byte + .csaat = false, // End command + .speed = kSpiSpeedQuad, // Quad speed + .direction = kSpiDirRxOnly // Read only + }); + spi_set_command(&spi, cmd_read_rx); + spi_wait_for_ready(&spi); + + /* COMMAND FINISHED */ + + /* + * Set RX watermark to length. The watermark is in words. + * If the length is not a multiple of 4, the RX watermark is set to length/4+1 + * to take into account the extra bytes. + * If the length is higher then the RX FIFO depth, the RX watermark is set to + * RX FIFO depth. In this case the flag is not set to 0, so the loop will + * continue until all the data is read. + */ + int flag = 1; + int to_read = 0; + int i_start = 0; + int length_original = length; + uint32_t *data_32bit = (uint32_t *)data; + while (flag) { + if (length >= SPI_HOST_PARAM_RX_DEPTH) { + spi_set_rx_watermark(&spi, SPI_HOST_PARAM_RX_DEPTH>>2); + length -= SPI_HOST_PARAM_RX_DEPTH; + to_read += SPI_HOST_PARAM_RX_DEPTH; + } + else { + spi_set_rx_watermark(&spi, (length%4==0 ? length>>2 : (length>>2)+1)); + to_read += length; + flag = 0; + } + // Wait till SPI RX FIFO is full (or I read all the data) + spi_wait_for_rx_watermark(&spi); + // Read data from SPI RX FIFO + for (int i = i_start; i < to_read>>2; i++) { + spi_read_word(&spi, &data_32bit[i]); // Writes a full word + } + // Update the starting index + i_start += SPI_HOST_PARAM_RX_DEPTH>>2; + } + // Take into account the extra bytes (if any) + if (length_original%4 != 0) { + uint32_t last_word = 0; + spi_read_word(&spi, &last_word); + memcpy(&data_32bit[length_original>>2], &last_word, length%4); + } + + return FLASH_OK; // Success +} + +w25q_error_codes_t w25q128jw_write_quad(uint32_t addr, void *data, uint32_t length) { + // Call the wrapper with quad = 1, dma = 0 + return page_write_wrapper(addr, data, length, 1, 0); +} + + +w25q_error_codes_t w25q128jw_erase_and_write_quad(uint32_t addr, void *data, uint32_t length) { + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_quad(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifdef TARGET_PYNQ_Z2 + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_PYNQ_Z2 + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_quad(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + + +w25q_error_codes_t w25q128jw_read_quad_dma(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Send quad read command at standard speed + uint32_t cmd_read_quadIO = FC_RDQIO; + spi_write_word(&spi, cmd_read_quadIO); + const uint32_t cmd_read = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_read); + spi_wait_for_ready(&spi); + + /* + * Send address at quad speed. + * Last byte is Fxh (here FFh) required by W25Q128JW + */ + uint32_t read_byte_cmd = (REVERT_24b_ADDR(addr) | (0xFF << 24)); + spi_write_word(&spi, read_byte_cmd); + const uint32_t cmd_address = spi_create_command((spi_command_t){ + .len = 3, // 3 Byte + .csaat = true, // Command not finished + .speed = kSpiSpeedQuad, // Quad speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_address); + spi_wait_for_ready(&spi); + + // Quad read requires dummy clocks + const uint32_t dummy_clocks_cmd = spi_create_command((spi_command_t){ + #ifdef TARGET_PYNQ_Z2 + .len = DUMMY_CLOCKS_FAST_READ_QUAD_IO-1, // W25Q128JW flash needs 4 dummy cycles + #else + .len = DUMMY_CLOCKS_SIM-1, // SPI flash simulation model needs 8 dummy cycles + #endif + .csaat = true, // Command not finished + .speed = kSpiSpeedQuad, // Quad speed + .direction = kSpiDirDummy // Dummy + }); + spi_set_command(&spi, dummy_clocks_cmd); + spi_wait_for_ready(&spi); + + // Read back the requested data at quad speed + const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ + .len = length-1, // length bytes + .csaat = false, // End command + .speed = kSpiSpeedQuad, // Quad speed + .direction = kSpiDirRxOnly // Read only + }); + spi_set_command(&spi, cmd_read_rx); + spi_wait_for_ready(&spi); + + /* COMMAND FINISHED */ + + /* + * SET UP DMA + */ + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_rx = spi.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; + + // Init DMA, the integrated DMA is used (peri == NULL) + dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH RX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_RX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_du = 0, // Target is peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is byte + }; + // Size is in data units (words in this case) + tgt_src.size_du = length>>2; + // Target is SPI RX FIFO + tgt_src.ptr = (uint8_t*)fifo_ptr_rx; + // Trigger to control the data flow + tgt_src.trig = slot; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is byte + .trig = DMA_TRIG_MEMORY, // Read-write operation to memory + }; + tgt_dst.ptr = (uint8_t*)data; // Target is the data buffer + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .end = DMA_TRANS_END_POLLING, + }; + + // Validate, load and launch DMA transaction + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + res = dma_load_transaction(&trans); + res = dma_launch(&trans); + + // Wait for DMA to finish transaction + while(!dma_is_ready()); + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + uint32_t last_word = 0; + spi_read_word(&spi, &last_word); + memcpy(&data[length - length%4], &last_word, length%4); + } + + return FLASH_OK; +} + +w25q_error_codes_t w25q128jw_write_quad_dma(uint32_t addr, void *data, uint32_t length) { + // Call the wrapper with quad = 1, dma = 1 + return page_write_wrapper(addr, data, length, 1, 1); +} + +w25q_error_codes_t w25q128jw_erase_and_write_quad_dma(uint32_t addr, void *data, uint32_t length) { + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_quad_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifdef TARGET_PYNQ_Z2 + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_PYNQ_Z2 + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_quad_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + +w25q_error_codes_t w25q128jw_4k_erase(uint32_t addr) { + // Sanity checks + if (addr > MAX_FLASH_ADDR || addr < 0) return FLASH_ERROR; + + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + uint32_t erase_4k_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_SE); + spi_write_word(&spi, erase_4k_cmd); + spi_wait_for_ready(&spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_erase); + spi_wait_for_ready(&spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +w25q_error_codes_t w25q128jw_32k_erase(uint32_t addr) { + // Sanity checks + if (addr > 0x00ffffff || addr < 0) return FLASH_ERROR; + + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + uint32_t erase_32k_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_BE32); + spi_write_word(&spi, erase_32k_cmd); + spi_wait_for_ready(&spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_erase); + spi_wait_for_ready(&spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +w25q_error_codes_t w25q128jw_64k_erase(uint32_t addr) { + // Sanity checks + if (addr > 0x00ffffff || addr < 0) return FLASH_ERROR; + + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + uint32_t erase_64k_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_BE64); + spi_write_word(&spi, erase_64k_cmd); + spi_wait_for_ready(&spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_erase); + spi_wait_for_ready(&spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +void w25q128jw_chip_erase(void) { + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + spi_write_word(&spi, FC_CE); + spi_wait_for_ready(&spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 0, // 1 Bytes + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_erase); + spi_wait_for_ready(&spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +void w25q128jw_reset(void) { + // Wait for ongoing operation to finish (if any) + flash_wait(); + + // Build and send reset command + flash_reset(); + + // Wait for the reset operation to be finished + flash_wait(); +} + +void w25q128jw_reset_force(void) { + // Build and send reset command without waiting for ongoing operation + flash_reset(); + + // Wait for the reset operation to be finished + flash_wait(); +} + +void w25q128jw_power_down(void) { + // Build and send power down command + spi_write_word(&spi, FC_PD); + const uint32_t cmd_power_down = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_power_down); + spi_wait_for_ready(&spi); +} + + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +static void flash_power_up(void) { + spi_write_word(&spi, FC_RPD); + spi_wait_for_ready(&spi); + const uint32_t cmd_powerup = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_powerup); + spi_wait_for_ready(&spi); +} + +static w25q_error_codes_t set_QE_bit(void) { + spi_set_rx_watermark(&spi,1); + + // Read Status Register 2 + const uint32_t reg2_read_cmd = FC_RSR2; + spi_write_word(&spi, reg2_read_cmd); + + const uint32_t reg2_read_1 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, reg2_read_1); + spi_wait_for_ready(&spi); + + const uint32_t reg2_read_2 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Standard speed + .direction = kSpiDirRxOnly // Read only + }); + spi_set_command(&spi, reg2_read_2); + spi_wait_for_ready(&spi); + spi_wait_for_rx_watermark(&spi); + + /* + * the partial word will be zero-padded and inserted into the RX FIFO once the segment is completed + * The actual register is 8 bit, but the SPI host gives a full word + */ + uint32_t reg2_data; + spi_read_word(&spi, ®2_data); + + // Set bit in position 1 (QE bit), leaving the others unchanged + reg2_data |= 0x2; + + // Enable write operation + flash_write_enable(); + + // Write Status Register 2 (set QE bit) + const uint32_t reg2_write_cmd = FC_WSR2; + spi_write_word(&spi, reg2_write_cmd); + + const uint32_t reg2_write_1 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, reg2_write_1); + spi_wait_for_ready(&spi); + + // Load data to TX FIFO + spi_write_word(&spi, reg2_data); + + // Create command segment + const uint32_t reg2_write_2 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Standard speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, reg2_write_2); + spi_wait_for_ready(&spi); + + // Wait flash to complete write routine + flash_wait(); + + // Read back Status Register 2 + spi_write_word(&spi, reg2_read_cmd); + spi_set_command(&spi, reg2_read_1); + spi_wait_for_ready(&spi); + spi_set_command(&spi, reg2_read_2); + spi_wait_for_ready(&spi); + spi_wait_for_rx_watermark(&spi); + uint32_t reg2_data_check = 0x00; + spi_read_word(&spi, ®2_data_check); + + // Check if the QE bit is set + if ((reg2_data_check & 0x2) == 0) return FLASH_ERROR; + else return FLASH_OK; +} + +static void configure_spi(void) { + // Configure SPI clock + uint32_t core_clk = soc_ctrl_peri->SYSTEM_FREQUENCY_HZ; + uint16_t clk_div = 0; + if(FLASH_CLK_MAX_HZ < core_clk/2){ + clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated + if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 + } + // SPI Configuration + // Configure chip 0 (flash memory) + const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ + .clkdiv = clk_div, + .csnidle = 0xF, + .csntrail = 0xF, + .csnlead = 0xF, + .fullcyc = false, + .cpha = 0, + .cpol = 0 + }); + spi_set_configopts(&spi, 0, chip_cfg); +} + +static void flash_wait(void) { + spi_set_rx_watermark(&spi,1); + bool flash_busy = true; + uint8_t flash_resp[4] = {0xff,0xff,0xff,0xff}; + + while(flash_busy){ + uint32_t flash_cmd = FC_RSR1; // [CMD] Read status register 1 + spi_write_word(&spi, flash_cmd); // Push TX buffer + uint32_t spi_status_cmd = spi_create_command((spi_command_t){ + .len = 0, + .csaat = true, + .speed = kSpiSpeedStandard, + .direction = kSpiDirTxOnly + }); + uint32_t spi_status_read_cmd = spi_create_command((spi_command_t){ + .len = 0, + .csaat = false, + .speed = kSpiSpeedStandard, + .direction = kSpiDirRxOnly + }); + spi_set_command(&spi, spi_status_cmd); + spi_wait_for_ready(&spi); + spi_set_command(&spi, spi_status_read_cmd); + spi_wait_for_ready(&spi); + spi_wait_for_rx_watermark(&spi); + spi_read_word(&spi, (uint32_t *)flash_resp); + if ((flash_resp[0] & 0x01) == 0) flash_busy = false; + } +} + +static void flash_reset(void) { + spi_write_word(&spi, FC_ERESET); + spi_write_word(&spi, FC_RESET); + spi_wait_for_ready(&spi); + + const uint32_t cmd_reset_enable = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_reset_enable); + spi_wait_for_ready(&spi); + const uint32_t cmd_reset = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = kSpiSpeedStandard, // Single speed + .direction = kSpiDirTxOnly // Write only + }); + spi_set_command(&spi, cmd_reset); + spi_wait_for_ready(&spi); +} + +w25q_error_codes_t erase_and_write(uint32_t addr, uint8_t *data, uint32_t length) { + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifdef TARGET_PYNQ_Z2 + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_PYNQ_Z2 + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash (without erasing this time) + status = w25q128jw_write(sector_start_addr, sector_data, FLASH_SECTOR_SIZE, 0); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; +} + +static w25q_error_codes_t page_write_wrapper(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Pointer arithmetics is not allowed on void pointers + uint8_t *data_8bit = (uint8_t *)data; + + /* + * Set speed and DMA flags. + * Robust implementation: no need to perform safety checks on the flags. + */ + uint8_t speed = quad==1 ? 1 : 0; + uint8_t dma_flag = dma==1 ? 1 : 0; + + /* + * Taking care of misalligned start address. + * If the start address is not aligned to a 256 bytes boundary, + * the first page is written with the first 256 - (addr % 256) bytes. + */ + if (addr % FLASH_PAGE_SIZE != 0) { + uint8_t tmp_len = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE); + tmp_len = MIN(tmp_len, length); + page_write(addr, data_8bit, tmp_len, speed, dma_flag); + addr += tmp_len; + data_8bit += tmp_len; + length -= tmp_len; + } + + // Check if we already finished + if (length == 0) return FLASH_OK; + + // I cannot program more than a page (256 Bytes) at a time. + int flag = 1; + while (flag) { + if (length > FLASH_PAGE_SIZE) { + page_write(addr, data_8bit, FLASH_PAGE_SIZE, speed, dma_flag); + addr += FLASH_PAGE_SIZE; + data_8bit += FLASH_PAGE_SIZE; + length -= FLASH_PAGE_SIZE; + } else { + page_write(addr, data_8bit, length, speed, dma_flag); + flag = 0; + } + } + return FLASH_OK; +} + +static w25q_error_codes_t page_write(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma) { + // Required every time before issuing a write command + flash_write_enable(); + + /* + * Build and send write command (24bit address + command). + * The command is picked based on the quad flag. + */ + const uint32_t write_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | (quad ? FC_PPQ : FC_PP)); + spi_write_word(&spi, write_byte_cmd); + const uint32_t cmd_write = spi_create_command((spi_command_t){ + .len = 3, + .csaat = true, + .speed = kSpiSpeedStandard, + .direction = kSpiDirTxOnly + }); + spi_set_command(&spi, cmd_write); + spi_wait_for_ready(&spi); + + /* + * Place data in TX FIFO + * In simulation it do not wait for the flash to be ready, so we must check + * if the FIFO is full before writing. + */ + if (dma) { + dma_send_toflash(data, length); + } else { + uint32_t *data_32bit = (uint32_t *)data; + for (int i = 0; i < length>>2; i++) { + spi_wait_for_tx_not_full(&spi); + spi_write_word(&spi, data_32bit[i]); + } + if (length % 4 != 0) { + uint32_t last_word = 0; + memcpy(&last_word, &data[length - length % 4], length % 4); + spi_wait_for_tx_not_full(&spi); + spi_write_word(&spi, last_word); + } + } + + /* + * Set up segment parameters -> send data. + * Speed is quad if quad flag is set, standard otherwise. + */ + const uint32_t cmd_write_2 = spi_create_command((spi_command_t){ + .len = length-1, + .csaat = false, + .speed = quad ? kSpiSpeedQuad : kSpiSpeedStandard, + .direction = kSpiDirTxOnly + }); + spi_set_command(&spi, cmd_write_2); + spi_wait_for_ready(&spi); + + // Wait for flash to be ready again (FPGA only) + #ifdef TARGET_PYNQ_Z2 + flash_wait(); + #endif // TARGET_PYNQ_Z2 +} + +static w25q_error_codes_t dma_send_toflash(uint8_t *data, uint32_t length) { + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_tx = spi.base_addr.base + SPI_HOST_TXDATA_REG_OFFSET; + + // Init DMA, the integrated DMA is used (peri == NULL) + dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH TX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_TX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_TX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + // Size is in data units (words in this case) + tgt_src.size_du = length>>2; + // Target is data buffer + tgt_src.ptr = data; + // Reads from memory + tgt_src.trig = DMA_TRIG_MEMORY; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_du = 0, // It's a peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + tgt_dst.trig = slot; + tgt_dst.ptr = (uint8_t*)fifo_ptr_tx; // Target is SPI TX FIFO + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_POLLING, + }; + + // Validate, load and launch DMA transaction + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + if (res != DMA_CONFIG_OK) return FLASH_ERROR_DMA; + res = dma_load_transaction(&trans); + if (res != DMA_CONFIG_OK) return FLASH_ERROR_DMA; + res = dma_launch(&trans); + if (res != DMA_CONFIG_OK) return FLASH_ERROR_DMA; + + // Wait for DMA to finish transaction + while(!dma_is_ready()); + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + uint32_t last_word = 0; + memcpy(&last_word, &data[length - length % 4], length % 4); + spi_wait_for_tx_not_full(&spi); + spi_write_word(&spi, last_word); + } + return FLASH_OK; +} + +static void flash_write_enable(void) { + spi_write_word(&spi, FC_WE); + const uint32_t cmd_write_en = spi_create_command((spi_command_t){ + .len = 0, + .csaat = false, + .speed = kSpiSpeedStandard, + .direction = kSpiDirTxOnly + }); + spi_set_command(&spi, cmd_write_en); + spi_wait_for_ready(&spi); +} + +static w25q_error_codes_t w25q128jw_sanity_checks(uint32_t addr, uint8_t *data, uint32_t length) { + // Check if address is out of range + if (addr > MAX_FLASH_ADDR || addr < 0) return FLASH_ERROR; + + // Check if data pointer is NULL + if (data == NULL) return FLASH_ERROR; + + // Check if length is 0 + if (length <= 0) return FLASH_ERROR; + + // Check if current address + length is out of range + if (addr + length > MAX_FLASH_ADDR) return FLASH_ERROR; + + return FLASH_OK; // Success +} + +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h new file mode 100644 index 00000000..c6f29e9c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h @@ -0,0 +1,433 @@ +/* + ******************* +******************************* H HEADER FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : w25q128jw.h +** version : 1 +** date : 1/11/2023 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file w25q128jw.h +* @date 13/02/23 +* @brief Header file for the W25Q128JW flash memory. +*/ + +#ifndef W25Q128JW_H +#define W25Q128JW_H + +/****************************************************************************/ +/** **/ +/** MODULES USED **/ +/** **/ +/****************************************************************************/ + +#include "spi_host.h" +#include "soc_ctrl.h" +#include "core_v_mini_mcu.h" + +/****************************************************************************/ +/** **/ +/** DEFINITIONS AND MACROS **/ +/** **/ +/****************************************************************************/ + +/** + * In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) +*/ +#define FLASH_CLK_MAX_HZ (133*1000*1000) + +/** + * @defgroup flash_commands Flash commands + * @{ + */ +#define FC_WE 0x06 /** Write Enable */ +#define FC_SRWE 0x50 /** Volatile SR Write Enable */ +#define FC_WD 0x04 /** Write Disable */ +#define FC_RPD 0xAB /** Release Power-Down, returns Device ID */ +#define FC_MFGID 0x90 /** Read Manufacturer/Device ID */ +#define FC_JEDECID 0x9F /** Read JEDEC ID */ +#define FC_UID 0x4B /** Read Unique ID */ +#define FC_RD 0x03 /** Read Data */ +#define FC_FR 0x0B /** Fast Read */ +#define FC_RDQIO 0xEB /** Fast Read Quad I/O */ +#define FC_PP 0x02 /** Page Program */ +#define FC_PPQ 0x32 /** Quad Input Page Program */ +#define FC_SE 0x20 /** Sector Erase 4kb */ +#define FC_BE32 0x52 /** Block Erase 32kb */ +#define FC_BE64 0xD8 /** Block Erase 64kb */ +#define FC_CE 0xC7 /** Chip Erase */ +#define FC_RSR1 0x05 /** Read Status Register 1 */ +#define FC_WSR1 0x01 /** Write Status Register 1 */ +#define FC_RSR2 0x35 /** Read Status Register 2 */ +#define FC_WSR2 0x31 /** Write Status Register 2 */ +#define FC_RSR3 0x15 /** Read Status Register 3 */ +#define FC_WSR3 0x11 /** Write Status Register 3 */ +#define FC_RSFDP 0x5A /** Read SFDP Register */ +#define FC_ESR 0x44 /** Erase Security Register */ +#define FC_PSR 0x42 /** Program Security Register */ +#define FC_RSR 0x48 /** Read Security Register */ +#define FC_GBL 0x7E /** Global Block Lock */ +#define FC_GBU 0x98 /** Global Block Unlock */ +#define FC_RBL 0x3D /** Read Block Lock */ +#define FC_RPR 0x3C /** Read Sector Protection Registers (adesto) */ +#define FC_IBL 0x36 /** Individual Block Lock */ +#define FC_IBU 0x39 /** Individual Block Unlock */ +#define FC_EPS 0x75 /** Erase / Program Suspend */ +#define FC_EPR 0x7A /** Erase / Program Resume */ +#define FC_PD 0xB9 /** Power-down */ +#define FC_QPI 0x38 /** Enter QPI mode */ +#define FC_ERESET 0x66 /** Enable Reset */ +#define FC_RESET 0x99 /** Reset Device */ +/** @} */ + +/** + * @defgroup error_codes Error codes + * @{ +*/ +#define FLASH_OK 0 /** No error @hideinitializer*/ +#define FLASH_ERROR 1 /** Generic error @hideinitializer*/ +#define FLASH_ERROR_DMA 2 /** DMA error @hideinitializer*/ +/** @} */ + +/** +/** + * @brief Threshold value for switching to DMA in read mode. + * If the number of bytes to be read exceeds this threshold, + * DMA is the more efficient data transfer. + */ +#define RX_DMA_THRESHOLD 75 + +/** + * @brief Threshold value for switching to DMA in write mode. + * If the number of bytes to be wrote exceeds this threshold, + * DMA is the more efficient data transfer. + */ +#define TX_DMA_THRESHOLD 0 + +/** + * @brief Dimension of a flash page, in bytes. +*/ +#define FLASH_PAGE_SIZE 256 + +/** + * @brief Dimension of a flash sector, in bytes. +*/ +#define FLASH_SECTOR_SIZE 4096 + +/** + * @brief Number of dummy clocks cycles required by the simulation model. +*/ +#define DUMMY_CLOCKS_SIM 8 + +/** + * @brief Number of dummy clocks cycles required by the flash during + * fast read quad I/O operations (command code: EBh). +*/ +#define DUMMY_CLOCKS_FAST_READ_QUAD_IO 4 + +/** + * @brief Upper bound for the flash address. +*/ +#define MAX_FLASH_ADDR 0x00ffffff + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/** **/ +/** TYPEDEFS AND STRUCTURES **/ +/** **/ +/****************************************************************************/ + +/** + * @brief Return status type. +*/ +typedef uint8_t w25q_error_codes_t; + +/****************************************************************************/ +/** **/ +/** EXPORTED VARIABLES **/ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/** EXPORTED FUNCTIONS **/ +/** **/ +/****************************************************************************/ + +/** + * @brief Initialize data structure used by crt0 flash_load. + * +*/ +void w25q128jw_init_crt0(); + +/** + * @brief Power up and itialize the flash. + * + * Enable the SPI interface. + * Power up the flash and set the SPI configuration specific to the flash. + * It also set the QE bit in order to accept Quad I/O commands. + * By default both error and event interrupts are disabled. + * + * @param spi_host SPI host to use. + * + * @note The flash uses CSID 0. If the CSID register value is changed, it must be + * restored back to 0 before using the flash again. + * + * @return FLASH_OK if the flash is correctly initialized, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_init(spi_host_t spi_host); + +/** + * @brief Read from flash. + * + * The function automatically uses the best parameters based on + * the current state of the system and the length of the data to read. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer to be filled. + * @param length number of bytes to read. + * @return FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Write to flash. + * + * The function automatically uses the best parameters based on + * the current state of the system and the length of the data to write. + * If erase_before_write is set, the function will take care of erasing + * the correct sectors before writing. All the bytes not written will be + * copied back in their current state before the write operation. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @param erase_before_write if set to 1, the function will take care of erasing + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write(uint32_t addr, void* data, uint32_t length, uint8_t erase_before_write); + +/** + * @brief Read from flash at standard speed. + * + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer to be filled. + * @param length number of bytes to read. + * @retval FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_standard(uint32_t addr, void* data, uint32_t length); + + +/** + * @brief Write to flash at standard speed. Use this function only to write to unitialized data + * + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_standard(uint32_t addr, void* data, uint32_t length); + + +/** + * @brief Erase and Write to flash at standard speed. + * + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_standard(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Read from flash at standard speed using DMA + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to read. + * @return FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_standard_dma(uint32_t addr, void* data, uint32_t length); + + +/** + * @brief Write to flash at standard speed using DMA. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_standard_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase and Write to flash at standard speed using DMA + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_standard_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Read from flash at quad speed. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_quad(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Write to flash at quad speed. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_quad(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase and Write to flash at quad speed. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_quad(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Read from flash at quad speed using DMA. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_quad_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Write to flash at quad speed using DMA. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_quad_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase and Write to flash at quad speed using DMA. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_quad_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase a 4kb sector. + * + * Sets all memory within a 4kb sector to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. + * + * @param addr 24-bit address of the sector to erase. +*/ +w25q_error_codes_t w25q128jw_4k_erase(uint32_t addr); + +/** + * @brief Erase a 32kb block. + * + * Sets all memory within a 32kb block to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. + * + * @param addr 24-bit address of the block to erase. +*/ +w25q_error_codes_t w25q128jw_32k_erase(uint32_t addr); + +/** + * @brief Erase a 64kb block. + * + * Sets all memory within a 64kb block to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. + * + * @param addr 24-bit address of the block to erase. +*/ +w25q_error_codes_t w25q128jw_64k_erase(uint32_t addr); + +/** + * @brief Erase the entire chip. + * + * Sets all memory within the chip to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. +*/ +void w25q128jw_chip_erase(void); + + +/** + * @brief Reset the flash. + * + * Before issuing the reset command, the function checks (and eventually wait) + * any ongoing read/write operation in order to preserve data integrity. + * After the reset is issued, wait for the flash to be ready. +*/ +void w25q128jw_reset(void); + +/** + * @brief Reset the flash without checking for ongoing operations. + * + * This function is used to reset the flash when it is not possible to check + * for ongoing operations (e.g. when the flash is not responding). + * Upon receiving the reset command, the flash will abort any ongoing operation. + * After the reset is issued, waits for the flash to be ready. +*/ +void w25q128jw_reset_force(void); + +/** + * @brief Power down the flash. + * + * During power down state, the only command that can be issued is the + * release power down command. All other commands are going to be ignored + * by the flash. +*/ +void w25q128jw_power_down(void); + +/****************************************************************************/ +/** **/ +/** INLINE FUNCTIONS **/ +/** **/ +/****************************************************************************/ +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* W25Q128JW_H */ +/****************************************************************************/ +/** **/ +/** EOF **/ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S index b5f843ab..82776471 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S @@ -14,11 +14,7 @@ #include "core_v_mini_mcu.h" #include "soc_ctrl_regs.h" -/* In case the operation is to load from FLASH -*/ -#ifdef FLASH_LOAD -#include "spi_host_regs.h" -#endif +#define RAMSIZE_COPIEDBY_BOOTROM 2048 /* Entry point for bare metal programs */ .section .text.start @@ -46,139 +42,69 @@ _start: #endif #ifdef FLASH_LOAD -/* copy the remaining (if any) text and data sections */ + + call w25q128jw_init_crt0 + + // This assumes ram base address is 0x00000000 and the section .text stars from ram0 (in the first RAMSIZE_COPIEDBY_BOOTROM Byte) + li s1, RAMSIZE_COPIEDBY_BOOTROM + li s2, FLASH_MEM_START_ADDRESS + + // copy the remaining (if any) text and data sections // // Setup the in/out pointers and copy size knowing 1KiB as already been copied - li a2, FLASH_MEM_START_ADDRESS # src ptr (flash) - addi a2, a2, 1024 - // This assumes ram base address is 0x00000000 - li s1, 1024 # dst ptr (ram) - la a0, _edata - addi a0, a0, -4 # _edata point to next address, so decrease it by one word - // Skip if everything has already been copied - blt a0, s1, _init_bss - addi a3, a0, -1024 # copy size in bytes (_edata is word aligned, so -1020 to make sure last word is copied) - - li a1, SPI_FLASH_START_ADDRESS - // Spi should already be enabled, powered-up and TXWM to 8 - // Address in byte reversed order (might be useless for the 1KiB address value) - // Highest byte is discarded(address on 3 bytes) - // ((x << 24) | (((x>>16)<<24)>>16) | (((x<<16)>>24)<<16)) - slli a4, a2, 24 - srli s0, a2, 16 - slli s0, s0, 24 - srli s0, s0, 16 - slli a5, a2, 16 - srli a5, a5, 24 - slli a5, a5, 16 - or a4, a4, s0 - or a2, a4, a5 - or a2, a2, 0x03 - sw a2, SPI_HOST_TXDATA_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_read_prog: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a5, _wait_spi_ready_read_prog - // Read command: 0x11000003 - lui a4, 0x11000 - addi a4, a4, 3 # spi cmd: txonly + stdspeed + csaat + 4B - sw a4, SPI_HOST_COMMAND_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_copy_cmd: - lw a4, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a4, _wait_spi_ready_copy_cmd - - // For loop until the copy from flash to ram is done - // Try first to do as much as 256-bytes copies as possible - // mv s0, a3 - li s6, 256 - // Read command: 0x90000FF - lui s5, 0x9000 - addi s5, s5, 255 # spi cmd: rxonly + stdspeed + csaat + 255 bytes - -_32B_chunk_loop: - blt s6, a3, _read_32B_chunk - // Read remaining bytes - lui a5, 0x8000 - addi a4, a3, -1 - or a5, a5, a4 # spi cmd: rxonly + stdspeed + remaining bytes (a3-1) - sw a5, SPI_HOST_COMMAND_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_remaining_bytes: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a5, _wait_spi_ready_remaining_bytes - li s4, 32 - j _last_bytes_read_start - -_read_32B_chunk: - sw s5, SPI_HOST_COMMAND_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_read_32B_chunk: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a5, _wait_spi_ready_read_32B_chunk - addi s7, s1, 256 # add 32*8 (256 bytes) to dst ptr - -_wait_spi_rxwm_8_words: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - srli a5, a5, 0x14 - andi a5, a5, 1 # SPI_HOST_STATUS_RXWM_BIT - beqz a5, _wait_spi_rxwm_8_words - addi a2, s1, 32 # add 32 bytes (4 words) to dst ptr - -_spi_fifo_read_8_words: - // Read 32B (8 words) from RX FIFO - lw a7, SPI_HOST_RXDATA_REG_OFFSET(a1) - sw a7, 0(s1) - addi s1, s1, 4 - bne s1, a2, _spi_fifo_read_8_words - bne s1, s7, _wait_spi_rxwm_8_words - addi a3, a3, -256 - j _32B_chunk_loop - -_wait_spi_rxwm_8_words_1: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - srli a5, a5, 0x14 - andi a5, a5, 1 # SPI_HOST_STATUS_RXWM_BIT - beqz a5, _wait_spi_rxwm_8_words_1 - addi a2, s1, 32 # add 32 bytes (4 words) to dst ptr - -_spi_fifo_read_8_words_1: - // Read 32B (8 words) from RX FIFO - lw a7, SPI_HOST_RXDATA_REG_OFFSET(a1) - sw a7, 0(s1) - addi s1, s1, 4 - bne s1, a2, _spi_fifo_read_8_words_1 - addi a3, a3, -32 - -_last_bytes_read_start: - bltu s4, a3, _wait_spi_rxwm_8_words_1 - // Update RX watermark with remaining words (<=8) - lw a4, SPI_HOST_CONTROL_REG_OFFSET(a1) - andi a4, a4, -256 # ~SPI_HOST_CONTROL_RX_WATERMARK_MASK - srli a5, a3, 0x2 # 4 bytes = 1 word - or a5, a5, a4 - sw a5, SPI_HOST_CONTROL_REG_OFFSET(a1) - -_wait_spi_rxwm_n_words: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - srli a5, a5, 0x14 - andi a5, a5, 1 # SPI_HOST_STATUS_RXWM_BIT - beqz a5, _wait_spi_rxwm_n_words - -_remaining_bytes_loop: - bnez a3, _spi_read_word - j _init_bss - -_spi_read_word: - lw a7, SPI_HOST_RXDATA_REG_OFFSET(a1) - sw a7, 0(s1) - addi a3, a3, -4 - addi s1, s1, 4 - j _remaining_bytes_loop - + mv a0, s2 // src ptr (flash) + add a0, a0, s1 + + la a1, _etext + // Skip if everything has already been copied, and copy the data section + blt a1, s1, _load_data_section + + // copy size in bytes, i.e. _etext - RAMSIZE_COPIEDBY_BOOTROM + sub a2, a1, s1 + + // dst ptr (ram) + mv a1, s1 + + // copy the remaining data --> w25q128jw_read_standard(a0 is src addr, a1 is dest ptr data, a2 is length) + + // this sub is redundat as we could have simply set a0 to RAMSIZE_COPIEDBY_BOOTROM+0x0, + // but like this is more readable as we set the FLASH address as memory mapped to FLASH_MEM_START_ADDRESS, and then remove the offset + // as required bz the w25q128jw_read_standard function + sub a0,a0,s2 + call w25q128jw_read_standard + +_load_data_section: + // src ptr + la a0, _lma_data_start + // dst ptr + la a1, __data_start + // copy size in bytes + la a2, _lma_data_end + sub a2, a2, a0 + + bltz a2, _load_data_interleaved_section // dont do anything if you do not have data + + sub a0,a0,s2 + call w25q128jw_read_standard + + +_load_data_interleaved_section: + #ifdef HAS_MEMORY_BANKS_IL + // src ptr + la a0, _lma_data_interleaved_start + // dst ptr + la a1, __data_interleaved_start + // copy size in bytes + la a2, _lma_data_interleaved_end + sub a2, a2, a0 + + bltz a2, _init_bss // dont do anything if you do not have interleaved data + + sub a0,a0,s2 + call w25q128jw_read_standard + #endif + +#endif + /* clear the bss segment */ _init_bss: la a0, __bss_start @@ -186,14 +112,6 @@ _init_bss: sub a2, a2, a0 li a1, 0 call memset -#else -/* clear the bss segment */ - la a0, __bss_start - la a2, __bss_end - sub a2, a2, a0 - li a1, 0 - call memset -#endif #ifdef FLASH_EXEC /* copy initialized data sections from flash to ram (to be verified, copied from picosoc)*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c index c30b6105..d0b977d2 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c @@ -562,7 +562,7 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * No further operations are done to prevent corrupting information * that could be useful for debugging purposes. */ - uint8_t isEnv = p_trans->dst->env; + uint8_t isEnv = (p_trans->dst->env != NULL); uint8_t isOutb = is_region_outbound( p_trans->dst->ptr, p_trans->dst->env->end, @@ -689,35 +689,21 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) /* * SET THE POINTERS */ - dma_cb.peri->SRC_PTR = dma_cb.trans->src->ptr; + dma_cb.peri->SRC_PTR = (uint32_t)dma_cb.trans->src->ptr; if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) { /* - Write to the destination pointers only if we are not in address mode, - otherwise the destination address is read in a separate port in parallel with the data - from the address port + Write to the destination pointers only if we are not in address mode, + otherwise the destination address is read in a separate port in parallel with the data + from the address port */ - dma_cb.peri->DST_PTR = dma_cb.trans->dst->ptr; - } - else - { - dma_cb.peri->ADDR_PTR = dma_cb.trans->src_addr->ptr; - } - - if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) + dma_cb.peri->DST_PTR = (uint32_t)dma_cb.trans->dst->ptr; + } + else { - /* - Write to the destination pointers only if we are not in address mode, - otherwise the destination address is read in a separate port in parallel with the data - from the address port - */ - dma_cb.peri->DST_PTR = dma_cb.trans->dst->ptr; - } - else - { - dma_cb.peri->ADDR_PTR = dma_cb.trans->src_addr->ptr; - } + dma_cb.peri->ADDR_PTR = (uint32_t)dma_cb.trans->src_addr->ptr; + } /* * SET THE INCREMENTS @@ -1107,7 +1093,7 @@ static inline uint8_t is_region_outbound( uint8_t *p_start, */ uint32_t affectedUnits = ( p_size_du - 1 ) * p_inc_du + 1; uint32_t rangeSize = DMA_DATA_TYPE_2_SIZE(p_type) * affectedUnits; - uint32_t lasByteInsideRange = p_start + rangeSize -1; + uint32_t lasByteInsideRange = (uint32_t)p_start + rangeSize -1; return ( p_end < lasByteInsideRange ); // Size is be guaranteed to be non-zero before calling this function. } @@ -1166,4 +1152,4 @@ static inline uint32_t get_increment_b( dma_target_t * p_tgt ) /** **/ /* EOF */ /** **/ -/****************************************************************************/ \ No newline at end of file +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h index 1956f9e8..85ee6475 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h @@ -104,6 +104,8 @@ typedef enum DMA_TRIG_SLOT_SPI_FLASH_RX = 4, /*!< Slot 3 (MEM < SPI FLASH). */ DMA_TRIG_SLOT_SPI_FLASH_TX = 8, /*!< Slot 4 (MEM > SPI FLASH). */ DMA_TRIG_SLOT_I2S = 16,/*!< Slot 5 (I2S). */ + DMA_TRIG_SLOT_EXT_TX = 32,/*!< Slot 6 (External peripherals TX). */ + DMA_TRIG_SLOT_EXT_RX = 64,/*!< Slot 7 (External peripherals RX). */ DMA_TRIG__size, /*!< Not used, only for sanity checks. */ DMA_TRIG__undef, /*!< DMA will not be used. */ } dma_trigger_slot_mask_t; @@ -463,4 +465,4 @@ uint8_t dma_window_ratio_warning_threshold(void); /** **/ /** EOF **/ /** **/ -/****************************************************************************/ \ No newline at end of file +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c index 3e733ecd..f5cb004f 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c @@ -150,7 +150,7 @@ gpio_result_t gpio_assign_irq_handler( uint32_t intr_id, { if( intr_id >= GPIO_INTR_START && intr_id <= GPIO_INTR_END ) { - gpio_handlers[ intr_id - GPIO_INTR_START ] = handler; + gpio_handlers[ intr_id - GPIO_INTR_START ] = (void (*)(void))handler; return GpioOk; } return GpioError; @@ -160,7 +160,7 @@ void gpio_reset_handlers_list( ) { for( uint8_t i = 0; i < GPIO_INTR_QTY; i++ ) { - gpio_handlers[ i ] = &gpio_handler_irq_dummy; + gpio_handlers[ i ] = (void (*)(void))&gpio_handler_irq_dummy; } } diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h new file mode 100644 index 00000000..03ec588a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h @@ -0,0 +1,56 @@ +/* + ******************* +******************************* C SOURCE FILE ******************************* +** ******************* ** +** ** +** project : x-heep ** +** filename : i2s.h ** +** date : 28/10/2023 ** +** ** +***************************************************************************** +** ** +** Copyright (c) EPFL contributors. ** +** All rights reserved. ** +** ** +***************************************************************************** + +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file iffifo.h +* @date 28/10/2023 +* @author Pierre Guillod +* @brief HAL of the IFFIFO peripheral +* +*/ + +#ifndef _DRIVERS_IFFIFO_H_ +#define _DRIVERS_IFFIFO_H_ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) void handler_irq_iffifo(uint32_t id); + +#ifdef __cplusplus +} +#endif + +#endif // _DRIVERS_IFFIFO_H_ + +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h new file mode 100644 index 00000000..6acd3aa8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h @@ -0,0 +1,47 @@ +// Generated register defines for iffifo + +// Copyright information found in source file: +// Copyright EPFL contributors. + +// Licensing information found in source file: +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef _IFFIFO_REG_DEFS_ +#define _IFFIFO_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define IFFIFO_PARAM_REG_WIDTH 32 + +// Data coming from the FIFO (Fifo Output/Software RX) +#define IFFIFO_FIFO_OUT_REG_OFFSET 0x0 + +// Data sent to the FIFO (Fifo Input/Software TX) +#define IFFIFO_FIFO_IN_REG_OFFSET 0x4 + +// General purpose status register +#define IFFIFO_STATUS_REG_OFFSET 0x8 +#define IFFIFO_STATUS_EMPTY_BIT 0 +#define IFFIFO_STATUS_AVAILABLE_BIT 1 +#define IFFIFO_STATUS_REACHED_BIT 2 +#define IFFIFO_STATUS_FULL_BIT 3 + +// Current number of occupied FIFO slots +#define IFFIFO_OCCUPANCY_REG_OFFSET 0xc + +// FIFO occupancy at which the STATUS:REACHED bit is asserted +#define IFFIFO_WATERMARK_REG_OFFSET 0x10 + +// Write any value to assert an interrupt. Write 0 or 1 to disable or enable +// an interrupt. +#define IFFIFO_INTERRUPTS_REG_OFFSET 0x14 +#define IFFIFO_INTERRUPTS_REACHED_BIT 0 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _IFFIFO_REG_DEFS_ +// End generated register defines for iffifo \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c index 7b6ba5f4..ffbb822d 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c @@ -371,7 +371,7 @@ plic_result_t plic_assign_external_irq_handler( uint32_t id, { if( id >= EXT_IRQ_START && id <= QTY_INTR ) { - handlers[ id ] = (handler_funct_t*) handler; + handlers[ id ] = (handler_funct_t) handler; return kPlicOk; } return kPlicBadArg; diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h index b5db646d..af81fe21 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h @@ -302,6 +302,15 @@ static inline __attribute__((always_inline)) void spi_wait_for_tx_not_empty(cons while (mmio_region_get_bit32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET, SPI_HOST_STATUS_TXEMPTY_BIT)); } +/** + * Wait TX FIFO not full. + * + * @param spi Pointer to spi_host_t representing the target SPI. + */ +static inline __attribute__((always_inline)) void spi_wait_for_tx_not_full(const spi_host_t *spi) { + while (mmio_region_get_bit32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET, SPI_HOST_STATUS_TXFULL_BIT)); +} + /** * Wait RX FIFO reach watermark. * diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c new file mode 100644 index 00000000..326fd963 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c @@ -0,0 +1,37 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "core_v_mini_mcu.h" +#include + +//heep functions prototypes +uint32_t * heep_get_flash_address_offset(uint32_t* data_address_lma); +void heep_init_lfsr(); +uint32_t heep_rand_lfsr(); + +// this translates the logical address of the FLASH relative to 0 instead of FLASH_MEM_START_ADDRESS, as used by the BSP +uint32_t * heep_get_flash_address_offset(uint32_t* data_address_lma){ + +#ifdef ON_CHIP + // no need to translate as FLASH is not memory mapped + return data_address_lma; +#else + uint32_t* data_address_adjusted = (uint32_t*) ((uint32_t)(data_address_lma) - FLASH_MEM_START_ADDRESS); + return data_address_adjusted; +#endif + +} + +//get random values +uint32_t lfsr; + +void heep_init_lfsr() { + lfsr = (uint32_t)0xAABBCCDD; +} + +uint32_t heep_rand_lfsr() { + uint32_t bit = (lfsr ^ (lfsr >> 10) ^ (lfsr >> 11) ^ (lfsr >> 12)) & 1; + lfsr = (lfsr >> 1) | (bit << 31); + return lfsr; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl index 1491a6ed..2bfec7d9 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl @@ -10,6 +10,9 @@ extern "C" { #endif // __cplusplus #define MEMORY_BANKS ${ram_numbanks} +% if ram_numbanks_il > 0: +#define HAS_MEMORY_BANKS_IL +% endif #define EXTERNAL_DOMAINS ${external_domains} @@ -67,6 +70,7 @@ extern "C" { #define GPIO_AO_DOMAIN_LIMIT 8 + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c index 8ee1a0d8..c9cd02d3 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c @@ -3,9 +3,9 @@ // SPDX-License-Identifier: Apache-2.0 #include "handler.h" - #include "csr.h" #include "stdasm.h" +#include ' /** * Return value of mtval diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c index 05dd28f9..a9a7fcc2 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c @@ -18,33 +18,41 @@ */ #include +#include #include #include +#include #include #include "uart.h" #include "soc_ctrl.h" #include "core_v_mini_mcu.h" #include "error.h" #include "x-heep.h" +#include #undef errno extern int errno; #define STDOUT_FILENO 1 -/* It turns out that older newlib versions use different symbol names which goes - * against newlib recommendations. Anyway this is fixed in later version. - */ -#if __NEWLIB__ <= 2 && __NEWLIB_MINOR__ <= 5 -# define _sbrk sbrk -# define _write write -# define _close close -# define _lseek lseek -# define _read read -# define _fstat fstat -# define _isatty isatty +#ifndef _LIBC +/* Provide prototypes for most of the _ names that are + provided in newlib for some compilers. */ +int _close (int __fildes); +pid_t _fork (void); +pid_t _getpid (void); +int _isatty (int __fildes); +int _link (const char *__path1, const char *__path2); +_off_t _lseek (int __fildes, _off_t __offset, int __whence); +ssize_t _read (int __fd, void *__buf, size_t __nbyte); +void * _sbrk (ptrdiff_t __incr); +int _unlink (const char *__path); +ssize_t _write (int __fd, const void *__buf, size_t __nbyte); +int _execve (const char *__path, char * const __argv[], char * const __envp[]); +int _kill (pid_t pid, int sig); #endif + void unimplemented_syscall() { const char *p = "Unimplemented system call called!\n"; @@ -108,7 +116,7 @@ int _faccessat(int dirfd, const char *file, int mode, int flags) return -1; } -int _fork(void) +pid_t _fork(void) { errno = EAGAIN; return -1; @@ -140,7 +148,7 @@ char *_getcwd(char *buf, size_t size) return NULL; } -int _getpid() +pid_t _getpid() { return 1; } @@ -156,7 +164,7 @@ int _isatty(int file) return (file == STDOUT_FILENO); } -int _kill(int pid, int sig) +int _kill(pid_t pid, int sig) { errno = EINVAL; return -1; diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h new file mode 100644 index 00000000..c1ef5c5c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h @@ -0,0 +1,30 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef X_HEEP +#define X_HEEP + +#pragma message ( "the x-heep.h for NEXYS-A7-100T is used" ) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +#define REFERENCE_CLOCK_Hz 15*1000*1000 +#define UART_BAUDRATE 9600 +#define TARGET_NEXYS_A7_100T 1 + +/** + * As the hw is configurable, we can have setups with different number of + * Gpio pins + */ +#define MAX_PIN 32 + + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // X_HEEP diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h new file mode 100644 index 00000000..1c1390cb --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h @@ -0,0 +1,30 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef X_HEEP +#define X_HEEP + +#pragma message ( "the x-heep.h for SIMULATION in SYSTEMC is used" ) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +#define REFERENCE_CLOCK_Hz 100*1000*1000 +#define UART_BAUDRATE 256000 +#define TARGET_SYSTEMC 1 + +/** + * As the hw is configurable, we can have setups with different number of + * Gpio pins + */ +#define MAX_PIN 32 + + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // X_HEEP diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h new file mode 100644 index 00000000..af1b4cd5 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h @@ -0,0 +1,28 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef X_HEEP +#define X_HEEP + +#pragma message ( "the x-heep.h for ZCU104 is used" ) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#define REFERENCE_CLOCK_Hz 15*1000*1000 +#define UART_BAUDRATE 9600 +#define TARGET_ZCU104 1 + +/** + * As the hw is configurable, we can have setups with different number of + * Gpio pins + */ +#define MAX_PIN 32 + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // X_HEEP diff --git a/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl b/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl index 98f491ce..7403248d 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl @@ -24,7 +24,7 @@ MEMORY ram1 (rwxai) : ORIGIN = 0x${linker_onchip_data_start_address}, LENGTH = 0x${linker_onchip_data_size_address} % if ram_numbanks_cont > 1 and ram_numbanks_il > 0: ram_il (rwxai) : ORIGIN = 0x${linker_onchip_il_start_address}, LENGTH = 0x${linker_onchip_il_size_address} -% endif +% endif } /* @@ -38,51 +38,13 @@ SECTIONS PROVIDE(__boot_address = 0x180); /* stack and heap related settings */ - __stack_size = DEFINED(__stack_size) ? __stack_size : 0x800; + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x${stack_size}; PROVIDE(__stack_size = __stack_size); - __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x${heap_size}; /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x10000)); . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS; - /* We don't do any dynamic linking so we remove everything related to it */ -/* - .interp : { *(.interp) } - .note.gnu.build-id : { *(.note.gnu.build-id) } - .hash : { *(.hash) } - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) - *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) - *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) - *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - PROVIDE_HIDDEN (__rela_iplt_start = .); - *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); - } - .rela.plt : - { - *(.rela.plt) - } -*/ - /* interrupt vectors */ .vectors (ORIGIN(ram0)): { @@ -97,11 +59,6 @@ SECTIONS KEEP (*(.text.start)) } >ram0 - /* More dynamic linking sections */ -/* - .plt : { *(.plt) } - .iplt : { *(.iplt) } -*/ /* the bulk of the program: main, libc, functions etc. */ .text : @@ -268,6 +225,8 @@ SECTIONS *(.data1) } >ram1 + _lma_vma_data_offset = 0x0; + /* no dynamic linking, no object tables required */ /* .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } */ @@ -335,12 +294,14 @@ SECTIONS PROVIDE(__freertos_irq_stack_top = .); } >ram1 -.data_interleaved : +% if ram_numbanks_cont > 1 and ram_numbanks_il > 0: + .data_interleaved : { . = ALIGN(4); *(.xheep_data_interleaved) . = ALIGN(4); } >ram_il +% endif /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff --git a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl index f8e0f83f..8bd9e64e 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl @@ -17,9 +17,9 @@ SECTIONS { PROVIDE(__boot_address = 0x40000180); /* stack and heap related settings */ - __stack_size = DEFINED(__stack_size) ? __stack_size : 0x1000; + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x${stack_size}; PROVIDE(__stack_size = __stack_size); - __heap_size = DEFINED(__heap_size) ? __heap_size : 0x1000; + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x${heap_size}; /* interrupt vectors */ .vectors (ORIGIN(FLASH)): @@ -70,6 +70,8 @@ SECTIONS { _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT >FLASH + _lma_vma_data_offset = 0x0; + .power_manager : ALIGN(4096) { PROVIDE(__power_manager_start = .); diff --git a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl index a33ca3dd..541b2233 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl @@ -7,47 +7,70 @@ ENTRY(_start) MEMORY { - FLASH (rx) : ORIGIN = 0x${flash_mem_start_address}, LENGTH = 0x${flash_mem_size_address} - RAM (xrw) : ORIGIN = 0x${'{:08X}'.format(int(ram_start_address,16))}, LENGTH = 0x${'{:08X}'.format(int(ram_size_address,16) - 4)} + ram0 (rwxai) : ORIGIN = 0x${linker_onchip_code_start_address}, LENGTH = 0x${linker_onchip_code_size_address} + ram1 (rwxai) : ORIGIN = 0x${linker_onchip_data_start_address}, LENGTH = 0x${linker_onchip_data_size_address} + FLASH0 (rx) : ORIGIN = 0x${linker_flash_code_start_address}, LENGTH = 0x${linker_onchip_code_size_address} + FLASH1 (rx) : ORIGIN = 0x${linker_flash_data_start_address}, LENGTH = 0x${linker_onchip_data_size_address} + % if ram_numbanks_cont > 1 and ram_numbanks_il > 0: + ram_il (rwxai) : ORIGIN = 0x${linker_onchip_il_start_address}, LENGTH = 0x${linker_onchip_il_size_address} + FLASH_il (rx) : ORIGIN = 0x${linker_flash_il_start_address}, LENGTH = 0x${linker_onchip_il_size_address} + % endif + FLASH_left (rx) : ORIGIN = 0x${linker_flash_left_start_address}, LENGTH = 0x${linker_flash_left_size_address} } + + SECTIONS { /* we want a fixed entry point */ PROVIDE(__boot_address = 0x180); /* stack and heap related settings */ - __stack_size = DEFINED(__stack_size) ? __stack_size : 0x1000; + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x${stack_size}; PROVIDE(__stack_size = __stack_size); - __heap_size = DEFINED(__heap_size) ? __heap_size : 0x1000; + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x${heap_size}; /* interrupt vectors */ - .vectors (ORIGIN(RAM)): + .vectors (ORIGIN(ram0)): { PROVIDE(__vector_start = .); + _lma_text_start = LOADADDR(.vectors); KEEP(*(.vectors)); __VECTORS_AT = .; - } >RAM AT >FLASH + } >ram0 AT >FLASH0 /* Fill memory up to __boot_address */ .fill : { FILL(0xDEADBEEF); - . = ORIGIN(RAM) + (__boot_address) - 1; + . = ORIGIN(ram0) + (__boot_address) - 1; BYTE(0xEE) - } >RAM AT >FLASH + } >ram0 AT >FLASH0 /* crt0 init code */ .init (__boot_address): { KEEP (*(SORT_NONE(.init))) KEEP (*(.text.start)) - } >RAM AT >FLASH + KEEP (*(.text.w25q128jw_init_crt0)) + KEEP (*(.text.w25q128jw_sanity_checks)) + KEEP (*(.text.spi_write_word*)) + KEEP (*(.text.spi_wait_for_ready*)) + KEEP (*(.text.spi_create_command*)) + KEEP (*(.text.spi_set_command*)) + KEEP (*(.text.spi_set_rx_watermark*)) + KEEP (*(.text.spi_wait_for_rx_watermark*)) + KEEP (*(.text.spi_read_word*)) + KEEP (*(.text.memcpy)) + KEEP (*(.text.w25q128jw_read_standard)) /* as this function is used in the crt0, link it in the top, should be before 1024 Bytes loaded by the bootrom */ + *(.xheep_init_data_crt0) /* this global variables are used in the crt0 */ + } >ram0 AT >FLASH0 /* The program code and other data goes into FLASH */ .text : ALIGN_WITH_INPUT { . = ALIGN(4); + __text_start = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ @@ -56,16 +79,17 @@ SECTIONS { *(.srodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ - } >RAM AT >FLASH + } >ram0 AT >FLASH0 /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ - .data : ALIGN_WITH_INPUT + .data : ALIGN(256) { - . = ALIGN(4); + __data_start = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ _sidata = LOADADDR(.data); + _lma_data_start = LOADADDR(.data); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ _ram_start = .; /* create a global symbol at ram start for garbage collector */ . = ALIGN(4); @@ -75,18 +99,20 @@ SECTIONS { __SDATA_BEGIN__ = .; *(.sdata) /* .sdata sections */ *(.sdata*) /* .sdata* sections */ - . = ALIGN(4); - _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ - } >RAM AT >FLASH + } >ram1 AT >FLASH1 + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ - .power_manager : ALIGN(4096) + .power_manager : ALIGN_WITH_INPUT { + . = ALIGN(4); PROVIDE(__power_manager_start = .); . += 256; - } >RAM + } >ram1 AT >FLASH1 /* Uninitialized data section */ - .bss : + .bss : ALIGN_WITH_INPUT { . = ALIGN(4); __bss_start = .; /* define a global symbol at bss start; used by startup code */ @@ -99,7 +125,14 @@ SECTIONS { . = ALIGN(4); __bss_end = .; /* define a global symbol at bss end; used by startup code */ __BSS_END__ = .; - } >RAM + } >ram1 AT >FLASH1 + + _lma_data_end = _lma_data_start + SIZEOF(.data) + SIZEOF(.power_manager) + SIZEOF(.bss); + _lma_vma_data_offset = _lma_data_start - __data_start; + + _lma_text_end = _lma_text_start + SIZEOF(.vectors) + SIZEOF(.init) + SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.power_manager) + SIZEOF(.bss); + _lma_text_vma_offset = _lma_text_start - __vector_start; + /* The compiler uses this to access data in the .sdata, .data, .sbss and .bss sections with fewer instructions (relaxation). This reduces code size. */ @@ -112,7 +145,7 @@ SECTIONS { PROVIDE(__heap_start = .); . = __heap_size; PROVIDE(__heap_end = .); - } >RAM + } >ram1 /* stack: we should consider putting this further to the top of the address space */ @@ -123,5 +156,29 @@ SECTIONS { PROVIDE(_sp = .); PROVIDE(__stack_end = .); PROVIDE(__freertos_irq_stack_top = .); - } >RAM + } >ram1 + + % if ram_numbanks_cont > 1 and ram_numbanks_il > 0: + .data_interleaved : ALIGN_WITH_INPUT + { + PROVIDE(__data_interleaved_start = .); + _lma_data_interleaved_start = LOADADDR(.data_interleaved); + . = ALIGN(4); + *(.xheep_data_interleaved) + . = ALIGN(4); + } >ram_il AT >FLASH_il + + . = ALIGN(4); + _eddata_interleaved = .; + _lma_data_interleaved_end = _lma_data_interleaved_start + SIZEOF(.data_interleaved); + + % endif + + .data_flash_only : ALIGN(256) + { + . = ALIGN(4); + *(.xheep_data_flash_only) + . = ALIGN(4); + } >FLASH_left + } diff --git a/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch b/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch index b325b7bc..1af9cacb 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch +++ b/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch @@ -1,8 +1,43 @@ diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c -index 8ee6443..38e308f 100644 +index 8ee6443..0413697 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c -@@ -506,6 +506,7 @@ static void help(const char *progname) +@@ -480,6 +480,34 @@ static void flash_enable_quad() + fprintf(stderr, "SR2: %08x\n", data[1]); + } + ++static void flash_disable_quad() ++{ ++ fprintf(stderr, "Disabling Quad operation...\n"); ++ ++ // Allow write ++ flash_write_enable(); ++ ++ // Write Status Register 2 <- 0x00 ++ uint8_t data[2] = { FC_WSR2, 0x00 }; ++ flash_chip_select(); ++ mpsse_xfer_spi(data, 2); ++ flash_chip_deselect(); ++ ++ flash_wait(); ++ ++ // Read Status Register 1 ++ data[0] = FC_RSR2; ++ ++ flash_chip_select(); ++ mpsse_xfer_spi(data, 2); ++ flash_chip_deselect(); ++ ++ if ((data[1] & 0x02) != 0x00) ++ fprintf(stderr, "failed to set QE=0, SR2 now equal to 0x%02x (expected 0x%02x)\n", data[1], data[1] | 0x00); ++ ++ fprintf(stderr, "SR2: %08x\n", data[1]); ++} ++ + // --------------------------------------------------------- + // iceprog implementation + // --------------------------------------------------------- +@@ -506,11 +534,13 @@ static void help(const char *progname) fprintf(stderr, " -s slow SPI (50 kHz instead of 6 MHz)\n"); fprintf(stderr, " -k keep flash in powered up state (i.e. skip power down command)\n"); fprintf(stderr, " -v verbose output\n"); @@ -10,25 +45,61 @@ index 8ee6443..38e308f 100644 fprintf(stderr, " -i [4,32,64] select erase block size [default: 64k]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Mode of operation:\n"); -@@ -587,6 +588,8 @@ int main(int argc, char **argv) + fprintf(stderr, " [default] write file contents to flash, then verify\n"); + fprintf(stderr, " -X write file contents to flash only\n"); ++ fprintf(stderr, " -a provides file size of the file to program\n"); + fprintf(stderr, " -r read first 256 kB from flash and write to file\n"); + fprintf(stderr, " -R read the specified number of bytes from flash\n"); + fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n"); +@@ -578,6 +608,7 @@ int main(int argc, char **argv) + bool bulk_erase = false; + bool dont_erase = false; + bool prog_sram = false; ++ bool filesize_mode = false; + int test_mode = 0; + bool slow_clock = false; + bool disable_protect = false; +@@ -587,6 +618,9 @@ int main(int argc, char **argv) const char *devstr = NULL; int ifnum = 0; + bool stop_spi = false; ++ long file_size = -1; + #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY); -@@ -600,7 +603,7 @@ int main(int argc, char **argv) +@@ -600,7 +634,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvspXk", long_options, NULL)) != -1) { -+ while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvTspXk", long_options, NULL)) != -1) { ++ while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:a:cbnStQvTspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; -@@ -696,6 +699,9 @@ int main(int argc, char **argv) +@@ -648,6 +682,20 @@ int main(int argc, char **argv) + return EXIT_FAILURE; + } + break; ++ case 'a': /* filesize used to program flash */ ++ filesize_mode = true; ++ file_size = strtol(optarg, &endptr, 0); ++ if (*endptr == '\0') ++ /* ok */; ++ else if (!strcmp(endptr, "k")) ++ file_size *= 1024; ++ else if (!strcmp(endptr, "M")) ++ file_size *= 1024 * 1024; ++ else { ++ fprintf(stderr, "%s: `%s' is not a valid size\n", my_name, optarg); ++ return EXIT_FAILURE; ++ } ++ break; + case 'e': /* Erase blocks as if we were writing n bytes */ + erase_mode = true; + erase_size = strtol(optarg, &endptr, 0); +@@ -696,6 +744,9 @@ int main(int argc, char **argv) case 'v': /* provide verbose output */ verbose = true; break; @@ -38,7 +109,46 @@ index 8ee6443..38e308f 100644 case 's': /* use slow SPI clock */ slow_clock = true; break; -@@ -997,22 +1003,59 @@ int main(int argc, char **argv) +@@ -778,7 +829,7 @@ int main(int argc, char **argv) + so we can fail before initializing the hardware */ + + FILE *f = NULL; +- long file_size = -1; ++ + + if (test_mode) { + /* nop */; +@@ -809,7 +860,7 @@ int main(int argc, char **argv) + named pipe, or contrarily, the standard input may be an + ordinary file. */ + +- if (!prog_sram && !check_mode) { ++ if (!prog_sram && !check_mode && !filesize_mode) { + if (fseek(f, 0L, SEEK_END) != -1) { + file_size = ftell(f); + if (file_size == -1) { +@@ -943,6 +994,8 @@ int main(int argc, char **argv) + flash_reset(); + flash_power_up(); + ++ flash_disable_quad(); ++ + flash_read_id(); + + +@@ -968,7 +1021,10 @@ int main(int argc, char **argv) + } + else + { +- fprintf(stderr, "file size: %ld\n", file_size); ++ if(filesize_mode) ++ fprintf(stderr, "provided file size: %ld\n", file_size); ++ else ++ fprintf(stderr, "file size: %ld\n", file_size); + + int block_size = erase_block_size << 10; + int block_mask = block_size - 1; +@@ -997,22 +1053,59 @@ int main(int argc, char **argv) } } @@ -62,7 +172,7 @@ index 8ee6443..38e308f 100644 + size_t len = 0; + uint8_t buffer[256]; + int count = 0; -+ while (true) { ++ while (true) { + rc = getline(&line_buffer, &len, f); + if (rc <= 0){ + if(count > 0){ @@ -107,20 +217,22 @@ index 8ee6443..38e308f 100644 fprintf(stderr, " \r"); fprintf(stderr, "done.\n"); -@@ -1026,6 +1069,12 @@ int main(int argc, char **argv) +@@ -1026,7 +1119,13 @@ int main(int argc, char **argv) // --------------------------------------------------------- if (read_mode) { +- fprintf(stderr, "reading..\n"); + if(stop_spi){ + /* Just to debug reading of values with the logic analyzer*/ + printf("Stoped before writting. Press ENTER to continue\n"); + getchar(); + } + - fprintf(stderr, "reading..\n"); ++ fprintf(stderr, "reading.."); for (int addr = 0; addr < read_size; addr += 256) { uint8_t buffer[256]; -@@ -1037,23 +1086,40 @@ int main(int argc, char **argv) + fprintf(stderr, " \r"); +@@ -1037,23 +1136,40 @@ int main(int argc, char **argv) fprintf(stderr, " \r"); fprintf(stderr, "done.\n"); } else if (!erase_mode && !disable_verify) { @@ -134,7 +246,7 @@ index 8ee6443..38e308f 100644 + int rc, addr = 0; + size_t len = 0; + uint8_t buffer_flash[256], buffer_file[256]; -+ while (true) { ++ while (true) { + rc = getline(&line_buffer, &len, f); if (rc <= 0) break; diff --git a/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c b/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c index 38e308f8..0413697d 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c +++ b/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c @@ -480,6 +480,34 @@ static void flash_enable_quad() fprintf(stderr, "SR2: %08x\n", data[1]); } +static void flash_disable_quad() +{ + fprintf(stderr, "Disabling Quad operation...\n"); + + // Allow write + flash_write_enable(); + + // Write Status Register 2 <- 0x00 + uint8_t data[2] = { FC_WSR2, 0x00 }; + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + flash_wait(); + + // Read Status Register 1 + data[0] = FC_RSR2; + + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + if ((data[1] & 0x02) != 0x00) + fprintf(stderr, "failed to set QE=0, SR2 now equal to 0x%02x (expected 0x%02x)\n", data[1], data[1] | 0x00); + + fprintf(stderr, "SR2: %08x\n", data[1]); +} + // --------------------------------------------------------- // iceprog implementation // --------------------------------------------------------- @@ -512,6 +540,7 @@ static void help(const char *progname) fprintf(stderr, "Mode of operation:\n"); fprintf(stderr, " [default] write file contents to flash, then verify\n"); fprintf(stderr, " -X write file contents to flash only\n"); + fprintf(stderr, " -a provides file size of the file to program\n"); fprintf(stderr, " -r read first 256 kB from flash and write to file\n"); fprintf(stderr, " -R read the specified number of bytes from flash\n"); fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n"); @@ -579,6 +608,7 @@ int main(int argc, char **argv) bool bulk_erase = false; bool dont_erase = false; bool prog_sram = false; + bool filesize_mode = false; int test_mode = 0; bool slow_clock = false; bool disable_protect = false; @@ -589,6 +619,7 @@ int main(int argc, char **argv) int ifnum = 0; bool stop_spi = false; + long file_size = -1; #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); @@ -603,7 +634,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvTspXk", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:a:cbnStQvTspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; @@ -651,6 +682,20 @@ int main(int argc, char **argv) return EXIT_FAILURE; } break; + case 'a': /* filesize used to program flash */ + filesize_mode = true; + file_size = strtol(optarg, &endptr, 0); + if (*endptr == '\0') + /* ok */; + else if (!strcmp(endptr, "k")) + file_size *= 1024; + else if (!strcmp(endptr, "M")) + file_size *= 1024 * 1024; + else { + fprintf(stderr, "%s: `%s' is not a valid size\n", my_name, optarg); + return EXIT_FAILURE; + } + break; case 'e': /* Erase blocks as if we were writing n bytes */ erase_mode = true; erase_size = strtol(optarg, &endptr, 0); @@ -784,7 +829,7 @@ int main(int argc, char **argv) so we can fail before initializing the hardware */ FILE *f = NULL; - long file_size = -1; + if (test_mode) { /* nop */; @@ -815,7 +860,7 @@ int main(int argc, char **argv) named pipe, or contrarily, the standard input may be an ordinary file. */ - if (!prog_sram && !check_mode) { + if (!prog_sram && !check_mode && !filesize_mode) { if (fseek(f, 0L, SEEK_END) != -1) { file_size = ftell(f); if (file_size == -1) { @@ -949,6 +994,8 @@ int main(int argc, char **argv) flash_reset(); flash_power_up(); + flash_disable_quad(); + flash_read_id(); @@ -974,7 +1021,10 @@ int main(int argc, char **argv) } else { - fprintf(stderr, "file size: %ld\n", file_size); + if(filesize_mode) + fprintf(stderr, "provided file size: %ld\n", file_size); + else + fprintf(stderr, "file size: %ld\n", file_size); int block_size = erase_block_size << 10; int block_mask = block_size - 1; @@ -1018,7 +1068,7 @@ int main(int argc, char **argv) size_t len = 0; uint8_t buffer[256]; int count = 0; - while (true) { + while (true) { rc = getline(&line_buffer, &len, f); if (rc <= 0){ if(count > 0){ @@ -1075,7 +1125,7 @@ int main(int argc, char **argv) getchar(); } - fprintf(stderr, "reading..\n"); + fprintf(stderr, "reading.."); for (int addr = 0; addr < read_size; addr += 256) { uint8_t buffer[256]; fprintf(stderr, " \r"); @@ -1093,7 +1143,7 @@ int main(int argc, char **argv) int rc, addr = 0; size_t len = 0; uint8_t buffer_flash[256], buffer_file[256]; - while (true) { + while (true) { rc = getline(&line_buffer, &len, f); if (rc <= 0) break; diff --git a/hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp b/hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp new file mode 100644 index 00000000..947d31ef --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp @@ -0,0 +1,100 @@ +#include "XHEEP_CmdLineOptions.hh" +#include +#include + +XHEEP_CmdLineOptions::XHEEP_CmdLineOptions(int argc, char* argv[]) // define default constructor +{ + this->argc = argc; + this->argv = argv; +} + +std::string XHEEP_CmdLineOptions::getCmdOption(int argc, char* argv[], const std::string& option) +{ + std::string cmd; + for( int i = 0; i < argc; ++i) + { + std::string arg = argv[i]; + size_t arg_size = arg.length(); + size_t option_size = option.length(); + + if(arg.find(option)==0){ + cmd = arg.substr(option_size,arg_size-option_size); + } + } + return cmd; +} + +bool XHEEP_CmdLineOptions::get_use_openocd() +{ + + std::string arg_openocd = this->getCmdOption(this->argc, this->argv, "+openOCD=");; + + bool use_openocd = false; + + if(arg_openocd.empty()){ + std::cout<<"[TESTBENCH]: No OpenOCD is used"<getCmdOption(this->argc, this->argv, "+firmware="); + + if(firmware.empty()){ + std::cout<<"[TESTBENCH]: No firmware specified"<getCmdOption(this->argc, this->argv, "+max_sim_time="); + unsigned int max_sim_time; + + max_sim_time = 0; + if(arg_max_sim_time.empty()){ + std::cout<<"[TESTBENCH]: No Max time specified"<getCmdOption(this->argc, this->argv, "+boot_sel="); + unsigned int boot_sel = 0; + + if(arg_boot_sel.empty()){ + std::cout<<"[TESTBENCH]: No Boot Option specified, using jtag (boot_sel=0)"< + +class XHEEP_CmdLineOptions // declare Calculator class +{ + + public: // public members + XHEEP_CmdLineOptions(int argc, char* argv[]); // default constructor + + std::string getCmdOption(int argc, char* argv[], const std::string& option); // get options from cmd lines + bool get_use_openocd(); + std::string get_firmware(); + unsigned int get_max_sim_time(bool& run_all); + unsigned int get_boot_sel(); + int argc; + char** argv; + +}; + + + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg b/hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg new file mode 100644 index 00000000..f0134765 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg @@ -0,0 +1,44 @@ +adapter driver ftdi +adapter speed 1000 +transport select jtag + + +# FT2232HQ Adapter Pynq Z2 +ftdi_vid_pid 0x0403 0x6010 + +ftdi_channel 0 +ftdi_layout_init 0x0088 0x008b + +reset_config none + +echo "ftdi setting..." + +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 6 -expected-id 0x23727093 +jtag newtap arm_dap_0 tap -irlen 4 -expected-id 0x4ba00477 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000 + +echo "target created..." + +#log_output openocd_fpga.log + +riscv set_ir idcode 0x09 +riscv set_ir dtmcs 0x22 +riscv set_ir dmi 0x23 + +riscv set_reset_timeout_sec 2000 +riscv set_command_timeout_sec 2000 + +echo "setting preferences..." + +scan_chain + +init + +echo "init routine started" + +halt + +echo "Ready for Remote Connections" \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h new file mode 100644 index 00000000..d9c94b5d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h @@ -0,0 +1,221 @@ +#ifndef CACHE_H +#define CACHE_H + +#include +#include +#include +#include + + +// Target module representing a simple direct mapped cache +class CacheMemory +{ + +public: + uint32_t cache_size_byte = 4*1024; + uint32_t number_of_blocks = 256; + + uint32_t nbits_blocks = 0; + uint32_t nbits_tags = 0; + uint32_t nbits_index = 0; + uint32_t block_size_byte = 0; + + enum { ARCHITECTURE_bits = 32 }; + + std::ofstream cacheFile; + + typedef struct cache_line { + uint32_t tag; + bool valid; + uint8_t* data; + } cache_line_t; + + cache_line_t* cache_array; + + + CacheMemory(): cacheFile("cache_status.log") + { + cache_array = NULL; + } + + void create_cache() { + cache_array = new cache_line_t[number_of_blocks]; + this->block_size_byte = get_block_size(); + this->nbits_blocks = log2(block_size_byte); + this->nbits_index = log2(number_of_blocks); + this->nbits_tags = ARCHITECTURE_bits - nbits_index - nbits_blocks; + printf("bits block %d, index %d, tags %d\n",nbits_blocks, nbits_index, nbits_tags ); + } + + void create_cache(uint32_t cache_size_byte, uint32_t number_of_blocks) { + this->cache_size_byte = cache_size_byte; + this->number_of_blocks = number_of_blocks; + cache_array = new cache_line_t[number_of_blocks]; + this->block_size_byte = get_block_size(); + this->nbits_blocks = log2(block_size_byte); + this->nbits_index = log2(number_of_blocks); + this->nbits_tags = ARCHITECTURE_bits - nbits_index - nbits_blocks; + } + + uint32_t initialize_cache() { + if(cache_array == NULL) { + return -1; + } + // Initialize memory with random data + for (int i = 0; i < number_of_blocks; i++) { + cache_array[i].valid = false; + cache_array[i].tag = 0; + cache_array[i].data = new uint8_t[block_size_byte]; + for(int j = 0; j> nbits_blocks) & mask_index ); + } + + uint32_t get_block_offset(uint32_t address) { + uint32_t mask_block = (1 << nbits_blocks) - 1; + return (uint32_t)(address & mask_block); + } + + uint32_t get_base_address(uint32_t address) { + return (uint32_t)((address >> nbits_blocks) << nbits_blocks); + } + + uint32_t get_tag(uint32_t address) { + return (uint32_t)(address >> (nbits_index+nbits_blocks)); + } + + uint32_t get_tag_from_index(uint32_t index) { + return cache_array[index].tag; + } + + + bool cache_hit(uint32_t address) { + uint32_t index = get_index(address); + uint32_t tag = get_tag(address); + return ( cache_array[index].valid && tag == cache_array[index].tag); + + } + + void add_entry(uint32_t address, uint8_t* new_data) { + uint32_t index = get_index(address); + uint32_t tag = get_tag(address); + cache_array[index].valid = true; + cache_array[index].tag = tag; + memcpy(cache_array[index].data, new_data, block_size_byte); + } + + void get_data(uint32_t address, uint8_t* new_data) { + uint32_t index = get_index(address); + memcpy(new_data, cache_array[index].data, block_size_byte); + } + + void get_data_at_index(uint32_t index, uint8_t* new_data) { + memcpy(new_data, cache_array[index].data, block_size_byte); + } + + uint32_t get_address(uint32_t address){ + uint32_t index = get_index(address); + uint32_t tag = cache_array[index].tag; + uint32_t new_address = (tag << (nbits_index+nbits_blocks)) | (index<get_block_offset(address); + uint8_t* new_data = new uint8_t[block_size_byte]; + this->get_data(address, new_data); + data_word = *((int32_t *)&new_data[block_offset]); + delete new_data; + return data_word; + } + + void set_word(uint32_t address, int32_t data_word) { + uint32_t block_offset = this->get_block_offset(address); + uint8_t* new_data = new uint8_t[block_size_byte]; + this->get_data(address, new_data); + *((int32_t *)&new_data[block_offset]) = data_word; + for(int i=0;iadd_entry(address, new_data); + delete new_data; + } + + bool is_entry_valid(uint32_t address) { + uint32_t index = get_index(address); + return cache_array[index].valid; + } + + bool is_entry_valid_at_index(uint32_t index) { + return cache_array[index].valid; + } + + void print_cache_status(uint32_t operation_id, std::string time_str) { + if (cacheFile.is_open()) { + std::string log_cache = ""; + std::ostringstream ss; + + log_cache+= std::to_string(operation_id) + "): " + time_str + "\n"; + log_cache+= "INDEX | TAG | DATA BLOCK | VALID\n"; + + for(int i=0;inbits_index/4) << std::setfill('0') << std::hex << static_cast(i); + log_cache+= ss.str() + " | "; + ss.str(""); + ss.clear(); + ss << "0x" << std::setw(this->nbits_tags/4) << std::setfill('0') << std::hex << cache_array[i].tag; + log_cache+= ss.str() + " | 0x"; + ss.str(""); + ss.clear(); + for(int j = 0; j(cache_array[i].data[j]); + log_cache+= ss.str() + " | "; + log_cache+= std::string( cache_array[i].valid ? "1" : "0" ) + "\n"; + + cacheFile << log_cache; + ss.str(""); + ss.clear(); + log_cache = std::string(""); + } + } else { + std::cout << "Failed to create the Cache file." << std::endl; + } + } + + /* main memory address + 0x7052 = 'b111_0000_0101_0010' + + cache size = 4KB, + number_of_blocks = 256, thus index is on 8bit + block_size_in_byte = 4KB/256 = 16bytes, i.e. 4 words + + 111: tag + 0000_0101: used as index + 0010: used for block offset , 4bits as 16 bytes + + + get_tag(0x7052) --> 0x7 + get_index(0x7052) --> 0x5 + get_block_offset(0x7052) --> 0x2 + + + */ +}; + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h new file mode 100644 index 00000000..984f81cf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h @@ -0,0 +1,68 @@ +#ifndef MEMORY_H +#define MEMORY_H + +// Needed for the simple_target_socket +#define SC_INCLUDE_DYNAMIC_PROCESSES + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" + + +// Target module representing a simple direct mapped cache +SC_MODULE(MainMemory) +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_target_socket socket; + + enum { SIZE = 32*1024/4 }; //32KB word addressable + + int32_t mem[SIZE]; + + + SC_CTOR(MainMemory) + : socket("socket") + { + // Register callback for incoming b_transport interface method call + socket.register_b_transport(this, &MainMemory::b_transport); + + // Initialize memory with random data + for (int i = 0; i < SIZE; i++) + mem[i] = 0xAA000000 | (rand() % 256); + } + + // TLM-2 blocking transport method + virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) + { + tlm::tlm_command cmd = trans.get_command(); + sc_dt::uint64 adr = trans.get_address() / 4; + unsigned char* ptr = trans.get_data_ptr(); + unsigned int len = trans.get_data_length(); + unsigned char* byt = trans.get_byte_enable_ptr(); + unsigned int wid = trans.get_streaming_width(); + + // Obliged to check address range and check for unsupported features, + // i.e. byte enables, streaming, and bursts + // Can ignore DMI hint and extensions + // Using the SystemC report handler is an acceptable way of signalling an error + + if (adr >= sc_dt::uint64(SIZE) || byt != 0 || len > 4 || wid < len) + SC_REPORT_ERROR("TLM-2", "Target does not support given generic payload transaction"); + + // Obliged to implement read and write commands + if ( cmd == tlm::TLM_READ_COMMAND ) + memcpy(ptr, &mem[adr], len); + else if ( cmd == tlm::TLM_WRITE_COMMAND ) + memcpy(&mem[adr], ptr, len); + + // Obliged to set response status to indicate successful completion + trans.set_response_status( tlm::TLM_OK_RESPONSE ); + } + +}; + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h new file mode 100644 index 00000000..c0a7d1c7 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h @@ -0,0 +1,241 @@ +#ifndef MEMORYREQUEST_H +#define MEMORYREQUEST_H + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" + +#include "Cache.h" + +#include +#include +#include +#include + +// MemoryRequest module generating generic payload transactions + +SC_MODULE(MemoryRequest) +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_initiator_socket socket; + bool we_i; + uint32_t be_i; + uint32_t addr_i; + uint32_t rwdata_io; + CacheMemory* cache; + std::ofstream heep_mem_transactions; + bool bypass_state = false; + + typedef struct cache_statistics + { + uint32_t number_of_transactions; + uint32_t number_of_hit; + uint32_t number_of_miss; + } cache_statistics_t; + + cache_statistics_t cache_stat; + + SC_CTOR(MemoryRequest) + : socket("socket"), // Construct and name socket + heep_mem_transactions("heep_mem_transactions.log") + { + + cache = new CacheMemory; + cache->create_cache(); + cache->initialize_cache(); + cache_stat.number_of_transactions = 0; + cache_stat.number_of_hit = 0; + cache_stat.number_of_miss = 0; + cache->print_cache_status(cache_stat.number_of_transactions++, sc_time_stamp().to_string()); + + SC_THREAD(thread_process); + } + + + uint32_t memory_copy(uint32_t addr, int32_t* buffer_data, int N, bool write_enable, tlm::tlm_generic_payload* trans, sc_time delay) { + + tlm::tlm_command cmd = write_enable ? tlm::TLM_WRITE_COMMAND : tlm::TLM_READ_COMMAND; + + //first read block_size bytes from memory to place them in cache regardless of the cmd + for(int i=0; i < N; i++){ + trans->set_command( cmd ); + trans->set_address( (addr + i*4) & 0x00007FFF ); //15bits + trans->set_data_ptr( reinterpret_cast(&buffer_data[i]) ); + trans->set_data_length( 4 ); + trans->set_streaming_width( 4 ); // = data_length to indicate no streaming + trans->set_byte_enable_ptr( 0 ); // 0 indicates unused + trans->set_dmi_allowed( false ); // Mandatory initial value + trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value + socket->b_transport( *trans, delay ); // Blocking transport call + + if(bypass_state){ + if(write_enable) + heep_mem_transactions << "Writing to Mem[" << hex << ((addr + i*4) & 0x00007FFF) << "]: " << buffer_data[i] << " at time " << sc_time_stamp() <is_response_error() ) + SC_REPORT_ERROR("TLM-2", "Response error from b_transport"); + } + return N; + } + + + void thread_process() + { + // TLM-2 generic payload transaction, reused across calls to b_transport + tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; + + sc_time delay_gnt_miss = sc_time(100, SC_NS); + sc_time delay_rvalid_miss = sc_time(100, SC_NS); + + sc_time delay_rvalid_hit = sc_time(20, SC_NS); //as of today, it must be >=20 + + sc_time delay = sc_time(1, SC_NS); + + uint32_t cache_block_size_byte = cache->get_block_size(); + uint32_t cache_block_size_word = cache->get_block_size()/4; + uint8_t* cache_data = new uint8_t[cache_block_size_byte]; + int32_t* main_mem_data = new int32_t[cache_block_size_word]; + uint32_t address_to_replace; + uint32_t cache_flushed; + + while(true) { + + wait(obi_new_req); + + heep_mem_transactions << "X-HEEP tlm_generic_payload REQ: { " << (we_i ? 'W' : 'R') << ", @0x" << hex << addr_i + << " , DATA = 0x" << hex << rwdata_io << " BE = " << hex << be_i <<", at time " << sc_time_stamp() << " }" << std::endl; + + if(be_i!=0xF) { + SC_REPORT_ERROR("OBI External Memory SystemC", "ByteEnable different than 0xF is not supported"); + } + + //if we are writing 1 or 2 to last address, flush cache or bypass + if(we_i && ((addr_i & 0x00007FFF) == 0x7FFC)){ + + if(rwdata_io == 1){ + //FLUSH Cache + heep_mem_transactions << "X-HEEP Flush Cache, at time " << sc_time_stamp() << " }" << std::endl; + uint32_t cache_number_of_blocks = cache->number_of_blocks; + heep_mem_transactions<<"Cache Flushing at time "<is_entry_valid_at_index(i)) { + cache_flushed++; + //if we are going to replace a valid entry + cache->get_data_at_index(i, cache_data); + address_to_replace = cache->get_address_at_index(i); + //write back + memory_copy(address_to_replace, (uint32_t *)cache_data, cache_block_size_word, true, trans, delay); + } + } + heep_mem_transactions<<"Cache Flushed "<< dec << cache_flushed << " entries"<cache_hit(addr_i)){ + + heep_mem_transactions << "Cache HIT on address " << hex << addr_i << " at time " << sc_time_stamp() <get_word(addr_i); + //if Write, writes to cache + if(we_i) + cache->set_word(addr_i, rwdata_io); + else + rwdata_io = main_mem_data[0]; + wait(delay_rvalid_hit); + } + + else { //miss case + + cache_stat.number_of_miss++; + + heep_mem_transactions << "Cache MISS on address " << hex << addr_i << " at time " << sc_time_stamp() <get_base_address(addr_i); + uint32_t addr_offset = cache->get_block_offset(addr_i); + + //first read block_size bytes from memory to place them in cache regardless of the cmd + memory_copy(addr_to_read, main_mem_data, cache_block_size_word, false, trans, delay); + uint32_t index_to_add = cache->get_index(addr_i); + uint32_t tag_to_add = cache->get_tag(addr_i); + + heep_mem_transactions << "Adding to Cache TAG " << hex << tag_to_add << " and index " << hex << index_to_add <is_entry_valid(addr_i)) { + //if we are going to replace a valid entry + cache->get_data(addr_i, cache_data); + address_to_replace = cache->get_address(addr_i); + uint32_t index_to_replace = cache->get_index(addr_i); + uint32_t tag_to_replace = cache->get_tag_from_index(index_to_replace); + + heep_mem_transactions << "Cache Replace address " << hex << addr_i << " with address " << hex << address_to_replace << " due to the MISS at time " << sc_time_stamp() <add_entry(addr_i, (uint8_t*)main_mem_data); + + //if Write, writes to cache + if(we_i) + cache->set_word(addr_i, rwdata_io); + + //now give back the rdata + rwdata_io = main_mem_data[addr_offset>>2]; //>>2 as addr_offset is for byte address, not words + + //wait some time before giving the rvalid + wait(delay_rvalid_miss); + + } + } + } + + heep_mem_transactions << "X-HEEP tlm_generic_payload RESP: { DATA = 0x" << hex << rwdata_io <<", at time " << sc_time_stamp() << " }" << std::endl; + cache->print_cache_status(cache_stat.number_of_transactions++, sc_time_stamp().to_string()); + + obi_new_rvalid.notify(); + + } + } +}; + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp b/hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp new file mode 100644 index 00000000..b619d950 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp @@ -0,0 +1,342 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "verilated.h" +#include +#include "Vtestharness.h" +#include "Vtestharness__Syms.h" +#include "systemc.h" +#include +#include +#include "XHEEP_CmdLineOptions.hh" + +sc_event reset_done_event; +sc_event obi_new_gnt; +sc_event obi_new_rvalid; +sc_event obi_new_req; + + +#include "systemc_tb/MemoryRequest.h" +#include "systemc_tb/MainMemory.h" + + +#define CLK_PERIOD 10 + +SC_MODULE(external_memory) +{ + MemoryRequest *memory_request; + MainMemory *memory; + + sc_in clk_i; + sc_in ext_systemc_req_req_i; + sc_in ext_systemc_req_we_i; + sc_in ext_systemc_req_be_i; + sc_in ext_systemc_req_addr_i; + sc_in ext_systemc_req_wdata_i; + sc_out ext_systemc_resp_gnt_o; + sc_out ext_systemc_resp_rvalid_o; + sc_out ext_systemc_resp_rdata_o; + + void notify_obi_transaction () { + if(ext_systemc_req_req_i) { + obi_new_req.notify(); + memory_request->we_i = ext_systemc_req_we_i; + memory_request->be_i = ext_systemc_req_be_i; + memory_request->addr_i = ext_systemc_req_addr_i; + memory_request->rwdata_io = ext_systemc_req_wdata_i; + } + } + + void give_gnt_back () { + while (true) { + ext_systemc_resp_gnt_o.write(false); + wait(obi_new_gnt); + ext_systemc_resp_gnt_o.write(true); + wait(); + } + } + + void give_rvalid_rdata_back () { + while (true) { + ext_systemc_resp_rvalid_o.write(false); + wait(obi_new_rvalid); + ext_systemc_resp_rvalid_o.write(true); + ext_systemc_resp_rdata_o.write(memory_request->rwdata_io); + wait(); + } + } + + SC_CTOR(external_memory) + { + // Instantiate components + memory_request = new MemoryRequest("memory_request"); + memory = new MainMemory ("main_memory"); + + SC_METHOD(notify_obi_transaction); + sensitive << ext_systemc_req_req_i; + + SC_CTHREAD(give_gnt_back, clk_i.pos()); + SC_CTHREAD(give_rvalid_rdata_back, clk_i.pos()); + + // Bind memory_request socket to target socket + memory_request->socket.bind( memory->socket ); + } +}; + + +SC_MODULE(testbench) +{ + + sc_in clk_i; + sc_out clk_o; + sc_out rst_no; + sc_out boot_select_o; + sc_out execute_from_flash_o; + sc_out jtag_tck_o; + sc_out jtag_tms_o; + sc_out jtag_trst_n_o; + sc_out jtag_tdi_o; + + Vtestharness* dut; + std::string* firmware; + + bool boot_select_option; + unsigned int reset_cycles = 30; + + void make_clock () { + while(1) { + clk_o.write(false); + wait(); + clk_o.write(true); + wait(); + } + } + + void do_reset_cycle () { + //active low + //----- + rst_no.write(false); + + for(int i=0;itb_loadHEX(firmware->c_str()); + } + + void set_exit_loop () { + wait(); + dut->tb_set_exit_loop(); + } + + void make_stimuli () { + + boot_select_o.write(boot_select_option); + execute_from_flash_o.write(true); + jtag_tck_o.write(false); + jtag_tms_o.write(false); + jtag_trst_n_o.write(false); + jtag_tdi_o.write(false); + + std::cout<<"Start Reset Cycle: "<c_str()<get_use_openocd(); + firmware = cmd_lines_options->get_firmware(); + + if(firmware.empty() && use_openocd==false) { + std::cout<<"You must specify the firmware if you are not using OpenOCD"<get_max_sim_time(run_all); + + boot_sel = cmd_lines_options->get_boot_sel(); + + if(use_openocd) { + std::cout<<"[TESTBENCH]: ERROR: Executing from OpenOCD in SystemC is not supported (yet) in X-HEEP"<>1, SC_NS, 0.5); + + Vtestharness dut("TOP"); + testbench tb("testbench"); + external_memory ext_mem("external_memory"); + + svSetScope(svGetScopeFromName("TOP.testharness")); + svScope scope = svGetScope(); + if (!scope) { + std::cout<<"Warning: svGetScope failed"<< std::endl; + exit(EXIT_FAILURE); + } + + + // static values + tb.boot_select_option = boot_sel == 1; + + + // Vtestharness interface + sc_signal clk; + sc_signal rst_n; + sc_signal boot_select; + sc_signal execute_from_flash; + sc_signal jtag_tck; + sc_signal jtag_tms; + sc_signal jtag_trst_n; + sc_signal jtag_tdi; + sc_signal jtag_tdo; + sc_signal exit_value; + sc_signal exit_valid; + sc_signal ext_systemc_req_req; + sc_signal ext_systemc_req_we; + sc_signal ext_systemc_req_be; + sc_signal ext_systemc_req_addr; + sc_signal ext_systemc_req_wdata; + sc_signal ext_systemc_resp_gnt; + sc_signal ext_systemc_resp_rvalid; + sc_signal ext_systemc_resp_rdata; + + + + tb.clk_i(clock_sig); + tb.clk_o(clk); + tb.rst_no(rst_n); + tb.boot_select_o(boot_select); + tb.execute_from_flash_o(execute_from_flash); + tb.jtag_tck_o(jtag_tck); + tb.jtag_tms_o(jtag_tms); + tb.jtag_trst_n_o(jtag_trst_n); + tb.jtag_tdi_o(jtag_tdi); + + tb.dut = &dut; + tb.firmware = &firmware; + + dut.clk_i(clk); + dut.rst_ni(rst_n); + dut.boot_select_i(boot_select); + dut.execute_from_flash_i(execute_from_flash); + dut.jtag_tck_i(jtag_tck); + dut.jtag_tms_i(jtag_tms); + dut.jtag_trst_ni(jtag_trst_n); + dut.jtag_tdi_i(jtag_tdi); + dut.jtag_tdo_o(jtag_tdo); + dut.exit_value_o(exit_value); + dut.exit_valid_o(exit_valid); + dut.ext_systemc_req_req_o(ext_systemc_req_req); + dut.ext_systemc_req_we_o(ext_systemc_req_we); + dut.ext_systemc_req_be_o(ext_systemc_req_be); + dut.ext_systemc_req_addr_o(ext_systemc_req_addr); + dut.ext_systemc_req_wdata_o(ext_systemc_req_wdata); + dut.ext_systemc_resp_gnt_i(ext_systemc_resp_gnt); + dut.ext_systemc_resp_rvalid_i(ext_systemc_resp_rvalid); + dut.ext_systemc_resp_rdata_i(ext_systemc_resp_rdata); + + ext_mem.clk_i(clk); + ext_mem.ext_systemc_req_req_i(ext_systemc_req_req); + ext_mem.ext_systemc_req_we_i(ext_systemc_req_we); + ext_mem.ext_systemc_req_be_i(ext_systemc_req_be); + ext_mem.ext_systemc_req_addr_i(ext_systemc_req_addr); + ext_mem.ext_systemc_req_wdata_i(ext_systemc_req_wdata); + ext_mem.ext_systemc_resp_gnt_o(ext_systemc_resp_gnt); + ext_mem.ext_systemc_resp_rdata_o(ext_systemc_resp_rdata); + ext_mem.ext_systemc_resp_rvalid_o(ext_systemc_resp_rvalid); + + + + // You must do one evaluation before enabling waves, in order to allow + // SystemC to interconnect everything for testing. + sc_start(1, SC_NS); + + + VerilatedVcdSc* tfp = nullptr; + tfp = new VerilatedVcdSc; + dut.trace(tfp, 99); // Trace 99 levels of hierarchy + tfp->open("waveform.vcd"); + + // Simulate until $finish + while (!Verilated::gotFinish() && exit_valid !=1 ) { + // Flush the wave files each cycle so we can immediately see the output + // Don't do this in "real" programs, do it in an abort() handler instead + if (tfp) tfp->flush(); + // Simulate 1ns + sc_start(1, SC_NS); + } + + if(exit_valid == 1) { + std::cout<<"Program Finished with value "<< exit_value <close(); + tfp = nullptr; + } + + + exit(exit_val); + +} diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp b/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp index 956b77d6..7dd4757e 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp +++ b/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp @@ -10,26 +10,10 @@ #include #include +#include "XHEEP_CmdLineOptions.hh" vluint64_t sim_time = 0; - -std::string getCmdOption(int argc, char* argv[], const std::string& option) -{ - std::string cmd; - for( int i = 0; i < argc; ++i) - { - std::string arg = argv[i]; - size_t arg_size = arg.length(); - size_t option_size = option.length(); - - if(arg.find(option)==0){ - cmd = arg.substr(option_size,arg_size-option_size); - } - } - return cmd; -} - void runCycles(unsigned int ncycles, Vtestharness *dut, VerilatedFstC *m_trace){ for(unsigned int i = 0; i < ncycles; i++) { dut->clk_i ^= 1; @@ -42,12 +26,11 @@ void runCycles(unsigned int ncycles, Vtestharness *dut, VerilatedFstC *m_trace){ int main (int argc, char * argv[]) { - unsigned int SRAM_SIZE; - std::string firmware, arg_max_sim_time, arg_openocd, arg_boot_sel, arg_execute_from_flash; - unsigned int max_sim_time; + std::string firmware; + unsigned int max_sim_time, boot_sel, exit_val; bool use_openocd; bool run_all = false; - int i,j, exit_val, boot_sel, execute_from_flash; + Verilated::commandArgs(argc, argv); // Instantiate the model @@ -59,59 +42,24 @@ int main (int argc, char * argv[]) dut->trace (m_trace, 99); m_trace->open ("waveform.vcd"); - arg_openocd = getCmdOption(argc, argv, "+openOCD="); - use_openocd = false; - if(arg_openocd.empty()){ - std::cout<<"[TESTBENCH]: No OpenOCD is used"<get_use_openocd(); + firmware = cmd_lines_options->get_firmware(); - arg_max_sim_time = getCmdOption(argc, argv, "+max_sim_time="); - max_sim_time = 0; - if(arg_max_sim_time.empty()){ - std::cout<<"[TESTBENCH]: No Max time specified"<get_max_sim_time(run_all); - arg_boot_sel = getCmdOption(argc, argv, "+execute_from_flash="); - execute_from_flash = 1; + boot_sel = cmd_lines_options->get_boot_sel(); if(boot_sel == 1) { std::cout<<"[TESTBENCH]: ERROR: Executing from SPI is not supported (yet) in Verilator"<jtag_tms_i = 0; dut->jtag_trst_ni = 0; dut->jtag_tdi_i = 0; - dut->execute_from_flash_i = execute_from_flash; + dut->execute_from_flash_i = 1; //this cause boot_sel cannot be 1 anyway dut->boot_select_i = boot_sel; dut->eval(); @@ -172,6 +120,7 @@ int main (int argc, char * argv[]) m_trace->close(); delete dut; + delete cmd_lines_options; exit(exit_val); diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl b/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl index ece91031..a0f295a4 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl +++ b/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl @@ -96,7 +96,7 @@ endtask % for bank in range(ram_numbanks): task tb_writetoSram${bank}; - input integer addr; + input int addr; input [7:0] val3; input [7:0] val2; input [7:0] val1; diff --git a/hw/vendor/esl_epfl_x_heep/tb/testharness.sv b/hw/vendor/esl_epfl_x_heep/tb/testharness.sv index fc216e7b..2a4c7040 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/testharness.sv +++ b/hw/vendor/esl_epfl_x_heep/tb/testharness.sv @@ -21,6 +21,17 @@ module testharness #( inout wire boot_select_i, inout wire execute_from_flash_i, +`ifdef SIM_SYSTEMC + output logic ext_systemc_req_req_o, + output logic ext_systemc_req_we_o, + output logic [ 3:0] ext_systemc_req_be_o, + output logic [31:0] ext_systemc_req_addr_o, + output logic [31:0] ext_systemc_req_wdata_o, + + input logic ext_systemc_resp_gnt_i, + input logic ext_systemc_resp_rvalid_i, + input logic [31:0] ext_systemc_resp_rdata_i, +`endif input wire jtag_tck_i, input wire jtag_tms_i, input wire jtag_trst_ni, @@ -74,6 +85,9 @@ module testharness #( logic [EXT_PERIPHERALS_PORT_SEL_WIDTH-1:0] ext_periph_select; + logic iffifo_in_ready, iffifo_out_valid; + logic iffifo_int_o; + // External xbar master/slave and peripheral ports obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_master_req; obi_req_t [EXT_XBAR_NMASTER_RND-1:0] heep_slave_req; @@ -99,10 +113,6 @@ module testharness #( reg_pkg::reg_req_t [testharness_pkg::EXT_NPERIPHERALS-1:0] ext_periph_slv_req; reg_pkg::reg_rsp_t [testharness_pkg::EXT_NPERIPHERALS-1:0] ext_periph_slv_rsp; - // External xbar slave example port - obi_req_t slow_ram_slave_req; - obi_resp_t slow_ram_slave_resp; - // External interrupts logic [NEXT_INT_RND-1:0] intr_vector_ext; logic memcopy_intr; @@ -132,6 +142,7 @@ module testharness #( end // Re-assign the interrupt lines used here intr_vector_ext[0] = memcopy_intr; + intr_vector_ext[1] = iffifo_int_o; end //log parameters @@ -249,7 +260,9 @@ module testharness #( .external_subsystem_powergate_iso_no(external_subsystem_powergate_iso_n), .external_subsystem_rst_no(external_subsystem_rst_n), .external_ram_banks_set_retentive_no(external_ram_banks_set_retentive_n), - .external_subsystem_clkgate_en_no(external_subsystem_clkgate_en_n) + .external_subsystem_clkgate_en_no(external_subsystem_clkgate_en_n), + .ext_dma_slot_tx_i(iffifo_in_ready), + .ext_dma_slot_rx_i(iffifo_out_valid) ); // Testbench external bus @@ -360,20 +373,45 @@ module testharness #( .exit() ); - assign mux_jtag_tck = JTAG_DPI ? sim_jtag_tck : jtag_tck_i; - assign mux_jtag_tms = JTAG_DPI ? sim_jtag_tms : jtag_tms_i; - assign mux_jtag_tdi = JTAG_DPI ? sim_jtag_tdi : jtag_tdi_i; - assign mux_jtag_trstn = JTAG_DPI ? sim_jtag_trstn : jtag_trst_ni; + assign mux_jtag_tck = JTAG_DPI ? sim_jtag_tck : jtag_tck_i; + assign mux_jtag_tms = JTAG_DPI ? sim_jtag_tms : jtag_tms_i; + assign mux_jtag_tdi = JTAG_DPI ? sim_jtag_tdi : jtag_tdi_i; + assign mux_jtag_trstn = JTAG_DPI ? sim_jtag_trstn : jtag_trst_ni; + + assign sim_jtag_tdo = JTAG_DPI ? mux_jtag_tdo : '0; + assign jtag_tdo_o = !JTAG_DPI ? mux_jtag_tdo : '0; - assign sim_jtag_tdo = JTAG_DPI ? mux_jtag_tdo : '0; - assign jtag_tdo_o = !JTAG_DPI ? mux_jtag_tdo : '0; + // External xbar slave example port + obi_req_t slow_ram_slave_req; + obi_resp_t slow_ram_slave_resp; + +`ifndef SIM_SYSTEMC assign slow_ram_slave_req = ext_slave_req[SLOW_MEMORY_IDX]; assign ext_slave_resp[SLOW_MEMORY_IDX] = slow_ram_slave_resp; +`else + + obi_req_t ext_systemc_req; + obi_resp_t ext_systemc_resp; + + assign ext_systemc_req_req_o = ext_systemc_req.req; + assign ext_systemc_req_we_o = ext_systemc_req.we; + assign ext_systemc_req_be_o = ext_systemc_req.be; + assign ext_systemc_req_addr_o = ext_systemc_req.addr; + assign ext_systemc_req_wdata_o = ext_systemc_req.wdata; + + assign ext_systemc_resp.gnt = ext_systemc_resp_gnt_i; + assign ext_systemc_resp.rvalid = ext_systemc_resp_rvalid_i; + assign ext_systemc_resp.rdata = ext_systemc_resp_rdata_i; + + assign ext_systemc_req = ext_slave_req[SLOW_MEMORY_IDX]; + assign ext_slave_resp[SLOW_MEMORY_IDX] = ext_systemc_resp; +`endif generate if (USE_EXTERNAL_DEVICE_EXAMPLE) begin : gen_USE_EXTERNAL_DEVICE_EXAMPLE +`ifndef SIM_SYSTEMC obi_pkg::obi_req_t slave_fifoout_req; obi_pkg::obi_resp_t slave_fifoout_resp; @@ -389,14 +427,14 @@ module testharness #( // External xbar slave memory example slow_memory #( - .NumWords (128), + .NumWords (8192), .DataWidth(32'd32) ) slow_ram_i ( .clk_i, .rst_ni, .req_i(slave_fifoout_req.req), .we_i(slave_fifoout_req.we), - .addr_i(slave_fifoout_req.addr[8:2]), + .addr_i(slave_fifoout_req.addr[15:2]), .wdata_i(slave_fifoout_req.wdata), .be_i(slave_fifoout_req.be), // output ports @@ -404,6 +442,7 @@ module testharness #( .rdata_o(slave_fifoout_resp.rdata), .rvalid_o(slave_fifoout_resp.rvalid) ); +`endif parameter DMA_TRIGGER_SLOT_NUM = 4; @@ -430,6 +469,22 @@ module testharness #( .dma_window_intr_o() ); + simple_accelerator #( + .reg_req_t (reg_pkg::reg_req_t), + .reg_rsp_t (reg_pkg::reg_rsp_t), + .obi_req_t (obi_pkg::obi_req_t), + .obi_resp_t(obi_pkg::obi_resp_t) + ) simple_accelerator_i ( + .clk_i, + .rst_ni, + .reg_req_i(ext_periph_slv_req[testharness_pkg::SIMPLE_ACC_IDX]), + .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::SIMPLE_ACC_IDX]), + .acc_read_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER2_IDX]), + .acc_read_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER2_IDX]), + .acc_write_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER3_IDX]), + .acc_write_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER3_IDX]) + ); + // AMS external peripheral ams #( .reg_req_t(reg_pkg::reg_req_t), @@ -441,6 +496,22 @@ module testharness #( .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::AMS_IDX]) ); + // InterFaced FIFO (IFFIFO) external peripheral + iffifo #( + .reg_req_t(reg_pkg::reg_req_t), + .reg_rsp_t(reg_pkg::reg_rsp_t) + ) iffifo_i ( + .clk_i, + .rst_ni, + .reg_req_i(ext_periph_slv_req[testharness_pkg::IFFIFO_IDX]), + .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::IFFIFO_IDX]), + // DMA slots + .iffifo_in_ready_o(iffifo_in_ready), + .iffifo_out_valid_o(iffifo_out_valid), + // Interrupt lines + .iffifo_int_o(iffifo_int_o) + ); + addr_decode #( .NoIndices(testharness_pkg::EXT_NPERIPHERALS), .NoRules(testharness_pkg::EXT_NPERIPHERALS), @@ -557,6 +628,7 @@ module testharness #( assign ext_master_req[testharness_pkg::EXT_MASTER0_IDX].wdata = '0; assign memcopy_intr = '0; + assign iffifo_int_o = '0; assign periph_slave_rsp = '0; end diff --git a/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv b/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv index 58e202ce..d74011f4 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv @@ -7,12 +7,14 @@ package testharness_pkg; import addr_map_rule_pkg::*; import core_v_mini_mcu_pkg::*; - localparam EXT_XBAR_NMASTER = 2; + localparam EXT_XBAR_NMASTER = 4; localparam EXT_XBAR_NSLAVE = 1; //master idx localparam logic [31:0] EXT_MASTER0_IDX = 0; localparam logic [31:0] EXT_MASTER1_IDX = 1; + localparam logic [31:0] EXT_MASTER2_IDX = 2; + localparam logic [31:0] EXT_MASTER3_IDX = 3; //slave mmap and idx localparam logic [31:0] SLOW_MEMORY_START_ADDRESS = core_v_mini_mcu_pkg::EXT_SLAVE_START_ADDRESS; @@ -29,7 +31,7 @@ package testharness_pkg; }; //slave encoder - localparam EXT_NPERIPHERALS = 2; + localparam EXT_NPERIPHERALS = 4; // Memcopy controller (external peripheral example) localparam logic [31:0] MEMCOPY_CTRL_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h0; @@ -38,11 +40,22 @@ package testharness_pkg; localparam logic [31:0] MEMCOPY_CTRL_IDX = 32'd0; // External AMS Peripheral - localparam logic [31:0] AMS_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h001000; + localparam logic [31:0] AMS_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h01000; localparam logic [31:0] AMS_SIZE = 32'h100; localparam logic [31:0] AMS_END_ADDRESS = AMS_START_ADDRESS + AMS_SIZE; localparam logic [31:0] AMS_IDX = 32'd1; + // External InterFaced FIFO (IFFIFO) Peripheral + localparam logic [31:0] IFFIFO_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h02000; + localparam logic [31:0] IFFIFO_SIZE = 32'h100; + localparam logic [31:0] IFFIFO_END_ADDRESS = IFFIFO_START_ADDRESS + IFFIFO_SIZE; + localparam logic [31:0] IFFIFO_IDX = 32'd2; + + // External Simple Accelerator Peripheral + localparam logic [31:0] SIMPLE_ACC_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h03000; + localparam logic [31:0] SIMPLE_ACC_SIZE = 32'h100; + localparam logic [31:0] SIMPLE_ACC_END_ADDRESS = SIMPLE_ACC_START_ADDRESS + SIMPLE_ACC_SIZE; + localparam logic [31:0] SIMPLE_ACC_IDX = 32'd3; localparam addr_map_rule_t [EXT_NPERIPHERALS-1:0] EXT_PERIPHERALS_ADDR_RULES = '{ '{ @@ -50,7 +63,13 @@ package testharness_pkg; start_addr: MEMCOPY_CTRL_START_ADDRESS, end_addr: MEMCOPY_CTRL_END_ADDRESS }, - '{idx: AMS_IDX, start_addr: AMS_START_ADDRESS, end_addr: AMS_END_ADDRESS} + '{idx: AMS_IDX, start_addr: AMS_START_ADDRESS, end_addr: AMS_END_ADDRESS}, + '{idx: IFFIFO_IDX, start_addr: IFFIFO_START_ADDRESS, end_addr: IFFIFO_END_ADDRESS}, + '{ + idx: SIMPLE_ACC_IDX, + start_addr: SIMPLE_ACC_START_ADDRESS, + end_addr: SIMPLE_ACC_END_ADDRESS + } }; localparam int unsigned EXT_PERIPHERALS_PORT_SEL_WIDTH = EXT_NPERIPHERALS > 1 ? $clog2( diff --git a/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py b/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py index e8c012f8..5c86308f 100755 --- a/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py +++ b/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py @@ -540,8 +540,28 @@ def len_extracted_peripherals(peripherals): linker_onchip_il_start_address = str('{:08X}'.format(int(linker_onchip_data_start_address,16) + int(linker_onchip_data_size_address,16))) linker_onchip_il_size_address = str('{:08X}'.format(ram_numbanks_il*32*1024)) + stack_size = string2int(obj['linker_script']['stack_size']) + heap_size = string2int(obj['linker_script']['heap_size']) + + + linker_flash_code_start_address = str('{:08X}'.format(int(linker_onchip_code_start_address,16) + int(flash_mem_start_address,16))) + linker_flash_data_start_address = str('{:08X}'.format(int(linker_onchip_data_start_address,16) + int(flash_mem_start_address,16))) + linker_flash_il_start_address = str('{:08X}'.format(int(linker_onchip_il_start_address,16) + int(flash_mem_start_address,16))) + + if ram_numbanks_il == 0 or (ram_numbanks_cont == 1 and ram_numbanks_il > 0): + linker_flash_left_start_address = str('{:08X}'.format(int(linker_flash_data_start_address,16) + int(linker_onchip_data_size_address,16))) + linker_flash_left_size_address = str('{:08X}'.format(int(flash_mem_size_address,16) - int(linker_onchip_code_size_address,16) - int(linker_onchip_data_size_address,16))) + else: + linker_flash_left_start_address = str('{:08X}'.format(int(linker_flash_il_start_address,16) + int(linker_onchip_il_size_address,16))) + linker_flash_left_size_address = str('{:08X}'.format(int(flash_mem_size_address,16) - int(linker_onchip_code_size_address,16) - int(linker_onchip_data_size_address,16) - int(linker_onchip_il_size_address,16))) + + if ((int(linker_onchip_data_size_address,16) + int(linker_onchip_code_size_address,16)) > int(ram_size_address,16)): exit("The code and data section must fit in the RAM size, instead they takes " + str(linker_onchip_data_size_address + linker_onchip_code_size_address)) + + if ((int(stack_size,16) + int(heap_size,16)) > int(ram_size_address,16)): + exit("The stack and heap section must fit in the RAM size, instead they takes " + str(stack_size + heap_size)) + plic_used_n_interrupts = len(obj['interrupts']['list']) plit_n_interrupts = obj['interrupts']['number'] @@ -841,12 +861,19 @@ def len_extracted_peripherals(peripherals): "ext_slave_size_address" : ext_slave_size_address, "flash_mem_start_address" : flash_mem_start_address, "flash_mem_size_address" : flash_mem_size_address, + "linker_flash_code_start_address" : linker_flash_code_start_address, + "linker_flash_data_start_address" : linker_flash_data_start_address, + "linker_flash_il_start_address" : linker_flash_il_start_address, + "linker_flash_left_start_address" : linker_flash_left_start_address, + "linker_flash_left_size_address" : linker_flash_left_size_address, "linker_onchip_code_start_address" : linker_onchip_code_start_address, "linker_onchip_code_size_address" : linker_onchip_code_size_address, "linker_onchip_data_start_address" : linker_onchip_data_start_address, "linker_onchip_data_size_address" : linker_onchip_data_size_address, "linker_onchip_il_start_address" : linker_onchip_il_start_address, "linker_onchip_il_size_address" : linker_onchip_il_size_address, + "stack_size" : stack_size, + "heap_size" : heap_size, "plic_used_n_interrupts" : plic_used_n_interrupts, "plit_n_interrupts" : plit_n_interrupts, "interrupts" : interrupts, diff --git a/hw/vendor/esl_epfl_x_heep/util/structs_gen.py b/hw/vendor/esl_epfl_x_heep/util/structs_gen.py index f815de76..3c776b42 100644 --- a/hw/vendor/esl_epfl_x_heep/util/structs_gen.py +++ b/hw/vendor/esl_epfl_x_heep/util/structs_gen.py @@ -1,4 +1,5 @@ import hjson +from math import ceil import string import argparse import sys @@ -297,7 +298,7 @@ def add_registers(peripheral_json): n_bits += count_bits(f["bits"]) # computes the number of registers needed to pack all the bit fields needed - n_multireg = int((count * n_bits) / int(peripheral_json["regwidth"])) + n_multireg = ceil((count * n_bits) / int(peripheral_json["regwidth"])) # generate the multiregisters for r in range(n_multireg): diff --git a/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core b/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core index 05b75ba5..98252573 100644 --- a/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core +++ b/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core @@ -14,7 +14,9 @@ filesets: - example:ip:gpio_cnt - example:ip:pdm2pcm_dummy - example:ip:ams + - example:ip:iffifo - example:ip:i2s_microphone + - example:ip:simple_accelerator files: file_type: systemVerilogSource @@ -22,6 +24,8 @@ filesets: files: - hw/ip_examples/slow_memory/slow_memory.vlt - hw/ip_examples/ams/ams.vlt + - hw/ip_examples/iffifo/iffifo.vlt + - hw/ip_examples/simple_accelerator/simple_accelerator.vlt - tb/tb.vlt file_type: vlt @@ -67,6 +71,11 @@ filesets: - tb/tb_top.cpp file_type: cppSource + tb-sc-verilator: + files: + - tb/tb_sc_top.cpp + file_type: cppSource + targets: default: &default_target filesets: @@ -75,13 +84,17 @@ targets: - tool_verilator? (uartdpi) - tool_modelsim? (systemverilog_only_uart) - tool_vcs? (systemverilog_only_uart) + - tool_xcelium? (systemverilog_only_uart) - tool_verilator? (files_verilator_waiver) - tool_verilator? (remote_bitbang_dpi) - tool_modelsim? (systemverilog_only_simjtag) - tool_vcs? (systemverilog_only_simjtag) + - tool_xcelium? (systemverilog_only_simjtag) - tool_modelsim? (cypress_flash) - tool_vcs? (cypress_flash) + - tool_xcelium? (cypress_flash) toplevel: - tool_modelsim? (tb_top) - tool_vcs? (tb_top) + - tool_xcelium? (tb_top) - tool_verilator? (testharness) diff --git a/hw/vendor/eslepfl_x_heep.lock.hjson b/hw/vendor/eslepfl_x_heep.lock.hjson index 04dcb944..0ae40dc6 100644 --- a/hw/vendor/eslepfl_x_heep.lock.hjson +++ b/hw/vendor/eslepfl_x_heep.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/esl-epfl/x-heep.git - rev: df569a88fc7eaa447645262f0d3a76dd22c519f7 + rev: 76d58efe7b9dec0723c1cb9aaf8ad76ad6c85373 } }