Code Monkey home page Code Monkey logo

clash-compiler's People

Contributors

alex-mckenna avatar basile-henry avatar bgamari avatar blaxill avatar bosj avatar cbiffle avatar cchalmers avatar christiaanb avatar digitalbrains1 avatar eagleerwin avatar ericson2314 avatar expipiplus1 avatar felixonmars avatar gergoerdi avatar ggreif avatar hcab14 avatar hiddemoll avatar jgjverheij avatar jonfowler avatar jvwesterveld avatar kleinreact avatar leonschoorl avatar lmbollen avatar martijnbastiaan avatar mmzx avatar omelkonian avatar rikstrijker avatar rowang077 avatar thoughtpolice avatar vmchale 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  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  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  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  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

clash-compiler's Issues

Add upper bound to `errors` dependency

errors-2.0 will be switching to use ExceptT instead of EitherT. If that will break your package, then add an upper bound of errors < 2.0 to your dependencies.

VHDL array constant ambiguous

Currently, generated VHDL array constants are ambiguous.
So when we have the following Haskell code:

b = (1 :> 2 :> 3 :> 4) :> a :> Nil :: Vec 2 (Vec 4 (Unsigned 16))

We get the following VHDL, where the & operator is actually implicitly generated for all array types, we just show them here to highlight the reason for ambiguity.

type array_of_unsigned16 is array (integer range <>) of unsigned(15 downto 0);
type array_of_array_of_unsigned16_4 is array (integer range <>) of array_of_unsigned16(3 downto 0);

function & (l,r : array_of_unsigned16) return array_of_array_of_unsigned16_4;
function & (l : array_of_array_of_unsigned16_4, r : array_of_unsigned16) return array_of_array_of_unsigned16_4;

The following use of & becomes ambiguous:

architecture rtl of top is
  signal a : array_of_unsigned16 (3 downto 0);
  signal b : array_of_array_of_unsigned16_4 (1 downto 0);
begin
  b <= (to_unsigned(1,16)
       ,to_unsigned(2,16)
       ,to_unsigned(3,16)
       ,to_unsigned(4,16)) & a;
end;

The reason is that:

(to_unsigned(1,16),to_unsigned(2,16),to_unsigned(3,16),to_unsigned(4,16))

Can be either of type:

array_of_unsigned16 (3 downto 0)

Or:

array_of_array_of_unsigned16_4 (0 downto 0)

This means that the VHDL compiler cannot know which overloaded version of the & operator to use, the first or the second version.

Array constants should hence be generated with their qualifier, so that we get the following unambiguous use of &:

architecture rtl of top is
  signal a : array_of_unsigned16 (3 downto 0);
  signal b : array_of_array_of_unsigned16_4 (1 downto 0);
begin
  b <= array_of_unsigned16'(to_unsigned(1,16)
       ,to_unsigned(2,16)
       ,to_unsigned(3,16)
       ,to_unsigned(4,16)) & a;
end;

Where the use of & can be resolved to the first version.

Initial blocks vs reset line

Quartus + Cyclone II for example supports synthesizing initial blocks--or at least those that initialize registers with a literal (that's what I've tried). It can also do this more efficiently than with a reset line in some cases.

Perhaps an option should be added for CLaSH to use a register primitive with initial blocks, and forgo adding extra reset lines?

Automated regression tests

We currently have "many" tests for the compiler in /tests, but they currently have to be run manually.

Eventually, we want a test framework where the tests are run automatically, including simulation of the generated VHDL.

Replace VHDL default hole by error hole

VHDL Blackboxes had a so-called ~DEFAULT hole, which would be filled with the default value belong to the type. These holes were however always used in a place where we were in an error state, and we had to assign a value to a signal regardless.

We should thus remove the ~DEFAULT, and replace it with the ERROR hole, which returns error values, e.g. (others => 'X') for the unsigned type.

toSLV fails on BlackBox with Vector type

The code:

topEntity = Just (replicate d4 (0 :: Signed 15))

Fails with:

*** Exception: CLaSH.Netlist.VHDL(527): toSLV: ty:Vector 4 (Signed 15)
 expr: BlackBoxE "array_of_signed_15'(0 to (4)-1 => to_signed(0,15))" Nothing

Hardcode `fromInteger` for `Signed` and `Unsigned`

Currently, the fromInteger functions for Signed and Unsigned are handled through the normal BlackBox mechanism: they are translated to to_signed and to_unsigned respectively.

This is however a problem when they are applied to an integer literal that is larger than 32-bits, as most VHDL tooling does not support integer literals larger than the 32-bit 2-complements representation. When this happens, we should write the the integers as a bit-string; we can't do this in the BlackBox definitions, as the templates are logic-less and so they can't determine if they are applied to a literal yes or no.

We must hence implement these two functions directly in the compiler.

CLaSH runs out of memory when translating a simple 96-way case...

I tried to make a simple character generator based on freeware 16x16 bitmap font, and got an out of memory error very quickly. It seems that there is a complexity blow-up for many-way case expressions:

