dau-core 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dau-core might be problematic. Click here for more details.

dau_core/__init__.py ADDED
@@ -0,0 +1,60 @@
1
+ from .aggregations import EmptyInputError, UnsupportedAggregationError, aggregate_values, synthetic_values
2
+ from .capabilities import DeviceCapabilities, DmaConstraints, OperatorCapability
3
+ from .registers import (
4
+ DAU_MAGIC_WORD,
5
+ DEFAULT_STREAM_JOB_REGISTER_CONTRACT,
6
+ JobControlFlag,
7
+ JobStatusFlag,
8
+ RegisterBlockSnapshot,
9
+ RegisterMapVersion,
10
+ RegisterOffset,
11
+ RegisterWriteError,
12
+ ResetScope,
13
+ StreamJobRegisterContract,
14
+ StreamProtocolVersion,
15
+ )
16
+ from .stream import (
17
+ BatchHeader,
18
+ ColumnDescriptor,
19
+ GroupRole,
20
+ InvalidStreamError,
21
+ LogicalType,
22
+ OperationCode,
23
+ OperationDescriptor,
24
+ PolicyFlag,
25
+ StreamAggregationErrorCode,
26
+ StreamFlag,
27
+ )
28
+
29
+ __version__ = "0.1.0"
30
+
31
+ __all__ = [
32
+ "BatchHeader",
33
+ "ColumnDescriptor",
34
+ "DAU_MAGIC_WORD",
35
+ "DEFAULT_STREAM_JOB_REGISTER_CONTRACT",
36
+ "DeviceCapabilities",
37
+ "DmaConstraints",
38
+ "EmptyInputError",
39
+ "GroupRole",
40
+ "InvalidStreamError",
41
+ "JobControlFlag",
42
+ "JobStatusFlag",
43
+ "LogicalType",
44
+ "OperationCode",
45
+ "OperationDescriptor",
46
+ "OperatorCapability",
47
+ "PolicyFlag",
48
+ "RegisterMapVersion",
49
+ "RegisterBlockSnapshot",
50
+ "RegisterOffset",
51
+ "RegisterWriteError",
52
+ "ResetScope",
53
+ "StreamAggregationErrorCode",
54
+ "StreamFlag",
55
+ "StreamJobRegisterContract",
56
+ "StreamProtocolVersion",
57
+ "UnsupportedAggregationError",
58
+ "aggregate_values",
59
+ "synthetic_values",
60
+ ]
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ from collections.abc import Iterable
5
+
6
+ from .stream import LogicalType, OperationCode
7
+
8
+
9
+ class EmptyInputError(ValueError):
10
+ pass
11
+
12
+
13
+ class UnsupportedAggregationError(ValueError):
14
+ pass
15
+
16
+
17
+ _INTEGER_RANGES = {
18
+ LogicalType.INT8: (-(1 << 7), (1 << 7) - 1),
19
+ LogicalType.INT16: (-(1 << 15), (1 << 15) - 1),
20
+ LogicalType.INT32: (-(1 << 31), (1 << 31) - 1),
21
+ LogicalType.INT64: (-(1 << 63), (1 << 63) - 1),
22
+ LogicalType.UINT8: (0, (1 << 8) - 1),
23
+ LogicalType.UINT16: (0, (1 << 16) - 1),
24
+ LogicalType.UINT32: (0, (1 << 32) - 1),
25
+ LogicalType.UINT64: (0, (1 << 64) - 1),
26
+ }
27
+
28
+ _FLOAT_TYPES = {LogicalType.FLOAT32, LogicalType.FLOAT64}
29
+
30
+
31
+ def aggregate_values(opcode: OperationCode, values: Iterable[int | float | bool], logical_type: LogicalType) -> int | float:
32
+ materialized_values = list(values)
33
+
34
+ if opcode == OperationCode.COUNT:
35
+ return len(materialized_values)
36
+
37
+ if not materialized_values:
38
+ if opcode == OperationCode.SUM:
39
+ return 0.0 if logical_type in _FLOAT_TYPES else 0
40
+ raise EmptyInputError(f"{opcode.name.lower()} requires at least one value")
41
+
42
+ if logical_type in _FLOAT_TYPES and any(_is_nan(value) for value in materialized_values):
43
+ return math.nan
44
+
45
+ if opcode == OperationCode.MIN:
46
+ return min(materialized_values)
47
+ if opcode == OperationCode.MAX:
48
+ return max(materialized_values)
49
+ if opcode == OperationCode.SUM:
50
+ return _sum_values(materialized_values, logical_type)
51
+ if opcode == OperationCode.AVERAGE:
52
+ return float(sum(materialized_values) / len(materialized_values))
53
+
54
+ raise UnsupportedAggregationError(f"unsupported operation {opcode!r}")
55
+
56
+
57
+ def synthetic_values(name: str, logical_type: LogicalType) -> list[int | float | bool]:
58
+ if name == "empty":
59
+ return []
60
+ if name == "one":
61
+ return [1.0] if logical_type in _FLOAT_TYPES else [1]
62
+ if name == "odd_ints":
63
+ return [-3, -1, 0, 1, 3]
64
+ if name == "with_nan":
65
+ if logical_type not in _FLOAT_TYPES:
66
+ raise ValueError("with_nan fixture requires a floating-point logical type")
67
+ return [1.0, math.nan, 3.0]
68
+ if name == "repeated":
69
+ return [2.0, 2.0, 2.0, 2.0] if logical_type in _FLOAT_TYPES else [2, 2, 2, 2]
70
+ if name == "sorted":
71
+ return [1.0, 2.0, 3.0, 4.0] if logical_type in _FLOAT_TYPES else [1, 2, 3, 4]
72
+ if name == "skewed":
73
+ return [0.0, 0.0, 0.0, 99.0] if logical_type in _FLOAT_TYPES else [0, 0, 0, 99]
74
+ if name == "bounds":
75
+ return _bounds_fixture(logical_type)
76
+ raise ValueError(f"unknown synthetic fixture {name!r}")
77
+
78
+
79
+ def _sum_values(values: list[int | float | bool], logical_type: LogicalType) -> int | float:
80
+ total = sum(values)
81
+ if logical_type in _INTEGER_RANGES:
82
+ minimum, maximum = _INTEGER_RANGES[logical_type]
83
+ return min(max(int(total), minimum), maximum)
84
+ if logical_type in _FLOAT_TYPES:
85
+ return float(total)
86
+ raise UnsupportedAggregationError(f"sum does not support {logical_type.name.lower()}")
87
+
88
+
89
+ def _bounds_fixture(logical_type: LogicalType) -> list[int | float | bool]:
90
+ if logical_type in _INTEGER_RANGES:
91
+ minimum, maximum = _INTEGER_RANGES[logical_type]
92
+ return [minimum, 0, maximum]
93
+ if logical_type in _FLOAT_TYPES:
94
+ return [-math.inf, 0.0, math.inf]
95
+ if logical_type == LogicalType.BOOL:
96
+ return [False, True]
97
+ raise ValueError(f"no bounds fixture for {logical_type.name.lower()}")
98
+
99
+
100
+ def _is_nan(value: int | float | bool) -> bool:
101
+ return isinstance(value, float) and math.isnan(value)
@@ -0,0 +1,57 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from .registers import RegisterMapVersion, StreamProtocolVersion
6
+ from .stream import LogicalType, OperationCode
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class DmaConstraints:
11
+ alignment_bytes: int
12
+ descriptor_bytes: int
13
+ max_transfer_bytes: int
14
+ read_channels: int
15
+ write_channels: int
16
+
17
+ def __post_init__(self) -> None:
18
+ if self.alignment_bytes <= 0:
19
+ raise ValueError("alignment_bytes must be positive")
20
+ if self.descriptor_bytes <= 0:
21
+ raise ValueError("descriptor_bytes must be positive")
22
+ if self.max_transfer_bytes <= 0:
23
+ raise ValueError("max_transfer_bytes must be positive")
24
+ if self.read_channels < 0 or self.write_channels < 0:
25
+ raise ValueError("DMA channel counts cannot be negative")
26
+
27
+ def is_aligned(self, value: int) -> bool:
28
+ return value % self.alignment_bytes == 0
29
+
30
+ @property
31
+ def max_aligned_transfer_bytes(self) -> int:
32
+ return self.max_transfer_bytes - (self.max_transfer_bytes % self.alignment_bytes)
33
+
34
+
35
+ @dataclass(frozen=True)
36
+ class OperatorCapability:
37
+ opcode: OperationCode
38
+ input_types: tuple[LogicalType, ...]
39
+ output_type: LogicalType
40
+ supports_group_by: bool
41
+
42
+ def supports(self, opcode: OperationCode, logical_type: LogicalType) -> bool:
43
+ return self.opcode == opcode and logical_type in self.input_types
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class DeviceCapabilities:
48
+ platform_id: str
49
+ pci_vendor_id: int
50
+ pci_device_id: int
51
+ register_map_version: RegisterMapVersion
52
+ stream_protocol_version: StreamProtocolVersion
53
+ dma: DmaConstraints
54
+ operators: tuple[OperatorCapability, ...]
55
+
56
+ def supports(self, opcode: OperationCode, logical_type: LogicalType) -> bool:
57
+ return any(operator.supports(opcode, logical_type) for operator in self.operators)
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from importlib.resources import files
4
+
5
+ DAU_IDENTITY_REGISTERS_SV = files(__package__).joinpath("dau_identity_registers.sv")
6
+ DAU_IDENTITY_AXIL_V = files(__package__).joinpath("dau_identity_axil.v")
7
+ DAU_INT32_AGGREGATION_TILE_SV = files(__package__).joinpath("dau_int32_aggregation_tile.sv")
8
+ DAU_INT32_STREAM_AGGREGATION_SV = files(__package__).joinpath("dau_int32_stream_aggregation.sv")
9
+ DAU_INT32_ARROW_LITE_STREAM_AGGREGATION_SV = files(__package__).joinpath("dau_int32_arrow_lite_stream_aggregation.sv")
10
+
11
+ __all__ = (
12
+ "DAU_IDENTITY_AXIL_V",
13
+ "DAU_IDENTITY_REGISTERS_SV",
14
+ "DAU_INT32_AGGREGATION_TILE_SV",
15
+ "DAU_INT32_ARROW_LITE_STREAM_AGGREGATION_SV",
16
+ "DAU_INT32_STREAM_AGGREGATION_SV",
17
+ )
@@ -0,0 +1,129 @@
1
+ `default_nettype none
2
+
3
+ module dau_identity_axil #(
4
+ parameter [31:0] REGISTER_MAP_VERSION = 32'h0000_0001,
5
+ parameter [31:0] STREAM_PROTOCOL_VERSION = 32'h0000_0001,
6
+ parameter [31:0] PLATFORM_ID = 32'h4554_494e,
7
+ parameter [31:0] SHELL_VERSION = 32'h0000_0000,
8
+ parameter [63:0] BUILD_ID = 64'h0000_0000_0000_0000,
9
+ parameter [31:0] STATUS = 32'h0000_0000,
10
+ parameter [31:0] DMA_CONSTRAINTS = 32'h0000_0000,
11
+ parameter [31:0] OPERATOR_BITMAP = 32'h0000_0000,
12
+ parameter [31:0] LAST_ERROR = 32'h0000_0000,
13
+ parameter [63:0] H2C_BYTES = 64'h0000_0000_0000_0000,
14
+ parameter [63:0] C2H_BYTES = 64'h0000_0000_0000_0000,
15
+ parameter [63:0] ROWS = 64'h0000_0000_0000_0000,
16
+ parameter [31:0] BATCHES = 32'h0000_0000,
17
+ parameter [31:0] STALLS = 32'h0000_0000
18
+ ) (
19
+ (* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 s_axi_aclk CLK" *)
20
+ (* X_INTERFACE_PARAMETER = "ASSOCIATED_BUSIF S_AXI, ASSOCIATED_RESET s_axi_aresetn" *)
21
+ input wire s_axi_aclk,
22
+ (* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 s_axi_aresetn RST" *)
23
+ (* X_INTERFACE_PARAMETER = "POLARITY ACTIVE_LOW" *)
24
+ input wire s_axi_aresetn,
25
+
26
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWADDR" *)
27
+ (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME S_AXI, PROTOCOL AXI4LITE, DATA_WIDTH 32, ADDR_WIDTH 16, HAS_BURST 0, HAS_LOCK 0, HAS_PROT 0, HAS_CACHE 0, HAS_QOS 0, HAS_REGION 0, HAS_WSTRB 1, HAS_BRESP 1, HAS_RRESP 1" *)
28
+ input wire [15:0] s_axi_awaddr,
29
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWVALID" *)
30
+ input wire s_axi_awvalid,
31
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWREADY" *)
32
+ output reg s_axi_awready,
33
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WDATA" *)
34
+ input wire [31:0] s_axi_wdata,
35
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WSTRB" *)
36
+ input wire [3:0] s_axi_wstrb,
37
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WVALID" *)
38
+ input wire s_axi_wvalid,
39
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WREADY" *)
40
+ output reg s_axi_wready,
41
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI BRESP" *)
42
+ output wire [1:0] s_axi_bresp,
43
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI BVALID" *)
44
+ output reg s_axi_bvalid,
45
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI BREADY" *)
46
+ input wire s_axi_bready,
47
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARADDR" *)
48
+ input wire [15:0] s_axi_araddr,
49
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARVALID" *)
50
+ input wire s_axi_arvalid,
51
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARREADY" *)
52
+ output reg s_axi_arready,
53
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RDATA" *)
54
+ output reg [31:0] s_axi_rdata,
55
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RRESP" *)
56
+ output wire [1:0] s_axi_rresp,
57
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RVALID" *)
58
+ output reg s_axi_rvalid,
59
+ (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RREADY" *)
60
+ input wire s_axi_rready,
61
+
62
+ output wire [31:0] reset_request
63
+ );
64
+ wire write_fire;
65
+ wire read_fire;
66
+ wire [15:0] selected_addr;
67
+ wire [15:0] identity_addr;
68
+ wire [31:0] identity_rdata;
69
+
70
+ assign write_fire = !s_axi_bvalid && s_axi_awvalid && s_axi_wvalid;
71
+ assign read_fire = !write_fire && !s_axi_rvalid && s_axi_arvalid;
72
+ assign selected_addr = write_fire ? s_axi_awaddr : s_axi_araddr;
73
+ assign identity_addr = {4'h0, selected_addr[11:0]};
74
+ assign s_axi_bresp = 2'b00;
75
+ assign s_axi_rresp = 2'b00;
76
+
77
+ dau_identity_registers #(
78
+ .REGISTER_MAP_VERSION(REGISTER_MAP_VERSION),
79
+ .STREAM_PROTOCOL_VERSION(STREAM_PROTOCOL_VERSION),
80
+ .PLATFORM_ID(PLATFORM_ID),
81
+ .SHELL_VERSION(SHELL_VERSION),
82
+ .BUILD_ID(BUILD_ID),
83
+ .STATUS(STATUS),
84
+ .DMA_CONSTRAINTS(DMA_CONSTRAINTS),
85
+ .OPERATOR_BITMAP(OPERATOR_BITMAP),
86
+ .LAST_ERROR(LAST_ERROR),
87
+ .H2C_BYTES(H2C_BYTES),
88
+ .C2H_BYTES(C2H_BYTES),
89
+ .ROWS(ROWS),
90
+ .BATCHES(BATCHES),
91
+ .STALLS(STALLS)
92
+ ) identity_registers (
93
+ .addr(identity_addr),
94
+ .wen(write_fire),
95
+ .wdata(s_axi_wdata),
96
+ .reset_request(reset_request),
97
+ .rdata(identity_rdata)
98
+ );
99
+
100
+ always @(posedge s_axi_aclk) begin
101
+ if (!s_axi_aresetn) begin
102
+ s_axi_awready <= 1'b0;
103
+ s_axi_wready <= 1'b0;
104
+ s_axi_bvalid <= 1'b0;
105
+ s_axi_arready <= 1'b0;
106
+ s_axi_rdata <= 32'h0000_0000;
107
+ s_axi_rvalid <= 1'b0;
108
+ end else begin
109
+ s_axi_awready <= write_fire;
110
+ s_axi_wready <= write_fire;
111
+ s_axi_arready <= read_fire;
112
+
113
+ if (write_fire) begin
114
+ s_axi_bvalid <= 1'b1;
115
+ end else if (s_axi_bvalid && s_axi_bready) begin
116
+ s_axi_bvalid <= 1'b0;
117
+ end
118
+
119
+ if (read_fire) begin
120
+ s_axi_rdata <= identity_rdata;
121
+ s_axi_rvalid <= 1'b1;
122
+ end else if (s_axi_rvalid && s_axi_rready) begin
123
+ s_axi_rvalid <= 1'b0;
124
+ end
125
+ end
126
+ end
127
+ endmodule
128
+
129
+ `default_nettype wire
@@ -0,0 +1,51 @@
1
+ `default_nettype none
2
+
3
+ module dau_identity_registers #(
4
+ parameter logic [31:0] REGISTER_MAP_VERSION = 32'h0000_0001,
5
+ parameter logic [31:0] STREAM_PROTOCOL_VERSION = 32'h0000_0001,
6
+ parameter logic [31:0] PLATFORM_ID = 32'h4554_494e,
7
+ parameter logic [31:0] SHELL_VERSION = 32'h0000_0000,
8
+ parameter logic [63:0] BUILD_ID = 64'h0000_0000_0000_0000,
9
+ parameter logic [31:0] STATUS = 32'h0000_0000,
10
+ parameter logic [31:0] DMA_CONSTRAINTS = 32'h0000_0000,
11
+ parameter logic [31:0] OPERATOR_BITMAP = 32'h0000_0000,
12
+ parameter logic [31:0] LAST_ERROR = 32'h0000_0000,
13
+ parameter logic [63:0] H2C_BYTES = 64'h0000_0000_0000_0000,
14
+ parameter logic [63:0] C2H_BYTES = 64'h0000_0000_0000_0000,
15
+ parameter logic [63:0] ROWS = 64'h0000_0000_0000_0000,
16
+ parameter logic [31:0] BATCHES = 32'h0000_0000,
17
+ parameter logic [31:0] STALLS = 32'h0000_0000
18
+ ) (
19
+ input wire logic [15:0] addr,
20
+ input wire logic wen,
21
+ input wire logic [31:0] wdata,
22
+ output logic [31:0] reset_request,
23
+ output logic [31:0] rdata
24
+ );
25
+ assign reset_request = (wen && (addr == 16'h0020)) ? wdata : 32'h0000_0000;
26
+
27
+ assign rdata =
28
+ (addr == 16'h0000) ? 32'h4441_5531 :
29
+ (addr == 16'h0004) ? REGISTER_MAP_VERSION :
30
+ (addr == 16'h0008) ? STREAM_PROTOCOL_VERSION :
31
+ (addr == 16'h000c) ? PLATFORM_ID :
32
+ (addr == 16'h0010) ? SHELL_VERSION :
33
+ (addr == 16'h0014) ? BUILD_ID[31:0] :
34
+ (addr == 16'h0018) ? BUILD_ID[63:32] :
35
+ (addr == 16'h001c) ? STATUS :
36
+ (addr == 16'h0020) ? 32'h0000_0000 :
37
+ (addr == 16'h0024) ? DMA_CONSTRAINTS :
38
+ (addr == 16'h0028) ? OPERATOR_BITMAP :
39
+ (addr == 16'h002c) ? LAST_ERROR :
40
+ (addr == 16'h0030) ? H2C_BYTES[31:0] :
41
+ (addr == 16'h0034) ? H2C_BYTES[63:32] :
42
+ (addr == 16'h0038) ? C2H_BYTES[31:0] :
43
+ (addr == 16'h003c) ? C2H_BYTES[63:32] :
44
+ (addr == 16'h0040) ? ROWS[31:0] :
45
+ (addr == 16'h0044) ? ROWS[63:32] :
46
+ (addr == 16'h0048) ? BATCHES :
47
+ (addr == 16'h004c) ? STALLS :
48
+ 32'hffff_ffff;
49
+ endmodule
50
+
51
+ `default_nettype wire
@@ -0,0 +1,90 @@
1
+ `default_nettype none
2
+
3
+ module dau_int32_aggregation_tile (
4
+ input wire logic clk,
5
+ input wire logic rst,
6
+ input wire logic input_valid,
7
+ output logic input_ready,
8
+ input wire logic input_last,
9
+ input wire logic signed [31:0] input_value,
10
+ input wire logic [2:0] input_opcode,
11
+ output logic result_valid,
12
+ input wire logic result_ready,
13
+ output logic signed [63:0] result_value,
14
+ output logic error
15
+ );
16
+ localparam logic [2:0] OP_MIN = 3'd1;
17
+ localparam logic [2:0] OP_MAX = 3'd2;
18
+ localparam logic [2:0] OP_SUM = 3'd3;
19
+ localparam logic [2:0] OP_COUNT = 3'd4;
20
+
21
+ logic signed [63:0] accumulator;
22
+ logic signed [63:0] sample_value;
23
+ logic signed [63:0] next_accumulator;
24
+ logic [63:0] sample_count;
25
+ logic [63:0] next_sample_count;
26
+
27
+ assign input_ready = !result_valid;
28
+ assign sample_value = {{32{input_value[31]}}, input_value};
29
+ assign next_sample_count = sample_count + 64'd1;
30
+
31
+ always_comb begin
32
+ unique case (input_opcode)
33
+ OP_MIN: begin
34
+ next_accumulator = (sample_count == 64'd0) ? sample_value : ((sample_value < accumulator) ? sample_value : accumulator);
35
+ end
36
+ OP_MAX: begin
37
+ next_accumulator = (sample_count == 64'd0) ? sample_value : ((sample_value > accumulator) ? sample_value : accumulator);
38
+ end
39
+ OP_SUM: begin
40
+ next_accumulator = (sample_count == 64'd0) ? sample_value : (accumulator + sample_value);
41
+ end
42
+ OP_COUNT: begin
43
+ next_accumulator = $signed(next_sample_count);
44
+ end
45
+ default: begin
46
+ next_accumulator = 64'sd0;
47
+ end
48
+ endcase
49
+ end
50
+
51
+ always_ff @(posedge clk) begin
52
+ if (rst) begin
53
+ accumulator <= 64'sd0;
54
+ sample_count <= 64'd0;
55
+ result_valid <= 1'b0;
56
+ result_value <= 64'sd0;
57
+ error <= 1'b0;
58
+ end else if (result_valid) begin
59
+ if (result_ready) begin
60
+ result_valid <= 1'b0;
61
+ error <= 1'b0;
62
+ end
63
+ end else if (input_valid && input_ready) begin
64
+ unique case (input_opcode)
65
+ OP_MIN, OP_MAX, OP_SUM, OP_COUNT: begin
66
+ error <= 1'b0;
67
+ if (input_last) begin
68
+ accumulator <= 64'sd0;
69
+ sample_count <= 64'd0;
70
+ result_value <= next_accumulator;
71
+ result_valid <= 1'b1;
72
+ end else begin
73
+ accumulator <= next_accumulator;
74
+ sample_count <= next_sample_count;
75
+ result_valid <= 1'b0;
76
+ end
77
+ end
78
+ default: begin
79
+ accumulator <= 64'sd0;
80
+ sample_count <= 64'd0;
81
+ result_value <= 64'sd0;
82
+ result_valid <= 1'b1;
83
+ error <= 1'b1;
84
+ end
85
+ endcase
86
+ end
87
+ end
88
+ endmodule
89
+
90
+ `default_nettype wire