Settings.pm 17.5 KB
Newer Older
1
## @file
2

3
## @class FIJI::Settings
4
#
5
# Contains helper functions to deal with FIJI Settings files.
6
7
package FIJI::Settings;

8
9
10
use strict;
use warnings;

11
use Scalar::Util 'blessed';
12
13
14
15
use Log::Log4perl qw(get_logger);
use Scalar::Util "looks_like_number";
use Config::Simple;

16
17
use FIJI qw(:all);

Stefan Tauner's avatar
Stefan Tauner committed
18
19
20
21
22
23
24
25
26
27
## @function new ($phase, $fiji_ini_file, $existing_settings)
# Create a new settings instance.
#
# \param $phase Tool flow phase the settings need to be compatible with.
# \param $fiji_ini_file (optional) Path to the configuration file to read.
# \param $existing_settings (optional) An instance to reuse and return
#        after overwriting existing values with defaults and any values
#        read from file. Existing values will not be validated.
#        Superfluous elements not present in the existing hash will be
#        removed, e.g. FIUs.
28
29
sub new ($;$$) {
  my $logger = get_logger();
Stefan Tauner's avatar
Stefan Tauner committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  my ($class, $phase, $fiji_ini_file, $existing_settings) = @_;

  my $fiji_settings_ref;
  # if there are no existing settings yet, create some with default values
  if (!defined($existing_settings)) {
    $fiji_settings_ref = {};
    $fiji_settings_ref->{'design'} = {};
    _set_defaults(DESIGNMAP, $fiji_settings_ref->{'design'}, $phase);
    $fiji_settings_ref = bless($fiji_settings_ref, $class);
    if (!ref($fiji_settings_ref) || !UNIVERSAL::can($fiji_settings_ref,'can')) {
      $logger->error("Could not bless FIJI::Settings class from \"$fiji_ini_file\".");
      return undef;
    }
  } else {
    $fiji_settings_ref = $existing_settings;
  }
46
47

  if (defined($fiji_ini_file)) {
Stefan Tauner's avatar
Stefan Tauner committed
48
49
    $fiji_settings_ref = read_settingsfile($phase, $fiji_ini_file, $fiji_settings_ref);
    if (!defined($fiji_settings_ref)) {
50
51
52
53
54
55
      return undef;
    }
    if (defined($existing_settings)) {
      return $existing_settings;
    }
  } else {
Stefan Tauner's avatar
Stefan Tauner committed
56
    $fiji_settings_ref->{'FIUs'} = ();
57
  }
Stefan Tauner's avatar
Stefan Tauner committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  return $fiji_settings_ref;
}


sub _export_value {
  my $logger = get_logger();
  my ($map_ref, $k, $v_ref) = @_;

  if (defined($map_ref->{$k}->{'type'})) {
    my $orig = ${$v_ref};
    if ($map_ref->{$k}->{'type'} eq 'hexadecimal') {
      ${$v_ref} = sprintf("0x%x", $orig);
    # } elsif ($map_ref->{$k}->{'type'} eq 'natural') {
    # } elsif ($map_ref->{$k}->{'type'} eq 'boolean') {
      $logger->trace("Converted value of $k (\"$orig\") to \"${$v_ref}\".") if ($orig ne ${$v_ref});
    }
  # } elsif (defined($map_ref->{$k}->{'values'})) {
75
76
77
78
79
80
81
82
83
  }
}

