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\Pinout;
|
||||||
use Targets\TargetDescriptionFiles\PinoutType;
|
use Targets\TargetDescriptionFiles\PinoutType;
|
||||||
use Targets\TargetDescriptionFiles\Variant;
|
use Targets\TargetDescriptionFiles\Variant;
|
||||||
|
use Targets\TargetPeripheral;
|
||||||
|
use Targets\TargetRegisterGroup;
|
||||||
|
|
||||||
require_once __DIR__ . '/../TargetDescriptionFile.php';
|
require_once __DIR__ . '/../TargetDescriptionFile.php';
|
||||||
|
|
||||||
@@ -150,6 +152,15 @@ class ValidationService
|
|||||||
$processedVariantNames[] = $variant->name;
|
$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;
|
return $failures;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,4 +926,59 @@ class ValidationService
|
|||||||
$failures
|
$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(
|
$output->registerGroups[] = $this->targetRegisterGroupFromRegisterGroup(
|
||||||
$registerGroupInstance->key,
|
$registerGroupInstance->key,
|
||||||
$registerGroupInstance->name,
|
$registerGroupInstance->name,
|
||||||
|
$registerGroupInstance->addressSpaceKey,
|
||||||
$registerGroup,
|
$registerGroup,
|
||||||
$registerGroupInstance->offset ?? 0,
|
$registerGroupInstance->offset ?? 0,
|
||||||
$peripheral->moduleKey
|
$peripheral->moduleKey
|
||||||
@@ -286,17 +287,19 @@ class TargetDescriptionFile
|
|||||||
private function targetRegisterGroupFromRegisterGroup(
|
private function targetRegisterGroupFromRegisterGroup(
|
||||||
string $key,
|
string $key,
|
||||||
string $name,
|
string $name,
|
||||||
|
string $addressSpaceKey,
|
||||||
RegisterGroup $registerGroup,
|
RegisterGroup $registerGroup,
|
||||||
int $addressOffset,
|
int $addressOffset,
|
||||||
string $moduleKey
|
string $moduleKey
|
||||||
): TargetRegisterGroup {
|
): TargetRegisterGroup {
|
||||||
$addressOffset += $registerGroup->offset ?? 0;
|
$addressOffset += $registerGroup->offset ?? 0;
|
||||||
$output = new TargetRegisterGroup($key, $name, $addressOffset, [], []);
|
$output = new TargetRegisterGroup($key, $name, $addressSpaceKey, $addressOffset, [], []);
|
||||||
|
|
||||||
foreach ($registerGroup->subgroups as $subgroup) {
|
foreach ($registerGroup->subgroups as $subgroup) {
|
||||||
$output->subgroups[] = $this->targetRegisterGroupFromRegisterGroup(
|
$output->subgroups[] = $this->targetRegisterGroupFromRegisterGroup(
|
||||||
$subgroup->key,
|
$subgroup->key,
|
||||||
$subgroup->name,
|
$subgroup->name,
|
||||||
|
$addressSpaceKey,
|
||||||
$subgroup,
|
$subgroup,
|
||||||
$addressOffset,
|
$addressOffset,
|
||||||
$moduleKey
|
$moduleKey
|
||||||
@@ -310,6 +313,7 @@ class TargetDescriptionFile
|
|||||||
$output->subgroups[] = $this->targetRegisterGroupFromRegisterGroup(
|
$output->subgroups[] = $this->targetRegisterGroupFromRegisterGroup(
|
||||||
$subgroupReference->key,
|
$subgroupReference->key,
|
||||||
$subgroupReference->name,
|
$subgroupReference->name,
|
||||||
|
$addressSpaceKey,
|
||||||
$subgroup,
|
$subgroup,
|
||||||
$addressOffset,
|
$addressOffset,
|
||||||
$moduleKey
|
$moduleKey
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class TargetRegisterGroup
|
|||||||
{
|
{
|
||||||
public ?string $key = null;
|
public ?string $key = null;
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
public ?string $addressSpaceKey = null;
|
||||||
public ?int $baseAddress = null;
|
public ?int $baseAddress = null;
|
||||||
|
|
||||||
/** @var TargetRegisterGroup[] */
|
/** @var TargetRegisterGroup[] */
|
||||||
@@ -28,10 +29,17 @@ class TargetRegisterGroup
|
|||||||
/** @var TargetRegister[] */
|
/** @var TargetRegister[] */
|
||||||
public array $registers = [];
|
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->key = $key;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
$this->addressSpaceKey = $addressSpaceKey;
|
||||||
$this->baseAddress = $baseAddress;
|
$this->baseAddress = $baseAddress;
|
||||||
$this->subgroups = $subgroups;
|
$this->subgroups = $subgroups;
|
||||||
$this->registers = $registers;
|
$this->registers = $registers;
|
||||||
|
|||||||
Reference in New Issue
Block a user