package Mcp(mcpBuffered, mcpUnit, mcpUnitF, IMcpUnitF(..)) where import Pull import ConfigReg -- ==================== interface IMcpUnitF b = result :: b isValid :: Bool mcpBuffered :: (IsModule m c, Bits b sb) => Integer -> (a -> b) -> Pull a -> m (Pull b) mcpBuffered 2 = mcp2_buffered mcpBuffered 3 = mcp3_buffered mcpBuffered 4 = mcp4_buffered mcpUnit :: (IsModule m c, Bits a sa, Bits b sb) => Integer -> (a -> b) -> a -> Bool -> m (Reg b) mcpUnit 2 = mcp2_unit mcpUnit 3 = mcp3_unit mcpUnit 4 = mcp4_unit mcpUnitF :: (IsModule m c, Bits a sa, Bits b sb) => Integer -> (a -> b) -> a -> Bool -> m (IMcpUnitF b) mcpUnitF 2 = mcp2_unitF mcpUnitF 3 = mcp3_unitF mcpUnitF 4 = mcp4_unitF -- ==================== delay2 :: Integer delay2 = 9 delay3 :: Integer delay3 = 14 delay4 :: Integer delay4 = 19 -- ==================== mcp2_buffer :: (IsModule m c, Bits a sa) => a -> Pull a -> m (Pull a) mcp2_buffer init src = module r_mcp2 :: Reg a <- mkReg init mcp_en_src :: Reg Bool <- mkReg False rules "toggle": when not mcp_en_src ==> mcp_en_src := True interface pull = do x :: a x <- src.pull action {r_mcp2 := x; mcp_en_src := False } return r_mcp2 when mcp_en_src mcp2_buffered :: (IsModule m c, Bits b sb) => (a -> b) -> Pull a -> m (Pull b) mcp2_buffered f = mcp2_buffer _ · apply f -- · buffer -- ------------- mcp3_buffer :: (IsModule m c, Bits a sa) => a -> Pull a -> m (Pull a) mcp3_buffer init src = module r_mcp3 :: Reg a <- mkReg init mcp_en_src :: Reg Bool <- mkReg False counter :: Reg (Bit 2) <- mkReg 0 rules "count": when counter/= 0 ==> counter := counter - 1 "toggle": when True ==> mcp_en_src := (counter == 0) interface pull = do x :: a x <- src.pull action {r_mcp3 := x; counter := 2} -- counter must be set to -- (length of path) - 1 return r_mcp3 when mcp_en_src mcp3_buffered :: (IsModule m c, Bits b sb) => (a -> b) -> Pull a -> m (Pull b) mcp3_buffered f = mcp3_buffer _ · apply f -- · buffer -- ------------- mcp4_buffer :: (IsModule m c, Bits a sa) => a -> Pull a -> m (Pull a) mcp4_buffer init src = module r_mcp4 :: Reg a <- mkReg init mcp_en_src :: Reg Bool <- mkReg False counter :: Reg (Bit 2) <- mkReg 0 rules "count": when counter/= 0 ==> counter := counter - 1 "toggle": when True ==> mcp_en_src := (counter == 0) interface pull = do x :: a x <- src.pull action {r_mcp4 := x; counter := 3} -- counter must be set to -- (length of path) - 1 return r_mcp4 when mcp_en_src mcp4_buffered :: (IsModule m c, Bits b sb) => (a -> b) -> Pull a -> m (Pull b) mcp4_buffered f = mcp4_buffer _ · apply f -- · buffer -- ==================== mcp2_unit :: (IsModule m c, Bits a sa, Bits b sb) => (a -> b) -> a -> Bool -> m (Reg b) mcp2_unit f src changed = -- src and changed are run-time values module r_mcp2 :: Reg b <- mkMcpRegU delay2 mcp_en_src :: Reg Bool <- mkReg False valid :: Reg Bool <- mkConfigReg False rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set": when mcp_en_src ==> r_mcp2 := f src {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set valid": when (mcp_en_src && not changed) ==> action valid := True mcp_en_src := False addRules $ (rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp changed": when changed ==> action mcp_en_src := False valid := False ) <+ (rules "Mcp toggle": -- only when not changed (by <+) when True ==> mcp_en_src := True ) interface _read = r_mcp2 when valid _write _ = _ -- ------------- mcp3_unit :: (IsModule m c, Bits a sa, Bits b sb) => (a -> b) -> a -> Bool -> m (Reg b) mcp3_unit f src changed = -- src and changed are run-time values module r_mcp3 :: Reg b <- mkMcpRegU delay3 counter :: Reg (Bit 1) <- mkReg 0 mcp_en_src :: Reg Bool <- mkReg False valid :: Reg Bool <- mkConfigReg False rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set": when mcp_en_src ==> r_mcp3 := f src {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set valid": when (mcp_en_src && not changed) ==> action valid := True mcp_en_src := False addRules $ (rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp changed": when changed ==> action counter := 1 -- cycle-multiplicity minus two mcp_en_src := False valid := False ) <+ (rules "Mcp toggle": -- only when not changed (by <+) when counter == 0 ==> mcp_en_src := True "Mcp count": when counter /= 0 ==> counter := counter - 1 ) interface _read = r_mcp3 when valid _write _ = _ -- ------------- mcp4_unit :: (IsModule m c, Bits a sa, Bits b sb) => (a -> b) -> a -> Bool -> m (Reg b) mcp4_unit f src changed = -- src and changed are run-time values module r_mcp4 :: Reg b <- mkMcpRegU delay4 counter :: Reg (Bit 2) <- mkReg 0 mcp_en_src :: Reg Bool <- mkReg False valid :: Reg Bool <- mkConfigReg False rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set": when mcp_en_src ==> r_mcp4 := f src {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set valid": when (mcp_en_src && not changed) ==> action valid := True mcp_en_src := False addRules $ (rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp changed": when changed ==> action counter := 2 -- cycle-multiplicity minus two mcp_en_src := False valid := False ) <+ (rules "Mcp toggle": -- only when not changed (by <+) when counter == 0 && not valid ==> mcp_en_src := True "Mcp count": when counter /= 0 ==> counter := counter - 1 ) interface _read = r_mcp4 when valid _write _ = _ -- ==================== mcp2_unitF :: (IsModule m c, Bits a sa, Bits b sb) => (a -> b) -> a -> Bool -> m (IMcpUnitF b) mcp2_unitF f src changed = -- src and changed are run-time values module r_mcp2 :: Reg b <- mkMcpRegU delay2 mcp_en_src :: Reg Bool <- mkReg False valid :: Reg Bool <- mkConfigReg False rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set": when mcp_en_src ==> r_mcp2 := f src {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set valid": when (mcp_en_src && not changed) ==> action valid := True mcp_en_src := False addRules $ (rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp changed": when changed ==> action mcp_en_src := False valid := False ) <+ (rules "Mcp toggle": -- only when not changed (by <+) when True ==> mcp_en_src := True ) interface result = r_mcp2 isValid = valid -- ------------- mcp3_unitF :: (IsModule m c, Bits a sa, Bits b sb) => (a -> b) -> a -> Bool -> m (IMcpUnitF b) mcp3_unitF f src changed = -- src and changed are run-time values module r_mcp3 :: Reg b <- mkMcpRegU delay3 counter :: Reg (Bit 1) <- mkReg 0 mcp_en_src :: Reg Bool <- mkReg False valid :: Reg Bool <- mkConfigReg False rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set": when mcp_en_src ==> r_mcp3 := f src {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set valid": when (mcp_en_src && not changed) ==> action valid := True mcp_en_src := False addRules $ (rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp changed": when changed ==> action counter := 1 -- cycle-multiplicity minus two mcp_en_src := False valid := False ) <+ (rules "Mcp toggle": -- only when not changed (by <+) when counter == 0 ==> mcp_en_src := True "Mcp count": when counter /= 0 ==> counter := counter - 1 ) interface result = r_mcp3 isValid = valid -- ------------- mcp4_unitF :: (IsModule m c, Bits a sa, Bits b sb) => (a -> b) -> a -> Bool -> m (IMcpUnitF b) mcp4_unitF f src changed = -- src and changed are run-time values module r_mcp4 :: Reg b <- mkMcpRegU delay4 counter :: Reg (Bit 2) <- mkReg 0 mcp_en_src :: Reg Bool <- mkReg False valid :: Reg Bool <- mkConfigReg False rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set": when mcp_en_src ==> r_mcp4 := f src {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp set valid": when (mcp_en_src && not changed) ==> action valid := True mcp_en_src := False addRules $ (rules {-# ASSERT no implicit conditions #-} {-# ASSERT fire when enabled #-} "Mcp changed": when changed ==> action counter := 2 -- cycle-multiplicity minus two mcp_en_src := False valid := False ) <+ (rules "Mcp toggle": -- only when not changed (by <+) when counter == 0 ==> mcp_en_src := True "Mcp count": when counter /= 0 ==> counter := counter - 1 ) interface result = r_mcp4 isValid = valid -- ======================================== mkMcpRegU :: (IsModule m c, Bits a sa) => Integer -> m (Reg a) mkMcpRegU d = liftModule $ if valueOf sa == 0 then module interface _read = unpack 0 _write _ = return () else module _r :: VReg sa _r <- vMkMcpRegU d let name = Valid (primGetModuleName _r) let t = typeOf (_ :: a) primSavePortType name "get" t primSavePortType name "val" t interface _read = unpack _r.get _write x = fromPrimAction (_r.set (pack x)) interface VReg n = set :: Bit n -> PrimAction get :: Bit n vMkMcpRegU :: Integer -> Module (VReg n) vMkMcpRegU d = module verilog "McpRegUN" (("width",valueOf n),("delay",d)) "CLK" "RST" { get = "get"{reg}; set = "val"{reg} "SET"; } [ get <> [get, set], set << set ]