Exemple #1
0
class Process:
    def __init__(self, aiger_file_name, index, data_mode=0, factor=1):
        self.index = index
        self.aig = AIG(aiger_file_name, False)
        # [C1,C2,D] where [C1,C2] is the exec time interval, and D relative deadline
        # number of modes is the size of this list
        #self.delays = [[5,10,15], [4,8,16]]
        self.delays = data[data_mode]
        self.delays = map(lambda tab: map(lambda x: factor * x, tab),
                          data[data_mode])
        self.lit_to_formula = dict()
        self._cached_transition = None

    def get_delays(self):
        return self.delays

    def preset1(self):
        # Other [C1,C2,D] values can be set here
        pass

    def set_lit2formula(self, lit, s):
        self.lit_to_formula[lit] = s

    """ Name of stripped literal which must be an input or latch """

    def name_of(self, lit):
        assert (lit == strip_lit(lit))
        (intput, latch, and_gate) = self.aig.get_lit_type(lit)
        # is it an input, latch, gate or constant
        #print >> sys.stderr, "lit", lit, (input,latch,and_gate)
        if latch:
            return "L" + self.aig.get_lit_name(lit).replace("<", "_").replace(
                ">", "_")
        elif input:
            # Boolean variables are encoded as 1-bit integers for now
            return "I" + self.aig.get_lit_name(lit).replace("<", "_").replace(
                ">", "_")
        else:
            raise "And gates or constant inputs have no name"

    def lit2formula(self, lit):
        if lit in self.lit_to_formula:
            return self.lit_to_formula[lit]
        # get stripped lit
        stripped_lit = strip_lit(lit)
        is_neg = lit_is_negated(lit)
        (input, latch, and_gate) = self.aig.get_lit_type(stripped_lit)
        # is it an input, latch, gate or constant
        if input or latch:
            # Boolean variables are encoded as 1-bit integers for now
            result = "({0})".format(self.name_of(stripped_lit))
        elif and_gate:
            if numeric_mode:
                result = ("({0} * {1})".format(self.lit2formula(and_gate.rhs0),
                                               self.lit2formula(
                                                   and_gate.rhs1)))
            else:
                result = ("({0} &amp;&amp; {1})".format(
                    self.lit2formula(and_gate.rhs0),
                    self.lit2formula(and_gate.rhs1)))
        else:  # 0 literal, 1 literal and errors
            result = "0"  # this means false
        # cache result
        self.lit_to_formula[stripped_lit] = result
        if is_neg:
            if result == "0":
                result = "1"
            else:
                if numeric_mode:
                    result = "(1-{0})".format(result)
                else:
                    result = "!{0}".format(result)
            self.lit_to_formula[lit] = result
        return result

    def get_next_funcs(self):
        if self._cached_transition is not None:
            return self._cached_transition
        vec = dict()
        for x in self.aig.iterate_latches():
            vec[x.lit] = self.lit2formula(x.next)
        self._cached_transition = vec
        return vec

    def make_template(self, nmachines):
        def latch_choice(name):
            return "state" in name or "counter" in name

        id = self.index
        latch_list = list(self.aig.iterate_latches())
        latch_locations = dict()

        temp = Template("Process" + str(id))
        # Choose here some latch which should become mode
        clocked_latches = filter(lambda x: latch_choice(self.name_of(x.lit)),
                                 latch_list)
        mode_latch = self.name_of(
            clocked_latches[0].lit
        )  # this is assumed to be non-empty of course

        w = Location("w", initial=True)
        dead = Location("dead")
        rel = Location("rel", committed=True)
        up = Location("up", committed=True)
        disc_up = Location("disc_up", committed=True)
        temp.add_locations([w, dead, rel, up])
        on = [Location("on{0}".format(m)) for m in range(len(self.delays))]
        for m, l in enumerate(on):
            # delay=(c1,c2,d). invariant is that the task finishes before c2
            l.set_invariant("x{0} &lt;= {1}".format(id, self.delays[m][1]))
            temp.add_location(l)

        nmodes = len(self.delays)
        for m, (c1, c2, d) in enumerate(self.delays):
            #            mg = "mode{0} == {1}".format(id, m)
            mg = "{0} == {1}".format(mode_latch, m)
            temp.add_transition(
                Transition(w,
                           on[m],
                           guard=mg,
                           sync="go{0}?".format(id),
                           up="x{0}:=0, w{0}:=0".format(id)))

            # Check deadline miss
            guard = "{0} &amp;&amp; x{1} &gt; {2}".format(mg, id, d - c2)
            temp.add_transition(Transition(w, dead, guard=guard))

            # on -> up
            guard = "{0} &amp;&amp; x{1} &gt;= {2} &amp;&amp; x{1} &lt;= {3}".format(
                mg, id, c1, c2)
            tr = Transition(on[m], up, up="x{0}:=0".format(id), guard=guard)
            temp.add_transition(tr)

        last_location = up
        # Discrete update part
        decl = StringIO.StringIO()
        input_list = list(
            chain(self.aig.iterate_uncontrollable_inputs(),
                  self.aig.iterate_controllable_inputs()))
        for i in input_list:
            print >> decl, "bool {0};".format(self.name_of(i.lit))
            loc_after_i = Location("JustSet" + self.name_of(i.lit),
                                   committed=True)
            tr0 = Transition(last_location,
                             loc_after_i,
                             up="{0} := 0".format(self.name_of(i.lit)))
            tr1 = Transition(last_location,
                             loc_after_i,
                             up="{0} := 1".format(self.name_of(i.lit)))
            temp.add_transition(tr0)
            temp.add_transition(tr1)
            last_location = loc_after_i
            pass

        next_funcs = self.get_next_funcs()
        for xi, x in enumerate(latch_list):
            print >> decl, "bool {0};".format(self.name_of(x.lit))
            latch_locations[x.lit] = Location("Updated" + self.name_of(x.lit),
                                              committed=True)
            up = "{0} := {1}".format(self.name_of(x.lit), next_funcs[x.lit])
            temp.add_transition(
                Transition(last_location, latch_locations[x.lit], up=up))
            last_location = latch_locations[x.lit]

        for j in range(nmachines):
            tr = Transition(last_location,
                            w,
                            guard="running{0} == {1}".format(j, id),
                            sync="release{0}!".format(j),
                            up="w{0}:=1".format(id))
            temp.add_transition(tr)

        temp.set_declaration(decl.getvalue())
        return temp
