def translate_addr_signal(self, mem_map, sig_in, sig_out): cases = [] AW = sig_in._dtype.bit_length() for (offset_in, size, offset_out) in mem_map: in_is_aligned = offset_in % size == 0 and isPow2(size) out_is_aligned = offset_out % size == 0 and isPow2(size) if in_is_aligned: L = (size - 1).bit_length() en_sig = sig_in[:L]._eq(offset_in >> L) _sig_in = sig_in[L:] if out_is_aligned: addr_drive = Concat( Bits(AW - L).from_py(offset_out), _sig_in) else: addr_drive = Concat(Bits(AW - L).from_py(0), _sig_in) + offset_out else: en_sig = inRange(sig_in, offset_in, offset_in + size) if offset_in == offset_out: addr_drive = sig_in elif offset_in < offset_out: addr_drive = sig_in + (offset_out - offset_in) else: # offset_in > offset_out: addr_drive = sig_in - (offset_in - offset_out) cases.append((en_sig, sig_out(addr_drive))) SwitchLogic(cases, default=sig_out(sig_in))
def propagate(self, src_addr_sig, dst_addr_sig, dst_offset: int = 0): """ :param src_addr_sig: input signal with address :param dst_addr_sig: output signal for address """ src_addr_step, dst_addr_step = self.src_addr_step, self.dst_addr_step if src_addr_step != dst_addr_step: src_w = src_addr_sig._dtype.bit_length() dst_w = dst_addr_sig._dtype.bit_length() if src_addr_step > dst_addr_step: # extend src address assert src_w + self.align_bits <= dst_w, ( "Destination address space is smaller than required", src_addr_sig, dst_addr_sig, src_w, self.align_bits, dst_w) padding = Bits(self.align_bits).from_py(0) src_addr_sig = Concat(src_addr_sig, padding) else: # cut src address assert src_w - self.align_bits <= dst_w, ( "Destination address space is smaller than required", src_addr_sig, dst_addr_sig, src_w, self.align_bits, dst_w) src_addr_sig = src_addr_sig[:self.align_bits] # first extend then add if required to prevent value overflow src_addr_sig = src_addr_sig._reinterpret_cast(dst_addr_sig._dtype) if dst_offset != 0: src_addr_sig = src_addr_sig + dst_offset return dst_addr_sig(src_addr_sig)
def connect_update_port(self, update: AxiCacheTagArrayUpdateIntf, tag_mem_port_w: BramPort_withoutClk): update_tmp = self._reg("update_tmp", HStruct( (update.addr._dtype, "addr"), (BIT, "delete"), (update.way_en._dtype, "way_en"), (BIT, "vld"), ), def_val={"vld": 0}) update_tmp(update) tag, index, _ = self.parse_addr(update.addr) tag_mem_port_w.en(update.vld) tag_mem_port_w.addr(index) # construct the byte enable mask for various tag enable configurations # prepare write tag in every way but byte enable only requested ways tag_record = self.tag_record_t.from_py({ "tag": tag, "valid": ~update.delete, }) tag_record = tag_record._reinterpret_cast( Bits(self.tag_record_t.bit_length())) tag_mem_port_w.din(Concat(*(tag_record for _ in range(self.WAY_CNT)))) tag_be_t = Bits(self.tag_record_t.bit_length() // 8) tag_en = tag_be_t.from_py(tag_be_t.all_mask()) tag_not_en = tag_be_t.from_py(0) tag_mem_port_w.we( Concat(*reversed( [en._ternary(tag_en, tag_not_en) for en in update.way_en]))) return update_tmp
def _impl(self): st_t = HEnum("state_t", ["IDLE", "LOAD_SR", "CONVERTING", "DONE"]) st = self._reg("st", st_t, def_val=st_t.IDLE) sr_shift = st.next._eq(st_t.CONVERTING) bcd = self.din bin_ = self.dout bcd_sr = self._reg("bcd_sr", bcd.data._dtype, def_val=0) binary_sr = self._reg("binary_sr", bin_.data._dtype, def_val=0) next_bcd = rename_signal(self, bcd_sr >> 1, "next_bcd") MAX_COUNT = binary_sr._dtype.bit_length() bit_count = self._reg("bit_count", Bits(log2ceil(MAX_COUNT), signed=False), def_val=MAX_COUNT) If(sr_shift, bit_count(bit_count - 1), ).Else( bit_count(MAX_COUNT), ) # dabble the digits digits = [] for i in range(self.BCD_DIGITS): d = next_bcd[(i + 1) * 4:i * 4]._unsigned() d_sig = (d < 7)._ternary(d, d - 3) digits.append(d_sig) If(st.next._eq(st_t.LOAD_SR), bcd_sr(bcd.data), binary_sr(0), ).Elif(sr_shift, # shift right binary_sr(Concat(bcd_sr[0], binary_sr[:1])), bcd_sr(Concat(*reversed(digits))), ) bin_.data(binary_sr) Switch(st)\ .Case(st_t.IDLE, If(bcd.vld, st(st_t.LOAD_SR), # load the shift registers ))\ .Case(st_t.LOAD_SR, # shift right each cycle st(st_t.CONVERTING), )\ .Case(st_t.CONVERTING, If(bit_count._eq(0), # indicate completion st(st_t.DONE), ) )\ .Case(st_t.DONE, If(bcd.vld & bin_.rd, st(st_t.LOAD_SR), ).Elif(bin_.rd, st(st_t.IDLE), ) ) bcd.rd(st._eq(st_t.IDLE) | (st._eq(st_t.DONE) & bin_.rd)) bin_.vld(st._eq(st_t.DONE))
def _impl(self) -> None: start = self._sig("start") part_res_t = Bits(self.DATA_WIDTH) # High-order n bits of product a = self._reg("a", part_res_t) # multiplicand m = self._reg("m", part_res_t) # Initially holds multiplier, ultimately holds low-order n bits of product q = self._reg("q", part_res_t) # previous bit 0 of q q_1 = self._reg("q_1") din = self.dataIn dout = self.dataOut counter = self._reg( "counter", Bits(log2ceil(self.DATA_WIDTH + 1), signed=False), def_val=0) done = counter._eq(0) waitinOnConsumer = self._reg("waitinOnConsumer", def_val=0) add = rename_signal(self, (a + m)._signed(), "add") sub = rename_signal(self, (a - m)._signed(), "sub") If(start, a(0), m(din.a), q(din.b), q_1(0), counter(self.DATA_WIDTH), ).Elif(~done, Switch(Concat(q[0], q_1)) .Case(0b01, # add multiplicand to left half of product a(add >> 1), q(Concat(add[0], q[:1])), ).Case(0b10, # substract multiplicand from left half of product a(sub >> 1), q(Concat(sub[0], q[:1])), ).Default( a(a._signed() >> 1), q(Concat(a[0], q[:1])), ), q_1(q[0]), counter(counter - 1) ) If(start, waitinOnConsumer(1) ).Elif(done & dout.rd, waitinOnConsumer(0), ) dout.data(Concat(a, q)._vec()) dout.vld(done & waitinOnConsumer) start(din.vld & done & ~waitinOnConsumer) din.rd(done & ~waitinOnConsumer)
def _impl(self): w = self.port[0] ram_w = self.ram.port[0] # True if each byte of the mask is 0xff or 0x00 we_bytes = list(iterBits(w.we, bitsInOne=8, fillup=True)) # cut off padding we_for_we_bytes = [] for last, b in iter_with_last(we_bytes): if last and self.MASK_PADDING_W: mask_rem_w = self.MASK_W % 8 b = b[mask_rem_w:] we_for_we_bytes.append(b != 0) we_for_we_bytes = rename_signal( self, Concat(*[ b | ~w.do_accumulate | w.do_overwrite for b in reversed(we_for_we_bytes) ]), "we_for_we_bytes") preload = self._reg("preload", def_val=0) If(w.en.vld, preload(~preload & w.do_accumulate & ~w.do_overwrite)) w.en.rd(~w.do_accumulate | w.do_overwrite | preload) ram_w.addr(w.addr) ram_w.en(w.en.vld & (w.do_overwrite | ~w.do_accumulate | preload)) ram_w.we(Concat(w.we, we_for_we_bytes)) w_mask = w.we if self.MASK_PADDING_W: w_mask = Concat(Bits(self.MASK_PADDING_W).from_py(0), w_mask) is_first_read_port = True for ram_r, r in zip(self.ram.port[1:], self.port[1:]): if is_first_read_port: w_mask = preload._ternary( w_mask | ram_r.dout[self.MASK_PADDING_W + self.MASK_W:], w_mask) w_mask = rename_signal(self, w_mask, "w_mask") ram_w.din(Concat(w.din, w_mask)) will_preload_for_accumulate = rename_signal( self, w.en.vld & w.do_accumulate & ~w.do_overwrite, "will_preload_for_accumulate") ram_r.addr(will_preload_for_accumulate._ternary( w.addr, r.addr)) ram_r.en(will_preload_for_accumulate | r.en.vld) # [TODO] check if r.en.rd is according to spec r.en.rd(~will_preload_for_accumulate | preload) is_first_read_port = False else: ram_r.addr(r.addr) ram_r.en(r.en.vld) r.en.rd(1) r.dout(ram_r.dout[:self.MASK_PADDING_W + self.MASK_W]) r.dout_mask(ram_r.dout[self.MASK_W:]) propagateClkRstn(self)
def expand_byte_mask_to_bit_mask(m): res = [] for b in m: B = [] for _ in range(8): B.append(b) res.append(Concat(*B)) return Concat(*reversed(res))
def insertLogic(self, ramW): In = self.insert if self.DATA_WIDTH: rec = Concat(In.key, In.data, In.vldFlag) else: rec = Concat(In.key, In.vldFlag) ramW.data(rec) ramW.addr(In.hash) StreamNode(masters=[In], slaves=[ramW]).sync()
def matchHandler(self, mem, key: Handshaked, match_res: Handshaked): key_data = key.data if self.USE_VLD_BIT: key_data = Concat(key.data, BIT.from_py(1)) out_one_hot = [] for i in range(self.ITEMS): b = mem[i]._eq(key_data) out_one_hot.append(b) match_res.data(Concat(*reversed(out_one_hot))) StreamNode([key], [match_res]).sync()
def delegate_to_children(self): MAX_DW = self.MAX_BLOCK_DATA_WIDTH DW = self.DATA_WIDTH for ports in zip(self.port, *[c.port for c in self.children]): dout = [] p = ports[0] clk = getattr(p, "clk", None) for i, cp in enumerate(ports[1:]): cp.en(p.en) cp.addr(p.addr) if p.HAS_R: dout.append(cp.dout) if p.HAS_W: if p.HAS_BE: cp.we(p.we[min((i + 1) * (MAX_DW // 8), DW // 8):i * (MAX_DW // 8)]) elif p.HAS_R: cp.we(p.we) cp.din(p.din[min((i + 1) * (MAX_DW), DW):i * (MAX_DW)]) if clk is not None: cp.clk(clk) if dout: p.dout(Concat(*reversed(dout))) clk = getattr(self, "clk", None) for c in self.children: c.clk(clk)
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)
def _count_leading_recurse(cls, data_in: RtlSignal, bit_to_count: int): """ Construct a balanced tree for counter of leading 0/1 :atterntion: result is for """ assert bit_to_count in (0, 1), bit_to_count in_width = data_in._dtype.bit_length() if in_width == 2: if bit_to_count == 0: return ~data_in[1] else: return data_in[1] else: assert in_width > 2, in_width lhs = data_in[:in_width // 2] rhs = data_in[in_width // 2:] if bit_to_count == 0: left_full = lhs._eq(0) else: left_full = lhs._eq(mask(lhs._dtype.bit_length())) in_ = left_full._ternary(rhs, lhs) half_count = cls._count_leading_recurse(in_, bit_to_count) return Concat(left_full, half_count)
def lookupResOfTablesDriver(self, resRead, resAck): tables = self.tables # one hot encoded index where item should be stored (where was found # or where is place) targetOH = self._reg("targetOH", Bits(self.TABLE_CNT)) res = list(map(lambda t: t.lookupRes, tables)) # synchronize all lookupRes from all tables StreamNode(masters=res).sync(resAck) insertFinal = self._reg("insertFinal") # select empty space or victim witch which current insert item # should be swapped with lookupResAck = StreamNode(masters=map( lambda t: t.lookupRes, tables)).ack() insertFoundOH = list(map(lambda t: t.lookupRes.found, tables)) isEmptyOH = list(map(lambda t:~t.lookupRes.occupied, tables)) _insertFinal = Or(*insertFoundOH, *isEmptyOH) If(resRead & lookupResAck, If(Or(*insertFoundOH), targetOH(Concat(*reversed(insertFoundOH))) ).Else( SwitchLogic([(empty, targetOH(1 << i)) for i, empty in enumerate(isEmptyOH) ], default=If(targetOH, targetOH(ror(targetOH, 1)) ).Else( targetOH(1 << (self.TABLE_CNT - 1)) )) ), insertFinal(_insertFinal) ) return lookupResAck, insertFinal, insertFoundOH, targetOH
def _impl(self): propagateClkRstn(self) r = self._reg START_BIT = hBit(0) STOP_BIT = hBit(1) BITS_TO_SEND = 1 + 8 + 1 BIT_RATE = self.FREQ // self.BAUD assert BIT_RATE >= 1 din = self.dataIn data = r("data", Bits(BITS_TO_SEND)) # data + start bit + stop bit en = r("en", defVal=False) tick, last = ClkBuilder(self, self.clk).timers( [BIT_RATE, BIT_RATE * BITS_TO_SEND], en) If(~en & din.vld, data(Concat(STOP_BIT, din.data, START_BIT)), en(1)).Elif( tick & en, # srl where 1 is shifted from left data(hBit(1)._concat(data[:1])), If( last, en(0), )) din.rd(~en) txd = r("reg_txd", defVal=1) If(tick & en, txd(data[0])) self.txd(txd)
def filter(self, name, sig): """attempt to remove glitches""" filter0 = self._reg(name + "_filter0", dtype=Bits(2), defVal=0) filter0(filter0[0]._concat(sig)) # let filter_cnt to be shared between filters try: filter_clk_cntr = self.filter_clk_cntr except AttributeError: filter_clk_cntr = self.filter_clk_cntr = self._reg("filter_clk_cntr", Bits(self.CLK_CNTR_WIDTH), defVal=self.clk_cnt_initVal) If(filter_clk_cntr._eq(0), filter_clk_cntr(self.clk_cnt_initVal) ).Else( filter_clk_cntr(filter_clk_cntr - 1) ) filter1 = self._reg(name + "_filter1", dtype=Bits(3), defVal=0b111) If(filter_clk_cntr._eq(0), filter1(Concat(filter1[2:], filter0[1])) ) filtered = ((filter1[2] & filter1[1]) | (filter1[2] & filter1[0]) | (filter1[1] & filter1[0])) return filtered
def shift_in_msb_first(reg, sig_in): """ Shift data in to register, MSB first """ w = reg._dtype.bit_length() w_in = sig_in._dtype.bit_length() return reg(Concat(reg[w - w_in:], sig_in))
def _vec_to_signal(extra_strbs: Union[Tuple[int, bool], RtlSignal]): """ :param extra_strbs: number of bits and padding flag or strb signal directly """ res = [] prev_len = 0 prev_val = None for s in extra_strbs: if isinstance(s, Tuple): if prev_val is None: prev_len, prev_val = s assert prev_len > 0, prev_len elif prev_val is s[1]: # try extend prev_len += s[0] else: StrbKeepStash._push_mask_vec(res, prev_len, prev_val) prev_len, prev_val = s elif isinstance(s, (RtlSignal, Interface)): res.append(s) prev_len, prev_val = 0, None if prev_val is not None: StrbKeepStash._push_mask_vec(res, prev_len, prev_val) return Concat(*reversed(res))
def dispatch_addr(self, id_to_use: RtlSignal, addr: RtlSignal, a: Axi4_addr): """ * if there is a valid item in buffer dispatch read request """ a_ld = self._sig("a_ld") a_tmp = self._reg("ar_tmp", HStruct( (a.id._dtype, "id"), (addr._dtype, "addr"), (BIT, "vld"), ), def_val={"vld": 0}) If(a_ld, a_tmp.id(id_to_use), a_tmp.addr(addr), a_tmp.vld(1)).Else(a_tmp.vld(a_tmp.vld & ~a.ready)) a.id(a_tmp.id) a.addr(Concat(a_tmp.addr, Bits(self.CACHE_LINE_OFFSET_BITS).from_py(0))) a.len(self.BUS_WORDS_IN_CACHE_LINE - 1) a.burst(BURST_INCR) a.prot(PROT_DEFAULT) a.size(BYTES_IN_TRANS(self.DATA_WIDTH // 8)) a.lock(LOCK_DEFAULT) a.cache(CACHE_DEFAULT) a.qos(QOS_DEFAULT) a.valid(a_tmp.vld) return a_ld
def _impl(self): START_BIT = 0 STOP_BIT = 1 os = int(self.OVERSAMPLING) baud = int(self.BAUD) freq = int(self.FREQ) assert freq >= baud * os, "Frequency too low for current Baud rate and oversampling" assert os >= 8 and (os & (os - 1)) == 0, "Invalid oversampling value" propagateClkRstn(self) clkBuilder = ClkBuilder(self, self.clk) en = self._reg("en", defVal=0) first = self._reg("first", defVal=1) RxD_data = self._reg("RxD_data", Bits(1 + 8)) startBitWasNotStartbit = self._sig("startBitWasNotStartbit") # it can happen that there is just glitch on wire and bit was not startbit only begin was resolved wrong # eval because otherwise vhdl int overflows sampleTick = clkBuilder.timer( ("sampleTick", self.FREQ // self.BAUD // self.OVERSAMPLING), enableSig=en, rstSig=~en) # synchronize RxD to our clk domain RxD_sync = self._reg("RxD_sync", defVal=1) RxD_sync(self.rxd) rxd, rxd_vld = clkBuilder.oversample(RxD_sync, self.OVERSAMPLING, sampleTick, rstSig=~en) isLastBit = clkBuilder.timer(("isLastBitTick", 10), enableSig=rxd_vld, rstSig=~en) If( en, If( rxd_vld, RxD_data(Concat(rxd, RxD_data[9:1])), # shift data from left If( startBitWasNotStartbit, en(0), first(1), ).Else( en(~isLastBit), first(isLastBit), ))).Elif( RxD_sync._eq(START_BIT), # potential start bit detected, begin scanning sequence en(1), ) startBitWasNotStartbit(first & rxd_vld & (rxd != START_BIT)) self.dataOut.vld(isLastBit & RxD_data[0]._eq(START_BIT) & rxd._eq(STOP_BIT)) self.dataOut.data(RxD_data[9:1])
def deparse_addr(self, tag, index, offset) -> Tuple[RtlSignal, RtlSignal, RtlSignal]: if isinstance(offset, int): offset = Bits(self.OFFSET_W).from_py(offset) if isinstance(index, int): index = Bits(self.INDEX_W).from_py(index) return Concat(tag, index, offset)
def writeHandler(self, mem): w = self.write w.rd(1) key_data = w.data if self.USE_VLD_BIT: key_data = Concat(w.data, w.vld_flag) If(self.clk._onRisingEdge() & w.vld, mem[w.addr](key_data))
def extend_to_width_multiple_of_8(sig): """ make width of signal modulo 8 equal to 0 """ w = sig._dtype.bit_length() cosest_multiple_of_8 = ceil((w // 8) / 8) * 8 if cosest_multiple_of_8 == w: return sig else: return Concat(Bits(cosest_multiple_of_8 - w).from_py(0), sig)
def _impl(self): propagateClkRstn(self) ITEM_WIDTH = int(self.ITEM_WIDTH) DATA_WIDTH = int(self.DATA_WIDTH) ITEMS_IN_DATA_WORD = self.ITEMS_IN_DATA_WORD ITEM_SIZE_IN_WORDS = 1 if ITEM_WIDTH % 8 != 0 or ITEM_SIZE_IN_WORDS * DATA_WIDTH != ITEMS_IN_DATA_WORD * ITEM_WIDTH: raise NotImplementedError(ITEM_WIDTH) req = self.rDatapump.req req.id(self.ID) req.len(ITEM_SIZE_IN_WORDS - 1) req.rem(0) if ITEMS_IN_DATA_WORD == 1: addr = Concat(self.index.data, vec(0, log2ceil(ITEM_WIDTH // 8))) req.addr(self.base + fitTo(addr, req.addr)) StreamNode(masters=[self.index], slaves=[req]).sync() self.item.data(self.rDatapump.r.data) StreamNode(masters=[self.rDatapump.r], slaves=[self.item]).sync() else: r = self.rDatapump.r.data f = self.itemSubIndexFifo subIndexBits = f.dataIn.data._dtype.bit_length() itemAlignBits = log2ceil(ITEM_WIDTH // 8) addr = Concat(self.index.data[:subIndexBits], vec(0, itemAlignBits + subIndexBits)) req.addr(self.base + fitTo(addr, req.addr)) f.dataIn.data(self.index.data[subIndexBits:]) StreamNode(masters=[self.index], slaves=[req, f.dataIn]).sync() Switch(f.dataOut.data).addCases([ (ITEMS_IN_DATA_WORD - i - 1, self.item.data(r[(ITEM_WIDTH * (i + 1)):(ITEM_WIDTH * i)])) for i in range(ITEMS_IN_DATA_WORD) ]) StreamNode(masters=[self.rDatapump.r, f.dataOut], slaves=[self.item]).sync()
def _impl(self): # prepare constants and bit arrays for inputs DW = int(self.DATA_WIDTH) polyBits, PW = CrcComb.parsePoly(self.POLY, self.POLY_WIDTH) XOROUT = int(self.XOROUT) finBits = [hBit(selectBit(XOROUT, i)) for i in range(PW)] # rename "dataIn_data" to "d" to make code shorter _d = self.wrapWithName(self.dataIn.data, "d") inBits = list(iterBits(_d)) if not self.IN_IS_BIGENDIAN: inBits = reversedEndianity(inBits) state = self._reg("c", Bits(self.POLY_WIDTH), self.INIT) stateBits = list(iterBits(state)) # build xor tree for CRC computation crcMatrix = CrcComb.buildCrcXorMatrix(DW, polyBits) res = CrcComb.applyCrcXorMatrix(crcMatrix, inBits, stateBits, bool(self.REFIN)) # next state logic # wrap crc next signals to separate signal to have nice code stateNext = [] for i, crcbit in enumerate(res): b = self.wrapWithName(crcbit, "crc_%d" % i) stateNext.append(b) If( self.dataIn.vld, # regNext is in format 0 ... N, we need to reverse it to litle # endian state(Concat(*reversed(stateNext)))) # output connection if self.REFOUT: finBits = reversed(finBits) self.dataOut( Concat(*[rb ^ fb for rb, fb in zip(iterBits(state), finBits)])) else: self.dataOut(state ^ Concat(*finBits))
def connectPhyout(self, segfaultFlag): phyAddrBase = self.lvl2get.item pageOffset = self.pageOffsetFifo.dataOut segfault = segfaultFlag | phyAddrBase.data[0]._eq(FLAG_INVALID) StreamNode(masters=[phyAddrBase, pageOffset], slaves=[self.physOut], extraConds={self.physOut:~segfault}).sync() self.physOut.data(Concat(phyAddrBase.data[:self.PAGE_OFFSET_WIDTH], pageOffset.data))
def binToOneHot(sig, en=1): try: _en = int(en) except: _en = None res = Concat(*reversed(list(sig._eq(i) for i in range(2 ** sig._dtype.bit_length())))) if _en == 1: return res else: return en._ternary(res, res._dtype.from_py(0))
def _impl(self): propagateClkRstn(self) dIn = AxiSBuilder(self, self.dataIn).buff().end sb = self.sizesBuff db = self.dataBuff wordCntr = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN) + 1), def_val=0) overflow = wordCntr._eq(self.MAX_LEN) last = dIn.last | overflow If( StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn]).ack(), If(last, wordCntr(0)).Else(wordCntr(wordCntr + 1))) length = self._sig("length", wordCntr._dtype) BYTE_CNT = dIn.data._dtype.bit_length() // 8 if dIn.USE_STRB: # compress strb mask as binary number rem = self._sig("rem", Bits(log2ceil(BYTE_CNT))) SwitchLogic(cases=[(dIn.strb[i], rem(0 if i == BYTE_CNT - 1 else i + 1)) for i in reversed(range(BYTE_CNT))], default=[ rem(0), ]) if self.EXPORT_ALIGNMENT_ERROR: errorAlignment = self._reg("errorAlignment_reg", def_val=0) self.errorAlignment(errorAlignment) If(dIn.valid & (dIn.strb != mask(BYTE_CNT)) & ~dIn.last, errorAlignment(1)) If(last & (dIn.strb != mask(BYTE_CNT)), length(wordCntr)).Else(length(wordCntr + 1)) else: length(wordCntr + 1) rem = Bits(log2ceil(BYTE_CNT)).from_py(0) sb.dataIn.data(Concat(length, rem)) db.dataIn(dIn, exclude=[dIn.valid, dIn.ready, dIn.last]) db.dataIn.last(last) StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn], extraConds={ sb.dataIn: last }).sync() self.sizes(sb.dataOut) self.dataOut(db.dataOut)
def applyShift(sh): if sh == 0 and wInfo.SHIFT_OPTIONS[0] == 0: return [ w.data(wIn.data), w.strb(wIn.strb), ] else: rem_w = self.DATA_WIDTH - sh return [ # wIn.data starts on 0 we need to shift it sh bits # in first word the prefix is invalid, in rest of the frames it is taken from # previous data If( waitForShift, w.data( Concat( Bits(rem_w).from_py(None), prevData.data[:rem_w])), ).Else( w.data( Concat(wIn.data[rem_w:], prevData.data[:rem_w])), ), If( waitForShift, # wait until remainder of previous data is send w.strb( Concat( Bits(rem_w // 8).from_py(0), prevData.strb[:rem_w // 8])), ).Elif( isFirst, # ignore previous data w.strb( Concat(wIn.strb[rem_w // 8:], Bits(sh // 8).from_py(0))), ).Else( # take what is left from prev data and append from wIn w.strb( Concat(wIn.strb[rem_w // 8:], prevData.strb[:rem_w // 8])), ) ]
def connectRegisters(self, st, onoff, baseAddr): """ connection of axilite registers """ idle = st._eq(st._dtype.fullIdle) regs = self.regsConventor.decoded regs.control.din(Concat(onoff, idle, vec(0, self.DATA_WIDTH - 2))) If(regs.control.dout.vld, onoff(regs.control.dout.data[0])) c(baseAddr, regs.baseAddr.din) If(regs.baseAddr.dout.vld, baseAddr(regs.baseAddr.dout.data))
def _impl(self): din = self.din internReg = [self._sig("internReg", BIT, defVal=False) for _ in range(2)] If(self.clk._onRisingEdge(), internReg[0](din), ) If(self.clk._onFallingEdge(), internReg[1](din), ) self.dout(Concat(*internReg))