## @method save ($fiji_ini_file)
# @brief Store contained FIJI Settings to file.
#
# @ATTENTION Will happily overwrite existing files!
#
# \param fiji_ini_file The file name to write the FIJI Settings to.
Stefan Tauner's avatar
Stefan Tauner committed
84
sub save ($) {
85
86
87
88
89
  my $logger = get_logger();
  my ($self, $fiji_ini_file) = @_;
  return "No file name given" if !defined($fiji_ini_file);

  my $fiji_ini = new Config::Simple(syntax=>'ini');
90
91
  my $design_ref;
  my $fiu_cnt = 0;
92
93
94
95
96
97
  foreach my $key (keys %{$self}) {
    my $val = $self->{$key};
    $logger->debug(sprintf("Key: %s, type: %s, value: %s", $key, ref(\$val), $val));
    if (ref(\$val) eq "REF") {
      if (ref($val) eq "HASH") {
        if ($key eq "design") {
98
          $design_ref = $val;
99
100
101
102
103
104
          next;
        }
      } elsif (ref($val) eq "ARRAY") {
        if ($key eq "FIUs") {
          foreach my $fiu (@{$val}) {
            my $ini_fiu;
Stefan Tauner's avatar
Stefan Tauner committed
105
            
106
            foreach my $k (keys $fiu) {
Stefan Tauner's avatar
Stefan Tauner committed
107
108
109
110
111
              _export_value(FIUMAP, $k, \$$fiu{$k});
              # Copy value to new hash with external naming.
              my $ini_name = FIUMAP->{$k}->{'ini_name'};
              $ini_fiu->{$ini_name} = $fiu->{$k};
              $logger->trace(sprintf("Renaming setting %s -> %s (=%s).", $k, $ini_name, defined($ini_fiu->{$ini_name}) ? $ini_fiu->{$ini_name} : "undef"));
112
113
114
115
116
117
118
119
120
121
122
            }
            $fiji_ini->set_block("FIU" . $fiu_cnt++, $ini_fiu);
          }
          next;
        }
      }
    }
    my $err = "Unknown element found in FIJI Settings: \"$val\"";
    $logger->error($err);
    return $err;
  }
123
  $design_ref->{'FIU_NUM'} = $fiu_cnt;
Stefan Tauner's avatar
Stefan Tauner committed
124
125
126
  foreach my $key (keys $design_ref) {
    _export_value(DESIGNMAP, $key, \$$design_ref{$key});
  }
127
128
  $fiji_ini->set_block("CONSTS", $design_ref);

129
130
131
132
133
134
135
136
137
138
  if (!defined($fiji_ini->write($fiji_ini_file))) {
    my $err = Config::Simple->error();
    $logger->error($err);
    return $err;
  }
  return undef;
}


## @function read_settingsfile ($fiji_ini_file)
139
# @brief Load the FIJI Settings file containing design and FIU constants.
140
#
Stefan Tauner's avatar
Stefan Tauner committed
141
142
# \param $phase Tool flow phase the settings stored in the given file
#               need to be compatible with.
143
144
# \param fiji_ini_file The name of an .ini file with FIJI Settings:
#         - a 'consts' block containing the constants specified by
Stefan Tauner's avatar
Stefan Tauner committed
145
#           \ref _sanitize_design.
146
147
148
#         - 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
149
150
#
# \returns a reference to the hash containing the read constants.
151
sub read_settingsfile {
152
  my $logger = get_logger();
Stefan Tauner's avatar
Stefan Tauner committed
153
  my ($phase, $fiji_ini_file, $existing_settings) = @_;
154
155
156
  my $fiji_ini;
  eval { $fiji_ini = new Config::Simple($fiji_ini_file) }; # pesky library tries to die on syntax errors
  if (!defined($fiji_ini)) {
157
    $logger->error("Could not read config file \"$fiji_ini_file\": " . (defined($@) ? $@ : Config::Simple->error()));
158
159
160
    return undef;
  }

Stefan Tauner's avatar
Stefan Tauner committed
161
162
  my $fiji_design_cfg = $fiji_ini->get_block("CONSTS");
  if (!(%$fiji_design_cfg)) {
163
    $logger->error("Could not fetch CONSTS block from config file \"$fiji_ini_file\"");
164
165
    return undef;
  }
Stefan Tauner's avatar
Stefan Tauner committed
166
167
168
169

  my $fiji_design = _rename_import(DESIGNMAP, $fiji_design_cfg);
  if (!defined($fiji_design)) {
    $logger->error("Design constants do not match the FIJI Settings naming scheme.");
170
171
    return undef;
  }
Stefan Tauner's avatar
Stefan Tauner committed
172

173
  my $fiji_settings_ref;
174
  if (defined($existing_settings)) {
Stefan Tauner's avatar
Stefan Tauner committed
175
    if (!blessed($existing_settings) || !$existing_settings->isa("FIJI::Settings")) {
176
177
178
      $logger->error("Given settings are not of type FIJI::Settings.");
      return undef;
    }
Stefan Tauner's avatar
Stefan Tauner committed
179
180
181
182
183
184
185
186
187
188
189
    # overwrite existing Design Constants
    foreach my $k (keys($fiji_design)) {
      $existing_settings->{'design'}->{$k} = $fiji_design->{$k};
    }
    $fiji_design = $existing_settings->{'design'};
    if (defined($existing_settings->{'FIUs'})) {
      $fiji_settings_ref->{'FIUs'} = $existing_settings->{'FIUs'};
    } else {
      $fiji_settings_ref->{'FIUs'} = ();
    }
  } else {
190
191
    $fiji_settings_ref->{'FIUs'} = ();
  }
Stefan Tauner's avatar
Stefan Tauner committed
192
193
194
195
196
197
198
199

  # sanitize and validate read design constants
  $fiji_design = _sanitize_design($fiji_design, $phase);
  if (!defined($fiji_design)) {
    $logger->error("Design constants in FIJI Settings invalid");
    return undef;
  }
  $fiji_settings_ref->{'design'} = $fiji_design;
200
201
202
203
204
205
206
207

  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;
    }
