P4C
The P4 Compiler
Loading...
Searching...
No Matches
tofino/salu_inst.cpp
1
17
18/* Tofino template specializations for instructions #included in salu_inst.cpp
19 * WARNING -- this is included in an anonymous namespace, as these SaluInstruction
20 * subclasses are all defined in that anonymous namespace */
21
22template <>
23void AluOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
24 LOG2(this);
25 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
26 BUG_CHECK(tbl, "expected stateful table");
27 int logical_home_row = tbl->layout[0].row;
28 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
29 auto &salu = meter_group.stateful.salu_instr_state_alu[act->code][slot - ALU2LO];
30 auto &salu_instr_common = meter_group.stateful.salu_instr_common[act->code];
31 salu.salu_op = opc->opcode & 0xf;
32 salu.salu_arith = opc->opcode >> 4;
33 salu.salu_pred = predication_encode & Target::Tofino::STATEFUL_PRED_MASK;
34 const int alu_const_min = Target::STATEFUL_ALU_CONST_MIN();
35 const int alu_const_max = Target::STATEFUL_ALU_CONST_MAX();
36 if (srca) {
37 if (auto m = srca.to<operand::Memory>()) {
38 salu.salu_asrc_memory = 1;
39 salu.salu_asrc_memory_index = m->field->bit(0) > 0;
40 } else if (auto k = srca.to<operand::Const>()) {
41 salu.salu_asrc_memory = 0;
42 if (k->value >= alu_const_min && k->value <= alu_const_max) {
43 salu.salu_const_src = k->value & Target::STATEFUL_ALU_CONST_MASK();
44 salu.salu_regfile_const = 0;
45 } else {
46 salu.salu_const_src = tbl->get_const(k->lineno, k->value);
47 salu.salu_regfile_const = 1;
48 }
49 } else if (auto r = srca.to<operand::Regfile>()) {
50 salu.salu_asrc_memory = 0;
51 salu.salu_const_src = r->index;
52 salu.salu_regfile_const = 1;
53 } else {
54 BUG("unknown operand");
55 }
56 }
57 if (srcb) {
58 if (auto f = srcb.to<operand::Phv>()) {
59 salu.salu_bsrc_phv = 1;
60 salu.salu_bsrc_phv_index = f->phv_index(tbl);
61 } else if (auto m = srcb.to<operand::MathFn>()) {
62 salu_instr_common.salu_alu2_lo_bsrc_math = 1;
63 if (auto b = m->of.to<operand::Phv>()) {
64 salu_instr_common.salu_alu2_lo_math_src = b->phv_index(tbl);
65 } else if (auto b = m->of.to<operand::Memory>()) {
66 salu_instr_common.salu_alu2_lo_math_src = b->field->bit(0) > 0 ? 3 : 2;
67 } else {
68 BUG("unknown operand");
69 }
70 } else if (auto k = srcb.to<operand::Const>()) {
71 salu.salu_bsrc_phv = 0;
72 if (k->value >= alu_const_min && k->value <= alu_const_max) {
73 salu.salu_const_src = k->value & Target::STATEFUL_ALU_CONST_MASK();
74 salu.salu_regfile_const = 0;
75 } else {
76 salu.salu_const_src = tbl->get_const(k->lineno, k->value);
77 salu.salu_regfile_const = 1;
78 }
79 } else if (auto r = srcb.to<operand::Regfile>()) {
80 salu.salu_bsrc_phv = 0;
81 salu.salu_const_src = r->index;
82 salu.salu_regfile_const = 1;
83 } else {
84 BUG("unknown operand");
85 }
86 }
87}
88void AluOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
89 write_regs<Target::Tofino::mau_regs>(regs, tbl, act);
90}
91
92template <>
93void BitOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
94 LOG2(this);
95 int logical_home_row = tbl->layout[0].row;
96 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
97 auto &salu = meter_group.stateful.salu_instr_state_alu[act->code][slot - ALU2LO];
98 salu.salu_op = opc->opcode & 0xf;
99 salu.salu_pred = predication_encode & Target::Tofino::STATEFUL_PRED_MASK;
100 // 1b instructions are from mem-lo to alu1-lo
101 salu.salu_asrc_memory = 1;
102 salu.salu_asrc_memory_index = 0;
103}
104void BitOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
105 write_regs<Target::Tofino::mau_regs>(regs, tbl, act);
106}
107
108template <>
109void CmpOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
110 LOG2(this);
111 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
112 BUG_CHECK(tbl, "expected stateful table");
113 int logical_home_row = tbl->layout[0].row;
114 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
115 auto &salu = meter_group.stateful.salu_instr_cmp_alu[act->code][slot];
116 if (srca) {
117 salu.salu_cmp_asrc_input = srca->field->bit(0) > 0;
118 salu.salu_cmp_asrc_sign = srca_neg;
119 salu.salu_cmp_asrc_enable = 1;
120 }
121 if (srcb) {
122 salu.salu_cmp_bsrc_input = srcb->phv_index(tbl);
123 salu.salu_cmp_bsrc_sign = srcb_neg;
124 salu.salu_cmp_bsrc_enable = 1;
125 }
126 if (srcc) {
127 if (auto k = dynamic_cast<const operand::Const *>(srcc)) {
128 const int cmp_const_min = Target::STATEFUL_CMP_CONST_MIN();
129 const int cmp_const_max = Target::STATEFUL_CMP_CONST_MAX();
130 if (k->value >= cmp_const_min && k->value <= cmp_const_max) {
131 salu.salu_cmp_const_src = k->value & Target::STATEFUL_CMP_CONST_MASK();
132 salu.salu_cmp_regfile_const = 0;
133 } else {
134 salu.salu_cmp_const_src = tbl->get_const(srcc->lineno, k->value);
135 salu.salu_cmp_regfile_const = 1;
136 }
137 } else if (auto r = dynamic_cast<const operand::Regfile *>(srcc)) {
138 salu.salu_cmp_const_src = r->index;
139 salu.salu_cmp_regfile_const = 1;
140 }
141 } else {
142 salu.salu_cmp_const_src = 0;
143 salu.salu_cmp_regfile_const = 0;
144 }
145 salu.salu_cmp_opcode = opc->opcode | (type << 2);
146}
147void CmpOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
148 write_regs<Target::Tofino::mau_regs>(regs, tbl, act);
149}
150
151void TMatchOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
152 BUG("Unreachable state.");
153}
154
155void OutOP::decode_output_mux(Target::Tofino, Table *tbl, value_t &op) {
156 static const std::map<std::string, int> ops_mux_lookup = {
157 {"mem_hi", 0}, {"mem_lo", 1}, {"memory_hi", 0}, {"memory_lo", 1},
158 {"phv_hi", 2}, {"phv_lo", 3}, {"alu_hi", 4}, {"alu_lo", 5},
159 {"alu_hi_out", 4}, {"alu_lo_out", 5}, {"predicate", 6}};
160 if (op.type == tCMD && ops_mux_lookup.count(op[0].s))
161 output_mux = ops_mux_lookup.at(op[0].s);
162 else if (op.type == tSTR && ops_mux_lookup.count(op.s))
163 output_mux = ops_mux_lookup.at(op.s);
164 else
165 output_mux = -1;
166 if (src) {
167 int tmp = output_mux;
168 if (auto *phv = src.to<operand::Phv>())
169 output_mux = 3 - phv->phv_index(tbl->to<StatefulTable>());
170 else if (auto *mem = src.to<operand::Memory>())
171 output_mux = mem->field->bit(0) > 0 ? 0 : 1;
172 BUG_CHECK(tmp < 0 || tmp == output_mux, "inconsistent output mux decode");
173 }
174}
175int OutOP::decode_output_option(Target::Tofino, value_t &op) { return -1; }
176
177template <>
178void OutOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
179 LOG2(this);
180 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
181 BUG_CHECK(tbl, "expected stateful table");
182 int logical_home_row = tbl->layout[0].row;
183 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
184 auto &salu = meter_group.stateful.salu_instr_output_alu[act->code];
185 if (predication_encode) {
186 salu.salu_output_cmpfn = predication_encode & Target::Tofino::STATEFUL_PRED_MASK;
187 } else {
188 salu.salu_output_cmpfn = STATEFUL_PREDICATION_ENCODE_UNCOND;
189 }
190 salu.salu_output_asrc = output_mux;
191}
192void OutOP::write_regs(Target::Tofino::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
193 write_regs<Target::Tofino::mau_regs>(regs, tbl, act);
194}
Definition tables.h:98
Definition salu_inst.cpp:45
Definition salu_inst.cpp:224
Definition salu_inst.cpp:164
Definition salu_inst.cpp:78
Definition salu_inst.cpp:60
Definition tables.h:538
Definition asm-types.h:114