Skip to content

Commit

Permalink
Implement new SVInt object to defer literal expansion and allow bit-f…
Browse files Browse the repository at this point in the history
…iddling operations. Fix invalid bit-slicing of literals if field reset value is a constant. #71
  • Loading branch information
amykyta3 committed Oct 25, 2023
1 parent b5b1ba7 commit 62518b3
Show file tree
Hide file tree
Showing 14 changed files with 147 additions and 62 deletions.
11 changes: 6 additions & 5 deletions src/peakrdl_regblock/addr_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from systemrdl.node import FieldNode, RegNode
from systemrdl.walker import WalkerAction

from .utils import get_indexed_path, get_sv_int
from .utils import get_indexed_path
from .struct_generator import RDLStructGenerator
from .forloop_generator import RDLForLoopGenerator
from .identifier_filter import kw_filter as kwf
from .sv_int import SVInt

if TYPE_CHECKING:
from .exporter import RegblockExporter
Expand Down Expand Up @@ -149,7 +150,7 @@ def enter_AddressableComponent(self, node: 'AddressableNode') -> Optional[Walker
# Is an external block
addr_str = self._get_address_str(node)
strb = self.addr_decode.get_external_block_access_strobe(node)
rhs = f"cpuif_req_masked & (cpuif_addr >= {addr_str}) & (cpuif_addr <= {addr_str} + {get_sv_int(node.size - 1, self.addr_decode.exp.ds.addr_width)})"
rhs = f"cpuif_req_masked & (cpuif_addr >= {addr_str}) & (cpuif_addr <= {addr_str} + {SVInt(node.size - 1, self.addr_decode.exp.ds.addr_width)})"
self.add_content(f"{strb} = {rhs};")
self.add_content(f"is_external |= {rhs};")
return WalkerAction.SkipDescendants
Expand All @@ -158,12 +159,12 @@ def enter_AddressableComponent(self, node: 'AddressableNode') -> Optional[Walker


def _get_address_str(self, node: 'AddressableNode', subword_offset: int=0) -> str:
a = get_sv_int(
a = str(SVInt(
node.raw_absolute_address - self.addr_decode.top_node.raw_absolute_address + subword_offset,
self.addr_decode.exp.ds.addr_width
)
))
for i, stride in enumerate(self._array_stride_stack):
a += f" + i{i}*{get_sv_int(stride, self.addr_decode.exp.ds.addr_width)}"
a += f" + i{i}*{SVInt(stride, self.addr_decode.exp.ds.addr_width)}"
return a


Expand Down
29 changes: 17 additions & 12 deletions src/peakrdl_regblock/dereferencer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from systemrdl.node import AddrmapNode, FieldNode, SignalNode, RegNode, AddressableNode
from systemrdl.rdltypes import PropertyReference

from .utils import get_sv_int
from .sv_int import SVInt

if TYPE_CHECKING:
from .exporter import RegblockExporter, DesignState
Expand Down Expand Up @@ -38,7 +38,7 @@ def ds(self) -> 'DesignState':
def top_node(self) -> AddrmapNode:
return self.exp.ds.top_node

def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], width: Optional[int] = None) -> str:
def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], width: Optional[int] = None) -> Union[SVInt, str]:
"""
Returns the Verilog string that represents the readable value associated
with the object.
Expand All @@ -52,20 +52,20 @@ def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], w
"""
if isinstance(obj, int):
# Is a simple scalar value
return get_sv_int(obj, width)
return SVInt(obj, width)

if isinstance(obj, FieldNode):
if obj.implements_storage:
return self.field_logic.get_storage_identifier(obj)

if self.hwif.has_value_input(obj):
return self.hwif.get_input_identifier(obj)
return self.hwif.get_input_identifier(obj, width)

# Field does not have a storage element, nor does it have a HW input
# must be a constant value as defined by its reset value
reset_value = obj.get_property('reset')
if reset_value is not None:
return self.get_value(reset_value)
return self.get_value(reset_value, obj.width)
else:
# No reset value defined!
obj.env.msg.warning(
Expand All @@ -76,11 +76,11 @@ def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], w