Stefan Tauner's avatar
Stefan Tauner committed
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    my $fiji_fiu = _rename_import(FIUMAP, $fiji_fiu_cfg);
    if (!defined($fiji_design)) {
      $logger->error("FIU constants of $fiu_name do not match the FIJI Settings naming scheme.");
      return undef;
    }
    my $tmp_fiu = {};
    _set_defaults(FIUMAP, $tmp_fiu, $phase);

    if (defined($existing_settings)) {
      my $ex_fiu = @{$existing_settings->{'FIUs'}}[$fiu_num];
      if (defined($ex_fiu)) {
        # overwrite default entries
        foreach my $k (keys($ex_fiu)) {
          $tmp_fiu->{$k} = $ex_fiu->{$k};
        }
      }
      # overwrite existing FIU entries
      # $logger->trace("Overwriting values of $fiu_name.") if (defined($ex_fiu) && scalar(keys($ex_fiu)) > 0);
      foreach my $k (keys($fiji_fiu)) {
        $tmp_fiu->{$k} = $fiji_fiu->{$k};
      }
      $fiji_fiu = $tmp_fiu;
    }
    $fiji_fiu = _sanitize_fiu($fiji_fiu, $phase);
232
    if (!defined($fiji_fiu)) {
233
      $logger->error("Constants for $fiu_name in FIJI Settings are invalid");
234
235
      return undef;
    }
Stefan Tauner's avatar
Stefan Tauner committed
236
    @{$fiji_settings_ref->{'FIUs'}}[$fiu_num] = $fiji_fiu;
237
238
239
240
241
    $fiu_num++;
    $logger->trace("Read in $fiu_name from FIJI Settings file successfully.");
  }

  if ($fiu_num == 0) {
242
243
    $logger->debug("Could not fetch any FIU block from config file \"$fiji_ini_file\"");
    $fiji_settings_ref->{'FIUs'} = [];
244
  }
245
246
247

  # FIU_NUM is optional in the Settings file... if it was set check that
  # it corresponds to the number of FIU<number> blocks.
Stefan Tauner's avatar
Stefan Tauner committed
248
  if (defined($fiji_design->{'FIU_NUM'}) && $fiji_design->{'FIU_NUM'} != $fiu_num) {
249
      $logger->error(FIU_NUM->{'ini_name'} . " does not match the numbers of FIU blocks found.");
250
251
      return undef;
  } else {
Stefan Tauner's avatar
Stefan Tauner committed
252
    $fiji_design->{'FIU_NUM'} = $fiu_num; # assume the best if FIU_NUM constant is not given
253
254
  }

Stefan Tauner's avatar
Stefan Tauner committed
255
  splice(@{$fiji_settings_ref->{'FIUs'}}, $fiu_num);
256
  $logger->info("Successfully read in design constants and $fiu_num FIU definitions from FIJI Settings file.");
257
258
259
  return $fiji_settings_ref;
}

