cores/cpu: Add intitial gowin_ae350 support.

This commit is contained in:
Florent Kermarrec 2024-01-11 13:11:56 +01:00
parent e689aab18a
commit 8aa5958fb7
8 changed files with 417 additions and 0 deletions

View File

@ -10,6 +10,8 @@
- build/openfpgaloader : Added kwargs support to flash for specific/less common cases.
- cpu/gowin_emcu : Improved/Cleaned-up.
- interconnect/ahb : Added data_width/address_width parameters.
- interconnect/ahb : Added proper byte/sel support to AHB2Wishbone.
- cpu/gowin_ae350 : Added initial support.
[> Changed
----------

View File

@ -0,0 +1 @@
from litex.soc.cores.cpu.gowin_ae350.core import GowinAE350

View File

@ -0,0 +1,4 @@
.section .text, "ax", @progbits
.global boot_helper
boot_helper:
jr x13

View File

@ -0,0 +1,308 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2024 Gwenhael Goavec-Merou <gwenhael@enjoy-digital.fr>
# Copyright (c) 2024 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import os
from migen import *
from litex.gen import *
from litex.soc.interconnect import wishbone, ahb
from litex.soc.interconnect.csr import *
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32
# Gowin AE350 Constants ----------------------------------------------------------------------------
APB_CE_APB = (1 << 0)
APB_CE_UART1 = (1 << 1)
APB_CE_UART2 = (1 << 2)
APB_CE_SPI = (1 << 3)
APB_CE_GPIO = (1 << 4)
APB_CE_PIT = (1 << 5)
APB_CE_I2C = (1 << 6)
APB_CE_WDT = (1 << 7)
# Gowin AE350 --------------------------------------------------------------------------------------
class GowinAE350(CPU):
variants = ["standard"]
category = "hardcore"
family = "riscv"
name = "gowin_ae350"
human_name = "Gowin AE350"
data_width = 32
endianness = "little"
reset_address = 0x8000_0000
gcc_triple = CPU_GCC_TRIPLE_RISCV32
linker_output_format = "elf32-littleriscv"
nop = "nop"
io_regions = {
# Origin, Length.
0xe800_0000: 0x6000_0000
}
@property
def mem_map(self):
return {
"rom" : 0x80000000,
"sram" : 0x00000000,
"peripherals" : 0xf0000000,
"csr" : 0xe8000000,
}
# GCC Flags.
@property
def gcc_flags(self):
flags = f" -mabi=ilp32 -march=rv32imafdc"
flags += f" -D__AE350__"
return flags
def __init__(self, platform, variant, *args, **kwargs):
self.platform = platform
self.reset = Signal()
self.ibus = ibus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
self.dbus = dbus = wishbone.Interface(data_width=64, address_width=32, addressing="word")
self.pbus = pbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
self.periph_buses = [ibus, dbus, pbus] # Peripheral buses (Connected to main SoC's bus).
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
# AHBLite Buses.
# --------------
self.ahb_rom = ahb_rom = ahb.AHBInterface(data_width=32, address_width=32)
self.ahb_ram = ahb_ram = ahb.AHBInterface(data_width=64, address_width=32)
self.ahb_exts = ahb_exts = ahb.AHBInterface(data_width=32, address_width=32)
self.comb += [
# Set AHBLite ROM static signals.
ahb_rom.sel.eq(1),
ahb_rom.size.eq(0b010),
ahb_rom.burst.eq(0),
# Set AHBLite RAM static signals.
ahb_ram.sel.eq(1),
]
# CPU Instance.
# -------------
self.cpu_params = dict(
# Clk/Rst.
i_CORE_CLK = ClockSignal("cpu"),
i_DDR_CLK = ClockSignal("sys"),
i_AHB_CLK = ClockSignal("sys"),
i_APB_CLK = ClockSignal("sys"),
i_POR_N = 1,
i_HW_RSTN = ~(ResetSignal("sys") | self.reset),
o_PRESETN = Open(),
o_HRESETN = Open(),
o_DDR_RSTN = Open(),
# Features/Peripherals Enable.
i_CORE_CE = 1,
i_AXI_CE = 1,
i_DDR_CE = 1,
i_AHB_CE = 1,
i_APB_CE = Constant(APB_CE_APB, 8),
i_APB2AHB_CE = 1,
# WFI.
o_CORE0_WFI_MODE = Open(),
i_WAKEUP_IN = 0,
# RTC.
i_RTC_CLK = ClockSignal("sys"),
o_RTC_WAKEUP = Open(),
# Interrupts.
i_GP_INT = Constant(0, 16),
# DMA.
i_DMA_REQ = Constant(0, 8),
o_DMA_ACK = Open(8),
# AHBLite ROM interface.
i_ROM_HRDATA = ahb_rom.rdata,
i_ROM_HREADY = ahb_rom.readyout,
i_ROM_HRESP = ahb_rom.resp,
o_ROM_HADDR = ahb_rom.addr,
o_ROM_HTRANS = ahb_rom.trans,
o_ROM_HWRITE = ahb_rom.write,
# APBLite Fabric interface (Slave).
o_APB_PADDR = Open(32),
o_APB_PENABLE = Open(),
i_APB_PRDATA = Constant(0, 32),
i_APB_PREADY = 0,
o_APB_PSEL = Open(),
o_APB_PWDATA = Open(32),
o_APB_PWRITE = Open(),
i_APB_PSLVERR = 0,
o_APB_PPROT = Open(3),
o_APB_PSTRB = Open(4),
# AHBLite Peripheral interface (Master).
i_EXTS_HRDATA = ahb_exts.rdata,
i_EXTS_HREADYIN = ahb_exts.readyout,
i_EXTS_HRESP = ahb_exts.resp,
o_EXTS_HADDR = ahb_exts.addr,
o_EXTS_HBURST = ahb_exts.burst,
o_EXTS_HPROT = ahb_exts.prot,
o_EXTS_HSEL = ahb_exts.sel,
o_EXTS_HSIZE = ahb_exts.size,
o_EXTS_HTRANS = ahb_exts.trans,
o_EXTS_HWDATA = ahb_exts.wdata,
o_EXTS_HWRITE = ahb_exts.write,
# AHBLite Peripheral interface (Slave).
i_EXTM_HADDR = Constant(0, 32),
i_EXTM_HBURST = Constant(0, 3),
i_EXTM_HPROT = Constant(0, 4),
o_EXTM_HRDATA = Open(64),
i_EXTM_HREADY = 0,
o_EXTM_HREADYOUT = Open(),
o_EXTM_HRESP = Open(),
i_EXTM_HSEL = 0,
i_EXTM_HSIZE = Constant(0, 3),
i_EXTM_HTRANS = Constant(0, 2),
i_EXTM_HWDATA = Constant(0, 64),
i_EXTM_HWRITE = 0,
# AHBLite RAM interface (Slave).
i_DDR_HRDATA = ahb_ram.rdata,
i_DDR_HREADY = ahb_ram.readyout,
i_DDR_HRESP = ahb_ram.resp,
o_DDR_HADDR = ahb_ram.addr,
o_DDR_HBURST = ahb_ram.burst,
o_DDR_HPROT = ahb_ram.prot,
o_DDR_HSIZE = ahb_ram.size,
o_DDR_HTRANS = ahb_ram.trans,
o_DDR_HWDATA = ahb_ram.wdata,
o_DDR_HWRITE = ahb_ram.write,
# GPIOs.
i_GPIO_IN = Constant(0, 32),
o_GPIO_OUT = Open(32),
o_GPIO_OE = Open(32),
# SCAN.
i_SCAN_EN = 0,
i_SCAN_TEST = 0,
i_SCAN_IN = Constant(0xfffff, 20),
o_SCAN_OUT = Open(20),
# Integrated JTAG.
i_INTEG_TCK = 1,
i_INTEG_TDI = 1,
i_INTEG_TMS = 1,
i_INTEG_TRST = 1,
o_INTEG_TDO = Open(),
# SRAM (FIXME : Cleanup).
i_PGEN_CHAIN_I = 1,
o_PRDYN_CHAIN_O = Open(),
i_EMA = Constant(0b011, 3),
i_EMAW = Constant(0b01, 2),
i_EMAS = 0,
i_RET1N = 1,
i_RET2N = 1,
# SPI.
i_SPI2_HOLDN_IN = 0,
i_SPI2_WPN_IN = 0,
i_SPI2_CLK_IN = 0,
i_SPI2_CSN_IN = 0,
i_SPI2_MISO_IN = 0,
i_SPI2_MOSI_IN = 0,
o_SPI2_HOLDN_OUT = Open(),
o_SPI2_HOLDN_OE = Open(),
o_SPI2_WPN_OUT = Open(),
o_SPI2_WPN_OE = Open(),
o_SPI2_CLK_OUT = Open(),
o_SPI2_CLK_OE = Open(),
o_SPI2_CSN_OUT = Open(),
o_SPI2_CSN_OE = Open(),
o_SPI2_MISO_OUT = Open(),
o_SPI2_MISO_OE = Open(),
o_SPI2_MOSI_OUT = Open(),
o_SPI2_MOSI_OE = Open(),
# I2C.
i_I2C_SCL_IN = 0,
i_I2C_SDA_IN = 0,
o_I2C_SCL = Open(),
o_I2C_SDA = Open(),
# PIT/PWM.
o_CH0_PWM = Open(),
o_CH0_PWMOE = Open(),
o_CH1_PWM = Open(),
o_CH1_PWMOE = Open(),
o_CH2_PWM = Open(),
o_CH2_PWMOE = Open(),
o_CH3_PWM = Open(),
o_CH3_PWMOE = Open(),
# UART1.
o_UART1_TXD = Open(),
o_UART1_RTSN = Open(),
i_UART1_RXD = 0,
i_UART1_CTSN = 0,
i_UART1_DSRN = 0,
i_UART1_DCDN = 0,
i_UART1_RIN = 0,
o_UART1_DTRN = Open(),
o_UART1_OUT1N = Open(),
o_UART1_OUT2N = Open(),
# UART2.
o_UART2_TXD = Open(),
o_UART2_RTSN = Open(),
i_UART2_RXD = 0,
i_UART2_CTSN = 1,
i_UART2_DCDN = 1,
i_UART2_DSRN = 1,
i_UART2_RIN = 1,
o_UART2_DTRN = Open(),
o_UART2_OUT1N = Open(),
o_UART2_OUT2N = Open(),
# JTAG.
i_DBG_TCK = 1,
i_TMS_IN = 1,
i_TRST_IN = 1,
i_TDI_IN = 0,
o_TDO_OUT = Open(),
o_TDO_OE = Open(),
# Test.
i_TEST_CLK = 0,
i_TEST_MODE = 0,
i_TEST_RSTN = 1,
)
# AHBLite ROM Interface.
# ----------------------
self.submodules += ahb.AHB2Wishbone(ahb_rom, self.ibus)
# AHBLite RAM Interface.
# ----------------------
self.submodules += ahb.AHB2Wishbone(ahb_ram, self.dbus)
# AHBLite Peripheral Interface.
# -----------------------------
self.submodules += ahb.AHB2Wishbone(ahb_exts, self.pbus)
def connect_jtag(self, pads):
self.cpu_params.update(
i_DBG_TCK = pads.tck,
i_TMS_IN = pads.tms,
i_TRST_IN = pads.trst,
i_TDI_IN = pads.tdi,
o_TDO_OUT = pads.tdo,
o_TDO_OE = Open(),
)
def do_finalize(self):
self.specials += Instance("AE350_SOC", **self.cpu_params)

View File

@ -0,0 +1,75 @@
#define MIE_MEIE 0x800
.global _start
_start:
j reset_vector
reset_vector:
la sp, _fstack
la t0, trap_vector
csrw mtvec, t0
// initialize .data
la t0, _fdata
la t1, _edata
la t2, _fdata_rom
1: beq t0, t1, 2f
lw t3, 0(t2)
sw t3, 0(t0)
addi t0, t0, 4
addi t2, t2, 4
j 1b
2:
// initialize .bss
la t0, _fbss
la t1, _ebss
1: beq t0, t1, 3f
sw zero, 0(t0)
addi t0, t0, 4
j 1b
3:
// enable external interrupts
li t0, MIE_MEIE
csrs mie, t0
call main
1: j 1b
trap_vector:
addi sp, sp, -16*4
sw ra, 0*4(sp)
sw t0, 1*4(sp)
sw t1, 2*4(sp)
sw t2, 3*4(sp)
sw a0, 4*4(sp)
sw a1, 5*4(sp)
sw a2, 6*4(sp)
sw a3, 7*4(sp)
sw a4, 8*4(sp)
sw a5, 9*4(sp)
sw a6, 10*4(sp)
sw a7, 11*4(sp)
sw t3, 12*4(sp)
sw t4, 13*4(sp)
sw t5, 14*4(sp)
sw t6, 15*4(sp)
call isr
lw ra, 0*4(sp)
lw t0, 1*4(sp)
lw t1, 2*4(sp)
lw t2, 3*4(sp)
lw a0, 4*4(sp)
lw a1, 5*4(sp)
lw a2, 6*4(sp)
lw a3, 7*4(sp)
lw a4, 8*4(sp)
lw a5, 9*4(sp)
lw a6, 10*4(sp)
lw a7, 11*4(sp)
lw t3, 12*4(sp)
lw t4, 13*4(sp)
lw t5, 14*4(sp)
lw t6, 15*4(sp)
addi sp, sp, 16*4
mret

View File

@ -0,0 +1,4 @@
#ifndef __IRQ_H
#define __IRQ_H
#endif /* __IRQ_H */

View File

@ -0,0 +1,19 @@
#ifndef __SYSTEM_H
#define __SYSTEM_H
#ifdef __cplusplus
extern "C" {
#endif
__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME */
__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME */
void flush_l2_cache(void);
void busy_wait(unsigned int ms);
void busy_wait_us(unsigned int us);
#ifdef __cplusplus
}
#endif
#endif /* __SYSTEM_H */

View File

@ -125,7 +125,11 @@ __attribute__((__used__)) int main(int i, char **c)
printf("--=============== \e[1mSoC\e[0m ==================--\n");
printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n",
CONFIG_CPU_HUMAN_NAME,
#ifdef CONFIG_CPU_CLK_FREQ
CONFIG_CPU_CLK_FREQ/1000000);
#else
CONFIG_CLOCK_FREQUENCY/1000000);
#endif
printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n",
CONFIG_BUS_STANDARD,
CONFIG_BUS_DATA_WIDTH,