Files
PeakRDL-regblock/peakrdl/regblock/field_logic/generators.py
2022-01-17 17:19:06 -08:00

190 lines
7.5 KiB
Python

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
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)
if node.is_up_counter:
self.add_up_counter_members(node)
if node.is_down_counter:
self.add_down_counter_members(node)
self.pop_struct()
def add_up_counter_members(self, node: 'FieldNode') -> None:
self.add_member('incrthreshold')
if self.field_logic.counter_incrsaturates(node):
self.add_member('incrsaturate')
else:
self.add_member('overflow')
def add_down_counter_members(self, node: 'FieldNode') -> None:
self.add_member('decrthreshold')
if self.field_logic.counter_decrsaturates(node):
self.add_member('decrsaturate')
else:
self.add_member('underflow')
class FieldStorageStructGenerator(RDLStructGenerator):
def enter_Field(self, node: 'FieldNode') -> None:
self.push_struct(node.inst_name)
if node.implements_storage:
self.add_member("value", node.width)
self.pop_struct()
class FieldLogicGenerator(RDLForLoopGenerator):
i_type = "genvar"
def __init__(self, field_logic: 'FieldLogic'):
super().__init__()
self.field_logic = field_logic
self.exp = field_logic.exp
self.field_storage_template = self.field_logic.exp.jj_env.get_template(
"field_logic/templates/field_storage.sv"
)
def enter_Field(self, node: 'FieldNode') -> None:
if node.implements_storage:
self.generate_field_storage(node)
self.assign_field_outputs(node)
def generate_field_storage(self, node: 'FieldNode') -> None:
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
resetsignal = node.get_property('resetsignal')
reset_value = node.get_property('reset')
if reset_value is not None:
reset_value_str = self.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_logic': self.field_logic,
'extra_combo_signals': extra_combo_signals,
'conditionals': conditionals,
'resetsignal': resetsignal,
'get_always_ff_event': lambda resetsignal : get_always_ff_event(self.exp.dereferencer, resetsignal),
'get_value': self.exp.dereferencer.get_value,
'get_resetsignal': self.exp.dereferencer.get_resetsignal,
}
self.add_content(self.field_storage_template.render(context))
def assign_field_outputs(self, node: 'FieldNode') -> None:
# Field value output
if self.exp.hwif.has_value_output(node):
output_identifier = self.exp.hwif.get_output_identifier(node)
value = self.exp.dereferencer.get_value(node)
self.add_content(
f"assign {output_identifier} = {value};"
)
# Inferred logical reduction outputs
if node.get_property('anded'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "anded")
value = self.exp.dereferencer.get_field_propref_value(node, "anded")
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('ored'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "ored")
value = self.exp.dereferencer.get_field_propref_value(node, "ored")
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('xored'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "xored")
value = self.exp.dereferencer.get_field_propref_value(node, "xored")
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('swmod'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "swmod")
value = self.field_logic.get_swmod_identifier(node)
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('swacc'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "swacc")
value = self.field_logic.get_swacc_identifier(node)
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('incrthreshold') is not False: # (explicitly not False. Not 0)
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "incrthreshold")
value = self.field_logic.get_field_combo_identifier(node, 'incrthreshold')
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('decrthreshold') is not False: # (explicitly not False. Not 0)
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "decrthreshold")
value = self.field_logic.get_field_combo_identifier(node, 'decrthreshold')
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('overflow'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "overflow")
value = self.field_logic.get_field_combo_identifier(node, 'overflow')
self.add_content(
f"assign {output_identifier} = {value};"
)
if node.get_property('underflow'):
output_identifier = self.exp.hwif.get_implied_prop_output_identifier(node, "underflow")
value = self.field_logic.get_field_combo_identifier(node, 'underflow')
self.add_content(
f"assign {output_identifier} = {value};"
)