From a182a5031498dce36b59d7a370a60bbbf091af55 Mon Sep 17 00:00:00 2001 From: Andreas Neiser Date: Wed, 3 Jul 2013 16:23:26 +0200 Subject: [PATCH] Major changes: Now xml-db.pl creates Storable objects in cache/ directory --- xml-db/.gitignore | 3 + xml-db/database/CTS.xml | 2 +- xml-db/database/Hub.xml | 2 +- xml-db/database/JtagController.xml | 72 +++++------ xml-db/database/TDC.xml | 60 +++++----- xml-db/database/TrbNet.xml | 2 +- xml-db/database/TrgRdo.xml | 2 +- xml-db/schema/TrbNetCommon.xsd | 9 +- xml-db/schema/TrbNetEntity.xsd | 10 +- xml-db/xml-db.pl | 184 +++++++++++++++++++++++++---- 10 files changed, 239 insertions(+), 107 deletions(-) create mode 100644 xml-db/.gitignore diff --git a/xml-db/.gitignore b/xml-db/.gitignore new file mode 100644 index 0000000..af99ff3 --- /dev/null +++ b/xml-db/.gitignore @@ -0,0 +1,3 @@ +# ignore the cache directory +/cache/ + diff --git a/xml-db/database/CTS.xml b/xml-db/database/CTS.xml index 642637a..e86924a 100644 --- a/xml-db/database/CTS.xml +++ b/xml-db/database/CTS.xml @@ -10,7 +10,7 @@ Number of clock cycles with trigger asserted - + diff --git a/xml-db/database/Hub.xml b/xml-db/database/Hub.xml index 6585a37..97e8d71 100644 --- a/xml-db/database/Hub.xml +++ b/xml-db/database/Hub.xml @@ -14,7 +14,7 @@ address="0000" repeat="4" purpose="status" mode="rw" > Current status of each port of the hub on each channel. + start="0" bits="17" mode="r" purpose="status" format="bitmask"> diff --git a/xml-db/database/JtagController.xml b/xml-db/database/JtagController.xml index eea44c5..edf0504 100644 --- a/xml-db/database/JtagController.xml +++ b/xml-db/database/JtagController.xml @@ -14,7 +14,7 @@ address="0007" mode="rw" purpose ="config" > Wait time between write sequence and start signal. + start="0" bits="20" mode="rw" purpose="config" format="integer"> The number of MAPS clock cycles to wait after last write before sending the start signal. @@ -22,7 +22,7 @@ address="000c" mode="w" purpose ="trigger" > Trigger the init sequence. + start="0" bits="5" mode="w" purpose="trigger" format="bitmask"> A bitmask to trigger the init sequence on individual JTAG chains. @@ -30,7 +30,7 @@ address="000d" mode="w" purpose ="trigger" > Trigger the init sequence. + start="0" bits="5" mode="w" purpose="trigger" format="bitmask"> A bitmask to trigger sending a reset pulse on individual JTAG chains @@ -38,7 +38,7 @@ address="000e" mode="w" purpose ="trigger" > Trigger sending a start pulse. + start="0" bits="5" mode="w" purpose="trigger" format="bitmask"> A bitmask to trigger sending a start pulse on individual JTAG chains @@ -46,7 +46,7 @@ address="000f" mode="w" purpose ="trigger" > Trigger running JTAG write. + start="0" bits="5" mode="w" purpose="trigger" format="bitmask"> A bitmask to trigger writing the JTAG registers three times on individual JTAG chains @@ -54,7 +54,7 @@ address="0010" mode="rw" purpose="config" > Generate a reset before doing init sequence + start="0" mode="rw" purpose="config" format="boolean"> Enable to send a reset pulse before starting init sequence @@ -62,7 +62,7 @@ address="0011" mode="rw" purpose="config" > Generate a reset after first register write sequence + start="0" mode="rw" purpose="config" format="boolean"> Enable to send a reset pulse after the first writing of JTAG registers @@ -70,70 +70,70 @@ address="0014" mode="w" purpose ="trigger" > Trigger writing all JTAG registers once + start="0" bits="5" mode="w" purpose="trigger" format="bitmask"> Trigger writing all JTAG registers once on individual JTAG chains Sets fixed values for all outputs for JTAG and sensor control and inverts the outputs if needed. One register for each JTAG chain. - + Sets fixed values for all outputs for JTAG and sensor control and inverts the outputs if needed. One register for each JTAG chain. + start="0" format="boolean"> Invert TDO input signal + start="2" format="boolean"> Invert TDI output signal + start="4" format="boolean"> Invert TMS output signal + start="6" format="boolean"> Invert TCK output signal + start="8" format="boolean"> Invert Start output signal + start="10" format="boolean"> Invert Reset output signal + start="12" format="boolean"> Invert Clock output signal + start="1" format="boolean"> Enable TDO input signal + start="3" format="boolean"> Enable TDI output signal + start="5" format="boolean"> Enable TMS output signal + start="7" format="boolean"> Enable TCK output signal + start="9" format="boolean"> Enable Start output signal + start="11" format="boolean"> Enable Reset output signal + start="13" format="boolean"> Enable Clock output signal @@ -143,18 +143,18 @@ + address="1800" size="40" purpose="status" mode="r" continuous="true"> Error counters for read and write operations on the JTAG chain + start="0" bits="16" mode="r" purpose="status" format="integer" > Number of read errors during "read id" operation + start="16" bits="16" mode="r" purpose="status" format="integer" > Number of read errors during write operation @@ -162,11 +162,11 @@ address="0003" purpose="status" mode="r" > Error counters for read and write operations on the JTAG chain + start="0" bits="16" mode="r" purpose="status" format="integer" > Number of times data read back from the sensor was not identical to the data written to the sensor. + start="16" bits="16" mode="r" purpose="status" format="integer" > Number of sampling errors of TDI signal. The signal from the sensor is sampled three times for each bit, all occurrences must be equal. @@ -174,34 +174,34 @@ address="0004" purpose="status" mode="r" > Number of times the JTAG controller run a full sequence + start="0" bits="32" mode="r" purpose="status" format="integer" > Status flags of the JTAG chain + start="0" mode="r" purpose="status" format="boolean" > JTAG has been started + start="4" mode="r" purpose="status" format="boolean" > Last JTAG run was successful + start="8" mode="r" purpose="status" format="boolean" > Data in the sensor was corrupted at last JTAG run + start="12" mode="r" purpose="status" format="boolean" > Last run had a JTAG write error + start="16" mode="r" purpose="status" format="boolean" > Last run had a JTAG read error + start="20" mode="r" purpose="status" format="boolean" > Last run had a JTAG CRC error diff --git a/xml-db/database/TDC.xml b/xml-db/database/TDC.xml index 7eecb3e..5700f8a 100644 --- a/xml-db/database/TDC.xml +++ b/xml-db/database/TDC.xml @@ -11,10 +11,10 @@ Channel-specific information - + Number of detected hits in channel - + State of LVDS input buffer Low High @@ -30,7 +30,7 @@ Basic config and status information for all channels - + Debug word of the TDC readout FSM IDLE WAIT_FOR_TRG_WIND_END @@ -43,20 +43,20 @@ SEND_TRG_RELEASE_B OTHERS - + Debug word of the TDC writeout FSM IDLE WR_CH OTHERS - + Number of implemented channels Reference time synchronised to 100 MHz Trb-Net clock - + Trigger type @@ -64,16 +64,16 @@ Empty the signals/hits of the specific channel. LSB is channel 1. - + Status of the TriggerWindow feature - + Trigger window width BEFORE the trigger with granularity of 5 ns - + Trigger window width AFTER the trigger with granularity of 5 ns @@ -84,89 +84,89 @@ Number of valid triggers received - + Number of valid timing triggers received - + Number of valid triggers received which are not timing triggers - + Number of invalid triggers received - + Number of multi timing triggers received (triggers received before trigger is released) - + Number of spurious triggers received (in case of timing trigger is validated although it was a timing-trigger-less trigger) - + Number of wrong readouts due to spurious triggers - + Number of spikes (pulses narrower than 40 ns) detected at the timing trigger input - + Total time length, that the readout FSM waited in the idle state (with granularity of 10 ns) - + Total time length, that the readout FSM waited in the wait states (with granularity of 10 ns) - + Total number of empty channels since the last reset signal - + Number of release signals sent - + Total time length of the readout process (with granularity of 10 ns) - + Number of timeouts detected (too long delay after the timing trigger) - + Number of sent finished signals - + @@ -178,7 +178,7 @@ address="0800" purpose="config" mode="rw" continuous="true"> Basic control for all channels - + Enables different signals to the HPLA* output for debugging with logic analyser @@ -189,7 +189,7 @@ Resets the internal counters - + Select the trigger mode: With trigger mode or trigger-less mode TRIGGERED @@ -199,11 +199,11 @@ Configuration of the TriggerWindow feature - + Trigger window width BEFORE the trigger with granularity of 5 ns - + Trigger window width AFTER the trigger with granularity of 5 ns. ATTENTION: Minimum value is x"00f"! @@ -215,12 +215,12 @@ Enable signals/hits of the specific channel. LSB is channel 1. - + Configuration of the data transfer limit feature - + Defines number of data words per channel to be read-out. Set it to 0x80 for full readout. diff --git a/xml-db/database/TrbNet.xml b/xml-db/database/TrbNet.xml index eed0a4e..4f22397 100644 --- a/xml-db/database/TrbNet.xml +++ b/xml-db/database/TrbNet.xml @@ -10,7 +10,7 @@ Common Status Register 0 - + Board temperature diff --git a/xml-db/database/TrgRdo.xml b/xml-db/database/TrgRdo.xml index 16a89b9..4285be0 100644 --- a/xml-db/database/TrgRdo.xml +++ b/xml-db/database/TrgRdo.xml @@ -9,7 +9,7 @@ IPU handler status register - + FSM state bits IDLE WaitForLength diff --git a/xml-db/schema/TrbNetCommon.xsd b/xml-db/schema/TrbNetCommon.xsd index fb534ce..97ea901 100644 --- a/xml-db/schema/TrbNetCommon.xsd +++ b/xml-db/schema/TrbNetCommon.xsd @@ -80,6 +80,7 @@ + @@ -184,11 +185,9 @@ - - + provided in the database --> + + + to redundant naming schemes, but addressing things gets less + confusing --> - - - - - + diff --git a/xml-db/xml-db.pl b/xml-db/xml-db.pl index b51bb81..6dd7858 100755 --- a/xml-db/xml-db.pl +++ b/xml-db/xml-db.pl @@ -9,6 +9,7 @@ use Pod::Usage; use File::chdir; use FindBin qw($RealBin); use Data::Dumper; +use Storable qw(lock_store); # some default config options @@ -20,7 +21,7 @@ my $help = 0; 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)); @@ -30,7 +31,7 @@ GetOptions( '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; @@ -51,18 +52,158 @@ if ($verbose) { # 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; @@ -73,18 +214,7 @@ sub PrintMessage($$) { 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'); @@ -151,9 +281,12 @@ BEGIN { 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 { @@ -184,7 +317,7 @@ xml-db.pl - Create cached data structures from the XML entities =head1 SYNOPSIS -xml-db.pl +xml-db.pl [entity names] xml-db.pl --dump [entity names] Options: @@ -216,6 +349,7 @@ Set the base directory where the default XML files can be found in sub-directori =head1 DESCRIPTION B 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 -- 2.43.0