From 8c1cc3a8f6e3d818b13482d823c3d8e19f551991 Mon Sep 17 00:00:00 2001 From: IveanEx Date: Fri, 29 Nov 2024 17:22:54 +0100 Subject: [PATCH] Update Bootrom --- Bender.yml | 3 +- target/rtl/bootrom/src/bootrom.c | 126 +++++++++++++++++++++++++------ target/rtl/bootrom/src/chip_id.h | 43 +++++++++++ target/rtl/bootrom/src/sys_dma.h | 117 ++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+), 22 deletions(-) create mode 100644 target/rtl/bootrom/src/chip_id.h create mode 100644 target/rtl/bootrom/src/sys_dma.h diff --git a/Bender.yml b/Bender.yml index 7454ded8..1884e2c4 100644 --- a/Bender.yml +++ b/Bender.yml @@ -118,7 +118,8 @@ sources: files: - target/rtl/test/uartdpi/uartdpi.sv - target/sim_chip/testharness/testharness.sv - - target/sim/test/bootrom.sv + # - target/sim/test/bootrom.sv + - target/rtl/bootrom/bootrom.sv - target/rtl/src/occamy_chip.sv diff --git a/target/rtl/bootrom/src/bootrom.c b/target/rtl/bootrom/src/bootrom.c index 54556174..390c60c5 100644 --- a/target/rtl/bootrom/src/bootrom.c +++ b/target/rtl/bootrom/src/bootrom.c @@ -12,6 +12,8 @@ // For values need to share between functions, use uninitialized global variable // + initialization function +#include "chip_id.h" +#include "sys_dma.h" #include "uart.h" #include "xmodem.h" @@ -30,52 +32,133 @@ void delay_cycles(uint64_t cycle) { } // Boot modes. -enum boot_mode_t { JTAG, UART, PRINTMEM, NORMAL }; +enum boot_mode_t { + TARGET_CHIPID, + UART, + COPY_TO_REMOTE, + COPY_FROM_REMOTE, + PRINTMEM, + NORMAL +}; void bootrom() { - enum boot_mode_t boot_mode = JTAG; - uint64_t start_address; + enum boot_mode_t boot_mode = NORMAL; + uint64_t local_chip_mem_start_address; + uint64_t remote_chip_mem_start_address; uint64_t memory_length; - uint32_t chip_id; - asm volatile("csrr %0, 0xf15" : "=r"(chip_id)); + uint32_t chip_id = get_current_chip_id(); + uint32_t target_chip_id = chip_id; uintptr_t address_prefix = ((uintptr_t)chip_id) << 40; char in_buf[8]; init_uart(address_prefix, 50000000, 1000000); while (1) { - start_address = 0x80000000L | ((uint64_t)address_prefix); + local_chip_mem_start_address = 0x80000000L | ((uint64_t)address_prefix); + remote_chip_mem_start_address = + 0x80000000L | ((uint64_t)target_chip_id << 40); print_str(address_prefix, "\033[2J"); print_str(address_prefix, "\r\n\t\t Welcome to HeMAiA Bootrom"); print_str(address_prefix, "\r\n"); print_str(address_prefix, "\r\n\t Chip ID: 0x"); print_u8(address_prefix, chip_id); + print_str(address_prefix, "\r\n\t Target Remote Chip ID: 0x"); + print_u8(address_prefix, target_chip_id); print_str(address_prefix, "\r\n\t Enter the number to select the mode: "); - print_str(address_prefix, "\r\n\t 1. Load from JTAG"); + print_str(address_prefix, "\r\n\t 1. Change the target remote Chip ID"); print_str(address_prefix, "\r\n\t 2. Load from UART to 0x"); - print_u48(address_prefix, start_address); - print_str(address_prefix, "\r\n\t 3. Print memory from 0x"); - print_u48(address_prefix, start_address); - print_str(address_prefix, "\r\n\t 4. Continue to Boot from 0x"); - print_u48(address_prefix, start_address); + print_u48(address_prefix, remote_chip_mem_start_address); + print_str(address_prefix, + "\r\n\t 3. Copy memory from local chip to remote chip"); + print_str(address_prefix, + "\r\n\t 4. Copy memory from remote chip to local chip"); + print_str(address_prefix, "\r\n\t 5. Print memory from 0x"); + print_u48(address_prefix, remote_chip_mem_start_address); + print_str(address_prefix, "\r\n\t 6. Continue to Boot from 0x"); + print_u48(address_prefix, local_chip_mem_start_address); print_str(address_prefix, "\r\n"); boot_mode = getchar(address_prefix) - '0' - 1; + char* cur = 0; + switch (boot_mode) { - case JTAG: + case TARGET_CHIPID: print_str(address_prefix, - "\r\n\t Handover to debugger... \r\n\r\n"); - __asm__ volatile( - "csrr a0, mhartid;" - "ebreak;"); + "\r\n\t Enter the target remote Chip ID: "); + scan_uart(address_prefix, in_buf); + cur = in_buf; + target_chip_id = 0; + while (*cur != '\0') { + if (*cur >= '0' || *cur <= '9') { + target_chip_id = (target_chip_id << 4) + *cur - '0'; + } else if (*cur >= 'A' || *cur <= 'F') { + target_chip_id = + (target_chip_id << 4) + *cur - 'A' + 10; + } else if (*cur >= 'a' || *cur <= 'f') { + target_chip_id = + (target_chip_id << 4) + *cur - 'a' + 10; + } else { + print_str(address_prefix, "\r\n\t Invalid input. "); + getchar(address_prefix); + break; + } + cur++; + } + break; + + case COPY_TO_REMOTE: + print_str(address_prefix, + "\r\n\t Enter the size of the memory in byte: "); + scan_uart(address_prefix, in_buf); + cur = in_buf; + memory_length = 0; + while (*cur != '\0') { + memory_length = memory_length * 10 + *cur - '0'; + cur++; + } + print_str(address_prefix, "\r\n\t Copying memory from 0x"); + print_u48(address_prefix, local_chip_mem_start_address); + print_str(address_prefix, " to 0x"); + print_u48(address_prefix, remote_chip_mem_start_address); + print_str(address_prefix, " with size "); + print_u48(address_prefix, memory_length); + print_str(address_prefix, " bytes..."); + sys_dma_blk_memcpy(remote_chip_mem_start_address, + local_chip_mem_start_address, memory_length); + print_str(address_prefix, "\r\n\t Copy finished. "); + getchar(address_prefix); + break; + + case COPY_FROM_REMOTE: + print_str(address_prefix, + "\r\n\t Enter the size of the memory in byte: "); + scan_uart(address_prefix, in_buf); + cur = in_buf; + memory_length = 0; + while (*cur != '\0') { + memory_length = memory_length * 10 + *cur - '0'; + cur++; + } + print_str(address_prefix, "\r\n\t Copying memory from 0x"); + print_u48(address_prefix, remote_chip_mem_start_address); + print_str(address_prefix, " to 0x"); + print_u48(address_prefix, local_chip_mem_start_address); + print_str(address_prefix, " with size "); + print_u48(address_prefix, memory_length); + print_str(address_prefix, " bytes..."); + sys_dma_blk_memcpy(local_chip_mem_start_address, + remote_chip_mem_start_address, + memory_length); + print_str(address_prefix, "\r\n\t Copy finished. "); + getchar(address_prefix); break; case UART: delay_cycles(50000000); // Delay for 1s - uart_xmodem(address_prefix, start_address); + uart_xmodem(address_prefix, remote_chip_mem_start_address); print_str(address_prefix, "\r\n\t Load finished. \r\n\r\n"); break; @@ -90,9 +173,10 @@ void bootrom() { cur++; } print_str(address_prefix, "\r\n\t The memory from 0x"); - print_u48(address_prefix, start_address); + print_u48(address_prefix, remote_chip_mem_start_address); print_str(address_prefix, " is:"); - print_mem_hex(address_prefix, (char*)start_address, + print_mem_hex(address_prefix, + (char*)remote_chip_mem_start_address, memory_length); print_str(address_prefix, "\r\n\r\n\t Print finished. "); getchar(address_prefix); @@ -101,7 +185,7 @@ void bootrom() { case NORMAL: print_str(address_prefix, "\033[2J"); print_str(address_prefix, "\r\n\t Booting at 0x"); - print_u48(address_prefix, start_address); + print_u48(address_prefix, local_chip_mem_start_address); print_str(address_prefix, "...\r\n\r\n\r\n"); return; break; diff --git a/target/rtl/bootrom/src/chip_id.h b/target/rtl/bootrom/src/chip_id.h new file mode 100644 index 00000000..8d6f00a7 --- /dev/null +++ b/target/rtl/bootrom/src/chip_id.h @@ -0,0 +1,43 @@ +#pragma once +#include + +inline uint8_t get_current_chip_id() { + uint32_t chip_id; +# if __riscv_xlen == 64 + // 64-bit system (CVA6), get chip_id from 0xf15 + asm volatile("csrr %0, 0xf15" : "=r"(chip_id)); +# else + // 32-bit system, get chip_id from 0xbc2 (base_addrh) + // and shift it to the right by 8 bits + asm volatile ("csrr %0, 0xbc2" : "=r"(chip_id)); + chip_id = chip_id >> 8; +# endif + return (uint8_t)chip_id; +} + +inline uint8_t *get_current_chip_baseaddress() { +#if __riscv_xlen == 64 + // 64-bit system (CVA6), get chip_id from 0xf15 + uint32_t chip_id; + asm volatile("csrr %0, 0xf15" : "=r"(chip_id)); + return (uint8_t *)((uintptr_t)chip_id << 40); +#else + // 32-bit system, return 0 (not supported) + return (uint8_t *)0; +#endif +} + +inline uint8_t *get_chip_baseaddress(uint8_t chip_id) { +#if __riscv_xlen == 64 + // 64-bit system, perform the shift and return the base address + return (uint8_t *)((uintptr_t)chip_id << 40); +#else + // 32-bit system, return 0 (not supported) + return (uint8_t *)0; +#endif +} + +inline uint32_t get_current_chip_baseaddress_h() { + uint32_t chip_id = get_current_chip_id(); + return (uint32_t)(chip_id << 8); +} diff --git a/target/rtl/bootrom/src/sys_dma.h b/target/rtl/bootrom/src/sys_dma.h new file mode 100644 index 00000000..3132ac5e --- /dev/null +++ b/target/rtl/bootrom/src/sys_dma.h @@ -0,0 +1,117 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Generated register defines for idma_reg64_frontend + +#ifndef _IDMA_REG64_FRONTEND_REG_DEFS_ +#define _IDMA_REG64_FRONTEND_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define IDMA_REG64_FRONTEND_PARAM_REG_WIDTH 64 + +// Source Address +#define IDMA_REG64_FRONTEND_SRC_ADDR_REG_OFFSET 0x0 + +// Destination Address +#define IDMA_REG64_FRONTEND_DST_ADDR_REG_OFFSET 0x8 + +// Number of bytes +#define IDMA_REG64_FRONTEND_NUM_BYTES_REG_OFFSET 0x10 + +// Configuration Register for DMA settings +#define IDMA_REG64_FRONTEND_CONF_REG_OFFSET 0x18 +#define IDMA_REG64_FRONTEND_CONF_DECOUPLE_BIT 0 +#define IDMA_REG64_FRONTEND_CONF_DEBURST_BIT 1 +#define IDMA_REG64_FRONTEND_CONF_SERIALIZE_BIT 2 + +// DMA Status +#define IDMA_REG64_FRONTEND_STATUS_REG_OFFSET 0x20 +#define IDMA_REG64_FRONTEND_STATUS_BUSY_BIT 0 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_FRONTEND_NEXT_ID_REG_OFFSET 0x28 + +// Get ID of finished transactions. +#define IDMA_REG64_FRONTEND_DONE_REG_OFFSET 0x30 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _IDMA_REG64_FRONTEND_REG_DEFS_ +// End generated register defines for idma_reg64_frontend + +#include +#include "chip_id.h" + +#define SYS_IDMA_CFG_BASE_ADDR 0x11000000 + +#define IDMA_SRC_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_SRC_ADDR_REG_OFFSET) +#define IDMA_DST_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_DST_ADDR_REG_OFFSET) +#define IDMA_NUMBYTES_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_NUM_BYTES_REG_OFFSET) +#define IDMA_CONF_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_CONF_REG_OFFSET) +#define IDMA_STATUS_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_STATUS_REG_OFFSET) +#define IDMA_NEXTID_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_NEXT_ID_REG_OFFSET) +#define IDMA_DONE_ADDR \ + (SYS_IDMA_CFG_BASE_ADDR + IDMA_REG64_FRONTEND_DONE_REG_OFFSET) + +#define IDMA_CONF_DECOUPLE 0 +#define IDMA_CONF_DEBURST 0 +#define IDMA_CONF_SERIALIZE 0 + +static inline volatile uint64_t *sys_dma_src_ptr(void) { + return (volatile uint64_t *)(IDMA_SRC_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} +static inline volatile uint64_t *sys_dma_dst_ptr(void) { + return (volatile uint64_t *)(IDMA_DST_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} +static inline volatile uint64_t *sys_dma_num_bytes_ptr(void) { + return (volatile uint64_t *)(IDMA_NUMBYTES_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} +static inline volatile uint64_t *sys_dma_conf_ptr(void) { + return (volatile uint64_t *)(IDMA_CONF_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} +static inline volatile uint64_t *sys_dma_status_ptr(void) { + return (volatile uint64_t *)(IDMA_STATUS_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} +static inline volatile uint64_t *sys_dma_nextid_ptr(void) { + return (volatile uint64_t *)(IDMA_NEXTID_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} +static inline volatile uint64_t *sys_dma_done_ptr(void) { + return (volatile uint64_t *)(IDMA_DONE_ADDR | + (uintptr_t)get_current_chip_baseaddress()); +} + +static inline uint64_t sys_dma_memcpy(uint64_t dst, uint64_t src, uint64_t size) { + *(sys_dma_src_ptr()) = (uint64_t)src; + *(sys_dma_dst_ptr()) = (uint64_t)dst; + *(sys_dma_num_bytes_ptr()) = size; + *(sys_dma_conf_ptr()) = + (IDMA_CONF_DECOUPLE << IDMA_REG64_FRONTEND_CONF_DECOUPLE_BIT) | + (IDMA_CONF_DEBURST << IDMA_REG64_FRONTEND_CONF_DEBURST_BIT) | + (IDMA_CONF_SERIALIZE << IDMA_REG64_FRONTEND_CONF_SERIALIZE_BIT); + return *(sys_dma_nextid_ptr()); +} + +static inline void sys_dma_blk_memcpy(uint64_t dst, uint64_t src, uint64_t size) { + volatile uint64_t tf_id = sys_dma_memcpy(dst, src, size); + + while (*(sys_dma_done_ptr()) != tf_id) { + asm volatile("nop"); + } +}