class TAWRITER:
    def __init__(self, aiger_file_name, time_file_name, factor=1):
        self.aig = AIG(aiger_file_name, False)
        self.lit_to_formula = dict()
        self._cached_transition = None
        self.factor = factor
        self.delays = self._read_delays(time_file_name)

    def _read_delays(self, time_file_name):
        delays = dict()
        latches = [x.lit for x in self.aig.iterate_latches()]
        with open(time_file_name, 'r') as fp:
            for l in range(len(latches)):
                s = fp.readline()
                if s <> "":
                    #print "Doing line:<{0}>".format(s)
                    #print s.split(" ")
                    si = map(lambda x: int(x), s.split(" "))
                    assert (len(si) == 2)
                    delays[latches[l]] = (si[0] * self.factor,
                                          si[1] * self.factor)
                else:
                    delays[latches[l]] = (self.factor, self.factor)
        log.DBG_MSG("Latch delays: " + str(delays))
        return delays

    def set_lit2formula(self, lit, s):
        self.lit_to_formula[lit] = s

    """ Name of stripped literal which must be an input or latch """

    def name_of(self, lit):
        assert (lit == strip_lit(lit))
        (intput, latch, and_gate) = self.aig.get_lit_type(lit)
        # is it an input, latch, gate or constant
        #print >> sys.stderr, "lit", lit, (input,latch,and_gate)
        if latch:
            return "L" + self.aig.get_lit_name(lit).replace("<", "_").replace(
                ">", "_")
        elif input:
            # Boolean variables are encoded as 1-bit integers for now
            return "I" + self.aig.get_lit_name(lit).replace("<", "_").replace(
                ">", "_")
        else:
            raise "And gates or constant inputs have no name"

    def lit2formula(self, lit):
        if lit in self.lit_to_formula:
            return self.lit_to_formula[lit]
        # get stripped lit
        stripped_lit = strip_lit(lit)
        is_neg = lit_is_negated(lit)
        (input, latch, and_gate) = self.aig.get_lit_type(stripped_lit)
        # is it an input, latch, gate or constant
        if input or latch:
            # Boolean variables are encoded as 1-bit integers for now
            result = "(_l.{0})".format(self.name_of(stripped_lit))
        elif and_gate:
            if numeric_mode:
                result = ("({0} * {1})".format(self.lit2formula(and_gate.rhs0),
                                               self.lit2formula(
                                                   and_gate.rhs1)))
            else:
                result = ("({0} && {1})".format(
                    self.lit2formula(and_gate.rhs0),
                    self.lit2formula(and_gate.rhs1)))
        else:  # 0 literal, 1 literal and errors
            result = "0"  # this means false
        # cache result
        self.lit_to_formula[stripped_lit] = result
        if is_neg:
            if result == "0":
                result = "1"
            else:
                if numeric_mode:
                    result = "(1-{0})".format(result)
                else:
                    result = "!{0}".format(result)
            self.lit_to_formula[lit] = result
        return result

    def get_next_funcs(self):
        if self._cached_transition is not None:
            return self._cached_transition
        vec = dict()
        for x in self.aig.iterate_latches():
            vec[x.lit] = self.lit2formula(x.next)
        self._cached_transition = vec
        return vec

    def make_discrete_guard(self, g):
        return """
        [](syntax::layout_t const & l){{\\
        monoprocess::layout_t const & _l = CAST(monoprocess::layout_t const &, l);\\
        return {0};\\
        }}
        """.format(g)

    def make_discrete_update(self, u):
        return """ [](syntax::layout_t  & l){{\\
                       monoprocess::layout_t & _l = CAST(monoprocess::layout_t &, l);\\
                       {0};\\
                    }}
                    """.format(u)

    """
    Given K, make timed automaton model that restricts each cycle to K time units.
    """

    def get_cycle_time_model(self, nb_clocked_latches, K):
        K = self.factor * K
        latch_locations = dict()
        # clock name associated to given lit which is a latch
        clock_name = dict()
        input_list = list(
            chain(self.aig.iterate_uncontrollable_inputs(),
                  self.aig.iterate_controllable_inputs()))
        latch_list = list(self.aig.iterate_latches())
        latch_num = len(latch_list)

        clocked_latches = filter(lambda x: "state" in self.name_of(x.lit),
                                 latch_list)
        clocked_latches = latch_list
        clocked_latches = clocked_latches[0:nb_clocked_latches]

        print """#include <iostream>
        #include "syntax/system.hh"
        #include "syntax/sync_product.hh"
        namespace monoprocess {
        class layout_t : public syntax::layout_t {
        public:
        """
        for i in input_list:
            print "\tbool {0};".format(self.name_of(i.lit))
        for x in latch_list:
            print "\tbool {0};".format(self.name_of(x.lit))

        print "\tlayout_t(){"
        for i in input_list:
            print "\t\t{0} = 0;".format(self.name_of(i.lit))
        for x in latch_list:
            print "\t\t{0} = 0;".format(self.name_of(x.lit))
        print "\t}\nvirtual ~layout_t(){}"
        print "layout_t (const layout_t &l) = default;"
        print """
        inline bool operator == (const syntax::layout_t & l) const {
            monoprocess::layout_t const & _l = CAST(monoprocess::layout_t const &, l);
        """
        for i in input_list:
            print "\t\tif({0} != _l.{0}) return false;".format(
                self.name_of(i.lit))
        for x in latch_list:
            print "\t\tif({0} != _l.{0}) return false;".format(
                self.name_of(x.lit))
        print "return true;\n}"

        print """
        inline size_t hash() const {
        size_t seed = global_t::instance().hash_seed();
        """
        for i in input_list + latch_list:
            print "\t\tboost::hash_combine(seed, {0});".format(
                self.name_of(i.lit))
        print "return seed;\n}"

        print """
        void output(std::ostream & os) const {
        """
        for i in input_list + latch_list:
            print "\t\tos << \"{0} = \" << {0} << \",\";".format(
                self.name_of(i.lit))
        print "\t}\n};\n}"

        print """void build_model(syntax::system_t & s){
        \ts.name(\"Mono\");
        \ts.layout_alloc< syntax::layout_T_alloc_t<monoprocess::layout_t> >();
        """
        for x in clocked_latches:
            clock_name[x.lit] = "x_" + str(x.lit)
            print "s.add_clock(\"{0}\");".format(clock_name[x.lit])
        print "s.add_clock(\"T\");"
        print "s.add_label(\"err\");"
        print "s.add_label(\"nothing\");"
        print "s.add_process(\"Circuit\");"

        print "s.add_location(\"Circuit\", \"init\", \"\", \"\", syntax::loc_t::INIT | syntax::loc_t::URGENT);"
        #init = Location("Init", urgent=True,initial=True)
        print "s.add_location(\"Circuit\", \"dead\", \"\", \"err\");"
        #deadlock = Location("dead")

        # nta.set_query("E<>Process.dead")
        # for x in self.aig.iterate_latches():
        last_location = "init"
        for i in input_list:
            loc_after_i = "JustSet" + self.name_of(i.lit)
            print "s.add_location(\"Circuit\", \"{0}\", \"\", \"\", syntax::loc_t::URGENT);".format(
                loc_after_i)
            #loc_after_i = Location("JustSet"+self.name_of(i.lit), urgent=True)
            #tr0 = Transition(last_location, loc_after_i, up="{0} := 0".format(self.name_of(i.lit)))
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"\", \"\", \"\", syntax::layout_true,".format(
                last_location, loc_after_i)
            print self.make_discrete_update("_l.{0}=0;".format(
                self.name_of(i.lit)))
            print ");"
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"\", \"\", \"\", syntax::layout_true,".format(
                last_location, loc_after_i)
            print self.make_discrete_update("_l.{0}=1;".format(
                self.name_of(i.lit)))
            print ");"

            #tr1 = Transition(last_location, loc_after_i, up="{0} := 1".format(self.name_of(i.lit)))
            #temp.add_transition(tr0)
            #temp.add_transition(tr1)
            last_location = loc_after_i

        next_funcs = self.get_next_funcs()

        for x in latch_list:
            #print >> decl, "bool {0};".format(self.name_of(x.lit))
            if not x in clocked_latches:
                continue
            #latch_locations[x.lit] = Location("Updated"+ self.name_of(x.lit), urgent=True)
            latch_locations[x.lit] = "Updated" + self.name_of(x.lit)
            print "s.add_location(\"Circuit\", \"{0}\", \"\", \"\", syntax::loc_t::URGENT);".format(
                latch_locations[x.lit])

            # if the value does not change:
            #g = "{0} == {1}".format(self.name_of(x.lit), next_funcs[x.lit])
            #tr = Transition(last_location, latch_locations[x.lit], guard=g)
            #temp.add_transition(tr)
            disc_g = self.make_discrete_guard("_l.{0}=={1};".format(
                self.name_of(x.lit), next_funcs[x.lit]))
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"\", \"\", \"\", {2});".format(
                last_location, latch_locations[x.lit], disc_g)

            # if it changes but the delay is already respected, move on directly
            # g = "{0} == 1 &amp;&amp; {0} != {1} &amp;&amp; {2} &gt;= {3}".format(self.name_of(x.lit), next_funcs[x.lit], clock_name[x.lit], self.delays[x.lit][0])
            # temp.add_transition(Transition(last_location, latch_locations[x.lit], guard=g))

            disc_g = self.make_discrete_guard(
                "_l.{0} == 1 && _l.{0} != {1}".format(self.name_of(x.lit),
                                                      next_funcs[x.lit]))
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"{2} <= {3}\", \"\", \"\", {4});".format(
                last_location, latch_locations[x.lit], clock_name[x.lit],
                self.delays[x.lit][0], disc_g)

            disc_g = self.make_discrete_guard(
                "_l.{0} == 0 && _l.{0} != {1}".format(self.name_of(x.lit),
                                                      next_funcs[x.lit]))
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"{2} <= {3}\", \"\", \"\", {4});".format(
                last_location, latch_locations[x.lit], clock_name[x.lit],
                self.delays[x.lit][1], disc_g)

            # if we have to wait to respect the delay go to specific wait state and wait precisely for the delay (matching invariant + guard)
            loc0 = latch_locations[x.lit] + "_becomes0"
            print "s.add_location(\"Circuit\", \"{0}\",\"{1}<={2}\", \"\");".format(
                loc0, clock_name[x.lit], self.delays[x.lit][0])
            #loc0.set_invariant("{1} <= {2}".format()
            loc1 = latch_locations[x.lit] + "_becomes1"
            #loc1.set_invariant("{0} &lt;= {1}".format(clock_name[x.lit], self.delays[x.lit][1]))
            print "s.add_location(\"Circuit\", \"{0}\",\"{1}<={2}\", \"\");".format(
                loc1, clock_name[x.lit], self.delays[x.lit][1])

            #            g = "{0} == 1 &amp;&amp; {0} != {1} &amp;&amp; {2} &lt; {3}".format(self.name_of(x.lit), next_funcs[x.lit], clock_name[x.lit], self.delays[x.lit][0])
            disc_g = self.make_discrete_guard(
                "_l.{0} == 1 && _l.{0} != {1}".format(self.name_of(x.lit),
                                                      next_funcs[x.lit]))
            g = "{0} < {1}".format(clock_name[x.lit], self.delays[x.lit][0])
            #tr = Transition(last_location, loc0, guard=g)
            #temp.add_transition(tr)
            if self.delays[x.lit][0] > 0:
                print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"{2}\", \"\", \"\", {3});".format(
                    last_location, loc0, g, disc_g)

            up = self.make_discrete_update("_l.{0} = {1};".format(
                self.name_of(x.lit), next_funcs[x.lit]))
            #            up="{0}:=0, {1} := {2}".format(clock_name[x.lit], self.name_of(x.lit), next_funcs[x.lit])
            g = "{0} >= {1}".format(clock_name[x.lit], self.delays[x.lit][0])
            #tr = Transition(loc0, latch_locations[x.lit], guard=g, up=up)
            #temp.add_transition(tr)
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"{2}\", \"{3}\", \"\", syntax::layout_true, {4});".format(
                loc0, latch_locations[x.lit], g, clock_name[x.lit], up)

            #            g = "{0} == 0 &amp;&amp; {0} != {1} &amp;&amp; {2} &lt; {3}".format(self.name_of(x.lit), next_funcs[x.lit], clock_name[x.lit], self.delays[x.lit][1])
            #            tr = Transition(last_location, loc1, guard=g)
            #            temp.add_transition(tr)
            g = "{0} < {1}".format(clock_name[x.lit], self.delays[x.lit][1])
            if self.delays[x.lit][1] > 0:
                disc_g = self.make_discrete_guard(
                    "_l.{0} == 0 && _l.{0} != {1}".format(
                        self.name_of(x.lit), next_funcs[x.lit]))
                print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"{2}\", \"\", \"\", {3});".format(
                    last_location, loc1, g, disc_g)

            up = self.make_discrete_update("_l.{0} = {1};".format(
                self.name_of(x.lit), next_funcs[x.lit]))
            #g = "{0} &gt;= {1}".format(clock_name[x.lit], self.delays[x.lit][1])
            g = "{0} >= {1}".format(clock_name[x.lit], self.delays[x.lit][1])
            print "s.add_edge(\"Circuit\", \"{0}\", \"{1}\", \"{2}\", \"{3}\", \"\", syntax::layout_true, {4});".format(
                loc1, latch_locations[x.lit], g, clock_name[x.lit], up)
            #tr = Transition(loc1, latch_locations[x.lit], guard=g, up=up)
            #temp.add_transition(tr)

            last_location = latch_locations[x.lit]
        #go_deadlock=Transition(last_location, deadlock, guard="T &gt;{0}".format(str(K)))
        print "s.add_edge(\"Circuit\", \"{0}\", \"dead\", \"T>{1}\", \"\", \"\", syntax::layout_true);".format(
            last_location, str(K))
        print "s.add_edge(\"Circuit\", \"{0}\", \"init\", \"T<={1}\", \"T\", \"\", syntax::layout_true);".format(
            last_location, str(K))

        print "s.synchronizer<syntax::asynchronous_product_t>();\n}"
