From 9242d82228d40a46350e7cf2163467f5b2dd1f87 Mon Sep 17 00:00:00 2001 From: tqchen Date: Mon, 23 Dec 2019 10:35:55 -0800 Subject: [PATCH] [DEPRECATION] Cleanup legacy verilog support This PR cleans up the left over code for legacy verilog support which was experimental. The new hardware backend path is now support by VTA via TSIM. --- CMakeLists.txt | 5 - docker/install/ubuntu_install_iverilog.sh | 30 -- include/tvm/channel.h | 73 ---- include/tvm/ir_pass.h | 15 - python/tvm/contrib/verilog.py | 316 ----------------- src/api/api_pass.cc | 2 - src/lang/channel.cc | 41 --- src/pass/narrow_channel_access.cc | 244 ------------- src/pass/split_host_device.cc | 8 - src/pass/split_pipeline.cc | 322 ------------------ src/runtime/module.cc | 2 - .../unittest/test_pass_split_pipeline.py | 81 ----- tests/scripts/packages.mk | 27 -- tests/scripts/task_verilog_test.sh | 25 -- tests/travis/run_test.sh | 60 ---- tests/travis/setup.sh | 31 -- tests/travis/travis_after_failure.sh | 17 - 17 files changed, 1299 deletions(-) delete mode 100755 docker/install/ubuntu_install_iverilog.sh delete mode 100644 include/tvm/channel.h delete mode 100644 python/tvm/contrib/verilog.py delete mode 100644 src/lang/channel.cc delete mode 100644 src/pass/narrow_channel_access.cc delete mode 100644 src/pass/split_pipeline.cc delete mode 100644 tests/python/unittest/test_pass_split_pipeline.py delete mode 100644 tests/scripts/packages.mk delete mode 100755 tests/scripts/task_verilog_test.sh delete mode 100644 tests/travis/run_test.sh delete mode 100644 tests/travis/setup.sh delete mode 100644 tests/travis/travis_after_failure.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 292bd6780c52..34607bdc3413 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,11 +169,6 @@ endif(USE_VM_PROFILER) file(GLOB DATATYPE_SRCS src/codegen/datatype/*.cc) list(APPEND COMPILER_SRCS ${DATATYPE_SRCS}) -if(NOT MSVC) - file(GLOB COMPILER_VERILOG_SRCS src/codegen/verilog/*.cc) - list(APPEND COMPILER_SRCS ${COMPILER_VERILOG_SRCS}) -endif() - file(GLOB_RECURSE NNVM_COMPILER_SRCS nnvm/src/c_api/*.cc nnvm/src/core/*.cc diff --git a/docker/install/ubuntu_install_iverilog.sh b/docker/install/ubuntu_install_iverilog.sh deleted file mode 100755 index da20730d491e..000000000000 --- a/docker/install/ubuntu_install_iverilog.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# 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. - -set -e -set -u -set -o pipefail - -apt-get install -y --no-install-recommends make bison flex -wget -q ftp://icarus.com/pub/eda/verilog/v10/verilog-10.1.tar.gz -tar xf verilog-10.1.tar.gz -cd verilog-10.1 -./configure --prefix=/usr -make install -j8 -cd .. -rm -rf verilog-10.1 verilog-10.1.tar.gz diff --git a/include/tvm/channel.h b/include/tvm/channel.h deleted file mode 100644 index 25ee7a9e531c..000000000000 --- a/include/tvm/channel.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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. - */ - -/*! - * \file tvm/channel.h - * \brief Channel object for pipeline. - */ -#ifndef TVM_CHANNEL_H_ -#define TVM_CHANNEL_H_ - -#include - -namespace tvm { -// Node container of channel -struct ChannelNode; - -/*! \brief The data channel. */ -class Channel : public NodeRef { - public: - /*! \brief default constructor */ - Channel() {} - explicit Channel(ObjectPtr n) : NodeRef(n) {} - /*! - * \brief access the internal node container - * \return the pointer to the internal node container - */ - inline const ChannelNode* operator->() const; - // The container type - using ContainerType = ChannelNode; -}; - -/*! - * \brief Generalized FIFO channel. - */ -struct ChannelNode : public Node { - /*! \brief Variable to channel handle */ - Var handle_var; - /*! \brief default data type in read/write */ - DataType dtype; - // visit all attributes - void VisitAttrs(AttrVisitor* v) { - v->Visit("handle_var", &handle_var); - v->Visit("dtype", &dtype); - } - - static Channel make(Var handle_var, DataType dtype); - static constexpr const char* _type_key = "Channel"; - - TVM_DECLARE_NODE_TYPE_INFO(ChannelNode, Node); -}; - -// Inline implementations -inline const ChannelNode* Channel::operator->() const { - return static_cast(get()); -} -} // namespace tvm -#endif // TVM_CHANNEL_H_ diff --git a/include/tvm/ir_pass.h b/include/tvm/ir_pass.h index 5c5c4bb2f452..b0b13df729cc 100644 --- a/include/tvm/ir_pass.h +++ b/include/tvm/ir_pass.h @@ -236,21 +236,6 @@ bool VerifyCompactBuffer(Stmt stmt); */ Stmt RemoveNoOp(Stmt stmt); -/*! - * \brief Split statement into pipeine stages. - * \param stmt The stmt to be splitted - * \param split_load Whether split load into its own stage. - * \return Transformed stmt. - */ -Stmt SplitPipeline(Stmt stmt, bool split_load); - -/*! - * \brief Narrow channel access to smaller range. - * \param stmt The stmt to do access rewriting. - * \return Transformed stmt. - */ -Stmt NarrowChannelAccess(Stmt stmt); - /*! * \brief unroll the constant loop marked by unroll. * This pass also automatically attach pragma unroll tag to loops which meets the standard. diff --git a/python/tvm/contrib/verilog.py b/python/tvm/contrib/verilog.py deleted file mode 100644 index 30fa6ce2c7dd..000000000000 --- a/python/tvm/contrib/verilog.py +++ /dev/null @@ -1,316 +0,0 @@ -# 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. -"""Verilog simulator modules.""" -from __future__ import absolute_import - -import subprocess -import sys -import os -import ctypes - -from .. import _api_internal -from .._ffi.base import string_types -from .._ffi.node import NodeBase, register_node -from .._ffi.function import register_func -from . import util - -@register_node -class VPISession(NodeBase): - """Verilog session""" - def __init__(self, handle): - super(VPISession, self).__init__(handle) - self.proc = None - self.execpath = None - self.yield_callbacks = [] - - def __del__(self): - self.proc.kill() - try: - super(VPISession, self).__del__() - except AttributeError: - pass - - 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_next_cycle(self): - """Yield until next posedge""" - for f in self.yield_callbacks: - f() - 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.realpath(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]) - 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.realpath(os.path.expanduser(__file__))) - ver_path = [os.path.join(curr_path, '../../../verilog/')] - ver_path += [os.path.join(curr_path, '../../../tests/verilog/unittest/')] - ver_path += [os.path.join(curr_path, '../../../tests/verilog/integration/')] - 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 not found: - raise ValueError("Cannot find %s in %s" % (file_name, flist)) - return found[0] - - -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_names, codes=None): - """Create a new iverilog session by compile the file. - - Parameters - ---------- - file_names : str or list of str - The name of the file - - codes : str or list of str - The code in str. - - Returns - ------- - sess : VPISession - The created session. - """ - if isinstance(file_names, string_types): - file_names = [file_names] - path = util.tempdir() - - if codes: - if isinstance(codes, (list, tuple)): - codes = '\n'.join(codes) - fcode = path.relpath("temp_code.v") - with open(fcode, "w") as out_file: - out_file.write(codes) - file_names.append(fcode) - - for name in file_names: - if not os.path.exists(name): - raise ValueError("Cannot find file %s" % name) - - target = path.relpath(os.path.basename(file_names[0].rsplit(".", 1)[0])) - compile_file(file_names, 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) - - try: - # close_fds does not work well for all python3 - # Use pass_fds instead. - # pylint: disable=unexpected-keyword-arg - pass_fds = (read_device, write_device, read_host, write_host) - proc = subprocess.Popen(cmd, pass_fds=pass_fds, env=env) - except TypeError: - # This is effective for python2 - proc = subprocess.Popen(cmd, close_fds=False, env=env) - - # 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 - - -@register_func -def tvm_callback_verilog_simulator(code, *args): - """Callback by TVM runtime to invoke verilog simulator - - Parameters - ---------- - code : str - The verilog code to be simulated - - args : list - Additional arguments to be set. - """ - libs = [ - find_file("tvm_vpi_mmap.v") - ] - sess = session(libs, code) - for i, value in enumerate(args): - vpi_h = sess.main["tvm_arg%d" % i] - if isinstance(value, ctypes.c_void_p): - int_value = int(value.value) - elif isinstance(value, int): - int_value = value - else: - raise ValueError( - "Do not know how to handle value type %s" % type(value)) - vpi_h.put_int(int_value) - - rst = sess.main.rst - done = sess.main.done - # start driving - rst.put_int(1) - sess.yield_until_next_cycle() - rst.put_int(0) - sess.yield_until_next_cycle() - while not done.get_int(): - sess.yield_until_next_cycle() - sess.yield_until_next_cycle() - sess.shutdown() diff --git a/src/api/api_pass.cc b/src/api/api_pass.cc index 4210788d52b5..c62cc8ad16a0 100644 --- a/src/api/api_pass.cc +++ b/src/api/api_pass.cc @@ -159,9 +159,7 @@ REGISTER_PASS(InjectPrefetch); REGISTER_PASS(InjectDoubleBuffer); REGISTER_PASS(LoopPartition); REGISTER_PASS(RemoveNoOp); -REGISTER_PASS(SplitPipeline); REGISTER_PASS(LiftAttrScope); -REGISTER_PASS(NarrowChannelAccess); REGISTER_PASS(LowerThreadAllreduce); REGISTER_PASS(LowerWarpMemory); REGISTER_PASS(RemapThreadAxis); diff --git a/src/lang/channel.cc b/src/lang/channel.cc deleted file mode 100644 index 555562aef065..000000000000 --- a/src/lang/channel.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -/*! - * \file channel.cc - */ -#include - -namespace tvm { - -Channel ChannelNode::make(Var handle_var, DataType dtype) { - auto n = make_node(); - n->handle_var = handle_var; - n->dtype = dtype; - return Channel(n); -} - -TVM_STATIC_IR_FUNCTOR(IRPrinter, vtable) -.set_dispatch([](const ObjectRef& node, IRPrinter *p) { - auto* op = static_cast(node.get()); - p->stream << "channel(" << op->handle_var << ", " << op->dtype << ")"; -}); - -TVM_REGISTER_NODE_TYPE(ChannelNode); -} // namespace tvm diff --git a/src/pass/narrow_channel_access.cc b/src/pass/narrow_channel_access.cc deleted file mode 100644 index 6687512ec739..000000000000 --- a/src/pass/narrow_channel_access.cc +++ /dev/null @@ -1,244 +0,0 @@ -/* - * 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. - */ - -/*! - * \file narrow_channel_access.cc - * \brief Narrow channel access to a smaller range - * when possible by bringing it to the internal loop. - */ -#include -#include -#include -#include -#include -#include -#include -#include "ir_util.h" - -namespace tvm { -namespace ir { -using namespace arith; - -// Bound deducer for channel access. -class ChannelAccessBound : public IRVisitor { - public: - ChannelAccessBound(const Variable* buf_var, bool read_access) - : buf_var_(buf_var), read_access_(read_access) {} - - void Visit_(const Store* op) final { - if (!read_access_ && buf_var_ == op->buffer_var.get()) { - ret_.emplace_back(EvalSet(op->index, dom_map_)); - } - IRVisitor::Visit_(op); - } - void Visit_(const For* op) final { - CHECK(is_zero(op->min)); - // We know that the extent of the loop won't depend on relaxed scope. - // TODO(tqchen) have a verification pass. - dom_map_[op->loop_var.get()] = IntSet::interval(op->min, op->extent - 1); - IRVisitor::Visit_(op); - } - void Visit_(const Load* op) final { - if (read_access_ && buf_var_ == op->buffer_var.get()) { - ret_.emplace_back(EvalSet(op->index, dom_map_)); - } - IRVisitor::Visit_(op); - } - void Visit_(const Let* op) final { - LOG(FATAL) << "cannot pass through let"; - } - void Visit_(const LetStmt* op) final { - LOG(FATAL) << "cannot pass through let"; - } - IntSet Eval(const Stmt& stmt) { - Visit(stmt); - return Union(ret_); - } - - private: - // The buffer variable. - const Variable* buf_var_; - // read or write - bool read_access_{true}; - // Box - std::vector ret_; - // Domain map. - std::unordered_map dom_map_; -}; - -class ChannelAccessIndexRewriter : public IRMutator { - public: - ChannelAccessIndexRewriter(const Variable* buf_var, - Expr min, - bool read_access) - : buf_var_(buf_var), min_(min), read_access_(read_access) {} - Expr Mutate_(const Load* op, const Expr& e) final { - Expr expr = IRMutator::Mutate_(op, e); - op = expr.as(); - if (read_access_ && buf_var_ == op->buffer_var.get()) { - return Load::make( - op->dtype, op->buffer_var, ir::Simplify(op->index - min_), - op->predicate); - } else { - return expr; - } - } - Stmt Mutate_(const Store* op, const Stmt& s) final { - Stmt stmt = IRMutator::Mutate_(op, s); - op = stmt.as(); - if (!read_access_ && buf_var_ == op->buffer_var.get()) { - return Store::make( - op->buffer_var, op->value, ir::Simplify(op->index - min_), - op->predicate); - } else { - return stmt; - } - } - - private: - // The buffer variable. - const Variable* buf_var_; - // The min bound. - Expr min_; - // read or write - bool read_access_{true}; -}; - - -// Rewrite channel access pattern. -class ChannelAccessRewriter : public IRMutator { - public: - Stmt Mutate_(const AttrStmt* op, const Stmt& s) final { - Stmt ret; - const AttrStmt* adv = op->body.as(); - if ((op->attr_key == ir::attr::channel_read_scope && - adv && adv->attr_key == ir::attr::channel_read_advance) || - (op->attr_key == ir::attr::channel_write_scope && - adv && adv->attr_key == ir::attr::channel_write_advance)) { - RewriteEntry e; - e.window = op; - e.advance = adv; - e.read_access = op->attr_key == ir::attr::channel_read_scope; - tasks_.push_back(e); - ret = IRMutator::Mutate_(op, s); - if (tasks_.back().rewrite_success) { - ret = ret.as()->body.as()->body; - } - tasks_.pop_back(); - return ret; - } else { - return IRMutator::Mutate_(op, s); - } - } - - Stmt Mutate_(const For* op, const Stmt& s) final { - std::vector tasks; - std::swap(tasks_, tasks); - Stmt body = op->body; - std::vector nest; - for (RewriteEntry& e : tasks) { - body = RewriteAccess(op, body, &e, &nest); - } - - if (!body.same_as(op->body)) { - body = Mutate(body); - body = For::make( - op->loop_var, op->min, op->extent, - op->for_type, op->device_api, body); - body = MergeNest(nest, body); - } else { - CHECK_EQ(nest.size(), 0U); - body = IRMutator::Mutate_(op, s); - } - std::swap(tasks_, tasks); - return body; - } - - private: - struct RewriteEntry { - bool read_access; - const AttrStmt* window; - const AttrStmt* advance; - bool rewrite_success{false}; - }; - - Stmt RewriteAccess(const For* for_op, - Stmt body, - RewriteEntry* e, - std::vector* outer_nest) { - const AttrStmt* adv_op = e->advance; - const Expr& window = e->window->value; - bool read_access = e->read_access; - Var var(for_op->loop_var); - Channel ch = Downcast(adv_op->node); - ChannelAccessBound acc(ch->handle_var.get(), read_access); - IntSet iset = acc.Eval(for_op->body); - Range r = iset.cover_range(Range::make_by_min_extent(0, window)); - r = Range::make_by_min_extent( - ir::Simplify(r->min), ir::Simplify(r->extent)); - if (ExprUseVar(r->extent, var)) return body; - Array linear_eq = DetectLinearEquation(r->min, {var}); - if (linear_eq.size() == 0) return body; - Expr coeff = linear_eq[0]; - Expr base = linear_eq[1]; - if (!is_zero(base)) return body; - Expr left = ir::Simplify(adv_op->value - coeff * for_op->extent); - if (!analyzer_.CanProve(left >= 0)) return body; - // rewrite access index. - ChannelAccessIndexRewriter rw( - ch->handle_var.get(), var * coeff, read_access); - body = rw.Mutate(body); - - if (read_access) { - body = AttrStmt::make( - ch, ir::attr::channel_read_scope, r->extent, - AttrStmt::make(ch, ir::attr::channel_read_advance, coeff, - body)); - } else { - body = AttrStmt::make( - ch, ir::attr::channel_write_scope, r->extent, - AttrStmt::make(ch, ir::attr::channel_write_advance, coeff, - body)); - } - - if (!is_zero(left)) { - Stmt no_op = Evaluate::make(0); - if (read_access) { - outer_nest->emplace_back( - AttrStmt::make(ch, ir::attr::channel_read_advance, left, no_op)); - } else { - outer_nest->emplace_back( - AttrStmt::make(ch, ir::attr::channel_write_advance, left, no_op)); - } - } - - e->rewrite_success = true; - return body; - } - - arith::Analyzer analyzer_; - std::vector tasks_; -}; - -Stmt NarrowChannelAccess(Stmt stmt) { - return ChannelAccessRewriter().Mutate(stmt); -} - -} // namespace ir -} // namespace tvm diff --git a/src/pass/split_host_device.cc b/src/pass/split_host_device.cc index 4cbc258efe56..5076300d968a 100644 --- a/src/pass/split_host_device.cc +++ b/src/pass/split_host_device.cc @@ -23,7 +23,6 @@ */ #include #include -#include #include #include #include @@ -54,13 +53,6 @@ class IRUseDefAnalysis : public IRMutator { Stmt body = this->Mutate(op->body); if (value.same_as(op->value) && body.same_as(op->body)) return s; return AttrStmt::make(op->node, op->attr_key, value, body); - } else if (op->attr_key == attr::channel_write_scope || - op->attr_key == attr::channel_read_scope) { - Channel ch = Downcast(op->node); - if (!use_count_.count(ch->handle_var.get())) { - this->HandleDef(ch->handle_var.get()); - } - return IRMutator::Mutate_(op, s); } else { return IRMutator::Mutate_(op, s); } diff --git a/src/pass/split_pipeline.cc b/src/pass/split_pipeline.cc deleted file mode 100644 index 549b4c69e63b..000000000000 --- a/src/pass/split_pipeline.cc +++ /dev/null @@ -1,322 +0,0 @@ -/* - * 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. - */ - -/*! - * \file split_pipeline.cc - * \brief Split statement into pipeline stage modules. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "ir_util.h" - -namespace tvm { -namespace ir { - -class MarkChannelAccess : public IRMutator { - public: - MarkChannelAccess( - const std::unordered_map& cmap, - const std::unordered_map& fifo_map) - : cmap_(cmap), fifo_map_(fifo_map) {} - using IRMutator::Mutate; - Stmt Mutate(Stmt stmt) final { - Stmt ret = IRMutator::Mutate(stmt); - if (read_fifos_.size() != 0) { - for (const Variable* v : read_fifos_) { - Channel ch = fifo_map_.at(v); - ret = ReadChannel(ch, 1, ret); - } - read_fifos_.clear(); - } - if (write_fifos_.size() != 0) { - for (const Variable* v : write_fifos_) { - Channel ch = fifo_map_.at(v); - ret = WriteChannel(ch, 1, ret); - } - write_fifos_.clear(); - } - return ret; - } - - Expr Mutate_(const Load *op, const Expr& e) final { - auto it = rmap_.find(op->buffer_var.get()); - if (it != rmap_.end()) { - ++it->second.read_count; - } - if (fifo_map_.count(op->buffer_var.get())) { - read_fifos_.insert(op->buffer_var.get()); - CHECK(!write_fifos_.count(op->buffer_var.get())); - } - return IRMutator::Mutate_(op, e); - } - Stmt Mutate_(const Store *op, const Stmt& s) final { - auto it = rmap_.find(op->buffer_var.get()); - if (it != rmap_.end()) { - ++it->second.write_count; - } - if (fifo_map_.count(op->buffer_var.get())) { - write_fifos_.insert(op->buffer_var.get()); - CHECK(!read_fifos_.count(op->buffer_var.get())); - } - return IRMutator::Mutate_(op, s); - } - Stmt Mutate_(const Allocate* op, const Stmt& s) final { - if (cmap_.count(op->buffer_var.get())) { - CHECK(!rmap_.count(op->buffer_var.get())); - rmap_[op->buffer_var.get()] = Entry(); - Stmt body = Mutate(op->body); - body = CreateChannelAccess(op, body); - rmap_.erase(op->buffer_var.get()); - return body; - } else { - return IRMutator::Mutate_(op, s); - } - } - Stmt Mutate_(const AttrStmt* op, const Stmt& s) final { - if (op->attr_key == ir::attr::storage_scope) { - Var buf_var = Downcast(op->node); - if (cmap_.count(buf_var.get())) return Mutate(op->body); - } - return IRMutator::Mutate_(op, s); - } - - private: - // Create channel access wrap - Stmt CreateChannelAccess(const Allocate* op, Stmt body) { - const Entry& rw = rmap_.at(op->buffer_var.get()); - CHECK(rw.write_count == 0 || rw.read_count == 0) - << "Cannot read/write to the same channel " << op->buffer_var - << " body:" << body; - if (rw.write_count == 0 && rw.read_count == 0) { - return body; - } - const Channel& ch = cmap_.at(op->buffer_var.get()); - int32_t csize = op->constant_allocation_size(); - Expr alloc_size; - if (csize > 0) { - alloc_size = IntImm::make(DataType::Int(32), csize); - } else { - alloc_size = op->extents[0]; - for (size_t i = 1; i < op->extents.size(); ++i) { - alloc_size = alloc_size * op->extents[i]; - } - } - - if (rw.write_count) { - return WriteChannel(ch, alloc_size, body); - } else { - CHECK(rw.read_count); - return ReadChannel(ch, alloc_size, body); - } - } - Stmt ReadChannel(Channel ch, Expr size, Stmt body) { - return AttrStmt::make( - ch, ir::attr::channel_read_scope, size, - AttrStmt::make(ch, ir::attr::channel_read_advance, size, - body)); - } - Stmt WriteChannel(Channel ch, Expr size, Stmt body) { - return AttrStmt::make( - ch, ir::attr::channel_write_scope, size, - AttrStmt::make(ch, ir::attr::channel_write_advance, size, - body)); - } - struct Entry { - int read_count{0}; - int write_count{0}; - }; - // The channels of each allocation. - const std::unordered_map& cmap_; - // FIFO map. - const std::unordered_map& fifo_map_; - // the result. - std::unordered_map rmap_; - // Accessed FIFOs - std::unordered_set read_fifos_, write_fifos_; -}; - -// Mark the statment of each stage. -class StageSplitter : public IRMutator { - public: - using IRMutator::Mutate; - explicit StageSplitter(bool split_load) - : split_load_(split_load) {} - - Stmt Mutate(Stmt stmt) final { - nest_.push_back(stmt); - Stmt ret = IRMutator::Mutate(stmt); - nest_.pop_back(); - return ret; - } - Stmt Mutate_(const ProducerConsumer* op, const Stmt& s) final { - if (!op->is_producer) { - return Mutate(op->body); - } - Stmt body = Mutate(op->body); - stages_.emplace_back(BuildStage(body, op->func)); - return Evaluate::make(0); - } - Expr Mutate_(const Load* op, const Expr& e) final { - if (!split_load_) return IRMutator::Mutate_(op, e); - std::ostringstream cname; - cname << "fifo." << temp_fifo_count_++; - // Create FIFO channel for load. - Channel ch = ChannelNode::make(Var(cname.str(), DataType::Handle()), op->dtype); - Expr index = Mutate(op->index); - Stmt provide = Store::make( - ch->handle_var, - Load::make(op->dtype, op->buffer_var, index, op->predicate), - 0, op->predicate); - Stmt temp = nest_.back(); nest_.pop_back(); - stages_.emplace_back(BuildStage(provide, ch)); - nest_.push_back(temp); - fifo_map_[ch->handle_var.get()] = ch; - return Load::make(op->dtype, ch->handle_var, 0, op->predicate); - } - - Stmt Split(Stmt stmt, const ProducerConsumer* env) { - stmt = Mutate(stmt); - if (env) { - stages_.emplace_back(BuildStage(stmt, env->func)); - } else { - stmt = RemoveNoOp(stmt); - CHECK(is_no_op(stmt)); - } - CHECK_NE(stages_.size(), 0); - stmt = stages_.back(); - for (size_t i = stages_.size() - 1; i != 0; --i) { - stmt = Block::make(stages_[i - 1], stmt); - } - stmt = MarkChannelAccess(cmap_, fifo_map_).Mutate(stmt); - return RemoveNoOp(stmt); - } - - private: - // Build the stage. - Stmt BuildStage(Stmt body, NodeRef target) { - int stage_index = static_cast(stages_.size()); - std::string stage_suffix = "." + std::to_string(stage_index); - // The Substitute - Map subst; - std::vector nest; - Stmt no_op = Evaluate::make(0); - - for (const Stmt& s : nest_) { - if (const For* op = s.as()) { - Var loop_var(op->loop_var); - Var new_var = loop_var.copy_with_suffix(stage_suffix); - subst.Set(loop_var, new_var); - nest.emplace_back(For::make( - new_var, op->min, op->extent, - op->for_type, op->device_api, no_op)); - } else if (const LetStmt* op = s.as()) { - Var var(op->var); - Var new_var = var.copy_with_suffix(stage_suffix); - subst.Set(var, new_var); - nest.emplace_back(LetStmt::make(new_var, op->value, no_op)); - } else if (const IfThenElse* op = s.as()) { - CHECK(!op->else_case.defined()); - nest.emplace_back(IfThenElse::make(op->condition, no_op)); - } else if (const AttrStmt* op = s.as()) { - nest.emplace_back(AttrStmt::make( - op->node, op->attr_key, op->value, no_op)); - } else if (s.as()) { - } else if (s.as()) { - } else if (const Allocate* op = s.as()) { - nest.emplace_back(Allocate::make( - op->buffer_var, op->dtype, op->extents, - op->condition, no_op, op->new_expr, op->free_function)); - MarkChannel(op); - } else { - LOG(FATAL) << "not supported nest type " << s->GetTypeKey(); - } - } - body = Substitute(MergeNest(nest, body), subst); - return AttrStmt::make( - target, ir::attr::pipeline_stage_scope, - make_const(DataType::Int(32), stage_index), body); - } - void MarkChannel(const Allocate* op) { - if (!cmap_.count(op->buffer_var.get())) { - Channel ch = ChannelNode::make(Var(op->buffer_var), op->dtype); - cmap_[op->buffer_var.get()] = ch; - } - } - // The stack - std::vector nest_; - // The stages - std::vector stages_; - // channel map - std::unordered_map cmap_; - // Whether split load into a temp fifo. - bool split_load_{true}; - // Counter for temp FIFOs. - size_t temp_fifo_count_{0}; - // fifo map - std::unordered_map fifo_map_; -}; - -class PipelineSplitter : public IRMutator { - public: - explicit PipelineSplitter(bool split_load) - : split_load_(split_load) {} - - Stmt Mutate_(const AttrStmt* op, const Stmt& s) final { - if (op->attr_key == ir::attr::pipeline_exec_scope) { - CHECK_LE(env_.size(), 1U); - const ProducerConsumer* env = nullptr; - if (env_.size() == 1) { - std::swap(env_[0], env); - } - Stmt body = StageSplitter(split_load_).Split( - op->body, env); - if (body.same_as(op->body)) return s; - return AttrStmt::make( - op->node, op->attr_key, op->value, body); - } else { - return IRMutator::Mutate_(op, s); - } - } - Stmt Mutate_(const ProducerConsumer* op, const Stmt& s) { - env_.push_back(op); - Stmt ret = IRMutator::Mutate_(op, s); - if (env_.back() == nullptr) { - ret = ret.as()->body; - } - env_.pop_back(); - return ret; - } - - private: - bool split_load_; - std::vector env_; -}; - -Stmt SplitPipeline(Stmt stmt, bool split_load) { - return PipelineSplitter(split_load).Mutate(stmt); -} - -} // namespace ir -} // namespace tvm diff --git a/src/runtime/module.cc b/src/runtime/module.cc index 2f3e337b4ce8..5bf9f6ad16c2 100644 --- a/src/runtime/module.cc +++ b/src/runtime/module.cc @@ -149,8 +149,6 @@ bool RuntimeEnabled(const std::string& target) { f_name = "codegen.build_stackvm"; } else if (target == "rpc") { f_name = "device_api.rpc"; - } else if (target == "vpi" || target == "verilog") { - f_name = "device_api.vpi"; } else if (target == "micro_dev") { f_name = "device_api.micro_dev"; } else if (target.length() >= 5 && target.substr(0, 5) == "nvptx") { diff --git a/tests/python/unittest/test_pass_split_pipeline.py b/tests/python/unittest/test_pass_split_pipeline.py deleted file mode 100644 index 380053420f44..000000000000 --- a/tests/python/unittest/test_pass_split_pipeline.py +++ /dev/null @@ -1,81 +0,0 @@ -# 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. -import tvm - -def lower(s, args): - binds = {} - arg_list = [] - - for x in args: - assert isinstance(x, tvm.tensor.Tensor) - buf = tvm.decl_buffer(x.shape, dtype=x.dtype, name=x.op.name) - binds[x] = buf - arg_list.append(buf) - s.normalize() - bounds = tvm.schedule.InferBound(s) - stmt = tvm.schedule.ScheduleOps(s, bounds) - stmt = tvm.ir_pass.StorageFlatten(stmt, binds, 64) - stmt = tvm.ir_pass.CanonicalSimplify(stmt) - stmt = tvm.ir_pass.Simplify(stmt) - return stmt - -def test_basic_pipeline(): - n = tvm.convert(128) - A = tvm.placeholder((n,), name='A') - stages = [] - num_stage = 3 - - B = A - for k in range(num_stage): - stages.append(B) - B = tvm.compute((n,), lambda i: B[i] + k, name="A%s" % k) - - s = tvm.create_schedule(B.op) - xo, xi = s[B].split(B.op.axis[0], nparts=1) - s[B].bind(xo, tvm.thread_axis("pipeline")) - xo, xi = s[B].split(xi, factor=4) - for S in stages: - s[S].compute_at(s[B], xo) - - stmt = lower(s, [A, B]) - stmt = tvm.ir_pass.SplitPipeline(stmt, False) - print(stmt) - stmt = tvm.ir_pass.NarrowChannelAccess(stmt) - print(stmt) - assert(tvm.ir_pass.VerifySSA(stmt)) - -def test_conv1d(): - n = tvm.var('n') - A = tvm.compute((n+2), lambda i: 1, name='A') - def computeB(ii): - i = ii + 1 - return A[i-1] + A[i] + A[i+1] - B = tvm.compute(n, computeB, name='B') - s = tvm.create_schedule(B.op) - px, xi = s[B].split(B.op.axis[0], nparts=1) - s[B].bind(px, tvm.thread_axis("pipeline")) - s[A].compute_at(s[B], px) - stmt = lower(s, [B]) - stmt = tvm.ir_pass.SplitPipeline(stmt, False) - print(stmt) - stmt = tvm.ir_pass.NarrowChannelAccess(stmt) - print(stmt) - - -if __name__ == "__main__": - test_basic_pipeline() - test_conv1d() diff --git a/tests/scripts/packages.mk b/tests/scripts/packages.mk deleted file mode 100644 index a735ba37246d..000000000000 --- a/tests/scripts/packages.mk +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -# rules for gtest -.PHONY: iverilog - -iverilog: | ${CACHE_PREFIX}/bin/vvp - -${CACHE_PREFIX}/bin/vvp: - rm -rf verilog-10.1.tar.gz verilog-10.1 - wget ftp://icarus.com/pub/eda/verilog/v10/verilog-10.1.tar.gz - tar xf verilog-10.1.tar.gz - cd verilog-10.1;./configure --prefix=${CACHE_PREFIX}; make install diff --git a/tests/scripts/task_verilog_test.sh b/tests/scripts/task_verilog_test.sh deleted file mode 100755 index 48bee0d34ce4..000000000000 --- a/tests/scripts/task_verilog_test.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# 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. - -set -e -set -u - -export PYTHONPATH=python -make verilog -python3 -m pytest -v tests/verilog/unittest -python3 -m pytest -v tests/verilog/integration diff --git a/tests/travis/run_test.sh b/tests/travis/run_test.sh deleted file mode 100644 index 0cb529b46e88..000000000000 --- a/tests/travis/run_test.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# 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. - -if [ ${TASK} == "lint" ] || [ ${TASK} == "all_test" ]; then - if [ ! ${TRAVIS_OS_NAME} == "osx" ]; then - ./tests/scripts/task_lint.sh || exit -1 - fi -fi - -cp make/config.mk config.mk -echo "USE_CUDA=0" >> config.mk -echo "USE_RPC=1" >> config.mk - -if [ ${TRAVIS_OS_NAME} == "osx" ]; then - echo "USE_OPENCL=1" >> config.mk - echo "USE_METAL=1" >> config.mk -else - # use g++-4.8 for linux - if [ ${CXX} == "g++" ]; then - export CXX=g++-4.8 - fi - echo "USE_OPENCL=0" >> config.mk -fi - -if [ ${TASK} == "verilog_test" ] || [ ${TASK} == "all_test" ]; then - if [ ! ${TRAVIS_OS_NAME} == "osx" ]; then - make -f tests/scripts/packages.mk iverilog - make all || exit -1 - ./tests/scripts/task_verilog_test.sh || exit -1 - fi -fi - -if [ ${TASK} == "cpp_test" ] || [ ${TASK} == "all_test" ]; then - make -f dmlc-core/scripts/packages.mk gtest - ./tests/scripts/task_cpp_unittest.sh || exit -1 -fi - -if [ ${TASK} == "python_test" ] || [ ${TASK} == "all_test" ]; then - make all || exit -1 - if [ ${TRAVIS_OS_NAME} == "osx" ]; then - ./tests/scripts/task_python_unittest.sh || exit -1 - else - pytests3 -v tests/python/unittest || exit -1 - fi -fi diff --git a/tests/travis/setup.sh b/tests/travis/setup.sh deleted file mode 100644 index 932c47d75f99..000000000000 --- a/tests/travis/setup.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# 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. - -if [ ${TASK} == "python_test" ] || [ ${TASK} == "all_test" ]; then - if [ ${TRAVIS_OS_NAME} == "osx" ]; then - brew update - brew install python3 - python3 -m pip install --user pytest numpy cython - fi -fi - -if [ ${TASK} == "lint" ] || [ ${TASK} == "all_test" ]; then - if [ ! ${TRAVIS_OS_NAME} == "osx" ]; then - pip install --user cpplint 'pylint==1.4.4' 'astroid==1.3.6' - fi -fi diff --git a/tests/travis/travis_after_failure.sh b/tests/travis/travis_after_failure.sh deleted file mode 100644 index 36bf5d2347fd..000000000000 --- a/tests/travis/travis_after_failure.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# 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.