Skip to content

Add Ethernet core #8

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

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ca5b6dd
Add clash-protocols as dependency
DigitalBrains1 Jan 29, 2025
832b1bc
Add Ethernet core
t-wallet Aug 28, 2024
62bddf6
Add top-level MAC module and improve its documentation
t-wallet Aug 28, 2024
6fbb3a7
Remove ARP stack example
t-wallet Aug 30, 2024
018f785
Document ICMP module
t-wallet Sep 2, 2024
8dbf0fd
Signicantly overhaul the Ethernet tests
t-wallet Sep 2, 2024
996839d
Refer to RFC 1624 in ICMP docs
t-wallet Sep 9, 2024
8320c58
Change the stripping of the preamble
t-wallet Sep 10, 2024
d4333e3
Add preamble test to unittests
t-wallet Sep 10, 2024
0c630cb
Simplify fcs validator and strip fcs
t-wallet Sep 14, 2024
143523c
Add detailed MAC TX example
t-wallet Sep 14, 2024
230794c
Upstream partitionS
t-wallet Sep 16, 2024
6feb2eb
Add top level IPv4 module, move InternetChecksum out of IP module
t-wallet Sep 16, 2024
fbc837b
100% documentation coverage, removed unqualified identifiers
t-wallet Sep 16, 2024
fbfeb41
Arp: fix timing issues and improve documentation
t-wallet Sep 20, 2024
1c756b3
Add multi-entry ARP table
t-wallet Sep 21, 2024
4be3802
ARP documentation improvements
t-wallet Sep 21, 2024
06c4cbb
EthernetStream: update outdated documentation, improve readability
t-wallet Sep 23, 2024
0c7794e
Make full UDP stack example more flexible
t-wallet Sep 27, 2024
d4f1db6
Udp: add port swapping, improve docs
t-wallet Sep 27, 2024
db9a614
Remove unused internet checksum functions: see new PR
t-wallet Sep 30, 2024
cb2e0df
Ethernet: support zero-byte transfers. (#19)
t-wallet Nov 14, 2024
0a59201
Support undefined null bytes
t-wallet Nov 14, 2024
3480b58
Unify copyright/license/maintainer notes
t-wallet Nov 22, 2024
422143e
IPv4: add utility functions, improve documentation.
t-wallet Nov 22, 2024
cc73de4
IPPacketizers: run formatter, improve docs
t-wallet Nov 22, 2024
f070e21
Internet checksum: improve docs, optimize
t-wallet Nov 22, 2024
acab5e1
Run formatter
t-wallet Nov 22, 2024
17d9213
Add detailed MAC RX example
t-wallet Nov 22, 2024
0a8d402
Edit detailed full stack example
t-wallet Feb 5, 2025
2ba0ed5
Revert undesired changes to Nix sources
DigitalBrains1 Feb 20, 2025
e65d92b
Remove duplicate dependency
DigitalBrains1 Feb 1, 2025
cf826f4
Increase test timeout
DigitalBrains1 Feb 2, 2025
55bbfba
The Ethernet core does not compile with Clash 1.8
DigitalBrains1 Feb 2, 2025
1e598a5
Fix partial function warnings
DigitalBrains1 Feb 2, 2025
fe1f4e8
Use temporary version of clash-protocols
DigitalBrains1 Feb 1, 2025
a209a4b
Fix bug in interpacket gap inserter
t-wallet Mar 10, 2025
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
14 changes: 14 additions & 0 deletions cabal.project-common
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,17 @@ package recursion-schemes
-- with -O2 provides gains around 5% to 10% in simple benchmarks
package regex-tdfa
optimization: 2

source-repository-package
type: git
location: https://github.com/cchalmers/circuit-notation.git
tag: 564769c52aa05b90f81bbc898b7af7087d96613d

source-repository-package
type: git
location: https://github.com/clash-lang/clash-protocols.git
tag: 15b4f4fe560f217609a387f4256927046099715c
subdir: clash-protocols-base clash-protocols

allow-newer:
clash-protocols:tasty
41 changes: 40 additions & 1 deletion clash-cores.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ common basic-config

build-depends:
base >= 4.18 && < 5,
clash-protocols,
constraints >= 0.9 && < 1.0,
containers >=0.5 && <0.8,
deepseq,
ghc-typelits-extra >= 0.3.2,
ghc-typelits-knownnat >= 0.6,
ghc-typelits-natnormalise >= 0.6,
Expand Down Expand Up @@ -174,6 +176,27 @@ library

if !flag(clash-18)
exposed-modules:
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.Sgmii
Clash.Cores.Sgmii.AutoNeg
Clash.Cores.Sgmii.BitSlip
Expand All @@ -186,8 +209,14 @@ library
Clash.Cores.Sgmii.Sync

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

if !flag(clash-18)
other-modules:
Clash.Signal.Extra

ghc-options:
-fexpose-all-unfoldings
-fno-worker-wrapper
Expand Down Expand Up @@ -225,6 +254,17 @@ test-suite unit-tests

if !flag(clash-18)
other-modules:
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.Sgmii.AutoNeg
Test.Cores.Sgmii.BitSlip
Test.Cores.Sgmii.RateAdapt
Expand All @@ -234,7 +274,6 @@ test-suite unit-tests
build-depends:
clash-cores,
clash-prelude-hedgehog,
deepseq,
hedgehog,
tasty >= 1.2 && < 1.6,
tasty-hedgehog >= 1.2.0,
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
5 changes: 5 additions & 0 deletions nix/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
37 changes: 25 additions & 12 deletions nix/sources.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
{
"circuit-notation": {
"branch": "master",
"description": "A plugin for circuit notation",
"homepage": null,
"owner": "cchalmers",
"repo": "circuit-notation",
"rev": "564769c52aa05b90f81bbc898b7af7087d96613d",
"sha256": "117kry20wxgxlpvrs050v96xvai8mq81vsrm6d8sbilc7d3cpxxh",
"type": "tarball",
"url": "https://github.com/cchalmers/circuit-notation/archive/564769c52aa05b90f81bbc898b7af7087d96613d.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"clash-compiler": {
"branch": "1.8",
"description": "Haskell to VHDL/Verilog/SystemVerilog compiler",
Expand All @@ -12,6 +24,19 @@
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz",
"version": "1.8.2"
},
"clash-protocols": {
"branch": "main",
"branch": "peter/for-ethernet-core",
"description": "a battery-included library for dataflow protocols",
"homepage": null,
"owner": "clash-lang",
"repo": "clash-protocols",
"rev": "15b4f4fe560f217609a387f4256927046099715c",
"sha256": "0ixs021kadbl70q6mgqfrq0pylc9qh1l519n384ij28l9w5x6ana",
"type": "tarball",
"url": "https://github.com/clash-lang/clash-protocols/archive/15b4f4fe560f217609a387f4256927046099715c.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"doctest-parallel": {
"branch": "main",
"description": "Test interactive Haskell examples",
Expand Down Expand Up @@ -50,18 +75,6 @@
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz",
"version": "1.4"
},
"circuit-notation": {
"branch": "master",
"description": "A plugin for circuit notation",
"homepage": null,
"owner": "cchalmers",
"repo": "circuit-notation",
"rev": "19b386c4aa3ff690758ae089c7754303f3500cc9",
"sha256": "0qz2w6akxj51kq50rbl88bnjyxzd2798a9sn9jj1z2kak7a6kqbg",
"type": "tarball",
"url": "https://github.com/cchalmers/circuit-notation/archive/19b386c4aa3ff690758ae089c7754303f3500cc9.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"niv": {
"branch": "master",
"description": "Easy dependency management for Nix projects",
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