Fix synthesizability of fields with msb0 ordering
This commit is contained in:
@@ -1 +1 @@
|
||||
__version__ = "0.7.0"
|
||||
__version__ = "0.8.0"
|
||||
|
||||
@@ -152,6 +152,7 @@ class RegblockExporter:
|
||||
context = {
|
||||
"module_name": module_name,
|
||||
"user_out_of_hier_signals": scanner.out_of_hier_signals.values(),
|
||||
"has_writable_msb0_fields": scanner.has_writable_msb0_fields,
|
||||
"cpuif": self.cpuif,
|
||||
"hwif": self.hwif,
|
||||
"get_resetsignal": self.dereferencer.get_resetsignal,
|
||||
|
||||
@@ -40,6 +40,14 @@ class _OnWrite(NextStateConditional):
|
||||
high = max(min(high, accesswidth), 0)
|
||||
low = max(min(low, accesswidth), 0)
|
||||
|
||||
if field.msb < field.lsb:
|
||||
# slice is for an msb0 field.
|
||||
# mirror it
|
||||
bus_width = self.exp.cpuif.data_width
|
||||
low = bus_width - 1 - low
|
||||
high = bus_width - 1 - high
|
||||
low, high = high, low
|
||||
|
||||
return f"[{high}:{low}]"
|
||||
|
||||
def _wr_data(self, field: 'FieldNode', subword_idx: int=0) -> str:
|
||||
@@ -47,7 +55,7 @@ class _OnWrite(NextStateConditional):
|
||||
|
||||
if field.msb < field.lsb:
|
||||
# Field gets bitswapped since it is in [low:high] orientation
|
||||
value = f"{{<<{{decoded_wr_data{bslice}}}}}"
|
||||
value = f"decoded_wr_data_bswap{bslice}"
|
||||
else:
|
||||
value = f"decoded_wr_data{bslice}"
|
||||
return value
|
||||
@@ -57,7 +65,7 @@ class _OnWrite(NextStateConditional):
|
||||
|
||||
if field.msb < field.lsb:
|
||||
# Field gets bitswapped since it is in [low:high] orientation
|
||||
value = f"{{<<{{decoded_wr_biten{bslice}}}}}"
|
||||
value = f"decoded_wr_biten_bswap{bslice}"
|
||||
else:
|
||||
value = f"decoded_wr_biten{bslice}"
|
||||
return value
|
||||
|
||||
@@ -96,6 +96,13 @@ module {{module_name}} (
|
||||
assign decoded_req_is_wr = cpuif_req_is_wr;
|
||||
assign decoded_wr_data = cpuif_wr_data;
|
||||
assign decoded_wr_biten = cpuif_wr_biten;
|
||||
{% if has_writable_msb0_fields %}
|
||||
// bitswap for use by fields with msb0 ordering
|
||||
logic [{{cpuif.data_width-1}}:0] decoded_wr_data_bswap;
|
||||
logic [{{cpuif.data_width-1}}:0] decoded_wr_biten_bswap;
|
||||
assign decoded_wr_data_bswap = {<<{decoded_wr_data}};
|
||||
assign decoded_wr_biten_bswap = {<<{decoded_wr_biten}};
|
||||
{%- endif %}
|
||||
|
||||
// Writes are always granted with no error response
|
||||
assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
|
||||
|
||||
@@ -25,6 +25,8 @@ class DesignScanner(RDLListener):
|
||||
self.in_hier_signal_paths = set() # type: Set[str]
|
||||
self.out_of_hier_signals = OrderedDict() # type: OrderedDict[str, SignalNode]
|
||||
|
||||
self.has_writable_msb0_fields = False
|
||||
|
||||
def _get_out_of_hier_field_reset(self) -> None:
|
||||
current_node = self.exp.top_node.parent
|
||||
while current_node is not None:
|
||||
@@ -80,6 +82,7 @@ class DesignScanner(RDLListener):
|
||||
self.in_hier_signal_paths.add(path)
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
# Collect any signals that are referenced by a property
|
||||
for prop_name in node.list_properties():
|
||||
value = node.get_property(prop_name)
|
||||
if isinstance(value, SignalNode):
|
||||
@@ -89,3 +92,6 @@ class DesignScanner(RDLListener):
|
||||
self.out_of_hier_signals[path] = value
|
||||
else:
|
||||
self.in_hier_signal_paths.add(path)
|
||||
|
||||
if node.is_sw_writable and (node.msb < node.lsb):
|
||||
self.has_writable_msb0_fields = True
|
||||
|
||||
@@ -7,8 +7,10 @@ from . import Simulator
|
||||
class Xilinx(Simulator):
|
||||
"""
|
||||
Don't bother using the Xilinx simulator... Its buggy and extraordinarily slow.
|
||||
As observed in v2021.1, clocking block assignments do not seem to actually simulate
|
||||
correctly - assignment statements get ignored or the values get mangled.
|
||||
As observed in v2021.1:
|
||||
- clocking block assignments do not seem to actually simulate correctly.
|
||||
assignment statements get ignored or the values get mangled.
|
||||
- Streaming operators have all sorts of limitations.
|
||||
|
||||
Keeping this here in case someday it works better...
|
||||
"""
|
||||
@@ -16,6 +18,7 @@ class Xilinx(Simulator):
|
||||
cmd = [
|
||||
"xvlog", "--sv",
|
||||
"--include", os.path.join(os.path.dirname(__file__), ".."),
|
||||
"--define", "XSIM",
|
||||
]
|
||||
cmd.extend(self.tb_files)
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
@@ -71,10 +71,13 @@
|
||||
cpuif.assert_read('h3000, 'h4DEAB000);
|
||||
|
||||
// rw_reg_lsb0
|
||||
cpuif.assert_read('h3004, 0);
|
||||
cpuif.write('h3004, 'h4DEAB000);
|
||||
@cb;
|
||||
assert({<<{cb.hwif_out.rw_reg_lsb0.f1.value}} == 8'hAB);
|
||||
assert({<<{cb.hwif_out.rw_reg_lsb0.f2.value}} == 11'h4DE);
|
||||
cpuif.assert_read('h3004, 'h4DEAB000);
|
||||
`ifndef XSIM
|
||||
// Xilinx simulator has poor support for streaming operators. Skip
|
||||
cpuif.assert_read('h3004, 0);
|
||||
cpuif.write('h3004, 'h4DEAB000);
|
||||
@cb;
|
||||
assert({<<{cb.hwif_out.rw_reg_lsb0.f1.value}} == 8'hAB);
|
||||
assert({<<{cb.hwif_out.rw_reg_lsb0.f2.value}} == 11'h4DE);
|
||||
cpuif.assert_read('h3004, 'h4DEAB000);
|
||||
`endif
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user