mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
123 lines
4.2 KiB
Python
123 lines
4.2 KiB
Python
#
|
|
# This file is part of LiteX.
|
|
#
|
|
# Copyright (c) 2020 Sean Cross <sean@xobs.io>
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
from migen.fhdl.module import DUID
|
|
from migen.util.misc import xdir
|
|
|
|
from litex.soc.interconnect.csr_eventmanager import EventManager
|
|
from litex.soc.integration.doc import ModuleDoc
|
|
|
|
import textwrap
|
|
|
|
from .rst import print_table, print_rst
|
|
|
|
def gather_submodules_inner(module, depth, seen_modules, submodules):
|
|
if module is None:
|
|
return submodules
|
|
if depth == 0:
|
|
if isinstance(module, ModuleDoc):
|
|
# print("{} is an instance of ModuleDoc".format(module))
|
|
submodules["module_doc"].append(module)
|
|
for k,v in module._submodules:
|
|
# print("{}Submodule {} {}".format(" "*(depth*4), k, v))
|
|
if v not in seen_modules:
|
|
seen_modules.add(v)
|
|
if isinstance(v, EventManager):
|
|
# print("{}{} appears to be an EventManager".format(" "*(depth*4), k))
|
|
submodules["event_managers"].append(v)
|
|
|
|
if isinstance(v, ModuleDoc):
|
|
submodules["module_doc"].append(v)
|
|
|
|
gather_submodules_inner(v, depth + 1, seen_modules, submodules)
|
|
return submodules
|
|
|
|
def gather_submodules(module):
|
|
depth = 0
|
|
seen_modules = set()
|
|
submodules = {
|
|
"event_managers": [],
|
|
"module_doc": [],
|
|
}
|
|
|
|
return gather_submodules_inner(module, depth, seen_modules, submodules)
|
|
|
|
class ModuleNotDocumented(Exception):
|
|
"""Indicates a Module has no documentation or sub-documentation"""
|
|
pass
|
|
|
|
class DocumentedModule:
|
|
"""Multi-section Documentation of a Module"""
|
|
|
|
def __init__(self, name, module, has_documentation=False):
|
|
self.name = name
|
|
self.sections = []
|
|
|
|
if isinstance(module, ModuleDoc):
|
|
has_documentation = True
|
|
self.sections.append(module)
|
|
|
|
if hasattr(module, "get_module_documentation"):
|
|
for doc in module.get_module_documentation():
|
|
has_documentation = True
|
|
self.sections.append(doc)
|
|
|
|
if not has_documentation:
|
|
raise ModuleNotDocumented()
|
|
|
|
def print_region(self, stream, base_dir, note_pulses=False):
|
|
title = "{}".format(self.name.upper())
|
|
print(title, file=stream)
|
|
print("=" * len(title), file=stream)
|
|
print("", file=stream)
|
|
|
|
for section in self.sections:
|
|
title = textwrap.dedent(section.title())
|
|
body = textwrap.dedent(section.body())
|
|
print("{}".format(title), file=stream)
|
|
print("-" * len(title), file=stream)
|
|
print(textwrap.dedent(body), file=stream)
|
|
print("", file=stream)
|
|
|
|
class DocumentedInterrupts(DocumentedModule):
|
|
"""A :obj:`DocumentedModule` that automatically documents interrupts in an SoC
|
|
|
|
This creates a :obj:`DocumentedModule` object that prints out the contents
|
|
of the interrupt map of an SoC.
|
|
"""
|
|
def __init__(self, interrupts):
|
|
DocumentedModule.__init__(self, "interrupts", None, has_documentation=True)
|
|
|
|
self.irq_table = [["Interrupt", "Module"]]
|
|
for module_name, irq_no in interrupts.items():
|
|
self.irq_table.append([str(irq_no), ":doc:`{} <{}>`".format(module_name.upper(), module_name)])
|
|
|
|
def print_region(self, stream, base_dir, note_pulses=False):
|
|
title = "Interrupt Controller"
|
|
print(title, file=stream)
|
|
print("=" * len(title), file=stream)
|
|
print("", file=stream)
|
|
|
|
print_rst(stream,
|
|
"""
|
|
This device has an ``EventManager``-based interrupt
|
|
system. Individual modules generate `events` which are wired
|
|
into a central interrupt controller.
|
|
|
|
When an interrupt occurs, you should look the interrupt number up
|
|
in the CPU-specific interrupt table and then call the relevant
|
|
module.
|
|
""")
|
|
|
|
section_title = "Assigned Interrupts"
|
|
print("{}".format(section_title), file=stream)
|
|
print("-" * len(section_title), file=stream)
|
|
print("", file=stream)
|
|
|
|
print("The following interrupts are assigned on this system:", file=stream)
|
|
print_table(self.irq_table, stream)
|
|
|
|
|