All files / TRANSPILE/3-Render/codegen/assignment/handlers RegisterUtils.ts

100% Statements 11/11
100% Branches 12/12
100% Functions 2/2
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73                                                                12x           5x     7x 7x   7x 1x     6x 6x   6x   12x                           29x          
/**
 * RegisterUtils
 * Shared utilities for register assignment handlers.
 *
 * Extracted from AccessPatternHandlers.ts and RegisterHandlers.ts to reduce duplication.
 */
import TypeCheckUtils from "../../../../../utils/TypeCheckUtils";
import RegisterAccessMode from "../../../../../utils/RegisterAccessMode";
import type TranspileState from "../../../../TranspileState";
 
/** Result from MMIO optimization attempt */
interface IOptimizationResult {
  success: boolean;
  statement?: string;
}
 
/**
 * Utilities for register access patterns
 */
class RegisterUtils {
  /**
   * Try to generate MMIO-optimized memory access for byte-aligned writes.
   * Returns success: true with statement if optimization applicable, false otherwise.
   */
  static tryGenerateMMIO(
    fullName: string,
    regName: string,
    startConst: number | undefined,
    widthConst: number | undefined,
    value: string,
    state: TranspileState,
  ): IOptimizationResult {
    if (
      startConst === undefined ||
      widthConst === undefined ||
      startConst % 8 !== 0 ||
      !TypeCheckUtils.isStandardWidth(widthConst)
    ) {
      return { success: false };
    }
 
    const baseAddr = state.symbols!.registerBaseAddresses.get(regName);
    const memberOffset = state.symbols!.registerMemberOffsets.get(fullName);
 
    if (baseAddr === undefined || memberOffset === undefined) {
      return { success: false };
    }
 
    const byteOffset = startConst / 8;
    const accessType = `uint${widthConst}_t`;
    const totalOffset =
      byteOffset === 0 ? memberOffset : `${memberOffset} + ${byteOffset}`;
 
    return {
      success: true,
      statement: `*((volatile ${accessType}*)(${baseAddr} + ${totalOffset})) = (${value});`,
    };
  }
  /**
   * Check if register is write-only based on access modifier.
   *
   * Write-only registers include:
   * - 'wo': Write-only
   * - 'w1s': Write-1-to-set
   * - 'w1c': Write-1-to-clear
   */
  static isWriteOnlyRegister(accessMod: string | undefined): boolean {
    return RegisterAccessMode.isWriteOne(accessMod);
  }
}
 
export default RegisterUtils;