Source code for hwtLib.xilinx.primitive.dsp48e1_constants

from enum import Enum
from pyMathBitPrecise.bit_utils import set_bit_range

# deassign_xyz_mux;
ARITHMETIC_MODES_DRC_deassign_xyz_mux = [
    # 0bxxx0101010
    * [set_bit_range(0b0000101010, 7, 3, i) for i in range(8)],
    0b0000000000,
    0b0000011000,
    0b0000011010,
    0b0000101000,
    0b0001000000,
    0b0001011000,
    0b0001011010,
    0b0001100000,
    0b0001100010,
    0b0001111000,
    0b0001111010,
    0b0010000000,
    0b0010011000,
    0b0010011001,
    0b0010011011,
    0b0010101000,
    0b0010101001,
    0b0010101011,
    0b0010101110,
    0b0011000000,
    0b0011011000,
    0b0011011001,
    0b0011011011,
    0b0011100000,
    0b0011100001,
    0b0011100011,
    0b0011100100,
    0b0011111000,
    0b0011111001,
    0b0011111011,
    0b0110000000,
    0b0110000010,
    0b0110011000,
    0b0110011010,
    0b0110101000,
    0b0110101110,
    0b0111000000,
    0b0111000010,
    0b0111011000,
    0b0111100000,
    0b0111100010,
    0b0111111000,
    0b1010000000,
    0b1010011000,
    0b1010011001,
    0b1010011011,
    0b1010101000,
    0b1010101001,
    0b1010101011,
    0b1010101110,
    0b1011000000,
    0b1011011000,
    0b1011011001,
    0b1011011011,
    0b1011100000,
    0b1011100001,
    0b1011100011,
    0b1011111000,
    0b1011111001,
    0b1011111011,
]

# if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
ARITHMETIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1 = [
    0b0000010000,
    0b0000010010,
    0b0000011100,
    0b0001010000,
    0b0001010010,
    0b0001011100,
    0b0001100100,
    0b0001110000,
    0b0001110010,
    0b0001110101,
    0b0001110111,
    0b0001111100,
    0b0010010000,
    0b0010010101,
    0b0010010111,
    0b0011010000,
    0b0011010101,
    0b0011010111,
    0b0011110000,
    0b0011110101,
    0b0011110111,
    0b0011110001,
    0b0011110011,
    0b0100000000,
    0b0100000010,
    0b0100010000,
    0b0100010010,
    0b0100011000,
    0b0100011010,
    0b0100011101,
    0b0100011111,
    0b0100101000,
    0b0100101101,
    0b0100101111,
    0b0101000000,
    0b0101000010,
    0b0101010000,
    0b0101011000,
    0b0101011101,
    0b0101011111,
    0b0101100000,
    0b0101100010,
    0b0101100101,
    0b0101100111,
    0b0101110000,
    0b0101110101,
    0b0101110111,
    0b0101111000,
    0b0101111101,
    0b0101111111,
    0b0110000100,
    0b0110010000,
    0b0110010010,
    0b0110010101,
    0b0110010111,
    0b0110011100,
    0b0111000100,
    0b0111010000,
    0b0111010101,
    0b0111010111,
    0b0111110000,
    0b1001000010,
    0b1010010000,
    0b1010010101,
    0b1010010111,
    0b1011010000,
    0b1011010101,
    0b1011010111,
    0b1011110000,
    0b1011110101,
    0b1011110111,
    0b1011110001,
    0b1011110011,
    0b1100000000,
    0b1100010000,
    0b1100011000,
    0b1100011101,
    0b1100011111,
    0b1100101000,
    0b1100101101,
    0b1100101111,
    0b1101000000,
    0b1101010000,
    0b1101011000,
    0b1101011101,
    0b1101011111,
    0b1101100000,
    0b1101100101,
    0b1101100111,
    0b1101110000,
    0b1101110101,
    0b1101110111,
    0b1101111000,
    0b1101111101,
    0b1101111111,
]

LOGIC_MODES_DRC_deassign_xyz_mux = [
    0b0000000,
    0b0000011,
    0b0010000,
    0b0010011,
    0b0110000,
    0b0110011,
    0b1010000,
    0b1010011,
    0b0001000,
    0b0001011,
    0b0011000,
    0b0011011,
    0b0111000,
    0b0111011,
    0b1011000,
    0b1011011,
]
LOGIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1 = [
    0b0000010,
    0b0010010,
    0b0100000,
    0b0100010,
    0b0100011,
    0b0110010,
    0b1010010,
    0b1100000,
    0b1100010,
    0b1100011,
    0b0001010,
    0b0011010,
    0b0101000,
    0b0101010,
    0b0101011,
    0b0111010,
    0b1011010,
    0b1101000,
    0b1101010,
    0b1101011,
]


