class XilinxPart():
    """
    Xilinx FPGA model name specification
    """

    class Package():
        cflva2104 = 'cflva2104'
        cflvb2104 = 'cflvb2104'
        cflvc2104 = 'cflvc2104'
        cl400 = 'cl400'
        cl484 = 'cl484'
        clg225 = 'clg225'
        clg400 = 'clg400'
        clg484 = 'clg484'
        clg485 = 'clg485'
        cna1509 = 'cna1509'
        cpg236 = 'cpg236'
        cpg238 = 'cpg238'
        cpga196 = 'cpga196'
        cs324 = 'cs324'
        cs325 = 'cs325'
        csg324 = 'csg324'
        csg325 = 'csg325'
        csga225 = 'csga225'
        csga324 = 'csga324'
        fbg484 = 'fbg484'
        fbg676 = 'fbg676'
        fbg900 = 'fbg900'
        fbv484 = 'fbv484'
        fbv676 = 'fbv676'
        fbv900 = 'fbv900'
        fbva676 = 'fbva676'
        fbva900 = 'fbva900'
        fbvb900 = 'fbvb900'
        ffg1156 = 'ffg1156'
        ffg1157 = 'ffg1157'
        ffg1158 = 'ffg1158'
        ffg1761 = 'ffg1761'
        ffg1926 = 'ffg1926'
        ffg1927 = 'ffg1927'
        ffg1928 = 'ffg1928'
        ffg1930 = 'ffg1930'
        ffg676 = 'ffg676'
        ffg900 = 'ffg900'
        ffg901 = 'ffg901'
        ffv1156 = 'ffv1156'
        ffv1157 = 'ffv1157'
        ffv1158 = 'ffv1158'
        ffv1761 = 'ffv1761'
        ffv1927 = 'ffv1927'
        ffv676 = 'ffv676'
        ffv900 = 'ffv900'
        ffv901 = 'ffv901'
        ffva1156 = 'ffva1156'
        ffva1517 = 'ffva1517'
        ffva1760 = 'ffva1760'
        ffva2104 = 'ffva2104'
        ffva676 = 'ffva676'
        ffvb1156 = 'ffvb1156'
        ffvb1517 = 'ffvb1517'
        ffvb1760 = 'ffvb1760'
        ffvb2104 = 'ffvb2104'
        ffvb676 = 'ffvb676'
        ffvc1156 = 'ffvc1156'
        ffvc1517 = 'ffvc1517'
        ffvc1760 = 'ffvc1760'
        ffvc2104 = 'ffvc2104'
        ffvc900 = 'ffvc900'
        ffvd1156 = 'ffvd1156'
        ffvd1517 = 'ffvd1517'
        ffvd1760 = 'ffvd1760'
        ffvd900 = 'ffvd900'
        ffve1156 = 'ffve1156'
        ffve1517 = 'ffve1517'
        ffve1760 = 'ffve1760'
        ffve1924 = 'ffve1924'
        ffve900 = 'ffve900'
        ffvf1517 = 'ffvf1517'
        ffvf1760 = 'ffvf1760'
        ffvg1517 = 'ffvg1517'
        ffvh1760 = 'ffvh1760'
        fg484 = 'fg484'
        fgg484 = 'fgg484'
        fgg676 = 'fgg676'
        fgga484 = 'fgga484'
        fgga676 = 'fgga676'
        fhg1761 = 'fhg1761'
        fhga2104 = 'fhga2104'
        fhgb2104 = 'fhgb2104'
        fhgc2104 = 'fhgc2104'
        figd2104 = 'figd2104'
        flg1155 = 'flg1155'
        flg1925 = 'flg1925'
        flg1926 = 'flg1926'
        flg1928 = 'flg1928'
        flg1930 = 'flg1930'
        flg1931 = 'flg1931'
        flg1932 = 'flg1932'
        flga2104 = 'flga2104'
        flga2577 = 'flga2577'
        flga2892 = 'flga2892'
        flgb2104 = 'flgb2104'
        flgb2377 = 'flgb2377'
        flgc2104 = 'flgc2104'
        flgf1924 = 'flgf1924'
        flva1517 = 'flva1517'
        flva2104 = 'flva2104'
        flvb1760 = 'flvb1760'
        flvb2104 = 'flvb2104'
        flvc2104 = 'flvc2104'
        flvd1517 = 'flvd1517'
        flvd1924 = 'flvd1924'
        flvf1924 = 'flvf1924'
        fsga2577 = 'fsga2577'
        fsgd2104 = 'fsgd2104'
        fsva3824 = 'fsva3824'
        fsvb3824 = 'fsvb3824'
        fsve1156 = 'fsve1156'
        fsvf1760 = 'fsvf1760'
        fsvg1517 = 'fsvg1517'
        fsvh1760 = 'fsvh1760'
        fsvh1924 = 'fsvh1924'
        fsvh2104 = 'fsvh2104'
        fsvh2892 = 'fsvh2892'
        ftg256 = 'ftg256'
        ftgb196 = 'ftgb196'
        hcg1155 = 'hcg1155'
        hcg1931 = 'hcg1931'
        hcg1932 = 'hcg1932'
        rb484 = 'rb484'
        rb676 = 'rb676'
        rf1156 = 'rf1156'
        rf1157 = 'rf1157'
        rf1158 = 'rf1158'
        rf1761 = 'rf1761'
        rf1930 = 'rf1930'
        rf676 = 'rf676'
        rf900 = 'rf900'
        rs484 = 'rs484'
        sbg484 = 'sbg484'
        sbg485 = 'sbg485'
        sbv484 = 'sbv484'
        sbv485 = 'sbv485'
        sbva484 = 'sbva484'
        sfva625 = 'sfva625'
        sfva784 = 'sfva784'
        sfvb784 = 'sfvb784'
        sfvc784 = 'sfvc784'
        vsva1365 = 'vsva1365'

    class Size():
        _007s = '007s'
        _010 = '010'
        _010i = '010i'
        _012s = '012s'
        _014s = '014s'
        _015 = '015'
        _015i = '015i'
        _020 = '020'
        _020i = '020i'
        _025 = '025'
        _030 = '030'
        _030i = '030i'
        _035 = '035'
        _035i = '035i'
        _040 = '040'
        _045 = '045'
        _045i = '045i'
        _060 = '060'
        _065 = '065'
        _080 = '080'
        _085 = '085'
        _095 = '095'
        _100 = '100'
        _100i = '100i'
        _100t = '100t'
        _100ti = '100ti'
        _100tl = '100tl'
        _115 = '115'
        _11eg = '11eg'
        _11p = '11p'
        _125 = '125'
        _12t = '12t'
        _13p = '13p'
        _15 = '15'
        _15eg = '15eg'
        _15p = '15p'
        _15t = '15t'
        _15ti = '15ti'
        _15tl = '15tl'
        _160 = '160'
        _160t = '160t'
        _160tl = '160tl'
        _17eg = '17eg'
        _190 = '190'
        _19eg = '19eg'
        _19p = '19p'
        _2000t = '2000t'
        _200t = '200t'
        _200ti = '200ti'
        _200tl = '200tl'
        _21dr = '21dr'
        _23p = '23p'
        _25 = '25'
        _25dr = '25dr'
        _25t = '25t'
        _27dr = '27dr'
        _27p = '27p'
        _28dr = '28dr'
        _29dr = '29dr'
        _29p = '29p'
        _2cg = '2cg'
        _2eg = '2eg'
        _31p = '31p'
        _325t = '325t'
        _325tl = '325tl'
        _33p = '33p'
        _355t = '355t'
        _355tl = '355tl'
        _35p = '35p'
        _35t = '35t'
        _35ti = '35ti'
        _35tl = '35tl'
        _37p = '37p'
        _39dr = '39dr'
        _3cg = '3cg'
        _3eg = '3eg'
        _3p = '3p'
        _410t = '410t'
        _410tl = '410tl'
        _420t = '420t'
        _420tl = '420tl'
        _43dr = '43dr'
        _440 = '440'
        _45p = '45p'
        _46dr = '46dr'
        _47dr = '47dr'
        _47p = '47p'
        _480t = '480t'
        _480tl = '480tl'
        _48dr = '48dr'
        _49dr = '49dr'
        _4cg = '4cg'
        _4eg = '4eg'
        _4ev = '4ev'
        _50 = '50'
        _50t = '50t'
        _50ti = '50ti'
        _50tl = '50tl'
        _585t = '585t'
        _58dr = '58dr'
        _59dr = '59dr'
        _5cg = '5cg'
        _5eg = '5eg'
        _5ev = '5ev'
        _5p = '5p'
        _6 = '6'
        _6cg = '6cg'
        _6eg = '6eg'
        _70t = '70t'
        _70tl = '70tl'
        _75 = '75'
        _75t = '75t'
        _75ti = '75ti'
        _75tl = '75tl'
        _7cg = '7cg'
        _7eg = '7eg'
        _7ev = '7ev'
        _7p = '7p'
        _9cg = '9cg'
        _9eg = '9eg'
        _9p = '9p'
        h580t = 'h580t'
        h870t = 'h870t'
        u060 = 'u060'
        x1140t = 'x1140t'
        x330t = 'x330t'
        x415t = 'x415t'
        x485t = 'x485t'
        x550t = 'x550t'
        x690t = 'x690t'
        x980t = 'x980t'

    class Family():
        atrix7 = '7a'
        kintex7 = '7k'
        virtex7 = '7v'
        zynq7000 = '7z'
        spartan7 = '7s'
        zynqUltrascale = 'zu'
        kintexUltrascale = 'ku'
        virtexUltrascale = "vu"
        rtKintexUltrascale = "rk"
        virtexuplus = "u2"
        # versal = 'vc'
        # versal = 'vm'

    class Speedgrade():
        _1 = "-1"
        _1H = "-1H"
        _1HV = "-1HV"
        _1I = "-1I"
        _1IL = "-1IL"
        _1L = "-1L"
        _1LV = "-1LV"
        _1M = "-1M"
        _1ML = "-1ML"
        _1Q = "-1Q"
        _1QL = "-1QL"
        _2 = "-2"
        _2G = "-2G"
        _2I = "-2I"
        _2IL = "-2IL"
        _2L = "-2L"
        _2LV = "-2LV"
        _2LVI = "-2LVI"
        _3 = "-3"

    class Grade():
        AUTOMOTIVE = "a"
        CUSTOMMER = "c"
        DEFENSE_AND_SPACE = "q"

    def __init__(self, family, size, package, speedgrade, grade="c"):
        self.family = family
        self.size = size
        self.package = package
        self.speedgrade = speedgrade
        self.grade = grade

    def as_tuple(self):
        return (
            self.family,
            self.size,
            self.package,
            self.speedgrade,
            self.grade,
        )

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.as_tuple() == other.as_tuple()

    def __hash__(self):
        return hash(self.as_tuple())

    def name(self):
        return "x" + self.grade + self.family + self.size + self.package + self.speedgrade

    def __repr__(self):
        return f"<{self.__class__.__name__:s} {self.grade:s} {self.family:s} {self.size:s} {self.package} {self.speedgrade:s}>"
