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

Added "Display Groups" to DESIGNMAP in FIJI.pm, allowing visually grouping the widgets.

Added GUI features for fiji_setup: Choose port names, choose drivers upon save, validate drivers.
Added driver type and path to INI files.
parent bc3be3e4
......@@ -46,15 +46,21 @@ use warnings;
# - depends_on = (optional) specifies the key of another constant.
# The respective constant is only relevant (and thuse required as input)
# if the value of the referenced constant is true.
# - group = (optional) specifies how to group this value in output. Value will not be displayed if undef
# - noedit = (optional) display value, but don't allow to alter
# - default = (optional) default value if not given in file and not determinable otherwise
# - help = (optional) short help text, e.g. to be displayed via Tk:Balloon
# - forbidden_by = (optional) specifies the key of another constant
# The respective constant may not be enabled if the value
# of the referenced constant is true
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
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",
......@@ -71,34 +77,43 @@ BEGIN {
phases_opt => [qw(setup instrument download)], # currently not user-configurable at all
},
CLOCK_NET => {
type => 'net',
description => "Clock net",
ini_name => "CLOCK_NET",
phases_opt => [qw(setup download)],
type => 'net',
help => "Select a net in the DUT which shall be used to clock the FIJI logic",
ini_name => "CLOCK_NET",
phases_opt => [qw(setup download)],
group => 'clock',
},
FREQUENCY => {
description => "Clock frequency",
ini_name => "FREQUENCY",
help => "Enter the clock frequency in Hz.\n This information is needed e.g. to calculate the Baud rate prescaler",
ini_name => "FREQUENCY",
default => 50e6,
type => 'natural',
phases_opt => [qw(setup download)],
unit => 'Hz',
unit => 'Hz',
group => 'clock',
},
BAUDRATE => {
description => "Baud rate",
help => "Enter the Baud rate for communication between Host and FIJI logic.",
ini_name => "BAUDRATE",
default => 115200,
type => 'natural',
unit => 'bps',
group => 'general_control',
},
ID => {
description => "Design ID",
help => "The design ID is automatically calculated upon instrumentation.",
ini_name => "ID",
type => 'hexadecimal',
phases_opt => [qw(setup instrument)], # generated in instrumentation
noedit => 1,
},
TIMER_WIDTH => {
description => "Timer width",
help => "Enter the timer width in bytes.\n This influences the maximum fault duration.",
ini_name => "TIMER_WIDTH",
default => 4,
type => 'natural',
......@@ -106,10 +121,12 @@ BEGIN {
values => sub {
my $val = shift;
return ($val > 0 && $val <= 16);
}
},
group => 'general_control',
},
LFSR_WIDTH => {
description => "LFSR width",
help => "Enter the width of the LFSR in bits.\n The LFSR is used to emulate \"floating\" nets in the stuck-open model.",
ini_name => "LFSR_WIDTH",
default => 16,
type => 'natural',
......@@ -117,79 +134,112 @@ BEGIN {
values => sub {
my $val = shift;
return $val > 0 && $val <= 64;
}
},
group => 'lfsr',
},
LFSR_POLY => {
description => "LFSR polynomial",
help => "Enter the polynomial for the LFSR.\n The LFSR is used to emulate \"floating\" nets in the stuck-open model.",
ini_name => "LFSR_POLY",
default => 0x2D,
type => 'hexadecimal',
values => sub {
my $val = shift; # FIXME: depends on LFSR_WIDTH
return $val > 0 && $val <= (2**64 - 1);
}
},
group => 'lfsr',
},
LFSR_SEED => {
description => "LFSR seed value",
help => "Enter the starting value for the LFSR.\n The LFSR is used to emulate \"floating\" nets in the stuck-open model.",
ini_name => "LFSR_SEED",
default => 0xCAFE,
type => 'hexadecimal',
values => sub {
my $val = shift; # FIXME: depends on LFSR_WIDTH
return $val >= 0 && $val <= (2**64 - 1);
}
},
group => 'lfsr',
},
# External reset
RESET_EXT_EN => {
description => "Use external reset",
help => "If enabled, the FIJI logic can be reset using an FPGA pin.",
ini_name => "RESET_EXT_EN",
default => 0,
type => 'boolean',
group => 'reset_external',
},
RESET_EXT_ACTIVE => {
description => "External Reset: Active level",
help => "If enabled, the FIJI logic can be reset using an FPGA pin.",
ini_name => "RESET_EXT_ACTIVE",
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'RESET_EXT_EN',
group => 'reset_external',
},
RESET_EXT_IN_NAME => {
description => "External Reset: Port name (prefix)",
help => "Specify the name prefix of the external reset port in the wrapper.\n".
"'_n' will be appended if low-active reset is selected,\n".
"'_i' will be appended at the end",
ini_name => "RESET_EXT_IN_NAME",
default => "s_fiji_reset",
group => 'reset_external',
depends_on => 'RESET_EXT_EN',
phases_opt => [qw(instrument download)],
},
# Reset from DUT
RESET_DUT_OUT_EN => {
description => "Enable DUT-to-FIJI reset",
ini_name => "RESET_DUT_OUT_EN",
default => 0,
type => 'boolean',
description => "Enable DUT-to-FIJI reset",
help => "If enabled, a net in the DUT is used as a reset source for the FIJI logic.",
ini_name => "RESET_DUT_OUT_EN",
default => 0,
type => 'boolean',
group => 'reset_from_dut',
forbidden_by => 'RESET_DUT_IN_EN',
},
RESET_DUT_OUT_NAME => {
description => "Source net for DUT-to-FIJI reset",
help => "If enabled, a net in the DUT is used as a reset source for the FIJI logic.",
ini_name => "RESET_DUT_OUT_NAME",
depends_on => 'RESET_DUT_OUT_EN',
type => 'net',
group => 'reset_from_dut',
},
RESET_DUT_OUT_ACTIVE => {
description => "Active level for DUT-to-FIJI reset",
help => "If enabled, a net in the DUT is used as a reset source for the FIJI logic.",
ini_name => "RESET_DUT_OUT_ACTIVE",
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'RESET_DUT_OUT_EN',
group => 'reset_from_dut',
},
# Reset to DUT
RESET_DUT_IN_EN => {
description => "Enable FIJI-to-DUT reset",
ini_name => "RESET_DUT_IN_EN",
default => 0,
type => 'boolean',
description => "Enable FIJI-to-DUT reset",
help => "If enabled, the DUT will be reset from the FIJI logic.",
ini_name => "RESET_DUT_IN_EN",
default => 0,
type => 'boolean',
group => 'reset_to_dut',
forbidden_by => 'RESET_DUT_OUT_EN',
},
RESET_DUT_IN_NAME => {
description => "Port for FIJI-to-DUT reset",
ini_name => "RESET_DUT_IN_NAME",
depends_on => 'RESET_DUT_IN_EN',
type => 'port',
help => "The specified DUT reset input will be connected\n to the FIJI logic's reset output.",
ini_name => "RESET_DUT_IN_NAME",
depends_on => 'RESET_DUT_IN_EN',
type => 'toplevel_port',
group => 'reset_to_dut',
},
RESET_DUT_IN_DURATION => {
description => "Duration for FIJI-to-DUT reset",
help => "Enter the duration of each FIJI-to-DUT reset operation in clock cycles.",
ini_name => "RESET_DUT_IN_DURATION",
type => 'natural',
default => 1,
......@@ -199,90 +249,154 @@ BEGIN {
return $val > 0 && $val <= 2**32-1;
},
depends_on => 'RESET_DUT_IN_EN',
group => 'reset_to_dut',
},
RESET_DUT_IN_ACTIVE => {
description => "Active level for FIJI-to-DUT reset",
help => "Enter the level the FIJI-to-DUT reset signal shall be brought to during reset.",
ini_name => "RESET_DUT_IN_ACTIVE",
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'RESET_DUT_IN_EN',
group => 'reset_to_dut',
},
# Trigger from DUT
TRIGGER_DUT_EN => {
description => "Enable DUT-to-FIJI trigger",
ini_name => "TRIGGER_DUT_EN",
default => 0,
type => 'boolean',
help => "If enabled, a signal in the DUT can be selected to trigger fault injection operations.\n".
"Once a pattern is downloaded with the INTERNAL trigger enabled, the FIJI logic waits for\n".
"an inactive-to-active transition on this signal before starting to count down duration t1.",
ini_name => "TRIGGER_DUT_EN",
default => 0,
type => 'boolean',
group => 'trigger',
},
TRIGGER_DUT_NAME => {
description => "Source net for DUT-to-FIJI trigger",
ini_name => "TRIGGER_DUT_NAME",
depends_on => 'TRIGGER_DUT_EN',
type => 'net',
help => "Select the net in the DUT which shall be used to trigger fault injection operations.",
ini_name => "TRIGGER_DUT_NAME",
depends_on => 'TRIGGER_DUT_EN',
type => 'net',
group => 'trigger',
},
TRIGGER_DUT_ACTIVE => {
description => "Active level for DUT-to-FIJI trigger",
ini_name => "TRIGGER_DUT_ACTIVE",
help => "Select the signal level to trigger fault injection.",
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'TRIGGER_DUT_EN',
group => 'trigger',
},
# External trigger
TRIGGER_EXT_EN => {
description => "Enable external trigger",
help => "If enabled, an I/O port can be selected to trigger fault injection operations.\n".
"Once a pattern is downloaded with the EXTERNAL trigger enabled, the FIJI logic waits for \n".
"an inactive-to-active transition on this port before starting to count down duration t1. \n".
"The port is synchronized to the FIJI logic's clock, thus introducing a few clock cycles delay.",
ini_name => "TRIGGER_EXT_EN",
default => 0,
type => 'boolean',
group => 'trigger',
},
TRIGGER_EXT_ACTIVE => {
description => "Active level for external trigger",
help => "Select the port level to trigger fault injection.",
ini_name => "TRIGGER_EXT_ACTIVE",
type => 'bit',
values => [qw(0 1)],
default => '1',
depends_on => 'TRIGGER_EXT_EN',
group => 'trigger',
},
TRIGGER_EXT_IN_NAME => {
description => "External trigger port name (prefix)",
help => "Specify the name of the external trigger port in the wrapper.\n".
"'_n' will be appended if low-active trigger level is selected,\n".
"'_i' will be appended at the end",
ini_name => "TRIGGER_EXT_IN_NAME",
default => "s_fiji_trigger_ext",
depends_on => 'TRIGGER_EXT_EN',
group => "trigger",
},
FAULT_DETECT_1_EN => {
description => "Enable fault-detect bit 1",
help => "If enabled, a signal in the DUT can be selected as a return channel.\n".
"This could e.g. be the output of a fault detection unit. \n".
"The FIJI logic registers inactive-to-active transition on this signal and returns the status \n".
"in the serial communication messages to the host.",
ini_name => "FAULT_DETECT_1_EN",
type => 'boolean',
default => 0,
group => 'fault_detect',
},
FAULT_DETECT_1_NAME => {
description => "Source net for fault-detect bit 1",
help => "Select the net in the DUT which shall be used for the fault detection feature.",
ini_name => "FAULT_DETECT_1_NAME",
type => 'net',
depends_on => 'FAULT_DETECT_1_EN',
group => 'fault_detect',
},
FAULT_DETECT_1_INVERT => {
description => "Invert fault detect bit 1",
help => "Specifies if the selected net shall be inverted prior to edge detection.\n".
"Leave unchecked if the net uses positive logic.",
ini_name => "FAULT_DETECT_1_INVERT",
type => 'boolean',
values => [qw(0 1)],
default => '0',
depends_on => 'FAULT_DETECT_1_EN',
group => 'fault_detect',
},
FAULT_DETECT_2_EN => {
description => "Enable fault-detect bit 2",
help => "If enabled, a signal in the DUT can be selected as a return channel.\n".
"This could e.g. be the output of a fault detection unit. \n".
"The FIJI logic registers inactive-to-active transition on this signal and returns the status \n".
"in the serial communication messages to the host.",
ini_name => "FAULT_DETECT_2_EN",
type => 'boolean',
default => 0,
group => 'fault_detect',
},
FAULT_DETECT_2_NAME => {
description => "Source net for fault-detect bit 2",
help => "Select the net in the DUT which shall be used for the fault detection feature.",
ini_name => "FAULT_DETECT_2_NAME",
type => 'net',
depends_on => 'FAULT_DETECT_2_EN',
},
FAULT_DETECT_1_EN => {
description => "Enable fault-detect bit 1",
ini_name => "FAULT_DETECT_1_EN",
type => 'boolean',
default => 0,
},
FAULT_DETECT_2_EN => {
description => "Enable fault-detect bit 2",
ini_name => "FAULT_DETECT_2_EN",
type => 'boolean',
default => 0,
},
FAULT_DETECT_1_INVERT => {
description => "Invert fault detect bit 1",
ini_name => "FAULT_DETECT_1_INVERT",
type => 'boolean',
values => [qw(0 1)],
default => '0',
depends_on => 'FAULT_DETECT_1_EN',
group => 'fault_detect',
},
FAULT_DETECT_2_INVERT => {
description => "Invert fault detect bit 2",
ini_name => "FAULT_DETECT_2_INVERT",
type => 'boolean',
values => [qw(0 1)],
default => '0',
depends_on => 'FAULT_DETECT_2_EN',
help => "Specify if the selected net shall be inverted prior to edge detection.\n".
"Leave unchecked if the net uses positive logic.",
ini_name => "FAULT_DETECT_2_INVERT",
type => 'boolean',
values => [qw(0 1)],
default => '0',
depends_on => 'FAULT_DETECT_2_EN',
group => 'fault_detect',
},
RX_IN_NAME => {
description => "RX port name",
help => "Specify the name of the Host-to-FIC serial RX port in the wrapper.",
ini_name => "RX_IN_NAME",
default => "s_fiji_rx_i",
phases_opt => [qw(instrument download)],
group => "general_control",
},
TX_OUT_NAME => {
description => "TX port name",
help => "Specify the name of the FIC-to-Host serial TX port in the wrapper.",
ini_name => "TX_OUT_NAME",
phases_opt => [qw(instrument download)],
default => "s_fiji_tx_o",
group => "general_control",
},
);
}
......@@ -290,6 +404,54 @@ BEGIN {
use constant \%designmap;
use constant DESIGNMAP => \%designmap;
my %displaygroups;
BEGIN {
%displaygroups = (
fault_detect => {
title => "Fault Detection Settings",
subtitle => "",
description => "Settings concerning internal fault detection propagation"
},
trigger => {
title => "Trigger Settings",
subtitle => "",
description => "Settings concerning internal and external fault injection triggers"
},
reset_to_dut => {
title => "Reset Settings",
subtitle => "Reset from FIC to DUT",
description => "Settings concerning FIJI's ability to reset the DUT"
},
reset_from_dut => {
title => "Reset Settings",
subtitle => "Reset from DUT to FIC",
description => "Settings concerning FIJI's internal (from DUT) reset feature"
},
reset_external => {
title => "Reset Settings",
subtitle => "External Reset",
description => "Settings concerning FIJI's external (via pin)reset feature"
},
lfsr => {
title => "LFSR Settings",
subtitle => "",
description => "Settings concerning the LFSR for Stuck-open emulation"
},
general_control => {
title => "General FIC settings",
subtitle => "",
description => "Settings concerning miscellanous features of FIJI"
},
clock => {
title => "Clock settings",
subtitle => "",
description => "Settings concerning the clocking of the FIJI logic"
}
)
}
use constant \%displaygroups;
use constant DISPLAYGROUPS => \%displaygroups;
my %fiumap;
BEGIN {
%fiumap = (
......@@ -297,6 +459,15 @@ BEGIN {
ini_name => "NET_NAME",
phases_opt => [qw(setup)], # defaults to undef
},
FIU_DRIVER_TYPE => {
ini_name => "DRIVER_TYPE",
values => [qw(PIN PORT ASSIGN)],
phases_opt => [qw(setup)], # defaults to undef
},
FIU_DRIVER_PATH => {
ini_name => "DRIVER_PATH",
phases_opt => [qw(setup)], # defaults to undef
},
FIU_MODEL => {
ini_name => "FAULT_MODEL",
default => "RUNTIME",
......@@ -442,8 +613,9 @@ sub ini2constkey {
use base 'Exporter';
our @EXPORT = (keys(%designmap), keys(%fiumap), keys(%testpatmap), keys(%testconstmap), keys(%fiuenum));
our @EXPORT_OK = (keys(%designmap), 'DESIGNMAP', keys(%fiumap), 'FIUMAP', keys(%testpatmap), 'TESTPATMAP', keys(%testconstmap), 'TESTCONSTMAP', keys(%fiuenum), 'FIUENUM', 'REVERSE_FIU_ENUM');
our @EXPORT = (keys(%designmap), keys(%fiumap), keys(%testpatmap), keys(%testconstmap), keys(%fiuenum), keys(%displaygroups));
our @EXPORT_OK = (keys(%designmap), 'DESIGNMAP', keys(%fiumap), 'FIUMAP', keys(%testpatmap),
'TESTPATMAP', keys(%testconstmap), 'TESTCONSTMAP', keys(%fiuenum), 'FIUENUM', 'REVERSE_FIU_ENUM','DISPLAYGROUPS',keys(%displaygroups));
## @var @EXPORT_TAGS Export Tags
#
......
......@@ -112,6 +112,17 @@ sub read_file ($) {
}
sub get_toplevel_port_names ($) {
my ($self) = @_;
my $ports_ref = [];
foreach my $mod ($self->{'nl'}->top_modules_sorted) {
foreach my $port ($mod->ports_sorted) {
push @{$ports_ref}, $port->name;
}
}
return $ports_ref;
}
# returns an array of hashes for all nets containing:
# 'name' the name of the net
# 'path' the hierarchical path of the net
......@@ -468,7 +479,7 @@ sub _select_driver($$) {
print "Select driver for net ".$net->name.": \n";
my $di;
for ($di = 0; $di < @{$connected}; $di++) {
printf ("[%d] %s\n",$di,_connection_tostr(@{$connected}[$di]));
printf ("[%d] %s\n",$di,FIJI::Netlist->_connection_tostr(@{$connected}[$di]));
}
printf ("[x] none of the above.\n",$di);
my $sel;
......@@ -490,16 +501,73 @@ sub _select_driver($$) {
#
# params
# connection the connection to print
sub _connection_tostr($) {
my ($connection) = @_;
sub _connection_tostr($;$) {
my ($self,$connection,$conn_str_list_ref) = @_;
my $path;
my $name;
my $type;
if(ref($connection) eq "Verilog::Netlist::Pin") {
return "pin: ".$connection->cell->name.$HIERSEP.$connection->name;
$name = $connection->name;
$path = $connection->cell->module->name.$HIERSEP.$connection->cell->name;
$type = "PIN";
} elsif (ref($connection) eq "Verilog::Netlist::Port") {
return "port: ".$connection->module->name.$HIERSEP.$connection->name;
$name = $connection->name;
$path = $connection->module->name;
$type = "PORT";
} elsif (ref($connection) eq "Verilog::Netlist::Contassign") {
return "assign: ".$connection->lhs."\n";
$name = $connection->lhs;
$path = $connection->module->name;
$type = "ASSIGN";
}
push @{$conn_str_list_ref}, {path=>$path.$HIERSEP.$name,type=>$type};
return $type.": ".$path.$HIERSEP.$name;
}
sub get_connection_object($$) {
my $logger = get_logger();
my ($self,$connection_path,$connection_type) = @_;
my $rv;
if ($connection_type eq "PIN") {
if($connection_path =~ /^(.+)\|(.+)\|(.+)$/) {
$logger->info("Looking for $connection_type:$1|$2|$3");
my $mod = $self->{'nl'}->find_module($1);
my $cell = $mod->find_cell($2) if (defined $mod);
my $pin = $cell->find_pin($3) if (defined $cell);
$rv = $pin;
}
} elsif ($connection_type eq "PORT") {
if($connection_path =~ /^(.+)\|(.+)$/) {
$logger->info("Looking for $connection_type:$1|$2");
my $mod = $self->{'nl'}->find_module($1);
my $port = $mod->find_port($2) if (defined $mod);
$rv = $port;
}
} elsif ($connection_type eq "ASSIGN") {
if($connection_path =~ /^(.+)\|(.+)$/) {
my $lhs = $2;
my $mod = $self->{'nl'}->find_module($1);
my $assign;
if (defined $mod) {
for my $a (grep {ref($_) eq "Verilog::ContAssign"} $mod->statements) {
if ($a->lhs eq $lhs) {
$assign = $a;
last;
}
}
}
$rv = $a;
}
}
return $rv;
}
# gets all pins, ports and assignments a net is connected to
......@@ -762,4 +830,39 @@ sub _export_module($) {
return $module_header."\n".$net_declarations."\n".$assigns."\n".$instantiations.$module_footer;
}
sub splitnet ($) {
my $logger = get_logger();
my ($self,$netpath) = @_;
my $rv = {};
my $msg;
my @net_split = split(/\|/,$netpath);
if(!defined $net_split[-2]) {
$msg = "Not a valid net path.\n";
return $msg;
}
my $mod = $self->{'nl'}->find_module($net_split[-2]);
if (!defined $mod) {
$msg = "Could not find module '".$net_split[-2]."'\n";
return $msg;
}
my $net = $mod->find_net($net_split[-1]);
if (!defined $net) {
$msg = "Could not find net '".$mod->name."|".$net_split[-1]."'\n";
return $msg;
}
$rv->{'mod'} = $mod;
$rv->{'net'} = $net;
return $rv;
}
1;
......@@ -529,6 +529,7 @@ sub _validate_hashmap ($$;$) {