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 connect_lookup_port(self, lookup: AddrHs, tag_mem_port_r: BramPort_withoutClk, lookupRes: AxiCacheTagArrayLookupResIntf, update_tmp: StructIntf): lookup_tmp = self._reg( "lookup_tmp", HStruct(*([(lookup.id._dtype, "id")] if lookup.ID_WIDTH else ()), (lookup.addr._dtype, "addr"), (BIT, "vld")), def_val={"vld": 0}) pa = self.parse_addr just_updated = rename_signal( self, # updated on same index (using "update" port) = the result which is currently on output # of the ram may be invalid update_tmp.vld & pa(lookup_tmp.addr)[1]._eq(pa(update_tmp.addr)[1]), "just_updated") # tag comparator tag, _, _ = self.parse_addr(lookup_tmp.addr) tags = tag_mem_port_r.dout._reinterpret_cast( self.tag_record_t[self.WAY_CNT]) found = [ # is matching and just this tag was not updated (t.valid & t.tag._eq(tag) & (~just_updated | (update_tmp.vld & ~update_tmp.way_en[i]))) | ( # or was updated to the matching tag just_updated & update_tmp.way_en[i] & ~update_tmp.delete & pa(lookup_tmp.addr)[0]._eq(pa(update_tmp.addr)[0])) for i, t in enumerate(tags) ] # if the data which is currently on output of the ram was # just updated it means that the data is invalid and the update # data will be lost in next clock cycle, if the consumer of lookupRes # can not consume the data just know, we need to perform lookup in tag_array # once again lookup.rd(~lookup_tmp.vld | lookupRes.rd) If( lookup.rd, lookup_tmp.id(lookup.id) if lookup.ID_WIDTH else [], lookup_tmp.addr(lookup.addr), ) lookup_tmp.vld(lookup.vld | (lookup_tmp.vld & ~lookupRes.rd)) tag_mem_port_r.addr((lookup_tmp.vld & ~lookupRes.rd)._ternary( self.parse_addr(lookup_tmp.addr) [1], # lookup previous address and look for a change self.parse_addr(lookup.addr)[1], # lookup a new address )) tag_mem_port_r.en(lookup.vld | (lookup_tmp.vld & ~lookupRes.rd)) if lookupRes.ID_WIDTH: lookupRes.id(lookup_tmp.id) lookupRes.addr(lookup_tmp.addr) lookupRes.way(oneHotToBin(self, found)) lookupRes.found(Or(*found)) lookupRes.tags(tags) lookupRes.vld(lookup_tmp.vld)