Stefan Tauner's avatar
Stefan Tauner committed
260
## @method set_fiu_defaults (%$fiu_ref)
261
262
263
264
# @brief Overwrite existing fields (if defined) with defaults defined in FIJI.pm.
#
sub set_fiu_defaults ($) {
  my ($self, $consts_ref) = @_;
Stefan Tauner's avatar
Stefan Tauner committed
265
266
267
268
269
270
271
272
  return _set_defaults(FIUMAP, $consts_ref);
}

## @function _set_defaults (%$map_ref, %$consts_ref)
# @brief Set defaults according to FIJI.pm.
sub _set_defaults {
  my $logger = get_logger();
  my ($map_ref, $consts_ref, $phase) = @_;
273
274
  foreach my $k (keys($map_ref)) {
    if (exists($map_ref->{$k}->{'default'})) {
Stefan Tauner's avatar
Stefan Tauner committed
275
276
277
278
      # Set default only if it is not mandatory in the given phase.
      if (!defined($phase) || scalar(grep {$_ eq $phase} @{$map_ref->{$k}->{'phases_opt'}}) > 0) {
        $consts_ref->{$k} = $map_ref->{$k}->{default};
        $logger->trace(sprintf("Adding default constant: %s (%s) = %s.", $k, $map_ref->{$k}->{'ini_name'}, $map_ref->{$k}->{default}));
279
280
281
      }
    }
  }
282
283
}

284

Stefan Tauner's avatar
Stefan Tauner committed
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
sub validate_design_value {
  my ($k, $v_ref) = @_;
  return validate_value(DESIGNMAP, $k, $v_ref);
}

sub validate_fiu_value {
  my ($k, $v_ref) = @_;
  return validate_value(FIUMAP, $k, $v_ref);
}

# Do validation (and conversation from external->internal representation)
sub validate_value ($$$;$) {
  my $logger = get_logger();
  my ($map_ref, $k, $v_ref, $log_func) = @_;
  $log_func = \&Log::Log4perl::Logger::trace if !defined($log_func);
  if (defined($map_ref->{$k}->{'type'})) {
    my $orig = ${$v_ref};
    if ($map_ref->{$k}->{'type'} eq 'hexadecimal') {
      if ($orig !~ /^(0|(0[xX][[:xdigit:]]+))$/) {
        $log_func->($logger, "$k: $orig does not look like a natural hexadecimal number.");
        return 0;
306
      }
Stefan Tauner's avatar
Stefan Tauner committed
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
      ${$v_ref} = hex($orig);
      # Check for natural value range. Should never trigger due to the regex above.
      if (${$v_ref} < 0) {
        $log_func->($logger, "$k: $orig is negative.");
        return 0;
      }
    } elsif ($map_ref->{$k}->{'type'} eq 'natural') {
      # Match hexadecimal, binary, octal and decimal numbers (the latter also in scientic notation)
      if ($orig !~ /^(0|(0(x[0-9a-fA-F]+|[0-7]+))|(0b[01]+)|([1-9][0-9]*(e(-[0-9])?[0-9]+)?))$/) {
        $log_func->($logger, "$k: $orig does not look like a number.");
        return 0;
      }
      
      # convert non-decimal (hexadecimal, binary, octal) values to decimal
      ${$v_ref} = oct($orig) if $orig =~ /^0/;
      if (!looks_like_number(${$v_ref})) {
        $log_func->($logger, "$k: $orig does not look like a number.");
        return 0;
      }
      # Check for natural value range. Should never trigger due to the regex above.
      if (${$v_ref} < 0) {
        $log_func->($logger, "$k: $orig is negative.");
        return 0;
      }
    } elsif ($map_ref->{$k}->{'type'} eq 'boolean') {
      # convert strings to binary if need be
      if (!defined($orig)) {
        $log_func->($logger, "$k: \"undef\" is not a boolean value.");
        return 0;
      } elsif (lc($orig) eq 'true') {
        $orig = 1;
      } elsif (lc($orig) eq 'false') {
        $orig = 0;
340
      }
Stefan Tauner's avatar
Stefan Tauner committed
341
342
343
344
345
346
      if (($orig ne '0') && ($orig ne '1')) {
        $log_func->($logger, "$k: \"$orig\" does not look like a boolean value.");
        return 0;
      }
      # ensure proper boolean value, i.e. 0 or 1
      ${$v_ref} = (!!$orig) ? 1 : 0;
347
    }
Stefan Tauner's avatar
Stefan Tauner committed
348
349
    $logger->trace("Converted value of $k (\"$orig\") to \"${$v_ref}\".") if ($orig ne ${$v_ref});
  }
350

Stefan Tauner's avatar
Stefan Tauner committed
351
352
353
354
355
356
357
  if (defined($map_ref->{$k}->{'values'})) {
    my $values_ref = $map_ref->{$k}->{'values'};
    if (ref($values_ref) eq 'ARRAY') {
      # Look for given value in allowed values
      if (scalar(grep {$_ eq ${$v_ref}} @{$values_ref}) == 0) {
        $log_func->($logger, "$k: ${$v_ref} is not allowed. Allowed values are: " . join(", ", @{$map_ref->{$k}->{'values'}}));
        return 0;
358
      }
Stefan Tauner's avatar
Stefan Tauner committed
359
360
361
362
    } elsif (ref($values_ref) eq 'CODE') {
      if (!$values_ref->(${$v_ref})) {
        $log_func->($logger, "$k: ${$v_ref} is not allowed.");
        return 0;
363
      }
364
365
    }
  }
Stefan Tauner's avatar
Stefan Tauner committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  return 1;
}


