packages feed

atom 0.1.2 → 0.1.3

raw patch · 9 files changed

+121/−61 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Atom.Code: cCover :: Config -> Bool
- Language.Atom.Elaboration: instance Eq Rule
- Language.Atom.Elaboration: instance Ord Rule
- Language.Atom.Elaboration: ruleAsserts :: Rule -> [(Name, UE)]
- Language.Atom.Elaboration: ruleCovers :: Rule -> [(Name, UE)]
+ Language.Atom.Common: linear :: (FloatingE a) => (E a, E a) -> (E a, E a) -> E a -> E a
+ Language.Atom.Elaboration: Assert :: Name -> UE -> UE -> Rule
+ Language.Atom.Elaboration: Cover :: Name -> UE -> UE -> Rule
+ Language.Atom.Elaboration: ruleAssert :: Rule -> UE
+ Language.Atom.Elaboration: ruleCover :: Rule -> UE
- Language.Atom.Code: Config :: String -> (Type -> String) -> ([Name] -> [Name] -> [(Name, Type)] -> (String, String)) -> Bool -> Bool -> String -> Bool -> String -> Config
+ Language.Atom.Code: Config :: String -> (Type -> String) -> ([Name] -> [Name] -> [(Name, Type)] -> (String, String)) -> Bool -> Bool -> String -> String -> Config
- Language.Atom.Code: writeC :: Name -> Config -> Schedule -> [UV] -> [UA] -> [Name] -> [Name] -> [(Name, Type)] -> IO RuleCoverage
+ Language.Atom.Code: writeC :: Name -> Config -> [Rule] -> Schedule -> [UV] -> [UA] -> [Name] -> [Name] -> [(Name, Type)] -> IO RuleCoverage
- Language.Atom.Elaboration: Rule :: Int -> Name -> UE -> [(UV, UE)] -> [([String] -> String, [UE])] -> Int -> Int -> [(Name, UE)] -> [(Name, UE)] -> Rule
+ Language.Atom.Elaboration: Rule :: Int -> Name -> UE -> [(UV, UE)] -> [([String] -> String, [UE])] -> Int -> Int -> Rule

Files

