Last active
October 9, 2018 07:56
-
-
Save ret/4217b3e0733727df99df251534381a87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module LEDsMojo.GameOfLife (CellT, gameOfLife) where | |
import qualified Data.List as L ((\\)) | |
import Data.Sized.Matrix as M | |
import Data.Sized.Unsigned | |
import Language.KansasLava | |
type CellT = Bool | |
gameOfLife :: Matrix (X8, X16) CellT -> Signal CLK Bool -> Matrix (X8, X16) (Signal CLK CellT) | |
gameOfLife initBoard ena = board | |
where | |
-- structural laziness is key here - board is defined in terms of board | |
-- at various coordinates as we iterate through cells (coordinates) | |
board = forAll (\ i@(ix, iy) -> | |
let neighbors = net board (fromIntegral ix, fromIntegral iy) | |
in cell (initBoard ! i) ena neighbors) | |
net :: Matrix (X8, X16) (Signal CLK CellT) -> (Int, Int) -> Matrix X8 (Maybe (Signal CLK CellT)) | |
net mat (ix,iy) = M.fromList $ map maybeE ixList | |
where | |
ixList :: [(Int, Int)] | |
ixList = [ (ix + dx, iy + dy) | dx <- [-1,0,1], dy <- [-1,0,1] ] L.\\ [(ix,iy)] | |
maybeE :: (Int, Int) -> Maybe (Signal CLK CellT) | |
maybeE (-1, _) = Nothing | |
maybeE ( _, -1) = Nothing | |
maybeE ( 8, _) = Nothing | |
maybeE ( _, 16) = Nothing | |
maybeE (ix, iy) = Just $ mat ! (fromIntegral ix, fromIntegral iy) | |
-- from KL paper, page 214, U3 is sufficient despite 8 neighbors | |
-- because 8 (mod 8 = 0) is 0, which still leads to a False | |
-- (i.e. starve) as opposed to over populuation. Would be cleaner to | |
-- use U4, but that's another (wasted) wire for each of the 8x16 | |
-- cells. | |
type NCountT = U3 -- has to be 0..8, but 8 has the same effect as 0, see above | |
cell :: CellT -> Signal CLK Bool -> Matrix X8 (Maybe (Signal CLK CellT)) -> Signal CLK CellT | |
cell init ena ns = res | |
where | |
n :: Signal CLK NCountT | |
n = foldr (\ a b -> | |
case a of | |
Just (v :: Signal CLK Bool) -> unsigned v + b | |
Nothing -> b) | |
0 | |
$ M.toList ns | |
res :: Signal CLK CellT | |
res = register init $ mux ena (res, funMap life (pack (n, res))) | |
life :: (NCountT, CellT) -> Maybe CellT | |
life (2, True) = return True -- survive | |
life (3, True) = return True -- survive | |
life (3, False) = return True -- birth | |
life _ = return False -- starve |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment