• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2022 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "sfn_alu_readport_validation.h"
28 
29 #include <cstring>
30 
31 namespace r600 {
32 
33 class ReserveReadport : public ConstRegisterVisitor {
34 public:
35    ReserveReadport(AluReadportReservation& reserv);
36 
37    void visit(const LocalArray& value) override;
38    void visit(const LiteralConstant& value) override;
39    void visit(const InlineConstant& value) override;
40 
41    void reserve_gpr(int sel, int chan);
42 
43    AluReadportReservation& reserver;
44    int cycle = -1;
45    int isrc = -1;
46    int src0_sel = -1;
47    int src0_chan = -1;
48    bool success = true;
49 
50    static const int max_const_readports = 2;
51 };
52 
53 
54 class ReserveReadportVec : public ReserveReadport {
55 public:
56    using ReserveReadport::ReserveReadport;
57 
58    void visit(const Register& value) override;
59    void visit(const LocalArrayValue& value) override;
60    void visit(const UniformValue& value) override;
61 };
62 
63 class ReserveReadportTrans : public ReserveReadport
64 {
65 public:
66    ReserveReadportTrans(AluReadportReservation& reserv);
67 
68    int n_consts;
69 };
70 
71 class ReserveReadportTransPass1 : public ReserveReadportTrans {
72 public:
73    using ReserveReadportTrans::ReserveReadportTrans;
74 
75    void visit(const Register& value) override;
76    void visit(const LocalArrayValue& value) override;
77    void visit(const UniformValue& value) override;
78    void visit(const InlineConstant& value) override;
79    void visit(const LiteralConstant& value) override;
80 };
81 
82 
83 class ReserveReadportTransPass2 : public ReserveReadportTrans {
84 public:
85    using ReserveReadportTrans::ReserveReadportTrans;
86 
87    void visit(const Register& value) override;
88    void visit(const LocalArrayValue& value) override;
89    void visit(const UniformValue& value) override;
90 };
91 
schedule_vec_src(PVirtualValue src[3],int nsrc,AluBankSwizzle swz)92 bool AluReadportReservation::schedule_vec_src(PVirtualValue src[3],  int nsrc, AluBankSwizzle swz)
93 {
94    ReserveReadportVec visitor(*this);
95 
96    if (src[0]->as_register()) {
97       visitor.src0_sel = src[0]->sel();
98       visitor.src0_chan = src[0]->chan();
99    } else {
100       visitor.src0_sel = 0xffff;
101       visitor.src0_chan = 8;
102    }
103 
104    for (int i = 0; i < nsrc; ++i) {
105       visitor.cycle = cycle_vec(swz, i);
106       visitor.isrc = i;
107       src[i]->accept(visitor);
108    }
109 
110    return visitor.success;
111 }
112 
schedule_vec_instruction(const AluInstr & alu,AluBankSwizzle swz)113 bool AluReadportReservation::schedule_vec_instruction(const AluInstr& alu, AluBankSwizzle swz)
114 {
115    ReserveReadportVec visitor(*this);
116 
117    for (unsigned i = 0; i < alu.n_sources() && visitor.success; ++i) {
118       visitor.cycle = cycle_vec(swz, i);
119       visitor.isrc = i;
120       if (i == 1 && alu.src(i).equal_to(alu.src(0)))
121          continue;
122       alu.src(i).accept(visitor);
123    }
124    return visitor.success;
125 }
126 
schedule_trans_instruction(const AluInstr & alu,AluBankSwizzle swz)127 bool AluReadportReservation::schedule_trans_instruction(const AluInstr& alu, AluBankSwizzle swz)
128 {
129 
130    ReserveReadportTransPass1 visitor1(*this);
131 
132    for (unsigned i = 0; i < alu.n_sources(); ++i) {
133       visitor1.cycle = cycle_trans(swz, i);
134       alu.src(i).accept(visitor1);
135    }
136    if (!visitor1.success)
137       return false;
138 
139 
140    ReserveReadportTransPass2 visitor2(*this);
141    visitor2.n_consts = visitor1.n_consts;
142 
143 
144    for (unsigned i = 0; i < alu.n_sources(); ++i) {
145       visitor2.cycle = cycle_trans(swz, i);
146 
147       alu.src(i).accept(visitor2);
148    }
149    return visitor2.success;
150 }
151 
152 
AluReadportReservation()153 AluReadportReservation::AluReadportReservation()
154 {
155    for (int i = 0; i < max_chan_channels; ++i) {
156       for (int j = 0; j < max_gpr_readports; ++j)
157          m_hw_gpr[j][i] = -1;
158       m_hw_const_addr[i] = -1;
159       m_hw_const_chan[i] = -1;
160       m_hw_const_bank[i] = -1;
161    }
162 }
163 
164 
reserve_gpr(int sel,int chan,int cycle)165 bool AluReadportReservation::reserve_gpr(int sel, int chan, int cycle)
166 {
167    if (m_hw_gpr[cycle][chan] == -1) {
168       m_hw_gpr[cycle][chan] = sel;
169    }
170    else if (m_hw_gpr[cycle][chan] != sel) {
171       return false;
172    }
173    return true;
174 }
175 
reserve_const(const UniformValue & value)176 bool AluReadportReservation::reserve_const(const UniformValue& value)
177 {
178    int match = -1;
179    int empty = -1;
180 
181    for (int res = 0; res < ReserveReadport::max_const_readports; ++res) {
182       if (m_hw_const_addr[res] == -1)
183          empty = res;
184       else if ((m_hw_const_addr[res] == value.sel()) &&
185                (m_hw_const_bank[res] == value.kcache_bank()) &&
186                (m_hw_const_chan[res] == (value.chan() >> 1)))
187          match = res;
188    }
189 
190    if (match < 0) {
191       if (empty >= 0) {
192          m_hw_const_addr[empty] = value.sel();
193          (m_hw_const_bank[empty] = value.kcache_bank());
194          m_hw_const_chan[empty] = value.chan() >> 1;
195       } else {
196          return false;
197       }
198    }
199    return true;
200 }
201 
add_literal(uint32_t value)202 bool 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 
cycle_vec(AluBankSwizzle swz,int src)215 int AluReadportReservation::cycle_vec(AluBankSwizzle swz, int src)
216 {
217    static const int mapping[AluBankSwizzle::alu_vec_unknown][max_gpr_readports] = {
218       {0, 1, 2},
219       {0, 2, 1},
220       {1, 0, 2},
221       {1, 2, 0},
222       {2, 0, 1},
223       {2, 1, 0}
224    };
225    return mapping[swz][src];
226 }
227 
cycle_trans(AluBankSwizzle swz,int src)228 int AluReadportReservation::cycle_trans(AluBankSwizzle swz, int src)
229 {
230    static const int mapping[AluBankSwizzle::sq_alu_scl_unknown][max_gpr_readports] = {
231       {2, 1, 0},
232       {1, 2, 2},
233       {2, 1, 2},
234       {2, 2, 1},
235    };
236    return mapping[swz][src];
237 }
238 
239 
ReserveReadport(AluReadportReservation & reserv)240 ReserveReadport::ReserveReadport(AluReadportReservation& reserv):
241    reserver(reserv)
242 {
243 }
244 
visit(const LocalArray & value)245 void ReserveReadport::visit(const LocalArray& value)
246 {
247    (void)value;
248    unreachable("a full array is not available here");
249 }
250 
visit(const LiteralConstant & value)251 void ReserveReadport::visit(const LiteralConstant& value)
252 {
253    success &= reserver.add_literal(value.value());
254 }
255 
visit(const InlineConstant & value)256 void ReserveReadport::visit(const InlineConstant& value)
257 {
258    (void)value;
259 }
260 
visit(const Register & value)261 void ReserveReadportVec::visit(const Register& value)
262 {
263    reserve_gpr(value.sel(), value.chan());
264 }
265 
visit(const LocalArrayValue & value)266 void ReserveReadportVec::visit(const LocalArrayValue& value)
267 {
268    // Set the hightest non-sign bit to indicated that we use the
269    // AR register
270    reserve_gpr(0x4000000 | value.sel(), value.chan());
271 }
272 
reserve_gpr(int sel,int chan)273 void ReserveReadport::reserve_gpr(int sel, int chan)
274 {
275    if (isrc == 1 && src0_sel == sel && src0_chan == chan)
276       return;
277    success &= reserver.reserve_gpr(sel, chan, cycle);
278 }
279 
visit(const UniformValue & value)280 void ReserveReadportVec::visit(const UniformValue& value)
281 {
282    // kcache bank?
283    success &= reserver.reserve_const(value);
284 }
285 
ReserveReadportTrans(AluReadportReservation & reserv)286 ReserveReadportTrans::ReserveReadportTrans(AluReadportReservation& reserv):
287    ReserveReadport(reserv),
288    n_consts(0)
289 {}
290 
visit(const Register & value)291 void ReserveReadportTransPass1::visit(const Register& value)
292 {
293    (void)value;
294 }
295 
visit(const LocalArrayValue & value)296 void ReserveReadportTransPass1::visit(const LocalArrayValue& value)
297 {
298    (void)value;
299 }
300 
visit(const UniformValue & value)301 void ReserveReadportTransPass1::visit(const UniformValue& value)
302 {
303    if (n_consts >= max_const_readports) {
304       success = false;
305       return;
306    }
307    n_consts++;
308    success &= reserver.reserve_const(value);
309 }
310 
visit(const InlineConstant & value)311 void ReserveReadportTransPass1::visit(const InlineConstant& value)
312 {
313    (void)value;
314    if (n_consts >= max_const_readports) {
315       success = false;
316       return;
317    }
318    n_consts++;
319 }
320 
visit(const LiteralConstant & value)321 void ReserveReadportTransPass1::visit(const LiteralConstant& value)
322 {
323    if (n_consts >= max_const_readports) {
324       success = false;
325       return;
326    }
327    n_consts++;
328    success &= reserver.add_literal(value.value());
329 }
330 
visit(const Register & value)331 void ReserveReadportTransPass2::visit(const Register& value)
332 {
333    if (cycle < n_consts) {
334       success = false;
335       return;
336    }
337    reserve_gpr(value.sel(), value.chan());
338 }
339 
visit(const LocalArrayValue & value)340 void ReserveReadportTransPass2::visit(const LocalArrayValue& value)
341 {
342    if (cycle < n_consts) {
343       success = false;
344       return;
345    }
346    reserve_gpr(0x4000000 | value.sel(), value.chan());
347 }
348 
visit(const UniformValue & value)349 void ReserveReadportTransPass2::visit(const UniformValue& value)
350 {
351    (void)value;
352 }
353 
354 
355 }
356