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

FIJI scripts: partial rewrite of FIJI Settings handling

 - get rid of backend store in FIJISettingsViewer
 - simplify overall function design and data structures
 - re-validate GUI elements on new data (settings or net lists)
 - warn before overwriting existing file in all cases
 - fix preliminary autocomplete (some remaining pre-existintg bugs in CompleteEntry.p)
parent 11f11613
...@@ -12,6 +12,7 @@ use Log::Log4perl qw(get_logger :easy); ...@@ -12,6 +12,7 @@ use Log::Log4perl qw(get_logger :easy);
use Verilog::Netlist; use Verilog::Netlist;
sub new ($) { sub new ($) {
my ($class) = @_; my ($class) = @_;
...@@ -26,11 +27,12 @@ sub new ($) { ...@@ -26,11 +27,12 @@ sub new ($) {
return $self; return $self;
} }
sub read_file ($) { sub read_file ($) {
my $logger = get_logger(); my $logger = get_logger();
my ($self, $filename) = @_; my ($self, $filename) = @_;
eval { eval {
$self->{'nl'}->read_file(filename=>$filename); # read vqm file $self->{'nl'}->read_file(filename => $filename); # read Verilog file
$self->{'nl'}->link(); # Read in any sub-modules $self->{'nl'}->link(); # Read in any sub-modules
}; };
...@@ -39,16 +41,22 @@ sub read_file ($) { ...@@ -39,16 +41,22 @@ sub read_file ($) {
return 1; return 1;
} }
$logger->info("Successfully read in netlist from file \"$filename\".");
return 0; return 0;
} }
# returns an array with all net names
#
# possible future extension:
# returns a hash with array of... # returns a hash with array of...
# - the 'names' of all nets # - the 'names' of all nets
# - the 'paths' of all nets (TODO) # - the 'paths' of all nets (TODO)
# - the 'metadata' of all nets (i.e. what VP's module->nets() returns) (TODO. needed? - it's huge) # - the 'metadata' of all nets (i.e. what VP's module->nets() returns) (TODO. needed? - it's huge)
sub get_nets ($) { sub get_nets ($) {
my ($self) = @_; my ($self) = @_;
my $nets_ref = {'metadata' => [], 'names' => []}; # my $nets_ref = {'metadata' => [], 'names' => [], 'nets' => []};
my $nets_ref = [];
foreach my $mod ($self->{'nl'}->top_modules_sorted) { foreach my $mod ($self->{'nl'}->top_modules_sorted) {
$self->_get_subnets($nets_ref, $mod); $self->_get_subnets($nets_ref, $mod);
} }
...@@ -59,8 +67,7 @@ sub get_nets ($) { ...@@ -59,8 +67,7 @@ sub get_nets ($) {
sub _get_subnets ($$) { sub _get_subnets ($$) {
my ($self, $nets_ref, $mod) = @_; my ($self, $nets_ref, $mod) = @_;
foreach my $n ($mod->nets) { foreach my $n ($mod->nets) {
# push($nets_ref->{'metadata'}, $n); push(@{$nets_ref}, $n->name);
push(@{$nets_ref->{'names'}}, $n->name);
} }
foreach my $cell ($mod->cells_sorted) { foreach my $cell ($mod->cells_sorted) {
......
...@@ -11,7 +11,6 @@ use warnings; ...@@ -11,7 +11,6 @@ use warnings;
use Scalar::Util 'blessed'; use Scalar::Util 'blessed';
use Log::Log4perl qw(get_logger); use Log::Log4perl qw(get_logger);
use Scalar::Util "looks_like_number"; use Scalar::Util "looks_like_number";
use Clone qw(clone);
use Config::Simple; use Config::Simple;
use FIJI qw(:all); use FIJI qw(:all);
...@@ -21,11 +20,8 @@ use FIJI qw(:all); ...@@ -21,11 +20,8 @@ use FIJI qw(:all);
# #
# \param $phase Tool flow phase the settings need to be compatible with. # \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 $fiji_ini_file (optional) Path to the configuration file to read.
# \param $existing_settings (optional) An instance to reuse and return # \param $existing_settings (optional) A reference to reuse and return
# after overwriting existing values with defaults and any values # with values read from file. Any contained data will be cleared.
# read from file. Existing values will not be validated.
# Superfluous elements not present in the existing hash will be
# removed, e.g. FIUs.
# \returns The new settings instance or a string describing the reason # \returns The new settings instance or a string describing the reason
# why it could not be created. # why it could not be created.
sub new ($;$$) { sub new ($;$$) {
...@@ -33,29 +29,34 @@ sub new ($;$$) { ...@@ -33,29 +29,34 @@ sub new ($;$$) {
my ($class, $phase, $fiji_ini_file, $existing_settings) = @_; my ($class, $phase, $fiji_ini_file, $existing_settings) = @_;
my $fiji_settings_ref; my $fiji_settings_ref;
# if there are no existing settings yet, create some with default values # if there is no existing settings instance yet, create one
if (!defined($existing_settings)) { if (!defined($existing_settings)) {
$fiji_settings_ref = {}; $fiji_settings_ref = {};
$fiji_settings_ref->{'design'} = {};
_set_defaults(DESIGNMAP, $fiji_settings_ref->{'design'}, $phase);
$fiji_settings_ref = bless($fiji_settings_ref, $class); $fiji_settings_ref = bless($fiji_settings_ref, $class);
if (!ref($fiji_settings_ref) || !UNIVERSAL::can($fiji_settings_ref,'can')) {
my $msg = "Could not bless FIJI::Settings class from \"$fiji_ini_file\".";
$logger->error($msg);
return $msg;
}
} else { } else {
$fiji_settings_ref = _clone($existing_settings); $fiji_settings_ref = $existing_settings;
}
if (!blessed($fiji_settings_ref) || !$fiji_settings_ref->isa("FIJI::Settings")) {
my $msg;
if (!defined($existing_settings)) {
$msg = "Could not create FIJI::Settings instance.";
} else {
$msg = "Given settings are not of type FIJI::Settings.";
}
$logger->error($msg);
return $msg;
} }
# If there is a file given, try to read it. Else just add an empty FIUs array. # If there is a file given, try to read it. Else just create a default instance.
if (defined($fiji_ini_file)) { if (defined($fiji_ini_file)) {
$fiji_settings_ref = read_settingsfile($phase, $fiji_ini_file, $fiji_settings_ref); $fiji_settings_ref = read_settingsfile($phase, $fiji_ini_file, $fiji_settings_ref);
if (!ref($fiji_settings_ref)) { if (!ref($fiji_settings_ref)) {
return $fiji_settings_ref; # actually an error message return $fiji_settings_ref; # actually an error message
} }
} else { } else {
$fiji_settings_ref->{'FIUs'} = (); $fiji_settings_ref->{'design'} = {};
_set_defaults(DESIGNMAP, $fiji_settings_ref->{'design'}, $phase);
$fiji_settings_ref->{'FIUs'} = [];
} }
return $fiji_settings_ref; return $fiji_settings_ref;
} }
...@@ -93,7 +94,6 @@ sub save ($) { ...@@ -93,7 +94,6 @@ sub save ($) {
my $fiu_cnt = 0; my $fiu_cnt = 0;
foreach my $key (keys %{$self}) { foreach my $key (keys %{$self}) {
my $val = $self->{$key}; 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 "REF") {
if (ref($val) eq "HASH") { if (ref($val) eq "HASH") {
if ($key eq "design") { if ($key eq "design") {
...@@ -114,8 +114,14 @@ sub save ($) { ...@@ -114,8 +114,14 @@ sub save ($) {
# Copy value to new hash with external naming. # Copy value to new hash with external naming.
$ini_fiu->{$ini_name} = $fiu->{$k}; $ini_fiu->{$ini_name} = $fiu->{$k};
# Convert value to external representation # Convert value to external representation
_export_value(FIUMAP, $k, \$$fiu{$k}); _export_value(FIUMAP, $k, \$ini_fiu->{$ini_name});
$logger->trace(sprintf("Renaming setting %s -> %s (=%s).", $k, $ini_name, defined($ini_fiu->{$ini_name}) ? $ini_fiu->{$ini_name} : "undef")); $logger->trace(sprintf("Exporting FIU%d setting %s -> %s (%s -> %s).",
$fiu_cnt,
$k,
$ini_name,
defined($fiu->{$k}) ? $fiu->{$k} : "undef",
defined($ini_fiu->{$ini_name}) ? $ini_fiu->{$ini_name} : "undef"),
);
} }
$fiji_ini->set_block("FIU" . $fiu_cnt++, $ini_fiu); $fiji_ini->set_block("FIU" . $fiu_cnt++, $ini_fiu);
} }
...@@ -138,7 +144,13 @@ sub save ($) { ...@@ -138,7 +144,13 @@ sub save ($) {
# Copy value to new hash with external naming. # Copy value to new hash with external naming.
$ini_design->{$ini_name} = $design_ref->{$k}; $ini_design->{$ini_name} = $design_ref->{$k};
# Convert value to external representation # Convert value to external representation
_export_value(DESIGNMAP, $k, \$$design_ref{$k}); _export_value(DESIGNMAP, $k, \$ini_design->{$ini_name});
$logger->trace(sprintf("Exporting Design setting %s -> %s (%s -> %s).",
$k,
$ini_name,
defined($design_ref->{$k}) ? $design_ref->{$k} : "undef",
defined($ini_design->{$ini_name}) ? $ini_design->{$ini_name} : "undef"),
);
} }
$fiji_ini->set_block("CONSTS", $ini_design); $fiji_ini->set_block("CONSTS", $ini_design);
...@@ -164,115 +176,114 @@ sub save ($) { ...@@ -164,115 +176,114 @@ sub save ($) {
# the constants for the respective FIU, see \ref _sanitize_fiu # the constants for the respective FIU, see \ref _sanitize_fiu
# #
# \returns a reference to the hash containing the read constants. # \returns a reference to the hash containing the read constants.
sub read_settingsfile { sub read_settingsfile ($$$) {
my $logger = get_logger(); my $logger = get_logger();
my ($phase, $fiji_ini_file, $existing_settings) = @_; my ($phase, $fiji_ini_file, $existing_settings) = @_;
my $fiji_ini; my $fiji_ini;
eval { $fiji_ini = new Config::Simple($fiji_ini_file) }; # pesky library tries to die on syntax errors eval { $fiji_ini = new Config::Simple($fiji_ini_file) }; # pesky library tries to die on syntax errors
if (!defined($fiji_ini)) { if (!defined($fiji_ini)) {
my $msg = "Could not read config file \"$fiji_ini_file\": " . (defined($@) ? $@ : Config::Simple->error()); my $submsg = defined($@) ? $@ : Config::Simple->error();
if (length($submsg) == 0) {
$submsg = "Empty file?";
}
my $msg = "Could not read config file \"$fiji_ini_file\": $submsg";
$logger->error($msg); $logger->error($msg);
return $msg; return $msg;
} }
my $fiji_design_cfg = $fiji_ini->get_block("CONSTS"); my $design_ref = $fiji_ini->get_block("CONSTS");
if (!(%$fiji_design_cfg)) { if (!(%$design_ref)) {
my $msg = "Could not fetch CONSTS block from config file \"$fiji_ini_file\""; my $msg = "Could not fetch CONSTS block from config file \"$fiji_ini_file\"";
$logger->error($msg); $logger->error($msg);
return $msg; return $msg;
} }
_set_defaults(DESIGNMAP, $design_ref, $phase);
my $fiji_design = _rename_import(DESIGNMAP, $fiji_design_cfg); $design_ref = _rename_import(DESIGNMAP, $design_ref);
if (!defined($fiji_design)) { if (!defined($design_ref)) {
my $msg = "Design constants do not match the FIJI Settings naming scheme."; my $msg = "Design constants do not match the FIJI Settings naming scheme.";
$logger->error($msg); $logger->error($msg);
return $msg; return $msg;
} }
# Create a new instance or reuse the shallow hull of the existing one
my $fiji_settings_ref; my $fiji_settings_ref;
if (defined($existing_settings)) { if (!defined($existing_settings)) {
if (!blessed($existing_settings) || !$existing_settings->isa("FIJI::Settings")) { $fiji_settings_ref = {};
my $msg ="Given settings are not of type FIJI::Settings."; bless($fiji_settings_ref, "FIJI::Settings");
$logger->error($msg); } else {
return $msg; $fiji_settings_ref = $existing_settings;
} # Clear the hash
# overwrite existing Design Constants for (keys %$fiji_settings_ref) {
foreach my $k (keys(%{$fiji_design})) { delete $fiji_settings_ref->{$_};
$existing_settings->{'design'}->{$k} = $fiji_design->{$k};
} }
$fiji_design = $existing_settings->{'design'}; }
if (defined($existing_settings->{'FIUs'})) { if (!blessed($fiji_settings_ref) || !$fiji_settings_ref->isa("FIJI::Settings")) {
$fiji_settings_ref->{'FIUs'} = $existing_settings->{'FIUs'}; my $msg;
if (!defined($existing_settings)) {
$msg = "Could not create FIJI::Settings instance.";
} else { } else {
$fiji_settings_ref->{'FIUs'} = (); $msg = "Given settings are not of type FIJI::Settings.";
} }
} else { $logger->error($msg);
$fiji_settings_ref->{'FIUs'} = (); return $msg;
} }
$fiji_settings_ref->{'design'} = $design_ref;
$fiji_settings_ref->{'FIUs'} = [];
# sanitize and validate read design constants # sanitize and validate read design constants
$fiji_design = _sanitize_design($fiji_design, $phase); $design_ref = _sanitize_design($design_ref, $phase);
if (!ref($fiji_design)) { if (!ref($design_ref)) {
$logger->error($fiji_design); $logger->error($design_ref);
return $fiji_design; return $design_ref;
} }
$fiji_settings_ref->{'design'} = $fiji_design;
my $fiu_num = 0; my $fiu_num = 0;
# loop over all read FIUs
while (1) { while (1) {
my $fiu_name = "FIU" . $fiu_num; my $fiu_name = "FIU" . $fiu_num;
my $fiji_fiu_cfg = $fiji_ini->get_block($fiu_name); my $fiu_ref = $fiji_ini->get_block($fiu_name);
if (!(%$fiji_fiu_cfg)) { if (!(%$fiu_ref)) {
last; last;
} }
my $fiji_fiu = _rename_import(FIUMAP, $fiji_fiu_cfg); $fiu_ref = _rename_import(FIUMAP, $fiu_ref);
if (!defined($fiji_design)) { if (!defined($design_ref)) {
my $msg = "FIU constants of $fiu_name do not match the FIJI Settings naming scheme."; my $msg = "FIU constants of $fiu_name do not match the FIJI Settings naming scheme.";
$logger->error($msg); $logger->error($msg);
return $msg; return $msg;
} }
my $tmp_fiu = {}; my $tmp_fiu = {};
_set_defaults(FIUMAP, $tmp_fiu, $phase); _set_defaults(FIUMAP, $tmp_fiu, $phase);
# overwrite default entries
if (defined($existing_settings)) { foreach my $k (keys(%{$fiu_ref})) {
my $ex_fiu = @{$existing_settings->{'FIUs'}}[$fiu_num]; $tmp_fiu->{$k} = $fiu_ref->{$k};
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); $fiu_ref = $tmp_fiu;
if (!defined($fiji_fiu)) {
my $msg = "Constants for $fiu_name in FIJI Settings are invalid"; $fiu_ref = _sanitize_fiu($fiu_ref, $phase);
if (!ref($fiu_ref)) {
my $msg = "(Some) constants for $fiu_name in FIJI Settings are invalid.";
$logger->error($msg); $logger->error($msg);
return $msg; return $msg;
} }
@{$fiji_settings_ref->{'FIUs'}}[$fiu_num] = $fiji_fiu; $fiji_settings_ref->{'FIUs'}->[$fiu_num] = $fiu_ref;
$fiu_num++; $fiu_num++;
$logger->trace("Read in $fiu_name from FIJI Settings file successfully."); $logger->trace("Read in $fiu_name from FIJI Settings file successfully.");
} }
if ($fiu_num == 0) { if ($fiu_num == 0) {
$logger->debug("Could not fetch any FIU block from config file \"$fiji_ini_file\""); $logger->debug("Could not fetch any FIU blocks from config file \"$fiji_ini_file\"");
$fiji_settings_ref->{'FIUs'} = [];
} }
# FIU_NUM is optional in the Settings file... if it was set check that # FIU_NUM is optional in the Settings file... if it was set check that
# it corresponds to the number of FIU<number> blocks. # it corresponds to the number of FIU<number> blocks.
if (defined($fiji_design->{'FIU_NUM'}) && $fiji_design->{'FIU_NUM'} != $fiu_num) { if (defined($design_ref->{'FIU_NUM'}) && $design_ref->{'FIU_NUM'} != $fiu_num) {
my $msg = FIU_NUM->{'ini_name'} . " does not match the numbers of FIU blocks found."; my $msg = FIU_NUM->{'ini_name'} . " does not match the numbers of FIU blocks found.";
$logger->error($msg); $logger->error($msg);
return $msg; return $msg;
} else { } else {
$fiji_design->{'FIU_NUM'} = $fiu_num; # assume the best if FIU_NUM constant is not given $design_ref->{'FIU_NUM'} = $fiu_num; # assume the best if FIU_NUM constant is not given
} }
splice(@{$fiji_settings_ref->{'FIUs'}}, $fiu_num); splice(@{$fiji_settings_ref->{'FIUs'}}, $fiu_num);
...@@ -300,6 +311,10 @@ sub _set_defaults { ...@@ -300,6 +311,10 @@ sub _set_defaults {
next; next;
} }
# Also, do not overwrite existing values
if (defined($consts_ref->{$k})) {
next;
}
$consts_ref->{$k} = $map_ref->{$k}->{default}; $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})); $logger->trace(sprintf("Adding default constant: %s (%s) = %s.", $k, $map_ref->{$k}->{'ini_name'}, $map_ref->{$k}->{default}));
} }
...@@ -307,13 +322,6 @@ sub _set_defaults { ...@@ -307,13 +322,6 @@ sub _set_defaults {
} }
sub _clone ($) {
my ($existing_settings_ref) = @_;
my $new_settings_ref = \%{ Clone::clone ($existing_settings_ref) };
return $new_settings_ref;
}
sub validate_design_value { sub validate_design_value {
my ($k, $v_ref) = @_; my ($k, $v_ref) = @_;
return validate_value(DESIGNMAP, $k, $v_ref); return validate_value(DESIGNMAP, $k, $v_ref);
...@@ -438,7 +446,11 @@ sub _rename_import { ...@@ -438,7 +446,11 @@ sub _rename_import {
my $ini_name = $map_ref->{$k}->{'ini_name'}; my $ini_name = $map_ref->{$k}->{'ini_name'};
if (exists($consts_ref->{$ini_name}) && $ini_name ne $k) { if (exists($consts_ref->{$ini_name}) && $ini_name ne $k) {
$consts_ref->{$k} = $consts_ref->{$ini_name}; $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")); $logger->trace(sprintf("Renaming Design setting %s -> %s (=%s).",
$ini_name,
$k,
defined($consts_ref->{$ini_name}) ? $consts_ref->{$ini_name} : "undef"),
);
delete $consts_ref->{$ini_name}; delete $consts_ref->{$ini_name};
} }
} }
......
...@@ -41,23 +41,57 @@ sub Populate { ...@@ -41,23 +41,57 @@ sub Populate {
my $logger = get_logger(); my $logger = get_logger();
my($self, $args) = @_; my($self, $args) = @_;
my $settings = delete $args->{'-settings'}; my $settings = delete $args->{'-settings'};
if (!defined($settings) || ref($settings) ne 'REF' || !blessed(${$settings}) || !${$settings}->isa("FIJI::Settings")) { if (!defined($settings) || !blessed($settings) || !$settings->isa("FIJI::Settings")) {
$logger->error("Given settings are not of type FIJI::Settings. No way to report this back from the constructor..."); $logger->error("Given settings are not of type FIJI::Settings. No way to report this back from the constructor...");
} else { } else {
$self->{'settings'} = $settings; $self->{'settings'} = $settings;
if (ref(${$self->{'settings'}}->{'FIUs'}) ne 'ARRAY') { if (ref($self->{'settings'}->{'FIUs'}) ne 'ARRAY') {
$logger->debug("Adding empty FIUs array to settings reference."); $logger->debug("Adding empty FIUs array to settings reference.");
${$self->{'settings'}}->{'FIUs'} = []; $self->{'settings'}->{'FIUs'} = [];
} }
} }
# FIXME: add an option to store a CODE reference that is called when any field is invalid # FIXME: add an option to store a CODE reference that is called when any field is invalid
$self->SUPER::Populate($args); $self->SUPER::Populate($args);
$self->_populate_widget($self); $self->_populate_widget($self);
$self->ConfigSpecs(
-nets => [qw/METHOD nets Nets/, undef],
-settings => [qw/METHOD settings Settings/, undef],
);
$self->update(); $self->update();
} }
sub nets {
my $logger = get_logger();
my ($self, $nets) = @_;
if (defined($nets)) {
if (ref($nets) ne 'ARRAY') {
$logger->error("Ignoring invalid nets array");
return undef;
}
$self->{'nets'} = $nets;
$self->update();
}
return $self->{'nets'}
}
sub settings {
my $logger = get_logger();
my ($self, $settings) = @_;
if (defined($settings)) {
if (!blessed($settings) || !$settings->isa("FIJI::Settings")) {
$logger->error("Given settings are not of type FIJI::Settings.");
return undef;
}
$self->{'settings'} = $settings;
$self->update();
}
return $self->{'settings'}
}
## @method update() ## @method update()
# @brief redraws the widget on fundamental changes # @brief redraws the widget on fundamental changes
# #
...@@ -95,14 +129,22 @@ sub update { ...@@ -95,14 +129,22 @@ sub update {
return; return;
} }
$logger->trace("Connect widget ($name) with new settings instance hash ($k)"); $logger->trace("Connect widget ($name) with new settings instance hash ($k)");
$valw->{'fiji_backend_ref'} = \${$self->{'settings'}}->{'design'}->{$k}; my $orig_ref = \$self->{'settings'}->{'design'}->{$k};
my $type = DESIGNMAP->{$k}->{'type'}; my $type = DESIGNMAP->{$k}->{'type'};
my $orig = ${$self->{'settings'}}->{'design'}->{$k}; my $orig = $$orig_ref;
my $val = defined($type) && $type eq 'hexadecimal' ? sprintf("0x%x", $orig) : $orig; my $val = defined($type) && $type eq 'hexadecimal' ? sprintf("0x%x", $orig) : $orig;
if (ref($valw) eq 'Tk::CompleteEntry') { if (ref($valw) eq 'Tk::CompleteEntry') {
$valw->configure('-choices' => $net_choices); $valw->configure('-choices' => $net_choices,
'-textvariable' => $orig_ref,
);
} else {
if (defined($val)) {
$valw->configure('-text' => $val);
} else {
$valw->delete('0', 'end');
}
} }
$valw->configure('-text' => $val); $valw->validate();
} }
############## ##############
...@@ -147,7 +189,7 @@ sub update { ...@@ -147,7 +189,7 @@ sub update {
my $fiu_cnt = $self->_fiu_cnt(); my $fiu_cnt = $self->_fiu_cnt();
for (my $i = 0; $i < $fiu_cnt; $i++) { for (my $i = 0; $i < $fiu_cnt; $i++) {
my $fiu_ref = @{${$self->{'settings'}}->{'FIUs'}}[$i]; my $fiu_ref = @{$self->{'settings'}->{'FIUs'}}[$i];
$self->_add_fiu($fiu_ref, $i); $self->_add_fiu($fiu_ref, $i);
} }
} }
...@@ -211,21 +253,15 @@ sub _populate_widget { ...@@ -211,21 +253,15 @@ sub _populate_widget {
);