Add copyright
[gram.git] / gram / frontend / adaptation.py
index 64650fcd25d9207ca95e4e06e5242f1e823c4e67..938670358625b8a88e52d7dd880c965d3b4e0139 100644 (file)
@@ -1,15 +1,16 @@
 # This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
+# This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
 # License: BSD
 
-from migen import *
+from nmigen import *
+from nmigen.compat import Case
 
-from litex.soc.interconnect import stream
-
-from litedram.common import *
+from gram.common import *
+import gram.stream as stream
 
 # LiteDRAMNativePortCDC ----------------------------------------------------------------------------
 
-class LiteDRAMNativePortCDC(Module):
+class gramNativePortCDC(Elaboratable):
     def __init__(self, port_from, port_to,
                  cmd_depth   = 4,
                  wdata_depth = 16,
@@ -18,21 +19,34 @@ class LiteDRAMNativePortCDC(Module):
         assert port_from.data_width    == port_to.data_width
         assert port_from.mode          == port_to.mode
 
-        address_width     = port_from.address_width
-        data_width        = port_from.data_width
-        mode              = port_from.mode
-        clock_domain_from = port_from.clock_domain
-        clock_domain_to   = port_to.clock_domain
+        self._port_from = port_from
+        self._port_to = port_to
+        self._cmd_depth = cmd_depth
+        self._wdata_depth = wdata_depth
+        self._rdata_depth = rdata_depth
+
+    def elaborate(self, platform):
+        m = Module()
 
-        # # #
+        port_from = self._port_from
+        port_to = self._port_to
+        cmd_depth = self._cmd_depth
+        wdata_depth = self._wdata_depth
+        rdata_depth = self._rdata_depth
+
+        address_width = port_from.address_width
+        data_width = port_from.data_width
+        mode = port_from.mode
+        clock_domain_from = port_from.clock_domain
+        clock_domain_to = port_to.clock_domain
 
         cmd_fifo = stream.AsyncFIFO(
             [("we", 1), ("addr", address_width)], cmd_depth)
         cmd_fifo = ClockDomainsRenamer(
             {"write": clock_domain_from,
              "read":  clock_domain_to})(cmd_fifo)
-        self.submodules += cmd_fifo
-        self.submodules += stream.Pipeline(
+        m.submodules += cmd_fifo
+        m.submodules += stream.Pipeline(
             port_from.cmd, cmd_fifo, port_to.cmd)
 
         if mode == "write" or mode == "both":
@@ -41,8 +55,8 @@ class LiteDRAMNativePortCDC(Module):
             wdata_fifo = ClockDomainsRenamer(
                 {"write": clock_domain_from,
                  "read":  clock_domain_to})(wdata_fifo)
-            self.submodules += wdata_fifo
-            self.submodules += stream.Pipeline(
+            m.submodules += wdata_fifo
+            m.submodules += stream.Pipeline(
                 port_from.wdata, wdata_fifo, port_to.wdata)
 
         if mode == "read" or mode == "both":
@@ -50,13 +64,15 @@ class LiteDRAMNativePortCDC(Module):
             rdata_fifo = ClockDomainsRenamer(
                 {"write": clock_domain_to,
                  "read":  clock_domain_from})(rdata_fifo)
-            self.submodules += rdata_fifo
-            self.submodules += stream.Pipeline(
+            m.submodules += rdata_fifo
+            m.submodules += stream.Pipeline(
                 port_to.rdata, rdata_fifo, port_from.rdata)
 
+        return m
+
 # LiteDRAMNativePortDownConverter ------------------------------------------------------------------
 
-class LiteDRAMNativePortDownConverter(Module):
+class gramNativePortDownConverter(Elaboratable):
     """LiteDRAM port DownConverter
 
     This module reduces user port data width to fit controller data width.
@@ -74,7 +90,16 @@ class LiteDRAMNativePortDownConverter(Module):
         if port_from.data_width % port_to.data_width:
             raise ValueError("Ratio must be an int")
 
-        # # #
+        self._port_from = port_from
+        self._port_to = port_to
+        self._reverse = reverse
+
+    def elaborate(self, platform):
+        m = Module()
+
+        port_from = self._port_from
+        port_to = self._port_to
+        reverse = self._reverse
 
         ratio = port_from.data_width//port_to.data_width
         mode  = port_from.mode
@@ -82,40 +107,37 @@ class LiteDRAMNativePortDownConverter(Module):
         counter       = Signal(max=ratio)
         counter_reset = Signal()
         counter_ce    = Signal()
-        self.sync += \
-            If(counter_reset,
-                counter.eq(0)
-            ).Elif(counter_ce,
-                counter.eq(counter + 1)
-            )
 
-        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-        fsm.act("IDLE",
-            counter_reset.eq(1),
-            If(port_from.cmd.valid,
-                NextState("CONVERT")
-            )
-        )
-        fsm.act("CONVERT",
-            port_to.cmd.valid.eq(1),
-            port_to.cmd.we.eq(port_from.cmd.we),
-            port_to.cmd.addr.eq(port_from.cmd.addr*ratio + counter),
-            If(port_to.cmd.ready,
-                counter_ce.eq(1),
-                If(counter == ratio - 1,
-                    port_from.cmd.ready.eq(1),
-                    NextState("IDLE")
-                )
-            )
-        )
+        with m.If(counter_reset):
+            m.d.sync += counter.eq(0)
+        with m.Elif(counter_ce):
+            m.d.sync += counter.eq(counter+1)
+
+        with m.FSM():
+            with m.State("Idle"):
+                m.d.comb += counter_reset.eq(1)
+                with m.If(port_from.cmd.valid):
+                    m.next = "Convert"
+
+            with m.State("Convert"):
+                m.d.comb += [
+                    port_to.cmd.valid.eq(1),
+                    port_to.cmd.we.eq(port_from.cmd.we),
+                    port_to.cmd.addr.eq(port_from.cmd.addr*ratio + counter),
+                ]
+                with m.If(port_to.cmd.ready):
+                    m.d.comb += counter_ce.eq(1)
+                    with m.If(counter == ratio - 1):
+                        m.d.comb += port_from.cmd.ready.eq(1)
+                        m.next = "Idle"
 
         if mode == "write" or mode == "both":
             wdata_converter = stream.StrideConverter(
                 port_from.wdata.description,
                 port_to.wdata.description,
                 reverse=reverse)
-            self.submodules += wdata_converter
-            self.submodules += stream.Pipeline(
+            m.submodules += wdata_converter
+            m.submodules += stream.Pipeline(
                 port_from.wdata, wdata_converter, port_to.wdata)
 
         if mode == "read" or mode == "both":
@@ -123,13 +145,15 @@ class LiteDRAMNativePortDownConverter(Module):
                 port_to.rdata.description,
                 port_from.rdata.description,
                 reverse=reverse)
-            self.submodules += rdata_converter
-            self.submodules += stream.Pipeline(
+            m.submodules += rdata_converter
+            m.submodules += stream.Pipeline(
                 port_to.rdata, rdata_converter, port_from.rdata)
 
+        return m
+
 # LiteDRAMNativeWritePortUpConverter ---------------------------------------------------------------
 
-class LiteDRAMNativeWritePortUpConverter(Module):
+class gramNativeWritePortUpConverter(Elaboratable):
     # TODO: finish and remove hack
     """LiteDRAM write port UpConverter
 
@@ -147,7 +171,16 @@ class LiteDRAMNativeWritePortUpConverter(Module):
         if port_to.data_width % port_from.data_width:
             raise ValueError("Ratio must be an int")
 
-        # # #
+        self._port_from = port_from
+        self._port_to = port_to
+        self._reverse = reverse
+
+    def elaborate(self, platform):
+        m = Module()
+
+        port_from = self._port_from
+        port_to = self._port_to
+        reverse = self._reverse
 
         ratio = port_to.data_width//port_from.data_width
 
@@ -164,47 +197,47 @@ class LiteDRAMNativeWritePortUpConverter(Module):
                 counter.eq(counter + 1)
             )
 
-        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-        fsm.act("IDLE",
-            port_from.cmd.ready.eq(1),
-            If(port_from.cmd.valid,
-                counter_ce.eq(1),
-                NextValue(we, port_from.cmd.we),
-                NextValue(address, port_from.cmd.addr),
-                NextState("RECEIVE")
-            )
-        )
-        fsm.act("RECEIVE",
-            port_from.cmd.ready.eq(1),
-            If(port_from.cmd.valid,
-                counter_ce.eq(1),
-                If(counter == ratio-1,
-                    NextState("GENERATE")
-                )
-            )
-        )
-        fsm.act("GENERATE",
-            port_to.cmd.valid.eq(1),
-            port_to.cmd.we.eq(we),
-            port_to.cmd.addr.eq(address[log2_int(ratio):]),
-            If(port_to.cmd.ready,
-                NextState("IDLE")
-            )
-        )
+        with m.FSM():
+            with m.State("Idle"):
+                m.d.comb += port_from.cmd.ready.eq(1)
+                with m.If(port_from.cmd.valid):
+                    m.d.sync += [
+                        we.eq(port_from.cmd.we),
+                        address.eq(port_from.cmd.addr),
+                    ]
+                    m.next = "Receive"
+
+            with m.State("Receive"):
+                m.d.comb += port_from.cmd.ready.eq(1)
+                with m.If(port_from.cmd.valid):
+                    m.d.comb += counter_ce.eq(1)
+                    with m.If(counter == ratio-1):
+                        m.next = "Generate"
+
+            with m.State("Generate"):
+                m.d.comb += [
+                    port_to.cmd.valid.eq(1),
+                    port_to.cmd.we.eq(we),
+                    port_to.cmd.addr.eq(address[log2_int(ratio):]),
+                ]
+                with m.If(port_to.cmd.ready):
+                    m.next = "Idle"
 
         wdata_converter = stream.StrideConverter(
             port_from.wdata.description,
             port_to.wdata.description,
             reverse=reverse)
-        self.submodules += wdata_converter
-        self.submodules += stream.Pipeline(
+        m.submodules += wdata_converter
+        m.submodules += stream.Pipeline(
             port_from.wdata,
             wdata_converter,
             port_to.wdata)
 
+        return m
+
 # LiteDRAMNativeReadPortUpConverter ----------------------------------------------------------------
 
-class LiteDRAMNativeReadPortUpConverter(Module):
+class gramNativeReadPortUpConverter(Elaboratable):
     """LiteDRAM port UpConverter
 
     This module increase user port data width to fit controller data width.
@@ -221,42 +254,49 @@ class LiteDRAMNativeReadPortUpConverter(Module):
         if port_to.data_width % port_from.data_width:
             raise ValueError("Ratio must be an int")
 
-        # # #
+        self._port_from = port_from
+        self._port_to = port_to
+        self._reverse = reverse
 
-        ratio = port_to.data_width//port_from.data_width
+    def elaborate(self, platform):
+        m = Module()
 
+        port_from = self._port_from
+        port_to = self._port_to
+        reverse = self._reverse
+
+        ratio = port_to.data_width//port_from.data_width
 
         # Command ----------------------------------------------------------------------------------
 
         cmd_buffer = stream.SyncFIFO([("sel", ratio)], 4)
-        self.submodules += cmd_buffer
+        m.submodules += cmd_buffer
 
-        counter = Signal(max=ratio)
+        counter = Signal(range(ratio))
         counter_ce = Signal()
-        self.sync += \
-            If(counter_ce,
-                counter.eq(counter + 1)
-            )
+        with m.If(counter_ce):
+            m.d.sync += counter.eq(counter+1)
 
-        self.comb += \
-            If(port_from.cmd.valid,
-                If(counter == 0,
+        with m.If(port_from.cmd.valid):
+            with m.If(counter == 0):
+                m.d.comb += [
                     port_to.cmd.valid.eq(1),
                     port_to.cmd.addr.eq(port_from.cmd.addr[log2_int(ratio):]),
                     port_from.cmd.ready.eq(port_to.cmd.ready),
-                    counter_ce.eq(port_to.cmd.ready)
-                ).Else(
+                    counter_ce.eq(port_to.cmd.ready),
+                ]
+            with m.Else():
+                m.d.comb += [
                     port_from.cmd.ready.eq(1),
-                    counter_ce.eq(1)
-                )
-            )
+                    counter_ce.eq(1),
+                ]
 
         # TODO: fix sel
-        self.comb += \
-            If(port_to.cmd.valid & port_to.cmd.ready,
+        with m.If(port_to.cmd.valid & port_to.cmd.ready):
+            m.d.comb += [
                 cmd_buffer.sink.valid.eq(1),
-                cmd_buffer.sink.sel.eq(2**ratio-1)
-            )
+                cmd_buffer.sink.sel.eq(2**ratio-1),
+            ]
 
         # Datapath ---------------------------------------------------------------------------------
 
@@ -265,60 +305,70 @@ class LiteDRAMNativeReadPortUpConverter(Module):
             port_to.rdata.description,
             port_from.rdata.description,
             reverse=reverse)
-        self.submodules +=  rdata_buffer, rdata_converter
+        m.submodules +=  rdata_buffer, rdata_converter
 
         rdata_chunk       = Signal(ratio, reset=1)
         rdata_chunk_valid = Signal()
-        self.sync += \
-            If(rdata_converter.source.valid &
-               rdata_converter.source.ready,
-                rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1]))
-            )
+        with m.If(rdata_converter.source.valid & rdata_converter.source.ready):
+            m.d.sync += rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1]))
 
-        self.comb += [
+        m.d.comb += [
             port_to.rdata.connect(rdata_buffer.sink),
             rdata_buffer.source.connect(rdata_converter.sink),
             rdata_chunk_valid.eq((cmd_buffer.source.sel & rdata_chunk) != 0),
-            If(port_from.flush,
-                rdata_converter.source.ready.eq(1)
-            ).Elif(cmd_buffer.source.valid,
-                If(rdata_chunk_valid,
+            cmd_buffer.source.ready.eq(rdata_converter.source.ready & rdata_chunk[ratio-1]),
+        ]
+
+        with m.If(port_from.flush):
+            m.d.comb += rdata_converter.source.ready.eq(1)
+        with m.Elif(cmd_buffer.source.valid):
+            with m.If(rdata_chunk_valid):
+                m.d.comb += [
                     port_from.rdata.valid.eq(rdata_converter.source.valid),
                     port_from.rdata.data.eq(rdata_converter.source.data),
-                    rdata_converter.source.ready.eq(port_from.rdata.ready)
-                ).Else(
-                    rdata_converter.source.ready.eq(1)
-                )
-            ),
-            cmd_buffer.source.ready.eq(
-                rdata_converter.source.ready & rdata_chunk[ratio-1])
-        ]
+                    rdata_converter.source.ready.eq(port_from.rdata.ready),
+                ]
+            with m.Else():
+                m.d.comb += rdata_converter.source.ready.eq(1)
+
+        return m
 
 # LiteDRAMNativePortConverter ----------------------------------------------------------------------
 
-class LiteDRAMNativePortConverter(Module):
+class LiteDRAMNativePortConverter(Elaboratable):
     def __init__(self, port_from, port_to, reverse=False):
         assert port_from.clock_domain == port_to.clock_domain
         assert port_from.mode         == port_to.mode
 
-        # # #
+        self._port_from = port_from
+        self._port_to = port_to
+        self._reverse = reverse
+
+    def elaborate(self, platform):
+        m = Module()
+
+        port_from = self._port_from
+        port_to = self._port_to
+        reverse = self._reverse
 
         mode = port_from.mode
 
         if port_from.data_width > port_to.data_width:
-            converter = LiteDRAMNativePortDownConverter(port_from, port_to, reverse)
-            self.submodules += converter
+            converter = gramNativePortDownConverter(port_from, port_to, reverse)
+            m.submodules += converter
         elif port_from.data_width < port_to.data_width:
             if mode == "write":
-                converter = LiteDRAMNativeWritePortUpConverter(port_from, port_to, reverse)
+                converter = gramNativeWritePortUpConverter(port_from, port_to, reverse)
             elif mode == "read":
-                converter = LiteDRAMNativeReadPortUpConverter(port_from, port_to, reverse)
+                converter = gramNativeReadPortUpConverter(port_from, port_to, reverse)
             else:
                 raise NotImplementedError
-            self.submodules += converter
+            m.submodules += converter
         else:
-            self.comb += [
+            m.d.comb += [
                 port_from.cmd.connect(port_to.cmd),
                 port_from.wdata.connect(port_to.wdata),
                 port_to.rdata.connect(port_from.rdata)
             ]
+
+        return m