{-# OPTIONS --safe --cubical #-}
module Spartan6.Validation.CycleSoundness where
open import Spartan6.Prelude
import Spartan6.Netlist.Raw as Raw
import Spartan6.Validation.Raw as Validation
open import Cubical.Data.Nat using (_≡ᵇ_)
open import Cubical.Data.Bool.Properties using (false≢true)
import Cubical.Data.Empty as Empty
private
variable
ℓ : Level
infix 4 _∈_
data _∈_ {A : Type ℓ} (item : A) : List A → Type ℓ where
here : ∀ {items} → item ∈ (item ∷ᴸ items)
there : ∀ {other items} → item ∈ items → item ∈ (other ∷ᴸ items)
or-true-sound : ∀ {left right}
→ left or right ≡ true
→ (left ≡ true) ⊎ (right ≡ true)
or-true-sound {false} {false} result =
Empty.rec (false≢true result)
or-true-sound {false} {true} result = inr refl
or-true-sound {true} {false} result = inl refl
or-true-sound {true} {true} result = inl refl
or-true-left : ∀ {left right}
→ left ≡ true
→ left or right ≡ true
or-true-left {left} {right} result =
cong (λ value → value or right) result
or-true-right : ∀ {left right}
→ right ≡ true
→ left or right ≡ true
or-true-right {false} result = result
or-true-right {true} result = refl
nat-equality-reflexive : ∀ number → (number ≡ᵇ number) ≡ true
nat-equality-reflexive zero = refl
nat-equality-reflexive (suc number) = nat-equality-reflexive number
nat-equality-sound : ∀ {left right}
→ (left ≡ᵇ right) ≡ true
→ left ≡ right
nat-equality-sound {zero} {zero} result = refl
nat-equality-sound {zero} {suc right} result =
Empty.rec (false≢true result)
nat-equality-sound {suc left} {zero} result =
Empty.rec (false≢true result)
nat-equality-sound {suc left} {suc right} result =
cong suc (nat-equality-sound result)
nat-equality-complete : ∀ {left right}
→ left ≡ right
→ (left ≡ᵇ right) ≡ true
nat-equality-complete {left} equality =
subst (λ right → (left ≡ᵇ right) ≡ true)
equality
(nat-equality-reflexive left)
data DependencyEdge
(source target : Raw.NetId)
: List Validation.Dependency → Type₀ where
edgeHere : ∀ {edge edges}
→ source ≡ Validation.Dependency.dependencySource edge
→ target ≡ Validation.Dependency.dependencyTarget edge
→ DependencyEdge source target (edge ∷ᴸ edges)
edgeThere : ∀ {edge edges}
→ DependencyEdge source target edges
→ DependencyEdge source target (edge ∷ᴸ edges)
targetsFrom-sound : ∀ {source target edges}
→ target ∈ Validation.targetsFrom source edges
→ DependencyEdge source target edges
targetsFrom-sound {edges = []ᴸ} ()
targetsFrom-sound
{source} {target} {edge ∷ᴸ edges} membership
with source ≡ᵇ Validation.Dependency.dependencySource edge UsingEq
... | false , comparison =
edgeThere
(targetsFrom-sound
(subst
(λ equal-source →
target ∈
(if equal-source
then Validation.Dependency.dependencyTarget edge
∷ᴸ Validation.targetsFrom source edges
else Validation.targetsFrom source edges))
comparison
membership))
... | true , comparison
with subst
(λ equal-source →
target ∈
(if equal-source
then Validation.Dependency.dependencyTarget edge
∷ᴸ Validation.targetsFrom source edges
else Validation.targetsFrom source edges))
comparison
membership
... | here = edgeHere (nat-equality-sound comparison) refl
... | there rest = edgeThere (targetsFrom-sound rest)
targetsFrom-complete : ∀ {source target edges}
→ DependencyEdge source target edges
→ target ∈ Validation.targetsFrom source edges
targetsFrom-complete {edges = []ᴸ} ()
targetsFrom-complete
{source} {target} {edge ∷ᴸ edges}
(edgeHere source-path target-path) =
subst
(λ equal-source →
target ∈
(if equal-source
then Validation.Dependency.dependencyTarget edge
∷ᴸ Validation.targetsFrom source edges
else Validation.targetsFrom source edges))
(sym (nat-equality-complete source-path))
(subst
(λ candidate →
candidate
∈ (Validation.Dependency.dependencyTarget edge
∷ᴸ Validation.targetsFrom source edges))
(sym target-path)
here)
targetsFrom-complete
{source} {target} {edge ∷ᴸ edges}
(edgeThere rest)
with source ≡ᵇ Validation.Dependency.dependencySource edge
... | false = targetsFrom-complete rest
... | true = there (targetsFrom-complete rest)
data ReachableWithin
(edges : List Validation.Dependency)
(target : Raw.NetId)
: ℕ → Raw.NetId → Type₀ where
atTarget : ∀ {fuel current}
→ current ≡ target
→ ReachableWithin edges target fuel current
followEdge : ∀ {fuel current next}
→ DependencyEdge current next edges
→ ReachableWithin edges target fuel next
→ ReachableWithin edges target (suc fuel) current
mutual
reachable-sound : ∀ {fuel target current edges}
→ Validation.reachable fuel target current edges ≡ true
→ ReachableWithin edges target fuel current
reachable-sound {fuel = zero} result =
atTarget (nat-equality-sound result)
reachable-sound {fuel = suc fuel} result
with or-true-sound result
... | inl current-is-target =
atTarget (nat-equality-sound current-is-target)
... | inr explored with explore-sound explored
... | next , membership , path =
followEdge (targetsFrom-sound membership) path
explore-sound : ∀ {fuel target nexts edges}
→ Validation.explore fuel target nexts edges ≡ true
→ Σ Raw.NetId λ next
→ (next ∈ nexts) × ReachableWithin edges target fuel next
explore-sound {nexts = []ᴸ} result =
Empty.rec (false≢true result)
explore-sound {nexts = next ∷ᴸ nexts} result
with or-true-sound result
... | inl found = next , here , reachable-sound found
... | inr found-later with explore-sound found-later
... | later-next , membership , path =
later-next , there membership , path
mutual
reachable-complete : ∀ {fuel target current edges}
→ ReachableWithin edges target fuel current
→ Validation.reachable fuel target current edges ≡ true
reachable-complete {fuel = zero} (atTarget equality) =
nat-equality-complete equality
reachable-complete {fuel = suc fuel} (atTarget equality) =
or-true-left (nat-equality-complete equality)
reachable-complete {fuel = suc fuel} (followEdge edge path) =
or-true-right
(explore-complete (targetsFrom-complete edge) path)
explore-complete : ∀ {fuel target next nexts edges}
→ next ∈ nexts
→ ReachableWithin edges target fuel next
→ Validation.explore fuel target nexts edges ≡ true
explore-complete here path =
or-true-left (reachable-complete path)
explore-complete (there membership) path =
or-true-right (explore-complete membership path)
CycleWithin : ℕ
→ List Validation.Dependency
→ List Validation.Dependency
→ Type₀
CycleWithin fuel all-edges candidate-edges =
Σ Validation.Dependency λ edge
→ (edge ∈ candidate-edges)
× ReachableWithin
all-edges
(Validation.Dependency.dependencySource edge)
fuel
(Validation.Dependency.dependencyTarget edge)
someDependencyCycles-sound : ∀ {fuel all-edges candidate-edges}
→ Validation.someDependencyCycles fuel all-edges candidate-edges ≡ true
→ CycleWithin fuel all-edges candidate-edges
someDependencyCycles-sound {candidate-edges = []ᴸ} result =
Empty.rec (false≢true result)
someDependencyCycles-sound
{fuel} {all-edges} {edge ∷ᴸ edges} result
with or-true-sound result
... | inl return-path =
edge , here , reachable-sound return-path
... | inr later-cycle with someDependencyCycles-sound later-cycle
... | found-edge , membership , return-path =
found-edge , there membership , return-path
someDependencyCycles-complete : ∀ {fuel all-edges candidate-edges}
→ CycleWithin fuel all-edges candidate-edges
→ Validation.someDependencyCycles fuel all-edges candidate-edges ≡ true
someDependencyCycles-complete {candidate-edges = []ᴸ}
(edge , () , return-path)
someDependencyCycles-complete {candidate-edges = edge ∷ᴸ edges}
(.edge , here , return-path) =
or-true-left (reachable-complete return-path)
someDependencyCycles-complete {candidate-edges = edge ∷ᴸ edges}
(found-edge , there membership , return-path) =
or-true-right
(someDependencyCycles-complete
(found-edge , membership , return-path))
CombinationalCycle : Raw.RawDesign → Type₀
CombinationalCycle design =
CycleWithin
(suc (lengthList (Validation.designDependencies design)))
(Validation.designDependencies design)
(Validation.designDependencies design)
combinationalCycle?-sound : ∀ design
→ Validation.combinationalCycle? design ≡ true
→ CombinationalCycle design
combinationalCycle?-sound design result =
someDependencyCycles-sound result
combinationalCycle?-complete : ∀ design
→ CombinationalCycle design
→ Validation.combinationalCycle? design ≡ true
combinationalCycle?-complete design cycle =
someDependencyCycles-complete cycle