mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: enhance DMA and RIB functionality with burst support and performance tests
- Updated dma_error_tb to implement burst transfer handling and performance measurement for INCR4 transfers. - Introduced rib_burst_bus_tb to validate RIB burst arbitration and protocol compliance. - Added soc_rib_burst_ram_tb to test SRAM behavior with burst commands. - Created spill_register_tb to verify the functionality of the spill register under various conditions. - Modified test_dma.py to reflect changes in DMA error handling and performance reporting. - Updated test_memory_map.py to include new RIB burst interfaces and spill register utilities. - Enhanced test_rib_burst.py with directed tests for RIB burst building blocks and spill register behavior. - Adjusted test_soc_topology.py to ensure correct instantiation counts for RIB interfaces. - Improved test_user_extensions.py to validate the generation of isolated scalar bindings for burst interfaces.
This commit is contained in:
57 files changed
+3239
-727
No files matched your search
@@ -18,6 +18,7 @@ REQUIRED_FIELDS = {
|
||||
"op",
|
||||
"words",
|
||||
"checksum",
|
||||
"cycles",
|
||||
"mgmt_wait",
|
||||
"rib_wait",
|
||||
"sdram_wait",
|
||||
@@ -46,8 +47,11 @@ def parse_log(content: str) -> dict[str, object]:
|
||||
"operation": fields["op"],
|
||||
"words": parse_number(fields["words"]),
|
||||
"checksum": int(fields["checksum"], 16),
|
||||
"cycles": parse_number(fields["cycles"]),
|
||||
}
|
||||
for counter in sorted(REQUIRED_FIELDS - {"region", "op", "words", "checksum"}):
|
||||
for counter in sorted(
|
||||
REQUIRED_FIELDS - {"region", "op", "words", "checksum", "cycles"}
|
||||
):
|
||||
sample[counter] = parse_number(fields[counter])
|
||||
samples.append(sample)
|
||||
passed = PASS_MARKER in content
|
||||
|
||||
@@ -113,6 +113,25 @@ def regression_environment() -> dict[str, str]:
|
||||
return environment
|
||||
|
||||
|
||||
def with_netsim_boot_only(
|
||||
commands: tuple[tuple[str, tuple[str, ...]], ...],
|
||||
) -> tuple[tuple[str, tuple[str, ...]], ...]:
|
||||
"""Replace only the local netlist target and retain its selected firmware image."""
|
||||
transformed: list[tuple[str, tuple[str, ...]]] = []
|
||||
for profile, values in commands:
|
||||
if "netsim" not in values:
|
||||
transformed.append((profile, values))
|
||||
continue
|
||||
filtered = tuple(
|
||||
value
|
||||
for value in values
|
||||
if not value.startswith("SIM_SUCCESS_MARKER=")
|
||||
and value != "netsim"
|
||||
)
|
||||
transformed.append((profile, (*filtered, "netsim-boot")))
|
||||
return tuple(transformed)
|
||||
|
||||
|
||||
def run_command(
|
||||
command: list[str], root: Path, capture_output: bool, environment: dict[str, str]
|
||||
) -> str:
|
||||
@@ -157,11 +176,18 @@ def main() -> int:
|
||||
parser.add_argument("--suite", choices=("smoke", "pr", "nightly"), required=True)
|
||||
parser.add_argument("--pdk", choices=tuple(PDK_PR_PROFILES), help="run one PDK matrix")
|
||||
parser.add_argument("--dry-run", action="store_true")
|
||||
parser.add_argument(
|
||||
"--netsim-boot-only",
|
||||
action="store_true",
|
||||
help="locally stop each Icarus assembly netlist run after Hello retroSoC!",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
commands, profiles = select_regression(args.suite, args.pdk)
|
||||
except ValueError as error:
|
||||
parser.error(str(error))
|
||||
if args.netsim_boot_only:
|
||||
commands = with_netsim_boot_only(commands)
|
||||
environment = regression_environment()
|
||||
for profile, values in commands:
|
||||
command = ["make", f"CONFIG={profile}", *values]
|
||||
|
||||
+37
-1
@@ -18,6 +18,9 @@ sys.path.insert(0, str(ROOT))
|
||||
from scripts.setup_helpers import atomic_write # noqa: E402
|
||||
|
||||
|
||||
FAILURE_MARKER = re.compile(r"(?:\bFAILED?\b|\bFATAL\b|assertion failed|%Error)", re.IGNORECASE)
|
||||
|
||||
|
||||
def parse_env(values: list[str]) -> dict[str, str]:
|
||||
environment = os.environ.copy()
|
||||
for item in values:
|
||||
@@ -84,11 +87,21 @@ def main() -> int:
|
||||
action="store_true",
|
||||
help="stream child output byte-by-byte and preserve raw log bytes",
|
||||
)
|
||||
parser.add_argument("--success-marker", help="marker used by an opt-in early-stop flow")
|
||||
parser.add_argument(
|
||||
"--terminate-on-success-marker",
|
||||
action="store_true",
|
||||
help="terminate the child successfully after --success-marker is logged",
|
||||
)
|
||||
parser.add_argument("command", nargs=argparse.REMAINDER)
|
||||
args = parser.parse_args()
|
||||
command = args.command[1:] if args.command[:1] == ["--"] else args.command
|
||||
if not command:
|
||||
parser.error("a command is required after --")
|
||||
if args.terminate_on_success_marker and not args.success_marker:
|
||||
parser.error("--terminate-on-success-marker requires --success-marker")
|
||||
if args.terminate_on_success_marker and args.stream_bytes:
|
||||
parser.error("success-marker termination is unsupported with --stream-bytes")
|
||||
try:
|
||||
environment = parse_env(args.env)
|
||||
except ValueError as error:
|
||||
@@ -101,6 +114,8 @@ def main() -> int:
|
||||
returncode = 127
|
||||
error_message = None
|
||||
process: subprocess.Popen[str] | subprocess.Popen[bytes] | None = None
|
||||
marker_seen = False
|
||||
rejected_matches: list[str] = []
|
||||
try:
|
||||
if args.stream_bytes:
|
||||
log_context = args.log.open("wb")
|
||||
@@ -128,9 +143,23 @@ def main() -> int:
|
||||
for line in process.stdout:
|
||||
log.write(line)
|
||||
log.flush()
|
||||
match = FAILURE_MARKER.search(line)
|
||||
if match:
|
||||
rejected_matches.append(match.group(0))
|
||||
if should_display(args.tool, line):
|
||||
write_console_output(line)
|
||||
returncode = process.wait()
|
||||
if args.terminate_on_success_marker and args.success_marker in line:
|
||||
marker_seen = True
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait()
|
||||
returncode = 1 if rejected_matches else 0
|
||||
break
|
||||
if not marker_seen:
|
||||
returncode = process.wait()
|
||||
except KeyboardInterrupt:
|
||||
error_message = "interrupted"
|
||||
if process is not None and process.poll() is None:
|
||||
@@ -159,6 +188,13 @@ def main() -> int:
|
||||
}
|
||||
if error_message:
|
||||
result["error"] = error_message
|
||||
if args.success_marker:
|
||||
result["success_marker"] = args.success_marker
|
||||
result["success_marker_seen"] = marker_seen
|
||||
if marker_seen:
|
||||
result["completion_mode"] = "success_marker"
|
||||
if rejected_matches:
|
||||
result["rejected_matches"] = sorted(set(rejected_matches))
|
||||
atomic_write(args.result, json.dumps(result, indent=2, sort_keys=True) + "\n")
|
||||
return returncode
|
||||
|
||||
|
||||
Reference in new issue
Block a user