diff --git a/CMakeLists.txt b/CMakeLists.txt index afcb73041469..f8d5a6e5389d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,11 +168,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 TOPI_SRCS topi/src/*.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.