P4C
The P4 Compiler
Loading...
Searching...
No Matches
jbay/salu_inst.cpp
1
17
18/* JBay 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
22struct DivMod : public AluOP {
23 struct Decode : public AluOP::Decode {
24 Decode(const char *name, target_t targ, int opc) : AluOP::Decode(name, targ, opc) {}
25 Instruction *decode(Table *tbl, const Table::Actions::Action *act,
26 const VECTOR(value_t) & op) const override {
27 auto *rv = new DivMod(this, op[0].lineno);
28 if (op.size != 3) error(op[0].lineno, "divmod must have exactly 2 operands");
29 if (op.size > 1) rv->srca = operand(tbl, act, op[1]);
30 if (op.size > 2) rv->srcb = operand(tbl, act, op[2]);
31 rv->dest = AluOP::HI;
32 rv->slot = ALU2HI;
33 return rv;
34 }
35 };
36 DivMod(const Decode *op, int l) : AluOP(op, l) {}
37
38 Instruction *pass1(Table *tbl, Table::Actions::Action *act) override {
39 tbl->stage->table_use[timing_thread(tbl->gress)] |= Stage::USE_STATEFUL_DIVIDE;
40 BUG_CHECK(tbl->to<StatefulTable>(), "stateful instruction on non-stateful table?");
41 tbl->to<StatefulTable>()->divmod_used = true;
42 return AluOP::pass1(tbl, act);
43 }
44 FOR_ALL_REGISTER_SETS(DECLARE_FORWARD_VIRTUAL_INSTRUCTION_WRITE_REGS)
45};
46
47// setz op, so can OR with alu1hi to get that result
48DivMod::Decode opDIVMOD("divmod", JBAY, 0x00);
49
50void DivMod::write_regs(Target::Tofino::mau_regs &, Table *, Table::Actions::Action *) {
51 BUG("unsupported");
52}
53void DivMod::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
54 AluOP::write_regs(regs, tbl, act);
55 int logical_home_row = tbl->layout[0].row;
56 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
57 auto &salu_instr_common = meter_group.stateful.salu_instr_common[act->code];
58 salu_instr_common.salu_divide_enable |= 1;
59}
60
61struct MinMax : public SaluInstruction {
62 const struct Decode : public Instruction::Decode {
63 std::string name;
64 unsigned opcode;
65 Decode(const char *name, target_t targ, int op)
66 : Instruction::Decode(name, targ, STATEFUL_ALU), name(name), opcode(op) {}
67 Instruction *decode(Table *tbl, const Table::Actions::Action *act,
68 const VECTOR(value_t) & op) const override;
69 } *opc;
70 bool phv = false; // source is mem or phv
71 operand mask, postmod;
72 // constants for mask and postmod packed together
73 boost::optional<unsigned> constval = boost::none;
74 MinMax(const Decode *op, int l) : SaluInstruction(l), opc(op) {}
75 std::string name() override { return opc->name; };
76 Instruction *pass1(Table *tbl, Table::Actions::Action *) override;
77 void pass2(Table *tbl, Table::Actions::Action *) override;
78 bool salu_alu() const override { return true; }
79 bool equiv(Instruction *a_) override {
80 if (auto *a = dynamic_cast<MinMax *>(a_))
81 return opc == a->opc && phv == a->phv && mask == a->mask && postmod == a->postmod;
82 return false;
83 }
84 bool phvRead(std::function<void(const ::Phv::Slice &sl)>) override { return phv; }
85 void dbprint(std::ostream &out) const override {
86 out << "INSTR: " << opc->name << (phv ? "phv, " : "mem, ") << mask;
87 if (postmod) out << ", " << postmod;
88 }
89 FOR_ALL_REGISTER_SETS(DECLARE_FORWARD_VIRTUAL_INSTRUCTION_WRITE_REGS)
90};
91
92MinMax::Decode opMIN8("min8", JBAY, 0), opMAX8("max8", JBAY, 1), opMIN16("min16", JBAY, 2),
93 opMAX16("max16", JBAY, 3);
94
95Instruction *MinMax::Decode::decode(Table *tbl, const Table::Actions::Action *act,
96 const VECTOR(value_t) & op) const {
97 auto *rv = new MinMax(this, op[0].lineno);
98 if (op.size > 2) {
99 if (op[1] == "phv")
100 rv->phv = true;
101 else if (op[1] != "mem")
102 error(op[1].lineno, "%s source must be 'mem' or 'phv'", op[0].s);
103 rv->mask = operand(tbl, act, op[2]);
104 if (!rv->mask.to<operand::Phv>() && !rv->mask.to<operand::Const>())
105 error(op[1].lineno, "%s mask must be constant or from phv or hash_dist", op[0].s);
106 } else {
107 error(op[0].lineno, "%s must have a single mask operand", op[0].s);
108 }
109 if (op.size == 4) {
110 rv->postmod = operand(tbl, act, op[3]);
111 } else if (op.size > 4) {
112 error(op[0].lineno, "too many operands for %s", op[0].s);
113 }
114 rv->slot = MINMAX;
115 return rv;
116}
117Instruction *MinMax::pass1(Table *tbl_, Table::Actions::Action *act) {
118 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
119 BUG_CHECK(tbl, "expected stateful table");
120 int mask_size = (opc->opcode & 2) ? 8 : 16;
121 constval = boost::none;
122 mask->pass1(tbl);
123 act->minmax_use = true;
124 if (auto k = mask.to<operand::Const>()) {
125 if (k->value < 0 || k->value >= (1U << mask_size) || mask.neg)
126 error(k->lineno, "%s mask value out of range", name().c_str());
127 constval = k->value & ((1U << mask_size) - 1);
128 } else if (auto p = mask.to<operand::Phv>()) {
129 if (p->phv_index(tbl))
130 error(lineno, "%s phv mask must come from the lower half input", name().c_str());
131 } else {
132 error(mask->lineno, "%s invalid mask", name().c_str());
133 }
134 if (postmod) {
135 if (auto k = postmod.to<operand::Const>()) {
136 if (k->value < 0) {
137 k->value = -k->value;
138 postmod.neg = !postmod.neg;
139 }
140 if (k->value > 255) error(lineno, "%s post mod too large", name().c_str());
141 constval = constval.get_value_or(0) | (k->value & 0xff) << mask_size;
142 } else if (auto p = postmod.to<operand::Phv>()) {
143 if (!p->phv_index(tbl))
144 error(lineno, "%s phv post mod must come from the upper half input",
145 name().c_str());
146 } else {
147 error(postmod->lineno, "%s invalid post mod", name().c_str());
148 }
149 }
150 // We allocate the value here in order to report an error in pass1 if the capacity
151 // of the register file is exceeded. The next call in write_regs with the same value
152 // will return already allocated register file row index.
153 if (constval) tbl->get_const(lineno, *constval);
154 return this;
155}
156void MinMax::pass2(Table *tbl, Table::Actions::Action *act) {
157 if (act->slot_use.intersects(bitvec(ALU2LO, 4)))
158 error(lineno, "min/max requires all 4 stateful alu slots be unused");
159}
160void MinMax::write_regs(Target::JBay::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
161 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
162 BUG_CHECK(tbl, "expected stateful table");
163 int logical_home_row = tbl->layout[0].row;
164 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
165 auto &salu_instr_common = meter_group.stateful.salu_instr_common[act->code];
166 if (auto k = mask.to<operand::Const>()) {
167 salu_instr_common.salu_minmax_mask_ctl = 1;
168 } else {
169 salu_instr_common.salu_minmax_mask_ctl = 0;
170 }
171 salu_instr_common.salu_minmax_ctl = opc->opcode;
172 salu_instr_common.salu_minmax_enable = 1;
173 if (postmod) {
174 if (auto k = postmod.to<operand::Const>()) {
175 salu_instr_common.salu_minmax_postmod_value_ctl = 0;
176 } else {
177 salu_instr_common.salu_minmax_postmod_value_ctl = 1;
178 }
179 if (postmod.neg)
180 salu_instr_common.salu_minmax_postdec_enable = 1;
181 else
182 salu_instr_common.salu_minmax_postinc_enable = 1;
183 }
184 if (constval) {
185 auto &salu_instr_cmp = meter_group.stateful.salu_instr_cmp_alu[act->code][3];
186 salu_instr_cmp.salu_cmp_regfile_adr = tbl->get_const(lineno, *constval);
187 }
188 // salu_instr_common.salu_minmax_src_sel = phv; -- FIXME -- specify PHV source?
189 for (auto &salu : meter_group.stateful.salu_instr_state_alu[act->code]) {
190 salu.salu_op = 0xd;
191 salu.salu_arith = 1;
192 salu.salu_pred = 0xffff;
193 }
194}
195void MinMax::write_regs(Target::Tofino::mau_regs &, Table *, Table::Actions::Action *) {
196 BUG("unsupported");
197}
198
199template <>
200void AluOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
201 LOG2(this);
202 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
203 BUG_CHECK(tbl, "expected stateful table");
204 int logical_home_row = tbl->layout[0].row;
205 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
206 auto &salu = meter_group.stateful.salu_instr_state_alu[act->code][slot - ALU2LO];
207 auto &salu_ext = meter_group.stateful.salu_instr2_state_alu[act->code][slot - ALU2LO];
208 auto &salu_instr_common = meter_group.stateful.salu_instr_common[act->code];
209 auto &salu_instr_output_alu = meter_group.stateful.salu_instr_output_alu[act->code];
210 salu.salu_op = opc->opcode & 0xf;
211 salu.salu_arith = opc->opcode >> 4;
212 salu.salu_pred = predication_encode;
213 bool need_flyover = (tbl->format->size >> tbl->is_dual_mode()) > 32;
214 const int alu_const_min = Target::STATEFUL_ALU_CONST_MIN();
215 const int alu_const_max = Target::STATEFUL_ALU_CONST_MAX();
216 if (srca) {
217 if (auto m = srca.to<operand::Memory>()) {
218 salu.salu_asrc_input = m->field->bit(0) > 0 ? 1 : 0;
219 if (need_flyover) {
220 salu_ext.salu_flyover_src_sel = 1;
221 need_flyover = false;
222 }
223 } else if (auto f = srca.to<operand::Phv>()) {
224 salu.salu_asrc_input = f->phv_index(tbl) ? 3 : 2;
225 if (need_flyover) {
226 salu_ext.salu_flyover_src_sel = 1;
227 need_flyover = false;
228 }
229 } else if (auto k = srca.to<operand::Const>()) {
230 salu.salu_asrc_input = 4;
231 if (k->value >= alu_const_min && k->value <= alu_const_max) {
232 salu.salu_const_src = k->value & Target::STATEFUL_ALU_CONST_MASK();
233 salu.salu_regfile_const = 0;
234 } else {
235 salu.salu_const_src = tbl->get_const(k->lineno, k->value);
236 salu.salu_regfile_const = 1;
237 }
238 } else if (auto r = srca.to<operand::Regfile>()) {
239 salu.salu_asrc_input = 4;
240 salu.salu_const_src = r->index;
241 salu.salu_regfile_const = 1;
242 } else {
243 BUG("invalid srca");
244 }
245 }
246 if (srcb) {
247 if (auto m = srcb.to<operand::Memory>()) {
248 salu.salu_bsrc_input = m->field->bit(0) > 0 ? 3 : 2;
249 if (need_flyover) {
250 salu_ext.salu_flyover_src_sel = 0;
251 need_flyover = false;
252 }
253 } else if (auto f = srcb.to<operand::Phv>()) {
254 salu.salu_bsrc_input = f->phv_index(tbl) ? 1 : 0;
255 if (need_flyover) {
256 salu_ext.salu_flyover_src_sel = 0;
257 need_flyover = false;
258 }
259 } else if (auto m = srcb.to<operand::MathFn>()) {
260 salu_instr_common.salu_alu2_lo_bsrc_math = 1;
261 if (auto b = m->of.to<operand::Phv>()) {
262 salu_instr_common.salu_alu2_lo_math_src = b->phv_index(tbl);
263 } else if (auto b = m->of.to<operand::Memory>()) {
264 salu_instr_common.salu_alu2_lo_math_src = b->field->bit(0) > 0 ? 3 : 2;
265 } else {
266 BUG("invalid mathfn operand");
267 }
268 } else if (auto k = srcb.to<operand::Const>()) {
269 salu.salu_bsrc_input = 4;
270 if (k->value >= alu_const_min && k->value <= alu_const_max) {
271 salu.salu_const_src = k->value & Target::STATEFUL_ALU_CONST_MASK();
272 salu.salu_regfile_const = 0;
273 } else {
274 salu.salu_const_src = tbl->get_const(k->lineno, k->value);
275 salu.salu_regfile_const = 1;
276 }
277 } else if (auto r = srcb.to<operand::Regfile>()) {
278 salu.salu_bsrc_input = 4;
279 salu.salu_const_src = r->index;
280 salu.salu_regfile_const = 1;
281 } else {
282 BUG("invalid srcb");
283 }
284 }
285}
286void AluOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
287 write_regs<Target::JBay::mau_regs>(regs, tbl, act);
288}
289
290template <>
291void BitOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
292 LOG2(this);
293 int logical_home_row = tbl->layout[0].row;
294 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
295 auto &salu = meter_group.stateful.salu_instr_state_alu[act->code][slot - ALU2LO];
296 salu.salu_op = opc->opcode & 0xf;
297 salu.salu_pred = predication_encode;
298 // 1b instructions are from mem-lo to alu1-lo
299 salu.salu_asrc_input = 0;
300}
301void BitOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
302 write_regs<Target::JBay::mau_regs>(regs, tbl, act);
303}
304
305static int sbus_mask(int alu, const std::vector<Table::Ref> &tbls) {
306 int rv = 0;
307 for (auto &tbl : tbls) {
308 int bit = tbl->layout[0].row / 4U;
309 if (bit > alu) --bit;
310 rv |= 1 << bit;
311 }
312 return rv;
313}
314
315template <>
316void CmpOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
317 LOG2(this);
318 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
319 BUG_CHECK(tbl, "expected stateful table");
320 int logical_home_row = tbl->layout[0].row;
321 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
322 auto &salu = meter_group.stateful.salu_instr_cmp_alu[act->code][slot];
323 auto &salu_instr_common = meter_group.stateful.salu_instr_common[act->code];
324 if (srca) {
325 salu.salu_cmp_asrc_input = srca->field->bit(0) > 0;
326 salu.salu_cmp_asrc_sign = srca_neg;
327 salu.salu_cmp_asrc_enable = 1;
328 if (maska != uint32_t(-1)) {
329 salu.salu_cmp_asrc_mask_enable = 1;
330 auto cval = 0;
331 if (auto k = dynamic_cast<const operand::Const *>(srcc))
332 cval = k->value;
333 else if (auto r = dynamic_cast<const operand::Regfile *>(srcc))
334 cval = tbl->get_const_val(r->index);
335 int64_t min = Target::STATEFUL_CMP_CONST_MIN();
336 int64_t max = Target::STATEFUL_CMP_CONST_MAX();
337 bool maska_outside = (maska < uint32_t(min) && maska > max);
338 bool maska_equal_inside = (uint32_t(cval) != maska && cval >= min && cval <= max);
339 if (!maska_outside && !maska_equal_inside) {
340 salu.salu_cmp_const_src = maska & Target::STATEFUL_CMP_CONST_MASK();
341 salu.salu_cmp_mask_input = 0;
342 } else {
343 salu.salu_cmp_regfile_adr = tbl->get_const(srca->lineno, maska);
344 salu.salu_cmp_mask_input = 1;
345 }
346 }
347 }
348 if (srcb) {
349 salu.salu_cmp_bsrc_input = srcb->phv_index(tbl);
350 salu.salu_cmp_bsrc_sign = srcb_neg;
351 salu.salu_cmp_bsrc_enable = 1;
352 if (maskb != uint32_t(-1)) {
353 // uarch 6.2.12.6.1, masks for operand a/b are sourced from the
354 // same regfile slot.
355 if (salu.salu_cmp_asrc_mask_enable && salu.salu_cmp_mask_input && maskb != maska)
356 error(lineno, "inconsistent operand mask %d and %d in salu compare operation",
357 maska, maskb);
358 salu.salu_cmp_bsrc_mask_enable = 1;
359 salu.salu_cmp_regfile_adr = tbl->get_const(srcb->lineno, maskb);
360 }
361 }
362 if (srcc) {
363 if (auto k = dynamic_cast<const operand::Const *>(srcc)) {
364 const int cmp_const_min = Target::STATEFUL_CMP_CONST_MIN();
365 const int cmp_const_max = Target::STATEFUL_CMP_CONST_MAX();
366 if (k->value >= cmp_const_min && k->value <= cmp_const_max) {
367 salu.salu_cmp_const_src = k->value & Target::STATEFUL_CMP_CONST_MASK();
368 salu.salu_cmp_regfile_const = 0;
369 } else {
370 // uarch 6.2.12.6.1, masks for operand a/b are sourced from the
371 // same regfile slot as operand c if c is a constant.
372 if (salu.salu_cmp_asrc_mask_enable && salu.salu_cmp_mask_input &&
373 maska != uint32_t(k->value))
374 error(lineno, "inconsistent operand mask %d and %d in salu compare operation",
375 maska, uint32_t(k->value));
376 if (salu.salu_cmp_bsrc_mask_enable && salu.salu_cmp_mask_input &&
377 maskb != uint32_t(k->value))
378 error(lineno, "inconsistent operand mask %d and %d in salu compare operation",
379 maskb, uint32_t(k->value));
380 salu.salu_cmp_regfile_adr = tbl->get_const(srcc->lineno, k->value);
381 salu.salu_cmp_regfile_const = 1;
382 }
383 } else if (auto r = dynamic_cast<const operand::Regfile *>(srcc)) {
384 salu.salu_cmp_regfile_adr = r->index;
385 salu.salu_cmp_regfile_const = 1;
386 }
387 } else {
388 salu.salu_cmp_const_src = 0;
389 salu.salu_cmp_regfile_const = 0;
390 }
391 salu.salu_cmp_opcode = opc->opcode | (type << 2);
392 auto lmask = sbus_mask(logical_home_row / 4U, tbl->sbus_learn);
393 auto mmask = sbus_mask(logical_home_row / 4U, tbl->sbus_match);
394 salu_instr_common.salu_lmatch_sbus_listen = lmask;
395 salu_instr_common.salu_match_sbus_listen = mmask;
396 salu_instr_common.salu_sbus_in_comb = tbl->sbus_comb;
397 if (lmask || mmask) {
398 // if lmask and mmask are both zero, these registers don't matter, but the model
399 // will assert if they are non-zero)
400 salu.salu_cmp_sbus_or = 0;
401 salu.salu_cmp_sbus_and = learn ? 1 : 0;
402 salu.salu_cmp_sbus_invert = learn_not ? 1 : 0;
403 }
404}
405void CmpOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
406 write_regs<Target::JBay::mau_regs>(regs, tbl, act);
407}
408
409template <>
410void TMatchOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
411 LOG2(this);
412 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
413 BUG_CHECK(tbl, "expected stateful table");
414 int logical_home_row = tbl->layout[0].row;
415 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
416 auto &salu = meter_group.stateful.salu_instr_cmp_alu[act->code][slot];
417 auto &salu_tmatch = meter_group.stateful.salu_instr_tmatch_alu[act->code][slot];
418 auto &salu_instr_common = meter_group.stateful.salu_instr_common[act->code];
419 salu.salu_cmp_tmatch_enable = 1;
420 salu.salu_cmp_asrc_enable = 1;
421 salu.salu_cmp_bsrc_enable = 1;
422 meter_group.stateful.tmatch_mask[slot][0] = ~mask & 0xffffffffU;
423 meter_group.stateful.tmatch_mask[slot][1] = ~mask >> 32;
424 salu.salu_cmp_opcode = 2;
425 salu.salu_cmp_asrc_input = srca->field->bit(0) > 0;
426 salu.salu_cmp_bsrc_input = srcb->phv_index(tbl);
427 if (auto lmask = sbus_mask(logical_home_row / 4U, tbl->sbus_learn))
428 salu_instr_common.salu_lmatch_sbus_listen = lmask;
429 if (auto mmask = sbus_mask(logical_home_row / 4U, tbl->sbus_match))
430 salu_instr_common.salu_match_sbus_listen = mmask;
431 salu.salu_cmp_sbus_or = 0;
432 salu.salu_cmp_sbus_and = learn ? 1 : 0;
433 salu.salu_cmp_sbus_invert = learn_not ? 1 : 0;
434 // we set the learn output unconditionally if there's a tmatch -- should it be controllable?
435 salu_tmatch.salu_tmatch_vld_ctl = 1;
436 // salu_tmatch.salu_tmatch_invert = 0; -- when can this be useful?
437}
438
439void TMatchOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
440 write_regs<Target::JBay::mau_regs>(regs, tbl, act);
441}
442
443void OutOP::decode_output_mux(Target::JBay, Table *tbl, value_t &op) {
444 static const std::map<std::string, int> ops_mux_lookup = {
445 {"mem_hi", 1}, {"mem_lo", 0}, {"memory_hi", 1}, {"memory_lo", 0}, {"phv_hi", 3},
446 {"phv_lo", 2}, {"alu_hi", 5}, {"alu_lo", 4}, {"minmax_index", 5}, {"minmax_post", 4},
447 {"predicate", 6}, {"address", 7}, {"div", 8}, {"mod", 9}, {"minmax", 10}};
448 if (op.type == tCMD && ops_mux_lookup.count(op[0].s))
449 output_mux = ops_mux_lookup.at(op[0].s);
450 else if (op.type == tSTR && ops_mux_lookup.count(op.s))
451 output_mux = ops_mux_lookup.at(op.s);
452 else
453 output_mux = -1;
454 if (src) {
455 int tmp = output_mux;
456 if (auto *phv = src.to<operand::Phv>())
457 output_mux = 2 + phv->phv_index(tbl->to<StatefulTable>());
458 else if (auto *mem = src.to<operand::Memory>())
459 output_mux = mem->field->bit(0) > 0 ? 1 : 0;
460 BUG_CHECK(tmp < 0 || tmp == output_mux, "inconsistent output mux decode");
461 }
462}
463int OutOP::decode_output_option(Target::JBay, value_t &op) {
464 if (op == "lmatch") {
465 lmatch = true;
466 if (op.type == tCMD)
467 lmatch_pred = decode_predicate(op[1]);
468 else
469 lmatch_pred = STATEFUL_PREDICATION_ENCODE_UNCOND;
470 } else {
471 return -1;
472 }
473 return 0;
474}
475
476template <>
477void OutOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl_, Table::Actions::Action *act) {
478 LOG2(this);
479 auto tbl = dynamic_cast<StatefulTable *>(tbl_);
480 BUG_CHECK(tbl, "expected stateful table");
481 int logical_home_row = tbl->layout[0].row;
482 auto &meter_group = regs.rams.map_alu.meter_group[logical_home_row / 4U];
483 auto &salu = meter_group.stateful.salu_instr_output_alu[act->code][slot - ALUOUT0];
484 if (predication_encode) {
485 salu.salu_output_cmpfn = predication_encode;
486 } else {
487 salu.salu_output_cmpfn = STATEFUL_PREDICATION_ENCODE_UNCOND;
488 }
489 salu.salu_output_asrc = output_mux;
490 if ((salu.salu_lmatch_adr_bit_enable = lmatch))
491 meter_group.stateful.salu_mathtable[0] = lmatch_pred;
492 if (output_mux == STATEFUL_PREDICATION_OUTPUT)
493 meter_group.stateful.stateful_ctl.salu_output_pred_sel = slot - ALUOUT0;
494}
495void OutOP::write_regs(Target::JBay::mau_regs &regs, Table *tbl, Table::Actions::Action *act) {
496 write_regs<Target::JBay::mau_regs>(regs, tbl, act);
497}
Definition tables.h:98
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
Definition jbay/salu_inst.cpp:23
Definition instruction.h:53
Definition instruction.h:26
Definition jbay/salu_inst.cpp:62
Definition tables.h:538
Definition asm-types.h:114