--- /dev/null
+# ignore the cache directory
+/cache/
+
<register name="TriggerAssertedCounter" address="0000" purpose="statistics">
<description>Number of clock cycles with trigger asserted</description>
- <field name="TriggerAssertedCounter" start="0" size="32" format="unsigned" />
+ <field name="TriggerAssertedCounter" start="0" bits="32" format="unsigned" />
</register>
</TrbNetEntity>
address="0000" repeat="4" purpose="status" mode="rw" >
<description>Current status of each port of the hub on each channel.</description>
<field name="PortStatusChannels"
- start="0" size="17" mode="r" purpose="status" format="bitmask">
+ start="0" bits="17" mode="r" purpose="status" format="bitmask">
</field>
</register>
</group>
address="0007" mode="rw" purpose ="config" >
<description>Wait time between write sequence and start signal.</description>
<field name="WaitBeforeStart"
- start="0" size="20" mode="rw" purpose="config" format="integer">
+ start="0" bits="20" mode="rw" purpose="config" format="integer">
<description>The number of MAPS clock cycles to wait after last write before sending the start signal. </description>
</field>
</register>
address="000c" mode="w" purpose ="trigger" >
<description>Trigger the init sequence.</description>
<field name="TriggerInitSeq"
- start="0" size="5" mode="w" purpose="trigger" format="bitmask">
+ start="0" bits="5" mode="w" purpose="trigger" format="bitmask">
<description>A bitmask to trigger the init sequence on individual JTAG chains. </description>
</field>
</register>
address="000d" mode="w" purpose ="trigger" >
<description>Trigger the init sequence.</description>
<field name="TriggerReset"
- start="0" size="5" mode="w" purpose="trigger" format="bitmask">
+ start="0" bits="5" mode="w" purpose="trigger" format="bitmask">
<description>A bitmask to trigger sending a reset pulse on individual JTAG chains </description>
</field>
</register>
address="000e" mode="w" purpose ="trigger" >
<description>Trigger sending a start pulse.</description>
<field name="TriggerStart"
- start="0" size="5" mode="w" purpose="trigger" format="bitmask">
+ start="0" bits="5" mode="w" purpose="trigger" format="bitmask">
<description>A bitmask to trigger sending a start pulse on individual JTAG chains </description>
</field>
</register>
address="000f" mode="w" purpose ="trigger" >
<description>Trigger running JTAG write.</description>
<field name="TriggerJtagRun"
- start="0" size="5" mode="w" purpose="trigger" format="bitmask">
+ start="0" bits="5" mode="w" purpose="trigger" format="bitmask">
<description>A bitmask to trigger writing the JTAG registers three times on individual JTAG chains </description>
</field>
</register>
address="0010" mode="rw" purpose="config" >
<description>Generate a reset before doing init sequence</description>
<field name="ResetBeforeInit"
- start="0" size="1" mode="rw" purpose="config" format="boolean">
+ start="0" mode="rw" purpose="config" format="boolean">
<description>Enable to send a reset pulse before starting init sequence</description>
</field>
</register>
address="0011" mode="rw" purpose="config" >
<description>Generate a reset after first register write sequence</description>
<field name="ResetAfterFirstWrite"
- start="0" size="1" mode="rw" purpose="config" format="boolean">
+ start="0" mode="rw" purpose="config" format="boolean">
<description>Enable to send a reset pulse after the first writing of JTAG registers</description>
</field>
</register>
address="0014" mode="w" purpose ="trigger" >
<description>Trigger writing all JTAG registers once</description>
<field name="TriggerWriteOnce"
- start="0" size="5" mode="w" purpose="trigger" format="bitmask">
+ start="0" bits="5" mode="w" purpose="trigger" format="bitmask">
<description>Trigger writing all JTAG registers once on individual JTAG chains</description>
</field>
</register>
<group name="JtagOverride"
address="0020" size="5" purpose="config" mode="rw" continuous="true">
<description>Sets fixed values for all outputs for JTAG and sensor control and inverts the outputs if needed. One register for each JTAG chain.</description>
- <register name="JtagOverride"
- address="0000" repeat="5" purpose="config" mode="rw" >
+ <register name="JtagOverrideRegister"
+ address="0000" repeat="5" >
<description>Sets fixed values for all outputs for JTAG and sensor control and inverts the outputs if needed. One register for each JTAG chain.</description>
<field name="InvertTDO"
- start="0" size="1" mode="rw" purpose="config" format="boolean">
+ start="0" format="boolean">
<description>Invert TDO input signal</description>
</field>
<field name="InvertTDI"
- start="2" size="1" mode="rw" purpose="config" format="boolean">
+ start="2" format="boolean">
<description>Invert TDI output signal</description>
</field>
<field name="InvertTMS"
- start="4" size="1" mode="rw" purpose="config" format="boolean">
+ start="4" format="boolean">
<description>Invert TMS output signal</description>
</field>
<field name="InvertTCK"
- start="6" size="1" mode="rw" purpose="config" format="boolean">
+ start="6" format="boolean">
<description>Invert TCK output signal</description>
</field>
<field name="InvertStart"
- start="8" size="1" mode="rw" purpose="config" format="boolean">
+ start="8" format="boolean">
<description>Invert Start output signal</description>
</field>
<field name="InvertReset"
- start="10" size="1" mode="rw" purpose="config" format="boolean">
+ start="10" format="boolean">
<description>Invert Reset output signal</description>
</field>
<field name="InvertClock"
- start="12" size="1" mode="rw" purpose="config" format="boolean">
+ start="12" format="boolean">
<description>Invert Clock output signal</description>
</field>
<field name="EnableTDO"
- start="1" size="1" mode="rw" purpose="config" format="boolean">
+ start="1" format="boolean">
<description>Enable TDO input signal</description>
</field>
<field name="EnableTDI"
- start="3" size="1" mode="rw" purpose="config" format="boolean">
+ start="3" format="boolean">
<description>Enable TDI output signal</description>
</field>
<field name="EnableTMS"
- start="5" size="1" mode="rw" purpose="config" format="boolean">
+ start="5" format="boolean">
<description>Enable TMS output signal</description>
</field>
<field name="EnableTCK"
- start="7" size="1" mode="rw" purpose="config" format="boolean">
+ start="7" format="boolean">
<description>Enable TCK output signal</description>
</field>
<field name="EnableStart"
- start="9" size="1" mode="rw" purpose="config" format="boolean">
+ start="9" format="boolean">
<description>Enable Start output signal</description>
</field>
<field name="EnableReset"
- start="11" size="1" mode="rw" purpose="config" format="boolean">
+ start="11" format="boolean">
<description>Enable Reset output signal</description>
</field>
<field name="EnableClock"
- start="13" size="1" mode="rw" purpose="config" format="boolean">
+ start="13" format="boolean">
<description>Enable Clock output signal</description>
</field>
</register>
<!--JTAG Status registers for each chain -->
<!--===========================================-->
<group name="JtagStatus"
- address="1800" size="40" purpose="status" mode="r" continuous="true">
+ address="1800" size="40" purpose="status" mode="r" continuous="true">
<group name="JtagStatusChain"
address="0000" size="8" repeat="5" purpose="status" mode="r" continuous="true">
<register name="JtagErrorCount1"
address="0002" purpose="status" mode="r" >
<description>Error counters for read and write operations on the JTAG chain</description>
<field name="ErrorsReadId"
- start="0" size="16" mode="r" purpose="status" format="integer" >
+ start="0" bits="16" mode="r" purpose="status" format="integer" >
<description>Number of read errors during "read id" operation</description>
</field>
<field name="ErrorsWrite"
- start="16" size="16" mode="r" purpose="status" format="integer" >
+ start="16" bits="16" mode="r" purpose="status" format="integer" >
<description>Number of read errors during write operation</description>
</field>
</register>
address="0003" purpose="status" mode="r" >
<description>Error counters for read and write operations on the JTAG chain</description>
<field name="ErrorsDataChanged"
- start="0" size="16" mode="r" purpose="status" format="integer" >
+ start="0" bits="16" mode="r" purpose="status" format="integer" >
<description>Number of times data read back from the sensor was not identical to the data written to the sensor.</description>
</field>
<field name="ErrorsSampling"
- start="16" size="16" mode="r" purpose="status" format="integer" >
+ start="16" bits="16" mode="r" purpose="status" format="integer" >
<description>Number of sampling errors of TDI signal. The signal from the sensor is sampled three times for each bit, all occurrences must be equal.</description>
</field>
</register>
address="0004" purpose="status" mode="r" >
<description>Number of times the JTAG controller run a full sequence</description>
<field name="JtagRunCounter"
- start="0" size="32" mode="r" purpose="status" format="integer" >
+ start="0" bits="32" mode="r" purpose="status" format="integer" >
</field>
</register>
<register name="JtagStatusFlags"
address="0005" purpose="status" mode="r" >
<description>Status flags of the JTAG chain</description>
<field name="JtagStarted"
- start="0" size="1" mode="r" purpose="status" format="boolean" >
+ start="0" mode="r" purpose="status" format="boolean" >
<description>JTAG has been started</description>
</field>
<field name="JtagLastSuccesful"
- start="4" size="1" mode="r" purpose="status" format="boolean" >
+ start="4" mode="r" purpose="status" format="boolean" >
<description>Last JTAG run was successful</description>
</field>
<field name="JtagLastDataChanged"
- start="8" size="1" mode="r" purpose="status" format="boolean" >
+ start="8" mode="r" purpose="status" format="boolean" >
<description>Data in the sensor was corrupted at last JTAG run</description>
</field>
<field name="JtagLastWriteError"
- start="12" size="1" mode="r" purpose="status" format="boolean" >
+ start="12" mode="r" purpose="status" format="boolean" >
<description>Last run had a JTAG write error</description>
</field>
<field name="JtagLastReadError"
- start="16" size="1" mode="r" purpose="status" format="boolean" >
+ start="16" mode="r" purpose="status" format="boolean" >
<description>Last run had a JTAG read error</description>
</field>
<field name="JtagCrcError"
- start="20" size="1" mode="r" purpose="status" format="boolean" >
+ start="20" mode="r" purpose="status" format="boolean" >
<description>Last run had a JTAG CRC error</description>
</field>
</register>
<!--===========================================-->
<register name="Channel" address="0000" mode="r" repeat="65">
<description>Channel-specific information</description>
- <field name="HitCounter" start="0" size="24" format="unsigned" purpose="statistics">
+ <field name="HitCounter" start="0" bits="24" format="unsigned" purpose="statistics">
<description>Number of detected hits in channel</description>
</field>
- <field name="InputState" start="31" size="1" format="enum" purpose="status">
+ <field name="InputState" start="31" bits="1" format="enum" purpose="status">
<description>State of LVDS input buffer</description>
<enumItem value="0">Low</enumItem>
<enumItem value="1">High</enumItem>
<group name="Status" purpose="statistics" address="0100" mode="r" continuous="true">
<register name="BasicStatus" address="0000" purpose="status">
<description>Basic config and status information for all channels</description>
- <field name="ReadoutFSM" start="0" size="4" format="enum" purpose="status">
+ <field name="ReadoutFSM" start="0" bits="4" format="enum" purpose="status">
<description>Debug word of the TDC readout FSM</description>
<enumItem value="1">IDLE</enumItem>
<enumItem value="2">WAIT_FOR_TRG_WIND_END</enumItem>
<enumItem value="9">SEND_TRG_RELEASE_B</enumItem>
<enumItem value="F">OTHERS</enumItem>
</field>
- <field name="WriteoutFSM" start="4" size="4" format="enum">
+ <field name="WriteoutFSM" start="4" bits="4" format="enum">
<description>Debug word of the TDC writeout FSM</description>
<enumItem value="1">IDLE</enumItem>
<enumItem value="2">WR_CH</enumItem>
<enumItem value="F">OTHERS</enumItem>
</field>
- <field name="ChannelCount" start="8" size="8" format="unsigned">
+ <field name="ChannelCount" start="8" bits="8" format="unsigned">
<description>Number of implemented channels</description>
</field>
<field name="RefTimeSyncedTo100" start="16" format="boolean">
<description>Reference time synchronised to 100 MHz Trb-Net
clock</description>
</field>
- <field name="TriggerType" start="28" size="4" format="boolean" mode="rw" purpose="config">
+ <field name="TriggerType" start="28" bits="4" format="boolean" mode="rw" purpose="config">
<description>Trigger type</description>
</field>
</register>
<memory name="EmptyChannels" address="0001" size="2" mode="w" purpose="trigger">
<description>Empty the signals/hits of the specific channel. LSB
is channel 1.</description>
- <field name="Mask" start="0" size="64" format="bitmask" />
+ <field name="EmptyChannels" start="0" bits="64" format="bitmask" />
</memory>
<register name="TriggerWindowStatus" address="0003" purpose="status">
<description>Status of the TriggerWindow feature</description>
- <field name="TriggerWindowBeforeValue" start="0" size="11" format="time" unit="ns" scale="5">
+ <field name="TriggerWindowBeforeValue" start="0" bits="11" format="time" unit="ns" scale="5">
<description>Trigger window width BEFORE the trigger with
granularity of 5 ns</description>
</field>
- <field name="TriggerWindowAfterValue" start="16" size="11" format="time" unit="ns" scale="5">
+ <field name="TriggerWindowAfterValue" start="16" bits="11" format="time" unit="ns" scale="5">
<description>Trigger window width AFTER the trigger with
granularity of 5 ns</description>
</field>
<register name="TriggerCounter" address="0004">
<description>Number of valid triggers received</description>
- <field name="TriggerCounter" start="0" size="24" format="unsigned" />
+ <field name="TriggerCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="TimingTriggerCounter" address="0005">
<description>Number of valid timing triggers
received</description>
- <field name="TimingTriggerCounter" start="0" size="24" format="unsigned" />
+ <field name="TimingTriggerCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="NoTimingTriggerCounter" address="0006">
<description>Number of valid triggers received which are not
timing triggers</description>
- <field name="NoTimingTriggerCounter" start="0" size="24" format="unsigned" />
+ <field name="NoTimingTriggerCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="InvalidTriggerCounter" address="0007">
<description>Number of invalid triggers received</description>
- <field name="InvalidTriggerCounter" start="0" size="24" format="unsigned" />
+ <field name="InvalidTriggerCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="MultiTimingTriggerCounter" address="0008">
<description>Number of multi timing triggers received (triggers
received before trigger is released)</description>
- <field name="MultiTimingTriggerCounter" start="0" size="24" format="unsigned" />
+ <field name="MultiTimingTriggerCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="SpuriousTriggerCounter" address="0009">
<description>Number of spurious triggers received (in case of
timing trigger is validated although it was a
timing-trigger-less trigger)</description>
- <field name="SpuriousTriggerCounter" start="0" size="24" format="unsigned" />
+ <field name="SpuriousTriggerCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="WrongReadoutsCounter" address="000a">
<description>Number of wrong readouts due to spurious
triggers</description>
- <field name="WrongReadoutsCounter" start="0" size="24" format="unsigned" />
+ <field name="WrongReadoutsCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="SpikesCounter" address="000b">
<description>Number of spikes (pulses narrower than 40 ns)
detected at the timing trigger input</description>
- <field name="SpikesCounter" start="0" size="24" format="unsigned" />
+ <field name="SpikesCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="IdleTime" address="000c">
<description>Total time length, that the readout FSM waited in
the idle state (with granularity of 10 ns)</description>
- <field name="IdleTime" start="0" size="24" format="time" unit="ns" scale="10" />
+ <field name="IdleTime" start="0" bits="24" format="time" unit="ns" scale="10" />
</register>
<register name="WaitTime" address="000d">
<description>Total time length, that the readout FSM waited in
the wait states (with granularity of 10 ns)</description>
- <field name="WaitTime" start="0" size="24" format="time" unit="ns" scale="10" />
+ <field name="WaitTime" start="0" bits="24" format="time" unit="ns" scale="10" />
</register>
<register name="TotalEmptyChannelsCounter" address="000e">
<description>Total number of empty channels since the last reset
signal</description>
- <field name="TotalEmptyChannelsCounter" start="0" size="24" format="unsigned" />
+ <field name="TotalEmptyChannelsCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="ReleaseCounter" address="000f">
<description>Number of release signals sent</description>
- <field name="ReleaseCounter" start="0" size="24" format="unsigned" />
+ <field name="ReleaseCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="ReadoutTime" address="0010">
<description>Total time length of the readout process (with
granularity of 10 ns)</description>
- <field name="ReadoutTime" start="0" size="24" format="time" unit="ns" scale="10" />
+ <field name="ReadoutTime" start="0" bits="24" format="time" unit="ns" scale="10" />
</register>
<register name="TimeoutCounter" address="0011">
<description>Number of timeouts detected (too long delay after
the timing trigger)</description>
- <field name="TimeoutCounter" start="0" size="24" format="unsigned" />
+ <field name="TimeoutCounter" start="0" bits="24" format="unsigned" />
</register>
<register name="FinishedCounter" address="0012">
<description>Number of sent finished signals</description>
- <field name="FinishedCounter" start="0" size="24" format="unsigned" />
+ <field name="FinishedCounter" start="0" bits="24" format="unsigned" />
</register>
</group>
address="0800" purpose="config" mode="rw" continuous="true">
<register name="BasicControl" address="0000">
<description>Basic control for all channels</description>
- <field name="DebugOutput" start="0" size="4" format="enum">
+ <field name="DebugOutput" start="0" bits="4" format="enum">
<description>Enables different signals to the HPLA* output for
debugging with logic analyser</description>
</field>
<field name="ResetCounters" start="8" purpose="trigger" mode="w">
<description>Resets the internal counters</description>
</field>
- <field name="TriggerMode" start="0" size="12" format="enum">
+ <field name="TriggerMode" start="0" bits="12" format="enum">
<description>Select the trigger mode: With trigger mode or
trigger-less mode</description>
<enumItem value="0">TRIGGERED</enumItem>
<register name="TriggerWindowConfig" address="0001">
<description>Configuration of the TriggerWindow feature</description>
- <field name="TriggerWindowBefore" start="0" size="11" format="time" unit="ns" scale="5">
+ <field name="TriggerWindowBefore" start="0" bits="11" format="time" unit="ns" scale="5">
<description>Trigger window width BEFORE the trigger with
granularity of 5 ns</description>
</field>
- <field name="TriggerWindowAfter" start="16" size="11" format="time" unit="ns" scale="5">
+ <field name="TriggerWindowAfter" start="16" bits="11" format="time" unit="ns" scale="5">
<description>Trigger window width AFTER the trigger with
granularity of 5 ns. ATTENTION: Minimum value is x"00f"!</description>
</field>
<memory name="ChannelEnable" address="0002" size="2">
<description>Enable signals/hits of the specific channel. LSB is
channel 1.</description>
- <field name="ChannelEnable" start="0" size="64" format="bitmask" />
+ <field name="ChannelEnable" start="0" bits="64" format="bitmask" />
</memory>
<register name="DataTransferLimit" address="0004">
<description>Configuration of the data transfer limit feature</description>
- <field name="MaxWords" start="0" size="8" format="unsigned">
+ <field name="MaxWords" start="0" bits="8" format="unsigned">
<description>Defines number of data words per channel to be
read-out. Set it to 0x80 for full readout.</description>
</field>
<group name="StatusRegisters" address="0000">
<register name="CommonStatus0" address="0000" purpose="status">
<description>Common Status Register 0</description>
- <field name="Temperature" start="20" size="12" format="integer" unit="°C" scale=".0625" >
+ <field name="Temperature" start="20" bits="12" format="integer" unit="°C" scale=".0625" >
<description>Board temperature</description>
</field>
</register>
<register name="IPUHandlerStatus" address="0202" purpose="status">
<description>IPU handler status register</description>
- <field name="IPUHandlerStatusState" start="0" size="4" format="enum">
+ <field name="IPUHandlerStatusState" start="0" bits="4" format="enum">
<description>FSM state bits</description>
<enumItem value="0">IDLE</enumItem>
<enumItem value="1">WaitForLength</enumItem>
<xs:attribute name="purpose" type="purposetype" />
<xs:attribute name="start" type="bittype" />
<xs:attribute name="size" type="xs:positiveInteger" />
+ <xs:attribute name="bits" type="xs:positiveInteger" />
<xs:attribute name="defaultValue" type="xs:string" />
<xs:attribute name="value" type="valuetype" />
<xs:attribute name="format" type="formattype" />
<xs:attribute ref="name" use="required" />
<!-- "start" (and "address" in basicTrbdata) should usually be
- provided in the database, but this is verified only
- programmatically. If it was required here, setup files
- would become more complicated as they need to be... -->
- <xs:attribute ref="start" />
- <xs:attribute ref="size" />
+ provided in the database -->
+ <xs:attribute ref="start" use="required" />
+ <xs:attribute ref="bits" />
<xs:attribute ref="purpose" />
<xs:attribute ref="mode" />
<!-- if the default value of that field is not 0x0 (in the
</xs:complexType>
<!-- although requiring "entity global" unique names usually leads
- to redundant naming schemes, its makes minor modifications to
- entities very easy to specify (which is desirable in setup files) -->
+ to redundant naming schemes, but addressing things gets less
+ confusing -->
<xs:unique name="UniqueFieldNames">
<xs:selector xpath=".//field" />
<xs:field xpath="@name" />
</xs:unique>
<xs:unique name="UniqueTrbDataNames">
- <xs:selector xpath=".//register | .//memory | .//fifo" />
- <xs:field xpath="@name" />
- </xs:unique>
- <xs:unique name="UniqueGroupNames">
- <xs:selector xpath=".//group" />
+ <xs:selector xpath=".//group | .//register | .//memory | .//fifo" />
<xs:field xpath="@name" />
</xs:unique>
use File::chdir;
use FindBin qw($RealBin);
use Data::Dumper;
+use Storable qw(lock_store);
# some default config options
my $verbose = 0;
my $warnings = 1;
my $dir = $RealBin;
-my $dump_database = 0;
+my $dump = 0;
my $force = 0;
Getopt::Long::Configure(qw(gnu_getopt));
'verbose|v+' => \$verbose,
'warnings|w!' => \$warnings,
'dir=s' => \$dir,
- 'dump' => \$dump_database,
+ 'dump' => \$dump,
'force|f=s' => \$force
) or pod2usage(2);
pod2usage(1) if $help;
# jump to subroutine which handles the job,
# depending on the options
-if ($dump_database) {
- &DumpDatabase;
-} else {
- &Main;
-}
+&Main;
sub Main {
+ # ensure a cache directory exists
+ local $CWD = $dir;
+ (mkdir 'cache' or die "Can't create cache directory") unless -d 'cache';
+
+ my @docs;
+ {
+ my %filter;
+ foreach (@ARGV) {
+ $_ = "$_.xml" unless /\.xml$/;
+ $filter{$_} = 1;
+ }
+ my $num = scalar @ARGV;
+ local $CWD = $db_dir;
+ while (<*.xml>) {
+ next if $num>0 and not defined $filter{$_};
+ my $doc = LoadXML($_);
+ if ($dump) {
+ DumpDocument($doc);
+ next;
+ }
+ push(@docs, $doc);
+ }
+ }
+
+ foreach my $doc (@docs) {
+ my $db = WorkOnDoc($doc);
+ #print Dumper($db->{'BasicStatus'});
+ #print Dumper($db->{'ChannelEnable'});
+ #print Dumper($db->{'ReadoutFSM'});
+ #print Dumper($db->{'JtagRunCounter'});
+ #print Dumper($db->{'TriggerStart'});
+ #print DumpTree($db);
+ my $name = $doc->getDocumentElement->getAttribute('name');
+ my $cachefile = "cache/$name.entity";
+ lock_store($db, $cachefile);
+ print STDERR "Wrote $cachefile\n" if $verbose>0;
+ #print DumpTree($db);
+ }
+
+
+}
+sub WorkOnDoc {
+ my $doc = shift;
+ my $db = {};
+
+ # we populate first the db. then we can check when adding the
+ # children that they exist, and we can also handle the special case
+ # when a node has the same name as the single field it contains
+ my $nodelist = $doc->findnodes('//register | //memory | //fifo | //group');
+ foreach my $node (@$nodelist) {
+ my $name = $node->getAttribute('name');
+ # this check should also be enforced by the schema, but
+ # double-check can't harm
+ PrintMessage($node, "Fatal Error: Name $name is not unique", 1) if defined $db->{$name};
+ $db->{$name} = MakeOrMergeDbItem($node);
+ }
+
+ # now add the children and the fields
+ foreach my $node (@$nodelist) {
+ my $name = $node->getAttribute('name');
+ my $dbitem = $db->{$name};
+
+ #print $n->nodeName," ",$name," ",$children->size,"\n";
+
+ my $children = $node->findnodes('group | register | memory | fifo | field');
+
+ # if there's only one child...
+ if ($children->size==1) {
+ my $childnode = $children->get_node(1);
+ my $childname = $childnode->getAttribute('name');
+ # ...and it's a field with the same name as the parent,
+ # we merge that
+ if ($childnode->nodeName eq 'field' and $childname eq $name) {
+ PrintMessage($childnode, "Merging field $childname into parent") if $verbose>1;
+ MakeOrMergeDbItem($childnode, $dbitem);
+ next;
+ }
+ }
+
+ foreach my $childnode (@$children) {
+ my $childname = $childnode->getAttribute('name');
+
+ if ($childnode->nodeName eq 'field') {
+ $db->{$childname} = MakeOrMergeDbItem($childnode);
+ } elsif (not defined $db->{$childname}) {
+ PrintMessage($childnode, "Fatal Error: Child $childname of $name not found in database", 1)
+ }
+ push(@{$dbitem->{'children'}}, $childname);
+ }
+ }
+ return $db;
}
-sub PrintMessage($$) {
+sub MakeOrMergeDbItem {
+ my $n = shift;
+ # always append the type, start with an empty one
+ my $dbitem = shift || {type => ''};
+ $dbitem->{'type'} .= $n->nodeName;
+
+ # determine the absolute address, include node itself (not necessarily a group)
+ # default address is 0, and we start from the base_address in TrbNetEntity
+ $dbitem->{'address'} = hex($n->ownerDocument->getDocumentElement->getAttribute('address') || '0');
+ foreach my $anc (($n, $n->findnodes('ancestor::group'))) {
+ $dbitem->{'address'} += hex($anc->getAttribute('address') || '0');
+ }
+
+ # add all attributes
+ foreach my $a (keys %$n) {
+ next if $a eq 'name' or $a eq 'address';
+ $dbitem->{$a} = $n->getAttribute($a);
+ }
+
+ # find required attributes from first ancestor which knows
+ # something about it, if we don't know it already
+ foreach my $a (qw(purpose mode)) {
+ next if defined $dbitem->{$a};
+ my $value = $n->findnodes("ancestor::*[\@$a][1]/\@$a");
+ $dbitem->{$a} = $value->string_value if $value->string_value;
+ }
+
+ # set description
+ foreach my $elem ($n->findnodes('(ancestor-or-self::*/description)[last()]')) {
+ $dbitem->{'description'} = SanitizedContent($elem);
+ }
+
+ # save enumItems (if any)
+ foreach my $item ($n->findnodes('enumItem')) {
+ my $val = $item->getAttribute('value');
+ $dbitem->{'enumItems'}->{$val} = SanitizedContent($item);
+ }
+
+ PrintMessage($n, "Warning: Found enumItems although not format=enum")
+ if $warnings and defined $dbitem->{'enumItems'} and $n->getAttribute('format') ne 'enum';
+
+ # determine size for repeatable???
+
+ return $dbitem;
+}
+
+sub SanitizedContent {
+ my $n = shift;
+ my $text = $n->textContent;
+ $text =~ s/\s+/ /g;
+ return $text;
+}
+
+sub PrintMessage {
my $node = shift;
my $file = $node->ownerDocument->URI;
my $line = $node->line_number;
exit 1 if shift;
}
-sub DumpDatabase($) {
- my %entities = map { $_.'.xml' => 1 } (@ARGV);
- my $num = scalar keys %entities;
- local $CWD = $db_dir;
- while(<*.xml>) {
- next if $num>0 and not defined $entities{$_};
- my($doc,$name) = LoadXML($_);
- DumpDocument($doc);
- }
-}
-
-sub DumpDocument($) {
+sub DumpDocument {
my $doc = shift;
my $entityName = $doc->getDocumentElement->getAttribute('name');
local $CWD = $db_dir;
my $doc = $parser->parse_file($filename);
ValidateXML($doc);
- my $dbname = $doc->getDocumentElement->getAttribute('name');
- print STDERR "Loaded and validated entity <$dbname> from database <$filename>\n" if $verbose>1;
- return ($doc, $dbname);
+ my $name = $doc->getDocumentElement->getAttribute('name');
+ print STDERR "Loaded and validated entity <$name> from database <$filename>\n"
+ if $verbose>1;
+ print STDERR "Warning: Filename not consistent with TrbNetEntity attribute"
+ if $warnings and "$name.xml" ne $filename;
+ return $doc;
}
sub ValidateXML {
=head1 SYNOPSIS
-xml-db.pl
+xml-db.pl [entity names]
xml-db.pl --dump [entity names]
Options:
=head1 DESCRIPTION
B<This program> updates the cache directory from the provided XML
-files in the database directory.
+files in the database directory. You can restrict the files being
+worked by stating them as arguments.
=cut