GithubHelp home page GithubHelp logo

clash-lang / clash-prelude Goto Github PK

View Code? Open in Web Editor NEW
31.0 31.0 27.0 3.37 MB

CLaSH prelude library containing datatypes and functions for circuit design

Home Page: http://www.clash-lang.org/

License: Other

Haskell 100.00%

clash-prelude's People

Contributors

basile-henry avatar bgamari avatar blaxill avatar bosj avatar cbiffle avatar christiaanb avatar cramsay avatar danielg avatar dented42 avatar digitalbrains1 avatar eagleerwin avatar ericson2314 avatar expipiplus1 avatar ggreif avatar jhana1 avatar jonfowler avatar leonschoorl avatar martijnbastiaan avatar strake avatar thoughtpolice avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clash-prelude's Issues

Make indexing/subscript of `Vec` ascending

Currently, the Vec type has a descending index, meaning the following:

v ! 0  == vlast v

The original reason for the descending index was to ensure the following equality:

testBit (s :: Signed n) 0 == ((toBV (s :: Signed n)) ! 0 == H)

That is, bit-encoding for numbers usually have the least-significant bit get the lowest subscript, and the most-significant bit the highest.

While the descending index makes sense for the bit-encoding of numbers, it is rather inconvenient for vectors in general. The proposal is thus to make the index/subscript of vectors ascending, like they are for other list-like structures in Haskell.

Perhaps it makes sense to also add an additional BitVector type which does have the descending index.

BlockRam write logic is clumsy to say the least

(Block)Ram write logic involves 3 distinct signals which are semantically coupled. Why not also represent them together? I came up with this adapter that consolidates the write logic to a Maybe (addr, dta):

maybeWrite :: (Signal addr -> Signal addr -> Signal Bool -> Signal dt -> Signal dt)
           -> Signal (Maybe (addr, dt)) -> Signal addr -> Signal dt
maybeWrite ram wr rd = ram wrAddr rd wrEn wrData
  where apart (Just (addr, dt)) = (True, addr, dt)
        apart Nothing = (False, undefined, undefined)
        (wrEn, wrAddr, wrData) = unbundle (apart <$> wr)

This invites the whole zoo of utilities dealing with Maybe. Which is a good thing.

What do you think? Would a pull request be accepted for inclusion? Maybe even make this the default interface to (block)Rams?

Could v be renamed?

Having a top-level identifier called v really pollutes the global namespace. Could it be renamed? (After a suitable deprecation cycle, of course).

Package name "CLaSH" is a disaster to type

The «two caps — small letter — two caps» is so unusual pattern, so I just cannot type it automatically, I need to fix my attention to that ridiculous casing. What's wrong with plain «Clash»?

Replace uses of undefined with error

It would be handy to know where an undefined value is coming from when running CLaSH dependent code through GHC.

Replacing uses of undefined with error "Some helpful string" would be very helpful.

Provide patterns for Bit

I just came up with these bidirectional pattern synonyms for high and low:

pattern I <- ((==high) -> True)
  where I = high
pattern O <- ((==low) -> True)
  where O = low

I'll happily submit a pull request if you think that they are useful.

Supply more common memory structures (in a highlevel style)

Currently the Clash prelude only supplies memory structures that are lowlevel wrapper around some vhdl primitives. This induces bugs and forces everyone to reinvent the wheel for using common memory structures.
The issue of lowlevel interface has been discussed in #42, and I agree the default blockRam signature should be something more Haskell like as in:
(KnownNat n, Enum addr) => Vec n a -> Signal addr -> Signal (Maybe (Addr, a)) -> Signal a

Besides that other common read/write port arrangements should be provided, such as a ram block with 2 read ports, and the more asic oriented ram with a single shared read/write port.

Also a vector memory or memory with a writemask (depending on your point of view) is quite useful:
vecmem :: (KnownNat n, KnownNat m, Enum addr) => Vec n (Vec m a) -> Signal addr -> Signal (Vec m (Maybe (Addr, a))) -> Signal (Vec m a)

As a discussion point, would be registerFile and lookupTable better names for asyncRam and asyncRom?

For register files a two read port variant is an essential building block in many designs.

I also would like a general n-read m-write port registerfile, if that is feasible in a synthesizable manner.

And it would be nice to supply other common memory structures such as fifos and stacks, although those have many variantions and may causes some bikeshedding.

Non-translatable `Enum` function interfere with `sassert` compilation

The Enum functions:

    -- | Used in Haskell's translation of @[n..]@.
    enumFrom            :: a -> [a]
    -- | Used in Haskell's translation of @[n,n'..]@.
    enumFromThen        :: a -> a -> [a]
    -- | Used in Haskell's translation of @[n..m]@.
    enumFromTo          :: a -> a -> [a]
    -- | Used in Haskell's translation of @[n,n'..m]@.
    enumFromThenTo      :: a -> a -> a -> [a]

Have a default implementation that currently result in the compiler complaining about not being able remove recursion.

This shows up for the sassert and csassert functions when applied to Signed and Unsigned.

The solution is to not use the default implementation, and mark the new implementation as NOINLINE.

build failure w/ GHC 8.0.2

clash-prelude-0.11 fails to build under ghc-8.0.2 w/ both hackage and github versions, failure is:

