blob: c69c731e703144cea31cbba6e62307159827d0f0 [file] [edit]
#!/usr/bin/env python3
# Copyright 2024 Google LLC
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
import abc
class BaseArchitecture:
"""Base architecture for GEMM microkernel generation."""
def __init__(self, m: int, n: int):
"""Initializes the `BaseArchitecture` with the given number of rows and columns."""
self._m = m
self._n = n // self.n_step()
self._c = 1
self.asm_string = ''
@property
def m(self) -> int:
return self._m
@property
def n(self) -> int:
return self._n
@property
def c(self) -> int:
raise NotImplementedError
def labels(self):
return [
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
'eleven',
]
@abc.abstractmethod
def adjust_kc(self) -> None:
"""Returns an assembly string computing the adjusted `kc`."""
raise NotImplementedError
@abc.abstractmethod
def outer_loop_prepare(self) -> None:
"""Returns an assembly string preparing the outer loop."""
raise NotImplementedError
@abc.abstractmethod
def init_accumulators(self) -> None:
"""Returns an assembly string initializing the accumulators."""
raise NotImplementedError
@abc.abstractmethod
def register_bytes(self) -> int:
raise NotImplementedError
@abc.abstractmethod
def isa(self) -> None:
"""Returns a string identifying the ISA of this `BaseArchitecture`."""
raise NotImplementedError
@abc.abstractmethod
def convert_to_output(self) -> None:
"""Returns an assembly string dequantizing the accumulators."""
raise NotImplementedError
@abc.abstractmethod
def store(self) -> None:
"""Returns an assembly string storing the results."""
raise NotImplementedError
@abc.abstractmethod
def astride_register(self):
"""Returns the register containing a_stride."""
raise NotImplementedError
@abc.abstractmethod
def compute_asm(self) -> dict[str, list[str]]:
raise NotImplementedError
@abc.abstractmethod
def input_asm(self) -> dict[str, list[str]]:
raise NotImplementedError
@abc.abstractmethod
def weights_asm(self) -> dict[str, list[str]]:
raise NotImplementedError
@abc.abstractmethod
def w_registers(self) -> list[str]:
raise NotImplementedError
@abc.abstractmethod
def a_registers(self, idx) -> None:
raise NotImplementedError
@abc.abstractmethod
def kc_register(self):
"""Returns the register containing kc, the number of channels (the reduction dimensions)."""
raise NotImplementedError
@abc.abstractmethod
def k_register(self):
"""Returns the register containing k, the current channel being processed."""
raise NotImplementedError
@abc.abstractmethod
def cm_stride_register(self):
"""Returns the register containing cm_stride."""
raise NotImplementedError
@abc.abstractmethod
def am_registers(self):
"""Returns the registers containing the pointers to each row of A (LHS)."""
raise NotImplementedError
@abc.abstractmethod
def a_ptr_register(self):
"""Returns the register containing the A pointer."""
raise NotImplementedError
@abc.abstractmethod
def c_ptr_register(self):
"""Returns the register containing the C pointer."""
raise NotImplementedError
@abc.abstractmethod
def cm_registers(self):
"""Returns the registers containing the pointers to each row of C (Output)."""
raise NotImplementedError
@abc.abstractmethod
def acc_registers(self):
"""Returns the accumulator registers."""
raise NotImplementedError
@abc.abstractmethod
def w_ptr_register(self):
"""Returns the register containing the weight's pointer."""
raise NotImplementedError
@abc.abstractmethod
def min_register(self):
"""Returns the register containing the min value for clamping."""
raise NotImplementedError
@abc.abstractmethod
def max_register(self):
"""Returns the register containing the max value for clamping."""
raise NotImplementedError
@abc.abstractmethod
def nc_register(self):
"""Returns the register containing nc, the number of output rows processed per iteration."""
raise NotImplementedError
@abc.abstractmethod
def mr_register(self):
"""Returns the register containing mr, the number of input rows processed per kernel call."""
raise NotImplementedError
@abc.abstractmethod
def tmp_gp_registers(self):
"""Returns some general purpose registers which may be used for storing temporary data."""
raise NotImplementedError
@abc.abstractmethod
def jump_to_label(self, label):
"""Jump to the given label."""
raise NotImplementedError
@abc.abstractmethod
def function_name(self):
"""Returns the microkernel name."""
raise NotImplementedError
@abc.abstractmethod
def header(self):
"""Returns the assembly header."""
raise NotImplementedError
@abc.abstractmethod
def input_output_register_setup(self):
"""Setup the input (A) and output (C) registers."""
raise NotImplementedError
@abc.abstractmethod
def max_m_before_spilling(self):
"""How large can M be before spilling A and C registers to the stack."""
raise NotImplementedError
@abc.abstractmethod
def read_a_registers(self):
"""Read the A registers from the stack."""
raise NotImplementedError
@abc.abstractmethod
def increment_ptr(self, ptr, step):
"""Increment the given pointer by step bytes."""
raise NotImplementedError
@abc.abstractmethod
def initialize_k_register(self):
"""Initialized the general purpose register for inner loop control."""
raise NotImplementedError
@abc.abstractmethod
def cmp_k_and_jump_if_less(self, label):
"""If k is less than kc, then do another iteration of the inner loop."""
raise NotImplementedError
@abc.abstractmethod
def epilogue(self):
"""Returns the function epilogue."""
raise NotImplementedError
@abc.abstractmethod
def inner_loop(self):
"""Returns the assemebly for the microkernel's inner loop."""
raise NotImplementedError
@abc.abstractmethod
def n_step(self) -> int:
"""Returns the n step for the microkernel's inner loop."""
raise NotImplementedError
@abc.abstractmethod
def prefix(self) -> None:
"""Returns the register name prefix."""
raise NotImplementedError
@abc.abstractmethod
def clamp_min(self, reg: str, prefix: str, other_reg: str):
"""Returns an assembly string computing the minimum clamp."""
raise NotImplementedError
@abc.abstractmethod
def clamp_max(self, reg: str, prefix: str, other_reg: str):
"""Returns an assembly string computing the maximum clamp."""
raise NotImplementedError
def output_n(self) -> int:
return self.n
def clamp(self) -> None:
"""Returns an assembly string computing the minimum/maximum clamp."""
acc_registers = self.acc_registers()
for nr in range(0, self.output_n()):
for mr in range(0, self.m):
self.clamp_min(
reg=acc_registers[self.n * mr + nr], prefix=self.prefix()
)
for nr in range(0, self.output_n()):
for mr in range(0, self.m):
self.clamp_max(
reg=acc_registers[self.n * mr + nr], prefix=self.prefix()
)
def label(self, label_name) -> None:
self.asm_string += f'\n.L{label_name}:\n'
def comment(self, comment_str) -> None:
self.asm_string += f'# {comment_str}\n'
def get_string(self) -> str:
return self.asm_string