def _declr(self): assert self.CACHE_LINE_CNT > 0, self.CACHE_LINE_CNT assert self.WAY_CNT > 0, self.WAY_CNT assert self.CACHE_LINE_CNT % self.WAY_CNT == 0, (self.CACHE_LINE_CNT, self.WAY_CNT) self._compupte_tag_index_offset_widths() addClkRstn(self) with self._paramsShared(): self.s = Axi4() self.m = Axi4()._m() rc = self.read_cancel = AddrHs()._m() rc.ID_WIDTH = 0 self.tag_array = AxiCacheTagArray() self.lru_array = AxiCacheLruArray() for a in [self.tag_array, self.lru_array]: a.PORT_CNT = 2 # r+w # self.flush = HandshakeSync() # self.init = HandshakeSync() data_array = self.data_array = RamSingleClock() data_array.MAX_BLOCK_DATA_WIDTH = self.MAX_BLOCK_DATA_WIDTH data_array.DATA_WIDTH = self.DATA_WIDTH data_array.ADDR_WIDTH = log2ceil( self.CACHE_LINE_CNT * ceil(self.CACHE_LINE_SIZE * 8 / self.DATA_WIDTH)) data_array.PORT_CNT = (READ, WRITE) data_array.HAS_BE = True
def _declr(self) -> None: addClkRstn(self) with self._paramsShared(): self.s = Axi4() self.ram = RamSingleClock() self.ram.ADDR_WIDTH = self.ADDR_WIDTH - log2ceil(self.DATA_WIDTH // 8 - 1)
def _declr(self): addClkRstn(self) with self._paramsShared(): self.r = RamHsR() self.w = AddrDataHs() self.conv = RamAsHs() self.ram = RamSingleClock()
def _declr(self): HashTableCoreWithRam._declr_common(self) t = self.table = RamSingleClock() t.PORT_CNT = 1 t.ADDR_WIDTH = log2ceil(self.ITEMS_CNT) t.DATA_WIDTH = self.KEY_WIDTH + self.DATA_WIDTH + 1 # +1 for item_vld tc = self.tableConnector = RamAsHs() tc.ADDR_WIDTH = t.ADDR_WIDTH tc.DATA_WIDTH = t.DATA_WIDTH
def _declr(self): PORT_CNT = self.PORT_CNT with self._paramsShared(): self.clk = Clk() # to let IDEs resolve type of port self.firstA = BramPort_withoutClk() self.secondA = BramPort_withoutClk() if PORT_CNT == 2: self.firstB = BramPort_withoutClk() self.secondB = BramPort_withoutClk() elif PORT_CNT > 2: raise NotImplementedError() self.select_sig = Signal() self.ram0 = RamSingleClock() self.ram1 = RamSingleClock()
def _declr(self): self.PAGE_OFFSET_WIDTH = log2ceil(self.PAGE_SIZE).val self.LVL1_PAGE_TABLE_INDX_WIDTH = log2ceil( self.LVL1_PAGE_TABLE_ITEMS).val self.LVL2_PAGE_TABLE_INDX_WIDTH = int(self.ADDR_WIDTH - self.LVL1_PAGE_TABLE_INDX_WIDTH - self.PAGE_OFFSET_WIDTH) self.LVL2_PAGE_TABLE_ITEMS = 2**int(self.LVL2_PAGE_TABLE_INDX_WIDTH) assert self.LVL1_PAGE_TABLE_INDX_WIDTH > 0, self.LVL1_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_INDX_WIDTH > 0, self.LVL2_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_ITEMS > 1, self.LVL2_PAGE_TABLE_ITEMS # public interfaces addClkRstn(self) with self._paramsShared(): self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) i = self.virtIn = Handshaked() i._replaceParam(i.DATA_WIDTH, self.VIRT_ADDR_WIDTH) i = self.physOut = Handshaked()._m() i._replaceParam(i.DATA_WIDTH, self.ADDR_WIDTH) self.segfault = Signal()._m() self.lvl1Table = BramPort_withoutClk() # internal components self.lvl1Storage = RamSingleClock() self.lvl1Storage.PORT_CNT.set(1) self.lvl1Converter = RamAsHs() for u in [self.lvl1Table, self.lvl1Converter, self.lvl1Storage]: u.DATA_WIDTH.set(self.ADDR_WIDTH) u.ADDR_WIDTH.set(self.LVL1_PAGE_TABLE_INDX_WIDTH) with self._paramsShared(): self.lvl2get = ArrayItemGetter() self.lvl2get.ITEM_WIDTH.set(self.ADDR_WIDTH) self.lvl2get.ITEMS.set(self.LVL2_PAGE_TABLE_ITEMS) self.lvl2indxFifo = HandshakedFifo(Handshaked) self.lvl2indxFifo.DEPTH.set(self.MAX_OVERLAP // 2) self.lvl2indxFifo.DATA_WIDTH.set(self.LVL2_PAGE_TABLE_INDX_WIDTH) self.pageOffsetFifo = HandshakedFifo(Handshaked) self.pageOffsetFifo.DEPTH.set(self.MAX_OVERLAP) self.pageOffsetFifo.DATA_WIDTH.set(self.PAGE_OFFSET_WIDTH)
def _declr(self): assert self.HAS_BE assert len( self.PORT_CNT) >= 2, "Requres at least 1 WRITE and 1 READ port" assert self.PORT_CNT == ( WRITE, *(READ for _ in range(len(self.PORT_CNT) - 1))),\ self.PORT_CNT addClkRstn(self) RamSingleClock._declr_ports(self) self.MASK_W = self.DATA_WIDTH // 8 # padding to make mask width % 8 == 0 self.MASK_PADDING_W = ceil(self.MASK_W / 8) * 8 - self.MASK_W with self._paramsShared(exclude=({"DATA_WIDTH"}, {})): ram = self.ram = RamSingleClock() ram.DATA_WIDTH = self.DATA_WIDTH + self.MASK_PADDING_W + self.MASK_W
def _declr(self): addClkRstn(self) with self._paramsShared(): if self.HAS_R: self.r = RamHsR() if self.HAS_W: self.w = AddrDataHs() self.conv = RamAsHs() r = self.ram = RamSingleClock() if not self.HAS_W: assert self.INIT_DATA is not None assert self.HAS_R r.PORT_CNT = (READ,) elif not self.HAS_R: assert self.HAS_W r.PORT_CNT = (WRITE,)
def _declr(self): self._compupte_tag_index_offset_widths() self.tag_record_t = self.define_tag_record_t() addClkRstn(self) with self._paramsShared(): self.lookup = HObjList(AddrHs() for _ in range(self.PORT_CNT)) self.lookupRes = HObjList(AxiCacheTagArrayLookupResIntf()._m() for _ in range(self.PORT_CNT)) for i in self.lookupRes: i.TAG_T = self.tag_record_t self.update = HObjList(AxiCacheTagArrayUpdateIntf() for _ in range(self.UPDATE_PORT_CNT)) tag_mem = self.tag_mem = RamSingleClock() tag_mem.ADDR_WIDTH = log2ceil(self.CACHE_LINE_CNT // self.WAY_CNT - 1) tag_mem.DATA_WIDTH = self.tag_record_t.bit_length() * self.WAY_CNT tag_mem.MAX_BLOCK_DATA_WIDTH = self.MAX_BLOCK_DATA_WIDTH tag_mem.PORT_CNT = ( *(WRITE for _ in range(self.UPDATE_PORT_CNT)), *(READ for _ in range(self.PORT_CNT)), ) tag_mem.HAS_BE = True
def _declr(self): addClkRstn(self) self._init_constants() with self._paramsShared(): self.m = Axi4()._m() self.ooo_fifo = FifoOutOfOrderRead() self.ooo_fifo.ITEMS = 2 ** self.ID_WIDTH sa = self.state_array = RamSingleClock() sa.PORT_CNT = (WRITE, READ) sa.ADDR_WIDTH = self.ID_WIDTH TRANSACTION_STATE_T = self.TRANSACTION_STATE_T # address + TRANSACTION_STATE_T sa.DATA_WIDTH = self.MAIN_STATE_INDEX_WIDTH + ( 0 if TRANSACTION_STATE_T is None else TRANSACTION_STATE_T.bit_length() ) self._declr_io()
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 _impl(self): if self._can_be_primitive_ram: super(RamXorSingleClock, self)._impl() else: if self.PRIMITIVE_MEMORY_PORTS != (WRITE, READ): raise NotImplementedError(self.PRIMITIVE_MEMORY_PORTS) if self._rw_ports: raise NotImplementedError("RW ports (supports only write and read ports)") r_ports = self._r_ports assert r_ports w_ports = self._w_ports assert w_ports # 1. construct a matrix N x N where N is a number of wrie ports # the diagonal is set to None because we do not need to synchronize the port with itself w_rams = HObjList( HObjList( RamSingleClock() if x != y else None for x in w_ports ) for y in w_ports) # construct a matrix M x N where M is number of read ports r_rams = HObjList(HObjList(RamSingleClock() for _ in w_ports) for _ in range(len(r_ports))) for row in w_rams + r_rams: for r in row: if r is None: continue r._updateParamsFrom(self, exclude=(("PORT_CNT",), ())) r.PORT_CNT = self.PRIMITIVE_MEMORY_PORTS if self.INIT_DATA is not None: raise NotImplementedError() r.INIT_DATA = tuple(0 for _ in range(2 ** r.ADDR_WIDTH)) self.w_rams = w_rams self.r_rams = r_rams # :type: List[Tuple[RtlSignal, RtlSignal, RtlSignal]] # List of tuples (en, address, write data), used for write forwarding on read ports write_in_progress_staus = [] # 2. connect them with XOR logic # add the register on write address and data because we need to load the data for XOR first for i, w in enumerate(w_ports): xor_src = [] for mem in w_rams[i]: if mem is not None: xor_src.append(mem) xor_loaded_src = [] for s in xor_src: p = s.port[1] p.addr(w.addr) p.en(w.en) xor_loaded_src.append(p.dout) w_addr_reg = self._reg(f"{w._name}_addr_reg", w.addr._dtype) w_addr_reg(w.addr) w_en_reg = self._reg(f"{w._name}_en_reg", def_val=0) w_en_reg(w.en) w_data_reg = self._reg(f"{w._name}_data_reg", w.din._dtype) w_data_reg(w.din) xored_data = Xor(w_data_reg, *xor_loaded_src) for ram_row in w_rams + r_rams: xor_dst = ram_row[i] if xor_dst is None: continue xor_dst = xor_dst.port[0] xor_dst.addr(w_addr_reg) xor_dst.en(w_en_reg) xor_dst.din(xored_data) write_in_progress_staus.append((w_en_reg, w_addr_reg, xored_data)) # 3. connect read ports to memories for (i, r), r_ram_column in zip(enumerate(r_ports), r_rams): out_xor_inputs = [] for r_ram, (w_en_reg, w_addr_reg, w_xored_data) in zip(r_ram_column, write_in_progress_staus): r_ram = r_ram.port[1] s = (w_en_reg & w_addr_reg._eq(r.addr))._ternary(w_xored_data, r_ram.dout) out_xor_inputs.append(s) r_ram.addr(r.addr) r_ram.en(r.en) r.dout(Xor(*out_xor_inputs)) propagateClk(self)
def setUpClass(cls): u = cls.u = RamSingleClock() u.DATA_WIDTH = 8 u.ADDR_WIDTH = 3 cls.compileSim(u)