cpu/cortex_m3: Review/Cleanup (Apply similar changes than for Cortex-M1).
This commit is contained in:
parent
2508b16f38
commit
b607de473d
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue