Documentation

SSA.Experimental.Bits.AutoStructs.FiniteStateMachine

structure AutoStructs.FSM (arity : Type) :

FSM n represents a function BitStream → ⋯ → BitStreamBitStream, where n is the number of BitStream arguments, as a finite state machine.

  • α : Type

    The arity of the (finite) type α determines how many bits the internal carry state of this FSM has

  • i : FinEnum self
  • dec_eq : DecidableEq self
  • initCarry : selfBool

    initCarry is the value of the initial internal carry state. It maps each α to a bit, thus it is morally a bitvector where the width is the arity of α

  • nextBitCirc : Option selfCircuit (self arity)

    nextBitCirc is a family of Boolean circuits, which may refer to the current input bits and the current state bits as free variables in the circuit.

    nextBitCirc none computes the current output bit. nextBitCirc (some a), computes the one bit of the new state that corresponds to a : α.

Instances For
    @[reducible, inline]
    abbrev AutoStructs.FSM.State {arity : Type} (p : AutoStructs.FSM arity) :

    The state of FSM p is given by a function from p.α to Bool.

    Note that p.α is assumed to be a finite type, so p.State is morally a finite bitvector whose width is given by the arity of p.α

    Equations
    • p.State = (pBool)
    Instances For
      def AutoStructs.FSM.nextBit {arity : Type} (p : AutoStructs.FSM arity) :
      p.State(arityBool)p.State × Bool

      p.nextBit state in computes both the next state bits and the output bit, where state are the current state bits, and in are the current input bits.

      Equations
      • p.nextBit carry inputBits = (fun (a : p) => (p.nextBitCirc (some a)).eval (Sum.elim carry inputBits), (p.nextBitCirc none).eval (Sum.elim carry inputBits))
      Instances For
        def AutoStructs.FSM.carry {arity : Type} (p : AutoStructs.FSM arity) (x : arityBitStream) :
        p.State

        p.carry in i computes the internal carry state at step i, given input streams in

        Equations
        • p.carry x 0 = p.initCarry
        • p.carry x n.succ = (p.nextBit (p.carry x n) fun (i : arity) => x i n).1
        Instances For
          def AutoStructs.FSM.eval {arity : Type} (p : AutoStructs.FSM arity) (x : arityBitStream) :

          eval p morally gives the function BitStream → ... → BitStream represented by FSM p

          Equations
          • p.eval x n = (p.nextBit (p.carry x n) fun (i : arity) => x i n).2
          Instances For
            def AutoStructs.FSM.eval' {arity : Type} (p : AutoStructs.FSM arity) (x : arityBitStream) :

            eval' is an alternative definition of eval

            Equations
            • One or more equations did not get rendered due to their size.
            Instances For
              def AutoStructs.FSM.changeInitCarry {arity : Type} (p : AutoStructs.FSM arity) (c : pBool) :

              p.changeInitCarry c yields an FSM with c as the initial state

              Equations
              Instances For
                theorem AutoStructs.FSM.carry_changeInitCarry_succ {arity : Type} (p : AutoStructs.FSM arity) (c : pBool) (x : arityBitStream) (n : ) :
                (p.changeInitCarry c).carry x (n + 1) = (p.changeInitCarry (p.nextBit c fun (a : arity) => x a 0).1).carry (fun (a : arity) (i : ) => x a (i + 1)) n
                theorem AutoStructs.FSM.eval_changeInitCarry_succ {arity : Type} (p : AutoStructs.FSM arity) (c : pBool) (x : arityBitStream) (n : ) :
                (p.changeInitCarry c).eval x (n + 1) = (p.changeInitCarry (p.nextBit c fun (a : arity) => x a 0).1).eval (fun (a : arity) (i : ) => x a (i + 1)) n
                theorem AutoStructs.FSM.eval_eq_carry {arity : Type} (p : AutoStructs.FSM arity) (x : arityBitStream) (n : ) :
                p.eval x n = (p.nextBit (p.carry x n) fun (i : arity) => x i n).2

                unfolds the definition of eval

                theorem AutoStructs.FSM.eval_eq_eval' {arity : Type} (p : AutoStructs.FSM arity) {x : arityBitStream} :
                p.eval x = p.eval' x
                def AutoStructs.FSM.changeVars {arity : Type} (p : AutoStructs.FSM arity) {arity2 : Type} (changeVars : arityarity2) :

                p.changeVars f changes the arity of an FSM. The function f determines how the new input bits map to the input expected by p

                Equations
                Instances For
                  def AutoStructs.FSM.compose {arity : Type} (p : AutoStructs.FSM arity) [FinEnum arity] [DecidableEq arity] (new_arity : Type) (q_arity : arityType) (vars : (a : arity) → q_arity anew_arity) (q : (a : arity) → AutoStructs.FSM (q_arity a)) :
                  AutoStructs.FSM new_arity

                  Given an FSM p of arity n, a family of n FSMs qᵢ of posibly different arities mᵢ, and given yet another arity m such that mᵢ ≤ m for all i, we can compose p with qᵢ yielding a single FSM of arity m, such that each FSM qᵢ computes the ith bit that is fed to the FSM p.

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    theorem AutoStructs.FSM.carry_compose {arity : Type} (p : AutoStructs.FSM arity) [FinEnum arity] [DecidableEq arity] (new_arity : Type) (q_arity : arityType) (vars : (a : arity) → q_arity anew_arity) (q : (a : arity) → AutoStructs.FSM (q_arity a)) (x : new_arityBitStream) (n : ) :
                    (p.compose new_arity q_arity vars q).carry x n = let z := p.carry (fun (a : arity) => (q a).eval fun (i : q_arity a) => x (vars a i)) n; Sum.elim z fun (a : (a : arity) × (q a)) => (q a.fst).carry (fun (t : q_arity a.fst) => x (vars a.fst t)) n a.snd
                    theorem AutoStructs.FSM.eval_compose {arity : Type} (p : AutoStructs.FSM arity) [FinEnum arity] [DecidableEq arity] (new_arity : Type) (q_arity : arityType) (vars : (a : arity) → q_arity anew_arity) (q : (a : arity) → AutoStructs.FSM (q_arity a)) (x : new_arityBitStream) :
                    (p.compose new_arity q_arity vars q).eval x = p.eval fun (a : arity) => (q a).eval fun (i : q_arity a) => x (vars a i)

                    Evaluating a composed fsm is equivalent to composing the evaluations of the constituent FSMs

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For
                      theorem AutoStructs.FSM.carry_add_succ (x : BoolBitStream) (n : ) :
                      AutoStructs.FSM.add.carry x (n + 1) = fun (x_1 : AutoStructs.FSM.add) => ((x true).addAux (x false) n).2

                      The internal carry state of the add FSM agrees with the carry bit of addition as implemented on bitstreams

                      @[simp]
                      theorem AutoStructs.FSM.carry_zero {arity : Type} (p : AutoStructs.FSM arity) (x : arityBitStream) :
                      p.carry x 0 = p.initCarry

                      We don't really need subtraction or negation FSMs, given that we can reduce both those operations to just addition and bitwise complement

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For
                        theorem AutoStructs.FSM.carry_sub (x : BoolBitStream) (n : ) :
                        AutoStructs.FSM.sub.carry x (n + 1) = fun (x_1 : AutoStructs.FSM.sub) => ((x true).subAux (x false) n).2
                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          theorem AutoStructs.FSM.carry_neg (x : UnitBitStream) (n : ) :
                          AutoStructs.FSM.neg.carry x (n + 1) = fun (x_1 : AutoStructs.FSM.neg) => ((x ()).negAux n).2
                          Equations
                          Instances For
                            Equations
                            Instances For
                              @[simp]
                              theorem AutoStructs.FSM.carry_one (x : Fin 0BitStream) (n : ) :
                              AutoStructs.FSM.one.carry x (n + 1) = fun (x : AutoStructs.FSM.one) => false
                              Equations
                              Instances For
                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  theorem AutoStructs.FSM.carry_ls (b : Bool) (x : UnitBitStream) (n : ) :
                                  (AutoStructs.FSM.ls b).carry x (n + 1) = fun (x_1 : (AutoStructs.FSM.ls b)) => x () n
                                  @[simp]
                                  @[simp]
                                  theorem AutoStructs.FSM.eval_var (n : ) (x : Fin (n + 1)BitStream) :
                                  (AutoStructs.FSM.var n).eval x = x (Fin.last n)
                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    theorem AutoStructs.FSM.carry_incr (x : UnitBitStream) (n : ) :
                                    AutoStructs.FSM.incr.carry x (n + 1) = fun (x_1 : AutoStructs.FSM.incr) => ((x ()).incrAux n).2
                                    @[simp]
                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For
                                      theorem AutoStructs.FSM.carry_decr (x : UnitBitStream) (n : ) :
                                      AutoStructs.FSM.decr.carry x (n + 1) = fun (x_1 : AutoStructs.FSM.decr) => ((x ()).decrAux n).2
                                      @[simp]
                                      theorem AutoStructs.FSM.evalAux_eq_zero_of_set {arity : Type} (p : AutoStructs.FSM arity) (R : Set (pBool)) (hR : ∀ (x : arityBool) (s : p.State), (p.nextBit s x).1 Rs R) (hi : p.initCarryR) (hr1 : ∀ (x : arityBool) (s : p.State), (p.nextBit s x).2 = trues R) (x : arityBitStream) (n : ) :
                                      p.eval x n = false p.carry x nR
                                      theorem AutoStructs.FSM.eval_eq_zero_of_set {arity : Type} (p : AutoStructs.FSM arity) (R : Set (pBool)) (hR : ∀ (x : arityBool) (s : p.State), (p.nextBit s x).1 Rs R) (hi : p.initCarryR) (hr1 : ∀ (x : arityBool) (s : p.State), (p.nextBit s x).2 = trues R) :
                                      p.eval = fun (x : arityBitStream) (x : ) => false
                                      @[simp]
                                      Instances For
                                        theorem AutoStructs.FSMSolution.good {t : AutoStructs.Term} (self : AutoStructs.FSMSolution t) :
                                        t.evalFinStream = self.eval
                                        Equations
                                        Instances For
                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          Instances For
                                            Equations
                                            • One or more equations did not get rendered due to their size.
                                            Instances For
                                              @[simp]
                                              theorem AutoStructs.composeUnary_eval (p : AutoStructs.FSM Unit) {t : AutoStructs.Term} (q : AutoStructs.FSMSolution t) (x : Fin t.arityBitStream) :
                                              (AutoStructs.composeUnary p q).eval x = p.eval fun (x_1 : Unit) => t.evalFinStream x
                                              @[simp]
                                              theorem AutoStructs.composeBinary_eval (p : AutoStructs.FSM Bool) {t₁ : AutoStructs.Term} {t₂ : AutoStructs.Term} (q₁ : AutoStructs.FSMSolution t₁) (q₂ : AutoStructs.FSMSolution t₂) (x : Fin (max t₁.arity t₂.arity)BitStream) :
                                              (AutoStructs.composeBinary p q₁ q₂).eval x = p.eval fun (b : Bool) => bif b then t₁.evalFinStream fun (i : Fin t₁.arity) => x (Fin.castLE i) else t₂.evalFinStream fun (i : Fin t₂.arity) => x (Fin.castLE i)
                                              instance AutoStructs.instFintypeCond_sSA {α : Type} {β : Type} [Fintype α] [Fintype β] (b : Bool) :
                                              Fintype (bif b then α else β)
                                              Equations
                                              • One or more equations did not get rendered due to their size.
                                              Equations
                                              Instances For

                                                FSM that implement bitwise-and. Since we use 0 as the good state, we keep the invariant that if both inputs are good and our state is 0, then we produce a 0. If not, we produce an infinite sequence of 1.

                                                Equations
                                                • One or more equations did not get rendered due to their size.
                                                Instances For

                                                  FSM that implement bitwise-or. Since we use 0 as the good state, we keep the invariant that if either inputs is 0 then our state is 0. If not, we produce a 1.

                                                  Equations
                                                  • One or more equations did not get rendered due to their size.
                                                  Instances For

                                                    FSM that implement logical not. we keep the invariant that if the input ever fails and becomes a 1, then we produce a 0. IF not, we produce an infinite sequence of 1.

                                                    EDIT: Aha, this doesn't work! We need NFA to DFA here (as the presburger book does), where we must produce an infinite sequence of0 iff the input can ever become a 1. But here, since we phrase things directly in terms of producing sequences, it's a bit less clear what we should do :)

                                                    Instances For
                                                      def AutoStructs.card_compl {α : Type} [Fintype α] [DecidableEq α] (c : Circuit α) :
                                                      Equations
                                                      Instances For
                                                        @[irreducible]
                                                        def AutoStructs.decideIfZerosAux {arity : Type} [DecidableEq arity] (p : AutoStructs.FSM arity) (c : Circuit p) :
                                                        Equations
                                                        • One or more equations did not get rendered due to their size.
                                                        Instances For
                                                          Equations
                                                          Instances For
                                                            @[irreducible]
                                                            theorem AutoStructs.decideIfZerosAux_correct {arity : Type} [DecidableEq arity] (p : AutoStructs.FSM arity) (c : Circuit p) (hc : ∀ (s : pBool), c.eval s = true∃ (m : ) (y : arityBitStream), (p.changeInitCarry s).eval y m = true) (hc₂ : ∀ (x : arityBool) (s : pBool), (p.nextBit s x).2 = truec.eval s = true) :
                                                            AutoStructs.decideIfZerosAux p c = true ∀ (n : ) (x : arityBitStream), p.eval x n = false
                                                            theorem AutoStructs.decideIfZeros_correct {arity : Type} [DecidableEq arity] (p : AutoStructs.FSM arity) :
                                                            AutoStructs.decideIfZeros p = true ∀ (n : ) (x : arityBitStream), p.eval x n = false

                                                            The fragment of predicate logic that we support in bv_automata. Currently, we support equality, conjunction, disjunction, and negation. This can be expanded to also support arithmetic constraints such as unsigned-less-than.

                                                            Instances For