# @function _rename_import (%$map_ref, %$consts_ref)
# Rename and convert entries in consts_ref according to map_ref.
#
# This function takes a hash of FIJI Settings and converts its contents
# to the respective internal representation. This allows to use different
# names and value representations in the external file than within the
# implementation.
#
# \returns $consts_ref, or undef on errors
sub _rename_import {
  my $logger = get_logger();
  my ($map_ref, $consts_ref) = @_;
  if (ref($consts_ref) ne 'HASH') {
    $logger->error("Parameter is not a reference to a hash (containing design constants).");
    return undef;
  }

  # Iterating over respective hash from FIJI.pm and rename the entries
  # to match our internal naming scheme.
  foreach my $k (keys($map_ref)) {
    my $ini_name = $map_ref->{$k}->{'ini_name'};
    if (exists($consts_ref->{$ini_name}) && $ini_name ne $k) {
      $consts_ref->{$k} = $consts_ref->{$ini_name};
      $logger->trace(sprintf("Renaming setting %s -> %s (=%s).", $ini_name, $k, defined($consts_ref->{$ini_name}) ? $consts_ref->{$ini_name} : "undef"));
      delete $consts_ref->{$ini_name};
    }
  }
  foreach my $entry_key (keys($consts_ref)) {
    if (!exists($map_ref->{$entry_key})) {
      $logger->debug("Deleting unknown setting %s = %s.", $entry_key, $consts_ref->{$entry_key});
      delete $consts_ref->{$entry_key};
    }
  }

404
  return $consts_ref;
405
406
}

Stefan Tauner's avatar
Stefan Tauner committed
407

408
## @function _sanitize_fiu (%$fiu_ref)
409
410
# @brief Convert and sanity check FIJI Settings.
#
411
412
413
414
415
# \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.
Stefan Tauner's avatar
Stefan Tauner committed
416
sub _sanitize_fiu ($;$) {
417
  my $logger = get_logger();
Stefan Tauner's avatar
Stefan Tauner committed
418
  my ($fiu_ref, $phase) = @_;
419
420
421
422
423
  if (ref($fiu_ref) ne 'HASH') {
    $logger->error("Parameter is not a reference to a hash (containing FIU constants).");
    return undef;
  }

Stefan Tauner's avatar
Stefan Tauner committed
424
425
426
427
  $fiu_ref = _validate_hashmap(FIUMAP, $fiu_ref, $phase);
  if (!defined($fiu_ref)) {
      $logger->error("Could not validate Design Constants.");
      return undef;
428
429
430
431
432
  }

  return $fiu_ref;
}

Stefan Tauner's avatar
Stefan Tauner committed
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

