{-# OPTIONS --safe --cubical #-}
module Spartan6.Netlist.NormalizeRegisterSoundness where
open import Spartan6.Prelude
import Spartan6.Architecture.Primitive as Architecture
import Spartan6.Netlist.Checked as Checked
import Spartan6.Netlist.NormalizeRegister as Normalize
import Spartan6.Netlist.Raw as Raw
import Spartan6.Netlist.TopInterface as TopInterface
import Spartan6.Validation.Diagnostic as Diagnostic
import Spartan6.Validation.Raw as Validation
open import Spartan6.Validation.CheckResult
using (rejected≢accepted; accepted-injective)
open import Spartan6.Validation.ParameterSoundness
using (ScalarInitial; scalarDefault; scalarExplicit)
open import Cubical.Foundations.Path using (inspect; [_]ᵢ)
import Cubical.Data.Empty as Empty
data CanonicalRegisterMode
: Raw.RawInstance → Normalize.RegisterMode → Type₀ where
canonicalFDRE : ∀ {name ports initial-bit value}
→ ScalarInitial low initial-bit value
→ CanonicalRegisterMode
(Raw.rawInstance
name
(Raw.knownPrimitive Architecture.FDRE)
ports
[]ᴸ
initial-bit)
(Normalize.fdreMode value)
canonicalFDSE : ∀ {name ports initial-bit value}
→ ScalarInitial high initial-bit value
→ CanonicalRegisterMode
(Raw.rawInstance
name
(Raw.knownPrimitive Architecture.FDSE)
ports
[]ᴸ
initial-bit)
(Normalize.fdseMode value)
normaliseRegisterMode-sound : ∀ item mode
→ Normalize.normaliseRegisterMode item ≡ Diagnostic.accepted mode
→ CanonicalRegisterMode item mode
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDRE) ports []ᴸ nothing)
mode result
with accepted-injective result
... | mode-path =
subst
(CanonicalRegisterMode
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDRE) ports []ᴸ nothing))
mode-path
(canonicalFDRE scalarDefault)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDRE) ports []ᴸ (just bit))
mode result
with accepted-injective result
... | mode-path =
subst
(CanonicalRegisterMode
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDRE) ports []ᴸ (just bit)))
mode-path
(canonicalFDRE (scalarExplicit bit))
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDRE)
ports (parameter ∷ᴸ parameters) nothing)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDRE)
ports (parameter ∷ᴸ parameters) (just bit))
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDSE) ports []ᴸ nothing)
mode result
with accepted-injective result
... | mode-path =
subst
(CanonicalRegisterMode
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDSE) ports []ᴸ nothing))
mode-path
(canonicalFDSE scalarDefault)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDSE) ports []ᴸ (just bit))
mode result
with accepted-injective result
... | mode-path =
subst
(CanonicalRegisterMode
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDSE) ports []ᴸ (just bit)))
mode-path
(canonicalFDSE (scalarExplicit bit))
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDSE)
ports (parameter ∷ᴸ parameters) nothing)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.FDSE)
ports (parameter ∷ᴸ parameters) (just bit))
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name (Raw.unknownPrimitive unknown) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.LUT1) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.LUT2) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.LUT3) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.LUT4) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.LUT5) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.LUT6) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.MUXF7) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.MUXF8) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.CARRY4) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.SRL16E) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.RAM64X1S) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.IBUF) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.OBUF) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.OBUFDS) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.OBUFT) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.BUFG) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
normaliseRegisterMode-sound
(Raw.rawInstance name
(Raw.knownPrimitive Architecture.BUFGCE) ports parameters initial-bit)
mode result =
Empty.rec (rejected≢accepted result)
canonical-register-kind : ∀ {item mode}
→ CanonicalRegisterMode item mode
→ (Raw.rawInstanceKind item ≡ Raw.knownPrimitive Architecture.FDRE)
⊎ (Raw.rawInstanceKind item ≡ Raw.knownPrimitive Architecture.FDSE)
canonical-register-kind (canonicalFDRE initial) = inl refl
canonical-register-kind (canonicalFDSE initial) = inr refl
record RegisterBuildWitness
(design : Raw.RawDesign)
(structural-proof : Validation.StructurallyValid design)
(candidate : Normalize.CheckedRegisterCandidate)
: Type₀ where
field
registerItem : Raw.RawInstance
exactlyOneInstance :
Raw.rawInstances design ≡ registerItem ∷ᴸ []ᴸ
registerPorts : Normalize.RegisterPorts
portsParsed :
Normalize.parseRegisterPorts (Raw.rawInstancePorts registerItem)
≡ just registerPorts
registerMode : Normalize.RegisterMode
modeNormalised :
Normalize.normaliseRegisterMode registerItem
≡ Diagnostic.accepted registerMode
canonicalMode : CanonicalRegisterMode registerItem registerMode
inputNets : List Raw.NetId
inputNetsCollected :
TopInterface.collectInputNets (Raw.rawTopPorts design)
≡ Diagnostic.accepted inputNets
outputNet : Raw.NetId
outputNetAccepted :
Normalize.outputNet registerItem registerPorts
≡ Diagnostic.accepted outputNet
clockIndex : Fin (lengthList inputNets)
clockAccepted :
Normalize.clockInput inputNets (Normalize.registerC registerPorts)
≡ Diagnostic.accepted clockIndex
dataWire : Checked.Wire (lengthList inputNets) 1 0
dataAccepted :
Normalize.resolveBasePort
inputNets outputNet "register.D" (Normalize.registerD registerPorts)
≡ Diagnostic.accepted dataWire
enableWire : Checked.Wire (lengthList inputNets) 1 0
enableAccepted :
Normalize.resolveBasePort
inputNets outputNet "register.CE" (Normalize.registerCE registerPorts)
≡ Diagnostic.accepted enableWire
controlWire : Checked.Wire (lengthList inputNets) 1 0
controlAccepted :
Normalize.resolveBasePort
inputNets outputNet "register.control"
(Normalize.registerControl registerPorts)
≡ Diagnostic.accepted controlWire
outputWires : List (Checked.Wire (lengthList inputNets) 1 0)
outputsAccepted :
Normalize.collectTopOutputs
inputNets outputNet (Raw.rawTopPorts design)
≡ Diagnostic.accepted outputWires
candidateBuilt :
candidate
≡ Normalize.buildCandidate
design structural-proof registerItem registerPorts registerMode
inputNets outputNet clockIndex
dataWire enableWire controlWire outputWires
open RegisterBuildWitness public
normaliseParsedRegister-witness :
∀ design structural-proof item ports mode candidate
→ Raw.rawInstances design ≡ item ∷ᴸ []ᴸ
→ Normalize.parseRegisterPorts (Raw.rawInstancePorts item) ≡ just ports
→ Normalize.normaliseRegisterMode item ≡ Diagnostic.accepted mode
→ CanonicalRegisterMode item mode
→ Normalize.normaliseParsedRegister
design structural-proof item ports mode
≡ Diagnostic.accepted candidate
→ RegisterBuildWitness design structural-proof candidate
normaliseParsedRegister-witness
design structural-proof item ports mode candidate
one-instance ports-path mode-path canonical-mode result
with TopInterface.collectInputNets (Raw.rawTopPorts design)
| inspect TopInterface.collectInputNets (Raw.rawTopPorts design)
... | Diagnostic.rejected diagnostics | [ inputs-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted input-nets | [ inputs-path ]ᵢ
with Normalize.outputNet item ports
| inspect (Normalize.outputNet item) ports
... | Diagnostic.rejected diagnostics | [ output-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted q-net | [ output-path ]ᵢ
with Normalize.clockInput input-nets (Normalize.registerC ports)
| inspect (Normalize.clockInput input-nets) (Normalize.registerC ports)
... | Diagnostic.rejected diagnostics | [ clock-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted clock-index | [ clock-path ]ᵢ
with Normalize.resolveBasePort
input-nets q-net "register.D" (Normalize.registerD ports)
| inspect
(Normalize.resolveBasePort input-nets q-net "register.D")
(Normalize.registerD ports)
... | Diagnostic.rejected diagnostics | [ data-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted data-wire | [ data-path ]ᵢ
with Normalize.resolveBasePort
input-nets q-net "register.CE" (Normalize.registerCE ports)
| inspect
(Normalize.resolveBasePort input-nets q-net "register.CE")
(Normalize.registerCE ports)
... | Diagnostic.rejected diagnostics | [ enable-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted enable-wire | [ enable-path ]ᵢ
with Normalize.resolveBasePort
input-nets q-net "register.control"
(Normalize.registerControl ports)
| inspect
(Normalize.resolveBasePort input-nets q-net "register.control")
(Normalize.registerControl ports)
... | Diagnostic.rejected diagnostics | [ control-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted control-wire | [ control-path ]ᵢ
with Normalize.collectTopOutputs
input-nets q-net (Raw.rawTopPorts design)
| inspect
(Normalize.collectTopOutputs input-nets q-net)
(Raw.rawTopPorts design)
... | Diagnostic.rejected diagnostics | [ outputs-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted outputs | [ outputs-path ]ᵢ
with accepted-injective result
... | build-is-candidate =
record
{ registerItem = item
; exactlyOneInstance = one-instance
; registerPorts = ports
; portsParsed = ports-path
; registerMode = mode
; modeNormalised = mode-path
; canonicalMode = canonical-mode
; inputNets = input-nets
; inputNetsCollected = inputs-path
; outputNet = q-net
; outputNetAccepted = output-path
; clockIndex = clock-index
; clockAccepted = clock-path
; dataWire = data-wire
; dataAccepted = data-path
; enableWire = enable-wire
; enableAccepted = enable-path
; controlWire = control-wire
; controlAccepted = control-path
; outputWires = outputs
; outputsAccepted = outputs-path
; candidateBuilt = sym build-is-candidate
}
normaliseRegisterItem-witness :
∀ design structural-proof item candidate
→ Raw.rawInstances design ≡ item ∷ᴸ []ᴸ
→ Normalize.normaliseRegisterItem design structural-proof item
≡ Diagnostic.accepted candidate
→ RegisterBuildWitness design structural-proof candidate
normaliseRegisterItem-witness
design structural-proof item candidate one-instance result
with Normalize.parseRegisterPorts (Raw.rawInstancePorts item)
| inspect Normalize.parseRegisterPorts (Raw.rawInstancePorts item)
... | nothing | [ ports-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | just ports | [ ports-path ]ᵢ
with Normalize.normaliseRegisterMode item
| inspect Normalize.normaliseRegisterMode item
... | Diagnostic.rejected diagnostics | [ mode-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted mode | [ mode-path ]ᵢ =
normaliseParsedRegister-witness
design structural-proof item ports mode candidate
one-instance ports-path mode-path
(normaliseRegisterMode-sound item mode mode-path)
result
normaliseSingleRegister-witness :
∀ checked candidate
→ Normalize.normaliseSingleRegister checked
≡ Diagnostic.accepted candidate
→ RegisterBuildWitness (fst checked) (snd checked) candidate
normaliseSingleRegister-witness
(Raw.rawDesign target top-ports (item ∷ᴸ []ᴸ) , structural-proof)
candidate result
with TopInterface.checkDevelopmentTarget
(Raw.rawDesign target top-ports (item ∷ᴸ []ᴸ))
| inspect TopInterface.checkDevelopmentTarget
(Raw.rawDesign target top-ports (item ∷ᴸ []ᴸ))
... | Diagnostic.rejected diagnostics | [ target-path ]ᵢ =
Empty.rec (rejected≢accepted result)
... | Diagnostic.accepted tt | [ target-path ]ᵢ =
normaliseRegisterItem-witness
(Raw.rawDesign target top-ports (item ∷ᴸ []ᴸ))
structural-proof item candidate refl result
normaliseSingleRegister-witness
(Raw.rawDesign target top-ports []ᴸ , structural-proof)
candidate result =
Empty.rec (rejected≢accepted result)
normaliseSingleRegister-witness
(Raw.rawDesign target top-ports (first ∷ᴸ second ∷ᴸ rest) ,
structural-proof)
candidate result =
Empty.rec (rejected≢accepted result)
candidateBoundary : Normalize.CheckedRegisterCandidate
→ Validation.StructurallyChecked
candidateBoundary candidate =
Normalize.candidateSource candidate
, Normalize.candidateStructuralProof candidate
candidate-boundary-preserved :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ candidateBoundary candidate ≡ (design , structural-proof)
candidate-boundary-preserved witness =
cong candidateBoundary (candidateBuilt witness)
candidate-source-preserved :
∀ {design structural-proof candidate}
→ RegisterBuildWitness design structural-proof candidate
→ Normalize.candidateSource candidate ≡ design
candidate-source-preserved witness =
cong Normalize.candidateSource (candidateBuilt witness)
accepted-canonical-register :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ Σ Raw.RawInstance λ item
→ (Raw.rawInstances design ≡ item ∷ᴸ []ᴸ)
× Σ Normalize.RegisterMode λ mode
→ CanonicalRegisterMode item mode
accepted-canonical-register witness =
registerItem witness
, exactlyOneInstance witness
, registerMode witness
, canonicalMode witness
InputClock : Type₀
InputClock = Σ ℕ Fin
NodesOfOneRegister : Type₀
NodesOfOneRegister = Σ ℕ λ input-count → Checked.Nodes input-count 1 2
NextOfOneRegister : Type₀
NextOfOneRegister =
Σ ℕ λ input-count
→ Vec (Checked.Wire input-count 1 2) 1
candidateInputClock : Normalize.CheckedRegisterCandidate → InputClock
candidateInputClock candidate =
Normalize.candidateInputCount candidate
, Normalize.candidateClockInput candidate
candidateNodes : Normalize.CheckedRegisterCandidate → NodesOfOneRegister
candidateNodes candidate =
Normalize.candidateInputCount candidate
, Checked.checkedNodes (Normalize.candidateNetlist candidate)
candidateNext : Normalize.CheckedRegisterCandidate → NextOfOneRegister
candidateNext candidate =
Normalize.candidateInputCount candidate
, Checked.checkedNext (Normalize.candidateNetlist candidate)
candidate-initial-is-mode :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ Checked.checkedInitial (Normalize.candidateNetlist candidate)
≡ Normalize.modeInitial (registerMode witness) ∷ []
candidate-initial-is-mode witness =
cong
(λ candidate →
Checked.checkedInitial (Normalize.candidateNetlist candidate))
(candidateBuilt witness)
candidate-has-two-register-nodes :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ candidateNodes candidate
≡ (lengthList (inputNets witness)
, Normalize.registerNodes
(registerMode witness)
(dataWire witness)
(enableWire witness)
(controlWire witness))
candidate-has-two-register-nodes witness =
cong candidateNodes (candidateBuilt witness)
candidate-has-one-local-next :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ candidateNext candidate
≡ (lengthList (inputNets witness)
, Checked.localWire fzero ∷ [])
candidate-has-one-local-next witness =
cong candidateNext (candidateBuilt witness)
candidate-records-clock-index :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ candidateInputClock candidate
≡ (lengthList (inputNets witness) , clockIndex witness)
candidate-records-clock-index witness =
cong candidateInputClock (candidateBuilt witness)
record RecordedTopLevelClock
(design : Raw.RawDesign)
(candidate : Normalize.CheckedRegisterCandidate)
: Type₀ where
field
clockRegisterItem : Raw.RawInstance
clockOnlyInstance :
Raw.rawInstances design ≡ clockRegisterItem ∷ᴸ []ᴸ
clockRegisterPorts : Normalize.RegisterPorts
clockPortsParsed :
Normalize.parseRegisterPorts
(Raw.rawInstancePorts clockRegisterItem)
≡ just clockRegisterPorts
collectedInputNets : List Raw.NetId
collectedInputsAccepted :
TopInterface.collectInputNets (Raw.rawTopPorts design)
≡ Diagnostic.accepted collectedInputNets
recordedClockIndex : Fin (lengthList collectedInputNets)
rawClockAccepted :
Normalize.clockInput
collectedInputNets (Normalize.registerC clockRegisterPorts)
≡ Diagnostic.accepted recordedClockIndex
checkedClockRecorded :
candidateInputClock candidate
≡ (lengthList collectedInputNets , recordedClockIndex)
open RecordedTopLevelClock public
accepted-records-top-level-clock :
∀ {design structural-proof candidate}
→ (witness : RegisterBuildWitness design structural-proof candidate)
→ RecordedTopLevelClock design candidate
accepted-records-top-level-clock witness =
record
{ clockRegisterItem = registerItem witness
; clockOnlyInstance = exactlyOneInstance witness
; clockRegisterPorts = registerPorts witness
; clockPortsParsed = portsParsed witness
; collectedInputNets = inputNets witness
; collectedInputsAccepted = inputNetsCollected witness
; recordedClockIndex = clockIndex witness
; rawClockAccepted = clockAccepted witness
; checkedClockRecorded = candidate-records-clock-index witness
}