Validating resolved target peripherals in TDF validation
This commit is contained in:
@@ -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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user