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

Allow for filtering drivers in the driver selection dialog

 - extract _add_driver_radiobutton_list from existing code
 - refactor it to allow it to be called repeatedly while reusing widgets
 - make some private Netlist functions public as they are used elsewhere :/
 - eliminate duplicated nets (low-hanging workaround) for a nuisance
   of _get_net_connections().
 - add FIJISearchWidget to the dialog and call _add_driver_radiobutton_list
   from its callback after filtering the driver list
parent 3ce68aa8
......@@ -858,7 +858,7 @@ sub _select_driver {
return @{$connected}[$sel];
}
## @method private _connection_tostr ($connection,$conn_str_list_ref)
## @method connection_tostr ($connection,$conn_str_list_ref)
# @brief Stringifies a connection information
#
# The string is in the format \<TYPE\>: \<PATH|TO|Netname\>
......@@ -869,7 +869,7 @@ sub _select_driver {
# @param conn_str_list_ref optional list where a hash describing the connection is pushed
#
# @returns STRING in the format \<TYPE\>: \<PATH|TO|Netname\>
sub _connection_tostr {
sub connection_tostr {
my ($self, $connection, $conn_str_list_ref) = @_;
my $path;
my $type;
......@@ -896,7 +896,14 @@ sub _connection_tostr {
return $str;
}
sub _sort_conn_str_list {
sub uniq_conn_str_list {
my %seen;
my ($self, $conn_str_list_ref) = @_;
my @list = grep !$seen{$_->{str}}++, @{$conn_str_list_ref};
return \@list;
}
sub sort_conn_str_list {
my ($self, $conn_str_list_ref) = @_;
my @list = sort {
my $a_out = ($a->{str} =~ /[QOqo](\[[0-9]+\]){0,1}[ ]*$/);
......@@ -905,6 +912,12 @@ sub _sort_conn_str_list {
return -1 if ($a_out);
return 1 if ($b_out);
} @{$conn_str_list_ref};
return \@list;
}
sub filter_conn_str_list {
my ($self, $conn_str_list_ref, $regex) = @_;
my @list = grep { $_->{'path'} =~ $regex } @{$conn_str_list_ref};
return \@list;
}
......@@ -1149,7 +1162,7 @@ sub _get_net_connections {
# FIXME: use that knowledge to fail early (if another iteration or loop matches too)?
if (exists($drivers[0]) && $assign_driver_supplied && $statement != $drivers[0]) {
# return "Driver mismatch: actual \"" . ($statement->rhs) . "\" is not given \"$driver_path\"";
$logger->debug("Driver mismatch: actual \"" . ($statement->rhs) . "\" is not given \"$driver_path\". This can happen for vectored nets if they are instrumented multiple times.");
$logger->debug("Driver mismatch: actual \"" . ($statement->rhs) . "\" is not the given \"$driver_path\". This can happen for vectored nets if they are instrumented multiple times.");
}
}
......@@ -1189,6 +1202,9 @@ sub _get_net_connections {
foreach my $cell ($mod->cells) {
foreach my $pin ($cell->pins) {
my $bit_offset_total = 0;
# FIXME: check for duplicates: nets can be present multiple times in a single pin declaration:
# in case of concatenations, e.g. .S({GND, GND, GND, some_wire}).
# These can never be drivers though in practice.
foreach my $netname ($pin->netnames) {
my $bit_offset_range = _offset_of_bit_in_range($bit, $netname->{'msb'}, $netname->{'lsb'});
if ($netname->{'netname'} eq $net_name && ($bit_offset_range != -1)) {
......
......@@ -1602,6 +1602,46 @@ sub _select_net_dialog {
return undef;
}
sub _add_driver_radiobutton_list {
my ($self, $frame, $conn_str_list, $sel, $driver_type, $driver_path) = @_;
my $driver_container_pane = @{$frame->children()}[2];
# Add a radio button for each possible object and save them
my $i = 0;
my @driver_widgets = @{@{$driver_container_pane->children()}[0]->children()}[0]->children();
my $driver_cnt = scalar(@driver_widgets)/2;
for my $conn (@{$conn_str_list}) {
my $radio_button;
my $driver_label;
# Reuse old widgets if possible
if ($driver_cnt > $i) {
$radio_button = @driver_widgets[2 * $i];
$radio_button->configure(-value => $conn);
$driver_label = @driver_widgets[2 * $i + 1];
$driver_label->configure(-text => $conn->{str});
} else {
$radio_button = $driver_container_pane->Radiobutton(-value => $conn, -variable => \$sel);
$driver_label = $driver_container_pane->Label(-text => $conn->{str}, -justify => "left");
$radio_button->grid(-row => $i + 1, -column => 0);
$driver_label->grid(-row => $i + 1, -column => 1, -sticky => "w");
}
# preselect driver
if (!defined($$sel) && ($driver_type eq $conn->{'type'}) && ($driver_path eq $conn->{'path'})) {
$$sel = $conn;
}
$i++;
}
# Remove superfluous widgets
if ($i < $driver_cnt) {
for (my $j = $i; $j < $driver_cnt; $j += 1) {
@driver_widgets[2 * $j]->destroy;
@driver_widgets[2 * $j + 1]->destroy;
}
}
}
## @method _select_driver_dialog(idx)
# prompt the user to select a driver from the objects connected to the given netpath
sub _select_driver_dialog($) {
......@@ -1643,29 +1683,6 @@ sub _select_driver_dialog($) {
$possible_drivers = $connections{'connected'};
}
# Build the DialogBox
my $name_str = "FIU $fiu_idx";
$name_str .= " (\"$fiu_name\")" if (defined($fiu_name) && length($fiu_name) > 0);
my $select_driver_dialog = $self->DialogBoxUL(-title => "Driver for $name_str", -buttons => ["~OK", "~Cancel"]);
my $frame = $select_driver_dialog->add('Frame');
my $driver_container_pane = $frame->Scrolled('Pane', '-scrollbars' => 're', '-sticky' => 'nwse');
my $esc_button = @{$select_driver_dialog->buttons()}[1];
if (defined($esc_button)) {
$logger->debug("Binding escape to $esc_button");
$select_driver_dialog->bind('<Escape>' => [$select_driver_dialog->Subwidget("B_$esc_button"), 'Invoke']);
}
Tk::FIJIUtils::bind_mousewheel($select_driver_dialog->toplevel,$driver_container_pane);
Tk::FIJIUtils::set_icon($select_driver_dialog);
$frame->Label(-text => "Select the driver for net \"" . $netpath . "\"", -justify => "left")->pack('-fill' => 'x', '-expand' => 0,'-side' => 'top');
$driver_container_pane->pack('-expand' => 1,
'-fill' => 'both',
'-anchor' => 'nw',
'-side' => 'top');
# Add a radio button for each possible object and save them
my $sel;
my $conn_str_list = [];
......@@ -1673,35 +1690,57 @@ sub _select_driver_dialog($) {
if (@{$possible_drivers} > 1) {
for my $conn (@{$possible_drivers}) {
FIJI::Netlist->_connection_tostr($conn, $conn_str_list);
FIJI::Netlist->connection_tostr($conn, $conn_str_list);
}
$conn_str_list = FIJI::Netlist->_sort_conn_str_list($conn_str_list);
# Remove duplicate elimination if Netlist's _get_net_connections does not longer
# create them in the cell pins loop in the first place
$conn_str_list = FIJI::Netlist->uniq_conn_str_list($conn_str_list);
$conn_str_list = FIJI::Netlist->sort_conn_str_list($conn_str_list);
# Build the DialogBox
my $name_str = "FIU $fiu_idx";
$name_str .= " (\"$fiu_name\")" if (defined($fiu_name) && length($fiu_name) > 0);
my $select_driver_dialog = $self->DialogBoxUL(-title => "Driver for $name_str", -buttons => ["~OK", "~Cancel"]);
my $frame = $select_driver_dialog->add('Frame');
$frame->Label(-text => "Select the driver for net \"" . $netpath . "\"", -justify => "left")->pack('-fill' => 'x', '-expand' => 0,'-side' => 'top');
my $search_widget = $frame->FIJISearchWidget(
'-label' => "Filter Drivers",
);
$search_widget->configure(-callback => sub {
my ($regex) = @_;
my $filtered_list = FIJI::Netlist->filter_conn_str_list($conn_str_list, $regex);
$self->_add_driver_radiobutton_list($frame, $filtered_list, \$sel, $driver_type, $driver_path);
return;
},
);
my $driver_container_pane = $frame->Scrolled('Pane', '-scrollbars' => 're', '-sticky' => 'nwse', -height => List::Util::max($self->screenheight/4, 600));
my $esc_button = @{$select_driver_dialog->buttons()}[1];
if (defined($esc_button)) {
$logger->debug("Binding escape to $esc_button");
$select_driver_dialog->bind('<Escape>' => [$select_driver_dialog->Subwidget("B_$esc_button"), 'Invoke']);
}
my $i = 0;
for my $conn (@{$conn_str_list}) { # FIXME: sort (and probably refactor this whole thing + FIJI::Netlist->_connection_tostr)
my $radio_button = $driver_container_pane->Radiobutton(-value => $i, -variable => \$sel);
my $driver_label = $driver_container_pane->Label(-text => $conn->{str}, -justify => "left");
Tk::FIJIUtils::bind_mousewheel($frame->toplevel,$driver_container_pane);
Tk::FIJIUtils::set_icon($select_driver_dialog);
# preselect driver
if ( !defined $sel
&& $driver_type eq @{$conn_str_list}[$i]->{'type'}
&& $driver_path eq @{$conn_str_list}[$i]->{'path'})
{
$sel = $i;
}
$radio_button->grid(-row => $i + 1, -column => 0);
$driver_label->grid(-row => $i + 1, -column => 1, -sticky => "w");
$i++;
}
$self->_add_driver_radiobutton_list($frame, $conn_str_list, \$sel, $driver_type, $driver_path);
$search_widget->pack(
'-fill' => 'x',
'-anchor' => 'nw',
'-side' => 'top'
);
$driver_container_pane->pack('-expand' => 1,
'-fill' => 'both',
'-anchor' => 'nw',
'-side' => 'top');
$frame->pack('-expand' => 1,
'-fill' => 'both',
'-anchor' => 'nw',
'-side' => 'top');
my $diag_ret;
$diag_ret = $select_driver_dialog->Show;
my $diag_ret = $select_driver_dialog->Show;
if (!defined($diag_ret) || ($diag_ret eq "Cancel") || !defined $sel) {
# User aborted driver selection.
# If there was no previous selection we should probably warn him
......@@ -1712,15 +1751,14 @@ sub _select_driver_dialog($) {
return undef;
}
};
} else {
FIJI::Netlist->_connection_tostr(@{$possible_drivers}[0], $conn_str_list);
$sel = 0;
$logger->info("Automatically selecting ".@{$conn_str_list}[$sel]->{'path'}."|".@{$conn_str_list}[$sel]->{'path'}." as a driver for $netpath as there's only one option");
$sel = @{$conn_str_list}[0];
$logger->info("Automatically selecting ".$sel->{'type'}.": ".$sel->{'path'}." as a driver for $netpath as there's only one option");
}
$self->{'settings'}->{'fius'}[$fiu_idx]->{'FIU_DRIVER_PATH'} = @{$conn_str_list}[$sel]->{'path'};
$self->{'settings'}->{'fius'}[$fiu_idx]->{'FIU_DRIVER_TYPE'} = @{$conn_str_list}[$sel]->{'type'};
$self->{'settings'}->{'fius'}[$fiu_idx]->{'FIU_DRIVER_PATH'} = $sel->{'path'};
$self->{'settings'}->{'fius'}[$fiu_idx]->{'FIU_DRIVER_TYPE'} = $sel->{'type'};
return undef;
}
......
Supports Markdown
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