Fix synthesizability of fields with msb0 ordering

This commit is contained in:
Alex Mykyta
2022-10-17 22:09:39 -07:00
parent e07e7d26b2
commit 808067fac9
7 changed files with 39 additions and 11 deletions

View File

@@ -1 +1 @@
__version__ = "0.7.0" __version__ = "0.8.0"

View File

@@ -152,6 +152,7 @@ class RegblockExporter:
context = { context = {
"module_name": module_name, "module_name": module_name,
"user_out_of_hier_signals": scanner.out_of_hier_signals.values(), "user_out_of_hier_signals": scanner.out_of_hier_signals.values(),
"has_writable_msb0_fields": scanner.has_writable_msb0_fields,
"cpuif": self.cpuif, "cpuif": self.cpuif,
"hwif": self.hwif, "hwif": self.hwif,
"get_resetsignal": self.dereferencer.get_resetsignal, "get_resetsignal": self.dereferencer.get_resetsignal,

View File

@@ -40,6 +40,14 @@ class _OnWrite(NextStateConditional):
high = max(min(high, accesswidth), 0) high = max(min(high, accesswidth), 0)
low = max(min(low, 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}]" return f"[{high}:{low}]"
def _wr_data(self, field: 'FieldNode', subword_idx: int=0) -> str: def _wr_data(self, field: 'FieldNode', subword_idx: int=0) -> str:
@@ -47,7 +55,7 @@ class _OnWrite(NextStateConditional):
if field.msb < field.lsb: if field.msb < field.lsb:
# Field gets bitswapped since it is in [low:high] orientation # Field gets bitswapped since it is in [low:high] orientation
value = f"{{<<{{decoded_wr_data{bslice}}}}}" value = f"decoded_wr_data_bswap{bslice}"
else: else:
value = f"decoded_wr_data{bslice}" value = f"decoded_wr_data{bslice}"
return value return value
@@ -57,7 +65,7 @@ class _OnWrite(NextStateConditional):
if field.msb < field.lsb: if field.msb < field.lsb:
# Field gets bitswapped since it is in [low:high] orientation # Field gets bitswapped since it is in [low:high] orientation
value = f"{{<<{{decoded_wr_biten{bslice}}}}}" value = f"decoded_wr_biten_bswap{bslice}"
else: else:
value = f"decoded_wr_biten{bslice}" value = f"decoded_wr_biten{bslice}"
return value return value

View File

@@ -96,6 +96,13 @@ module {{module_name}} (
assign decoded_req_is_wr = cpuif_req_is_wr; assign decoded_req_is_wr = cpuif_req_is_wr;
assign decoded_wr_data = cpuif_wr_data; assign decoded_wr_data = cpuif_wr_data;
assign decoded_wr_biten = cpuif_wr_biten; 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 // Writes are always granted with no error response
assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;

View File

@@ -25,6 +25,8 @@ class DesignScanner(RDLListener):
self.in_hier_signal_paths = set() # type: Set[str] self.in_hier_signal_paths = set() # type: Set[str]
self.out_of_hier_signals = OrderedDict() # type: OrderedDict[str, SignalNode] 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: def _get_out_of_hier_field_reset(self) -> None:
current_node = self.exp.top_node.parent current_node = self.exp.top_node.parent
while current_node is not None: while current_node is not None:
@@ -80,6 +82,7 @@ class DesignScanner(RDLListener):
self.in_hier_signal_paths.add(path) self.in_hier_signal_paths.add(path)
def enter_Field(self, node: 'FieldNode') -> None: def enter_Field(self, node: 'FieldNode') -> None:
# Collect any signals that are referenced by a property
for prop_name in node.list_properties(): for prop_name in node.list_properties():
value = node.get_property(prop_name) value = node.get_property(prop_name)
if isinstance(value, SignalNode): if isinstance(value, SignalNode):
@@ -89,3 +92,6 @@ class DesignScanner(RDLListener):
self.out_of_hier_signals[path] = value self.out_of_hier_signals[path] = value
else: else:
self.in_hier_signal_paths.add(path) self.in_hier_signal_paths.add(path)
if node.is_sw_writable and (node.msb < node.lsb):
self.has_writable_msb0_fields = True

View File

@@ -7,8 +7,10 @@ from . import Simulator
class Xilinx(Simulator): class Xilinx(Simulator):
""" """
Don't bother using the Xilinx simulator... Its buggy and extraordinarily slow. 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 As observed in v2021.1:
correctly - assignment statements get ignored or the values get mangled. - 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... Keeping this here in case someday it works better...
""" """
@@ -16,6 +18,7 @@ class Xilinx(Simulator):
cmd = [ cmd = [
"xvlog", "--sv", "xvlog", "--sv",
"--include", os.path.join(os.path.dirname(__file__), ".."), "--include", os.path.join(os.path.dirname(__file__), ".."),
"--define", "XSIM",
] ]
cmd.extend(self.tb_files) cmd.extend(self.tb_files)
subprocess.run(cmd, check=True) subprocess.run(cmd, check=True)

View File

@@ -71,10 +71,13 @@
cpuif.assert_read('h3000, 'h4DEAB000); cpuif.assert_read('h3000, 'h4DEAB000);
// rw_reg_lsb0 // rw_reg_lsb0
`ifndef XSIM
// Xilinx simulator has poor support for streaming operators. Skip
cpuif.assert_read('h3004, 0); cpuif.assert_read('h3004, 0);
cpuif.write('h3004, 'h4DEAB000); cpuif.write('h3004, 'h4DEAB000);
@cb; @cb;
assert({<<{cb.hwif_out.rw_reg_lsb0.f1.value}} == 8'hAB); assert({<<{cb.hwif_out.rw_reg_lsb0.f1.value}} == 8'hAB);
assert({<<{cb.hwif_out.rw_reg_lsb0.f2.value}} == 11'h4DE); assert({<<{cb.hwif_out.rw_reg_lsb0.f2.value}} == 11'h4DE);
cpuif.assert_read('h3004, 'h4DEAB000); cpuif.assert_read('h3004, 'h4DEAB000);
`endif
{% endblock %} {% endblock %}