xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_alu_readport_validation.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2022 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "sfn_alu_readport_validation.h"
8 
9 #include <cstring>
10 
11 namespace r600 {
12 
13 class ReserveReadport : public ConstRegisterVisitor {
14 public:
15    ReserveReadport(AluReadportReservation& reserv);
16 
17    using ConstRegisterVisitor::visit;
18 
19    void visit(const LocalArray& value) override;
20    void visit(const LiteralConstant& value) override;
21    void visit(const InlineConstant& value) override;
22 
23    void reserve_gpr(int sel, int chan);
24 
25    AluReadportReservation& reserver;
26    int cycle = -1;
27    int isrc = -1;
28    int src0_sel = -1;
29    int src0_chan = -1;
30    bool success = true;
31 
32    static const int max_const_readports = 2;
33 };
34 
35 class ReserveReadportVec : public ReserveReadport {
36 public:
37    using ReserveReadport::ReserveReadport;
38    using ReserveReadport::visit;
39 
40    void visit(const Register& value) override;
41    void visit(const LocalArrayValue& value) override;
42    void visit(const UniformValue& value) override;
43 };
44 
45 class ReserveReadportTrans : public ReserveReadport {
46 public:
47    ReserveReadportTrans(AluReadportReservation& reserv);
48 
49    int n_consts;
50 };
51 
52 class ReserveReadportTransPass1 : public ReserveReadportTrans {
53 public:
54    using ReserveReadportTrans::ReserveReadportTrans;
55    using ReserveReadportTrans::visit;
56 
57    void visit(const Register& value) override;
58    void visit(const LocalArrayValue& value) override;
59    void visit(const UniformValue& value) override;
60    void visit(const InlineConstant& value) override;
61    void visit(const LiteralConstant& value) override;
62 };
63 
64 class ReserveReadportTransPass2 : public ReserveReadportTrans {
65 public:
66    using ReserveReadportTrans::ReserveReadportTrans;
67    using ReserveReadportTrans::visit;
68 
69    void visit(const Register& value) override;
70    void visit(const LocalArrayValue& value) override;
71    void visit(const UniformValue& value) override;
72 };
73 
74 bool
schedule_vec_src(PVirtualValue src[3],int nsrc,AluBankSwizzle swz)75 AluReadportReservation::schedule_vec_src(PVirtualValue src[3],
76                                          int nsrc,
77                                          AluBankSwizzle swz)
78 {
79    ReserveReadportVec visitor(*this);
80 
81    if (src[0]->as_register()) {
82       visitor.src0_sel = src[0]->sel();
83       visitor.src0_chan = src[0]->chan();
84    } else {
85       visitor.src0_sel = 0xffff;
86       visitor.src0_chan = 8;
87    }
88 
89    for (int i = 0; i < nsrc; ++i) {
90       visitor.cycle = cycle_vec(swz, i);
91       visitor.isrc = i;
92       src[i]->accept(visitor);
93    }
94 
95    return visitor.success;
96 }
97 
98 bool
schedule_vec_instruction(const AluInstr & alu,AluBankSwizzle swz)99 AluReadportReservation::schedule_vec_instruction(const AluInstr& alu, AluBankSwizzle swz)
100 {
101    ReserveReadportVec visitor(*this);
102 
103    for (unsigned i = 0; i < alu.n_sources() && visitor.success; ++i) {
104       visitor.cycle = cycle_vec(swz, i);
105       visitor.isrc = i;
106       if (i == 1 && alu.src(i).equal_to(alu.src(0)))
107          continue;
108       alu.src(i).accept(visitor);
109    }
110    return visitor.success;
111 }
112 
113 bool
schedule_trans_instruction(const AluInstr & alu,AluBankSwizzle swz)114 AluReadportReservation::schedule_trans_instruction(const AluInstr& alu,
115                                                    AluBankSwizzle swz)
116 {
117 
118    ReserveReadportTransPass1 visitor1(*this);
119 
120    for (unsigned i = 0; i < alu.n_sources(); ++i) {
121       visitor1.cycle = cycle_trans(swz, i);
122       alu.src(i).accept(visitor1);
123    }
124    if (!visitor1.success)
125       return false;
126 
127    ReserveReadportTransPass2 visitor2(*this);
128    visitor2.n_consts = visitor1.n_consts;
129 
130    for (unsigned i = 0; i < alu.n_sources(); ++i) {
131       visitor2.cycle = cycle_trans(swz, i);
132 
133       alu.src(i).accept(visitor2);
134    }
135    return visitor2.success;
136 }
137 
print(std::ostream & os) const138 void AluReadportReservation::print(std::ostream& os) const
139 {
140    os << "AluReadportReservation\n";
141    for (int i = 0; i < max_chan_channels; ++i) {
142       os << "  chan " << i << ":";
143       for (int j = 0; j < max_gpr_readports; ++j) {
144          os << m_hw_gpr[j][i] << " ";
145       }
146       os << "\n";
147    }
148    os << "\n";
149 
150 }
151 
AluReadportReservation()152 AluReadportReservation::AluReadportReservation()
153 {
154    for (int i = 0; i < max_chan_channels; ++i) {
155       for (int j = 0; j < max_gpr_readports; ++j)
156          m_hw_gpr[j][i] = -1;
157       m_hw_const_addr[i] = -1;
158       m_hw_const_chan[i] = -1;
159       m_hw_const_bank[i] = -1;
160    }
161 }
162 
163 bool
reserve_gpr(int sel,int chan,int cycle)164 AluReadportReservation::reserve_gpr(int sel, int chan, int cycle)
165 {
166    if (m_hw_gpr[cycle][chan] == -1) {
167       m_hw_gpr[cycle][chan] = sel;
168    } else if (m_hw_gpr[cycle][chan] != sel) {
169       return false;
170    }
171    return true;
172 }
173 
174 bool
reserve_const(const UniformValue & value)175 AluReadportReservation::reserve_const(const UniformValue& value)
176 {
177    int match = -1;
178    int empty = -1;
179 
180    for (int res = 0; res < ReserveReadport::max_const_readports; ++res) {
181       if (m_hw_const_addr[res] == -1)
182          empty = res;
183       else if ((m_hw_const_addr[res] == value.sel()) &&
184                (m_hw_const_bank[res] == value.kcache_bank()) &&
185                (m_hw_const_chan[res] == (value.chan() >> 1)))
186          match = res;
187    }
188 
189    if (match < 0) {
190       if (empty >= 0) {
191          m_hw_const_addr[empty] = value.sel();
192          (m_hw_const_bank[empty] = value.kcache_bank());
193          m_hw_const_chan[empty] = value.chan() >> 1;
194       } else {
195          return false;
196       }
197    }
198    return true;
199 }
200 
201 bool
add_literal(uint32_t value)202 AluReadportReservation::add_literal(uint32_t value)
203 {
204    for (unsigned i = 0; i < m_nliterals; ++i) {
205       if (m_literals[i] == value)
206          return true;
207    }
208    if (m_nliterals < m_literals.size()) {
209       m_literals[m_nliterals++] = value;
210       return true;
211    }
212    return false;
213 }
214 
215 int
cycle_vec(AluBankSwizzle swz,int src)216 AluReadportReservation::cycle_vec(AluBankSwizzle swz, int src)
217 {
218    static const int mapping[AluBankSwizzle::alu_vec_unknown][max_gpr_readports] = {
219       {0, 1, 2},
220       {0, 2, 1},
221       {1, 2, 0},
222       {1, 0, 2},
223       {2, 0, 1},
224       {2, 1, 0}
225    };
226    return mapping[swz][src];
227 }
228 
229 int
cycle_trans(AluBankSwizzle swz,int src)230 AluReadportReservation::cycle_trans(AluBankSwizzle swz, int src)
231 {
232    static const int mapping[AluBankSwizzle::sq_alu_scl_unknown][max_gpr_readports] = {
233       {2, 1, 0},
234       {1, 2, 2},
235       {2, 1, 2},
236       {2, 2, 1},
237    };
238    return mapping[swz][src];
239 }
240 
ReserveReadport(AluReadportReservation & reserv)241 ReserveReadport::ReserveReadport(AluReadportReservation& reserv):
242     reserver(reserv)
243 {
244 }
245 
246 void
visit(const LocalArray & value)247 ReserveReadport::visit(const LocalArray& value)
248 {
249    (void)value;
250    unreachable("a full array is not available here");
251 }
252 
253 void
visit(const LiteralConstant & value)254 ReserveReadport::visit(const LiteralConstant& value)
255 {
256    success &= reserver.add_literal(value.value());
257 }
258 
259 void
visit(const InlineConstant & value)260 ReserveReadport::visit(const InlineConstant& value)
261 {
262    (void)value;
263 }
264 
265 void
visit(const Register & value)266 ReserveReadportVec::visit(const Register& value)
267 {
268    reserve_gpr(value.sel(), value.chan());
269 }
270 
271 void
visit(const LocalArrayValue & value)272 ReserveReadportVec::visit(const LocalArrayValue& value)
273 {
274    // Set the highest non-sign bit to indicated that we use the
275    // AR register
276    reserve_gpr(0x4000000 | value.sel(), value.chan());
277 }
278 
279 void
reserve_gpr(int sel,int chan)280 ReserveReadport::reserve_gpr(int sel, int chan)
281 {
282    if (isrc == 1 && src0_sel == sel && src0_chan == chan)
283       return;
284    success &= reserver.reserve_gpr(sel, chan, cycle);
285 }
286 
287 void
visit(const UniformValue & value)288 ReserveReadportVec::visit(const UniformValue& value)
289 {
290    // kcache bank?
291    success &= reserver.reserve_const(value);
292 }
293 
ReserveReadportTrans(AluReadportReservation & reserv)294 ReserveReadportTrans::ReserveReadportTrans(AluReadportReservation& reserv):
295     ReserveReadport(reserv),
296     n_consts(0)
297 {
298 }
299 
300 void
visit(const Register & value)301 ReserveReadportTransPass1::visit(const Register& value)
302 {
303    (void)value;
304 }
305 
306 void
visit(const LocalArrayValue & value)307 ReserveReadportTransPass1::visit(const LocalArrayValue& value)
308 {
309    (void)value;
310 }
311 
312 void
visit(const UniformValue & value)313 ReserveReadportTransPass1::visit(const UniformValue& value)
314 {
315    if (n_consts >= max_const_readports) {
316       success = false;
317       return;
318    }
319    n_consts++;
320    success &= reserver.reserve_const(value);
321 }
322 
323 void
visit(const InlineConstant & value)324 ReserveReadportTransPass1::visit(const InlineConstant& value)
325 {
326    (void)value;
327    if (n_consts >= max_const_readports) {
328       success = false;
329       return;
330    }
331    n_consts++;
332 }
333 
334 void
visit(const LiteralConstant & value)335 ReserveReadportTransPass1::visit(const LiteralConstant& value)
336 {
337    if (n_consts >= max_const_readports) {
338       success = false;
339       return;
340    }
341    n_consts++;
342    success &= reserver.add_literal(value.value());
343 }
344 
345 void
visit(const Register & value)346 ReserveReadportTransPass2::visit(const Register& value)
347 {
348    if (cycle < n_consts) {
349       success = false;
350       return;
351    }
352    reserve_gpr(value.sel(), value.chan());
353 }
354 
355 void
visit(const LocalArrayValue & value)356 ReserveReadportTransPass2::visit(const LocalArrayValue& value)
357 {
358    if (cycle < n_consts) {
359       success = false;
360       return;
361    }
362    reserve_gpr(0x4000000 | value.sel(), value.chan());
363 }
364 
365 void
visit(const UniformValue & value)366 ReserveReadportTransPass2::visit(const UniformValue& value)
367 {
368    (void)value;
369 }
370 
371 } // namespace r600
372