# 虚拟地址和真实地址的D代表的是真实页中数据的偏移量,一页是128B,以字节为单位,那么D是7位 # D是7位,那么C是12-7=5位,A=16-7=9位,B=A=9位,TLB和页表的页框号均为C=5位 # 那么A代表的是某一页的虚拟地址,C是某一页的真实地址 # TLB大小没有说明,所以假设TLB可以存储4页(4个虚拟地址->物理地址的映射) # 主存大小为4KB,块的大小为32B。那么主存有128块,4块一页,共有32页 # 假设页表可以存储32页(32个虚拟地址->物理地址的映射) # cache的数据区大小为1KB,块大小为32B,所以共有32块,由于为两路组相连,每组2块,共16组 # 主存有128块, 所以128 / 16 = 8, 所以主存分属16组,每组可能的数据有8块, 那么cache属于8选2,由E确定组内序号 # E=8=2^3=3位,F=16=2^4=4位,G=32B/B=2^5=5位 # cache里有16行,主存序号/16 = 组相连组号, F确定cache里的第几行 # H和E比较,位数为3,如果对应上,对应数据就在cache,没对应,则数据在主存 # -------------------------------------------------------------------- # # (1) 设置主存的字节内容,并且输出第28和29块的第一字节内容 # -------------------------------------------------------------------- # main_storage = [] s = '' for i in range(1, 51): if i % 2 == 1: s = '' for j in range(1, 33): s += '01010101' main_storage.append(s) if i % 2 == 0: s = '' for j in range(1, 33): s += '11111111' main_storage.append(s) print("# -------------------------------------------------------------------- #") print("(1) 设置主存的字节内容,并且输出第28和29块的第一字节内容") print("# -------------------------------------------------------------------- #") # 输出第28号块的第一个字节 print("输出第28号块的第一个字节:" + main_storage[27][0:8]) # 输出第29号块的第一个字节 print("输出第29号块的第一个字节:" + main_storage[28][0:8]) print('\n') # -------------------------------------------------------------------- # # (2) 第29块装入Cache,打印对应的cache组号以及H字段内容 # -------------------------------------------------------------------- # # 由于2路组相连,所以每组两块,共有16组,cache有16行, 每行两块数据(标记(3位)+ 有效位(1位)+ 数据(32B)+ 标记(3位)+ 有效位(1位)+ 数据(32位)+ 填充位(若干位)) # 主存有128块, 所以128 / 16 = 8, 所以主存分属16组,每组可能的数据有8块, 那么cache属于8选2 # 29 % 16 = 1 ······ 13, 所以第29块属于13组,组内序号位1 # 初始化cache, 设置16行,代表16组,由F(4位)确定对应的行数,再由E和H比较确定是否在在cache里 cache = [] for i in range(0, 16): test = '' for j in range(0, 33): test += '00000000' cache.append(test) # 确定组号以及H line = 29 % 16 - 1 h = int(29 / 16) H = str(bin(h))[2:] while len(H) < 3: H = '0' + H if cache[line][3] == '0': cache[line] = H + '1' + main_storage[28] elif cache[line][3+1+32*8+3] == '0': cache[line] = cache[line][0:3] + '0' + cache[4: 4+32*8+1] + H + '1' + main_storage[28] print("# -------------------------------------------------------------------- #") print("(2) 第29块装入Cache,打印对应的cache组号以及H字段内容") print("# -------------------------------------------------------------------- #") print("块号位29的主存块对应的cache组号为:" + str(line)) print("对应的H字段内容为:" + H) print("cache对应的标记、有效位、数据第一个字节的内容为:" + cache[line][0: 3+1+8]) print('\n') # -------------------------------------------------------------------- # # (3) 模拟缺页处理的过程 # -------------------------------------------------------------------- # print("# -------------------------------------------------------------------- #") print("(3) 模拟缺页处理的过程") print("# -------------------------------------------------------------------- #") # 虚拟地址,A为9位,D为7位 virtual_address = '0000000000000000' A = virtual_address[0:9] B = [] C = '' D = virtual_address[9:16] # TLB的格式为:有效位(1位) + 虚拟页号(9位) + 真实页号(5位) + 填充位(1位) # 假设TLB有4行 # 假设此时TLB为空 TLB = [] # 页表的格式为:有效位(1位) + 虚拟页号(9位) + 真实页号(5位) + 填充位(1位) # 页表32行,包含所有页的虚拟地址向真实地址的映射 table = [] vir = '' real = '' # 生产32个映射,此时的C包含了00000-11111共2^5=32个页的地址 for i in range(0, 32): vir = str(bin(i*16))[2:] while len(vir) < 9: vir = '0' + vir real = str(bin(i))[2:] while len(real) < 5: real = '0' + real if i % 10 == 1: TLB.append('1' + vir + real + '0') table.append('1' + vir + real + '0') # 1、虚拟地址的对应页地址是否在TLB中 # 在 -> 读取TLB的中的物理地址,跳转到4 table_vir = [] for i in TLB: B.append(i[1: 0]) for i in table: table_vir.append(i[1: 10]) if A in B: C = TLB[B.index(A)][10: 15] print("虚拟地址和物理地址的转换在TLB查找") # 不在 -> 访问页表 # 2、访问页表查找 elif A in table_vir: C = table[table_vir.index(A)][10: 15] print("虚拟地址和物理地址的转换在页表查找") else: print("地址错误") # 4、对应页数据是否在cache中 # 此时得到5位的C和7位的D,把这拆解为3位的E,4位的F,5位的G # F确定组号, E进行标记对比, G进行地址寻址 # 在 -> 跳转6 E = C[0: 3] F = C[3: 4] + D[0: 3] G = D[3: 6] data = '' line = int(F) if E == cache[line][0: 3] and cache[line][3] == '1': data = cache[line][4: 4 + 32 * 8] print("在cache中找到相关数据") elif E == cache[line][3+1+32*8: 3+1+32*8+3] and cache[line][3+1+32*8+3] == '1': data = cache[line][3 + 1 + 32 * 8 + 3 + 1: 3 + 1 + 32 * 8 + 3 + 1 + 32 * 8] print("在cache中找到相关数据") # 不在 -> cache更新 # 5、更新cache else: print("在cache中没有找到相关数据") print("对cache进行更新") data = main_storage[int(E)*16+int(F)] if cache[line][3] == '0': cache[line] = E + '1' + data + cache[line][3+1+32*8:3+1+32*8+3] + '0' + cache[line][3 + 1 + 32 * 8 + 3 + 1:] else: cache[line] = cache[line][0: 3] + '0' + cache[line][4: 3 + 1 + 32 * 8 + 1] + E + '1' + data print("cache数据更新完成") print("数据的第一个字节为:" + data[0:8]) # -------------------------------------------------------------------- # # (4) 模拟修改页面内容的过程 # -------------------------------------------------------------------- # # 1、过程大致和(3)差不多 # 2、查询cache时,如果在cache内则需要直接修改数据并且更新主存数据 # 3、如果不在cache内,则需要访问主存修改数据,并且更新cache