diff --git a/src/peakrdl_regblock/field_logic/bases.py b/src/peakrdl_regblock/field_logic/bases.py index 5f629a5..9dd47f5 100644 --- a/src/peakrdl_regblock/field_logic/bases.py +++ b/src/peakrdl_regblock/field_logic/bases.py @@ -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 diff --git a/src/peakrdl_regblock/field_logic/generators.py b/src/peakrdl_regblock/field_logic/generators.py index 6dbf4c2..e334fdb 100644 --- a/src/peakrdl_regblock/field_logic/generators.py +++ b/src/peakrdl_regblock/field_logic/generators.py @@ -212,10 +212,19 @@ def exit_Reg(self, node: 'RegNode') -> None: 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 @@ def generate_field_storage(self, node: 'FieldNode') -> None: '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, diff --git a/src/peakrdl_regblock/field_logic/hw_interrupts.py b/src/peakrdl_regblock/field_logic/hw_interrupts.py index 8552730..88859a1 100644 --- a/src/peakrdl_regblock/field_logic/hw_interrupts.py +++ b/src/peakrdl_regblock/field_logic/hw_interrupts.py @@ -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 @@ def is_match(self, field: 'FieldNode') -> bool: 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 @@ def is_match(self, field: 'FieldNode') -> bool: 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 @@ def is_match(self, field: 'FieldNode') -> bool: 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) diff --git a/src/peakrdl_regblock/field_logic/hw_write.py b/src/peakrdl_regblock/field_logic/hw_write.py index af9b387..003cd68 100644 --- a/src/peakrdl_regblock/field_logic/hw_write.py +++ b/src/peakrdl_regblock/field_logic/hw_write.py @@ -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 @@ def is_match(self, field: 'FieldNode') -> bool: 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 @@ def get_assignments(self, field: 'FieldNode') -> List[str]: ] class WEWrite(AlwaysWrite): + is_unconditional = False comment = "HW Write - we" def is_match(self, field: 'FieldNode') -> bool: return ( @@ -59,6 +59,7 @@ def get_predicate(self, field: 'FieldNode') -> str: return identifier class WELWrite(AlwaysWrite): + is_unconditional = False comment = "HW Write - wel" def is_match(self, field: 'FieldNode') -> bool: return ( diff --git a/src/peakrdl_regblock/field_logic/sw_singlepulse.py b/src/peakrdl_regblock/field_logic/sw_singlepulse.py index 5c4e61d..e8863e4 100644 --- a/src/peakrdl_regblock/field_logic/sw_singlepulse.py +++ b/src/peakrdl_regblock/field_logic/sw_singlepulse.py @@ -6,15 +6,11 @@ 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;", diff --git a/src/peakrdl_regblock/field_logic/templates/field_storage.sv b/src/peakrdl_regblock/field_logic/templates/field_storage.sv index 431fbc6..62c7fd7 100644 --- a/src/peakrdl_regblock/field_logic/templates/field_storage.sv +++ b/src/peakrdl_regblock/field_logic/templates/field_storage.sv @@ -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)}}