fanout/fainin wip
This commit is contained in:
@@ -16,9 +16,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
@functools.lru_cache
|
@functools.lru_cache
|
||||||
def get_cpuifs(
|
def get_cpuifs(config: list[tuple[str, Any]]) -> dict[str, type[BaseCpuif]]:
|
||||||
config: dict[str, Any],
|
|
||||||
) -> dict[str, type[BaseCpuif]]:
|
|
||||||
# All built-in CPUIFs
|
# All built-in CPUIFs
|
||||||
cpuifs: dict[str, type[BaseCpuif]] = {
|
cpuifs: dict[str, type[BaseCpuif]] = {
|
||||||
# "passthrough": passthrough.PassthroughCpuif,
|
# "passthrough": passthrough.PassthroughCpuif,
|
||||||
@@ -45,7 +43,7 @@ def get_cpuifs(
|
|||||||
cpuifs[name] = cpuif
|
cpuifs[name] = cpuif
|
||||||
|
|
||||||
# Load any CPUIFs via config import
|
# Load any CPUIFs via config import
|
||||||
for name, cpuif in config.items():
|
for name, cpuif in config:
|
||||||
if name in cpuifs:
|
if name in cpuifs:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"A plugin for 'peakrdl-busdecoder' tried to load cpuif '{name}' but it already exists"
|
f"A plugin for 'peakrdl-busdecoder' tried to load cpuif '{name}' but it already exists"
|
||||||
@@ -69,7 +67,7 @@ class Exporter(ExporterSubcommandPlugin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def get_cpuifs(self) -> dict[str, type[BaseCpuif]]:
|
def get_cpuifs(self) -> dict[str, type[BaseCpuif]]:
|
||||||
return get_cpuifs(self.cfg["cpuifs"])
|
return get_cpuifs(map(tuple, self.cfg["cpuifs"].items()))
|
||||||
|
|
||||||
def add_exporter_arguments(self, arg_group: "argparse.ArgumentParser") -> None: # type: ignore
|
def add_exporter_arguments(self, arg_group: "argparse.ArgumentParser") -> None: # type: ignore
|
||||||
cpuifs = self.get_cpuifs()
|
cpuifs = self.get_cpuifs()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
|
from ...utils import get_indexed_path
|
||||||
from ..base_cpuif import BaseCpuif
|
from ..base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
@@ -26,20 +27,32 @@ class APB3Cpuif(BaseCpuif):
|
|||||||
self,
|
self,
|
||||||
signal: str,
|
signal: str,
|
||||||
node: AddressableNode | None = None,
|
node: AddressableNode | None = None,
|
||||||
idx: str | int | None = None,
|
|
||||||
) -> str:
|
) -> str:
|
||||||
if node is None:
|
if node is None:
|
||||||
# Node is none, so this is a slave signal
|
# Node is none, so this is a slave signal
|
||||||
return f"s_apb.{signal}"
|
return f"s_apb.{signal}"
|
||||||
|
|
||||||
# Master signal
|
# Master signal
|
||||||
base = f"m_apb_{node.inst_name}"
|
return f"m_apb_{node.inst_name}.{signal}"
|
||||||
if not node.is_array:
|
|
||||||
return f"{base}.{signal}"
|
|
||||||
if node.current_idx is not None:
|
|
||||||
# This is a specific instance of an array
|
|
||||||
return f"{base}_{'_'.join(map(str, node.current_idx))}.{signal}"
|
|
||||||
if idx is not None:
|
|
||||||
return f"{base}[{idx}].{signal}"
|
|
||||||
|
|
||||||
raise ValueError("Must provide an index for arrayed interface signals")
|
def fanout(self, node: AddressableNode, idx: str | None = None) -> str:
|
||||||
|
fanout: dict[str, str] = {}
|
||||||
|
fanout[self.signal("PSEL", node, idx)] = (
|
||||||
|
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node)}|cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node)}"
|
||||||
|
)
|
||||||
|
fanout[self.signal("PSEL", node, idx)] = self.signal("PSEL")
|
||||||
|
fanout[self.signal("PWRITE", node, idx)] = (
|
||||||
|
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node)}"
|
||||||
|
)
|
||||||
|
fanout[self.signal("PADDR", node, idx)] = self.signal("PADDR")
|
||||||
|
fanout[self.signal("PWDATA", node, idx)] = "cpuif_wr_data"
|
||||||
|
|
||||||
|
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
||||||
|
|
||||||
|
def fanin(self, node: AddressableNode, idx: str | None = None) -> str:
|
||||||
|
fanin: dict[str, str] = {}
|
||||||
|
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, idx)
|
||||||
|
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, idx)
|
||||||
|
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, idx)
|
||||||
|
|
||||||
|
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
||||||
|
|||||||
@@ -11,47 +11,20 @@
|
|||||||
|
|
||||||
assign cpuif_req = {{cpuif.signal("PSELx")}};
|
assign cpuif_req = {{cpuif.signal("PSELx")}};
|
||||||
assign cpuif_wr_en = {{cpuif.signal("PWRITE")}};
|
assign cpuif_wr_en = {{cpuif.signal("PWRITE")}};
|
||||||
assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
|
|
||||||
assign cpuif_rd_en = !{{cpuif.signal("PWRITE")}};
|
assign cpuif_rd_en = !{{cpuif.signal("PWRITE")}};
|
||||||
|
|
||||||
{%- for child in cpuif.addressable_children -%}
|
assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
|
||||||
{%- if child is array -%}
|
|
||||||
for (genvar gi = 0; gi < N_{{child.inst_name|upper}}S; gi++) begin : g_passthrough_{{child.inst_name|lower}}
|
|
||||||
assign {{cpuif.signal("PCLK", child, "gi")}} = {{cpuif.signal("PCLK")}};
|
|
||||||
assign {{cpuif.signal("PRESETn", child, "gi")}} = {{cpuif.signal("PRESETn")}};
|
|
||||||
assign {{cpuif.signal("PSELx", child, "gi")}} = (cpuif_wr_req[{{loop.index}}] || cpuif_rd_req[{{loop.index}}]) ? 1'b1 : 1'b0;
|
|
||||||
assign {{cpuif.signal("PENABLE", child, "gi")}} = {{cpuif.signal("PENABLE")}};
|
|
||||||
assign {{cpuif.signal("PWRITE", child, "gi")}} = (cpuif_wr_req[{{loop.index}}]) ? 1'b1 : 1'b0;
|
|
||||||
assign {{cpuif.signal("PADDR", child, "gi")}} = {{child|address_slice(cpuif_addr="cpuif_wr_addr")}};
|
|
||||||
assign {{cpuif.signal("PWDATA", child, "gi")}} = cpuif_wr_data;
|
|
||||||
assign cpuif_rd_ack[loop.index] = {{cpuif.signal("PREADY", child)}};
|
|
||||||
assign cpuif_rd_data[loop.index] = {{cpuif.signal("PRDATA", child)}};
|
|
||||||
assign cpuif_rd_err[loop.index] = {{cpuif.signal("PSLVERR", child)}};
|
|
||||||
end
|
|
||||||
{%- else -%}
|
|
||||||
assign {{cpuif.signal("PCLK", child)}} = {{cpuif.signal("PCLK")}};
|
|
||||||
assign {{cpuif.signal("PRESETn", child)}} = {{cpuif.signal("PRESETn")}};
|
|
||||||
assign {{cpuif.signal("PSELx", child)}} = (cpuif_wr_sel[{{loop.index0}}] || cpuif_rd_sel[{{loop.index0}}]) ? 1'b1 : 1'b0;
|
|
||||||
assign {{cpuif.signal("PENABLE", child)}} = {{cpuif.signal("PENABLE")}};
|
|
||||||
assign {{cpuif.signal("PWRITE", child)}} = (cpuif_wr_req[{{loop.index}}]) ? 1'b1 : 1'b0;
|
|
||||||
assign {{cpuif.signal("PADDR", child)}} = {{child|address_slice(cpuif_addr="cpuif_wr_addr")}};
|
|
||||||
assign {{cpuif.signal("PWDATA", child)}} = cpuif_wr_data;
|
|
||||||
assign cpuif_rd_ack[loop.index] = {{cpuif.signal("PREADY", child)}};
|
|
||||||
assign cpuif_rd_data[loop.index] = {{cpuif.signal("PRDATA", child)}};
|
|
||||||
assign cpuif_rd_err[loop.index] = {{cpuif.signal("PSLVERR", child)}};
|
|
||||||
{%- endif -%}
|
|
||||||
{%- endfor%}
|
|
||||||
|
|
||||||
always_comb begin
|
assign {{cpuif.signal("PRDATA")}} = cpuif_rd_data;
|
||||||
{{cpuif.signal("PREADY")}} = 1'b0;
|
assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack;
|
||||||
{{cpuif.signal("PRDATA")}} = '0;
|
assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err;
|
||||||
{{cpuif.signal("PSLVERR")}} = 1'b0;
|
|
||||||
|
|
||||||
for(int i = 0; i < {{cpuif.addressable_children | length}}; i++) begin
|
//--------------------------------------------------------------------------
|
||||||
if (cpuif_rd_sel[i]) begin
|
// Fanout CPU Bus interface signals
|
||||||
{{cpuif.signal("PREADY")}} = cpuif_rd_ack[i];
|
//--------------------------------------------------------------------------
|
||||||
{{cpuif.signal("PRDATA")}} = cpuif_rd_data[i];
|
{{fanout|walk(cpuif=cpuif)}}
|
||||||
{{cpuif.signal("PSLVERR")}} = cpuif_rd_err[i];
|
|
||||||
end
|
//--------------------------------------------------------------------------
|
||||||
end
|
// Fanin CPU Bus interface signals
|
||||||
end
|
//--------------------------------------------------------------------------
|
||||||
|
{{fanin|walk(cpuif=cpuif)}}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
|
from ...utils import get_indexed_path
|
||||||
from ..base_cpuif import BaseCpuif
|
from ..base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
@@ -27,21 +28,34 @@ class APB4Cpuif(BaseCpuif):
|
|||||||
self,
|
self,
|
||||||
signal: str,
|
signal: str,
|
||||||
node: AddressableNode | None = None,
|
node: AddressableNode | None = None,
|
||||||
idx: str | int | None = None,
|
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Returns the signal name for the given signal and node."""
|
|
||||||
if node is None:
|
if node is None:
|
||||||
# Node is none, so this is a slave signal
|
# Node is none, so this is a slave signal
|
||||||
return f"s_apb.{signal}"
|
return f"s_apb.{signal}"
|
||||||
|
|
||||||
# Master signal
|
# Master signal
|
||||||
base = f"m_apb_{node.inst_name}"
|
return f"m_apb_{node.inst_name}.{signal}"
|
||||||
if not node.is_array:
|
|
||||||
return f"{base}.{signal}"
|
|
||||||
if node.current_idx is not None:
|
|
||||||
# This is a specific instance of an array
|
|
||||||
return f"{base}_{'_'.join(map(str, node.current_idx))}.{signal}"
|
|
||||||
if idx is not None:
|
|
||||||
return f"{base}[{idx}].{signal}"
|
|
||||||
|
|
||||||
raise ValueError("Must provide an index for arrayed interface signals")
|
def fanout(self, node: AddressableNode) -> str:
|
||||||
|
fanout: dict[str, str] = {}
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PSEL"] = (
|
||||||
|
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node)}|cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node)}"
|
||||||
|
)
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PSEL"] = self.signal("PSEL")
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PWRITE"] = (
|
||||||
|
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
|
||||||
|
)
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PADDR"] = self.signal("PADDR")
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PPROT"] = self.signal("PPROT")
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PWDATA"] = "cpuif_wr_data"
|
||||||
|
fanout[f"m_apb_{get_indexed_path(node.parent, node, 'gi')}.PSTRB"] = "cpuif_wr_byte_en"
|
||||||
|
|
||||||
|
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
||||||
|
|
||||||
|
def fanin(self, node: AddressableNode) -> str:
|
||||||
|
fanin: dict[str, str] = {}
|
||||||
|
fanin["cpuif_rd_data"] = self.signal("PRDATA", node)
|
||||||
|
fanin["cpuif_rd_ack"] = self.signal("PREADY", node)
|
||||||
|
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node)
|
||||||
|
|
||||||
|
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
||||||
|
|||||||
@@ -11,72 +11,21 @@
|
|||||||
|
|
||||||
assign cpuif_req = {{cpuif.signal("PSELx")}};
|
assign cpuif_req = {{cpuif.signal("PSELx")}};
|
||||||
assign cpuif_wr_en = {{cpuif.signal("PWRITE")}};
|
assign cpuif_wr_en = {{cpuif.signal("PWRITE")}};
|
||||||
assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
|
|
||||||
assign cpuif_rd_en = !{{cpuif.signal("PWRITE")}};
|
assign cpuif_rd_en = !{{cpuif.signal("PWRITE")}};
|
||||||
|
|
||||||
|
assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
|
||||||
|
assign cpuif_wr_byte_en = {{cpuif.signal("PSTRB")}};
|
||||||
|
|
||||||
|
assign {{cpuif.signal("PRDATA")}} = cpuif_rd_data;
|
||||||
|
assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack;
|
||||||
|
assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Fanout CPU Bus interface signals
|
// Fanout CPU Bus interface signals
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
{{fanout|walk(cpuif=cpuif)}}
|
||||||
// {%- for child in cpuif.addressable_children -%}
|
|
||||||
// {%- if child is array %}
|
|
||||||
// for (genvar gi = 0; gi < N_{{child.inst_name|upper}}S; gi++) begin : g_passthrough_{{child.inst_name|lower}}
|
|
||||||
// assign {{cpuif.signal("PCLK", child, "gi")}} = {{cpuif.signal("PCLK")}};
|
|
||||||
// assign {{cpuif.signal("PRESETn", child, "gi")}} = {{cpuif.signal("PRESETn")}};
|
|
||||||
// assign {{cpuif.signal("PSELx", child, "gi")}} = (cpuif_wr_sel[{{loop.index}}] || cpuif_rd_sel[{{loop.index}}]) ? 1'b1 : 1'b0;
|
|
||||||
// assign {{cpuif.signal("PENABLE", child, "gi")}} = {{cpuif.signal("PENABLE")}};
|
|
||||||
// assign {{cpuif.signal("PWRITE", child, "gi")}} = (cpuif_wr_sel[{{loop.index}}]) ? 1'b1 : 1'b0;
|
|
||||||
// assign {{cpuif.signal("PADDR", child, "gi")}} = {{child|address_slice(cpuif_addr="cpuif_wr_addr")}};
|
|
||||||
// assign {{cpuif.signal("PPROT", child, "gi")}} = {{cpuif.signal("PPROT")}};
|
|
||||||
// assign {{cpuif.signal("PWDATA", child, "gi")}} = cpuif_wr_data;
|
|
||||||
// assign {{cpuif.signal("PSTRB", child, "gi")}} = {{cpuif.signal("PSTRB")}};
|
|
||||||
// assign cpuif_rd_ack[{{loop.index}}] = {{cpuif.signal("PREADY", child, "gi")}};
|
|
||||||
// assign cpuif_rd_data[{{loop.index}}] = {{cpuif.signal("PRDATA", child, "gi")}};
|
|
||||||
// assign cpuif_rd_err[{{loop.index}}] = {{cpuif.signal("PSLVERR", child, "gi")}};
|
|
||||||
// end
|
|
||||||
// {%- else %}
|
|
||||||
// assign {{cpuif.signal("PCLK", child)}} = {{cpuif.signal("PCLK")}};
|
|
||||||
// assign {{cpuif.signal("PRESETn", child)}} = {{cpuif.signal("PRESETn")}};
|
|
||||||
// assign {{cpuif.signal("PSELx", child)}} = (cpuif_wr_sel[{{loop.index}}] || cpuif_rd_sel[{{loop.index}}]) ? 1'b1 : 1'b0;
|
|
||||||
// assign {{cpuif.signal("PENABLE", child)}} = {{cpuif.signal("PENABLE")}};
|
|
||||||
// assign {{cpuif.signal("PWRITE", child)}} = cpuif_wr_sel[{{loop.index}}] ? 1'b1 : 1'b0;
|
|
||||||
// assign {{cpuif.signal("PADDR", child)}} = {{child|address_slice(cpuif_addr="cpuif_wr_addr")}};
|
|
||||||
// assign {{cpuif.signal("PPROT", child)}} = {{cpuif.signal("PPROT")}};
|
|
||||||
// assign {{cpuif.signal("PWDATA", child)}} = cpuif_wr_data;
|
|
||||||
// assign {{cpuif.signal("PSTRB", child)}} = {{cpuif.signal("PSTRB")}};
|
|
||||||
// assign cpuif_rd_ack[{{loop.index}}] = {{cpuif.signal("PREADY", child)}};
|
|
||||||
// assign cpuif_rd_data[{{loop.index}}] = {{cpuif.signal("PRDATA", child)}};
|
|
||||||
// assign cpuif_rd_err[{{loop.index}}] = {{cpuif.signal("PSLVERR", child)}};
|
|
||||||
// {%- endif -%}
|
|
||||||
// {%- endfor %}
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Fanin CPU Bus interface signals
|
// Fanin CPU Bus interface signals
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
always_comb begin
|
{{fanin|walk(cpuif=cpuif)}}
|
||||||
{{cpuif.signal("PREADY")}} = 1'b0;
|
|
||||||
{{cpuif.signal("PRDATA")}} = '0;
|
|
||||||
{{cpuif.signal("PSLVERR")}} = 1'b0;
|
|
||||||
|
|
||||||
|
|
||||||
{%- for child in cpuif.addressable_children -%}
|
|
||||||
{%- if loop.first %}
|
|
||||||
if (cpuif_rd_sel.{{child|get_path}}) begin
|
|
||||||
{%- else %}
|
|
||||||
end else if (cpuif_rd_sel.{{child|get_path}}) begin
|
|
||||||
{%- endif %}
|
|
||||||
{{cpuif.signal("PREADY")}} = cpuif_rd_ack[{{loop.index}}];
|
|
||||||
{{cpuif.signal("PRDATA")}} = cpuif_rd_data[{{loop.index}}];
|
|
||||||
{{cpuif.signal("PSLVERR")}} = cpuif_rd_err[{{loop.index}}];
|
|
||||||
{%- endfor %}
|
|
||||||
end
|
|
||||||
|
|
||||||
// for(int i = 0; i < {{cpuif.addressable_children | length}}; i++) begin
|
|
||||||
// if (cpuif_rd_sel[i]) begin
|
|
||||||
// {{cpuif.signal("PREADY")}} = cpuif_rd_ack[i];
|
|
||||||
// {{cpuif.signal("PRDATA")}} = cpuif_rd_data[i];
|
|
||||||
// {{cpuif.signal("PSLVERR")}} = cpuif_rd_err[i];
|
|
||||||
// end
|
|
||||||
// end
|
|
||||||
end
|
|
||||||
@@ -106,8 +106,14 @@ class BaseCpuif:
|
|||||||
|
|
||||||
return f"({cpuif_addr} - 'h{addr:x})[{clog2(size) - 1}:0]"
|
return f"({cpuif_addr} - 'h{addr:x})[{clog2(size) - 1}:0]"
|
||||||
|
|
||||||
def walk(self, listener_cls: type[BusDecoderListener], **kwargs: Any) -> str:
|
def walk(self, listener_cls: type[BusDecoderListener], **kwargs: Any) -> str: # noqa: ANN401
|
||||||
walker = RDLSteerableWalker()
|
walker = RDLSteerableWalker()
|
||||||
listener = listener_cls(self.exp.ds, **kwargs)
|
listener = listener_cls(self.exp.ds, **kwargs)
|
||||||
walker.walk(self.exp.ds.top_node, listener, skip_top=True)
|
walker.walk(self.exp.ds.top_node, listener, skip_top=True)
|
||||||
return str(listener)
|
return str(listener)
|
||||||
|
|
||||||
|
def fanout(self, node: AddressableNode) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def fanin(self, node: AddressableNode) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|||||||
@@ -1,19 +1,49 @@
|
|||||||
|
from collections import deque
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
from systemrdl.walker import WalkerAction
|
from systemrdl.walker import WalkerAction
|
||||||
|
|
||||||
|
from ..body import Body, CombinationalBody, ForLoopBody
|
||||||
from ..design_state import DesignState
|
from ..design_state import DesignState
|
||||||
from ..listener import BusDecoderListener
|
from ..listener import BusDecoderListener
|
||||||
from .base_cpuif import BaseCpuif
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
class FaninGenerator(BusDecoderListener):
|
class FaninGenerator(BusDecoderListener):
|
||||||
def __init__(self, ds: DesignState, cpuif: BaseCpuif) -> None:
|
def __init__(self, ds: DesignState, cpuif: "BaseCpuif") -> None:
|
||||||
super().__init__(ds)
|
super().__init__(ds)
|
||||||
self._cpuif = cpuif
|
self._cpuif = cpuif
|
||||||
|
|
||||||
|
self._stack: deque[Body] = deque()
|
||||||
|
self._stack.append(CombinationalBody())
|
||||||
|
|
||||||
def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
|
def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
|
||||||
action = super().enter_AddressableComponent(node)
|
action = super().enter_AddressableComponent(node)
|
||||||
|
|
||||||
|
if node.array_dimensions:
|
||||||
|
for i, dim in enumerate(node.array_dimensions):
|
||||||
|
fb = ForLoopBody(
|
||||||
|
"int",
|
||||||
|
f"i{i}",
|
||||||
|
dim,
|
||||||
|
)
|
||||||
|
self._stack.append(fb)
|
||||||
|
|
||||||
|
self._stack[-1] += self._cpuif.fanin(node)
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def exit_AddressableComponent(self, node: AddressableNode) -> None:
|
def exit_AddressableComponent(self, node: AddressableNode) -> None:
|
||||||
|
if node.array_dimensions:
|
||||||
|
for _ in node.array_dimensions:
|
||||||
|
b = self._stack.pop()
|
||||||
|
if not b:
|
||||||
|
continue
|
||||||
|
self._stack[-1] += b
|
||||||
|
|
||||||
super().exit_AddressableComponent(node)
|
super().exit_AddressableComponent(node)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return "\n".join(map(str, self._stack))
|
||||||
|
|||||||
@@ -1,19 +1,49 @@
|
|||||||
|
from collections import deque
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
from systemrdl.walker import WalkerAction
|
from systemrdl.walker import WalkerAction
|
||||||
|
|
||||||
|
from ..body import Body, ForLoopBody
|
||||||
from ..design_state import DesignState
|
from ..design_state import DesignState
|
||||||
from ..listener import BusDecoderListener
|
from ..listener import BusDecoderListener
|
||||||
from .base_cpuif import BaseCpuif
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
class FanoutGenerator(BusDecoderListener):
|
class FanoutGenerator(BusDecoderListener):
|
||||||
def __init__(self, ds: DesignState, cpuif: BaseCpuif) -> None:
|
def __init__(self, ds: DesignState, cpuif: "BaseCpuif") -> None:
|
||||||
super().__init__(ds)
|
super().__init__(ds)
|
||||||
self._cpuif = cpuif
|
self._cpuif = cpuif
|
||||||
|
|
||||||
|
self._stack: deque[Body] = deque()
|
||||||
|
self._stack.append(Body())
|
||||||
|
|
||||||
def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
|
def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
|
||||||
action = super().enter_AddressableComponent(node)
|
action = super().enter_AddressableComponent(node)
|
||||||
|
|
||||||
|
if node.array_dimensions:
|
||||||
|
for i, dim in enumerate(node.array_dimensions):
|
||||||
|
fb = ForLoopBody(
|
||||||
|
"genvar",
|
||||||
|
f"gi{i}",
|
||||||
|
dim,
|
||||||
|
)
|
||||||
|
self._stack.append(fb)
|
||||||
|
|
||||||
|
self._stack[-1] += self._cpuif.fanout(node)
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def exit_AddressableComponent(self, node: AddressableNode) -> None:
|
def exit_AddressableComponent(self, node: AddressableNode) -> None:
|
||||||
|
if node.array_dimensions:
|
||||||
|
for _ in node.array_dimensions:
|
||||||
|
b = self._stack.pop()
|
||||||
|
if not b:
|
||||||
|
continue
|
||||||
|
self._stack[-1] += b
|
||||||
|
|
||||||
super().exit_AddressableComponent(node)
|
super().exit_AddressableComponent(node)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return "\n".join(map(str, self._stack))
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class DecodeLogicGenerator(BusDecoderListener):
|
|||||||
condition = " && ".join(f"({c})" for c in conditions)
|
condition = " && ".join(f"({c})" for c in conditions)
|
||||||
|
|
||||||
# Generate condition string and manage stack
|
# Generate condition string and manage stack
|
||||||
if isinstance(self._decode_stack[-1], IfBody) and node.array_dimensions:
|
if node.array_dimensions:
|
||||||
# arrayed component with new if-body
|
# arrayed component with new if-body
|
||||||
self._cond_stack.append(condition)
|
self._cond_stack.append(condition)
|
||||||
for i, dim in enumerate(
|
for i, dim in enumerate(
|
||||||
@@ -101,6 +101,8 @@ class DecodeLogicGenerator(BusDecoderListener):
|
|||||||
# non-arrayed component with if-body
|
# non-arrayed component with if-body
|
||||||
with self._decode_stack[-1].cm(condition) as b:
|
with self._decode_stack[-1].cm(condition) as b:
|
||||||
b += f"{self._flavor.cpuif_select}.{get_indexed_path(self._ds.top_node, node)} = 1'b1;"
|
b += f"{self._flavor.cpuif_select}.{get_indexed_path(self._ds.top_node, node)} = 1'b1;"
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Invalid decode stack state")
|
||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user