blob: 7b7041c78808193c18967a22d0099351c49a27f9 [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!
FT_ENGINES = "bdd bmc bddbmc msat ic3".split()
(FT_ENGINE_BDD,
FT_ENGINE_BMC,
FT_ENGINE_BDD_BMC,
FT_ENGINE_MSAT,
FT_ENGINE_IC3, ) = FT_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("--faults-bound", "-N",
type=int,
metavar="BOUND",
help="Sets a bound to the maximum number of faults")
parser.add_argument("--prop-index", "-n",
type=int,
metavar="INDEX",
help="Property index to be used as TLE")
parser.add_argument("--prop-name", "-P",
metavar="NAME",
help="Property name to be used as TLE")
parser.add_argument("--prop-text", "-p",
metavar="PROPERTY",
help="Textual property to be used as TLE")
parser.add_argument('--verbose', '-v',
action='store_true',
default=False,
help='Sets verbosity to high level')
parser.add_argument('--engine', '-E',
choices=FT_ENGINES,
default=FT_ENGINE_BDD,
help='Use given engine (default: %(default)s)')
parser.add_argument('--dynamic',
action='store_true',
default=False,
help='Generates dynamic fault tree')
parser.add_argument('--gen-trace', "-e",
action='store_true',
default=False,
help='Generates xml trace from fault tree')
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 fault tree')
parser.add_argument("--probability",
action='store_true',
default=False,
help="Computes probability when generating FT")
parser.add_argument("--symbolic", '-S',
action='store_true',
default=False,
help="Generates symbolic probability as well "
"when computing probability",)
parser.add_argument("--quick", '-Q',
action='store_true',
default=False,
help="For quick computation, avoid ordering the "
"FT and when computing probability avoid computing"
"probability of intermediate nodes. Use to"
"speedup computation.",)
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_index, args.prop_name, args.prop_text)
if p is not None]
if len(prop) > 1:
parser.error("Only one property can be specified")
if args.symbolic and not args.probability:
parser.error("Option -S (--symbolic) requires --probability")
return args
if "__main__" == __name__:
_paths.setup_path()
import xsap.utils.misc.log
from xsap.utils.processes.xsap_process import XsapProcess
xsap.utils.misc.log.init()
opts = handle_options()
if not os.path.exists(opts.outdir):
os.makedirs(opts.outdir)
if opts.verbose:
logging.getLogger().setLevel(logging.INFO)
# automatically searches for inputs when not explicitly provided
smv_fname = _utils.get_suitable_smv_file(opts.smv_file, opts.outdir)
if smv_fname is None:
sys.exit(1)
fms_fname = _utils.get_suitable_fms_file(opts.fms_file,
smv_fname,
opts.outdir)
if fms_fname is None:
sys.exit(1)
stdouterr_fname = os.path.join(opts.outdir, "xsap_compute_ft.out")
if os.path.exists(stdouterr_fname):
os.remove(stdouterr_fname)
stdouterr_file = open(stdouterr_fname, "w")
# instantiate the process
logging.info("Invoking xsap to compute fault tree")
need_msat = XsapProcess.has_infinite_domain_vars(smv_fname) or opts.engine == FT_ENGINE_MSAT
with XsapProcess(smv_fname, fms_fname,
ord_fname=None, need_msat=need_msat,
args=["-v", "%d" % (5 if opts.verbose else 0)],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
dumpers=[stdouterr_file]) as xsap_process:
# set the prefix
full_base, _ext = os.path.splitext(smv_fname)
base = os.path.basename(full_base)
xsap_process.set_tmp_filename_prefix(opts.outdir + "/" + base)
stdouterr_file.write("\n" + "-" * 70)
stdouterr_file.write("\nInvoking: %s %s\n" % (xsap_process.get_path(),
" ".join(xsap_process.get_args())))
stdouterr_file.write("\n" + "-" * 70)
stdouterr_file.write("\n")
prop = (('-n %d' % opts.prop_index) if opts.prop_index is not None
else
('-P "%s"' % opts.prop_name) if opts.prop_name is not None
else
('"%s"' % opts.prop_text) if opts.prop_text is not None
else "")
ev_file, gates_file, xml_file = xsap_process.compute_fault_tree(
prop, opts.dynamic, opts.bmc_length,
use_bdd=opts.engine==FT_ENGINE_BDD,
use_bdd_bmc=opts.engine==FT_ENGINE_BDD_BMC,
compute_probabilities=opts.probability,
use_param=opts.engine==FT_ENGINE_IC3,
fails_nbr=opts.faults_bound,
symbolic=opts.symbolic,
quick=opts.quick,
gen_trace=opts.gen_trace,
gen_random_prefix=False)
stdouterr_file.close()
logging.info("xsap produced fault tree in: ")
logging.info(" events: '%s'" % ev_file)
logging.info(" gates: '%s'" % gates_file)
if ev_file is not None and gates_file is not None and opts.show:
logging.info("Now showing result fault tree")
import fault_tree_viewer.ftv as ftv
ftv.run(ev_file, gates_file, xml_file, None, None)