Skip to content

Commit

Permalink
Update Bootrom
Browse files Browse the repository at this point in the history
  • Loading branch information
IveanEx committed Nov 29, 2024
1 parent 889b9e9 commit 8c1cc3a
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 22 deletions.
3 changes: 2 additions & 1 deletion Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
126 changes: 105 additions & 21 deletions target/rtl/bootrom/src/bootrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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;

Expand All @@ -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);
Expand All @@ -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;
Expand Down
43 changes: 43 additions & 0 deletions target/rtl/bootrom/src/chip_id.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once
#include <stdint.h>

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);
}
117 changes: 117 additions & 0 deletions target/rtl/bootrom/src/sys_dma.h
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>
#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");
}
}

0 comments on commit 8c1cc3a

Please sign in to comment.