Settings.pm 9.4 KB
 Stefan Tauner committed Feb 16, 2015 1 2 3 4 ## @file [Settings.pm] ## @class [FIJI::Settings] #  Stefan Tauner committed Feb 19, 2015 5 # Contains helper functions to deal with FIJI Settings files.  Stefan Tauner committed Feb 16, 2015 6 7 8 9 10 11 package FIJI::Settings; use Log::Log4perl qw(get_logger); use Scalar::Util "looks_like_number"; use Config::Simple;  12 13 use FIJI qw(:all);  Stefan Tauner committed Feb 19, 2015 14 15 ## @function read_configfile ($fiji_ini_file) # @brief Load the FIJI Settings file containing design and FIU constants.  Stefan Tauner committed Feb 16, 2015 16 #  Stefan Tauner committed Feb 19, 2015 17 18 19 20 21 22 # \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" where "" # is a strictly increasing integer starting with 0 containing # the constants for the respective FIU, see \ref _sanitize_fiu  Stefan Tauner committed Feb 16, 2015 23 24 25 26 # # \returns a reference to the hash containing the read constants. sub read_configfile { my$logger = get_logger();  Stefan Tauner committed Feb 19, 2015 27 28 29 30 31  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()));  Stefan Tauner committed Feb 16, 2015 32 33 34  return undef; }  Stefan Tauner committed Feb 19, 2015 35  my$fiji_consts = $fiji_ini->get_block("CONSTS");  Stefan Tauner committed Feb 16, 2015 36  if (!(%$fiji_consts)) {  Stefan Tauner committed Feb 19, 2015 37  $logger->fatal("Could not fetch CONSTS block from config file \"$fiji_ini_file\"");  Stefan Tauner committed Feb 16, 2015 38 39  return undef; }  40 41  $fiji_consts = _sanitize_consts($fiji_consts); if (!defined($fiji_consts)) {  Stefan Tauner committed Feb 19, 2015 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 $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;  Stefan Tauner committed Feb 16, 2015 66  }  Stefan Tauner committed Feb 19, 2015 67 68 69 70 71 72 73 74 75 76 77  # FIU_NUM is optional in the Settings file... if it was set check that # it corresponds to the number of FIU 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.");  Stefan Tauner committed Feb 16, 2015 78 79 80 81  return $fiji_consts; }  Stefan Tauner committed Feb 19, 2015 82 83 84 85 sub _bla { } ## @function _sanitize_fiu (%$fiu_ref)  86 87 # @brief Convert and sanity check FIJI Settings. #  Stefan Tauner committed Feb 19, 2015 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 # \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  145 146 147 148 149 150 151 152 # respective internal representation. This allows to use different # names in the external file than within the implementation. # # First, this function sets some default values for missing constants if # there is a default stored for the respective constant in FIJI.pm. # If there is no default available it has to be a mandatory value and # hence the function returns non-0 in that case. #  Stefan Tauner committed Feb 19, 2015 153 154 155 156 157 158 # 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.  159 160 161 # # The second part of the function deals with sanity checks for the values # themselves. It checks for the following conditions:  Stefan Tauner committed Feb 16, 2015 162 163 164 # # - FIU_NUM: > 0 # - FIU_CFG_BITS: > 0  165 # - ARM_DURATION_WIDTH, INJECT_DURATION_WIDTH: > 0, multiple of 8  Stefan Tauner committed Feb 16, 2015 166 167 168 # - ID: > 0, < 2^15-1 # - BAUDRATE: > 0 #  Stefan Tauner committed Feb 19, 2015 169 # \param consts_ref a reference to a hash containing some design settings  170 #  Stefan Tauner committed Feb 19, 2015 171 172 # \returns A new hash with all constants required in the design settings # in sanitized form, or undef on errors.  Stefan Tauner committed Feb 16, 2015 173 174 175 176 sub _sanitize_consts { my $logger = get_logger(); my ($consts_ref) = @_; if (ref($consts_ref) ne 'HASH') {  Stefan Tauner committed Feb 19, 2015 177 $logger->error("Parameter is not a reference to a hash (containing design constants).");  178 179 180 181 182 183  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') {  Stefan Tauner committed Feb 19, 2015 184  if (!exists($consts_ref->{DESIGNMAP->{$k}->{'ini_name'}})) {  185  if (exists($consts_ref->{'TIMER_WIDTH'})) {  Stefan Tauner committed Feb 19, 2015 186 187  $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'}));  188  } else {  Stefan Tauner committed Feb 19, 2015 189 190  $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}));  191 192  } }  Stefan Tauner committed Feb 16, 2015 193 194  }  195  my $new_consts = {};  Stefan Tauner committed Feb 19, 2015 196 197 198  # 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'};  199 200 201 202  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 {  Stefan Tauner committed Feb 19, 2015 203 204 205 206 207 208 209 210  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; }  211  } else {  Stefan Tauner committed Feb 19, 2015 212 $logger->error(sprintf("%s is missing from FIJI constants.", $ini_name));  213 214  return undef; }  Stefan Tauner committed Feb 16, 2015 215 216  }  217  my$orig = $new_consts->{$k};  Stefan Tauner committed Feb 19, 2015 218 219 220 221 222 223 224 225  # 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; }  Stefan Tauner committed Feb 16, 2015 226 227 228  } }  229 230  # check for sane values if (($new_consts->{FIU_CFG_BITS} <= 0)) {  Stefan Tauner committed Feb 16, 2015 231  $logger->error("FIU_CFG_BITS is <= 0.");  232  return undef;  Stefan Tauner committed Feb 16, 2015 233  }  234 235 236  if (($new_consts->{ARM_DURATION_WIDTH} <= 0) || ($new_consts->{ARM_DURATION_WIDTH} % 8 != 0)) {$logger->error("ARM_DURATION_WIDTH is invalid ($new_consts->{ARM_DURATION_WIDTH})."); return undef;  Stefan Tauner committed Feb 16, 2015 237  }  238 239 240  if (($new_consts->{INJECT_DURATION_WIDTH} <= 0) || (($new_consts->{INJECT_DURATION_WIDTH} % 8) != 0)) {$logger->error("INJECT_DURATION_WIDTH is invalid ($new_consts->{INJECT_DURATION_WIDTH})."); return undef;  Stefan Tauner committed Feb 16, 2015 241  }  242 243 244  if (($new_consts->{ID} <= 0) || ($new_consts->{ID} > (2**15 - 1))) {$logger->error("ID is invalid ($new_consts->{ID})."); return undef;  Stefan Tauner committed Feb 16, 2015 245  }  246  if (($new_consts->{BAUDRATE} <= 0)) {  Stefan Tauner committed Feb 16, 2015 247  $logger->error("BAUDRATE missing is <= 0.");  248  return undef;  Stefan Tauner committed Feb 16, 2015 249  }  250  return$new_consts;  Stefan Tauner committed Feb 16, 2015 251 252 253 } 1;