def _impl(self): DW = int(self.DATA_WIDTH) polyBits, PW = self.parsePoly(self.POLY, self.POLY_WIDTH) # xorMatrix = buildCrcMatrix_dataMatrix(polyCoefs, PW, DW) # initXorMatrix = buildCrcMatrix_reg0Matrix(polyCoefs, PW, DW) XOROUT = int(self.XOROUT) _INIT = int(self.INIT) initBits = [hBit(selectBit(_INIT, i)) for i in range(PW)] finBits = [hBit(selectBit(XOROUT, i)) for i in range(PW)] # rename to have shorter code _inD = self._sig("d", self.dataIn._dtype) _inD(self.dataIn) inBits = list(iterBits(_inD)) if not self.IN_IS_BIGENDIAN: inBits = reversedEndianity(inBits) outBits = iterBits(self.dataOut) crcMatrix = self.buildCrcXorMatrix(DW, polyBits) res = self.applyCrcXorMatrix(crcMatrix, inBits, initBits, bool(self.REFIN)) if self.REFOUT: res = list(reversed(res)) finBits = reversedBitsInBytes(finBits) for ob, b, fb in zip(outBits, res, finBits): ob(b ^ fb)
def _impl(self): DW = int(self.DATA_WIDTH) polyBits, PW = self.parsePoly(self.POLY, self.POLY_WIDTH) # xorMatrix = buildCrcMatrix_dataMatrix(polyCoefs, PW, DW) # initXorMatrix = buildCrcMatrix_reg0Matrix(polyCoefs, PW, DW) XOROUT = int(self.XOROUT) _INIT = int(self.INIT) initBits = [hBit(selectBit(_INIT, i)) for i in range(PW)] finBits = [hBit(selectBit(XOROUT, i)) for i in range(PW)] # rename to have shorter code _inD = self._sig("d", self.dataIn._dtype) _inD(self.dataIn) inBits = list(iterBits(_inD)) if not self.IN_IS_BIGENDIAN: inBits = reversedEndianity(inBits) outBits = iterBits(self.dataOut) crcMatrix = self.buildCrcXorMatrix(DW, polyBits) res = self.applyCrcXorMatrix( crcMatrix, inBits, initBits, bool(self.REFIN)) if self.REFOUT: res = list(reversed(res)) finBits = reversedBitsInBytes(finBits) for ob, b, fb in zip(outBits, res, finBits): ob(b ^ fb)
def _impl(self): DW = int(self.DATA_WIDTH) polyBits, PW = self.parsePoly(self.POLY, self.POLY_WIDTH) XOROUT = int(self.XOROUT) _INIT = int(self.INIT) initBits = [BIT.from_py(get_bit(_INIT, i)) for i in range(PW)] finBits = [BIT.from_py(get_bit(XOROUT, i)) for i in range(PW)] # rename to have shorter code _inD = self._sig("d", self.dataIn._dtype) _inD(self.dataIn) inBits = list(iterBits(_inD)) if not self.IN_IS_BIGENDIAN: # we need to process lower byte first inBits = bit_list_reversed_endianity(inBits, extend=False) crcMatrix = self.buildCrcXorMatrix(DW, polyBits) res = self.applyCrcXorMatrix(crcMatrix, inBits, initBits, bool(self.REFIN)) if self.REFOUT: res = list(reversed(res)) finBits = bit_list_reversed_bits_in_bytes(finBits, extend=False) outBits = iterBits(self.dataOut) for ob, b, fb in zip(outBits, res, finBits): ob(b ^ fb)
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 packAxiSFrame(dataWidth, structVal, withStrb=False): """ pack data of structure into words on axis interface """ if withStrb: byte_cnt = dataWidth // 8 words = iterBits(structVal, bitsInOne=dataWidth, skipPadding=False, fillup=True) for last, d in iter_with_last(words): assert d._dtype.bit_length() == dataWidth, d._dtype.bit_length() if withStrb: word_mask = 0 for B_i in range(byte_cnt): m = get_bit_range(d.vld_mask, B_i * 8, 8) if m == 0xff: word_mask = set_bit(word_mask, B_i) else: assert m == 0, ("Each byte has to be entirely valid" " or entirely invalid," " because of mask granularity", m) yield (d, word_mask, last) else: yield (d, last)
def hstruct_checksum(structVal): """ Checksum of values in StructValue instance """ valAsBytes = iterBits(structVal, bitsInOne=8) valAsBytes = [x.val for x in valAsBytes] return checksum(valAsBytes)
def _test_s0(self, u): DW = 64 N = 3 self.compileSimAndStart(u) m = AxiDpSimRam(DW, u.clk, u.rDatapump) # init expectedFieldValues expectedFieldValues = {} for f in s0.fields: if f.name is not None: expectedFieldValues[f.name] = [] for _ in range(N): d = s0RandVal(self) for name, val in d.items(): expectedFieldValues[name].append(val) asFrame = list( iterBits(s0.from_py(d), bitsInOne=DW, skipPadding=False, fillup=True)) addr = m.calloc(len(asFrame), DW // 8, initValues=asFrame) assert m.getStruct(addr, s0) == s0.from_py(d) u.get._ag.data.append(addr) self.runSim(500 * Time.ns) for f in s0.fields: if f.name is not None: expected = expectedFieldValues[f.name] got = u.dataOut._fieldsToInterfaces[(f.name, )]._ag.data self.assertValSequenceEqual(got, expected, f.name)
def _downscale(self, factor): inputRegs_cntr = self._reg("inputRegs_cntr", Bits(log2ceil(factor + 1), False), defVal=0) # instantiate HandshakedReg, handshaked builder is not used to avoid dependencies inReg = HandshakedReg(self.intfCls) inReg._updateParamsFrom(self.dataIn) self.inReg = inReg inReg.clk(self.clk) inReg.rst_n(self.rst_n) inReg.dataIn(self.dataIn) dataIn = inReg.dataOut dataOut = self.dataOut # create output mux for din, dout in zip(self.getData(dataIn), self.getData(dataOut)): widthOfPart = din._dtype.bit_length() // factor inParts = iterBits(din, bitsInOne=widthOfPart) Switch(inputRegs_cntr).addCases( [(i, dout(inPart)) for i, inPart in enumerate(inParts)] ) self.getVld(dataOut)(self.getVld(dataIn)) self.getRd(dataIn)(inputRegs_cntr._eq(factor - 1) & self.getRd(dataOut)) If(self.getVld(dataIn) & self.getRd(dataOut), If(inputRegs_cntr._eq(factor - 1), inputRegs_cntr(0) ).Else( inputRegs_cntr(inputRegs_cntr + 1) ) )
def hstruct_checksum(structVal): """ Checksum of values in StructValue instance """ valAsBytes = iterBits(structVal, bitsInOne=8) valAsBytes = list(map(lambda x: x.val, valAsBytes)) return checksum(valAsBytes)
def _test_s0(self, u): DW = 64 N = 3 self.prepareUnit(u) m = DenseMemory(DW, u.clk, u.rDatapump) # init expectedFieldValues expectedFieldValues = {} for f in s0.fields: if f.name is not None: expectedFieldValues[f.name] = [] for _ in range(N): d = s0RandVal(self) for name, val in d.items(): expectedFieldValues[name].append(val) asFrame = list(iterBits(s0.fromPy(d), bitsInOne=DW, skipPadding=False, fillup=True)) addr = m.calloc(len(asFrame), DW // 8, initValues=asFrame) u.get._ag.data.append(addr) self.runSim(500 * Time.ns) for f in s0.fields: if f.name is not None: expected = expectedFieldValues[f.name] got = u.dataOut._fieldsToInterfaces[f]._ag.data self.assertValSequenceEqual(got, expected)
def _downscale(self, factor): inputRegs_cntr = self._reg("inputRegs_cntr", Bits(log2ceil(factor + 1), False), def_val=0) # instantiate HandshakedReg, handshaked builder is not used to avoid dependencies inReg = HandshakedReg(self.intfCls) inReg._updateParamsFrom(self.dataIn) self.inReg = inReg inReg.clk(self.clk) inReg.rst_n(self.rst_n) inReg.dataIn(self.dataIn) dataIn = inReg.dataOut dataOut = self.dataOut # create output mux for din, dout in zip(self.get_data(dataIn), self.get_data(dataOut)): widthOfPart = din._dtype.bit_length() // factor inParts = iterBits(din, bitsInOne=widthOfPart) Switch(inputRegs_cntr).add_cases( [(i, dout(inPart)) for i, inPart in enumerate(inParts)] ) vld = self.get_valid_signal rd = self.get_ready_signal vld(dataOut)(vld(dataIn)) self.get_ready_signal(dataIn)(inputRegs_cntr._eq(factor - 1) & rd(dataOut)) If(vld(dataIn) & rd(dataOut), If(inputRegs_cntr._eq(factor - 1), inputRegs_cntr(0) ).Else( inputRegs_cntr(inputRegs_cntr + 1) ) )
def test_struct_packUnpack(self): f = self.create_ICMP_echo_frame() asBytes = iterBits(f, bitsInOne=8, skipPadding=False) asBytes = [valToInt(x) for x in asBytes] f_out = HdlValue_unpack(echoFrame_t, asBytes, dataWidth=8) self.assertEqual(f, f_out) _f = f f = f_out asBytes = iterBits(f, bitsInOne=8, skipPadding=False) asBytes = [valToInt(x) for x in asBytes] f_out = HdlValue_unpack(echoFrame_t, asBytes, dataWidth=8) self.assertEqual(_f, f_out)
def test_struct_packUnpack(self): f = self.create_ICMP_echo_frame() asBytes = iterBits(f, bitsInOne=8, skipPadding=False) asBytes = list(map(valToInt, asBytes)) f_out = HStruct_unpack(echoFrame_t, asBytes, dataWidth=8) self.assertEqual(f, f_out) _f = f f = f_out asBytes = iterBits(f, bitsInOne=8, skipPadding=False) asBytes = list(map(valToInt, asBytes)) f_out = HStruct_unpack(echoFrame_t, asBytes, dataWidth=8) self.assertEqual(_f, f_out)
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 reinterpret_bits_to_harray(sigOrVal, hArrayT): elmT = hArrayT.element_t elmWidth = elmT.bit_length() a = hArrayT.from_py(None) for i, item in enumerate( iterBits(sigOrVal, bitsInOne=elmWidth, skipPadding=False)): item = item._reinterpret_cast(elmT) a[i] = item return a
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 is_mask_byte_unaligned(mask_signal: RtlSignal) -> RtlSignal: # True if each byte of the mask is all 0 or all 1 we_bytes = list(iterBits(mask_signal, bitsInOne=8, fillup=True)) write_mask_not_aligned = [] for last, b in iter_with_last(we_bytes): if last: # cut off padding if required mask_rem_w = mask_signal._dtype.bit_length() % 8 if mask_rem_w: b = b[mask_rem_w:] write_mask_not_aligned.append((b != 0) & (b != mask(b._dtype.bit_length()))) return Or(*write_mask_not_aligned)
def _impl(self): accumulator = self._reg("accumulator", Bits(self.POLY_WIDTH), defVal=self.INIT) POLY = int(self.POLY) xorBits = [] for i, b in enumerate(iterBits(accumulator)): if selectBit(POLY, i): xorBits.append(b) assert xorBits nextBit = Xor(*xorBits) accumulator(Concat(accumulator[self.POLY_WIDTH - 1:], nextBit)) self.dataOut(accumulator[0])
def reinterpret_bits_to_harray(sigOrVal: Union[RtlSignal, HValue], hArrayT: HArray): elmT = hArrayT.element_t elmWidth = elmT.bit_length() if isinstance(sigOrVal, HValue): a = hArrayT.from_py(None) else: a = HObjList([None for _ in range(hArrayT.size)]) for i, item in enumerate(iterBits(sigOrVal, bitsInOne=elmWidth, skipPadding=False)): item = item._reinterpret_cast(elmT) a[i] = item return a
def packAxiSFrame(dataWidth, structVal, withStrb=False): """ pack data of structure into words on axis interface """ if withStrb: maskAll = mask(dataWidth // 8) words = iterBits(structVal, bitsInOne=dataWidth, skipPadding=False, fillup=True) for last, d in iter_with_last(words): assert d._dtype.bit_length() == dataWidth, d._dtype.bit_length() if withStrb: # [TODO] mask in last resolved from size of datatype, mask for padding yield (d, maskAll, last) else: yield (d, last)
def packAxiSFrame(dataWidth, structVal, withStrb=False): """ pack data of structure into words on axis interface """ if withStrb: maskAll = mask(dataWidth // 8) words = iterBits(structVal, bitsInOne=dataWidth, skipPadding=False, fillup=True) for last, d in iter_with_last(words): assert d._dtype.bit_length() == dataWidth, d._dtype.bit_length() if withStrb: # [TODO] mask in last resolved from size of datatype, mask for padding yield (d, maskAll, last) else: yield (d, last)
def test_reply1x(self): u = self.u f = self.create_ICMP_echo_frame() u.rx._ag.data.extend(packAxiSFrame(self.DATA_WIDTH, f, withStrb=False)) u.myIp._ag.data.append(int.from_bytes(socket.inet_aton("192.168.0.2"), byteorder="little")) self.runSim(500 * Time.ns) res = unpackAxiSFrame(echoFrame_t, u.tx._ag.data) model_res = pingResponder_model(f) _res = iterBits(res, bitsInOne=8, skipPadding=False) _res = bytes(map(valToInt, _res)) # print("") # print("f", f) # print("res", res) # print("model_res", HStruct_unpack(echoFrame_t, model_res, dataWidth=8)) self.assertEqual(_res, model_res)
def pingResponder_model(packetStructVal): """ Modify ICMP Echo Request to an ICMP Echo Reply packet. :param packet: struct val of packet """ packet = iterBits(packetStructVal, bitsInOne=8, skipPadding=False) packet = [valToInt(p) for p in packet] eth = 0 # swap eht addr (packet[(eth + 0):(eth + 6)], packet[(eth + 6):(eth + 12)]) = (packet[(eth + 6):(eth + 12)], packet[(eth + 0):(eth + 6)]) ip = 2 * 6 + 2 # Swap source and destination address. (packet[(ip + 12):(ip + 16)], packet[(ip + 16):(ip + 20)]) = (packet[(ip + 16):(ip + 20)], packet[(ip + 12):(ip + 16)]) icmp = ip + 20 # Change ICMP type code to Echo Reply (0). packet[icmp] = ICMP_TYPE.ECHO_REPLY # clean checksum packet[icmp + 2] = 0 packet[icmp + 3] = 0 # Calculate new ICMP Checksum field. checksum = 0 # for every 16-bit of the ICMP payload: for i in range(icmp, len(packet), 2): half_word = (packet[i] << 8) + (packet[i + 1]) checksum += half_word # Get one's complement of the checksum. checksum = ~checksum & 0xffff # Put the new checksum back into the packet. (bigendian) packet[icmp + 2] = checksum >> 8 packet[icmp + 3] = checksum & ((1 << 8) - 1) return bytes(packet)
def priorityAck(priorityReg, vldSignals, index): """ Generate ack logic for selected input :param priorityReg: priority register with one hot encoding, 1 means input of this index should have be prioritized. :param vldSignals: list of vld signals of input :param index: index of input for which you wont get ack logic :return: ack signal for this input """ priorityOverdrives = [] vldWithHigherPriority = list(vldSignals[:index]) for i, (p, vld) in enumerate(zip(iterBits(priorityReg), vldSignals)): if i > index: priorityOverdrives.append(p & vld) # ack when no one with higher priority has vld or this input have the # priority ack = ~Or(*priorityOverdrives, * vldWithHigherPriority) | priorityReg[index] return ack
def priorityAck(priorityReg, vldSignals, index): """ Generate ack logic for selected input :param priorityReg: priority register with one hot encoding, 1 means input of this index should have be prioritized. :param vldSignals: list of vld signals of input :param index: index of input for which you wont get ack logic :return: ack signal for this input """ priorityOverdrives = [] vldWithHigherPriority = list(vldSignals[:index]) for i, (p, vld) in enumerate(zip(iterBits(priorityReg), vldSignals)): if i > index: priorityOverdrives.append(p & vld) # ack when no one with higher priority has vld or this input have the # priority ack = ~Or(*priorityOverdrives, * vldWithHigherPriority) | priorityReg[index] return ack
def pingResponder_model(packetStructVal): """ Modify ICMP Echo Request to an ICMP Echo Reply packet. :param packet: struct val of packet """ packet = iterBits(packetStructVal, bitsInOne=8, skipPadding=False) packet = list(map(valToInt, packet)) eth = 0 # swap eht addr packet[(eth + 0):(eth + 6)], packet[(eth + 6):(eth + 12)] = packet[(eth + 6):(eth + 12)], packet[(eth + 0):(eth + 6)] ip = 2 * 6 + 2 # Swap source and destination address. packet[(ip + 12):(ip + 16)], packet[(ip + 16):(ip + 20)] = packet[(ip + 16):(ip + 20)], packet[(ip + 12):(ip + 16)] icmp = ip + 20 # Change ICMP type code to Echo Reply (0). packet[icmp] = ICMP_TYPE.ECHO_REPLY # clean checksum packet[icmp + 2] = 0 packet[icmp + 3] = 0 # Calculate new ICMP Checksum field. checksum = 0 # for every 16-bit of the ICMP payload: for i in range(icmp, len(packet), 2): half_word = (packet[i] << 8) + (packet[i + 1]) checksum += half_word # Get one's complement of the checksum. checksum = ~checksum & 0xffff # Put the new checksum back into the packet. (bigendian) packet[icmp + 2] = checksum >> 8 packet[icmp + 3] = checksum & ((1 << 8) - 1) return bytes(packet)
def _impl(self): self.bin.data(oneHotToBin(self, self.oneHot)) self.bin.vld(Or(*[bit for bit in iterBits(self.oneHot)]))
def _impl(self): self.bin.data(oneHotToBin(self, self.oneHot)) self.bin.vld(Or(*[bit for bit in iterBits(self.oneHot)]))
def reversedBits(sigOrVal): return Concat(*list(iterBits(sigOrVal)))
def _impl(self): # prepare constants and bit arrays for inputs poly_bits, PW = CrcComb.parsePoly(self.POLY, self.POLY_WIDTH) din = self.dataIn # rename "dataIn_data" to "d" to make code shorter _d = rename_signal(self, din.data, "d") data_in_bits = list(iterBits(_d)) if not self.IN_IS_BIGENDIAN: data_in_bits = bit_list_reversed_endianity(data_in_bits) if self.MASK_GRANULARITY: din.rd(1) rst = self.rst_n._isOn() | (din.vld & din.last) else: rst = self.rst_n state = self._reg("c", Bits(self.POLY_WIDTH), self.INIT, rst=rst) state_in_bits = list(iterBits(state)) if self.MASK_GRANULARITY is None or self.MASK_GRANULARITY == self.DATA_WIDTH: state_next = self.build_crc_xor_matrix(state_in_bits, poly_bits, data_in_bits) If( din.vld, # state_next is in format 0 ... N, # we need to reverse it to litle-endian state(Concat(*reversed(state_next)))) else: mask_in = din.mask mask_width = mask_in._dtype.bit_length() state_next_cases = [] for vld_byte_cnt in range(1, mask_width + 1): # because bytes are already reversed in bit vector of input bits _data_in_bits = data_in_bits[(mask_width - vld_byte_cnt) * self.MASK_GRANULARITY:] state_next = self.build_crc_xor_matrix(state_in_bits, poly_bits, _data_in_bits) # reversed because of because of MSB..LSB state_next_cases.append( (mask(vld_byte_cnt), state(Concat(*reversed(state_next))))) If( din.vld, Switch(mask_in).add_cases(state_next_cases).Default( state(None))) # output connection if self.LATENCY == 0: state = state.next elif self.LATENCY == 1: if self.MASK_GRANULARITY is not None: # to avoid the case where the state is restarted by dataIn.last state_tmp = self._reg("state_tmp", state._dtype) state_tmp(state.next) state = state_tmp else: raise NotImplementedError(self.LATENCY) XOROUT = int(self.XOROUT) fin_bits = [BIT.from_py(get_bit(XOROUT, i)) for i in range(PW)] fin_bits = rename_signal(self, Concat(*fin_bits), "fin_bits") if self.REFOUT: state_reversed = rename_signal(self, Concat(*iterBits(state)), "state_revered") state = state_reversed self.dataOut(state ^ fin_bits)