6eedb1cd26a5c2105fb37f0dd7119e5138a65c3a
[soc.git] / src / iommu / axi_rab / slice_top.py
1 # // Copyright 2018 ETH Zurich and University of Bologna.
2 # // Copyright and related rights are licensed under the Solderpad Hardware
3 # // License, Version 0.51 (the "License"); you may not use this file except in
4 # // compliance with the License. You may obtain a copy of the License at
5 # // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 # // or agreed to in writing, software, hardware and materials distributed under
7 # // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 # // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 # // specific language governing permissions and limitations under the License.
10
11 # this file has been generated by sv2nmigen
12
13 from nmigen import Signal, Module, Const, Cat, Elaboratable
14 import rab_slice
15 import coreconfig
16
17 #
18 # module slice_top
19 # //#(
20 # // parameter N_SLICES = 16,
21 # // parameter N_REGS = 4*N_SLICES,
22 # // parameter ADDR_WIDTH_PHYS = 40,
23 # // parameter ADDR_WIDTH_VIRT = 32
24 # // )
25 # (
26 # input logic [N_REGS-1:0] [63:0] int_cfg_regs,
27 # input logic int_rw,
28 # input logic [ADDR_WIDTH_VIRT-1:0] int_addr_min,
29 # input logic [ADDR_WIDTH_VIRT-1:0] int_addr_max,
30 # input logic multi_hit_allow,
31 # output logic multi_hit,
32 # output logic [N_SLICES-1:0] prot,
33 # output logic [N_SLICES-1:0] hit,
34 # output logic cache_coherent,
35 # output logic [ADDR_WIDTH_PHYS-1:0] out_addr
36 # );
37 #
38
39
40 class slice_top(Elaboratable):
41
42 def __init__(self):
43 # FIXME self.int_cfg_regs = Signal() # input
44 self.params = coreconfig.CoreConfig() # rename ?
45 self.int_rw = Signal() # input
46 self.int_addr_min = Signal(self.params.ADDR_WIDTH_VIRT) # input
47 self.int_addr_max = Signal(self.params.ADDR_WIDTH_VIRT) # input
48 self.multi_hit_allow = Signal() # input
49 self.multi_hit = Signal() # output
50 self.prot = Signal(self.params.N_SLICES) # output
51 self.hit = Signal(self.params.N_SLICES) # output
52 self.cache_coherent = Signal() # output
53 self.out_addr = Signal(self.params.ADDR_WIDTH_PHYS) # output
54
55 def elaborate(self, platform=None):
56 m = Module()
57
58 first_hit = Signal()
59
60 for i in range(self.params.N_SLICES):
61 # TODO pass params / core config here
62 u_slice = rab_slice.rab_slice(self.params)
63 setattr(m.submodules, "u_slice%d" % i, u_slice)
64 # TODO set param and connect ports
65
66 # In case of a multi hit, the lowest slice with a hit is selected.
67 # TODO always_comb begin : HIT_CHECK
68 m.d.comb += [
69 first_hit.eq(0),
70 self.multi_hit.eq(0),
71 self.out_addr.eq(0),
72 self.cache_coherent.eq(0)]
73
74 for j in range(self.params.N_SLICES):
75 with m.If(self.hit[j] == 1):
76 with m.If(first_hit == 1):
77 with m.If(self.multi_hit_allow == 0):
78 m.d.comb += [self.multi_hit.eq(1)]
79 with m.Elif(first_hit == 1):
80 m.d.comb += [first_hit.eq(1)
81 # only output first slice that was hit
82 # SV self.out_addr.eq(slice_out_addr[ADDR_WIDTH_PHYS*j + : ADDR_WIDTH_PHYS]),
83 # SV self.cache_coherent.eq(int_cfg_regs[4*j+3][3]),
84 ]
85 return m
86
87 # TODO translate generate statement
88
89
90 """
91 logic [ADDR_WIDTH_PHYS*N_SLICES-1:0] slice_out_addr;
92
93 generate
94 for ( i=0; i<N_SLICES; i++ )
95 begin
96 rab_slice
97 #(
98 .ADDR_WIDTH_PHYS ( ADDR_WIDTH_PHYS ),
99 .ADDR_WIDTH_VIRT ( ADDR_WIDTH_VIRT )
100 )
101 u_slice
102 (
103 .cfg_min ( int_cfg_regs[4*i] [ADDR_WIDTH_VIRT-1:0] ),
104 .cfg_max ( int_cfg_regs[4*i+1][ADDR_WIDTH_VIRT-1:0] ),
105 .cfg_offset ( int_cfg_regs[4*i+2][ADDR_WIDTH_PHYS-1:0] ),
106 .cfg_wen ( int_cfg_regs[4*i+3][2] ),
107 .cfg_ren ( int_cfg_regs[4*i+3][1] ),
108 .cfg_en ( int_cfg_regs[4*i+3][0] ),
109 .in_trans_type ( int_rw ),
110 .in_addr_min ( int_addr_min ),
111 .in_addr_max ( int_addr_max ),
112 .out_addr ( slice_out_addr[ADDR_WIDTH_PHYS*i+ADDR_WIDTH_PHYS-1:ADDR_WIDTH_PHYS*i] ),
113 .out_prot ( prot[i] ),
114 .out_hit ( hit[i] )
115 );
116 end
117 endgenerate
118
119 // In case of a multi hit, the lowest slice with a hit is selected.
120 always_comb begin : HIT_CHECK
121 first_hit = 0;
122 multi_hit = 0;
123 out_addr = '0;
124 cache_coherent = 0;
125 for (j = 0; j < N_SLICES; j++) begin
126 if (hit[j] == 1'b1) begin
127 if (first_hit == 1'b1) begin
128 if (multi_hit_allow == 1'b0) begin
129 multi_hit = 1'b1;
130 end
131 end else begin
132 first_hit = 1'b1;
133 out_addr = slice_out_addr[ADDR_WIDTH_PHYS*j +: ADDR_WIDTH_PHYS];
134 cache_coherent = int_cfg_regs[4*j+3][3];
135 end
136 end
137 end
138 end
139 """
140
141 # sv 2 migen: TODO add translate code for generate statements and for loops inside always_comb