[docs]class X_SEL(Enum): ZERO = 0b000_00_00 M = 0b000_01_01 P = 0b000_00_10 # Must select with PREG = 1 A_B = 0b000_00_11 # 48 bits wide
[docs]class Y_SEL(Enum): ZERO = 0b000_00_00 M = 0b000_01_01 # Used mainly for logic unit # bitwise operations on the X and # Z multiplexers MINUS_1 = 0b000_10_00 C = 0b000_11_00
[docs]class Z_SEL(Enum): ZERO = 0b000_00_00 PCIN = 0b001_00_00 P = 0b010_00_00 # Must select with PREG = 1 C = 0b011_00_00 P_MACC = 0b100_10_00 # Use for MACC extend only. Must select with PREG = 1 PCIN_SHIFT_17b = 0b101_00_00 P_SHIFT_17b = 0b110_00_00 # Must select with PREG = 1
[docs]def get_opmode(x: X_SEL, y: Y_SEL, z: Z_SEL): if x == X_SEL.M: assert y == Y_SEL.M elif y == Y_SEL.M: assert x == X_SEL.M if z == Z_SEL.P_MACC: assert x == X_SEL.ZERO assert y == Y_SEL.MINUS_1 return (z.value | y.value | x.value)
ALU_MODE = { "Z + X + Y + CIN": 0b0000, "Z - (X + Y + CIN)": 0b0011, # In two’s complement: -Z = ~Z + 1 "-Z + (X + Y + CIN) - 1": 0b0001, "-Z - X - Y - CIN - 1": 0b0010, "X ^ Z": (Y_SEL.ZERO, 0b0100), "~(X ^ Z)": (Y_SEL.ZERO, 0b0101), # xnor "X & Z": (Y_SEL.ZERO, 0b1100), "X & ~Z": (Y_SEL.ZERO, 0b1101), "~(X & Z)": (Y_SEL.ZERO, 0b1110), "~X | Z": (Y_SEL.ZERO, 0b1111), "X | Z": (Y_SEL.MINUS_1, 0b1100), "X | ~Z": (Y_SEL.MINUS_1, 0b1101), "~(X | Z)": (Y_SEL.MINUS_1, 0b1110), # nor "~X & Z": (Y_SEL.MINUS_1, 0b1111) }
[docs]class CARRYIN_SEL(Enum): CARRYIN = 0b000 # General interconnect PCIN_47_n = 0b001 # Rounding PCIN (round towards infinity) CARRYCASCIN = 0b010 # Larger add/sub/acc (parallel operation) PCIN_47 = 0b011 # Rounding PCIN (round towards zero) # For larger add/sub/acc (sequential # operation via internal feedback). Must select # with PREG = 1 CARRYCASCOUT = 0b100 P_47_n = 0b101 # Rounding P (round towards infinity). Must select with PREG = 1 A_27_eq_B_17 = 0b110 # Rounding A x B P_47 = 0b111 # For rounding P (round towards zero). Must select with PREG = 1
[docs]class MUL_A_SEL(Enum): ( A2, A1, ZERO, D_PLUS_A2, D_PLUS_A1, D, MINUS_A2, MINUS_A1, D_MINUS_A2, D_MINUS_A1 ) = range(10)
[docs]class MUL_B_SEL(Enum): B2 = 0 B1 = 1
_inmode_with_not_use_dport = { MUL_A_SEL.A2: 0b0000, MUL_A_SEL.A1: 0b0001, MUL_A_SEL.ZERO: 0b0010, } _inmode_with_use_dport = { **_inmode_with_not_use_dport, MUL_A_SEL.D_PLUS_A2: 0b0100, MUL_A_SEL.D_PLUS_A1: 0b0101, MUL_A_SEL.D: 0b0110, MUL_A_SEL.MINUS_A2: 0b1000, MUL_A_SEL.MINUS_A1: 0b1001, MUL_A_SEL.D_MINUS_A2: 0b1100, MUL_A_SEL.D_MINUS_A1: 0b1101, }
[docs]def get_inmode(AREG: int, USE_DPORT: bool, mul_a_sel: MUL_A_SEL, mul_b_sel: MUL_B_SEL): assert AREG in [0, 1, 2], AREG if USE_DPORT: v = _inmode_with_not_use_dport[mul_a_sel] else: v = _inmode_with_use_dport[mul_a_sel] return (mul_b_sel.value << 3 | v)