Added additional TDF validation for pinouts and pin counts

This commit is contained in:
Nav
2021-06-09 22:50:32 +01:00
parent be1e978bb6
commit b119ee8c4b
4 changed files with 122 additions and 7 deletions

View File

@@ -19,7 +19,7 @@ class Avr8TargetDescriptionFile extends TargetDescriptionFile
const AVR8_PHYSICAL_INTERFACE_JTAG = 'JTAG'; const AVR8_PHYSICAL_INTERFACE_JTAG = 'JTAG';
const AVR8_PHYSICAL_INTERFACE_PDI = 'PDI'; const AVR8_PHYSICAL_INTERFACE_PDI = 'PDI';
const AVR8_PHYSICAL_INTERFACE_UPDI = 'UPDI'; const AVR8_PHYSICAL_INTERFACE_UPDI = 'UPDI';
const AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE = 'debugWire'; const AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE = 'DEBUG_WIRE';
public ?Signature $signature = null; public ?Signature $signature = null;
public ?string $family = null; public ?string $family = null;

View File

@@ -0,0 +1,8 @@
<?php
namespace Bloom\BuildScripts\TargetDescriptionFiles;
class Pin
{
public ?string $pad = null;
public ?int $position = null;
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Bloom\BuildScripts\TargetDescriptionFiles;
require_once __DIR__ . "/Pin.php";
class Pinout
{
const TYPE_SOIC = 'SOIC';
const TYPE_DIP = 'DIP';
const TYPE_QFN = 'QFN';
const TYPE_BGA = 'BGA';
public ?string $name = null;
public ?string $function = null;
public ?string $type = null;
/**
* The name of the pinouts typically include the number of pins. We extract this if we can, so that we can
* validate against it.
*
* For example, for an SOIC pinout with 20 pins, the name of the pinout would be something like "SOIC20"
* or "SOIC_20".
*
* @var int|null
*/
public ?int $expectedPinCount = null;
/** @var Pin[] */
public array $pins = [];
}

View File

@@ -10,11 +10,18 @@ require_once __DIR__ . "/PropertyGroup.php";
require_once __DIR__ . "/Module.php"; require_once __DIR__ . "/Module.php";
require_once __DIR__ . "/PhysicalInterface.php"; require_once __DIR__ . "/PhysicalInterface.php";
require_once __DIR__ . "/Signal.php"; require_once __DIR__ . "/Signal.php";
require_once __DIR__ . "/Pinout.php";
class TargetDescriptionFile class TargetDescriptionFile
{ {
const ARCHITECTURE_AVR8 = 'AVR8'; const ARCHITECTURE_AVR8 = 'AVR8';
public string $filePath;
public ?SimpleXMLElement $xml = null;
public ?string $targetName = null;
public ?string $targetArchitecture = null;
/** @var AddressSpace[] */ /** @var AddressSpace[] */
protected array $addressSpacesById = []; protected array $addressSpacesById = [];
@@ -30,15 +37,12 @@ class TargetDescriptionFile
/** @var PhysicalInterface[] */ /** @var PhysicalInterface[] */
protected array $physicalInterfacesByName = []; protected array $physicalInterfacesByName = [];
public string $filePath;
public ?SimpleXMLElement $xml = null;
public ?string $targetName = null;
public ?string $targetArchitecture = null;
/** @var Variant[] */ /** @var Variant[] */
public array $variants = []; public array $variants = [];
/** @var Pinout[] */
public array $pinoutsMappedByName = [];
public function __construct(string $filePath) public function __construct(string $filePath)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
@@ -78,6 +82,7 @@ class TargetDescriptionFile
$this->loadModules(); $this->loadModules();
$this->loadPeripheralModules(); $this->loadPeripheralModules();
$this->loadPhysicalInterfaces(); $this->loadPhysicalInterfaces();
$this->loadPinouts();
} }
protected function rawValueToInt(string $value): ?int protected function rawValueToInt(string $value): ?int
@@ -317,6 +322,50 @@ class TargetDescriptionFile
} }
} }
private function loadPinouts(): void
{
$pinoutElements = $this->xml->xpath('pinouts/pinout');
foreach ($pinoutElements as $pinoutElement) {
$pinoutAttrs = $pinoutElement->attributes();
$pinout = new Pinout();
$pinout->name = isset($pinoutAttrs['name']) ? $pinoutAttrs['name'] : null;
$pinout->function = isset($pinoutAttrs['function']) ? $pinoutAttrs['function'] : null;
if (stristr($pinout->name, Pinout::TYPE_DIP) !== false) {
$pinout->type = Pinout::TYPE_DIP;
} else if (stristr($pinout->name, Pinout::TYPE_SOIC) !== false) {
$pinout->type = Pinout::TYPE_SOIC;
} else if (stristr($pinout->name, Pinout::TYPE_QFN) !== false) {
$pinout->type = Pinout::TYPE_QFN;
} else if (stristr($pinout->name, Pinout::TYPE_BGA) !== false) {
$pinout->type = Pinout::TYPE_BGA;
}
// Attempt to extract the number of expected pins for this pinout, from the pinout name
$expectedPinCount = filter_var($pinout->name, FILTER_SANITIZE_NUMBER_INT);
if (is_numeric($expectedPinCount)) {
$pinout->expectedPinCount = (int) $expectedPinCount;
}
$pinElements = $pinoutElement->xpath('pin');
foreach ($pinElements as $pinElement) {
$pinAttrs = $pinElement->attributes();
$pin = new Pin();
$pin->pad = isset($pinAttrs['pad']) ? $pinAttrs['pad'] : null;
$pin->position = isset($pinAttrs['position']) ? $this->rawValueToInt($pinAttrs['position']) : null;
$pinout->pins[] = $pin;
}
$this->pinoutsMappedByName[strtolower($pinout->name)] = $pinout;
}
}
public function validate(): array public function validate(): array
{ {
$failures = []; $failures = [];
@@ -341,6 +390,34 @@ class TargetDescriptionFile
} }
} }
if (empty($this->pinoutsMappedByName)) {
$failures[] = 'No pinouts found';
}
foreach ($this->pinoutsMappedByName as $pinout) {
if (!is_null($pinout->expectedPinCount)) {
if ($pinout->expectedPinCount != count($pinout->pins)) {
$failures[] = 'Pin count (' . count($pinout->pins) . ') for pinout "' . $pinout->name
. '" does not match expected pin count (' . $pinout->expectedPinCount . ')';
}
} else {
$failures[] = 'Could not deduce expected pin count for pinout "' . $pinout->name . '"';
}
if (in_array($pinout->type, [Pinout::TYPE_DIP, Pinout::TYPE_QFN, Pinout::TYPE_SOIC])) {
foreach ($pinout->pins as $index => $pin) {
if (is_null($pin->position)) {
$failures[] = 'Missing/invalid pin position for pin (index: ' . $index . ').';
}
if (is_null($pin->pad)) {
$failures[] = 'Missing/invalid pin pad for pin (index: ' . $index . ').';
}
}
}
}
return $failures; return $failures;
} }
} }