Validating resolved target peripherals in TDF validation

This commit is contained in:
Nav
2024-06-05 19:28:49 +01:00
parent 4e837218e5
commit 75c58310ad
4 changed files with 101 additions and 3 deletions

View File

@@ -61,4 +61,24 @@ class AddressSpace
)
);
}
/**
* Returns all memory segments that intercept with the given address range.
*
* @param int $startAddress
* @param int $endAddress
*
* @return MemorySegment[]
*/
public function findIntersectingMemorySegments(int $startAddress, int $endAddress): array
{
return array_filter(
$this->memorySegments,
function (MemorySegment $segment) use ($startAddress, $endAddress) : bool {
$segmentEndAddress = $segment->startAddress + $segment->size - 1;
return ($startAddress <= $segment->startAddress && $endAddress >= $segment->startAddress)
|| ($startAddress >= $segment->startAddress && $startAddress <= $segmentEndAddress);
}
);
}
}

View File

@@ -19,6 +19,8 @@ use Targets\TargetDescriptionFiles\Signal;
use Targets\TargetDescriptionFiles\Pinout;
use Targets\TargetDescriptionFiles\PinoutType;
use Targets\TargetDescriptionFiles\Variant;
use Targets\TargetPeripheral;
use Targets\TargetRegisterGroup;
require_once __DIR__ . '/../TargetDescriptionFile.php';
@@ -150,6 +152,15 @@ class ValidationService
$processedVariantNames[] = $variant->name;
}
// Validate resolved peripherals
foreach ($tdf->peripherals as $peripheral) {
if (($targetPeripheral = $tdf->getTargetPeripheral($peripheral->key)) === null) {
continue;
}
$failures = array_merge($failures, $this->validateTargetPeripheral($targetPeripheral, $tdf));
}
return $failures;
}
@@ -915,4 +926,59 @@ class ValidationService
$failures
);
}
protected function validateTargetPeripheral(TargetPeripheral $targetPeripheral, TargetDescriptionFile $tdf): array
{
$failures = [];
foreach ($targetPeripheral->registerGroups as $registerGroup) {
$failures = array_merge($failures, $this->validateTargetRegisterGroup($registerGroup, $tdf));;
}
return array_map(
fn (string $failure): string => 'Resolved target peripheral "' . $targetPeripheral->name
. '" validation failure: ' . $failure,
$failures
);
}
protected function validateTargetRegisterGroup(
TargetRegisterGroup $registerGroup,
TargetDescriptionFile $tdf
): array {
$failures = [];
if (
!empty($registerGroup->addressSpaceKey)
&& ($addressSpace = $tdf->getAddressSpace($registerGroup->addressSpaceKey)) instanceof AddressSpace
) {
foreach ($registerGroup->registers as $register) {
$intersectingSegments = $addressSpace->findIntersectingMemorySegments(
$register->address,
($register->address + $register->size - 1)
);
if (empty($intersectingSegments)) {
$failures[] = 'Register "' . $register->key . '" is not contained within any memory segment';
continue;
}
if (count($intersectingSegments) > 1) {
$segmentKeys = array_map(
fn (MemorySegment $segment): string => '"' . $segment->key . '"',
$intersectingSegments
);
$failures[] = 'Register "' . $register->key . '" spans multiple memory segments ('
. implode(',', $segmentKeys) . ')';
continue;
}
}
}
return array_map(
fn (string $failure): string => 'Target register group "' . $registerGroup->name
. '" validation failure: ' . $failure,
$failures
);
}
}

View File

@@ -273,6 +273,7 @@ class TargetDescriptionFile
$output->registerGroups[] = $this->targetRegisterGroupFromRegisterGroup(
$registerGroupInstance->key,
$registerGroupInstance->name,
$registerGroupInstance->addressSpaceKey,
$registerGroup,
$registerGroupInstance->offset ?? 0,
$peripheral->moduleKey
@@ -286,17 +287,19 @@ class TargetDescriptionFile
private function targetRegisterGroupFromRegisterGroup(
string $key,
string $name,
string $addressSpaceKey,
RegisterGroup $registerGroup,
int $addressOffset,
string $moduleKey
): TargetRegisterGroup {
$addressOffset += $registerGroup->offset ?? 0;
$output = new TargetRegisterGroup($key, $name, $addressOffset, [], []);
$output = new TargetRegisterGroup($key, $name, $addressSpaceKey, $addressOffset, [], []);
foreach ($registerGroup->subgroups as $subgroup) {
$output->subgroups[] = $this->targetRegisterGroupFromRegisterGroup(
$subgroup->key,
$subgroup->name,
$addressSpaceKey,
$subgroup,
$addressOffset,
$moduleKey
@@ -310,6 +313,7 @@ class TargetDescriptionFile
$output->subgroups[] = $this->targetRegisterGroupFromRegisterGroup(
$subgroupReference->key,
$subgroupReference->name,
$addressSpaceKey,
$subgroup,
$addressOffset,
$moduleKey

View File

@@ -20,6 +20,7 @@ class TargetRegisterGroup
{
public ?string $key = null;
public ?string $name = null;
public ?string $addressSpaceKey = null;
public ?int $baseAddress = null;
/** @var TargetRegisterGroup[] */
@@ -28,10 +29,17 @@ class TargetRegisterGroup
/** @var TargetRegister[] */
public array $registers = [];
public function __construct(?string $key, ?string $name, ?int $baseAddress, array $subgroups, array $registers)
{
public function __construct(
?string $key,
?string $name,
?string $addressSpaceKey,
?int $baseAddress,
array $subgroups,
array $registers
) {
$this->key = $key;
$this->name = $name;
$this->addressSpaceKey = $addressSpaceKey;
$this->baseAddress = $baseAddress;
$this->subgroups = $subgroups;
$this->registers = $registers;