cpu/cortex_m3: Review/Cleanup (Apply similar changes than for Cortex-M1).

This commit is contained in:
Florent Kermarrec 2022-04-22 17:03:02 +02:00
parent 2508b16f38
commit b607de473d
1 changed files with 125 additions and 57 deletions

View File

@ -2,14 +2,19 @@
# This file is part of LiteX. # This file is part of LiteX.
# #
# Copyright (c) 2022 Ilia Sergachev <ilia@sergachev.ch> # Copyright (c) 2022 Ilia Sergachev <ilia@sergachev.ch>
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause # SPDX-License-Identifier: BSD-2-Clause
import os import os
from migen import * from migen import *
from litex.soc.interconnect import wishbone
from litex.soc.cores.cpu import CPU from litex.soc.cores.cpu import CPU
from litex.soc.interconnect import axi from litex.soc.interconnect import axi
class Open(Signal): pass
# Cortex-M3 ----------------------------------------------------------------------------------------
class CortexM3(CPU): class CortexM3(CPU):
variants = ["standard"] variants = ["standard"]
@ -23,85 +28,148 @@ class CortexM3(CPU):
gcc_flags = "-march=armv7-m -mthumb" gcc_flags = "-march=armv7-m -mthumb"
linker_output_format = "elf32-littlearm" linker_output_format = "elf32-littlearm"
nop = "nop" nop = "nop"
io_regions = {0x4000_0000: 0x2000_0000, io_regions = {
0xA000_0000: 0x6000_0000 # Origin, Length.
} # Origin, Length. 0x4000_0000 : 0x2000_0000,
0xa000_0000 : 0x6000_0000,
}
@property @property
def mem_map(self): def mem_map(self):
return { return {
"rom": 0x0000_0000, "rom" : 0x0000_0000,
"main_ram": 0x1000_0000, "sram" : 0x2000_0000,
"sram": 0x2000_0000, "main_ram" : 0x1000_0000,
"csr": 0xA000_0000 "csr" : 0xa000_0000,
} }
def __init__(self, platform, variant, *args, **kwargs): def __init__(self, platform, variant="standard"):
super().__init__(*args, **kwargs) self.platform = platform
self.platform = platform self.reset = Signal()
self.reset = Signal() self.interrupt = Signal(2)
self.interrupt = Signal(2) ibus = axi.AXILiteInterface(data_width=32, address_width=32)
pbus = wishbone.Interface(data_width=32, adr_width=30) dbus = axi.AXILiteInterface(data_width=32, address_width=32)
ibus = wishbone.Interface(data_width=32, adr_width=30) self.periph_buses = [ibus, dbus]
self.periph_buses = [pbus, ibus] self.memory_buses = []
self.memory_buses = []
def _mem_size(x): # Peripheral Bus AXI <-> AXILite conversion.
return log2_int(x // 512) ibus_axi = axi.AXIInterface(data_width=self.data_width, address_width=32)
self.submodules += axi.AXI2AXILite(ibus_axi, ibus)
dbus_axi = axi.AXIInterface(data_width=self.data_width, address_width=32)
self.submodules += axi.AXI2AXILite(dbus_axi, dbus)
# CPU Instance.
self.cpu_params = dict( self.cpu_params = dict(
# Clk/Rst.
i_HCLK = ClockSignal("sys"), i_HCLK = ClockSignal("sys"),
i_SYSRESETn = ~(ResetSignal() | self.reset), i_SYSRESETn = ~(ResetSignal() | self.reset),
p_NUM_IRQ = len(self.interrupt),
i_IRQ = self.interrupt, # Control/Status.
i_DBGRESETn = ~(ResetSignal() | self.reset),
p_MPU_PRESENT = 0, p_MPU_PRESENT = 0,
p_ITCM_SIZE = _mem_size(0 * 1024), # embedded ROM p_TRACE_LVL = 0,
p_DTCM_SIZE = _mem_size(0 * 1024), # embedded RAM p_DEBUG_LVL = 2,
p_TRACE_LVL = 0,
p_DEBUG_LVL = 2, # Interrupts.
p_NUM_IRQ = len(self.interrupt),
i_IRQ = self.interrupt,
# Embedded ROM/SRAM.
p_ITCM_SIZE = 0, # Use LiteX's ROM.
p_DTCM_SIZE = 0, # Use LiteX's RAM.
i_CFGITCMEN = 0, # 1 = alias ITCM at 0x0 i_CFGITCMEN = 0, # 1 = alias ITCM at 0x0
# Debug.
i_DBGRESETn = ~(ResetSignal() | self.reset),
# Instruction Bus (AXI).
o_AWVALIDC = ibus_axi.aw.valid,
i_AWREADYC = ibus_axi.aw.ready,
o_AWADDRC = ibus_axi.aw.addr,
o_AWBURSTC = ibus_axi.aw.burst,
o_AWCACHEC = ibus_axi.aw.cache,
o_AWLENC = ibus_axi.aw.len,
o_AWLOCKC = ibus_axi.aw.lock,
o_AWPROTC = ibus_axi.aw.prot,
o_AWSIZEC = ibus_axi.aw.size,
o_WVALIDC = ibus_axi.w.valid,
i_WREADYC = ibus_axi.w.ready,
o_WLASTC = ibus_axi.w.last,
o_WSTRBC = ibus_axi.w.strb,
o_HWDATAC = ibus_axi.w.data,
i_BVALIDC = ibus_axi.b.valid,
o_BREADYC = ibus_axi.b.ready,
i_BRESPC = ibus_axi.b.resp,
o_ARVALIDC = ibus_axi.ar.valid,
i_ARREADYC = ibus_axi.ar.ready,
o_ARADDRC = ibus_axi.ar.addr,
o_ARBURSTC = ibus_axi.ar.burst,
o_ARCACHEC = ibus_axi.ar.cache,
o_ARLENC = ibus_axi.ar.len,
o_ARLOCKC = ibus_axi.ar.lock,
o_ARPROTC = ibus_axi.ar.prot,
o_ARSIZEC = ibus_axi.ar.size,
i_RVALIDC = ibus_axi.r.valid,
o_RREADYC = ibus_axi.r.ready,
i_RLASTC = ibus_axi.r.last,
i_RRESPC = ibus_axi.r.resp,
i_HRDATAC = ibus_axi.r.data,
# Data Bus (AXI).
o_AWVALIDS = dbus_axi.aw.valid,
i_AWREADYS = dbus_axi.aw.ready,
o_AWADDRS = dbus_axi.aw.addr,
o_AWBURSTS = dbus_axi.aw.burst,
o_AWCACHES = dbus_axi.aw.cache,
o_AWLENS = dbus_axi.aw.len,
o_AWLOCKS = dbus_axi.aw.lock,
o_AWPROTS = dbus_axi.aw.prot,
o_AWSIZES = dbus_axi.aw.size,
o_WVALIDS = dbus_axi.w.valid,
i_WREADYS = dbus_axi.w.ready,
o_WLASTS = dbus_axi.w.last,
o_WSTRBS = dbus_axi.w.strb,
o_HWDATAS = dbus_axi.w.data,
i_BVALIDS = dbus_axi.b.valid,
o_BREADYS = dbus_axi.b.ready,
i_BRESPS = dbus_axi.b.resp,
o_ARVALIDS = dbus_axi.ar.valid,
i_ARREADYS = dbus_axi.ar.ready,
o_ARADDRS = dbus_axi.ar.addr,
o_ARBURSTS = dbus_axi.ar.burst,
o_ARCACHES = dbus_axi.ar.cache,
o_ARLENS = dbus_axi.ar.len,
o_ARLOCKS = dbus_axi.ar.lock,
o_ARPROTS = dbus_axi.ar.prot,
o_ARSIZES = dbus_axi.ar.size,
i_RVALIDS = dbus_axi.r.valid,
o_RREADYS = dbus_axi.r.ready,
i_RLASTS = dbus_axi.r.last,
i_RRESPS = dbus_axi.r.resp,
i_HRDATAS = dbus_axi.r.data,
) )
def connect_axi(axi_bus, suffix):
layout = axi_bus.layout_flat()
dir_map = {DIR_M_TO_S: 'o', DIR_S_TO_M: 'i'}
for group, signal, direction in layout:
if signal in ['id', 'qos', 'first']:
continue
if signal == 'last':
if group in ['b', 'a', 'ar', 'aw']:
continue
prefix = 'H' if signal == 'data' else ''
direction = dir_map[direction]
self.cpu_params[f'{direction}_{prefix}{group.upper()}{signal.upper()}{suffix}'] = \
getattr(getattr(axi_bus, group), signal)
ibus_axi = axi.AXIInterface(data_width=self.data_width, address_width=32)
ibus_a2w = axi.AXI2Wishbone(ibus_axi, ibus, base_address=0)
self.submodules += ibus_a2w
connect_axi(ibus_axi, 'C')
pbus_axi = axi.AXIInterface(data_width=self.data_width, address_width=32)
pbus_a2w = axi.AXI2Wishbone(pbus_axi, pbus, base_address=0)
self.submodules += pbus_a2w
connect_axi(pbus_axi, 'S')
platform.add_source_dir("AT426-BU-98000-r0p1-00rel0/vivado/Arm_ipi_repository/CM3DbgAXI/rtl") platform.add_source_dir("AT426-BU-98000-r0p1-00rel0/vivado/Arm_ipi_repository/CM3DbgAXI/rtl")
def connect_jtag(self, pads): def add_jtag(self, pads):
self.cpu_params.update( self.cpu_params.update(
p_JTAG_PRESENT = 1, p_JTAG_PRESENT = 1,
i_SWDITMS = pads.tms, i_SWDITMS = pads.tms,
i_TDI = pads.tdi, i_TDI = pads.tdi,
o_TDO = pads.tdo, o_TDO = pads.tdo,
o_nTDOEN = Signal(), o_nTDOEN = Open(),
i_nTRST = pads.ntrst, i_nTRST = pads.ntrst,
i_SWCLKTCK = pads.tck, i_SWCLKTCK = pads.tck,
o_JTAGNSW = Signal(), # Indicates debug mode, JTAG or SWD o_JTAGNSW = Open(), # Indicates debug mode, JTAG or SWD
o_JTAGTOP = Signal(), # ? o_JTAGTOP = Open(), # ?
o_SWDO = Signal(), # TODO o_SWDO = Open(), # TODO
o_SWDOEN = Signal(), # TODO o_SWDOEN = Open(), # TODO
) )
def do_finalize(self): def do_finalize(self):