Merge pull request #1199 from sergachev/feature/zynqmp
cores/cpu: add ZynqMP (UltraScale+ MPSoC) support
This commit is contained in:
commit
bd3d063d87
|
@ -0,0 +1 @@
|
|||
from litex.soc.cores.cpu.zynqmp.core import ZynqMP
|
|
@ -0,0 +1,5 @@
|
|||
void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr);
|
||||
|
||||
void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr) {
|
||||
goto *addr;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
from migen import *
|
||||
from litex.soc.cores.cpu import CPU
|
||||
from litex.soc.interconnect import axi
|
||||
|
||||
|
||||
class ZynqMP(CPU):
|
||||
variants = ["standard"]
|
||||
family = "aarch64"
|
||||
name = "zynqmp"
|
||||
human_name = "Zynq Ultrascale+ MPSoC"
|
||||
data_width = 64
|
||||
endianness = "little"
|
||||
reset_address = 0xc000_0000
|
||||
gcc_triple = "aarch64-none-elf"
|
||||
gcc_flags = ""
|
||||
linker_output_format = "elf64-littleaarch64"
|
||||
nop = "nop"
|
||||
io_regions = { # Origin, Length.
|
||||
0x8000_0000: 0x4000_0000,
|
||||
0xe000_0000: 0xff_2000_0000 # TODO: there are more details here
|
||||
}
|
||||
|
||||
@property
|
||||
def mem_map(self):
|
||||
return {
|
||||
"sram": 0x0000_0000, # DDR low in fact
|
||||
"rom": 0xc000_0000, # Quad SPI memory
|
||||
}
|
||||
|
||||
def __init__(self, platform, variant, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.platform = platform
|
||||
self.reset = Signal()
|
||||
self.periph_buses = [] # Peripheral buses (Connected to main SoC's bus).
|
||||
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
|
||||
self.axi_gp_masters = [] # General Purpose AXI Masters.
|
||||
|
||||
self.clock_domains.cd_ps = ClockDomain()
|
||||
|
||||
self.ps_name = "ps"
|
||||
self.ps_tcl = []
|
||||
self.config = {'PSU__FPGA_PL0_ENABLE': 1} # enable pl_clk0
|
||||
rst_n = Signal()
|
||||
self.cpu_params = dict(
|
||||
o_pl_clk0=ClockSignal("ps"),
|
||||
o_pl_resetn0=rst_n
|
||||
)
|
||||
self.comb += ResetSignal("ps").eq(~rst_n)
|
||||
self.ps_tcl.append(f"set ps [create_ip -vendor xilinx.com -name zynq_ultra_ps_e -module_name {self.ps_name}]")
|
||||
|
||||
def add_axi_gp_master(self):
|
||||
assert len(self.axi_gp_masters) < 3
|
||||
n = len(self.axi_gp_masters)
|
||||
axi_gpn = axi.AXIInterface(data_width=32, address_width=32, id_width=16)
|
||||
self.config[f'PSU__USE__M_AXI_GP{n}'] = 1
|
||||
self.config[f'PSU__MAXIGP{n}__DATA_WIDTH'] = axi_gpn.data_width
|
||||
self.axi_gp_masters.append(axi_gpn)
|
||||
self.cpu_params['i_maxihpm0_fpd_aclk'] = ClockSignal("ps")
|
||||
layout = axi_gpn.layout_flat()
|
||||
dir_map = {DIR_M_TO_S: 'o', DIR_S_TO_M: 'i'}
|
||||
for group, signal, direction in layout:
|
||||
sig_name = group + signal
|
||||
if sig_name in ['bfirst', 'blast', 'rfirst', 'arfirst', 'arlast', 'awfirst', 'awlast', 'wfirst', 'wid']:
|
||||
continue
|
||||
direction = dir_map[direction]
|
||||
self.cpu_params[f'{direction}_maxigp{n}_{group}{signal}'] = getattr(getattr(axi_gpn, group), signal)
|
||||
|
||||
return axi_gpn
|
||||
|
||||
def do_finalize(self):
|
||||
if len(self.ps_tcl):
|
||||
self.ps_tcl.append("set_property -dict [list \\")
|
||||
for config, value in self.config.items():
|
||||
self.ps_tcl.append("CONFIG.{} {} \\".format(config, '{{' + str(value) + '}}'))
|
||||
self.ps_tcl.append(f"] [get_ips {self.ps_name}]")
|
||||
|
||||
self.ps_tcl += [
|
||||
f"generate_target all [get_ips {self.ps_name}]",
|
||||
f"synth_ip [get_ips {self.ps_name}]"
|
||||
]
|
||||
self.platform.toolchain.pre_synthesis_commands += self.ps_tcl
|
||||
self.specials += Instance(self.ps_name, **self.cpu_params)
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef __IRQ_H
|
||||
#define __IRQ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline unsigned int irq_getie(void)
|
||||
{
|
||||
return 0; /* FIXME */
|
||||
}
|
||||
|
||||
static inline void irq_setie(unsigned int ie)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static inline unsigned int irq_getmask(void)
|
||||
{
|
||||
return 0; /* FIXME */
|
||||
}
|
||||
|
||||
static inline void irq_setmask(unsigned int mask)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static inline unsigned int irq_pending(void)
|
||||
{
|
||||
return 0; /* FIXME */
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __IRQ_H */
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef __SYSTEM_H
|
||||
#define __SYSTEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "xuartps_hw.h"
|
||||
#include "xil_cache.h"
|
||||
|
||||
__attribute__((unused)) static void flush_cpu_icache(void){};
|
||||
|
||||
__attribute__((unused)) static void flush_cpu_dcache(void) {
|
||||
Xil_DCacheFlush();
|
||||
};
|
||||
|
||||
void flush_l2_cache(void); // TODO: use Xil_L2CacheFlush(); !
|
||||
|
||||
void busy_wait(unsigned int ms);
|
||||
void busy_wait_us(unsigned int us);
|
||||
|
||||
#define CSR_UART_BASE
|
||||
#define UART_POLLING
|
||||
|
||||
static inline void uart_rxtx_write(char c) {
|
||||
XUartPs_WriteReg(STDOUT_BASEADDRESS, XUARTPS_FIFO_OFFSET, (uint32_t) c);
|
||||
}
|
||||
|
||||
static inline uint8_t uart_rxtx_read(void) {
|
||||
return XUartPs_ReadReg(STDOUT_BASEADDRESS, XUARTPS_FIFO_OFFSET);
|
||||
}
|
||||
|
||||
static inline uint8_t uart_txfull_read(void) {
|
||||
return XUartPs_IsTransmitFull(STDOUT_BASEADDRESS);
|
||||
}
|
||||
|
||||
static inline uint8_t uart_rxempty_read(void) {
|
||||
return !XUartPs_IsReceiveData(STDOUT_BASEADDRESS);
|
||||
}
|
||||
|
||||
static inline void uart_ev_pending_write(uint8_t x) {}
|
||||
|
||||
static inline uint8_t uart_ev_pending_read(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void uart_ev_enable_write(uint8_t x) {}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_H */
|
|
@ -156,7 +156,7 @@ class SoCCore(LiteXSoC):
|
|||
integrated_rom_size = 4*len(integrated_rom_init)
|
||||
|
||||
# Disable ROM when no CPU/hard-CPU.
|
||||
if cpu_type in [None, "zynq7000", "eos_s3"]:
|
||||
if cpu_type in [None, "zynq7000", "zynqmp", "eos_s3"]:
|
||||
integrated_rom_init = []
|
||||
integrated_rom_size = 0
|
||||
self.integrated_rom_size = integrated_rom_size
|
||||
|
|
|
@ -41,6 +41,8 @@ endif
|
|||
|
||||
ifeq ($(CPU), zynq7000)
|
||||
LSCRIPT = linker-zynq.ld
|
||||
else ifeq ($(CPU), zynqmp)
|
||||
LSCRIPT = linker-zynqmp.ld
|
||||
else
|
||||
LSCRIPT = linker.ld
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
/*******************************************************************/
|
||||
/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */
|
||||
/* */
|
||||
/* Description : Cortex-A53 Linker Script */
|
||||
/*******************************************************************/
|
||||
|
||||
INCLUDE generated/output_format.ld
|
||||
ENTRY(_start)
|
||||
|
||||
INCLUDE generated/regions.ld
|
||||
|
||||
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
|
||||
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;
|
||||
|
||||
_EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024;
|
||||
_EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048;
|
||||
_EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024;
|
||||
|
||||
ENTRY(_vector_table)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
_ftext = .;
|
||||
KEEP (*(.vectors))
|
||||
*(.boot)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.plt)
|
||||
*(.gnu_warning)
|
||||
*(.gcc_execpt_table)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.ARM.extab)
|
||||
*(.gnu.linkonce.armextab.*)
|
||||
} > sram
|
||||
|
||||
.commands :
|
||||
{
|
||||
PROVIDE_HIDDEN (__bios_cmd_start = .);
|
||||
KEEP(*(.bios_cmd))
|
||||
PROVIDE_HIDDEN (__bios_cmd_end = .);
|
||||
} > sram
|
||||
|
||||
.init (ALIGN(64)) : {
|
||||
PROVIDE_HIDDEN (__bios_init_start = .);
|
||||
KEEP (*(.bios_init))
|
||||
PROVIDE_HIDDEN (__bios_init_end = .);
|
||||
} > sram
|
||||
|
||||
.fini (ALIGN(64)) : {
|
||||
KEEP (*(.fini))
|
||||
} > sram
|
||||
|
||||
.interp : {
|
||||
KEEP (*(.interp))
|
||||
} > sram
|
||||
|
||||
.note-ABI-tag : {
|
||||
KEEP (*(.note-ABI-tag))
|
||||
} > sram
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(64);
|
||||
__rodata_start = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
__rodata_end = .;
|
||||
} > sram
|
||||
|
||||
.rodata1 : {
|
||||
. = ALIGN(64);
|
||||
__rodata1_start = .;
|
||||
*(.rodata1)
|
||||
*(.rodata1.*)
|
||||
|
||||
/* Make sure the file is aligned on disk as well
|
||||
as in memory; CRC calculation requires that. */
|
||||
FILL(0);
|
||||
. = ALIGN(8);
|
||||
|
||||
__rodata1_end = .;
|
||||
} > sram
|
||||
|
||||
.sdata2 : {
|
||||
. = ALIGN(64);
|
||||
__sdata2_start = .;
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
__sdata2_end = .;
|
||||
} > sram
|
||||
|
||||
.sbss2 : {
|
||||
. = ALIGN(64);
|
||||
__sbss2_start = .;
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
__sbss2_end = .;
|
||||
} > sram
|
||||
|
||||
.data : {
|
||||
. = ALIGN(64);
|
||||
__data_start = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.jcr)
|
||||
*(.got)
|
||||
*(.got.plt)
|
||||
__data_end = .;
|
||||
} > sram
|
||||
|
||||
.data1 : {
|
||||
. = ALIGN(64);
|
||||
__data1_start = .;
|
||||
*(.data1)
|
||||
*(.data1.*)
|
||||
|
||||
/* Make sure the file is aligned on disk as well
|
||||
as in memory; CRC calculation requires that. */
|
||||
FILL(0);
|
||||
. = ALIGN(8);
|
||||
|
||||
__data1_end = .;
|
||||
} > sram
|
||||
|
||||
.got : {
|
||||
*(.got)
|
||||
} > sram
|
||||
|
||||
.got1 : {
|
||||
*(.got1)
|
||||
} > sram
|
||||
|
||||
.got2 : {
|
||||
*(.got2)
|
||||
} > sram
|
||||
|
||||
.note.gnu.build-id : {
|
||||
KEEP (*(.note.gnu.build-id))
|
||||
} > sram
|
||||
|
||||
.ctors : {
|
||||
. = ALIGN(64);
|
||||
__CTOR_LIST__ = .;
|
||||
___CTORS_LIST___ = .;
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
__CTOR_END__ = .;
|
||||
___CTORS_END___ = .;
|
||||
} > sram
|
||||
|
||||
.dtors : {
|
||||
. = ALIGN(64);
|
||||
__DTOR_LIST__ = .;
|
||||
___DTORS_LIST___ = .;
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
__DTOR_END__ = .;
|
||||
___DTORS_END___ = .;
|
||||
} > sram
|
||||
|
||||
.fixup : {
|
||||
__fixup_start = .;
|
||||
*(.fixup)
|
||||
__fixup_end = .;
|
||||
} > sram
|
||||
|
||||
.eh_frame : {
|
||||
*(.eh_frame)
|
||||
} > sram
|
||||
|
||||
.eh_framehdr : {
|
||||
__eh_framehdr_start = .;
|
||||
*(.eh_framehdr)
|
||||
__eh_framehdr_end = .;
|
||||
} > sram
|
||||
|
||||
.gcc_except_table : {
|
||||
*(.gcc_except_table)
|
||||
} > sram
|
||||
|
||||
.mmu_tbl0 (ALIGN(4096)) : {
|
||||
__mmu_tbl0_start = .;
|
||||
*(.mmu_tbl0)
|
||||
__mmu_tbl0_end = .;
|
||||
} > sram
|
||||
|
||||
.mmu_tbl1 (ALIGN(4096)) : {
|
||||
__mmu_tbl1_start = .;
|
||||
*(.mmu_tbl1)
|
||||
__mmu_tbl1_end = .;
|
||||
} > sram
|
||||
|
||||
.mmu_tbl2 (ALIGN(4096)) : {
|
||||
__mmu_tbl2_start = .;
|
||||
*(.mmu_tbl2)
|
||||
__mmu_tbl2_end = .;
|
||||
} > sram
|
||||
|
||||
.ARM.exidx : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
*(.gnu.linkonce.armexidix.*.*)
|
||||
__exidx_end = .;
|
||||
} > sram
|
||||
|
||||
.preinit_array : {
|
||||
. = ALIGN(64);
|
||||
__preinit_array_start = .;
|
||||
KEEP (*(SORT(.preinit_array.*)))
|
||||
KEEP (*(.preinit_array))
|
||||
__preinit_array_end = .;
|
||||
} > sram
|
||||
|
||||
.init_array : {
|
||||
. = ALIGN(64);
|
||||
__init_array_start = .;
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
__init_array_end = .;
|
||||
} > sram
|
||||
|
||||
.fini_array : {
|
||||
. = ALIGN(64);
|
||||
__fini_array_start = .;
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array))
|
||||
__fini_array_end = .;
|
||||
} > sram
|
||||
|
||||
.ARM.attributes : {
|
||||
__ARM.attributes_start = .;
|
||||
*(.ARM.attributes)
|
||||
__ARM.attributes_end = .;
|
||||
} > sram
|
||||
|
||||
.sdata : {
|
||||
. = ALIGN(64);
|
||||
__sdata_start = .;
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
__sdata_end = .;
|
||||
} > sram
|
||||
|
||||
.sbss (NOLOAD) : {
|
||||
. = ALIGN(64);
|
||||
__sbss_start = .;
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
. = ALIGN(64);
|
||||
__sbss_end = .;
|
||||
} > sram
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(64);
|
||||
__tdata_start = .;
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
*(.gnu.linkonce.td.*)
|
||||
__tdata_end = .;
|
||||
} > sram
|
||||
|
||||
.tbss : {
|
||||
. = ALIGN(64);
|
||||
__tbss_start = .;
|
||||
*(.tbss)
|
||||
*(.tbss.*)
|
||||
*(.gnu.linkonce.tb.*)
|
||||
__tbss_end = .;
|
||||
} > sram
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(64);
|
||||
__bss_start__ = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(64);
|
||||
__bss_end__ = .;
|
||||
} > sram
|
||||
|
||||
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
|
||||
|
||||
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
|
||||
|
||||
.stack (NOLOAD) : {
|
||||
. = ALIGN(64);
|
||||
_el3_stack_end = .;
|
||||
. += _STACK_SIZE;
|
||||
__el3_stack = .;
|
||||
_el2_stack_end = .;
|
||||
. += _EL2_STACK_SIZE;
|
||||
. = ALIGN(64);
|
||||
__el2_stack = .;
|
||||
_el1_stack_end = .;
|
||||
. += _EL1_STACK_SIZE;
|
||||
. = ALIGN(64);
|
||||
__el1_stack = .;
|
||||
_el0_stack_end = .;
|
||||
. += _EL0_STACK_SIZE;
|
||||
. = ALIGN(64);
|
||||
__el0_stack = .;
|
||||
} > sram
|
||||
|
||||
_end = .;
|
||||
}
|
||||
|
||||
PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data));
|
|
@ -9,23 +9,35 @@ OBJECTS = xil_cache.o \
|
|||
xil_exception.o \
|
||||
asm_vectors.o \
|
||||
boot.o \
|
||||
cpu_init.o \
|
||||
translation_table.o \
|
||||
xil-crt0.o \
|
||||
vectors.o \
|
||||
xtime_l.o
|
||||
|
||||
libxil.a: $(OBJECTS)
|
||||
$(AR) crs $@ $^
|
||||
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/cortexa9/%.c
|
||||
$(compile)
|
||||
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/common/%.c
|
||||
$(compile)
|
||||
|
||||
ifeq ($(CPU), zynqmp)
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/ARMv8/64bit/%.c
|
||||
$(compile)
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/ARMv8/64bit/gcc/%.S
|
||||
$(assemble)
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/ARMv8/64bit/platform/ZynqMP/gcc/%.S
|
||||
$(assemble)
|
||||
|
||||
else ifeq ($(CPU), zynq7000)
|
||||
|
||||
OBJECTS += cpu_init.o
|
||||
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/cortexa9/%.c
|
||||
$(compile)
|
||||
%.o: embeddedsw/lib/bsp/standalone/src/arm/cortexa9/gcc/%.S
|
||||
$(assemble)
|
||||
|
||||
endif
|
||||
|
||||
libxil.a: $(OBJECTS)
|
||||
$(AR) crs $@ $^
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJECTS) libxil.a
|
||||
|
|
Loading…
Reference in New Issue