Skip to content

Commit

Permalink
Merge pull request #7 from clash-lang/sim-hack
Browse files Browse the repository at this point in the history
 Apply workaround to make HDL generation and simulation work
  • Loading branch information
martijnbastiaan authored Sep 29, 2023
2 parents 288d6e2 + 22e5541 commit 72cf31b
Show file tree
Hide file tree
Showing 12 changed files with 349 additions and 36 deletions.
4 changes: 4 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: 2022 Google LLC
#
# SPDX-License-Identifier: Apache-2.0
use_nix -j8
8 changes: 8 additions & 0 deletions .github/cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- SPDX-FileCopyrightText: 2022 Google LLC
--
-- SPDX-License-Identifier: CC0-1.0
package clash-vexriscv
ghc-options: -Werror

package clash-vexriscv-sim
ghc-options: -Werror
19 changes: 10 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
container:
image: ubuntu:22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v1
uses: fsfe/reuse-action@v2


rust-checks:
Expand All @@ -31,7 +31,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install dependencies
run: |
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install dependencies
run: |
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:
cd clash-vexriscv-sim; sh bundle_test_binaries.sh
- name: Upload Integration Test Binaries
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: vexriscv-test-binaries
path: clash-vexriscv-sim/vexriscv-test-binaries.tar
Expand All @@ -108,18 +108,19 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v4

- name: Update Cabal index info
run: |
cp .github/cabal.project cabal.project.local
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cabal/store
key: packages-cachebust-1-${{ hashFiles('cabal.project.freeze') }}
key: packages-cachebust-1-${{ hashFiles('cabal.project.freeze', 'cabal.project') }}
restore-keys: packages-cachebust-1-

- name: Install build deps
Expand Down Expand Up @@ -149,7 +150,7 @@ jobs:
cabal build clash-vexriscv-sim
- name: Download VexRiscv Integration Tests
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: vexriscv-test-binaries

Expand Down
10 changes: 5 additions & 5 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,31 @@ package clash-prelude
-- index state, to go along with the cabal.project.freeze file. update the index
-- state by running `cabal update` twice and looking at the index state it
-- displays to you (as the second update will be a no-op)
index-state: 2023-01-09T23:37:48Z
index-state: 2023-09-28T08:48:26Z

-- Needed to simulate dynamic clocks.
source-repository-package
type: git
location: https://github.com/clash-lang/clash-compiler.git
tag: 11ef54f9d7254d952eedf8e63f80ed430851df58
tag: 149885cef097ecfdb910797f73f0c1f54fc5b191
subdir: clash-prelude

source-repository-package
type: git
location: https://github.com/clash-lang/clash-compiler.git
tag: 11ef54f9d7254d952eedf8e63f80ed430851df58
tag: 149885cef097ecfdb910797f73f0c1f54fc5b191
subdir: clash-ghc

source-repository-package
type: git
location: https://github.com/clash-lang/clash-compiler.git
tag: 11ef54f9d7254d952eedf8e63f80ed430851df58
tag: 149885cef097ecfdb910797f73f0c1f54fc5b191
subdir: clash-lib

source-repository-package
type: git
location: https://github.com/clash-lang/clash-compiler.git
tag: 11ef54f9d7254d952eedf8e63f80ed430851df58
tag: 149885cef097ecfdb910797f73f0c1f54fc5b191
subdir: clash-cores

source-repository-package
Expand Down
18 changes: 2 additions & 16 deletions clash-vexriscv-sim/src/Utils/Cpu.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ module Utils.Cpu where

import Clash.Prelude

import Clash.Signal.Internal (Signal((:-)))
import Protocols.Wishbone
import VexRiscv

Expand Down Expand Up @@ -50,7 +49,7 @@ cpu ::
)
cpu bootIMem bootDMem = (output, writes, iS2M, dS2M)
where
output = vexRiscv (emptyInput :- input)
output = vexRiscv input
dM2S = dBusWbM2S <$> output

iM2S = unBusAddr . iBusWbM2S <$> output
Expand Down Expand Up @@ -94,19 +93,6 @@ cpu bootIMem bootDMem = (output, writes, iS2M, dS2M)
)
(pure Nothing)

-- When passing S2M values from Haskell to VexRiscv over the FFI, undefined
-- bits/values cause errors when forcing their evaluation to something that can
-- be passed through the FFI.
--
-- This function makes sure the Wishbone S2M values are free from undefined bits.
makeDefined :: WishboneS2M (BitVector 32) -> WishboneS2M (BitVector 32)
makeDefined wb = wb {readData = defaultX 0 (readData wb)}

defaultX :: (NFDataX a) => a -> a -> a
defaultX dflt val
| hasUndefined val = dflt
| otherwise = val

mapAddr :: (BitVector aw1 -> BitVector aw2) -> WishboneM2S aw1 selWidth a -> WishboneM2S aw2 selWidth a
mapAddr f wb = wb {addr = f (addr wb)}

