Ejemplo n.º 1
0
 def _eq(self, other: Union["StructIntf", StructValBase]):
     if isinstance(other, self.__class__):
         assert self._dtype == other._dtype
         return And(
             *(si._eq(oi)
               for si, oi in zip(self._interfaces, other._interfaces)))
     else:
         return And(*(si._eq(getattr(other, si._name))
                      for si in self._interfaces))
Ejemplo n.º 2
0
    def get_lru(self):
        """
        To find LRU, we can perform a depth-first-search starting from root,
        and traverse nodes in lower levels. If the node is 0, then we traverse the left sub-tree;
        otherwise, we traverse the right sub-tree. In the diagram above, the LRU is set 3.
        """
        # node_index: bits  rlu register
        node_paths = {}
        self._build_node_paths(node_paths, 0, tuple())
        # also number of levels of rlu tree
        bin_index_w = log2ceil(
            self.lru_reg_items(self.lru_regs._dtype.bit_length()))

        lru_index_bin = []
        # msb first in lru binary index
        for output_bit_i in range(bin_index_w):
            items_on_current_level = int(2**output_bit_i)
            current_level_offset = 2**output_bit_i - 1
            possible_paths = []
            for node_i in range(current_level_offset,
                                current_level_offset + items_on_current_level):
                p = node_paths[node_i]
                possible_paths.append(And(*p))
            lru_index_bin.append(Or(*possible_paths))

        # MSB was first so the result is in little endian MSB..LSB
        return Concat(*lru_index_bin)
Ejemplo n.º 3
0
 def stashLoad(self, isIdle, stash, lookupOrigin_out):
     lookup = self.lookup
     insert = self.insert
     delete = self.delete
     If(isIdle,
         If(self.clean.vld,
            stash.vldFlag(0)
            ).Elif(delete.vld,
                   stash.key(delete.key),
                   lookupOrigin_out(ORIGIN_TYPE.DELETE),
                   stash.vldFlag(0),
                   ).Elif(insert.vld,
                          lookupOrigin_out(ORIGIN_TYPE.INSERT),
                          stash.key(insert.key),
                          stash.data(insert.data),
                          stash.vldFlag(1),
                          ).Elif(lookup.vld,
                                 lookupOrigin_out(ORIGIN_TYPE.LOOKUP),
                                 stash.key(lookup.key),
                                 )
        )
     priority = [self.clean, self.delete, self.insert, lookup]
     for i, intf in enumerate(priority):
         withLowerPrio = priority[:i]
         intf.rd(And(isIdle, *map(lambda x:~x.vld, withLowerPrio)))
Ejemplo n.º 4
0
    def ack(self):
        """
        :return: expression which's value is high when transaction can be made over interfaces
        """
        # every interface has to have skip flag or it has to be ready/valid
        # and extraCond has to be True if present
        acks = []
        for m in self.masters:
            extra, skip = self.getExtraAndSkip(m)
            if isinstance(m, ExclusiveStreamGroups):
                a = m.ack()
            else:
                a = _get_valid_signal(m)

            if extra:
                a = And(a, *extra)

            if skip is not None:
                a = Or(a, skip)

            acks.append(a)

        for s in self.slaves:
            extra, skip = self.getExtraAndSkip(s)
            if isinstance(s, ExclusiveStreamGroups):
                a = s.ack()
            else:
                a = _get_ready_signal(s)

            if extra:
                a = And(a, *extra)

            if skip is not None:
                a = Or(a, skip)

            acks.append(a)

        if not acks:
            return True

        return And(*acks)
Ejemplo n.º 5
0
    def state_trans_cond(self, sst: StateTransItem, input_regs):
        cond = []
        assert len(sst.input) == len(input_regs)
        for in_metas, in_regs in zip(sst.input, input_regs):
            assert len(in_metas) == len(in_regs)
            for in_meta, in_reg in zip(in_metas, in_regs):
                for k_i, k in enumerate(in_meta.keep):
                    self.add_cond_bit(cond, in_reg.keep[k_i], k)
                self.add_cond_bit(cond, in_reg.relict, in_meta.relict)
                self.add_cond_bit(cond, in_reg.last, in_meta.last)

        return And(*cond)
Ejemplo n.º 6
0
    def renderEventDepIfContainer(self, ifStm: IfContainer, s: RtlSignalBase,
                                  connectOut):
        assert not ifStm.ifFalse, ifStm
        if ifStm.elIfs:
            raise NotImplementedError(MUX)

        subStms = list(walkStatementsForSig(ifStm.ifTrue, s))
        assert len(subStms) == 1, subStms
        subStm = subStms[0]

        assig = None
        clk_spec = [
            ifStm.cond,
        ]
        subStm_tmp = subStm
        while True:
            if isinstance(subStm_tmp, IfContainer):
                clk_spec.append(subStm.cond)
                subStm_tmp = list(walkStatementsForSig(subStm_tmp.ifTrue, s))
                if len(subStm_tmp) > 1:
                    raise NotImplementedError("Probably write with the mask",
                                              subStm_tmp)

                subStm_tmp = subStm_tmp[0]
                continue

            elif isinstance(subStm_tmp, HdlAssignmentContainer):
                if subStm_tmp.indexes:
                    assig = subStm_tmp
                    break

            break

        if assig is None:
            _, _in = self.renderForSignal(subStm, s, False)
            return self.createFFNode(s, ifStm.cond, _in, connectOut)

        if len(assig.indexes) != 1:
            raise NotImplementedError()

        addr = assig.indexes[0]
        # ram write port
        # collect clk and clk_en

        if len(clk_spec) > 1:
            clk = clk_spec[0]
            w_en = And(*clk_spec[1:])
        else:
            clk = clk_spec[0]
            w_en = None
        return self.createRamWriteNode(assig.dst, clk, addr, assig.src, w_en,
                                       connectOut)
Ejemplo n.º 7
0
    def _impl(self):
        rd = self.getRd
        vld = self.getVld
        data = self.getData

        for io in self.dataOut:
            for i, o in zip(data(self.dataIn), data(io)):
                o(i)

        outRd = And(*[rd(i) for i in self.dataOut])
        rd(self.dataIn)(outRd)

        for o in self.dataOut:
            # everyone else is ready and input is valid
            deps = [vld(self.dataIn)]
            for otherO in self.dataOut:
                if otherO is o:
                    continue
                deps.append(rd(otherO))
            _vld = And(*deps)

            vld(o)(_vld)
Ejemplo n.º 8
0
    def ackForMaster(self, master):
        """
        :return: driver of ready signal for master
        """
        otherMasters = where(self.masters, lambda x: x is not master)
        extra, skip = self.getExtraAndSkip(master)

        conds = [*map(self.vld, otherMasters),
                 *map(self.rd, self.slaves),
                 *extra]
        if conds:
            r = And(*conds)
        else:
            r = BIT.from_py(1)

        if skip is not None:
            r = r & ~skip

        return r
