| /* -*- c++ -*- |
| * yosys -- Yosys Open SYnthesis Suite |
| * |
| * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| * |
| * --- |
| * |
| * This is the AST frontend library. |
| * |
| * The AST frontend library is not a frontend on it's own but provides a |
| * generic abstract syntax tree (AST) abstraction for HDL code and can be |
| * used by HDL frontends. See "ast.h" for an overview of the API and the |
| * Verilog frontend for an usage example. |
| * |
| */ |
| |
| #ifndef AST_H |
| #define AST_H |
| |
| #include "kernel/rtlil.h" |
| #include <stdint.h> |
| #include <set> |
| |
| YOSYS_NAMESPACE_BEGIN |
| |
| namespace AST |
| { |
| // all node types, type2str() must be extended |
| // whenever a new node type is added here |
| enum AstNodeType |
| { |
| AST_NONE, |
| AST_DESIGN, |
| AST_MODULE, |
| AST_TASK, |
| AST_FUNCTION, |
| AST_DPI_FUNCTION, |
| |
| AST_WIRE, |
| AST_MEMORY, |
| AST_AUTOWIRE, |
| AST_PARAMETER, |
| AST_LOCALPARAM, |
| AST_DEFPARAM, |
| AST_PARASET, |
| AST_ARGUMENT, |
| AST_RANGE, |
| AST_MULTIRANGE, |
| AST_CONSTANT, |
| AST_REALVALUE, |
| AST_CELLTYPE, |
| AST_IDENTIFIER, |
| AST_PREFIX, |
| AST_ASSERT, |
| AST_ASSUME, |
| AST_LIVE, |
| AST_FAIR, |
| AST_COVER, |
| |
| AST_FCALL, |
| AST_TO_BITS, |
| AST_TO_SIGNED, |
| AST_TO_UNSIGNED, |
| AST_CONCAT, |
| AST_REPLICATE, |
| AST_BIT_NOT, |
| AST_BIT_AND, |
| AST_BIT_OR, |
| AST_BIT_XOR, |
| AST_BIT_XNOR, |
| AST_REDUCE_AND, |
| AST_REDUCE_OR, |
| AST_REDUCE_XOR, |
| AST_REDUCE_XNOR, |
| AST_REDUCE_BOOL, |
| AST_SHIFT_LEFT, |
| AST_SHIFT_RIGHT, |
| AST_SHIFT_SLEFT, |
| AST_SHIFT_SRIGHT, |
| AST_LT, |
| AST_LE, |
| AST_EQ, |
| AST_NE, |
| AST_EQX, |
| AST_NEX, |
| AST_GE, |
| AST_GT, |
| AST_ADD, |
| AST_SUB, |
| AST_MUL, |
| AST_DIV, |
| AST_MOD, |
| AST_POW, |
| AST_POS, |
| AST_NEG, |
| AST_LOGIC_AND, |
| AST_LOGIC_OR, |
| AST_LOGIC_NOT, |
| AST_TERNARY, |
| AST_MEMRD, |
| AST_MEMWR, |
| AST_MEMINIT, |
| |
| AST_TCALL, |
| AST_ASSIGN, |
| AST_CELL, |
| AST_PRIMITIVE, |
| AST_CELLARRAY, |
| AST_ALWAYS, |
| AST_INITIAL, |
| AST_BLOCK, |
| AST_ASSIGN_EQ, |
| AST_ASSIGN_LE, |
| AST_CASE, |
| AST_COND, |
| AST_CONDX, |
| AST_CONDZ, |
| AST_DEFAULT, |
| AST_FOR, |
| AST_WHILE, |
| AST_REPEAT, |
| |
| AST_GENVAR, |
| AST_GENFOR, |
| AST_GENIF, |
| AST_GENCASE, |
| AST_GENBLOCK, |
| AST_TECALL, |
| |
| AST_POSEDGE, |
| AST_NEGEDGE, |
| AST_EDGE, |
| |
| AST_INTERFACE, |
| AST_INTERFACEPORT, |
| AST_INTERFACEPORTTYPE, |
| AST_MODPORT, |
| AST_MODPORTMEMBER, |
| AST_PACKAGE, |
| |
| AST_WIRETYPE, |
| AST_TYPEDEF |
| }; |
| |
| // convert an node type to a string (e.g. for debug output) |
| std::string type2str(AstNodeType type); |
| |
| // The AST is built using instances of this struct |
| struct AstNode |
| { |
| // for dict<> and pool<> |
| unsigned int hashidx_; |
| unsigned int hash() const { return hashidx_; } |
| |
| // this nodes type |
| AstNodeType type; |
| |
| // the list of child nodes for this node |
| std::vector<AstNode*> children; |
| |
| // the list of attributes assigned to this node |
| std::map<RTLIL::IdString, AstNode*> attributes; |
| bool get_bool_attribute(RTLIL::IdString id); |
| |
| // node content - most of it is unused in most node types |
| std::string str; |
| std::vector<RTLIL::State> bits; |
| bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type; |
| int port_id, range_left, range_right; |
| uint32_t integer; |
| double realvalue; |
| |
| // if this is a multirange memory then this vector contains offset and length of each dimension |
| std::vector<int> multirange_dimensions; |
| |
| // this is set by simplify and used during RTLIL generation |
| AstNode *id2ast; |
| |
| // this is used by simplify to detect if basic analysis has been performed already on the node |
| bool basic_prep; |
| |
| // this is the original sourcecode location that resulted in this AST node |
| // it is automatically set by the constructor using AST::current_filename and |
| // the AST::get_line_num() callback function. |
| std::string filename; |
| int linenum; |
| |
| // creating and deleting nodes |
| AstNode(AstNodeType type = AST_NONE, AstNode *child1 = NULL, AstNode *child2 = NULL, AstNode *child3 = NULL); |
| AstNode *clone() const; |
| void cloneInto(AstNode *other) const; |
| void delete_children(); |
| ~AstNode(); |
| |
| enum mem2reg_flags |
| { |
| /* status flags */ |
| MEM2REG_FL_ALL = 0x00000001, |
| MEM2REG_FL_ASYNC = 0x00000002, |
| MEM2REG_FL_INIT = 0x00000004, |
| |
| /* candidate flags */ |
| MEM2REG_FL_FORCED = 0x00000100, |
| MEM2REG_FL_SET_INIT = 0x00000200, |
| MEM2REG_FL_SET_ELSE = 0x00000400, |
| MEM2REG_FL_SET_ASYNC = 0x00000800, |
| MEM2REG_FL_EQ2 = 0x00001000, |
| MEM2REG_FL_CMPLX_LHS = 0x00002000, |
| MEM2REG_FL_CONST_LHS = 0x00004000, |
| MEM2REG_FL_VAR_LHS = 0x00008000, |
| |
| /* proc flags */ |
| MEM2REG_FL_EQ1 = 0x01000000, |
| }; |
| |
| // simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc. |
| // it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL() |
| bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param); |
| AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init); |
| void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map); |
| void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules); |
| void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places, |
| dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags); |
| bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block); |
| bool mem2reg_check(pool<AstNode*> &mem2reg_set); |
| void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes); |
| void meminfo(int &mem_width, int &mem_size, int &addr_bits); |
| |
| // additional functionality for evaluating constant functions |
| struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; |
| bool has_const_only_constructs(bool &recommend_const_eval); |
| void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall); |
| AstNode *eval_const_function(AstNode *fcall); |
| bool is_simple_const_expr(); |
| |
| // create a human-readable text representation of the AST (for debugging) |
| void dumpAst(FILE *f, std::string indent) const; |
| void dumpVlog(FILE *f, std::string indent) const; |
| |
| // used by genRTLIL() for detecting expression width and sign |
| void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL); |
| void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = NULL); |
| |
| // create RTLIL code for this AST node |
| // for expressions the resulting signal vector is returned |
| // all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module |
| RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false); |
| RTLIL::SigSpec genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = NULL); |
| |
| // compare AST nodes |
| bool operator==(const AstNode &other) const; |
| bool operator!=(const AstNode &other) const; |
| bool contains(const AstNode *other) const; |
| |
| // helper functions for creating AST nodes for constants |
| static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32); |
| static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized); |
| static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed); |
| static AstNode *mkconst_str(const std::vector<RTLIL::State> &v); |
| static AstNode *mkconst_str(const std::string &str); |
| |
| // helper function for creating sign-extended const objects |
| RTLIL::Const bitsAsConst(int width, bool is_signed); |
| RTLIL::Const bitsAsConst(int width = -1); |
| RTLIL::Const bitsAsUnsizedConst(int width); |
| RTLIL::Const asAttrConst(); |
| RTLIL::Const asParaConst(); |
| uint64_t asInt(bool is_signed); |
| bool bits_only_01() const; |
| bool asBool() const; |
| |
| // helper functions for real valued const eval |
| int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE |
| double asReal(bool is_signed); |
| RTLIL::Const realAsConst(int width); |
| }; |
| |
| // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code |
| void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit, |
| bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire); |
| |
| // parametric modules are supported directly by the AST library |
| // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions |
| struct AstModule : RTLIL::Module { |
| AstNode *ast; |
| bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire; |
| ~AstModule() YS_OVERRIDE; |
| RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; |
| RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; |
| std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out); |
| void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE; |
| RTLIL::Module *clone() const YS_OVERRIDE; |
| void loadconfig() const; |
| }; |
| |
| // this must be set by the language frontend before parsing the sources |
| // the AstNode constructor then uses current_filename and get_line_num() |
| // to initialize the filename and linenum properties of new nodes |
| extern std::string current_filename; |
| extern void (*set_line_num)(int); |
| extern int (*get_line_num)(); |
| |
| // set set_line_num and get_line_num to internal dummy functions (done by simplify() and AstModule::derive |
| // to control the filename and linenum properties of new nodes not generated by a frontend parser) |
| void use_internal_line_num(); |
| |
| // call a DPI function |
| AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args); |
| |
| // Helper functions related to handling SystemVerilog interfaces |
| std::pair<std::string,std::string> split_modport_from_type(std::string name_type); |
| AstNode * find_modport(AstNode *intf, std::string name); |
| void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport); |
| } |
| |
| namespace AST_INTERNAL |
| { |
| // internal state variables |
| extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit; |
| extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_pwires, flag_autowire; |
| extern AST::AstNode *current_ast, *current_ast_mod; |
| extern std::map<std::string, AST::AstNode*> current_scope; |
| extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr; |
| extern RTLIL::SigSpec ignoreThisSignalsInInitial; |
| extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child; |
| extern AST::AstModule *current_module; |
| extern bool current_always_clocked; |
| struct ProcessGenerator; |
| } |
| |
| YOSYS_NAMESPACE_END |
| |
| #endif |