def run(xclbin: SourceType.Path) -> SourceType.String: """Run the xclbin with datafile""" if self.data_path is None: raise errors.MissingDynamicConfiguration("fpga.data") data = sjson.load(open(self.data_path), use_decimal=True) xclbin_source = xclbin.open("rb").read() # create a temporary directory with an xrt.ini file that redirects # the runtime log to a file so that we can control how it's printed. # This is hacky, but it's the only way to do it tmp_dir = TmpDir() os.chdir(tmp_dir.name) xrt_output_logname = "output.log" with open("xrt.ini", "w+") as f: f.writelines( ["[Runtime]\n", f"runtime_log={xrt_output_logname}"]) ctx = self.cl.create_some_context(0) dev = ctx.devices[0] cmds = self.cl.CommandQueue(ctx, dev) prg = self.cl.Program(ctx, [dev], [xclbin_source]) prg.build() buffers = {} for mem in data.keys(): # allocate memory on the device buf = self.cl.Buffer( ctx, self.cl.mem_flags.READ_WRITE | self.cl.mem_flags.COPY_HOST_PTR, hostbuf=np.array(data[mem]["data"]).astype(np.uint32), ) # TODO: use real type information buffers[mem] = buf start_time = time.time() prg.Toplevel(cmds, (1, ), (1, ), np.uint32(10000), *buffers.values()) end_time = time.time() # read the result output = {"memories": {}, "runtime": end_time - start_time} for name, buf in buffers.items(): out_buf = np.zeros_like(data[name]["data"]).astype(np.uint32) self.cl.enqueue_copy(cmds, out_buf, buf) buf.release() output["memories"][name] = list(map(lambda x: int(x), out_buf)) # cleanup del ctx # add xrt log output to our debug output with open(xrt_output_logname, "r") as f: for line in f.readlines(): log.debug(line.strip()) return sjson.dumps(output, indent=2, use_decimal=True)
def download_xclbin( client: SourceType.UnTyped, tmpdir: SourceType.String, ) -> SourceType.Stream: """ Download xclbin file """ local_tmpdir = TmpDir() xclbin_path = Path(local_tmpdir.name) / "kernel.xclbin" with self.SCPClient(client.get_transport()) as scp: scp.get(f"{tmpdir}/xclbin/kernel.xclbin", local_path=str(xclbin_path)) return xclbin_path.open("rb")
def download_wdb( client: SourceType.UnTyped, tmpdir: SourceType.String, ) -> SourceType.Stream: """ Download xclbin file """ local_tmpdir = TmpDir() wdb_path = Path(local_tmpdir.name) / "kernel.wdb" with SCPClient(client.get_transport()) as scp: scp.get( f"{tmpdir}/xilinx_u50_gen3x16_xdma_201920_3-0-kernel.wdb", local_path=str(wdb_path), ) return wdb_path.open("rb")
def create(self, input_files): """Copy input files to a fresh temporary directory. `input_files` is a dict with the same format as `open_and_send`: it maps local Source paths to destination strings. Return a path to the newly-created temporary directory. """ def copy_file(tmpdir, src, dst): src_str = "{src}" if isinstance(src, Source) else str(src) dst_str = "{dst}" if isinstance(dst, Source) else str(dst) tmp_str = "{tmpdir}" if isinstance(tmpdir, Source) else str(tmpdir) @self.builder.step( description=f"copy {src_str} to {tmp_str}/{dst_str}") def copy( tmpdir: SourceType.String, src_path: SourceType.Path, dest_path: SourceType.String, ): shutil.copyfile(src_path, Path(tmpdir) / dest_path) if not isinstance(src, Source): src = Source(src, SourceType.Path) if not isinstance(dst, Source): dst = Source(dst, SourceType.String) return copy(tmpdir, src, dst) # Schedule tmpdir = Source( FreshDir() if self.save_temps else TmpDir(), SourceType.Directory, ) for src_path, dest_path in input_files.items(): copy_file(tmpdir, src_path, dest_path) self.tmpdir = tmpdir return tmpdir
def mktmp() -> SourceType.Directory: """ Make temporary directory to store Verilator build files. """ return TmpDir()
def run(xclbin: SourceType.Path) -> SourceType.String: """Run the xclbin with datafile""" if data_path is None: raise errors.MissingDynamicConfiguration("fpga.data") data = sjson.load(open(data_path), use_decimal=True) xclbin_source = xclbin.open("rb").read() # create a temporary directory with an xrt.ini file that redirects # the runtime log to a file so that we can control how it's printed. # This is hacky, but it's the only way to do it tmp_dir = TmpDir() os.chdir(tmp_dir.name) xrt_output_logname = "output.log" with open("xrt.ini", "w") as f: f.writelines( [ "[Runtime]\n", f"runtime_log={xrt_output_logname}\n", "[Emulation]\n", "print_infos_in_console=false\n", ] ) ctx = self.cl.create_some_context(0) dev = ctx.devices[0] cmds = self.cl.CommandQueue(ctx, dev) prg = self.cl.Program(ctx, [dev], [xclbin_source]) prg.build() # Work around an intermittent PyOpenCL bug. Using prg.Toplevel # internally accesses prg._source, expecting it to be a normal # attribute instead of a kernel name. kern = self.cl.Kernel(prg, "Toplevel") buffers = {} for mem in data.keys(): # allocate memory on the device buf = self.cl.Buffer( ctx, self.cl.mem_flags.READ_WRITE | self.cl.mem_flags.COPY_HOST_PTR, hostbuf=np.array(data[mem]["data"]).astype(np.uint32), ) # TODO: use real type information buffers[mem] = buf start_time = time.time() kern(cmds, (1,), (1,), np.uint32(10000), *buffers.values()) end_time = time.time() log.debug(f"Emulation time: {end_time - start_time} sec") # read the result output = {"memories": {}} for name, buf in buffers.items(): out_buf = np.zeros_like(data[name]["data"]).astype(np.uint32) self.cl.enqueue_copy(cmds, out_buf, buf) buf.release() output["memories"][name] = list(map(lambda x: int(x), out_buf)) # cleanup del ctx # Add xrt log output to our debug output. if os.path.exists(xrt_output_logname): log.debug("XRT log:") with open(xrt_output_logname, "r") as f: for line in f.readlines(): log.debug(line.strip()) # And, in emulation mode, also include the emulation log. emu_log = "emulation_debug.log" if os.path.exists(emu_log): log.debug("Emulation log:") with open(emu_log, "r") as f: for line in f.readlines(): log.debug(line.strip()) return sjson.dumps(output, indent=2, use_decimal=True)
def mktmp() -> SourceType.Directory: """ Make temporary directory to store Vivado synthesis files. """ return TmpDir()