Commit bb5d5c3e authored by Stefan Tauner's avatar Stefan Tauner
Browse files

fiji_scripts: add support for FIU blocks in Settings file

parent cdd68038
......@@ -9,45 +9,85 @@ package FIJI;
# Fields:
# name = key name in FIJI Settings file
# is_numeric = (optional) enables conversion of oct, hex, binary
# strings and checking that the value is really a number.
# default = (optional) default value if not given in file and not determinable otherwise
my %constmap;
my %designmap;
BEGIN {
%constmap = (
%designmap = (
ID => {
name => "ID",
ini_name => "ID",
is_numeric => 1,
},
FIU_NUM => {
name => "FIU_NUM",
ini_name => "FIU_NUM",
default => undef, # optional in .ini, is set to number of FIU blocks
is_numeric => 1,
},
BAUDRATE => {
name => "BAUDRATE",
ini_name => "BAUDRATE",
default => 115200,
is_numeric => 1,
},
FIU_CFG_BITS => {
name => "FIU_CFG_BITS",
ini_name => "FIU_CFG_BITS",
default => 3,
is_numeric => 1,
},
TIMER_WIDTH => {
name => "TIMER_WIDTH",
ini_name => "TIMER_WIDTH",
default => 32,
is_numeric => 1,
},
ARM_DURATION_WIDTH => {
name => "ARM_DUR_WIDTH2",
ini_name => "ARM_DUR_WIDTH",
is_numeric => 1,
},
INJECT_DURATION_WIDTH => {
name => "INJECT_DUR_WIDTH",
ini_name => "INJECT_DUR_WIDTH",
is_numeric => 1,
},
);
}
use constant \%constmap;
use constant CONSTS => \%constmap;
use constant \%designmap;
use constant DESIGNMAP => \%designmap;
my %fiumap;
BEGIN {
%fiumap = (
FIU_NET_NAME => {
ini_name => "NET_NAME",
},
FIU_MODEL => {
ini_name => "FAULT_MODEL",
default => "RUNTIME",
},
FIU_LFSR_EN => {
ini_name => "ENABLED_BY_LFSR",
default => 0,
},
FIU_LFSR_MASK => {
ini_name => "LFSR_MASK",
default => 0,
is_numeric => 1,
},
FIU_LFSR_STUCK_OPEN_BIT => {
ini_name => "LFSR_BIT_FOR_STUCK_OPEN",
default => 0,
is_numeric => 1,
},
);
}
use constant \%fiumap;
use constant FIUMAP => \%fiumap;
use base 'Exporter';
# our @EXPORT = ();
our @EXPORT = keys(%constmap);
our @EXPORT_OK = (keys(%constmap), 'CONSTS');
our @EXPORT = (keys(%designmap), keys(%fiumap));
our @EXPORT_OK = (keys(%designmap), 'DESIGNMAP', keys(%fiumap), 'FIUMAP');
our %EXPORT_TAGS = (
all => \@EXPORT_OK,
default => \@EXPORT,
......
......@@ -2,7 +2,7 @@
## @class [FIJI::Settings]
#
# Contains helper functions to deal with FIJI configuration files.
# Contains helper functions to deal with FIJI Settings files.
package FIJI::Settings;
use Log::Log4perl qw(get_logger);
......@@ -11,41 +11,137 @@ use Config::Simple;
use FIJI qw(:all);
## @function read_configfile ($fiji_cfg_file)
# @brief Load the configuration file containing design constants.
## @function read_configfile ($fiji_ini_file)
# @brief Load the FIJI Settings file containing design and FIU constants.
#
# \param fiji_cfg_file The name of an .ini file with a 'consts' block
# containing the constants specified by \ref _sanitize_consts.
# \param fiji_ini_file The name of an .ini file with FIJI Settings:
# - a 'consts' block containing the constants specified by
# \ref _sanitize_consts.
# - at least one FIU block named "FIU<number>" where "<number>"
# is a strictly increasing integer starting with 0 containing
# the constants for the respective FIU, see \ref _sanitize_fiu
#
# \returns a reference to the hash containing the read constants.
sub read_configfile {
my $logger = get_logger();
my ($fiji_cfg_file) = @_;
my $fiji_cfg;
eval { $fiji_cfg = new Config::Simple($fiji_cfg_file) }; # pesky library tries to die on syntax errors
if (!defined($fiji_cfg)) {
$logger->fatal("Could not read config file \"$fiji_cfg_file\": " . (defined($@) ? $@ : Config::Simple->error()));
my ($fiji_ini_file) = @_;
my $fiji_ini;
eval { $fiji_ini = new Config::Simple($fiji_ini_file) }; # pesky library tries to die on syntax errors
if (!defined($fiji_ini)) {
$logger->fatal("Could not read config file \"$fiji_ini_file\": " . (defined($@) ? $@ : Config::Simple->error()));
return undef;
}
my $fiji_consts = $fiji_cfg->get_block("consts");
my $fiji_consts = $fiji_ini->get_block("CONSTS");
if (!(%$fiji_consts)) {
$logger->fatal("Could not fetch consts block from config file \"$fiji_cfg_file\"");
$logger->fatal("Could not fetch CONSTS block from config file \"$fiji_ini_file\"");
return undef;
}
$fiji_consts = _sanitize_consts($fiji_consts);
if (!defined($fiji_consts)) {
$logger->error("Constants in fiji configuration invalid");
$logger->fatal("Design constants in FIJI Settings invalid");
return undef;
}
my $fiu_num = 0;
while (1) {
my $fiu_name = "FIU" . $fiu_num;
my $fiji_fiu_cfg = $fiji_ini->get_block($fiu_name);
if (!(%$fiji_fiu_cfg)) {
last;
}
my $fiji_fiu = _sanitize_fiu($fiji_fiu_cfg);
if (!defined($fiji_fiu)) {
$logger->fatal("Constants for $fiu_name in FIJI Settings are invalid");
return undef;
}
push(@{$fiji_consts->{'FIUs'}}, $fiji_fiu);
$fiu_num++;
$logger->trace("Read in $fiu_name from FIJI Settings file successfully.");
}
if ($fiu_num == 0) {
$logger->fatal("Could not fetch any FIU block from config file \"$fiji_ini_file\"");
return undef;
}
# FIU_NUM is optional in the Settings file... if it was set check that
# it corresponds to the number of FIU<number> blocks.
if (defined($fiji_consts->{'FIU_NUM'}) && $fiji_consts->{'FIU_NUM'} != $fiu_num) {
$logger->fatal(FIU_NUM->{'ini_name'} . " does not match the numbers of FIU blocks found.");
return undef;
} else {
$fiji_consts->{'FIU_NUM'} = $fiu_num; # assume the best if FIU_NUM constant is not given
}
$logger->info("Successfully read in design constants and $fiu_num FIU definitions from FIJI Settings file.");
return $fiji_consts;
}
## @function _sanitize_consts (%$consts_ref)
sub _bla {
}
## @function _sanitize_fiu (%$fiu_ref)
# @brief Convert and sanity check FIJI Settings.
#
# This function takes a hash of FIJI Settings and converts it to the
# \param fiu_ref a reference to a hash containing FIJI Settings for a
# single FIU.
#
# \returns A new hash with all constants required in the FIU settings
# in sanitized form, or undef on errors.
sub _sanitize_fiu {
my $logger = get_logger();
my ($fiu_ref) = @_;
if (ref($fiu_ref) ne 'HASH') {
$logger->error("Parameter is not a reference to a hash (containing FIU constants).");
return undef;
}
my $new_hash = {};
# Iterate over FIUMAP hash from FIJI.pm and set defaults if need be
# FIXME: part of the loop almost identical to _sanitize_consts below
foreach my $k (keys(FIUMAP)) {
my $ini_name = FIUMAP->{$k}->{'ini_name'};
if (exists($fiu_ref->{$ini_name})) {
$new_hash->{$k} = $fiu_ref->{$ini_name};
$logger->trace(sprintf("Copying setting %s (%s) = %s.", $k, $ini_name, $fiu_ref->{$ini_name}));
} else {
if (exists(FIUMAP->{$k}->{default})) {
$new_hash->{$k} = FIUMAP->{$k}->{default};
$logger->trace(sprintf("Adding default constant: %s (%s) = %s.", $k, $ini_name, FIUMAP->{$k}->{default}));
} else {
$logger->error(sprintf("%s is missing from FIJI constants.", $ini_name));
return undef;
}
}
# convert non-decimal (hexadecimal, binary, octal) values to decimal
# my $orig = $new_hash->{$k};
# $new_hash->{$k} = oct($orig) if $orig =~ /^0/;
# $logger->trace("Converted value of $k (\"$orig\") to \"$new_hash->{$k}\".") if ($orig ne $new_hash->{$k});
# if (!looks_like_number($new_hash->{$k})) {
# $logger->error("$orig does not look like a number.");
# return undef;
# }
}
# check for sane values
# if (($new_hash->{FIU_CFG_BITS} <= 0)) {
# $logger->error("FIU_CFG_BITS is <= 0.");
# return undef;
# }
return $fiu_ref;
}
## @function _sanitize_consts (%$consts_ref)
# @brief Convert and sanity check FIJI Settings for the whole design.
#
# NOTE: The function returns a reference to a *new* hashmap that contains
# only the design constants!
#
# This function takes a hash of design settings and converts it to the
# respective internal representation. This allows to use different
# names in the external file than within the implementation.
#
......@@ -54,12 +150,12 @@ sub read_configfile {
# If there is no default available it has to be a mandatory value and
# hence the function returns non-0 in that case.
#
# ARM_DURATION_WIDTH and INJECT_DURATION_WIDTH are handled different because
# they are no official FIJI Settings because there is only a single timer
# (yet). However, the Perl implementation supports independet timer widths
# named as above. If they are not given in consts_ref then the value of
# TIMER_WIDTH is used. If that is not given either the default value for
# TIMER_WIDTH is used.
# ARM_DURATION_WIDTH and INJECT_DURATION_WIDTH are handled differently
# because they are not official FIJI Settings because there is only a
# single timer (yet). However, the Perl implementation supports
# independent timer widths named as above. If they are not given in
# consts_ref then the value of TIMER_WIDTH is used. If that is not given
# either the default value for TIMER_WIDTH is used.
#
# The second part of the function deals with sanity checks for the values
# themselves. It checks for the following conditions:
......@@ -70,64 +166,67 @@ sub read_configfile {
# - ID: > 0, < 2^15-1
# - BAUDRATE: > 0
#
# \param consts_ref a reference to a hash containing some FIJI Settings
# \param consts_ref a reference to a hash containing some design settings
#
# \returns A new hash with all required constants in sanitized form,
# or undef on errors.
# \returns A new hash with all constants required in the design settings
# in sanitized form, or undef on errors.
sub _sanitize_consts {
my $logger = get_logger();
my ($consts_ref) = @_;
if (ref($consts_ref) ne 'HASH') {
$logger->error("Parameter is not a reference to a hash (containing FIJI constants).");
$logger->error("Parameter is not a reference to a hash (containing design constants).");
return undef;
}
# Special cases of defaults handled separately here.
# Set ARM_DURATION_WIDTH and INJECT_DURATION_WIDTH to TIMER_WIDTH (or its default)
foreach my $k ('ARM_DURATION_WIDTH', 'INJECT_DURATION_WIDTH') {
if (!exists($consts_ref->{CONSTS->{$k}->{name}})) {
if (!exists($consts_ref->{DESIGNMAP->{$k}->{'ini_name'}})) {
if (exists($consts_ref->{'TIMER_WIDTH'})) {
$consts_ref->{CONSTS->{$k}->{name}} = $consts_ref->{'TIMER_WIDTH'};
$logger->trace(sprintf("Using TIMER_WIDTH value as default for %s (%s).", CONSTS->{$k}->{name}, $consts_ref->{'TIMER_WIDTH'}));
$consts_ref->{DESIGNMAP->{$k}->{'ini_name'}} = $consts_ref->{'TIMER_WIDTH'};
$logger->trace(sprintf("Using TIMER_WIDTH value as default for %s (%s).", DESIGNMAP->{$k}->{'ini_name'}, $consts_ref->{'TIMER_WIDTH'}));
} else {
$consts_ref->{CONSTS->{$k}->{name}} = TIMER_WIDTH->{'default'};
$logger->trace(sprintf("Using TIMER_WIDTH default as default for %s (%s).", CONSTS->{$k}->{name}, TIMER_WIDTH->{default}));
$consts_ref->{DESIGNMAP->{$k}->{'ini_name'}} = TIMER_WIDTH->{'default'};
$logger->trace(sprintf("Using TIMER_WIDTH default as default for %s (%s).", DESIGNMAP->{$k}->{'ini_name'}, TIMER_WIDTH->{default}));
}
}
}
my $new_consts = {};
# Iterating over CONSTS hash from FIJI.pm and set defaults if need be
foreach my $k (keys(CONSTS)) {
my $ini_name = CONSTS->{$k}->{name};
# Iterating over DESIGNMAP hash from FIJI.pm and set defaults if need be
foreach my $k (keys(DESIGNMAP)) {
my $ini_name = DESIGNMAP->{$k}->{'ini_name'};
if (exists($consts_ref->{$ini_name})) {
$new_consts->{$k} = $consts_ref->{$ini_name};
$logger->trace(sprintf("Copying setting %s (%s) = %s.", $k, $ini_name, $consts_ref->{$ini_name}));
} else {
if (defined(CONSTS->{$k}->{default})) {
$new_consts->{$k} = CONSTS->{$k}->{default};
$logger->trace(sprintf("Adding default constant: %s (%s) = %s.", $k, CONSTS->{$k}->{name}, CONSTS->{$k}->{default}));
if (exists(DESIGNMAP->{$k}->{default})) {
$new_consts->{$k} = DESIGNMAP->{$k}->{default};
$logger->trace(sprintf("Adding default constant: %s (%s) = %s.", $k, $ini_name, DESIGNMAP->{$k}->{default}));
# If the default key is there but its value is undef then
# the value will be set somewhere else later (used for FIU_NUM)
if (!defined($new_consts->{$k})) {
next;
}
} else {
$logger->error(sprintf("%s is missing from FIJI constants.", CONSTS->{$k}->{name}));
$logger->error(sprintf("%s is missing from FIJI constants.", $ini_name));
return undef;
}
}
# convert non-decimal (hexadecimal, binary, octal) values to decimal
my $orig = $new_consts->{$k};
$new_consts->{$k} = oct($orig) if $orig =~ /^0/;
$logger->trace("Converted value of $k (\"$orig\") to \"$new_consts->{$k}\".") if ($orig ne $new_consts->{$k});
if (!looks_like_number($new_consts->{$k})) {
$logger->error("$orig does not look like a number.");
return undef;
# convert non-decimal (hexadecimal, binary, octal) values to decimal
if (DESIGNMAP->{$k}->{is_numeric}) {
$new_consts->{$k} = oct($orig) if $orig =~ /^0/;
$logger->trace("Converted value of $k (\"$orig\") to \"$new_consts->{$k}\".") if ($orig ne $new_consts->{$k});
if (!looks_like_number($new_consts->{$k})) {
$logger->error("$orig does not look like a number.");
return undef;
}
}
}
# check for sane values
if (($new_consts->{FIU_NUM} <= 0)) {
$logger->error("FIU_NUM is <= 0.");
return undef;
}
if (($new_consts->{FIU_CFG_BITS} <= 0)) {
$logger->error("FIU_CFG_BITS is <= 0.");
return undef;
......
[consts]
[CONSTS]
FIU_NUM=8
TIMER_WIDTH=32
ID=0x0123
BAUDRATE=115200
[FIU0]
NET_NAME=siegfried
FAULT_MODEL=RUNTIME
ENABLED_BY_LFSR=false
LFSR_BIT_FOR_STUCK_OPEN=1
LFSR_MASK=0x0000
[FIU1]
NET_NAME = bla1
[FIU2]
NET_NAME = bla2
[FIU3]
NET_NAME = bla3
[FIU4]
NET_NAME = bla4
[FIU5]
NET_NAME = bla5
[FIU6]
NET_NAME = bla6
[FIU7]
NET_NAME = bla7
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment