Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
ebabe82c7This file is pinned to the selected release. Download the original to open it in your design tool.
#
# 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)