feat: update APU tests to synchronize with P4 ISA and add APU primitives filelist checks

- Modified test_apu_register_parity.py to reflect changes in P4 ISA definitions.
- Updated test_apu_register_parity.py to include new manifest entries for P4.
- Enhanced test_script_tools.py to include checks for APU primitives filelists.
- Added assertions for APU primitives in the formal filelists test to ensure proper scoping and inclusion.
This commit is contained in:
maksyuki committed 2026-09-05 07:29:50 +08:00
1 parent 29a667415b
commit 57ffd03216
38 files changed
+8742 -434

No files matched your search

@@ -0,0 +1,174 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// SPDX-License-Identifier: MulanPSL-2.0
`include "apu_define.svh"
module apu_reconstruction_engine (
// verilog_format: off -- preserve arithmetic operand columns
input logic [ 3:0] opcode_i,
input logic [ 7:0] aux_i,
input logic signed [31:0] value0_i,
input logic signed [31:0] value1_i,
input logic signed [31:0] scale_i,
input logic signed [31:0] residual_i,
input logic signed [31:0] predictor_shift_i,
input logic signed [31:0] history_i [0:31],
input logic signed [31:0] coefficient_i [0:31],
output logic signed [31:0] result0_o,
output logic signed [31:0] result1_o,
output logic overflow_o
// verilog_format: on
);
logic signed [71:0] s_accumulator;
logic signed [63:0] s_value0, s_value1;
logic signed [63:0] s_product;
logic signed [63:0] s_predictor;
logic signed [63:0] s_shifted;
logic signed [63:0] s_value0_ext, s_value1_ext, s_residual_ext;
logic signed [71:0] s_lpc_shifted;
logic signed [72:0] s_lpc_value;
logic s_lpc_shift_overflow;
logic [ 5:0] s_order;
function automatic logic signed [63:0] rne(input logic signed [63:0] value_i,
input logic [5:0] shift_i);
logic signed [63:0] s_magnitude;
logic signed [63:0] s_quotient;
logic [63:0] s_remainder;
logic [63:0] s_half;
begin
if (shift_i == 6'd0) return value_i;
s_magnitude = (value_i < 0) ? -value_i : value_i;
s_quotient = s_magnitude >>> shift_i;
s_remainder = s_magnitude & ((64'd1 << shift_i) - 1'b1);
s_half = 64'd1 << (shift_i - 1'b1);
if ((s_remainder > s_half) || ((s_remainder == s_half) && s_quotient[0])) begin
s_quotient = s_quotient + 1'b1;
end
return (value_i < 0) ? -s_quotient : s_quotient;
end
endfunction
function automatic logic signed [31:0] sat32(input logic signed [63:0] value_i);
if (value_i > 64'sh0000_0000_7fff_ffff) return 32'sh7fff_ffff;
if (value_i < -64'sh0000_0000_8000_0000) return -32'sh8000_0000;
return value_i[31:0];
endfunction
function automatic logic signed [31:0] sat_width(input logic signed [63:0] value_i,
input logic [1:0] width_i);
logic signed [63:0] s_minimum, s_maximum;
begin
unique case (width_i)
2'd0: begin
s_minimum = -64'sd32768;
s_maximum = 64'sd32767;
end
2'd1: begin
s_minimum = -64'sd8388608;
s_maximum = 64'sd8388607;
end
default: begin
s_minimum = -64'sh0000_0000_8000_0000;
s_maximum = 64'sh0000_0000_7fff_ffff;
end
endcase
if (value_i < s_minimum) return s_minimum[31:0];
if (value_i > s_maximum) return s_maximum[31:0];
return value_i[31:0];
end
endfunction
always_comb begin
s_order = aux_i[5:0];
s_accumulator = 72'sd0;
for (int index = 0; index < 32; index++) begin
if (index < s_order) begin
s_accumulator += $signed(coefficient_i[index]) * $signed(history_i[index]);
end
end
s_product = $signed(value0_i) * $signed(scale_i);
s_value0_ext = {{32{value0_i[31]}}, value0_i};
s_value1_ext = {{32{value1_i[31]}}, value1_i};
s_residual_ext = {{32{residual_i[31]}}, residual_i};
s_predictor = 64'sd0;
unique case (aux_i[2:0])
3'd1: s_predictor = {{32{history_i[0][31]}}, history_i[0]};
3'd2:
s_predictor = 64'sd2 * {{32{history_i[0][31]}}, history_i[0]} -
{{32{history_i[1][31]}}, history_i[1]};
3'd3:
s_predictor = 64'sd3 * {{32{history_i[0][31]}}, history_i[0]} -
64'sd3 * {{32{history_i[1][31]}}, history_i[1]} +
{{32{history_i[2][31]}}, history_i[2]};
3'd4:
s_predictor = 64'sd4 * {{32{history_i[0][31]}}, history_i[0]} -
64'sd6 * {{32{history_i[1][31]}}, history_i[1]} +
64'sd4 * {{32{history_i[2][31]}}, history_i[2]} -
{{32{history_i[3][31]}}, history_i[3]};
default: s_predictor = 64'sd0;
endcase
s_value0 = s_value0_ext;
s_value1 = s_value1_ext;
if (predictor_shift_i >= 0) begin
s_lpc_shifted = s_accumulator >>> predictor_shift_i[5:0];
s_lpc_shift_overflow = 1'b0;
end else begin
s_lpc_shifted = s_accumulator <<< (-predictor_shift_i);
s_lpc_shift_overflow = (s_lpc_shifted >>> (-predictor_shift_i)) != s_accumulator;
end
s_shifted = s_lpc_shifted[63:0];
s_lpc_value = {s_lpc_shifted[71], s_lpc_shifted} + {{41{residual_i[31]}}, residual_i};
result0_o = value0_i;
result1_o = value1_i;
overflow_o = (s_accumulator[71:63] != {9{s_accumulator[63]}});
unique case (opcode_i)
`APB4_APU__MC_KERNEL_REQUANT: begin
s_shifted = aux_i[5] ?
rne(s_product, 6'(30 + aux_i[4:0])) : (s_product >>> (30 + aux_i[4:0]));
result0_o = sat_width(s_shifted, aux_i[7:6]);
end
`APB4_APU__MC_KERNEL_STEREO, `APB4_APU__MC_KERNEL_DECORRELATE: begin
unique case (aux_i[1:0])
2'd0: begin
s_value0 = s_value0_ext;
s_value1 = s_value1_ext;
end
2'd1: begin
s_value0 = s_value0_ext;
s_value1 = s_value0_ext - s_value1_ext;
end
2'd2: begin
s_value0 = s_value0_ext + s_value1_ext;
s_value1 = s_value1_ext;
end
default: begin
s_predictor = s_value0_ext * 64'sd2 + (s_value1_ext & 64'sd1);
s_value0 = (s_predictor + s_value1_ext) >>> 1;
s_value1 = (s_predictor - s_value1_ext) >>> 1;
end
endcase
overflow_o = (s_value0 > 64'sh0000_0000_7fff_ffff) ||
(s_value0 < -64'sh0000_0000_8000_0000) ||
(s_value1 > 64'sh0000_0000_7fff_ffff) ||
(s_value1 < -64'sh0000_0000_8000_0000);
result0_o = sat32(s_value0);
result1_o = sat32(s_value1);
end
`APB4_APU__MC_KERNEL_FIXED: begin
s_value0 = s_predictor + s_residual_ext;
overflow_o = (s_value0 > 64'sh0000_0000_7fff_ffff) ||
(s_value0 < -64'sh0000_0000_8000_0000);
result0_o = s_value0[31:0];
end
`APB4_APU__MC_KERNEL_LPC: begin
overflow_o = overflow_o || s_lpc_shift_overflow ||
(s_lpc_value > 73'sh0000_0000_7fff_ffff) ||
(s_lpc_value < -73'sh0000_0000_8000_0000);
result0_o = s_lpc_value[31:0];
end
default: begin
end
endcase
end
endmodule