diff --git a/docs/dev_notes/Hierarchy-and-Indexing b/docs/dev_notes/Hierarchy-and-Indexing index d6da96b..9819b31 100644 --- a/docs/dev_notes/Hierarchy-and-Indexing +++ b/docs/dev_notes/Hierarchy-and-Indexing @@ -40,7 +40,7 @@ For example, given this RDL: } rf_loop[16]; }; -The 'next' assignment will have a reference that has the following hierarchcial +The 'next' assignment will have a reference that has the following hierarchical path: top.rf_loop[].x[3].f1 | | diff --git a/docs/dev_notes/Validation Needed b/docs/dev_notes/Validation Needed index df0f8a4..b9ee814 100644 --- a/docs/dev_notes/Validation Needed +++ b/docs/dev_notes/Validation Needed @@ -123,6 +123,8 @@ X we/wel + implied or explicit "sticky"/"stickybit" ! Illegal to use enable/mask/haltenable/haltmask on non-intr fields +! sticky/stickybit shall be hw writable + ================================================================================ Things that need validation by this exporter ================================================================================ diff --git a/peakrdl/regblock/field_logic/__init__.py b/peakrdl/regblock/field_logic/__init__.py index f43c9a7..88e246e 100644 --- a/peakrdl/regblock/field_logic/__init__.py +++ b/peakrdl/regblock/field_logic/__init__.py @@ -69,7 +69,7 @@ class FieldLogic: """ assert field.implements_storage path = get_indexed_path(self.top_node, field) - return f"field_storage.{path}" + return f"field_storage.{path}.value" def get_field_combo_identifier(self, field: 'FieldNode', name: str) -> str: """ diff --git a/peakrdl/regblock/field_logic/generators.py b/peakrdl/regblock/field_logic/generators.py index d450664..0b91842 100644 --- a/peakrdl/regblock/field_logic/generators.py +++ b/peakrdl/regblock/field_logic/generators.py @@ -62,8 +62,12 @@ class CombinationalStructGenerator(RDLStructGenerator): class FieldStorageStructGenerator(RDLStructGenerator): def enter_Field(self, node: 'FieldNode') -> None: + self.push_struct(node.inst_name) + if node.implements_storage: - self.add_member(node.inst_name, node.width) + self.add_member("value", node.width) + + self.pop_struct() class FieldLogicGenerator(RDLForLoopGenerator): @@ -104,7 +108,6 @@ class FieldLogicGenerator(RDLForLoopGenerator): context = { 'node': node, 'reset': reset_value_str, - 'field_path': get_indexed_path(self.exp.top_node, node), 'field_logic': self.field_logic, 'extra_combo_signals': extra_combo_signals, 'conditionals': conditionals, @@ -117,8 +120,6 @@ class FieldLogicGenerator(RDLForLoopGenerator): def assign_field_outputs(self, node: 'FieldNode') -> None: - field_path = get_indexed_path(self.exp.top_node, node) - # Field value output if self.exp.hwif.has_value_output(node): output_identifier = self.exp.hwif.get_output_identifier(node) diff --git a/peakrdl/regblock/field_logic/hw_set_clr.py b/peakrdl/regblock/field_logic/hw_set_clr.py index bb2cf38..236c8ec 100644 --- a/peakrdl/regblock/field_logic/hw_set_clr.py +++ b/peakrdl/regblock/field_logic/hw_set_clr.py @@ -21,11 +21,9 @@ class HWSet(NextStateConditional): return identifier def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) - hwmask = field.get_property('hwmask') hwenable = field.get_property('hwenable') - R = f"field_storage.{field_path}" + R = self.exp.field_logic.get_storage_identifier(field) if hwmask is not None: M = self.exp.dereferencer.get_value(hwmask) next_val = f"{R} | ~{M}" @@ -56,11 +54,9 @@ class HWClear(NextStateConditional): return identifier def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) - hwmask = field.get_property('hwmask') hwenable = field.get_property('hwenable') - R = f"field_storage.{field_path}" + R = self.exp.field_logic.get_storage_identifier(field) if hwmask is not None: M = self.exp.dereferencer.get_value(hwmask) next_val = f"{R} & {M}" diff --git a/peakrdl/regblock/field_logic/hw_write.py b/peakrdl/regblock/field_logic/hw_write.py index e4f4073..fb6eb15 100644 --- a/peakrdl/regblock/field_logic/hw_write.py +++ b/peakrdl/regblock/field_logic/hw_write.py @@ -23,12 +23,10 @@ class AlwaysWrite(NextStateConditional): return "1" def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) - hwmask = field.get_property('hwmask') hwenable = field.get_property('hwenable') I = self.exp.hwif.get_input_identifier(field) - R = f"field_storage.{field_path}" + R = self.exp.field_logic.get_storage_identifier(field) if hwmask is not None: M = self.exp.dereferencer.get_value(hwmask) next_val = f"{I} & ~{M} | {R} & {M}" @@ -36,7 +34,7 @@ class AlwaysWrite(NextStateConditional): E = self.exp.dereferencer.get_value(hwenable) next_val = f"{I} & {E} | {R} & ~{E}" else: - next_val = self.exp.hwif.get_input_identifier(field) + next_val = I return [ f"next_c = {next_val};", diff --git a/peakrdl/regblock/field_logic/sw_onread.py b/peakrdl/regblock/field_logic/sw_onread.py index 0678160..843ae5c 100644 --- a/peakrdl/regblock/field_logic/sw_onread.py +++ b/peakrdl/regblock/field_logic/sw_onread.py @@ -22,7 +22,6 @@ class ClearOnRead(_OnRead): onreadtype = OnReadType.rclr def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) return [ f"next_c = '0;", f"load_next_c = '1;", @@ -34,7 +33,6 @@ class SetOnRead(_OnRead): onreadtype = OnReadType.rset def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) return [ f"next_c = '1;", f"load_next_c = '1;", diff --git a/peakrdl/regblock/field_logic/sw_onwrite.py b/peakrdl/regblock/field_logic/sw_onwrite.py index 8471774..a5e27c6 100644 --- a/peakrdl/regblock/field_logic/sw_onwrite.py +++ b/peakrdl/regblock/field_logic/sw_onwrite.py @@ -38,9 +38,9 @@ class WriteOneSet(_OnWrite): onwritetype = OnWriteType.woset def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) + R = self.exp.field_logic.get_storage_identifier(field) return [ - f"next_c = field_storage.{field_path} | {self._wr_data(field)};", + f"next_c = {R} | {self._wr_data(field)};", f"load_next_c = '1;", ] @@ -49,9 +49,9 @@ class WriteOneClear(_OnWrite): onwritetype = OnWriteType.woclr def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) + R = self.exp.field_logic.get_storage_identifier(field) return [ - f"next_c = field_storage.{field_path} & ~{self._wr_data(field)};", + f"next_c = {R} & ~{self._wr_data(field)};", f"load_next_c = '1;", ] @@ -60,9 +60,9 @@ class WriteOneToggle(_OnWrite): onwritetype = OnWriteType.wot def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) + R = self.exp.field_logic.get_storage_identifier(field) return [ - f"next_c = field_storage.{field_path} ^ {self._wr_data(field)};", + f"next_c = {R} ^ {self._wr_data(field)};", f"load_next_c = '1;", ] @@ -71,9 +71,9 @@ class WriteZeroSet(_OnWrite): onwritetype = OnWriteType.wzs def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) + R = self.exp.field_logic.get_storage_identifier(field) return [ - f"next_c = field_storage.{field_path} | ~{self._wr_data(field)};", + f"next_c = {R} | ~{self._wr_data(field)};", f"load_next_c = '1;", ] @@ -82,9 +82,9 @@ class WriteZeroClear(_OnWrite): onwritetype = OnWriteType.wzc def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) + R = self.exp.field_logic.get_storage_identifier(field) return [ - f"next_c = field_storage.{field_path} & {self._wr_data(field)};", + f"next_c = {R} & {self._wr_data(field)};", f"load_next_c = '1;", ] @@ -93,9 +93,9 @@ class WriteZeroToggle(_OnWrite): onwritetype = OnWriteType.wzt def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) + R = self.exp.field_logic.get_storage_identifier(field) return [ - f"next_c = field_storage.{field_path} ^ ~{self._wr_data(field)};", + f"next_c = {R} ^ ~{self._wr_data(field)};", f"load_next_c = '1;", ] @@ -104,7 +104,6 @@ class WriteClear(_OnWrite): onwritetype = OnWriteType.wclr def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) return [ f"next_c = '0;", f"load_next_c = '1;", @@ -115,7 +114,6 @@ class WriteSet(_OnWrite): onwritetype = OnWriteType.wset def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) return [ f"next_c = '1;", f"load_next_c = '1;", @@ -126,7 +124,6 @@ class Write(_OnWrite): onwritetype = None def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) return [ f"next_c = {self._wr_data(field)};", f"load_next_c = '1;", diff --git a/peakrdl/regblock/field_logic/sw_singlepulse.py b/peakrdl/regblock/field_logic/sw_singlepulse.py index 56d8c4b..5c89548 100644 --- a/peakrdl/regblock/field_logic/sw_singlepulse.py +++ b/peakrdl/regblock/field_logic/sw_singlepulse.py @@ -16,7 +16,6 @@ class Singlepulse(NextStateConditional): return "1" def get_assignments(self, field: 'FieldNode') -> List[str]: - field_path = self.get_field_path(field) return [ f"next_c = '0;", f"load_next_c = '1;", diff --git a/peakrdl/regblock/field_logic/templates/counter_macros.sv b/peakrdl/regblock/field_logic/templates/counter_macros.sv index 4cba925..3c2b6f1 100644 --- a/peakrdl/regblock/field_logic/templates/counter_macros.sv +++ b/peakrdl/regblock/field_logic/templates/counter_macros.sv @@ -7,18 +7,18 @@ next_c = next_c + {{field_logic.get_counter_incrvalue(node)}}; end {%- else %} - field_combo.{{field_path}}.overflow = ((({{node.width+1}})'(next_c) + {{field_logic.get_counter_incrvalue(node)}}) > {{get_value(2**node.width - 1)}}); + {{field_logic.get_field_combo_identifier(node, "overflow")}} = ((({{node.width+1}})'(next_c) + {{field_logic.get_counter_incrvalue(node)}}) > {{get_value(2**node.width - 1)}}); next_c = next_c + {{field_logic.get_counter_incrvalue(node)}}; {%- endif %} load_next_c = '1; {%- if not field_logic.counter_incrsaturates(node) %} end else begin - field_combo.{{field_path}}.overflow = '0; + {{field_logic.get_field_combo_identifier(node, "overflow")}} = '0; {%- endif %} end - field_combo.{{field_path}}.incrthreshold = (field_storage.{{field_path}} >= {{field_logic.get_counter_incrthreshold_value(node)}}); + {{field_logic.get_field_combo_identifier(node, "incrthreshold")}} = ({{field_logic.get_storage_identifier(node)}} >= {{field_logic.get_counter_incrthreshold_value(node)}}); {%- if field_logic.counter_incrsaturates(node) %} - field_combo.{{field_path}}.incrsaturate = (field_storage.{{field_path}} >= {{field_logic.get_counter_incrsaturate_value(node)}}); + {{field_logic.get_field_combo_identifier(node, "incrsaturate")}} = ({{field_logic.get_storage_identifier(node)}} >= {{field_logic.get_counter_incrsaturate_value(node)}}); if(next_c > {{field_logic.get_counter_incrsaturate_value(node)}}) begin next_c = {{field_logic.get_counter_incrsaturate_value(node)}}; load_next_c = '1; @@ -36,18 +36,18 @@ next_c = next_c - {{field_logic.get_counter_decrvalue(node)}}; end {%- else %} - field_combo.{{field_path}}.underflow = (next_c < ({{field_logic.get_counter_decrvalue(node)}})); + {{field_logic.get_field_combo_identifier(node, "underflow")}} = (next_c < ({{field_logic.get_counter_decrvalue(node)}})); next_c = next_c - {{field_logic.get_counter_decrvalue(node)}}; {%- endif %} load_next_c = '1; {%- if not field_logic.counter_decrsaturates(node) %} end else begin - field_combo.{{field_path}}.underflow = '0; + {{field_logic.get_field_combo_identifier(node, "underflow")}} = '0; {%- endif %} end - field_combo.{{field_path}}.decrthreshold = (field_storage.{{field_path}} <= {{field_logic.get_counter_decrthreshold_value(node)}}); + {{field_logic.get_field_combo_identifier(node, "decrthreshold")}} = ({{field_logic.get_storage_identifier(node)}} <= {{field_logic.get_counter_decrthreshold_value(node)}}); {%- if field_logic.counter_decrsaturates(node) %} - field_combo.{{field_path}}.decrsaturate = (field_storage.{{field_path}} <= {{field_logic.get_counter_decrsaturate_value(node)}}); + {{field_logic.get_field_combo_identifier(node, "decrsaturate")}} = ({{field_logic.get_storage_identifier(node)}} <= {{field_logic.get_counter_decrsaturate_value(node)}}); if(next_c < {{field_logic.get_counter_decrsaturate_value(node)}}) begin next_c = {{field_logic.get_counter_decrsaturate_value(node)}}; load_next_c = '1; diff --git a/peakrdl/regblock/field_logic/templates/field_storage.sv b/peakrdl/regblock/field_logic/templates/field_storage.sv index d763311..a6ca856 100644 --- a/peakrdl/regblock/field_logic/templates/field_storage.sv +++ b/peakrdl/regblock/field_logic/templates/field_storage.sv @@ -1,10 +1,10 @@ {%- import 'field_logic/templates/counter_macros.sv' as counter_macros with context -%} // Field: {{node.get_path()}} always_comb begin - automatic logic [{{node.width-1}}:0] next_c = field_storage.{{field_path}}; + automatic logic [{{node.width-1}}:0] next_c = {{field_logic.get_storage_identifier(node)}}; automatic logic load_next_c = '0; {%- for signal in extra_combo_signals %} - field_combo.{{field_path}}.{{signal.name}} = {{signal.default_assignment}}; + {{field_logic.get_field_combo_identifier(node, signal.name)}} = {{signal.default_assignment}}; {%- endfor %} {% for conditional in conditionals %} {%- if not loop.first %} else {% endif %}if({{conditional.get_predicate(node)}}) begin // {{conditional.comment}} @@ -19,14 +19,14 @@ always_comb begin {%- if node.is_down_counter %} {{counter_macros.down_counter(node)}} {%- endif %} - field_combo.{{field_path}}.next = next_c; - field_combo.{{field_path}}.load_next = load_next_c; + {{field_logic.get_field_combo_identifier(node, "next")}} = next_c; + {{field_logic.get_field_combo_identifier(node, "load_next")}} = load_next_c; end always_ff {{get_always_ff_event(resetsignal)}} begin {% if reset is not none -%} if({{get_resetsignal(resetsignal)}}) begin - field_storage.{{field_path}} <= {{reset}}; - end else {% endif %}if(field_combo.{{field_path}}.load_next) begin - field_storage.{{field_path}} <= field_combo.{{field_path}}.next; + {{field_logic.get_storage_identifier(node)}} <= {{reset}}; + end else {% endif %}if({{field_logic.get_field_combo_identifier(node, "load_next")}}) begin + {{field_logic.get_storage_identifier(node)}} <= {{field_logic.get_field_combo_identifier(node, "next")}}; end end