if isinstance(obj, SignalNode):
# Signals are always inputs from the hwif
return self.hwif.get_input_identifier(obj)
return self.hwif.get_input_identifier(obj, width)

if isinstance(obj, PropertyReference):
if isinstance(obj.node, FieldNode):
return self.get_field_propref_value(obj.node, obj.name)
return self.get_field_propref_value(obj.node, obj.name, width)
elif isinstance(obj.node, RegNode):
return self.get_reg_propref_value(obj.node, obj.name)
else:
Expand All @@ -89,7 +89,12 @@ def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], w
raise RuntimeError(f"Unhandled reference to: {obj}")


def get_field_propref_value(self, field: FieldNode, prop_name: str) -> str:
def get_field_propref_value(
self,
field: FieldNode,
prop_name: str,
width: Optional[int] = None,
) -> Union[SVInt, str]:
# Value reduction properties.
# Wrap with the appropriate Verilog reduction operator
if prop_name == "anded":
Expand All @@ -115,7 +120,7 @@ def get_field_propref_value(self, field: FieldNode, prop_name: str) -> str:
'reset',
'resetsignal',
}:
return self.get_value(field.get_property(prop_name))
return self.get_value(field.get_property(prop_name), width)

# Field Next
if prop_name == "next":
Expand All @@ -124,7 +129,7 @@ def get_field_propref_value(self, field: FieldNode, prop_name: str) -> str:
# unset by the user, points to the implied internal signal
return self.field_logic.get_field_combo_identifier(field, "next")
else:
return self.get_value(prop_value)
return self.get_value(prop_value, width)

# References to another component value, or an implied input
if prop_name in {'hwclr', 'hwset'}:
Expand Down Expand Up @@ -163,7 +168,7 @@ def get_field_propref_value(self, field: FieldNode, prop_name: str) -> str:
else:
return f"!({self.get_value(prop_value)})"
else:
return self.get_value(prop_value)
return self.get_value(prop_value, width)

if prop_name == "swacc":
return self.field_logic.get_swacc_identifier(field)
Expand Down Expand Up @@ -232,7 +237,7 @@ def get_resetsignal(self, obj: Optional[SignalNode] = None) -> str:
if isinstance(obj, SignalNode):
s = self.get_value(obj)
if obj.get_property('activehigh'):
return s
return str(s)
else:
return f"~{s}"

Expand Down
19 changes: 10 additions & 9 deletions src/peakrdl_regblock/field_logic/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Union

from systemrdl.rdltypes import PrecedenceType, InterruptType

Expand All @@ -11,6 +11,7 @@
from . import hw_interrupts

from ..utils import get_indexed_path
from ..sv_int import SVInt

from .generators import CombinationalStructGenerator, FieldStorageStructGenerator, FieldLogicGenerator

Expand Down Expand Up @@ -99,12 +100,12 @@ def get_counter_incr_strobe(self, field: 'FieldNode') -> str:
"""
prop_value = field.get_property('incr')
if prop_value:
return self.exp.dereferencer.get_value(prop_value)
return str(self.exp.dereferencer.get_value(prop_value))

# unset by the user, points to the implied input signal
return self.exp.hwif.get_implied_prop_input_identifier(field, "incr")

def get_counter_incrvalue(self, field: 'FieldNode') -> str:
def get_counter_incrvalue(self, field: 'FieldNode') -> Union[SVInt, str]:
"""
Return the string that represents the field's increment value
"""
Expand All @@ -115,7 +116,7 @@ def get_counter_incrvalue(self, field: 'FieldNode') -> str:
return self.exp.hwif.get_implied_prop_input_identifier(field, "incrvalue")
return "1'b1"

def get_counter_incrsaturate_value(self, field: 'FieldNode') -> str:
def get_counter_incrsaturate_value(self, field: 'FieldNode') -> Union[SVInt, str]:
prop_value = field.get_property('incrsaturate')
if prop_value is True:
return self.exp.dereferencer.get_value(2**field.width - 1, field.width)
Expand All @@ -127,7 +128,7 @@ def counter_incrsaturates(self, field: 'FieldNode') -> bool:
"""
return field.get_property('incrsaturate') is not False

