Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VTA][TSIM] Introduce Virtual Memory for TSIM Driver #3686

Merged
merged 29 commits into from
Aug 26, 2019
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f4fa007
initial virtual memory;
liangfu Jul 30, 2019
74a5426
initial integration;
liangfu Jul 30, 2019
2efdc9f
include the header file in cmake;
liangfu Jul 30, 2019
bdc9814
implement allocation with virtual to logical address mapping;
liangfu Jul 30, 2019
78e08db
Merge branch 'master' into virtual_memory
liangfu Aug 1, 2019
296abbb
virtual memory for tsim_driver;
liangfu Aug 1, 2019
4a7674b
implement the missing memory release function;
liangfu Aug 1, 2019
91d93c9
readability improvement;
liangfu Aug 1, 2019
477633c
readability improvement;
liangfu Aug 1, 2019
ed97480
address review comments;
liangfu Aug 2, 2019
832a598
improved robustness in virtual memory allocation;
liangfu Aug 2, 2019
b0a185a
remove VTA_TSIM_USE_VIRTUAL_MEMORY macro and use virtual memory for t…
liangfu Aug 2, 2019
843b27b
Merge branch 'master' into virtual_memory
liangfu Aug 13, 2019
98a9496
link tvm against vta library;
liangfu Aug 14, 2019
7fdf943
Merge branch 'master' into virtual_memory
liangfu Aug 14, 2019
70a8f26
merge with master
liangfu Aug 14, 2019
d8ce8b6
build virtual memory system without linking tvm against vta;
liangfu Aug 14, 2019
0cdaf42
minor change;
liangfu Aug 14, 2019
586fd89
reuse VTA_PAGE_BYTES;
liangfu Aug 14, 2019
9064fb9
using DRAM class from sim_driver as VirtualMemoryManager;
liangfu Aug 14, 2019
9dab853
satisfy linter;
liangfu Aug 14, 2019
3ea1354
add comments in code;
liangfu Aug 14, 2019
7f6fd85
Merge branch 'master' into virtual_memory
liangfu Aug 19, 2019
7a1774a
undo changes to Makefile
liangfu Aug 19, 2019
676a998
undo changes to Makefile
liangfu Aug 19, 2019
17814ce
retrigger ci;
liangfu Aug 19, 2019
4c0f0f9
Merge branch 'virtual_memory' of github.com:liangfu/tvm into virtual_…
liangfu Aug 19, 2019
c223923
retrigger ci;
liangfu Aug 19, 2019
1617787
directly call into VirtualMemoryManager::Global()
liangfu Aug 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/modules/VTA.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ elseif(PYTHON)
endif()
# Add tsim driver sources
if(${VTA_TARGET} STREQUAL "tsim")
file(GLOB __vta_target_srcs vta/src/tsim/*.cc)
file(GLOB __vta_target_srcs vta/src/tsim/*.cc vta/src/tsim/*.h)
file(GLOB RUNTIME_DPI_SRCS vta/src/dpi/module.cc)
list(APPEND RUNTIME_SRCS ${RUNTIME_DPI_SRCS})
endif()
Expand Down
13 changes: 10 additions & 3 deletions vta/hardware/chisel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ TOP_TEST = Test
BUILD_NAME = build
USE_TRACE = 0
VTA_LIBNAME = libvta_hw
DEBUG = 0

config_test = $(TOP_TEST)$(CONFIG)
vta_dir = $(abspath ../../)
Expand All @@ -56,7 +57,11 @@ verilator_opt += --top-module ${TOP_TEST}
verilator_opt += -Mdir ${verilator_build_dir}
verilator_opt += -I$(chisel_build_dir)

cxx_flags = -O2 -Wall -fPIC -shared
ifeq ($(DEBUG), 1)
cxx_flags = -O0 -g -Wall -fPIC -shared
else
cxx_flags = -O2 -Wall -fPIC -shared
endif
cxx_flags += -fvisibility=hidden -std=c++11
cxx_flags += -DVL_TSIM_NAME=V$(TOP_TEST)
cxx_flags += -DVL_PRINTF=printf
Expand Down Expand Up @@ -112,7 +117,9 @@ $(chisel_build_dir)/$(TOP_TEST).$(CONFIG).v:
sbt 'runMain vta.$(config_test) --target-dir $(chisel_build_dir) --top-name $(TOP_TEST).$(CONFIG)'

clean:
-rm -rf target project/target project/project
rm -rf target project/target project/project

cleanall:
-rm -rf $(vta_dir)/$(BUILD_NAME)
rm -rf $(vta_dir)/$(BUILD_NAME)/verilator
rm -rf $(vta_dir)/$(BUILD_NAME)/libvta_hw.so
rm -rf $(vta_dir)/$(BUILD_NAME)/chisel
4 changes: 4 additions & 0 deletions vta/include/vta/dpi/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include <condition_variable>
#include <string>

#ifndef VTA_TSIM_USE_VIRTUAL_MEMORY
#define VTA_TSIM_USE_VIRTUAL_MEMORY (1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we going to leave this parameter turned on by default? what are the pros/cons to leaving this macro to be user-defined (with the idea that we're trying to minimize ifdefs in our code)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advantage

Disadvantage

  • Current virtual memory system uses virtual memory page file system to write and read address mappings, these may not be compatible to Windows.

Otherwise, I think it's safe to enable virtual memory for tsim_driver by default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clear explanation. I'd opt towards leaving it on by default, at the detriment to Windows users, but others can chime in @tqchen @vegaluisjose

#endif // VTA_TSIM_USE_VIRTUAL_MEMORY

namespace vta {
namespace dpi {

Expand Down
38 changes: 38 additions & 0 deletions vta/src/dpi/module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
#include <queue>
#include <thread>
#include <condition_variable>
#include <fstream>

#if VTA_TSIM_USE_VIRTUAL_MEMORY
#include "../tsim/virtual_memory.h"
#endif

namespace vta {
namespace dpi {
Expand Down Expand Up @@ -179,12 +184,45 @@ void HostDevice::WaitPopResponse(HostResponse* r) {

void MemDevice::SetRequest(uint8_t opcode, uint64_t addr, uint32_t len) {
std::lock_guard<std::mutex> lock(mutex_);
#if VTA_TSIM_USE_VIRTUAL_MEMORY
// get logical address
uint64_t laddr = 0;
{
std::ifstream in(VTA_VMEM_PAGEFILE, std::ifstream::ate | std::ifstream::binary);
size_t size = in.tellg();
FILE * fin = fopen(VTA_VMEM_PAGEFILE, "rb");
CHECK(fin);
if (fin) {
uint64_t * tlb = new uint64_t[size / sizeof(uint64_t)];
fread(tlb, size, 1, fin);
uint32_t cnt = size / (sizeof(uint64_t) * 3);
for (uint32_t i = 0; i < cnt; i++) {
if ((addr >= tlb[i * 3]) && (addr < tlb[i * 3 + 1])) {
uint32_t offset = addr - tlb[i * 3];
laddr = tlb[i * 3 + 2] + offset;
break;
}
}
delete [] tlb;
fclose(fin);
CHECK_NE(laddr, 0);
}
}
#endif
if (opcode == 1) {
wlen_ = len + 1;
#if VTA_TSIM_USE_VIRTUAL_MEMORY
waddr_ = reinterpret_cast<uint64_t*>(laddr);
#else
waddr_ = reinterpret_cast<uint64_t*>(addr);
#endif
} else {
rlen_ = len + 1;
#if VTA_TSIM_USE_VIRTUAL_MEMORY
raddr_ = reinterpret_cast<uint64_t*>(laddr);
#else
raddr_ = reinterpret_cast<uint64_t*>(addr);
#endif
}
}

Expand Down
20 changes: 20 additions & 0 deletions vta/src/tsim/tsim_driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include <vta/driver.h>
#include <vta/dpi/module.h>

#if VTA_TSIM_USE_VIRTUAL_MEMORY
#include "virtual_memory.h"
#endif

namespace vta {
namespace tsim {

Expand Down Expand Up @@ -208,24 +212,40 @@ TVM_REGISTER_GLOBAL("vta.tsim.profiler_status")
} // namespace vta

void* VTAMemAlloc(size_t size, int cached) {
#if VTA_TSIM_USE_VIRTUAL_MEMORY
void *p = vmalloc(size);
#else
void *p = malloc(size);
#endif
return p;
}

void VTAMemFree(void* buf) {
#if VTA_TSIM_USE_VIRTUAL_MEMORY
vfree(buf);
#else
free(buf);
#endif
}

vta_phy_addr_t VTAMemGetPhyAddr(void* buf) {
return reinterpret_cast<uint64_t>(reinterpret_cast<uint64_t*>(buf));
}

void VTAMemCopyFromHost(void* dst, const void* src, size_t size) {
#if VTA_TSIM_USE_VIRTUAL_MEMORY
vmemcpy(dst, src, size, kVirtualMemCopyFromHost);
#else
memcpy(dst, src, size);
#endif
}

void VTAMemCopyToHost(void* dst, const void* src, size_t size) {
#if VTA_TSIM_USE_VIRTUAL_MEMORY
vmemcpy(dst, src, size, kVirtualMemCopyToHost);
#else
memcpy(dst, src, size);
#endif
}

void VTAFlushCache(void* vir_addr, vta_phy_addr_t phy_addr, int size) {
Expand Down
186 changes: 186 additions & 0 deletions vta/src/tsim/virtual_memory.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "virtual_memory.h"

#include <dmlc/logging.h>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <list>
#include <utility>
#include <iterator>
#include <unordered_map>

/*! page size of virtual address */
#ifndef VTA_TSIM_VM_PAGE_SIZE
#define VTA_TSIM_VM_PAGE_SIZE (4096)
#endif // VTA_TSIM_VM_PAGE_SIZE

/*! starting point of the virtual address system */
#ifndef VTA_TSIM_VM_ADDR_BEGIN
#define VTA_TSIM_VM_ADDR_BEGIN (0x40000000)
#endif // VTA_TSIM_VM_ADDR_BEGIN

namespace vta {
namespace tsim {
liangfu marked this conversation as resolved.
Show resolved Hide resolved

static const uint64_t kPageSize = VTA_TSIM_VM_PAGE_SIZE;
static const uint64_t kVirtualMemoryOffset = VTA_TSIM_VM_ADDR_BEGIN;

class VirtualMemoryManager {
public:
/*! \brief allocate virtual memory for given size */
void * Allocate(uint64_t sz) {
uint64_t size = ((sz + kPageSize - 1) / kPageSize) * kPageSize;
void * ptr = malloc(size);
size_t laddr = reinterpret_cast<size_t>(ptr);
// search for available virtual memory space
uint64_t vaddr = kVirtualMemoryOffset;
auto it = page_table_.end();
if (page_table_.size() > 0) {
for (it = page_table_.begin(); it != page_table_.end(); it++) {
if (it == page_table_.begin()) { continue; }
if (((*it).first - (*std::prev(it)).second) > size) {
vaddr = (*it).second;
break;
}
}
if (it == page_table_.end()) {
vaddr = (*std::prev(it)).second;
}
}
page_table_.insert(it, std::make_pair(vaddr, vaddr + size));
tlb_[vaddr] = laddr;
// save tlb to file in order to be accessed externally.
FILE * fout = fopen(VTA_VMEM_PAGEFILE, "wb");
CHECK(fout);
if (fout) {
uint32_t tlb_size = sizeof(uint64_t)*3*tlb_.size();
uint32_t tlb_cnt = 0;
uint64_t * tlb = new uint64_t[3*tlb_.size()];
for (auto iter = tlb_.begin(); iter != tlb_.end(); iter++, tlb_cnt++) {
tlb[tlb_cnt * 3] = (*iter).first;
uint64_t vend = 0;
for (auto iter_in = page_table_.begin(); iter_in != page_table_.end(); iter_in++) {
if ((*iter_in).first == (*iter).first) { vend = (*iter_in).second; break; }
}
tlb[tlb_cnt * 3 + 1] = vend;
tlb[tlb_cnt * 3 + 2] = (*iter).second;
}
fwrite(tlb, tlb_size, 1, fout);
fflush(fout);
fclose(fout);
}
// return virtual address
return reinterpret_cast<void*>(vaddr);
}

/*! \brief release virtual memory for pointer */
void Release(void * ptr) {
uint64_t src = reinterpret_cast<uint64_t>(ptr);
auto it = page_table_.begin();
for (; it != page_table_.end(); it++) {
if (((*it).first <= src) && ((*it).second > src)) { break; }
}
CHECK(it != page_table_.end());
uint64_t * laddr = reinterpret_cast<uint64_t*>(tlb_[(*it).first]);
delete [] laddr;
page_table_.erase(it);
tlb_.erase((*it).first);
}

/*! \brief copy virtual memory from host */
void MemCopyFromHost(void * dstptr, const void * src, uint64_t size) {
// get logical address from virtual address
size_t dst = reinterpret_cast<size_t>(dstptr);
auto it = page_table_.begin();
for (; it != page_table_.end(); it++) {
if (((*it).first <= dst) && ((*it).second > dst)) { break; }
}
CHECK(it != page_table_.end());
size_t offset = dst - (*it).first;
char * laddr = reinterpret_cast<char*>(tlb_[(*it).first]);
// copy content from src to logic address
memcpy(laddr + offset, src, size);
}

/*! \brief copy virtual memory to host */
void MemCopyToHost(void * dst, const void * srcptr, uint64_t size) {
// get logical address from virtual address
size_t src = reinterpret_cast<size_t>(srcptr);
auto it = page_table_.begin();
for (; it != page_table_.end(); it++) {
if (((*it).first <= src) && ((*it).second > src)) { break; }
}
CHECK(it != page_table_.end());
size_t offset = src - (*it).first;
char * laddr = reinterpret_cast<char*>(tlb_[(*it).first]);
// copy content from logic address to dst
memcpy(dst, laddr + offset, size);
}

/*! \brief get logical address from virtual memory */
void * GetLogicalAddr(uint64_t src) {
if (src == 0) { return 0; }
auto it = page_table_.begin();
for (; it != page_table_.end(); it++) {
if (((*it).first <= src) && ((*it).second > src)) { break; }
}
CHECK(it != page_table_.end());
return reinterpret_cast<void*>(tlb_[(*it).first]);
}

/*! \brief get global handler of the instance */
static VirtualMemoryManager* Global() {
static VirtualMemoryManager inst;
return &inst;
}

private:
/*! \brief page table */
std::list<std::pair<uint64_t, uint64_t> > page_table_;
/*! \brief translation lookaside buffer */
std::unordered_map<uint64_t, size_t> tlb_;
};

} // namespace tsim
} // namespace vta


void * vmalloc(uint64_t size) {
return vta::tsim::VirtualMemoryManager::Global()->Allocate(size);
}

void vfree(void * ptr) {
vta::tsim::VirtualMemoryManager::Global()->Release(ptr);
}

void vmemcpy(void * dst, const void * src, uint64_t size, VMemCopyType dir) {
auto * mgr = vta::tsim::VirtualMemoryManager::Global();
if (kVirtualMemCopyFromHost == dir) {
mgr->MemCopyFromHost(dst, src, size);
} else {
mgr->MemCopyToHost(dst, src, size);
}
}

void * vmem_get_log_addr(uint64_t vaddr) {
return vta::tsim::VirtualMemoryManager::Global()->GetLogicalAddr(vaddr);
}
Loading