Exemple #3
0
class Process:
    def __init__(self, aiger_file_name, index, data_mode=0, factor=1):
        self.index = index
        self.aig = AIG(aiger_file_name, False);
        # [C1,C2,D] where [C1,C2] is the exec time interval, and D relative deadline
        # number of modes is the size of this list
#        self.delays = [[5,10,15], [4,8,16]]
        self.delays = map(lambda tab: map(lambda x: factor*x, tab), data[data_mode])
        self.lit_to_formula = dict()
        self._cached_transition = None
        self.input_list = list(chain(self.aig.iterate_uncontrollable_inputs(),self.aig.iterate_controllable_inputs()))
        self.latch_list = list(self.aig.iterate_latches())


    def get_delays(self):
        return self.delays

    def preset1(self):
        # Other [C1,C2,D] values can be set here
        pass

    def set_lit2formula(self, lit, s):
        self.lit_to_formula[lit] = s

    """ Name of stripped literal which must be an input or latch """
    def name_of(self, lit):
        assert(lit == strip_lit(lit))
        ident = "P"+str(self.index)
        (intput, latch, and_gate) = self.aig.get_lit_type(lit)
        # is it an input, latch, gate or constant
        #print >> sys.stderr, "lit", lit, (input,latch,and_gate)
        if latch:
            return "L"+ident+self.aig.get_lit_name(lit).replace("<", "_").replace(">", "_");
        elif input:
            # Boolean variables are encoded as 1-bit integers for now
            return "I"+ident+self.aig.get_lit_name(lit).replace("<", "_").replace(">", "_");
        else:
            raise "And gates or constant inputs have no name"
    def lit2formula(self, lit):
        if lit in self.lit_to_formula:
            return self.lit_to_formula[lit]
        # get stripped lit
        stripped_lit = strip_lit(lit)
        is_neg = lit_is_negated(lit)
        (input, latch, and_gate) = self.aig.get_lit_type(stripped_lit)
        # is it an input, latch, gate or constant
        if input or latch:
            # Boolean variables are encoded as 1-bit integers for now
            result = "(_l.{0})".format(self.name_of(stripped_lit))
        elif and_gate:
            if numeric_mode:
                result = ("({0} * {1})".format(self.lit2formula(and_gate.rhs0),
                      self.lit2formula(and_gate.rhs1)))
            else:
                result = ("({0} && {1})".format(self.lit2formula(and_gate.rhs0),
                      self.lit2formula(and_gate.rhs1)))
        else:  # 0 literal, 1 literal and errors
            result = "0" # this means false
        # cache result
        self.lit_to_formula[stripped_lit] = result
        if is_neg:
            if result == "0":
                result = "1"
            else:
                if numeric_mode:
                    result = "(1-{0})".format(result)
                else:
                    result = "!{0}".format(result)
            self.lit_to_formula[lit] = result
        return result


    def get_next_funcs(self):
        if self._cached_transition is not None:
            return self._cached_transition
        vec = dict()
        for x in self.aig.iterate_latches():
            vec[x.lit] = self.lit2formula(x.next)
        self._cached_transition = vec
        return vec

    def dump(self, nmachines):
        def latch_choice(name):
            return "state" in name or "counter" in name
        input_list = self.input_list
        latch_list = self.latch_list
        id = self.index

        latch_locations = dict()
        print "s.add_process(\"Process{0}\");".format(id)
        pr = "\"Process{0}\"".format(id)
        # Choose here some latch which should become mode
        clocked_latches = filter(lambda x: latch_choice(self.name_of(x.lit)), latch_list)
        mode_latch = self.name_of(clocked_latches[0].lit) # this is assumed to be non-empty of course

        # w = Location("w", initial=True)
        # dead = Location("dead", error=True)
        # rel = Location("rel", committed = True)
        # up = Location("up", committed = True)
        #disc_up = Location("disc_up", committed=True)
        print "s.add_location({0}, \"w\", \"\", \"\", syntax::loc_t::INIT);".format(pr)
        print "s.add_location({0}, \"dead\", \"\", \"err\");".format(pr)
        print "s.add_location({0}, \"rel\", \"\", \"\", syntax::loc_t::COMMITTED);".format(pr)
        print "s.add_location({0}, \"up\", \"\", \"\", syntax::loc_t::COMMITTED);".format(pr)
        print "s.add_location({0}, \"disc_up\", \"\", \"\", syntax::loc_t::COMMITTED);".format(pr)

        for m in range(len(self.delays)):
            print "s.add_location({0}, \"on{1}\", \"x{2} <= {3}\",\"\");".format(pr, m, id, self.delays[m][1])
        #on = [Location("on{0}".format(m)) for m in range(len(self.delays))]
        #for m,l in enumerate(on):
        #    # delay=(c1,c2,d). invariant is that the task finishes before c2
        #    l.set_invariant("x{0} &lt;= {1}".format(id, self.delays[m][1]))
        #    temp.add_location(l)


        nmodes = len(self.delays)
        for m,(c1,c2,d) in enumerate(self.delays):
