blob: 91a18cc9283565c2c9360d89824d6bdc7a33fd1f [file] [log] [blame]
# takes: fei (either xml or text) and smv,
# and produces smv and fault modes files
import sys
import os.path
import logging
import subprocess
import _paths
import _utils
# WARNING! ordering is important here!
FMEA_ENGINES = "bdd bmc msat".split()
FMEA_ENGINE_BDD, FMEA_ENGINE_BMC, FMEA_ENGINE_MSAT = FMEA_ENGINES
def handle_options():
"""returns (options, input_file):
values (as a map) and the name of the input file"""
import argparse
parser = argparse.ArgumentParser(description="Produces an extend smv file"
" out of given nominal smv file and fei")
parser.add_argument("--smv-file",
metavar="SMV-FILE",
help="The input extended smv file name")
parser.add_argument("--fms-file",
metavar="FMS-FILE",
help="The input fault mode xml file name")
parser.add_argument("--prop-indices", "-n",
type=int,
metavar="INDICES",
help="Property indices to be used as TLE "
"(separated by ':' or spaces, ranges like "
"'0-10' are allowed)")
parser.add_argument("--props-text", "-p",
metavar="PROPERTIES",
help="Textual properties to be used as TLE, "
"separated by ':' or by spaces")
parser.add_argument('--verbose', '-v',
action='store_true',
default=False,
help='Sets verbosity to high level')
parser.add_argument('--engine', '-E',
choices=FMEA_ENGINES,
default=FMEA_ENGINE_BDD,
help='Use given engine (default: %(default)s)')
parser.add_argument('--dynamic',
action='store_true',
default=False,
help='Generates dynamic fmea table')
parser.add_argument('--compact', '-c',
action='store_true',
default=False,
help='Generates compact fmea table')
parser.add_argument('--card', "-N",
type=int,
default=1,
help='Cut-Set cardinality (default: %(default)d)')
parser.add_argument('--bmc-length', "-k",
type=int,
default=10,
help='Specify BMC length (integer)')
parser.add_argument('--show', '-s',
action='store_true',
default=False,
help='Show the generated fmea table')
parser.add_argument(
"-d", "--outdir",
default="out",
metavar="PATH",
help="Output directory, where all generated file should be "
"put into (default:%(default)s)")
args = parser.parse_args()
for fn in (args.smv_file, args.fms_file):
if fn and not os.path.isfile(fn):
parser.error("File not found: " + fn)
if os.path.exists(args.outdir) and not os.path.isdir(args.outdir):
parser.error("Not a directory: " + args.outdir)
prop = [p for p in (args.prop_indices, args.props_text)
if p is not None]
if len(prop) > 1:
parser.error("Properties can be specified only "
"in one way (multiple used)")
if args.engine in (FMEA_ENGINE_MSAT, FMEA_ENGINE_BMC) and args.dynamic:
parser.error("Dynamic fmea not available with engine %s" % args.engine)
return args
def show_fmea_table(fmea_fname, card, show):
count = 0
import csv
with open(fmea_fname, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter='\t', quotechar="'")
reader.next()
for row in reader:
if show:
print "-" * 70
print "ID: ", row[0]
print "TLE:", row[3]
print "FMS:", row[2]
count += 1
if show:
print "=" * 70
print "Total cut sets with cardinality %d: %d" % (card, count)
elif count == 0:
logging.warn("The FMEA table is empty with cardinality %d" % card)
return
if "__main__" == __name__:
_paths.setup_path()
import xsap.utils.misc.log
from xsap.utils.processes.xsap_process import XsapProcess
xsap.utils.misc.log.init()
args = handle_options()
if not os.path.exists(args.outdir):
os.makedirs(args.outdir)
if args.verbose:
logging.getLogger().setLevel(logging.INFO)
prop = [('-n %d' % args.prop_indices) if args.prop_indices is not None
else
('%s' % args.props_text) if args.props_text is not None
else ""]
# automatically searches for inputs when not explicitly provided
smv_fname = _utils.get_suitable_smv_file(args.smv_file, args.outdir)
if smv_fname is None:
sys.exit(1)
fms_fname = _utils.get_suitable_fms_file(args.fms_file,
smv_fname,
args.outdir)
if fms_fname is None:
sys.exit(1)
stdouterr_fname = os.path.join(args.outdir, "xsap_compute_fmea.out")
if os.path.exists(stdouterr_fname):
os.remove(stdouterr_fname)
stdouterr_file = open(stdouterr_fname, "w")
logging.info("Invoking xsap to compute fmea table")
need_msat = XsapProcess.has_infinite_domain_vars(smv_fname) or args.engine == FMEA_ENGINE_MSAT
with XsapProcess(smv_fname, fms_fname,
need_msat=need_msat,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
dumpers=[stdouterr_file]) as xsap_proc:
# set the prefix of generated files
full_base, _ext = os.path.splitext(smv_fname)
base = os.path.basename(full_base)
xsap_proc.set_tmp_filename_prefix(args.outdir + "/" + base)
stdouterr_file.write("\n" + "-" * 70)
stdouterr_file.write("\nInvoking: %s %s\n" % (xsap_proc.get_path(),
" ".join(xsap_proc.get_args())))
stdouterr_file.write("\n" + "-" * 70)
stdouterr_file.write("\n")
res = xsap_proc.compute_fmea_table(
prop, args.card, dynamic=args.dynamic, bmc_length=args.bmc_length,
compact=args.compact, engine=args.engine)
logging.info("xsap produced fmea table in: '%s'" % res)
stdouterr_file.close()
show_fmea_table(res, args.card, args.show)