Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ethernet core #8

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0c59cff
Add Ethernet core
t-wallet Aug 28, 2024
9cf12fd
Add top-level MAC module and improve its documentation
t-wallet Aug 28, 2024
b89f52e
Remove ARP stack example
t-wallet Aug 30, 2024
669673f
Document ICMP module
t-wallet Sep 2, 2024
a73282a
Signicantly overhaul the Ethernet tests
t-wallet Sep 2, 2024
29d774d
Refer to RFC 1624 in ICMP docs
t-wallet Sep 9, 2024
a3c4a6f
Change the stripping of the preamble
t-wallet Sep 10, 2024
60cd05b
Add preamble test to unittests
t-wallet Sep 10, 2024
270e582
Simplify fcs validator and strip fcs
t-wallet Sep 14, 2024
44626b8
Add detailed MAC TX example
t-wallet Sep 14, 2024
3b031f2
Upstream partitionS
t-wallet Sep 16, 2024
52a3f2d
Add top level IPv4 module, move InternetChecksum out of IP module
t-wallet Sep 16, 2024
039aa9e
100% documentation coverage, removed unqualified identifiers
t-wallet Sep 16, 2024
69f8944
Arp: fix timing issues and improve documentation
t-wallet Sep 20, 2024
903707e
Add multi-entry ARP table
t-wallet Sep 21, 2024
815b19c
ARP documentation improvements
t-wallet Sep 21, 2024
3acdaff
EthernetStream: update outdated documentation, improve readability
t-wallet Sep 23, 2024
2658307
Make full UDP stack example more flexible
t-wallet Sep 27, 2024
c70dc3b
Udp: add port swapping, improve docs
t-wallet Sep 27, 2024
4b5be3f
Remove unused internet checksum functions: see new PR
t-wallet Sep 30, 2024
bd518d3
Ethernet: support zero-byte transfers. (#19)
t-wallet Nov 14, 2024
e5dd967
Support undefined null bytes
t-wallet Nov 14, 2024
5c6df09
Unify copyright/license/maintainer notes
t-wallet Nov 22, 2024
3b2af77
IPv4: add utility functions, improve documentation.
t-wallet Nov 22, 2024
7e7c464
IPPacketizers: run formatter, improve docs
t-wallet Nov 22, 2024
c86dcfb
Internet checksum: improve docs, optimize
t-wallet Nov 22, 2024
bb0c3f0
Run formatter
t-wallet Nov 22, 2024
a1ddf8b
Add detailed MAC RX example
t-wallet Nov 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions clash-cores.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ common basic-config
build-depends:
base >= 4.10 && < 5,
clash-prelude,
clash-protocols,
constraints,
containers >=0.5 && <0.8,
deepseq,
ghc-typelits-extra >= 0.3.2,
ghc-typelits-knownnat >= 0.6,
ghc-typelits-natnormalise >= 0.6,
Expand All @@ -126,6 +128,27 @@ library
Clash.Cores.Crc
Clash.Cores.Crc.Internal
Clash.Cores.Crc.Catalog
Clash.Cores.Ethernet.Arp
Clash.Cores.Ethernet.Arp.ArpManager
Clash.Cores.Ethernet.Arp.ArpTable
Clash.Cores.Ethernet.Arp.ArpTypes
Clash.Cores.Ethernet.Examples.FullUdpStack
Clash.Cores.Ethernet.Examples.RxStacks
Clash.Cores.Ethernet.Examples.TxStacks
Clash.Cores.Ethernet.Icmp
Clash.Cores.Ethernet.InternetChecksum
Clash.Cores.Ethernet.IPv4
Clash.Cores.Ethernet.IP.EthernetStream
Clash.Cores.Ethernet.IP.IPPacketizers
Clash.Cores.Ethernet.IP.IPv4Types
Clash.Cores.Ethernet.Mac
Clash.Cores.Ethernet.Mac.EthernetTypes
Clash.Cores.Ethernet.Mac.FrameCheckSequence
Clash.Cores.Ethernet.Mac.InterpacketGapInserter
Clash.Cores.Ethernet.Mac.MacPacketizers
Clash.Cores.Ethernet.Mac.PaddingInserter
Clash.Cores.Ethernet.Mac.Preamble
Clash.Cores.Ethernet.Udp
Clash.Cores.LatticeSemi.ECP5.Blackboxes.IO
Clash.Cores.LatticeSemi.ECP5.IO
Clash.Cores.LatticeSemi.ICE40.Blackboxes.IO
Expand Down Expand Up @@ -165,6 +188,9 @@ library
Clash.Cores.Xilinx.Xpm.Cdc.SyncRst

other-modules:
Clash.Signal.Extra
Clash.Sized.Vector.Extra
Data.Maybe.Extra
Data.Text.Extra

ghc-options:
Expand Down Expand Up @@ -197,6 +223,17 @@ test-suite unittests

other-Modules:
Test.Cores.Crc
Test.Cores.Ethernet
Test.Cores.Ethernet.Arp.ArpManager
Test.Cores.Ethernet.Base
Test.Cores.Ethernet.InternetChecksum
Test.Cores.Ethernet.Icmp
Test.Cores.Ethernet.IP.EthernetStream
Test.Cores.Ethernet.IP.IPPacketizers
Test.Cores.Ethernet.Mac.FrameCheckSequence
Test.Cores.Ethernet.Mac.InterpacketGapInserter
Test.Cores.Ethernet.Mac.PaddingInserter
Test.Cores.Ethernet.Mac.Preamble
Test.Cores.Internal.SampleSPI
Test.Cores.LineCoding8b10b
Test.Cores.Internal.Signals
Expand Down
2 changes: 2 additions & 0 deletions fourmolu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
indentation: 2
column-limit: 90
7 changes: 6 additions & 1 deletion nix/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ let
};
};

