uvx format
This commit is contained in:
@@ -26,9 +26,7 @@ class AddressDecode:
|
|||||||
assert s is not None
|
assert s is not None
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def get_access_strobe(
|
def get_access_strobe(self, node: RegNode | FieldNode, reduce_substrobes: bool = True) -> str:
|
||||||
self, node: RegNode | FieldNode, reduce_substrobes: bool = True
|
|
||||||
) -> str:
|
|
||||||
"""
|
"""
|
||||||
Returns the Verilog string that represents the register/field's access strobe.
|
Returns the Verilog string that represents the register/field's access strobe.
|
||||||
"""
|
"""
|
||||||
@@ -72,9 +70,7 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
|||||||
# List of address strides for each dimension
|
# List of address strides for each dimension
|
||||||
self._array_stride_stack: list[int] = []
|
self._array_stride_stack: list[int] = []
|
||||||
|
|
||||||
def enter_AddressableComponent(
|
def enter_AddressableComponent(self, node: "AddressableNode") -> WalkerAction | None:
|
||||||
self, node: "AddressableNode"
|
|
||||||
) -> WalkerAction | None:
|
|
||||||
super().enter_AddressableComponent(node)
|
super().enter_AddressableComponent(node)
|
||||||
|
|
||||||
if node.array_dimensions:
|
if node.array_dimensions:
|
||||||
@@ -103,9 +99,7 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
|||||||
expr_width = self.addr_decode.exp.ds.addr_width
|
expr_width = self.addr_decode.exp.ds.addr_width
|
||||||
a = str(
|
a = str(
|
||||||
SVInt(
|
SVInt(
|
||||||
node.raw_absolute_address
|
node.raw_absolute_address - self.addr_decode.top_node.raw_absolute_address + subword_offset,
|
||||||
- self.addr_decode.top_node.raw_absolute_address
|
|
||||||
+ subword_offset,
|
|
||||||
expr_width,
|
expr_width,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
from ..base_cpuif import BaseCpuif
|
from ..base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
@@ -17,9 +18,7 @@ class APB3Cpuif(BaseCpuif):
|
|||||||
@property
|
@property
|
||||||
def port_declaration(self) -> str:
|
def port_declaration(self) -> str:
|
||||||
slave_ports: list[str] = ["apb3_intf.slave s_apb"]
|
slave_ports: list[str] = ["apb3_intf.slave s_apb"]
|
||||||
master_ports: list[str] = list(
|
master_ports: list[str] = list(map(self._port_declaration, self.addressable_children))
|
||||||
map(self._port_declaration, self.addressable_children)
|
|
||||||
)
|
|
||||||
|
|
||||||
return ",\n".join(slave_ports + master_ports)
|
return ",\n".join(slave_ports + master_ports)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
from ..base_cpuif import BaseCpuif
|
from ..base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,85 +31,3 @@ assign {{self.signal("PADDR", child)}} = {{self.signal("PADDR")}} [{{child.add
|
|||||||
assign {{self.signal("PWDATA", child)}} = {{self.signal("PWDATA")}};
|
assign {{self.signal("PWDATA", child)}} = {{self.signal("PWDATA")}};
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
|
||||||
//======================================================
|
|
||||||
// Address Decode Logic
|
|
||||||
//======================================================
|
|
||||||
always_comb begin
|
|
||||||
// Default all PSELx signals to 0
|
|
||||||
{%- for child in cpuif.addressable_children -%}
|
|
||||||
{%- if child is array -%}
|
|
||||||
for (int {{child.inst_name|lower}}_idx = 0; {{child.inst_name|lower}}_idx < N_{{child.inst_name|upper}}S; {{child.inst_name|lower}}_idx++) begin
|
|
||||||
{{self.signal("PSELx", child, f"{child.inst_name.lower()}_idx")}} = 1'b0;
|
|
||||||
end
|
|
||||||
{%- else -%}
|
|
||||||
{{self.signal("PSELx", child)}} = 1'b0;
|
|
||||||
{%- endif -%}
|
|
||||||
{%- endfor -%}
|
|
||||||
|
|
||||||
if ({{self.signal("PSELx")}}) begin
|
|
||||||
{%- for child in cpuif.addressable_children -%}
|
|
||||||
{%- if loop.first -%}
|
|
||||||
if ({{cpuif.get_address_decode_condition(child)}}) begin
|
|
||||||
{%- else -%}
|
|
||||||
end else if ({{cpuif.get_address_decode_condition(child)}}) begin
|
|
||||||
{%- endif -%}
|
|
||||||
// Address matched for {{child.inst_name}}
|
|
||||||
{%- if child is array -%}
|
|
||||||
for (genvar {{child.inst_name|lower}}_idx = 0; {{child.inst_name|lower}}_idx < N_{{child.inst_name|upper}}S; {{child.inst_name|lower}}_idx++) begin
|
|
||||||
{{self.signal("PSELx", child, f"{child.inst_name.lower()}_idx")}} = 1'b1;
|
|
||||||
end
|
|
||||||
{%- else -%}
|
|
||||||
{{self.signal("PSELx", child)}} = 1'b1;
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if loop.last -%}
|
|
||||||
end else begin
|
|
||||||
// No address matched
|
|
||||||
{%- endif -%}
|
|
||||||
{%- endfor -%}
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
// PSELx is low, nothing to do
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//======================================================
|
|
||||||
// Read Data Mux
|
|
||||||
//======================================================
|
|
||||||
always_comb begin
|
|
||||||
// Default read data to 0
|
|
||||||
{{self.signal("PRDATA")}} = '0;
|
|
||||||
{{self.signal("PREADY")}} = 1'b1;
|
|
||||||
{{self.signal("PSLVERR")}} = 1'b0;
|
|
||||||
|
|
||||||
if ({{self.signal("PSELx")}} && !{{self.signal("PWRITE")}} && {{self.signal("PENABLE")}}) begin
|
|
||||||
{%- for child in cpuif.addressable_children -%}
|
|
||||||
{%- if loop.first -%}
|
|
||||||
if ({{cpuif.get_address_decode_condition(child)}}) begin
|
|
||||||
{%- else -%}
|
|
||||||
end else if ({{cpuif.get_address_decode_condition(child)}}) begin
|
|
||||||
{%- endif -%}
|
|
||||||
// Address matched for {{child.inst_name}}
|
|
||||||
{%- if child is array -%}
|
|
||||||
for (genvar {{child.inst_name|lower}}_idx = 0; {{child.inst_name|lower}}_idx < N_{{child.inst_name|upper}}S; {{child.inst_name|lower}}_idx++) begin
|
|
||||||
{{self.signal("PRDATA")}} = {{self.signal("PRDATA", child, f"{child.inst_name.lower()}_idx")}};
|
|
||||||
{{self.signal("PREADY")}} = {{self.signal("PREADY", child, f"{child.inst_name.lower()}_idx")}};
|
|
||||||
{{self.signal("PSLVERR")}} = {{self.signal("PSLVERR", child, f"{child.inst_name.lower()}_idx")}};
|
|
||||||
end
|
|
||||||
{%- else -%}
|
|
||||||
{{self.signal("PRDATA")}} = {{self.signal("PRDATA", child)}};
|
|
||||||
{{self.signal("PREADY")}} = {{self.signal("PREADY", child)}};
|
|
||||||
{{self.signal("PSLVERR")}} = {{self.signal("PSLVERR", child)}};
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if loop.last -%}
|
|
||||||
end else begin
|
|
||||||
// No address matched
|
|
||||||
{{self.signal("PRDATA")}} = {'hdeadbeef}[{{ds.data_width - 1}}:0]; // Indicate error on no match
|
|
||||||
{{self.signal("PSLVERR")}} = 1'b1; // Indicate error on no match
|
|
||||||
end
|
|
||||||
{%- endif -%}
|
|
||||||
{%- endfor -%}
|
|
||||||
end else begin
|
|
||||||
// Not a read transfer, nothing to do
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -18,9 +18,7 @@ class APB4Cpuif(BaseCpuif):
|
|||||||
def port_declaration(self) -> str:
|
def port_declaration(self) -> str:
|
||||||
"""Returns the port declaration for the APB4 interface."""
|
"""Returns the port declaration for the APB4 interface."""
|
||||||
slave_ports: list[str] = ["apb4_intf.slave s_apb"]
|
slave_ports: list[str] = ["apb4_intf.slave s_apb"]
|
||||||
master_ports: list[str] = list(
|
master_ports: list[str] = list(map(self._port_declaration, self.addressable_children))
|
||||||
map(self._port_declaration, self.addressable_children)
|
|
||||||
)
|
|
||||||
|
|
||||||
return ",\n".join(slave_ports + master_ports)
|
return ",\n".join(slave_ports + master_ports)
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ class Dereferencer:
|
|||||||
def top_node(self) -> AddrmapNode:
|
def top_node(self) -> AddrmapNode:
|
||||||
return self.exp.ds.top_node
|
return self.exp.ds.top_node
|
||||||
|
|
||||||
def get_access_strobe(
|
def get_access_strobe(self, obj: RegNode | FieldNode, reduce_substrobes: bool = True) -> str:
|
||||||
self, obj: RegNode | FieldNode, reduce_substrobes: bool = True
|
|
||||||
) -> str:
|
|
||||||
"""
|
"""
|
||||||
Returns the Verilog string that represents the register's access strobe
|
Returns the Verilog string that represents the register's access strobe
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ class BusDecoderExporter:
|
|||||||
def __init__(self, **kwargs: Any) -> None:
|
def __init__(self, **kwargs: Any) -> None:
|
||||||
# Check for stray kwargs
|
# Check for stray kwargs
|
||||||
if kwargs:
|
if kwargs:
|
||||||
raise TypeError(
|
raise TypeError(f"got an unexpected keyword argument '{list(kwargs.keys())[0]}'")
|
||||||
f"got an unexpected keyword argument '{list(kwargs.keys())[0]}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
loader = jj.ChoiceLoader(
|
loader = jj.ChoiceLoader(
|
||||||
[
|
[
|
||||||
@@ -49,9 +47,7 @@ class BusDecoderExporter:
|
|||||||
undefined=jj.StrictUndefined,
|
undefined=jj.StrictUndefined,
|
||||||
)
|
)
|
||||||
|
|
||||||
def export(
|
def export(self, node: RootNode | AddrmapNode, output_dir: str, **kwargs: Any) -> None:
|
||||||
self, node: RootNode | AddrmapNode, output_dir: str, **kwargs: Any
|
|
||||||
) -> None:
|
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
@@ -88,9 +84,7 @@ class BusDecoderExporter:
|
|||||||
|
|
||||||
# Check for stray kwargs
|
# Check for stray kwargs
|
||||||
if kwargs:
|
if kwargs:
|
||||||
raise TypeError(
|
raise TypeError(f"got an unexpected keyword argument '{list(kwargs.keys())[0]}'")
|
||||||
f"got an unexpected keyword argument '{list(kwargs.keys())[0]}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Construct exporter components
|
# Construct exporter components
|
||||||
self.cpuif = cpuif_cls(self)
|
self.cpuif = cpuif_cls(self)
|
||||||
@@ -139,12 +133,8 @@ class DesignState:
|
|||||||
# Extract compiler args
|
# Extract compiler args
|
||||||
# ------------------------
|
# ------------------------
|
||||||
self.reuse_hwif_typedefs: bool = kwargs.pop("reuse_hwif_typedefs", True)
|
self.reuse_hwif_typedefs: bool = kwargs.pop("reuse_hwif_typedefs", True)
|
||||||
self.module_name: str = kwargs.pop("module_name", None) or kwf(
|
self.module_name: str = kwargs.pop("module_name", None) or kwf(self.top_node.inst_name)
|
||||||
self.top_node.inst_name
|
self.package_name: str = kwargs.pop("package_name", None) or (self.module_name + "_pkg")
|
||||||
)
|
|
||||||
self.package_name: str = kwargs.pop("package_name", None) or (
|
|
||||||
self.module_name + "_pkg"
|
|
||||||
)
|
|
||||||
user_addr_width: int | None = kwargs.pop("address_width", None)
|
user_addr_width: int | None = kwargs.pop("address_width", None)
|
||||||
|
|
||||||
self.cpuif_unroll: bool = kwargs.pop("cpuif_unroll", False)
|
self.cpuif_unroll: bool = kwargs.pop("cpuif_unroll", False)
|
||||||
@@ -172,9 +162,7 @@ class DesignState:
|
|||||||
|
|
||||||
# ------------------------
|
# ------------------------
|
||||||
# Min address width encloses the total size AND at least 1 useful address bit
|
# Min address width encloses the total size AND at least 1 useful address bit
|
||||||
self.addr_width = max(
|
self.addr_width = max(clog2(self.top_node.size), clog2(self.cpuif_data_width // 8) + 1)
|
||||||
clog2(self.top_node.size), clog2(self.cpuif_data_width // 8) + 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if user_addr_width is not None:
|
if user_addr_width is not None:
|
||||||
if user_addr_width < self.addr_width:
|
if user_addr_width < self.addr_width:
|
||||||
|
|||||||
@@ -82,9 +82,7 @@ class RDLForLoopGenerator(ForLoopGenerator, RDLListener):
|
|||||||
walker.walk(node, self, skip_top=True)
|
walker.walk(node, self, skip_top=True)
|
||||||
return self.finish()
|
return self.finish()
|
||||||
|
|
||||||
def enter_AddressableComponent(
|
def enter_AddressableComponent(self, node: "AddressableNode") -> WalkerAction | None:
|
||||||
self, node: "AddressableNode"
|
|
||||||
) -> WalkerAction | None:
|
|
||||||
if not node.array_dimensions:
|
if not node.array_dimensions:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,253 @@
|
|||||||
|
|
||||||
# All SystemVerilog 2017 keywords
|
# All SystemVerilog 2017 keywords
|
||||||
SV_KEYWORDS = {
|
SV_KEYWORDS = {
|
||||||
'accept_on', 'alias', 'always', 'always_comb', 'always_ff', 'always_latch',
|
"accept_on",
|
||||||
'and', 'assert', 'assign', 'assume', 'automatic', 'before', 'begin', 'bind',
|
"alias",
|
||||||
'bins', 'binsof', 'bit', 'break', 'buf', 'bufif0', 'bufif1', 'byte', 'case',
|
"always",
|
||||||
'casex', 'casez', 'cell', 'chandle', 'checker', 'class', 'clocking', 'cmos',
|
"always_comb",
|
||||||
'config', 'const', 'constraint', 'context', 'continue', 'cover', 'covergroup',
|
"always_ff",
|
||||||
'coverpoint', 'cross', 'deassign', 'default', 'defparam', 'design', 'disable',
|
"always_latch",
|
||||||
'dist', 'do', 'edge', 'else', 'end', 'endcase', 'endchecker', 'endclass',
|
"and",
|
||||||
'endclocking', 'endconfig', 'endfunction', 'endgenerate', 'endgroup',
|
"assert",
|
||||||
'endinterface', 'endmodule', 'endpackage', 'endprimitive', 'endprogram',
|
"assign",
|
||||||
'endproperty', 'endspecify', 'endsequence', 'endtable', 'endtask', 'enum',
|
"assume",
|
||||||
'event', 'eventually', 'expect', 'export', 'extends', 'extern', 'final',
|
"automatic",
|
||||||
'first_match', 'for', 'force', 'foreach', 'forever', 'fork', 'forkjoin',
|
"before",
|
||||||
'function', 'generate', 'genvar', 'global', 'highz0', 'highz1', 'if', 'iff',
|
"begin",
|
||||||
'ifnone', 'ignore_bins', 'illegal_bins', 'implements', 'implies', 'import',
|
"bind",
|
||||||
'incdir', 'include', 'initial', 'inout', 'input', 'inside', 'instance',
|
"bins",
|
||||||
'int', 'integer', 'interconnect', 'interface', 'intersect', 'join',
|
"binsof",
|
||||||
'join_any', 'join_none', 'large', 'let', 'liblist', 'library', 'local',
|
"bit",
|
||||||
'localparam', 'logic', 'longint', 'macromodule', 'matches', 'medium',
|
"break",
|
||||||
'modport', 'module', 'nand', 'negedge', 'nettype', 'new', 'nexttime', 'nmos',
|
"buf",
|
||||||
'nor', 'noshowcancelled', 'not', 'notif0', 'notif1', 'null', 'or', 'output',
|
"bufif0",
|
||||||
'package', 'packed', 'parameter', 'pmos', 'posedge', 'primitive', 'priority',
|
"bufif1",
|
||||||
'program', 'property', 'protected', 'pull0', 'pull1', 'pulldown', 'pullup',
|
"byte",
|
||||||
'pulsestyle_ondetect', 'pulsestyle_onevent', 'pure', 'rand', 'randc',
|
"case",
|
||||||
'randcase', 'randsequence', 'rcmos', 'real', 'realtime', 'ref', 'reg',
|
"casex",
|
||||||
'reject_on', 'release', 'repeat', 'restrict', 'return', 'rnmos', 'rpmos',
|
"casez",
|
||||||
'rtran', 'rtranif0', 'rtranif1', 's_always', 's_eventually', 's_nexttime',
|
"cell",
|
||||||
's_until', 's_until_with', 'scalared', 'sequence', 'shortint', 'shortreal',
|
"chandle",
|
||||||
'showcancelled', 'signed', 'small', 'soft', 'solve', 'specify', 'specparam',
|
"checker",
|
||||||
'static', 'string', 'strong', 'strong0', 'strong1', 'struct', 'super',
|
"class",
|
||||||
'supply0', 'supply1', 'sync_accept_on', 'sync_reject_on', 'table', 'tagged',
|
"clocking",
|
||||||
'task', 'this', 'throughout', 'time', 'timeprecision', 'timeunit', 'tran',
|
"cmos",
|
||||||
'tranif0', 'tranif1', 'tri', 'tri0', 'tri1', 'triand', 'trior', 'trireg',
|
"config",
|
||||||
'type', 'typedef', 'union', 'unique', 'unique0', 'unsigned', 'until',
|
"const",
|
||||||
'until_with', 'untyped', 'use', 'uwire', 'var', 'vectored', 'virtual', 'void',
|
"constraint",
|
||||||
'wait', 'wait_order', 'wand', 'weak', 'weak0', 'weak1', 'while', 'wildcard',
|
"context",
|
||||||
'wire', 'with', 'within', 'wor', 'xnor', 'xor'
|
"continue",
|
||||||
|
"cover",
|
||||||
|
"covergroup",
|
||||||
|
"coverpoint",
|
||||||
|
"cross",
|
||||||
|
"deassign",
|
||||||
|
"default",
|
||||||
|
"defparam",
|
||||||
|
"design",
|
||||||
|
"disable",
|
||||||
|
"dist",
|
||||||
|
"do",
|
||||||
|
"edge",
|
||||||
|
"else",
|
||||||
|
"end",
|
||||||
|
"endcase",
|
||||||
|
"endchecker",
|
||||||
|
"endclass",
|
||||||
|
"endclocking",
|
||||||
|
"endconfig",
|
||||||
|
"endfunction",
|
||||||
|
"endgenerate",
|
||||||
|
"endgroup",
|
||||||
|
"endinterface",
|
||||||
|
"endmodule",
|
||||||
|
"endpackage",
|
||||||
|
"endprimitive",
|
||||||
|
"endprogram",
|
||||||
|
"endproperty",
|
||||||
|
"endspecify",
|
||||||
|
"endsequence",
|
||||||
|
"endtable",
|
||||||
|
"endtask",
|
||||||
|
"enum",
|
||||||
|
"event",
|
||||||
|
"eventually",
|
||||||
|
"expect",
|
||||||
|
"export",
|
||||||
|
"extends",
|
||||||
|
"extern",
|
||||||
|
"final",
|
||||||
|
"first_match",
|
||||||
|
"for",
|
||||||
|
"force",
|
||||||
|
"foreach",
|
||||||
|
"forever",
|
||||||
|
"fork",
|
||||||
|
"forkjoin",
|
||||||
|
"function",
|
||||||
|
"generate",
|
||||||
|
"genvar",
|
||||||
|
"global",
|
||||||
|
"highz0",
|
||||||
|
"highz1",
|
||||||
|
"if",
|
||||||
|
"iff",
|
||||||
|
"ifnone",
|
||||||
|
"ignore_bins",
|
||||||
|
"illegal_bins",
|
||||||
|
"implements",
|
||||||
|
"implies",
|
||||||
|
"import",
|
||||||
|
"incdir",
|
||||||
|
"include",
|
||||||
|
"initial",
|
||||||
|
"inout",
|
||||||
|
"input",
|
||||||
|
"inside",
|
||||||
|
"instance",
|
||||||
|
"int",
|
||||||
|
"integer",
|
||||||
|
"interconnect",
|
||||||
|
"interface",
|
||||||
|
"intersect",
|
||||||
|
"join",
|
||||||
|
"join_any",
|
||||||
|
"join_none",
|
||||||
|
"large",
|
||||||
|
"let",
|
||||||
|
"liblist",
|
||||||
|
"library",
|
||||||
|
"local",
|
||||||
|
"localparam",
|
||||||
|
"logic",
|
||||||
|
"longint",
|
||||||
|
"macromodule",
|
||||||
|
"matches",
|
||||||
|
"medium",
|
||||||
|
"modport",
|
||||||
|
"module",
|
||||||
|
"nand",
|
||||||
|
"negedge",
|
||||||
|
"nettype",
|
||||||
|
"new",
|
||||||
|
"nexttime",
|
||||||
|
"nmos",
|
||||||
|
"nor",
|
||||||
|
"noshowcancelled",
|
||||||
|
"not",
|
||||||
|
"notif0",
|
||||||
|
"notif1",
|
||||||
|
"null",
|
||||||
|
"or",
|
||||||
|
"output",
|
||||||
|
"package",
|
||||||
|
"packed",
|
||||||
|
"parameter",
|
||||||
|
"pmos",
|
||||||
|
"posedge",
|
||||||
|
"primitive",
|
||||||
|
"priority",
|
||||||
|
"program",
|
||||||
|
"property",
|
||||||
|
"protected",
|
||||||
|
"pull0",
|
||||||
|
"pull1",
|
||||||
|
"pulldown",
|
||||||
|
"pullup",
|
||||||
|
"pulsestyle_ondetect",
|
||||||
|
"pulsestyle_onevent",
|
||||||
|
"pure",
|
||||||
|
"rand",
|
||||||
|
"randc",
|
||||||
|
"randcase",
|
||||||
|
"randsequence",
|
||||||
|
"rcmos",
|
||||||
|
"real",
|
||||||
|
"realtime",
|
||||||
|
"ref",
|
||||||
|
"reg",
|
||||||
|
"reject_on",
|
||||||
|
"release",
|
||||||
|
"repeat",
|
||||||
|
"restrict",
|
||||||
|
"return",
|
||||||
|
"rnmos",
|
||||||
|
"rpmos",
|
||||||
|
"rtran",
|
||||||
|
"rtranif0",
|
||||||
|
"rtranif1",
|
||||||
|
"s_always",
|
||||||
|
"s_eventually",
|
||||||
|
"s_nexttime",
|
||||||
|
"s_until",
|
||||||
|
"s_until_with",
|
||||||
|
"scalared",
|
||||||
|
"sequence",
|
||||||
|
"shortint",
|
||||||
|
"shortreal",
|
||||||
|
"showcancelled",
|
||||||
|
"signed",
|
||||||
|
"small",
|
||||||
|
"soft",
|
||||||
|
"solve",
|
||||||
|
"specify",
|
||||||
|
"specparam",
|
||||||
|
"static",
|
||||||
|
"string",
|
||||||
|
"strong",
|
||||||
|
"strong0",
|
||||||
|
"strong1",
|
||||||
|
"struct",
|
||||||
|
"super",
|
||||||
|
"supply0",
|
||||||
|
"supply1",
|
||||||
|
"sync_accept_on",
|
||||||
|
"sync_reject_on",
|
||||||
|
"table",
|
||||||
|
"tagged",
|
||||||
|
"task",
|
||||||
|
"this",
|
||||||
|
"throughout",
|
||||||
|
"time",
|
||||||
|
"timeprecision",
|
||||||
|
"timeunit",
|
||||||
|
"tran",
|
||||||
|
"tranif0",
|
||||||
|
"tranif1",
|
||||||
|
"tri",
|
||||||
|
"tri0",
|
||||||
|
"tri1",
|
||||||
|
"triand",
|
||||||
|
"trior",
|
||||||
|
"trireg",
|
||||||
|
"type",
|
||||||
|
"typedef",
|
||||||
|
"union",
|
||||||
|
"unique",
|
||||||
|
"unique0",
|
||||||
|
"unsigned",
|
||||||
|
"until",
|
||||||
|
"until_with",
|
||||||
|
"untyped",
|
||||||
|
"use",
|
||||||
|
"uwire",
|
||||||
|
"var",
|
||||||
|
"vectored",
|
||||||
|
"virtual",
|
||||||
|
"void",
|
||||||
|
"wait",
|
||||||
|
"wait_order",
|
||||||
|
"wand",
|
||||||
|
"weak",
|
||||||
|
"weak0",
|
||||||
|
"weak1",
|
||||||
|
"while",
|
||||||
|
"wildcard",
|
||||||
|
"wire",
|
||||||
|
"with",
|
||||||
|
"within",
|
||||||
|
"wor",
|
||||||
|
"xnor",
|
||||||
|
"xor",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ module {{ds.module_name}}
|
|||||||
// Default all read select signals to 0
|
// Default all read select signals to 0
|
||||||
cpuif_rd_sel = '0;
|
cpuif_rd_sel = '0;
|
||||||
|
|
||||||
|
|
||||||
if (cpuif_req && !cpuif_wr_en) begin
|
if (cpuif_req && !cpuif_wr_en) begin
|
||||||
// A read request is pending
|
// A read request is pending
|
||||||
{%- for child in cpuif.addressable_children -%}
|
{%- for child in cpuif.addressable_children -%}
|
||||||
|
|||||||
@@ -6,18 +6,20 @@ from systemrdl.component import Field
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from systemrdl.node import Node
|
from systemrdl.node import Node
|
||||||
|
|
||||||
|
|
||||||
class ReadSwacc(UDPDefinition):
|
class ReadSwacc(UDPDefinition):
|
||||||
name = "rd_swacc"
|
name = "rd_swacc"
|
||||||
valid_components = {Field}
|
valid_components = {Field}
|
||||||
valid_type = bool
|
valid_type = bool
|
||||||
|
|
||||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class WriteSwacc(UDPDefinition):
|
class WriteSwacc(UDPDefinition):
|
||||||
name = "wr_swacc"
|
name = "wr_swacc"
|
||||||
valid_components = {Field}
|
valid_components = {Field}
|
||||||
valid_type = bool
|
valid_type = bool
|
||||||
|
|
||||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -20,16 +20,12 @@ class _FixedpointWidth(UDPDefinition):
|
|||||||
|
|
||||||
# incompatible with "counter" fields
|
# incompatible with "counter" fields
|
||||||
if node.get_property("counter"):
|
if node.get_property("counter"):
|
||||||
self.msg.error(
|
self.msg.error("Fixed-point representations are not supported for counter fields.", prop_ref)
|
||||||
"Fixed-point representations are not supported for counter fields.",
|
|
||||||
prop_ref
|
|
||||||
)
|
|
||||||
|
|
||||||
# incompatible with "encode" fields
|
# incompatible with "encode" fields
|
||||||
if node.get_property("encode") is not None:
|
if node.get_property("encode") is not None:
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"Fixed-point representations are not supported for fields encoded as an enum.",
|
"Fixed-point representations are not supported for fields encoded as an enum.", prop_ref
|
||||||
prop_ref
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# ensure node width = fracwidth + intwidth
|
# ensure node width = fracwidth + intwidth
|
||||||
@@ -37,7 +33,7 @@ class _FixedpointWidth(UDPDefinition):
|
|||||||
self.msg.error(
|
self.msg.error(
|
||||||
f"Number of integer bits ({intwidth}) plus number of fractional bits ({fracwidth})"
|
f"Number of integer bits ({intwidth}) plus number of fractional bits ({fracwidth})"
|
||||||
f" must be equal to the width of the component ({node.width}).",
|
f" must be equal to the width of the component ({node.width}).",
|
||||||
prop_ref
|
prop_ref,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ class xBufferTrigger(UDPDefinition):
|
|||||||
|
|
||||||
if value is NoValue:
|
if value is NoValue:
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"Double-buffer trigger property is missing a value assignment",
|
"Double-buffer trigger property is missing a value assignment", self.get_src_ref(node)
|
||||||
self.get_src_ref(node)
|
|
||||||
)
|
)
|
||||||
elif isinstance(value, VectorNode):
|
elif isinstance(value, VectorNode):
|
||||||
# Trigger can reference a vector, but only if it is a single-bit
|
# Trigger can reference a vector, but only if it is a single-bit
|
||||||
@@ -25,17 +24,19 @@ class xBufferTrigger(UDPDefinition):
|
|||||||
self.msg.error(
|
self.msg.error(
|
||||||
"%s '%s' references %s '%s' but its width is not 1"
|
"%s '%s' references %s '%s' but its width is not 1"
|
||||||
% (
|
% (
|
||||||
type(node.inst).__name__.lower(), node.inst_name,
|
type(node.inst).__name__.lower(),
|
||||||
type(value.inst).__name__.lower(), value.inst_name
|
node.inst_name,
|
||||||
|
type(value.inst).__name__.lower(),
|
||||||
|
value.inst_name,
|
||||||
),
|
),
|
||||||
self.get_src_ref(node)
|
self.get_src_ref(node),
|
||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(value, SignalNode):
|
if isinstance(value, SignalNode):
|
||||||
if not value.get_property('activehigh') and not value.get_property('activelow'):
|
if not value.get_property("activehigh") and not value.get_property("activelow"):
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"Trigger was asigned a signal, but it does not specify whether it is activehigh/activelow",
|
"Trigger was asigned a signal, but it does not specify whether it is activehigh/activelow",
|
||||||
self.get_src_ref(node)
|
self.get_src_ref(node),
|
||||||
)
|
)
|
||||||
|
|
||||||
elif isinstance(value, PropertyReference) and value.width is not None:
|
elif isinstance(value, PropertyReference) and value.width is not None:
|
||||||
@@ -44,10 +45,12 @@ class xBufferTrigger(UDPDefinition):
|
|||||||
self.msg.error(
|
self.msg.error(
|
||||||
"%s '%s' references property '%s->%s' but its width is not 1"
|
"%s '%s' references property '%s->%s' but its width is not 1"
|
||||||
% (
|
% (
|
||||||
type(node.inst).__name__.lower(), node.inst_name,
|
type(node.inst).__name__.lower(),
|
||||||
value.node.inst_name, value.name,
|
node.inst_name,
|
||||||
|
value.node.inst_name,
|
||||||
|
value.name,
|
||||||
),
|
),
|
||||||
self.get_src_ref(node)
|
self.get_src_ref(node),
|
||||||
)
|
)
|
||||||
elif isinstance(value, RegNode):
|
elif isinstance(value, RegNode):
|
||||||
# Trigger can reference a register, which implies access of the
|
# Trigger can reference a register, which implies access of the
|
||||||
@@ -60,34 +63,35 @@ class xBufferTrigger(UDPDefinition):
|
|||||||
self.msg.error(
|
self.msg.error(
|
||||||
"Reference to a %s component is incompatible with the '%s' property."
|
"Reference to a %s component is incompatible with the '%s' property."
|
||||||
% (type(node.inst).__name__.lower(), self.name),
|
% (type(node.inst).__name__.lower(), self.name),
|
||||||
self.get_src_ref(node)
|
self.get_src_ref(node),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
class BufferWrites(UDPDefinition):
|
class BufferWrites(UDPDefinition):
|
||||||
name = "buffer_writes"
|
name = "buffer_writes"
|
||||||
valid_components = {Reg}
|
valid_components = {Reg}
|
||||||
valid_type = bool
|
valid_type = bool
|
||||||
|
|
||||||
def validate(self, node: 'Node', value: Any) -> None:
|
def validate(self, node: "Node", value: Any) -> None:
|
||||||
assert isinstance(node, RegNode)
|
assert isinstance(node, RegNode)
|
||||||
if value:
|
if value:
|
||||||
if not node.has_sw_writable:
|
if not node.has_sw_writable:
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"'buffer_writes' is set to true, but this register does not contain any writable fields.",
|
"'buffer_writes' is set to true, but this register does not contain any writable fields.",
|
||||||
self.get_src_ref(node)
|
self.get_src_ref(node),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class WBufferTrigger(xBufferTrigger):
|
class WBufferTrigger(xBufferTrigger):
|
||||||
name = "wbuffer_trigger"
|
name = "wbuffer_trigger"
|
||||||
|
|
||||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
# If buffering is enabled, trigger is the register itself
|
# If buffering is enabled, trigger is the register itself
|
||||||
if node.get_property('buffer_writes'):
|
if node.get_property("buffer_writes"):
|
||||||
return node
|
return node
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -107,24 +111,24 @@ class BufferReads(UDPDefinition):
|
|||||||
valid_components = {Reg}
|
valid_components = {Reg}
|
||||||
valid_type = bool
|
valid_type = bool
|
||||||
|
|
||||||
def validate(self, node: 'Node', value: Any) -> None:
|
def validate(self, node: "Node", value: Any) -> None:
|
||||||
assert isinstance(node, RegNode)
|
assert isinstance(node, RegNode)
|
||||||
if value:
|
if value:
|
||||||
if not node.has_sw_readable:
|
if not node.has_sw_readable:
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"'buffer_reads' is set to true, but this register does not contain any readable fields.",
|
"'buffer_reads' is set to true, but this register does not contain any readable fields.",
|
||||||
self.get_src_ref(node)
|
self.get_src_ref(node),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class RBufferTrigger(xBufferTrigger):
|
class RBufferTrigger(xBufferTrigger):
|
||||||
name = "rbuffer_trigger"
|
name = "rbuffer_trigger"
|
||||||
|
|
||||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
# If buffering is enabled, trigger is the register itself
|
# If buffering is enabled, trigger is the register itself
|
||||||
if node.get_property('buffer_reads'):
|
if node.get_property("buffer_reads"):
|
||||||
return node
|
return node
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ class IsSigned(UDPDefinition):
|
|||||||
if value and node.get_property("counter"):
|
if value and node.get_property("counter"):
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"The property is_signed=true is not supported for counter fields.",
|
"The property is_signed=true is not supported for counter fields.",
|
||||||
node.inst.property_src_ref["is_signed"]
|
node.inst.property_src_ref["is_signed"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# incompatible with "encode" fields
|
# incompatible with "encode" fields
|
||||||
if value and node.get_property("encode") is not None:
|
if value and node.get_property("encode") is not None:
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"The property is_signed=true is not supported for fields encoded as an enum.",
|
"The property is_signed=true is not supported for fields encoded as an enum.",
|
||||||
node.inst.property_src_ref["is_signed"]
|
node.inst.property_src_ref["is_signed"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_unassigned_default(self, node: "Node") -> Any:
|
def get_unassigned_default(self, node: "Node") -> Any:
|
||||||
|
|||||||
@@ -49,9 +49,7 @@ class DesignValidator(RDLListener):
|
|||||||
if isinstance(value, PropertyReference):
|
if isinstance(value, PropertyReference):
|
||||||
src_ref = value.src_ref
|
src_ref = value.src_ref
|
||||||
else:
|
else:
|
||||||
src_ref = node.inst.property_src_ref.get(
|
src_ref = node.inst.property_src_ref.get(prop_name, node.inst.inst_src_ref)
|
||||||
prop_name, node.inst.inst_src_ref
|
|
||||||
)
|
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"Property is assigned a reference that points to a component not internal to the busdecoder being exported.",
|
"Property is assigned a reference that points to a component not internal to the busdecoder being exported.",
|
||||||
src_ref,
|
src_ref,
|
||||||
@@ -125,9 +123,9 @@ class DesignValidator(RDLListener):
|
|||||||
def enter_Field(self, node: "FieldNode") -> None:
|
def enter_Field(self, node: "FieldNode") -> None:
|
||||||
parent_accesswidth = node.parent.get_property("accesswidth")
|
parent_accesswidth = node.parent.get_property("accesswidth")
|
||||||
parent_regwidth = node.parent.get_property("regwidth")
|
parent_regwidth = node.parent.get_property("regwidth")
|
||||||
if (parent_accesswidth < parent_regwidth) and (
|
if (parent_accesswidth < parent_regwidth) and (node.lsb // parent_accesswidth) != (
|
||||||
node.lsb // parent_accesswidth
|
node.msb // parent_accesswidth
|
||||||
) != (node.msb // parent_accesswidth):
|
):
|
||||||
# field spans multiple sub-words
|
# field spans multiple sub-words
|
||||||
|
|
||||||
if node.is_sw_writable and not node.parent.get_property("buffer_writes"):
|
if node.is_sw_writable and not node.parent.get_property("buffer_writes"):
|
||||||
@@ -141,9 +139,7 @@ class DesignValidator(RDLListener):
|
|||||||
node.inst.inst_src_ref,
|
node.inst.inst_src_ref,
|
||||||
)
|
)
|
||||||
|
|
||||||
if node.get_property("onread") is not None and not node.parent.get_property(
|
if node.get_property("onread") is not None and not node.parent.get_property("buffer_reads"):
|
||||||
"buffer_reads"
|
|
||||||
):
|
|
||||||
# ... is modified by an onread action without the atomicity of read buffering
|
# ... is modified by an onread action without the atomicity of read buffering
|
||||||
# Enforce 10.6.1-f
|
# Enforce 10.6.1-f
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
|
|||||||
Reference in New Issue
Block a user