Ejemplo n.º 9
0
    def ackForSlave(self, slave):
        """
        :return: driver of valid signal for slave
        """
        otherSlaves = where(self.slaves, lambda x: x is not slave)
        extra, skip = self.getExtraAndSkip(slave)

        conds = [*map(self.vld, self.masters),
                 *map(self.rd, otherSlaves),
                 *extra]
        if conds:
            v = And(*conds)
        else:
            v = BIT.from_py(1)

        if skip is not None:
            v = v & ~skip

        return v
Ejemplo n.º 10
0
    def _impl(self):
        rd = self.get_ready_signal
        vld = self.get_valid_signal
        dout = self.dataOut

        vldSignals = [vld(d) for d in self.dataIn]

        # data out mux
        dataCases = []
        for i, din in enumerate(self.dataIn):
            allLowerPriorNotReady = map(lambda x: ~x, vldSignals[:i])
            rd(din)(And(rd(dout), *allLowerPriorNotReady))

            cond = vld(din)
            dataConnectExpr = self.dataConnectionExpr(din, dout)
            dataCases.append((cond, dataConnectExpr))

        dataDefault = self.dataConnectionExpr(None, dout)
        SwitchLogic(dataCases, dataDefault)

        vld(dout)(Or(*vldSignals))
Ejemplo n.º 11
0
def getAckOfOthers(self: OutNodeInfo, others: List[OutNodeInfo]):
    ackOfOthers = [hBit(1) if o is self else o.ack() for o in others]
    if ackOfOthers:
        return And(*ackOfOthers)
    else:
        return hBit(1)
Ejemplo n.º 12
0
def getAckOfOthers(self: OutNodeInfo, others: List[OutNodeInfo]):
    ackOfOthers = [BIT.from_py(1) if o is self else o.ack() for o in others]
    return And(*ackOfOthers)
Ejemplo n.º 13
0
    def stash_load(self, isIdle, lookupResNext, insertTargetOH, stash, lookup_not_in_progress, another_lookup_possible):
        """
        load a stash register from lookup/insert/delete interface
        """
        lookup = self.lookup
        insert = self.insert
        delete = self.delete
        table_lookup_ack = StreamNode(slaves=[t.lookup for t in self.tables]).ack()
        lookup_currently_executed = stash.origin_op._eq(ORIGIN_TYPE.LOOKUP)
        assert self.MAX_REINSERT > 0, self.MAX_REINSERT
        If(isIdle,
            If(lookup_not_in_progress & self.clean.vld,
                stash.origin_op(ORIGIN_TYPE.DELETE),
                stash.item_vld(0)
            ).Elif(lookup_not_in_progress & delete.vld,
                stash.origin_op(ORIGIN_TYPE.DELETE),
                stash.key(delete.key),
                stash.item_vld(0),
            ).Elif(lookup_not_in_progress & insert.vld,
                stash.origin_op(ORIGIN_TYPE.INSERT),
                stash.key(insert.key),
                stash.data(insert.data),
                stash.reinsert_cntr(self.MAX_REINSERT),
                stash.item_vld(1),
            ).Elif(lookup.vld & lookup.rd,
                stash.origin_op(ORIGIN_TYPE.LOOKUP),
                stash.key(lookup.key),
            ).Elif(table_lookup_ack,
                stash.origin_op(ORIGIN_TYPE.DELETE),  # need to set something else than lookup
                stash.key(None),
            )
        ).Elif(lookupResNext,
            SwitchLogic([
                (insertTargetOH[i],
                    [
                        # load stash from item found previously
                        # :note: happens in same time as write to table
                        #     so the stash and item in table is swapped
                        stash.key(t.lookupRes.key),
                        stash.data(t.lookupRes.data),
                        stash.reinsert_cntr(stash.reinsert_cntr - 1),
                        stash.item_vld(t.lookupRes.occupied),
                    ]
                  )
                  for i, t in enumerate(self.tables)
                ],
                default=[
                    stash.origin_op(ORIGIN_TYPE.DELETE),
                    stash.key(None),
                    stash.data(None),
                    stash.reinsert_cntr(None),
                    stash.item_vld(None),
                ])
        )
        cmd_priority = [self.clean, self.delete, self.insert, lookup]
        for i, intf in enumerate(cmd_priority):
            withLowerPrio = cmd_priority[:i]
            rd = And(isIdle, *[~x.vld for x in withLowerPrio])
            if intf is lookup:
                rd = rd & (~lookup_currently_executed |  # the stash not loaded yet
                     table_lookup_ack  # stash will be consumed
                    ) & another_lookup_possible
            else:
                rd = rd & lookup_not_in_progress

            intf.rd(rd)
Ejemplo n.º 14
0
 def ack(self) -> RtlSignal:
     if self:
         return And(*map(lambda x: x.ack(), self))
     else:
         return BIT.from_py(1)
Ejemplo n.º 15
0
 def ack(self) -> RtlSignal:
     if self:
         return And(*map(lambda x: x.ack(), self))
     else:
         return hBit(1)
Ejemplo n.º 16
0
    def _impl(self):
        propagateClkRstn(self)
        lookupRes = self.lookupRes
        tables = self.tables

        # stash is storage for item which is going to be swapped with actual
        stash_t = HStruct(
            (Bits(self.KEY_WIDTH), "key"),
            (Bits(self.DATA_WIDTH), "data"),
            (BIT, "vldFlag")
        )
        stash = self._reg("stash", stash_t)
        lookupOrigin = self._reg("lookupOrigin", Bits(2))

        cleanAck = self._sig("cleanAck")
        cleanAddr, cleanLast = self.cleanUpAddrIterator(cleanAck)
        lookupResRead = self._sig("lookupResRead")
        lookupResNext = self._sig("lookupResNext")
        (lookupResAck,
         insertFinal,
         insertFound,
         targetOH) = self.lookupResOfTablesDriver(lookupResRead,
                                                  lookupResNext)
        lookupAck = StreamNode(slaves=map(lambda t: t.lookup, tables)).ack()
        insertAck = StreamNode(slaves=map(lambda t: t.insert, tables)).ack()

        fsm_t = HEnum("insertFsm_t", ["idle", "cleaning",
                                      "lookup", "lookupResWaitRd",
                                      "lookupResAck"])

        isExternLookup = lookupOrigin._eq(ORIGIN_TYPE.LOOKUP)
        state = FsmBuilder(self, fsm_t, "insertFsm")\
            .Trans(fsm_t.idle,
                   (self.clean.vld, fsm_t.cleaning),
                   # before each insert suitable place has to be searched first
                   (self.insert.vld | self.lookup.vld | 
                    self.delete.vld, fsm_t.lookup)
                   ).Trans(fsm_t.cleaning,
                           # walk all items and clean it's vldFlags
                           (cleanLast, fsm_t.idle)
                           ).Trans(fsm_t.lookup,
                                   # search and resolve in which table item
                                   # should be stored
                                   (lookupAck, fsm_t.lookupResWaitRd)
                                   ).Trans(fsm_t.lookupResWaitRd,
                                           # process result of lookup and
                                           # write data stash to tables if
                                           # required
                                           (lookupResAck, fsm_t.lookupResAck)
                                           ).Trans(fsm_t.lookupResAck,
                                                   # process lookupRes, if we are going to insert on place where
                                                   # valid item is, it has to
                                                   # be stored
                                                   (lookupOrigin._eq(
                                                       ORIGIN_TYPE.DELETE), fsm_t.idle),
                                                   (isExternLookup & 
                                                    lookupRes.rd, fsm_t.idle),
                                                   # insert into specified
                                                   # table
                                                   (~isExternLookup & insertAck & 
                                                    insertFinal, fsm_t.idle),
                                                   (~isExternLookup & insertAck & 
                                                    ~insertFinal, fsm_t.lookup)
                                                   ).stateReg

        cleanAck(StreamNode(slaves=[t.insert for t in tables]).ack() & 
                 state._eq(fsm_t.cleaning))
        lookupResRead(state._eq(fsm_t.lookupResWaitRd))
        lookupResNext(And(state._eq(fsm_t.lookupResAck),
                          Or(lookupOrigin != ORIGIN_TYPE.LOOKUP, lookupRes.rd)))

        isIdle = state._eq(fsm_t.idle)
        self.stashLoad(isIdle, stash, lookupOrigin)
        insertIndex = self.insertAddrSelect(targetOH, state, cleanAddr)
        self.insetOfTablesDriver(
            state, targetOH, insertIndex, stash, isExternLookup)
        self.lookupResDriver(state, lookupOrigin, lookupAck, insertFound)
        self.lookupOfTablesDriver(state, stash.key)
