From d1fad2b23fa5333efb42ac204595c58ae14d1a8f Mon Sep 17 00:00:00 2001 From: Tobias Platen Date: Fri, 24 Jan 2020 08:41:24 +0100 Subject: [PATCH] translate slice_top and rab_slice from systemverilog to nmigen --- src/iommu/axi_rab/coreconfig.py | 6 ++ src/iommu/axi_rab/rab_slice.py | 94 ++++++++++++------------ src/iommu/axi_rab/slice_top.py | 92 ++++++++++++++--------- src/iommu/axi_rab/test/test_slice_top.py | 14 ++++ 4 files changed, 126 insertions(+), 80 deletions(-) create mode 100644 src/iommu/axi_rab/coreconfig.py create mode 100644 src/iommu/axi_rab/test/test_slice_top.py diff --git a/src/iommu/axi_rab/coreconfig.py b/src/iommu/axi_rab/coreconfig.py new file mode 100644 index 00000000..247d0ce3 --- /dev/null +++ b/src/iommu/axi_rab/coreconfig.py @@ -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 diff --git a/src/iommu/axi_rab/rab_slice.py b/src/iommu/axi_rab/rab_slice.py index 0471061a..59f84e3e 100644 --- a/src/iommu/axi_rab/rab_slice.py +++ b/src/iommu/axi_rab/rab_slice.py @@ -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 diff --git a/src/iommu/axi_rab/slice_top.py b/src/iommu/axi_rab/slice_top.py index 0419d21f..6eedb1cd 100644 --- a/src/iommu/axi_rab/slice_top.py +++ b/src/iommu/axi_rab/slice_top.py @@ -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 index 00000000..c234b908 --- /dev/null +++ b/src/iommu/axi_rab/test/test_slice_top.py @@ -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") -- 2.30.2