def get_counter_incrthreshold_value(self, field: 'FieldNode') -> str:
def get_counter_incrthreshold_value(self, field: 'FieldNode') -> Union[SVInt, str]:
prop_value = field.get_property('incrthreshold')
if isinstance(prop_value, bool):
# No explicit value set. use max
Expand All @@ -140,12 +141,12 @@ def get_counter_decr_strobe(self, field: 'FieldNode') -> str:
"""
prop_value = field.get_property('decr')
if prop_value:
return self.exp.dereferencer.get_value(prop_value)
return str(self.exp.dereferencer.get_value(prop_value))

# unset by the user, points to the implied input signal
return self.exp.hwif.get_implied_prop_input_identifier(field, "decr")

def get_counter_decrvalue(self, field: 'FieldNode') -> str:
def get_counter_decrvalue(self, field: 'FieldNode') -> Union[SVInt, str]:
"""
Return the string that represents the field's decrement value
"""
Expand All @@ -156,7 +157,7 @@ def get_counter_decrvalue(self, field: 'FieldNode') -> str:
return self.exp.hwif.get_implied_prop_input_identifier(field, "decrvalue")
return "1'b1"

def get_counter_decrsaturate_value(self, field: 'FieldNode') -> str:
def get_counter_decrsaturate_value(self, field: 'FieldNode') -> Union[SVInt, str]:
prop_value = field.get_property('decrsaturate')
if prop_value is True:
return f"{field.width}'d0"
Expand All @@ -168,7 +169,7 @@ def counter_decrsaturates(self, field: 'FieldNode') -> bool:
"""
return field.get_property('decrsaturate') is not False

def get_counter_decrthreshold_value(self, field: 'FieldNode') -> str:
def get_counter_decrthreshold_value(self, field: 'FieldNode') -> Union[SVInt, str]:
prop_value = field.get_property('decrthreshold')
if isinstance(prop_value, bool):
# No explicit value set. use min
Expand Down
4 changes: 2 additions & 2 deletions src/peakrdl_regblock/field_logic/hw_set_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def get_predicate(self, field: 'FieldNode') -> str:
identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "hwset")
else:
# signal or field
identifier = self.exp.dereferencer.get_value(prop)
identifier = str(self.exp.dereferencer.get_value(prop))
return identifier

def get_assignments(self, field: 'FieldNode') -> List[str]:
Expand Down Expand Up @@ -50,7 +50,7 @@ def get_predicate(self, field: 'FieldNode') -> str:
identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "hwclr")
else:
# signal or field
identifier = self.exp.dereferencer.get_value(prop)
identifier = str(self.exp.dereferencer.get_value(prop))
return identifier

def get_assignments(self, field: 'FieldNode') -> List[str]:
Expand Down
6 changes: 3 additions & 3 deletions src/peakrdl_regblock/field_logic/hw_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def is_match(self, field: 'FieldNode') -> bool:
def get_assignments(self, field: 'FieldNode') -> List[str]:
hwmask = field.get_property('hwmask')
hwenable = field.get_property('hwenable')
I = self.exp.hwif.get_input_identifier(field)
I = str(self.exp.hwif.get_input_identifier(field))
R = self.exp.field_logic.get_storage_identifier(field)
if hwmask is not None:
M = self.exp.dereferencer.get_value(hwmask)
Expand Down Expand Up @@ -55,7 +55,7 @@ def get_predicate(self, field: 'FieldNode') -> str:
identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "we")
else:
# signal or field
identifier = self.exp.dereferencer.get_value(prop)
identifier = str(self.exp.dereferencer.get_value(prop))
return identifier

