clash-lang / clash-compiler Goto Github PK
View Code? Open in Web Editor NEWHaskell to VHDL/Verilog/SystemVerilog compiler
Home Page: https://clash-lang.org/
License: Other
Haskell to VHDL/Verilog/SystemVerilog compiler
Home Page: https://clash-lang.org/
License: Other
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.
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.
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?
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.
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.
I'd like to index a vector by unsigned integer, how to do it?
Refer to https://groups.google.com/forum/#!topic/clash-language/E6FKgHxit2M
If a module which contains a function 'topEntity' is loaded in a CλaSH-file while hiding this topEntity function, compilation of the root still fails due to multiple topEntity's.
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
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.
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
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 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])
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.
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.
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.
There are cases where only vhdlTypeMark
is called (e.g. for constants, or ~TYPM in BlackBoxes), but a call to vhdlType
never happens. This resulted in the VHDL type not being included in the generated types.vhdl file.
This happened as I was trying to implement https://github.com/christiaanb/clash-prelude/issues/3
http://hackage.haskell.org/package/clash-prelude-0.6.0.1/docs/CLaSH-Sized-Vector.html#v:exact
Shouldn't it be named 'extract'?
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.
Today we cheat, tomorrow we won't.
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?
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.
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.
Implement dependently type core
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.
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 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.
Now, bug fixes to the primitive definitions always require an upgrade of the binary. With a seperate package that could be fixed.
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.)
I am trying to learn CLaSH following the turorial at http://hackage.haskell.org/package/clash-prelude-0.5/docs/CLaSH-Tutorial.html#g:5
for example, there is no simulateP
, but there are simulate
and simulateB
.
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.
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".
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" ;)
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:
Note that using clock at lower frequency could save power.
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.
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 Vec
tor 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.
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
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
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?
How to name inputs and outputs, so they can be immediately mapped to chip pins?
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 1
s 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;
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.
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
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]));
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
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)
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)
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.