Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Can't create selector: `TyCon` has no `DataCons`" error when trying to reify clock period from `Clock` constructor to term level #348

Open
gergoerdi opened this Issue Sep 8, 2018 · 6 comments

Comments

Projects
None yet
3 participants
@gergoerdi
Copy link

gergoerdi commented Sep 8, 2018

Given this module:

import Clash.Prelude hiding (clkPeriod)
import Clash.Signal.Internal (Clock(..))

clkPeriod :: Clock dom gated -> Integer
clkPeriod (Clock _ period) = snatToInteger period
clkPeriod (GatedClock _ period _) = snatToInteger period

clkRate :: Clock dom gated -> Integer
clkRate clk = 10^12 `div` clkPeriod clk

when I try using clkRate from somewhere accessible from my topEntity, it crashes with the following error message:

*** Exception: Clash.Rewrite.Util(566): Can't create selector ("Clash.Normalize.Transformations(1136): doPatBndr",1,0) for: ($dKnownNat23000 :: GHC.Natural.Natural)
Additional info: TyCon has no DataCons: Name {nameSort = User, nameOcc = GHC.Natural.Natural3674937295934324782, nameLoc = UnhelpfulSpan "<no location info>"} GHC.Natural.Natural3674937295934324782
CallStack (from HasCallStack):
  error, called at src/Clash/Rewrite/Util.hs:583:35 in clash-lib-0.99.3-KL27I695LX557MJWOLD5fy:Clash.Rewrite.Util

@gergoerdi

This comment has been minimized.

Copy link
Author

gergoerdi commented Sep 8, 2018

I should mention that clkRate/clkPeriod as defined above behaves quite weird in the simulator as well, as if it was always using the System clock domain:

*> sampleN 1 $ pure $ hideClock $ \(clk :: Clock (Dom "foo" 1234) Source) -> clkPeriod clk
[10000]

shouldn't this return [1234]?

In fact, even without using any custom functions, we can see in the simulator that something is very, very wrong:

*> sampleN 1 $ pure $ hideClock $ \(clk :: Clock (Dom "foo" 1234) Source) -> show clk
["system10000"]

@christiaanb christiaanb added the bug label Sep 8, 2018

@Jhana1

This comment has been minimized.

Copy link
Contributor

Jhana1 commented Sep 11, 2018

I'm having a similar issue without reifying the clock domain (but still involving reifying type level Nats to the term level)

I'm working on reducing it down to a minimal repro, hopefully I'll be able to show it working with 0.7 (which the more complex/full example does) and failing on 0.99.3 (which is currently blocking me from upgrading, and has been since at least April of this year)

@gergoerdi

This comment has been minimized.

Copy link
Author

gergoerdi commented Sep 11, 2018

Here's a full, standalone repro for my problem:

module Test where

import Clash.Prelude hiding (clkPeriod)
import Data.Word
import Clash.Signal.Internal (Clock(..))

type FromHz rate = 1000000000000 `Div` rate
type Dom25 = Dom "CLK_25MHZ" (FromHz 25175000)

topEntity
    :: Clock Dom25 Source
    -> Reset Dom25 Asynchronous
    -> Signal Dom25 Bit
topEntity = exposeClockReset board
  where
    board = boolToBit <$> r

    r = regEn False (counter .==. 0) (not <$> r)
    counter = register clkrt $ mux (counter .==. 0) (pure clkrt) (pred <$> counter)
    clkrt = fromIntegral $ hideClock clkRate

clkPeriod :: Clock dom gated -> Integer
clkPeriod (Clock _ period) = snatToInteger period
clkPeriod (GatedClock _ period _) = snatToInteger period

clkRate :: Clock dom gated -> Integer
clkRate clk = 10^12 `div` clkPeriod clk

@Jhana1

This comment has been minimized.

Copy link
Contributor

Jhana1 commented Sep 11, 2018

If you avoid pattern matching on the clock constructors (which I'm not sure if you're allowed to do?) then you can avoid the problem. e.g.

module Test where

import           Clash.Prelude         hiding (clkPeriod)
import           Clash.Signal.Internal (Clock (..))
import           Data.Word

type FromHz rate = 1000000000000 `Div` rate
type Dom25 = Dom "CLK_25MHZ" (FromHz 25175000)

topEntity
    :: Clock Dom25 Source
    -> Reset Dom25 Asynchronous
    -> Signal Dom25 Bit
topEntity = exposeClockReset board
  where
    board = boolToBit <$> r

    r = regEn False (counter .==. 0) (not <$> r)
    counter = register clkrt $ mux (counter .==. 0) (pure clkrt) (pred <$> counter)
    clkrt = fromIntegral $ hideClock clkRate

clkPeriod :: forall name period gated . KnownNat period => Clock (Dom name period) gated -> Integer
clkPeriod _ = snatToInteger $ SNat @period

clkRate :: KnownNat period => Clock (Dom name period) gated -> Integer
clkRate clk = 10^12 `div` clkPeriod clk
@gergoerdi

This comment has been minimized.

Copy link
Author

gergoerdi commented Sep 12, 2018

@christiaanb

This comment has been minimized.

Copy link
Contributor

christiaanb commented Sep 12, 2018

So the issue is that the Core we're getting is pattern-matching on something of type Integer and exposing the internals of its representation; something the compiler obviously doesn't handle. I'll create a work-around/hack to always pick the branch where the Integer fits inside the [-2^63 .. 2^63-1] range, since Clash currently "erroneously" translates Integer to 64-bit numbers anyways.

@christiaanb christiaanb added this to the 1.0 milestone Dec 18, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.