teakLink :: String -> NetworkLink -> MkPNMonad SimFlow SimValue Chan
    teakLink partName link
        | depth == 0 = withLabel linkName $ do
            inp <- withLabel "a" $ pair
            out <- withLabel "p" $ pair
            withLabel "L" $ linkTrans "L" inp out
            return (out, inp)
        | otherwise = withLabel linkName $ do
            inp <- withLabel "a" $ pair
            out <- withLabel "p" $ pair
            internalLinks <- mapM (\i -> withLabel ("i" ++ show i) $ pair) [0..depth]
            withLabel "A" $ linkTrans "A" inp (head internalLinks)
            withLabel "P" $ linkTrans "P" (last internalLinks) out
            mapM_ (\(i, inp, out) -> withLabel (show i) $ latch inp out) $ zip3
                [(1::Int)..] (init internalLinks) (tail internalLinks)
            return (out, inp)
        where
            HalfBuffer depth = nwLinkLatching link
            ref = refLink link
            width = nwLinkWidth link
            linkName = show ref

            linkTrans end (inpR, inpA) (outR, outA) = do
                reqPlace <- withLabel "r" $ newBlackPlace [token]
                ackPlace <- withLabel "a" $ newBlackPlace []
                withLabel "r" $ trans "R" [inpR, reqPlace] [outR, ackPlace]
                withLabel "a" $ trans "SPACER" [outA, ackPlace] [inpA, reqPlace]
                where
                    trans event inp out = newReportTrans inp out
                        [PNInput 0, PNLiteral token]
                        $ \[v, _] -> do
                            TimeState time <- simFlowGet TimeRef
                            FileState handle <- simFlowGet LogFileRef
                            lift $ hPutStrLn handle $ "#" ++ show time ++ " " ++ partName ++ "."
                                ++ linkName ++ "." ++ end ++ " " ++ event
                                ++ case v of
                                    SimValue int [] -> " " ++ show int
                                    _ -> ""
                            return ()

            pair = do
                req <- withLabel "r" $ newNumericPlace width []
                ack <- withLabel "a" $ newBlackPlace []
                return (req, ack)
teakLink :: String -> NetworkLink -> MkPNMonad SimFlow SimValue Chan
teakLink partName link
        | depth == 0 = withLabel linkName $ do
            inp <- withLabel "a" $ pair
            out <- withLabel "p" $ pair
            withLabel "L" $ linkTrans "L" inp out
            return (out, inp)
        | otherwise = withLabel linkName $ do
            inp <- withLabel "a" $ pair
            out <- withLabel "p" $ pair
            internalLinks <- mapM (\i -> withLabel ("i" ++ show i) $ pair) [0..depth]
            withLabel "A" $ linkTrans "A" inp (head internalLinks)
            withLabel "P" $ linkTrans "P" (last internalLinks) out
            mapM_ (\(i, inp, out) -> withLabel (show i) $ latch inp out) $ zip3
                [(1::Int)..] (init internalLinks) (tail internalLinks)
            return (out, inp)
        where
            HalfBuffer depth = nwLinkLatching link
            ref = refLink link
            width = nwLinkWidth link
            linkName = show ref

            linkTrans end (inpR, inpA) (outR, outA) = do
                reqPlace <- withLabel "r" $ newBlackPlace [token]
                ackPlace <- withLabel "a" $ newBlackPlace []
                withLabel "r" $ trans "R" [inpR, reqPlace] [outR, ackPlace]
                withLabel "a" $ trans "SPACER" [outA, ackPlace] [inpA, reqPlace]
                where
                    trans event inp out = newReportTrans inp out
                        [PNInput 0, PNLiteral token]
                        $ \[v, _] -> do
                            TimeState time <- simFlowGet TimeRef
                            FileState handle <- simFlowGet LogFileRef
                            lift $ hPutStrLn handle $ "#" ++ show time ++ " " ++ partName ++ "."
                                ++ linkName ++ "." ++ end ++ " " ++ event
                                ++ case v of
                                    SimValue int [] -> " " ++ show int
                                    _ -> ""
                            return ()

            pair = do
                req <- withLabel "r" $ newNumericPlace width []
                ack <- withLabel "a" $ newBlackPlace []
                return (req, ack)
teakLink partName link
        | depth == 0 = withLabel linkName $ do
            inp <- withLabel "a" $ pair
            out <- withLabel "p" $ pair
            withLabel "L" $ linkTrans "L" inp out
            return (out, inp)
        | otherwise = withLabel linkName $ do
            inp <- withLabel "a" $ pair
            out <- withLabel "p" $ pair
            internalLinks <- mapM (\i -> withLabel ("i" ++ show i) $ pair) [0..depth]
            withLabel "A" $ linkTrans "A" inp (head internalLinks)
            withLabel "P" $ linkTrans "P" (last internalLinks) out
            mapM_ (\(i, inp, out) -> withLabel (show i) $ latch inp out) $ zip3
                [(1::Int)..] (init internalLinks) (tail internalLinks)
            return (out, inp)
        where
            HalfBuffer depth = nwLinkLatching link
            ref = refLink link
            width = nwLinkWidth link
            linkName = show ref

            linkTrans end (inpR, inpA) (outR, outA) = do
                reqPlace <- withLabel "r" $ newBlackPlace [token]
                ackPlace <- withLabel "a" $ newBlackPlace []
                withLabel "r" $ trans "R" [inpR, reqPlace] [outR, ackPlace]
                withLabel "a" $ trans "SPACER" [outA, ackPlace] [inpA, reqPlace]
                where
                    trans event inp out = newReportTrans inp out
                        [PNInput 0, PNLiteral token]
                        $ \[v, _] -> do
                            TimeState time <- simFlowGet TimeRef
                            FileState handle <- simFlowGet LogFileRef
                            lift $ hPutStrLn handle $ "#" ++ show time ++ " " ++ partName ++ "."
                                ++ linkName ++ "." ++ end ++ " " ++ event
                                ++ case v of
                                    SimValue int [] -> " " ++ show int
                                    _ -> ""
                            return ()

            pair = do
                req <- withLabel "r" $ newNumericPlace width []
                ack <- withLabel "a" $ newBlackPlace []
                return (req, ack)