"updt"
This commit is contained in:
92
src/peakrdl_busdecoder/cpuif/base_cpuif.py
Normal file
92
src/peakrdl_busdecoder/cpuif/base_cpuif.py
Normal file
@@ -0,0 +1,92 @@
|
||||
from typing import TYPE_CHECKING
|
||||
import inspect
|
||||
import os
|
||||
|
||||
import jinja2 as jj
|
||||
from systemrdl.node import AddressableNode
|
||||
|
||||
from ..utils import clog2, is_pow2, roundup_pow2
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..exporter import BusDecoderExporter
|
||||
|
||||
|
||||
class BaseCpuif:
|
||||
# Path is relative to the location of the class that assigns this variable
|
||||
template_path = ""
|
||||
|
||||
def __init__(self, exp: "BusDecoderExporter") -> None:
|
||||
self.exp = exp
|
||||
self.reset = exp.ds.top_node.cpuif_reset
|
||||
self.unroll = exp.ds.cpuif_unroll
|
||||
|
||||
@property
|
||||
def addressable_children(self) -> list[AddressableNode]:
|
||||
return [
|
||||
child
|
||||
for child in self.exp.ds.top_node.children(unroll=self.unroll)
|
||||
if isinstance(child, AddressableNode)
|
||||
]
|
||||
|
||||
@property
|
||||
def addr_width(self) -> int:
|
||||
return self.exp.ds.addr_width
|
||||
|
||||
@property
|
||||
def data_width(self) -> int:
|
||||
return self.exp.ds.cpuif_data_width
|
||||
|
||||
@property
|
||||
def data_width_bytes(self) -> int:
|
||||
return self.data_width // 8
|
||||
|
||||
@property
|
||||
def port_declaration(self) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def parameters(self) -> list[str]:
|
||||
"""
|
||||
Optional list of additional parameters this CPU interface provides to
|
||||
the module's definition
|
||||
"""
|
||||
array_parameters = [
|
||||
f"parameter N_{child.inst_name.upper()}S = {child.n_elements}"
|
||||
for child in self.addressable_children
|
||||
if self.check_is_array(child)
|
||||
]
|
||||
return array_parameters
|
||||
|
||||
def _get_template_path_class_dir(self) -> str:
|
||||
"""
|
||||
Traverse up the MRO and find the first class that explicitly assigns
|
||||
template_path. Returns the directory that contains the class definition.
|
||||
"""
|
||||
for cls in inspect.getmro(self.__class__):
|
||||
if "template_path" in cls.__dict__:
|
||||
class_dir = os.path.dirname(inspect.getfile(cls))
|
||||
return class_dir
|
||||
raise RuntimeError
|
||||
|
||||
def check_is_array(self, node: AddressableNode) -> bool:
|
||||
return node.is_array and not self.unroll
|
||||
|
||||
def get_implementation(self) -> str:
|
||||
class_dir = self._get_template_path_class_dir()
|
||||
loader = jj.FileSystemLoader(class_dir)
|
||||
jj_env = jj.Environment(
|
||||
loader=loader,
|
||||
undefined=jj.StrictUndefined,
|
||||
)
|
||||
jj_env.tests["array"] = self.check_is_array # type: ignore
|
||||
jj_env.filters["clog2"] = clog2 # type: ignore
|
||||
jj_env.filters["is_pow2"] = is_pow2 # type: ignore
|
||||
jj_env.filters["roundup_pow2"] = roundup_pow2 # type: ignore
|
||||
|
||||
context = {
|
||||
"cpuif": self,
|
||||
"ds": self.exp.ds,
|
||||
}
|
||||
|
||||
template = jj_env.get_template(self.template_path)
|
||||
return template.render(context)
|
||||
Reference in New Issue
Block a user