/*! * Copyright (c) 2017 by Contributors * \file verilog_ir.h * \brief A lowered IR that resembles verilog blocks, * This is data structure before final codegen. */ #ifndef TVM_CODEGEN_VERILOG_VERILOG_IR_H_ #define TVM_CODEGEN_VERILOG_VERILOG_IR_H_ #include <tvm/ir.h> #include <tvm/expr.h> #include <tvm/channel.h> #include <tvm/lowered_func.h> #include <vector> #include <memory> #include <unordered_map> namespace tvm { namespace codegen { namespace verilog { /*! \brief The data argument type */ enum StageInputType : int { /*! \brief Data channel input. */ kChannel, /*! \brief Loop variable generated by compute block. */ kLoopVar, /*! \brief Global constant. */ kGlobalConst }; /*! \brief The data argument type */ enum ControlSignalType : int { // Read advance signal kReadAdvance, // Write advance signal kWriteAdvance, // Pipeline stage finish signal kComputeFinish }; class ControlSignal; class StageInput; class SignalTrigger; /*! \brief The control signal of a channel */ struct ControlSignalNode : public Node { /*! \brief The control signal type */ ControlSignalType ctrl_type; /*! \brief Advance size of the signal */ int advance_size{0}; // visit all attributes void VisitAttrs(AttrVisitor* v) final { v->Visit("ctrl_type", &ctrl_type); v->Visit("advance_size", &advance_size); } static ControlSignal make(ControlSignalType ctrl_type, int advance_size); static constexpr const char* _type_key = "VerilogControlSignal"; TVM_DECLARE_NODE_TYPE_INFO(ControlSignalNode, Node); }; TVM_DEFINE_NODE_REF(ControlSignal, ControlSignalNode); /*! \brief Information about channel. */ struct ChannelBlockNode : public Node { /*! \brief The channel we are refer to */ Channel channel; /*! \brief Read window */ int read_window{0}; /*! \brief Write window */ int write_window{0}; /*! \brief Control signals in the channel */ Array<ControlSignal> ctrl_signals; // visit all attributes void VisitAttrs(AttrVisitor* v) final { v->Visit("channel", &channel); v->Visit("read_window", &read_window); v->Visit("write_window", &write_window); v->Visit("ctrl_signals", &ctrl_signals); } static constexpr const char* _type_key = "VerilogChannelBlock"; TVM_DECLARE_NODE_TYPE_INFO(ChannelBlockNode, Node); }; TVM_DEFINE_NODE_REF(ChannelBlock, ChannelBlockNode); /*! * \brief Input to the compute block. * These represents the data values that need to be shared; */ struct StageInputNode : public Node { /*! * \brief The corresponding var of the input * For loop and global const it is the var. * For channel this corresponds to the channel handle. */ Var var; /*! \brief The type of the input. */ StageInputType input_type; // visit all attributes void VisitAttrs(AttrVisitor* v) final { v->Visit("var", &var); v->Visit("input_type", &input_type); } // constructor static StageInput make(Var var, StageInputType input_type); static constexpr const char* _type_key = "VerilogStageInput"; TVM_DECLARE_NODE_TYPE_INFO(StageInputNode, Node); }; TVM_DEFINE_NODE_REF(StageInput, StageInputNode); /*! \brief The trigger signal for certain channel */ struct SignalTriggerNode : public Node { /*! \brief The channel handle variable */ Var channel_var; /*! \brief Boolean predicate to trigger the signal */ Expr predicate; /*! \brief siginal index of the channel */ int signal_index; // visit all attributes void VisitAttrs(AttrVisitor* v) final { v->Visit("channel_var", &channel_var); v->Visit("predicate", &predicate); v->Visit("signal_index", &signal_index); } // constructor static constexpr const char* _type_key = "VerilogSignalTrigger"; TVM_DECLARE_NODE_TYPE_INFO(SignalTriggerNode, Node); }; TVM_DEFINE_NODE_REF(SignalTrigger, SignalTriggerNode); /*! \brief compute block for verilog */ struct ComputeBlockNode : public Node { /*! \brief The body of the block. */ Stmt body; /*! \brief The loop nest around the body, each is a For with no_op as body */ Array<Stmt> loop; /*! \brief The channel advance trigger */ Array<SignalTrigger> triggers; /*! \brief The input variables that need to be synced. */ Map<Var, StageInput> inputs; // visit all attributes void VisitAttrs(AttrVisitor* v) final { v->Visit("body", &body); v->Visit("loop", &loop); v->Visit("triggers", &triggers); v->Visit("inputs", &inputs); } static constexpr const char* _type_key = "VerilogComputeBlock"; TVM_DECLARE_NODE_TYPE_INFO(ComputeBlockNode, Node); }; TVM_DEFINE_NODE_REF(ComputeBlock, ComputeBlockNode); /*! \brief Codeblock for verilog module. */ struct PipelineNode : public Node { /*! \brief arguments to the module */ Array<Var> args; /*! \brief Computation stages */ Array<ComputeBlock> stages; /*! \brief The data channels */ Map<Var, ChannelBlock> channels; // visit all attributes void VisitAttrs(AttrVisitor* v) final { v->Visit("args", &args); v->Visit("stages", &stages); v->Visit("channels", &channels); } static constexpr const char* _type_key = "VerilogPipeline"; TVM_DECLARE_NODE_TYPE_INFO(PipelineNode, Node); }; TVM_DEFINE_NODE_REF(Pipeline, PipelineNode); /*! * \brief Build a lowered verilog pipeline given function. * \param f The function to be transformed. * \param The created verilog pipeline. */ Pipeline MakePipeline(LoweredFunc f); } // namespace verilog } // namespace codegen } // namespace tvm #endif // TVM_CODEGEN_VERILOG_VERILOG_IR_H_