#            mg = "mode{0} == {1}".format(id, m)
            mg = make_discrete_guard("_l.{0} == {1}".format(mode_latch, m))
            up = make_discrete_update("_l.w{0} = 0".format(id))
#            temp.add_transition(Transition(w, on[m], disc_guard=mg, sync="go{0}?".format(id), disc_up="w{0}=0;".format(id), reset="x{0}".format(id)))
            print "s.add_edge({0}, \"w\", \"on{1}\", \"\", \"x{2}\", \"go{2}?\", {3}, {4});".format(pr, m, id, mg, up)

            # Check deadline miss
            g="x{0} >= {1}".format(id, d - c2-1)
            up=make_discrete_update("_l.dead=1;")
            #temp.add_transition(Transition(w,dead,disc_guard=mg, disc_up="dead=1;",guard=guard))
            print "s.add_edge({0}, \"w\", \"dead\", \"{1}\", \"\", \"\", {2}, {3});".format(pr, g , mg, up)

            # on -> up
            #guard = "x{1} &gt;= {2} &amp;&amp; x{1} &lt;= {3}".format(mg, id, c1, c2)
            #tr = Transition(on[m], up, reset="x{0}".format(id), disc_guard=mg, guard=guard)
            #temp.add_transition(tr)
            guard = "x{1} >= {2} && x{1} <= {3}".format(mg, id, c1, c2)
            print "s.add_edge({0}, \"on{1}\", \"up\", \"{2}\", \"x{3}\", \"\", {4});".format(pr, m, guard, id, mg)


        last_location = "up"
        # Discrete update part
        for i in input_list:
            # print >> decl, "var {0} :".format(self.name_of(i.lit))+"{0..1}=0;"
            loc_after_i = "JustSet"+self.name_of(i.lit)
            print "s.add_location({0}, \"{1}\", \"\", \"\", syntax::loc_t::COMMITTED);".format(pr, loc_after_i)
            print "s.add_edge({0}, \"{1}\", \"{2}\", \"\", \"\", \"\", syntax::layout_true, {3});".format(pr, last_location, loc_after_i, make_discrete_update("_l.{0} = 0;".format(self.name_of(i.lit))))
            print "s.add_edge({0}, \"{1}\", \"{2}\", \"\", \"\", \"\", syntax::layout_true, {3});".format(pr, last_location, loc_after_i, make_discrete_update("_l.{0} = 1;".format(self.name_of(i.lit))))
            #tr0 = Transition(last_location, loc_after_i, disc_up="{0} = 0;".format(self.name_of(i.lit)))
            #tr1 = Transition(last_location, loc_after_i, disc_up="{0} = 1;".format(self.name_of(i.lit)))
            #temp.add_transition(tr0)
            #temp.add_transition(tr1)
            last_location = loc_after_i
            pass

        next_funcs = self.get_next_funcs()
        for xi, x in enumerate(latch_list):
            #print >> decl, "var {0} :".format(self.name_of(x.lit))+"{0..1}=0;"
            latch_locations[x.lit] = "Updated"+ self.name_of(x.lit)
            print "s.add_location({0}, \"{1}\", \"\", \"\", syntax::loc_t::COMMITTED);".format(pr, latch_locations[x.lit])

            disc_up=make_discrete_update("_l.{0} = {1};".format(self.name_of(x.lit), next_funcs[x.lit]))
            #temp.add_transition(Transition(last_location, latch_locations[x.lit],disc_up=disc_up))
            print "s.add_edge({0}, \"{1}\", \"{2}\", \"\", \"\", \"\", syntax::layout_true, {3});".format(pr, last_location, latch_locations[x.lit], disc_up)
            last_location = latch_locations[x.lit]

        for j in range(nmachines):
            up = make_discrete_update("_l.w{0} = 1;".format(id))
            dg = make_discrete_guard("_l.running{0} == {1}".format(j, id))
            print "s.add_edge({0}, \"{1}\", \"w\", \"\", \"\", \"release{2}!\", {3}, {4});".format(pr, last_location, j, dg, up)
