clash-lang / clash-compiler

Haskell to VHDL/Verilog/SystemVerilog compiler
https://clash-lang.org/
Other
1.44k stars 154 forks source link

"Can't translate non-tycon type" with latest version of CLaSH #461

Closed gergoerdi closed 5 years ago

gergoerdi commented 5 years ago

The following CLaSH code compiles into VHDL with CLaSH 0.99.3 (with all the references to Undefined removed), but fails with f2060a07705b:

The source code as a single module:

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, DerivingStrategies #-}
module CHIP8 where

import Clash.Prelude hiding (lift)
import Control.Monad.State
import Data.Word
import Control.Monad.RWS
import Data.Monoid

{-# NOINLINE topEntity #-}
topEntity
    :: Clock System Source
    -> Reset System Asynchronous
    -> ( Signal System Bit
       )
topEntity = exposeClockReset output
  where
    cpuIn = pure CPUIn{ cpuInMem = 0x00 }
    cpuOut = mealyState (runCPU defaultOut cpu) initState cpuIn
    output = boolToBit . (== 0x00) . cpuOutMemAddr <$> cpuOut

mealyState :: (HiddenClockReset domain gated synchronous, Undefined s)
           => (i -> State s o) -> s -> (Signal domain i -> Signal domain o)
mealyState f = mealy $ \s x -> let (y, s') = runState (f x) s in (s', y)

data Phase
    = Init
    | Fetch1
    | Exec
    deriving (Generic, Undefined)

data CPUIn = CPUIn
    { cpuInMem :: Word8
    }

data CPUState = CPUState
    { pc :: Word8
    , phase :: Phase
    }
    deriving (Generic, Undefined)

initState :: CPUState
initState = CPUState
    { pc = 0x20
    , phase = Init
    }

data CPUOut = CPUOut
    { cpuOutMemAddr :: Word8
    }

defaultOut :: CPUState -> CPUOut
defaultOut CPUState{..} = CPUOut{..}
  where
    cpuOutMemAddr = pc

cpu :: CPU CPUIn CPUState CPUOut ()
cpu = do
    CPUIn{..} <- input
    CPUState{..} <- get

    case phase of
        Init -> goto Fetch1
        Fetch1 -> goto Init
  where
    goto ph = modify $ \s -> s{ phase = ph }

newtype CPU i s o a = CPU{ unCPU :: RWS i (Endo o) s a }
                    deriving newtype (Functor, Applicative, Monad, MonadState s)

input :: CPU i s o i
input = CPU ask

runCPU :: (s -> o) -> CPU i s o () -> (i -> State s o)
runCPU mkDef cpu inp = do
    s <- get
    let (s', f) = execRWS (unCPU cpu) inp s
    put s'
    def <- gets mkDef
    return $ appEndo f def

Here is the error message with f2060a07705b:

$ clash -isrc -outputdir _build  --vhdl src/CHIP8.hs

Loading dependencies took 2.207219931s
Parsing and compiling primitives took 0.736510531s
Compiling: CHIP8.topEntity
Applied 117 transformations
Normalisation took 0.755448261s

<no location info>: error:
    Clash.Netlist(260): Can't translate non-tycon type: CHIP8.CPUOut -> CHIP8.CPUOut

    NB: The source location of the error is not exact, only indicative, as it is acquired after optimisations.
    The actual location of the error can be in a function that is inlined.
    To prevent inlining of those functions, annotate them with a NOINLINE pragma.
martijnbastiaan commented 5 years ago

Thanks for the report! I'll see if I can find which commit breaks it.

martijnbastiaan commented 5 years ago

Commit https://github.com/clash-lang/clash-compiler/commit/32489b7a7b91f80a7fdcb4dcb3b88b366cd2dfae changes the type of EmptyCase, causing https://github.com/clash-lang/clash-compiler/blob/f2060a07705b5a76addd8240a999b187848544f2/clash-lib/src/Clash/Normalize/Transformations.hs#L411 to misfire. Will fix in a bit.