• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright © 2024 Imagination Technologies Ltd.
2# SPDX-License-Identifier: MIT
3
4from mako.template import Template, exceptions
5from pco_map import *
6
7template = """/*
8 * Copyright © 2024 Imagination Technologies Ltd.
9 *
10 * SPDX-License-Identifier: MIT
11 */
12
13#ifndef PCO_MAP_H
14#define PCO_MAP_H
15
16/**
17 * \\file pco_map.h
18 *
19 * \\brief PCO mapping definitions.
20 */
21
22#include "pco_builder.h"
23#include "pco_common.h"
24#include "pco_internal.h"
25#include "pco_isa.h"
26#include "pco_ops.h"
27#include "util/macros.h"
28
29#include <stdbool.h>
30
31/* Enum mappings. */
32% for enum_map in enum_maps.values():
33static inline
34${enum_map.type_to} ${enum_map.name}(${enum_map.type_from} val)
35{
36   switch (val) {
37   % for elem_from, elem_to in enum_map.mappings:
38   case ${elem_from}:
39      return ${elem_to};
40
41   % endfor
42   default: break;
43   }
44
45   unreachable();
46}
47
48% endfor
49static inline
50enum pco_regbank pco_map_reg_bank(pco_ref ref)
51{
52   enum pco_regbank regbank = pco_map_reg_class_to_regbank(pco_ref_get_reg_class(ref));
53   return pco_ref_is_idx_reg(ref) ? regbank + ref.idx_reg.num : regbank;
54}
55
56static inline
57unsigned pco_map_reg_bank_bits(pco_ref ref)
58{
59   return util_last_bit(pco_map_reg_bank(ref));
60}
61
62static inline
63enum pco_idxbank pco_map_idx_bank(pco_ref ref)
64{
65   assert(pco_ref_is_idx_reg(ref));
66   return pco_map_reg_class_to_idxbank(ref.reg_class);
67}
68
69static inline unsigned pco_map_reg_index(pco_ref ref)
70{
71   if (pco_ref_is_reg(ref)) {
72      switch (ref.reg_class) {
73      case PCO_REG_CLASS_TEMP:
74      case PCO_REG_CLASS_VTXIN:
75      case PCO_REG_CLASS_COEFF:
76      case PCO_REG_CLASS_SHARED:
77      case PCO_REG_CLASS_SPEC:
78      case PCO_REG_CLASS_CONST:
79         return ref.val;
80
81      case PCO_REG_CLASS_INTERN:
82         return ref.val + PCO_SR_INTL0;
83
84      case PCO_REG_CLASS_PIXOUT:
85         if (ref.val >= 4)
86            return ref.val + PCO_SR_PIXOUT4 - 4;
87         else
88            return ref.val + PCO_SR_PIXOUT0;
89
90      case PCO_REG_CLASS_GLOBAL:
91         return ref.val + PCO_SR_GLOBAL0;
92
93      case PCO_REG_CLASS_SLOT:
94         return (7 - ref.val) + PCO_SR_SLOT7;
95
96      default:
97         break;
98      }
99   } else if (pco_ref_is_idx_reg(ref)) {
100      return pco_map_idx_bank(ref) | (ref.idx_reg.offset << 3);
101   }
102
103   unreachable();
104}
105
106static inline unsigned pco_map_reg_index_bits(pco_ref ref)
107{
108   if (pco_ref_is_reg(ref))
109      return util_last_bit(pco_map_reg_index(ref));
110   else if (pco_ref_is_idx_reg(ref))
111      return 11;
112
113   unreachable();
114}
115
116static inline
117enum pco_igrp_hdr_variant pco_igrp_hdr_variant(pco_igrp *igrp)
118{
119   if (igrp->hdr.alutype == PCO_ALUTYPE_BITWISE)
120      return PCO_IGRP_HDR_BITWISE;
121   else if (igrp->hdr.alutype == PCO_ALUTYPE_CONTROL)
122      return PCO_IGRP_HDR_CONTROL;
123   else
124      assert(igrp->hdr.alutype == PCO_ALUTYPE_MAIN);
125
126   if (!igrp->hdr.end && !igrp->hdr.atom && !igrp->hdr.rpt && !igrp->hdr.cc)
127      return PCO_IGRP_HDR_MAIN_BRIEF;
128
129   return PCO_IGRP_HDR_MAIN;
130}
131
132static inline
133enum pco_src_variant pco_igrp_src_variant(const pco_igrp *igrp,
134                                          bool is_upper)
135{
136   unsigned offset = is_upper ? ROGUE_ALU_INPUT_GROUP_SIZE : 0;
137
138   pco_ref sA = igrp->srcs.s[0 + offset];
139   pco_ref sB = igrp->srcs.s[1 + offset];
140   pco_ref sC = igrp->srcs.s[2 + offset];
141   pco_ref mux = is_upper ? pco_ref_null() : igrp->iss.is[0];
142
143   bool sA_set = !pco_ref_is_null(sA);
144   bool sB_set = !pco_ref_is_null(sB);
145   bool sC_set = !pco_ref_is_null(sC);
146   bool mux_set = !pco_ref_is_null(mux);
147
148   int sbA_bits = sA_set ? pco_map_reg_bank_bits(sA) : -1;
149   int sA_bits = sA_set ? pco_map_reg_index_bits(sA) : -1;
150
151   int sbB_bits = sB_set ? pco_map_reg_bank_bits(sB) : -1;
152   int sB_bits = sB_set ? pco_map_reg_index_bits(sB) : -1;
153
154   int sbC_bits = sC_set ? pco_map_reg_bank_bits(sC) : -1;
155   int sC_bits = sC_set ? pco_map_reg_index_bits(sC) : -1;
156
157   int mux_bits = mux_set ? util_last_bit(pco_map_io_to_is0_sel(pco_ref_get_io(mux))) : -1;
158
159   bool is_ctrl = igrp->hdr.alutype == PCO_ALUTYPE_CONTROL;
160   bool no_srcs_set = !sA_set && !sB_set && !sC_set && !mux_set;
161   if (is_ctrl && no_srcs_set)
162      return PCO_SRC_NONE;
163
164% for variant, spec in [(bs.name.upper(), bs.data) for bs in I_SRC.bit_structs.values()]:
165   ${'else ' if not loop.first else ''}if (${'!' if not spec.is_upper else ''}is_upper &&
166            sbA_bits ${'==' if spec.sbA_bits == -1 else '<='} ${spec.sbA_bits} && sA_bits ${'==' if spec.sA_bits == -1 else '<='} ${spec.sA_bits} &&
167            sbB_bits ${'==' if spec.sbB_bits == -1 else '<='} ${spec.sbB_bits} && sB_bits ${'==' if spec.sB_bits == -1 else '<='} ${spec.sB_bits} &&
168            sbC_bits ${'==' if spec.sbC_bits == -1 else '<='} ${spec.sbC_bits} && sC_bits ${'==' if spec.sC_bits == -1 else '<='} ${spec.sC_bits} &&
169            mux_bits ${'==' if spec.mux_bits == -1 else '<='} ${spec.mux_bits}) {
170      return ${variant};
171   }
172% endfor
173
174   unreachable();
175}
176
177static inline
178enum pco_iss_variant pco_igrp_iss_variant(const pco_igrp *igrp)
179{
180   if (igrp->hdr.alutype == PCO_ALUTYPE_MAIN)
181      return PCO_ISS_ISS;
182
183   return PCO_ISS_NONE;
184}
185
186static inline
187enum pco_dst_variant pco_igrp_dest_variant(pco_igrp *igrp)
188{
189   pco_ref w0 = igrp->dests.w[0];
190   pco_ref w1 = igrp->dests.w[1];
191
192   bool w0_set = !pco_ref_is_null(w0);
193   bool w1_set = !pco_ref_is_null(w1);
194
195   bool no_dsts = !w0_set && !w1_set;
196   bool one_dest = w0_set != w1_set;
197   bool dual_dsts = w0_set && w1_set;
198
199   if (no_dsts)
200      return PCO_DST_NONE;
201
202   int db0_bits = w0_set ? pco_map_reg_bank_bits(w0) : -1;
203   int d0_bits = w0_set ? pco_map_reg_index_bits(w0) : -1;
204
205   int db1_bits = w1_set ? pco_map_reg_bank_bits(w1) : -1;
206   int d1_bits = w1_set ? pco_map_reg_index_bits(w1) : -1;
207
208   int dbN_bits = w0_set ? db0_bits : db1_bits;
209   int dN_bits = w0_set ? d0_bits : d1_bits;
210
211   if (one_dest) {
212      db0_bits = dbN_bits;
213      d0_bits = dN_bits;
214
215      db1_bits = -1;
216      d1_bits = -1;
217   }
218
219% for variant, spec in [(bs.name.upper(), bs.data) for bs in I_DST.bit_structs.values()]:
220   ${'else ' if not loop.first else ''}if (${'!' if not spec.dual_dsts else ''}dual_dsts &&
221        db0_bits ${'==' if spec.db0_bits == -1 else '<='} ${spec.db0_bits} && d0_bits ${'==' if spec.d0_bits == -1 else '<='} ${spec.d0_bits} &&
222        db1_bits ${'==' if spec.db1_bits == -1 else '<='} ${spec.db1_bits} && d1_bits ${'==' if spec.d1_bits == -1 else '<='} ${spec.d1_bits}) {
223      return ${variant};
224   }
225% endfor
226
227   unreachable();
228}
229
230/* Instruction group mappings. */
231% for op_map in op_maps.values():
232static inline
233void ${op_map.name}_map_igrp(pco_igrp *igrp, pco_instr *instr)
234{
235   % for mapping_group in op_map.igrp_mappings:
236      % for mapping in mapping_group:
237   ${mapping.format('igrp', 'instr')}
238      % endfor
239
240   % endfor
241   igrp->variant.hdr = pco_igrp_hdr_variant(igrp);
242   igrp->variant.lower_src = pco_igrp_src_variant(igrp, false);
243   igrp->variant.upper_src = pco_igrp_src_variant(igrp, true);
244   igrp->variant.iss = pco_igrp_iss_variant(igrp);
245   igrp->variant.dest = pco_igrp_dest_variant(igrp);
246}
247
248% endfor
249static inline
250void pco_map_igrp(pco_igrp *igrp, pco_instr *instr)
251{
252   switch (instr->op) {
253% for op_map in op_maps.values():
254   case ${op_map.cop_name}:
255      return ${op_map.name}_map_igrp(igrp, instr);
256
257% endfor
258   default:
259      break;
260   }
261
262   const struct pco_op_info *info = &pco_op_info[instr->op];
263   printf("Instruction group mapping not defined for %s op '%s'.\\n",
264          info->type == PCO_OP_TYPE_PSEUDO ? "pseudo" : "hardware",
265          info->str);
266
267   unreachable();
268}
269
270static inline unsigned pco_igrp_hdr_map_encode(uint8_t *bin, pco_igrp *igrp)
271{
272   switch (igrp->variant.hdr) {
273   case PCO_IGRP_HDR_MAIN_BRIEF:
274      return pco_igrp_hdr_main_brief_encode(bin,
275                                            .da = igrp->hdr.da,
276                                            .length = igrp->hdr.length,
277                                            .oporg = igrp->hdr.oporg,
278                                            .olchk = igrp->hdr.olchk,
279                                            .w1p = igrp->hdr.w1p,
280                                            .w0p = igrp->hdr.w0p,
281                                            .cc = igrp->hdr.cc);
282
283   case PCO_IGRP_HDR_MAIN:
284      return pco_igrp_hdr_main_encode(bin,
285                                      .da = igrp->hdr.da,
286                                      .length = igrp->hdr.length,
287                                      .oporg = igrp->hdr.oporg,
288                                      .olchk = igrp->hdr.olchk,
289                                      .w1p = igrp->hdr.w1p,
290                                      .w0p = igrp->hdr.w0p,
291                                      .cc = igrp->hdr.cc,
292                                      .end = igrp->hdr.end,
293                                      .atom = igrp->hdr.atom,
294                                      .rpt = igrp->hdr.rpt);
295
296   case PCO_IGRP_HDR_BITWISE:
297      return pco_igrp_hdr_bitwise_encode(bin,
298                                         .da = igrp->hdr.da,
299                                         .length = igrp->hdr.length,
300                                         .opcnt = igrp->hdr.opcnt,
301                                         .olchk = igrp->hdr.olchk,
302                                         .w1p = igrp->hdr.w1p,
303                                         .w0p = igrp->hdr.w0p,
304                                         .cc = igrp->hdr.cc,
305                                         .end = igrp->hdr.end,
306                                         .atom = igrp->hdr.atom,
307                                         .rpt = igrp->hdr.rpt);
308
309   case PCO_IGRP_HDR_CONTROL:
310      return pco_igrp_hdr_control_encode(bin,
311                                         .da = igrp->hdr.da,
312                                         .length = igrp->hdr.length,
313                                         .olchk = igrp->hdr.olchk,
314                                         .w1p = igrp->hdr.w1p,
315                                         .w0p = igrp->hdr.w0p,
316                                         .cc = igrp->hdr.cc,
317                                         .miscctl = igrp->hdr.miscctl,
318                                         .ctrlop = igrp->hdr.ctrlop);
319
320   default:
321      break;
322   }
323
324   unreachable();
325}
326
327
328% for op_map in encode_maps.values():
329static inline
330   % if len(op_map.encode_variants) > 1:
331unsigned ${op_map.name}_map_encode(uint8_t *bin, pco_instr *instr, unsigned variant)
332{
333   switch (variant) {
334   % for variant, mapping in op_map.encode_variants:
335   case ${variant}:
336      return ${mapping.format('bin', 'instr', 'variant')};
337
338   % endfor
339   default:
340      break;
341   }
342
343   unreachable();
344}
345   % else:
346unsigned ${op_map.name}_map_encode(uint8_t *bin, pco_instr *instr)
347{
348   return ${op_map.encode_variants[0][1].format('bin', 'instr', 'variant')};
349}
350   % endif
351
352% endfor
353static inline
354unsigned pco_instr_map_encode(uint8_t *bin, pco_igrp *igrp, enum pco_op_phase phase)
355{
356   pco_instr *instr = igrp->instrs[phase];
357   switch (instr->op) {
358% for op_map in encode_maps.values():
359   case ${op_map.cop_name}:
360   % if len(op_map.encode_variants) > 1:
361      return ${op_map.name}_map_encode(bin, instr, pco_igrp_variant(igrp, phase));
362   % else:
363      return ${op_map.name}_map_encode(bin, instr);
364   % endif
365
366% endfor
367   default:
368      break;
369   }
370
371   unreachable();
372}
373
374static inline
375unsigned pco_srcs_map_encode(uint8_t *bin, pco_igrp *igrp, bool is_upper)
376{
377   unsigned offset = is_upper ? ROGUE_ALU_INPUT_GROUP_SIZE : 0;
378
379   pco_ref _sA = igrp->srcs.s[0 + offset];
380   pco_ref _sB = igrp->srcs.s[1 + offset];
381   pco_ref _sC = igrp->srcs.s[2 + offset];
382   pco_ref _mux = is_upper ? pco_ref_null() : igrp->iss.is[0];
383
384   bool sA_set = !pco_ref_is_null(_sA);
385   bool sB_set = !pco_ref_is_null(_sB);
386   bool sC_set = !pco_ref_is_null(_sC);
387   bool mux_set = !pco_ref_is_null(_mux);
388
389   unsigned sbA = sA_set ? pco_map_reg_bank(_sA) : 0;
390   unsigned sA = sA_set ? pco_map_reg_index(_sA) : 0;
391
392   unsigned sbB = sB_set ? pco_map_reg_bank(_sB) : 0;
393   unsigned sB = sB_set ? pco_map_reg_index(_sB) : 0;
394
395   unsigned sbC = sC_set ? pco_map_reg_bank(_sC) : 0;
396   unsigned sC = sC_set ? pco_map_reg_index(_sC) : 0;
397
398   unsigned mux = mux_set ? pco_map_io_to_is0_sel(pco_ref_get_io(_mux)) : 0;
399
400   enum pco_src_variant variant = is_upper ? igrp->variant.upper_src : igrp->variant.lower_src;
401   switch (variant) {
402% for variant, encode_func, spec, offset in [(bs.name.upper(), f'{bs.name}_encode', bs.data, 3 if bs.data.is_upper else 0) for bs in I_SRC.bit_structs.values()]:
403   case ${variant}:
404      return ${encode_func}(bin,
405   % if spec.sbA_bits != -1:
406         .s${offset + 0} = sA,
407         .sb${offset + 0} = sbA,
408   % endif
409   % if spec.sbB_bits != -1:
410         .s${offset + 1} = sB,
411         .sb${offset + 1} = sbB,
412   % endif
413   % if spec.sbC_bits != -1:
414         .s${offset + 2} = sC,
415         .sb${offset + 2} = sbC,
416   % endif
417   % if spec.mux_bits != -1:
418         .is0 = mux,
419   % endif
420      );
421
422% endfor
423   default:
424      break;
425   }
426
427   unreachable();
428}
429
430static inline
431unsigned pco_iss_map_encode(uint8_t *bin, pco_igrp *igrp)
432{
433   bool is5_set = !pco_ref_is_null(igrp->iss.is[5]);
434   bool is4_set = !pco_ref_is_null(igrp->iss.is[4]);
435   bool is3_set = !pco_ref_is_null(igrp->iss.is[3]);
436   bool is2_set = !pco_ref_is_null(igrp->iss.is[2]);
437   bool is1_set = !pco_ref_is_null(igrp->iss.is[1]);
438
439   unsigned is5 = is5_set ? pco_map_io_to_is5_sel(pco_ref_get_io(igrp->iss.is[5])) : 0;
440   unsigned is4 = is4_set ? pco_map_io_to_is4_sel(pco_ref_get_io(igrp->iss.is[4])) : 0;
441   unsigned is3 = is3_set ? pco_map_io_to_is3_sel(pco_ref_get_io(igrp->iss.is[3])) : 0;
442   unsigned is2 = is2_set ? pco_map_io_to_is2_sel(pco_ref_get_io(igrp->iss.is[2])) : 0;
443   unsigned is1 = is1_set ? pco_map_io_to_is1_sel(pco_ref_get_io(igrp->iss.is[1])) : 0;
444
445   assert(igrp->variant.iss == PCO_ISS_ISS);
446   return pco_iss_iss_encode(bin, .is5 = is5, .is4 = is4, .is3 = is3, .is2 = is2, .is1 = is1);
447}
448
449static inline
450unsigned pco_dests_map_encode(uint8_t *bin, pco_igrp *igrp)
451{
452   pco_ref w0 = igrp->dests.w[0];
453   pco_ref w1 = igrp->dests.w[1];
454
455   bool w0_set = !pco_ref_is_null(w0);
456   bool w1_set = !pco_ref_is_null(w1);
457
458   bool one_dest = w0_set != w1_set;
459
460   int db0 = w0_set ? pco_map_reg_bank(w0) : 0;
461   int d0 = w0_set ? pco_map_reg_index(w0) : 0;
462
463   int db1 = w1_set ? pco_map_reg_bank(w1) : 0;
464   int d1 = w1_set ? pco_map_reg_index(w1) : 0;
465
466   int dbN = w0_set ? db0 : db1;
467   int dN = w0_set ? d0 : d1;
468
469   if (one_dest) {
470      db0 = dbN;
471      d0 = dN;
472
473      db1 = 0;
474      d1 = 0;
475   }
476
477   switch (igrp->variant.dest) {
478% for variant, encode_func, spec in [(bs.name.upper(), f'{bs.name}_encode', bs.data) for bs in I_DST.bit_structs.values()]:
479   case ${variant}:
480      return ${encode_func}(bin,
481   % if spec.db0_bits != -1:
482      % if spec.dual_dsts:
483         .d0 = d0,
484         .db0 = db0,
485      % else:
486         .dN = d0,
487         .dbN = db0,
488      % endif
489   % endif
490   % if spec.db1_bits != -1:
491         .d1 = d1,
492         .db1 = db1,
493   % endif
494      );
495
496% endfor
497   default:
498      break;
499   }
500
501   unreachable();
502}
503#endif /* PCO_MAP_H */"""
504
505def main():
506   try:
507      print(Template(template).render(enum_maps=enum_maps, op_maps=op_maps, encode_maps=encode_maps, I_SRC=I_SRC, I_DST=I_DST))
508   except:
509       raise Exception(exceptions.text_error_template().render())
510
511if __name__ == '__main__':
512   main()
513