Clean up ugly unconditional 'if(1)' conditionals in field logic. #50
This commit is contained in:
@@ -64,7 +64,13 @@ class NextStateConditional:
|
|||||||
end
|
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 = ""
|
comment = ""
|
||||||
|
|
||||||
def __init__(self, exp:'RegblockExporter'):
|
def __init__(self, exp:'RegblockExporter'):
|
||||||
self.exp = exp
|
self.exp = exp
|
||||||
|
|
||||||
|
|||||||
@@ -212,10 +212,19 @@ class FieldLogicGenerator(RDLForLoopGenerator):
|
|||||||
def generate_field_storage(self, node: 'FieldNode') -> None:
|
def generate_field_storage(self, node: 'FieldNode') -> None:
|
||||||
conditionals = self.field_logic.get_conditionals(node)
|
conditionals = self.field_logic.get_conditionals(node)
|
||||||
extra_combo_signals = OrderedDict()
|
extra_combo_signals = OrderedDict()
|
||||||
|
unconditional = None
|
||||||
|
new_conditionals = []
|
||||||
for conditional in conditionals:
|
for conditional in conditionals:
|
||||||
for signal in conditional.get_extra_combo_signals(node):
|
for signal in conditional.get_extra_combo_signals(node):
|
||||||
extra_combo_signals[signal.name] = signal
|
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')
|
resetsignal = node.get_property('resetsignal')
|
||||||
|
|
||||||
reset_value = node.get_property('reset')
|
reset_value = node.get_property('reset')
|
||||||
@@ -232,6 +241,7 @@ class FieldLogicGenerator(RDLForLoopGenerator):
|
|||||||
'field_logic': self.field_logic,
|
'field_logic': self.field_logic,
|
||||||
'extra_combo_signals': extra_combo_signals,
|
'extra_combo_signals': extra_combo_signals,
|
||||||
'conditionals': conditionals,
|
'conditionals': conditionals,
|
||||||
|
'unconditional': unconditional,
|
||||||
'resetsignal': resetsignal,
|
'resetsignal': resetsignal,
|
||||||
'get_always_ff_event': self.exp.dereferencer.get_always_ff_event,
|
'get_always_ff_event': self.exp.dereferencer.get_always_ff_event,
|
||||||
'get_value': self.exp.dereferencer.get_value,
|
'get_value': self.exp.dereferencer.get_value,
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ class PosedgeNonsticky(NextStateConditional):
|
|||||||
"""
|
"""
|
||||||
Positive edge non-stickybit
|
Positive edge non-stickybit
|
||||||
"""
|
"""
|
||||||
|
is_unconditional = True
|
||||||
comment = "posedge nonsticky"
|
comment = "posedge nonsticky"
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return (
|
return (
|
||||||
@@ -145,9 +146,6 @@ class PosedgeNonsticky(NextStateConditional):
|
|||||||
and field.get_property('intr type') == InterruptType.posedge
|
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]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
I = self.exp.hwif.get_input_identifier(field)
|
I = self.exp.hwif.get_input_identifier(field)
|
||||||
Iq = self.exp.field_logic.get_next_q_identifier(field)
|
Iq = self.exp.field_logic.get_next_q_identifier(field)
|
||||||
@@ -160,6 +158,7 @@ class NegedgeNonsticky(NextStateConditional):
|
|||||||
"""
|
"""
|
||||||
Negative edge non-stickybit
|
Negative edge non-stickybit
|
||||||
"""
|
"""
|
||||||
|
is_unconditional = True
|
||||||
comment = "negedge nonsticky"
|
comment = "negedge nonsticky"
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return (
|
return (
|
||||||
@@ -168,9 +167,6 @@ class NegedgeNonsticky(NextStateConditional):
|
|||||||
and field.get_property('intr type') == InterruptType.negedge
|
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]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
I = self.exp.hwif.get_input_identifier(field)
|
I = self.exp.hwif.get_input_identifier(field)
|
||||||
Iq = self.exp.field_logic.get_next_q_identifier(field)
|
Iq = self.exp.field_logic.get_next_q_identifier(field)
|
||||||
@@ -183,6 +179,7 @@ class BothedgeNonsticky(NextStateConditional):
|
|||||||
"""
|
"""
|
||||||
edge-sensitive non-stickybit
|
edge-sensitive non-stickybit
|
||||||
"""
|
"""
|
||||||
|
is_unconditional = True
|
||||||
comment = "bothedge nonsticky"
|
comment = "bothedge nonsticky"
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return (
|
return (
|
||||||
@@ -191,9 +188,6 @@ class BothedgeNonsticky(NextStateConditional):
|
|||||||
and field.get_property('intr type') == InterruptType.bothedge
|
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]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
I = self.exp.hwif.get_input_identifier(field)
|
I = self.exp.hwif.get_input_identifier(field)
|
||||||
Iq = self.exp.field_logic.get_next_q_identifier(field)
|
Iq = self.exp.field_logic.get_next_q_identifier(field)
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ class AlwaysWrite(NextStateConditional):
|
|||||||
"""
|
"""
|
||||||
hw writable, without any qualifying we/wel
|
hw writable, without any qualifying we/wel
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
is_unconditional = True
|
||||||
comment = "HW Write"
|
comment = "HW Write"
|
||||||
|
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return (
|
return (
|
||||||
field.is_hw_writable
|
field.is_hw_writable
|
||||||
@@ -18,10 +21,6 @@ class AlwaysWrite(NextStateConditional):
|
|||||||
and not field.get_property('wel')
|
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]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
hwmask = field.get_property('hwmask')
|
hwmask = field.get_property('hwmask')
|
||||||
hwenable = field.get_property('hwenable')
|
hwenable = field.get_property('hwenable')
|
||||||
@@ -42,6 +41,7 @@ class AlwaysWrite(NextStateConditional):
|
|||||||
]
|
]
|
||||||
|
|
||||||
class WEWrite(AlwaysWrite):
|
class WEWrite(AlwaysWrite):
|
||||||
|
is_unconditional = False
|
||||||
comment = "HW Write - we"
|
comment = "HW Write - we"
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return (
|
return (
|
||||||
@@ -59,6 +59,7 @@ class WEWrite(AlwaysWrite):
|
|||||||
return identifier
|
return identifier
|
||||||
|
|
||||||
class WELWrite(AlwaysWrite):
|
class WELWrite(AlwaysWrite):
|
||||||
|
is_unconditional = False
|
||||||
comment = "HW Write - wel"
|
comment = "HW Write - wel"
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,15 +6,11 @@ if TYPE_CHECKING:
|
|||||||
from systemrdl.node import FieldNode
|
from systemrdl.node import FieldNode
|
||||||
|
|
||||||
class Singlepulse(NextStateConditional):
|
class Singlepulse(NextStateConditional):
|
||||||
|
is_unconditional = True
|
||||||
comment = "singlepulse clears back to 0"
|
comment = "singlepulse clears back to 0"
|
||||||
def is_match(self, field: 'FieldNode') -> bool:
|
def is_match(self, field: 'FieldNode') -> bool:
|
||||||
return field.get_property('singlepulse')
|
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]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
return [
|
return [
|
||||||
"next_c = '0;",
|
"next_c = '0;",
|
||||||
|
|||||||
@@ -14,6 +14,19 @@ always_comb begin
|
|||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
end
|
end
|
||||||
{%- endfor %}
|
{%- 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 %}
|
{%- if node.is_up_counter %}
|
||||||
{{counter_macros.up_counter(node)}}
|
{{counter_macros.up_counter(node)}}
|
||||||
|
|||||||
Reference in New Issue
Block a user