Expand Down Expand Up @@ -134,7 +120,7 @@ dummyWb m2s' = delayControls m2s' (reply <$> m2s')
where
inCycle = (busCycle <$> m2s) .&&. (strobe <$> m2s)

-- It takes a single cycle to lookup elements in a block ram. We can therfore
-- It takes a single cycle to lookup elements in a block ram. We can therefore
-- only process a request every other clock cycle.
ack = (acknowledge <$> s2m0) .&&. (not <$> delayedAck) .&&. inCycle
err1 = (err <$> s2m0) .&&. inCycle
Expand Down
35 changes: 29 additions & 6 deletions clash-vexriscv/src/VexRiscv.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE QuasiQuotes #-}

{-# OPTIONS_GHC -fconstraint-solver-iterations=10 #-}

module VexRiscv where

import Clash.Prelude
Expand All @@ -19,10 +21,10 @@ import Foreign.Marshal (alloca)
import Foreign.Storable
import GHC.IO (unsafePerformIO)
import GHC.Stack (HasCallStack)
import Language.Haskell.TH.Syntax
import Protocols.Wishbone
import VexRiscv.FFI
import VexRiscv.TH
import Language.Haskell.TH.Syntax


data Input = Input
Expand All @@ -32,13 +34,13 @@ data Input = Input
, iBusWbS2M :: "IBUS_IN_" ::: WishboneS2M (BitVector 32)
, dBusWbS2M :: "DBUS_IN_" ::: WishboneS2M (BitVector 32)
}
deriving (Generic, NFDataX, ShowX, Eq)
deriving (Generic, NFDataX, ShowX, Eq, BitPack)

data Output = Output
{ iBusWbM2S :: "IBUS_OUT_" ::: WishboneM2S 30 4 (BitVector 32)
, dBusWbM2S :: "DBUS_OUT_" ::: WishboneM2S 30 4 (BitVector 32)
}
deriving (Generic, NFDataX, ShowX, Eq)
deriving (Generic, NFDataX, ShowX, Eq, BitPack)

inputToFFI :: Bool -> Input -> INPUT
inputToFFI reset Input {..} =
Expand Down Expand Up @@ -82,6 +84,19 @@ outputFromFFI OUTPUT {..} =
}
}

-- When passing S2M values from Haskell to VexRiscv over the FFI, undefined
-- bits/values cause errors when forcing their evaluation to something that can
-- be passed through the FFI.
--
-- This function makes sure the Wishbone S2M values are free from undefined bits.
makeDefined :: WishboneS2M (BitVector 32) -> WishboneS2M (BitVector 32)
makeDefined wb = wb {readData = defaultX 0 (readData wb)}

defaultX :: (NFDataX a) => a -> a -> a
defaultX dflt val
| hasUndefined val = dflt
| otherwise = val

vexRiscv :: (HasCallStack, HiddenClockResetEnable dom) => Signal dom Input -> Signal dom Output
vexRiscv input =
Output <$>
Expand Down Expand Up @@ -111,13 +126,21 @@ vexRiscv input =

where
(unbundle -> (timerInterrupt, externalInterrupt, softwareInterrupt, iBusS2M, dBusS2M))
= (<$> input) $ \(Input a b c d e) -> (a, b, c, d, e)
-- A hack that enables us to both generate synthesizable HDL and simulate vexRisc in Haskell/Clash
= (<$> if clashSimulation then unpack 0 :- input else input)
$ \(Input a b c d e) -> (a, b, c, d, e)

(unbundle -> (iBus_DAT_MISO, iBus_ACK, iBus_ERR))
= (<$> iBusS2M) $ \(WishboneS2M a b c _ _) -> (a, b, c)
= (\(WishboneS2M a b c _ _) -> (a, b, c))
-- A hack that enables us to both generate synthesizable HDL and simulate vexRisc in Haskell/Clash
. (if clashSimulation then makeDefined else id)
<$> iBusS2M

(unbundle -> (dBus_DAT_MISO, dBus_ACK, dBus_ERR))
= (<$> dBusS2M) $ \(WishboneS2M a b c _ _) -> (a, b, c)
= (\(WishboneS2M a b c _ _) -> (a, b, c))
-- A hack that enables us to both generate synthesizable HDL and simulate vexRisc in Haskell/Clash
. (if clashSimulation then makeDefined else id)
<$> dBusS2M

sourcePath = $(do
cpuSrcPath <- runIO $ getPackageRelFilePath "example-cpu/VexRiscv.v"
Expand Down
33 changes: 33 additions & 0 deletions nix/nixpkgs.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# SPDX-FileCopyrightText: 2022 Google LLC
#
# SPDX-License-Identifier: Apache-2.0
{ sources ? import ./sources.nix }:

let
rust_overlay = import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz");
overlay = _: nixpkgs: {
# Nix tooling
niv = (import sources.niv {}).niv;
gitignore = import sources.gitignore { inherit (nixpkgs) lib; };

# Haskell overrides
haskellPackages = nixpkgs.haskellPackages.override {
overrides = self: super: {
# Disables library profiling, documentation building, and building/running
# test suites to speed up compilation times. This should only be applied
# to local packages. Adding them to others will defeat caching.
applyPrefs = p:
(nixpkgs.haskell.lib.disableLibraryProfiling
(nixpkgs.haskell.lib.dontHaddock
(nixpkgs.haskell.lib.dontCheck p)));

# External overrides
# .. no external overrides yet ..

# Internal overrides
# .. no internal overrides yet ..
};
};
};

in import sources.nixpkgs { overlays = [ rust_overlay overlay ]; }
26 changes: 26 additions & 0 deletions nix/sources.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"gitignore": {
"branch": "master",
"description": "Nix functions for filtering local git sources",
"homepage": "",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"sha256": "07vg2i9va38zbld9abs9lzqblz193vc5wvqd6h7amkmwf66ljcgh",
"type": "tarball",
"url": "https://github.com/hercules-ci/gitignore.nix/archive/a20de23b925fd8264fd7fad6454652e142fd7f73.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixpkgs": {
"branch": "nixos-22.11",
"description": "Nix Packages collection",
"homepage": "",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8c54d842d9544361aac5f5b212ba04e4089e8efe",
"sha256": "14hk2lyxy8ajczn77363vw05w24fyx9889q3b89riqgs28acyz87",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/8c54d842d9544361aac5f5b212ba04e4089e8efe.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}
3 changes: 3 additions & 0 deletions nix/sources.json.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2023 Google LLC

SPDX-License-Identifier: CC0-1.0
Loading

0 comments on commit 72cf31b

Please sign in to comment.