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

Added random test, comments

parent ffd9111d
......@@ -43,6 +43,9 @@ sub new($) {
return $self;
}
## Wrapper for port->send_config
# Generates a configuration hash from discrete parameters
#
sub _test_fi_uart {
my (
$port, $payload_ref, $t1_duration, $t2_duration,
......@@ -59,9 +62,14 @@ sub _test_fi_uart {
reset => $reset,
consts => $fiji_consts,
);
# FIXME timeout must correspond to t1_duration/t2_duration
return $port->send_config( \%config, 1000, 0, 1 );
}
## Download tests contained in the .cfg file
# Params
# portname Optional serial port to use
sub download_auto ($;$$) {
my $msg;
my $logger = get_logger();
......@@ -78,7 +86,6 @@ sub download_auto ($;$$) {
or $logger->fatal("Could not init UART.")
and return "Could not init UART.";
my $toff = 0;
my $ri = 0;
my $halt;
......@@ -116,7 +123,61 @@ sub download_auto ($;$$) {
return $msg;
}
sub download_manual ($;$$) {
## Download randomly generated tests
# Params
# cfg Configuration hash
# cfg->{'min_duration'}[0..n] Minimum duration constraints for patterns
# cfg->{'max_duration'}[0..n] Maximum duration constraints for patterns
# cfg->{'probabilities'}[FIJI::FIUENUM->{'NONE'}] Probability of fault-free case
# cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_AT_0'}] Probability of stuck-at-0 error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_AT_1'}] Probability of stuck-at-1 error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'DELAY'}] Probability of delay error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'SEU'}] Probability of seu error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_OPEN'}] Probability of stuck-open error
# testref Reference where download_random() places the modified FIJI::Tests object
# after the test execution
# portname Optional serial port to use
sub download_random ($$$;$) {
my $logger = get_logger();
my ($self,$cfg,$testref,$portname) = @_;
my $fiji_design_consts = $self->{'fiji_tests'}->{'ext'}->{'global_settings'}->{'design'};
$portname = $self->{'fiji_tests'}->{'design'}->{'UART'} if (!defined $portname);
my $port =
FIJI::Connection->init( $portname, $self->{'fiji_tests'}->{'ext'}->{'global_settings'}->{'design'}->{'BAUDRATE'} )
or $logger->fatal("Could not init UART.")
and return "Could not init UART.";
$logger->info("Downloading in random mode.");
my @tests;
my $ti = 0;
my $recv_msg;
do {
@tests[$ti] = $self->{'fiji_tests'}->make_random_test($cfg);
$logger->info("=== Test $ti ===");
$recv_msg = $self->download_test($tests[$ti++],$port);
} while ($self->_check_halt($recv_msg) != 1);
my $msg = "Halt because of HALT_ON_xxx. Failed test: ".($ti-1);
$self->{'fiji_tests'}->{'design'}->{'NUM_TESTS'} = $ti;
$self->{'fiji_tests'}->{'design'}->{'REPEAT'} = 0;
$self->{'fiji_tests'}->{'design'}->{'REPEAT_OFFSET'} = 0;
$self->{'fiji_tests'}->{'tests'} = \@tests;
$self->{'fiji_tests'}->export_as_sim_script("sim.script",$ti-1,0);
$testref = $self->{'fiji_tests'};
$self->{'fiji_tests'}->save("fiji_tests_random.cfg");
return $msg;
}
## Download manually defined tests prompted from <STDIN>
# portname Optional serial port to use
sub download_manual ($;$) {
my $msg;
my $logger = get_logger();
......@@ -159,6 +220,9 @@ sub download_manual ($;$$) {
return $msg;
}
## Prompt tests from <STDIN>
# Params
#
sub _get_test_from_stdin {
my $logger = get_logger();
my ($self) = @_;
......@@ -266,6 +330,13 @@ sub _get_test_from_stdin {
return $test;
}
## Download a single test defined by a test hash
# Params
# test The hash defining the test
# test->{'TIMER_VALUE_1'}
# test->{'TIMER_VALUE_2'}
# test->{"FIU_[0..FIU_NUM]_PATTERN_[0..CFGS_PER_MSG]"}
# portname Optional serial port to use
sub download_test ($$) {
my $logger = get_logger();
my ($self,$test,$port) = @_;
......@@ -326,8 +397,11 @@ sub download_test ($$) {
$reset, $fiji_design_consts);
}
## Check the hash returned by _test_fi_uart() against HALT_ON_xxx-conditions
# Params
# recv_msg The hash returned by _test_fi_uart() containing the decoded
# return message
# Returns 1 if execution shall be halted and 0 otherwise
sub _check_halt ($) {
my $halt = 0;
my $logger = get_logger();
......
......@@ -38,6 +38,9 @@ use FIJI::Settings;
use FIJI qw(:all);
use File::Spec;
# FIXME rather similar to Settings.pm
# Can we generalize this?
## @function new ($phase, $fiji_ini_file, $existing_settings)
# Create a new settings instance.
#
......@@ -154,7 +157,6 @@ sub save ($) {
foreach my $test (@{$val}) {
my $ini_test;
foreach my $k (keys(%{$test})) {
my $ini_name = $self->{'ext'}->{'TESTPATMAP'}->{$k}->{'ini_name'};
if (!defined($test->{$k})) {
......@@ -259,8 +261,6 @@ sub read_settingsfile ($$$) {
return $msg;
}
#TODO load fiji cfg file
# Create a new instance or reuse the shallow hull of the existing one
my $fiji_settings_ref;
if (!defined($existing_settings)) {
......@@ -375,6 +375,8 @@ sub _read_fiji_cfg ($) {
return $global_settings;
}
# generate tailored TESTPATMAP for validating
# test patterns
sub _generate_testpatmap {
my ($self) = @_;
......@@ -706,6 +708,10 @@ sub _sanitize_design {
return $consts_ref;
}
# generate a sim script from the current test file
# depending on repetitions and the last executed test
# TODO: validate generated sim script files in Questa
# makes use of random_force functionality.
sub export_as_sim_script ($$$) {
my $logger = get_logger();
my ($self,$sim_file_name,$last_test,$num_repetitions) = @_;
......@@ -722,6 +728,7 @@ sub export_as_sim_script ($$$) {
return $msg;
}
# FIXME translate in actual Questasim tcl syntax
if($global_settings_ref->{'design'}->{'RESET_DUT_OUT_EN'} == 1) {
$script_text .= "Wait until ";
$script_text .= $global_settings_ref->{'design'}->{'RESET_DUT_OUT_NAME'};
......@@ -791,6 +798,82 @@ sub export_as_sim_script ($$$) {
print $sfd $script_text;
close($sfd);
return $msg;
}
# randomly generate a test pattern
# depending on a cfg hash
#
# cfg->{'min_duration'}[0..n] Minimum duration constraints for patterns
# cfg->{'max_duration'}[0..n] Maximum duration constraints for patterns
# cfg->{'probabilities'}[FIJI::FIUENUM->{'NONE'}] Probability of fault-free case
# cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_AT_0'}] Probability of stuck-at-0 error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_AT_1'}] Probability of stuck-at-1 error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'DELAY'}] Probability of delay error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'SEU'}] Probability of seu error
# cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_OPEN'}] Probability of stuck-open error
sub make_random_test {
my ($self,$cfg) = @_;
my $msg;
my $test = {};
my $global_settings_ref = $self->{'ext'}->{'global_settings'};
# TODO: Move this somewhere else?
for(my $pi = 0; $pi < $global_settings_ref->{'design'}->{'CFGS_PER_MSG'}; $pi++) {
if($cfg->{'max_duration'}[$pi] < $cfg->{'min_duration'}[$pi]) {
$msg = "Maximum duration ".($pi+1)." must be greater than or equal to minimum duration ".($pi+1);
return $msg;
} elsif($cfg->{'max_duration'}[$pi] < 0 || $cfg->{'min_duration'}[$pi] < 0) {
$msg = "Durations must be positive.";
return $msg;
} elsif($cfg->{'max_duration'}[$pi] > 2**($global_settings_ref->{'design'}->{'TIMER_WIDTH'}*8)-1) {
$msg = "Durations must be at most ".$global_settings_ref->{'design'}->{'TIMER_WIDTH'}." bytes.";
return $msg;
}
}
$test->{'RESET_DUT_AFTER_CONFIG'} = 0;
$test->{'TRIGGER'} = "NONE";
for(my $pi = 1; $pi <= $global_settings_ref->{'design'}->{'CFGS_PER_MSG'}; $pi++) {
$test->{"TIMER_VALUE_${pi}"} = int(rand($cfg->{'max_duration'}[$pi-1] - $cfg->{'min_duration'}[$pi-1]) + $cfg->{'min_duration'}[$pi-1]);
for(my $fi = 0; $fi < $global_settings_ref->{'design'}->{'FIU_NUM'}; $fi++) {
$test->{"FIU_${fi}_PATTERN_${pi}"} = choose_random_fault($cfg->{'probabilities'});
}
}
return $test;
}
# Randomly choose a fault model represented as string
# depending on probability constraints
# cfg[FIJI::FIUENUM->{'NONE'}] Probability of fault-free case
# cfg[FIJI::FIUENUM->{'STUCK_AT_0'}] Probability of stuck-at-0 error
# cfg[FIJI::FIUENUM->{'STUCK_AT_1'}] Probability of stuck-at-1 error
# cfg[FIJI::FIUENUM->{'DELAY'}] Probability of delay error
# cfg[FIJI::FIUENUM->{'SEU'}] Probability of seu error
# cfg[FIJI::FIUENUM->{'STUCK_OPEN'}] Probability of stuck-open error
sub choose_random_fault {
my ($cfg) = @_;
my $random = rand(1);
my ($sum_old, $sum_new);
$sum_old = 0;
$sum_new = 0;
my $fault = 0;
# loop through fault probabilities and accumulate
# check if $random is in the current range
for (my $ti = 0; $ti <= [FIJI::FIUENUM->{'STUCK_OPEN'}]; $ti++) {
$sum_new = $sum_old + @$cfg[$ti];
if ($random >= $sum_old && $random < $sum_new) {
$fault = $ti;
last;
}
$sum_old = $sum_new;
}
return REVERSE_FIU_ENUM($fault);
}
1;
......@@ -30,72 +30,121 @@ use Log::Log4perl qw(get_logger);
use FIJI::Downloader;
use Data::Dumper;
use Getopt::Long;
my $USAGE = <<END_USAGE;
Usage: perl $0 MODE CFG
MODE manual
auto
CFG FIJI::Tests file
END_USAGE
Usage: perl $0 [OPTIONS]
sub test_fi_uart {
my (
$port, $payload_ref, $t1_duration, $t2_duration,
$trigger_en, $trigger_ext, $reset, $fiji_consts
) = @_;
# my @payload = map hex($_), $cfg_str =~ /(..)/g; # TODO: how to do this with unpack?
my %config = (
payload => $payload_ref,
t1_duration => $t1_duration,
t2_duration => $t2_duration,
trigger_en => $trigger_en,
trigger_ext => $trigger_ext,
reset => $reset,
consts => $fiji_consts,
);
return $port->send_config( \%config, 1000, 0, 1 );
}
Required:
--mode=<mode> Download mode:
manual Prompt for fault patterns & timer values
auto Download tests in cfg file
random Download randomly generated tests
--cfg=<cfg file> FIJI::Tests file
Required for random mode:
--min_t1=<#> Minimum duration t1
--min_t2=<#> Minimum duration t2
--max_t1=<#> Maximum duration t1
--max_t2=<#> Maximum duration t2
--prob_s0=<#> Probability of stuck-at-0 fault
--prob_s1=<#> Probability of stuck-at-1 fault
--prob_dly=<#> Probability of delay fault
--prob_seu=<#> Probability of SEU fault
--prob_so=<#> Probability of stuck-open fault
Optional:
--port=<port> Serial port to use. Defaults to value configured in cfg file
END_USAGE
sub main {
my $logger = get_logger();
my $cfg = shift;
my $name = $0;
$name =~ s/\.p[lm]//;
my $mode = $_[0];
my $cfgname = $_[1];
my $port = $_[2];
my $rv;
$logger->debug("=== Starting new execution of $name ===");
$logger->debug(
sprintf( "%d argument(s)%s", scalar(@_), scalar(@_) > 0 ? ": @_" : "" )
);
if ( !defined $mode || !defined $cfgname ) {
# Validate parameters
if(!defined $cfg->{'cfgname'} || !defined $cfg->{'mode'}) {
print $USAGE;
return 1;
}
my $fiji_downloader = FIJI::Downloader->new( $cfgname );
# Make new downloader
my $fiji_downloader = FIJI::Downloader->new( $cfg->{'cfgname'} );
if ( !ref($fiji_downloader) ) {
logger->error( $fiji_downloader . " Aborting.\n" );
$logger->error( $fiji_downloader . " Aborting.\n" );
return 1;
}
if ( $mode eq "auto" ) {
$rv = $fiji_downloader->download_auto($port);
# Check mode and execute tests accordingly
if ( $cfg->{'mode'} eq "auto" ) {
$rv = $fiji_downloader->download_auto($cfg->{'port'});
} elsif ( $cfg->{'mode'} eq "manual" ) {
$rv = $fiji_downloader->download_manual($cfg->{'port'});
} elsif ($cfg->{'mode'} eq "random" ) {
my $new_tests;
my $prob = 0;
for(my $pi = FIJI::FIUENUM->{'STUCK_AT_0'}; $pi <= FIJI::FIUENUM->{'STUCK_OPEN'}; $pi++) {
if (!defined $cfg->{'probabilities'}[$pi]) {
$logger->error("Probability for fault ".FIJI::REVERSE_FIU_ENUM($pi)." missing.");
print $USAGE;
return 1;
}
elsif ( $mode eq "manual" ) {
$rv = $fiji_downloader->download_manual($port);
$prob += $cfg->{'probabilities'}[$pi];
}
if($prob >= 1.0) {
$logger->error("Invalid probabilities.");
return 1;
} else {
$cfg->{'probabilities'}[FIJI::FIUENUM->{'NONE'}] = 1.0 - $prob;
$rv = $fiji_downloader->download_random($cfg,$new_tests,$cfg->{'port'});
}
} else {
print "$0: Invalid mode \"".$cfg->{'mode'}."\"\n";
print $USAGE;
return 1;
}
if(defined $rv && !ref($rv)) {
$logger->error($rv);
return 1;
}
$logger->trace("=== Stopping execution ===");
return 0;
}
my $cfg = {};
GetOptions ("mode=s" => \($cfg->{'mode'}),
"cfg=s" => \($cfg->{'cfgname'}),
"port=s" => \($cfg->{'portname'}),
"min_t1=i" => \($cfg->{'min_duration'}[0]),
"min_t2=i" => \($cfg->{'min_duration'}[1]),
"max_t1=i" => \($cfg->{'max_duration'}[0]),
"max_t2=i" => \($cfg->{'max_duration'}[1]),
"prob_s0=f" => \($cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_AT_0'}]),
"prob_s1=f" => \($cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_AT_1'}]),
"prob_dly=f" => \($cfg->{'probabilities'}[FIJI::FIUENUM->{'DELAY'}]),
"prob_seu=f" => \($cfg->{'probabilities'}[FIJI::FIUENUM->{'SEU'}]),
"prob_so=f" => \($cfg->{'probabilities'}[FIJI::FIUENUM->{'STUCK_OPEN'}])
) or print $USAGE and die ("Invalid arguments");
Log::Log4perl::init_and_watch( 'logger.conf', 'HUP' );
exit main(@ARGV);
exit main($cfg);
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