/*! * Copyright (c) 2017 by Contributors * \file codegen_verilog.h * \brief Generate verilog code. */ #ifndef TVM_CODEGEN_VERILOG_CODEGEN_VERILOG_H_ #define TVM_CODEGEN_VERILOG_CODEGEN_VERILOG_H_ #include <tvm/base.h> #include <tvm/ir.h> #include <tvm/ir_functor_ext.h> #include <tvm/codegen.h> #include <tvm/lowered_func.h> #include <string> #include <vector> #include <unordered_map> #include "verilog_ir.h" #include "../codegen_source_base.h" namespace tvm { namespace codegen { namespace verilog { using namespace ir; /* \brief The variable type in register.*/ enum VerilogVarType { kWire, kInput, kOutput, kReg, kConst }; /*! \brief The verilog value */ struct VerilogValue { /*! \brief The variable id */ std::string vid; /*! \brief The variable type */ VerilogVarType vtype{kReg}; /*! \brief The data type it encodes */ Type dtype; VerilogValue() {} VerilogValue(std::string vid, VerilogVarType vtype, Type dtype) : vid(vid), vtype(vtype), dtype(dtype) {} }; /*! \brief Information of each procedure function generated */ struct VerilogFuncEntry { /*! \brief The original functions */ std::vector<Type> arg_types; /*! \brief The real argument ids of the function */ std::vector<std::string> arg_ids; /*! \brief The VPI Modules in the function */ std::vector<std::string> vpi_modules; }; /*! * \brief The code module of generated verilog code. */ class VerilogCodeGenModule { public: /*! \brief the code of each modoules */ std::string code; /*! \brief map of functions */ std::unordered_map<std::string, VerilogFuncEntry> fmap; /*! * \brief Generate a code that append simulator function to call func_name. * \param func_name The function to be called. * \return The generated code. */ std::string AppendSimMain(const std::string& func_name) const; }; /*! * \brief Verilog generator */ class CodeGenVerilog : public ExprFunctor<VerilogValue(const Expr&)>, public CodeGenSourceBase { public: /*! * \brief Initialize the code generator. * \param output_ssa Whether output SSA. */ void Init(); /*! * \brief Add the function to the generated module. * \param f The function to be compiled. */ void AddFunction(LoweredFunc f); /*! * \brief Finalize the compilation and return the code. * \return The code. */ VerilogCodeGenModule Finish(); /*! * \brief Transform expression to verilog value. * \param n The expression to be printed. */ VerilogValue MakeValue(const Expr& n) { return VisitExpr(n); } // The following parts are overloadable print operations. // expression VerilogValue VisitExpr_(const Variable* op) final; VerilogValue VisitExpr_(const Let* op) final; VerilogValue VisitExpr_(const Call* op) final; VerilogValue VisitExpr_(const Add* op) final; VerilogValue VisitExpr_(const Sub* op) final; VerilogValue VisitExpr_(const Mul* op) final; VerilogValue VisitExpr_(const Div* op) final; VerilogValue VisitExpr_(const Mod* op) final; VerilogValue VisitExpr_(const Min* op) final; VerilogValue VisitExpr_(const Max* op) final; VerilogValue VisitExpr_(const EQ* op) final; VerilogValue VisitExpr_(const NE* op) final; VerilogValue VisitExpr_(const LT* op) final; VerilogValue VisitExpr_(const LE* op) final; VerilogValue VisitExpr_(const GT* op) final; VerilogValue VisitExpr_(const GE* op) final; VerilogValue VisitExpr_(const And* op) final; VerilogValue VisitExpr_(const Or* op) final; VerilogValue VisitExpr_(const Cast* op) final; VerilogValue VisitExpr_(const Not* op) final; VerilogValue VisitExpr_(const Select* op) final; VerilogValue VisitExpr_(const Ramp* op) final; VerilogValue VisitExpr_(const Broadcast* op) final; VerilogValue VisitExpr_(const IntImm* op) final; VerilogValue VisitExpr_(const UIntImm* op) final; VerilogValue VisitExpr_(const FloatImm* op) final; VerilogValue VisitExpr_(const StringImm* op) final; protected: void InitFuncState(LoweredFunc f); void PrintDecl(const std::string& vid, VerilogVarType vtype, Type dtype, const char* suffix = ";\n", bool indent = true); void PrintAssign( const std::string& target, const std::string& src); void PrintAssignAnd( const std::string& target, const std::vector<std::string>& conds); void PrintLine(const std::string& line); void PrintSSAAssign( const std::string& target, const std::string& src, Type t) final; // make binary op VerilogValue MakeBinary(Type t, VerilogValue a, VerilogValue b, const char* opstr); private: // Hand shake signal name. // These name can be empty. // Indicate that the signal is always true // or do not need to take these signals. struct SignalEntry { std::string valid; std::string ready; }; // Information about port struct PortEntry { // The port value std::string value; // The data type Type dtype; }; // Channel setup struct ChannelEntry { // The channel block ChannelBlock block; // The port map, on how port is assigned. std::unordered_map<std::string, PortEntry> ports; // Assign port to be valueo void AssignPort(std::string port, std::string value, Type dtype); // Assign port to be valueo const PortEntry& GetPort(const std::string& port) const; // Signal port name std::string SignalPortName(int index) const; }; // Get wire ssa value from s VerilogValue GetSSAValue(std::string s, Type dtype) { VerilogValue ret; ret.vid = SSAGetID(s, dtype); ret.vtype = kWire; ret.dtype = dtype; return ret; } void CodeGen(const Pipeline& pipeine); // codegen the delays void MakeDelay(const std::string& dst, const std::string& src, Type dtype, int delay, const std::string& not_stall); // codegen the loop macros SignalEntry MakeLoop(const Array<Stmt>& loop); // codegen the loop macros void MakeStageInputs(const ComputeBlock& block, const std::string& not_stall, std::string* out_all_input_valid); // codegen compute block void MakeStore(const ComputeBlock& block, const Store* store); // Codegen of load statement into FIFO void MakeLoadToFIFO(const ComputeBlock& block, const Store* store, const Load* load); // Make channel unit. void MakeChannelUnit(const ChannelEntry& ch); void MakeChannelFIFO(const ChannelEntry& ch); void MakeChannelBuffer(const ChannelEntry& ch); void MakeChannelMemMap(const ChannelEntry& ch); // Get channel information ChannelEntry* GetChannelInfo(const Variable* var); // channel setup map. std::unordered_map<const Variable*, ChannelEntry> cmap_; // list of vpi modules to be hooked. std::vector<std::string> tvm_vpi_modules_; // The signals for done. std::vector<std::string> done_sigs_; // The verilog function. std::unordered_map<std::string, VerilogFuncEntry> functions_; }; } // namespace verilog } // namespace codegen } // namespace tvm #endif // TVM_CODEGEN_VERILOG_CODEGEN_VERILOG_H_