Language/Atom/Code.hs view
@@ -28,9 +28,8 @@   , cType         :: Type -> String                                          -- ^ C type naming rules.   , cCode         :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)  -- ^ Custom C code to insert above and below, given assertion names, coverage names, and probe names and types.   , cRuleCoverage :: Bool                                                    -- ^ Enable rule coverage tracking.-  , cAssert       :: Bool                                                    -- ^ Enable assertion checking.+  , cAssert       :: Bool                                                    -- ^ Enable assertions and functional coverage.   , cAssertName   :: String                                                  -- ^ Name of assertion function.  Type: void assert(int, cType Bool, cType Word64);-  , cCover        :: Bool                                                    -- ^ Enable functional coverage accumulation.   , cCoverName    :: String                                                  -- ^ Name of coverage function.  Type: void cover(int, cType Bool, cType Word64);   } @@ -43,7 +42,6 @@   , cRuleCoverage = True   , cAssert       = True   , cAssertName   = "assert"-  , cCover        = True   , cCoverName    = "cover"   } @@ -129,10 +127,10 @@  type RuleCoverage = [(Name, Int, Int)] -writeC :: Name -> Config -> Schedule -> [UV] -> [UA] -> [Name] -> [Name] -> [(Name, Type)] -> IO RuleCoverage-writeC name config schedule uvs uas assertionNames coverageNames probeNames = do+writeC :: Name -> Config -> [Rule] -> Schedule -> [UV] -> [UA] -> [Name] -> [Name] -> [(Name, Type)] -> IO RuleCoverage+writeC name config rules schedule uvs uas assertionNames coverageNames probeNames = do   writeFile (name ++ ".c") c-  return [ (ruleName r, div (ruleId r) 32, mod (ruleId r) 32) | r <- rules ]+  return [ (ruleName r, div (ruleId r) 32, mod (ruleId r) 32) | r <- rules' ]   where   (preCode, postCode) = cCode config assertionNames coverageNames probeNames   c = unlines@@ -144,7 +142,8 @@     , codeIf (cRuleCoverage config) $ "static " ++ cType config Word32 ++ " __coverage_index = 0;"     , concatMap (declUV config) uvs     , concatMap (declUA config) uas-    , concatMap (codeRule config assertionNames coverageNames) $ rules+    , concatMap (codeRule config) rules'+    , codeAssertionChecks config assertionNames coverageNames rules     , "void " ++ (if null (cFuncName config) then name else cFuncName config) ++ "(void) {"     , concatMap (codePeriodPhase config) schedule     , "  __global_clock = __global_clock + 1;"@@ -153,10 +152,10 @@     , postCode     ] -  rules :: [Rule]-  rules = concat [ r | (_, _, r) <- schedule ]+  rules' :: [Rule]+  rules' = concat [ r | (_, _, r) <- schedule ] -  covLen = 1 + div (maximum $ map ruleId rules) 32+  covLen = 1 + div (maximum $ map ruleId rules') 32  codeIf :: Bool -> String -> String codeIf a b = if a then b else ""@@ -191,16 +190,14 @@ doubleBits :: Double -> Word64 doubleBits = unsafeCoerce -codeRule :: Config -> [Name] -> [Name] -> Rule -> String-codeRule config assertionNames coverageNames rule =+codeRule :: Config -> Rule -> String+codeRule config rule@(Rule _ _ _ _ _ _ _) =   "/* " ++ show rule ++ " */\n" ++   "static void __r" ++ show (ruleId rule) ++ "(void) {\n" ++   concatMap (codeUE    config ues "  ") ues ++   "  if (" ++ id (ruleEnable rule) ++ ") {\n" ++   concatMap codeAction (ruleActions rule) ++   codeIf (cRuleCoverage config) ("    __coverage[" ++ covWord ++ "] = __coverage[" ++ covWord ++ "] | (1 << " ++ covBit ++ ");\n") ++-  concat [ codeIf (cAssert config) ("    " ++ cAssertName config ++ "(" ++ assertionId name ++ ", " ++ id check ++ ", __global_clock);\n") | (name, check) <- ruleAsserts rule ] ++-  concat [ codeIf (cCover  config) ("    " ++ cCoverName  config ++ "(" ++ coverageId  name ++ ", " ++ id check ++ ", __global_clock);\n") | (name, check) <- ruleCovers  rule ] ++   "  }\n" ++   concatMap codeAssign (ruleAssigns rule) ++   "}\n\n"@@ -208,12 +205,6 @@   ues = topo $ allUEs rule   id ue = fromJust $ lookup ue ues -  assertionId :: Name -> String-  assertionId name = show $ fromJust $ elemIndex name assertionNames--  coverageId :: Name -> String-  coverageId name = show $ fromJust $ elemIndex name coverageNames-   codeAction :: (([String] -> String), [UE]) -> String   codeAction (f, args) = "    " ++ f (map id args) ++ ";\n" @@ -229,6 +220,23 @@       UVArray (UAExtern n _) index -> concat [n, "[", id index, "]"]       UVExtern n _                 -> n +codeRule _ _ = ""++codeAssertionChecks :: Config -> [Name] -> [Name] -> [Rule] -> String+codeAssertionChecks config assertionNames coverageNames rules = codeIf (cAssert config) $+  "static void __assertion_checks(void) {\n" +++  concatMap (codeUE config ues "  ") ues +++  concat [ "  if (" ++ id enable ++ ") " ++ cAssertName config ++ "(" ++ assertionId name ++ ", " ++ id check ++ ", __global_clock);\n" | Assert name enable check <- rules ] +++  concat [ "  if (" ++ id enable ++ ") " ++ cCoverName  config ++ "(" ++ coverageId  name ++ ", " ++ id check ++ ", __global_clock);\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 ]+  id ue = fromJust $ lookup ue ues+  assertionId :: Name -> String+  assertionId name = show $ fromJust $ elemIndex name assertionNames+  coverageId :: Name -> String+  coverageId name = show $ fromJust $ elemIndex name coverageNames+ codePeriodPhase :: Config -> (Int, Int, [Rule]) -> String codePeriodPhase config (period, phase, rules) = unlines   [ printf "  {"@@ -246,5 +254,5 @@   clockType | period < 2 ^  8 = Word8             | period < 2 ^ 16 = Word16             | otherwise       = Word32-  callRule r = concat ["      __r", show (ruleId r), "();  /* ", show r, " */"]+  callRule r = concat ["      ", codeIf (cAssert config) "__assertion_checks(); ", "__r", show (ruleId r), "();  /* ", show r, " */"] 
Language/Atom/Common.hs view
@@ -14,6 +14,7 @@   , debounce   -- * Lookup Tables   , lookupTable+  , linear   -- * Hysteresis   , hysteresis   ) where@@ -87,6 +88,13 @@     slope = (y1 - y0) / (x1 - x0)     interp = (x - x0) * slope + y0 +-- | Linear extrapolation and interpolation on a line with 2 points.+--   The two x points must be different to prevent a divide-by-zero.+linear :: FloatingE a => (E a, E a) -> (E a, E a) -> E a -> E a+linear (x1, y1) (x2, y2) a = slope * a + inter+  where+  slope = y2 - y1 / x2 - x1+  inter = y1 - slope * x1  -- | Hysteresis returns 'True' when the input exceeds @max@ and 'False' when --   the input is less than @min@.  The state is held when the input is between
Language/Atom/Compile.hs view
@@ -23,6 +23,6 @@     Nothing -> putStrLn "ERROR: Design rule checks failed." >> exitWith (ExitFailure 1)     Just (rules, uvs, uas, assertionNames, coverageNames, probeNames) -> do       let schedule' = schedule rules-      ruleCoverage <- writeC name config schedule' uvs uas assertionNames coverageNames probeNames+      ruleCoverage <- writeC name config rules schedule' uvs uas assertionNames coverageNames probeNames       return (schedule', ruleCoverage, assertionNames, coverageNames, probeNames) 
Language/Atom/Elaboration.hs view
@@ -63,29 +63,36 @@   , atomCovers      :: [(Name, UE)]   } -data Rule = Rule-  { ruleId        :: Int-  , ruleName      :: Name-  , ruleEnable    :: UE-  , ruleAssigns   :: [(UV, UE)]-  , ruleActions   :: [([String] -> String, [UE])]-  , rulePeriod    :: Int-  , rulePhase     :: Int-  , ruleAsserts   :: [(Name, UE)]-  , ruleCovers    :: [(Name, UE)]-  }+data Rule+  = Rule+    { ruleId        :: Int+    , ruleName      :: Name+    , ruleEnable    :: UE+    , ruleAssigns   :: [(UV, UE)]+    , ruleActions   :: [([String] -> String, [UE])]+    , rulePeriod    :: Int+    , rulePhase     :: Int+    }+  | Assert+    { ruleName      :: Name+    , ruleEnable    :: UE+    , ruleAssert    :: UE+    }+  | Cover+    { ruleName      :: Name+    , ruleEnable    :: UE+    , ruleCover     :: UE+    }  instance Show AtomDB where show = atomName instance Eq   AtomDB where (==) = (==) `on` atomId instance Ord  AtomDB where compare a b = compare (atomId a) (atomId b) instance Show Rule   where show = ruleName-instance Eq   Rule   where (==) = (==) `on` ruleId-instance Ord  Rule   where compare a b = compare (ruleId a) (ruleId b)  elaborateRules:: UE -> AtomDB -> [Rule] elaborateRules parentEnable atom = if isRule then rule : rules else rules   where-  isRule = not $ null (atomAssigns atom) && null (atomActions atom) && null (atomAsserts atom) && null (atomCovers atom)+  isRule = not $ null (atomAssigns atom) && null (atomActions atom)   enable = uand parentEnable $ atomEnable atom   rule = Rule     { ruleId        = atomId   atom@@ -95,17 +102,26 @@     , ruleActions   = atomActions atom     , rulePeriod    = atomPeriod  atom     , rulePhase     = atomPhase   atom-    , ruleAsserts   = atomAsserts atom-    , ruleCovers    = atomCovers  atom     }-  rules = concatMap (elaborateRules enable) (atomSubs 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) -reIdRules :: [Rule] -> [Rule]-reIdRules rules = map (\ r -> r { ruleId = fromJust $ lookup (ruleId r) ids } ) rules-  where-  ids = zip (map ruleId rules) [0..]+reIdRules :: Int -> [Rule] -> [Rule]+reIdRules _ [] = []+reIdRules i (a:b) = case a of+  Rule _ _ _ _ _ _ _ -> a { ruleId = i } : reIdRules (i + 1) 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@@ -154,9 +170,9 @@ elaborate :: Name -> Atom () -> IO (Maybe ([Rule], [UV], [UA], [Name], [Name], [(Name, Type)])) elaborate name atom = do   (_, (g, atomDB)) <- buildAtom Global { gRuleId = 0, gVarId = 0, gArrayId = 0, gVars = [], gArrays = [], gProbes = [], gPeriod = 1, gPhase  = 0 } name atom-  let rules = reIdRules $ elaborateRules (ubool True) atomDB-      coverageNames  = concatMap (fst . unzip . ruleCovers ) rules-      assertionNames = concatMap (fst . unzip . ruleAsserts) rules+  let rules = reIdRules 0 $ elaborateRules (ubool True) atomDB+      coverageNames  = [ name | Cover  name _ _ <- rules ]+      assertionNames = [ name | Assert name _ _ <- rules ]       probeNames = [ (n, typeOf a) | (n, a) <- gProbes g ]   if (null rules)     then do@@ -177,7 +193,7 @@  -- | 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 =+checkAssignConflicts rule@(Rule _ _ _ _ _ _ _) =   if length vars /= length vars'     then do       putStrLn $ "ERROR: Rule " ++ show rule ++ " contains multiple assignments to the same variable(s)."@@ -187,6 +203,7 @@   where   vars = fst $ unzip $ ruleAssigns rule   vars' = nub vars+checkAssignConflicts _ = return True  {- -- | Checks that all array indices are not a function of array variables.@@ -280,7 +297,7 @@ allUVs :: [Rule] -> UE -> [UV] allUVs rules ue = fixedpoint next $ nearestUVs ue   where-  assigns = concatMap ruleAssigns rules+  assigns = concat [ ruleAssigns r | r@(Rule _ _ _ _ _ _ _) <- rules ]   previousUVs :: UV -> [UV]   previousUVs uv = concat [ nearestUVs ue | (uv', ue) <- assigns, uv == uv' ]   next :: [UV] -> [UV]@@ -292,9 +309,13 @@  -- | All primary expressions used in a rule. allUEs :: Rule -> [UE]-allUEs rule = ruleEnable rule : concat [ ue : index uv | (uv, ue) <- ruleAssigns rule ] ++ concat (snd (unzip (ruleActions rule))) ++ snd (unzip (ruleAsserts rule)) ++ snd (unzip (ruleCovers rule))+allUEs rule = ruleEnable rule : ues   where   index :: UV -> [UE]   index (UVArray _ ue) = [ue]   index _ = []+  ues = case rule of+    Rule _ _ _ _ _ _ _ -> concat [ ue : index uv | (uv, ue) <- ruleAssigns rule ] ++ concat (snd (unzip (ruleActions rule)))+    Assert _ _ a       -> [a]+    Cover  _ _ a       -> [a] 
Language/Atom/Language.hs view
@@ -287,7 +287,9 @@   return (value $ V $ UVExtern "__coverage_index" Word32, value $ V $ UVExtern "__coverage[__coverage_index]" Word32)  --- | Assertion that checks an E Bool.  Assertions are only checked if the containing rule is enabled and executed.+-- | 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@@ -301,11 +303,13 @@   assert name $ imply a b   cover (name ++ "Precondition") a --- | Adds a functional coverage point.+-- | A functional coverage point tracks if an event has occured (true).+--   Coverage points are checked at the same time as assertions.+--   Coverage names should be globally unique. cover :: Name -> E Bool -> Atom () cover name check = do   (g, atom) <- get-  let names = fst $ unzip $ atomAsserts atom-  when (elem name names) (liftIO $ putStrLn $ "WARNING: Assertion name already used: " ++ name)+  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 }) 
Language/Atom/Scheduling.hs view
@@ -13,8 +13,9 @@ type Schedule = [(Int, Int, [Rule])]  -- (period, phase, rules)  schedule :: [Rule] -> Schedule-schedule rules = concatMap spread periods+schedule rules' = concatMap spread periods   where+  rules = [ r | r@(Rule _ _ _ _ _ _ _) <- rules' ]    -- Algorithm for assigning rules to phases for a given period: 
Language/Atom/Unit.hs view
@@ -88,6 +88,8 @@ runTest :: Int -> IO Test -> IO (Name, Bool, Int, [Name], [Name]) runTest seed test = do   test <- test+  putStrLn $ "running test " ++ name test ++ " ..."+  hFlush stdout   (_, _, _, coverageNames, _) <- compile "atom_unit_test" defaults { cCode = prePostCode test, cRuleCoverage = False } $ testbench test   (exit, out, err) <- readProcessWithExitCode "gcc" (["-Wall", "-g", "-o", "atom_unit_test"] ++ [ "-i" ++ i | i <- includes test ] ++ modules test ++ ["atom_unit_test.c"]) ""   let file = name test ++ ".log"@@ -110,11 +112,15 @@       , "#include <stdlib.h>"       , "void assert (int id, unsigned char check, unsigned long long clock) {"       , "  static unsigned char failed[" ++ show (length assertionNames) ++ "] = {" ++ intercalate "," (replicate (length assertionNames) "0") ++ "};"-      , "  " ++ intercalate "\n  else " [ "if (id == " ++ show id ++ ") { if (! check && ! failed[id]) { printf(\"ASSERTION FAILURE: " ++ name ++ " at time %lli\\n\", clock); failed[id] = 1; } }" | (name, id) <- zip assertionNames [0..] ]+      , "  if (! check) {"+      , "    " ++ intercalate "\n    else " [ "if (id == " ++ show id ++ ") { if (! failed[id]) { printf(\"ASSERTION FAILURE: " ++ name ++ " at time %lli\\n\", clock); failed[id] = 1; } }" | (name, id) <- zip assertionNames [0..] ]+      , "  }"       , "}"       , "void cover  (int id, unsigned char check, unsigned long long clock) {"       , "  static unsigned char covered[" ++ show (length coverageNames) ++ "] = {" ++ intercalate "," (replicate (length coverageNames) "0") ++ "};"-      , "  " ++ intercalate "\n  else " [ "if (id == " ++ show id ++ ") { if (check && ! covered[id]) { printf(\"covered: " ++ name ++ " at time %lli\\n\", clock); covered[id] = 1; } }" | (name, id) <- zip coverageNames [0..] ]+      , "  if (check) {"+      , "    " ++ intercalate "\n    else " [ "if (id == " ++ show id ++ ") { if (! covered[id]) { printf(\"covered: " ++ name ++ " at time %lli\\n\", clock); covered[id] = 1; } }" | (name, id) <- zip coverageNames [0..] ]+      , "  }"       , "}"       ] ++ declCode test 
RELEASE-NOTES view
@@ -1,3 +1,9 @@+atom 0.1.3    12/03/2009++- Added linear lookup (Common). +- Assertions and coverage points are checked between the execution of every rule, not just once per cycle.+- Removed cCover code configuration.  Assertions and coverage are enabled by cAssert.+ atom 0.1.2    11/25/2009  - Added div0_ and mod0_ functions, that instrument runtime checks for divide-by-zero (Lee Pike).
atom.cabal view
@@ -1,15 +1,21 @@ name:    atom-version: 0.1.2+version: 0.1.3  category: Language  synopsis: A DSL for embedded hard realtime applications.  description:-    Atom is a Haskell DSL for designing hard realtime embedded programs. Based-    on conditional term rewriting, atom will compile a collection of atomic-    state transition rules to a C program with constant memory use and-    deterministic execution time.+    Atom is a Haskell DSL for designing hard realtime embedded software.+    Based on guarded atomic actions (similar to STM), Atom enables+    highly concurrent programming without the need for mutex locking.++    In addition, Atom performs compile-time task scheduling and generates code+    with deterministic execution time and constant memory use, simplifying the+    process of timing verification and memory consumption in hard realtime applications.++    Without mutex locking and run-time task scheduling, Atom eliminates+    the need and overhead of RTOSs for many embedded applications.  author:     Tom Hawkins <tomahawkins@gmail.com> maintainer: Tom Hawkins <tomahawkins@gmail.com>