diff --git a/dev/sim/coco/A2L2.py b/dev/sim/coco/A2L2.py index c67292c..4956b41 100755 --- a/dev/sim/coco/A2L2.py +++ b/dev/sim/coco/A2L2.py @@ -181,11 +181,8 @@ class A2L2Trans(DotMap): mask = 0xFFFF00FF else: mask = 0xFFFFFF00 - print(word, mask, dataStart, byte) word = (word & mask) | (int(self.data[dataStart:dataStart+2], 16) << ((3-byte)*8)) self.sim.mem.write(addr, word) - print(addr,word) - #quit() elif self.len == 2: word = self.sim.mem.read(addr) @@ -253,81 +250,81 @@ class A2L2Trans(DotMap): # ------------------------------------------------------------------------------------------------ # Tasks +transTypes = { + '00': 'IFETCH', + '08': 'LOAD', + '20': 'STORE' +} + async def A2L2Driver(dut, sim): """A2L2 node interface""" - transTypes = { - '00': 'IFETCH', - '08': 'LOAD', - '20': 'STORE' - } - ok = True readPending = [] countReads = 0 mem = {} sim.msg('A2L2 Driver: started.') - dut.an_ac_flh2l2_gate.value = 0 + sim.a2o.root.an_ac_flh2l2_gate.value = 0 while ok and not sim.done: await RisingEdge(dut.clk_1x) - dut.an_ac_req_ld_pop.value = 0 - dut.an_ac_req_st_pop.value = 0 - dut.an_ac_req_st_gather.value = 0 + sim.a2o.root.an_ac_req_ld_pop.value = 0 + sim.a2o.root.an_ac_req_st_pop.value = 0 + sim.a2o.root.an_ac_req_st_gather.value = 0 - dut.an_ac_reld_data_coming.value = 0 - dut.an_ac_reld_data_vld.value = 0 - dut.an_ac_reld_ecc_err.value = 0 - dut.an_ac_reld_ecc_err_ue.value = 0 - dut.an_ac_reld_ditc.value = 0 - dut.an_ac_reld_l1_dump.value = 0 - dut.an_ac_req_spare_ctrl_a1.value = 0 + sim.a2o.root.an_ac_reld_data_coming.value = 0 + sim.a2o.root.an_ac_reld_data_vld.value = 0 + sim.a2o.root.an_ac_reld_ecc_err.value = 0 + sim.a2o.root.an_ac_reld_ecc_err_ue.value = 0 + sim.a2o.root.an_ac_reld_ditc.value = 0 + sim.a2o.root.an_ac_reld_l1_dump.value = 0 + sim.a2o.root.an_ac_req_spare_ctrl_a1.value = 0 if sim.threads == 1: - dut.an_ac_reservation_vld.value = 0 - dut.an_ac_stcx_complete.value = 0 - dut.an_ac_stcx_pass.value = 0 + sim.a2o.root.an_ac_reservation_vld.value = 0 + sim.a2o.root.an_ac_stcx_complete.value = 0 + sim.a2o.root.an_ac_stcx_pass.value = 0 else: for i in range(sim.threads): - dut.an_ac_reservation_vld[i].value = 0 - dut.an_ac_stcx_complete[i].value = 0 - dut.an_ac_stcx_pass[i].value = 0 + sim.a2o.root.an_ac_reservation_vld[i].value = 0 + sim.a2o.root.an_ac_stcx_complete[i].value = 0 + sim.a2o.root.an_ac_stcx_pass[i].value = 0 - dut.an_ac_sync_ack.value = 0 - dut.an_ac_icbi_ack.value = 0 - dut.an_ac_back_inv.value = 0 + sim.a2o.root.an_ac_sync_ack.value = 0 + sim.a2o.root.an_ac_icbi_ack.value = 0 + sim.a2o.root.an_ac_back_inv.value = 0 # bummer IndexError: Slice indexing is not supported - #dut.an_ac_reld_data[0:31].value = 0x48000000 - #dut.an_ac_reld_data[32:63].value = 0x48000000 - #dut.an_ac_reld_data[64:95].value = 0x48000000 - #dut.an_ac_reld_data[96:127].value = 0x48000000 + #sim.a2o.root.an_ac_reld_data[0:31].value = 0x48000000 + #sim.a2o.root.an_ac_reld_data[32:63].value = 0x48000000 + #sim.a2o.root.an_ac_reld_data[64:95].value = 0x48000000 + #sim.a2o.root.an_ac_reld_data[96:127].value = 0x48000000 # bummer TypeError: Unsupported type for value assignment: ('48000000480000004800000048000000') - #dut.an_ac_reld_data.value = '48000000480000004800000048000000' + #sim.a2o.root.an_ac_reld_data.value = '48000000480000004800000048000000' #v = 0x48000000 # bummer TypeError: Unsupported type for value assignment: ('01001000000000000000000000000000010010000000000000000000000000000100100000000000000000000000000001001000000000000000000000000000') - #dut.an_ac_reld_data.value = f'{v:0>32b}{v:0>32b}{v:0>32b}{v:0>32b}' + #sim.a2o.root.an_ac_reld_data.value = f'{v:0>32b}{v:0>32b}{v:0>32b}{v:0>32b}' # otay! #v1 = cocotb.binary.BinaryValue() #v1.assign(f'{v:0>32b}{v:0>32b}{v:0>32b}{v:0>32b}') - #dut.an_ac_reld_data.value = v1.value + #sim.a2o.root.an_ac_reld_data.value = v1.value - if dut.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc + if sim.a2o.root.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc - tt = hex(dut.ac_an_req_ttype, 2) + tt = hex(sim.a2o.root.ac_an_req_ttype, 2) transType = transTypes[tt] - tid = hex(dut.ac_an_req_thread) - ra = hex(dut.ac_an_req_ra, 8) - tag = hex(dut.ac_an_req_ld_core_tag, 2) - lenEnc = hex(dut.ac_an_req_ld_xfr_len) - le = 'LE ' if dut.ac_an_req_endian.value else '' - wimg_w = dut.ac_an_req_wimg_w.value - wimg_i = dut.ac_an_req_wimg_i.value - wimg_m = dut.ac_an_req_wimg_m.value - wimg_g = dut.ac_an_req_wimg_g.value + tid = hex(sim.a2o.root.ac_an_req_thread) + ra = hex(sim.a2o.root.ac_an_req_ra, 8) + tag = hex(sim.a2o.root.ac_an_req_ld_core_tag, 2) + lenEnc = hex(sim.a2o.root.ac_an_req_ld_xfr_len) + le = 'LE ' if sim.a2o.root.ac_an_req_endian.value else '' + wimg_w = sim.a2o.root.ac_an_req_wimg_w.value + wimg_i = sim.a2o.root.ac_an_req_wimg_i.value + wimg_m = sim.a2o.root.ac_an_req_wimg_m.value + wimg_g = sim.a2o.root.ac_an_req_wimg_g.value wimg = 0 if wimg_w: wimg += 8 @@ -349,39 +346,39 @@ async def A2L2Driver(dut, sim): sim.msg(f'T{tid} {transType} {ra} tag={tag} len={trans.len} {le}WIMG:{wimg:X} reld data:{trans.cycD}') elif transType == 'STORE': # should verify st_data_pwr_token prev cycle - be = hex(dut.ac_an_st_byte_enbl, 8) - data = hex(dut.ac_an_st_data, 64) + be = hex(sim.a2o.root.ac_an_st_byte_enbl, 8) + data = hex(sim.a2o.root.ac_an_st_data, 64) trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, be=be, data=data, le=le) sim.msg(f'T{tid} {transType} {ra} tag={tag} len={trans.len} be={be} data={data} {le}WIMG:{wimg:X}') trans.doStore() - dut.an_ac_req_st_pop.value = 1 #wtf can randomize, etc. + sim.a2o.root.an_ac_req_st_pop.value = 1 #wtf can randomize, etc. #assert False, 'got a store' # data early indicator (d-3) - dut.an_ac_reld_data_coming.value = 0 + sim.a2o.root.an_ac_reld_data_coming.value = 0 for i in range(len(readPending)): trans = readPending[i] if trans.cycC == sim.cycle: - dut.an_ac_reld_data_coming.value = 1 + sim.a2o.root.an_ac_reld_data_coming.value = 1 if trans.xferNum == 0 and trans.xfers == 4: # 4 beats b2b - need diff scheduling for all modes trans.cycC += 2 # data valid indicator (d-2) - dut.an_ac_reld_data_vld.value = 0 - dut.an_ac_reld_core_tag.value = 0x1F - dut.an_ac_reld_ditc.value = 1 - dut.an_ac_reld_qw.value = 3 - dut.an_ac_reld_crit_qw.value = 1 + sim.a2o.root.an_ac_reld_data_vld.value = 0 + sim.a2o.root.an_ac_reld_core_tag.value = 0x1F + sim.a2o.root.an_ac_reld_ditc.value = 1 + sim.a2o.root.an_ac_reld_qw.value = 3 + sim.a2o.root.an_ac_reld_crit_qw.value = 1 for i in range(len(readPending)): trans = readPending[i] if trans.cycV == sim.cycle: trans.xferNum += 1 - dut.an_ac_reld_data_vld.value = 1 - dut.an_ac_reld_core_tag.value = trans.tag - dut.an_ac_reld_ditc.value = 1 if trans.ditc else 0 - dut.an_ac_reld_qw.value = trans.xferNum - 1 - dut.an_ac_reld_crit_qw.value = 1 if trans.xferNum == trans.xferCrit else 0 + sim.a2o.root.an_ac_reld_data_vld.value = 1 + sim.a2o.root.an_ac_reld_core_tag.value = trans.tag + sim.a2o.root.an_ac_reld_ditc.value = 1 if trans.ditc else 0 + sim.a2o.root.an_ac_reld_qw.value = trans.xferNum - 1 + sim.a2o.root.an_ac_reld_crit_qw.value = 1 if trans.xferNum == trans.xferCrit else 0 if trans.xferNum < 4 and trans.xfers == 4: trans.cycV += 1 @@ -393,7 +390,7 @@ async def A2L2Driver(dut, sim): v1 = cocotb.binary.BinaryValue() v1.assign(f'{w0:0>32b}{w1:0>32b}{w2:0>32b}{w3:0>32b}') - dut.an_ac_reld_data.value = v1.value + sim.a2o.root.an_ac_reld_data.value = v1.value sim.msg(f'RELD tag={trans.tag:02X} {w0:08X}{w1:08X}{w2:08X}{w3:08X} {beatNum}of{trans.xfers}{" crit" if beatNum == trans.xferCrit else ""}') @@ -404,7 +401,7 @@ async def A2L2Driver(dut, sim): readPending = [] else: readPending = readPending[1:] - dut.an_ac_req_ld_pop.value = 1 #wtf can randomize, etc. + sim.a2o.root.an_ac_req_ld_pop.value = 1 #wtf can randomize, etc. # A2L2 Checker @@ -423,23 +420,58 @@ async def A2L2Checker(dut, sim): # A2L2 Monitor # count transactions, etc. # fail on bad addresses -async def A2L2Monitor(dut, sim): + +# TRANS MONITORING NOT COMPLETE! +async def A2L2Monitor(dut, sim, watchTrans=False): """A2L2 interface monitor""" me = 'A2L2 Monitor' ok = True start = len(sim.config.a2l2.badAddr) > 0 sim.msg(f'{me}: started.') + reqValid = [] + rldValidCyc = [] + dataValidCyc = [] while start and ok: await RisingEdge(dut.clk_1x) - if dut.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc + if sim.a2o.root.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc + + tt = hex(sim.a2o.root.ac_an_req_ttype, 2) + transType = transTypes[tt] + tid = hex(sim.a2o.root.ac_an_req_thread) + ra = hex(sim.a2o.root.ac_an_req_ra, 8) + tag = hex(sim.a2o.root.ac_an_req_ld_core_tag, 2) + lenEnc = hex(sim.a2o.root.ac_an_req_ld_xfr_len) + le = 'LE ' if sim.a2o.root.ac_an_req_endian.value else '' + wimg_w = sim.a2o.root.ac_an_req_wimg_w.value + wimg_i = sim.a2o.root.ac_an_req_wimg_i.value + wimg_m = sim.a2o.root.ac_an_req_wimg_m.value + wimg_g = sim.a2o.root.ac_an_req_wimg_g.value + wimg = 0 + if wimg_w: + wimg += 8 + if wimg_i: + wimg += 4 + if wimg_m: + wimg += 2 + if wimg_g: + wimg += 1 + + if transType == 'IFETCH' or transType == 'LOAD': + sim.msg(f'T{tid} {transType} {ra} tag={tag} len={lenEnc} {le}WIMG:{wimg:X}') + trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, le=le) + reqValid.append(trans) + elif transType == 'STORE': + be = hex(sim.a2o.root.ac_an_st_byte_enbl, 8) + data = hex(sim.a2o.root.ac_an_st_data, 64) + trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, be=be, data=data, le=le) + sim.msg(f'T{tid} {transType} {ra} tag={tag} len={lenEnc} be={be} data={data} {le}WIMG:{wimg:X}') - tt = hex(dut.ac_an_req_ttype, 2) if tt == '00': #wtf someone should make this a enum/class - ra = dut.ac_an_req_ra.value.integer + ra = sim.a2o.root.ac_an_req_ra.value.integer for i in range(len(sim.config.a2l2.badAddr)): blk = sim.config.a2l2.badAddr[i] if 'I' in blk[2].upper(): @@ -447,7 +479,30 @@ async def A2L2Monitor(dut, sim): blkEnd = int(blk[1], 16) if ra >= blkStart and ra <= blkEnd: ok = False - assert False, (f'{me}: Bad IFetch @={ra:08X}') #wtf want this to end back in main code for summary + assert False, (f'{me}: Bad IFetch @={ra:08X}') + + # coming (d-3_) + if sim.a2o.root.an_ac_reld_data_coming.value: + rldValidCyc.append(sim.cycle + 1) + + # data valid indicator (d-2) + if len(rldValidCyc) > 0 and rldValidCyc[0] == sim.cycle: + if sim.a2o.root.an_ac_reld_data_vld.value: + #wtf append obj to rldValid! + tag = sim.a2o.root.an_ac_reld_core_tag.value + ditc = sim.a2o.root.an_ac_reld_ditc.value + qw = sim.a2o.root.an_ac_reld_qw.value + crit = sim.a2o.root.an_ac_reld_crit_qw.value + rldValidCyc = rldValidCyc[1:] + dataValidCyc.append(sim.cycle + 2) + else: + assert False, (f'{me}: Missing valid cycle') + + # data beat (d-0) + if len(dataValidCyc) > 0 and dataValidCyc[0] == sim.cycle: + data = hex(sim.a2o.root.an_ac_reld_data, 32) + sim.msg(f'RELD tag={tag:02X} {data:32X}') #wtf need qw,crit + dataValidCyc = dataValidCyc[1:] class A2L2: driver = A2L2Driver diff --git a/dev/sim/coco/A2O.py b/dev/sim/coco/A2O.py index 0daf689..2ed4c4f 100755 --- a/dev/sim/coco/A2O.py +++ b/dev/sim/coco/A2O.py @@ -15,6 +15,78 @@ from OPEnv import * # ------------------------------------------------------------------------------------------------ # Tasks +async def A2OConfig(dut, sim): + """Configure A2O. """ + + # A2L2 load/store credits + creditsLd = sim.a2o.root.lq0.lsq.arb.load_cred_cnt_d # 8 max + creditsLdMax = sim.a2o.root.lq0.lsq.arb.ld_cred_max # hdw check + creditsSt = sim.a2o.root.lq0.lsq.arb.store_cred_cnt_d # 32 max + creditsStMax = sim.a2o.root.lq0.lsq.arb.st_cred_max # hdw check + creditsLdStSingle = sim.a2o.root.lq0.lsq.arb.spr_xucr0_cred_d # 1 total credit + #wtf this affects A2L2 - default=1 + # sim.a2o.root.lq0.lsq.arb.spr_lsucr0_b2b_q # 0=crit first, every other 1=crit first, b2b **the a2l2 spec does not say crit must be first** + lsucr0_d = sim.a2o.root.lq0.ctl.spr.lq_spr_cspr.lsucr0_d + lsucr0_q = sim.a2o.root.lq0.ctl.spr.lq_spr_cspr.lsucr0_q + cpcr2_d = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_d + cpcr2_q = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_l2 + cpcr2_act = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_wren + cpcr4_d = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_d + cpcr4_q = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_l2 + cpcr4_act = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_wren + + await RisingEdge(dut.clk_1x) + + if sim.a2o.config.creditsLd is not None: + creditsLd.value = Force(sim.a2o.config.creditsLd) + creditsLdMax.value = Force(sim.a2o.config.creditsLd) + sim.msg(f'A2O: load credits changed from {creditsLd.value.integer} to {sim.a2o.config.creditsLd}.') + await RisingEdge(dut.clk_1x) + creditsLd.value = Release() + + if sim.a2o.config.creditsSt is not None: + creditsSt.value = Force(sim.a2o.config.creditsSt) + creditsStMax.value = Force(sim.a2o.config.creditsSt) + sim.msg(f'A2O: store credits changed from {creditsSt.value.integer} to {sim.a2o.config.creditsSt}.') + await RisingEdge(dut.clk_1x) + creditsSt.value = Release() + + if sim.a2o.config.creditsLdStSingle is not None: + v = 1 if sim.a2o.config.creditsLdStSingle else 0 + creditsLdStSingle.value = Force(v) + sim.msg(f'A2O: only one load OR store allowed when credits=1/1.') + await RisingEdge(dut.clk_1x) + #creditsLdStSingle.value = Release() # to release have to set _q with xucr0_d[51] and xucr0_act + + #wtf make a function - needs mask,thread + if sim.a2o.config.lsDataForward is not None: + v = 1 if sim.a2o.config.lsDataForward else 0 + sim.msg(f'A2O: LSUCR0 = {hex(lsucr0_q.value), 8}') + sim.msg(f'A2O: Setting LSUCR0[DFWD] = {v}.') + v = v << 2 + v = (lsucr0_q.value.integer & ~0x4) | v + lsucr0_d.value = Force(v) + await RisingEdge(dut.clk_1x) + lsucr0_d.value = Release() + sim.msg(f'A2O: LSUCR0 = {hex(lsucr0_q.value), 8}') + + if sim.a2o.config.cpcr4_sq_cnt is not None: + v = sim.a2o.config.cpcr4_sq_cnt + sim.msg(f'A2O: CPCR4 = {hex(cpcr4_q[0], 8)}') + sim.msg(f'A2O: Setting CPCR4[SQ_CNT] = {v}.') + v = v << 0 + v = (cpcr4_q[0].value.integer & ~0x1F) | v + await RisingEdge(dut.clk_1x) # need cuz of act? + cpcr4_d[0].value = Force(v) + cpcr4_act.value = Force(1) + await RisingEdge(dut.clk_1x) + await RisingEdge(dut.clk_1x) # need cuz of act? + cpcr4_d[0].value = Release() + cpcr4_act.value = Release() + sim.msg(f'A2O: CPCR4 = {hex(cpcr4_q[0], 8)}') + + await RisingEdge(dut.clk_1x) + async def A2ODriver(dut, sim): """A2O Core Driver""" @@ -44,8 +116,8 @@ async def A2OChecker(dut, sim): sim.msg(f'{me}: started.') # errors - creditsLdErr = dut.c0.lq0.lsq.arb.ld_cred_err_q - creditsStErr = dut.c0.lq0.lsq.arb.st_cred_err_q + creditsLdErr = sim.a2o.root.lq0.lsq.arb.ld_cred_err_q + creditsStErr = sim.a2o.root.lq0.lsq.arb.st_cred_err_q errors = [ {'name': 'Load Credits', 'sig': creditsLdErr}, {'name': 'Store Credits', 'sig': creditsStErr}, @@ -72,68 +144,68 @@ async def A2OMonitor(dut, sim): sim.msg(f'{me}: started.') # completions - iu0Comp = dut.c0.iu_lq_i0_completed - iu0CompIFAR = dut.c0.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i0_ifar - iu1Comp = dut.c0.iu_lq_i1_completed - iu1CompIFAR = dut.c0.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i1_ifar - iuCompFlushIFAR = dut.c0.cp_t0_flush_ifar - cp3NIA = dut.c0.iuq0.iuq_cpl_top0.iuq_cpl0.iuq_cpl_ctrl.cp3_nia_q # nia after last cycle's completions + iu0Comp = sim.a2o.root.iu_lq_i0_completed + iu0CompIFAR = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i0_ifar + iu1Comp = sim.a2o.root.iu_lq_i1_completed + iu1CompIFAR = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i1_ifar + iuCompFlushIFAR = sim.a2o.root.cp_t0_flush_ifar + cp3NIA = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.iuq_cpl_ctrl.cp3_nia_q # nia after last cycle's completions # GPR ppol and arch map gprCompMap = [] lastGprCompMap = [] #wtf check what 33:36 are! for i in range(36): - gprCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.gpr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) + gprCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.gpr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) lastGprCompMap.append(i) gpr = [] for i in range(144): - gpr.append(dut.c0.xu0.gpr.gpr0.loc[i].dat) + gpr.append(sim.a2o.root.xu0.gpr.gpr0.loc[i].dat) # CR fields pool and arch map crCompMap = [] lastCrCompMap = [] for i in range(8): - crCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.cr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) + crCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.cr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) lastCrCompMap.append(i) cr = [] for i in range(24): - cr.append(dut.c0.xu0.cr.entry[i].reg_latch.dout) + cr.append(sim.a2o.root.xu0.cr.entry[i].reg_latch.dout) # XER pool and arch map xerCompMap = [] lastXerCompMap = [] for i in range(1): - xerCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.xer_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) + xerCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.xer_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) lastXerCompMap.append(i) xer = [] for i in range(12): - xer.append(dut.c0.xu0.xer.entry[i].reg_latch.dout) + xer.append(sim.a2o.root.xu0.xer.entry[i].reg_latch.dout) # CTR pool and arch map ctrCompMap = [] lastCtrCompMap = [] for i in range(1): - ctrCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.ctr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) + ctrCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.ctr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) lastCtrCompMap.append(i) ctr = [] for i in range(8): - ctr.append(dut.c0.xu0.ctr.entry[i].reg_latch.dout) + ctr.append(sim.a2o.root.xu0.ctr.entry[i].reg_latch.dout) # LR pool and arch map lrCompMap = [] lastLrCompMap = [] for i in range(1): - lrCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.lr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) + lrCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.lr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout) lastLrCompMap.append(i) lr = [] for i in range(8): - lr.append(dut.c0.xu0.lr.entry[i].reg_latch.dout) + lr.append(sim.a2o.root.xu0.lr.entry[i].reg_latch.dout) lastComp = '' lastCompCount = 0 @@ -231,6 +303,7 @@ async def A2OMonitor(dut, sim): # Classes class A2O: + config = A2OConfig driver = A2ODriver checker = A2OChecker monitor = A2OMonitor @@ -239,10 +312,21 @@ class A2O: pass class A2OCore(DotMap): - def __init__(self, sim): + def __init__(self, sim, root=None): super().__init__() self.sim = sim + if root is None: + self.root = sim.dut.c0 + else: + self.root = root self.traceFacUpdates = False self.stopOnLoop = 0 self.iarPass = None - self.iarFail = None \ No newline at end of file + self.iarFail = None + self.config = DotMap({ + 'creditsLd': None, + 'creditsSt': None, + 'creditsLdStSingle': None, + 'lsDataForward' : None, + 'cpcr4_sq_cnt' : None + }) diff --git a/dev/sim/coco/OPEnv.py b/dev/sim/coco/OPEnv.py index 669de0b..57056d1 100755 --- a/dev/sim/coco/OPEnv.py +++ b/dev/sim/coco/OPEnv.py @@ -127,7 +127,7 @@ class Memory(DotMap): return self.default # word-aligned byte address + data - def write(self, addr, data): + def write(self, addr, data, be=None): try: addr = addr + 0 except: @@ -136,6 +136,23 @@ class Memory(DotMap): data = data + 0 except: data = int(data, 16) + + if be is not None: + try: + be = be + 0 + except: + be = int(be, 2) + be = f'{be:04b}' + if be == '0000': + return + + mask = 0 + for i in range(4): + mask = mask << 8 + if be[i]: + mask += 0xFF + data = (self.read(addr) & ~mask) | (data & mask) + if self.logStores: if addr not in self.data: self.sim.msg(f'Mem Update: @{addr:08X} XXXXXXXX->{data:08X}') @@ -164,6 +181,8 @@ class Memory(DotMap): rowTransDict = {} for i in range(32): rowTransDict[i] = '.' + for i in range(127, 256): + rowTransDict[i] = '.' # first line may be unaligned by row zeros = True diff --git a/dev/sim/coco/tb-node.py b/dev/sim/coco/tb-node.py deleted file mode 100644 index 1fb0310..0000000 --- a/dev/sim/coco/tb-node.py +++ /dev/null @@ -1,331 +0,0 @@ -# a2o test tb -# uses a2owb with sim mem interface - -import cocotb -from cocotb.clock import Clock -from cocotb.triggers import Timer -from cocotb.triggers import FallingEdge -from cocotb.handle import Force -from cocotb.handle import Release - -import itertools -from dotmap import DotMap - -from OPEnv import * -from A2O import * -from A2L2 import * - -# ------------------------------------------------------------------------------------------------ -# Tasks - -# get rid of z on anything that will be sampled here -# is there a func to get all inputs? -async def init(dut, sim): - """Initialize inputs. """ - - dut.nclk.value = 0 - dut.scan_in.value = 0 - dut.an_ac_scan_type_dc.value = 0x0 - dut.an_ac_chipid_dc.value = 0x0 - dut.an_ac_coreid.value = 0x0 - dut.an_ac_scom_sat_id.value = 0x0 - - dut.an_ac_lbist_ary_wrt_thru_dc.value = 0 - dut.an_ac_gsd_test_enable_dc.value = 0 - dut.an_ac_gsd_test_acmode_dc.value = 0 - dut.an_ac_ccflush_dc.value = 0 - dut.an_ac_ccenable_dc.value = 0 - dut.an_ac_lbist_en_dc.value = 0 - dut.an_ac_lbist_ip_dc.value = 0 - dut.an_ac_lbist_ac_mode_dc.value = 0 - dut.an_ac_scan_diag_dc.value = 0 - dut.an_ac_scan_dis_dc_b.value = 0 - - dut.an_ac_rtim_sl_thold_8.value = 0 - dut.an_ac_func_sl_thold_8.value = 0 - dut.an_ac_func_nsl_thold_8.value = 0 - dut.an_ac_ary_nsl_thold_8.value = 0 - dut.an_ac_sg_8.value = 0 - dut.an_ac_fce_8.value = 0 - dut.an_ac_abst_scan_in.value = 0 - - dut.an_ac_checkstop.value = 0 - - dut.an_ac_reset_1_complete.value = 0 - dut.an_ac_reset_2_complete.value = 0 - dut.an_ac_reset_3_complete.value = 0 - dut.an_ac_reset_wd_complete.value = 0 - - dut.an_ac_pm_fetch_halt.value = 0 - dut.an_ac_debug_stop.value = 0 - - dut.an_ac_tb_update_enable.value = 1 - dut.an_ac_tb_update_pulse.value = 0 # tb clock if xucr0[tcs]=1 (must be <1/2 proc clk; tb pulse is 2x this clock) - - # why is coco turning [0] into non-vector??? or is that gpi/vpi/icarus/??? - if sim.threads == 1: - dut.an_ac_pm_thread_stop.value = 0x1 - dut.an_ac_external_mchk.value = 0 - dut.an_ac_sleep_en.value = 0 - dut.an_ac_ext_interrupt.value = 0 - dut.an_ac_crit_interrupt.value = 0 - dut.an_ac_perf_interrupt.value = 0 - dut.an_ac_hang_pulse.value = 0 - dut.an_ac_uncond_dbg_event.value = 0 - else: - for i in range(sim.threads): - dut.an_ac_pm_thread_stop[i].value = 0x1 - dut.an_ac_external_mchk[i].value = 0 - dut.an_ac_sleep_en[i].value = 0 - dut.an_ac_ext_interrupt[i].value = 0 - dut.an_ac_crit_interrupt[i].value = 0 - dut.an_ac_perf_interrupt[i].value = 0 - dut.an_ac_hang_pulse[i].value = 0 - dut.an_ac_uncond_dbg_event[i].value = 0 - - await Timer(9, units='ns') - -async def config(dut, sim): - """Configure core, etc. """ - - #wtf make A2 module to do core-specific stuff - # A2L2 load/store credits - creditsLd = dut.c0.lq0.lsq.arb.load_cred_cnt_d # 8 max - creditsLdMax = dut.c0.lq0.lsq.arb.ld_cred_max # hdw check - creditsSt = dut.c0.lq0.lsq.arb.store_cred_cnt_d # 32 max - creditsStMax = dut.c0.lq0.lsq.arb.st_cred_max # hdw check - creditsLdStSingle = dut.c0.lq0.lsq.arb.spr_xucr0_cred_d # 1 total credit - #wtf this affects A2L2 - default=1 - # dut.c0.lq0.lsq.arb.spr_lsucr0_b2b_q # 0=crit first, every other 1=crit first, b2b **the a2l2 spec does not say crit must be first** - lsucr0_d = dut.c0.lq0.ctl.spr.lq_spr_cspr.lsucr0_d - lsucr0_q = dut.c0.lq0.ctl.spr.lq_spr_cspr.lsucr0_q - cpcr2_d = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_d - cpcr2_q = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_l2 - cpcr2_act = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_wren - cpcr4_d = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_d - cpcr4_q = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_l2 - cpcr4_act = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_wren - - await RisingEdge(dut.clk_1x) - - if sim.config.core.creditsLd is not None: - creditsLd.value = Force(sim.config.core.creditsLd) - creditsLdMax.value = Force(sim.config.core.creditsLd) - sim.msg(f'A2L2: load credits changed from {creditsLd.value.integer} to {sim.config.core.creditsLd}.') - await RisingEdge(dut.clk_1x) - creditsLd.value = Release() - - if sim.config.core.creditsSt is not None: - creditsSt.value = Force(sim.config.core.creditsSt) - creditsStMax.value = Force(sim.config.core.creditsSt) - sim.msg(f'A2L2: store credits changed from {creditsSt.value.integer} to {sim.config.core.creditsSt}.') - await RisingEdge(dut.clk_1x) - creditsSt.value = Release() - - if sim.config.core.creditsLdStSingle is not None: - v = 1 if sim.config.core.creditsLdStSingle else 0 - creditsLdStSingle.value = Force(v) - sim.msg(f'A2L2: only one load OR store allowed when credits=1/1.') - await RisingEdge(dut.clk_1x) - creditsLdStSingle.value = Release() - - #wtf make a function - needs mask,thread - if sim.config.core.lsDataForward is not None: - v = 1 if sim.config.core.lsDataForward else 0 - sim.msg(f'LSUCR0 = {hex(lsucr0_q.value), 8}') - sim.msg(f'Setting LSUCR0[DFWD] = {v}.') - v = v << 2 - v = (lsucr0_q.value.integer & ~0x4) | v - lsucr0_d.value = Force(v) - await RisingEdge(dut.clk_1x) - lsucr0_d.value = Release() - sim.msg(f'LSUCR0 = {hex(lsucr0_q.value), 8}') - - if sim.config.core.cpcr4_sq_cnt is not None: - v = sim.config.core.cpcr4_sq_cnt - sim.msg(f'CPCR4 = {hex(cpcr4_q[0], 8)}') - sim.msg(f'Setting CPCR4[SQ_CNT] = {v}.') - v = v << 0 - v = (cpcr4_q[0].value.integer & ~0x1F) | v - await RisingEdge(dut.clk_1x) # need cuz of act? - cpcr4_d[0].value = Force(v) - cpcr4_act.value = Force(1) - await RisingEdge(dut.clk_1x) - await RisingEdge(dut.clk_1x) # need cuz of act? - cpcr4_d[0].value = Release() - cpcr4_act.value = Release() - sim.msg(f'CPCR4 = {hex(cpcr4_q[0], 8)}') - - await RisingEdge(dut.clk_1x) - -# trilib/tri.vh:`define NCLK_WIDTH 6 // 0 1xClk, 1 Reset, 2 2xClk, 3 4xClk, 4 Even .5xClk, 5 Odd .5xClk -async def genReset(dut, sim): - """Generate reset. """ - - first = True - done = False - - while not done: - await RisingEdge(dut.clk_1x) - if sim.cycle < sim.resetCycle: - if first: - dut._log.info(f'[{sim.cycle:08d}] Resetting...') - first = False - dut.nclk[1].value = 1 - elif not done: - dut._log.info(f'[{sim.cycle:08d}] Releasing reset.') - dut.nclk[1].value = 0 - done = True - sim.resetDone = True - -async def genClocks(dut, sim): - """Generate 1x, 2x, 4x clock pulses, depending on parms. """ - - if sim.clk2x and sim.clk4x: - sim.clk1x = Clock(dut.nclk[0], 8, 'ns') - await cocotb.start(sim.clk1x.start()) - sim.clk2x = Clock(dut.nclk[2], 4, 'ns') - await cocotb.start(sim.clk2x.start()) - sim.clk4x = Clock(dut.nclk[3], 2, 'ns') - await cocotb.start(sim.clk4x.start()) - elif sim.clk2x: - sim.clk1x = Clock(dut.nclk[0], 8, 'ns') - await cocotb.start(sim.clk1x.start()) - sim.clk2x = Clock(dut.nclk[2], 4, 'ns') - await cocotb.start(sim.clk2x.start()) - else: - sim.clk1x = Clock(dut.nclk[0], 8, 'ns') - await cocotb.start(sim.clk1x.start()) - - - for cycle in range(sim.maxCycles): - - sim.cycle = cycle - - if cycle % sim.hbCycles == 0: - dut._log.info(f'[{cycle:08d}] ...tick...') - - await RisingEdge(dut.clk_1x) - - dut._log.info(f'[{sim.cycle:08d}] Reached max cycle. Clocks stopped.') - sim.ok = False - sim.fail = 'Max cycle reached.' - -# ------------------------------------------------------------------------------------------------ -# Interfaces - -# SCOM -async def scom(dut, sim): - """scom interface""" - - dut.an_ac_scom_dch.value = 0 - dut.an_ac_scom_cch.value = 0 - - -# ------------------------------------------------------------------------------------------------ -# Do something - -@cocotb.test() -async def tb(dut): - """A Vulgar Display of OpenPower""" - - sim = Sim(dut) - sim.mem = Memory(sim) - sim.maxCycles = 9000 - # original fpga design needed 4 cred, no fwd (set in logic currently) - #sim.config.core.creditsSt = 32 - #sim.config.core.lsDataForward = 0 # disable=1 - #sim.config.core.cpcr4_sq_cnt = 0 # default=6 - - ''' - # rom - sim.memFiles = ['../mem/boot.bin.hex'] #wtf cmdline parm - - for i in range(len(sim.memFiles)): #wtf el should be object with name, format, etc. - sim.mem.loadFile(sim.memFiles[i]) - ''' - - ''' - # rom+test; should end at 700 - sim.memFiles = [ - { - 'addr': 0x00000000, - 'file' : '../mem/test1/rom.init' - }, - { - 'addr': 0x10000000, - 'file' : '../mem/test1/test.init' - } - ] - ''' - ''' - # rom+bios; should end at 7FC - sim.memFiles = [ - { - 'addr': 0x00000000, - 'file' : '../mem/test2/rom.init' - } - ] - ''' - - - # rom+bios+arcitst - sim.memFiles = [ - { - 'addr': 0x00000000, - 'file' : '../mem/test3/rom.init' - } - ] - - for i in range(len(sim.memFiles)): #wtf el should be object with name, format, etc. - sim.mem.loadFile(sim.memFiles[i]['file'], addr=sim.memFiles[i]['addr']) - - if sim.resetAddr is not None and sim.mem.read(sim.resetAddr) == sim.mem.default: - sim.mem.write(sim.resetAddr, sim.resetOp) - sim.msg(f'Set reset fetch @{sim.resetAddr:08X} to {sim.resetOp:08X}.') - - # init stuff - await init(dut, sim) - - # start clocks,reset - await cocotb.start(genClocks(dut, sim)) - await cocotb.start(genReset(dut, sim)) - - # start interfaces - await cocotb.start(scom(dut, sim)) - - sim.a2o = A2OCore(sim) - sim.a2o.traceFacUpdates = True - await cocotb.start(A2O.driver(dut, sim)) - await cocotb.start(A2O.checker(dut, sim)) - await cocotb.start(A2O.monitor(dut, sim)) - - await cocotb.start(A2L2.driver(dut, sim)) - await cocotb.start(A2L2.checker(dut, sim)) - await cocotb.start(A2L2.monitor(dut, sim)) - - await Timer((sim.resetCycle + 5)*8, units='ns') - if dut.nclk[1].value != 0: - sim.ok = False - sim.fail = 'Reset active too long!' - - # config stuff - await config(dut, sim) - - # monitor stuff - #await cocotb.start(coreMonitor(dut, sim)) - - # release thread(s) - dut.an_ac_pm_thread_stop.value = 0 - await RisingEdge(dut.clk_1x) - dut._log.info(f'[{sim.cycle:08d}] Threads enabled.') - - # should await sim.done - await Timer((sim.maxCycles+100)*8, units='ns') - - if sim.ok: - dut._log.info(f'[{sim.cycle:08d}] You has opulence.') - else: - dut._log.info(f'[{sim.cycle:08d}] You are worthless and weak!') - dut._log.info(f'[{sim.cycle:08d}] {sim.fail}') - assert False diff --git a/dev/sim/coco/tb.py b/dev/sim/coco/tb.py index af472a6..036f217 100755 --- a/dev/sim/coco/tb.py +++ b/dev/sim/coco/tb.py @@ -231,7 +231,8 @@ async def tb(dut): sim = Sim(dut) sim.mem = Memory(sim) - sim.maxCycles = 20000 + #sim.maxCycles = 2000000 + sim.maxCycles = 300 # original fpga design needed 4 cred, no fwd (set in logic currently) #sim.config.core.creditsSt = 32 #sim.config.core.lsDataForward = 0 # disable=1 @@ -268,7 +269,7 @@ async def tb(dut): ] ''' - + ''' # rom+bios+arcitst sim.memFiles = [ { @@ -276,6 +277,15 @@ async def tb(dut): 'file' : '../mem/test3/rom.init' } ] + ''' + + # rom+bios+dhrystone + sim.memFiles = [ + { + 'addr': 0x00000000, + 'file' : '../mem/dhrystone/rom.init' + } + ] for i in range(len(sim.memFiles)): #wtf el should be object with name, format, etc. sim.mem.loadFile(sim.memFiles[i]['file'], addr=sim.memFiles[i]['addr'])