• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Imagination Technologies Ltd.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 /**
8  * \file pco_binary.c
9  *
10  * \brief PCO binary-specific functions.
11  */
12 
13 #include "pco.h"
14 #include "pco_internal.h"
15 #include "pco_isa.h"
16 #include "pco_map.h"
17 #include "util/u_dynarray.h"
18 
19 #include <assert.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 
23 /**
24  * \brief Encodes instruction group alignment.
25  *
26  * \param[in,out] buf Binary buffer.
27  * \param[in] igrp PCO instruction group.
28  */
pco_encode_align(struct util_dynarray * buf,pco_igrp * igrp)29 static inline unsigned pco_encode_align(struct util_dynarray *buf,
30                                         pco_igrp *igrp)
31 {
32    unsigned bytes_encoded = 0;
33 
34    if (igrp->enc.len.word_padding) {
35       util_dynarray_append(buf, uint8_t, 0xff);
36       bytes_encoded += 1;
37    }
38 
39    if (igrp->enc.len.align_padding) {
40       assert(!(igrp->enc.len.align_padding % 2));
41 
42       unsigned align_words = igrp->enc.len.align_padding / 2;
43       util_dynarray_append(buf, uint8_t, 0xf0 | align_words);
44       bytes_encoded += 1;
45 
46       for (unsigned u = 0; u < igrp->enc.len.align_padding - 1; ++u) {
47          util_dynarray_append(buf, uint8_t, 0xff);
48          bytes_encoded += 1;
49       }
50    }
51 
52    return bytes_encoded;
53 }
54 
55 /**
56  * \brief Encodes a PCO instruction group into binary.
57  *
58  * \param[in,out] buf Binary buffer.
59  * \param[in] igrp PCO instruction group.
60  * \return The number of bytes encoded.
61  */
pco_encode_igrp(struct util_dynarray * buf,pco_igrp * igrp)62 static unsigned pco_encode_igrp(struct util_dynarray *buf, pco_igrp *igrp)
63 {
64    uint8_t *ptr;
65    unsigned bytes_encoded = 0;
66 
67    /* Header. */
68    ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.hdr);
69    bytes_encoded += pco_igrp_hdr_map_encode(ptr, igrp);
70 
71    /* Instructions. */
72    for (enum pco_op_phase p = _PCO_OP_PHASE_COUNT; p-- > 0;) {
73       if (!igrp->enc.len.instrs[p])
74          continue;
75 
76       ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.instrs[p]);
77       bytes_encoded += pco_instr_map_encode(ptr, igrp, p);
78    }
79 
80    /* I/O. */
81    if (igrp->enc.len.lower_srcs) {
82       ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.lower_srcs);
83       bytes_encoded += pco_srcs_map_encode(ptr, igrp, false);
84    }
85 
86    if (igrp->enc.len.upper_srcs) {
87       ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.upper_srcs);
88       bytes_encoded += pco_srcs_map_encode(ptr, igrp, true);
89    }
90 
91    if (igrp->enc.len.iss) {
92       ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.iss);
93       bytes_encoded += pco_iss_map_encode(ptr, igrp);
94    }
95 
96    if (igrp->enc.len.dests) {
97       ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.dests);
98       bytes_encoded += pco_dests_map_encode(ptr, igrp);
99    }
100 
101    /* Word/alignment padding. */
102    bytes_encoded += pco_encode_align(buf, igrp);
103 
104    assert(bytes_encoded == igrp->enc.len.total);
105 
106    return bytes_encoded;
107 }
108 
109 /**
110  * \brief Encodes a PCO shader into binary.
111  *
112  * \param[in] ctx PCO compiler context.
113  * \param[in,out] shader PCO shader.
114  */
pco_encode_ir(pco_ctx * ctx,pco_shader * shader)115 void pco_encode_ir(pco_ctx *ctx, pco_shader *shader)
116 {
117    assert(shader->is_grouped);
118 
119    util_dynarray_init(&shader->binary.buf, shader);
120 
121    unsigned bytes_encoded = 0;
122    pco_foreach_func_in_shader (func, shader) {
123       func->enc_offset = bytes_encoded;
124       pco_foreach_block_in_func (block, func) {
125          pco_foreach_igrp_in_block (igrp, block) {
126             bytes_encoded += pco_encode_igrp(&shader->binary.buf, igrp);
127          }
128       }
129    }
130 
131    if (pco_should_print_binary(shader))
132       pco_print_binary(shader, stdout, "after encoding");
133 }
134 
135 /**
136  * \brief Finalizes a PCO shader binary.
137  *
138  * \param[in] ctx PCO compiler context.
139  * \param[in,out] shader PCO shader.
140  */
pco_shader_finalize(pco_ctx * ctx,pco_shader * shader)141 void pco_shader_finalize(pco_ctx *ctx, pco_shader *shader)
142 {
143    puts("finishme: pco_shader_finalize");
144 
145    pco_func *entry = pco_entrypoint(shader);
146    shader->data.common.entry_offset = entry->enc_offset;
147 
148    if (pco_should_print_binary(shader))
149       pco_print_binary(shader, stdout, "after finalizing");
150 }
151 
152 /**
153  * \brief Returns the size in bytes of a PCO shader binary.
154  *
155  * \param[in] shader PCO shader.
156  * \return The size in bytes of the PCO shader binary.
157  */
pco_shader_binary_size(pco_shader * shader)158 unsigned pco_shader_binary_size(pco_shader *shader)
159 {
160    return shader->binary.buf.size;
161 }
162 
163 /**
164  * \brief Returns the PCO shader binary data.
165  *
166  * \param[in] shader PCO shader.
167  * \return The PCO shader binary data.
168  */
pco_shader_binary_data(pco_shader * shader)169 const void *pco_shader_binary_data(pco_shader *shader)
170 {
171    return shader->binary.buf.data;
172 }
173