Loading dependencies took 1.169786s
clash: out of memory (requested 2097152 bytes)

The character generator is a simple ROM like below:

{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE DataKinds      #-}
module Font(glyph, topEntity) where
import CLaSH.Prelude

topEntity = glyph
glyph :: Unsigned 8 -> Unsigned 3 -> Unsigned 8

glyph 32 scanLine =case scanLine of --' '
    0 -> 0b0000000000000000

Full code example is on lpaste

Lost system1000 clock in VHDL generation...

Simplest code example that seems to trigger this issue is here: http://lpaste.net/raw/6250056196053532672

CLaSH compiler occasionally misses the clock forwarding to an entity:

entity topEntity28_14 is
  port(eta_i1   : in unsigned(10 downto 0);
       topLet_o : out product5);
end;

architecture structural of topEntity28_14 is

...and then it tries to instantiate subordinate entity with this missing clock:

  mealyzm_7_tup_1 : entity mealyzm_7
    port mapl
      (bodyVar_o      => tup_1
      ,system1000     => system1000
      ,system1000_rst => system1000_rst);

That naturally leads to uncompilable VHDL code.

Circuit testbench generation with MAC example fails

Circuit testbench generation with the MAC example in the tutorial fails when generating VHDL: Exception: CLaSH.Netlist.BlackBox(155): CLaSH.Sized.Unsigned.fromIntegerU: CLaSH.Sized.Unsigned.fromIntegerU. (Maybe fix #9 broke it?)

Exception-causing code:

module MAC where

import CLaSH.Prelude

ma acc (x,y) = acc + x * y

macT acc (x,y) = (acc',o)
  where
    acc' = ma acc (x,y)
    o    = acc

mac = macT <^> 0

topEntity :: (Signal (Signed 9),Signal (Signed 9)) -> Signal (Signed 9)
topEntity = mac

testInput :: Signal (Signed 9,Signed 9)
testInput = stimuliGenerator $(v [(1,1) :: (Signed 9,Signed 9),(2,2),(3,3),(4,4)])

expectedOutput :: Signal (Signed 9) -> Signal Bool
expectedOutput = outputVerifier $(v [0 :: Signed 9,1,5,14])

Signals declared twice when not using a clock-generating component

architecture structural of compute_main is
  signal system1000      : std_logic;
  signal system1000_rstn : std_logic;
  signal input_0         : product0;
  signal output_0        : product1;
begin
  ...
end;

When generating VHDL without specifying a clock generating component the synthesis fails because CλaSH adds the signals "system1000" and "system1000_rstn" to the input ports of the main component. This cλashes (hehe) with signal naming used in the generated VHDL (displayed above), resulting in this error in the Quartus VHDL compiler.

The fix is to simply comment or remove the second and third line of the above code snippet.

Type synonym improperly expanded

The types:

type SF = SFixed 16 20
type SFixed int frac = Fixed frac Signed (int + frac)

Get (improperly) expanded to:

(Fixed frac Signed (int + frac)) 16 20

Insteand of:

Fixed 20 Signed (16 + 20)

The reason why we expand in the first place is that CLaSH Core does not have type synonyms, unlike GHC Core.

Normalization failure with ADT

I've just tried to abstract my VGA controller over different possible modeline parameters, and got a rather obscure error message:

[1 of 2] Compiling Modeline         ( Modeline.hs, Modeline.o )
[2 of 2] Compiling Main             ( Video.hs, Video.o )
Loading dependencies took 0.473015s

<no location info>:
    CLaSH Error:
CLaSH.Normalize(96): Expr belonging to bndr: nubBy'1272 (:: GHC.Types.[]
  (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
-> GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int
-> GHC.Types.[]
     (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)) remains recursive after normalization:
λ(pTS :: GHC.Types.[]
           (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)) ->
λ(y :: GHC.Tuple.(,,)
         GHC.Types.Double GHC.Types.Int GHC.Types.Int) ->
letrec
  subjLet :: GHC.Types.Bool
  = Data.OldList.elem_by
    @(GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
      Modeline.modeline91912625679
      y1
      (GHC.Types.:
       @(GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
         y
         (GHC.Types.[]
          @(GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)))
  altLet2 :: GHC.Types.[]
               (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
  = GHC.Types.:
    @(GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
      y1
      (nubBy'1321
         ys
         y1
         y)
  altLet1 :: GHC.Types.[]
               (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
  = nubBy'1272
      ys
      y
  altLet :: GHC.Types.[]
              (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
  = case subjLet of
      GHC.Types.False -> altLet2
      GHC.Types.True -> altLet1
  y1 :: GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int
  = case pTS of
      GHC.Types.:
        (sel :: GHC.Tuple.(,,)
                  GHC.Types.Double GHC.Types.Int GHC.Types.Int)
        (wild :: GHC.Types.[]
                   (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)) ->
        sel
  ys :: GHC.Types.[]
          (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
  = case pTS of
      GHC.Types.:
        (wild :: GHC.Tuple.(,,)
                   GHC.Types.Double GHC.Types.Int GHC.Types.Int)
        (sel :: GHC.Types.[]
                  (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)) ->
        sel
in case pTS of
     GHC.Types.[] ->
       GHC.Types.[]
       @(GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
     GHC.Types.:
       (y2 :: GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)
       (ys1 :: GHC.Types.[]
        ru     (GHC.Tuple.(,,) GHC.Types.Double GHC.Types.Int GHC.Types.Int)) ->
       altLet

Most of the types and indeed most of the code is identical with previous version, just it is abstracted over Modeline, I have no idea what to attribute it to.

I attach lpaste links to the two source modules.

Binary distribution and installer

Only being able to install CLaSH via source through cabal is not ideal. It works well enough for people who are already working with Haskell, but not for anyone else. Eventually we want to have installers and/or a binary distributions of CLaSH.

Vector of functions cannot be translated

The following code:

import CLaSH.Prelude

topEntity :: Signal Int -> Signal Int
topEntity = processor <^> 0

processor :: Int -> Int -> (Int, Int)
processor s _ = (s', s') where
    s' = (work (3:>2:>1:>Nil))!0

work :: Vec 3 Int -> Vec 3 Int
work xs = vzipWith sel xs funs where
    funs    = fun:>fun:>fun:>Nil
    fun x   = x + 1
    sel x f = f x

Produces the following error:

*** Exception: CLaSH.Netlist.BlackBox(207): Can't translate non-tycon type: GHC.Types.Int -> GHC.Types.Int

It seems as if a vector of functions is not acceptable. If it should be possible; this is a bug?

Dependently-typed Core

At the moment, the internal Core language of clash is a simple polymorphic calculus, with support for existential types, impredicative types, and higher-rank polymorphism. This is however insufficient to handle GADT pattern matching that is a available in GHC's Core language.

In the long run, we want to have a dependently typed Core language, with dependent pattern matching. That way, we can properly support e.g. GADT pattern matching. We can then also succesfully support translating idris to VHDL.

Make ANF lift non-representable values

At the moment, the ANF transformation does not lift non-representable values, which has been a constant source of bogus free variables and resulting in strange error messages about non-locatable top-level binders.

The ANF transform should just ignore representability, that way, netlist creation will catch the error with a much better error message that the Core is not in normal form.

0.4

Implement dependently type core

Refactor Netlist/BlackBox

At the moment there is a lot of duplicated code, both within and between, the CLaSH.Netlist and CLaSH.Netlist.BlackBox modules.

This should be refactored so that the functionality only exists in one place in the source code.

Better blackbox operation for vindex

Solves wrong integer initialization when an integer is used as array-index, it is by default initialized as "Integer 'LOW" (-1). The simulator (Questa Sim) reports after a few delta cycles: Fatal error #_#_vindex_integer at <file>

[
{ "BlackBox" :
    { "name"      : "CLaSH.Sized.Vector.vindex_integer"
    , "templateD" :
"~SYM[0]_vindex_integer : block
  signal ~SYM[1] : ~TYP[1];
begin
  ~SYM[1] <= ~ARG[1];
  -- pragma translate_off
  ~SYM[2]_proc : process (~SYM[1],~ARG[2]) is
  begin
    if ~ARG[2] < 0 then
       ~RESULT <= ~SYM[1](0);
    else
    -- pragma translate_on
    ~RESULT <= ~SYM[1](~ARG[2]);
    -- pragma translate_off
    end if;
  end process;
  -- pragma translate_on
end block;"
    }
  }
]

EDIT: the above goes still wrong with constants in the second argument, maybe the code below is better?

[
{ "BlackBox" :
    { "name"      : "CLaSH.Sized.Vector.vindex_integer"
    , "templateD" :
"~SYM[0]_vindex_integer : block
  signal ~SYM[1] : ~TYP[1];
  signal ~SYM[2] : ~TYP[2] := 0;
begin
  ~SYM[1] <= ~ARG[1];
  ~SYM[2] <= ~ARG[2];
  -- pragma translate_off
  ~SYM[2]_proc : process (~SYM[1],~SYM[2]) is
  begin
    if ~ARG[2] < 0 then
       ~RESULT <= ~SYM[1](0);
    else
    -- pragma translate_on
    ~RESULT <= ~SYM[1](~SYM[2]);
    -- pragma translate_off
    end if;
  end process;
  -- pragma translate_on
end block;"
    }
  }
]

Type families are not expanded

Type families in Haskell are currently not properly expanded.

So given:

instance (KnownNat (BitSize a), KnownNat (BitSize b), BitVector a, BitVector b) => BitVector (a,b) where
  type BitSize (a,b) = (BitSize a) + (BitSize b)
  toBV (a,b) = toBV a <++> toBV b
  fromBV bv  = (fromBV (vtakeI bv), fromBV (vdropI bv))

topEntity :: Vec 16 Bit -> Vec 16 Bit
topEntity vec = toBV tup
    where
        tup :: (Vec 8 Bit, Vec 8 Bit)
        tup = fromBV vec

The compiler cannot translate topEntity, because the toBV gets the type:

toBV :: (Vec 8 Bit, Vec 8 Bit) -> Vec (BitSize (Vec 8 Bit, Vec 8 Bit)) Bit

Which is not translatable, because BitSize (Vec 8 Bit, Vec 8 Bit) is not a syntactically a natural number which the compiler knows about.

The compiler should thus expand the BitSize (Vec 8 Bit, Vec 8 Bit) type family in toBV to 16. A natural number that the compiler knows.

Automatic testing of examples...

Hi,

I've just tried to compile clash example Fifo.hs with the 0.6 compiler, and got an error:

[1 of 1] Compiling Fifo ( Fifo.hs, Fifo.o )

Fifo.hs:14:23: Not in scope: type constructor or class ‘SingRep’

Fifo.hs:14:34: Not in scope: type constructor or class ‘SingI’

Fifo.hs:14:47: Not in scope: type constructor or class ‘SingI’

Fifo.hs:25:13:
Not in scope: ‘resizeU’
Perhaps you meant one of these:
‘resize’ (imported from CLaSH.Prelude),
‘resizeF’ (imported from CLaSH.Prelude)

Fifo.hs:29:25:
Not in scope: ‘vreplace’
Perhaps you meant ‘replace’ (imported from CLaSH.Prelude)

Fifo.hs:32:23: Not in scope: ‘fromSing’

Fifo.hs:32:33:
Not in scope: ‘sing’
Perhaps you meant one of these:
‘sin’ (imported from CLaSH.Prelude),
‘sinh’ (imported from CLaSH.Prelude)

Fifo.hs:32:41: Not in scope: type constructor or class ‘Sing’

Fifo.hs:38:15: Not in scope: ‘vindex’

Fifo.hs:40:10: Not in scope: type constructor or class ‘Comp’

Fifo.hs:41:14:
Not in scope: ‘^^^’
Perhaps you meant ‘^^’ (imported from CLaSH.Prelude)

Fifo.hs:41:23: Not in scope: ‘vcopyE’

Fifo.hs:41:31:
Not in scope: ‘sing’
Perhaps you meant one of these:
‘sin’ (imported from CLaSH.Prelude),
‘sinh’ (imported from CLaSH.Prelude)

Fifo.hs:41:39: Not in scope: type constructor or class ‘Sing’
Would be great to know how to fix it, or get a CI to compile examples (I use Travis CI, may give config.)

How to install in cabal sandbox?

I couldn't install with the recommended cabal install clash-gcc because of too many clashes with other installed packages (is that where the name "clash" comes from?). I got it to build in a sandbox but now

$ .cabal-sandbox/bin/clash --interactive
CLaSHi, version 0.3.3 (using clash-lib, version 0.3.2):
http://christiaanb.github.io/clash2/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.

Top level:
    Failed to load interface for ‘CLaSH.Prelude’
    Use -v to see a list of the files searched for.

clash-ghc ignores "-package-db" flag

I am trying to synthesize to VHDL (after using just clash-prelude for a while), and am running into difficulty. Because my school runs Debian and I don't have root, I have a custom compiled copy of ghc + cabal to be less out of date. I used that version of cabal to install clash.

When I ran "clash --interactive " it was unable to find the ghc package database built by cabal, so it couldn't find clash-prelude. I used "-package-db" to point clash to the gh pkgs database. That worked enough for me to successful load the REPL, and simulate my circuit in the REPL (in order to force any of the linking I've seen normal GHCi do lazily).

However when I ran ":vhdl" in the clash REPL, the command threw an exception saying it could not find clash-prelude. It appears then that the clash-specific code run by ":vhdl" does not have access to the extra package databases I specified on the command line with "-package-db".

Ambiguous type: 'std_logic_vector' or 'std_ulogic_vector'

Compiling my Tunneling Ball Device, commit fb7f4b9 from gitcaes, with CλaSH v0.3.3 and Prelude 0.5.1 gives the old

Parsing architecture <structural> of entity <planzm2_316>.
ERROR:HDLCompiler:631 - "/local/home/s9902708/Tunneling Ball Device/src/vhdl/CLaSHMain/planzm2_316.vhdl" Line 56: Near string "00000000000000000000000000000000000" ; 6 visible types match here
ERROR:HDLCompiler:200 - "/local/home/s9902708/Tunneling Ball Device/src/vhdl/CLaSHMain/planzm2_316.vhdl" Line 56: Ambiguous type: 'std_logic_vector' or 'std_ulogic_vector'
ERROR:HDLCompiler:622 - "/local/home/s9902708/Tunneling Ball Device/src/vhdl/CLaSHMain/planzm2_316.vhdl" Line 56: Near std_logic_vector ; type conversion expression type cannot be determined uniquely
ERROR:HDLCompiler:1212 - "/local/home/s9902708/Tunneling Ball Device/src/vhdl/CLaSHMain/planzm2_316.vhdl" Line 56: Type conversion (to std_logic_vector) cannot have string literal operand
ERROR:HDLCompiler:854 - "/local/home/s9902708/Tunneling Ball Device/src/vhdl/CLaSHMain/planzm2_316.vhdl" Line 13: Unit <structural> ignored due to previous errors.
VHDL file /local/home/s9902708/Tunneling Ball Device/src/vhdl/CLaSHMain/planzm2_316.vhdl ignored due to errors

from Xilinx ISE 14.7.

The following CλaSH code:

data PlanState = PIdle | PAdjusting Fxp0p35 Fxp0p17 Fxp10p16

    (...)
        s'           = PAdjusting $(F.lit (F.fromReal 0 :: Fxp0p35)) lt omt

generates the following VHDL:

repANF_5 <= std_logic_vector'("1" & std_logic_vector("00000000000000000000000000000000000") & std_logic_vector(lt_10) & std_logic_vector(omt_9));

(note: the Template Haskell simply evaluates to "F.Fxp0p35 0")

The fix to the VHDL is simply this:

diff -ur vhdl~/CLaSHMain/planzm2_316.vhdl vhdl/CLaSHMain/planzm2_316.vhdl
--- vhdl~/CLaSHMain/planzm2_316.vhdl    2014-09-10 17:57:05.401940823 +0200
+++ vhdl/CLaSHMain/planzm2_316.vhdl     2014-09-10 18:22:17.226857211 +0200
@@ -53,7 +53,7 @@
       ,eta_i1   => o_11
       ,eta_i2   => omt_9);

-  repANF_5 <= std_logic_vector'("1" & std_logic_vector("00000000000000000000000000000000000") & std_logic_vector(lt_10) & std_logic_vector(omt_9));
+  repANF_5 <= std_logic_vector'("1" & std_logic_vector'("00000000000000000000000000000000000") & std_logic_vector(lt_10) & std_logic_vector(omt_9));

   repANF_6 <= fomtzm_15;

We've encountered a variation of this before, which is why I say "the old" ;)

Tutorial for custom clocks?

I'd like to generate a circuit with several custom clocks, but didn't find any tutorial as of how to do it.
Example applications may be:

  • to use 1kHz clock for seven segment display controller, while rest of FPGA runs 32MHz,
  • to use 9.6kHz clock for UART controller,
  • to use output from clock divider circuit to drive real time clock at 1Hz.

Note that using clock at lower frequency could save power.

Remove/CPP special-case conversion of `Control.Exception.Base.irrefutPatError`

Until and including GHC 7.8, Control.Exception.Base.irrefutPatError is applied to () and then subsequently casted to the desired type. As our Core language does not support casts, we added a special case translation in CLaSH.GHC.GHC2Core for casts such that Control.Exception.Base.irrefutPatError gets applied to the right type (the one in the coercion used for the cast).

In GHC-HEAD, Control.Exception.Base.irrefutPatError is no longer casted, put applied to the correct type. We should hence either add some CPP stuff around the special-case translation once GHC 7.10 is out, and eventually remove it all together.

VHDL syntax error when generating array of records...

Latest CLaSH 0.5 generates invalid VHDL, according to Xilinx ISE compiler:

Compiling vhdl file "/home/m/exp/fpga/vga/vhdl/Main/topEntity1_11.vhdl" in Library work.
Entity <topentity1_11> compiled.
ERROR:HDLParsers:164 - "/home/m/exp/fpga/vga/vhdl/Main/topEntity1_11.vhdl" Line 27. parse error, unexpected SEMICOLON, expecting COMMA or CLOSEPAR

Relevant VHDL code fragment is as follows:

    n_32 <= array_of_product1'((product1_sel0 => unsigned'(3-1 downto 0 => '1');,product1_sel1 => unsigned'(3-1 downto 0 => '0');,product1_sel2 => unsigned'(3-1 downto 0 => '0');),(product1_sel0 => unsigned'(3-1 downto 0 => '1');,product1_sel1 => unsigned'(3-1 downto 0 => '1');,product1_sel2 => unsigned'(3-1 downto 0 => '0');),(product1_sel0 => unsigned'(3-1 downto 0 => '0');,product1_sel1 => unsigned'(3-1 downto 0 => '1');,product1_sel2 => unsigned'(3-1 downto 0 => '0');),(product1_sel0 => unsigned'(3-1 downto 0 => '0');,product1_sel1 => unsigned'(3-1 downto 0 => '0');,product1_sel2 => unsigned'(3-1 downto 0 => '1');),(product1_sel0 => unsigned'(3-1 downto 0 => '1');,product1_sel1 => unsigned'(3-1 downto 0 => '0');,product1_sel2 => unsigned'(3-1 downto 0 => '1');),(product1_sel0 => unsigned'(3-1 downto 0 => '0');,product1_sel1 => unsigned'(3-1 downto 0 => '1');,product1_sel2 => unsigned'(3-1 downto 0 => '1');),(product1_sel0 => unsigned'(3-1 downto 0 => '1');,product1_sel1 => unsigned'(3-1 downto 0 => '1');,product1_sel2 => unsigned'(3-1 downto 0 => '1');),(product1_sel0 => unsigned'(3-1 downto 0 => '0');,product1_sel1 => unsigned'(3-1 downto 0 => '0');,product1_sel2 => unsigned'(3-1 downto 0 => '0');));
    n_33 <= repANF_1;

It seems from creation of Vector of records:

        colors     :: Vec 8 (VGAColor 3)
        colors      = red :> yellow :> green :> blue :> magenta :> cyan :> white :> black :> Nil 

I put entire CLaSH input file on Paste

Even if you plan to revamp source entirely, this seems to be a good candidate to add to the unit tests.

GHC 7.10 compatibility?

Since GHC 7.10 is out yet, it would be great to add compatibility for this version.

I'd also love to see clash-ghc and clash-prelude to become part of Stackage, and thus automatically checked against all compiler releases supported by Stackage.

Incorrect vhdl generation for default value in blackbox

The following code:

module Error where 

import CLaSH.Prelude

data Dat = Con Rec | Nop 
data Rec = Rec { testVec :: Vec 3 Bool } 

topEntity :: Dat -> Vec 3 Bool
topEntity x = testVec h where
    (Con h) = x

Is translated to:

entity topEntity_0 is
  port(x_i1      : in std_logic_vector(3 downto 0);
       bodyVar_o : out array_of_boolean(2 downto 0));
end;

architecture structural of topEntity_0 is
  signal ds1_0 : array_of_boolean(2 downto 0);
  signal h_1   : array_of_boolean(2 downto 0);
  signal ds_2  : array_of_boolean(2 downto 0);
begin
  ds1_0 <= ds_2;

  h_1 <= (fromSL(x_i1(2))
         ,fromSL(x_i1(1))
         ,fromSL(x_i1(0)));

  ds_2 <= h_1 when (x_i1(3 downto 3) = "0") else
          (others => '0');

  bodyVar_o <= ds1_0;
end;
type array_of_boolean is array (integer range <>) of boolean;

But the assignment to ds_2 should be:

  ds_2 <= h_1 when (x_i1(3 downto 3) = "0") else
          (others => false);

Workaround:

module Error where 

import CLaSH.Prelude

data Dat = Con Rec | Nop 
data Rec = Rec { testVec :: Vec 3 Bool } 

topEntity :: Dat -> Vec 3 Bool
topEntity x = case x of
        (Con h) -> testVec h
        _       -> undefined

Does not install from cabal on Arch Linux

running cabal install clash-ghc produces errors:

src-bin/Main.hs:628:60:
    Couldn't match expected type ‘Phase’
                with actual type ‘Bool -> Phase’
    Probable cause: ‘As’ is applied to too few arguments
    In the first argument of ‘stopBeforeMode’, namely ‘As’
    In the first argument of ‘setMode’, namely ‘(stopBeforeMode As)’

src-bin/Main.hs:691:55:
    Couldn't match type ‘Phase’ with ‘Bool -> Phase’
    Expected type: [(String, Maybe (Bool -> Phase))]
      Actual type: [(String, Maybe Phase)]
    In the second argument of ‘partition’, namely ‘srcs’
    In the expression: partition haskellish srcs
t
src-bin/Main.hs:696:32:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cc
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:36:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cobjc
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:43:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cobjcpp
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:52:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: CmmCpp
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:60:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cmm
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:65:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: StopLn
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:709:18:
    Couldn't match type ‘Bool -> Phase’ with ‘Phase’
    Expected type: [(FilePath, Maybe Phase)]
      Actual type: [(String, Maybe (Bool -> Phase))]
    In the second argument of ‘mapM’, namely ‘non_hs_srcs’
    In a stmt of a 'do' block:
      o_files <- mapM
                   (\ x -> liftIO $ compileFile hsc_env StopLn x) non_hs_srcs

src-bin/Main.hs:715:47:
    Couldn't match type ‘Bool -> Phase’ with ‘Phase’
    Expected type: [(String, Maybe Phase)]
      Actual type: [(String, Maybe (Bool -> Phase))]
    In the second argument of ‘mapM’, namely ‘hs_srcs’
    In a stmt of a 'do' block:
      targets <- mapM (uncurry GHC.guessTarget) hs_srcs
cabal: Error: some packages failed to install:
clash-ghc-0.3.2 failed during the building phase. The exception was:
ExitFailure 1

system info that may be useful:

$ghc  --version
The Glorious Glasgow Haskell Compilation System, version 7.8.3
$cabal --version
cabal-install version 1.20.0.3
using version 1.20.0.0 of the Cabal library 
$uname -r -m -s
Linux 3.15.7-1-ARCH x86_64

Edit: Removed pacakage version table, to be replaced in second comment

If you would like any more info please let me know,
-jimmy

How to define Block ROM BlackBox...

Hi Christiaan,

Considering that both Altera and Xilinx support Block ROM IP Core generators, and these seem to work quite fast, I'd love to see Block ROM black box defined.

Could you please lend me a hand, and give a tutorial about how to define such a custom BlackBox? Is it something an average user could do, or is it supposed to be hard-wired in the internals of the compiler?

BlackBox for `Signed` `maxBound` and `minBound` generate incorrect VHDL.

maxBound for Signed 8 generates the following VHDL:

signed'(7 => '0', 6 downto 0 => '1')

However, when used like:

entity fun is
  port(in1 : in Signed (7 downto 0);
       in2 : in boolean;
       outp : out Signed(7 downto 0));
end;

architecture rtl of fun is
begin
  outp <= in1 when in2 else
          signed'(7 => '0', 6 downto 0 => '1');
end;

outp does not get the, initially expected, but falsely assumed, value:

0111111

when in2 is false.
That is, an bit-string with a /descending/ index, with the most significant bit, 7, set to 0, and the rest set to 1.
We however get the value:

1111110

That is, signed'(7 => '0', 6 downto 0 => '1') has an /ascending/ index, meaning that the least significant bit is bit 7. So we get a bit-string of 1s followed by a 0.

The fix is to make sure that maxBound is not inlined, so that the following VHDL is generated:

entity fun is
  port(in1 : in Signed (7 downto 0);
       in2 : in boolean;
       outp : out Signed(7 downto 0));
end;

architecture rtl of fun is
  signal tmp : Signed(7 downto 0);
begin
  tmp <= (7 => '0', 6 downto 0 => '1');
  outp <= in1 when in2 else
          tmp;
end;

Duplicate type names when multiple ADTs need the same amount of bits

The following code:

module Error where 

import CLaSH.Prelude

data Valid = Valid | Invalid
data Exec  = Exec  | NOP

topEntity :: Vec 3 Valid -> Vec 4 Exec
topEntity xs = fun (vtail xs) <++> fun (vinit xs)

fun :: Vec 2 Valid -> Vec 2 Exec
fun xs = vmap convert xs where
        convert Valid = Exec
        convert Invalid = NOP 

Is translated to VHDL, which contains (in types.vhdl):

...
type array_of_unsigned_1 is array (integer range <>) of unsigned(0 downto 0);
type array_of_unsigned_1 is array (integer range <>) of unsigned(0 downto 0);
...

This produces the following error (in Questa Sim):
Declaration with designator "array_of_unsigned_1" already exists in this region.

Fails install

Update: It installs fine from the Github source. I guess the hackage one is probably a little behind.

Tried installing in a fresh cabal sandbox under the latest Haskell Platform on OSX. GHC version is:

The Glorious Glasgow Haskell Compilation System, version 7.8.3

Fails compiling Main.hs

src-bin/Main.hs:628:60:
    Couldn't match expected type ‘Phase’
                with actual type ‘Bool -> Phase’
    Probable cause: ‘As’ is applied to too few arguments
    In the first argument of ‘stopBeforeMode’, namely ‘As’
    In the first argument of ‘setMode’, namely ‘(stopBeforeMode As)’

src-bin/Main.hs:691:55:
    Couldn't match type ‘Phase’ with ‘Bool -> Phase’
    Expected type: [(String, Maybe (Bool -> Phase))]
      Actual type: [(String, Maybe Phase)]
    In the second argument of ‘partition’, namely ‘srcs’
    In the expression: partition haskellish srcs

src-bin/Main.hs:696:32:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cc
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:36:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cobjc
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:43:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cobjcpp
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:52:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: CmmCpp
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:60:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: Cmm
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:696:65:
    Couldn't match expected type ‘Bool -> Phase’
                with actual type ‘Phase’
    In the expression: StopLn
    In the second argument of ‘notElem’, namely
      ‘[As, Cc, Cobjc, Cobjcpp, ....]’

src-bin/Main.hs:709:18:
    Couldn't match type ‘Bool -> Phase’ with ‘Phase’
    Expected type: [(FilePath, Maybe Phase)]
      Actual type: [(String, Maybe (Bool -> Phase))]
    In the second argument of ‘mapM’, namely ‘non_hs_srcs’
    In a stmt of a 'do' block:
      o_files <- mapM
                   (\ x -> liftIO $ compileFile hsc_env StopLn x) non_hs_srcs

src-bin/Main.hs:715:47:
    Couldn't match type ‘Bool -> Phase’ with ‘Phase’
    Expected type: [(String, Maybe Phase)]
      Actual type: [(String, Maybe (Bool -> Phase))]
    In the second argument of ‘mapM’, namely ‘hs_srcs’
    In a stmt of a 'do' block:
      targets <- mapM (uncurry GHC.guessTarget) hs_srcs
Failed to install clash-ghc-0.3.2

primitives (clash.sized.vector)

I think some bug here: https://github.com/christiaanb/clash2/blob/master/primitives/clash.sized.vector.json#L84

Versions:
CAES Language for Synchronous Hardware, version 0.3.0.2
clash-lib-0.3.0.1
clash-prelude-0.5

TestCode:
https://gist.github.com/alexin-ivan/ec568a97cdb27d53fa22#file-fpgamodel-L218

Result:
https://gist.github.com/alexin-ivan/3c6e17eb7f193e3f33b6

Quartus ouput:
Error (10344): VHDL expression error at switchBoxBlock_1.vhdl(66): expression has 32 elements, but must have 17 elements

Patch (just swap tuple elements)

-~RESULT <= (~SYM[1](~SYM[1]'high downto ~LIT[0]),~SYM[1](~LIT[0]-1 downto 0));
+~RESULT <= (~SYM[1](~LIT[0]-1 downto 0), ~SYM[1](~SYM[1]'high downto ~LIT[0]));

Exception: CLaSH.Netlist.VHDL(512): fromSLV: Vector 13 Bool

It seems as if in VHDL.hs the function fromSLV is incomplete;
it can handle Bool and tuples of Bool but no Vector of Bool.

The minimal code below generates this error.

module Error where 

import CLaSH.Prelude

data Dat = Con Rec | Nop 
data Rec = Rec { testVec :: Vec 13 Bool } 

topEntity :: Dat -> Vec 13 Bool
topEntity x = testVec h where
    (Con h) = x

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)

ERROR: VHDL generation fails due to excessive inlining of d30 constant... (which is not used)

I get the following error when compiling a simple code example (will attach), even though ds30 seems never used:

Loading dependencies took 0.187611s
*** Exception: CLaSH.Normalize.Transformations(154): InlineNonRep: ds30 already inlined 100 times in:ds30, GHC.Tuple.(,)
  (CLaSH.Signal.Internal.CSignal
     (CLaSH.Signal.Internal.Clk system 1000)
     (CLaSH.Sized.Internal.Unsigned.Unsigned 8))
  (CLaSH.Signal.Internal.CSignal
     (CLaSH.Signal.Internal.Clk system 1000)
     (GHC.Tuple.(,)
        (CLaSH.Sized.Internal.Unsigned.Unsigned 8) GHC.Types.Bool))

Below the sample code:

{-# LANGUAGE DataKinds #-}
module DigitalClock where

import CLaSH.Prelude

-- | Generate an impulse every N cycles.
every :: (Num t, Eq t) => t -> Unbundled' Bool -> Unbundled' Bool
every x reset = (fsm <^> 0) reset
  where
    fsm _  rst | rst     = (0,    False)
    fsm st _   | x == st = (0,    True )
    fsm st _             = (st+1, False)

type Word = Unsigned 32

everySecond ::  Unbundled' Bool -- ^ reset signal
             -> Unbundled' Bool -- ^ trigger every one second
everySecond = every $ (2 :: Word) ^ (15 :: Word) * (1000 :: Word) -- or Signed 16?

-- | Simple counter with reset, and clock inputs.
counter :: (Num s, Eq s) => s
                         -> Unbundled' (Bool, Bool)
                         -> Unbundled' (s, Bool)
counter x (clk, reset) = (fsm <^> 0) (clk, reset)
  where
    fsm st (_,     True)               = (0,    (st,   False))
    fsm st (False, _   )               = (0,    (st,   False))

topEntity :: Signal Bool -> Signal (Unsigned 8)
topEntity rst = secondsCounter
  where
    secondPulse         = everySecond rst 
    (secondsCounter, _) = counter 255 (secondPulse, rst)

Exception: can't create selector

The following code:

{-# LANGUAGE FlexibleInstances #-}

import CLaSH.Prelude

type CacheOut = Vec 4 (Unsigned 32)

instance Default (Vec 4 (Unsigned 32)) where def = vcopyI 0

topEntity :: Signal (Unsigned 8)
topEntity = pc where
    pc = (processor <^> 0) (unpack cacheOut)
    cacheOut = cache pc

processor :: Unsigned 8 -> CacheOut -> (Unsigned 8, Unsigned 8)
processor xstate cv = (xstate + fromIntegral(cv!2), xstate)

cache :: Signal (Unsigned 8) -> Signal CacheOut    
cache pc = blockRam d8 0 pc (signal False) (signal (vcopyI 0))

Produces the following error when it is translated to VHDL:

*** Exception: CLaSH.Rewrite.Util(421): Can't create selector ("CLaSH.Normalize.Transformations(543): doPatBndr",1,1) for: (eta2876 :: CLaSH.Signal.Types.Signal
  (CLaSH.Sized.Vector.Vec 4 (CLaSH.Sized.Unsigned.Unsigned 32)))
Additional info: Field index exceed max

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.