Exemple #4
0
class TAWRITER:
    def __init__(self, aiger_file_name, time_file_name, factor=1):
        self.aig = AIG(aiger_file_name, False)
        self.lit_to_formula = dict()
        self._cached_transition = None
        self.factor = factor
        self.delays = self._read_delays(time_file_name)

    def _read_delays(self, time_file_name):
        delays = dict()
        latches = [x.lit for x in self.aig.iterate_latches()]
        with open(time_file_name, 'r') as fp:
            for l in range(len(latches)):
                s = fp.readline()
                if s <> "":
                    #print "Doing line:&lt;{0}&gt;".format(s)
                    #print s.split(" ")
                    si = map(lambda x: int(x), s.split(" "))
                    assert (len(si) == 2)
                    delays[latches[l]] = (si[0] * self.factor,
                                          si[1] * self.factor)
                else:
                    delays[latches[l]] = (self.factor, self.factor)
        log.DBG_MSG("Latch delays: " + str(delays))
        return delays

    def set_lit2formula(self, lit, s):
        self.lit_to_formula[lit] = s

    """ Name of stripped literal which must be an input or latch """

    def name_of(self, lit):
        assert (lit == strip_lit(lit))
        (intput, latch, and_gate) = self.aig.get_lit_type(lit)
        # is it an input, latch, gate or constant
        #print &gt;&gt; sys.stderr, "lit", lit, (input,latch,and_gate)
        if latch:
            return "L" + self.aig.get_lit_name(lit).replace(
                "&lt;", "_").replace("&gt;", "_")
        elif input:
            # Boolean variables are encoded as 1-bit integers for now
            return "I" + self.aig.get_lit_name(lit).replace(
                "&lt;", "_").replace("&gt;", "_")
        else:
            raise "And gates or constant inputs have no name"

    def lit2formula(self, lit):
        if lit in self.lit_to_formula:
            return self.lit_to_formula[lit]
        # get stripped lit
        stripped_lit = strip_lit(lit)
        is_neg = lit_is_negated(lit)
        (input, latch, and_gate) = self.aig.get_lit_type(stripped_lit)
        # is it an input, latch, gate or constant
        if input or latch:
            # Boolean variables are encoded as 1-bit integers for now
            result = "({0})".format(self.name_of(stripped_lit))
        elif and_gate:
            if numeric_mode:
                result = ("({0} * {1})".format(self.lit2formula(and_gate.rhs0),
                                               self.lit2formula(
                                                   and_gate.rhs1)))
            else:
                result = ("({0} &amp;&amp; {1})".format(
                    self.lit2formula(and_gate.rhs0),
                    self.lit2formula(and_gate.rhs1)))
        else:  # 0 literal, 1 literal and errors
            result = "0"  # this means false
        # cache result
        self.lit_to_formula[stripped_lit] = result
        if is_neg:
            if result == "0":
                result = "1"
            else:
                if numeric_mode:
                    result = "(1-{0})".format(result)
                else:
                    result = "!{0}".format(result)
            self.lit_to_formula[lit] = result
        return result

    def get_next_funcs(self):
        if self._cached_transition is not None:
            return self._cached_transition
        vec = dict()
        for x in self.aig.iterate_latches():
            vec[x.lit] = self.lit2formula(x.next)
        self._cached_transition = vec
        return vec

    """
    Given K, make timed automaton model that restricts each cycle to K time units.
    """

    def get_cycle_time_model(self, nb_clocked_latches, K):
        K = K * self.factor
        latch_locations = dict()
        # clock name associated to given lit which is a latch
        clock_name = dict()
        nta = NTA()
        temp = Template("Circuit")
        nta.add_template(temp)

        decl = StringIO.StringIO()
        init = Location("Init", urgent=True, initial=True)
        deadlock = Location("dead", error=True)

        latch_list = list(self.aig.iterate_latches())
        latch_num = len(latch_list)

        clocked_latches = filter(lambda x: "state" in self.name_of(x.lit),
                                 latch_list)
        clocked_latches = latch_list
        clocked_latches = clocked_latches[0:nb_clocked_latches]
        clock_decl = []
        print >> sys.stderr, "Clocked latches: "
        for x in clocked_latches:
            print >> sys.stderr, x.lit, " ", self.name_of(
                x.lit), self.delays[x.lit]
            clock_name[x.lit] = "x_" + str(x.lit)
            clock_decl.append(clock_name[x.lit])
        clock_decl.append("t")
        temp.decl = ("clock: " + ", ".join(clock_decl) + ";")
        last_location = init
        input_list = list(
            chain(self.aig.iterate_uncontrollable_inputs(),
                  self.aig.iterate_controllable_inputs()))
        print >> decl, "var fdead :{0..1} = 0;"
        for i in input_list:
            print >> decl, "var {0}".format(self.name_of(
                i.lit)), ":{0..1} = 0;"
            loc_after_i = Location("JustSet" + self.name_of(i.lit),
                                   urgent=True)
            tr0 = Transition(last_location,
                             loc_after_i,
                             disc_up="{0} = 0;".format(self.name_of(i.lit)))
            tr1 = Transition(last_location,
                             loc_after_i,
                             disc_up="{0} = 1;".format(self.name_of(i.lit)))
            temp.add_transition(tr0)
            temp.add_transition(tr1)
            last_location = loc_after_i
            pass

        next_funcs = self.get_next_funcs()

        for x in latch_list:
            print >> decl, "var {0} ".format(self.name_of(
                x.lit)), ":{0..1} = 0;"
            if not x in clocked_latches:
                continue
            latch_locations[x.lit] = Location("Updated" + self.name_of(x.lit),
                                              urgent=True)

            # Basically, we add the following transitions but use intermediary states
            # with invariants so that all transitions are urgent
            # updated(l_{i-1},urg) ---- f(vec(l),I) = l_i ----&gt; updated(l_{i+1})
            # updated(l_{i-1},urg) ---- f(vec(l),I) = 0 && l_i = 1, x_i &gt;= D_i^1, l_i := 0, x_i := 0 ----&gt; updated(l_{i},urg)
            # updated(l_{i-1},urg) ---- f(vec(l),I) = 0 && l_i = 1, x_i &lt; D_i^1, l_i := 0, x_i := 0 ----&gt; will_become1_nurg(l_{i})
            # symmetrically for when the new value is 1
            # will_become1_nurg(l_{i},invar:x_i&lt;=D_i^1) ---- x_i &gt;= D_i^0, l_i := 1, x_i := 0 ----&gt; updated(l_{i}, urg)

            # if the value does not change:
            disc_g = "{0} == {1}".format(self.name_of(x.lit),
                                         next_funcs[x.lit])
            tr = Transition(last_location,
                            latch_locations[x.lit],
                            disc_guard=disc_g)
            temp.add_transition(tr)

            # if it changes but the delay is already respected, move on directly
            disc_g = "{0} == 1 &amp;&amp; {0} != {1}".format(
                self.name_of(x.lit), next_funcs[x.lit])
            clock_g = "{0} &gt;= {1}".format(clock_name[x.lit],
                                             self.delays[x.lit][0])
            temp.add_transition(
                Transition(last_location,
                           latch_locations[x.lit],
                           disc_guard=disc_g,
                           guard=clock_g))
            g = "{0} == 0 &amp;&amp; {0} != {1}".format(
                self.name_of(x.lit), next_funcs[x.lit])
            clock_g = "{0} &gt;= {1}".format(clock_name[x.lit],
                                             self.delays[x.lit][1])
            temp.add_transition(
                Transition(last_location,
                           latch_locations[x.lit],
                           guard=clock_g,
                           disc_guard=g))

            # if we have to wait to respect the delay go to specific wait state and wait precisely for the delay (matching invariant + guard)
            loc0 = Location(latch_locations[x.lit].name + "_becomes0")
            loc0.set_invariant("{0} &lt;= {1}".format(clock_name[x.lit],
                                                      self.delays[x.lit][0]))
            loc1 = Location(latch_locations[x.lit].name + "_becomes1")
            loc1.set_invariant("{0} &lt;= {1}".format(clock_name[x.lit],
                                                      self.delays[x.lit][1]))

            g = "{0} == 1 &amp;&amp; {0} != {1}".format(
                self.name_of(x.lit), next_funcs[x.lit])
            if self.delays[x.lit][0] > 0:
                clock_g = "{0} &lt;= {1}".format(clock_name[x.lit],
                                                 self.delays[x.lit][0] - 1)
            else:
                clock_g = ""
            tr = Transition(last_location, loc0, guard=clock_g, disc_guard=g)
            temp.add_transition(tr)

            up = "{0} = {1};".format(self.name_of(x.lit), next_funcs[x.lit])
            g = "{0} &gt;= {1}".format(clock_name[x.lit],
                                       self.delays[x.lit][0])
            tr = Transition(loc0,
                            latch_locations[x.lit],
                            guard=g,
                            disc_up=up,
                            reset=clock_name[x.lit])
            temp.add_transition(tr)

            g = "{0} == 0 &amp;&amp; {0} != {1} ".format(
                self.name_of(x.lit), next_funcs[x.lit])
            if self.delays[x.lit][1] > 0:
                clock_g = "{0} &lt;= {1}".format(clock_name[x.lit],
                                                 self.delays[x.lit][1] - 1)
            else:
                clock_g = ""
            tr = Transition(last_location, loc1, guard=clock_g, disc_guard=g)
            temp.add_transition(tr)

            up = "{0} = {1};".format(self.name_of(x.lit), next_funcs[x.lit])
            g = "{0} &gt;= {1}".format(clock_name[x.lit],
                                       self.delays[x.lit][1])
            tr = Transition(loc1,
                            latch_locations[x.lit],
                            guard=g,
                            disc_up=up,
                            reset=clock_name[x.lit])
            temp.add_transition(tr)

            last_location = latch_locations[x.lit]
            pass
        go_deadlock = Transition(last_location,
                                 deadlock,
                                 guard="t &gt;={0}".format(str(K + 1)),
                                 disc_up="fdead = 1;")
        come_back = Transition(last_location,
                               init,
                               guard="t &lt;= {0}".format(str(K)),
                               reset="t")
        temp.add_transition(come_back)
        temp.add_transition(go_deadlock)
        last_location = init
        print >> decl, "System = Circuit();"
        print >> decl, "#define Dead fdead==1;"
        print >> decl, "#assert System reaches Dead;"
        nta.set_declaration(decl.getvalue())
        nta.dump()

    def test(self):
        vec = self.get_next_funcs()
        for x in vec:
            print >> sys.stderr, "NEXT(", x, ")"
            print >> sys.stderr, vec[x]
            print >> sys.stderr, ""