{-# OPTIONS --safe --cubical #-}
module Spartan6.Hierarchy.Interface where
open import Spartan6.Prelude
record StablePort : Type₀ where
constructor stablePort
field
stablePortId : ℕ
stablePortName : String
stablePortWidth : ℕ
open StablePort public
infixr 5 _∥ᵢ_
data Interface : Type₀ where
emptyInterface : Interface
signalInterface : StablePort -> Interface
_∥ᵢ_ : Interface -> Interface -> Interface
interfaceWidth : Interface -> ℕ
interfaceWidth emptyInterface = 0
interfaceWidth (signalInterface port) = stablePortWidth port
interfaceWidth (left ∥ᵢ right) = interfaceWidth left + interfaceWidth right
Environment : Interface -> Type₀
Environment emptyInterface = Unit
Environment (signalInterface port) = Vec Bit (stablePortWidth port)
Environment (left ∥ᵢ right) = Environment left × Environment right
infixr 5 _∥ᵉ_
_∥ᵉ_ : ∀ {left right}
-> Environment left -> Environment right
-> Environment (left ∥ᵢ right)
_∥ᵉ_ = _,_
leftEnvironment : ∀ {left right}
-> Environment (left ∥ᵢ right) -> Environment left
leftEnvironment = fst
rightEnvironment : ∀ {left right}
-> Environment (left ∥ᵢ right) -> Environment right
rightEnvironment = snd
appendVec : ∀ {ℓ} {A : Type ℓ} {leftCount rightCount}
-> Vec A leftCount -> Vec A rightCount
-> Vec A (leftCount + rightCount)
appendVec [] right = right
appendVec (item ∷ left) right = item ∷ appendVec left right
splitVec : ∀ {ℓ} {A : Type ℓ} (leftCount rightCount : ℕ)
-> Vec A (leftCount + rightCount)
-> Vec A leftCount × Vec A rightCount
splitVec zero rightCount values = [] , values
splitVec (suc leftCount) rightCount (item ∷ values) =
item ∷ fst pieces , snd pieces
where
pieces : Vec _ leftCount × Vec _ rightCount
pieces = splitVec leftCount rightCount values
splitVec-append : ∀ {ℓ} {A : Type ℓ} {leftCount rightCount}
(left : Vec A leftCount) (right : Vec A rightCount)
-> splitVec leftCount rightCount (appendVec left right)
≡ (left , right)
splitVec-append [] right = refl
splitVec-append (item ∷ left) right =
cong
(λ pieces -> item ∷ fst pieces , snd pieces)
(splitVec-append left right)
appendVec-split : ∀ {ℓ} {A : Type ℓ}
(leftCount rightCount : ℕ)
(values : Vec A (leftCount + rightCount))
-> appendVec
(fst (splitVec leftCount rightCount values))
(snd (splitVec leftCount rightCount values))
≡ values
appendVec-split zero rightCount values = refl
appendVec-split (suc leftCount) rightCount (item ∷ values) =
cong (item ∷_) (appendVec-split leftCount rightCount values)
flattenEnvironment : ∀ {interface}
-> Environment interface -> Vec Bit (interfaceWidth interface)
flattenEnvironment {emptyInterface} environment = []
flattenEnvironment {signalInterface port} values = values
flattenEnvironment {left ∥ᵢ right} (left-values , right-values) =
appendVec
(flattenEnvironment {left} left-values)
(flattenEnvironment {right} right-values)
unflattenEnvironment : ∀ {interface}
-> Vec Bit (interfaceWidth interface) -> Environment interface
unflattenEnvironment {emptyInterface} values = tt
unflattenEnvironment {signalInterface port} values = values
unflattenEnvironment {left ∥ᵢ right} values =
unflattenEnvironment {left} (fst pieces)
, unflattenEnvironment {right} (snd pieces)
where
pieces : Vec Bit (interfaceWidth left) × Vec Bit (interfaceWidth right)
pieces = splitVec (interfaceWidth left) (interfaceWidth right) values
flatten-unflatten : ∀ {interface}
(values : Vec Bit (interfaceWidth interface))
-> flattenEnvironment (unflattenEnvironment {interface} values) ≡ values
flatten-unflatten {emptyInterface} [] = refl
flatten-unflatten {signalInterface port} values = refl
flatten-unflatten {left ∥ᵢ right} values =
cong₂ appendVec
(flatten-unflatten {left}
(fst (splitVec (interfaceWidth left) (interfaceWidth right) values)))
(flatten-unflatten {right}
(snd (splitVec (interfaceWidth left) (interfaceWidth right) values)))
∙ appendVec-split (interfaceWidth left) (interfaceWidth right) values
unflatten-append : ∀ {left right}
(left-values : Vec Bit (interfaceWidth left))
(right-values : Vec Bit (interfaceWidth right))
-> unflattenEnvironment {left ∥ᵢ right}
(appendVec left-values right-values)
≡ (unflattenEnvironment {left} left-values
, unflattenEnvironment {right} right-values)
unflatten-append {left} {right} left-values right-values =
cong
(λ pieces ->
(unflattenEnvironment {left} (fst pieces)
, unflattenEnvironment {right} (snd pieces)))
(splitVec-append left-values right-values)
unflatten-flatten : ∀ {interface}
(environment : Environment interface)
-> unflattenEnvironment (flattenEnvironment environment) ≡ environment
unflatten-flatten {emptyInterface} tt = refl
unflatten-flatten {signalInterface port} values = refl
unflatten-flatten {left ∥ᵢ right} (left-values , right-values) =
unflatten-append
(flattenEnvironment left-values)
(flattenEnvironment right-values)
∙ cong₂ _,_
(unflatten-flatten left-values)
(unflatten-flatten right-values)
environment-from-flat : ∀ {interface}
{left right : Environment interface}
-> flattenEnvironment left ≡ flattenEnvironment right
-> left ≡ right
environment-from-flat {left = left} {right = right} equality =
sym (unflatten-flatten left)
∙ cong unflattenEnvironment equality
∙ unflatten-flatten right
record Renaming (source target : Interface) : Type₀ where
constructor mkRenaming
field applyRenaming : Environment source -> Environment target
open Renaming public
identityRenaming : (interface : Interface) -> Renaming interface interface
identityRenaming interface = mkRenaming (λ environment -> environment)
composeRenaming : ∀ {source middle target}
-> Renaming source middle -> Renaming middle target
-> Renaming source target
composeRenaming first second =
mkRenaming
(λ environment -> applyRenaming second (applyRenaming first environment))
parallelRenaming : ∀ {left-source right-source left-target right-target}
-> Renaming left-source left-target
-> Renaming right-source right-target
-> Renaming
(left-source ∥ᵢ right-source)
(left-target ∥ᵢ right-target)
parallelRenaming left-map right-map =
mkRenaming
(λ environment ->
applyRenaming left-map (fst environment)
, applyRenaming right-map (snd environment))
leftProjection : ∀ {left right}
-> Renaming (left ∥ᵢ right) left
leftProjection = mkRenaming fst
rightProjection : ∀ {left right}
-> Renaming (left ∥ᵢ right) right
rightProjection = mkRenaming snd
swapParallel : ∀ {left right}
-> Renaming (left ∥ᵢ right) (right ∥ᵢ left)
swapParallel =
mkRenaming (λ environment -> snd environment , fst environment)
renaming-identity : ∀ {interface} (environment : Environment interface)
-> applyRenaming (identityRenaming interface) environment ≡ environment
renaming-identity environment = refl
renaming-compose : ∀ {source middle target}
(first : Renaming source middle)
(second : Renaming middle target)
(environment : Environment source)
-> applyRenaming (composeRenaming first second) environment
≡ applyRenaming second (applyRenaming first environment)
renaming-compose first second environment = refl