# # Copyright (C) 2019 ETH Zurich, University of Bologna # # 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. # #include "archi/pulp.h" #include "pulp.h" .section .text .global pos_init_entry pos_init_entry: # Cluster PEs will also starts here to avoid aligning another entry point # Just re-route them to the right entry #if defined(ARCHI_HAS_CLUSTER) csrr a0, 0xF14 andi a1, a0, 0x1f #ifdef ARCHI_NO_FC # PEs from 1 to 7 will go to sync_loop and wait. PE0 will reach them # later after the pos_init_start. Then, they'll set up their stack into # the L1 and jump to cluster_entry_stub #if PULP_CHIP == CHIP_CARFIELD li t0, 0x5003FFF0 #elif PULP_CHIP == CHIP_ASTRAL li t0, 0x5003FFF0 #else li t0, 0x1003FF0 #endif sw x0, 0(t0) # We check if the offset of the core is zero, so that even if the cluster # ID is not zero, the execution does not break here andi a2, a0, 0x0f bnez a2, sync_loop #else srli a0, a0, 5 #ifdef ARCHI_CL_BOOT li a2, ARCHI_FC_CID beq a0, a2, do_cl_boot bnez a1, pe_start #else #ifdef ARCHI_FC_CID li a2, ARCHI_FC_CID bne a0, a2, pe_start #else bnez a1, pe_start #endif #endif #endif #endif # Clear the bss segment la t0, _bss_start la t1, _bss_end 1: sw zero,0(t0) addi t0, t0, 4 bltu t0, t1, 1b # Stack initialization la x2, stack /* Do all other initializations from C code */ jal x1, pos_init_start #ifdef ARCHI_NO_FC csrr a0, 0xF14 andi a1, a0, 0x1f #if PULP_CHIP == CHIP_CARFIELD li t0, 0x5003FFF0 #elif PULP_CHIP == CHIP_ASTRAL li t0, 0x5003FFF0 #else li t0, 0x1003FFF0 #endif li t1, 0x1 sw t1, 0(t0) j pe_start #endif .section .text # On all other chips we simply pass 0. addi a0, x0, 0 addi a1, x0, 0 # Jump to main program entry point (argc = a0, argv = a1). la t2, main jalr x1, t2 mv s0, a0 /* Do all other deinitializations from C code */ jal x1, pos_init_stop # If program returns from main, call exit routine mv a0, s0 jal x1, exit .section .vectors, "ax" .option norvc; #ifdef ARCHI_CORE_HAS_1_10 j __rt_handle_illegal_instr #else j pos_no_irq_handler #endif j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler j pos_no_irq_handler .org 0x80 .global _start _start: jal x0, pos_init_entry pos_illegal_instr: j __rt_handle_illegal_instr pos_no_irq_handler: mret .global pos_semihosting_call pos_semihosting_call: ebreak jr ra #if defined(ARCHI_HAS_CLUSTER) pe_start: #if defined(ARCHI_HMR) csrr t0, 0xf14 li t1, ARCHI_HMR_ADDR + HMR_CORE_OFFSET andi t0, t0, 0x01f sll t0, t0, HMR_CORE_SLL add t0, t0, t1 lw t1, HMR_CORE_REGS_SP_STORE_REG_OFFSET(t0) bnez t1, pos_hmr_sw_reload #endif la x2, cluster_stacks lw x2, 0(x2) li x3, CLUSTER_STACK_SIZE addi a1, a1, 1 mul x1, x3, a1 add x2, x2, x1 j cluster_entry_stub #endif do_cl_boot: li x2, 0x10200000 li x3, 0x1 la x4, _start sw x4, 0x40(x2) sw x3, 8(x2) loop: li x2, 0x1a109800 sw x0, 0(x2) wfi j loop sync_loop: lw t1, 0(t0) bnez t1, pe_start j sync_loop