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 setUpCrc(self, poly, dataWidth=None, refin=None, refout=None, initval=None, finxor=None, bigendian=False): if dataWidth is None: dataWidth = poly.WIDTH u = self.u = CrcComb() u.setConfig(poly) u.DATA_WIDTH = dataWidth if initval is not None: u.INIT = Bits(poly.WIDTH).from_py(initval) if refin is not None: u.REFIN = refin if refout is not None: u.REFOUT = refout if finxor is not None: u.XOROUT = Bits(poly.WIDTH).from_py(finxor) u.IN_IS_BIGENDIAN = bigendian self.compileSimAndStart(u) return u
def naive_crc(dataBits, crcBits, polyBits, refin=False, refout=False): crc_mask = CrcComb.buildCrcXorMatrix(len(dataBits), polyBits) dataBits = bit_list_reversed_endianity(dataBits) # print("") # for r in crc_mask: # print(r) if refin: # reflect bytes in input data signal # whole signal should not be reflected if DW > PW # polyBits = list(reversed(polyBits)) dataBits = bit_list_reversed_bits_in_bytes(dataBits) # crcBits = reversedBitsInBytes(crcBits) res = [] for stateMask, dataMask in crc_mask: # if refin: # stateMask = reversed(stateMask) # dataMask = reversed(dataMask) v = 0 for useBit, b in zip(stateMask, crcBits): if useBit: v ^= b for useBit, b in zip(dataMask, dataBits): if useBit: v ^= b res.append(v) assert len(res) == len(polyBits) if refout: res = reversed(res) return bit_list_to_int(res)
def build_crc_xor_matrix(self, state_in_bits: List[RtlSignal], poly_bits: List[int], data_in_bits:[RtlSignal])\ ->List[RtlSignal]: """ build xor tree for CRC computation """ crcMatrix = CrcComb.buildCrcXorMatrix(len(data_in_bits), poly_bits) res = CrcComb.applyCrcXorMatrix(crcMatrix, data_in_bits, state_in_bits, self.REFIN) # next state logic # wrap crc next signals to separate signal to have nice code stateNext = [] for i, crcbit in enumerate(res): b = rename_signal(self, crcbit, f"crc_{i:d}") stateNext.append(b) return stateNext
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 setUpCrc(self, poly, dataWidth=None, refin=False, refout=False, initval=0, finxor=0): if dataWidth is None: dataWidth = poly.WIDTH u = self.u = CrcComb() self.DATA_WIDTH = dataWidth self.POLY_WIDTH = poly.WIDTH u.DATA_WIDTH.set(dataWidth) u.POLY_WIDTH.set(poly.WIDTH) u.POLY.set(vec(poly.POLY, poly.WIDTH)) u.INIT.set(vec(initval, poly.WIDTH)) u.REFIN.set(refin) u.REFOUT.set(refout) u.XOROUT.set(vec(finxor, poly.WIDTH)) self.prepareUnit(u) return u
def _declr(self): addClkRstn(self) assert int(self.KEY_WIDTH) > 0 assert int(self.DATA_WIDTH) >= 0 assert int(self.ITEMS_CNT) > 1 self.HASH_WITH = log2ceil(self.ITEMS_CNT).val assert self.HASH_WITH < int(self.KEY_WIDTH), ( "It makes no sense to use hash table when you can use key directly as index", self.HASH_WITH, self.KEY_WIDTH) with self._paramsShared(): self.insert = InsertIntf() self.insert.HASH_WIDTH.set(self.HASH_WITH) self.lookup = LookupKeyIntf() self.lookupRes = LookupResultIntf()._m() self.lookupRes.HASH_WIDTH.set(self.HASH_WITH) t = self.table = RamSingleClock() t.PORT_CNT.set(1) t.ADDR_WIDTH.set(log2ceil(self.ITEMS_CNT)) t.DATA_WIDTH.set(self.KEY_WIDTH + self.DATA_WIDTH + 1) # +1 for vldFlag tc = self.tableConnector = RamAsHs() tc.ADDR_WIDTH.set(t.ADDR_WIDTH.get()) tc.DATA_WIDTH.set(t.DATA_WIDTH.get()) hashWidth = max(int(self.KEY_WIDTH), int(self.HASH_WITH)) h = self.hash = CrcComb() h.DATA_WIDTH.set(hashWidth) h.setConfig(self.POLYNOME) h.POLY_WIDTH.set(hashWidth)
def setConfig(self, crcConfigCls): """ Apply configuration from CRC configuration class """ CrcComb.setConfig(self, crcConfigCls)
def _config(self): CrcComb._config(self)
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)
def _config(self): CrcComb._config(self) self.setConfig(CRC_32) self.LATENCY = Param(1) self.DATA_WIDTH = 32 self.MASK_GRANULARITY = Param(None)
def test_CrcComb(self): u = CrcComb() u.DATA_WIDTH = 8 convert(u)