Ejemplo n.º 17
0
    def _impl(self):
        # internal signals
        ACASCREG, ADREG, ALUMODEREG, AREG, AUTORESET_PATDET, A_INPUT, BCASCREG, BREG, B_INPUT, CARRYINREG, CARRYINSELREG, \
        CREG, DREG, INMODEREG, IS_ALUMODE_INVERTED, IS_CARRYIN_INVERTED, IS_CLK_INVERTED, IS_INMODE_INVERTED, IS_OPMODE_INVERTED, MASK, MREG, \
        OPMODEREG, PATTERN, PREG, SEL_MASK, SEL_PATTERN, USE_DPORT, USE_MULT, USE_PATTERN_DETECT, USE_SIMD, ACOUT, \
        BCOUT, CARRYCASCOUT, CARRYOUT, MULTSIGNOUT, OVERFLOW, P, PATTERNBDETECT, PATTERNDETECT, PCOUT, UNDERFLOW, \
        A, ACIN, ALUMODE, B, BCIN, C, CARRYCASCIN, CARRYIN, CARRYINSEL, CEA1, \
        CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL, CED, CEINMODE, \
        CEM, CEP, CLK, D, INMODE, MULTSIGNIN, OPMODE, PCIN, RSTA, RSTALLCARRYIN, \
        RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP = \
        self.ACASCREG, self.ADREG, self.ALUMODEREG, self.AREG, self.AUTORESET_PATDET, self.A_INPUT, self.BCASCREG, self.BREG, self.B_INPUT, self.CARRYINREG, self.CARRYINSELREG, \
        self.CREG, self.DREG, self.INMODEREG, self.IS_ALUMODE_INVERTED, self.IS_CARRYIN_INVERTED, self.IS_CLK_INVERTED, self.IS_INMODE_INVERTED, self.IS_OPMODE_INVERTED, self.MASK, self.MREG, \
        self.OPMODEREG, self.PATTERN, self.PREG, self.SEL_MASK, self.SEL_PATTERN, self.USE_DPORT, self.USE_MULT, self.USE_PATTERN_DETECT, self.USE_SIMD, self.ACOUT, \
        self.BCOUT, self.CARRYCASCOUT, self.CARRYOUT, self.MULTSIGNOUT, self.OVERFLOW, self.P, self.PATTERNBDETECT, self.PATTERNDETECT, self.PCOUT, self.UNDERFLOW, \
        self.A, self.ACIN, self.ALUMODE, self.B, self.BCIN, self.C, self.CARRYCASCIN, self.CARRYIN, self.CARRYINSEL, self.CEA1, \
        self.CEA2, self.CEAD, self.CEALUMODE, self.CEB1, self.CEB2, self.CEC, self.CECARRYIN, self.CECTRL, self.CED, self.CEINMODE, \
        self.CEM, self.CEP, self.CLK, self.D, self.INMODE, self.MULTSIGNIN, self.OPMODE, self.PCIN, self.RSTA, self.RSTALLCARRYIN, \
        self.RSTALUMODE, self.RSTB, self.RSTC, self.RSTCTRL, self.RSTD, self.RSTINMODE, self.RSTM, self.RSTP
        #------------------- constants -------------------------
        CARRYOUT_W = 4
        A_W = 30
        ALUMODE_W = 4
        A_MULT_W = 25
        B_W = 18
        B_MULT_W = 18
        D_W = 25
        INMODE_W = 5
        OPMODE_W = 7
        ALU_FULL_W = 48

        IS_ALUMODE_INVERTED_BIN = self._sig("IS_ALUMODE_INVERTED_BIN",
                                            Bits(4),
                                            def_val=IS_ALUMODE_INVERTED)
        IS_CARRYIN_INVERTED_BIN = self._sig("IS_CARRYIN_INVERTED_BIN",
                                            def_val=IS_CARRYIN_INVERTED)
        IS_CLK_INVERTED_BIN = self._sig("IS_CLK_INVERTED_BIN",
                                        def_val=IS_CLK_INVERTED)
        IS_INMODE_INVERTED_BIN = self._sig("IS_INMODE_INVERTED_BIN",
                                           Bits(5),
                                           def_val=IS_INMODE_INVERTED)
        IS_OPMODE_INVERTED_BIN = self._sig("IS_OPMODE_INVERTED_BIN",
                                           Bits(7),
                                           def_val=IS_OPMODE_INVERTED)
        a_o_mux = self._sig("a_o_mux", Bits(30))
        qa_o_mux = self._sig("qa_o_mux", Bits(30))
        qa_o_reg1 = self._sig("qa_o_reg1", Bits(30))
        qa_o_reg2 = self._sig("qa_o_reg2", Bits(30))
        qacout_o_mux = self._sig("qacout_o_mux", Bits(30))
        # new
        qinmode_o_mux = self._sig("qinmode_o_mux", Bits(5))
        qinmode_o_reg = self._sig("qinmode_o_reg", Bits(5))
        # new
        a_preaddsub = self._sig("a_preaddsub", Bits(25))
        b_o_mux = self._sig("b_o_mux", Bits(18))
        qb_o_mux = self._sig("qb_o_mux", Bits(18))
        qb_o_reg1 = self._sig("qb_o_reg1", Bits(18))
        qb_o_reg2 = self._sig("qb_o_reg2", Bits(18))
        qbcout_o_mux = self._sig("qbcout_o_mux", Bits(18))
        qcarryinsel_o_mux = self._sig("qcarryinsel_o_mux", Bits(3))
        qcarryinsel_o_reg1 = self._sig("qcarryinsel_o_reg1", Bits(3))
        # new
        #d_o_mux = self._sig("d_o_mux", Bits(D_W))
        qd_o_mux = self._sig("qd_o_mux", Bits(D_W))
        qd_o_reg1 = self._sig("qd_o_reg1", Bits(D_W))
        qmult_o_mux = self._sig("qmult_o_mux", Bits(A_MULT_W + B_MULT_W))
        qmult_o_reg = self._sig("qmult_o_reg", Bits(A_MULT_W + B_MULT_W))
        # 42:0
        qc_o_mux = self._sig("qc_o_mux", Bits(48))
        qc_o_reg1 = self._sig("qc_o_reg1", Bits(48))
        qp_o_mux = self._sig("qp_o_mux", Bits(48))
        qp_o_reg1 = self._sig("qp_o_reg1", Bits(48))
        qx_o_mux = self._sig("qx_o_mux", Bits(48))
        qy_o_mux = self._sig("qy_o_mux", Bits(48))
        qz_o_mux = self._sig("qz_o_mux", Bits(48))
        qopmode_o_mux = self._sig("qopmode_o_mux", Bits(7))
        qopmode_o_reg1 = self._sig("qopmode_o_reg1", Bits(7))
        qcarryin_o_mux0 = self._sig("qcarryin_o_mux0")
        qcarryin_o_reg0 = self._sig("qcarryin_o_reg0")
        qcarryin_o_mux7 = self._sig("qcarryin_o_mux7")
        qcarryin_o_reg7 = self._sig("qcarryin_o_reg7")
        qcarryin_o_mux = self._sig("qcarryin_o_mux")
        qalumode_o_mux = self._sig("qalumode_o_mux", Bits(4))
        qalumode_o_reg1 = self._sig("qalumode_o_reg1", Bits(4))
        self.invalid_opmode = self._sig("invalid_opmode", def_val=1)
        self.opmode_valid_flag = opmode_valid_flag = self._sig(
            "opmode_valid_flag", def_val=1)
        #   reg [47:0] alu_o;
        alu_o = self._sig("alu_o", Bits(48))
        qmultsignout_o_reg = self._sig("qmultsignout_o_reg")
        multsignout_o_mux = self._sig("multsignout_o_mux")
        multsignout_o_opmode = self._sig("multsignout_o_opmode")
        pdet_o_mux = self._sig("pdet_o_mux")
        pdetb_o_mux = self._sig("pdetb_o_mux")
        the_pattern = self._sig("the_pattern", Bits(48))
        the_mask = self._sig("the_mask", Bits(48), def_val=0)
        carrycascout_o = self._sig("carrycascout_o")
        the_auto_reset_patdet = self._sig("the_auto_reset_patdet")
        carrycascout_o_reg = self._sig("carrycascout_o_reg", def_val=0)
        carrycascout_o_mux = self._sig("carrycascout_o_mux", def_val=0)

        # CR 588861
        carryout_o_reg = self._sig("carryout_o_reg", Bits(4), def_val=0)
        carryout_o_mux = self._sig("carryout_o_mux", Bits(4))
        carryout_x_o = self._sig("carryout_x_o", Bits(4))
        pdet_o = self._sig("pdet_o")
        pdetb_o = self._sig("pdetb_o")
        pdet_o_reg1 = self._sig("pdet_o_reg1")
        pdet_o_reg2 = self._sig("pdet_o_reg2")
        pdetb_o_reg1 = self._sig("pdetb_o_reg1")
        pdetb_o_reg2 = self._sig("pdetb_o_reg2")
        overflow_o = self._sig("overflow_o")
        underflow_o = self._sig("underflow_o")
        mult_o = self._sig("mult_o", Bits(A_MULT_W + B_MULT_W))
        #   reg [(MSB_A_MULT+MSB_B_MULT+1):0] mult_o;  // 42:0
        # new
        ad_addsub = self._sig("ad_addsub", Bits(A_MULT_W))
        ad_mult = self._sig("ad_mult", Bits(A_MULT_W))
        qad_o_reg1 = self._sig("qad_o_reg1", Bits(A_MULT_W))
        qad_o_mux = self._sig("qad_o_mux", Bits(A_MULT_W))
        b_mult = self._sig("b_mult", Bits(B_MULT_W))
        # cci_drc_msg = self._sig("cci_drc_msg", def_val=0b0)
        # cis_drc_msg = self._sig("cis_drc_msg", def_val=0b0)
        opmode_in = self._sig("opmode_in", Bits(OPMODE_W))
        alumode_in = self._sig("alumode_in", Bits(ALUMODE_W))
        carryin_in = self._sig("carryin_in")
        clk_in = self._sig("clk_in")
        inmode_in = self._sig("inmode_in", Bits(INMODE_W))
        #*** Y mux
        # 08-06-08
        # IR 478378
        y_mac_cascd = rename_signal(
            self,
            qopmode_o_mux[7:4]._eq(0b100)._ternary(replicate(48, MULTSIGNIN),
                                                   Bits(48).from_py(mask(48))),
            "y_mac_cascd")
        #--####################################################################
        #--#####                         ALU                              #####
        #--####################################################################
        co = self._sig("co", Bits(ALU_FULL_W))
        s = self._sig("s", Bits(ALU_FULL_W))
        comux = self._sig("comux", Bits(ALU_FULL_W))
        smux = self._sig("smux", Bits(ALU_FULL_W))
        carryout_o = self._sig("carryout_o", Bits(CARRYOUT_W))
        # FINAL ADDER
        s0 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[11:0], qcarryin_o_mux) +
            Concat(BIT.from_py(0), smux[12:0]), "s0")
        cout0 = rename_signal(self, comux[11] + s0[12], "cout0")
        C1 = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else s0[12], "C1")
        co11_lsb = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else comux[11],
            "co11_lsb")
        s1 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[23:12], co11_lsb) +
            Concat(BIT.from_py(0), smux[24:12]) +
            Concat(Bits(12).from_py(0), C1), "s1")
        cout1 = rename_signal(self, comux[23] + s1[12], "cout1")
        C2 = rename_signal(
            self,
            BIT.from_py(0b0) if (USE_SIMD in ["TWO24", "FOUR12"]) else s1[12],
            "C2")
        co23_lsb = rename_signal(
            self,
            BIT.from_py(0b0) if
            (USE_SIMD in ["TWO24", "FOUR12"]) else comux[23], "co23_lsb")
        s2 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[35:24], co23_lsb) +
            Concat(BIT.from_py(0), smux[36:24]) +
            Concat(Bits(12).from_py(0), C2), "s2")
        cout2 = rename_signal(self, comux[35] + s2[12], "cout2")
        C3 = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else s2[12], "C3")
        co35_lsb = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else comux[35],
            "co35_lsb")
        s3 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[48:36], co35_lsb) +
            Concat(Bits(2).from_py(0), smux[48:36]) +
            Concat(Bits(13).from_py(0), C3), "s3")
        cout3 = rename_signal(self, s3[12], "cout3")
        #cout4 = rename_signal(self, s3[13], "cout4")
        qcarryin_o_mux_tmp = self._sig("qcarryin_o_mux_tmp")

        ACOUT(qacout_o_mux)
        BCOUT(qbcout_o_mux)
        CARRYCASCOUT(carrycascout_o_mux)
        CARRYOUT(carryout_x_o)
        MULTSIGNOUT(multsignout_o_mux)
        OVERFLOW(overflow_o)
        P(qp_o_mux)
        PCOUT(qp_o_mux)
        PATTERNDETECT(pdet_o_mux)
        PATTERNBDETECT(pdetb_o_mux)
        UNDERFLOW(underflow_o)
        alumode_in(ALUMODE ^ IS_ALUMODE_INVERTED_BIN)
        carryin_in(CARRYIN ^ IS_CARRYIN_INVERTED_BIN)
        clk_in(CLK ^ IS_CLK_INVERTED_BIN)
        inmode_in(INMODE ^ IS_INMODE_INVERTED_BIN)
        opmode_in(OPMODE ^ IS_OPMODE_INVERTED_BIN)

        #*********************************************************
        #**********  INMODE signal registering        ************
        #*********************************************************
        If(
            clk_in._onRisingEdge(),
            If(RSTINMODE, qinmode_o_reg(0b0)).Elif(CEINMODE,
                                                   qinmode_o_reg(inmode_in)))
        if INMODEREG == 0:
            qinmode_o_mux(inmode_in)
        elif INMODEREG == 1:
            qinmode_o_mux(qinmode_o_reg)
        else:
            raise AssertionError()

        if A_INPUT == "DIRECT":
            a_o_mux(A)
        elif A_INPUT == "CASCADE":
            a_o_mux(ACIN)
        else:
            raise AssertionError()

        if AREG in (1, 2):
            If(
                clk_in._onRisingEdge(),
                If(RSTA, qa_o_reg1(0b0), qa_o_reg2(0b0)).Else(
                    If(CEA1, qa_o_reg1(a_o_mux)),
                    If(
                        CEA2,
                        qa_o_reg2(a_o_mux if AREG ==
                                  1 else qa_o_reg1 if AREG == 2 else None))))
        else:
            qa_o_reg1(None)

        if AREG == 0:
            qa_o_mux(a_o_mux)
        elif AREG == 1:
            qa_o_mux(qa_o_reg2)
        elif AREG == 2:
            qa_o_mux(qa_o_reg2)
        else:
            raise AssertionError()

        if ACASCREG == 1:
            qacout_o_mux(qa_o_reg1 if AREG == 2 else qa_o_mux)
        elif ACASCREG == 0:
            qacout_o_mux(qa_o_mux)
        elif ACASCREG == 2:
            qacout_o_mux(qa_o_mux)
        else:
            raise AssertionError()

        If(qinmode_o_mux[1], a_preaddsub(0b0)).Elif(
            qinmode_o_mux[0],
            a_preaddsub(qa_o_reg1[25:0]),
        ).Else(a_preaddsub(qa_o_mux[25:0]), )
        if B_INPUT == "DIRECT":
            b_o_mux(B)
        elif B_INPUT == "CASCADE":
            b_o_mux(BCIN)
        else:
            raise AssertionError()

        if BREG in (1, 2):
            If(
                clk_in._onRisingEdge(),
                If(RSTB, qb_o_reg1(0b0), qb_o_reg2(0b0)).Else(
                    If(CEB1, qb_o_reg1(b_o_mux)),
                    If(
                        CEB2,
                        qb_o_reg2(b_o_mux if BREG ==
                                  1 else qb_o_reg1 if BREG == 1 else None))))
        else:
            qb_o_reg1(None)

        if BREG == 0:
            qb_o_mux(b_o_mux)
        elif BREG == 1:
            qb_o_mux(qb_o_reg2)
        elif BREG == 2:
            qb_o_mux(qb_o_reg2)
        else:
            raise AssertionError()

        if BCASCREG == 1:
            qbcout_o_mux(qb_o_reg1 if BREG == 2 else qb_o_mux)
        elif BCASCREG == 0:
            qbcout_o_mux(qb_o_mux)
        elif BCASCREG == 2:
            qbcout_o_mux(qb_o_mux)
        else:
            raise AssertionError()

        b_mult(qinmode_o_mux[4]._ternary(qb_o_reg1, qb_o_mux))

        #*********************************************************
        #*** Input register C with 1 level deep of register
        #*********************************************************
        If(clk_in._onRisingEdge(),
           If(RSTC, qc_o_reg1(0b0)).Elif(CEC, qc_o_reg1(C)))
        if CREG == 0:
            qc_o_mux(C)
        elif CREG == 1:
            qc_o_mux(qc_o_reg1)
        else:
            raise AssertionError()

        #*********************************************************
        #*** Input register D with 1 level deep of register
        #*********************************************************
        If(clk_in._onRisingEdge(),
           If(RSTD, qd_o_reg1(0b0)).Elif(CED, qd_o_reg1(D)))
        if DREG == 0:
            qd_o_mux(D)
        elif DREG == 1:
            qd_o_mux(qd_o_reg1)
        else:
            raise AssertionError()

        ad_addsub(qinmode_o_mux[3]._ternary(
            -a_preaddsub + qinmode_o_mux[2]._ternary(qd_o_mux, 0b0),
            a_preaddsub + qinmode_o_mux[2]._ternary(qd_o_mux, 0b0)))

        If(clk_in._onRisingEdge(),
           If(RSTD, qad_o_reg1(0b0)).Elif(CEAD, qad_o_reg1(ad_addsub)))
        if ADREG == 0:
            qad_o_mux(ad_addsub)
        elif ADREG == 1:
            qad_o_mux(qad_o_reg1)
        else:
            raise AssertionError()

        ad_mult(qad_o_mux if USE_DPORT == "TRUE" else a_preaddsub)

        #*********************************************************
        #*********************************************************
        #***************      25x18 Multiplier     ***************
        #*********************************************************
        # 05/26/05 -- FP -- Added warning for invalid mult when USE_MULT=NONE
        # SIMD=FOUR12 and SIMD=TWO24
        # Made mult_o to be "X"
        if USE_MULT == "NONE" or USE_SIMD != "ONE48":
            mult_o(0b0)
        else:
            If(CARRYINSEL._eq(0b010), mult_o(None)).Else(
                mult_o(
                    replicate(18, ad_mult[24])._concat(ad_mult[25:0]) *
                    replicate(25, b_mult[17])._concat(b_mult)))

        If(clk_in._onRisingEdge(),
           If(RSTM, qmult_o_reg(0b0)).Elif(CEM, qmult_o_reg(mult_o)))

        If(qcarryinsel_o_mux._eq(0b010), qmult_o_mux(None)).Else(
            qmult_o_mux(qmult_o_reg if MREG == 1 else mult_o))

        #*** X mux
        # ask jmt
        # add post 2014.4
        # else
        Switch(qopmode_o_mux[2:0])\
            .Case(0b00,
                # X_SEL.ZERO
                qx_o_mux(0b0))\
            .Case(0b01,
                # X_SEL.M
                qx_o_mux(replicate(5, qmult_o_mux[A_MULT_W + B_MULT_W - 1])._concat(qmult_o_mux)))\
            .Case(0b10,
                # X_SEL.P
                qx_o_mux(qp_o_mux if PREG == 1 else None))\
            .Case(0b11,
                # X_SEL.A_B
                qx_o_mux(None)
                if USE_MULT == "MULTIPLY" and (
                    (AREG == 0 and BREG == 0 and MREG == 0) or
                    (AREG == 0 and BREG == 0 and PREG == 0) or
                    (MREG == 0 and PREG == 0))
                # print("OPMODE Input Warning : The OPMODE[1:0] %b to DSP48E1 instance %m is invalid when using attributes USE_MULT = MULTIPLY at %.3f ns. Please set USE_MULT to either NONE or DYNAMIC.", qopmode_o_mux[slice(2, 0)], sim.now // 1000.000000)
                else qx_o_mux(qa_o_mux[A_W:0]._concat(qb_o_mux[B_W:0]))
            )

        # add post 2014.4
        Switch(qopmode_o_mux[4:2])\
            .Case(0b00,
                qy_o_mux(0b0))\
            .Case(0b01,
                qy_o_mux(0b0))\
            .Case(0b10,
                qy_o_mux(y_mac_cascd))\
            .Case(0b11,
                qy_o_mux(qc_o_mux))

        #*** Z mux
        # ask jmt
        # add post 2014.4
        Switch(qopmode_o_mux[7:4])\
            .Case(0b000,
                qz_o_mux(0b0))\
            .Case(0b001,
                qz_o_mux(PCIN))\
            .Case(0b010,
                qz_o_mux(qp_o_mux))\
            .Case(0b011,
                qz_o_mux(qc_o_mux))\
            .Case(0b100,
                qz_o_mux(qp_o_mux))\
            .Case(0b101,
                qz_o_mux(replicate(17, PCIN[47])._concat(PCIN[48:17])))\
            .Case(0b110,
                qz_o_mux(replicate(17, qp_o_mux[47])._concat(qp_o_mux[48:17])))\
            .Case(0b111,
                qz_o_mux(replicate(17, qp_o_mux[47])._concat(qp_o_mux[48:17])))

        #*** CarryInSel and OpMode with 1 level of register
        If(
            clk_in._onRisingEdge(),
            If(RSTCTRL, qcarryinsel_o_reg1(0b0),
               qopmode_o_reg1(0b0)).Elif(CECTRL,
                                         qcarryinsel_o_reg1(CARRYINSEL),
                                         qopmode_o_reg1(opmode_in)))
        if CARRYINSELREG == 0:
            qcarryinsel_o_mux(CARRYINSEL)

        elif CARRYINSELREG == 1:
            qcarryinsel_o_mux(qcarryinsel_o_reg1)
        else:
            raise AssertionError()

        # CR 219047 (3)
        # If(qcarryinsel_o_mux._eq(0b010),
        #    If(~((cci_drc_msg._eq(0b1) | qopmode_o_mux._eq(0b1001000)) | (MULTSIGNIN._eq(0b0) & CARRYCASCIN._eq(0b0))),
        #        #print("DRC warning : CARRYCASCIN can only be used in the current DSP48E1 instance %m if the previous DSP48E1 is performing a two input ADD or SUBTRACT operation, or the current DSP48E1 is configured in the MAC extend opmode 7'b1001000 at %.3f ns.", sim.now // 1000.000000),
        #        cci_drc_msg(0b1)
        #    ),
        #    If(~((qopmode_o_mux[4:0] != 0b0101)._isOn())._isOn(),
        #        #print("DRC warning : CARRYINSEL is set to 010 with OPMODE set to multiplication (xxx0101). This is an illegal mode and may show deviation between simulation results and hardware behavior. DSP48E1 instance %m at %.3f ns.", sim.now // 1000.000000)
        #    ),
        #    If(~cis_drc_msg._eq(0b1),
        #        #print("DRC warning : CARRYINSEL is set to 010 with OPMODEREG set to 0. This causes unknown values after reset occurs. It is suggested to use OPMODEREG = 1 when cascading large adders. DSP48E1 instance %m at %.3f ns.", sim.now // 1000.000000),
        #        cis_drc_msg(0b1)
        #    ) if OPMODEREG == 0b1 else []
        # )
        if OPMODEREG == 0:
            qopmode_o_mux(opmode_in)
        elif OPMODEREG == 1:
            qopmode_o_mux(qopmode_o_reg1)
        else:
            raise AssertionError()

        #*** ALUMODE with 1 level of register
        If(
            clk_in._onRisingEdge(),
            If(RSTALUMODE,
               qalumode_o_reg1(0b0)).Elif(CEALUMODE,
                                          qalumode_o_reg1(alumode_in)))
        if ALUMODEREG == 0:
            qalumode_o_mux(alumode_in)
        elif ALUMODEREG == 1:
            qalumode_o_mux(qalumode_o_reg1)
        else:
            raise AssertionError()

        def deassign_xyz_mux_if_PREG_eq_1():
            if PREG != 1:
                return self.display_invalid_opmode()
            else:
                return self.deassign_xyz_mux()

        def DCR_check_logic_modes():
            # -- LOGIC MODES DRC
            return If(
                In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux),
                self.deassign_xyz_mux()
            ).Elif(
                In(qopmode_o_mux,
                   LOGIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1),
                deassign_xyz_mux_if_PREG_eq_1(),
            ).Else(
                # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000)
            )

        # display_invalid_opmode
        arith_mode_tmp = qopmode_o_mux._concat(qcarryinsel_o_mux)
        # no check at first 100ns
        Switch(qalumode_o_mux[4:2])\
            .Case(0b00,
                # -- ARITHMETIC MODES DRC
                If(In(arith_mode_tmp, ARITHMETIC_MODES_DRC_deassign_xyz_mux),
                    self.deassign_xyz_mux()
                ).Elif(In(arith_mode_tmp, ARITHMETIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1),
                    deassign_xyz_mux_if_PREG_eq_1()
                ).Else(
                    # CR 444150
                    # If(qopmode_o_mux._concat(qcarryinsel_o_mux)._eq(0b0000000010)._isOn() & (OPMODEREG._eq(1)._isOn() & CARRYINSELREG._eq(0)._isOn())._isOn(),
                    #    print("DRC warning : CARRYINSELREG is set to %d. It is required to have CARRYINSELREG be set to 1 to match OPMODEREG, in order to ensure that the simulation model will match the hardware behavior in all use cases.", CARRYINSELREG)
                    # ),
                    # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is either invalid or the CARRYINSEL %b for that specific OPMODE is invalid at %.3f ns. This warning may be due to a mismatch in the OPMODEREG and CARRYINSELREG attribute settings. It is recommended that OPMODEREG and CARRYINSELREG always be set to the same value. ", qopmode_o_mux, qcarryinsel_o_mux, sim.now // 1000.000000)
                )
            )\
            .Case(0b01,
               DCR_check_logic_modes()
            )\
            .Case(0b11,
               DCR_check_logic_modes()
            )\
            .Default(
                # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000)
            )

        If(
            qalumode_o_mux[0],
            co(qx_o_mux & qy_o_mux
               | ~qz_o_mux & qy_o_mux | qx_o_mux & ~qz_o_mux),
            s(~qz_o_mux ^ qx_o_mux ^ qy_o_mux)).Else(
                co(qx_o_mux & qy_o_mux | qz_o_mux & qy_o_mux
                   | qx_o_mux & qz_o_mux), s(qz_o_mux ^ qx_o_mux ^ qy_o_mux))

        If(
            qalumode_o_mux[2],
            comux(0),
        ).Else(comux(co), )
        smux(qalumode_o_mux[3]._ternary(co, s))

        carryout_o_hw = self._sig("carryout_o_hw", Bits(CARRYOUT_W))
        carryout_o_hw[0](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout0, cout0))
        carryout_o_hw[1](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout1, cout1))
        carryout_o_hw[2](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout2, cout2))
        carryout_o_hw[3](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout3, cout3))
        alu_o(qalumode_o_mux[1]._ternary(
            ~Concat(s3[12:0], s2[12:0], s1[12:0], s0[12:0]),
            Concat(s3[12:0], s2[12:0], s1[12:0], s0[12:0])))
        carrycascout_o(cout3)
        multsignout_o_opmode(
            (qopmode_o_mux[7:4]._eq(0b100))._ternary(MULTSIGNIN,
                                                     qmult_o_mux[42]))
        If(
            (qopmode_o_mux[4:0]._eq(0b0101) | (qalumode_o_mux[4:2] != 0b00)),
            carryout_o[3](None),
            carryout_o[2](None),
            carryout_o[1](None),
            carryout_o[0](None),
        ).Else(
            carryout_o[3](carryout_o_hw[3]),
            carryout_o[2](carryout_o_hw[2] if USE_SIMD == "FOUR12" else None),
            carryout_o[1](carryout_o_hw[1] if USE_SIMD in
                          ["TWO24", "FOUR12"] else None),
            carryout_o[0](carryout_o_hw[0] if USE_SIMD == "FOUR12" else None),
        )

        #--########################### END ALU ################################
        #*** CarryIn Mux and Register
        #-------  input 0
        If(
            clk_in._onRisingEdge(),
            If(RSTALLCARRYIN,
               qcarryin_o_reg0(0b0)).Elif(CECARRYIN,
                                          qcarryin_o_reg0(carryin_in)))
        if CARRYINREG == 0:
            qcarryin_o_mux0(carryin_in)
        elif CARRYINREG == 1:
            qcarryin_o_mux0(qcarryin_o_reg0)
        else:
            raise AssertionError()

        #-------  input 7
        If(
            clk_in._onRisingEdge(),
            If(RSTALLCARRYIN, qcarryin_o_reg7(0b0)).Elif(
                CEM, qcarryin_o_reg7(ad_mult[24]._eq(b_mult[17]))))

        if MREG == 0:
            qcarryin_o_mux7(ad_mult[24]._eq(b_mult[17]))
        elif MREG == 1:
            qcarryin_o_mux7(qcarryin_o_reg7)
        else:
            raise ValueError(
                "MREG is set to %d. Legal values for this attribute are 0 or 1.",
                MREG)

        Switch(qcarryinsel_o_mux)\
            .Case(CARRYIN_SEL.CARRYIN.value,
                qcarryin_o_mux_tmp(qcarryin_o_mux0))\
            .Case(CARRYIN_SEL.PCIN_47_n.value,
                qcarryin_o_mux_tmp(~PCIN[47]))\
            .Case(CARRYIN_SEL.CARRYCASCIN.value,
                qcarryin_o_mux_tmp(CARRYCASCIN))\
            .Case(CARRYIN_SEL.PCIN_47.value,
                qcarryin_o_mux_tmp(PCIN[47]))\
            .Case(CARRYIN_SEL.CARRYCASCOUT.value,
                qcarryin_o_mux_tmp(carrycascout_o_mux))\
            .Case(CARRYIN_SEL.P_47_n.value,
                qcarryin_o_mux_tmp(~qp_o_mux[47]))\
            .Case(CARRYIN_SEL.A_27_eq_B_17.value,
                qcarryin_o_mux_tmp(qcarryin_o_mux7))\
            .Case(CARRYIN_SEL.P_47.value,
                qcarryin_o_mux_tmp(qp_o_mux[47]))

        # disable carryin when performing logic operation
        If(qalumode_o_mux[3] | qalumode_o_mux[2],
           qcarryin_o_mux(0b0)).Else(qcarryin_o_mux(qcarryin_o_mux_tmp))

        if AUTORESET_PATDET == "RESET_MATCH":
            the_auto_reset_patdet(pdet_o_reg1)
        elif AUTORESET_PATDET == "RESET_NOT_MATCH":
            the_auto_reset_patdet(pdet_o_reg2 & ~pdet_o_reg1)
        else:
            the_auto_reset_patdet(0)

        #--####################################################################
        #--#####      CARRYOUT, CARRYCASCOUT. MULTSIGNOUT and PCOUT      ######
        #--####################################################################
        #*** register with 1 level of register
        If(
            clk_in._onRisingEdge(),
            If(RSTP._isOn() | the_auto_reset_patdet._isOn(),
               carryout_o_reg(0b0), carrycascout_o_reg(0b0),
               qmultsignout_o_reg(0b0),
               qp_o_reg1(0b0)).Elif(CEP, carryout_o_reg(carryout_o),
                                    carrycascout_o_reg(carrycascout_o),
                                    qmultsignout_o_reg(multsignout_o_opmode),
                                    qp_o_reg1(alu_o)))
        if PREG == 0:
            carryout_o_mux(carryout_o)
            carrycascout_o_mux(carrycascout_o)
            multsignout_o_mux(multsignout_o_opmode)
            qp_o_mux(alu_o)

        elif PREG == 1:
            carryout_o_mux(carryout_o_reg)
            carrycascout_o_mux(carrycascout_o_reg)
            multsignout_o_mux(qmultsignout_o_reg)
            qp_o_mux(qp_o_reg1)
        else:
            raise AssertionError()

        carryout_x_o(
            Concat(
                carryout_o_mux[3],
                carryout_o_mux[2]
                if USE_SIMD == "FOUR12" else BIT.from_py(None),
                carryout_o_mux[1]
                if USE_SIMD in ["TWO24", "FOUR12"] else BIT.from_py(None),
                carryout_o_mux[0]
                if USE_SIMD == "FOUR12" else BIT.from_py(None),
            ))

        the_pattern(PATTERN if SEL_PATTERN == "PATTERN" else qc_o_mux)

        # selet mask
        if USE_PATTERN_DETECT == "NO_PATDET":
            the_mask(mask(48))
        elif SEL_MASK == "MASK":
            the_mask(MASK)
        elif SEL_MASK == "C":
            the_mask(qc_o_mux)
        elif SEL_MASK == "ROUNDING_MODE1":
            the_mask(~qc_o_mux << 1)
        elif SEL_MASK == "ROUNDING_MODE2":
            the_mask(~qc_o_mux << 2)
        else:
            raise AssertionError()

        If(
            opmode_valid_flag,
            pdet_o(And(*(~(the_pattern ^ alu_o) | the_mask))),
            pdetb_o(And(*(the_pattern ^ alu_o | the_mask))),
        ).Else(
            pdet_o(None),
            pdetb_o(None),
        )
        pdet_o_mux(pdet_o_reg1 if PREG == 1 else pdet_o)
        pdetb_o_mux(pdetb_o_reg1 if PREG == 1 else pdetb_o)

        #*** Output register PATTERN DETECT and UNDERFLOW / OVERFLOW
        If(
            clk_in._onRisingEdge(),
            If(RSTP._isOn() | the_auto_reset_patdet._isOn(), pdet_o_reg1(0b0),
               pdet_o_reg2(0b0), pdetb_o_reg1(0b0),
               pdetb_o_reg2(0b0)).Elif(CEP, pdet_o_reg2(pdet_o_reg1),
                                       pdet_o_reg1(pdet_o),
                                       pdetb_o_reg2(pdetb_o_reg1),
                                       pdetb_o_reg1(pdetb_o)))
        if PREG == 1 or USE_PATTERN_DETECT == "PATDET":
            overflow_o(pdet_o_reg2 & ~pdet_o_reg1 & ~pdetb_o_reg1),
            underflow_o(pdetb_o_reg2 & ~pdet_o_reg1 & ~pdetb_o_reg1)
        else:
            overflow_o(None),
            underflow_o(None)