# Haskell overrides
# Haskell overrides
haskellPackages = pkgs.haskell.packages.${haskell_compiler}.override {
overrides = self: super: {
# Ignore dependency bounds for tasty < 1.5
Expand All @@ -42,6 +42,11 @@ let
self.callCabal2nix "doctest-parallel" sources.doctest-parallel {};
clash-prelude =
self.callCabal2nix "clash-prelude" (sources.clash-compiler + "/clash-prelude") {};
# clash-protocols also requires tasty < 1.5, so we need to jailbreak.
clash-protocols-base =
pkgs.haskell.lib.doJailbreak (self.callCabal2nix "clash-protocols-base" (sources.clash-protocols + "/clash-protocols-base") {});
clash-protocols =
pkgs.haskell.lib.doJailbreak (self.callCabal2nix "clash-protocols" (sources.clash-protocols + "/clash-protocols") {});
clash-lib =
self.callCabal2nix "clash-lib" (sources.clash-compiler + "/clash-lib") {};
clash-ghc =
Expand Down
18 changes: 15 additions & 3 deletions nix/sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@
"homepage": "https://clash-lang.org/",
"owner": "clash-lang",
"repo": "clash-compiler",
"rev": "b14ff0ef2ccfad8854210a9035e9db1e32b3be07",
"sha256": "00gq0v4fi2dy13xchllxxhhjfpvvj0ig8cgp5y65c7zb7qw5b30y",
"rev": "f946617561565440d82f67747acb2486f6526a66",
"sha256": "0924xzzwzrpjb1yid9mvy2imxwrzyxfdmkd2l1wfrsdwgrc53dpg",
"type": "tarball",
"url": "https://github.com/clash-lang/clash-compiler/archive/b14ff0ef2ccfad8854210a9035e9db1e32b3be07.tar.gz",
"url": "https://github.com/clash-lang/clash-compiler/archive/f946617561565440d82f67747acb2486f6526a66.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz",
"version": "1.8.1"
},
"clash-protocols": {
"branch": "packetstream",
"description": "a battery-included library for dataflow protocols",
"homepage": null,
"owner": "clash-lang",
"repo": "clash-protocols",
"rev": "2e9557dc974687e52bfacf9b6feccc6ba125e3ce",
"sha256": "0d362mkc298mcs3rhwdjcgmks5wy5zlqc66rspbf9bar8ai2rjpy",
"type": "tarball",
"url": "https://github.com/clash-lang/clash-protocols/archive/2e9557dc974687e52bfacf9b6feccc6ba125e3ce.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"doctest-parallel": {
"branch": "main",
"description": "Test interactive Haskell examples",
Expand Down
95 changes: 95 additions & 0 deletions src/Clash/Cores/Ethernet/Arp.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -fplugin=Protocols.Plugin #-}

{- |
Copyright : (C) 2024, QBayLogic B.V.
License : BSD2 (see the file LICENSE)
Maintainer : QBayLogic B.V. <[email protected]>

Provides a top-level ARP circuit sufficient for most use cases, along with
the individual components it is composed of.
-}
module Clash.Cores.Ethernet.Arp (
-- * Types, constants and simple operations
module Clash.Cores.Ethernet.Arp.ArpTypes,

-- * Top-level ARP stack
arpC,

-- * Individual components
module Clash.Cores.Ethernet.Arp.ArpTable,
module Clash.Cores.Ethernet.Arp.ArpManager,
) where

import Clash.Prelude

import Protocols
import qualified Protocols.Df as Df
import Protocols.PacketStream

import Clash.Cores.Ethernet.Arp.ArpManager
import Clash.Cores.Ethernet.Arp.ArpTable
import Clash.Cores.Ethernet.Arp.ArpTypes
import Clash.Cores.Ethernet.IP.IPv4Types
import Clash.Cores.Ethernet.Mac.EthernetTypes

{- |
A fully functional ARP stack which handles ARP lookups from client circuits.
Maintains a multi-entry ARP table which the client circuit can query via the
'ArpLookup' input. If the client-supplied IPv4 address is not found in the
table, it broadcasts an ARP request for this specific address. The circuit will
assert backpressure until either a reply has been received, or a timeout
occurs. The maximum number of milliseconds the stack will wait for a reply to
this request is configurable. The timeout (in seconds) of ARP table entries is
configurable as well.

Moreover, it takes in an Ethernet packet stream with the ARP etherType
(0x0806), and updates the ARP table upon receiving a valid ARP reply or
gratuitous ARP packet. If an ARP request directed to our IPv4 address is
received, it transmits a reply. Outbound requests receive priority over
outbound replies in the output stream.

For more specific information, refer to the documentation of the individual
components.
-}
arpC ::
forall
(dataWidth :: Nat)
(dom :: Domain)
(maxAgeSeconds :: Nat)
(maxWaitMs :: Nat)
(tableDepth :: Nat).
(HiddenClockResetEnable dom) =>
(KnownNat dataWidth) =>
(1 <= dataWidth) =>
(1 <= tableDepth) =>
-- | Entries are evicted from the ARP table this many seconds after being inserted
SNat maxAgeSeconds ->
-- | The maximum amount of milliseconds to wait for an incoming ARP reply
SNat maxWaitMs ->
-- | The ARP table will contain @2^depth@ entries
SNat tableDepth ->
-- | Our MAC address
Signal dom MacAddress ->
-- | Our IPv4 address
Signal dom IPv4Address ->
Circuit
(PacketStream dom dataWidth EthernetHeader, ArpLookup dom)
(PacketStream dom dataWidth EthernetHeader)
arpC maxAge maxWaitMs tableDepth ourMacS ourIPv4S =
circuit $ \(ethStream, lookupIn) -> do
-- Add a skid buffer to improve timing. We don't need the metadata, so we
-- can throw it away.
bufferedStream <- mapMeta (const ()) |> registerBoth -< ethStream
(entry, replyOut) <- arpReceiverC ourIPv4S -< bufferedStream
(lookupOut, requestOut) <- arpManagerC maxWaitMs -< lookupIn
() <- arpTableC tableDepth maxAge -< (lookupOut, entry)
-- Being biased towards outbound requests is favourable, as it
-- lessens the impact of ARP request DoS attacks. Moreover,
-- @CollectMode@ @Df.Parallel@ is not always more expensive
-- than @Df.Skip@ with two sources. Under certain circumstances
-- it may be cheaper.
arpPktOut <- Df.roundrobinCollect Df.Parallel -< [replyOut, requestOut]
arpStreamOut <- arpTransmitterC ourMacS ourIPv4S |> registerBoth -< arpPktOut
mapMetaS ((\src dst -> EthernetHeader dst src arpEtherType) <$> ourMacS)
-< arpStreamOut
Loading