more field logic
This commit is contained in:
99
peakrdl/regblock/field_logic/generators.py
Normal file
99
peakrdl/regblock/field_logic/generators.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from ..struct_generator import RDLStructGenerator
|
||||
from ..forloop_generator import RDLForLoopGenerator
|
||||
from ..utils import get_indexed_path, get_always_ff_event
|
||||
from ..signals import RDLSignal
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import FieldLogic
|
||||
from systemrdl.node import FieldNode
|
||||
|
||||
class CombinationalStructGenerator(RDLStructGenerator):
|
||||
|
||||
def __init__(self, field_logic: 'FieldLogic'):
|
||||
super().__init__()
|
||||
self.field_logic = field_logic
|
||||
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
# If a field doesn't implement storage, it is not relevant here
|
||||
if not node.implements_storage:
|
||||
return
|
||||
|
||||
# collect any extra combo signals that this field requires
|
||||
extra_combo_signals = OrderedDict()
|
||||
for conditional in self.field_logic.get_conditionals(node):
|
||||
for signal in conditional.get_extra_combo_signals(node):
|
||||
if signal.name in extra_combo_signals:
|
||||
# Assert that subsequent declarations of the same signal
|
||||
# are identical
|
||||
assert signal == extra_combo_signals[signal.name]
|
||||
else:
|
||||
extra_combo_signals[signal.name] = signal
|
||||
|
||||
self.push_struct(node.inst_name)
|
||||
self.add_member("next", node.width)
|
||||
self.add_member("load_next")
|
||||
for signal in extra_combo_signals.values():
|
||||
self.add_member(signal.name, signal.width)
|
||||
self.pop_struct()
|
||||
|
||||
|
||||
class FieldStorageStructGenerator(RDLStructGenerator):
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
if node.implements_storage:
|
||||
self.add_member(node.inst_name, node.width)
|
||||
|
||||
|
||||
class FieldLogicGenerator(RDLForLoopGenerator):
|
||||
i_type = "genvar"
|
||||
def __init__(self, field_logic: 'FieldLogic'):
|
||||
super().__init__()
|
||||
self.field_logic = field_logic
|
||||
self.template = self.field_logic.exp.jj_env.get_template(
|
||||
"field_logic/templates/field_storage.sv"
|
||||
)
|
||||
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
# If a field doesn't implement storage, it is not relevant here
|
||||
if not node.implements_storage:
|
||||
return
|
||||
|
||||
conditionals = self.field_logic.get_conditionals(node)
|
||||
extra_combo_signals = OrderedDict()
|
||||
for conditional in conditionals:
|
||||
for signal in conditional.get_extra_combo_signals(node):
|
||||
extra_combo_signals[signal.name] = signal
|
||||
|
||||
sig = node.get_property("resetsignal")
|
||||
if sig is not None:
|
||||
resetsignal = RDLSignal(sig)
|
||||
else:
|
||||
resetsignal = self.field_logic.exp.default_resetsignal
|
||||
|
||||
reset_value = node.get_property("reset")
|
||||
if reset_value is not None:
|
||||
reset_value_str = self.field_logic.exp.dereferencer.get_value(reset_value)
|
||||
else:
|
||||
# 5.9.1-g: If no reset value given, the field is not reset, even if it has a resetsignal.
|
||||
reset_value_str = None
|
||||
resetsignal = None
|
||||
|
||||
context = {
|
||||
'node': node,
|
||||
'reset': reset_value_str,
|
||||
'field_path': get_indexed_path(self.field_logic.top_node, node),
|
||||
'extra_combo_signals': extra_combo_signals,
|
||||
'conditionals': conditionals,
|
||||
'resetsignal': resetsignal,
|
||||
'get_always_ff_event': get_always_ff_event,
|
||||
'has_value_output': self.field_logic.exp.hwif.has_value_output,
|
||||
'get_output_identifier': self.field_logic.exp.hwif.get_output_identifier,
|
||||
|
||||
}
|
||||
self.add_content(self.template.render(context))
|
||||
Reference in New Issue
Block a user