From 2cdde1787c6a891f9e139bc1a41908073d4623a9 Mon Sep 17 00:00:00 2001 From: John Demme Date: Thu, 14 Nov 2024 11:57:12 -0500 Subject: [PATCH] [PyCDE] Binding for FIFOs (#7806) Adds a `seq` module which contains a FIFO class which produces a `seq.fifo` op. Does not include anything related to almost full/empty. --- frontends/PyCDE/src/CMakeLists.txt | 1 + frontends/PyCDE/src/pycde/seq.py | 61 ++++++++++++++++++++++++++++++ frontends/PyCDE/test/test_seq.py | 53 ++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 frontends/PyCDE/src/pycde/seq.py create mode 100644 frontends/PyCDE/test/test_seq.py diff --git a/frontends/PyCDE/src/CMakeLists.txt b/frontends/PyCDE/src/CMakeLists.txt index a3a87a27bf45..cbcd48839214 100644 --- a/frontends/PyCDE/src/CMakeLists.txt +++ b/frontends/PyCDE/src/CMakeLists.txt @@ -32,6 +32,7 @@ declare_mlir_python_sources(PyCDESources pycde/system.py pycde/devicedb.py pycde/instance.py + pycde/seq.py pycde/signals.py pycde/ndarray.py pycde/esi.py diff --git a/frontends/PyCDE/src/pycde/seq.py b/frontends/PyCDE/src/pycde/seq.py new file mode 100644 index 000000000000..6170fd24019d --- /dev/null +++ b/frontends/PyCDE/src/pycde/seq.py @@ -0,0 +1,61 @@ +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from .circt.dialects import seq as raw_seq +from .constructs import Wire + +from .types import Bits, Type +from .signals import _FromCirctValue, BitsSignal, ClockSignal, Signal + + +class FIFO: + """Creates a FIFO operation with the specified type, depth, clock, and reset + signal. Adds push and pop methods to wire up the FIFO.""" + + def __init__(self, + type: Type, + depth: int, + clk: ClockSignal, + rst: BitsSignal, + rd_latency: int = 0): + self.type = type + self.input = Wire(type) + self.wr_en = Wire(Bits(1)) + self.rd_en = Wire(Bits(1)) + i1 = Bits(1)._type + self.fifo = raw_seq.FIFOOp(self.input.type._type, + i1, + i1, + i1, + i1, + self.input.value, + self.rd_en.value, + self.wr_en.value, + clk.value, + rst.value, + depth, + rdLatency=rd_latency) + self._output = _FromCirctValue(self.fifo.output) + + def push(self, data: Signal, en: BitsSignal): + """Connect 'data' to the FIFO input and 'en' to write enable.""" + self.input.assign(data) + self.wr_en.assign(en) + + def pop(self, en: BitsSignal): + """Wire up 'en' to read enable and returns the FIFO output.""" + self.rd_en.assign(en) + return self._output + + @property + def output(self): + return self._output + + @property + def full(self): + return _FromCirctValue(self.fifo.full) + + @property + def empty(self): + return _FromCirctValue(self.fifo.empty) diff --git a/frontends/PyCDE/test/test_seq.py b/frontends/PyCDE/test/test_seq.py new file mode 100644 index 000000000000..95385fb89f1e --- /dev/null +++ b/frontends/PyCDE/test/test_seq.py @@ -0,0 +1,53 @@ +# RUN: %PYTHON% %s | FileCheck %s + +from pycde import Module, Clock, Reset, Input, Output +from pycde.seq import FIFO +from pycde.testing import unittestmodule +from pycde.types import Bits, UInt + +from pycde.module import generator + +# CHECK-LABEL: hw.module @SimpleFIFOTest(in %clk : !seq.clock, in %rst : i1) +# CHECK-NEXT: %false = hw.constant false +# CHECK-NEXT: [[R0:%.+]] = hwarith.constant 0 : ui32 +# CHECK-NEXT: %out, %full, %empty, %almostFull, %almostEmpty = seq.fifo depth 16 in [[R0]] rdEn %false wrEn %false clk %clk rst %rst : ui32 + + +@unittestmodule(run_passes=False) +class SimpleFIFOTest(Module): + clk = Clock() + rst = Reset() + + @generator + def construct(ports): + c0 = Bits(1)(0) + ui32 = UInt(32)(0) + + fifo = FIFO(type=UInt(32), depth=16, clk=ports.clk, rst=ports.rst) + fifo.push(ui32, c0) + fifo.pop(c0) + + +# CHECK-LABEL: hw.module @SimpleFIFOTestRd1(in %clk : !seq.clock, in %rst : i1) +# CHECK-NEXT: %false = hw.constant false +# CHECK-NEXT: [[R0:%.+]] = hwarith.constant 0 : ui32 +# CHECK-NEXT: %out, %full, %empty, %almostFull, %almostEmpty = seq.fifo depth 16 rd_latency 1 in [[R0]] rdEn %false wrEn %false clk %clk rst %rst : ui32 + + +@unittestmodule(run_passes=False) +class SimpleFIFOTestRd1(Module): + clk = Clock() + rst = Reset() + + @generator + def construct(ports): + c0 = Bits(1)(0) + ui32 = UInt(32)(0) + + fifo = FIFO(type=UInt(32), + depth=16, + clk=ports.clk, + rst=ports.rst, + rd_latency=1) + fifo.push(ui32, c0) + fifo.pop(c0)