Skip to content

Commit

Permalink
Merge pull request #33 from clash-lang/small-fixes
Browse files Browse the repository at this point in the history
Replace topEntity and enable extra extensions
  • Loading branch information
lmbollen authored Feb 12, 2024
2 parents 572614b + 62e8416 commit abbd43d
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 89 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
# Stack Templates
Templates for `stack new` command. If you wish to alter a template, edit them in `projects/` and run `./render.hs`. To instantiate one the projects:

Templates for `stack new` command. To use this template perform the following steps:
1. [Install Stack](https://docs.haskellstack.org/en/stable/README/#how-to-install)
2. Run `stack new my-clash-project clash-lang/simple`. Replace `simple` by the template you'd like to use.
3. Read `my-clash-project/README.md`. Enjoy!

## Cabal users
All starter projects are also available on [clash-lang/clash-starters](https://github.com/clash-lang/clash-starters).

## Contributing
If you wish to contribute to this template, edit them in `projects/` and perform the following steps to test the template:
1. Edit the template
2. Run `./render.hs` to instantiate them.
3. Go to the parent directory: `cd ..` and instantiate the template using the rendered `.hsfiles`.
```
cd ..
stack new my-template stack-templates/simple.hsfiles
```
4. Use the template:
```
cd my-template
cabal build
cabal test
```

## License
The default license for each of the starter project is BSD2. However, this whole repository -including every starter project- is licensed under CC0. That means the authors, to the extent possible under law, have waived all copyright and related or neighboring rights to this "Clash Example Project". Feel free to choose any license for the starter projects that you want.
1 change: 1 addition & 0 deletions deca.hsfiles
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ extra-deps:
- clash-ghc-1.8.1@sha256:3bab304fa5584f3541650bddd01160f2710b9ced52e52c06481a91ac73d71bb8,9753
- clash-lib-1.8.1@sha256:17d78e786dedf16a76394cd5813372870a3d70a1a4c7f964309f126b800e90f6,15693
- clash-prelude-1.8.1@sha256:c3fbb9f6b8e74140fb3d5c4d59ec84cfe4a53e9f8520e606c187cfc04b149065,17626
- clash-prelude-hedgehog-1.8.1@sha256:9ec3aa3f8195481f5ce4942b34a49c97dd132dd1c8f1fa58aeecbd82c2602e86,1410
- concurrent-supply-0.1.8@sha256:80b658533141660818d0781b8c8fb9a8cf69b987fcfbab782dc788bfc7df4846,1627
- prettyprinter-interp-0.2.0.0@sha256:69c339a95b265dab9b3478ca19ec96952b6b472bd0ff6e2127112a9562362c1d,2086

Expand Down
2 changes: 2 additions & 0 deletions projects/simple-nix/nix/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ let
self.callCabal2nix "clash-lib" (sources.clash-compiler + "/clash-lib") {};
clash-ghc =
self.callCabal2nix "clash-ghc" (sources.clash-compiler + "/clash-ghc") {};
clash-prelude-hedgehog =
self.callCabal2nix "clash-prelude" (sources.clash-compiler + "/clash-prelude-hedgehog") {};
tasty-hedgehog =
self.callCabal2nix "tasty-hedgehog" sources.tasty-hedgehog {};
hedgehog =
Expand Down
8 changes: 0 additions & 8 deletions projects/simple-nix/stack.yaml

This file was deleted.

1 change: 1 addition & 0 deletions projects/simple-nix/stack.yaml
4 changes: 4 additions & 0 deletions projects/simple-nix/{{name}}.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ common common-options
DeriveLift
DeriveTraversable
DerivingStrategies
FlexibleContexts
InstanceSigs
KindSignatures
LambdaCase
NamedFieldPuns
NoStarIsType
PolyKinds
RankNTypes
RecordWildCards
ScopedTypeVariables
StandaloneDeriving
TupleSections
Expand Down Expand Up @@ -120,6 +123,7 @@ test-suite test-library
build-depends:
{{name}},
QuickCheck,
clash-prelude-hedgehog,
hedgehog,
tasty >= 1.2 && < 1.5,
tasty-hedgehog,
Expand Down
2 changes: 1 addition & 1 deletion projects/simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Note that this whole section is a `common` "stanza". We'll use it as a template
Cabal,
-- clash-prelude will set suitable version bounds for the plugins
clash-prelude >= 1.6.4 && < 1.8,
clash-prelude >= 1.8.1 && < 1.10,
ghc-typelits-natnormalise,
ghc-typelits-extra,
ghc-typelits-knownnat
Expand Down
63 changes: 49 additions & 14 deletions projects/simple/src/Example/Project.hs
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
module Example.Project (topEntity, plus) where
-- @createDomain@ below generates a warning about orphan instances, but we like
-- our code to be warning-free.
{-# OPTIONS_GHC -Wno-orphans #-}

module Example.Project where

import Clash.Prelude

-- | Add two numbers. Example:
-- Create a domain with the frequency of your input clock. For this example we used
-- 50 MHz.
createDomain vSystem{vName="Dom50", vPeriod=hzToPeriod 50e6}

-- | @topEntity@ is Clash@s equivalent of @main@ in other programming languages.
-- Clash will look for it when compiling "Example.Project" and translate it to
-- HDL. While polymorphism can be used freely in Clash projects, a @topEntity@
-- must be monomorphic and must use non- recursive types. Or, to put it
-- hand-wavily, a @topEntity@ must be translatable to a static number of wires.
--
-- >>> plus 3 5
-- 8
plus :: Signed 8 -> Signed 8 -> Signed 8
plus a b = a + b
-- Top entities must be monomorphic, meaning we have to specify all type variables.
-- In this case, we are using the @Dom50@ domain, which we created with @createDomain@
-- and we are using 8-bit unsigned numbers.
topEntity ::
Clock Dom50 ->
Reset Dom50 ->
Enable Dom50 ->
Signal Dom50 (Unsigned 8) ->
Signal Dom50 (Unsigned 8)
topEntity = exposeClockResetEnable accum

-- To specify the names of the ports of our top entity, we create a @Synthesize@ annotation.
{-# ANN topEntity
(Synthesize
{ t_name = "accum"
, t_inputs = [ PortName "CLK"
, PortName "RST"
, PortName "EN"
, PortName "DIN"
]
, t_output = PortName "DOUT"
}) #-}

-- Make sure GHC does not apply any optimizations to the boundaries of the design.
-- For GHC versions 9.2 or older, use: {-# NOINLINE topEntity #-}
{-# OPAQUE topEntity #-}

-- | 'topEntity' is Clash's equivalent of 'main' in other programming
-- languages. Clash will look for it when compiling 'Example.Project'
-- and translate it to HDL. While polymorphism can be used freely in
-- Clash projects, a 'topEntity' must be monomorphic and must use non-
-- recursive types. Or, to put it hand-wavily, a 'topEntity' must be
-- translatable to a static number of wires.
topEntity :: Signed 8 -> Signed 8 -> Signed 8
topEntity = plus
-- | A simple accumulator that works on unsigned numbers of any size.
-- It has hidden clock, reset, and enable signals.
accum ::
(HiddenClockResetEnable dom, KnownNat n) =>
Signal dom (Unsigned n) ->
Signal dom (Unsigned n)
accum = mealy accumT 0
where
accumT s i = (s + i, s)
1 change: 1 addition & 0 deletions projects/simple/stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ extra-deps:
- clash-ghc-1.8.1@sha256:3bab304fa5584f3541650bddd01160f2710b9ced52e52c06481a91ac73d71bb8,9753
- clash-lib-1.8.1@sha256:17d78e786dedf16a76394cd5813372870a3d70a1a4c7f964309f126b800e90f6,15693
- clash-prelude-1.8.1@sha256:c3fbb9f6b8e74140fb3d5c4d59ec84cfe4a53e9f8520e606c187cfc04b149065,17626
- clash-prelude-hedgehog-1.8.1@sha256:9ec3aa3f8195481f5ce4942b34a49c97dd132dd1c8f1fa58aeecbd82c2602e86,1410
- concurrent-supply-0.1.8@sha256:80b658533141660818d0781b8c8fb9a8cf69b987fcfbab782dc788bfc7df4846,1627
- prettyprinter-interp-0.2.0.0@sha256:69c339a95b265dab9b3478ca19ec96952b6b472bd0ff6e2127112a9562362c1d,2086
44 changes: 34 additions & 10 deletions projects/simple/tests/Tests/Example/Project.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,49 @@ module Tests.Example.Project where

import Prelude

import Clash.Hedgehog.Sized.Unsigned
import Test.Tasty
import Test.Tasty.TH
import Test.Tasty.Hedgehog

import Hedgehog ((===))
import qualified Clash.Prelude as C
import qualified Hedgehog as H
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range

import Example.Project (plus)
-- Import the module containing the @accum@ function
import Example.Project (accum)

prop_plusIsCommutative :: H.Property
prop_plusIsCommutative = H.property $ do
a <- H.forAll (Gen.integral (Range.linear minBound maxBound))
b <- H.forAll (Gen.integral (Range.linear minBound maxBound))
plus a b === plus b a
-- Define a Hedgehog property to test the @accum@ function
prop_accum :: H.Property
prop_accum = H.property $ do

tests :: TestTree
tests = $(testGroupGenerator)
-- Simulate for a random duration between 1 and 100 cycles
simDuration <- H.forAll (Gen.integral (Range.linear 1 100))

-- Generate a list of random unsigned numbers.
inp <- H.forAll
(Gen.list (Range.singleton simDuration)
(genUnsigned Range.linearBounded))
let

-- Simulate the @accum@ function for the pre-existing @System@ domain
-- and 8 bit unsigned numbers.
--
-- The (hidden) reset input of @accum@ will be asserted in the first cycle;
-- during this cycle it will emit its initial value and the input is
-- ignored. So we need to present a dummy input value.
simOut = C.sampleN (simDuration + 1) (accum @C.System @8 (C.fromList (0:inp)))
-- Calculate the expected output. The first cycle is the initial value, and
-- the result of the final input value does not appear because the
-- accumulator has 1 cycle latency.
expected = 0 : init (scanl (+) 0 inp)

-- Check that the simulated output matches the expected output
simOut H.=== expected

accumTests :: TestTree
accumTests = $(testGroupGenerator)

main :: IO ()
main = defaultMain tests
main = defaultMain accumTests
2 changes: 1 addition & 1 deletion projects/simple/tests/unittests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import qualified Tests.Example.Project

main :: IO ()
main = defaultMain $ testGroup "."
[ Tests.Example.Project.tests
[ Tests.Example.Project.accumTests
]
4 changes: 4 additions & 0 deletions projects/simple/{{name}}.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ common common-options
DeriveLift
DeriveTraversable
DerivingStrategies
FlexibleContexts
InstanceSigs
KindSignatures
LambdaCase
NamedFieldPuns
NoStarIsType
PolyKinds
RankNTypes
RecordWildCards
ScopedTypeVariables
StandaloneDeriving
TupleSections
Expand Down Expand Up @@ -124,6 +127,7 @@ test-suite test-library
build-depends:
{{name}},
QuickCheck,
clash-prelude-hedgehog,
hedgehog,
tasty >= 1.2 && < 1.5,
tasty-hedgehog,
Expand Down
Loading

0 comments on commit abbd43d

Please sign in to comment.