translate slice_top and rab_slice from systemverilog to nmigen
authorTobias Platen <tplaten@posteo.de>
Fri, 24 Jan 2020 07:41:24 +0000 (08:41 +0100)
committerTobias Platen <tplaten@posteo.de>
Fri, 24 Jan 2020 07:41:24 +0000 (08:41 +0100)
src/iommu/axi_rab/coreconfig.py [new file with mode: 0644]
src/iommu/axi_rab/rab_slice.py
src/iommu/axi_rab/slice_top.py
src/iommu/axi_rab/test/test_slice_top.py [new file with mode: 0644]

diff --git a/src/iommu/axi_rab/coreconfig.py b/src/iommu/axi_rab/coreconfig.py
new file mode 100644 (file)
index 0000000..247d0ce
--- /dev/null
@@ -0,0 +1,6 @@
+class CoreConfig:
+    def __init__(self):
+        self.N_SLICES = 16
+        self.N_REGS = 4*self.N_SLICES
+        self.ADDR_WIDTH_PHYS = 40
+        self.ADDR_WIDTH_VIRT = 32
index 0471061adc18b9ec7ab67270c359bda33d8b313a..59f84e3e4983346e26c9bb9f0cea207725f78d86 100644 (file)
@@ -1,34 +1,3 @@
-# this file has been generated by sv2nmigen
-
-from nmigen import Signal, Module, Const, Cat, Elaboratable
-
-
-class rab_slice(Elaboratable):
-
-    def __init__(self):
-        self.cfg_min = Signal(ADDR_WIDTH_VIRT)  # input
-        self.cfg_max = Signal(ADDR_WIDTH_VIRT)  # input
-        self.cfg_offset = Signal(ADDR_WIDTH_PHYS)  # input
-        self.cfg_wen = Signal()  # input
-        self.cfg_ren = Signal()  # input
-        self.cfg_en = Signal()  # input
-        self.in_trans_type = Signal()  # input
-        self.in_addr_min = Signal(ADDR_WIDTH_VIRT)  # input
-        self.in_addr_max = Signal(ADDR_WIDTH_VIRT)  # input
-        self.out_hit = Signal()  # output
-        self.out_prot = Signal()  # output
-        self.out_addr = Signal(ADDR_WIDTH_PHYS)  # output
-
-    def elaborate(self, platform=None):
-        m = Module()
-        m.d.comb += self.min_above_min.eq(self.None)
-        m.d.comb += self.min_below_max.eq(self.None)
-        m.d.comb += self.max_below_max.eq(self.None)
-        m.d.comb += self.out_hit.eq(self.None)
-        m.d.comb += self.out_prot.eq(self.None)
-        m.d.comb += self.out_addr.eq(self.None)
-        return m
-
 # // Copyright 2018 ETH Zurich and University of Bologna.
 # // Copyright and related rights are licensed under the Solderpad Hardware
 # // License, Version 0.51 (the "License"); you may not use this file except in
@@ -58,19 +27,50 @@ class rab_slice(Elaboratable):
 #    output logic                       out_prot,
 #    output logic [ADDR_WIDTH_PHYS-1:0] out_addr
 #  );
-#
-#  wire min_above_min;
-#  wire min_below_max;
-#  wire max_below_max;
-#
-#  assign min_above_min = (in_addr_min >= cfg_min) ? 1'b1 : 1'b0;
-#  assign min_below_max = (in_addr_min <= cfg_max) ? 1'b1 : 1'b0;
-#  assign max_below_max = (in_addr_max <= cfg_max) ? 1'b1 : 1'b0;
-#
-#  assign out_hit  = cfg_en & min_above_min & min_below_max & max_below_max;
-#  assign out_prot = out_hit & ((in_trans_type & ~cfg_wen) | (~in_trans_type & ~cfg_ren));
-#  assign out_addr = in_addr_min - cfg_min + cfg_offset;
-#
-# endmodule
-#
-#
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class rab_slice(Elaboratable):
+
+    def __init__(self, params):  # pass config object
+        # TODO parameters
+        self.params = params
+        self.cfg_min = Signal(params.ADDR_WIDTH_VIRT)  # input
+        self.cfg_max = Signal(params.ADDR_WIDTH_VIRT)  # input
+        self.cfg_offset = Signal(params.ADDR_WIDTH_PHYS)  # input
+        self.cfg_wen = Signal()  # input
+        self.cfg_ren = Signal()  # input
+        self.cfg_en = Signal()  # input
+        self.in_trans_type = Signal()  # input
+        self.in_addr_min = Signal(params.ADDR_WIDTH_VIRT)  # input
+        self.in_addr_max = Signal(params.ADDR_WIDTH_VIRT)  # input
+        self.out_hit = Signal()  # output
+        self.out_prot = Signal()  # output
+        self.out_addr = Signal(params.ADDR_WIDTH_PHYS)  # output
+
+    def elaborate(self, platform=None):
+        m = Module()
+        min_above_min = Signal()
+        min_below_max = Signal()
+        max_below_max = Signal()
+
+        #  assign min_above_min = (in_addr_min >= cfg_min) ? 1'b1 : 1'b0;
+        #  assign min_below_max = (in_addr_min <= cfg_max) ? 1'b1 : 1'b0;
+        #  assign max_below_max = (in_addr_max <= cfg_max) ? 1'b1 : 1'b0;
+        #  assign out_hit  = cfg_en & min_above_min & min_below_max & max_below_max;
+        #  assign out_prot = out_hit & ((in_trans_type & ~cfg_wen) | (~in_trans_type & ~cfg_ren));
+        #  assign out_addr = in_addr_min - cfg_min + cfg_offset;
+        m.d.comb += [
+            min_above_min.eq(self.in_addr_min >= self.cfg_min),
+            min_below_max.eq(self.in_addr_min <= self.cfg_max),
+            max_below_max.eq(self.in_addr_max <= self.cfg_max),
+            self.out_hit.eq(self.cfg_en & min_above_min &
+                            min_below_max & max_below_max),
+            self.out_prot.eq(self.out_hit & (
+                (self.in_trans_type & ~self.cfg_wen) | (~self.in_trans_type & ~self.cfg_ren))),
+            self.out_addr.eq(self.in_addr_min - self.cfg_min + self.cfg_offset)
+        ]
+
+        return m
index 0419d21f27165ff677b274b4ddf34a19e41f7537..6eedb1cd26a5c2105fb37f0dd7119e5138a65c3a 100644 (file)
@@ -1,27 +1,3 @@
-# this file has been generated by sv2nmigen
-
-from nmigen import Signal, Module, Const, Cat, Elaboratable
-
-
-class slice_top(Elaboratable):
-
-    def __init__(self):
-        self.int_cfg_regs = Signal()  # input
-        self.int_rw = Signal()  # input
-        self.int_addr_min = Signal(ADDR_WIDTH_VIRT)  # input
-        self.int_addr_max = Signal(ADDR_WIDTH_VIRT)  # input
-        self.multi_hit_allow = Signal()  # input
-        self.multi_hit = Signal()  # output
-        self.prot = Signal(N_SLICES)  # output
-        self.hit = Signal(N_SLICES)  # output
-        self.cache_coherent = Signal()  # output
-        self.out_addr = Signal(ADDR_WIDTH_PHYS)  # output
-
-    def elaborate(self, platform=None):
-        m = Module()
-        return m
-
-
 # // Copyright 2018 ETH Zurich and University of Bologna.
 # // Copyright and related rights are licensed under the Solderpad Hardware
 # // License, Version 0.51 (the "License"); you may not use this file except in
