Clean up ugly unconditional 'if(1)' conditionals in field logic. #50

This commit is contained in:
Alex Mykyta
2023-07-19 20:49:38 -07:00
parent da8ff4aaeb
commit 211224116e
6 changed files with 38 additions and 18 deletions

View File

@@ -64,7 +64,13 @@ class NextStateConditional:
end
"""
# Assign to True if predicate can never evaluate to false.
# This will be generated as an 'else' clause, or a direct assignment
is_unconditional = False
# Optional comment to emit next to the conditional
comment = ""
def __init__(self, exp:'RegblockExporter'):
self.exp = exp

View File

@@ -212,10 +212,19 @@ class FieldLogicGenerator(RDLForLoopGenerator):
def generate_field_storage(self, node: 'FieldNode') -> None:
conditionals = self.field_logic.get_conditionals(node)
extra_combo_signals = OrderedDict()
unconditional = None
new_conditionals = []
for conditional in conditionals:
for signal in conditional.get_extra_combo_signals(node):
extra_combo_signals[signal.name] = signal
if conditional.is_unconditional:
assert unconditional is None # Can only have one unconditional assignment per field
unconditional = conditional
else:
new_conditionals.append(conditional)
conditionals = new_conditionals
resetsignal = node.get_property('resetsignal')
reset_value = node.get_property('reset')
@@ -232,6 +241,7 @@ class FieldLogicGenerator(RDLForLoopGenerator):
'field_logic': self.field_logic,
'extra_combo_signals': extra_combo_signals,
'conditionals': conditionals,
'unconditional': unconditional,
'resetsignal': resetsignal,
'get_always_ff_event': self.exp.dereferencer.get_always_ff_event,
'get_value': self.exp.dereferencer.get_value,

View File

@@ -137,6 +137,7 @@ class PosedgeNonsticky(NextStateConditional):
"""
Positive edge non-stickybit
"""
is_unconditional = True
comment = "posedge nonsticky"
def is_match(self, field: 'FieldNode') -> bool:
return (
@@ -145,9 +146,6 @@ class PosedgeNonsticky(NextStateConditional):
and field.get_property('intr type') == InterruptType.posedge
)
def get_predicate(self, field: 'FieldNode') -> str:
return "1"
def get_assignments(self, field: 'FieldNode') -> List[str]:
I = self.exp.hwif.get_input_identifier(field)
Iq = self.exp.field_logic.get_next_q_identifier(field)
@@ -160,6 +158,7 @@ class NegedgeNonsticky(NextStateConditional):
"""
Negative edge non-stickybit
"""
is_unconditional = True
comment = "negedge nonsticky"
def is_match(self, field: 'FieldNode') -> bool:
return (
@@ -168,9 +167,6 @@ class NegedgeNonsticky(NextStateConditional):
and field.get_property('intr type') == InterruptType.negedge
)
def get_predicate(self, field: 'FieldNode') -> str:
return "1"
def get_assignments(self, field: 'FieldNode') -> List[str]:
I = self.exp.hwif.get_input_identifier(field)
Iq = self.exp.field_logic.get_next_q_identifier(field)
@@ -183,6 +179,7 @@ class BothedgeNonsticky(NextStateConditional):
"""
edge-sensitive non-stickybit
"""
is_unconditional = True
comment = "bothedge nonsticky"
def is_match(self, field: 'FieldNode') -> bool:
return (
@@ -191,9 +188,6 @@ class BothedgeNonsticky(NextStateConditional):
and field.get_property('intr type') == InterruptType.bothedge
)
def get_predicate(self, field: 'FieldNode') -> str:
return "1"
def get_assignments(self, field: 'FieldNode') -> List[str]:
I = self.exp.hwif.get_input_identifier(field)
Iq = self.exp.field_logic.get_next_q_identifier(field)

View File

@@ -10,7 +10,10 @@ class AlwaysWrite(NextStateConditional):
"""
hw writable, without any qualifying we/wel
"""
is_unconditional = True
comment = "HW Write"
def is_match(self, field: 'FieldNode') -> bool:
return (
field.is_hw_writable
@@ -18,10 +21,6 @@ class AlwaysWrite(NextStateConditional):
and not field.get_property('wel')
)
def get_predicate(self, field: 'FieldNode') -> str:
# TODO: make exporter promote this to an "else"?
return "1"
def get_assignments(self, field: 'FieldNode') -> List[str]:
hwmask = field.get_property('hwmask')
hwenable = field.get_property('hwenable')
@@ -42,6 +41,7 @@ class AlwaysWrite(NextStateConditional):
]
class WEWrite(AlwaysWrite):
is_unconditional = False
comment = "HW Write - we"
def is_match(self, field: 'FieldNode') -> bool:
return (
@@ -59,6 +59,7 @@ class WEWrite(AlwaysWrite):
return identifier
class WELWrite(AlwaysWrite):
is_unconditional = False
comment = "HW Write - wel"
def is_match(self, field: 'FieldNode') -> bool:
return (

View File

@@ -6,15 +6,11 @@ if TYPE_CHECKING:
from systemrdl.node import FieldNode
class Singlepulse(NextStateConditional):
is_unconditional = True
comment = "singlepulse clears back to 0"
def is_match(self, field: 'FieldNode') -> bool:
return field.get_property('singlepulse')
def get_predicate(self, field: 'FieldNode') -> str:
# TODO: make exporter promote this to an "else"?
# Be mindful of sw/hw precedence. this would have to come last regardless
return "1"
def get_assignments(self, field: 'FieldNode') -> List[str]:
return [
"next_c = '0;",

View File

@@ -14,6 +14,19 @@ always_comb begin
{%- endfor %}
end
{%- endfor %}
{%- if unconditional %}
{%- if conditionals %} else begin // {{unconditional.comment}}
{%- for assignment in unconditional.get_assignments(node) %}
{{assignment|indent}}
{%- endfor %}
end
{%- else %}
// {{unconditional.comment}}
{%- for assignment in unconditional.get_assignments(node) %}
{{assignment|indent}}
{%- endfor %}
{%- endif %}
{%- endif %}
{%- if node.is_up_counter %}
{{counter_macros.up_counter(node)}}