decoder compiles
This commit is contained in:
@@ -42,37 +42,4 @@ class APB3Cpuif(BaseCpuif):
|
||||
if idx is not None:
|
||||
return f"{base}[{idx}].{signal}"
|
||||
|
||||
raise ValueError("Must provide an index for arrayed interface signals")
|
||||
|
||||
def get_address_predicate(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that evaluates to true when the
|
||||
address on the bus matches the address range of the given node.
|
||||
"""
|
||||
|
||||
addr_mask = (1 << self.addr_width) - 1
|
||||
addr = node.absolute_address & addr_mask
|
||||
size = node.size
|
||||
if size == 0:
|
||||
raise ValueError("Node size must be greater than 0")
|
||||
if (addr % size) != 0:
|
||||
raise ValueError("Node address must be aligned to its size")
|
||||
|
||||
# Calculate the address range of the node
|
||||
addr_start = addr
|
||||
addr_end = addr + size - 1
|
||||
if addr_end > addr_mask:
|
||||
raise ValueError("Node address range exceeds address width")
|
||||
|
||||
if addr_start == addr_end:
|
||||
return f"({self.signal('PADDR')} == 'h{addr_start:X})"
|
||||
|
||||
return f"({self.signal('PADDR')} >= 'h{addr_start:X} && {self.signal('PADDR')} <= 'h{addr_end:X})"
|
||||
|
||||
def get_address_decode_condition(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that evaluates to true when the
|
||||
address on the bus matches the address range of the given node.
|
||||
"""
|
||||
addr_pred = self.get_address_predicate(node)
|
||||
return addr_pred
|
||||
raise ValueError("Must provide an index for arrayed interface signals")
|
||||
@@ -16,14 +16,14 @@ assign cpuif_rd_en = !{{cpuif.signal("PWRITE")}};
|
||||
|
||||
{%- for child in cpuif.addressable_children -%}
|
||||
{%- if child is array -%}
|
||||
for (genvar g_idx = 0; g_idx < N_{{child.inst_name|upper}}S; g_idx++) begin : g_passthrough_{{child.inst_name|lower}}
|
||||
assign {{cpuif.signal("PCLK", child, "g_idx")}} = {{cpuif.signal("PCLK")}};
|
||||
assign {{cpuif.signal("PRESETn", child, "g_idx")}} = {{cpuif.signal("PRESETn")}};
|
||||
assign {{cpuif.signal("PSELx", child, "g_idx")}} = (cpuif_wr_req[{{loop.index}}] || cpuif_rd_req[{{loop.index}}]) ? 1'b1 : 1'b0;
|
||||
assign {{cpuif.signal("PENABLE", child, "g_idx")}} = {{cpuif.signal("PENABLE")}};
|
||||
assign {{cpuif.signal("PWRITE", child, "g_idx")}} = (cpuif_wr_req[{{loop.index}}]) ? 1'b1 : 1'b0;
|
||||
assign {{cpuif.signal("PADDR", child, "g_idx")}} = cpuif_wr_addr{{child|address_slice}};
|
||||
assign {{cpuif.signal("PWDATA", child, "g_idx")}} = cpuif_wr_data;
|
||||
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)}};
|
||||
@@ -31,10 +31,10 @@ 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("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)}} = cpuif_wr_addr{{child|address_slice}};
|
||||
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)}};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from systemrdl.node import AddressableNode
|
||||
|
||||
from ..base_cpuif import BaseCpuif
|
||||
|
||||
|
||||
@@ -44,36 +45,3 @@ class APB4Cpuif(BaseCpuif):
|
||||
return f"{base}[{idx}].{signal}"
|
||||
|
||||
raise ValueError("Must provide an index for arrayed interface signals")
|
||||
|
||||
def get_address_predicate(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that evaluates to true when the
|
||||
address on the bus matches the address range of the given node.
|
||||
"""
|
||||
|
||||
addr_mask = (1 << self.addr_width) - 1
|
||||
addr = node.absolute_address & addr_mask
|
||||
size = node.size
|
||||
if size == 0:
|
||||
raise ValueError("Node size must be greater than 0")
|
||||
if (addr % size) != 0:
|
||||
raise ValueError("Node address must be aligned to its size")
|
||||
|
||||
# Calculate the address range of the node
|
||||
addr_start = addr
|
||||
addr_end = addr + size - 1
|
||||
if addr_end > addr_mask:
|
||||
raise ValueError("Node address range exceeds address width")
|
||||
|
||||
if addr_start == addr_end:
|
||||
return f"({self.signal('PADDR')} == 'h{addr_start:X})"
|
||||
|
||||
return f"({self.signal('PADDR')} >= 'h{addr_start:X} && {self.signal('PADDR')} <= 'h{addr_end:X})"
|
||||
|
||||
def get_address_decode_condition(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that evaluates to true when the
|
||||
address on the bus matches the address range of the given node.
|
||||
"""
|
||||
addr_pred = self.get_address_predicate(node)
|
||||
return addr_pred
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from systemrdl.node import AddressableNode
|
||||
|
||||
from ..base_cpuif import BaseCpuif
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{%- if cpuif.is_interface -%}
|
||||
{%- if cpuif.is_interface %}
|
||||
`ifndef SYNTHESIS
|
||||
initial begin
|
||||
assert_bad_addr_width: assert($bits({{cpuif.signal("PADDR")}}) >= {{ds.package_name}}::{{ds.module_name|upper}}_MIN_ADDR_WIDTH)
|
||||
@@ -7,55 +7,76 @@
|
||||
else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits({{cpuif.signal("PWDATA")}}), {{ds.package_name}}::{{ds.module_name|upper}}_DATA_WIDTH);
|
||||
end
|
||||
`endif
|
||||
{% endif -%}
|
||||
{%- endif %}
|
||||
|
||||
assign cpuif_req = {{cpuif.signal("PSELx")}};
|
||||
assign cpuif_wr_en = {{cpuif.signal("PWRITE")}};
|
||||
assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
|
||||
assign cpuif_rd_en = !{{cpuif.signal("PWRITE")}};
|
||||
|
||||
{%- for child in cpuif.addressable_children -%}
|
||||
{%- if child is array -%}
|
||||
for (genvar g_{{child.inst_name|lower}}_idx = 0; g_{{child.inst_name|lower}}_idx < N_{{child.inst_name|upper}}S; g_{{child.inst_name|lower}}_idx++) begin : g_passthrough_{{child.inst_name|lower}}
|
||||
assign {{self.signal("PCLK", child, f"g_{child.inst_name.lower()}_idx")}} = {{self.signal("PCLK")}};
|
||||
assign {{self.signal("PRESETn", child, f"g_{child.inst_name.lower()}_idx")}} = {{self.signal("PRESETn")}};
|
||||
assign {{self.signal("PSELx", child, f"g_{child.inst_name.lower()}_idx")}} = (cpuif_wr_sel[{{loop.index}}] || cpuif_rd_sel[{{loop.index}}]) ? 1'b1 : 1'b0;
|
||||
assign {{self.signal("PENABLE", child, f"g_{child.inst_name.lower()}_idx")}} = {{self.signal("PENABLE")}};
|
||||
assign {{self.signal("PWRITE", child, f"g_{child.inst_name.lower()}_idx")}} = (cpuif_wr_sel[{{loop.index}}]) ? 1'b1 : 1'b0;
|
||||
assign {{self.signal("PADDR", child, f"g_{child.inst_name.lower()}_idx")}} = {{cpuif.get_address_slice(cpuif_wr_addr, child)}};
|
||||
assign {{self.signal("PPROT", child, f"g_{child.inst_name.lower()}_idx")}} = {{self.signal("PPROT")}};
|
||||
assign {{self.signal("PWDATA", child, f"g_{child.inst_name.lower()}_idx")}} = cpuif_wr_data;
|
||||
assign {{self.signal("PSTRB", child, f"g_{child.inst_name.lower()}_idx")}} = {{self.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)}};
|
||||
end
|
||||
{%- else -%}
|
||||
assign {{self.signal("PCLK", child)}} = {{self.signal("PCLK")}};
|
||||
assign {{self.signal("PRESETn", child)}} = {{self.signal("PRESETn")}};
|
||||
assign {{self.signal("PSELx", child)}} = (cpuif_wr_sel[{{loop.index0}}] || cpuif_rd_sel[{{loop.index0}}]) ? 1'b1 : 1'b0;
|
||||
assign {{self.signal("PENABLE", child)}} = {{self.signal("PENABLE")}};
|
||||
assign {{self.signal("PWRITE", child)}} = cpuif_wr_sel[{{loop.index}}] ? 1'b1 : 1'b0;
|
||||
assign {{self.signal("PADDR", child)}} = {{cpuif.get_address_slice(cpuif_wr_addr, child)}};
|
||||
assign {{self.signal("PPROT", child)}} = {{self.signal("PPROT")}};
|
||||
assign {{self.signal("PWDATA", child)}} = cpuif_wr_data;
|
||||
assign {{self.signal("PSTRB", child)}} = {{self.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 -%}
|
||||
//--------------------------------------------------------------------------
|
||||
// Fanout CPU Bus interface signals
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// {%- 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
|
||||
//--------------------------------------------------------------------------
|
||||
always_comb begin
|
||||
{{cpuif.signal("PREADY")}} = 1'b0;
|
||||
{{cpuif.signal("PRDATA")}} = '0;
|
||||
{{cpuif.signal("PSLVERR")}} = 1'b0;
|
||||
|
||||
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
|
||||
|
||||
{%- 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
|
||||
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
|
||||
import jinja2 as jj
|
||||
from systemrdl.node import AddressableNode
|
||||
|
||||
from ..utils import clog2, is_pow2, roundup_pow2
|
||||
from ..utils import clog2, get_indexed_path, is_pow2, roundup_pow2
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..exporter import BusDecoderExporter
|
||||
@@ -83,6 +83,7 @@ class BaseCpuif:
|
||||
jj_env.filters["is_pow2"] = is_pow2 # type: ignore
|
||||
jj_env.filters["roundup_pow2"] = roundup_pow2 # type: ignore
|
||||
jj_env.filters["address_slice"] = self.get_address_slice # type: ignore
|
||||
jj_env.filters["get_path"] = lambda x: get_indexed_path(self.exp.ds.top_node, x, "i") # type: ignore
|
||||
|
||||
context = {
|
||||
"cpuif": self,
|
||||
@@ -92,33 +93,13 @@ class BaseCpuif:
|
||||
template = jj_env.get_template(self.template_path)
|
||||
return template.render(context)
|
||||
|
||||
def get_address_slice(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that extracts the address bits
|
||||
relevant to the given node.
|
||||
"""
|
||||
addr_mask = (1 << self.addr_width) - 1
|
||||
addr = node.absolute_address & addr_mask
|
||||
def get_address_slice(self, node: AddressableNode, cpuif_addr: str = "cpuif_addr") -> str:
|
||||
addr = node.raw_absolute_address - self.exp.ds.top_node.raw_absolute_address
|
||||
size = node.size
|
||||
if size == 0:
|
||||
raise ValueError(f"Node size '{size:#X}' must be greater than 0")
|
||||
if (addr % size) != 0:
|
||||
raise ValueError(f"Node address '{addr:#X}' must be aligned to its size '{size:#X}'")
|
||||
|
||||
# Calculate the address range of the node
|
||||
addr_start = addr
|
||||
addr_end = addr + size - 1
|
||||
if addr_end > addr_mask:
|
||||
raise ValueError("Node address range exceeds address width")
|
||||
addr_msb = clog2(addr + size) - 1
|
||||
addr_lsb = clog2(addr)
|
||||
|
||||
# Calculate the number of bits needed to represent the size
|
||||
size_bits = size.bit_length() - 1
|
||||
if size_bits < 0:
|
||||
size_bits = 0
|
||||
|
||||
if size_bits >= self.addr_width:
|
||||
# Node covers entire address space, so return full address
|
||||
return ""
|
||||
|
||||
# Extract the relevant bits from PADDR
|
||||
return f"[{self.addr_width - 1}:{size_bits}]"
|
||||
if addr_msb == addr_lsb:
|
||||
return f"{cpuif_addr}[{addr_lsb}]"
|
||||
return f"{cpuif_addr}[{addr_msb}:{addr_lsb}]"
|
||||
|
||||
Reference in New Issue
Block a user