atom 1.0.8 → 1.0.9
raw patch · 9 files changed
+853/−373 lines, 9 filesdep +bimapdep +containersdep −uniplatedep ~mtlPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: bimap, containers
Dependencies removed: uniplate
Dependency ranges changed: mtl
API changes (from Hackage documentation)
- Language.Atom.Expressions: arrayIndices :: UE -> [(UA, UE)]
- Language.Atom.Expressions: nearestUVs :: UE -> [UV]
- Language.Atom.Expressions: ueUpstream :: UE -> [UE]
+ Language.Atom.UeMap: MUAcos :: !Hash -> UeElem
+ Language.Atom.UeMap: MUAcosh :: !Hash -> UeElem
+ Language.Atom.UeMap: MUAdd :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUAnd :: [Hash] -> UeElem
+ Language.Atom.UeMap: MUAsin :: !Hash -> UeElem
+ Language.Atom.UeMap: MUAsinh :: !Hash -> UeElem
+ Language.Atom.UeMap: MUAtan :: !Hash -> UeElem
+ Language.Atom.UeMap: MUAtanh :: !Hash -> UeElem
+ Language.Atom.UeMap: MUB2D :: !Hash -> UeElem
+ Language.Atom.UeMap: MUB2F :: !Hash -> UeElem
+ Language.Atom.UeMap: MUBWAnd :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUBWNot :: !Hash -> UeElem
+ Language.Atom.UeMap: MUBWOr :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUCast :: !Type -> !Hash -> UeElem
+ Language.Atom.UeMap: MUConst :: !Const -> UeElem
+ Language.Atom.UeMap: MUCos :: !Hash -> UeElem
+ Language.Atom.UeMap: MUCosh :: !Hash -> UeElem
+ Language.Atom.UeMap: MUD2B :: !Hash -> UeElem
+ Language.Atom.UeMap: MUDiv :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUEq :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUExp :: !Hash -> UeElem
+ Language.Atom.UeMap: MUF2B :: !Hash -> UeElem
+ Language.Atom.UeMap: MULog :: !Hash -> UeElem
+ Language.Atom.UeMap: MULt :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUMod :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUMul :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUMux :: !Hash -> !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUNot :: !Hash -> UeElem
+ Language.Atom.UeMap: MUPi :: UeElem
+ Language.Atom.UeMap: MUPow :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUShift :: !Hash -> !Int -> UeElem
+ Language.Atom.UeMap: MUSin :: !Hash -> UeElem
+ Language.Atom.UeMap: MUSinh :: !Hash -> UeElem
+ Language.Atom.UeMap: MUSqrt :: !Hash -> UeElem
+ Language.Atom.UeMap: MUSub :: !Hash -> !Hash -> UeElem
+ Language.Atom.UeMap: MUV :: Int -> String -> Const -> MUV
+ Language.Atom.UeMap: MUVArray :: UA -> Hash -> MUV
+ Language.Atom.UeMap: MUVExtern :: String -> Type -> MUV
+ Language.Atom.UeMap: MUVRef :: !MUV -> UeElem
+ Language.Atom.UeMap: arrayIndices :: Hash -> UeMap -> [(UA, Hash)]
+ Language.Atom.UeMap: data MUV
+ Language.Atom.UeMap: data UeElem
+ Language.Atom.UeMap: emptyMap :: UeMap
+ Language.Atom.UeMap: getUE :: Hash -> UeMap -> UeElem
+ Language.Atom.UeMap: instance Eq MUV
+ Language.Atom.UeMap: instance Eq UeElem
+ Language.Atom.UeMap: instance Ord MUV
+ Language.Atom.UeMap: instance Ord UeElem
+ Language.Atom.UeMap: instance Show MUV
+ Language.Atom.UeMap: instance Show UeElem
+ Language.Atom.UeMap: isMathHCall :: UeElem -> Bool
+ Language.Atom.UeMap: maybeUpdate :: UeElem -> UeState Hash
+ Language.Atom.UeMap: nearestUVs :: Hash -> UeMap -> [MUV]
+ Language.Atom.UeMap: newUE :: UE -> UeMap -> (Hash, UeMap)
+ Language.Atom.UeMap: newUV :: UV -> UeMap -> (MUV, UeMap)
+ Language.Atom.UeMap: recoverUE :: UeMap -> Hash -> UE
+ Language.Atom.UeMap: type Hash = Int
+ Language.Atom.UeMap: type UeMap = (Hash, Bimap Int UeElem)
+ Language.Atom.UeMap: type UeState a = State UeMap a
+ Language.Atom.UeMap: typeOf :: Hash -> UeMap -> Type
+ Language.Atom.UeMap: ueUpstream :: Hash -> UeMap -> [Hash]
- Language.Atom.Analysis: ruleComplexity :: Rule -> Int
+ Language.Atom.Analysis: ruleComplexity :: UeMap -> Rule -> Int
- Language.Atom.Analysis: topo :: [UE] -> [(UE, String)]
+ Language.Atom.Analysis: topo :: UeMap -> [Hash] -> [(Hash, String)]
- Language.Atom.Compile: type Schedule = [(Int, Int, [Rule])]
+ Language.Atom.Compile: type Schedule = (UeMap, [(Int, Int, [Rule])])
- Language.Atom.Elaboration: Assert :: Name -> UE -> UE -> Rule
+ Language.Atom.Elaboration: Assert :: Name -> Hash -> Hash -> Rule
- Language.Atom.Elaboration: AtomDB :: Int -> Name -> [Name] -> UE -> [AtomDB] -> Int -> Phase -> [(UV, UE)] -> [([String] -> String, [UE])] -> [(Name, UE)] -> [(Name, UE)] -> AtomDB
+ Language.Atom.Elaboration: AtomDB :: Int -> Name -> [Name] -> Hash -> [AtomDB] -> Int -> Phase -> [(MUV, Hash)] -> [([String] -> String, [Hash])] -> [(Name, Hash)] -> [(Name, Hash)] -> AtomDB
- Language.Atom.Elaboration: Cover :: Name -> UE -> UE -> Rule
+ Language.Atom.Elaboration: Cover :: Name -> Hash -> Hash -> Rule
- Language.Atom.Elaboration: Global :: Int -> Int -> Int -> [StateHierarchy] -> [(String, UE)] -> Int -> Phase -> Global
+ Language.Atom.Elaboration: Global :: Int -> Int -> Int -> [StateHierarchy] -> [(String, Hash)] -> Int -> Phase -> Global
- Language.Atom.Elaboration: Rule :: Int -> Name -> UE -> [(UV, UE)] -> [([String] -> String, [UE])] -> Int -> Phase -> Rule
+ Language.Atom.Elaboration: Rule :: Int -> Name -> Hash -> [(MUV, Hash)] -> [([String] -> String, [Hash])] -> Int -> Phase -> Rule
- Language.Atom.Elaboration: allUEs :: Rule -> [UE]
+ Language.Atom.Elaboration: allUEs :: Rule -> [Hash]
- Language.Atom.Elaboration: allUVs :: [Rule] -> UE -> [UV]
+ Language.Atom.Elaboration: allUVs :: UeMap -> [Rule] -> Hash -> [MUV]
- Language.Atom.Elaboration: atomActions :: AtomDB -> [([String] -> String, [UE])]
+ Language.Atom.Elaboration: atomActions :: AtomDB -> [([String] -> String, [Hash])]
- Language.Atom.Elaboration: atomAsserts :: AtomDB -> [(Name, UE)]
+ Language.Atom.Elaboration: atomAsserts :: AtomDB -> [(Name, Hash)]
- Language.Atom.Elaboration: atomAssigns :: AtomDB -> [(UV, UE)]
+ Language.Atom.Elaboration: atomAssigns :: AtomDB -> [(MUV, Hash)]
- Language.Atom.Elaboration: atomCovers :: AtomDB -> [(Name, UE)]
+ Language.Atom.Elaboration: atomCovers :: AtomDB -> [(Name, Hash)]
- Language.Atom.Elaboration: atomEnable :: AtomDB -> UE
+ Language.Atom.Elaboration: atomEnable :: AtomDB -> Hash
- Language.Atom.Elaboration: buildAtom :: Global -> Name -> Atom a -> IO (a, (Global, AtomDB))
+ Language.Atom.Elaboration: buildAtom :: UeMap -> Global -> Name -> Atom a -> IO (a, AtomSt)
- Language.Atom.Elaboration: elaborate :: Name -> Atom () -> IO (Maybe (StateHierarchy, [Rule], [Name], [Name], [(Name, Type)]))
+ Language.Atom.Elaboration: elaborate :: UeMap -> Name -> Atom () -> IO (Maybe (UeMap, (StateHierarchy, [Rule], [Name], [Name], [(Name, Type)])))
- Language.Atom.Elaboration: gProbes :: Global -> [(String, UE)]
+ Language.Atom.Elaboration: gProbes :: Global -> [(String, Hash)]
- Language.Atom.Elaboration: get :: Atom (Global, AtomDB)
+ Language.Atom.Elaboration: get :: Atom AtomSt
- Language.Atom.Elaboration: put :: (Global, AtomDB) -> Atom ()
+ Language.Atom.Elaboration: put :: AtomSt -> Atom ()
- Language.Atom.Elaboration: ruleActions :: Rule -> [([String] -> String, [UE])]
+ Language.Atom.Elaboration: ruleActions :: Rule -> [([String] -> String, [Hash])]
- Language.Atom.Elaboration: ruleAssert :: Rule -> UE
+ Language.Atom.Elaboration: ruleAssert :: Rule -> Hash
- Language.Atom.Elaboration: ruleAssigns :: Rule -> [(UV, UE)]
+ Language.Atom.Elaboration: ruleAssigns :: Rule -> [(MUV, Hash)]
- Language.Atom.Elaboration: ruleCover :: Rule -> UE
+ Language.Atom.Elaboration: ruleCover :: Rule -> Hash
- Language.Atom.Elaboration: ruleEnable :: Rule -> UE
+ Language.Atom.Elaboration: ruleEnable :: Rule -> Hash
- Language.Atom.Scheduling: schedule :: [Rule] -> Schedule
+ Language.Atom.Scheduling: schedule :: [Rule] -> UeMap -> Schedule
- Language.Atom.Scheduling: type Schedule = [(Int, Int, [Rule])]
+ Language.Atom.Scheduling: type Schedule = (UeMap, [(Int, Int, [Rule])])
Files
- Language/Atom/Analysis.hs +8/−7
- Language/Atom/Code.hs +205/−146
- Language/Atom/Compile.hs +12/−9
- Language/Atom/Elaboration.hs +175/−87
- Language/Atom/Expressions.hs +4/−64
- Language/Atom/Language.hs +49/−35
- Language/Atom/Scheduling.hs +19/−19
- Language/Atom/UeMap.hs +375/−0
- atom.cabal +6/−6
Language/Atom/Analysis.hs view
@@ -4,22 +4,23 @@ ) where import Language.Atom.Elaboration-import Language.Atom.Expressions+import Language.Atom.UeMap -- | Topologically sorts a list of expressions and subexpressions.-topo :: [UE] -> [(UE, String)]-topo ues = reverse ues'+topo :: UeMap -> [Hash] -> [(Hash, String)]+topo mp ues = reverse ues' where start = 0 (_, ues') = foldl collect (start, []) ues- collect :: (Int, [(UE, String)]) -> UE -> (Int, [(UE, String)])+ collect :: (Int, [(Hash, String)]) -> Hash -> (Int, [(Hash, String)]) collect (n, ues) ue | any ((== ue) . fst) ues = (n, ues)- collect (n, ues) ue = (n' + 1, (ue, e n') : ues') where (n', ues') = foldl collect (n, ues) $ ueUpstream ue+ collect (n, ues) ue = (n' + 1, (ue, e n') : ues') + where (n', ues') = foldl collect (n, ues) $ ueUpstream ue mp e :: Int -> String e i = "__" ++ show i -- | Number of UE's computed in rule.-ruleComplexity :: Rule -> Int-ruleComplexity = length . topo . allUEs+ruleComplexity :: UeMap -> Rule -> Int+ruleComplexity mp = length . (topo mp) . allUEs
Language/Atom/Code.hs view
@@ -13,13 +13,14 @@ import Data.Maybe import Text.Printf import Data.Word--import Data.Generics.Uniplate.Data+import qualified Data.Bimap as M import Language.Atom.Analysis import Language.Atom.Elaboration-import Language.Atom.Expressions-import Language.Atom.Scheduling+import Language.Atom.Expressions hiding (typeOf)+import qualified Language.Atom.Expressions as E+import Language.Atom.Scheduling +import Language.Atom.UeMap -- | C code configuration parameters. data Config = Config@@ -44,7 +45,7 @@ } -- | Data associated with sampling a hardware clock. For the clock to work--- correctly, you MUST assign @__global_clock@ the current time (accoring to +-- correctly, you MUST assign @__global_clock@ the current time (accoring to -- @clockName@) the first time you enter the main Atom-generated function -- calling your rules. data Clock = Clock@@ -54,7 +55,7 @@ -- @clockType clockName(void)@. , clockType :: Type -- ^ Clock type. Assumed to be one of Word8, -- Word16, Word32, or Word64. It is permissible- -- for the clock to rollover. + -- for the clock to rollover. , delta :: Integer -- ^ Number of ticks in a phase. Must be greater than 0. , delay :: String -- ^ C function to delay/sleep. The function is -- assumed to have the prototype @void@@ -114,87 +115,75 @@ Float -> "float" Double -> "double" -codeUE :: Config -> [(UE, String)] -> String -> (UE, String) -> String-codeUE config ues d (ue, n) = d ++ cType (typeOf ue) ++ " " ++ n ++ " = " ++ basic operands ++ ";\n"+codeUE :: UeMap -> Config -> [(Hash, String)] -> String -> (Hash, String) -> String+codeUE mp config ues d (ue, n) = + d ++ cType (typeOf ue mp) ++ " " ++ n ++ " = " ++ basic ++ ";\n" where- operands = map (fromJust . flip lookup ues) $ ueUpstream ue- basic :: [String] -> String- basic operands = concat $ case ue of- UVRef (UV _ n _) -> [cStateName config, ".", n]- UVRef (UVArray (UA _ n _) _) -> [cStateName config, ".", n, "[", a, "]"]- UVRef (UVArray (UAExtern n _) _) -> [n, "[", a, "]"]- UVRef (UVExtern n _) -> [n]- UCast _ _ -> ["(", cType (typeOf ue), ") ", a]- UConst c -> [showConst c]- UAdd _ _ -> [a, " + ", b]- USub _ _ -> [a, " - ", b]- UMul _ _ -> [a, " * ", b]- UDiv _ _ -> [a, " / ", b]- UMod _ _ -> [a, " % ", b]- UNot _ -> ["! ", a]- UAnd _ -> intersperse " && " operands- UBWNot _ -> ["~ ", a]- UBWAnd _ _ -> [a, " & ", b]- UBWOr _ _ -> [a, " | ", b]- UShift _ n -> (if n >= 0 then [a, " << ", show n] else [a, " >> ", show (negate n)])- UEq _ _ -> [a, " == ", b]- ULt _ _ -> [a, " < " , b]- UMux _ _ _ -> [a, " ? " , b, " : ", c]- UF2B _ -> ["*((", ct Word32, " *) &(", a, "))"]- UD2B _ -> ["*((", ct Word64, " *) &(", a, "))"]- UB2F _ -> ["*((", ct Float , " *) &(", a, "))"]- UB2D _ -> ["*((", ct Double, " *) &(", a, "))"]+ operands = map (fromJust . flip lookup ues) $ ueUpstream ue mp+ basic :: String+ basic = concat $ case getUE ue mp of+ MUVRef (MUV _ n _) -> [cStateName config, ".", n]+ MUVRef (MUVArray (UA _ n _) _) -> [cStateName config, ".", n, "[", a, "]"]+ MUVRef (MUVArray (UAExtern n _) _) -> [n, "[", a, "]"]+ MUVRef (MUVExtern n _) -> [n]+ MUCast _ _ -> ["(", cType (typeOf ue mp), ") ", a]+ MUConst c -> [showConst c]+ MUAdd _ _ -> [a, " + ", b]+ MUSub _ _ -> [a, " - ", b]+ MUMul _ _ -> [a, " * ", b]+ MUDiv _ _ -> [a, " / ", b]+ MUMod _ _ -> [a, " % ", b]+ MUNot _ -> ["! ", a]+ MUAnd _ -> intersperse " && " operands+ MUBWNot _ -> ["~ ", a]+ MUBWAnd _ _ -> [a, " & ", b]+ MUBWOr _ _ -> [a, " | ", b]+ MUShift _ n -> (if n >= 0 then [a, " << ", show n] else [a, " >> ", show (negate n)])+ MUEq _ _ -> [a, " == ", b]+ MULt _ _ -> [a, " < " , b]+ MUMux _ _ _ -> [a, " ? " , b, " : ", c]+ MUF2B _ -> ["*((", ct Word32, " *) &(", a, "))"]+ MUD2B _ -> ["*((", ct Word64, " *) &(", a, "))"]+ MUB2F _ -> ["*((", ct Float , " *) &(", a, "))"]+ MUB2D _ -> ["*((", ct Double, " *) &(", a, "))"] -- math.h:- UPi -> [ "M_PI" ]- UExp _ -> [ "exp", f, " ( ", a, " )"]- ULog _ -> [ "log", f, " ( ", a, " )"]- USqrt _ -> [ "sqrt", f, " ( ", a, " )"]- UPow _ _ -> [ "pow", f, " ( ", a, ", ", b, " )"]- USin _ -> [ "sin", f, " ( ", a, " )"]- UAsin _ -> [ "asin", f, " ( ", a, " )"]- UCos _ -> [ "cos", f, " ( ", a, " )"]- UAcos _ -> [ "acos", f, " ( ", a, " )"]- USinh _ -> [ "sinh", f, " ( ", a, " )"]- UCosh _ -> [ "cosh", f, " ( ", a, " )"]- UAsinh _ -> [ "asinh", f, " ( ", a, " )"]- UAcosh _ -> [ "acosh", f, " ( ", a, " )"]- UAtan _ -> [ "atan", f, " ( ", a, " )"]- UAtanh _ -> [ "atanh", f, " ( ", a, " )"]+ MUPi -> [ "M_PI" ]+ MUExp _ -> [ "exp", f, " ( ", a, " )"]+ MULog _ -> [ "log", f, " ( ", a, " )"]+ MUSqrt _ -> [ "sqrt", f, " ( ", a, " )"]+ MUPow _ _ -> [ "pow", f, " ( ", a, ", ", b, " )"]+ MUSin _ -> [ "sin", f, " ( ", a, " )"]+ MUAsin _ -> [ "asin", f, " ( ", a, " )"]+ MUCos _ -> [ "cos", f, " ( ", a, " )"]+ MUAcos _ -> [ "acos", f, " ( ", a, " )"]+ MUSinh _ -> [ "sinh", f, " ( ", a, " )"]+ MUCosh _ -> [ "cosh", f, " ( ", a, " )"]+ MUAsinh _ -> [ "asinh", f, " ( ", a, " )"]+ MUAcosh _ -> [ "acosh", f, " ( ", a, " )"]+ MUAtan _ -> [ "atan", f, " ( ", a, " )"]+ MUAtanh _ -> [ "atanh", f, " ( ", a, " )"] where ct = cType a = head operands b = operands !! 1 c = operands !! 2- f = case ( typeOf ue ) of+ f = case ( typeOf ue mp) of Float -> "f" Double -> "" _ -> error "unhandled float type" type RuleCoverage = [(Name, Int, Int)] -containMathHFunctions rules = any isMathHCall ues- where ues = rules >>= allUEs >>= universe- isMathHCall fc = case fc of- UPi -> True- UExp _ -> True- ULog _ -> True- USqrt _ -> True- UPow _ _ -> True- USin _ -> True- UAsin _ -> True- UCos _ -> True- UAcos _ -> True- USinh _ -> True- UCosh _ -> True- UAsinh _ -> True- UAcosh _ -> True- UAtan _ -> True- UAtanh _ -> True- _ -> False+-- containMathHFunctions :: [Rule] -> Bool+-- containMathHFunctions rules = +-- any math rules+-- where math rule = case rule of+-- Rule _ _ _ _ _ _ _ b -> b+-- _ -> False -writeC :: Name -> Config -> StateHierarchy -> [Rule] -> Schedule -> [Name] +writeC :: Name -> Config -> StateHierarchy -> [Rule] -> Schedule -> [Name] -> [Name] -> [(Name, Type)] -> IO RuleCoverage-writeC name config state rules schedule assertionNames coverageNames probeNames = do+writeC name config state rules (mp, schedule) assertionNames coverageNames probeNames = do writeFile (name ++ ".c") c writeFile (name ++ ".h") h return [ (ruleName r, div (ruleId r) 32, mod (ruleId r) 32) | r <- rules' ]@@ -203,22 +192,33 @@ c = unlines [ "#include <stdbool.h>" , "#include <stdint.h>"- , codeIf ( containMathHFunctions rules ) "#include <math.h>"+ , codeIf (M.fold (\_ e ans -> isMathHCall e || ans ) False (snd mp)) + "#include <math.h>" , "" , preCode , "" , "static " ++ globalType ++ " " ++ globalClk ++ " = 0;"- , codeIf (cRuleCoverage config) $ "static const " ++ cType Word32 + , ""+ , case hardwareClock config of+ Nothing -> ""+ Just _ -> "static " ++ globalType ++ " " ++ phaseStartTime ++ ";"+ , ""+ , codeIf (cRuleCoverage config) $ "static const " ++ cType Word32 ++ " __coverage_len = " ++ show covLen ++ ";"- , codeIf (cRuleCoverage config) $ "static " ++ cType Word32 - ++ " __coverage[" ++ show covLen ++ "] = {" + , codeIf (cRuleCoverage config) $ "static " ++ cType Word32+ ++ " __coverage[" ++ show covLen ++ "] = {" ++ (concat $ intersperse ", " $ replicate covLen "0") ++ "};"- , codeIf (cRuleCoverage config) $ "static " ++ cType Word32 ++ " __coverage_index = 0;"- , declState True $ StateHierarchy (cStateName config) [state]- , concatMap (codeRule config) rules'- , codeAssertionChecks config assertionNames coverageNames rules+ , codeIf (cRuleCoverage config) + ("static " ++ cType Word32 ++ " __coverage_index = 0;")+ , declState True (StateHierarchy (cStateName config) [state])+ , concatMap (codeRule mp config) rules'+ , codeAssertionChecks mp config assertionNames coverageNames rules , "void " ++ funcName ++ "() {" , swOrHwClock+ , unlines [ swOrHwClock+ , codePeriodPhases+ , " " ++ globalClk ++ " = " ++ globalClk ++ " + 1;"+ ] , "}" , "" , postCode@@ -226,32 +226,84 @@ codePeriodPhases = concatMap (codePeriodPhase config) schedule - swOrHwClock = + swOrHwClock = case hardwareClock config of- Nothing -> unlines [codePeriodPhases, " " ++ globalClk ++ " = " ++ globalClk ++ " + 1;"]- Just clkData -> unlines + Nothing -> ""+ Just clkData -> unlines [ ""- , codePeriodPhases- , " // In the following we sample the hardware clock, waiting for the next phase."- , "" , " " ++ declareConst phaseConst clkDelta- , " " ++ declareConst maxConst maxVal- , " " ++ globalType ++ " " ++ setTime+ , " " ++ declareConst maxConst maxVal+ , " static " ++ globalType ++ " " ++ lastPhaseStartTime ++ ";"+ , " static " ++ globalType ++ " " ++ lastTime ++ ";"+ , " static bool __first_call = true;"+ , " " ++ globalType ++ " " ++ currentTime ++ ";" , ""- , errCheck - , " " ++ setTime ++ " // Update the current time."- , " // Wait until the phase has expired. If the current time hasn't"- , " // overflowed, execute the first branch; otherwise, the second."- , " if (" ++ currentTime ++ " >= " ++ globalClk ++ ") {"- , " " ++ delayFn ++ "(" ++ phaseConst ++ " - (" ++ currentTime- ++ " - " ++ globalClk ++ "));" + , " /* save the current time */"+ , " " ++ setTime+ , ""+ , " /* initialize static variables on the first call */"+ , " if ( __first_call ) {"+ , " " ++ lastPhaseStartTime ++ " = " ++ phaseStartTime ++ ";"+ , " " ++ lastTime ++ " = " ++ currentTime ++ ";"+ , " __first_call = false;" , " }"- , " else {"- , " " ++ delayFn ++ "(" ++ phaseConst ++ " - (" ++ currentTime ++ " + (" - ++ maxConst ++ " - " ++ globalClk ++ ")));"+ , ""+ , " /* wait for the amount left for the phase start time to be reached,"+ , " handle roll-overs of the system timer and the phase start time */"+ , " if ( " ++ phaseStartTime ++ " >= " ++ lastPhaseStartTime ++ " ) {"+ , " /* phase start time did not roll over */"+ , " if ( " ++ currentTime ++ " >= " ++ lastTime ++ " ) {"+ , " /* system time and the phase start time did not roll over */"+ , " if ( " ++ phaseStartTime ++ " >= " ++ currentTime ++ " ) {"+ , " " ++ delayFn ++ " ( " ++ phaseStartTime ++ " - " ++ currentTime ++ " );"+ , " } else {"+ , " /* we are late */"+ , " " ++ errHandler+ , " }"+ , " } else {"+ , " /* system time rolled over, the start time of the"+ , " phase did not, i.e. we are not late if currentTime"+ , " is already in between lastPhaseStartTime and phaseStartTime */"+ , " if ( ( " ++ currentTime ++ " >= " ++ lastPhaseStartTime ++ " )"+ , " && ( " ++ phaseStartTime ++ " >= " ++ currentTime ++ " ) ) {"+ , " " ++ delayFn ++ " ( " ++ phaseStartTime ++ " - " ++ currentTime ++ " );"+ , " } else {"+ , " /* we are late */"+ , " " ++ errHandler+ , " }"+ , " }"+ , " } else {"+ , " /* phase start time rolled over */"+ , " if ( " ++ currentTime ++ " >= " ++ lastTime ++ " ) {"+ , " /* current time did not yet roll over */"+ , " if ( " ++ currentTime ++ " >= " ++ phaseStartTime ++ " ) {"+ , " " ++ delayFn ++ " ( ( " ++ maxConst+ ++ " - ( " ++ currentTime+ ++ " - " ++ phaseStartTime ++ " ) + 1 )" ++ " );"+ , " } else {"+ , " /* this should not happen, since " ++ phaseConst ++ " should be"+ , " smaller than " ++ maxConst ++ " and " ++ lastTime ++ " should"+ , " be smaller than or equal to " ++ currentTime ++ " */"+ , " " ++ errHandler+ , " }"+ , " } else {"+ , " /* current time and phase start time rolled over"+ , " equal to the first case */"+ , " if ( " ++ phaseStartTime ++ " >= " ++ currentTime ++ " ) {"+ , " " ++ delayFn ++ " ( " ++ phaseStartTime ++ " - " ++ currentTime ++ " );"+ , " } else {"+ , " /* we are late */"+ , " " ++ errHandler+ , " }"+ , " }" , " }" , ""- , " " ++ setGlobalClk clkData+ , ""+ , " /* update to the next phase start time */"+ , " " ++ lastPhaseStartTime ++ " = " ++ phaseStartTime ++ ";"+ , " " ++ phaseStartTime ++ " = " ++ phaseStartTime ++ " + "+ ++ phaseConst ++ ";"+ , " " ++ lastTime ++ " = " ++ currentTime ++ ";" ] where delayFn = delay clkData@@ -266,8 +318,9 @@ ++ " = " ++ showConst (constType c) ++ ";" setTime = currentTime ++ " = " ++ clockName clkData ++ "();" maxConst = "__max"- phaseConst = "__phase_len"+ phaseConst = "__phase_len" currentTime = "__curr_time"+ lastTime = "__last_time" clkDelta | d <= 0 = error $ "The delta " ++ show d@@ -283,23 +336,10 @@ | otherwise = d where d = delta clkData- errCheck =+ errHandler = case err clkData of Nothing -> ""- Just errF -> unlines- [ " // An error check for when the phase has already expired."- , " // The first disjunct is for when the current time has not overflowed,"- , " // and the second for when it has."- , " if ( ((" ++ currentTime ++ " >= " ++ globalClk ++ ") && (" - ++ currentTime ++ " - " ++ globalClk - ++ " > " ++ phaseConst ++ "))" - , " || (("- ++ currentTime ++ " < " ++ globalClk ++ ") && ((" ++ maxConst - ++ " - " ++ globalClk ++ ") + " ++ currentTime ++ " > " - ++ phaseConst ++ "))) {"- , " " ++ errF ++ "();"- , " }"- ]+ Just errF -> errF ++ " ();" constType :: Integer -> Const constType c = case clockType clkData of Word8 -> CWord8 (fromInteger c :: Word8)@@ -307,14 +347,14 @@ Word32 -> CWord32 (fromInteger c :: Word32) Word64 -> CWord64 (fromInteger c :: Word64) _ -> clkTypeErr- + h = unlines [ "#include <stdbool.h>" , "#include <stdint.h>" , "" , "void " ++ funcName ++ "();" , ""- , declState False $ StateHierarchy (cStateName config) [state]+ , declState False (StateHierarchy (cStateName config) [state]) ] globalType = cType (case hardwareClock config of@@ -325,7 +365,6 @@ Word32 -> Word32 Word64 -> Word64 _ -> clkTypeErr)- clkTypeErr :: a clkTypeErr = error "Clock type must be one of Word8, Word16, Word32, Word64." @@ -336,68 +375,88 @@ covLen = 1 + div (maximum $ map ruleId rules') 32 - setGlobalClk clkData = globalClk ++ " = " ++ clockName clkData ++ "();"+ phaseStartTime = "__phase_start_time"+ lastPhaseStartTime = "__last_phase_start_time" + codeIf :: Bool -> String -> String codeIf a b = if a then b else "" declState :: Bool -> StateHierarchy -> String-declState define a = (if define then "" else "extern ") ++ init (init (f1 "" a)) ++ (if define then " =\n" ++ f2 "" a else "") ++ ";\n"+declState define a = + (if define then "" else "extern ") ++ init (init (f1 "" a)) + ++ (if define then " =\n" ++ f2 "" a else "") ++ ";\n" where f1 i a = case a of- StateHierarchy name items -> i ++ "struct { /* " ++ name ++ " */\n" ++ concatMap (f1 (" " ++ i)) items ++ i ++ "} " ++ name ++ ";\n"- StateVariable name c -> i ++ cType (typeOf c) ++ " " ++ name ++ ";\n"- StateArray name c -> i ++ cType (typeOf $ head c) ++ " " ++ name ++ "[" ++ show (length c) ++ "];\n"+ StateHierarchy name items -> + i ++ "struct { /* " ++ name ++ " */\n" + ++ concatMap (f1 (" " ++ i)) items ++ i ++ "} " ++ name ++ ";\n"+ StateVariable name c -> i ++ cType (E.typeOf c) ++ " " ++ name ++ ";\n"+ StateArray name c -> + i ++ cType (E.typeOf $ head c) ++ " " ++ name ++ "[" ++ show (length c) ++ "];\n" f2 i a = case a of- StateHierarchy name items -> i ++ "{ /* " ++ name ++ " */\n" ++ intercalate ",\n" (map (f2 (" " ++ i)) items) ++ "\n" ++ i ++ "}"+ StateHierarchy name items -> + i ++ "{ /* " ++ name ++ " */\n" + ++ intercalate ",\n" (map (f2 (" " ++ i)) items) ++ "\n" ++ i ++ "}" StateVariable name c -> i ++ "/* " ++ name ++ " */ " ++ showConst c- StateArray name c -> i ++ "/* " ++ name ++ " */\n" ++ i ++ "{ " ++ intercalate ("\n" ++ i ++ ", ") (map showConst c) ++ "\n" ++ i ++ "}"+ StateArray name c -> + i ++ "/* " ++ name ++ " */\n" ++ i ++ "{ " + ++ intercalate ("\n" ++ i ++ ", ") (map showConst c) ++ "\n" ++ i ++ "}" -codeRule :: Config -> Rule -> String-codeRule config rule@(Rule _ _ _ _ _ _ _) =+codeRule :: UeMap -> Config -> Rule -> String+codeRule mp config rule@(Rule _ _ _ _ _ _ _) = "/* " ++ show rule ++ " */\n" ++ "static void __r" ++ show (ruleId rule) ++ "() {\n" ++- concatMap (codeUE config ues " ") ues +++ concatMap (codeUE mp config ues " ") ues ++ " if (" ++ id (ruleEnable rule) ++ ") {\n" ++ concatMap codeAction (ruleActions rule) ++- codeIf (cRuleCoverage config) (" __coverage[" ++ covWord ++ "] = __coverage[" ++ covWord ++ "] | (1 << " ++ covBit ++ ");\n") ++- " }\n" ++- concatMap codeAssign (ruleAssigns rule) ++- "}\n\n"+ codeIf (cRuleCoverage config) + ( " __coverage[" ++ covWord ++ "] = __coverage[" ++ covWord + ++ "] | (1 << " ++ covBit ++ ");\n") + ++ " }\n" ++ concatMap codeAssign (ruleAssigns rule) ++ "}\n\n" where- ues = topo $ allUEs rule+ ues = topo mp $ allUEs rule id ue = fromJust $ lookup ue ues - codeAction :: (([String] -> String), [UE]) -> String+ codeAction :: (([String] -> String), [Hash]) -> String codeAction (f, args) = " " ++ f (map id args) ++ ";\n" covWord = show $ div (ruleId rule) 32 covBit = show $ mod (ruleId rule) 32 - codeAssign :: (UV, UE) -> String+ codeAssign :: (MUV, Hash) -> String codeAssign (uv, ue) = concat [" ", lh, " = ", id ue, ";\n"] where lh = case uv of- UV _ n _ -> concat [cStateName config, ".", n]- UVArray (UA _ n _) index -> concat [cStateName config, ".", n, "[", id index, "]"]- UVArray (UAExtern n _) index -> concat [n, "[", id index, "]"]- UVExtern n _ -> n+ MUV _ n _ -> concat [cStateName config, ".", n]+ MUVArray (UA _ n _) index -> + concat [cStateName config, ".", n, "[", id index, "]"]+ MUVArray (UAExtern n _) index -> concat [n, "[", id index, "]"]+ MUVExtern n _ -> n -codeRule _ _ = ""+codeRule _ _ _ = "" globalClk :: String globalClk = "__global_clock" -codeAssertionChecks :: Config -> [Name] -> [Name] -> [Rule] -> String-codeAssertionChecks config assertionNames coverageNames rules = codeIf (cAssert config) $+codeAssertionChecks :: UeMap -> Config -> [Name] -> [Name] -> [Rule] -> String+codeAssertionChecks mp config assertionNames coverageNames rules = + codeIf (cAssert config) $ "static void __assertion_checks() {\n" ++- concatMap (codeUE config ues " ") ues ++- concat [ " if (" ++ id enable ++ ") " ++ cAssertName config ++ "(" ++ assertionId name ++ ", " ++ id check ++ ", " ++ globalClk ++ ");\n" | Assert name enable check <- rules ] ++- concat [ " if (" ++ id enable ++ ") " ++ cCoverName config ++ "(" ++ coverageId name ++ ", " ++ id check ++ ", " ++ globalClk ++ ");\n" | Cover name enable check <- rules ] +++ concatMap (codeUE mp config ues " ") ues +++ concat [ " if (" ++ id enable ++ ") " ++ cAssertName config + ++ "(" ++ assertionId name ++ ", " ++ id check ++ ", " + ++ globalClk ++ ");\n" + | Assert name enable check <- rules ] +++ concat [ " if (" ++ id enable ++ ") " ++ cCoverName config + ++ "(" ++ coverageId name ++ ", " ++ id check ++ ", " + ++ globalClk ++ ");\n" + | Cover name enable check <- rules ] ++ "}\n\n" where- ues = topo $ concat [ [a, b] | Assert _ a b <- rules ] ++ concat [ [a, b] | Cover _ a b <- rules ]+ ues = topo mp $ concat [ [a, b] | Assert _ a b <- rules ] + ++ concat [ [a, b] | Cover _ a b <- rules ] id ue = fromJust $ lookup ue ues assertionId :: Name -> String assertionId name = show $ fromJust $ elemIndex name assertionNames
Language/Atom/Compile.hs view
@@ -12,25 +12,28 @@ import Language.Atom.Code import Language.Atom.Scheduling import Language.Atom.Elaboration+import Language.Atom.UeMap (emptyMap) import Language.Atom.Language hiding (Atom) -- | Compiles an atom description to C.-compile :: Name -> Config -> Atom () -> IO (Schedule, RuleCoverage, [Name], [Name], [(Name, Type)])+compile :: Name -> Config -> Atom () + -> IO (Schedule, RuleCoverage, [Name], [Name], [(Name, Type)]) compile name config atom = do- r <- elaborate name atom- case r of+ res <- elaborate emptyMap name atom+ case res of Nothing -> putStrLn "ERROR: Design rule checks failed." >> exitWith (ExitFailure 1)- Just (state, rules, assertionNames, coverageNames, probeNames) -> do- let schedule' = schedule rules- ruleCoverage <- writeC name config state rules schedule' assertionNames coverageNames probeNames+ Just (st,(state, rules, assertionNames, coverageNames, probeNames)) -> do+ let schedule' = schedule rules st+ ruleCoverage <- writeC name config state rules schedule' assertionNames+ coverageNames probeNames when (isJust $ hardwareClock config) (putStrLn hwClockWarning) return (schedule', ruleCoverage, assertionNames, coverageNames, probeNames) hwClockWarning :: String hwClockWarning = unlines [ ""- , "*** Atom WARNING: you are configuring to use a harware clock. Please remember to assign" - , " the current time (accoring to your clockName field in Clock) the first time you"- , " enter the main Atom-generated function calling your rules."+ , "*** Atom WARNING: you are configuring to use a harware clock. Please remember to set"+ , " the \"__phase_start_time\" variable to the time at which the first phase should be"+ , " run before you enter the main Atom-generated function the first time." , "" ]
Language/Atom/Elaboration.hs view
@@ -1,5 +1,6 @@ module Language.Atom.Elaboration (+-- UeStateT -- * Atom monad and container. Atom , AtomDB (..)@@ -28,8 +29,12 @@ import Data.Function (on) import Data.List import Data.Char-import Language.Atom.Expressions+import qualified Control.Monad.State.Strict as S +import Language.Atom.Expressions hiding (typeOf)+import Language.Atom.UeMap++ type UID = Int -- | A name.@@ -46,7 +51,7 @@ , gVarId :: Int , gArrayId :: Int , gState :: [StateHierarchy]- , gProbes :: [(String, UE)]+ , gProbes :: [(String, Hash)] , gPeriod :: Int , gPhase :: Phase }@@ -55,35 +60,36 @@ { atomId :: Int , atomName :: Name , atomNames :: [Name] -- Names used at this level.- , atomEnable :: UE -- Enabling condition.+ , atomEnable :: Hash -- Enabling condition. , atomSubs :: [AtomDB] -- Sub atoms. , atomPeriod :: Int , atomPhase :: Phase- , atomAssigns :: [(UV, UE)]- , atomActions :: [([String] -> String, [UE])]- , atomAsserts :: [(Name, UE)]- , atomCovers :: [(Name, UE)]+ , atomAssigns :: [(MUV, Hash)]+ , atomActions :: [([String] -> String, [Hash])]+ , atomAsserts :: [(Name, Hash)]+ , atomCovers :: [(Name, Hash)] } data Rule = Rule { ruleId :: Int , ruleName :: Name- , ruleEnable :: UE- , ruleAssigns :: [(UV, UE)]- , ruleActions :: [([String] -> String, [UE])]+ , ruleEnable :: Hash+ , ruleAssigns :: [(MUV, Hash)]+ , ruleActions :: [([String] -> String, [Hash])] , rulePeriod :: Int , rulePhase :: Phase+-- , mathH :: Bool -- Contains a math.h call? } | Assert { ruleName :: Name- , ruleEnable :: UE- , ruleAssert :: UE+ , ruleEnable :: Hash+ , ruleAssert :: Hash } | Cover { ruleName :: Name- , ruleEnable :: UE- , ruleCover :: UE+ , ruleEnable :: Hash+ , ruleCover :: Hash } data StateHierarchy@@ -96,57 +102,109 @@ instance Ord AtomDB where compare a b = compare (atomId a) (atomId b) instance Show Rule where show = ruleName -elaborateRules:: UE -> AtomDB -> [Rule]-elaborateRules parentEnable atom = if isRule then rule : rules else rules+elaborateRules:: Hash -> AtomDB -> UeState [Rule]+elaborateRules parentEnable atom = + if isRule + then do r <- rule+ rs <- rules + return $ r : rs + else rules where isRule = not $ null (atomAssigns atom) && null (atomActions atom)- enable = uand parentEnable $ atomEnable atom- rule = Rule- { ruleId = atomId atom- , ruleName = atomName atom- , ruleEnable = enable- , ruleAssigns = map enableAssign $ atomAssigns atom- , ruleActions = atomActions atom- , rulePeriod = atomPeriod atom- , rulePhase = atomPhase atom- }- assert (name, ue) = Assert- { ruleName = name- , ruleEnable = enable- , ruleAssert = ue- }- cover (name, ue) = Cover- { ruleName = name- , ruleEnable = enable- , ruleCover = ue- }- rules = map assert (atomAsserts atom) ++ map cover (atomCovers atom) ++ concatMap (elaborateRules enable) (atomSubs atom)- enableAssign :: (UV, UE) -> (UV, UE)- enableAssign (uv, ue) = (uv, umux enable ue $ UVRef uv)+ enable :: UeState Hash+ enable = do+ st <- S.get+ let (h,st') = newUE (uand (recoverUE st parentEnable)+ (recoverUE st (atomEnable atom)))+ st+ S.put st'+ return h+ rule :: UeState Rule+ rule = do + h <- enable + assigns <- S.foldM (\prs pr -> do pr' <- enableAssign pr + return $ pr' : prs) [] + (atomAssigns atom)+-- st <- S.get+ return $ Rule+ { ruleId = atomId atom+ , ruleName = atomName atom+ , ruleEnable = h+ , ruleAssigns = assigns+ , ruleActions = atomActions atom+ , rulePeriod = atomPeriod atom+ , rulePhase = atomPhase atom+ }+ assert :: (Name, Hash) -> UeState Rule+ assert (name, ue) = do + h <- enable + return $ Assert+ { ruleName = name+ , ruleEnable = h+ , ruleAssert = ue+ }+ cover :: (Name, Hash) -> UeState Rule+ cover (name, ue) = do + h <- enable + return $ Cover+ { ruleName = name+ , ruleEnable = h+ , ruleCover = ue+ }+ rules :: UeState [Rule]+ rules = do+ asserts <- S.foldM (\rs e -> do r <- assert e+ return $ r:rs+ ) [] (atomAsserts atom) + covers <- S.foldM (\rs e -> do r <- cover e+ return $ r:rs+ ) [] (atomCovers atom) + rules' <- S.foldM (\rs db -> do en <- enable+ r <- elaborateRules en db+ return $ r:rs+ ) [] (atomSubs atom)+ return $ asserts ++ covers ++ concat rules'+ enableAssign :: (MUV, Hash) -> UeState (MUV, Hash)+ enableAssign (uv, ue) = do + e <- enable+ h <- maybeUpdate (MUVRef uv)+ st <- S.get + let (h',st') = newUE (umux (recoverUE st e) + (recoverUE st ue) + (recoverUE st h))+ st+ S.put st'+ return (uv, h') reIdRules :: Int -> [Rule] -> [Rule] reIdRules _ [] = [] reIdRules i (a:b) = case a of Rule _ _ _ _ _ _ _ -> a { ruleId = i } : reIdRules (i + 1) b- _ -> a : reIdRules i b+ _ -> a : reIdRules i b -buildAtom :: Global -> Name -> Atom a -> IO (a, (Global, AtomDB))-buildAtom g name (Atom f) = f (g { gRuleId = gRuleId g + 1 }, AtomDB- { atomId = gRuleId g- , atomName = name- , atomNames = []- , atomEnable = ubool True- , atomSubs = []- , atomPeriod = gPeriod g- , atomPhase = gPhase g- , atomAssigns = []- , atomActions = []- , atomAsserts = []- , atomCovers = []- })+buildAtom :: UeMap -> Global -> Name -> Atom a -> IO (a, AtomSt)+buildAtom st g name (Atom f) = do+ let (h,st') = newUE (ubool True) st+-- S.put st' + f (st', (g { gRuleId = gRuleId g + 1 }, AtomDB+ { atomId = gRuleId g+ , atomName = name+ , atomNames = []+ , atomEnable = h + , atomSubs = []+ , atomPeriod = gPeriod g+ , atomPhase = gPhase g+ , atomAssigns = []+ , atomActions = []+ , atomAsserts = []+ , atomCovers = []+ }))+-- S.return db +type AtomSt = (UeMap, (Global, AtomDB))+ -- | The Atom monad holds variable and rule declarations.-data Atom a = Atom ((Global, AtomDB) -> IO (a, (Global, AtomDB)))+data Atom a = Atom (AtomSt -> IO (a, AtomSt)) instance Monad Atom where return a = Atom (\ s -> return (a, s))@@ -164,35 +222,58 @@ a <- io return (a, s) -get :: Atom (Global, AtomDB)+get :: Atom AtomSt get = Atom (\ s -> return (s, s)) -put :: (Global, AtomDB) -> Atom ()+put :: AtomSt -> Atom () put s = Atom (\ _ -> return ((), s)) -- | A Relation is used for relative performance constraints between 'Action's. -- data Relation = Higher UID | Lower UID deriving (Show, Eq) +-- XXX elaborate is a bit hacky since we're threading state through this+-- function, but I don't want to go change all the UeState monads to UeStateT+-- monads. -- | Given a top level name and design, elaborates design and returns a design database.-elaborate :: Name -> Atom () -> IO (Maybe (StateHierarchy, [Rule], [Name], [Name], [(Name, Type)]))-elaborate name atom = do- (_, (g, atomDB)) <- buildAtom Global { gRuleId = 0, gVarId = 0, gArrayId = 0, gState = [], gProbes = [], gPeriod = 1, gPhase = MinPhase 0 } name atom- let rules = reIdRules 0 $ elaborateRules (ubool True) atomDB+elaborate :: UeMap -> Name -> Atom () + -> IO (Maybe ( UeMap+ , ( StateHierarchy, [Rule], [Name], [Name]+ , [(Name, Type)])+ ))+elaborate st name atom = do+ (_, (st0, (g, atomDB))) <- buildAtom st Global { gRuleId = 0+ , gVarId = 0+ , gArrayId = 0+ , gState = []+ , gProbes = []+ , gPeriod = 1+ , gPhase = MinPhase 0 + } + name atom + let (h,st1) = newUE (ubool True) st0+ (getRules,st2) = S.runState (elaborateRules h atomDB) st1+ rules = reIdRules 0 (reverse getRules) coverageNames = [ name | Cover name _ _ <- rules ] assertionNames = [ name | Assert name _ _ <- rules ]- probeNames = [ (n, typeOf a) | (n, a) <- gProbes g ]- if (null rules)+ probeNames = [ (n, typeOf a st2) | (n, a) <- gProbes g ]+ if (null rules) then do putStrLn "ERROR: Design contains no rules. Nothing to do." return Nothing else do- mapM_ checkEnable rules+ mapM_ (checkEnable st2) rules ok <- mapM checkAssignConflicts rules- return (if and ok then Just (trimState $ StateHierarchy name $ gState g, rules, assertionNames, coverageNames, probeNames) else Nothing)+ return (if and ok + then Just ( st2+ , (trimState $ StateHierarchy name + $ gState g, rules, assertionNames+ , coverageNames, probeNames))+ else Nothing) trimState :: StateHierarchy -> StateHierarchy trimState a = case a of- StateHierarchy name items -> StateHierarchy name $ filter f $ map trimState items+ StateHierarchy name items -> + StateHierarchy name $ filter f $ map trimState items a -> a where f (StateHierarchy _ []) = False@@ -200,16 +281,21 @@ -- | Checks that a rule will not be trivially disabled.-checkEnable :: Rule -> IO ()-checkEnable rule | ruleEnable rule == ubool False = putStrLn $ "WARNING: Rule will never execute: " ++ show rule- | otherwise = return ()+checkEnable :: UeMap -> Rule -> IO ()+checkEnable st rule + | ruleEnable rule == (fst $ newUE (ubool False) st) = + putStrLn $ "WARNING: Rule will never execute: " ++ show rule+ | otherwise = return () --- | Check that a variable is assigned more than once in a rule. Will eventually be replaced consistent assignment checking.+-- | Check that a variable is assigned more than once in a rule. Will+-- eventually be replaced consistent assignment checking. checkAssignConflicts :: Rule -> IO Bool-checkAssignConflicts rule@(Rule _ _ _ _ _ _ _) =+checkAssignConflicts rule@(Rule _ _ _ _ _ _ _) = if length vars /= length vars' then do- putStrLn $ "ERROR: Rule " ++ show rule ++ " contains multiple assignments to the same variable(s)."+ putStrLn $ "ERROR: Rule " + ++ show rule + ++ " contains multiple assignments to the same variable(s)." return False else do return True@@ -246,10 +332,10 @@ var :: Expr a => Name -> a -> Atom (V a) var name init = do name' <- addName name- (g, atom) <- get+ (st, (g, atom)) <- get let uv = UV (gVarId g) name' c c = constant init- put (g { gVarId = gVarId g + 1, gState = gState g ++ [StateVariable name c] }, atom)+ put (st, (g { gVarId = gVarId g + 1, gState = gState g ++ [StateVariable name c] }, atom)) return $ V uv -- | Generic external variable declaration.@@ -261,10 +347,10 @@ array name [] = error $ "ERROR: arrays can not be empty: " ++ name array name init = do name' <- addName name- (g, atom) <- get+ (st, (g, atom)) <- get let ua = UA (gArrayId g) name' c c = map constant init- put (g { gArrayId = gArrayId g + 1, gState = gState g ++ [StateArray name c] }, atom)+ put (st, (g { gArrayId = gArrayId g + 1, gState = gState g ++ [StateArray name c] }, atom)) return $ A ua -- | Generic external array declaration.@@ -273,12 +359,12 @@ addName :: Name -> Atom Name addName name = do- (g, atom) <- get+ (st, (g, atom)) <- get checkName name if elem name (atomNames atom) then error $ "ERROR: Name \"" ++ name ++ "\" not unique in " ++ show atom ++ "." else do- put (g, atom { atomNames = name : atomNames atom })+ put (st, (g, atom { atomNames = name : atomNames atom })) return $ atomName atom ++ "." ++ name -- still accepts some misformed names@@ -319,13 +405,13 @@ -} -- | All the variables that directly and indirectly control the value of an expression.-allUVs :: [Rule] -> UE -> [UV]-allUVs rules ue = fixedpoint next $ nearestUVs ue+allUVs :: UeMap -> [Rule] -> Hash -> [MUV]+allUVs st rules ue = fixedpoint next $ nearestUVs ue st where assigns = concat [ ruleAssigns r | r@(Rule _ _ _ _ _ _ _) <- rules ]- previousUVs :: UV -> [UV]- previousUVs uv = concat [ nearestUVs ue | (uv', ue) <- assigns, uv == uv' ]- next :: [UV] -> [UV]+ previousUVs :: MUV -> [MUV]+ previousUVs uv = concat [ nearestUVs ue st | (uv', ue) <- assigns, uv == uv' ]+ next :: [MUV] -> [MUV] next uvs = sort $ nub $ uvs ++ concatMap previousUVs uvs fixedpoint :: Eq a => (a -> a) -> a -> a@@ -333,14 +419,16 @@ | otherwise = fixedpoint f $ f a -- | All primary expressions used in a rule.-allUEs :: Rule -> [UE]+allUEs :: Rule -> [Hash] allUEs rule = ruleEnable rule : ues where- index :: UV -> [UE]- index (UVArray _ ue) = [ue]+ index :: MUV -> [Hash]+ index (MUVArray _ ue) = [ue] index _ = [] ues = case rule of- Rule _ _ _ _ _ _ _ -> concat [ ue : index uv | (uv, ue) <- ruleAssigns rule ] ++ concat (snd (unzip (ruleActions rule)))+ Rule _ _ _ _ _ _ _ -> + concat [ ue : index uv | (uv, ue) <- ruleAssigns rule ] + ++ concat (snd (unzip (ruleActions rule))) Assert _ _ a -> [a] Cover _ _ a -> [a]
Language/Atom/Expressions.hs view
@@ -19,9 +19,10 @@ , bytes , ue , uv- , ueUpstream- , nearestUVs- , arrayIndices+-- , ueUpstream+-- , isMathHCall+-- , nearestUVs+-- , arrayIndices , NumE , IntegralE , FloatingE@@ -708,67 +709,6 @@ (!.) :: (Expr a, IntegralE b) => A a -> E b -> E a a !. i = value $ a ! i ----- | The list of UEs adjacent upstream of a UE.-ueUpstream :: UE -> [UE]-ueUpstream t = case t of- UVRef (UV _ _ _) -> []- UVRef (UVArray _ a) -> [a]- UVRef (UVExtern _ _) -> []- UCast _ a -> [a]- UConst _ -> []- UAdd a b -> [a, b]- USub a b -> [a, b]- UMul a b -> [a, b]- UDiv a b -> [a, b]- UMod a b -> [a, b]- UNot a -> [a]- UAnd a -> a- UBWNot a -> [a]- UBWAnd a b -> [a, b]- UBWOr a b -> [a, b]- UShift a _ -> [a]- UEq a b -> [a, b]- ULt a b -> [a, b]- UMux a b c -> [a, b, c]- UF2B a -> [a]- UD2B a -> [a]- UB2F a -> [a]- UB2D a -> [a]--- math.h:- UPi -> []- UExp a -> [a]- ULog a -> [a]- USqrt a -> [a]- UPow a b -> [a, b]- USin a -> [a]- UAsin a -> [a]- UCos a -> [a]- UAcos a -> [a]- USinh a -> [a]- UCosh a -> [a]- UAsinh a -> [a]- UAcosh a -> [a]- UAtan a -> [a]- UAtanh a -> [a]---- | The list of all UVs that directly control the value of an expression.-nearestUVs :: UE -> [UV]-nearestUVs = nub . f- where- f :: UE -> [UV]- f (UVRef uv@(UVArray _ i)) = [uv] ++ f i- f (UVRef uv) = [uv]- f ue = concatMap f $ ueUpstream ue---- | All array indexing subexpressions.-arrayIndices :: UE -> [(UA, UE)]-arrayIndices = nub . f- where- f :: UE -> [(UA, UE)]- f (UVRef (UVArray ua ue)) = (ua, ue) : f ue- f ue = concatMap f $ ueUpstream ue -- | Converts an typed expression (E a) to an untyped expression (UE). ue :: Expr a => E a -> UE
Language/Atom/Language.hs view
@@ -66,10 +66,12 @@ import Control.Monad.Trans import Data.Int import Data.Word+import Data.List (foldl') import Language.Atom.Elaboration hiding (Atom) import qualified Language.Atom.Elaboration as E import Language.Atom.Expressions+import Language.Atom.UeMap hiding (typeOf) infixr 1 <== @@ -80,9 +82,10 @@ atom :: Name -> Atom a -> Atom a atom name design = do name' <- addName name- (g1, parent) <- get- (a, (g2, child)) <- liftIO $ buildAtom g1 { gState = [] } name' design- put (g2 { gState = gState g1 ++ [StateHierarchy name $ gState g2] }, parent { atomSubs = atomSubs parent ++ [child] })+ (st1, (g1, parent)) <- get+ (a, (st2, (g2, child))) <- liftIO $ buildAtom st1 g1 { gState = [] } name' design+ put (st2, ( g2 { gState = gState g1 ++ [StateHierarchy name $ gState g2] }+ , parent { atomSubs = atomSubs parent ++ [child] })) return a -- | Defines the period of execution of sub rules as a factor of the base rate of the system.@@ -92,30 +95,30 @@ period :: Int -> Atom a -> Atom a period n _ | n <= 0 = error "ERROR: Execution period must be greater than 0." period n atom = do- (g, a) <- get- put (g { gPeriod = n }, a)+ (st, (g, a)) <- get+ put (st, (g { gPeriod = n }, a)) r <- atom- (g', a) <- get- put (g' { gPeriod = gPeriod g }, a)+ (st', (g', a)) <- get+ put (st', (g' { gPeriod = gPeriod g }, a)) return r -- | Returns the execution period of the current scope. getPeriod :: Atom Int getPeriod = do- (g, _) <- get+ (_, (g, _)) <- get return $ gPeriod g phase' :: (Int -> Phase) -> Int -> Atom a -> Atom a phase' _ n _ | n < 0 = error $ "ERROR: phase " ++ show n ++ " must be at least 0." phase' phType n atom = do- (g, a) <- get+ (st, (g, a)) <- get if (n >= gPeriod g) then error $ "ERROR: phase " ++ show n ++ " must be less than the current period " ++ show (gPeriod g) ++ "."- else do put (g { gPhase = phType n }, a)+ else do put (st, (g { gPhase = phType n }, a)) r <- atom- (g', a) <- get- put (g' { gPhase = gPhase g }, a)+ (st', (g', a)) <- get+ put (st', (g' { gPhase = gPhase g }, a)) return r -- XXX -- else do put (g { gPhase = n }, a)@@ -138,7 +141,7 @@ -- | Returns the phase of the current scope. getPhase :: Atom Int getPhase = do- (g, _) <- get+ (_, (g, _)) <- get return $ case gPhase g of MinPhase ph -> ph ExactPhase ph -> ph@@ -146,7 +149,7 @@ -- | Returns the current atom hierarchical path. path :: Atom String path = do- (_, atom) <- get+ (_, (_, atom)) <- get return $ atomName atom -- | Local boolean variable declaration.@@ -240,8 +243,11 @@ -- | Declares an action. action :: ([String] -> String) -> [UE] -> Atom () action f ues = do- (g, a) <- get- put (g, a { atomActions = atomActions a ++ [(f, ues)] })+ (st, (g, a)) <- get+ let (st', hashes) = foldl' (\(accSt,hs) ue -> let (h,accSt') = newUE ue accSt in+ (accSt',h:hs))+ (st,[]) ues+ put (st', (g, a { atomActions = atomActions a ++ [(f, hashes)] })) -- | Calls an external C function of type 'void f(void)'. call :: Name -> Atom ()@@ -250,18 +256,19 @@ -- | Declares a probe. probe :: Expr a => Name -> E a -> Atom () probe name a = do- (g, atom) <- get+ (st, (g, atom)) <- get+ let (h,st') = newUE (ue a) st if any (\ (n, _) -> name == n) $ gProbes g then error $ "ERROR: Duplicated probe name: " ++ name- else put (g { gProbes = (name, ue a) : gProbes g }, atom)-+ else put (st', (g { gProbes = (name, h) : gProbes g }, atom)) -- | Fetches all declared probes to current design point. probes :: Atom [(String, UE)] probes = do- (g, _) <- get- return $ gProbes g-+ (st, (g, _)) <- get+ let (strs,hs) = unzip (gProbes g)+ let g' = zip strs (map (recoverUE st) hs)+ return g' -- | Increments a NumE 'V'. incr :: (Assign a, NumE a) => V a -> Atom ()@@ -276,8 +283,10 @@ -- | Assign an 'E' to a 'V'. (<==) :: V a -> E a -> Atom () v <== e = do- (g, atom) <- get- put (g, atom { atomAssigns = (uv v, ue e) : atomAssigns atom })+ (st, (g, atom)) <- get+ let (h,st0) = newUE (ue e) st+ let (muv,st1) = newUV (uv v) st0+ put (st1, (g, atom { atomAssigns = (muv, h) : atomAssigns atom })) instance Assign Bool instance Assign Int8@@ -292,12 +301,14 @@ instance Assign Double -- | Adds an enabling condition to an atom subtree of rules.--- This condition must be true before any rules in hierarchy--- are allowed to execute.+-- This condition must be true before any rules in hierarchy+-- are allowed to execute. cond :: E Bool -> Atom () cond c = do- (g, atom) <- get- put (g, atom { atomEnable = uand (atomEnable atom) (ue c) })+ (st, (g, atom)) <- get+ let ae = recoverUE st (atomEnable atom)+ let (h,st') = newUE (uand ae (ue c)) st+ put (st', (g, atom { atomEnable = h})) -- | Reference to the 64-bit free running clock. clock :: E Word64@@ -310,15 +321,17 @@ return (value $ word32' "__coverage_index", value $ word32' "__coverage[__coverage_index]") --- | An assertions checks that an E Bool is true. Assertions are checked between the execution of every rule.--- Parent enabling conditions can disable assertions, but period and phase constraints do not.--- Assertion names should be globally unique.+-- | An assertions checks that an E Bool is true. Assertions are checked+-- between the execution of every rule. Parent enabling conditions can+-- disable assertions, but period and phase constraints do not. Assertion+-- names should be globally unique. assert :: Name -> E Bool -> Atom () assert name check = do- (g, atom) <- get+ (st, (g, atom)) <- get let names = fst $ unzip $ atomAsserts atom when (elem name names) (liftIO $ putStrLn $ "WARNING: Assertion name already used: " ++ name)- put (g, atom { atomAsserts = (name, ue check) : atomAsserts atom })+ let (chk,st') = newUE (ue check) st+ put (st', (g, atom { atomAsserts = (name, chk) : atomAsserts atom })) -- | Implication assertions. Creates an implicit coverage point for the precondition. assertImply :: Name -> E Bool -> E Bool -> Atom ()@@ -331,8 +344,9 @@ -- Coverage names should be globally unique. cover :: Name -> E Bool -> Atom () cover name check = do- (g, atom) <- get+ (st, (g, atom)) <- get let names = fst $ unzip $ atomCovers atom when (elem name names) (liftIO $ putStrLn $ "WARNING: Coverage name already used: " ++ name)- put (g, atom { atomCovers = (name, ue check) : atomCovers atom })+ let (chk,st') = newUE (ue check) st+ put (st', (g, atom { atomCovers = (name, chk) : atomCovers atom }))
Language/Atom/Scheduling.hs view
@@ -5,15 +5,17 @@ , reportSchedule ) where +import Text.Printf import Data.List+ import Language.Atom.Analysis import Language.Atom.Elaboration-import Text.Printf+import Language.Atom.UeMap -type Schedule = [(Int, Int, [Rule])] -- (period, phase, rules)+type Schedule = (UeMap, [(Int, Int, [Rule])]) -- (period, phase, rules) -schedule :: [Rule] -> Schedule-schedule rules' = concatMap spread periods+schedule :: [Rule] -> UeMap -> Schedule+schedule rules' mp = (mp, concatMap spread periods) where rules = [ r | r@(Rule _ _ _ _ _ _ _) <- rules' ] @@ -42,7 +44,7 @@ -- C. The sum of the difference between between each rule's offset and it's -- scheduled phase is the minimum of all schedules satisfying (A) and (B). - spread :: (Int, [Rule]) -> Schedule+ spread :: (Int, [Rule]) -> [(Int, Int, [Rule])] spread (period, rules) = placeRules (placeExactRules (replicate period []) exactRules) orderedByPhase@@ -88,32 +90,30 @@ grow ((a, bs):rest) (a', b) | a' == a = (a, b : bs) : rest | otherwise = (a, bs) : grow rest (a', b) -- reportSchedule :: Schedule -> String-reportSchedule schedule = concat+reportSchedule (mp, schedule) = concat [ "Rule Scheduling Report\n\n" , "Period Phase Exprs Rule\n" , "------ ----- ----- ----\n"- , concatMap reportPeriod schedule+ , concatMap (reportPeriod mp) schedule , " -----\n"- , printf " %5i\n" $ sum $ map ruleComplexity rules+ , printf " %5i\n" $ sum $ map (ruleComplexity mp) rules , "\n" , "Hierarchical Expression Count\n\n" , " Total Local Rule\n" , " ------ ------ ----\n"- , reportUsage "" $ usage rules+ , reportUsage "" $ usage mp rules , "\n" ] where rules = concat $ [ r | (_, _, r) <- schedule ] -reportPeriod :: (Int, Int, [Rule]) -> String-reportPeriod (period, phase, rules) = concatMap reportRule rules+reportPeriod :: UeMap -> (Int, Int, [Rule]) -> String+reportPeriod mp (period, phase, rules) = concatMap reportRule rules where reportRule :: Rule -> String- reportRule rule = printf "%6i %5i %5i %s\n" period phase (ruleComplexity rule) (show rule)+ reportRule rule = printf "%6i %5i %5i %s\n" period phase (ruleComplexity mp rule) (show rule) data Usage = Usage String Int [Usage] deriving Eq@@ -126,15 +126,15 @@ totalComplexity :: Usage -> Int totalComplexity (Usage _ n subs) = n + sum (map totalComplexity subs) -usage :: [Rule] -> Usage-usage = head . foldl insertUsage [] . map usage'+usage :: UeMap -> [Rule] -> Usage+usage mp = head . foldl insertUsage [] . map (usage' mp) -usage' :: Rule -> Usage-usage' rule = f $ split $ ruleName rule+usage' :: UeMap -> Rule -> Usage+usage' mp rule = f $ split $ ruleName rule where f :: [String] -> Usage f [] = undefined- f [name] = Usage name (ruleComplexity rule) []+ f [name] = Usage name (ruleComplexity mp rule) [] f (name:names) = Usage name 0 [f names] split :: String -> [String]
+ Language/Atom/UeMap.hs view
@@ -0,0 +1,375 @@+-- | Sharing for UEs, based on IntMaps. The idea is to share subexpressions of 'UE's.++module Language.Atom.UeMap + ( UeElem (..)+ , MUV (..)+ , UeMap+ , emptyMap+ , Hash+ , typeOf+ , UeState+ , recoverUE+ , getUE+ , newUE+ , newUV+-- , share+ , maybeUpdate+ , ueUpstream+ , nearestUVs+ , arrayIndices+ , isMathHCall+ ) where++import Control.Monad.State.Strict+--import qualified Data.IntMap as M+import qualified Data.Bimap as M+import Data.List (nub)++import Language.Atom.Expressions hiding (typeOf)+import qualified Language.Atom.Expressions as E++type Hash = Int++-- | Untyped variables map.+data MUV+ = MUV Int String Const+ | MUVArray UA Hash+ | MUVExtern String Type+ deriving (Show, Eq, Ord)++-- | Transforms a 'UV' into a 'MUV', returning the possibly updated map.+newUV :: UV -> UeMap -> (MUV, UeMap)+newUV uv mp = + case uv of+ UV i j k -> (MUV i j k, mp)+ UVExtern i j -> (MUVExtern i j, mp)+ UVArray arr ue -> let (h,mp') = newUE ue mp in+ (MUVArray arr h, mp')++-- | Corresponds to 'UE's --- the elements in the sharing structure.+data UeElem+ = MUVRef !MUV+ | MUConst !Const+ | MUCast !Type !Hash+ | MUAdd !Hash !Hash+ | MUSub !Hash !Hash+ | MUMul !Hash !Hash+ | MUDiv !Hash !Hash+ | MUMod !Hash !Hash+ | MUNot !Hash+ | MUAnd [Hash]+ | MUBWNot !Hash+ | MUBWAnd !Hash !Hash+ | MUBWOr !Hash !Hash+ | MUShift !Hash !Int+ | MUEq !Hash !Hash+ | MULt !Hash !Hash+ | MUMux !Hash !Hash !Hash+ | MUF2B !Hash+ | MUD2B !Hash+ | MUB2F !Hash+ | MUB2D !Hash+-- math.h:+ | MUPi+ | MUExp !Hash+ | MULog !Hash+ | MUSqrt !Hash+ | MUPow !Hash !Hash+ | MUSin !Hash+ | MUAsin !Hash+ | MUCos !Hash+ | MUAcos !Hash+ | MUSinh !Hash+ | MUCosh !Hash+ | MUAsinh !Hash+ | MUAcosh !Hash+ | MUAtan !Hash+ | MUAtanh !Hash+ deriving (Show, Eq, Ord)++typeOf :: Hash -> UeMap -> Type+typeOf h mp = case getUE h mp of+ MUVRef (MUV _ _ a) -> E.typeOf a+ MUVRef (MUVArray a _) -> E.typeOf a+ MUVRef (MUVExtern _ t) -> t+ MUCast t _ -> t+ MUConst c -> E.typeOf c+ MUAdd a _ -> typeOf' a+ MUSub a _ -> typeOf' a+ MUMul a _ -> typeOf' a+ MUDiv a _ -> typeOf' a+ MUMod a _ -> typeOf' a+ MUNot _ -> Bool+ MUAnd _ -> Bool+ MUBWNot a -> typeOf' a+ MUBWAnd a _ -> typeOf' a+ MUBWOr a _ -> typeOf' a+ MUShift a _ -> typeOf' a+ MUEq _ _ -> Bool+ MULt _ _ -> Bool+ MUMux _ a _ -> typeOf' a+ MUF2B _ -> Word32+ MUD2B _ -> Word64+ MUB2F _ -> Float+ MUB2D _ -> Double+-- math.h:+ MUPi -> Double+ MUExp a -> typeOf' a+ MULog a -> typeOf' a+ MUSqrt a -> typeOf' a+ MUPow a _ -> typeOf' a+ MUSin a -> typeOf' a+ MUAsin a -> typeOf' a+ MUCos a -> typeOf' a+ MUAcos a -> typeOf' a+ MUSinh a -> typeOf' a+ MUCosh a -> typeOf' a+ MUAsinh a -> typeOf' a+ MUAcosh a -> typeOf' a+ MUAtan a -> typeOf' a+ MUAtanh a -> typeOf' a+ where + typeOf' h' = typeOf h' mp++-- | An entry in the Map.+type UeMap = (Hash, M.Bimap Int UeElem)++-- | Wrapped in the State Monad.+type UeState a = State UeMap a++-- | Get the element associated with a 'Hash' value. It's an error if the+-- element is not in the map.+getUE :: Hash -> UeMap -> UeElem+getUE h (_,mp) = + case M.lookup h mp of+ Nothing -> error $ "Error looking up hash " ++ show h ++ " in the UE map\n" ++ show mp+ Just e -> e++-- | Put a new 'UE' in the map, unless it's already in there, and return the+-- hash pointing to the 'UE' and a new map.+newUE :: UE -> UeMap -> (Hash, UeMap)+newUE ue mp = runState (share ue) mp++emptyMap :: UeMap+emptyMap = (0, M.empty)++-- | Create the sharing map.+share :: UE -> UeState Hash+share e = case e of + UVRef (UV i j k) -> maybeUpdate (MUVRef $ MUV i j k)+ UVRef (UVExtern i j) -> maybeUpdate (MUVRef $ MUVExtern i j)+ UVRef (UVArray arr a) -> unOp a (\x -> MUVRef (MUVArray arr x))+ UConst a -> maybeUpdate (MUConst a)+ UCast t a -> unOp a (MUCast t)+ UAdd a b -> binOp (a,b) MUAdd+ USub a b -> binOp (a,b) MUSub+ UMul a b -> binOp (a,b) MUMul+ UDiv a b -> binOp (a,b) MUDiv+ UMod a b -> binOp (a,b) MUMod+ UNot a -> unOp a MUNot+ UAnd ls -> listOp ls MUAnd+ UBWNot a -> unOp a MUBWNot+ UBWAnd a b -> binOp (a,b) MUBWAnd+ UBWOr a b -> binOp (a,b) MUBWOr+ UShift a b -> unOp a (\x -> MUShift x b)+ UEq a b -> binOp (a,b) MUEq+ ULt a b -> binOp (a,b) MULt+ UMux a b c -> triOp (a,b,c) MUMux+ UF2B a -> unOp a MUF2B+ UD2B a -> unOp a MUD2B+ UB2F a -> unOp a MUB2F+ UB2D a -> unOp a MUB2D+-- math.h:+ UPi -> maybeUpdate (MUPi)+ UExp a -> unOp a MUExp+ ULog a -> unOp a MULog+ USqrt a -> unOp a MUSqrt+ UPow a b -> binOp (a,b) MUPow+ USin a -> unOp a MUSin+ UAsin a -> unOp a MUAsin+ UCos a -> unOp a MUCos+ UAcos a -> unOp a MUAcos+ USinh a -> unOp a MUSinh+ UCosh a -> unOp a MUCosh+ UAsinh a -> unOp a MUAsinh+ UAcosh a -> unOp a MUAcosh+ UAtan a -> unOp a MUAtan+ UAtanh a -> unOp a MUAtanh++-- XXX I could combine some of the following functions (unOp, binOp, etc.) to+-- slightly reduce code...+unOp :: UE -> (Hash -> UeElem) -> UeState Hash+unOp e code = do+ h <- share e + maybeUpdate (code h)++binOp :: (UE, UE) -> (Hash -> Hash -> UeElem) -> UeState Hash+binOp (e0,e1) code = do+ h0 <- share e0 + h1 <- share e1 + maybeUpdate (code h0 h1)++triOp :: (UE, UE, UE) -> (Hash -> Hash -> Hash -> UeElem) -> UeState Hash+triOp (e0,e1,e2) code = do+ h0 <- share e0 + h1 <- share e1 + h2 <- share e2 + maybeUpdate (code h0 h1 h2)++listOp :: [UE] -> ([Hash] -> UeElem) -> UeState Hash+listOp es code = do+ hashes <- foldM (\hashes e -> do h <- share e + return (h:hashes)+ ) [] es+ maybeUpdate (code hashes)++-- | Lookup an element in the map, and if it's in there, do nothing, but return+-- its hash value. Otherwise, update the map and return the new hash value+-- for the inserted element.+maybeUpdate :: UeElem -> UeState Hash+maybeUpdate e = do+ st <- get+ let mp = snd st+ case M.lookupR e mp of+ Nothing -> do let hash = fst st + 1+ put (hash, M.insert hash e mp)+ return hash+ Just h -> return h++-- -- Lookup an elem, returning 'Nothing' if no hash exists in the map and 'Just'+-- -- the hash value otherwise.+-- getHash :: UeElem -> UeMap -> Maybe Hash+-- getHash e mp = M.lookupR e+++-- ((k,e'):_) | e == e' = Just k+-- getHash e (_:es) | otherwise = getHash e es+-- getHash _ [] = Nothing++-- | Get a 'UE' back out of the 'UeMap'.+recoverUE :: UeMap -> Hash -> UE+recoverUE st h = case getUE h st of+ MUVRef (MUV i j k) -> UVRef (UV i j k)+ MUVRef (MUVArray i a) -> UVRef (UVArray i (recover' a))+ MUVRef (MUVExtern i j) -> UVRef (UVExtern i j)+ MUCast t a -> UCast t (recover' a)+ MUConst a -> UConst a+ MUAdd a b -> UAdd (recover' a) (recover' b)+ MUSub a b -> USub (recover' a) (recover' b)+ MUMul a b -> UMul (recover' a) (recover' b)+ MUDiv a b -> UDiv (recover' a) (recover' b)+ MUMod a b -> UMod (recover' a) (recover' b)+ MUNot a -> UNot (recover' a)+ MUAnd a -> UAnd $ map recover' a+ MUBWNot a -> UBWNot (recover' a)+ MUBWAnd a b -> UBWAnd (recover' a) (recover' b)+ MUBWOr a b -> UBWOr (recover' a) (recover' b)+ MUShift a b -> UShift (recover' a) b+ MUEq a b -> UEq (recover' a) (recover' b)+ MULt a b -> ULt (recover' a) (recover' b)+ MUMux a b c -> UMux (recover' a) (recover' b) (recover' c)+ MUF2B a -> UF2B (recover' a)+ MUD2B a -> UD2B (recover' a)+ MUB2F a -> UB2F (recover' a)+ MUB2D a -> UB2D (recover' a)+-- math.h:+ MUPi -> UPi+ MUExp a -> UExp (recover' a)+ MULog a -> ULog (recover' a)+ MUSqrt a -> USqrt (recover' a)+ MUPow a b -> UPow (recover' a) (recover' b)+ MUSin a -> USin (recover' a)+ MUAsin a -> UAsin (recover' a)+ MUCos a -> UCos (recover' a)+ MUAcos a -> UAcos (recover' a)+ MUSinh a -> USinh (recover' a)+ MUCosh a -> UCosh (recover' a)+ MUAsinh a -> UAsinh (recover' a)+ MUAcosh a -> UAcosh (recover' a)+ MUAtan a -> UAtan (recover' a)+ MUAtanh a -> UAtanh (recover' a)+ where recover' h' = recoverUE st h'++-- | The list of Hashes to adjacent upstream of a UE.+ueUpstream :: Hash -> UeMap -> [Hash]+ueUpstream h t = case getUE h t of+ MUVRef (MUV _ _ _) -> []+ MUVRef (MUVArray _ a) -> [a]+ MUVRef (MUVExtern _ _) -> []+ MUCast _ a -> [a]+ MUConst _ -> []+ MUAdd a b -> [a, b]+ MUSub a b -> [a, b]+ MUMul a b -> [a, b]+ MUDiv a b -> [a, b]+ MUMod a b -> [a, b]+ MUNot a -> [a]+ MUAnd a -> a+ MUBWNot a -> [a]+ MUBWAnd a b -> [a, b]+ MUBWOr a b -> [a, b]+ MUShift a _ -> [a]+ MUEq a b -> [a, b]+ MULt a b -> [a, b]+ MUMux a b c -> [a, b, c]+ MUF2B a -> [a]+ MUD2B a -> [a]+ MUB2F a -> [a]+ MUB2D a -> [a]+-- math.h:+ MUPi -> []+ MUExp a -> [a]+ MULog a -> [a]+ MUSqrt a -> [a]+ MUPow a b -> [a, b]+ MUSin a -> [a]+ MUAsin a -> [a]+ MUCos a -> [a]+ MUAcos a -> [a]+ MUSinh a -> [a]+ MUCosh a -> [a]+ MUAsinh a -> [a]+ MUAcosh a -> [a]+ MUAtan a -> [a]+ MUAtanh a -> [a]++-- | The list of all UVs that directly control the value of an expression.+nearestUVs :: Hash -> UeMap -> [MUV]+nearestUVs h mp = nub $ f h+ where+ f :: Hash -> [MUV]+ f hash = case getUE hash mp of+ (MUVRef uv@(MUVArray _ h')) -> [uv] ++ f h'+ (MUVRef uv) -> [uv]+ _ -> concatMap f $ ueUpstream hash mp++-- | All array indexing subexpressions.+arrayIndices :: Hash -> UeMap -> [(UA, Hash)]+arrayIndices h mp = nub $ f h+ where+ f :: Hash -> [(UA, Hash)]+ f hash = case getUE hash mp of+ (MUVRef (MUVArray ua h')) -> (ua, h') : f h'+ _ -> concatMap f $ ueUpstream hash mp++-- XXX can put this back after making UE map---won't be expensive.+isMathHCall :: UeElem -> Bool+isMathHCall fc = + case fc of+ MUPi -> True+ MUExp _ -> True+ MULog _ -> True+ MUSqrt _ -> True+ MUPow _ _ -> True+ MUSin _ -> True+ MUAsin _ -> True+ MUCos _ -> True+ MUAcos _ -> True+ MUSinh _ -> True+ MUCosh _ -> True+ MUAsinh _ -> True+ MUAcosh _ -> True+ MUAtan _ -> True+ MUAtanh _ -> True+ _ -> False+
atom.cabal view
@@ -1,5 +1,5 @@ name: atom-version: 1.0.8+version: 1.0.9 category: Language, Embedded @@ -34,10 +34,11 @@ library build-depends: base >= 4.0 && < 5,- mtl >= 1.1.0.1 && < 1.2,+ mtl >= 1.1.0.1, process >= 1.0.1.1 && < 1.2, syb >= 0.1.0.0,- uniplate >= 1.5.0 && < 2.0+ containers >= 0.4,+ bimap >= 0.2.4 exposed-modules: Language.Atom@@ -51,12 +52,11 @@ Language.Atom.Language Language.Atom.Scheduling Language.Atom.Unit+ Language.Atom.UeMap extensions: GADTs, DeriveDataTypeable - if impl(ghc > 6.8)- ghc-options: -fwarn-tabs- ghc-options: -W+ ghc-options: -Wall source-repository head type: git