Rework field combo/storage paths
This commit is contained in:
@@ -40,7 +40,7 @@ For example, given this RDL:
|
|||||||
} rf_loop[16];
|
} 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:
|
path:
|
||||||
top.rf_loop[].x[3].f1
|
top.rf_loop[].x[3].f1
|
||||||
| |
|
| |
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ X we/wel + implied or explicit "sticky"/"stickybit"
|
|||||||
|
|
||||||
! Illegal to use enable/mask/haltenable/haltmask on non-intr fields
|
! Illegal to use enable/mask/haltenable/haltmask on non-intr fields
|
||||||
|
|
||||||
|
! sticky/stickybit shall be hw writable
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Things that need validation by this exporter
|
Things that need validation by this exporter
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class FieldLogic:
|
|||||||
"""
|
"""
|
||||||
assert field.implements_storage
|
assert field.implements_storage
|
||||||
path = get_indexed_path(self.top_node, field)
|
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:
|
def get_field_combo_identifier(self, field: 'FieldNode', name: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -62,8 +62,12 @@ class CombinationalStructGenerator(RDLStructGenerator):
|
|||||||
class FieldStorageStructGenerator(RDLStructGenerator):
|
class FieldStorageStructGenerator(RDLStructGenerator):
|
||||||
|
|
||||||
def enter_Field(self, node: 'FieldNode') -> None:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
|
self.push_struct(node.inst_name)
|
||||||
|
|
||||||
if node.implements_storage:
|
if node.implements_storage:
|
||||||
self.add_member(node.inst_name, node.width)
|
self.add_member("value", node.width)
|
||||||
|
|
||||||
|
self.pop_struct()
|
||||||
|
|
||||||
|
|
||||||
class FieldLogicGenerator(RDLForLoopGenerator):
|
class FieldLogicGenerator(RDLForLoopGenerator):
|
||||||
@@ -104,7 +108,6 @@ class FieldLogicGenerator(RDLForLoopGenerator):
|
|||||||
context = {
|
context = {
|
||||||
'node': node,
|
'node': node,
|
||||||
'reset': reset_value_str,
|
'reset': reset_value_str,
|
||||||
'field_path': get_indexed_path(self.exp.top_node, node),
|
|
||||||
'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,
|
||||||
@@ -117,8 +120,6 @@ class FieldLogicGenerator(RDLForLoopGenerator):
|
|||||||
|
|
||||||
|
|
||||||
def assign_field_outputs(self, node: 'FieldNode') -> None:
|
def assign_field_outputs(self, node: 'FieldNode') -> None:
|
||||||
field_path = get_indexed_path(self.exp.top_node, node)
|
|
||||||
|
|
||||||
# Field value output
|
# Field value output
|
||||||
if self.exp.hwif.has_value_output(node):
|
if self.exp.hwif.has_value_output(node):
|
||||||
output_identifier = self.exp.hwif.get_output_identifier(node)
|
output_identifier = self.exp.hwif.get_output_identifier(node)
|
||||||
|
|||||||
@@ -21,11 +21,9 @@ class HWSet(NextStateConditional):
|
|||||||
return identifier
|
return identifier
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
|
|
||||||
hwmask = field.get_property('hwmask')
|
hwmask = field.get_property('hwmask')
|
||||||
hwenable = field.get_property('hwenable')
|
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:
|
if hwmask is not None:
|
||||||
M = self.exp.dereferencer.get_value(hwmask)
|
M = self.exp.dereferencer.get_value(hwmask)
|
||||||
next_val = f"{R} | ~{M}"
|
next_val = f"{R} | ~{M}"
|
||||||
@@ -56,11 +54,9 @@ class HWClear(NextStateConditional):
|
|||||||
return identifier
|
return identifier
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
|
|
||||||
hwmask = field.get_property('hwmask')
|
hwmask = field.get_property('hwmask')
|
||||||
hwenable = field.get_property('hwenable')
|
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:
|
if hwmask is not None:
|
||||||
M = self.exp.dereferencer.get_value(hwmask)
|
M = self.exp.dereferencer.get_value(hwmask)
|
||||||
next_val = f"{R} & {M}"
|
next_val = f"{R} & {M}"
|
||||||
|
|||||||
@@ -23,12 +23,10 @@ class AlwaysWrite(NextStateConditional):
|
|||||||
return "1"
|
return "1"
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
|
|
||||||
hwmask = field.get_property('hwmask')
|
hwmask = field.get_property('hwmask')
|
||||||
hwenable = field.get_property('hwenable')
|
hwenable = field.get_property('hwenable')
|
||||||
I = self.exp.hwif.get_input_identifier(field)
|
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:
|
if hwmask is not None:
|
||||||
M = self.exp.dereferencer.get_value(hwmask)
|
M = self.exp.dereferencer.get_value(hwmask)
|
||||||
next_val = f"{I} & ~{M} | {R} & {M}"
|
next_val = f"{I} & ~{M} | {R} & {M}"
|
||||||
@@ -36,7 +34,7 @@ class AlwaysWrite(NextStateConditional):
|
|||||||
E = self.exp.dereferencer.get_value(hwenable)
|
E = self.exp.dereferencer.get_value(hwenable)
|
||||||
next_val = f"{I} & {E} | {R} & ~{E}"
|
next_val = f"{I} & {E} | {R} & ~{E}"
|
||||||
else:
|
else:
|
||||||
next_val = self.exp.hwif.get_input_identifier(field)
|
next_val = I
|
||||||
|
|
||||||
return [
|
return [
|
||||||
f"next_c = {next_val};",
|
f"next_c = {next_val};",
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ class ClearOnRead(_OnRead):
|
|||||||
onreadtype = OnReadType.rclr
|
onreadtype = OnReadType.rclr
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
return [
|
return [
|
||||||
f"next_c = '0;",
|
f"next_c = '0;",
|
||||||
f"load_next_c = '1;",
|
f"load_next_c = '1;",
|
||||||
@@ -34,7 +33,6 @@ class SetOnRead(_OnRead):
|
|||||||
onreadtype = OnReadType.rset
|
onreadtype = OnReadType.rset
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
return [
|
return [
|
||||||
f"next_c = '1;",
|
f"next_c = '1;",
|
||||||
f"load_next_c = '1;",
|
f"load_next_c = '1;",
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ class WriteOneSet(_OnWrite):
|
|||||||
onwritetype = OnWriteType.woset
|
onwritetype = OnWriteType.woset
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
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 [
|
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;",
|
f"load_next_c = '1;",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ class WriteOneClear(_OnWrite):
|
|||||||
onwritetype = OnWriteType.woclr
|
onwritetype = OnWriteType.woclr
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
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 [
|
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;",
|
f"load_next_c = '1;",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@ class WriteOneToggle(_OnWrite):
|
|||||||
onwritetype = OnWriteType.wot
|
onwritetype = OnWriteType.wot
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
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 [
|
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;",
|
f"load_next_c = '1;",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -71,9 +71,9 @@ class WriteZeroSet(_OnWrite):
|
|||||||
onwritetype = OnWriteType.wzs
|
onwritetype = OnWriteType.wzs
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
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 [
|
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;",
|
f"load_next_c = '1;",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -82,9 +82,9 @@ class WriteZeroClear(_OnWrite):
|
|||||||
onwritetype = OnWriteType.wzc
|
onwritetype = OnWriteType.wzc
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
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 [
|
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;",
|
f"load_next_c = '1;",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -93,9 +93,9 @@ class WriteZeroToggle(_OnWrite):
|
|||||||
onwritetype = OnWriteType.wzt
|
onwritetype = OnWriteType.wzt
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
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 [
|
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;",
|
f"load_next_c = '1;",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -104,7 +104,6 @@ class WriteClear(_OnWrite):
|
|||||||
onwritetype = OnWriteType.wclr
|
onwritetype = OnWriteType.wclr
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
return [
|
return [
|
||||||
f"next_c = '0;",
|
f"next_c = '0;",
|
||||||
f"load_next_c = '1;",
|
f"load_next_c = '1;",
|
||||||
@@ -115,7 +114,6 @@ class WriteSet(_OnWrite):
|
|||||||
onwritetype = OnWriteType.wset
|
onwritetype = OnWriteType.wset
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
return [
|
return [
|
||||||
f"next_c = '1;",
|
f"next_c = '1;",
|
||||||
f"load_next_c = '1;",
|
f"load_next_c = '1;",
|
||||||
@@ -126,7 +124,6 @@ class Write(_OnWrite):
|
|||||||
onwritetype = None
|
onwritetype = None
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
return [
|
return [
|
||||||
f"next_c = {self._wr_data(field)};",
|
f"next_c = {self._wr_data(field)};",
|
||||||
f"load_next_c = '1;",
|
f"load_next_c = '1;",
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class Singlepulse(NextStateConditional):
|
|||||||
return "1"
|
return "1"
|
||||||
|
|
||||||
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
def get_assignments(self, field: 'FieldNode') -> List[str]:
|
||||||
field_path = self.get_field_path(field)
|
|
||||||
return [
|
return [
|
||||||
f"next_c = '0;",
|
f"next_c = '0;",
|
||||||
f"load_next_c = '1;",
|
f"load_next_c = '1;",
|
||||||
|
|||||||
@@ -7,18 +7,18 @@
|
|||||||
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
||||||
end
|
end
|
||||||
{%- else %}
|
{%- 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)}};
|
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
load_next_c = '1;
|
load_next_c = '1;
|
||||||
{%- if not field_logic.counter_incrsaturates(node) %}
|
{%- if not field_logic.counter_incrsaturates(node) %}
|
||||||
end else begin
|
end else begin
|
||||||
field_combo.{{field_path}}.overflow = '0;
|
{{field_logic.get_field_combo_identifier(node, "overflow")}} = '0;
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
end
|
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) %}
|
{%- 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
|
if(next_c > {{field_logic.get_counter_incrsaturate_value(node)}}) begin
|
||||||
next_c = {{field_logic.get_counter_incrsaturate_value(node)}};
|
next_c = {{field_logic.get_counter_incrsaturate_value(node)}};
|
||||||
load_next_c = '1;
|
load_next_c = '1;
|
||||||
@@ -36,18 +36,18 @@
|
|||||||
next_c = next_c - {{field_logic.get_counter_decrvalue(node)}};
|
next_c = next_c - {{field_logic.get_counter_decrvalue(node)}};
|
||||||
end
|
end
|
||||||
{%- else %}
|
{%- 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)}};
|
next_c = next_c - {{field_logic.get_counter_decrvalue(node)}};
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
load_next_c = '1;
|
load_next_c = '1;
|
||||||
{%- if not field_logic.counter_decrsaturates(node) %}
|
{%- if not field_logic.counter_decrsaturates(node) %}
|
||||||
end else begin
|
end else begin
|
||||||
field_combo.{{field_path}}.underflow = '0;
|
{{field_logic.get_field_combo_identifier(node, "underflow")}} = '0;
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
end
|
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) %}
|
{%- 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
|
if(next_c < {{field_logic.get_counter_decrsaturate_value(node)}}) begin
|
||||||
next_c = {{field_logic.get_counter_decrsaturate_value(node)}};
|
next_c = {{field_logic.get_counter_decrsaturate_value(node)}};
|
||||||
load_next_c = '1;
|
load_next_c = '1;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{%- import 'field_logic/templates/counter_macros.sv' as counter_macros with context -%}
|
{%- import 'field_logic/templates/counter_macros.sv' as counter_macros with context -%}
|
||||||
// Field: {{node.get_path()}}
|
// Field: {{node.get_path()}}
|
||||||
always_comb begin
|
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;
|
automatic logic load_next_c = '0;
|
||||||
{%- for signal in extra_combo_signals %}
|
{%- 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 %}
|
{%- endfor %}
|
||||||
{% for conditional in conditionals %}
|
{% for conditional in conditionals %}
|
||||||
{%- if not loop.first %} else {% endif %}if({{conditional.get_predicate(node)}}) begin // {{conditional.comment}}
|
{%- 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 %}
|
{%- if node.is_down_counter %}
|
||||||
{{counter_macros.down_counter(node)}}
|
{{counter_macros.down_counter(node)}}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
field_combo.{{field_path}}.next = next_c;
|
{{field_logic.get_field_combo_identifier(node, "next")}} = next_c;
|
||||||
field_combo.{{field_path}}.load_next = load_next_c;
|
{{field_logic.get_field_combo_identifier(node, "load_next")}} = load_next_c;
|
||||||
end
|
end
|
||||||
always_ff {{get_always_ff_event(resetsignal)}} begin
|
always_ff {{get_always_ff_event(resetsignal)}} begin
|
||||||
{% if reset is not none -%}
|
{% if reset is not none -%}
|
||||||
if({{get_resetsignal(resetsignal)}}) begin
|
if({{get_resetsignal(resetsignal)}}) begin
|
||||||
field_storage.{{field_path}} <= {{reset}};
|
{{field_logic.get_storage_identifier(node)}} <= {{reset}};
|
||||||
end else {% endif %}if(field_combo.{{field_path}}.load_next) begin
|
end else {% endif %}if({{field_logic.get_field_combo_identifier(node, "load_next")}}) begin
|
||||||
field_storage.{{field_path}} <= field_combo.{{field_path}}.next;
|
{{field_logic.get_storage_identifier(node)}} <= {{field_logic.get_field_combo_identifier(node, "next")}};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user