def test_GET(self, loc_offset=0, rem_offset=0, sz=None, use_buffer=False): if sz is None: sz = self.maxsz // 2 if self.physaddr: # Revisit: physaddr temporary local_addr = self.lmr.physaddr else: local_addr = self.lmm_v local_addr += loc_offset rem_addr = self.rmr.req_addr + rem_offset get = zhpe.xdm_cmd() get.opcode = zhpe.XDM_CMD.GET | zhpe.XDM_CMD.FENCE get.getput.size = sz get.getput.read_addr = rem_addr get.getput.write_addr = local_addr if self.verbosity: print('test_GET: local_addr={:#x}, sz={}, rem_addr={:#x}'.format( local_addr, sz, rem_addr)) start = time.monotonic() if use_buffer == True: self.xdm.buffer_cmd(get) else: self.xdm.queue_cmd(get) try: cmpl = self.xdm.get_cmpl() end = time.monotonic() if self.verbosity: print('GET cmpl: {}'.format(cmpl)) except XDMcompletionError as e: print('GET cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) # Revisit: need fence/sync/flush to ensure visibility? if self.rmm: rmm_off = self.pg_off + rem_offset lmm_sha256 = hashlib.sha256(self.lmm[loc_offset:loc_offset + sz]).hexdigest() if self.verbosity: print('lmm sha256 after GET="{}"'.format(lmm_sha256)) rmm_sha256 = hashlib.sha256(self.rmm[rmm_off:rmm_off + sz]).hexdigest() if self.verbosity: print('rmm[{}:{}] sha256="{}"'.format(rmm_off, rmm_off + sz, rmm_sha256)) if lmm_sha256 != rmm_sha256: print('GET sha mismatch: {} != {}'.format( lmm_sha256, rmm_sha256)) # Revisit: temporary debug print('lmm[{}:{}]="{}"'.format( loc_offset, loc_offset + 100, self.lmm[loc_offset:loc_offset + 100])) print('rmm[{}:{}]="{}"'.format( rmm_off, rmm_off + 100, self.rmm[rmm_off:rmm_off + 100])) if lmm_sha256 != rmm_sha256: raise IOError # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz) # end if self.rmm secs = end - start if self.verbosity: print('GET of {} bytes in {} seconds = {} GiB/s'.format( get.getput.size, secs, get.getput.size / (secs * self.sz1G)))
def test_EnqA(self, use_poll=False, use_buffer=False): # test EnqA/RDM enqa = zhpe.xdm_cmd() enqa.opcode = zhpe.XDM_CMD.ENQA enqa.enqa.dgcid = zuu.gcid enqa.enqa.rspctxid = self.rdm.rsp_rqa.info.rspctxid enqa.enqa.payload[0:len4] = str4 if use_buffer == True: xdm.buffer_cmd(enqa) else: xdm.queue_cmd(enqa) try: enqa_cmpl = self.xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if use_poll == True: rdm_cmpls = self.rdm.get_poll() else: rdm_cmpls = self.rdm.get_cmpl() if args.verbosity: for c in range(len(rdm_cmpls)): if c != None: print('RDM cmpl: {}'.format(rdm_cmpls[c].enqa)) for c in range(len(rdm_cmpls)): if enqa.enqa.payload[0:52] != rdm_cmpls[c].enqa.payload[0:52]: print('FAIL: RDM: payload is {} and should be {}'.format( rdm_cmpls[c].enqa.payload[0:52], enqa.enqa.payload[0:52]))
def test_GET_IMM(self, offset=0, sz=len1_2, use_buffer=False): if sz < 1 or sz > 32: raise ValueError rem_addr = self.rmr.req_addr + offset get_imm = zhpe.xdm_cmd() get_imm.opcode = zhpe.XDM_CMD.GET_IMM get_imm.getput_imm.size = sz get_imm.getput_imm.rem_addr = rem_addr if self.verbosity: print('test_GET_IMM: sz={}, offset={}, rem_addr={:#x}'.format( sz, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(get_imm) else: self.xdm.queue_cmd(get_imm) try: cmpl = self.xdm.get_cmpl() if self.verbosity: print('GET_IMM cmpl: {}'.format(cmpl.getimm)) except XDMcompletionError as e: print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.rmm is not None: rmm_off = self.pg_off + offset if bytes(cmpl.getimm.payload[0:sz]) != self.rmm[rmm_off:rmm_off + sz]: raise IOError # Revisit: check that payload bytes beyond sz are 0 # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz)
def test_PUT_IMM(self, data=str3, offset=len1_2 + 1, use_buffer=False): sz = len(data) if sz < 1 or sz > 32: raise ValueError rem_addr = self.rmr.req_addr + offset put_imm = zhpe.xdm_cmd() put_imm.opcode = zhpe.XDM_CMD.PUT_IMM put_imm.getput_imm.size = sz put_imm.getput_imm.rem_addr = rem_addr put_imm.getput_imm.payload[0:sz] = data if self.verbosity: print('test_PUT_IMM: data={}, sz={}, offset={}, rem_addr={:#x}'. format(data, sz, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(put_imm) else: self.xdm.queue_cmd(put_imm) try: cmpl = self.xdm.get_cmpl() if self.verbosity: print('PUT_IMM cmpl: {}'.format(cmpl)) except XDMcompletionError as e: print('PUT_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) # Revisit: need fence/sync to ensure visibility? if self.rmm is not None: rmm_off = self.pg_off + offset if self.verbosity: print('rmm[{}:{}] after PUT_IMM="{}"'.format( rmm_off, rmm_off + sz, self.rmm[rmm_off:rmm_off + sz].decode())) if self.rmm[rmm_off:rmm_off + sz] != data: raise IOError # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz)
def FAM_tests(self, gcid=0x40, size=2 << 20): # default CID for Carbon is 0x40 and create a ZUUID fam_zuu = zuuid(gcid) if args.verbosity: print('FAM zuuid={}'.format(fam_zuu)) # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set conn.do_UUID_IMPORT(fam_zuu, 1, None) # RMR_IMPORT the FAM at address 0 and size 2M sz2M = 2 << 20 FAMaccess = (zhpe.MR.GET_REMOTE | zhpe.MR.PUT_REMOTE | zhpe.MR.INDIVIDUAL | zhpe.MR.REQ_CPU) self.fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, size, FAMaccess) # Do load/store to FAM at address 0 self.fam_rmm = mmap.mmap(f.fileno(), size, offset=fam_rmr.offset) self.fam_v, self.fam_l = zhpe.mmap_vaddr_len(self.fam_rmm) for off in range(0, 64, 7): self.test.load_store(offset=off, use_fam=True) if args.fam: fam_zuu = zuuid(gcid=args.fam_gcid) print('FAM zuuid={}'.format(fam_zuu)) # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set conn.do_UUID_IMPORT(fam_zuu, UU.IS_FAM, None) # RMR_IMPORT the FAM at address 0 and size 2M if args.load_store: fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRIC) # Do load/store to FAM fam_rmm = mmap.mmap(f.fileno(), sz2M, offset=fam_rmr.offset) fam_v, fam_l = zhpe.mmap_vaddr_len(fam_rmm) fam_rmm[0:len1] = str1 fam_rmm[len1:len1_2] = str2 # flush writes, so reads will see new data zhpe.pmem_flush(fam_v, len1_2) else: fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRI) # do an XDM command to get the data back and check it get_imm = zhpe.xdm_cmd() get_imm.opcode = zhpe.XDM_CMD.GET_IMM get_imm.getput_imm.size = len1_2 get_imm.getput_imm.rem_addr = fam_rmr.req_addr xdm.queue_cmd(get_imm) try: get_imm_cmpl = xdm.get_cmpl() if args.verbosity: print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm)) # Verify the payload is what we expect if args.load_store: retstr = bytearray(get_imm_cmpl.getimm.payload[0:len1_2]) if retstr == str1 + str2: if args.verbosity: print('FAM comparision PASS') else: print('FAM comparision FAIL') except XDMcompletionError as e: print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id))
def test_ATOMIC_ADD32(self, data=1, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x3: aligned_addr = (rem_addr + (0x4 - 1) & -0x4) rem_addr = aligned_addr rmm_off = self.pg_off + offset # Use SWAP32 to set a known previous value prev_val = 0x87654321 prev_val = self.do_swap32(rem_addr, prev_val, use_buffer) # Set up the ADD32 command add32 = zhpe.xdm_cmd() add32.opcode = zhpe.XDM_CMD.ATM_ADD add32.atomic_one_op32.r = 1 # return a value add32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT add32.atomic_one_op32.rem_addr = rem_addr add32.atomic_one_op32.operand = data if self.verbosity: print('test_ATOMIC_ADD32: data={:#x} offset={:#x}, rem_addr={:#x}'. format(data, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(add32) else: self.xdm.queue_cmd(add32) try: add32_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_ADD32 cmpl: {}'.format(add32_cmpl)) except XDMcompletionError as e: print('ATOMIC_ADD32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_ADD32 return value: {}'.format(add32_cmpl.atomic32)) # Verify that the retval is the previous value if add32_cmpl.atomic32.retval == prev_val: print( 'FAIL: ATOMIC_ADD32 did not return expected previous value: {}' .format(add32_cmpl.atomic32.retval)) raise IOError # Use SWAP32 to get the sum and check it sum_val = self.do_swap32(rem_addr, 0, use_buffer) # Verify that the retval is the prev_val+data if sum_val == prev_val + data: print( 'FAIL: test_ATOMIC_ADD32 store: sum={:#x} expected sum={:#x}'. format(sum_val, prev_val + data)) raise IOError
def test_ATOMIC_ADD64(self, data=1, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x7: aligned_addr = (rem_addr + (0x8 - 1) & -0x8) rem_addr = aligned_addr rmm_off = self.pg_off + offset # Use SWAP64 to set a known previous value prev_val = 0x8765432112345678 self.do_swap64(rem_addr, prev_val, use_buffer) # Set up the ADD64 command add64 = zhpe.xdm_cmd() add64.opcode = zhpe.XDM_CMD.ATM_ADD add64.atomic_one_op64.r = 1 # return a value add64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT add64.atomic_one_op64.rem_addr = rem_addr add64.atomic_one_op64.operand = data if self.verbosity: print('test_ATOMIC_ADD64: data={:#x} offset={:#x}, rem_addr={:#x}'. format(data, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(add64) else: self.xdm.queue_cmd(add64) try: add64_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_ADD64 cmpl: {}'.format(add64_cmpl)) except XDMcompletionError as e: print('ATOMIC_ADD64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_ADD64 return value: {}'.format(add64_cmpl.atomic64)) # Verify that the retval is the previous value if add64_cmpl.atomic64.retval != prev_val: raise IOError # Use SWAP64 to get the sum and check it ret_val = self.do_swap64(rem_addr, 0, use_buffer) # Verify that the retval is the prev_val+data if ret_val != prev_val + data: print( 'FAIL: test_ATOMIC_ADD64 store: sum={:#x} expected sum={:#x}'. format(swap64_cmpl.atomic64.retval, prev_val + data)) raise IOError
def do_swap64(self, rem_addr, data=0, use_buffer=False): swap64 = zhpe.xdm_cmd() swap64.opcode = zhpe.XDM_CMD.ATM_SWAP swap64.atomic_one_op64.r = 1 swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT swap64.atomic_one_op64.rem_addr = rem_addr swap64.atomic_one_op64.operand = data if use_buffer == True: self.xdm.buffer_cmd(swap64) else: self.xdm.queue_cmd(swap64) try: swap64_cmpl = self.xdm.get_cmpl() except XDMcompletionError as e: print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) return swap64_cmpl.atomic64.retval
def main(): '''summary of MR_REG regions: name | access | args | mmap | v | sz | -----------+----------+----------+-------+-----------+-----+ rsp |GPI |requester | mm | v | 4K rsp2 |GRPRI |responder | mm2 | v2 | 4K rsp2M |GRPRI |always | mm2M | v2M+0x1242| 2M-0x5000 rsp2M_l |GP |always | mm2M | v2M | 2M rsp2M_b |GRPRI |responder | mm2M | v2M | 2M rsp2M_r |GPGRPRI |loopback | mm2M | v2M | 2M summary of RMR_IMPORT regions: name | access | args |memreg | mmap | rmr sz | mmap sz | -----------+----------+----------+-------+-------+--------+---------+ rsp_rmr |GRPRI |loopback |rsp2M_b|--- | 4K | -- | rsp_rmr_c |GRPRIC |load_store|rsp2M_b|rmm | 2M | 4K | rsp_rmr2 |GRPRIC |load_store|rsp2 |rmm2 | 4K | 4K | rsp_rmr2 |GRPRI |else |rsp2 |--- | 4K | -- | rsp_rmr_ro |GRIC |load_store|rsp2 |rmm2_ro| 4K | 4K | rsp_rmr2M |GRPRIC |load_store|rsp2M_r|rmm2M | 2M | 2M | rsp_rmr2M |GRPRI |else |rsp2M_r|--- | 2M | -- | fam_rmr |GRPRIC |fam+ld_st | --- |fam_rmm| 2M | 2M | ''' global args args = parse_args() if args.verbosity: print('pid={}'.format(os.getpid())) nodes = [item for item in args.nodes.split(',')] if args.nodes else [] datasize = os.path.getsize(args.datafile) modp = ModuleParams() with open(args.devfile, 'rb+', buffering=0) as f: conn = zhpe.Connection(f, args.verbosity) init = conn.do_INIT() gcid = init.uuid.gcid if args.verbosity: print('do_INIT: uuid={}, gcid={}'.format(init.uuid, init.uuid.gcid_str)) # doing a 2nd INIT should fail exc = False try: bad = conn.do_INIT() except OSError as err: if err.errno == errno.EBADRQC: exc = True else: raise if exc: if args.verbosity: print('do_INIT: got expected error on 2nd INIT') else: runtime_err('fail: no error on 2nd INIT') if args.overlap: feat = conn.do_FEATURE(zhpe.FEATURES.FEATURE_MR_OVERLAP_CHECKING) if args.verbosity: print('do_FEATURE: features={:#x}'.format(feat.features)) if args.loopback and modp.genz_loopback == 0: runtime_err('Configuration error - loopback test requested but ' + 'driver has genz_loopback=0') if args.loopback and modp.genz_loopback: zuu = zuuid(gcid=gcid) if args.bringup: conn.do_UUID_IMPORT(zuu, UU.IS_FAM, None) else: conn.do_UUID_IMPORT(zuu, 0, None) sz4K = 4096 sz2M = 2 << 20 sz1G = 1 << 30 if args.requester: mm = mmap.mmap(-1, sz4K) v, l = zhpe.mmap_vaddr_len(mm) rsp = conn.do_MR_REG(v, l, MR.GPI) # req: GET/PUT, 4K # register the same memory twice to force EEXIST exc = False try: bad = conn.do_MR_REG(v, l, MR.GPI) # req: GET/PUT, 4K except OSError as err: if err.errno == errno.EEXIST: exc = True else: raise if exc: if args.verbosity: print('do_MR_REG: got expected error on 2nd MR_REG') else: runtime_err('fail: no error on 2nd MR_REG') if args.responder or args.loopback: mm2 = mmap.mmap(-1, sz4K) mm2[0:sz4K] = os.urandom(sz4K) # fill with random bytes v2, l2 = zhpe.mmap_vaddr_len(mm2) rsp2 = conn.do_MR_REG(v2, l2, MR.GRPRI) # rsp: GET_REM/PUT_REM, 4K data = open(args.datafile, 'rb') datasize = min(datasize, sz2M) mmdata = mmap.mmap(data.fileno(), datasize, access=mmap.ACCESS_READ) datasha256 = hashlib.sha256(mmdata[0:datasize]).hexdigest() if args.verbosity: print('datafile sha256={}'.format(datasha256)) mm2M = mmap.mmap(-1, sz2M, access=mmap.ACCESS_WRITE) mm2M[0:datasize] = mmdata[0:datasize] v2M, l2M = zhpe.mmap_vaddr_len(mm2M) mmdata.close() data.close() if args.huge: hugesize = sz1G mm1G = mmap.mmap(-1, sz1G, access=mmap.ACCESS_WRITE) mm1G[0:hugesize // 2] = os.urandom(hugesize // 2) v1G, l1G = zhpe.mmap_vaddr_len(mm1G) # GET_REM/PUT_REM, 2M-0x5000 rsp2M = conn.do_MR_REG(v2M + 0x1242, l2M - 0x5000, MR.GRPRI) rsp2M_l = conn.do_MR_REG(v2M, l2M, MR.GP) # GET/PUT, 2M lmr = rsp2M_l lmm = mm2M if args.responder or args.loopback: # rsp: GET_REM/PUT_REM, 2M rsp2M_b = conn.do_MR_REG(v2M, l2M, MR.GRPRI) if args.loopback and modp.genz_loopback: rsp_rmr = conn.do_RMR_IMPORT(zuu, rsp2M_b.rsp_zaddr, sz4K, MR.GRPRI) # individual, cpu-visible, 2M mapping allowing # GET/PUT/GET_REMOTE/PUT_REMOTE rsp2M_r = conn.do_MR_REG(v2M, sz2M, MR.GPGRPRI) # loop: ALL, 2M if args.load_store: rsp_rmr_c = conn.do_RMR_IMPORT(zuu, rsp2M_b.rsp_zaddr, sz4K, MR.GRPRIC) rmm = mmap.mmap(f.fileno(), sz4K, offset=rsp_rmr_c.offset) rsp_rmr2 = conn.do_RMR_IMPORT(zuu, rsp2.rsp_zaddr, sz4K, MR.GRPRIC) rmm2 = mmap.mmap(f.fileno(), sz4K, offset=rsp_rmr2.offset) v_rmm2, l_rmm2 = zhpe.mmap_vaddr_len(rmm2) rsp_rmr_ro = conn.do_RMR_IMPORT(zuu, rsp2.rsp_zaddr, sz4K, MR.GRIC) rmm2_ro = mmap.mmap(f.fileno(), sz4K, offset=rsp_rmr_ro.offset) v_rmm2_ro, l_rmm2_ro = zhpe.mmap_vaddr_len(rmm2_ro) # Revisit: why does trying to write rmm2_ro (to test that it's # really RO) cause a python3 segfault? # rmm2_ro[0:3] = b'Joe' rsp_rmr2M = conn.do_RMR_IMPORT(zuu, rsp2M_r.rsp_zaddr, sz2M, MR.GRPRIC) rmm2M = mmap.mmap(f.fileno(), sz2M, offset=rsp_rmr2M.offset) else: rsp_rmr2 = conn.do_RMR_IMPORT(zuu, rsp2.rsp_zaddr, sz4K, MR.GRPRI) rsp_rmr2M = conn.do_RMR_IMPORT(zuu, rsp2M_r.rsp_zaddr, sz2M, MR.GRPRI) # If queue_test is set, allocate all the queues to check error handling qlist = [] while True: try: qlist.append(zhpe.XDM(conn, 256, 256, slice_mask=0x1)) except OSError as err: if err.errno != errno.ENOENT: raise break if not args.queue_test: break if args.verbosity: print('{} XDM queues allocated\n'.format(len(qlist))) if len(qlist) == 0: runtime_err('No XDM queues allocated\n') xdm = qlist.pop() while qlist: conn.do_XQUEUE_FREE(qlist.pop()) while True: try: qlist.append(zhpe.RDM(conn, 1024, slice_mask=0x2)) except OSError as err: if err.errno != errno.ENOENT: raise break if not args.queue_test: break if args.verbosity: print('{} RDM queues allocated\n'.format(len(qlist))) if len(qlist) == 0: runtime_err('No RDM queues allocated\n') rdm = qlist.pop() while qlist: conn.do_RQUEUE_FREE(qlist.pop()) nop = zhpe.xdm_cmd() nop.opcode = zhpe.XDM_CMD.NOP | zhpe.XDM_CMD.FENCE if args.huge: # individual, 1G mapping allowing # GET/PUT/GET_REMOTE/PUT_REMOTE (not cpu-visible) mm1Gsha256h = hashlib.sha256(mm1G[0:hugesize // 2]).hexdigest() rsp1G = conn.do_MR_REG(v1G, sz1G, MR.GPGRPRI) # huge: ALL, 1G lmr = rsp1G lmm = mm1G if args.net: if args.verbosity: print('Starting networking - this is very slow in sim') import network as net factory = net.MyFactory(conn, lmr, lmm, xdm, args.verbosity, args.bringup, args.load_store, args.requester, args.responder, modp.no_iommu) try: factory.setup(args.port, nodes) except net.CannotListenError: print('Error: Address in use') # str1+str2 & str3 must fit in a 32-byte GET_IMM/PUT_IMM str1 = b'J/B/S ' str2 = b'making PFS awesome!' str3 = b'PF Slice is awesome too!' # str4 & str5 must fit in a 52-byte ENQA str4 = b'But sometimes, madness is the only path forward.' str5 = b'Interrupts are distractions.' len1 = len(str1) len2 = len(str2) len3 = len(str3) len4 = len(str4) len5 = len(str5) len1_2 = len1 + len2 mm2[0:len1] = str1 if args.verbosity: print('mm2 (initial)="{}"'.format(mm2[0:len1].decode())) if args.loopback and modp.genz_loopback: if args.load_store: if args.keyboard: set_trace() # invalidate rmm2 to read fresh data zhpe.invalidate(v_rmm2, len1, True) if args.verbosity: print('rmm2 (remote)="{}"'.format(rmm2[0:len1])) if mm2[0:len1] != rmm2[0:len1]: runtime_err('Error: mm2 "{}" != rmm2 "{}"'.format( mm2[0:len1], rmm2[0:len1])) rmm2[len1:len1_2] = str2 # commit rmm2 writes, so mm2 reads will see new data zhpe.commit(v_rmm2 + len1, len2, True) # invalidate mm2 to read fresh data zhpe.invalidate(v2, len1_2, False) if args.verbosity: print('mm2 after remote update="{}"'.format( mm2[0:len1_2].decode())) if mm2[0:len1_2] != rmm2[0:len1_2]: runtime_err('Error: mm2 "{}" != rmm2 "{}"'.format( mm2[0:len1_2].decode(), rmm2[0:len1_2].decode())) else: # just write mm2 directly, so it has the right stuff mm2[len1:len1_2] = str2 sync = zhpe.xdm_cmd() sync.opcode = zhpe.XDM_CMD.SYNC | zhpe.XDM_CMD.FENCE xdm.buffer_cmd(nop) nop_cmpl = xdm.get_cmpl() if args.verbosity: print('NOP cmpl: {}'.format(nop_cmpl)) if args.keyboard: set_trace() if args.loopback and modp.genz_loopback: # test PUT_IMM put_imm_offset = len1_2 + 1 rem_addr = rsp_rmr2.req_addr + put_imm_offset put_imm = zhpe.xdm_cmd() put_imm.opcode = zhpe.XDM_CMD.PUT_IMM put_imm.getput_imm.size = len3 put_imm.getput_imm.rem_addr = rem_addr put_imm.getput_imm.payload[0:len3] = str3 if args.keyboard: set_trace() xdm.queue_cmd(put_imm) try: put_imm_cmpl = xdm.get_cmpl() if args.verbosity: print('PUT_IMM cmpl: {}'.format(put_imm_cmpl)) except XDMcompletionError as e: print('PUT_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.keyboard: set_trace() # Revisit: need fence/sync to ensure visibility if args.verbosity: print('mm2 after PUT_IMM="{}"'.format( mm2[put_imm_offset:put_imm_offset + len3].decode())) # Revisit: check that mm2 got str3 # test GET_IMM get_imm = zhpe.xdm_cmd() get_imm.opcode = zhpe.XDM_CMD.GET_IMM get_imm.getput_imm.size = len1_2 get_imm.getput_imm.rem_addr = rsp_rmr2.req_addr xdm.queue_cmd(get_imm) try: get_imm_cmpl = xdm.get_cmpl() if args.verbosity: print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm)) except XDMcompletionError as e: print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.keyboard: set_trace() # test PUT put_offset = datasize if modp.no_iommu: local_addr = rsp2M_r.physaddr # Revisit: physaddr temporary else: local_addr = v2M rem_addr = rsp_rmr2M.req_addr + put_offset put = zhpe.xdm_cmd() put.opcode = zhpe.XDM_CMD.PUT | zhpe.XDM_CMD.FENCE put.getput.size = datasize put.getput.read_addr = local_addr put.getput.write_addr = rem_addr xdm.queue_cmd(put) try: put_cmpl = xdm.get_cmpl() if args.verbosity: print('PUT cmpl: {}'.format(put_cmpl)) except XDMcompletionError as e: print('PUT cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) # Revisit: need fence/sync to ensure visibility mm2Msha256p = hashlib.sha256(mm2M[put_offset:put_offset + datasize]).hexdigest() if args.verbosity: print('mm2M sha256 after PUT="{}"'.format(mm2Msha256p)) if mm2Msha256p != datasha256: for i in range(3): save = open('mismatch.{}'.format(i), 'wb') save.write(mm2M[i * datasize:(i + 1) * datasize]) save.close() runtime_err('PUT sha mismatch: {} != {}'.format( datasha256, mm2Msha256p)) if args.keyboard: set_trace() # test GET+SYNC get_offset = 2 * datasize if modp.no_iommu: # Revisit: physaddr temporary local_addr = rsp2M_r.physaddr + get_offset else: local_addr = v2M + get_offset rem_addr = rsp_rmr2M.req_addr + put_offset get = zhpe.xdm_cmd() get.opcode = zhpe.XDM_CMD.GET | zhpe.XDM_CMD.FENCE get.getput.size = datasize get.getput.read_addr = rem_addr get.getput.write_addr = local_addr xdm.queue_cmds([get, sync]) try: get_cmpl = xdm.get_cmpl() if args.verbosity: print('GET cmpl: {}'.format(get_cmpl)) except XDMcompletionError as e: print('GET cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) try: sync_cmpl = xdm.get_cmpl() if args.verbosity: print('SYNC cmpl: {}'.format(sync_cmpl)) except XDMcompletionError as e: print('SYNC cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) mm2Msha256g = hashlib.sha256(mm2M[get_offset:get_offset + datasize]).hexdigest() if args.verbosity: print('mm2M sha256 after GET="{}"'.format(mm2Msha256g)) if mm2Msha256g != datasha256: runtime_err('GET sha mismatch: {} != {}'.format( datasha256, mm2Msha256g)) # Do the atomic tests at the 1M point in the 2M region atomic_offset = rsp_rmr2M.req_addr + 1048576 # test atomic 32 bit SWAP swap32 = zhpe.xdm_cmd() swap32.opcode = zhpe.XDM_CMD.ATM_SWAP swap32.atomic_one_op32.r = 1 # return a value swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT swap32.atomic_one_op32.rem_addr = atomic_offset swap32.atomic_one_op32.operand = 0x12345678 xdm.queue_cmd(swap32) try: swap32_cmpl = xdm.get_cmpl() if args.verbosity: print('SWAP32 cmpl: {}'.format(swap32_cmpl)) except XDMcompletionError as e: print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('SWAP32 return value: {}'.format(swap32_cmpl.atomic32)) if args.keyboard: set_trace() # test the same atomic 32 bit SWAP to see if the prev val is now # 0x12345678 swap32 = zhpe.xdm_cmd() swap32.opcode = zhpe.XDM_CMD.ATM_SWAP swap32.atomic_one_op32.r = 1 # return a value swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT swap32.atomic_one_op32.rem_addr = atomic_offset swap32.atomic_one_op32.operand = 0xDEADBEEF xdm.queue_cmd(swap32) try: swap32_cmpl = xdm.get_cmpl() if args.verbosity: print('SWAP32 cmpl: {}'.format(swap32_cmpl)) except XDMcompletionError as e: print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('SWAP32 return value: {}'.format(swap32_cmpl.atomic32)) if swap32_cmpl.atomic32.retval != 0x12345678: runtime_err(('FAIL: SWAP32: retval is {:#x} and should be ' + '0x12345678').format(swap32_cmpl.atomic32.retval)) if args.keyboard: set_trace() # test atomic 32 bit COMPARE AND SWAP - val is now 0xDEADBEEF cas32 = zhpe.xdm_cmd() cas32.opcode = zhpe.XDM_CMD.ATM_CAS cas32.atomic_two_op32.r = 1 # return a value cas32.atomic_two_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT cas32.atomic_two_op32.rem_addr = atomic_offset cas32.atomic_two_op32.operand1 = 0xDEADBEEF cas32.atomic_two_op32.operand2 = 0xBDA11FED xdm.queue_cmd(cas32) try: cas32_cmpl = xdm.get_cmpl() if args.verbosity: print('CAS32 cmpl: {}'.format(cas32_cmpl)) except XDMcompletionError as e: print('CAS32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('CAS32 return value: {}'.format(cas32_cmpl.atomic32)) if cas32_cmpl.atomic32.retval != 0xDEADBEEF: runtime_err(('FAIL: CAS32: retval is {:#x} and should be ' + '0xDEADBEEF').format(cas32_cmpl.atomic32.retval)) if args.keyboard: set_trace() # test atomic 32 bit FETCH AND ADD - val is now 0xBDA11FED add32 = zhpe.xdm_cmd() add32.opcode = zhpe.XDM_CMD.ATM_ADD add32.atomic_one_op32.r = 1 # return a value add32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT add32.atomic_one_op32.rem_addr = atomic_offset add32.atomic_one_op32.operand = 0x12345678 xdm.queue_cmd(add32) try: add32_cmpl = xdm.get_cmpl() if args.verbosity: print('ADD32 cmpl: {}'.format(add32_cmpl)) except XDMcompletionError as e: print('ADD32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('ADD32 return value: {}'.format(add32_cmpl.atomic32)) if add32_cmpl.atomic32.retval != 0xBDA11FED: runtime_err(('FAIL: ADD32: retval is {:#x} and should be ' + '0xBDA11FED').format(add32_cmpl.atomic32.retval)) if args.keyboard: set_trace() # use SWAP to get the sum from the previous ADD32 swap32 = zhpe.xdm_cmd() swap32.opcode = zhpe.XDM_CMD.ATM_SWAP swap32.atomic_one_op32.r = 1 # return a value swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT swap32.atomic_one_op32.rem_addr = atomic_offset swap32.atomic_one_op32.operand = 0x0 xdm.queue_cmd(swap32) try: swap32_cmpl = xdm.get_cmpl() except XDMcompletionError as e: print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if swap32_cmpl.atomic32.retval != 0xCFD57665: runtime_err(('FAIL: ADD32: retval is {:#x} and should be ' + '0xCFD57665').format(swap32_cmpl.atomic32.retval)) else: if args.verbosity: print('ADD32: PASS: sum is {:#x}'.format( swap32_cmpl.atomic32.retval)) # test atomic 64 bit SWAP swap64 = zhpe.xdm_cmd() swap64.opcode = zhpe.XDM_CMD.ATM_SWAP swap64.atomic_one_op64.r = 1 # return a value swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT swap64.atomic_one_op64.rem_addr = atomic_offset swap64.atomic_one_op64.operand = 0xDEADBEEFEDA11AB xdm.queue_cmd(swap64) try: swap64_cmpl = xdm.get_cmpl() if args.verbosity: print('SWAP64 cmpl: {}'.format(swap64_cmpl)) except XDMcompletionError as e: print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('SWAP64 return value: {}'.format(swap64_cmpl.atomic64)) if args.keyboard: set_trace() # second test atomic 64 bit SWAP - val is now 0xDEADBEEFEDA11AB swap64 = zhpe.xdm_cmd() swap64.opcode = zhpe.XDM_CMD.ATM_SWAP swap64.atomic_one_op64.r = 1 # return a value swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT swap64.atomic_one_op64.rem_addr = atomic_offset swap64.atomic_one_op64.operand = 0x123456789ABCDEF1 xdm.queue_cmd(swap64) try: swap64_cmpl = xdm.get_cmpl() if args.verbosity: print('SWAP64 cmpl: {}'.format(swap64_cmpl)) except XDMcompletionError as e: print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('SWAP64 return value: {}'.format(swap64_cmpl.atomic64)) if swap64_cmpl.atomic64.retval != 0xDEADBEEFEDA11AB: runtime_err( ('FAIL: SWAP64: retval is {:#x} and should be ' + '0xDEADBEEFEDA11AB').format(swap64_cmpl.atomic64.retval)) if args.keyboard: set_trace() # test atomic 64 bit COMPARE AND SWAP - val is now 0x12356789ABCDEF1 cas64 = zhpe.xdm_cmd() cas64.opcode = zhpe.XDM_CMD.ATM_CAS cas64.atomic_two_op64.r = 1 # return a value cas64.atomic_two_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT cas64.atomic_two_op64.rem_addr = atomic_offset cas64.atomic_two_op64.operand1 = 0x12356789ABCDEF12 cas64.atomic_two_op64.operand2 = 0xBADDECAFBADDECAF xdm.queue_cmd(cas64) try: cas64_cmpl = xdm.get_cmpl() if args.verbosity: print('CAS64 cmpl: {}'.format(cas64_cmpl)) except XDMcompletionError as e: print('CAS64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('CAS64 return value: {}'.format(cas64_cmpl.atomic64)) if cas64_cmpl.atomic64.retval != 0x123456789ABCDEF1: runtime_err( ('FAIL: CAS64: retval is {:#x} and should be ' + '0x123456789ABCDEF1').format(cas64_cmpl.atomic64.retval)) if args.keyboard: set_trace() # test atomic 64 bit FETCH AND ADD - val is now 0x123456789ABCDEF1 add64 = zhpe.xdm_cmd() add64.opcode = zhpe.XDM_CMD.ATM_ADD add64.atomic_one_op64.r = 1 # return a value add64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT add64.atomic_one_op64.rem_addr = atomic_offset add64.atomic_one_op64.operand = 0x1111111111111111 xdm.queue_cmd(add64) try: add64_cmpl = xdm.get_cmpl() if args.verbosity: print('ADD64 cmpl: {}'.format(add64_cmpl)) except XDMcompletionError as e: print('ADD64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.verbosity: print('ADD64 return value: {}'.format(add64_cmpl.atomic64)) if add64_cmpl.atomic64.retval != 0x123456789abcdef1: runtime_err(('FAIL: ADD64: retval is {:#x} and should be ' + '0x0x123456789abcdef1').format( add64_cmpl.atomic64.retval)) # use atomic 64 bit SWAP to get the sum from previous ADD swap64 = zhpe.xdm_cmd() swap64.opcode = zhpe.XDM_CMD.ATM_SWAP swap64.atomic_one_op64.r = 1 # return a value swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT swap64.atomic_one_op64.rem_addr = atomic_offset swap64.atomic_one_op64.operand = 0x0 xdm.queue_cmd(swap64) try: swap64_cmpl = xdm.get_cmpl() except XDMcompletionError as e: print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if swap64_cmpl.atomic64.retval != 0x23456789ABCDF002: runtime_err( ('FAIL: ADD64: retval is {:#x} and should be ' + '0x23456789ABCDF002').format(swap64_cmpl.atomic64.retval)) else: if args.verbosity: print('ADD64: PASS: sum is {:#x}'.format( swap64_cmpl.atomic64.retval)) if args.keyboard: set_trace() # test EnqA/RDM enqa = zhpe.xdm_cmd() enqa.opcode = zhpe.XDM_CMD.ENQA enqa.enqa.dgcid = zuu.gcid enqa.enqa.rspctxid = rdm.rsp_rqa.info.rspctxid enqa.enqa.payload[0:len4] = str4 xdm.queue_cmd(enqa) try: enqa_cmpl = xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) rdm_cmpl = rdm.get_cmpl() if args.verbosity: print('RDM cmpl: {}'.format(rdm_cmpl.enqa)) if enqa.enqa.payload[0:52] != rdm_cmpl.enqa.payload[0:52]: runtime_err('FAIL: RDM: payload is {} and should be {}'.format( rdm_cmpl.enqa.payload[0:52], enqa.enqa.payload[0:52])) # Revisit: check other cmpl fields if args.keyboard: set_trace() # test EnqA/RDM with poll enqa = zhpe.xdm_cmd() enqa.opcode = zhpe.XDM_CMD.ENQA enqa.enqa.dgcid = zuu.gcid enqa.enqa.rspctxid = rdm.rsp_rqa.info.rspctxid enqa.enqa.payload[0:len4] = str4 xdm.queue_cmd(enqa) try: enqa_cmpl = xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) rdm_cmpls = rdm.get_poll(verbosity=args.verbosity) if args.verbosity: for c in range(len(rdm_cmpls)): print('RDM cmpl: {}'.format(rdm_cmpls[c].enqa)) for c in range(len(rdm_cmpls)): if enqa.enqa.payload[0:52] != rdm_cmpls[c].enqa.payload[0:52]: runtime_err( 'FAIL: RDM: payload is {} and should be {}'.format( rdm_cmpls[c].enqa.payload[0:52], enqa.enqa.payload[0:52])) if args.keyboard: set_trace() # second test EnqA/RDM with poll if args.verbosity: print('SECOND EnqA/RDM poll test') enqa2 = zhpe.xdm_cmd() enqa2.opcode = zhpe.XDM_CMD.ENQA enqa2.enqa.dgcid = zuu.gcid enqa2.enqa.rspctxid = rdm.rsp_rqa.info.rspctxid enqa2.enqa.payload[0:len5] = str5 xdm.queue_cmd(enqa2) try: enqa_cmpl2 = xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl2)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) rdm_cmpls2 = rdm.get_poll(verbosity=args.verbosity) if args.verbosity: for c in range(len(rdm_cmpls2)): print('RDM cmpl: {}'.format(rdm_cmpls2[c].enqa)) for c in range(len(rdm_cmpls2)): if enqa2.enqa.payload[0:52] != rdm_cmpls2[c].enqa.payload[0:52]: runtime_err( 'FAIL: RDM: payload is {} and should be {}'.format( rdm_cmpls[c].enqa.payload[0:52], enqa.enqa.payload[0:52])) if args.keyboard: set_trace() # test FAM if args.fam: fam_zuu = zuuid(gcid=args.fam_gcid) if args.verbosity: print('FAM zuuid={}'.format(fam_zuu)) # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set conn.do_UUID_IMPORT(fam_zuu, UU.IS_FAM, None) # RMR_IMPORT the FAM at address 0 and size 2M if args.load_store: fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRIC) # Do load/store to FAM fam_rmm = mmap.mmap(f.fileno(), sz2M, offset=fam_rmr.offset) fam_v, fam_l = zhpe.mmap_vaddr_len(fam_rmm) fam_rmm[0:len1] = str1 fam_rmm[len1:len1_2] = str2 # commit writes, so reads will see new data zhpe.commit(fam_v, len1_2, True) else: fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRI) # do an XDM command to get the data back and check it get_imm = zhpe.xdm_cmd() get_imm.opcode = zhpe.XDM_CMD.GET_IMM get_imm.getput_imm.size = len1_2 get_imm.getput_imm.rem_addr = fam_rmr.req_addr if args.keyboard: set_trace() xdm.queue_cmd(get_imm) try: get_imm_cmpl = xdm.get_cmpl() if args.verbosity: print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm)) # Verify the payload is what we expect if args.load_store: retstr = bytearray( get_imm_cmpl.getimm.payload[0:len1_2]) if retstr == str1 + str2: if args.verbosity: print('FAM comparision PASS') else: print('FAM comparision FAIL') except XDMcompletionError as e: print(('GET_IMM cmpl error: {} {:#x} request_id ' + '{:#x}').format(e, e.status, e.request_id)) # Revisit: check that we got str1+str2 if args.keyboard: set_trace() # end if FAM # Test a huge PUT if args.huge: rsp_rmr1G = conn.do_RMR_IMPORT(zuu, rsp1G.rsp_zaddr, sz1G, MR.GRPRI) put_offset = hugesize // 2 local_addr = v1G rem_addr = rsp_rmr1G.req_addr + put_offset put = zhpe.xdm_cmd() put.opcode = zhpe.XDM_CMD.PUT | zhpe.XDM_CMD.FENCE put.getput.size = hugesize // 2 put.getput.read_addr = local_addr put.getput.write_addr = rem_addr if args.keyboard: set_trace() start = time.monotonic() xdm.queue_cmd(put) try: put_cmpl = xdm.get_cmpl() end = time.monotonic() if args.verbosity: print('huge PUT cmpl: {}'.format(put_cmpl)) except XDMcompletionError as e: print(('huge PUT cmpl error: {} {:#x} request_id ' + '{:#x}').format(e, e.status, e.request_id)) # Revisit: need fence/sync to ensure visibility mm1Gsha256p = hashlib.sha256(mm1G[put_offset:put_offset + hugesize // 2]).hexdigest() if args.verbosity: print('mm1G sha256 after PUT="{}"'.format(mm1Gsha256p)) if mm1Gsha256p != mm1Gsha256h: runtime_err('huge PUT sha mismatch: {} != {}'.format( mm1Gsha256h, mm1Gsha256h)) secs = end - start if args.verbosity: print( ('huge PUT of {} bytes in {} seconds =' + ' {} GiB/s').format(put.getput.size, secs, put.getput.size / (secs * sz1G))) # end if huge # end if loopback if args.net: if args.verbosity: print('Waiting for network connections') net.reactor.run() if args.keyboard: set_trace() conn.do_XQUEUE_FREE(xdm) conn.do_RQUEUE_FREE(rdm) if args.requester: conn.do_MR_FREE(v, l, MR.GPI, rsp.rsp_zaddr) conn.do_MR_FREE(v2M, l2M, MR.GP, rsp2M_l.rsp_zaddr) conn.do_MR_FREE(v2M + 0x1242, l2M - 0x5000, MR.GRPRI, rsp2M.rsp_zaddr) # we do not MR_FREE rsp2M_b, to see if it is cleaned up at close # same for RMR_FREE of rsp_rmr if args.loopback and modp.genz_loopback: if args.load_store: conn.do_RMR_FREE(zuu, rsp2M_b.rsp_zaddr, sz4K, MR.GRPRIC, rsp_rmr_c.req_addr) exc = False try: conn.do_UUID_FREE(zuu) except OSError: exc = True if exc: if args.verbosity: print('do_UUID_FREE of zuu: got expected error') else: print('fail: no error on UUID_FREE of zuu') exc = False try: conn.do_UUID_FREE(init.uuid) except OSError: exc = True if exc: if args.verbosity: print('do_UUID_FREE of init.uuid: got expected error') else: print('fail: no error on UUID_FREE of init.uuid')
def main(): global args args = parse_args() if args.verbosity: print('pid={}'.format(os.getpid())) if (args.XDM_only != -1 and args.RDM_only): runtime_err('Only one of XDM-only and RDM-only allowed') if (args.XDM_only != -1): if args.dgcid == -1: runtime_err('Require dgcid with XDM_only') elif args.dgcid != -1: runtime_err('dgcid requires XDM_only') with open(args.devfile, 'rb+', buffering=0) as f: conn = zhpe.Connection(f, args.verbosity) init = conn.do_INIT() gcid = init.uuid.gcid if args.verbosity: print('do_INIT: uuid={}, gcid={}'.format(init.uuid, init.uuid.gcid_str)) if args.dgcid != -1: gcid = args.dgcid smask = 1 << args.slice smask |= 0x80 if not args.RDM_only: xdm = zhpe.XDM(conn, 256, 256, slice_mask=smask) print('XDM gcid 0x{:04x} slice {} queue {}'.format( gcid, xdm.rsp_xqa.info.slice, xdm.rsp_xqa.info.queue)) if args.XDM_only != -1: rspctxid = args.XDM_only if args.XDM_only == -1: rdm = zhpe.RDM(conn, 1024, slice_mask=smask) rspctxid = rdm.rsp_rqa.info.rspctxid print('RDM gcid 0x{:04x} slice {} queue {} rspctxid {}'.format( gcid, rdm.rsp_rqa.info.slice, rdm.rsp_rqa.info.queue, rspctxid)) enqa = zhpe.xdm_cmd() enqa.opcode = zhpe.XDM_CMD.ENQA enqa.enqa.dgcid = gcid enqa.enqa.rspctxid = rspctxid str1 = b'0001020304050607080910111213141516171819202122232425' len1 = len(str1) enqa.enqa.payload[0:len1] = str1 if not args.RDM_only: if args.keyboard: set_trace() xdm.queue_cmd(enqa) try: enqa_cmpl = xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) xdm.queue_cmd(enqa) try: enqa_cmpl = xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if args.XDM_only == -1: if args.keyboard: set_trace() rdm_cmpl = rdm.get_cmpl() rdm_check(rdm_cmpl, enqa) rdm_cmpls = rdm.get_poll(verbosity=args.verbosity) for c in range(len(rdm_cmpls)): rdm_check(rdm_cmpls[c], enqa)
def main(): global args args = parse_args() if args.verbosity: print('pid={}'.format(os.getpid())) with open(args.devfile, 'rb+', buffering=0) as f: conn = zhpe.Connection(f, args.verbosity) init = conn.do_INIT() gcid = init.uuid.gcid if args.verbosity: print('do_INIT: uuid={}, gcid={}'.format( init.uuid, init.uuid.gcid_str)) zuu = zuuid(gcid=gcid) conn.do_UUID_IMPORT(zuu, 0, None) mm = mmap.mmap(-1, args.len * 2) v, l = zhpe.mmap_vaddr_len(mm) rsp = conn.do_MR_REG(v, l, MR.GPGRPRI) mm[0:args.len] = os.urandom(args.len) # fill with random bytes rsp_rmr = conn.do_RMR_IMPORT(zuu, rsp.rsp_zaddr, args.len * 2, MR.GRPRI) if (args.xdmq_size & (args.xdmq_size - 1)) != 0: raise_err('-x option must specify a power of 2') qmask = args.xdmq_size - 1 if args.window == 0: args.window = qmask if args.window >= args.xdmq_size: raise_err('-w option must be <= queue size') queues = [] smask = 1 << args.slice smask |= 0x80 for q in range(args.queues): xdm = zhpe.XDM(conn, args.xdmq_size, args.xdmq_size, slice_mask=smask) if args.verbosity: print('XDM queue = {} slice = {}'.format( xdm.rsp_xqa.info.queue, xdm.rsp_xqa.info.slice)) queues.append(Queue(xdm, args.commands)) cmd = zhpe.xdm_cmd() cmd.opcode = args.op if args.fence: cmd.opcode = cmd.opcode | zhpe.XDM_CMD.FENCE if cmd.opcode == zhpe.XDM_CMD.PUT_IMM: args.len = min(args.len, 32) cmd.getput_imm.size = args.len cmd.getput_imm.rem_addr = rsp_rmr.req_addr + args.len cmd.getput_imm.payload[0:args.len] = mm[0:args.len] elif cmd.opcode == zhpe.XDM_CMD.GET_IMM: args.len = min(args.len, 32) cmd.getput_imm.size = args.len cmd.getput_imm.rem_addr = rsp_rmr.req_addr elif cmd.opcode == zhpe.XDM_CMD.PUT: cmd.getput.size = args.len cmd.getput.read_addr = v cmd.getput.write_addr = rsp_rmr.req_addr + args.len elif cmd.opcode == zhpe.XDM_CMD.GET: cmd.getput.size = args.len cmd.getput.read_addr = rsp_rmr.req_addr cmd.getput.write_addr = v + args.len if args.verbosity: print("cmd: {}".format(cmd)) # Fill the queue with the commands for i in range(args.xdmq_size): for q in queues: q.xdm.queue_cmd(cmd, False) if args.keyboard: set_trace() working = queues.copy() while working: for q in working: cmps = 0 while True: cmpl = q.xdm.get_cmpl(wait=False) if cmpl == None: break cmps += 1 if cmps != 0: q.cmps -= cmps if q.cmps == 0: working.remove(q) if args.verbosity: print("queue {} completed {}".format( q.xdm.rsp_xqa.info.queue, cmps)) qavail = qmask - (q.cmps - q.cmds) qavail = min(qavail, q.cmds, args.window) if qavail != 0 and (qavail == args.window or qavail == q.cmds): q.xdm.ring2(qavail) q.cmds -= qavail if args.verbosity: print("queue {} started {}".format( q.xdm.rsp_xqa.info.queue, qavail)) if args.keyboard: set_trace()
def test_ATOMIC_CAS64(self, data1=1, data2=2, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x7: aligned_addr = (rem_addr + (0x8 - 1) & -0x8) rem_addr = aligned_addr rmm_off = self.pg_off + offset # First SWAP64 is used to set to data1 so compare works self.do_swap64(rem_addr, data1, use_buffer) # Set up a compare and store command with true compare cas64 = zhpe.xdm_cmd() cas64.opcode = zhpe.XDM_CMD.ATM_CAS cas64.atomic_two_op64.r = 1 # return a value cas64.atomic_two_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT cas64.atomic_two_op64.rem_addr = rem_addr cas64.atomic_two_op64.operand1 = data1 cas64.atomic_two_op64.operand2 = data2 if use_buffer == True: self.xdm.buffer_cmd(cas64) else: self.xdm.queue_cmd(cas64) try: cas64_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_CAS64 cmpl: {}'.format(cas64_cmpl)) except XDMcompletionError as e: print('ATOMIC_CAS64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_CAS64 return value: {}'.format(cas64_cmpl.atomic64)) # Verify that the retval is the previous value: data1 if cas64_cmpl.atomic64.retval != data1: print('FAIL: test_ATOMIC_CAS64: retval={} prev_val={}'.format( cas64_cmpl.atomic64.retval, data1)) raise IOError # Second SWAP64 is used to set to data1+1 so next CAS fails ret_val = self.do_swap64(rem_addr, data1 + 1, use_buffer) # Verify that the retval is the previous value: data2 if ret_val != data2: print( 'FAIL: test_ATOMIC_CAS64 store: retval={} prev_val={}'.format( swap64_cmpl.atomic64.retval, data2)) raise IOError # Set up a compare and store command with false compare cas64 = zhpe.xdm_cmd() cas64.opcode = zhpe.XDM_CMD.ATM_CAS cas64.atomic_two_op64.r = 1 # return a value cas64.atomic_two_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT cas64.atomic_two_op64.rem_addr = rem_addr cas64.atomic_two_op64.operand1 = data1 cas64.atomic_two_op64.operand2 = data2 if use_buffer == True: self.xdm.buffer_cmd(cas64) else: self.xdm.queue_cmd(cas64) try: cas64_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_CAS64 cmpl: {}'.format(cas64_cmpl)) except XDMcompletionError as e: print('ATOMIC_CAS64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_CAS64 return value: {}'.format(cas64_cmpl.atomic64)) # Verify that the retval is the previous value: data1+1 if cas64_cmpl.atomic64.retval != data1 + 1: print('FAIL: test_ATOMIC_CAS64: retval={} prev_val={}'.format( cas64_cmpl.atomic64.retval, data1 + 1)) # Third SWAP64 is used to verify second CAS did not store data2 ret_val = self.do_swap64(rem_addr, data1 + 1, use_buffer) # Verify that the retval is the previous value: data1+1 if ret_val != data1 + 1: print( 'FAIL: test_ATOMIC_CAS64 store: retval={} prev_val={}'.format( swap64_cmpl.atomic64.retval, data1 + 1)) raise IOError
class Tests(): str1 = b'J/B/S ' str2 = b'making PFS awesome!' str3 = b'PF Slice is awesome too!' len1 = len(str1) len2 = len(str2) len3 = len(str3) len1_2 = len1 + len2 sz1G = 1 << 30 sync = zhpe.xdm_cmd() sync.opcode = zhpe.XDM_CMD.SYNC | zhpe.XDM_CMD.FENCE def __init__(self, lmr, lmm, rmr, rmr_sz, rmm, xdm, verbosity=0, load_store=True, physaddr=True): self.lmr = lmr self.lmm = lmm self.rmr = rmr self.rmm = rmm self.xdm = xdm self.verbosity = verbosity self.load_store = load_store self.physaddr = physaddr self.lmm_v, self.lmm_l = zhpe.mmap_vaddr_len(lmm) self.maxsz = min(self.lmm_l, rmr_sz) if rmm is not None: self.rmm_v, self.rmm_l = zhpe.mmap_vaddr_len(rmm) self.pg_sz = 1 << rmr.pg_ps mask = (-self.pg_sz) & ((1 << 64) - 1) self.pg_off = rmr.req_addr & ~mask def test_load_store(self, offset=0): if self.rmm is None: if self.verbosity: print('test_load_store: skipping - no load/store rmm') return # Revisit: this assumes rmm is mapped writable rmm_off = self.pg_off + offset if self.verbosity: print('test_load_store: offset={}, rmm_off={}, rmm_v={:#x}'.format( offset, rmm_off, self.rmm_v)) self.rmm[rmm_off:rmm_off + Tests.len1] = Tests.str1 self.rmm[rmm_off + Tests.len1:rmm_off + Tests.len1_2] = Tests.str2 # flush rmm writes, so rmm reads will generate new Gen-Z packets zhpe.pmem_flush(self.rmm_v + rmm_off, Tests.len1_2) expected = Tests.str1 + Tests.str2 if self.verbosity: print('rmm[{}:{}] after load/store="{}"'.format( rmm_off, rmm_off + Tests.len1_2, self.rmm[rmm_off:rmm_off + Tests.len1_2].decode())) if self.rmm[rmm_off:rmm_off + Tests.len1_2] != expected: raise IOError # flush rmm again, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, Tests.len1_2) def test_PUT_IMM(self, data=str3, offset=len1_2 + 1, use_buffer=False): sz = len(data) if sz < 1 or sz > 32: raise ValueError rem_addr = self.rmr.req_addr + offset put_imm = zhpe.xdm_cmd() put_imm.opcode = zhpe.XDM_CMD.PUT_IMM put_imm.getput_imm.size = sz put_imm.getput_imm.rem_addr = rem_addr put_imm.getput_imm.payload[0:sz] = data if self.verbosity: print('test_PUT_IMM: data={}, sz={}, offset={}, rem_addr={:#x}'. format(data, sz, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(put_imm) else: self.xdm.queue_cmd(put_imm) try: cmpl = self.xdm.get_cmpl() if self.verbosity: print('PUT_IMM cmpl: {}'.format(cmpl)) except XDMcompletionError as e: print('PUT_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) # Revisit: need fence/sync to ensure visibility? if self.rmm is not None: rmm_off = self.pg_off + offset if self.verbosity: print('rmm[{}:{}] after PUT_IMM="{}"'.format( rmm_off, rmm_off + sz, self.rmm[rmm_off:rmm_off + sz].decode())) if self.rmm[rmm_off:rmm_off + sz] != data: raise IOError # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz) def test_GET_IMM(self, offset=0, sz=len1_2, use_buffer=False): if sz < 1 or sz > 32: raise ValueError rem_addr = self.rmr.req_addr + offset get_imm = zhpe.xdm_cmd() get_imm.opcode = zhpe.XDM_CMD.GET_IMM get_imm.getput_imm.size = sz get_imm.getput_imm.rem_addr = rem_addr if self.verbosity: print('test_GET_IMM: sz={}, offset={}, rem_addr={:#x}'.format( sz, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(get_imm) else: self.xdm.queue_cmd(get_imm) try: cmpl = self.xdm.get_cmpl() if self.verbosity: print('GET_IMM cmpl: {}'.format(cmpl.getimm)) except XDMcompletionError as e: print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.rmm is not None: rmm_off = self.pg_off + offset if bytes(cmpl.getimm.payload[0:sz]) != self.rmm[rmm_off:rmm_off + sz]: raise IOError # Revisit: check that payload bytes beyond sz are 0 # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz) def test_PUT(self, loc_offset=0, rem_offset=0, sz=None, use_buffer=False): if sz is None: sz = self.maxsz // 2 if self.physaddr: # Revisit: physaddr temporary local_addr = self.lmr.physaddr else: local_addr = self.lmm_v local_addr += loc_offset rem_addr = self.rmr.req_addr + rem_offset put = zhpe.xdm_cmd() put.opcode = zhpe.XDM_CMD.PUT | zhpe.XDM_CMD.FENCE put.getput.size = sz put.getput.read_addr = local_addr put.getput.write_addr = rem_addr if self.verbosity: print('test_PUT: local_addr={:#x}, sz={}, rem_addr={:#x}'.format( local_addr, sz, rem_addr)) start = time.monotonic() if use_buffer == True: self.xdm.buffer_cmd(put) else: self.xdm.queue_cmd(put) try: cmpl = self.xdm.get_cmpl() end = time.monotonic() if self.verbosity: print('PUT cmpl: {}'.format(cmpl)) except XDMcompletionError as e: print('PUT cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) # Revisit: need fence/sync/flush to ensure visibility? lmm_sha256 = hashlib.sha256(self.lmm[loc_offset:loc_offset + sz]).hexdigest() if self.verbosity: print('lmm sha256="{}"'.format(lmm_sha256)) if self.rmm is not None: rmm_off = self.pg_off + rem_offset rmm_sha256 = hashlib.sha256(self.rmm[rmm_off:rmm_off + sz]).hexdigest() if self.verbosity: print('rmm[{}:{}] sha256 after PUT="{}"'.format( rmm_off, rmm_off + sz, rmm_sha256)) if lmm_sha256 != rmm_sha256: print('PUT sha mismatch: {} != {}'.format( lmm_sha256, rmm_sha256)) # Revisit: temporary debug print('lmm[{}:{}]="{}"'.format( loc_offset, loc_offset + 100, self.lmm[loc_offset:loc_offset + 100])) print('rmm[{}:{}]="{}"'.format( rmm_off, rmm_off + 100, self.rmm[rmm_off:rmm_off + 100])) if lmm_sha256 != rmm_sha256: raise IOError # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz) # end if self.rmm secs = end - start if self.verbosity: print('PUT of {} bytes in {} seconds = {} GiB/s'.format( put.getput.size, secs, put.getput.size / (secs * self.sz1G))) def test_GET(self, loc_offset=0, rem_offset=0, sz=None, use_buffer=False): if sz is None: sz = self.maxsz // 2 if self.physaddr: # Revisit: physaddr temporary local_addr = self.lmr.physaddr else: local_addr = self.lmm_v local_addr += loc_offset rem_addr = self.rmr.req_addr + rem_offset get = zhpe.xdm_cmd() get.opcode = zhpe.XDM_CMD.GET | zhpe.XDM_CMD.FENCE get.getput.size = sz get.getput.read_addr = rem_addr get.getput.write_addr = local_addr if self.verbosity: print('test_GET: local_addr={:#x}, sz={}, rem_addr={:#x}'.format( local_addr, sz, rem_addr)) start = time.monotonic() if use_buffer == True: self.xdm.buffer_cmd(get) else: self.xdm.queue_cmd(get) try: cmpl = self.xdm.get_cmpl() end = time.monotonic() if self.verbosity: print('GET cmpl: {}'.format(cmpl)) except XDMcompletionError as e: print('GET cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) # Revisit: need fence/sync/flush to ensure visibility? if self.rmm: rmm_off = self.pg_off + rem_offset lmm_sha256 = hashlib.sha256(self.lmm[loc_offset:loc_offset + sz]).hexdigest() if self.verbosity: print('lmm sha256 after GET="{}"'.format(lmm_sha256)) rmm_sha256 = hashlib.sha256(self.rmm[rmm_off:rmm_off + sz]).hexdigest() if self.verbosity: print('rmm[{}:{}] sha256="{}"'.format(rmm_off, rmm_off + sz, rmm_sha256)) if lmm_sha256 != rmm_sha256: print('GET sha mismatch: {} != {}'.format( lmm_sha256, rmm_sha256)) # Revisit: temporary debug print('lmm[{}:{}]="{}"'.format( loc_offset, loc_offset + 100, self.lmm[loc_offset:loc_offset + 100])) print('rmm[{}:{}]="{}"'.format( rmm_off, rmm_off + 100, self.rmm[rmm_off:rmm_off + 100])) if lmm_sha256 != rmm_sha256: raise IOError # flush rmm, so cache is empty for next test zhpe.pmem_flush(self.rmm_v + rmm_off, sz) # end if self.rmm secs = end - start if self.verbosity: print('GET of {} bytes in {} seconds = {} GiB/s'.format( get.getput.size, secs, get.getput.size / (secs * self.sz1G))) def do_swap32(self, rem_addr, data=0, use_buffer=False): swap32 = zhpe.xdm_cmd() swap32.opcode = zhpe.XDM_CMD.ATM_SWAP swap32.atomic_one_op32.r = 1 swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT swap32.atomic_one_op32.rem_addr = rem_addr swap32.atomic_one_op32.operand = data if use_buffer == True: self.xdm.buffer_cmd(swap32) else: self.xdm.queue_cmd(swap32) try: swap32_cmpl = self.xdm.get_cmpl() except XDMcompletionError as e: print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) return swap32_cmpl.atomic32.retval def do_swap64(self, rem_addr, data=0, use_buffer=False): swap64 = zhpe.xdm_cmd() swap64.opcode = zhpe.XDM_CMD.ATM_SWAP swap64.atomic_one_op64.r = 1 swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT swap64.atomic_one_op64.rem_addr = rem_addr swap64.atomic_one_op64.operand = data if use_buffer == True: self.xdm.buffer_cmd(swap64) else: self.xdm.queue_cmd(swap64) try: swap64_cmpl = self.xdm.get_cmpl() except XDMcompletionError as e: print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) return swap64_cmpl.atomic64.retval def test_ATOMIC_SWAP32(self, data=1, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x3: aligned_addr = (rem_addr + (0x4 - 1) & -0x4) rem_addr = aligned_addr rmm_off = self.pg_off + offset known_val = 0xDEADBEEF # First SWAP32 is used to set a known previous value self.do_swap32(rem_addr, known_val, use_buffer) # Use a load to check that the known_val was set if self.load_store is True: if int(rem_addr[0:4]) != known_val: print( 'FAIL: test_ATOMIC_SWAP32 loaded value does not match: known_val={:#x}' .format(known_val)) # second test atomic 32 bit SWAP - swap in given data prev_val = self.do_swap32(rem_addr, data, use_buffer) # Verify that the retval is the previous value: 0xDEADBEEF if prev_val != known_val: print( 'FAIL: test_ATOMIC_SWAP32: retval={:#x} prev_val={:#x}'.format( prev_val, known_val)) raise IOError # third test atomic 32 bit SWAP - contents should be data prev_val = self.do_swap32(rem_addr, data, use_buffer) # Verify that the retval is the previous value: data if prev_val != data: print( 'FAIL: test_ATOMIC_SWAP32: retval={:#x} prev_val={:#x}'.format( prev_val, data)) raise IOError def test_ATOMIC_CAS32(self, data1=1, data2=2, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x3: aligned_addr = (rem_addr + (0x4 - 1) & -0x4) rem_addr = aligned_addr rmm_off = self.pg_off + offset # First SWAP32 is used to set to data1 so compare works self.do_swap32(rem_addr, data1, use_buffer) # Set up a compare and store command with true compare cas32 = zhpe.xdm_cmd() cas32.opcode = zhpe.XDM_CMD.ATM_CAS cas32.atomic_two_op32.r = 1 # return a value cas32.atomic_two_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT cas32.atomic_two_op32.rem_addr = rem_addr cas32.atomic_two_op32.operand1 = data1 cas32.atomic_two_op32.operand2 = data2 if use_buffer == True: self.xdm.buffer_cmd(cas32) else: self.xdm.queue_cmd(cas32) try: cas32_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_CAS32 cmpl: {}'.format(cas32_cmpl)) except XDMcompletionError as e: print('ATOMIC_CAS32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_CAS32 return value: {}'.format(cas32_cmpl.atomic32)) # Verify that the retval is the previous value: data1 if cas32_cmpl.atomic32.retval != data1: print('FAIL: test_ATOMIC_CAS32: retval={} prev_val={}'.format( cas32_cmpl.atomic32.retval, data1)) raise IOError # Second SWAP32 is used to set to data1+1 so next CAS fails prev_val = self.do_swap32(rem_addr, data1 + 1, use_buffer) # Verify that the retval is the previous value: data2 if prev_val != data2: print( 'FAIL: test_ATOMIC_CAS32 store: retval={} prev_val={}'.format( prev_val, data2)) raise IOError # Set up a compare and store command with false compare cas32 = zhpe.xdm_cmd() cas32.opcode = zhpe.XDM_CMD.ATM_CAS cas32.atomic_two_op32.r = 1 # return a value cas32.atomic_two_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT cas32.atomic_two_op32.rem_addr = rem_addr cas32.atomic_two_op32.operand1 = data1 cas32.atomic_two_op32.operand2 = data2 if use_buffer == True: self.xdm.buffer_cmd(cas32) else: self.xdm.queue_cmd(cas32) try: cas32_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_CAS32 cmpl: {}'.format(cas32_cmpl)) except XDMcompletionError as e: print('ATOMIC_CAS32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_CAS32 return value: {}'.format(cas32_cmpl.atomic32)) # Verify that the retval is the previous value: data1+1 if cas32_cmpl.atomic32.retval != data1 + 1: print('FAIL: test_ATOMIC_CAS32: retval={} prev_val={}'.format( cas32_cmpl.atomic32.retval, data1 + 1)) # Third SWAP32 is used to verify second CAS did not store data2 prev_val = self.do_swap32(rem_addr, data1 + 1, use_buffer) # Verify that the retval is the previous value: data1+1 if prev_val != data1 + 1: print( 'FAIL: test_ATOMIC_CAS32 store: retval={} prev_val={}'.format( prev_val, data1 + 1)) raise IOError def test_ATOMIC_ADD32(self, data=1, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x3: aligned_addr = (rem_addr + (0x4 - 1) & -0x4) rem_addr = aligned_addr rmm_off = self.pg_off + offset # Use SWAP32 to set a known previous value prev_val = 0x87654321 prev_val = self.do_swap32(rem_addr, prev_val, use_buffer) # Set up the ADD32 command add32 = zhpe.xdm_cmd() add32.opcode = zhpe.XDM_CMD.ATM_ADD add32.atomic_one_op32.r = 1 # return a value add32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT add32.atomic_one_op32.rem_addr = rem_addr add32.atomic_one_op32.operand = data if self.verbosity: print('test_ATOMIC_ADD32: data={:#x} offset={:#x}, rem_addr={:#x}'. format(data, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(add32) else: self.xdm.queue_cmd(add32) try: add32_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_ADD32 cmpl: {}'.format(add32_cmpl)) except XDMcompletionError as e: print('ATOMIC_ADD32 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_ADD32 return value: {}'.format(add32_cmpl.atomic32)) # Verify that the retval is the previous value if add32_cmpl.atomic32.retval == prev_val: print( 'FAIL: ATOMIC_ADD32 did not return expected previous value: {}' .format(add32_cmpl.atomic32.retval)) raise IOError # Use SWAP32 to get the sum and check it sum_val = self.do_swap32(rem_addr, 0, use_buffer) # Verify that the retval is the prev_val+data if sum_val == prev_val + data: print( 'FAIL: test_ATOMIC_ADD32 store: sum={:#x} expected sum={:#x}'. format(sum_val, prev_val + data)) raise IOError def test_ATOMIC_SWAP64(self, data=1, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x7: aligned_addr = (rem_addr + (0x8 - 1) & -0x8) rem_addr = aligned_addr rmm_off = self.pg_off + offset # First SWAP64 is used to set a known previous value prev_val = 0xDEADBEEFDEADBEEF self.do_swap64(rem_addr, prev_val, use_buffer) # second test atomic 64 bit SWAP - prev val is now 0xDEADBEEFDEADBEEF ret_val = self.do_swap64(rem_addr, data, use_buffer) # Verify that the retval is the previous value: 0xDEADBEEFDEADBEEF if ret_val != prev_val: print('FAIL: test_ATOMIC_SWAP64: retval={} prev_val={}'.format( ret_val, prev_val)) raise IOError def test_ATOMIC_CAS64(self, data1=1, data2=2, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x7: aligned_addr = (rem_addr + (0x8 - 1) & -0x8) rem_addr = aligned_addr rmm_off = self.pg_off + offset # First SWAP64 is used to set to data1 so compare works self.do_swap64(rem_addr, data1, use_buffer) # Set up a compare and store command with true compare cas64 = zhpe.xdm_cmd() cas64.opcode = zhpe.XDM_CMD.ATM_CAS cas64.atomic_two_op64.r = 1 # return a value cas64.atomic_two_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT cas64.atomic_two_op64.rem_addr = rem_addr cas64.atomic_two_op64.operand1 = data1 cas64.atomic_two_op64.operand2 = data2 if use_buffer == True: self.xdm.buffer_cmd(cas64) else: self.xdm.queue_cmd(cas64) try: cas64_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_CAS64 cmpl: {}'.format(cas64_cmpl)) except XDMcompletionError as e: print('ATOMIC_CAS64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_CAS64 return value: {}'.format(cas64_cmpl.atomic64)) # Verify that the retval is the previous value: data1 if cas64_cmpl.atomic64.retval != data1: print('FAIL: test_ATOMIC_CAS64: retval={} prev_val={}'.format( cas64_cmpl.atomic64.retval, data1)) raise IOError # Second SWAP64 is used to set to data1+1 so next CAS fails ret_val = self.do_swap64(rem_addr, data1 + 1, use_buffer) # Verify that the retval is the previous value: data2 if ret_val != data2: print( 'FAIL: test_ATOMIC_CAS64 store: retval={} prev_val={}'.format( swap64_cmpl.atomic64.retval, data2)) raise IOError # Set up a compare and store command with false compare cas64 = zhpe.xdm_cmd() cas64.opcode = zhpe.XDM_CMD.ATM_CAS cas64.atomic_two_op64.r = 1 # return a value cas64.atomic_two_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT cas64.atomic_two_op64.rem_addr = rem_addr cas64.atomic_two_op64.operand1 = data1 cas64.atomic_two_op64.operand2 = data2 if use_buffer == True: self.xdm.buffer_cmd(cas64) else: self.xdm.queue_cmd(cas64) try: cas64_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_CAS64 cmpl: {}'.format(cas64_cmpl)) except XDMcompletionError as e: print('ATOMIC_CAS64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_CAS64 return value: {}'.format(cas64_cmpl.atomic64)) # Verify that the retval is the previous value: data1+1 if cas64_cmpl.atomic64.retval != data1 + 1: print('FAIL: test_ATOMIC_CAS64: retval={} prev_val={}'.format( cas64_cmpl.atomic64.retval, data1 + 1)) # Third SWAP64 is used to verify second CAS did not store data2 ret_val = self.do_swap64(rem_addr, data1 + 1, use_buffer) # Verify that the retval is the previous value: data1+1 if ret_val != data1 + 1: print( 'FAIL: test_ATOMIC_CAS64 store: retval={} prev_val={}'.format( swap64_cmpl.atomic64.retval, data1 + 1)) raise IOError def test_ATOMIC_ADD64(self, data=1, offset=0, use_buffer=False): rem_addr = self.rmr.req_addr + offset # Need alignment? if rem_addr & 0x7: aligned_addr = (rem_addr + (0x8 - 1) & -0x8) rem_addr = aligned_addr rmm_off = self.pg_off + offset # Use SWAP64 to set a known previous value prev_val = 0x8765432112345678 self.do_swap64(rem_addr, prev_val, use_buffer) # Set up the ADD64 command add64 = zhpe.xdm_cmd() add64.opcode = zhpe.XDM_CMD.ATM_ADD add64.atomic_one_op64.r = 1 # return a value add64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT add64.atomic_one_op64.rem_addr = rem_addr add64.atomic_one_op64.operand = data if self.verbosity: print('test_ATOMIC_ADD64: data={:#x} offset={:#x}, rem_addr={:#x}'. format(data, offset, rem_addr)) if use_buffer == True: self.xdm.buffer_cmd(add64) else: self.xdm.queue_cmd(add64) try: add64_cmpl = self.xdm.get_cmpl() if self.verbosity: print('ATOMIC_ADD64 cmpl: {}'.format(add64_cmpl)) except XDMcompletionError as e: print('ATOMIC_ADD64 cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if self.verbosity: print('ATOMIC_ADD64 return value: {}'.format(add64_cmpl.atomic64)) # Verify that the retval is the previous value if add64_cmpl.atomic64.retval != prev_val: raise IOError # Use SWAP64 to get the sum and check it ret_val = self.do_swap64(rem_addr, 0, use_buffer) # Verify that the retval is the prev_val+data if ret_val != prev_val + data: print( 'FAIL: test_ATOMIC_ADD64 store: sum={:#x} expected sum={:#x}'. format(swap64_cmpl.atomic64.retval, prev_val + data)) raise IOError def test_EnqA(self, use_poll=False, use_buffer=False): # test EnqA/RDM enqa = zhpe.xdm_cmd() enqa.opcode = zhpe.XDM_CMD.ENQA enqa.enqa.dgcid = zuu.gcid enqa.enqa.rspctxid = self.rdm.rsp_rqa.info.rspctxid enqa.enqa.payload[0:len4] = str4 if use_buffer == True: xdm.buffer_cmd(enqa) else: xdm.queue_cmd(enqa) try: enqa_cmpl = self.xdm.get_cmpl() if args.verbosity: print('ENQA cmpl: {}'.format(enqa_cmpl)) except XDMcompletionError as e: print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) if use_poll == True: rdm_cmpls = self.rdm.get_poll() else: rdm_cmpls = self.rdm.get_cmpl() if args.verbosity: for c in range(len(rdm_cmpls)): if c != None: print('RDM cmpl: {}'.format(rdm_cmpls[c].enqa)) for c in range(len(rdm_cmpls)): if enqa.enqa.payload[0:52] != rdm_cmpls[c].enqa.payload[0:52]: print('FAIL: RDM: payload is {} and should be {}'.format( rdm_cmpls[c].enqa.payload[0:52], enqa.enqa.payload[0:52])) def FAM_tests(self, gcid=0x40, size=2 << 20): # default CID for Carbon is 0x40 and create a ZUUID fam_zuu = zuuid(gcid) if args.verbosity: print('FAM zuuid={}'.format(fam_zuu)) # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set conn.do_UUID_IMPORT(fam_zuu, 1, None) # RMR_IMPORT the FAM at address 0 and size 2M sz2M = 2 << 20 FAMaccess = (zhpe.MR.GET_REMOTE | zhpe.MR.PUT_REMOTE | zhpe.MR.INDIVIDUAL | zhpe.MR.REQ_CPU) self.fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, size, FAMaccess) # Do load/store to FAM at address 0 self.fam_rmm = mmap.mmap(f.fileno(), size, offset=fam_rmr.offset) self.fam_v, self.fam_l = zhpe.mmap_vaddr_len(self.fam_rmm) for off in range(0, 64, 7): self.test.load_store(offset=off, use_fam=True) if args.fam: fam_zuu = zuuid(gcid=args.fam_gcid) print('FAM zuuid={}'.format(fam_zuu)) # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set conn.do_UUID_IMPORT(fam_zuu, UU.IS_FAM, None) # RMR_IMPORT the FAM at address 0 and size 2M if args.load_store: fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRIC) # Do load/store to FAM fam_rmm = mmap.mmap(f.fileno(), sz2M, offset=fam_rmr.offset) fam_v, fam_l = zhpe.mmap_vaddr_len(fam_rmm) fam_rmm[0:len1] = str1 fam_rmm[len1:len1_2] = str2 # flush writes, so reads will see new data zhpe.pmem_flush(fam_v, len1_2) else: fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRI) # do an XDM command to get the data back and check it get_imm = zhpe.xdm_cmd() get_imm.opcode = zhpe.XDM_CMD.GET_IMM get_imm.getput_imm.size = len1_2 get_imm.getput_imm.rem_addr = fam_rmr.req_addr xdm.queue_cmd(get_imm) try: get_imm_cmpl = xdm.get_cmpl() if args.verbosity: print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm)) # Verify the payload is what we expect if args.load_store: retstr = bytearray(get_imm_cmpl.getimm.payload[0:len1_2]) if retstr == str1 + str2: if args.verbosity: print('FAM comparision PASS') else: print('FAM comparision FAIL') except XDMcompletionError as e: print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format( e, e.status, e.request_id)) def all_tests(self): for off in range(0, 64, 7): self.test_load_store(offset=off) self.test_PUT_IMM() self.test_GET_IMM() self.test_PUT() self.test_GET() self.test_ATOMIC_SWAP32(data=0x12345678) self.test_ATOMIC_CAS32(data1=0x12345678, data2=0xBDA11ABC) self.test_ATOMIC_ADD32(data=0x137ff731) self.test_ATOMIC_SWAP64(data=0x1234567887654321) self.test_ATOMIC_CAS64(data1=0x1234567887654321, data2=0xBDA11ABCBDA11ABC) self.test_ATOMIC_ADD64(data=0x137ff731137ff731) # Test XDM Command Buffers self.test_PUT_IMM(use_buffer=True) self.test_GET_IMM(use_buffer=True) self.test_PUT(use_buffer=True) self.test_GET(use_buffer=True) self.test_ATOMIC_SWAP32(use_buffer=True, data=0x12345678) self.test_ATOMIC_CAS32(use_buffer=True, data1=0x12345678, data2=0xBDA11ABC) self.test_ATOMIC_ADD32(use_buffer=True, data=0x137ff731) self.test_ATOMIC_SWAP64(use_buffer=True, data=0x1234567887654321) self.test_ATOMIC_CAS64(use_buffer=True, data1=0x1234567887654321, data2=0xBDA11ABCBDA11ABC) self.test_ATOMIC_ADD64(use_buffer=True, data=0x137ff731137ff731)