Ejemplo n.º 18
0
    def _injectParametersIntoPortTypes(
            self, port_type_variants: List[Tuple[HdlPortItem,
                                                 Dict[Tuple[Param, HValue],
                                                      List[HdlType]]]],
            param_signals: List[RtlSignal]):
        updated_type_ids = set()
        param_sig_by_name = {p.name: p for p in param_signals}
        param_value_domain = {}
        for parent_port, param_val_to_t in port_type_variants:
            for (param, param_value), port_types in param_val_to_t.items():
                param_value_domain.setdefault(param, set()).add(param_value)

        for parent_port, param_val_to_t in port_type_variants:
            if id(parent_port._dtype) in updated_type_ids:
                continue
            # check which unique parameter values affects the type of the port
            # if the type changes with any parameter value integrate it in to type of the port
            # print(parent_port, param_val_to_t)
            type_to_param_values = {}
            for (param, param_value), port_types in param_val_to_t.items():
                for pt in port_types:
                    cond = type_to_param_values.setdefault(pt, UniqList())
                    cond.append((param, param_value))

            assert type_to_param_values, parent_port
            if len(type_to_param_values) == 1:
                continue  # type does not change

            # Param: values
            params_used = {}
            for t, param_values in type_to_param_values.items():
                for (param, param_val) in param_values:
                    params_used.setdefault(param, set()).add(param_val)

                # filter out parameters which are not part of type specification process
                for p, p_vals in list(params_used.items()):
                    if len(param_value_domain[p]) == len(p_vals):
                        params_used.pop(p)
                # reset sets used to check parameter values
                for p, p_vals in params_used.items():
                    p_vals.clear()

            if not params_used:
                raise AssertionError(
                    parent_port,
                    "Type changes between the variants but it does not depend on parameter",
                    param_val_to_t)

            if len(params_used) == 1 and list(
                    params_used.keys())[0].get_hdl_type() == INT:
                # try to extract param * x + y
                p_val_to_port_w = {}
                for t, param_values in type_to_param_values.items():
                    for (param, param_val) in param_values:
                        if param not in params_used:
                            continue
                        assert param_val not in p_val_to_port_w or p_val_to_port_w[
                            param_val] == t.bit_length(), parent_port
                        p_val_to_port_w[param_val] = t.bit_length()
                # t_width = n*p + c
                _p_val_to_port_w = sorted(p_val_to_port_w.items())
                t_width0, p0 = _p_val_to_port_w[0]
                t_width1, p1 = _p_val_to_port_w[1]
                # 0 == t_width0 - n*p0 + c
                # 0 == t_width1 - n*p1 + c

                # 0 == t_width0 - n*p0 - c + t_width1 - n*p1 - c
                # 0 == t_width0 + t_width1 - n*(p0 + p1) - 2c
                # c == (t_width0 + t_width1 - n*(p0 + p1) ) //2
                # n has to be int, 0 < n <= t_width0/p0
                # n is something like base size of port which is multipled by parameter
                # we searching n for which we can resolve c
                found_nc = None
                for n in range(1, t_width0 // p0 + 1):
                    c = (t_width0 + t_width1 - n * (p0 + p1)) // 2
                    if t_width0 - n * p0 + c == 0 and t_width1 - n * p1 + c == 0:
                        found_nc = (n, c)
                        break

                if found_nc is None:
                    raise NotImplementedError()
                else:
                    p = list(params_used.keys())[0]
                    p = param_sig_by_name[p._name]
                    (n, c) = found_nc
                    t = parent_port._dtype
                    t._bit_length = INT.from_py(n) * p + c
                    t._bit_length._const = True
                    updated_type_ids.add(id(t))
            else:
                condition_and_type_width = []
                default_width = None
                for t, p_vals in sorted(type_to_param_values.items(),
                                        key=lambda x: x[0].bit_length()):
                    cond = And(*(param_sig_by_name[p.hdl_name]._eq(p_val)
                                 for p, p_val in p_vals if p in params_used))
                    w = t.bit_length()
                    if default_width is None:
                        default_width = w
                    condition_and_type_width.append((cond, w))

                t = parent_port._dtype
                t._bit_length = reduce_ternary(condition_and_type_width,
                                               default_width)
                t._bit_length._const = True
                updated_type_ids.add(id(t))