Commit f13fe943 authored by Christian Fibich's avatar Christian Fibich Committed by Stefan Tauner
Browse files

find_nets now returns an array of hashes

GUI changed to Tabbed layout, Enable checkboxes, Drop-Down for bit values
parent 1fbbae33
......@@ -32,28 +32,33 @@ my %designmap;
BEGIN {
%designmap = (
FIU_NUM => {
description => "Number of FIUs",
ini_name => "FIU_NUM",
type => 'natural',
phases_opt => [qw(setup instrument download)], # auto-generated if need be
},
FIU_CFG_BITS => {
description => "Bits per FIU pattern",
ini_name => "FIU_CFG_BITS",
default => 3,
type => 'natural',
phases_opt => [qw(setup instrument download)], # currently not user-configurable at all
},
CFGS_PER_MSG => {
description => "Patterns per FIU configuration",
ini_name => "CFGS_PER_MSG",
default => 2,
type => 'natural',
phases_opt => [qw(setup instrument download)], # currently not user-configurable at all
},
CLOCK_NET => {
description => "Clock net",
ini_name => "CLOCK_NET",
phases_opt => [qw(setup download)],
type => 'net',
},
FREQUENCY => {
description => "Clock frequency",
ini_name => "FREQUENCY",
default => 50e6,
type => 'natural',
......@@ -61,27 +66,31 @@ BEGIN {
unit => 'Hz',
},
BAUDRATE => {
description => "Baud rate",
ini_name => "BAUDRATE",
default => 115200,
type => 'natural',
unit => 'bps',
},
ID => {
description => "Design ID",
ini_name => "ID",
type => 'hexadecimal',
phases_opt => [qw(setup instrument)], # generated in instrumentation
},
TIMER_WIDTH => {
description => "Timer width",
ini_name => "TIMER_WIDTH",
default => 32,
default => 4,
type => 'natural',
unit => 'bits',
unit => 'bytes',
values => sub {
my $val = shift;
return $val % 8 == 0 && $val > 0 && $val <= 64;
return ($val > 0 && $val <= 16);
}
},
LFSR_WIDTH => {
description => "LFSR width",
ini_name => "LFSR_WIDTH",
default => 16,
type => 'natural',
......@@ -92,6 +101,7 @@ BEGIN {
}
},
LFSR_POLY => {
description => "LFSR polynomial",
ini_name => "LFSR_POLY",
default => 0x2D,
type => 'hexadecimal',
......@@ -101,6 +111,7 @@ BEGIN {
}
},
LFSR_SEED => {
description => "LFSR seed value",
ini_name => "LFSR_SEED",
default => 0xCAFE,
type => 'hexadecimal',
......@@ -111,43 +122,55 @@ BEGIN {
},
# External reset
RESET_EXT_EN => {
description => "Use external reset",
ini_name => "RESET_EXT_EN",
default => 0,
type => 'boolean',
},
RESET_EXT_ACTIVE => {
description => "External Reset: Active level",
ini_name => "RESET_EXT_ACTIVE",
type => 'boolean',
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'RESET_EXT_EN',
},
# Reset from DUT
RESET_DUT_OUT_EN => {
description => "Enable DUT-to-FIJI reset",
ini_name => "RESET_DUT_OUT_EN",
default => 0,
type => 'boolean',
},
RESET_DUT_OUT_NAME => {
description => "Source net for DUT-to-FIJI reset",
ini_name => "RESET_DUT_OUT_NAME",
depends_on => 'RESET_DUT_OUT_EN',
type => 'net',
},
RESET_DUT_OUT_ACTIVE => {
description => "Active level for DUT-to-FIJI reset",
ini_name => "RESET_DUT_OUT_ACTIVE",
type => 'boolean',
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'RESET_DUT_OUT_EN',
},
# Reset to DUT
RESET_DUT_IN_EN => {
description => "Enable FIJI-to-DUT reset",
ini_name => "RESET_DUT_IN_EN",
default => 0,
type => 'boolean',
},
RESET_DUT_IN_NAME => {
description => "Net for FIJI-to-DUT reset",
ini_name => "RESET_DUT_IN_NAME",
depends_on => 'RESET_DUT_IN_EN',
type => 'net',
},
RESET_DUT_IN_DURATION => {
description => "Duration for FIJI-to-DUT reset",
ini_name => "RESET_DUT_IN_DURATION",
type => 'natural',
unit => 'cycles',
......@@ -158,35 +181,47 @@ BEGIN {
depends_on => 'RESET_DUT_IN_EN',
},
RESET_DUT_IN_ACTIVE => {
description => "Active level for FIJI-to-DUT reset",
ini_name => "RESET_DUT_IN_ACTIVE",
type => 'boolean',
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'RESET_DUT_IN_EN',
},
# Trigger from DUT
TRIGGER_DUT_EN => {
description => "Enable DUT-to-FIJI trigger",
ini_name => "TRIGGER_DUT_EN",
default => 0,
type => 'boolean',
},
TRIGGER_DUT_NAME => {
description => "Source net for DUT-to-FIJI trigger",
ini_name => "TRIGGER_DUT_NAME",
depends_on => 'TRIGGER_DUT_EN',
type => 'net',
},
TRIGGER_DUT_ACTIVE => {
description => "Active level for DUT-to-FIJI trigger",
ini_name => "TRIGGER_DUT_ACTIVE",
type => 'boolean',
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'TRIGGER_DUT_EN',
},
# External trigger
TRIGGER_EXT_EN => {
description => "Enable external trigger",
ini_name => "TRIGGER_EXT_EN",
default => 0,
type => 'boolean',
},
TRIGGER_EXT_ACTIVE => {
description => "Active level for external trigger",
ini_name => "TRIGGER_EXT_ACTIVE",
type => 'boolean',
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'TRIGGER_EXT_EN',
},
);
......@@ -220,6 +255,93 @@ BEGIN {
use constant \%fiumap;
use constant FIUMAP => \%fiumap;
my %testconstmap;
BEGIN {
%testconstmap = (
NUM_TESTS => {
ini_name => "NUM_TESTS",
type => 'natural',
phases_opt => [qw(download)],
},
REPEAT => {
ini_name => "REPEAT",
default => 0,
type => 'boolean',
phases_opt => [qw(download)],
},
REPEAT_OFFSET => {
ini_name => "REPEAT_OFFSET",
default => 0,
type => 'natural',
phases_opt => [qw(download)],
},
HALT_ON_FAULT_DETECT => {
ini_name => "HALT_ON_FAULT_DETECT",
default => 1,
type => 'boolean',
phases_opt => [qw(download)],
},
HALT_ON_UART_ERROR => {
ini_name => "HALT_ON_UART_ERROR",
default => 1,
type => 'boolean',
phases_opt => [qw(download)],
},
HALT_ON_CRC_ERROR => {
ini_name => "HALT_ON_CRC_ERROR",
default => 1,
type => 'boolean',
phases_opt => [qw(download)],
},
HALT_ON_ID_ERROR => {
ini_name => "HALT_ON_ID_ERROR",
default => 1,
type => 'boolean',
phases_opt => [qw(download)],
},
HALT_ON_UNDERRUN => {
ini_name => "HALT_ON_UNDERRUN",
default => 1,
type => 'boolean',
phases_opt => [qw(download)],
},
);
}
use constant \%testconstmap;
use constant TESTCONSTMAP => \%testconstmap;
my %testpatmap;
BEGIN {
%testpatmap = (
TIMER_VALUE_1 => {
ini_name => "TIMER_VALUE_1",
type => 'natural',
phases_opt => [qw(download)], # defaults to undef
},
TIMER_VALUE_2 => {
ini_name => "TIMER_VALUE_2",
type => 'natural',
phases_opt => [qw(download)],
},
TRIGGER => {
ini_name => "TRIGGER",
default => "NONE",
values => [qw(INT EXT NONE)],
phases_opt => [qw(setup)],
},
RESET_DUT_AFTER_CONFIG => {
ini_name => "RESET_DUT_AFTER_CONFIG",
type => 'boolean',
default => 0,
phases_opt => [qw(setup)],
},
);
}
use constant \%testpatmap;
use constant TESTPATMAP => \%testpatmap;
## @function ini2constkey ($ini_name, %$map_ref)
#
# Allows to retrieve the reversal of the mapping established by the
......@@ -238,8 +360,8 @@ sub ini2constkey {
use base 'Exporter';
our @EXPORT = (keys(%designmap), keys(%fiumap));
our @EXPORT_OK = (keys(%designmap), 'DESIGNMAP', keys(%fiumap), 'FIUMAP');
our @EXPORT = (keys(%designmap), keys(%fiumap), keys(%testpatmap), keys(%testconstmap));
our @EXPORT_OK = (keys(%designmap), 'DESIGNMAP', keys(%fiumap), 'FIUMAP', keys(%testpatmap), 'TESTPATMAP', keys(%testconstmap), 'TESTCONSTMAP');
## @var @EXPORT_TAGS Export Tags
#
......
......@@ -55,42 +55,45 @@ sub read_file ($) {
}
# returns an array with all net names
# returns an array of hashes for all nets containing:
# 'name' the name of the net
# 'path' the hierarchical path of the net
# 'net' the Verilog::Netlist::Net reference to the net
#
# possible future extension:
# returns a hash with array of...
# - the 'names' of all nets
# - the 'paths' of all nets (TODO)
# - the 'metadata' of all nets (i.e. what VP's module->nets() returns) (TODO. needed? - it's huge)
sub get_nets ($) {
my ($self) = @_;
# my $nets_ref = {'metadata' => [], 'names' => [], 'nets' => []};
my $nets_ref = [];
my $hier = "";
foreach my $mod ($self->{'nl'}->top_modules_sorted) {
$self->_get_subnets($nets_ref, $mod,"");
$self->_get_subnets($nets_ref, $mod, $hier);
}
return $nets_ref;
}
sub _get_subnets ($$) {
my ($self, $nets_ref, $mod, $hier) = @_;
$hier .= $HIERSEP if $hier ne "";
$hier .= $mod->name;
my $thishier = $hier;
$thishier .= $HIERSEP if $thishier ne "";
$thishier .= $mod->name;
foreach my $n ($mod->nets) {
if ((defined $n->msb && defined $n->lsb)) {
print "Net ".$hier.$HIERSEP.$n->name." is bussed [".$n->msb.":".$n->lsb."]\n";
for (my $i = $n->lsb; $i <= $n->msb; $i++) {
push(@{$nets_ref}, $hier.$HIERSEP.$n->name."[$i]");
}
} else {
push(@{$nets_ref}, $hier.$HIERSEP.$n->name);
print "Net ".$thishier.$HIERSEP.$n->name." is bussed [".$n->msb.":".$n->lsb."]\n";
# for (my $i = $n->lsb; $i <= $n->msb; $i++) {
# my $thisnet_ref = {name => $n->name[$i], path => $thishier, net => $n};
# push(@{$nets_ref}, $thisnet_ref);
# }
}
my $thisnet_ref = {name => $n->name, path => $thishier, net => $n};
push(@{$nets_ref}, $thisnet_ref);
#$self->_get_net_connections($n,$mod,$hier);
}
foreach my $cell ($mod->cells_sorted) {
if (defined($cell->submod)) {
$self->_get_subnets($nets_ref, $cell->submod,$hier);
$self->_get_subnets($nets_ref, $cell->submod, $thishier);
}
}
}
......
......@@ -553,7 +553,7 @@ sub _validate_hashmap ($$;$) {
#
# - FIU_NUM: > 0
# - FIU_CFG_BITS: > 0
# - TIMER_WIDTH: > 0, multiple of 8
# - TIMER_WIDTH: > 0, <= 16
# - ID: > 0, < 2^15-1
# - BAUDRATE: > 0
#
......@@ -584,7 +584,7 @@ sub _sanitize_design {
$logger->error($msg);
return $msg;
}
if (($consts_ref->{'TIMER_WIDTH'} <= 0) || ($consts_ref->{'TIMER_WIDTH'} % 8 != 0)) {
if (($consts_ref->{'TIMER_WIDTH'} <= 0) || ($consts_ref->{'TIMER_WIDTH'} > 16)) {
my $msg = "TIMER_WIDTH is invalid ($consts_ref->{'TIMER_WIDTH'}).";
$logger->error($msg);
return $msg;
......
......@@ -11,7 +11,7 @@ use warnings;
use Log::Log4perl qw(get_logger);
use Scalar::Util 'blessed';
use Tk;
use Tk::widgets qw(LabFrame Label Entry Pane Button Dialog Checkbutton CompleteEntry);
use Tk::widgets qw(LabFrame Label Entry Pane Button Dialog Checkbutton CompleteEntry NoteBook);
use Tk::DynaMouseWheelBind;
......@@ -20,10 +20,13 @@ use base qw(Tk::Frame);
use FIJI qw(:all);
use FIJI::Netlist;
Construct Tk::Widget 'FIJISettingsViewer';
use Data::Dumper;
Construct Tk::Widget 'FIJISettingsViewer';
my $fr_design; # labled frame surrounding widgets representing design constant
my $nb; # notebook holding constants and FIU frame
my $pg_design; # notebook page containing constants
my $pg_fius; # notebook page containing constants
my $fr_fius; # labled frame surrounding widgets representing design constant
my $widget_background;
......@@ -70,10 +73,12 @@ sub nets {
$logger->error("Ignoring invalid nets array");
return undef;
}
$self->{'nets'} = $nets;
# generates a list of all nets with full paths from the nets hashref
my @n = map { $_->{'path'}."|".$_->{'name'}} @{$nets};
$self->{'nets'} = \@n;
$self->update();
}
return $self->{'nets'}
return $self->{'nets'};
}
......@@ -111,13 +116,13 @@ sub update {
# 3. fetch the internal constant name for the ini_name (stored in the first label)
# 4. set the reference to the value of that name within the current settings instance
# as textvariable of the respective widget.
my @design_widgets = ${${$fr_design->children}[0]->children}[1]->children;
my @design_widgets = $pg_design->children;
my $const_cnt = @design_widgets;
my $net_choices = defined($self->{'nets'}) ? $self->{'nets'} : [];
for (my $i = 3; $i < $const_cnt; $i += 3) {
# The order of the widgets depends on their *construction* time(!)
my ($namew, $unitw, $valw) = @design_widgets[$i..$i+3];
my $name = $namew->cget('-text');
my $name = $namew->{'fiji_id'};
my $k = FIJI::ini2constkey($name);
if (!defined($k)) {
my $msg = "Could not find FIJI definition for constant named \"$name\"";
......@@ -135,16 +140,26 @@ sub update {
my $val = defined($type) && $type eq 'hexadecimal' ? sprintf("0x%x", $orig) : $orig;
if (ref($valw) eq 'Tk::CompleteEntry') {
$valw->configure('-choices' => $net_choices,
'-textvariable' => $orig_ref,
'-textvariable' => $orig_ref
);
$valw->validate();
} elsif (ref($valw) eq 'Tk::Checkbutton') {
$valw->configure('-variable' => $orig_ref);
if (defined($self->{'depends'}->{$k})) {
$valw->configure('-command' => [\&_set_fields_by_button, $self, $valw, @{$self->{'depends'}->{$k}} ]);
}
_set_fields_by_button($self, $valw, @{$self->{'depends'}->{$k}});
} elsif (ref($valw) eq 'Tk::Optionmenu') {
$valw->configure('-textvariable' => $orig_ref);
} else {
if (defined($val)) {
$valw->configure('-text' => $val);
} else {
$valw->delete('0', 'end');
}
$valw->validate();
}
$valw->validate();
}
##############
......@@ -202,23 +217,33 @@ sub _populate_widget {
my $logger = get_logger();
my ($self, $fr) = @_;
$fr->DynaMouseWheelBind('Tk::Pane');
$nb = $fr->NoteBook()->pack(
-expand => 1,
-fill => 'both'
);
$pg_design = $nb->add('designconstants',
-label=>'Design Constants',
-underline=>0);
$pg_fius = $nb->add('fius',
-label=>'FIUs',
-underline=>0);
$pg_design->DynaMouseWheelBind('Tk::Pane');
################
# design panel #
################
$fr_design = $fr->LabFrame(
-label => "Design Constants",
-labelside => "acrosstop"
)->pack(
'-side' => 'top',
'-anchor' => 'nw',
'-fill' => 'x'
);
$fr_design->gridColumnconfigure(2, '-weight' => 1);
# $pg_design = $pg_design->Frame(
# -borderwidth => 0
# )->pack(
# '-side' => 'top',
# '-anchor' => 'nw',
# '-fill' => 'x'
# );
$pg_design->gridColumnconfigure(2, '-weight' => 1);
my $i = 0;
foreach my $hdr (qw(Name Unit Value)) {
$fr_design->Label(
$pg_design->Label(
-text => $hdr,
)->grid(
'-row' => 0,
......@@ -236,15 +261,16 @@ sub _populate_widget {
foreach my $k (@keys) {
$row++;
# label
my $label = $fr_design->Label(
'-text' => DESIGNMAP->{$k}->{'ini_name'},
my $label = $pg_design->Label(
'-text' => DESIGNMAP->{$k}->{'description'},
'-justify' => 'left',
);
$label->{'fiji_id'} = DESIGNMAP->{$k}->{'ini_name'};
$label->grid(-row => $row, -column => 0,
'-sticky' => 'w'
);
# unit
my $unit = $fr_design->Label(
my $unit = $pg_design->Label(
'-text' => DESIGNMAP->{$k}->{'unit'},
);
$unit->grid(-row => $row, -column => 1,
......@@ -254,22 +280,46 @@ sub _populate_widget {
# entry
my $type = DESIGNMAP->{$k}->{'type'};
if (defined($type) && $type eq 'net') {
$entry = $fr_design->CompleteEntry(
$entry = $pg_design->CompleteEntry(
);
$entry->configure(
'-validate' => 'key',
'-validatecommand' => [\&_validate_net_entry, $self, $entry, $k],
);
$entry->grid(-row => $row, -column => 2,
'-sticky' => 'ew'
);
} elsif (defined($type) && $type eq 'boolean') {
$entry = $pg_design->Checkbutton(
'-justify' => 'left'
);
$entry->grid(-row => $row, -column => 2,
'-sticky' => 'w'
);
} elsif (defined($type) && $type eq 'bit') {
$entry = $pg_design->Optionmenu(
'-options' => DESIGNMAP->{$k}->{'values'},
'-textvariable' => \$self->{'settings'}->{'design'}->{$k},
'-width' => -1,
'-justify' => 'left');
$entry->grid(-row => $row, -column => 2,
'-sticky' => 'w'
);
} else {
$entry = $fr_design->Entry();
$entry = $pg_design->Entry();
$entry->configure(
'-validate' => 'key',
'-validatecommand' => [\&_validate_design_entry, $self, $entry, $k],
);
}
$entry->grid(-row => $row, -column => 2,
'-sticky' => 'ew'
'-sticky' => 'ew'
);
}
if (defined(DESIGNMAP->{$k}->{'depends_on'})) {
push @{$self->{'depends'}->{DESIGNMAP->{$k}->{'depends_on'}}},$entry;
}
$entry->bind('<Control-a>',
sub {
my $w = shift;
......@@ -283,7 +333,7 @@ sub _populate_widget {
# $self->_highlight_widget($entry, (FIJI::Settings::validate_design_value($k, \$entry_var)));
# }
# );
# $fr_design->Button(
# $pg_design->Button(
# -text => 'Defaults',
# -command => [\&_save, $self],
# sub {
......@@ -298,22 +348,14 @@ sub _populate_widget {
##############
# FIUs panel #
##############
$self->_add_fiu_panel($fr);
$self->_add_fiu_panel($pg_fius);
}
sub _add_fiu_panel {
my($self, $fr) = @_;
my $fr_fius_main = $fr->LabFrame(
-label => "FIUs",
-labelside => "acrosstop"
)->pack(
'-expand' => 1,
'-side' => 'top',
'-anchor' => 'nw',
'-fill' => 'both'
);
my $fr_fius_main = $fr;
$fr_fius_main->Button(
-text => 'Append empty FIU',
......
; Config::Simple 4.58
; Mon Jun 8 12:41:48 2015
; Tue Jun 9 16:53:10 2015
[FIU0]
NET_NAME=i2c_master_top|i2c_master_byte_ctrl|N_152_tz
LFSR_MASK=0x1
FAULT_MODEL=RUNTIME
[CONSTS]
TIMER_WIDTH=32
LFSR_WIDTH=16
CFGS_PER_MSG=2
FIU_NUM=1
TRIGGER_DUT_EN=0
LFSR_POLY=0x2d
RESET_DUT_IN_EN=0
LFSR_SEED=0xcafe
TRIGGER_DUT_EN=0
FREQUENCY=50000000