Implement TLP output channels using a CIF helper process.
Input channels will be similar, but are stubbed out for now.
This commit is contained in:
parent
882d0c002a
commit
7eaab68f04
|
@ -118,7 +118,6 @@ cgenOps = GenOps {
|
||||||
genSpecMode = cgenSpecMode,
|
genSpecMode = cgenSpecMode,
|
||||||
genStop = cgenStop,
|
genStop = cgenStop,
|
||||||
genStructured = cgenStructured,
|
genStructured = cgenStructured,
|
||||||
genTLPChannel = cgenTLPChannel,
|
|
||||||
genTimerRead = cgenTimerRead,
|
genTimerRead = cgenTimerRead,
|
||||||
genTimerWait = cgenTimerWait,
|
genTimerWait = cgenTimerWait,
|
||||||
genTopLevel = cgenTopLevel,
|
genTopLevel = cgenTopLevel,
|
||||||
|
@ -141,42 +140,54 @@ cgenOps = GenOps {
|
||||||
generateC :: Handle -> A.AST -> PassM ()
|
generateC :: Handle -> A.AST -> PassM ()
|
||||||
generateC = generate cgenOps
|
generateC = generate cgenOps
|
||||||
|
|
||||||
cgenTLPChannel :: TLPChannel -> CGen ()
|
|
||||||
cgenTLPChannel TLPIn = tell ["in"]
|
|
||||||
cgenTLPChannel TLPOut = tell ["out"]
|
|
||||||
cgenTLPChannel TLPError = tell ["err"]
|
|
||||||
|
|
||||||
cgenTopLevel :: A.AST -> CGen ()
|
cgenTopLevel :: A.AST -> CGen ()
|
||||||
cgenTopLevel s
|
cgenTopLevel s
|
||||||
= do tell ["#include <tock_support_cif.h>\n"]
|
= do tell ["#include <tock_support_cif.h>\n"]
|
||||||
cs <- getCompState
|
cs <- getCompState
|
||||||
(tlpName, chans) <- tlpInterface
|
(tlpName, tlpChans) <- tlpInterface
|
||||||
|
chans <- sequence [csmLift $ makeNonce "tlp_channel" | _ <- tlpChans]
|
||||||
|
killChans <- sequence [csmLift $ makeNonce "tlp_channel_kill" | _ <- tlpChans]
|
||||||
|
workspaces <- sequence [csmLift $ makeNonce "tlp_channel_ws" | _ <- tlpChans]
|
||||||
|
|
||||||
sequence_ $ map (call genForwardDeclaration)
|
sequence_ $ map (call genForwardDeclaration)
|
||||||
(listify (const True :: A.Specification -> Bool) s)
|
(listify (const True :: A.Specification -> Bool) s)
|
||||||
|
|
||||||
sequence_ [do tell ["extern int " ++ nameString n ++ "_wrapper_stack_size;\n"]
|
sequence_ [do tell ["extern int ", nameString n, "_wrapper_stack_size;\n"]
|
||||||
cgenProcWrapper n
|
cgenProcWrapper n
|
||||||
| n <- tlpName : (Set.toList $ csParProcs cs)]
|
| n <- Set.toList $ csParProcs cs]
|
||||||
|
tell ["extern int "]
|
||||||
|
genName tlpName
|
||||||
|
tell ["_stack_size;\n"]
|
||||||
|
|
||||||
call genStructured s (\m _ -> tell ["\n#error Invalid top-level item: ", show m])
|
call genStructured s (\m _ -> tell ["\n#error Invalid top-level item: ", show m])
|
||||||
|
|
||||||
tell ["void tock_main (Workspace wptr) {\n\
|
tell ["void tock_main (Workspace wptr) {\n"]
|
||||||
\ Workspace tlp = ProcAlloc (wptr, ", show $ length chans, ", "]
|
sequence_ [do tell [" Channel ", c, ";\n"]
|
||||||
genName tlpName
|
tell [" ChanInit (wptr, &", c, ");\n"]
|
||||||
tell ["_wrapper_stack_size);\n"]
|
| c <- chans ++ killChans]
|
||||||
sequence_ [do tell [" ProcParam (wptr, tlp, " ++ show i ++ ", "]
|
tell ["\n"]
|
||||||
call genTLPChannel c
|
|
||||||
tell [");\n"]
|
funcs <- sequence [genTLPHandler tc c kc ws
|
||||||
| (i, (_, c)) <- zip [(0 :: Int)..] chans]
|
| (tc, c, kc, ws) <- zip4 tlpChans chans killChans workspaces]
|
||||||
|
|
||||||
|
tell [" LightProcBarrier bar;\n\
|
||||||
|
\ LightProcBarrierInit (wptr, &bar, ", show $ length chans, ");\n"]
|
||||||
|
|
||||||
|
sequence_ [tell [" LightProcStart (wptr, &bar, ", ws, ", (Process) ", func, ");\n"]
|
||||||
|
| (ws, func) <- zip workspaces funcs]
|
||||||
|
|
||||||
tell ["\n\
|
tell ["\n\
|
||||||
\ LightProcBarrier bar;\n\
|
\ "]
|
||||||
\ LightProcBarrierInit (wptr, &bar, 1);\n\
|
|
||||||
\ LightProcStart (wptr, &bar, tlp, (Process) "]
|
|
||||||
genName tlpName
|
genName tlpName
|
||||||
tell ["_wrapper);\n\
|
tell [" (wptr"]
|
||||||
\ LightProcBarrierWait (wptr, &bar);\n\
|
sequence_ [tell [", &", c] | c <- chans]
|
||||||
|
tell [");\n\
|
||||||
|
\\n\
|
||||||
|
\ bool b = true;\n"]
|
||||||
|
sequence_ [tell [" ChanOut (wptr, &", kc, ", &b, sizeof b);\n"]
|
||||||
|
| kc <- killChans]
|
||||||
|
|
||||||
|
tell [" LightProcBarrierWait (wptr, &bar);\n\
|
||||||
\ Shutdown (wptr);\n\
|
\ Shutdown (wptr);\n\
|
||||||
\}\n\
|
\}\n\
|
||||||
\\n\
|
\\n\
|
||||||
|
@ -184,12 +195,30 @@ cgenTopLevel s
|
||||||
\ if (!ccsp_init ())\n\
|
\ if (!ccsp_init ())\n\
|
||||||
\ return 1;\n\
|
\ return 1;\n\
|
||||||
\\n\
|
\\n\
|
||||||
\ Workspace p = ProcAllocInitial (0, 512);\n\
|
\ Workspace p = ProcAllocInitial (0, "]
|
||||||
|
genName tlpName
|
||||||
|
tell ["_stack_size + 512);\n\
|
||||||
\ ProcStartInitial (p, tock_main);\n\
|
\ ProcStartInitial (p, tock_main);\n\
|
||||||
\\n\
|
\\n\
|
||||||
\ // NOTREACHED\n\
|
\ // NOTREACHED\n\
|
||||||
\ return 0;\n\
|
\ return 0;\n\
|
||||||
\}\n"]
|
\}\n"]
|
||||||
|
where
|
||||||
|
-- | Allocate a TLP channel handler process, and return the function that
|
||||||
|
-- implements it.
|
||||||
|
genTLPHandler :: (A.Direction, TLPChannel) -> String -> String -> String -> CGen String
|
||||||
|
genTLPHandler (_, tc) c kc ws
|
||||||
|
= do tell [" Workspace ", ws, " = ProcAlloc (wptr, 3, 1024);\n\
|
||||||
|
\ ProcParam (wptr, ", ws, ", 0, &", c, ");\n\
|
||||||
|
\ ProcParam (wptr, ", ws, ", 1, &", kc, ");\n\
|
||||||
|
\ ProcParam (wptr, ", ws, ", 2, ", fp, ");\n\
|
||||||
|
\\n"]
|
||||||
|
return func
|
||||||
|
where
|
||||||
|
(fp, func) = case tc of
|
||||||
|
TLPIn -> ("stdin", "tock_tlp_input")
|
||||||
|
TLPOut -> ("stdout", "tock_tlp_output")
|
||||||
|
TLPError -> ("stderr", "tock_tlp_output")
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
--{{{ utilities
|
--{{{ utilities
|
||||||
|
|
|
@ -30,7 +30,6 @@ import Errors
|
||||||
import Metadata
|
import Metadata
|
||||||
import Pass
|
import Pass
|
||||||
import qualified Properties as Prop
|
import qualified Properties as Prop
|
||||||
import TLP
|
|
||||||
|
|
||||||
cCppCommonPreReq :: [Property]
|
cCppCommonPreReq :: [Property]
|
||||||
cCppCommonPreReq =
|
cCppCommonPreReq =
|
||||||
|
@ -166,7 +165,6 @@ data GenOps = GenOps {
|
||||||
-- | Generates a STOP process that uses the given Meta tag and message as its printed message.
|
-- | Generates a STOP process that uses the given Meta tag and message as its printed message.
|
||||||
genStop :: Meta -> String -> CGen (),
|
genStop :: Meta -> String -> CGen (),
|
||||||
genStructured :: forall a. Data a => A.Structured a -> (Meta -> a -> CGen ()) -> CGen (),
|
genStructured :: forall a. Data a => A.Structured a -> (Meta -> a -> CGen ()) -> CGen (),
|
||||||
genTLPChannel :: TLPChannel -> CGen (),
|
|
||||||
genTimerRead :: A.Variable -> A.Variable -> CGen (),
|
genTimerRead :: A.Variable -> A.Variable -> CGen (),
|
||||||
genTimerWait :: A.Expression -> CGen (),
|
genTimerWait :: A.Expression -> CGen (),
|
||||||
genTopLevel :: A.AST -> CGen (),
|
genTopLevel :: A.AST -> CGen (),
|
||||||
|
|
|
@ -146,11 +146,14 @@ cppgenTopLevel s
|
||||||
where
|
where
|
||||||
tlpChannel :: (A.Direction,TLPChannel) -> CGen()
|
tlpChannel :: (A.Direction,TLPChannel) -> CGen()
|
||||||
tlpChannel (dir,c) = case dir of
|
tlpChannel (dir,c) = case dir of
|
||||||
A.DirUnknown -> tell ["&"] >> chanName
|
A.DirUnknown -> tell ["&", chanName]
|
||||||
A.DirInput -> chanName >> tell [" .reader() "]
|
A.DirInput -> tell [chanName, ".reader() "]
|
||||||
A.DirOutput -> chanName >> tell [" .writer() "]
|
A.DirOutput -> tell [chanName, ".writer() "]
|
||||||
where
|
where
|
||||||
chanName = call genTLPChannel c
|
chanName = case c of
|
||||||
|
TLPIn -> "in"
|
||||||
|
TLPOut -> "out"
|
||||||
|
TLPError -> "err"
|
||||||
|
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define TOCK_SUPPORT_CIF_H
|
#define TOCK_SUPPORT_CIF_H
|
||||||
|
|
||||||
#include <cif.h>
|
#include <cif.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
//{{{ occam_stop
|
//{{{ occam_stop
|
||||||
#define occam_stop(pos, nargs, format, args...) \
|
#define occam_stop(pos, nargs, format, args...) \
|
||||||
|
@ -42,4 +43,40 @@ static inline void tock_init_chan_array (Channel *pointTo, Channel **pointFrom,
|
||||||
}
|
}
|
||||||
//}}}
|
//}}}
|
||||||
|
|
||||||
|
//{{{ top-level process interface
|
||||||
|
static void tock_tlp_input (Workspace wptr) occam_unused;
|
||||||
|
static void tock_tlp_input (Workspace wptr) {
|
||||||
|
Channel *out = ProcGetParam (wptr, 0, Channel *);
|
||||||
|
Channel *kill = ProcGetParam (wptr, 1, Channel *);
|
||||||
|
FILE *in = ProcGetParam (wptr, 2, FILE *);
|
||||||
|
|
||||||
|
// FIXME: Implement using killable BSC
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tock_tlp_output (Workspace wptr) occam_unused;
|
||||||
|
static void tock_tlp_output (Workspace wptr) {
|
||||||
|
Channel *in = ProcGetParam (wptr, 0, Channel *);
|
||||||
|
Channel *kill = ProcGetParam (wptr, 1, Channel *);
|
||||||
|
FILE *out = ProcGetParam (wptr, 2, FILE *);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
switch (ProcAlt (wptr, in, kill, NULL)) {
|
||||||
|
case 0: {
|
||||||
|
uint8_t ch;
|
||||||
|
ChanIn (wptr, in, &ch, sizeof ch);
|
||||||
|
ExternalCallN (fputc, 2, ch, out);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
bool b;
|
||||||
|
ChanIn (wptr, kill, &b, sizeof b);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//}}}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user