src/CLaSH/Prelude/Synchronizer.hs:136:17: error:
    • Could not deduce (GHC.TypeLits.KnownNat
                          ((addrSize + 1) - (addrSize - 1)))
        arising from a use of ‘complement’
      from the context: 2 <= addrSize
        bound by the type signature for:
                   isFull :: (2 <= addrSize) =>
                             SNat addrSize
                             -> BitVector (addrSize + 1) -> BitVector (addrSize + 1) -> Bool
        at src/CLaSH/Prelude/Synchronizer.hs:(126,1)-(131,14)
      or from: GHC.TypeLits.KnownNat addrSize
        bound by a pattern with constructor:
                   SNat :: forall (n :: GHC.Types.Nat).
                           GHC.TypeLits.KnownNat n =>
                           SNat n,
                 in an equation for ‘isFull’
        at src/CLaSH/Prelude/Synchronizer.hs:132:17-20
      or from: 1 <= addrSize
        bound by a pattern with constructor:
                   Dict :: forall (a :: Constraint). a => Dict a,
                 in a case alternative
        at src/CLaSH/Prelude/Synchronizer.hs:133:7-10
    • In the first argument of ‘(++#)’, namely
        ‘complement (slice addrSize a1 s_ptr)’
      In the second argument of ‘(==)’, namely
        ‘(complement (slice addrSize a1 s_ptr) ++# slice a2 d0 s_ptr)’
      In the expression:
        ptr == (complement (slice addrSize a1 s_ptr) ++# slice a2 d0 s_ptr)

Comonad instance for Vec

This is a (low-prio) feature request. Comonad interface is very convenient for looking at a vector from all perspectives (indices) at once. It allows tranformations of the entire vector by allowing the mapping to peek into neighbouring elements . Think blurring of pixels 0, or other image transformations 1. Writing down the instance is easy:

{-# language DeriveFunctor, TupleSections #-}

module CoVec where

import CLaSH.Prelude hiding (extend)
import Control.Comonad

newtype CoVec n a = CoVec (Index n, Vec n a) deriving (Eq, Show, Functor)

instance KnownNat n => Comonad (CoVec n) where
  extract (CoVec (i, v)) = v !! i
  duplicate (CoVec (i, v)) = CoVec (i, CoVec . (,v) <$> indicesI)

The question is whether one wants to add the Comonad dependency.

Another problem might be the consumption of logical resources (LUTs). I did not evaluate this issue.

GHC HEAD compile error

(I tried --ghc-options="-fplugin GHC.TypeLits.Normalise" but it did not help)

Maybe below error messages ring a bell what could have gone wrong...

[21 of 42] Compiling CLaSH.Sized.Fixed ( src/CLaSH/Sized/Fixed.hs, dist/dist-sandbox-fa345477/build/CLaSH/Sized/Fixed.o )

src/CLaSH/Sized/Fixed.hs:116:1: error:
    Couldn't match representation of type ?a2?
                             with that of ?rep (int + frac)?
      arising from a use of ?coerce?
    Relevant bindings include
      minBound :: Fixed rep int frac
        (bound at src/CLaSH/Sized/Fixed.hs:116:1)
    In the expression:
        coerce (minBound :: rep ((+) int frac)) :: Fixed rep int frac
    In an equation for ?minBound?:
        minBound
          = coerce (minBound :: rep ((+) int frac)) :: Fixed rep int frac
    When typechecking the code for ?minBound?
      in a derived instance for ?Bounded (Fixed rep int frac)?:
      To see the code I am typechecking, use -ddump-deriv
    In the instance declaration for ?Bounded (Fixed rep int frac)?

src/CLaSH/Sized/Fixed.hs:116:1: error:
    Couldn't match representation of type ?a3?
                             with that of ?rep (int + frac)?
      arising from a use of ?coerce?
    Relevant bindings include
      maxBound :: Fixed rep int frac
        (bound at src/CLaSH/Sized/Fixed.hs:116:1)
    In the expression:
        coerce (maxBound :: rep ((+) int frac)) :: Fixed rep int frac
    In an equation for ?maxBound?:
        maxBound
          = coerce (maxBound :: rep ((+) int frac)) :: Fixed rep int frac
    When typechecking the code for ?maxBound?
      in a derived instance for ?Bounded (Fixed rep int frac)?:
      To see the code I am typechecking, use -ddump-deriv
    In the instance declaration for ?Bounded (Fixed rep int frac)?

src/CLaSH/Sized/Fixed.hs:117:1: error:
    Couldn't match representation of type ?a1?
                             with that of ?rep (int + frac)?
      arising from a use of ?coerce?
    Relevant bindings include
      def :: Fixed rep int frac (bound at src/CLaSH/Sized/Fixed.hs:117:1)
    In the expression:
        coerce (def :: rep ((+) int frac)) :: Fixed rep int frac
    In an equation for ?def?:
        def = coerce (def :: rep ((+) int frac)) :: Fixed rep int frac
    When typechecking the code for ?def?
      in a derived instance for ?Default (Fixed rep int frac)?:
      To see the code I am typechecking, use -ddump-deriv
    In the instance declaration for ?Default (Fixed rep int frac)?

src/CLaSH/Sized/Fixed.hs:123:1: error:
    Couldn't match representation of type ?a0?
                             with that of ?rep (int + frac)?
      arising from a use of ?coerce?
    Relevant bindings include
      zeroBits :: Fixed rep int frac
        (bound at src/CLaSH/Sized/Fixed.hs:123:1)
    In the expression:
        coerce (zeroBits :: rep ((+) int frac)) :: Fixed rep int frac
    In an equation for ?zeroBits?:
        zeroBits
          = coerce (zeroBits :: rep ((+) int frac)) :: Fixed rep int frac
    When typechecking the code for ?zeroBits?
      in a derived instance for ?Bits (Fixed rep int frac)?:
      To see the code I am typechecking, use -ddump-deriv
    In the instance declaration for ?Bits (Fixed rep int frac)?
Failed to install clash-prelude-0.10
cabal.lnk: Error: some packages failed to install:
clash-prelude-0.10 failed during the building phase. The exception was:
ExitFailure 1

Should signal be that general?

The function signal currently has the type:

signal :: Applicative f => a -> f a

It seems like it is simply an alias for pure. But I encountered a situation where a type inference failed because of this. I had a component that wrapped another component (adding functionality on top) and where the inner component had a constant output (unused functionality of a connected piece of hardware). The following dumb code illustrates the issue:

module Test where

import CLaSH.Prelude
import CLaSH.Signal.Internal (signal#)

c1 i = (o1, o2)
    where
        o1 = register 0 i
        o2 = signal 0
        -- Works:
        -- o2 = signal# 0

c2 i = (o1, o2)
    where
        (o1, o2) = c1 i

This fails with the following error:

Test.hs:15:9: error:
    • Could not deduce (Applicative f0)
      from the context: (Num a1, Num a, Applicative f)
        bound by the inferred type of
                 c2 :: (Num a1, Num a, Applicative f) =>
                       Signal a1 -> (Signal a1, f a)
        at Test.hs:(13,1)-(15,23)
      The type variable ‘f0’ is ambiguous
    • When checking that the inferred type
        o1 :: forall a (f :: * -> *). (Applicative f, Num a) => Signal a1
      is as general as its inferred signature
        o1 :: Signal a1
      In an equation for ‘c2’:
          c2 i
            = (o1, o2)
            where
                (o1, o2) = c1 i
Failed, modules loaded: none.

As noted in the example code, using a less general version of signal solves the issue and correctly infers the type of the functions.

Does it serve a purpose that signal is this general? We already have pure anyway, and in which case would you use a function called signal to create something different than a Signal? :-) Perhaps there is a totally valid reason to do it like it is now, but I'd like to point out that it can force people to add type declarations where type inference could otherwise do a fine job.

maxIndex on Vec is inconsistent with maxIndex from Data.Vector

Data.Vector maxIndex returns "the index of the maximum element of the vector". This is completely different from Clash's maxIndex from CLaSH.Sized.Vector which is "The index (subscript) of the last element in a Vector as an Int value.".

At the very least there should be a big warning that these are different. However, Clash's maxIndex is redundant because that information is present in the type so I would go even further and either remove maxIndex from Clash or (more dangerously) change it to the Data.Vector behavior and perhaps add a differently named function with Data.Vector's behaviour.

Moore machine combinatores

We have mealy machines in here, why not more machines? While its not too hard to use the Mealy combinators to make a more machine, I found myself using Moore machines often enough to warrant writing the contaminator. I'd be happy to submit a pull request if you want one.

Better interface for regEn

regEn would be strictly typesafer if its signature were

regEn :: a -> Signal (Maybe a) -> Signal a

rather than

regEn :: a -> Signal Bool -> Signal a -> Signal a

This is very similar to #42

Something triggering invalid infinite loop detection

This occurs in the Haskell simulation, I can't easily verify the HDL version behaves the same currently.

This might also be my code at fault, but I can't see how, it seems to be something introduced by either the lift into the Mealy state machine or Signal or the BlockRAM implementation, it's hard to pinpoint.

The code that triggers it is here https://github.com/polygonhell/J1LikeCPU

If I run "main", which just simulates the first 5 steps of the CPU, I get *** Exception: < loop >
If I run "test" which does basically the same thing, but without the Signal mechanics and using a List instead of RAM it appears to work.

What triggers it appears to be the next PC being dependent on the current instruction, if you goto line 193, and replace the code that generates pc' with simply pc' = pc + 1, main will complete correctly.
Note that in both cases pc' = pc + 1 for all inputs.

Obviously instruction is dependent on the previous pc, since that's how it was looked up, and this seems like the obvious potential issue, but I can't see how this introduces an infinite loop.

TopEntity annotations don't support differential clock sources

Creating a "wrapper" for the ClockWizard generated IP in Vivado I get

architecture STRUCTURE of design_1 is
  component design_1_clk_wiz_0_0 is
  port (
    clk_in1_p : in STD_LOGIC;
    clk_in1_n : in STD_LOGIC;
    clk_out1 : out STD_LOGIC;
    reset : in STD_LOGIC;
    locked : out STD_LOGIC
  );
  end component design_1_clk_wiz_0_0;

This is not supported by the current TopEntity generator.

asyncRam' :: Enum addr => SClock wclk -> SClock rclk -> SNat n -> Signal' wclk (Maybe (addr, a)) -> Signal' rclk (addr -> a)

and likewise asyncRam.

The path from read address to output is combinational, which we can so encode in the type.

My use case is a register file where we have a Signal (Either RegNum Word), either a register number or an immediate value, and we want a Signal Word, either the value in that register or the immediate value. It is much more convenient and less heinous with the proposed type of asyncRam:

liftA2 (flip either id) (asyncRam _ _) :: Signal (Either RegNum Word) -> Signal Word

versus

(\ rsi ->
 let rs = either id (pure undefined) <$> rsi
 in liftA2 (\ x -> either (pure x) id) (asyncRam _ _ rs) rsi) :: Signal (Either RegNum Word) -> Signal Word

moore' can't be synthesized?

When I try to compile a design that uses a moore machine, I get the following error:

Loading dependencies took 17.130628s

<no location info>:
    CLaSH Error:
CLaSH.Normalize(180): Callgraph after normalisation contains following recursive cycles: [[CLaSH.Prelude.Moore.$wmoore'_s1138]]
make: *** [out/gen/vhdl/*.vhdl] Error 1

It seems to indicate that moore machines can't be synthesized? but I'm wondering if perhaps optimizations are hiding the fact that the problem is in my program. If that's the case then I suppose this is really a compiler bug because it's failing to leave an appropriate error message.

Function to replace slice of vector

Would it be possible to add a function, replaceVec, similar to "replace" from CLaSH.Sized.Vector which replaces a slice instead of a single element?
Perhaps something like:

replaceVec :: (KnownNat m) => SNat o -> Vec m a -> Vec (o + p + m) a -> Vec (o + p + m) a
replaceVec offset replacement vec = vecTruncated ++ replacement ++ vecTail
    where
    vecTruncated =  take offset vec
    vecTail      =  drop (offset `addSNat` lengthS replacement) vec

(Feature req) Better optimisation for operator /=

Operator /= is not threated same at optimisation as ==. Where there is possibility for code to be optimised away operator == works better (eliminates dead code) where /= does not

To show this we need some non trivial functions that generates files

common code

module Pg2 where
import CLaSH.Prelude

type T = Signed 8

funcA :: T -> T
funcA a = fold (+) $ a :> 1 :> 2 :> 3 :> Nil

funcB :: T -> T
funcB a = fold (+) $ a :> 2 :> 3 :> 4 :> Nil

topEntity = funcC d0

Using ==

funcC :: (KnownNat n) => SNat n -> T -> T
funcC s
    | not ( snatToInteger s == 0 ) = funcA . funcA
    | otherwise = funcB . funcB

compiling to verilog generates this files

Pg2_funcB_2.v
Pg2_funcC_zdsfuncC_1.v
Pg2_testbench.v
Pg2_topEntity_0.v
Pg2_topEntity.v

We see that funcA is optimised out
Now same code with operator /=

funcC :: (KnownNat n) => SNat n -> T -> T
funcC s
    | snatToInteger s /= 0 = funcA . funcA
    | otherwise = funcB . funcB

generated files

Pg2_funcA_3.v
Pg2_funcB_2.v
Pg2_funcC_zdsfuncC_1.v
Pg2_testbench.v
Pg2_topEntity_0.v
Pg2_topEntity.v

Here we see that funcA is also instantiated. It is also used in generated code, but I omitted this here.

error in Tutorial

while (Signal a, Signal b) and Signal (a,b) are not equal, they are isomorphic and can be converted from on to the other using bundle and unbundle.

I think you mean "from or to" ?

Instantiation for `blockRAM`

Currently, blockRam looks like this:

blockRam :: forall n m a . (KnownNat n, KnownNat m, Pack a, Default a)
         => SNat n              -- ^ Size @n@ of the blockram
         -> Signal (Unsigned m) -- ^ Write address @w@
         -> Signal (Unsigned m) -- ^ Read address @r@
         -> Signal Bool         -- ^ Write enable
         -> Signal a            -- ^ Value to write (at address @w@)
         -> Signal a            -- ^ Value of the 'blockRAM' at address @r@ from the previous clock cycle

Where the BRAM on the FPGA is filled with the value defined by the Default instance for a. The contents of the the BRAM really should be configurable though, which would change the blockRam function to:

blockRam :: forall n m a . (KnownNat n, KnownNat m, Pack a)
         => Vec n a             -- ^ Initial content of the BRAM, also determines the size ,@n@, of the BRAM.
                                -- NB: *MUST* be a constant.
         -> Signal (Unsigned m) -- ^ Write address @w@
         -> Signal (Unsigned m) -- ^ Read address @r@
         -> Signal Bool         -- ^ Write enable
         -> Signal a            -- ^ Value to write (at address @w@)
         -> Signal a            -- ^ Value of the 'blockRAM' at address @r@ from the previous clock cycle

Where the initial content must be a constant, and not be seen as an extra input for the BRAM.

Suggestions for some utility functions

Looking at some clash code I found useful functions missing from the prelude.

  • snatToNum (as Integer is rarely used in designs)
  • bitCast = unpack . pack (implemented with zero cost in hardware)
  • constructing a vector from a index mapping function (Index n -> a) -> Vec n a
  • multiplexor function with n inputs on Signal types so that it be conveniently written on one line (using a list of inputs or variadic function, or whatever synthesizes efficiently) instead the now common:
res = myMux <$> sels <*> xs <*> ys <*> zs
  where myMux A _ _ _ = 0
            myMux B x _ _ = x
            myMux C _ y _ = y
            myMux D _ _ z = z
-- want to write something like:
multiplexor sels (A,0) (B,xs) (C,ys) (D,zs)

Changing `()`'s `Bundle` instance to be like the other tuple instances?

Currently we have:

instance Bundle () where
  type Unbundled () = Signal ()
  bundle :: Signal () -> Signal ()
  bundle = id
  unbundle :: Signal () -> Signal ()
  unbundle = id

which is completely _|_-preserving is both directions, but, doesn't correspond to the other Bundle instances for tuples.

Should this be changed to:

instance Bundle () where
  type Unbundled () = ()
  bundle :: () -> Signal ()
  bundle t = pure t
  unbundle :: Signal () -> ()
  unbundle _ = ()

which corresponds more to the other Bundle instances for tuples, but isn't _|_-preserving in its unbundle method.

0.10.13: Conflicting exports for ‘Min’ and ‘Max’

I don't understand why this started happening in the Stackage Nightly build, but reporting it here:

[45 of 48] Compiling CLaSH.Prelude.Safe ( src/CLaSH/Prelude/Safe.hs, dist/build/CLaSH/Prelude/Safe.o )

src/CLaSH/Prelude/Safe.hs:93:5: error:
    Conflicting exports for ‘Min’:
       ‘module GHC.TypeLits.Extra’ exports ‘GHC.TypeLits.Extra.Min’
         imported from ‘GHC.TypeLits.Extra’ at src/CLaSH/Prelude/Safe.hs:111:1-25
       ‘module CLaSH.Promoted.Ord’ exports ‘CLaSH.Promoted.Ord.Min’
         imported from ‘CLaSH.Promoted.Ord’ at src/CLaSH/Prelude/Safe.hs:135:1-25
         (and originally defined at src/CLaSH/Promoted/Ord.hs:22:1-44)

src/CLaSH/Prelude/Safe.hs:93:5: error:
    Conflicting exports for ‘Max’:
       ‘module GHC.TypeLits.Extra’ exports ‘GHC.TypeLits.Extra.Max’
         imported from ‘GHC.TypeLits.Extra’ at src/CLaSH/Prelude/Safe.hs:111:1-25
       ‘module CLaSH.Promoted.Ord’ exports ‘CLaSH.Promoted.Ord.Max’
         imported from ‘CLaSH.Promoted.Ord’ at src/CLaSH/Prelude/Safe.hs:135:1-25
         (and originally defined at src/CLaSH/Promoted/Ord.hs:27:1-44)

I could not reproduce locally with ``stack -resolver nightly build clash-prelude.

Any ideas?

Reading block RAM from undefined address breaks simulation?

It seems that if I ever try to read from an undefined address then the block RAM simulation breaks.

> let br addr = blockRam (0 :> Nil) (pure 0) addr (pure False) (pure 0)
> Prelude.take 10 $ Prelude.drop 5 $ simulate (br . register (error "foo")) [0,0..]
[*** Exception: foo

Add Safe vector indexing

Just as we have pow2 block ram, etc, it would be nice if we had safe pow2 vector indexing.

I was just refactoring one of my processors to change the word size, and some bugs got caught with my tests instead of the type checker because I was using !!.

Maybe something like

(!!!) :: Integral i
      => KnownNat (2 ^ BitSize i)
      => Vec (2 ^ BitSize i) a
      -> i -> a
(!!!) = (CL.!!)

should go in CLaSH.Sized.Vector?

Feel free to suggest a different identifier if you like the idea, of course.

clockWizard broken

Looks like it was broken by part of the differential signaling change
My top entity def looks like this

{-# ANN topEntity
  (TopEntity
    { t_name = "main"
    , t_inputs = []
    , t_outputs = ["LED", "TX"]
    , t_extraIn = [ ("SYS_CLK", 1)
                  ]
    , t_extraOut = []
    , t_clocks   = [ clockWizard "clkwiz50"
                             "SYS_CLK(0)"
                             "'0'" 
                   ]
}) #-}  

and it results in this

  clkwiz50_inst : entity clkwiz50
    port map
      (CLK_IN1 => SYS_CLK(0)
      ,CLK_IN1 => SYS_CLK(0)
      ,RESET   => '0'
      ,LOCKED  => clkwiz50_locked);

Note that CLK_IN1 is specifed twice, which causes XISE to give these errors
Also note that CLK_OUT1 is not bound at all.

ERROR:HDLCompiler:433 - "\psf\home\git\Clash\examples\Alu\vhdl\Main\main.vhdl" Line 25: Formal <clk_in1> is already associated.
ERROR:HDLCompiler:854 - "\psf\home\git\Clash\examples\Alu\vhdl\Main\main.vhdl" Line 16: Unit ignored due to previous errors.

Test suite failure with GHC 8

This is a strange report, because the build log looks like the test succeeded, but nonetheless it's reporting as a failure.

> /tmp/stackage-build9/clash-prelude-0.10.7$ runghc -clear-package-db -global-package-db -package-db=/home/stackage/work/builds/nightly/pkgdb Setup configure --enable-tests --package-db=clear --package-db=global --package-db=/home/stackage/work/builds/nightly/pkgdb --libdir=/home/stackage/work/builds/nightly/lib --bindir=/home/stackage/work/builds/nightly/bin --datadir=/home/stackage/work/builds/nightly/share --libexecdir=/home/stackage/work/builds/nightly/libexec --sysconfdir=/home/stackage/work/builds/nightly/etc --docdir=/home/stackage/work/builds/nightly/doc/clash-prelude-0.10.7 --htmldir=/home/stackage/work/builds/nightly/doc/clash-prelude-0.10.7 --haddockdir=/home/stackage/work/builds/nightly/doc/clash-prelude-0.10.7 --flags=
Configuring clash-prelude-0.10.7...
> /tmp/stackage-build9/clash-prelude-0.10.7$ runghc -clear-package-db -global-package-db -package-db=/home/stackage/work/builds/nightly/pkgdb Setup build
Building clash-prelude-0.10.7...
Preprocessing library clash-prelude-0.10.7...
[ 1 of 47] Compiling CLaSH.Sized.Internal.Index[boot] ( src/CLaSH/Sized/Internal/Index.hs-boot, dist/build/CLaSH/Sized/Internal/Index.o-boot )
[ 2 of 47] Compiling CLaSH.Sized.Internal.BitVector[boot] ( src/CLaSH/Sized/Internal/BitVector.hs-boot, dist/build/CLaSH/Sized/Internal/BitVector.o-boot )
[ 3 of 47] Compiling CLaSH.Sized.Vector[boot] ( src/CLaSH/Sized/Vector.hs-boot, dist/build/CLaSH/Sized/Vector.o-boot )
[ 4 of 47] Compiling CLaSH.Promoted.Symbol ( src/CLaSH/Promoted/Symbol.hs, dist/build/CLaSH/Promoted/Symbol.o )
[ 5 of 47] Compiling CLaSH.Promoted.Ord ( src/CLaSH/Promoted/Ord.hs, dist/build/CLaSH/Promoted/Ord.o )
[ 6 of 47] Compiling CLaSH.Promoted.Nat ( src/CLaSH/Promoted/Nat.hs, dist/build/CLaSH/Promoted/Nat.o )
[ 7 of 47] Compiling CLaSH.Promoted.Nat.TH ( src/CLaSH/Promoted/Nat/TH.hs, dist/build/CLaSH/Promoted/Nat/TH.o )
[ 8 of 47] Compiling CLaSH.Promoted.Nat.Literals ( src/CLaSH/Promoted/Nat/Literals.hs, dist/build/CLaSH/Promoted/Nat/Literals.o )
[ 9 of 47] Compiling CLaSH.Promoted.Nat.Unsafe ( src/CLaSH/Promoted/Nat/Unsafe.hs, dist/build/CLaSH/Promoted/Nat/Unsafe.o )
[10 of 47] Compiling CLaSH.Sized.RTree ( src/CLaSH/Sized/RTree.hs, dist/build/CLaSH/Sized/RTree.o )
[11 of 47] Compiling CLaSH.Class.Resize ( src/CLaSH/Class/Resize.hs, dist/build/CLaSH/Class/Resize.o )
[12 of 47] Compiling CLaSH.Class.Num  ( src/CLaSH/Class/Num.hs, dist/build/CLaSH/Class/Num.o )
[13 of 47] Compiling CLaSH.Signal.Internal ( src/CLaSH/Signal/Internal.hs, dist/build/CLaSH/Signal/Internal.o )
[14 of 47] Compiling CLaSH.Sized.Internal.BitVector ( src/CLaSH/Sized/Internal/BitVector.hs, dist/build/CLaSH/Sized/Internal/BitVector.o )
[15 of 47] Compiling CLaSH.Sized.BitVector ( src/CLaSH/Sized/BitVector.hs, dist/build/CLaSH/Sized/BitVector.o )
[16 of 47] Compiling CLaSH.Class.BitPack ( src/CLaSH/Class/BitPack.hs, dist/build/CLaSH/Class/BitPack.o )
[17 of 47] Compiling CLaSH.Prelude.BitIndex ( src/CLaSH/Prelude/BitIndex.hs, dist/build/CLaSH/Prelude/BitIndex.o )
[18 of 47] Compiling CLaSH.Prelude.BitReduction ( src/CLaSH/Prelude/BitReduction.hs, dist/build/CLaSH/Prelude/BitReduction.o )
[19 of 47] Compiling CLaSH.Sized.Internal.Index ( src/CLaSH/Sized/Internal/Index.hs, dist/build/CLaSH/Sized/Internal/Index.o )
[20 of 47] Compiling CLaSH.Sized.Index ( src/CLaSH/Sized/Index.hs, dist/build/CLaSH/Sized/Index.o )
[21 of 47] Compiling CLaSH.Sized.Vector ( src/CLaSH/Sized/Vector.hs, dist/build/CLaSH/Sized/Vector.o )

src/CLaSH/Sized/Vector.hs:1139:1: warning: [-Wredundant-constraints]
    • Redundant constraint: CmpNat (i + s) (s * n) ~ 'GT
    • In the type signature for:
           select :: CmpNat (i + s) (s * n) ~ 'GT =>
                     SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
[22 of 47] Compiling CLaSH.Sized.Internal.Signed ( src/CLaSH/Sized/Internal/Signed.hs, dist/build/CLaSH/Sized/Internal/Signed.o )
[23 of 47] Compiling CLaSH.Sized.Signed ( src/CLaSH/Sized/Signed.hs, dist/build/CLaSH/Sized/Signed.o )
[24 of 47] Compiling CLaSH.Sized.Internal.Unsigned ( src/CLaSH/Sized/Internal/Unsigned.hs, dist/build/CLaSH/Sized/Internal/Unsigned.o )
[25 of 47] Compiling CLaSH.Sized.Unsigned ( src/CLaSH/Sized/Unsigned.hs, dist/build/CLaSH/Sized/Unsigned.o )
[26 of 47] Compiling CLaSH.Sized.Fixed ( src/CLaSH/Sized/Fixed.hs, dist/build/CLaSH/Sized/Fixed.o )
[27 of 47] Compiling CLaSH.Signal.Bundle ( src/CLaSH/Signal/Bundle.hs, dist/build/CLaSH/Signal/Bundle.o )
[28 of 47] Compiling CLaSH.Signal.Explicit ( src/CLaSH/Signal/Explicit.hs, dist/build/CLaSH/Signal/Explicit.o )
[29 of 47] Compiling CLaSH.Signal     ( src/CLaSH/Signal.hs, dist/build/CLaSH/Signal.o )
[30 of 47] Compiling CLaSH.Prelude.BlockRam ( src/CLaSH/Prelude/BlockRam.hs, dist/build/CLaSH/Prelude/BlockRam.o )
[31 of 47] Compiling CLaSH.Prelude.BlockRam.File ( src/CLaSH/Prelude/BlockRam/File.hs, dist/build/CLaSH/Prelude/BlockRam/File.o )
[32 of 47] Compiling CLaSH.Prelude.Mealy ( src/CLaSH/Prelude/Mealy.hs, dist/build/CLaSH/Prelude/Mealy.o )
[33 of 47] Compiling CLaSH.Prelude.DataFlow ( src/CLaSH/Prelude/DataFlow.hs, dist/build/CLaSH/Prelude/DataFlow.o )

src/CLaSH/Prelude/DataFlow.hs:540:10: warning: [-Wredundant-constraints]
    • Redundant constraint: KnownNat m
    • In the instance declaration for ‘LockStep (Vec m en) (Vec m a)’
[34 of 47] Compiling CLaSH.Prelude.Moore ( src/CLaSH/Prelude/Moore.hs, dist/build/CLaSH/Prelude/Moore.o )
[35 of 47] Compiling CLaSH.Prelude.RAM ( src/CLaSH/Prelude/RAM.hs, dist/build/CLaSH/Prelude/RAM.o )
[36 of 47] Compiling CLaSH.Prelude.ROM ( src/CLaSH/Prelude/ROM.hs, dist/build/CLaSH/Prelude/ROM.o )
[37 of 47] Compiling CLaSH.Prelude.ROM.File ( src/CLaSH/Prelude/ROM/File.hs, dist/build/CLaSH/Prelude/ROM/File.o )
[38 of 47] Compiling CLaSH.Prelude.Synchronizer ( src/CLaSH/Prelude/Synchronizer.hs, dist/build/CLaSH/Prelude/Synchronizer.o )
[39 of 47] Compiling CLaSH.Prelude.Explicit.Safe ( src/CLaSH/Prelude/Explicit/Safe.hs, dist/build/CLaSH/Prelude/Explicit/Safe.o )
[40 of 47] Compiling CLaSH.Prelude.Testbench ( src/CLaSH/Prelude/Testbench.hs, dist/build/CLaSH/Prelude/Testbench.o )
[41 of 47] Compiling CLaSH.Prelude.Explicit ( src/CLaSH/Prelude/Explicit.hs, dist/build/CLaSH/Prelude/Explicit.o )
[42 of 47] Compiling CLaSH.Signal.Delayed ( src/CLaSH/Signal/Delayed.hs, dist/build/CLaSH/Signal/Delayed.o )
[43 of 47] Compiling CLaSH.Annotations.TopEntity ( src/CLaSH/Annotations/TopEntity.hs, dist/build/CLaSH/Annotations/TopEntity.o )
[44 of 47] Compiling CLaSH.Prelude.Safe ( src/CLaSH/Prelude/Safe.hs, dist/build/CLaSH/Prelude/Safe.o )
[45 of 47] Compiling CLaSH.Prelude    ( src/CLaSH/Prelude.hs, dist/build/CLaSH/Prelude.o )
[46 of 47] Compiling CLaSH.Tutorial   ( src/CLaSH/Tutorial.hs, dist/build/CLaSH/Tutorial.o )
[47 of 47] Compiling CLaSH.Examples   ( src/CLaSH/Examples.hs, dist/build/CLaSH/Examples.o )
Preprocessing test suite 'doctests' for clash-prelude-0.10.7...
[1 of 1] Compiling Main             ( tests/doctests.hs, dist/build/doctests/doctests-tmp/Main.o )
Linking dist/build/doctests/doctests ...
> /tmp/stackage-build9/clash-prelude-0.10.7$ dist/build/doctests/doctests

The documentation for asyncFIFOSynchronizer is incorrect

The documentation says that the FIFO contains 2^addrSize elements: "Size of the internally used addresses, the FIFO contains 2^addrSize elements." however the SNat passed in has value addrSize + 2.

I think the documentation should say the FIFO contains 2^(addrSize + 2) elements. Better yet would be to pass in addrSize and have the constraint 2 < addrSize

VHDL generation error: wrapper for sum-of-products type

When wrapping a sum-of-products type in a single-field record type, the generated VHDL is wrong; it seems to me like a superfluous VHDL signal is generated that has the type of the sum-of-products type (equivalently, the record type), but is used both that way and as if it where the product term in one of the sum constructors:

  port(w_i1     : in std_logic_vector(29 downto 0);
[...]
  signal repANF_0 : std_logic_vector(29 downto 0);
  signal repANF_1 : unsigned(3 downto 0);
  signal n_6      : unsigned(3 downto 0);
  signal ww1_8    : std_logic_vector(29 downto 0);
[...]
 repANF_0 <= ww1_8;

  repANF_1 <= n_6 + to_unsigned(1,4);

  n_6 <= unsigned(ww1_8(27 downto 24));

  ww1_8 <= unsigned(w_i1(27 downto 24));

Where it seems to me it should be this:

[...]
  signal repANF_0 : std_logic_vector(29 downto 0);
  signal repANF_1 : unsigned(3 downto 0);
  signal n_6      : unsigned(3 downto 0);
[...]
  repANF_0 <= w_i1;

  repANF_1 <= n_6 + to_unsigned(1,4);

  n_6 <= unsigned(w_i1(27 downto 24));

Obviously, if it were used correctly, it wouldn't matter that the signal is superfluous. But right now it is trying to be two things at once.

The VHDL generated above is generated by CλaSH v0.4.1 with Prelude v0.6.1 for the following CλaSH code:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}

module RecordSumOfProducts where

import CLaSH.Prelude
import Control.Applicative

data DbState = DbInitDisp (Unsigned 4) | DbWriteRam (Signed 14) (Signed 14)
             | DbDone
    deriving (Show, Eq)

data DbS = DbS { dbS :: DbState }


topEntity = walkState <^> DbS (DbInitDisp 0)

walkState :: DbS
          -> Bit
          -> (DbS, Bit)

walkState (DbS (DbInitDisp n    )) i = (DbS (DbInitDisp (n+1)  ), 0)
walkState s                        i = (s                       , i)

Pipelines?

I have just written a toy 3-stage pipeline for a moore machine:

pip3 :: (a -> b) -> (b -> c) -> (c -> d) -> (b, c, d) -> a -> (b, c, d)
pip3 f g h (b, c, _) a = (f a, g b, h c)

pmoore = moore (pip3 (*2) show read) project3 (0, "42", 1)
  where project3 (b, c, d) = d

I wonder whether such a thing would be useful for folks. If not, please close. Otherwise I could come up with a pull request. Of course many variants (types of feedback/mealy etc.) would be possible, so some guidance is welcome.

instance BitPack ()

There should be

instance BitPack () where
  type BitSize () = 0
  pack   _ = minBound
  unpack _ = ()

I know this seems trivial but it's going to be needed by someone sooner or later (probably because they are generating code).

stepLock eats my tuple data

stepLock seems to go very wrong when the data is a tuple:

import CLaSH.Prelude

a = mooreDF (\(s1, s2) i -> (s1+1, s2-1)) id ( 0 :: Unsigned 4
                                             , 0 :: Unsigned 8)

b = pureDF (id :: (Unsigned 4, Unsigned 8) -> (Unsigned 4, Unsigned 8))

fine = a `seqDF` b

wrong = a `seqDF` stepLock `seqDF` (b `parDF` b)

CλaSH says:

    • Couldn't match type ‘(Unsigned 4, Unsigned 8)’ with ‘Unsigned 4’
      Expected type: DataFlow'
                       ('CLaSH.Signal.Internal.Clk nm rate)
                       (Bool, Bool)
                       (Bool, Bool)
                       (Unsigned 4, Unsigned 8)
                       ((Unsigned 4, Unsigned 8), (Unsigned 4, Unsigned 8))
        Actual type: DataFlow'
                       ('CLaSH.Signal.Internal.Clk nm rate)
                       (Bool, Bool)
                       (Bool, Bool)
                       ((Unsigned 4, Unsigned 8), (Unsigned 4, Unsigned 8))
                       ((Unsigned 4, Unsigned 8), (Unsigned 4, Unsigned 8))
    • In the second argument of ‘seqDF’, namely ‘(b `parDF` b)’
      In the expression: a `seqDF` stepLock `seqDF` (b `parDF` b)
      In an equation for ‘wrong’:
          wrong = a `seqDF` stepLock `seqDF` (b `parDF` b)

That's because the data output of stepLock is not ((Unsigned 4, Unsigned 8), (Unsigned 4, Unsigned 8)) as would be expected when you use stepLock, but it is just the single (Unsigned 4, Unsigned 8) output.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.