Fix --unroll CLI argument to properly unroll arrays instead of repeating them (#5)
* Initial plan * Fix --unroll CLI argument to properly unroll arrays Updated check_is_array() method and all CPUIF implementations to correctly detect and handle unrolled array elements. When unroll=True, each array element is now treated as an individual instance instead of being repeated as an array. Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Add comprehensive tests for --unroll functionality Created tests to verify that array elements are correctly unrolled into individual instances when --unroll flag is used. Also fixed conftest.py fixture to keep temp files for later reference. Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>
This commit is contained in:
@@ -12,11 +12,16 @@ class APB3Cpuif(BaseCpuif):
|
||||
|
||||
def _port_declaration(self, child: AddressableNode) -> str:
|
||||
base = f"apb3_intf.master m_apb_{child.inst_name}"
|
||||
if child.array_dimensions is None:
|
||||
return base
|
||||
|
||||
# When unrolled, current_idx is set - append it to the name
|
||||
if child.current_idx is not None:
|
||||
return f"{base}_{'_'.join(map(str, child.current_idx))} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
base = f"{base}_{'_'.join(map(str, child.current_idx))}"
|
||||
|
||||
# Only add array dimensions if this should be treated as an array
|
||||
if self.check_is_array(child):
|
||||
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
|
||||
return base
|
||||
|
||||
@property
|
||||
def port_declaration(self) -> str:
|
||||
|
||||
@@ -54,11 +54,13 @@ class APB3CpuifFlat(BaseCpuif):
|
||||
|
||||
# Master signal
|
||||
base = f"m_apb_{node.inst_name}"
|
||||
if not node.is_array:
|
||||
if not self.check_is_array(node):
|
||||
# Not an array or an unrolled element
|
||||
if node.current_idx is not None:
|
||||
# This is a specific instance of an unrolled array
|
||||
return f"{base}_{signal}_{'_'.join(map(str, node.current_idx))}"
|
||||
return f"{base}_{signal}"
|
||||
if node.current_idx is not None:
|
||||
# This is a specific instance of an array
|
||||
return f"{base}_{signal}_{'_'.join(map(str, node.current_idx))}"
|
||||
# Is an array
|
||||
if idx is not None:
|
||||
return f"{base}_{signal}[{idx}]"
|
||||
return f"{base}_{signal}[N_{node.inst_name.upper()}S]"
|
||||
|
||||
@@ -12,11 +12,16 @@ class APB4Cpuif(BaseCpuif):
|
||||
|
||||
def _port_declaration(self, child: AddressableNode) -> str:
|
||||
base = f"apb4_intf.master m_apb_{child.inst_name}"
|
||||
if child.array_dimensions is None:
|
||||
return base
|
||||
|
||||
# When unrolled, current_idx is set - append it to the name
|
||||
if child.current_idx is not None:
|
||||
return f"{base}_{'_'.join(map(str, child.current_idx))} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
base = f"{base}_{'_'.join(map(str, child.current_idx))}"
|
||||
|
||||
# Only add array dimensions if this should be treated as an array
|
||||
if self.check_is_array(child):
|
||||
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
|
||||
return base
|
||||
|
||||
@property
|
||||
def port_declaration(self) -> str:
|
||||
|
||||
@@ -58,11 +58,13 @@ class APB4CpuifFlat(BaseCpuif):
|
||||
|
||||
# Master signal
|
||||
base = f"m_apb_{node.inst_name}"
|
||||
if not node.is_array:
|
||||
if not self.check_is_array(node):
|
||||
# Not an array or an unrolled element
|
||||
if node.current_idx is not None:
|
||||
# This is a specific instance of an unrolled array
|
||||
return f"{base}_{signal}_{'_'.join(map(str, node.current_idx))}"
|
||||
return f"{base}_{signal}"
|
||||
if node.current_idx is not None:
|
||||
# This is a specific instance of an array
|
||||
return f"{base}_{signal}_{'_'.join(map(str, node.current_idx))}"
|
||||
# Is an array
|
||||
if idx is not None:
|
||||
return f"{base}_{signal}[{idx}]"
|
||||
return f"{base}_{signal}[N_{node.inst_name.upper()}S]"
|
||||
|
||||
@@ -12,11 +12,16 @@ class AXI4LiteCpuif(BaseCpuif):
|
||||
|
||||
def _port_declaration(self, child: AddressableNode) -> str:
|
||||
base = f"axi4lite_intf.master m_axil_{child.inst_name}"
|
||||
if child.array_dimensions is None:
|
||||
return base
|
||||
|
||||
# When unrolled, current_idx is set - append it to the name
|
||||
if child.current_idx is not None:
|
||||
return f"{base}_{'_'.join(map(str, child.current_idx))} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
base = f"{base}_{'_'.join(map(str, child.current_idx))}"
|
||||
|
||||
# Only add array dimensions if this should be treated as an array
|
||||
if self.check_is_array(child):
|
||||
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||
|
||||
return base
|
||||
|
||||
@property
|
||||
def port_declaration(self) -> str:
|
||||
|
||||
@@ -71,7 +71,11 @@ class BaseCpuif:
|
||||
raise RuntimeError
|
||||
|
||||
def check_is_array(self, node: AddressableNode) -> bool:
|
||||
return node.is_array and not self.unroll
|
||||
# When unrolling is enabled, children(unroll=True) returns individual
|
||||
# array elements with current_idx set. These should NOT be treated as arrays.
|
||||
if self.unroll and hasattr(node, 'current_idx') and node.current_idx is not None:
|
||||
return False
|
||||
return node.is_array
|
||||
|
||||
def get_implementation(self) -> str:
|
||||
class_dir = self._get_template_path_class_dir()
|
||||
|
||||
Reference in New Issue
Block a user