Skip to content

Commit

Permalink
[VERILOG] Basic Verilog Testflow (apache#70)
Browse files Browse the repository at this point in the history
* [VERILOG] Basic Verilog Testflow

* fix build

* fix the comment

* fix lint in verilog
  • Loading branch information
tqchen authored Mar 14, 2017
1 parent 2548ced commit 9e660db
Show file tree
Hide file tree
Showing 20 changed files with 1,203 additions and 4 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ addons:
- python3-dev
- python3-nose
- graphviz
- bison
- flex

before_install:
- source dmlc-core/scripts/travis/travis_setup_env.sh
- export PYTHONPATH=${PYTHONPATH}:${PWD}/python

install:
- source dmlc-core/scripts/travis/travis_setup_env.sh
- source tests/travis/setup.sh

script:
Expand Down
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ endif
include $(config)

# specify tensor path
.PHONY: clean all test doc pylint cpplint lint
.PHONY: clean all test doc pylint cpplint lint verilog

all: lib/libtvm.so lib/libtvm_runtime.so lib/libtvm.a

Expand Down Expand Up @@ -79,6 +79,9 @@ include tests/cpp/unittest.mk

test: $(TEST)

include verilog/verilog.mk
verilog: $(VER_LIBS)

build/%.o: src/%.cc
@mkdir -p $(@D)
$(CXX) $(CFLAGS) -MM -MT build/$*.o $< >build/$*.d
Expand All @@ -92,6 +95,8 @@ lib/libtvm_runtime.so: $(RUNTIME_DEP)
@mkdir -p $(@D)
$(CXX) $(CFLAGS) $(FRAMEWORKS) -shared -o $@ $(filter %.o %.a, $^) $(LDFLAGS)



lib/libtvm.a: $(ALL_DEP)
@mkdir -p $(@D)
ar crv $@ $(filter %.o, $?)
Expand All @@ -102,7 +107,7 @@ LIBHALIDEIR:
+ cd HalideIR; make lib/libHalideIR.a ; cd $(ROOTDIR)

cpplint:
python2 dmlc-core/scripts/lint.py tvm cpp include src
python2 dmlc-core/scripts/lint.py tvm cpp include src verilog

pylint:
pylint python/tvm --rcfile=$(ROOTDIR)/tests/lint/pylintrc
Expand Down
2 changes: 1 addition & 1 deletion dmlc-core
2 changes: 2 additions & 0 deletions include/tvm/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class Channel : public NodeRef {
* \return the pointer to the internal node container
*/
inline const ChannelNode* operator->() const;
// The container type
using ContainerType = ChannelNode;
};

/*!
Expand Down
233 changes: 233 additions & 0 deletions python/tvm/addon/verilog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
"""Information about nnvm."""
from __future__ import absolute_import

import subprocess
import sys
import os

from .. import _api_internal
from .._base import string_types
from .._ctypes._node import NodeBase, register_node
from . import testing

@register_node
class VPISession(NodeBase):
"""Verilog session"""
def __init__(self, handle):
super(VPISession, self).__init__(handle)
self.proc = None
self.execpath = None

def __del__(self):
self.proc.kill()
super(VPISession, self).__del__()

def arg(self, index):
"""Get handle passed to host session.
Parameters
----------
index : int
The index value.
Returns
-------
handle : VPIHandle
The handle
"""
return _api_internal._vpi_SessGetArg(self, index)

def __getitem__(self, name):
if not isinstance(name, string_types):
raise ValueError("have to be string types")
return _api_internal._vpi_SessGetHandleByName(self, name)

def __getattr__(self, name):
return _api_internal._vpi_SessGetHandleByName(self, name)

def yield_until_posedge(self):
"""Yield until next posedge"""
return _api_internal._vpi_SessYield(self)

def shutdown(self):
"""Shutdown the simulator"""
return _api_internal._vpi_SessShutdown(self)


@register_node
class VPIHandle(NodeBase):
"""Handle to a verilog variable."""
def __init__(self, handle):
super(VPIHandle, self).__init__(handle)
self._name = None
self._size = None

def get_int(self):
"""Get integer value from handle.
Returns
-------
value : int
"""
return _api_internal._vpi_HandleGetInt(self)

def put_int(self, value):
"""Put integer value to handle.
Parameters
----------
value : int
The value to put
"""
return _api_internal._vpi_HandlePutInt(self, value)

@property
def name(self):
if self._name is None:
self._name = _api_internal._vpi_HandleGetName(self)
return self._name

@property
def size(self):
if self._size is None:
self._size = _api_internal._vpi_HandleGetSize(self)
return self._size

def __getitem__(self, name):
if not isinstance(name, string_types):
raise ValueError("have to be string types")
return _api_internal._vpi_HandleGetHandleByName(self, name)

def __getattr__(self, name):
return _api_internal._vpi_HandleGetHandleByName(self, name)


def _find_vpi_path():
curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
api_path = os.path.join(curr_path, '../../../lib/')
vpi_path = [curr_path, api_path]
vpi_path = [os.path.join(p, 'tvm_vpi.vpi') for p in vpi_path]
vpi_found = [p for p in vpi_path if os.path.exists(p) and os.path.isfile(p)]
if vpi_found:
return os.path.dirname(vpi_found[0])
else:
raise ValueError("Cannot find tvm_vpi.vpi, make sure you did `make verilog`")

def search_path():
"""Get the search directory."""
curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
ver_path = [os.path.join(curr_path, '../../../verilog/')]
ver_path += [os.path.join(curr_path, '../../../tests/verilog/')]
return ver_path


def find_file(file_name):
"""Find file in the search directories.
Parameters
----------
file_name : str
The file name
Return
------
file_name : str
The absolute path to the file, raise Error if cannot find it.
"""
ver_path = search_path()
flist = [os.path.join(p, file_name) for p in ver_path]
found = [p for p in flist if os.path.exists(p) and os.path.isfile(p)]
if len(found):
return found[0]
else:
raise ValueError("Cannot find %s in %s" % (file_name, flist))


def compile_file(file_name, file_target, options=None):
"""Compile verilog via iverilog
Parameters
----------
file_name : str or list of str
The cuda code.
file_target : str
The target file.
"""
cmd = ["iverilog"]
for path in search_path():
cmd += ["-I%s" % path]

cmd += ["-o", file_target]
if options:
cmd += options

if isinstance(file_name, string_types):
file_name = [file_name]
cmd += file_name
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(out, _) = proc.communicate()

if proc.returncode != 0:
raise ValueError("Compilation error:\n%s" % out)


def session(file_name):
"""Create a new iverilog session by compile the file.
Parameters
----------
file_name : str or list of str
The name of the file
Returns
-------
sess : VPISession
The created session.
"""
if isinstance(file_name, string_types):
file_name = [file_name]

for name in file_name:
if not os.path.exists(name):
raise ValueError("Cannot find file %s" % name)

path = testing.tempdir()
target = path.relpath(os.path.basename(file_name[0].rsplit(".", 1)[0]))
compile_file(file_name, target)
vpi_path = _find_vpi_path()

cmd = ["vvp"]
cmd += ["-M", vpi_path]
cmd += ["-m", "tvm_vpi"]
cmd += [target]
env = os.environ.copy()

read_device, write_host = os.pipe()
read_host, write_device = os.pipe()

if sys.platform == "win32":
import msvcrt
env['TVM_DREAD_PIPE'] = str(msvcrt.get_osfhandle(read_device))
env['TVM_DWRITE_PIPE'] = str(msvcrt.get_osfhandle(write_device))
read_host = msvcrt.get_osfhandle(read_host)
write_host = msvcrt.get_osfhandle(write_host)
else:
env['TVM_DREAD_PIPE'] = str(read_device)
env['TVM_DWRITE_PIPE'] = str(write_device)

env['TVM_HREAD_PIPE'] = str(read_host)
env['TVM_HWRITE_PIPE'] = str(write_host)

proc = subprocess.Popen(cmd, env=env, close_fds=False)
# close device side pipe
os.close(read_device)
os.close(write_device)

sess = _api_internal._vpi_SessMake(read_host, write_host)
sess.proc = proc
sess.execpath = path
return sess
1 change: 1 addition & 0 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Header files in include are public APIs that share across modules.
There can be internal header files within each module that sit in src.

The current code modules in src.
- common Internal common utilities.
- api API function registration
- lang The definition of DSL related data structure
- arithmetic Arithmetic expression and set simplification
Expand Down
Loading

0 comments on commit 9e660db

Please sign in to comment.