@@ -31,6 +7,13 @@ class slice_top(Elaboratable):
 # // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 # // CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # // specific language governing permissions and limitations under the License.
+
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+import rab_slice
+import coreconfig
+
 #
 # module slice_top
 # //#(
@@ -52,13 +35,59 @@ class slice_top(Elaboratable):
 #    output  logic [ADDR_WIDTH_PHYS-1:0] out_addr
 #  );
 #
-"""  #docstring_begin
 
-  logic first_hit;
 
-  genvar  i;
-  integer j;
+class slice_top(Elaboratable):
+
+    def __init__(self):
+        # FIXME self.int_cfg_regs = Signal()  # input
+        self.params = coreconfig.CoreConfig() # rename ?
+        self.int_rw = Signal()  # input
+        self.int_addr_min = Signal(self.params.ADDR_WIDTH_VIRT)  # input
+        self.int_addr_max = Signal(self.params.ADDR_WIDTH_VIRT)  # input
+        self.multi_hit_allow = Signal()  # input
+        self.multi_hit = Signal()  # output
+        self.prot = Signal(self.params.N_SLICES)  # output
+        self.hit = Signal(self.params.N_SLICES)  # output
+        self.cache_coherent = Signal()  # output
+        self.out_addr = Signal(self.params.ADDR_WIDTH_PHYS)  # output
+
+    def elaborate(self, platform=None):
+        m = Module()
+
+        first_hit = Signal()
 
+        for i in range(self.params.N_SLICES):
+            # TODO pass params / core config here
+            u_slice = rab_slice.rab_slice(self.params)
+            setattr(m.submodules, "u_slice%d" % i, u_slice)
+            # TODO set param and connect ports
+
+        # In case of a multi hit, the lowest slice with a hit is selected.
+        # TODO always_comb begin : HIT_CHECK
+        m.d.comb += [
+            first_hit.eq(0),
+            self.multi_hit.eq(0),
+            self.out_addr.eq(0),
+            self.cache_coherent.eq(0)]
+
+        for j in range(self.params.N_SLICES):
+            with m.If(self.hit[j] == 1):
+                with m.If(first_hit == 1):
+                    with m.If(self.multi_hit_allow == 0):
+                        m.d.comb += [self.multi_hit.eq(1)]
+                with m.Elif(first_hit == 1):
+                    m.d.comb += [first_hit.eq(1)
+                                 # only output first slice that was hit
+                                 # SV self.out_addr.eq(slice_out_addr[ADDR_WIDTH_PHYS*j + : ADDR_WIDTH_PHYS]),
+                                 # SV self.cache_coherent.eq(int_cfg_regs[4*j+3][3]),
+                                 ]
+        return m
+
+  # TODO translate generate statement
+
+
+"""
   logic [ADDR_WIDTH_PHYS*N_SLICES-1:0]  slice_out_addr;
 
   generate
@@ -108,8 +137,5 @@ class slice_top(Elaboratable):
     end
   end
 """
-# endmodule
-#
-# // vim: ts=2 sw=2 sts=2 et nosmartindent autoindent foldmethod=marker
-#
-#
+
+# sv 2 migen: TODO add translate code for generate statements and for loops inside always_comb
diff --git a/src/iommu/axi_rab/test/test_slice_top.py b/src/iommu/axi_rab/test/test_slice_top.py
new file mode 100644 (file)
index 0000000..c234b90
--- /dev/null
@@ -0,0 +1,14 @@
+from nmigen.compat.sim import run_simulation
+import sys
+sys.path.append("../")
+# sys.path.append("../../../TestUtil")
+from slice_top import slice_top
+
+def tbench(dut):
+    yield
+
+
+if __name__ == "__main__":
+    dut = slice_top()
+    run_simulation(dut, tbench(dut), vcd_name="test_slice_top.vcd")
+    print("slice_top Unit Test Success")