----------------------------------------------------------------------------- -- | -- Module : ForSyDe.Deep.Backend.GraphML.Traverse -- Copyright : (c) ES Group, KTH/ICT/ES 2007-2013 -- License : BSD-style (see the file LICENSE) -- -- Maintainer : forsyde-dev@ict.kth.se -- Stability : experimental -- Portability : portable -- -- This module provides specialized Netlist traversing functions aimed at -- GraphML compilation. ----------------------------------------------------------------------------- module ForSyDe.Deep.Backend.GraphML.Traverse (writeGraphMLM, module ForSyDe.Deep.Backend.GraphML.Traverse.GraphMLM) where import ForSyDe.Deep.Backend.GraphML.Traverse.GraphMLM import ForSyDe.Deep.Backend.GraphML.FileIO import ForSyDe.Deep.Backend.GraphML.AST import ForSyDe.Deep.System.SysDef import ForSyDe.Deep.Netlist.Traverse import ForSyDe.Deep.Netlist import ForSyDe.Deep.OSharing import Data.Traversable.GenericZipWith import System.Directory import System.FilePath import Control.Monad.State -- | Internal GraphML-Monad version of 'ForSyDe.Backend.writeGraphML writeGraphMLM :: GraphMLM () writeGraphMLM = do -- create and change to systemName/graphml rootDir <- gets (sid.globalSysDef.global) let graphmlDir = rootDir "graphml" liftIO $ createDirectoryIfMissing True graphmlDir liftIO $ setCurrentDirectory graphmlDir -- write the local results for the first-level entity writeLocalGraphMLM -- if we are in recursive mode, also write the local results -- for the rest of the subsystems rec <- isRecursiveSet when rec $ do subs <- gets (subSys.globalSysDef.global) let writeSub s = withLocalST (initLocalST ((readURef.unPrimSysDef) s)) writeLocalGraphMLM mapM_ writeSub subs -- go back to the original directory liftIO $ setCurrentDirectory (".." "..") -- | Traverse the netlist and write the local results (i.e. system graphs) writeLocalGraphMLM :: GraphMLM () writeLocalGraphMLM = do lSysDefVal <- gets (currSysDef.local) let lSysDefId = sid lSysDefVal debugMsg $ "Compiling system definition `" ++ lSysDefId ++ "' ...\n" -- Obtain the output Nodes of the system -- Obtain the netlist of the system definition let nl = netlist lSysDefVal -- Traverse the netlist, and get the traversing results intOutsInfo <- traverseGraphML nl LocalTravResult nodes edges <- gets (localRes.local) -- For each output signal, we need a node and an edge between its -- intermediate signal and the final output signal declared in the system -- interface. let outIds = map fst (oIface lSysDefVal) outNodes = map (\id -> OutNode id (id ++ "_in")) outIds outEdges = zipWith (\(IntSignalInfo n pId) id -> GraphMLEdge n pId (OutNode id (id ++ "_in")) (id ++ "_in")) intOutsInfo outIds -- Generate the final Graph finalGraph = GraphMLGraph lSysDefId (nodes ++ outNodes) (edges ++ outEdges) -- and write it to disk yFiles <- genyFilesMarkup return () liftIO $ writeGraph yFiles finalGraph (lSysDefId ++ ".graphml") -- | Traverse the netlist of a System Definition, -- returning the (implicit) final traversing state and a list -- containing the 'IntSignalInfo' of each output of the system traverseGraphML :: Netlist [] -> GraphMLM [IntSignalInfo] traverseGraphML = traverseSEIO newGraphML defineGraphML -- | \'new\' traversing function for the GraphML backend newGraphML :: NlNode NlSignal -> GraphMLM [(NlNodeOut, IntSignalInfo)] newGraphML node = do let id = case node of InPort id -> id Proc pid _ -> pid -- node inputs insNode = zipWithTF (\_ n -> id ++ "_in" ++ show n) node [(1::Int)..] -- node outputs tagged with the edge label taggedOutsNode = zipWith (\t n -> (t, id ++ "_out" ++ show n)) (outTags node) [(1::Int)..] -- graphml node gMLNode = ProcNode insNode (map snd taggedOutsNode) return $ map (\(t,out) -> (t, IntSignalInfo gMLNode out)) taggedOutsNode -- | \'define\' traversing function for the GraphML backend defineGraphML :: [(NlNodeOut, IntSignalInfo)] -> NlNode IntSignalInfo -> GraphMLM () defineGraphML outs ins = do let id = case ins of InPort id -> id Proc pid _ -> pid -- Formal input signals of the proces formalInL = [id ++ "_in" ++ show n | n <- [(1::Int)..]] -- Generate the graph node -- Formal output ports of the process outPids = map (\(_, IntSignalInfo _ pid) -> pid) outs -- Substitute actual inputs by formal inputs in "ins" insFormal = zipWithTF (\_ n -> n) ins formalInL node = ProcNode insFormal outPids -- Generate the input edges of the node -- Actual input signals of the process actualInL = arguments ins inEdges = zipWith (\(IntSignalInfo aN aPid) fPid -> GraphMLEdge aN aPid node fPid ) actualInL formalInL mapM_ addEdge inEdges addNode node