1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2018 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_value.h"
28 #include "util/macros.h"
29 
30 #include <iostream>
31 #include <iomanip>
32 #include <cassert>
33 
34 namespace r600 {
35 
36 using std::unique_ptr;
37 using std::make_shared;
38 
39 const char *Value::component_names = "xyzw01?_!";
40 
Value()41 Value::Value():
42    m_type(gpr),
43    m_chan(0)
44 {
45 }
46 
Value(Type type,uint32_t chan)47 Value::Value(Type type, uint32_t chan):
48    m_type(type),
49    m_chan(chan)
50 {
51 
52 }
53 
54 
55 
Value(Type type)56 Value::Value(Type type):
57    Value(type, 0)
58 {
59 }
60 
type() const61 Value::Type Value::type() const
62 {
63    return m_type;
64 }
65 
set_chan(uint32_t chan)66 void Value::set_chan(uint32_t chan)
67 {
68    m_chan = chan;
69 }
70 
print(std::ostream & os) const71 void Value::print(std::ostream& os) const
72 {
73    do_print(os);
74 }
75 
print(std::ostream & os,const PrintFlags & flags) const76 void Value::print(std::ostream& os, const PrintFlags& flags) const
77 {
78    if (flags.flags & PrintFlags::has_neg) os << '-';
79    if (flags.flags & PrintFlags::has_abs) os << '|';
80    do_print(os, flags);
81    if (flags.flags & PrintFlags::has_abs) os << '|';
82 }
83 
do_print(std::ostream & os,const PrintFlags & flags) const84 void Value::do_print(std::ostream& os, const PrintFlags& flags) const
85 {
86    (void)flags;
87    do_print(os);
88 }
89 
operator <(const Value & lhs) const90 bool Value::operator < (const Value& lhs) const
91 {
92    return sel() < lhs.sel() ||
93          (sel() == lhs.sel() && chan() < lhs.chan());
94 }
95 
96 
LiteralValue(float value,uint32_t chan)97 LiteralValue::LiteralValue(float value, uint32_t chan):
98    Value(Value::literal, chan)
99 {
100    m_value.f=value;
101 }
102 
103 
LiteralValue(uint32_t value,uint32_t chan)104 LiteralValue::LiteralValue(uint32_t value, uint32_t chan):
105    Value(Value::literal, chan)
106 {
107    m_value.u=value;
108 }
109 
LiteralValue(int value,uint32_t chan)110 LiteralValue::LiteralValue(int value, uint32_t chan):
111    Value(Value::literal, chan)
112 {
113    m_value.u=value;
114 }
115 
sel() const116 uint32_t LiteralValue::sel() const
117 {
118    return ALU_SRC_LITERAL;
119 }
120 
value() const121 uint32_t LiteralValue::value() const
122 {
123    return m_value.u;
124 }
125 
value_float() const126 float LiteralValue::value_float() const
127 {
128    return m_value.f;
129 }
130 
do_print(std::ostream & os) const131 void LiteralValue::do_print(std::ostream& os) const
132 {
133    os << "[0x" << std::setbase(16) << m_value.u << " " << std::setbase(10)
134       << m_value.f << "].";
135    os << component_names[chan()];
136 }
137 
do_print(std::ostream & os,UNUSED const PrintFlags & flags) const138 void LiteralValue::do_print(std::ostream& os, UNUSED const PrintFlags& flags) const
139 {
140    os << "[0x" << std::setbase(16) << m_value.u << " "
141       << std::setbase(10);
142 
143    os << m_value.f << "f";
144 
145    os<< "]";
146 }
147 
is_equal_to(const Value & other) const148 bool LiteralValue::is_equal_to(const Value& other) const
149 {
150    assert(other.type() == Value::Type::literal);
151    const auto& rhs = static_cast<const LiteralValue&>(other);
152    return (sel() == rhs.sel() &&
153            value() == rhs.value());
154 }
155 
InlineConstValue(int value,int chan)156 InlineConstValue::InlineConstValue(int value, int chan):
157    Value(Value::cinline,  chan),
158    m_value(static_cast<AluInlineConstants>(value))
159 {
160 }
161 
sel() const162 uint32_t InlineConstValue::sel() const
163 {
164    return m_value;
165 }
166 
do_print(std::ostream & os) const167 void InlineConstValue::do_print(std::ostream& os) const
168 {
169    auto sv_info = alu_src_const.find(m_value);
170    if (sv_info != alu_src_const.end()) {
171       os << sv_info->second.descr;
172       if (sv_info->second.use_chan)
173          os << '.' << component_names[chan()];
174       else if (chan() > 0)
175          os << "." << component_names[chan()]
176             << " (W: Channel ignored)";
177    } else {
178       if (m_value >= ALU_SRC_PARAM_BASE && m_value < ALU_SRC_PARAM_BASE + 32)
179          os << " Param" << m_value - ALU_SRC_PARAM_BASE;
180       else
181          os << " E: unknown inline constant " << m_value;
182    }
183 }
184 
is_equal_to(const Value & other) const185 bool InlineConstValue::is_equal_to(const Value& other) const
186 {
187    assert(other.type() == Value::Type::cinline);
188    const auto& rhs = static_cast<const InlineConstValue&>(other);
189    return sel() == rhs.sel();
190 }
191 
192 PValue Value::zero(new InlineConstValue(ALU_SRC_0, 0));
193 PValue Value::one_f(new InlineConstValue(ALU_SRC_1, 0));
194 PValue Value::one_i(new InlineConstValue(ALU_SRC_1_INT, 0));
195 PValue Value::zero_dot_5(new InlineConstValue(ALU_SRC_0_5, 0));
196 
UniformValue(uint32_t sel,uint32_t chan,uint32_t kcache_bank)197 UniformValue::UniformValue(uint32_t sel, uint32_t chan, uint32_t kcache_bank):
198    Value(Value::kconst, chan)
199 {
200    m_index = sel;
201    m_kcache_bank = kcache_bank;
202 }
203 
UniformValue(uint32_t sel,uint32_t chan,PValue addr)204 UniformValue::UniformValue(uint32_t sel, uint32_t chan, PValue addr):
205    Value(Value::kconst, chan),
206    m_index(sel),
207    m_kcache_bank(1),
208    m_addr(addr)
209 {
210 
211 }
212 
sel() const213 uint32_t UniformValue::sel() const
214 {
215    const int bank_base[4] = {128, 160, 256, 288};
216    return m_index < 512 ? m_index + bank_base[m_kcache_bank] : m_index;
217 }
218 
kcache_bank() const219 uint32_t UniformValue::kcache_bank() const
220 {
221    return m_kcache_bank;
222 }
223 
is_equal_to(const Value & other) const224 bool UniformValue::is_equal_to(const Value& other) const
225 {
226    const UniformValue& o = static_cast<const UniformValue&>(other);
227    return sel()  == o.sel() &&
228          m_kcache_bank == o.kcache_bank();
229 }
230 
do_print(std::ostream & os) const231 void UniformValue::do_print(std::ostream& os) const
232 {
233    if (m_index < 512)
234       os << "KC" << m_kcache_bank << "[" << m_index;
235    else if (m_addr)
236       os << "KC[" << *m_addr << "][" << m_index;
237    else
238       os << "KCx[" << m_index;
239    os << "]." << component_names[chan()];
240 }
241 
242 }
243