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

nmigen.lib: Add RoundRobin #450

Merged
merged 20 commits into from Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f233f09
nmigen.lib: Add RoundRobin
Jul 24, 2020
30176ab
nmigen.compat.genlib: Use RoundRobin implementation from oMigen
Jul 24, 2020
37c14c4
Remove buggy formal test case
Jul 24, 2020
bb2fafd
Revamp RoundRobin interface and tests, add documentation
Jul 24, 2020
24d9954
nmigen.test.test_lib_roundrobin: Validate width parameter
Jul 24, 2020
fed5de2
nmigen.test.test_lib_roundrobin: Add tests for parameters, add simula…
Jul 24, 2020
578b554
nmigen.test.test_lib_roundrobin: Add delay to take delta cycle into a…
Jul 24, 2020
237a505
nmigen.lib.roundrobin: Remove EnableInserter
Jul 27, 2020
77c99b9
nmigen.lib.roundrobin: Fix ValueError message in constructor
Jul 28, 2020
0e00f12
nmigen.test.test_lib_roundrobin: Fix test_wrong_width regex
Jul 28, 2020
dbd3926
nmigen.lib.roundrobin: Add valid output
Jul 28, 2020
69d697e
nmigen.lib.roundrobin: Use .any() instead of reduce(or_, ...)
Jul 28, 2020
de770e5
nmigen.compat.genlib.roundrobin: Update deprecation warning, make it …
Jul 28, 2020
7680568
nmigen.lib.roundrobin: Reformulate grant and valid descriptions
Jul 28, 2020
4f9c2ad
nmigen.lib.roundrobin: Update Elaboratable and attributes documentation
Jul 28, 2020
1eac37c
Rename nmigen.lib.roundrobin to nmigen.lib.scheduler
Jul 28, 2020
f92af9b
Update nmigen/compat/genlib/roundrobin.py
Jul 28, 2020
ec4c336
Update nmigen/compat/genlib/roundrobin.py
Jul 28, 2020
ff198d1
nmigen.lib.scheduler: Rename width to count in RoundRobin
Jul 28, 2020
74c3ec4
Merge branch 'roundrobin' of github.com:jeanthom/nmigen into roundrobin
Jul 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions nmigen/compat/genlib/roundrobin.py
@@ -0,0 +1,22 @@
from ..._utils import deprecated
from ...lib.roundrobin import RoundRobin as NativeRoundRobin


__all__ = ["RoundRobin", "SP_WITHDRAW", "SP_CE"]

(SP_WITHDRAW, SP_CE) = range(2)

@deprecated("instead of `migen.genlib.roundrobin.RoundRobin`, "
"use `nmigen.lib.roundrobin.RoundRobin`; note that RoundRobin does not "
"require a policy anymore, and that the `ce` attribute has been renamed"
"to `en`")
jeanthom marked this conversation as resolved.
Show resolved Hide resolved
class CompatRoundRobin(NativeRoundRobin):
def __init__(self, n, switching_policy=SP_WITHDRAW):
super().__init__(n)

if switching_policy == SP_CE:
self.ce = Signal()
self.comb += self.en.eq(self.ce)
jeanthom marked this conversation as resolved.
Show resolved Hide resolved


RoundRobin = CompatRoundRobin
28 changes: 28 additions & 0 deletions nmigen/lib/roundrobin.py
@@ -0,0 +1,28 @@
from .. import *


__all__ = ["RoundRobin"]


class RoundRobin(Elaboratable):
def __init__(self, n):
self.requests = Signal(n)
self.grant = Signal(range(n))
self.en = Signal(reset=1)

def elaborate(self, platform):
m = Module()

n = self.requests.width

with m.Switch(self.grant):
for i in range(n):
with m.Case(i):
for pred in reversed(range(i)):
with m.If(self.requests[pred]):
m.d.sync += self.grant.eq(pred)
for succ in reversed(range(i + 1, n)):
with m.If(self.requests[succ]):
m.d.sync += self.grant.eq(succ)

return EnableInserter(self.en)(m)
54 changes: 54 additions & 0 deletions nmigen/test/test_lib_roundrobin.py
@@ -0,0 +1,54 @@
from .utils import *
from ..hdl import *
from ..asserts import *
from ..sim.pysim import *
from ..lib.roundrobin import *

class RoundRobinIndividualSpec(Elaboratable):
def __init__(self, n):
self.n = n

def elaborate(self, platform):
m = Module()

m.submodules.dut = dut = RoundRobin(self.n)

for i in range(self.n):
m.d.sync += Assert((Past(dut.requests) == (1 << i)).implies(dut.grant == i))

return m

class RoundRobinTestCase(FHDLTestCase):
def test_individual(self):
self.assertFormal(RoundRobinIndividualSpec(1))
self.assertFormal(RoundRobinIndividualSpec(10))

def test_transitions(self):
m = Module()
m.submodules.dut = dut = RoundRobin(3)

sim = Simulator(m)
def process():
yield dut.requests.eq(0b11)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield dut.grant), 1)

yield dut.requests.eq(0b01)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield dut.grant), 0)

yield dut.requests.eq(0b01)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield dut.grant), 0)

yield dut.requests.eq(0b10)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield dut.grant), 1)

yield dut.requests.eq(0b01)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield dut.grant), 0)
sim.add_process(process)
sim.add_clock(1e-6)
with sim.write_vcd("test.vcd"):
sim.run()