Skip to content

Commit

Permalink
BasicFifo tweaks (#516)
Browse files Browse the repository at this point in the history
  • Loading branch information
lekcyjna123 authored Dec 1, 2023
1 parent 324ce64 commit e898af5
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 17 deletions.
2 changes: 2 additions & 0 deletions test/utils/test_fifo.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from amaranth import *
from amaranth.sim import Settle

from transactron.utils.fifo import BasicFifo
from transactron.lib import AdapterTrans
Expand Down Expand Up @@ -55,6 +56,7 @@ def source():

if random.random() < 0.005:
yield from fifoc.fifo_clear.call()
yield Settle()
expq.clear()

self.done = True
Expand Down
31 changes: 14 additions & 17 deletions transactron/utils/fifo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from transactron import Method, def_method, Priority, TModule
from transactron._utils import MethodLayout
from transactron.utils._typing import ValueLike
from transactron.utils.utils import mod_incr


class BasicFifo(Elaboratable):
Expand Down Expand Up @@ -51,25 +52,21 @@ def __init__(self, layout: MethodLayout, depth: int) -> None:
# current fifo depth
self.level = Signal((self.depth).bit_length())

self.clear.add_conflict(self.read, Priority.LEFT)
self.clear.add_conflict(self.write, Priority.LEFT)
# for interface compatibility with MultiportFifo
self.read_methods = [self.read]
self.write_methods = [self.write]

def elaborate(self, platform):
def mod_incr(sig: Value, mod: int) -> Value:
# perform (sig+1)%mod operation
if mod == 2 ** len(sig):
return sig + 1
return Mux(sig == mod - 1, 0, sig + 1)

m = TModule()

m.submodules.buff_rdport = self.buff_rdport = self.buff.read_port(
domain="comb", transparent=True
) # FWFT behaviour
next_read_idx = Signal.like(self.read_idx)
m.d.comb += next_read_idx.eq(mod_incr(self.read_idx, self.depth))

m.submodules.buff_rdport = self.buff_rdport = self.buff.read_port(domain="sync", transparent=True)
m.submodules.buff_wrport = self.buff_wrport = self.buff.write_port()

m.d.comb += self.read_ready.eq(self.level > 0)
m.d.comb += self.write_ready.eq(self.level < self.depth)
m.d.comb += self.read_ready.eq(self.level != 0)
m.d.comb += self.write_ready.eq(self.level != self.depth)

with m.If(self.read.run & ~self.write.run):
m.d.sync += self.level.eq(self.level - 1)
Expand All @@ -78,20 +75,20 @@ def mod_incr(sig: Value, mod: int) -> Value:
with m.If(self.clear.run):
m.d.sync += self.level.eq(0)

m.d.comb += self.buff_rdport.addr.eq(self.read_idx)
m.d.comb += self.buff_rdport.addr.eq(Mux(self.read.run, next_read_idx, self.read_idx))
m.d.comb += self.head.eq(self.buff_rdport.data)

@def_method(m, self.write, ready=self.write_ready)
def _(arg: Record) -> None:
m.d.comb += self.buff_wrport.addr.eq(self.write_idx)
m.d.comb += self.buff_wrport.data.eq(arg)
m.d.top_comb += self.buff_wrport.addr.eq(self.write_idx)
m.d.top_comb += self.buff_wrport.data.eq(arg)
m.d.comb += self.buff_wrport.en.eq(1)

m.d.sync += self.write_idx.eq(mod_incr(self.write_idx, self.depth))

@def_method(m, self.read, self.read_ready)
def _() -> ValueLike:
m.d.sync += self.read_idx.eq(mod_incr(self.read_idx, self.depth))
m.d.sync += self.read_idx.eq(next_read_idx)
return self.head

@def_method(m, self.clear)
Expand Down
10 changes: 10 additions & 0 deletions transactron/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,19 @@
"popcount",
"count_leading_zeros",
"count_trailing_zeros",
"mod_incr",
]


def mod_incr(sig: Value, mod: int) -> Value:
"""
Perform `(sig+1) % mod` operation.
"""
if mod == 2 ** len(sig):
return sig + 1
return Mux(sig == mod - 1, 0, sig + 1)


@contextmanager
def OneHotSwitch(m: ModuleLike, test: Value):
"""One-hot switch.
Expand Down

0 comments on commit e898af5

Please sign in to comment.