Skip to main content

logicaffeine_compile/spatial/decode_engine/rtl/
weights.rs

1//! The weight decoders as Verilog: each GGUF block format the array reads, unpacked in place into one form the array
2//! and the block-scale unit share.
3//!
4//! Every weight is `a·c_u·(code − z) + b·n_u`: `code` an unsigned integer (one or two 4-bit digits), `z` the format's
5//! offset, `c_u` and `n_u` small signed integers of the weight's 16-element unit, `a` and `b` the block's binary16
6//! scales. That is the coded row's `coef = c_u·(code − z)` and `offs = n_u`
7//! ([`crate::spatial::decode_engine::numerics::CodedRow`]), so a decoder is held to the coded row element by element.
8//!
9//! A decoder `logos_dec_<format>` takes one block's bytes (`blk`, byte 0 in bits 7:0) and gives `code` (8 bits an
10//! element), `c` and `n` (16 signed bits a unit), `a` and `b` (the scales' bits), and its offset `z` as a constant. An
11//! IQ4 nibble indexes a non-linear level; its code is the level in excess form, `level + 128`.
12
13use crate::model::quant::{GgmlType, KVALUES_IQ4NL};
14
15/// A format's decoder: the offset it subtracts from its codes and the bits a code spans.
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub struct Decoder {
18    pub ty: GgmlType,
19    pub offset: u32,
20    pub code_bits: u32,
21}
22
23/// Every format the engine reads, with its decoder.
24pub const DECODERS: [Decoder; 12] = [
25    Decoder { ty: GgmlType::Q4_0, offset: 8, code_bits: 4 },
26    Decoder { ty: GgmlType::Q4_1, offset: 0, code_bits: 4 },
27    Decoder { ty: GgmlType::Q5_0, offset: 16, code_bits: 5 },
28    Decoder { ty: GgmlType::Q5_1, offset: 0, code_bits: 5 },
29    Decoder { ty: GgmlType::Q8_0, offset: 128, code_bits: 8 },
30    Decoder { ty: GgmlType::Q2K, offset: 0, code_bits: 2 },
31    Decoder { ty: GgmlType::Q3K, offset: 4, code_bits: 3 },
32    Decoder { ty: GgmlType::Q4K, offset: 0, code_bits: 4 },
33    Decoder { ty: GgmlType::Q5K, offset: 0, code_bits: 5 },
34    Decoder { ty: GgmlType::Q6K, offset: 32, code_bits: 6 },
35    Decoder { ty: GgmlType::Iq4Nl, offset: 128, code_bits: 8 },
36    Decoder { ty: GgmlType::Iq4Xs, offset: 128, code_bits: 8 },
37];
38
39/// Elements one unit multiplier `c`/`n` covers.
40pub const UNIT: usize = 16;
41
42/// One block as its decoder decodes it: every element's code, every unit's multipliers, the two scales' bits.
43#[derive(Clone, Debug, PartialEq, Eq)]
44pub struct Units {
45    pub code: Vec<u32>,
46    pub c: Vec<i16>,
47    pub n: Vec<i16>,
48    pub a: u16,
49    pub b: u16,
50}
51
52/// `ty`'s decoder in software, field for field: what `logos_dec_<format>` gives for the block `blk`.
53pub fn units(ty: GgmlType, blk: &[u8]) -> Units {
54    assert_eq!(blk.len(), ty.block_bytes(), "one {} block", ty.name());
55    let half = |at: usize| u16::from_le_bytes([blk[at], blk[at + 1]]);
56    let word = |at: usize| u32::from_le_bytes([blk[at], blk[at + 1], blk[at + 2], blk[at + 3]]);
57    let n = ty.block_len();
58    let mut code = vec![0u32; n];
59    let mut c = vec![1i16; n / UNIT];
60    let mut nn = vec![0i16; n / UNIT];
61    let (a, b) = match ty {
62        GgmlType::Q4_0 | GgmlType::Q4_1 => {
63            let qs = if ty == GgmlType::Q4_0 { 2 } else { 4 };
64            for j in 0..16 {
65                code[j] = (blk[qs + j] & 15) as u32;
66                code[j + 16] = (blk[qs + j] >> 4) as u32;
67            }
68            if ty == GgmlType::Q4_1 {
69                nn = vec![1; 2];
70                (half(0), half(2))
71            } else {
72                (half(0), 0)
73            }
74        }
75        GgmlType::Q5_0 | GgmlType::Q5_1 => {
76            let one = ty == GgmlType::Q5_1;
77            let (qh, qs) = if one { (word(4), 8) } else { (word(2), 6) };
78            for j in 0..16 {
79                code[j] = (blk[qs + j] & 15) as u32 | ((qh >> j) & 1) << 4;
80                code[j + 16] = (blk[qs + j] >> 4) as u32 | ((qh >> (j + 16)) & 1) << 4;
81            }
82            if one {
83                nn = vec![1; 2];
84                (half(0), half(2))
85            } else {
86                (half(0), 0)
87            }
88        }
89        GgmlType::Q8_0 => {
90            for j in 0..32 {
91                code[j] = (blk[2 + j] ^ 0x80) as u32;
92            }
93            (half(0), 0)
94        }
95        GgmlType::Q2K => {
96            for h in 0..2 {
97                for sh in 0..4 {
98                    for hf in 0..2 {
99                        let u = 8 * h + 2 * sh + hf;
100                        c[u] = (blk[u] & 15) as i16;
101                        nn[u] = -((blk[u] >> 4) as i16);
102                        for l in 0..16 {
103                            code[128 * h + 32 * sh + 16 * hf + l] = ((blk[16 + 32 * h + 16 * hf + l] >> (2 * sh)) & 3) as u32;
104                        }
105                    }
106                }
107            }
108            (half(80), half(82))
109        }
110        GgmlType::Q3K => {
111            let (w0, w1, w2) = (word(96), word(100), word(104));
112            let (k1, k2) = (0x0303_0303u32, 0x0f0f_0f0fu32);
113            let scales: Vec<u8> = [
114                (w0 & k2) | ((w2 & k1) << 4),
115                (w1 & k2) | (((w2 >> 2) & k1) << 4),
116                ((w0 >> 4) & k2) | (((w2 >> 4) & k1) << 4),
117                ((w1 >> 4) & k2) | (((w2 >> 6) & k1) << 4),
118            ]
119            .iter()
120            .flat_map(|v| v.to_le_bytes())
121            .collect();
122            for h in 0..2 {
123                for sh in 0..4 {
124                    for hf in 0..2 {
125                        let u = 8 * h + 2 * sh + hf;
126                        c[u] = scales[u] as i16 - 32;
127                        for l in 0..16 {
128                            let low = (blk[32 + 32 * h + 16 * hf + l] >> (2 * sh)) & 3;
129                            let high = (blk[16 * hf + l] >> (4 * h + sh)) & 1;
130                            code[128 * h + 32 * sh + 16 * hf + l] = (high << 2 | low) as u32;
131                        }
132                    }
133                }
134            }
135            (half(108), 0)
136        }
137        GgmlType::Q4K | GgmlType::Q5K => {
138            let five = ty == GgmlType::Q5K;
139            let q = &blk[4..16];
140            let scale_min = |j: usize| -> (u8, u8) {
141                if j < 4 {
142                    (q[j] & 63, q[j + 4] & 63)
143                } else {
144                    ((q[j + 4] & 15) | ((q[j - 4] >> 6) << 4), (q[j + 4] >> 4) | ((q[j] >> 6) << 4))
145                }
146            };
147            let qs = if five { 48 } else { 16 };
148            for p in 0..4 {
149                let (s1, m1) = scale_min(2 * p);
150                let (s2, m2) = scale_min(2 * p + 1);
151                for (u, (sc, mn)) in [(4 * p, (s1, m1)), (4 * p + 1, (s1, m1)), (4 * p + 2, (s2, m2)), (4 * p + 3, (s2, m2))] {
152                    c[u] = sc as i16;
153                    nn[u] = -(mn as i16);
154                }
155                for l in 0..32 {
156                    let byte = blk[qs + 32 * p + l];
157                    let (hi1, hi2) = if five { (((blk[16 + l] >> (2 * p)) & 1) as u32, ((blk[16 + l] >> (2 * p + 1)) & 1) as u32) } else { (0, 0) };
158                    code[64 * p + l] = (byte & 15) as u32 | hi1 << 4;
159                    code[64 * p + 32 + l] = (byte >> 4) as u32 | hi2 << 4;
160                }
161            }
162            (half(0), half(2))
163        }
164        GgmlType::Q6K => {
165            for part in 0..2 {
166                for u in 0..8 {
167                    c[8 * part + u] = blk[192 + 8 * part + u] as i8 as i16;
168                }
169                for l in 0..32 {
170                    let (ql0, ql1, qh) = (blk[64 * part + l], blk[64 * part + l + 32], blk[128 + 32 * part + l]);
171                    code[128 * part + l] = (ql0 & 15) as u32 | ((qh & 3) as u32) << 4;
172                    code[128 * part + l + 32] = (ql1 & 15) as u32 | (((qh >> 2) & 3) as u32) << 4;
173                    code[128 * part + l + 64] = (ql0 >> 4) as u32 | (((qh >> 4) & 3) as u32) << 4;
174                    code[128 * part + l + 96] = (ql1 >> 4) as u32 | (((qh >> 6) & 3) as u32) << 4;
175                }
176            }
177            (half(208), 0)
178        }
179        GgmlType::Iq4Nl | GgmlType::Iq4Xs => {
180            // A nibble's level as an excess code: the array reads `level + 128` as two digits.
181            let level = |nibble: u8| (KVALUES_IQ4NL[nibble as usize] as i32 + 128) as u32;
182            if ty == GgmlType::Iq4Nl {
183                for j in 0..16 {
184                    code[j] = level(blk[2 + j] & 15);
185                    code[j + 16] = level(blk[2 + j] >> 4);
186                }
187            } else {
188                let scales_h = half(2);
189                for ib in 0..8 {
190                    let ls = ((blk[4 + ib / 2] >> (4 * (ib % 2))) & 0xf) as i16 | ((((scales_h >> (2 * ib)) & 3) as i16) << 4);
191                    c[2 * ib] = ls - 32;
192                    c[2 * ib + 1] = ls - 32;
193                    for j in 0..16 {
194                        code[32 * ib + j] = level(blk[8 + 16 * ib + j] & 15);
195                        code[32 * ib + 16 + j] = level(blk[8 + 16 * ib + j] >> 4);
196                    }
197                }
198            }
199            (half(0), 0)
200        }
201        other => panic!("no decoder for {}", other.name()),
202    };
203    Units { code, c, n: nn, a, b }
204}
205
206/// The module name of `ty`'s decoder.
207pub fn decoder_name(ty: GgmlType) -> String {
208    format!("logos_dec_{}", ty.name().to_lowercase())
209}
210
211/// Every decoder.
212pub fn weights_verilog() -> &'static str {
213    WEIGHTS_VERILOG
214}
215
216const WEIGHTS_VERILOG: &str = r#"// The block decoders: GGUF bytes to codes, unit multipliers and the block's scales.
217
218// ggml's get_scale_min_k4: sub-block j's 6-bit scale and min from a K-quant's 12 packed bytes.
219module logos_scale_min_k4(input [95:0] q, input [2:0] j, output [5:0] sc, output [5:0] mn);
220  function [7:0] qb(input [95:0] v, input [3:0] i); qb = v[8*i +: 8]; endfunction
221  wire [7:0] here = qb(q, {1'b0, j}), ahead = qb(q, {1'b0, j} + 4'd4), behind = qb(q, {1'b0, j} - 4'd4);
222  assign sc = (j < 3'd4) ? here[5:0] : {behind[7:6], ahead[3:0]};
223  assign mn = (j < 3'd4) ? ahead[5:0] : {here[7:6], ahead[7:4]};
224endmodule
225
226module logos_dec_q4_0(input [143:0] blk, output [255:0] code, output [31:0] c, output [31:0] n, output [15:0] a, output [15:0] b);
227  assign a = blk[15:0];
228  assign b = 16'd0;
229  assign c = {16'sd1, 16'sd1};
230  assign n = 32'd0;
231  genvar j;
232  generate for (j = 0; j < 16; j = j + 1) begin : e
233    assign code[8*j +: 8] = {4'd0, blk[16 + 8*j +: 4]};
234    assign code[8*(j+16) +: 8] = {4'd0, blk[20 + 8*j +: 4]};
235  end endgenerate
236endmodule
237
238module logos_dec_q4_1(input [159:0] blk, output [255:0] code, output [31:0] c, output [31:0] n, output [15:0] a, output [15:0] b);
239  assign a = blk[15:0];
240  assign b = blk[31:16];
241  assign c = {16'sd1, 16'sd1};
242  assign n = {16'sd1, 16'sd1};
243  genvar j;
244  generate for (j = 0; j < 16; j = j + 1) begin : e
245    assign code[8*j +: 8] = {4'd0, blk[32 + 8*j +: 4]};
246    assign code[8*(j+16) +: 8] = {4'd0, blk[36 + 8*j +: 4]};
247  end endgenerate
248endmodule
249
250module logos_dec_q5_0(input [175:0] blk, output [255:0] code, output [31:0] c, output [31:0] n, output [15:0] a, output [15:0] b);
251  wire [31:0] qh = blk[47:16];
252  assign a = blk[15:0];
253  assign b = 16'd0;
254  assign c = {16'sd1, 16'sd1};
255  assign n = 32'd0;
256  genvar j;
257  generate for (j = 0; j < 16; j = j + 1) begin : e
258    assign code[8*j +: 8] = {3'd0, qh[j], blk[48 + 8*j +: 4]};
259    assign code[8*(j+16) +: 8] = {3'd0, qh[j+16], blk[52 + 8*j +: 4]};
260  end endgenerate
261endmodule
262
263module logos_dec_q5_1(input [191:0] blk, output [255:0] code, output [31:0] c, output [31:0] n, output [15:0] a, output [15:0] b);
264  wire [31:0] qh = blk[63:32];
265  assign a = blk[15:0];
266  assign b = blk[31:16];
267  assign c = {16'sd1, 16'sd1};
268  assign n = {16'sd1, 16'sd1};
269  genvar j;
270  generate for (j = 0; j < 16; j = j + 1) begin : e
271    assign code[8*j +: 8] = {3'd0, qh[j], blk[64 + 8*j +: 4]};
272    assign code[8*(j+16) +: 8] = {3'd0, qh[j+16], blk[68 + 8*j +: 4]};
273  end endgenerate
274endmodule
275
276module logos_dec_q8_0(input [271:0] blk, output [255:0] code, output [31:0] c, output [31:0] n, output [15:0] a, output [15:0] b);
277  assign a = blk[15:0];
278  assign b = 16'd0;
279  assign c = {16'sd1, 16'sd1};
280  assign n = 32'd0;
281  genvar j;
282  generate for (j = 0; j < 32; j = j + 1) begin : e
283    assign code[8*j +: 8] = blk[16 + 8*j +: 8] ^ 8'h80;
284  end endgenerate
285endmodule
286
287module logos_dec_q2_k(input [671:0] blk, output [2047:0] code, output [255:0] c, output [255:0] n, output [15:0] a, output [15:0] b);
288  assign a = blk[655:640];
289  assign b = blk[671:656];
290  genvar h, s, hf, l;
291  generate
292    for (h = 0; h < 2; h = h + 1) begin : nb
293      for (s = 0; s < 4; s = s + 1) begin : sh
294        for (hf = 0; hf < 2; hf = hf + 1) begin : half
295          localparam integer U = 8*h + 2*s + hf;
296          wire [7:0] sc = blk[8*U +: 8];
297          assign c[16*U +: 16] = {12'd0, sc[3:0]};
298          assign n[16*U +: 16] = -$signed({12'd0, sc[7:4]});
299          for (l = 0; l < 16; l = l + 1) begin : el
300            wire [7:0] q = blk[128 + 8*(32*h + 16*hf + l) +: 8];
301            assign code[8*(128*h + 32*s + 16*hf + l) +: 8] = {6'd0, q[2*s +: 2]};
302          end
303        end
304      end
305    end
306  endgenerate
307endmodule
308
309module logos_dec_q3_k(input [879:0] blk, output [2047:0] code, output [255:0] c, output [255:0] n, output [15:0] a, output [15:0] b);
310  assign a = blk[879:864];
311  assign b = 16'd0;
312  assign n = 256'd0;
313  // ggml's 6-bit scales from the 12 packed bytes at 96..107.
314  wire [31:0] w0 = blk[768 +: 32], w1 = blk[800 +: 32], w2 = blk[832 +: 32];
315  wire [31:0] k1 = 32'h0303_0303, k2 = 32'h0f0f_0f0f;
316  wire [31:0] s2 = ((w0 >> 4) & k2) | (((w2 >> 4) & k1) << 4);
317  wire [31:0] s3 = ((w1 >> 4) & k2) | (((w2 >> 6) & k1) << 4);
318  wire [31:0] s0 = (w0 & k2) | ((w2 & k1) << 4);
319  wire [31:0] s1 = (w1 & k2) | (((w2 >> 2) & k1) << 4);
320  wire [127:0] scales = {s3, s2, s1, s0};
321  genvar h, s, hf, l;
322  generate
323    for (h = 0; h < 2; h = h + 1) begin : nb
324      for (s = 0; s < 4; s = s + 1) begin : sh
325        for (hf = 0; hf < 2; hf = hf + 1) begin : half
326          localparam integer U = 8*h + 2*s + hf;
327          wire [7:0] sc = scales[8*U +: 8];
328          assign c[16*U +: 16] = $signed({8'd0, sc}) - 16'sd32;
329          for (l = 0; l < 16; l = l + 1) begin : el
330            wire [7:0] q = blk[256 + 8*(32*h + 16*hf + l) +: 8];
331            wire [7:0] hm = blk[8*(16*hf + l) +: 8];
332            assign code[8*(128*h + 32*s + 16*hf + l) +: 8] = {5'd0, hm[4*h + s], q[2*s +: 2]};
333          end
334        end
335      end
336    end
337  endgenerate
338endmodule
339
340module logos_dec_q4_k(input [1151:0] blk, output [2047:0] code, output [255:0] c, output [255:0] n, output [15:0] a, output [15:0] b);
341  assign a = blk[15:0];
342  assign b = blk[31:16];
343  wire [95:0] scq = blk[127:32];
344  genvar p, l;
345  generate
346    for (p = 0; p < 4; p = p + 1) begin : pair
347      wire [5:0] s1, m1, s2, m2;
348      logos_scale_min_k4 lo(.q(scq), .j(2*p), .sc(s1), .mn(m1));
349      logos_scale_min_k4 hi(.q(scq), .j(2*p+1), .sc(s2), .mn(m2));
350      assign c[16*(4*p) +: 32] = {{10'd0, s1}, {10'd0, s1}};
351      assign c[16*(4*p+2) +: 32] = {{10'd0, s2}, {10'd0, s2}};
352      assign n[16*(4*p) +: 32] = {-$signed({10'd0, m1}), -$signed({10'd0, m1})};
353      assign n[16*(4*p+2) +: 32] = {-$signed({10'd0, m2}), -$signed({10'd0, m2})};
354      for (l = 0; l < 32; l = l + 1) begin : el
355        wire [7:0] q = blk[128 + 8*(32*p + l) +: 8];
356        assign code[8*(64*p + l) +: 8] = {4'd0, q[3:0]};
357        assign code[8*(64*p + 32 + l) +: 8] = {4'd0, q[7:4]};
358      end
359    end
360  endgenerate
361endmodule
362
363module logos_dec_q5_k(input [1407:0] blk, output [2047:0] code, output [255:0] c, output [255:0] n, output [15:0] a, output [15:0] b);
364  assign a = blk[15:0];
365  assign b = blk[31:16];
366  wire [95:0] scq = blk[127:32];
367  genvar p, l;
368  generate
369    for (p = 0; p < 4; p = p + 1) begin : pair
370      wire [5:0] s1, m1, s2, m2;
371      logos_scale_min_k4 lo(.q(scq), .j(2*p), .sc(s1), .mn(m1));
372      logos_scale_min_k4 hi(.q(scq), .j(2*p+1), .sc(s2), .mn(m2));
373      assign c[16*(4*p) +: 32] = {{10'd0, s1}, {10'd0, s1}};
374      assign c[16*(4*p+2) +: 32] = {{10'd0, s2}, {10'd0, s2}};
375      assign n[16*(4*p) +: 32] = {-$signed({10'd0, m1}), -$signed({10'd0, m1})};
376      assign n[16*(4*p+2) +: 32] = {-$signed({10'd0, m2}), -$signed({10'd0, m2})};
377      for (l = 0; l < 32; l = l + 1) begin : el
378        wire [7:0] qh = blk[128 + 8*l +: 8];
379        wire [7:0] q = blk[384 + 8*(32*p + l) +: 8];
380        assign code[8*(64*p + l) +: 8] = {3'd0, qh[2*p], q[3:0]};
381        assign code[8*(64*p + 32 + l) +: 8] = {3'd0, qh[2*p+1], q[7:4]};
382      end
383    end
384  endgenerate
385endmodule
386
387module logos_dec_q6_k(input [1679:0] blk, output [2047:0] code, output [255:0] c, output [255:0] n, output [15:0] a, output [15:0] b);
388  assign a = blk[1679:1664];
389  assign b = 16'd0;
390  assign n = 256'd0;
391  genvar part, u, l;
392  generate
393    for (part = 0; part < 2; part = part + 1) begin : pt
394      for (u = 0; u < 8; u = u + 1) begin : un
395        wire [7:0] sc = blk[8*(192 + 8*part + u) +: 8];
396        assign c[16*(8*part + u) +: 16] = {{8{sc[7]}}, sc};
397      end
398      for (l = 0; l < 32; l = l + 1) begin : el
399        wire [7:0] ql0 = blk[8*(64*part + l) +: 8];
400        wire [7:0] ql1 = blk[8*(64*part + l + 32) +: 8];
401        wire [7:0] qh = blk[8*(128 + 32*part + l) +: 8];
402        assign code[8*(128*part + l) +: 8] = {2'd0, qh[1:0], ql0[3:0]};
403        assign code[8*(128*part + l + 32) +: 8] = {2'd0, qh[3:2], ql1[3:0]};
404        assign code[8*(128*part + l + 64) +: 8] = {2'd0, qh[5:4], ql0[7:4]};
405        assign code[8*(128*part + l + 96) +: 8] = {2'd0, qh[7:6], ql1[7:4]};
406      end
407    end
408  endgenerate
409endmodule
410
411// An IQ4 nibble's level as an excess code (ggml's kvalues_iq4nl, plus 128).
412module logos_iq4_level(input [3:0] q, output reg [7:0] level);
413  always @* begin
414    case (q)
415      4'd0: level = 8'd1;
416      4'd1: level = 8'd24;
417      4'd2: level = 8'd45;
418      4'd3: level = 8'd63;
419      4'd4: level = 8'd79;
420      4'd5: level = 8'd93;
421      4'd6: level = 8'd106;
422      4'd7: level = 8'd118;
423      4'd8: level = 8'd129;
424      4'd9: level = 8'd141;
425      4'd10: level = 8'd153;
426      4'd11: level = 8'd166;
427      4'd12: level = 8'd181;
428      4'd13: level = 8'd197;
429      4'd14: level = 8'd217;
430      4'd15: level = 8'd241;
431    endcase
432  end
433endmodule
434
435module logos_dec_iq4_nl(input [143:0] blk, output [255:0] code, output [31:0] c, output [31:0] n, output [15:0] a, output [15:0] b);
436  assign a = blk[15:0];
437  assign b = 16'd0;
438  assign c = {16'sd1, 16'sd1};
439  assign n = 32'd0;
440  genvar j;
441  generate for (j = 0; j < 16; j = j + 1) begin : e
442    logos_iq4_level lo(.q(blk[16 + 8*j +: 4]), .level(code[8*j +: 8]));
443    logos_iq4_level hi(.q(blk[20 + 8*j +: 4]), .level(code[8*(j+16) +: 8]));
444  end endgenerate
445endmodule
446
447module logos_dec_iq4_xs(input [1087:0] blk, output [2047:0] code, output [255:0] c, output [255:0] n, output [15:0] a, output [15:0] b);
448  assign a = blk[15:0];
449  assign b = 16'd0;
450  assign n = 256'd0;
451  wire [15:0] scales_h = blk[31:16];
452  genvar ib, j;
453  generate
454    for (ib = 0; ib < 8; ib = ib + 1) begin : sub
455      wire [5:0] ls = {scales_h[2*ib +: 2], blk[32 + 8*(ib/2) + 4*(ib%2) +: 4]};
456      wire signed [15:0] cs = $signed({10'd0, ls}) - 16'sd32;
457      assign c[16*(2*ib) +: 16] = cs;
458      assign c[16*(2*ib + 1) +: 16] = cs;
459      for (j = 0; j < 16; j = j + 1) begin : e
460        logos_iq4_level lo(.q(blk[64 + 8*(16*ib + j) +: 4]), .level(code[8*(32*ib + j) +: 8]));
461        logos_iq4_level hi(.q(blk[68 + 8*(16*ib + j) +: 4]), .level(code[8*(32*ib + 16 + j) +: 8]));
462      end
463    end
464  endgenerate
465endmodule
466"#;