sub _validate_hashmap ($$;$) {
  my $logger = get_logger();
  my ($map_ref, $consts_ref, $phase) = @_;
  my @map_keys = keys($map_ref);
  foreach my $entry_key (keys($consts_ref)) {
    my $ini_name = $map_ref->{$entry_key}->{'ini_name'};
    
    if (!exists($map_ref->{$entry_key})) {
      $logger->debug("Deleting unknown setting %s = %s.", $entry_key, $consts_ref->{$entry_key});
      next;
    }

    # mark constant key as done
    @map_keys = grep {$_ ne $entry_key} @map_keys;
    if (!validate_value($map_ref, $entry_key, \$consts_ref->{$entry_key})) {
      $logger->error("$entry_key = $consts_ref->{$entry_key} is invalid.");
      return undef;
    }
  }

  if (!defined($phase)) {
    # If there is no phase we are creating an "empty" hash that has
    # all possible defaults set earlier already and the there is
    # nothing we can or should do here.
    return $consts_ref;
  }

  # Iterate over the constants defined in FIJI.pm that apparently are
  # not contained in $consts_ref.
  foreach my $k (@map_keys) {
    if (scalar(grep {$_ eq $phase} @{$map_ref->{$k}->{'phases_opt'}}) == 0) {
      $logger->error("$k is mandatory in phase $phase.");
      return undef;
    }
  }
  return $consts_ref
}


## @function _sanitize_design (%$consts_ref)
# @brief Sanity check FIJI Design Settings.
475
#
Stefan Tauner's avatar
Stefan Tauner committed
476
# The function deals with sanity checks for the values
477
# themselves. It checks for the following conditions:
478
479
480
#
#   - FIU_NUM: > 0
#   - FIU_CFG_BITS: > 0
Stefan Tauner's avatar
Stefan Tauner committed
481
#   - TIMER_WIDTH: > 0, multiple of 8
482
483
484
#   - ID: > 0, < 2^15-1
#   - BAUDRATE: > 0
#
485
# \param consts_ref a reference to a hash containing some design settings
Stefan Tauner's avatar
Stefan Tauner committed
486
# \param phase the tool flow phase that defines the rules to check against
487
#
Stefan Tauner's avatar
Stefan Tauner committed
488
489
490
# \returns The given hash with all constants required in the design
#          settings in sanitized form, or undef on errors.
sub _sanitize_design {
491
  my $logger = get_logger();
Stefan Tauner's avatar
Stefan Tauner committed
492
  my ($consts_ref, $phase) = @_;
493
  if (ref($consts_ref) ne 'HASH') {
494
    $logger->error("Parameter is not a reference to a hash (containing design constants).");
495
496
    return undef;
  }
Stefan Tauner's avatar
Stefan Tauner committed
497
  
498
  # check for sane values
Stefan Tauner's avatar
Stefan Tauner committed
499
500
501
  $consts_ref = _validate_hashmap(DESIGNMAP, $consts_ref, $phase);
  if (!defined($consts_ref)) {
      $logger->error("Could not validate Design Constants.");
502
      return undef;
503
  }
Stefan Tauner's avatar
Stefan Tauner committed
504
505
506

  if (($consts_ref->{'FIU_CFG_BITS'} <= 0)) {
      $logger->error("FIU_CFG_BITS is <= 0.");
507
      return undef;
508
  }
Stefan Tauner's avatar
Stefan Tauner committed
509
510
  if (($consts_ref->{'TIMER_WIDTH'} <= 0) || ($consts_ref->{'TIMER_WIDTH'} % 8 != 0)) {
      $logger->error("TIMER_WIDTH is invalid ($consts_ref->{'TIMER_WIDTH'}).");
511
      return undef;
512
  }
Stefan Tauner's avatar
Stefan Tauner committed
513
  if (defined($consts_ref->{'ID'}) && ($consts_ref->{ID} < 0 || $consts_ref->{ID} > (2**15 - 1))) {
514
      $logger->error("ID is invalid ($consts_ref->{ID}).");
515
      return undef;
516
  }
Stefan Tauner's avatar
Stefan Tauner committed
517
  if (($consts_ref->{'BAUDRATE'} <= 0)) {
518
      $logger->error("BAUDRATE missing is <= 0.");
519
      return undef;
520
  }
Stefan Tauner's avatar
Stefan Tauner committed
521

522
  return $consts_ref;
523
524
525
}

1;