teakV :: Width -> [Slice Int] -> [Slice Int] -> [Chan] -> [Chan] -> [Chan] -> [Chan] ->
        MkPNMonad SimFlow SimValue ()
    teakV width wSlices rSlices wg wd rg rd = withLabel "V" $ do
        idlePlaces <- mapM read $ zip4 [(0::Int)..] rSlices rg rd
        mapM_ (write idlePlaces) $ zip4 [(0::Int)..] wSlices wg wd
        where
            write idlePlaces (i, slice, ((goR, goA), _), (_, (doneR, doneA))) = withLabel ("w" ++ show i) $ do
                withLabel "r" $ newTrans (goR : idlePlaces) (doneR : idlePlaces)
                    ((PNLiteral token) : replicate readCount writeExpr)
                withLabel "a" $ newTrans [doneA] [goA] [PNLiteral token]
                where
                    writeExpr
                        | slice == 0 +: width = PNInput 0
                        | otherwise = PNInsertBitfield slice (PNInput 1) (PNInput 0)

            read (i, slice, ((goR, goA), _), (_, (doneR, doneA))) = withLabel ("r" ++ show i) $ do
                idlePlace <- withLabel "idle" $ newNumericPlace width [initValue]
                busyPlace <- withLabel "busy" $ newNumericPlace width []
                withLabel "r" $ newTrans [goR, idlePlace] [doneR, busyPlace] [pnBitfield slice (PNInput 1), PNInput 1]
                withLabel "a" $ newTrans [doneA, busyPlace] [goA, idlePlace] [PNLiteral token, PNInput 1]
                return idlePlace

            readCount = length rg
            initValue = SimValue 0 []
teakV :: Width -> [Slice Int] -> [Slice Int] -> [Chan] -> [Chan] -> [Chan] -> [Chan] ->
        MkPNMonad SimFlow SimValue ()
teakV width wSlices rSlices wg wd rg rd = withLabel "V" $ do
        idlePlaces <- mapM read $ zip4 [(0::Int)..] rSlices rg rd
        mapM_ (write idlePlaces) $ zip4 [(0::Int)..] wSlices wg wd
        where
            write idlePlaces (i, slice, ((goR, goA), _), (_, (doneR, doneA))) = withLabel ("w" ++ show i) $ do
                withLabel "r" $ newTrans (goR : idlePlaces) (doneR : idlePlaces)
                    ((PNLiteral token) : replicate readCount writeExpr)
                withLabel "a" $ newTrans [doneA] [goA] [PNLiteral token]
                where
                    writeExpr
                        | slice == 0 +: width = PNInput 0
                        | otherwise = PNInsertBitfield slice (PNInput 1) (PNInput 0)

            read (i, slice, ((goR, goA), _), (_, (doneR, doneA))) = withLabel ("r" ++ show i) $ do
                idlePlace <- withLabel "idle" $ newNumericPlace width [initValue]
                busyPlace <- withLabel "busy" $ newNumericPlace width []
                withLabel "r" $ newTrans [goR, idlePlace] [doneR, busyPlace] [pnBitfield slice (PNInput 1), PNInput 1]
                withLabel "a" $ newTrans [doneA, busyPlace] [goA, idlePlace] [PNLiteral token, PNInput 1]
                return idlePlace

            readCount = length rg
            initValue = SimValue 0 []
teakV width wSlices rSlices wg wd rg rd = withLabel "V" $ do
        idlePlaces <- mapM read $ zip4 [(0::Int)..] rSlices rg rd
        mapM_ (write idlePlaces) $ zip4 [(0::Int)..] wSlices wg wd
        where
            write idlePlaces (i, slice, ((goR, goA), _), (_, (doneR, doneA))) = withLabel ("w" ++ show i) $ do
                withLabel "r" $ newTrans (goR : idlePlaces) (doneR : idlePlaces)
                    ((PNLiteral token) : replicate readCount writeExpr)
                withLabel "a" $ newTrans [doneA] [goA] [PNLiteral token]
                where
                    writeExpr
                        | slice == 0 +: width = PNInput 0
                        | otherwise = PNInsertBitfield slice (PNInput 1) (PNInput 0)

            read (i, slice, ((goR, goA), _), (_, (doneR, doneA))) = withLabel ("r" ++ show i) $ do
                idlePlace <- withLabel "idle" $ newNumericPlace width [initValue]
                busyPlace <- withLabel "busy" $ newNumericPlace width []
                withLabel "r" $ newTrans [goR, idlePlace] [doneR, busyPlace] [pnBitfield slice (PNInput 1), PNInput 1]
                withLabel "a" $ newTrans [doneA, busyPlace] [goA, idlePlace] [PNLiteral token, PNInput 1]
                return idlePlace

            readCount = length rg
            initValue = SimValue 0 []