From b1ac652a7f671addb80d080e24b628a603900ced Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 5 Jun 2021 22:41:12 +0100 Subject: [PATCH] Added derivation of TDF base class, for AVR8 targets. Includes initialisation and validation code. --- .../AVR8/Avr8TargetDescriptionFile.php | 431 ++++++++++++++++++ .../TargetDescriptionFiles/AddressSpace.php | 15 + .../TargetDescriptionFiles/Factory.php | 70 +++ .../TargetDescriptionFiles/MemorySegment.php | 11 + .../scripts/TargetDescriptionFiles/Module.php | 16 + .../TargetDescriptionFiles/ModuleInstance.php | 12 + .../PhysicalInterface.php | 8 + .../TargetDescriptionFiles/Property.php | 8 + .../TargetDescriptionFiles/PropertyGroup.php | 12 + .../TargetDescriptionFiles/Register.php | 9 + .../TargetDescriptionFiles/RegisterGroup.php | 13 + .../TargetDescriptionFile.php | 255 ++++++++++- .../TargetDescriptionFiles/Variant.php | 1 + 13 files changed, 850 insertions(+), 11 deletions(-) create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php create mode 100644 build/scripts/TargetDescriptionFiles/AddressSpace.php create mode 100644 build/scripts/TargetDescriptionFiles/Factory.php create mode 100644 build/scripts/TargetDescriptionFiles/MemorySegment.php create mode 100644 build/scripts/TargetDescriptionFiles/Module.php create mode 100644 build/scripts/TargetDescriptionFiles/ModuleInstance.php create mode 100644 build/scripts/TargetDescriptionFiles/PhysicalInterface.php create mode 100644 build/scripts/TargetDescriptionFiles/Property.php create mode 100644 build/scripts/TargetDescriptionFiles/PropertyGroup.php create mode 100644 build/scripts/TargetDescriptionFiles/Register.php create mode 100644 build/scripts/TargetDescriptionFiles/RegisterGroup.php diff --git a/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php b/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php new file mode 100644 index 00000000..2ac2f48e --- /dev/null +++ b/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php @@ -0,0 +1,431 @@ +xml->device; + if (empty($device)) { + return; + } + + $deviceAttributes = $device->attributes(); + + if (!empty($deviceAttributes['family'])) { + if (stristr($deviceAttributes['family'], 'xmega') !== false) { + $this->family = self::AVR8_FAMILY_XMEGA; + + } else if (stristr($deviceAttributes['family'], 'tiny') !== false) { + $this->family = self::AVR8_FAMILY_TINY; + + } else if (stristr($deviceAttributes['family'], 'mega') !== false) { + $this->family = self::AVR8_FAMILY_MEGA; + } + } + + if (isset($this->physicalInterfacesByName['debugwire'])) { + $this->debugPhysicalInterface = self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE; + + } else if (isset($this->physicalInterfacesByName['jtag'])) { + $this->debugPhysicalInterface = self::AVR8_PHYSICAL_INTERFACE_JTAG; + + } else if (isset($this->physicalInterfacesByName['updi'])) { + $this->debugPhysicalInterface = self::AVR8_PHYSICAL_INTERFACE_UPDI; + + } else if (isset($this->physicalInterfacesByName['pdi'])) { + $this->debugPhysicalInterface = self::AVR8_PHYSICAL_INTERFACE_PDI; + } + + $progAddressSpace = $this->addressSpacesById['prog'] ?? null; + if (!empty($progAddressSpace)) { + $flashMemorySegment = $progAddressSpace->memorySegmentsByTypeAndName['flash']['flash'] + ?? $progAddressSpace->memorySegmentsByTypeAndName['flash']['app_section'] ?? null; + $bootSectionMemorySegment = $progAddressSpace->memorySegmentsByTypeAndName['flash']['boot_section_1'] + ?? $progAddressSpace->memorySegmentsByTypeAndName['flash']['boot_section'] ?? null; + + if (!empty($flashMemorySegment)) { + $this->flashSize = $flashMemorySegment->size; + $this->flashStartAddress = $flashMemorySegment->startAddress; + $this->flashPageSize = $flashMemorySegment->pageSize; + } + + if (!empty($bootSectionMemorySegment)) { + $this->bootSectionSize = $bootSectionMemorySegment->size; + $this->bootSectionStartAddress = $bootSectionMemorySegment->startAddress; + } + } + + $dataAddressSpace = $this->addressSpacesById['data'] ?? null; + if (!empty($dataAddressSpace)) { + $ramMemorySegments = $dataAddressSpace->memorySegmentsByTypeAndName['ram'] ?? null; + $registerMemorySegments = $dataAddressSpace->memorySegmentsByTypeAndName['regs'] ?? null; + + if (!empty($ramMemorySegments)) { + $ramMemorySegment = reset($ramMemorySegments); + $this->ramSize = $ramMemorySegment->size; + $this->ramStartAddress = $ramMemorySegment->startAddress; + } + + if (!empty($registerMemorySegments)) { + $registerMemorySegment = reset($registerMemorySegments); + $this->gpRegisterSize = $registerMemorySegment->size; + $this->gpRegisterStartAddress = $registerMemorySegment->startAddress; + } + } + + $eepromAddressSpace = $this->addressSpacesById['eeprom'] ?? null; + if (!empty($eepromAddressSpace)) { + $eepromMemorySegments = $eepromAddressSpace->memorySegmentsByTypeAndName['eeprom'] ?? null; + + if (!empty($eepromMemorySegments)) { + $eepromMemorySegment = reset($eepromMemorySegments); + $this->eepromSize = $eepromMemorySegment->size; + $this->eepromPageSize = $eepromMemorySegment->pageSize; + } + } + + if (isset($this->propertyGroupsByName['ocd'])) { + $ocdProperties = $this->propertyGroupsByName['ocd']->propertiesMappedByName; + + $this->ocdRevision = isset($ocdProperties['ocd_revision']) ? (int) $ocdProperties['ocd_revision']->value : null; + $this->ocdDataRegister = isset($ocdProperties['ocd_datareg']) + ? $this->rawValueToInt($ocdProperties['ocd_datareg']->value) : null; + } + + if (isset($this->modulesByName['cpu'])) { + $cpuModule = $this->modulesByName['cpu']; + + if (isset($cpuModule->registerGroupsMappedByName['cpu'])) { + $cpuRegisterGroup = $cpuModule->registerGroupsMappedByName['cpu']; + + if (isset($cpuRegisterGroup->registersMappedByName['sreg'])) { + $statusRegister = $cpuRegisterGroup->registersMappedByName['sreg']; + $this->statusRegisterSize = $statusRegister->size; + $this->statusRegisterStartAddress = $statusRegister->offset; + } + + if (isset($cpuRegisterGroup->registersMappedByName['sp'])) { + $stackPointerRegister = $cpuRegisterGroup->registersMappedByName['sp']; + $this->stackPointerRegisterSize = $stackPointerRegister->size; + $this->stackPointerRegisterStartAddress = $stackPointerRegister->offset; + + } else { + if (isset($cpuRegisterGroup->registersMappedByName['spl'])) { + $stackPointerLowRegister = $cpuRegisterGroup->registersMappedByName['spl']; + $this->stackPointerRegisterSize = $stackPointerLowRegister->size; + $this->stackPointerRegisterStartAddress = $stackPointerLowRegister->offset; + + if (isset($cpuRegisterGroup->registersMappedByName['sph'])) { + $stackPointerHighRegister = $cpuRegisterGroup->registersMappedByName['sph']; + $this->stackPointerRegisterSize += $stackPointerHighRegister->size; + } + } + } + + if (isset($cpuRegisterGroup->registersMappedByName['spmcsr'])) { + $spmcsRegister = $cpuRegisterGroup->registersMappedByName['spmcsr']; + $this->spmcRegisterStartAddress = $spmcsRegister->offset; + + } else if (isset($cpuRegisterGroup->registersMappedByName['spmcr'])) { + $spmcRegister = $cpuRegisterGroup->registersMappedByName['spmcr']; + $this->spmcRegisterStartAddress = $spmcRegister->offset; + + } else { + if (isset($this->modulesByName['boot_load']) + && isset($this->modulesByName['boot_load']->registerGroupsMappedByName['boot_load']) + ) { + $bootLoadedModule = $this->modulesByName['boot_load']; + $bootLoaderRegisterGroup = $bootLoadedModule->registerGroupsMappedByName['boot_load']; + + if (isset($bootLoaderRegisterGroup->registersMappedByName['spmcr'])) { + $spmcRegister = $bootLoaderRegisterGroup->registersMappedByName['spmcr']; + $this->spmcRegisterStartAddress = $spmcRegister->offset; + + } else if (isset($bootLoaderRegisterGroup->registersMappedByName['spmcsr'])) { + $spmcsRegister = $bootLoaderRegisterGroup->registersMappedByName['spmcsr']; + $this->spmcRegisterStartAddress = $spmcsRegister->offset; + } + } + } + + if (isset($cpuRegisterGroup->registersMappedByName['osccal'])) { + $osccalRegister = $cpuRegisterGroup->registersMappedByName['osccal']; + $this->osccalAddress = $osccalRegister->offset; + } + } + } + + if (isset($this->modulesByName['eeprom'])) { + $eepromModule = $this->modulesByName['eeprom']; + + if (isset($eepromModule->registerGroupsMappedByName['eeprom'])) { + $eepromRegisterGroup = $eepromModule->registerGroupsMappedByName['eeprom']; + + if (isset($eepromRegisterGroup->registersMappedByName['eear'])) { + $eearRegister = $eepromRegisterGroup->registersMappedByName['eear']; + $this->eepromAddressRegisterLow = $eearRegister->offset; + $this->eepromAddressRegisterHigh = ($eearRegister->size == 2) + ? $eearRegister->offset + 1 : $eearRegister->offset; + + } else { + if (isset($eepromRegisterGroup->registersMappedByName['eearl'])) { + $eearlRegister = $eepromRegisterGroup->registersMappedByName['eearl']; + $this->eepromAddressRegisterLow = $eearlRegister->offset; + + if (isset($eepromRegisterGroup->registersMappedByName['eearh'])) { + $eearhRegister = $eepromRegisterGroup->registersMappedByName['eearh']; + $this->eepromAddressRegisterHigh = $eearhRegister->offset; + + } else { + $this->eepromAddressRegisterHigh = $eearlRegister->offset; + } + + } + } + + if (isset($eepromRegisterGroup->registersMappedByName['eedr'])) { + $eedrRegister = $eepromRegisterGroup->registersMappedByName['eedr']; + $this->eepromDataRegisterAddress = $eedrRegister->offset; + } + + if (isset($eepromRegisterGroup->registersMappedByName['eecr'])) { + $eecrRegister = $eepromRegisterGroup->registersMappedByName['eecr']; + $this->eepromControlRegisterAddress = $eecrRegister->offset; + } + } + } + + if (isset($this->propertyGroupsByName['pdi_interface'])) { + $pdiInterfacePropertyGroup = $this->propertyGroupsByName['pdi_interface']; + $pdiInterfacePropertiesByName = $pdiInterfacePropertyGroup->propertiesMappedByName; + + if (isset($pdiInterfacePropertiesByName['app_section_offset'])) { + $this->appSectionPdiOffset = isset($pdiInterfacePropertiesByName['app_section_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['app_section_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['boot_section_offset'])) { + $this->bootSectionPdiOffset = isset($pdiInterfacePropertiesByName['boot_section_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['boot_section_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['datamem_offset'])) { + $this->ramPdiOffset = isset($pdiInterfacePropertiesByName['datamem_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['datamem_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['eeprom_offset'])) { + $this->eepromPdiOffset = isset($pdiInterfacePropertiesByName['eeprom_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['eeprom_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['user_signatures_offset'])) { + $this->userSignaturesPdiOffset = isset($pdiInterfacePropertiesByName['user_signatures_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['user_signatures_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['prod_signatures_offset'])) { + $this->productSignaturesPdiOffset = isset($pdiInterfacePropertiesByName['prod_signatures_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['prod_signatures_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['fuse_registers_offset'])) { + $this->fuseRegistersPdiOffset = isset($pdiInterfacePropertiesByName['fuse_registers_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['fuse_registers_offset']->value) : null; + } + + if (isset($pdiInterfacePropertiesByName['lock_registers_offset'])) { + $this->lockRegistersPdiOffset = isset($pdiInterfacePropertiesByName['lock_registers_offset']->value) + ? $this->rawValueToInt($pdiInterfacePropertiesByName['lock_registers_offset']->value) : null; + } + + if (isset($this->peripheralModulesByName['nvm'])) { + $nvmModule = $this->peripheralModulesByName['nvm']; + + if (isset($nvmModule->instancesMappedByName['nvm'])) { + $nvmInstance = $nvmModule->instancesMappedByName['nvm']; + + if (isset($nvmInstance->registerGroupsMappedByName['nvm'])) { + $this->nvmBaseAddress = $nvmInstance->registerGroupsMappedByName['nvm']->offset; + } + } + } + } + } + + public function validate(): array + { + $failures = parent::validate(); + + if (is_null($this->debugPhysicalInterface)) { + $failures[] = 'Target does not support any known AVR8 debug interface - the TDF will need to be deleted.' + . ' Aborting validation.'; + return $failures; + } + + if (is_null($this->stackPointerRegisterStartAddress)) { + $failures[] = 'Missing stack pointer register start address.'; + } + + if (is_null($this->stackPointerRegisterSize)) { + $failures[] = 'Missing stack pointer register size.'; + } + + if (is_null($this->statusRegisterStartAddress)) { + $failures[] = 'Missing status register start address.'; + } + + if (is_null($this->statusRegisterSize)) { + $failures[] = 'Missing status register size.'; + } + + if (is_null($this->flashSize)) { + $failures[] = 'Missing flash size.'; + } + + if (is_null($this->flashPageSize)) { + $failures[] = 'Missing flash page size.'; + } + + if (is_null($this->flashStartAddress)) { + $failures[] = 'Missing flash start address.'; + } + + if (is_null($this->ramStartAddress)) { + $failures[] = 'Missing ram start address.'; + } + + if (is_null($this->eepromSize)) { + $failures[] = 'Missing eeprom size.'; + } + + if (is_null($this->eepromPageSize)) { + $failures[] = 'Missing eeprom page size.'; + } + + if ($this->debugPhysicalInterface == self::AVR8_PHYSICAL_INTERFACE_JTAG + || $this->debugPhysicalInterface == self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE + ) { + if (is_null($this->ocdRevision)) { + $failures[] = 'Missing OCD revision.'; + } + + if (is_null($this->ocdDataRegister)) { + $failures[] = 'Missing OCD data register address.'; + } + + if (is_null($this->spmcRegisterStartAddress)) { + $failures[] = 'Missing store program memory control register start address.'; + } + + if (is_null($this->osccalAddress)) { + $failures[] = 'Missing oscillator calibration register address.'; + } + } + + if ($this->debugPhysicalInterface == self::AVR8_PHYSICAL_INTERFACE_PDI) { + if (is_null($this->appSectionPdiOffset)) { + $failures[] = 'Missing app section PDI offset.'; + } + + if (is_null($this->bootSectionPdiOffset)) { + $failures[] = 'Missing boot section PDI offset.'; + } + + if (is_null($this->ramPdiOffset)) { + $failures[] = 'Missing datamem PDI offset.'; + } + + if (is_null($this->eepromPdiOffset)) { + $failures[] = 'Missing eeprom PDI offset.'; + } + + if (is_null($this->userSignaturesPdiOffset)) { + $failures[] = 'Missing user signatures PDI offset.'; + } + + if (is_null($this->productSignaturesPdiOffset)) { + $failures[] = 'Missing product signatures PDI offset.'; + } + + if (is_null($this->lockRegistersPdiOffset)) { + $failures[] = 'Missing lock registers PDI offset.'; + } + + if (is_null($this->nvmBaseAddress)) { + $failures[] = 'Missing nvm start address.'; + } + } + + return $failures; + } +} + +//$j = new Avr8TargetDescriptionFile( +// "/home/nav/Projects/Bloom/build/resources/TargetDescriptionFiles/AVR/AVR8/MEGAAVR/ATMEGA48P.xml" +//); +// +//$h = new Avr8TargetDescriptionFile( +// "/home/nav/Projects/Bloom/build/resources/TargetDescriptionFiles/AVR/AVR8_XMEGA/AVR_XMEGA/ATXMEGA16C4.xml" +//); +// +//$jj = $j->validate(); +// +//$hh = $h->validate(); +// +//echo "Done\n"; diff --git a/build/scripts/TargetDescriptionFiles/AddressSpace.php b/build/scripts/TargetDescriptionFiles/AddressSpace.php new file mode 100644 index 00000000..c4a9daea --- /dev/null +++ b/build/scripts/TargetDescriptionFiles/AddressSpace.php @@ -0,0 +1,15 @@ +targetArchitecture == TargetDescriptionFile::ARCHITECTURE_AVR8) { + $tdf = new Avr8TargetDescriptionFile($filePath); + } + + return $tdf; + } + + /** + * Loads all AVR8 target description files. + * + * @return Avr8TargetDescriptionFile[] + */ + public static function loadAvr8Tdfs(): array + { + /** @var Avr8TargetDescriptionFile[] $output */ + $output = []; + + foreach (self::loadXmlFiles(self::AVR8_TDF_PATH) as $xmlFile) { + $output[] = new Avr8TargetDescriptionFile($xmlFile->getPathname()); + } + + return $output; + } + + /** + * Recursively loads all XML files from a given directory. + * + * @param string $dirPath + * @return \SplFileInfo[] + */ + private static function loadXmlFiles(string $dirPath): array + { + $output = []; + + $directory = new \DirectoryIterator($dirPath); + foreach ($directory as $entry) { + if ($entry->isFile() && $entry->getExtension() == 'xml') { + $output[] = clone $entry; + + } else if ($entry->isDir() && !$entry->isDot()) { + $output = array_merge($output, self::loadXmlFiles($entry->getPathname())); + } + } + + return $output; + } +} diff --git a/build/scripts/TargetDescriptionFiles/MemorySegment.php b/build/scripts/TargetDescriptionFiles/MemorySegment.php new file mode 100644 index 00000000..d8991757 --- /dev/null +++ b/build/scripts/TargetDescriptionFiles/MemorySegment.php @@ -0,0 +1,11 @@ +init(); } - private function init() + protected function init() { if (!file_exists($this->filePath)) { throw new Exception("Invalid TDF file path - file does not exist."); @@ -41,12 +66,28 @@ class TargetDescriptionFile } if (!empty($deviceAttributes['architecture'])) { - $this->targetArchitecture = $device['architecture']; + $this->targetArchitecture = stristr($device['architecture'], 'avr') !== false + ? self::ARCHITECTURE_AVR8 : $device['architecture']; } } - $variantElements = $xml->xpath('variants/variant'); + $this->loadVariants(); + $this->loadAddressSpaces(); + $this->loadPropertyGroups(); + $this->loadModules(); + $this->loadPeripheralModules(); + $this->loadPhysicalInterfaces(); + } + protected function rawValueToInt(string $value): ?int + { + return stristr($value, '0x') !== false ? (int) hexdec($value) : + (strlen($value) > 0 ? (int) $value : null); + } + + private function loadVariants(): void + { + $variantElements = $this->xml->xpath('variants/variant'); foreach ($variantElements as $variantElement) { $variantAttributes = $variantElement->attributes(); $variant = new Variant(); @@ -71,6 +112,198 @@ class TargetDescriptionFile } } + private function loadAddressSpaces(): void + { + $addressSpaceElements = $this->xml->xpath('device/address-spaces/address-space'); + foreach ($addressSpaceElements as $addressSpaceElement) { + $addressSpaceAttrs = $addressSpaceElement->attributes(); + $addressSpace = new AddressSpace(); + + $addressSpace->id = isset($addressSpaceElement['id']) ? $addressSpaceElement['id'] : null; + if (is_null($addressSpace->id)) { + // All address spaces must have an ID - don't bother if one isn't found + continue; + } + + $addressSpace->name = isset($addressSpaceAttrs['name']) ? $addressSpaceAttrs['name'] : null; + $addressSpace->startAddress = isset($addressSpaceAttrs['start']) + ? $this->rawValueToInt($addressSpaceAttrs['start']) : null; + $addressSpace->size = isset($addressSpaceAttrs['size']) + ? $this->rawValueToInt($addressSpaceAttrs['size']) : null; + + $memorySegmentElements = $addressSpaceElement->xpath('memory-segment'); + foreach ($memorySegmentElements as $memorySegmentElement) { + $memorySegmentAttrs = $memorySegmentElement->attributes(); + $memorySegment = new MemorySegment(); + + $memorySegment->name = isset($memorySegmentAttrs['name']) ? $memorySegmentAttrs['name'] : null; + $memorySegment->startAddress = isset($memorySegmentAttrs['start']) + ? $this->rawValueToInt($memorySegmentAttrs['start']) : null; + $memorySegment->type = isset($memorySegmentAttrs['type']) ? $memorySegmentAttrs['type'] : null; + $memorySegment->size = isset($memorySegmentAttrs['size']) + ? $this->rawValueToInt($memorySegmentAttrs['size']) : null; + $memorySegment->pageSize = isset($memorySegmentAttrs['pagesize']) + ? $this->rawValueToInt($memorySegmentAttrs['pagesize']) : null; + + $addressSpace->memorySegmentsByTypeAndName[strtolower($memorySegment->type)] + [strtolower($memorySegment->name)] = $memorySegment; + } + + $this->addressSpacesById[strtolower($addressSpace->id)] = $addressSpace; + } + } + + private function loadPropertyGroups(): void + { + $propertyGroupElements = $this->xml->xpath('device/property-groups/property-group'); + foreach ($propertyGroupElements as $propertyGroupElement) { + $propertyGroupAttrs = $propertyGroupElement->attributes(); + $propertyGroup = new PropertyGroup(); + + $propertyGroup->name = isset($propertyGroupAttrs['name']) ? $propertyGroupAttrs['name'] : null; + if (empty($propertyGroup->name)) { + continue; + } + + $propertyElements = $propertyGroupElement->xpath('property'); + foreach ($propertyElements as $propertyElement) { + $propertyAttrs = $propertyElement->attributes(); + $property = new Property(); + + $property->name = isset($propertyAttrs['name']) ? $propertyAttrs['name'] : null; + if (empty($propertyGroup->name)) { + continue; + } + + $property->value = isset($propertyAttrs['value']) ? $propertyAttrs['value'] : null; + + $propertyGroup->propertiesMappedByName[strtolower($property->name)] = $property; + } + + $this->propertyGroupsByName[strtolower($propertyGroup->name)] = $propertyGroup; + } + } + + private function generateRegisterGroupFromElement(SimpleXMLElement $registerGroupElement): ?RegisterGroup + { + $registerGroupAttrs = $registerGroupElement->attributes(); + $registerGroup = new RegisterGroup(); + + $registerGroup->name = isset($registerGroupAttrs['name']) ? $registerGroupAttrs['name'] : null; + if (empty($registerGroup->name)) { + return null; + } + + $registerGroup->offset = isset($registerGroupAttrs['offset']) + ? $this->rawValueToInt($registerGroupAttrs['offset']) : null; + + $registerElements = $registerGroupElement->xpath('register'); + foreach ($registerElements as $registerElement) { + $registerAttrs = $registerElement->attributes(); + $register = new Register(); + + $register->name = isset($registerAttrs['name']) ? $registerAttrs['name'] : null; + if (empty($register->name)) { + continue; + } + + $register->offset = isset($registerAttrs['offset']) + ? $this->rawValueToInt($registerAttrs['offset']) : null; + $register->size = isset($registerAttrs['size']) + ? $this->rawValueToInt($registerAttrs['size']) : null; + + $registerGroup->registersMappedByName[strtolower($register->name)] = $register; + } + + return $registerGroup; + } + + private function generateModuleFromElement(SimpleXMLElement $moduleElement): ?Module + { + $moduleAttrs = $moduleElement->attributes(); + $module = new Module(); + + $module->name = isset($moduleAttrs['name']) ? $moduleAttrs['name'] : null; + if (empty($module->name)) { + return null; + } + + $registerGroupElements = $moduleElement->xpath('register-group'); + foreach ($registerGroupElements as $registerGroupElement) { + $registerGroup = $this->generateRegisterGroupFromElement($registerGroupElement); + + if ($registerGroup instanceof RegisterGroup) { + $module->registerGroupsMappedByName[strtolower($registerGroup->name)] = $registerGroup; + } + } + + $instanceElements = $moduleElement->xpath('instance'); + foreach ($instanceElements as $instanceElement) { + $instanceAttrs = $instanceElement->attributes(); + $moduleInstance = new ModuleInstance(); + + $moduleInstance->name = isset($instanceAttrs['name']) ? $instanceAttrs['name'] : null; + if (empty($moduleInstance->name)) { + continue; + } + + $registerGroupElements = $instanceElement->xpath('register-group'); + foreach ($registerGroupElements as $registerGroupElement) { + $registerGroup = $this->generateRegisterGroupFromElement($registerGroupElement); + + if ($registerGroup instanceof RegisterGroup) { + $moduleInstance->registerGroupsMappedByName[strtolower($registerGroup->name)] = $registerGroup; + } + } + + $module->instancesMappedByName[strtolower($moduleInstance->name)] = $moduleInstance; + } + + return $module; + } + + private function loadModules(): void + { + $moduleElements = $this->xml->xpath('modules/module'); + foreach ($moduleElements as $moduleElement) { + $module = $this->generateModuleFromElement($moduleElement); + + if ($module instanceof Module) { + $this->modulesByName[strtolower($module->name)] = $module; + } + } + } + + private function loadPeripheralModules(): void + { + $moduleElements = $this->xml->xpath('device/peripherals/module'); + foreach ($moduleElements as $moduleElement) { + $module = $this->generateModuleFromElement($moduleElement); + + if ($module instanceof Module) { + $this->peripheralModulesByName[strtolower($module->name)] = $module; + } + } + } + + private function loadPhysicalInterfaces(): void + { + $interfaceElements = $this->xml->xpath('device/interfaces/interface'); + foreach ($interfaceElements as $interfaceElement) { + $interfaceAttrs = $interfaceElement->attributes(); + $physicalInterface = new PhysicalInterface(); + + $physicalInterface->name = isset($interfaceAttrs['name']) ? $interfaceAttrs['name'] : null; + if (empty($physicalInterface->name)) { + continue; + } + + $physicalInterface->type = isset($interfaceAttrs['type']) ? $interfaceAttrs['type'] : null; + + $this->physicalInterfacesByName[strtolower($physicalInterface->name)] = $physicalInterface; + } + } + public function validate(): array { $failures = []; @@ -84,16 +317,16 @@ class TargetDescriptionFile } if (empty($this->variants)) { - $failures[] = 'Missing target variants'; +// $failures[] = 'Missing target variants'; } - foreach ($this->variants as $variant) { - $variantValidationFailures = $variant->validate(); - - if (!empty($variantValidationFailures)) { - $failures[] = 'Variant validation failures: ' . implode(", ", $variantValidationFailures); - } - } +// foreach ($this->variants as $variant) { +// $variantValidationFailures = $variant->validate(); +// +// if (!empty($variantValidationFailures)) { +// $failures[] = 'Variant validation failures: ' . implode(", ", $variantValidationFailures); +// } +// } return $failures; } diff --git a/build/scripts/TargetDescriptionFiles/Variant.php b/build/scripts/TargetDescriptionFiles/Variant.php index a8a18f78..988b2010 100644 --- a/build/scripts/TargetDescriptionFiles/Variant.php +++ b/build/scripts/TargetDescriptionFiles/Variant.php @@ -1,4 +1,5 @@