Source code for luna_soc.generate.introspect

#
# This file is part of LUNA.
#
# Copyright (c) 2023 Great Scott Gadgets <info@greatscottgadgets.com>
# SPDX-License-Identifier: BSD-3-Clause

"""Introspection tools for SoC designs."""

import logging

from collections          import defaultdict

from amaranth.lib         import wiring

from amaranth_soc         import csr
from amaranth_soc.memory  import MemoryMap, ResourceInfo

from ..gateware.cpu.ic    import InterruptMap


# - soc attributes ------------------------------------------------------------

[docs] def soc(fragment: wiring.Component) -> wiring.Component: if hasattr(fragment, "soc"): fragment = fragment.soc if not hasattr(fragment, "wb_decoder"): logging.warning("SoC designs need to have a 'wb_decoder' attribute.") if not hasattr(fragment, "interrupt_controller"): logging.warning("SoC designs need to have an 'interrupt_controller' attribute.") return fragment
[docs] def memory_map(fragment: wiring.Component) -> MemoryMap: return fragment.wb_decoder.bus.memory_map
[docs] def interrupts(fragment: wiring.Component) -> InterruptMap: return fragment.interrupt_controller.interrupts()
[docs] def reset_addr(fragment: wiring.Component) -> MemoryMap: return fragment.cpu.reset_addr
# - soc introspections --------------------------------------------------------
[docs] def csr_base(memory_map: MemoryMap) -> int: """Scan a memory map for the starting address for csr peripheral registers.""" window: MemoryMap name: MemoryMap.Name for window, name, (start, end, ratio) in memory_map.windows(): if name[0] == "wb_to_csr": return start
[docs] def csr_peripherals(memory_map: MemoryMap) -> dict[MemoryMap.Name, list[ResourceInfo]]: """Scan a memory map for csr peripheral registers.""" # group registers by peripheral csr_peripherals = defaultdict(list) # scan memory map for peripheral registers window: MemoryMap name: MemoryMap.Name for window, name, (start, end, ratio) in memory_map.windows(): resource_info: ResourceInfo for resource_info in window.all_resources(): peripheral: MemoryMap.Name = resource_info.path[0] register: csr.Register = resource_info.resource if issubclass(register.__class__, csr.Register): csr_peripherals[peripheral].append(resource_info) return csr_peripherals
[docs] def wb_peripherals(memory_map: MemoryMap) -> dict[ MemoryMap.Name, list[ tuple[ wiring.Component, MemoryMap.Name, (int, int) ] ]]: """Scan a memory map for wishbone peripherals.""" # group by peripheral wb_peripherals = defaultdict(list) # scan memory map for wb peripherals window: MemoryMap for window, name, (start, end, ratio) in memory_map.windows(): # window.resources() yields a tuple: `resource, resource_name, (start, end)` # where resource is the actual peripheral e.g. `core.blockram.Peripheral` for resource, path, (start, stop) in window.resources(): wb_peripherals[name].append((resource, path, (start, stop))) return wb_peripherals