class WELWrite(AlwaysWrite):
Expand All @@ -73,5 +73,5 @@ def get_predicate(self, field: 'FieldNode') -> str:
identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "wel")
else:
# signal or field
identifier = self.exp.dereferencer.get_value(prop)
identifier = str(self.exp.dereferencer.get_value(prop))
return f"!{identifier}"
13 changes: 9 additions & 4 deletions src/peakrdl_regblock/hwif/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import TYPE_CHECKING, Union, Set, Dict, Optional, TextIO, Type, List
from typing import TYPE_CHECKING, Union, Optional, TextIO

from systemrdl.node import AddrmapNode, SignalNode, FieldNode, RegNode, AddressableNode
from systemrdl.rdltypes import PropertyReference, UserEnum
from systemrdl.rdltypes import PropertyReference

from ..utils import get_indexed_path
from ..identifier_filter import kw_filter as kwf
from ..sv_int import SVInt

from .generators import InputStructGenerator_Hier, OutputStructGenerator_Hier
from .generators import InputStructGenerator_TypeScope, OutputStructGenerator_TypeScope
Expand Down Expand Up @@ -127,7 +128,11 @@ def has_value_output(self, obj: FieldNode) -> bool:
return obj.is_hw_readable


def get_input_identifier(self, obj: Union[FieldNode, SignalNode, PropertyReference]) -> str:
def get_input_identifier(
self,
obj: Union[FieldNode, SignalNode, PropertyReference],
width: Optional[int] = None,
) -> Union[SVInt, str]:
"""
Returns the identifier string that best represents the input object.
Expand All @@ -143,7 +148,7 @@ def get_input_identifier(self, obj: Union[FieldNode, SignalNode, PropertyReferen
next_value = obj.get_property('next')
if next_value is not None:
# 'next' property replaces the inferred input signal
return self.exp.dereferencer.get_value(next_value)
return self.exp.dereferencer.get_value(next_value, width)
# Otherwise, use inferred
path = get_indexed_path(self.top_node, obj)
return "hwif_in." + path + ".next"
Expand Down
4 changes: 2 additions & 2 deletions src/peakrdl_regblock/hwif/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from ..struct_generator import RDLFlatStructGenerator
from ..identifier_filter import kw_filter as kwf
from ..utils import get_sv_int
from ..sv_int import SVInt

if TYPE_CHECKING:
from systemrdl.node import Node, SignalNode, AddressableNode, RegfileNode
Expand Down Expand Up @@ -289,7 +289,7 @@ def _enum_typedef(self, user_enum: Type['UserEnum']) -> str:

lines = []
for enum_member in user_enum:
lines.append(f" {prefix}__{enum_member.name} = {get_sv_int(enum_member.value)}")
lines.append(f" {prefix}__{enum_member.name} = {SVInt(enum_member.value)}")

return (
"typedef enum {\n"
Expand Down
9 changes: 5 additions & 4 deletions src/peakrdl_regblock/read_buffering/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Union

from systemrdl.node import AddrmapNode, RegNode, FieldNode, SignalNode
from systemrdl.node import AddrmapNode, RegNode, SignalNode

from .storage_generator import RBufStorageStructGenerator
from .implementation_generator import RBufLogicGenerator
from ..utils import get_indexed_path
from ..sv_int import SVInt

if TYPE_CHECKING:
from ..exporter import RegblockExporter
Expand Down Expand Up @@ -47,12 +48,12 @@ def get_trigger(self, node: RegNode) -> str:
elif isinstance(trigger, SignalNode):
s = self.exp.dereferencer.get_value(trigger)
if trigger.get_property('activehigh'):
return s
return str(s)
else:
return f"~{s}"
else:
# Trigger is a field or propref bit
return self.exp.dereferencer.get_value(trigger)
return str(self.exp.dereferencer.get_value(trigger))

def get_rbuf_data(self, node: RegNode) -> str:
return "rbuf_storage." + get_indexed_path(self.top_node, node) + ".data"
Loading

0 comments on commit 62518b3

Please sign in to comment.