| 1 |
-- "A problem with functional dependencies. |
|---|
| 2 |
-- use -fcontext-stack=100 ghc switch. |
|---|
| 3 |
|
|---|
| 4 |
{-# LANGUAGE GADTs, FunctionalDependencies, MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, FlexibleContexts, UndecidableInstances #-} |
|---|
| 5 |
|
|---|
| 6 |
module Problem where |
|---|
| 7 |
|
|---|
| 8 |
import Data.Bits |
|---|
| 9 |
import Data.Word |
|---|
| 10 |
|
|---|
| 11 |
------------------------------------------------------------------------------- |
|---|
| 12 |
-- Type level arithmetic. |
|---|
| 13 |
|
|---|
| 14 |
data Zero = Zero |
|---|
| 15 |
data Succ n = Succ n |
|---|
| 16 |
|
|---|
| 17 |
type ZERO = Zero |
|---|
| 18 |
type ONE = Succ ZERO |
|---|
| 19 |
type TWO = Succ ONE |
|---|
| 20 |
type THREE = Succ TWO |
|---|
| 21 |
type FOUR = Succ THREE |
|---|
| 22 |
type FIVE = Succ FOUR |
|---|
| 23 |
type SIX = Succ FIVE |
|---|
| 24 |
type SEVEN = Succ SIX |
|---|
| 25 |
type EIGHT = Succ SEVEN |
|---|
| 26 |
type NINE = Succ EIGHT |
|---|
| 27 |
type SIZE10 = Succ NINE |
|---|
| 28 |
type SIZE11 = Succ SIZE10 |
|---|
| 29 |
type SIZE12 = Succ SIZE11 |
|---|
| 30 |
type SIZE13 = Succ SIZE12 |
|---|
| 31 |
type SIZE15 = Succ (Succ SIZE13) |
|---|
| 32 |
type SIZE16 = Succ SIZE15 |
|---|
| 33 |
type SIZE20 = Succ (Succ (Succ (Succ (Succ SIZE15)))) |
|---|
| 34 |
type SIZE25 = Succ (Succ (Succ (Succ (Succ SIZE20)))) |
|---|
| 35 |
type SIZE26 = Succ SIZE25 |
|---|
| 36 |
type SIZE30 = Succ (Succ (Succ (Succ (Succ SIZE25)))) |
|---|
| 37 |
type SIZE32 = Succ (Succ SIZE30) |
|---|
| 38 |
|
|---|
| 39 |
class Nat n where fromNat :: n -> Int |
|---|
| 40 |
|
|---|
| 41 |
instance Nat Zero where fromNat = const 0 |
|---|
| 42 |
instance Nat n => Nat (Succ n) where fromNat ~(Succ n) = 1+fromNat n |
|---|
| 43 |
|
|---|
| 44 |
class (Nat a, Nat b, Nat c) => CPlus a b c | a b -> c, a c -> b |
|---|
| 45 |
|
|---|
| 46 |
--instance Nat a => CPlus a Zero a |
|---|
| 47 |
instance Nat a => CPlus Zero a a |
|---|
| 48 |
instance (CPlus a b c) => CPlus (Succ a) b (Succ c) |
|---|
| 49 |
--instance (CPlus a b c) => CPlus (Succ a) b (Succ c) |
|---|
| 50 |
--instance (CPlus a b c) => CPlus a (Succ b) (Succ c) |
|---|
| 51 |
|
|---|
| 52 |
class (Nat a, Nat b, Nat c) => CMax a b c | a b -> c |
|---|
| 53 |
instance CMax Zero Zero Zero |
|---|
| 54 |
instance Nat a => CMax (Succ a) Zero (Succ a) |
|---|
| 55 |
instance Nat a => CMax Zero (Succ a) (Succ a) |
|---|
| 56 |
instance CMax a b c => CMax (Succ a) (Succ b) (Succ c) |
|---|
| 57 |
|
|---|
| 58 |
class (Nat a, Nat b) => CDbl a b | a -> b |
|---|
| 59 |
instance CPlus a a b => CDbl a b |
|---|
| 60 |
|
|---|
| 61 |
class (Nat a, Nat b) => CPow2 a b | a -> b |
|---|
| 62 |
instance CPow2 Zero (Succ Zero) |
|---|
| 63 |
instance (CPow2 a b, CDbl b b2) => CPow2 (Succ a) b2 |
|---|
| 64 |
|
|---|
| 65 |
------------------------------------------------------------------------------- |
|---|
| 66 |
-- Sized integer. |
|---|
| 67 |
|
|---|
| 68 |
data IntSz n where |
|---|
| 69 |
IntSz :: Nat sz => Integer -> IntSz sz |
|---|
| 70 |
|
|---|
| 71 |
intSzSizeType :: IntSz n -> n; intSzSizeType _ = undefined |
|---|
| 72 |
intSzSize :: Nat n => IntSz n -> Int; intSzSize n = fromNat $ intSzSizeType n |
|---|
| 73 |
|
|---|
| 74 |
instance Nat sz => Eq (IntSz sz) where |
|---|
| 75 |
(IntSz a) == (IntSz b) = a == b |
|---|
| 76 |
|
|---|
| 77 |
instance Show (IntSz n) where |
|---|
| 78 |
show n@(IntSz x) = show x++"{"++show (intSzSize n)++"}" |
|---|
| 79 |
|
|---|
| 80 |
instance Nat sz => Num (IntSz sz) where |
|---|
| 81 |
fromInteger x = IntSz x |
|---|
| 82 |
(IntSz a) + (IntSz b) = IntSz $ a+b |
|---|
| 83 |
(IntSz a) - (IntSz b) = IntSz $ a-b |
|---|
| 84 |
(IntSz a) * (IntSz b) = IntSz $ a*b |
|---|
| 85 |
abs = error "No abs for IntSz." |
|---|
| 86 |
signum = error "No signum for IntSz." |
|---|
| 87 |
|
|---|
| 88 |
------------------------------------------------------------------------------- |
|---|
| 89 |
-- ToWires class, the main source of problems. |
|---|
| 90 |
|
|---|
| 91 |
class Nat aSz => ToWires a aSz | a -> aSz where |
|---|
| 92 |
wireSizeType :: a -> aSz |
|---|
| 93 |
wireSizeType _ = undefined |
|---|
| 94 |
wireSize :: a -> Int |
|---|
| 95 |
wireSize x = fromNat $ wireSizeType x |
|---|
| 96 |
wireMul :: a -> Integer |
|---|
| 97 |
wireMul x = Data.Bits.shiftL 1 (wireSize x) |
|---|
| 98 |
wireSelSize :: a -> Int |
|---|
| 99 |
wireSelSize = const 0 |
|---|
| 100 |
-- Integer should occupy no more than wireSize bits, higher ones should 0 |
|---|
| 101 |
toWires :: a -> Integer |
|---|
| 102 |
-- fromWires should work with integers that have non-zero bits |
|---|
| 103 |
-- above wireSize index. |
|---|
| 104 |
fromWires :: Integer -> a |
|---|
| 105 |
-- enumeration. |
|---|
| 106 |
-- valuesCount of (Maybe a) returns 1+valuesCount (x::a) |
|---|
| 107 |
-- valuesCount of Either a b returns valuesCount (x::a) + valuesCount (yLLb) |
|---|
| 108 |
-- valuesCount of (a,b) returns valuesCoutn (x::a) * valuesCount (y::b) |
|---|
| 109 |
valuesCount :: a -> Integer |
|---|
| 110 |
-- valueIndex. |
|---|
| 111 |
-- get a value and return an index inside enumeration. |
|---|
| 112 |
valueIndex :: a -> Integer |
|---|
| 113 |
|
|---|
| 114 |
------------------------------------------------------------------------------- |
|---|
| 115 |
-- Instances. |
|---|
| 116 |
|
|---|
| 117 |
instance (ToWires x a,ToWires y b, CPlus a b c) => ToWires (x,y) c where |
|---|
| 118 |
toWires (a,b) = Data.Bits.shiftL (toWires a) (wireSize b) .|. toWires b |
|---|
| 119 |
fromWires x = (a,b) |
|---|
| 120 |
where |
|---|
| 121 |
b = fromWires x |
|---|
| 122 |
a = fromWires $ Data.Bits.shiftR x (wireSize b) |
|---|
| 123 |
valuesCount (a,b) = valuesCount a*valuesCount b |
|---|
| 124 |
valueIndex (a,b) = valueIndex a*valuesCount b + valueIndex b |
|---|
| 125 |
|
|---|
| 126 |
instance (ToWires x1 a,ToWires x2 b,ToWires x3 c, |
|---|
| 127 |
CPlus b c bc, CPlus a bc abc) => |
|---|
| 128 |
ToWires (x1,x2,x3) abc where |
|---|
| 129 |
toWires (a,b,c) = toWires (a,(b,c)) |
|---|
| 130 |
fromWires abc = (a,b,c) |
|---|
| 131 |
where |
|---|
| 132 |
(a,(b,c)) = fromWires abc |
|---|
| 133 |
valuesCount (a,b,c) = valuesCount (a,(b,c)) |
|---|
| 134 |
valueIndex (a,b,c) = valueIndex (a,(b,c)) |
|---|
| 135 |
|
|---|
| 136 |
instance (ToWires x1 a,ToWires x2 b,ToWires x3 c,ToWires x4 d,ToWires x5 e, |
|---|
| 137 |
CPlus d e de, CPlus c de cde, CPlus b cde bcde, CPlus a bcde abcde) => |
|---|
| 138 |
ToWires (x1,x2,x3,x4,x5) abcde where |
|---|
| 139 |
toWires (a,b,c,d,e) = toWires (a,(b,(c,(d,e)))) |
|---|
| 140 |
fromWires abcde = (a,b,c,d,e) |
|---|
| 141 |
where |
|---|
| 142 |
(a,(b,(c,(d,e)))) = fromWires abcde |
|---|
| 143 |
valuesCount (a,b,c,d,e) = valuesCount (a,(b,(c,(d,e)))) |
|---|
| 144 |
valueIndex (a,b,c,d,e) = valueIndex (a,(b,(c,(d,e)))) |
|---|
| 145 |
|
|---|
| 146 |
instance CPow2 FIVE size32 => ToWires Int size32 where |
|---|
| 147 |
toWires n = fromIntegral n .&. 0xffffffff |
|---|
| 148 |
fromWires x = fromIntegral x |
|---|
| 149 |
valuesCount = const (Data.Bits.shiftL (1::Integer) 32) |
|---|
| 150 |
valueIndex = fromIntegral |
|---|
| 151 |
|
|---|
| 152 |
instance CPow2 FIVE size32 => ToWires Word32 size32 where |
|---|
| 153 |
toWires n = fromIntegral n .&. 0xffffffff |
|---|
| 154 |
fromWires x = fromIntegral x |
|---|
| 155 |
valuesCount = const (Data.Bits.shiftL (1::Integer) 32) |
|---|
| 156 |
valueIndex = fromIntegral |
|---|
| 157 |
|
|---|
| 158 |
instance Nat size => ToWires (IntSz size) size where |
|---|
| 159 |
toWires x@(IntSz n) = n .&. (Data.Bits.shiftL 1 (wireSize x) - 1) |
|---|
| 160 |
fromWires x = fromIntegral x |
|---|
| 161 |
valuesCount x = Data.Bits.shiftL (1::Integer) (wireSize x) |
|---|
| 162 |
valueIndex x = toWires x |
|---|
| 163 |
|
|---|
| 164 |
------------------------------------------------------------------------------- |
|---|
| 165 |
-- Types for a problem. |
|---|
| 166 |
|
|---|
| 167 |
-- A hack around bugs (??) in ghc 6.10.1. |
|---|
| 168 |
data RI = RI (IntSz FIVE) |
|---|
| 169 |
deriving (Eq,Show) |
|---|
| 170 |
data Imm5 = Imm5 (IntSz FIVE) |
|---|
| 171 |
deriving (Eq,Show) |
|---|
| 172 |
data Imm16 = Imm16 (IntSz SIZE16) |
|---|
| 173 |
deriving (Eq,Show) |
|---|
| 174 |
data Imm26 = Imm26 (IntSz SIZE26) |
|---|
| 175 |
deriving (Eq,Show) |
|---|
| 176 |
|
|---|
| 177 |
instance ToWires RI FIVE where |
|---|
| 178 |
toWires (RI x) = toWires x |
|---|
| 179 |
fromWires x = RI $ fromWires x |
|---|
| 180 |
valuesCount = const 32 |
|---|
| 181 |
valueIndex (RI x) = toWires x |
|---|
| 182 |
|
|---|
| 183 |
instance ToWires Imm5 FIVE where |
|---|
| 184 |
toWires (Imm5 x) = toWires x |
|---|
| 185 |
fromWires x = Imm5 $ fromWires x |
|---|
| 186 |
valuesCount = const 32 |
|---|
| 187 |
valueIndex (Imm5 x) = toWires x |
|---|
| 188 |
|
|---|
| 189 |
instance ToWires Imm16 SIZE16 where |
|---|
| 190 |
toWires (Imm16 x) = toWires x |
|---|
| 191 |
fromWires x = Imm16 $ fromWires x |
|---|
| 192 |
valuesCount (Imm16 x) = valuesCount x |
|---|
| 193 |
valueIndex (Imm16 x) = valueIndex x |
|---|
| 194 |
|
|---|
| 195 |
instance ToWires Imm26 SIZE26 where |
|---|
| 196 |
toWires (Imm26 x) = toWires x |
|---|
| 197 |
fromWires x = Imm26 $ fromWires x |
|---|
| 198 |
valuesCount (Imm26 x) = valuesCount x |
|---|
| 199 |
valueIndex (Imm26 x) = toWires x |
|---|
| 200 |
|
|---|
| 201 |
instance ToWires a sz => ToWires (Maybe a) (Succ sz) where |
|---|
| 202 |
toWires Nothing = 0 |
|---|
| 203 |
toWires (Just x) = shiftL (toWires x) 1 .|. 1 |
|---|
| 204 |
fromWires = undefined |
|---|
| 205 |
valuesCount x = 1+valuesCount y |
|---|
| 206 |
where |
|---|
| 207 |
~(Just y) = x |
|---|
| 208 |
|
|---|
| 209 |
valueIndex Nothing = 0 |
|---|
| 210 |
valueIndex (Just x) = 1+valueIndex x |
|---|
| 211 |
|
|---|
| 212 |
------------------------------------------------------------------------------- |
|---|
| 213 |
-- And a problem itself. |
|---|
| 214 |
|
|---|
| 215 |
data Signed = Signed | Unsigned |
|---|
| 216 |
deriving (Eq,Show) |
|---|
| 217 |
|
|---|
| 218 |
data MIPSCmd regv = |
|---|
| 219 |
Nop |
|---|
| 220 |
| Trap |
|---|
| 221 |
-- we mark destination register with RI. It never gets fetched. |
|---|
| 222 |
-- we mark source registers as regv, because they can change their size |
|---|
| 223 |
-- at FETCH stage (became Word32). |
|---|
| 224 |
| AddU regv regv RI |
|---|
| 225 |
| And regv regv RI |
|---|
| 226 |
| Div Signed regv regv |
|---|
| 227 |
deriving (Eq,Show) |
|---|
| 228 |
|
|---|
| 229 |
instance ToWires Signed (Succ Zero) where |
|---|
| 230 |
toWires (Signed) = Data.Bits.shiftL 0 1 .|. 0 |
|---|
| 231 |
toWires (Unsigned) = Data.Bits.shiftL 0 1 .|. 1 |
|---|
| 232 |
fromWires x = undefined |
|---|
| 233 |
valuesCount x = 1 + (1 + 0) |
|---|
| 234 |
where |
|---|
| 235 |
~(Signed) = x |
|---|
| 236 |
~(Unsigned) = x |
|---|
| 237 |
valueIndex x = case x of |
|---|
| 238 |
Signed -> 0 + 0 |
|---|
| 239 |
Unsigned -> (0 + 0) + 0 |
|---|
| 240 |
where |
|---|
| 241 |
~(Signed) = x |
|---|
| 242 |
~(Unsigned) = x |
|---|
| 243 |
|
|---|
| 244 |
instance (ToWires regv_0 v_1, ToWires RI v_2, |
|---|
| 245 |
CPlus v_1 v_1 vCPlus_3, CPlus vCPlus_3 v_2 vCPlus_4, |
|---|
| 246 |
CPlus v_1 v_1 vCPlus_5, CPlus vCPlus_5 v_2 vCPlus_6, |
|---|
| 247 |
ToWires Signed v_7, CPlus v_7 v_1 vCPlus_8, CPlus vCPlus_8 v_1 vCPlus_9, |
|---|
| 248 |
CMax vCPlus_4 vCPlus_6 vCMax_10, CMax vCMax_10 vCPlus_9 vCMax_11) |
|---|
| 249 |
=> ToWires (MIPSCmd regv_0) (Succ (Succ (Succ vCMax_11))) where |
|---|
| 250 |
|
|---|
| 251 |
toWires (Nop) = Data.Bits.shiftL 0 3 .|. 0 |
|---|
| 252 |
toWires (Trap) = Data.Bits.shiftL 0 3 .|. 1 |
|---|
| 253 |
toWires (AddU a_12 a_13 a_14) = |
|---|
| 254 |
Data.Bits.shiftL (Data.Bits.shiftL (Data.Bits.shiftL (Data.Bits.shiftL 0 (wireSize a_12) .|. toWires a_12) (wireSize a_13) .|. toWires a_13) (wireSize a_14) .|. toWires a_14) 3 .|. 2 |
|---|
| 255 |
toWires (And a_15 a_16 a_17) = |
|---|
| 256 |
Data.Bits.shiftL (Data.Bits.shiftL (Data.Bits.shiftL (Data.Bits.shiftL 0 (wireSize a_15) .|. toWires a_15) (wireSize a_16) .|. toWires a_16) (wireSize a_17) .|. toWires a_17) 3 .|. 3 |
|---|
| 257 |
toWires (Div a_18 a_19 a_20) = |
|---|
| 258 |
Data.Bits.shiftL (Data.Bits.shiftL (Data.Bits.shiftL (Data.Bits.shiftL 0 (wireSize a_18) .|. toWires a_18) (wireSize a_19) .|. toWires a_19) (wireSize a_20) .|. toWires a_20) 3 .|. 4 |
|---|
| 259 |
fromWires x = undefined |
|---|
| 260 |
valuesCount x = 1 + (1 + ((valuesCount x_21 * (valuesCount x_22 * (valuesCount x_23 * 1))) + ((valuesCount x_24 * (valuesCount x_25 * (valuesCount x_26 * 1))) + ((valuesCount x_27 * (valuesCount x_28 * (valuesCount x_29 * 1))) + 0)))) |
|---|
| 261 |
where |
|---|
| 262 |
~(Nop) = x |
|---|
| 263 |
~(Trap) = x |
|---|
| 264 |
~(AddU x_21 x_22 x_23) = x |
|---|
| 265 |
~(And x_24 x_25 x_26) = x |
|---|
| 266 |
~(Div x_27 x_28 x_29) = x |
|---|
| 267 |
valueIndex x = case x of |
|---|
| 268 |
Nop -> 0 + 0 |
|---|
| 269 |
Trap -> (0 + 0) + 0 |
|---|
| 270 |
-- THE PROBLEM!!! |
|---|
| 271 |
AddU ax_30 ax_31 ax_32 -> |
|---|
| 272 |
((0 + 0) + 0) + valueIndex (ax_32,(ax_30, ax_31)) |
|---|
| 273 |
-- /THE PROBLEM!!! |
|---|
| 274 |
{- |
|---|
| 275 |
And x_33 x_34 x_35 -> (((0 + 0) + 0) + valuesCount (x_32, |
|---|
| 276 |
(x_30, |
|---|
| 277 |
x_31))) + valueIndex (x_35, |
|---|
| 278 |
(x_33, |
|---|
| 279 |
x_34)) |
|---|
| 280 |
-} |
|---|
| 281 |
Div x_36 x_37 x_38 -> ((((0 + 0) + 0) + valuesCount (x_32,(x_30,x_31))) + valuesCount (x_35,(x_33,x_34))) + |
|---|
| 282 |
-- valueIndex (x_38,(x_36,x_37)) |
|---|
| 283 |
valueIndex x_38*valuesCount x_36*valuesCount x_37 + valueIndex x_36 * valuesCount x_37+valueIndex x_37 |
|---|
| 284 |
where ~(Nop) = x |
|---|
| 285 |
~(Trap) = x |
|---|
| 286 |
~(AddU x_30 x_31 x_32) = x |
|---|
| 287 |
~(And x_33 x_34 x_35) = x |
|---|
| 288 |
~(Div x_36 x_37 x_38) = x |
|---|