From 7ac54ec259709ffa29c9ccd370d7f593b77d2228 Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 17 Feb 2024 21:44:02 +0000 Subject: [PATCH] Implemented parsing for new `register-group-instance` element in TDF scripts --- .../TargetDescriptionFiles/Peripheral.php | 18 ++--- .../RegisterGroupInstance.php | 30 ++++++++ .../Services/ValidationService.php | 75 +++++++++++++++++-- .../Services/Xml/FromXmlService.php | 19 ++++- .../Services/Xml/ToXmlService.php | 24 +++++- .../TargetDescriptionFile.php | 15 +++- 6 files changed, 157 insertions(+), 24 deletions(-) create mode 100644 build/scripts/Targets/TargetDescriptionFiles/RegisterGroupInstance.php diff --git a/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php b/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php index 59042f18..62eb5a5e 100644 --- a/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php +++ b/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php @@ -2,7 +2,7 @@ namespace Targets\TargetDescriptionFiles; require_once __DIR__ . "/RegisterGroup.php"; -require_once __DIR__ . "/RegisterGroupReference.php"; +require_once __DIR__ . "/RegisterGroupInstance.php"; require_once __DIR__ . "/Signal.php"; class Peripheral @@ -12,8 +12,8 @@ class Peripheral public ?string $moduleKey = null; public ?string $moduleName = null; - /** @var RegisterGroupReference[] */ - public array $registerGroupReferences = []; + /** @var RegisterGroupInstance[] */ + public array $registerGroupInstances = []; /** @var Signal[] */ public array $signals = []; @@ -22,21 +22,21 @@ class Peripheral ?string $key, ?string $name, ?string $moduleKey, - array $registerGroupReferences, + array $registerGroupInstances, array $signals ) { $this->key = $key; $this->name = $name; $this->moduleKey = $moduleKey; - $this->registerGroupReferences = $registerGroupReferences; + $this->registerGroupInstances = $registerGroupInstances; $this->signals = $signals; } - public function getRegisterGroupReference(string $key): ?RegisterGroupReference + public function getRegisterGroupInstance(string $key): ?RegisterGroupInstance { - foreach ($this->registerGroupReferences as $reference) { - if ($reference->key === $key) { - return $reference; + foreach ($this->registerGroupInstances as $instance) { + if ($instance->key === $key) { + return $instance; } } diff --git a/build/scripts/Targets/TargetDescriptionFiles/RegisterGroupInstance.php b/build/scripts/Targets/TargetDescriptionFiles/RegisterGroupInstance.php new file mode 100644 index 00000000..c928a54d --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/RegisterGroupInstance.php @@ -0,0 +1,30 @@ +key = $key; + $this->name = $name; + $this->registerGroupKey = $registerGroupKey; + $this->addressSpaceKey = $addressSpaceKey; + $this->offset = $offset; + $this->description = $description; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/Services/ValidationService.php b/build/scripts/Targets/TargetDescriptionFiles/Services/ValidationService.php index 1ae1e44b..42cee940 100644 --- a/build/scripts/Targets/TargetDescriptionFiles/Services/ValidationService.php +++ b/build/scripts/Targets/TargetDescriptionFiles/Services/ValidationService.php @@ -9,6 +9,7 @@ use Targets\TargetDescriptionFiles\MemorySegment; use Targets\TargetDescriptionFiles\MemorySegmentSection; use Targets\TargetDescriptionFiles\Module; use Targets\TargetDescriptionFiles\Peripheral; +use Targets\TargetDescriptionFiles\RegisterGroupInstance; use Targets\TargetDescriptionFiles\Property; use Targets\TargetDescriptionFiles\PropertyGroup; use Targets\TargetDescriptionFiles\Register; @@ -687,26 +688,26 @@ class ValidationService $failures[] = 'Missing module key'; } - if (empty($peripheral->registerGroupReferences) && empty($peripheral->signals)) { - $failures[] = 'Empty - no register group references or signals'; + if (empty($peripheral->registerGroupInstances) && empty($peripheral->signals)) { + $failures[] = 'Empty - no register group instances or signals'; } $processedChildKeys = []; - foreach ($peripheral->registerGroupReferences as $registerGroupReference) { + foreach ($peripheral->registerGroupInstances as $registerGroupInstance) { $failures = array_merge( $failures, - $this->validateRegisterGroupReference( - $registerGroupReference, + $this->validateRegisterGroupInstance( + $registerGroupInstance, $peripheral->moduleKey ?? '', $tdf ) ); - if ($registerGroupReference->key !== null && in_array($registerGroupReference->key, $processedChildKeys)) { - $failures[] = 'Duplicate register group reference key ("' . $registerGroupReference->key . '") detected'; + if ($registerGroupInstance->key !== null && in_array($registerGroupInstance->key, $processedChildKeys)) { + $failures[] = 'Duplicate register group instance key ("' . $registerGroupInstance->key . '") detected'; } - $processedChildKeys[] = $registerGroupReference->key; + $processedChildKeys[] = $registerGroupInstance->key; } foreach ($peripheral->signals as $signal) { @@ -719,6 +720,64 @@ class ValidationService ); } + protected function validateRegisterGroupInstance( + RegisterGroupInstance $registerGroupInstance, + string $moduleKey, + TargetDescriptionFile $tdf + ): array { + $failures = []; + + if (empty($registerGroupInstance->key)) { + $failures[] = 'Missing key'; + } + + if (!mb_check_encoding((string) $registerGroupInstance->key, 'ASCII')) { + $failures[] = 'Key contains non ASCII characters'; + } + + if (str_contains((string) $registerGroupInstance->key, ' ')) { + $failures[] = 'Key contains at least one period space'; + } + + if (str_contains((string) $registerGroupInstance->key, '.')) { + $failures[] = 'Key contains at least one period (".") character'; + } + + if (empty($registerGroupInstance->registerGroupKey)) { + $failures[] = 'Missing register group key'; + } + + if (empty($registerGroupInstance->name)) { + $failures[] = 'Missing name'; + } + + if ($registerGroupInstance->offset === null) { + $failures[] = 'Missing offset'; + + } elseif ($registerGroupInstance->offset > 0xFFFFFFFF) { + $failures[] = 'Offset exceeds 32-bit unsigned integer'; + } + + if (empty($registerGroupInstance->addressSpaceKey)) { + $failures[] = 'Missing address space key'; + + } elseif ($tdf->getAddressSpace($registerGroupInstance->addressSpaceKey) === null) { + $failures[] = 'Could not find address space "' . $registerGroupInstance->addressSpaceKey + . '" - check address space key'; + } + + if ($tdf->resolveRegisterGroupInstance($registerGroupInstance, $moduleKey) === null) { + $failures[] = 'Could not resolve register group instance "' . $registerGroupInstance->key + . '" - check register group key ("' . $registerGroupInstance->registerGroupKey . '")'; + } + + return array_map( + fn (string $failure): string => 'Register group instance (group key: "' + . $registerGroupInstance->registerGroupKey . '") validation failure: ' . $failure, + $failures + ); + } + protected function validateSignal(Signal $signal): array { $failures = []; diff --git a/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/FromXmlService.php b/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/FromXmlService.php index c8c628a0..5eca7ab7 100644 --- a/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/FromXmlService.php +++ b/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/FromXmlService.php @@ -14,6 +14,7 @@ use Targets\TargetDescriptionFiles\MemorySegmentSection; use Targets\TargetDescriptionFiles\MemorySegmentType; use Targets\TargetDescriptionFiles\Module; use Targets\TargetDescriptionFiles\Peripheral; +use Targets\TargetDescriptionFiles\RegisterGroupInstance; use Targets\TargetDescriptionFiles\PhysicalInterface; use Targets\TargetDescriptionFiles\Property; use Targets\TargetDescriptionFiles\PropertyGroup; @@ -325,8 +326,8 @@ class FromXmlService continue; } - if ($childNode->nodeName === 'register-group-reference') { - $output->registerGroupReferences[] = $this->registerGroupReferenceFromElement($childNode); + if ($childNode->nodeName === 'register-group-instance') { + $output->registerGroupInstances[] = $this->registerGroupInstanceFromElement($childNode); continue; } @@ -356,6 +357,20 @@ class FromXmlService return $output; } + public function registerGroupInstanceFromElement(DOMElement $element): RegisterGroupInstance + { + $attributes = $this->getNodeAttributesByName($element); + + return new RegisterGroupInstance( + $attributes['key'] ?? null, + $attributes['name'] ?? null, + $attributes['register-group-key'] ?? null, + $attributes['address-space-key'] ?? null, + $this->stringService->tryStringToInt($attributes['offset'] ?? null), + $attributes['description'] ?? null + ); + } + public function signalFromElement(DOMElement $element): Signal { $attributes = $this->getNodeAttributesByName($element); diff --git a/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/ToXmlService.php b/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/ToXmlService.php index bc4d98c6..3210f5ce 100644 --- a/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/ToXmlService.php +++ b/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/ToXmlService.php @@ -9,6 +9,7 @@ use Targets\TargetDescriptionFiles\MemorySegment; use Targets\TargetDescriptionFiles\MemorySegmentSection; use Targets\TargetDescriptionFiles\Module; use Targets\TargetDescriptionFiles\Peripheral; +use Targets\TargetDescriptionFiles\RegisterGroupInstance; use Targets\TargetDescriptionFiles\PhysicalInterface; use Targets\TargetDescriptionFiles\Pin; use Targets\TargetDescriptionFiles\Pinout; @@ -135,8 +136,8 @@ class ToXmlService $element->setAttribute('name', $peripheral->name); $element->setAttribute('module-key', $peripheral->moduleKey); - foreach ($peripheral->registerGroupReferences as $registerGroupReference) { - $element->append($this->registerGroupReferenceToXml($registerGroupReference, $document)); + foreach ($peripheral->registerGroupInstances as $registerGroupInstance) { + $element->append($this->registerGroupInstanceToXml($registerGroupInstance, $document)); } if (!empty($peripheral->signals)) { @@ -151,6 +152,25 @@ class ToXmlService return $element; } + public function registerGroupInstanceToXml( + RegisterGroupInstance $registerGroupInstance, + DOMDocument $document + ): DOMElement { + $element = $document->createElement('register-group-instance'); + $element->setAttribute('key', $registerGroupInstance->key); + $element->setAttribute('name', $registerGroupInstance->name); + + if (!empty($registerGroupInstance->description)) { + $element->setAttribute('description', $registerGroupInstance->description); + } + + $element->setAttribute('register-group-key', $registerGroupInstance->registerGroupKey); + $element->setAttribute('address-space-key', $registerGroupInstance->addressSpaceKey); + $element->setAttribute('offset', $this->stringService->tryIntToHex($registerGroupInstance->offset)); + + return $element; + } + public function signalToXml(Signal $signal, DOMDocument $document): DOMElement { $element = $document->createElement('signal'); diff --git a/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php b/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php index e5fc38c0..cb9a54c3 100644 --- a/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php +++ b/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php @@ -10,6 +10,7 @@ require_once __DIR__ . "/PropertyGroup.php"; require_once __DIR__ . "/AddressSpace.php"; require_once __DIR__ . "/PhysicalInterface.php"; require_once __DIR__ . "/Peripheral.php"; +require_once __DIR__ . "/RegisterGroupInstance.php"; require_once __DIR__ . "/Signal.php"; require_once __DIR__ . "/Module.php"; require_once __DIR__ . "/RegisterGroup.php"; @@ -246,6 +247,14 @@ class TargetDescriptionFile : null; } + public function resolveRegisterGroupInstance( + RegisterGroupInstance $registerGroupInstance, + string $moduleKey + ): ?RegisterGroup { + $module = $this->getModule($moduleKey); + return $module instanceof Module ? $module->getRegisterGroup($registerGroupInstance->registerGroupKey) : null; + } + public function resolveRegisterGroupReference( RegisterGroupReference $registerGroupReference, string $moduleKey @@ -258,12 +267,12 @@ class TargetDescriptionFile { $output = new TargetPeripheral($peripheral->name, []); - foreach ($peripheral->registerGroupReferences as $registerGroupReference) { - $registerGroup = $this->resolveRegisterGroupReference($registerGroupReference, $peripheral->moduleKey); + foreach ($peripheral->registerGroupInstances as $registerGroupInstance) { + $registerGroup = $this->resolveRegisterGroupInstance($registerGroupInstance, $peripheral->moduleKey); if ($registerGroup instanceof RegisterGroup) { $output->registerGroups[] = $this->targetRegisterGroupFromRegisterGroup( $registerGroup, - $registerGroupReference->offset ?? 0, + $registerGroupInstance->offset ?? 0, $peripheral->moduleKey ); }