def __getitem__(self, key: Union[int, slice, "Bits3val"]) -> "Bits3val": "self[key]" if isinstance(key, slice): firstBitNo, size = normalize_slice(key, self._dtype.bit_length()) val = get_bit_range(self.val, firstBitNo, size) vld = get_bit_range(self.vld_mask, firstBitNo, size) elif isinstance(key, (int, Bits3val)): size = 1 try: _i = int(key) except ValidityError: _i = None if _i is None: val = 0 vld = 0 else: if _i < 0 or _i >= self._dtype.bit_length(): raise IndexError("Index out of range", _i) val = get_bit(self.val, _i) vld = get_bit(self.vld_mask, _i) else: raise TypeError(key) new_t = self._dtype.__class__(size, signed=self._dtype.signed) return new_t.from_py(val, vld)
def _write_single_word(self, data: HValue, strb: int, word_i: int): if strb == 0: return if strb != self.allMask: cur = self.data.get(word_i, None) if cur is None: cur_val = 0 cur_mask = 0 elif isinstance(cur, int): cur_val = cur cur_mask = self.allMask else: cur_val = cur.val cur_mask = cur.vld_mask for i in range(self.cellSize): if get_bit(strb, i): cur_val = set_bit_range( cur_val, i * 8, 8, get_bit_range(data.val, i * 8, 8)) cur_mask = set_bit_range( cur_mask, i * 8, 8, get_bit_range(data.vld_mask, i * 8, 8)) if cur_mask == self.allMask: data = cur_val else: data = self.word_t.from_py(cur_val, cur_mask) # print(f"data[{word_i:d}] = {data}") self.data[word_i] = data
def is_footer_mask_set_values(self, LOOK_AHEAD, regs): D_W = self.DATA_WIDTH BYTE_CNT = D_W // 8 FOOTER_WIDTH = self.FOOTER_WIDTH din = self.dataIn if self.USE_KEEP: in_mask = din.keep elif self.USE_STRB: in_mask = din.strb elif self.DATA_WIDTH == 8: in_mask = BIT.from_py(1, 1) else: raise NotImplementedError( "keep/strb can be ignored only for DATA_WIDTH=8") set_is_footer = self._sig("set_is_footer") set_is_footer(din.valid & din.last) mask_cases = [] for last_B_valid, bytes_in_last_input_word in iter_with_last( range(1, BYTE_CNT + 1)): footer_end = (LOOK_AHEAD * BYTE_CNT + bytes_in_last_input_word) * 8 footer_start = footer_end - FOOTER_WIDTH assert footer_start > 0, ( "otherwise we would not be able to send last for previous frame", footer_start) assert footer_start < D_W * 3, ( "footer start can appear only in last-1 or last-2 regster," " last register is output register", footer_start, D_W) _is_footer = set_bit_range(0, footer_start // 8, FOOTER_WIDTH // 8, mask(FOOTER_WIDTH // 8)) set_flags = [] for i, (_, _, is_footer_set_val, _, _) in enumerate(regs): if i == 0: is_footer_val = 0 is_footer_val_last_word = get_bit_range( _is_footer, (LOOK_AHEAD - i) * BYTE_CNT, BYTE_CNT) set_flags.append( If(set_is_footer, is_footer_set_val(is_footer_val_last_word)).Else( is_footer_set_val(is_footer_val))) else: is_footer_val = get_bit_range( _is_footer, (LOOK_AHEAD - i + 1) * BYTE_CNT, BYTE_CNT) set_flags.append(is_footer_set_val(is_footer_val)) if last_B_valid: # last byte also valid mask_default = set_flags else: # last 0 from the end of the validity mask mask_cases.append( (~in_mask[bytes_in_last_input_word], set_flags)) SwitchLogic(mask_cases, mask_default) return set_is_footer
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 _append_frame(self, frame: List[int], add_preamble=True): data = self.data if add_preamble: preamble = [ 0x0, *[int(ETH.PREAMBLE_1B) for _ in range(7)], int(ETH.SFD), ] frame = chain(preamble, frame) for b in frame: b01 = b & 0b11 b23 = get_bit_range(b, 2, 2) b45 = get_bit_range(b, 4, 2) b67 = get_bit_range(b, 6, 2) data.extend([b01, b23, b45, b67])
def check_r_trans(self, ar_ref, driver_r_ref): u = self.u self.assertEqual(len(u.driver._ag.req.data), 0) self.assertEqual(len(u.axi.r._ag.data), 0) r_data = [] m_width = u.driver.r.strb._dtype.bit_length() for (d, m, l) in u.driver.r._ag.data: if l: m = int(m) invalid_seen = False for B_i in range(m_width): B = get_bit_range(d.vld_mask, B_i * 8, 8) _m = get_bit(m, B_i) if _m and B != 0xff: d = None break if invalid_seen: if _m: raise ValueError( "The value prefix is invalid, but there is a part of the value which is valid", d, B_i) else: if not _m: invalid_seen = True if d is not None: # mask removes the potentially invalid bytes d = d.val r_data.append((d, m, l)) self.assertValSequenceEqual(r_data, driver_r_ref) self.assertValSequenceEqual(u.axi.ar._ag.data, ar_ref)
def _impl(self) -> None: if len(self.MASTERS) > 1: raise NotImplementedError() m = self.s[0] wrack = rdack = err = BIT.from_py(0) AW = int(self.ADDR_WIDTH) rdata = [] for i, (s, (s_offset, s_size)) in\ enumerate(zip(self.m, self.SLAVES)): s.bus2ip_addr(m.bus2ip_addr, fit=True) s.bus2ip_be(m.bus2ip_be) s.bus2ip_rnw(m.bus2ip_rnw) s.bus2ip_data(m.bus2ip_data) bitsOfSubAddr = log2ceil(s_size - 1) prefix = get_bit_range(s_offset, bitsOfSubAddr, AW - bitsOfSubAddr) cs = self._sig(f"m_cs_{i:d}") cs(m.bus2ip_addr[AW:bitsOfSubAddr]._eq(prefix)) s.bus2ip_cs(m.bus2ip_cs & cs) err = err | (cs & s.ip2bus_error) rdack = rdack | (cs & s.ip2bus_rdack) wrack = wrack | (cs & s.ip2bus_wrack) rdata.append((cs, s.ip2bus_data)) m.ip2bus_error(err) m.ip2bus_rdack(rdack) m.ip2bus_wrack(wrack) SwitchLogic([(sel, m.ip2bus_data(data)) for sel, data in rdata], default=m.ip2bus_data(None))
def getBits(self, start, end, sign): """ Gets value of bits between selected range from memory :param start: bit address of start of bit of bits :param end: bit address of first bit behind bits :return: instance of BitsVal (derived from SimBits type) which contains copy of selected bits """ wordWidth = self.cellSize * 8 inFieldOffset = 0 allMask = mask(wordWidth) value = Bits(end - start, signed=sign).from_py(None) while start != end: assert start < end, (start, end) dataWordIndex = start // wordWidth v = self.data.get(dataWordIndex, None) endOfWord = (dataWordIndex + 1) * wordWidth width = min(end, endOfWord) - start offset = start % wordWidth if v is None: val = 0 vld_mask = 0 elif isinstance(v, int): val = get_bit_range(v, offset, width) vld_mask = allMask else: val = get_bit_range(v.val, offset, width) vld_mask = get_bit_range(v.vld_mask, offset, width) m = mask(width) value.val |= (val & m) << inFieldOffset value.vld_mask |= (vld_mask & m) << inFieldOffset inFieldOffset += width start += width return value
def getBits_from_array(array, wordWidth, start, end, reinterpretElmToType=None): """ Gets value of bits between selected range from memory :param start: bit address of start of bit of bits :param end: bit address of first bit behind bits :return: instance of BitsVal (derived from SimBits type) which contains copy of selected bits """ inPartOffset = 0 value = Bits(end - start, None).from_py(None) while start != end: assert start < end, (start, end) dataWordIndex = start // wordWidth v = array[dataWordIndex] if reinterpretElmToType is not None: v = v._reinterpret_cast(reinterpretElmToType) endOfWord = (dataWordIndex + 1) * wordWidth width = min(end, endOfWord) - start offset = start % wordWidth val = get_bit_range(v.val, offset, width) vld_mask = get_bit_range(v.vld_mask, offset, width) m = mask(width) value.val |= (val & m) << inPartOffset value.vld_mask |= (vld_mask & m) << inPartOffset inPartOffset += width start += width return value
def test_single_write(self): u = self.u d = int_list_to_int(range(u.CACHE_LINE_SIZE), 8) u.w._ag.data.append((1, d, mask(u.CACHE_LINE_SIZE))) self.runSim(10 * CLK_PERIOD) aw = u.m.aw._ag self.assertValSequenceEqual(aw.data, [ aw.create_addr_req(addr=1 * u.CACHE_LINE_SIZE, _len=u.BUS_WORDS_IN_CACHE_LINE - 1, _id=0), ]) self.assertValSequenceEqual( u.m.w._ag.data, [(get_bit_range(d, u.DATA_WIDTH * i, u.DATA_WIDTH), mask(u.DATA_WIDTH // 8), int(last)) for last, i in iter_with_last(range(u.BUS_WORDS_IN_CACHE_LINE))])
def packData(self, data): """ Pack data into list of BitsVal of specified dataWidth :param data: dict of values for struct fields {fieldName: value} :return: list of BitsVal which are representing values of words """ typeOfWord = Bits(self.wordWidth, None) fieldToVal = self._fieldToTPart if fieldToVal is None: fieldToVal = self._fieldToTPart = self.fieldToDataDict( self.origin.dtype, data, {}) for _, transParts in self.walkWords(showPadding=True): # build a single data word actualVldMask = 0 actualVal = 0 for tPart in transParts: high, low = tPart.getBusWordBitRange() fhigh, flow = tPart.getFieldBitRange() if not tPart.isPadding: val = fieldToVal.get(tPart.tmpl.origin, None) else: val = None if val is None: newBits = 0 vld = 0 else: newBits = get_bit_range(val, flow, fhigh - flow) vld = mask(high - low) actualVal = set_bit_range(actualVal, low, high - low, newBits) actualVldMask = set_bit_range(actualVldMask, low, high - low, vld) v = typeOfWord.getValueCls()(typeOfWord, actualVal, actualVldMask) yield v
def _axis_recieve_bytes(ag_data, D_B, use_keep, use_id, offset=0) -> Tuple[int, List[int]]: offset = None data_B = [] last = False first = True current_id = 0 mask_all = mask(D_B) while ag_data: _d = ag_data.popleft() if use_id: if use_keep: id_, data, keep, last = _d keep = int(keep) else: id_, data, last = _d keep = mask_all id_ = int(id_) else: if use_keep: data, keep, last = _d keep = int(keep) else: data, last = _d keep = mask_all id_ = 0 last = int(last) assert keep > 0 if offset is None: # first iteration # expecting potential 0s in keep and the rest 1 for i in range(D_B): # i represents number of 0 from te beginning of of the keep # value if keep & (1 << i): offset = i break assert offset is not None, keep for i in range(D_B): if get_bit(keep, i): d = get_bit_range(data.val, i * 8, 8) if get_bit_range(data.vld_mask, i * 8, 8) != 0xff: raise AssertionError( "Data not valid but it should be" f" based on strb/keep B_i:{i:d}, 0x{keep:x}, 0x{data.vld_mask:x}" ) data_B.append(d) if first: offset_mask = mask(offset) assert offset_mask & keep == 0, (offset_mask, keep) first = False current_id = id_ elif not last: assert keep == mask_all, keep if not first: assert current_id == id_, ("id changed in frame beats", current_id, "->", id_) if last: break if not last: if data_B: raise ValueError("Unfinished frame", data_B) else: raise ValueError("No frame available") if use_id: return offset, id_, data_B else: return offset, data_B
def _impl(self) -> None: if len(self.MASTERS) > 1: raise NotImplementedError() m = self.s[0] # :note: theoretically not required b = Mi32Buff() b.ADDR_BUFF_DEPTH = 1 b.DATA_BUFF_DEPTH = 1 b._updateParamsFrom(self) self.s_0_buff = b b.s(m) m = b.m propagateClkRstn(self) r_order = self.r_data_order.dataIn AW = int(self.ADDR_WIDTH) rdata = [] r_data_t = HStruct( (m.drd._dtype, "data"), (BIT, "vld"), ) for i, (s, (s_offset, s_size)) in\ enumerate(zip(self.m, self.SLAVES)): # s = Mi32() s.addr(m.addr, fit=True) s.be(m.be) s.dwr(m.dwr) bitsOfSubAddr = log2ceil(s_size - 1) prefix = get_bit_range(s_offset, bitsOfSubAddr, AW - bitsOfSubAddr) cs = self._sig(f"m_cs_{i:d}") cs(m.addr[AW:bitsOfSubAddr]._eq(prefix)) s.rd(m.rd & cs & r_order.rd) s.wr(m.wr & cs & r_order.rd) # we have to add 1 read data latency because the slave index would not be ready # oder fifo r_data_tmp = self._reg(f"r_data{i:d}_tmp", r_data_t, def_val={"vld": 0}) r_data_tmp.data(s.drd) r_data_tmp.vld(s.drdy) rdata.append((i, cs & s.ardy, r_data_tmp)) # r_data_order feed SwitchLogic([(addr_en, r_order.data(i)) for i, addr_en, _ in rdata], default=r_order.data(None)) addr_ack = Or(*[x[1] for x in rdata]) r_order.vld(addr_ack & m.rd) # m = Mi32() m.ardy(addr_ack & r_order.rd & (m.rd | m.wr)) r_order = self.r_data_order.dataOut If( r_order.vld, Switch(r_order.data).add_cases( [(slave_i, [m.drd(data.data), m.drdy(1)]) for slave_i, _, data in rdata], ).Default( # this case can not happen unless bug in code m.drd(None), m.drdy(None))).Else( m.drd(None), m.drdy(False), ) r_order.rd(Or(*[data.vld for _, _, data in rdata]))
def monitor(self): i = self.intf while True: # print(self.sim.now // Time.ns) yield Edge(i.en) yield WaitTimeslotEnd() if i.en.read(): rs = int(i.rs.read()) rw = int(i.rw.read()) d = int(i.d.read()) if rs == Hd44780Intf.RS_CONTROL: # command processing if rw == Hd44780Intf.RW_WRITE: if d & 0b10000000: # cursor position set (DDRAM addr) d = get_bit_range(d, 0, 7) self.cursor[0] = ceil(d / i.COLS) assert self.cursor[0] < i.ROWS, self.cursor[0] self.cursor[1] = d % i.ROWS elif d & 0b01000000: raise NotImplementedError() elif d & 0b00100000: # CMD_FUNCTION_SET self.data_len = get_bit(d, 4) self.lines = get_bit(d, 3) self.font = get_bit(d, 2) elif d & 0b00010000: # CMD_CURSOR_OR_DISPLAY_SHIFT shift_or_cursor = get_bit(d, 3) right_left = get_bit(d, 2) if shift_or_cursor == Hd44780Intf.SC_CURSOR_MOVE: c = self.cursor if right_left == Hd44780Intf.SHIFT_RIGHT: c[1] += 1 if c[1] == i.COLS: c[1] = 0 c[0] += 1 if c[0] == i.ROWS: c[0] = 0 else: raise NotImplementedError() elif d & 0b00001000: # CMD_DISPLAY_CONTROL self.display_on = get_bit(d, 2) self.cursor_on = get_bit(d, 1) self.cursor_blink = get_bit(d, 0) elif d & 0b00000100: # CMD_ENTRY_MODE_SET shift_en = get_bit(d, 0) incr_decr = get_bit(d, 1) if shift_en: self.shift = 1 if incr_decr == Hd44780Intf.INCR else -1 else: self.shift = 0 elif d & Hd44780Intf.CMD_RETURN_HOME: raise NotImplementedError() elif d == Hd44780Intf.CMD_CLEAR_DISPLAY: for line in self.screen: for x in range(i.COLS): line[x] = ' ' self.cursor = [0, 0] else: raise NotImplementedError("{0:8b}".format(d)) else: assert rw == Hd44780Intf.RW_READ, rw raise NotImplementedError() else: # data processing assert rs == Hd44780Intf.RS_DATA, rs if self.data_len == Hd44780Intf.DATA_LEN_8b: d = int(d) d = self.REV_CHAR_MAP.get(d, " ") cur = self.cursor self.screen[cur[0]][cur[1]] = d cur[1] += self.shift else: raise NotImplementedError()