aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast/ast.h
blob: 8932108e3790dd2fbc4b2ffb734a060e1e517d03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
[metadata]
long_description = file: README.rst
long_description_content_type = text/x-rst
description = Seamless operability between C++11 and Python
author = Wenzel Jakob
author_email = wenzel.jakob@epfl.ch
url = https://github.com/pybind/pybind11
license = BSD

classifiers =
    Development Status :: 5 - Production/Stable
    Intended Audience :: Developers
    Topic :: Software Development :: Libraries :: Python Modules
    Topic :: Utilities
    Programming Language :: C++
    Programming Language :: Python :: 2.7
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3.5
    Programming Language :: Python :: 3.6
    Programming Language :: Python :: 3.7
    Programming Language :: Python :: 3.8
    Programming Language :: Python :: 3.9
    License :: OSI Approved :: BSD License
    Programming Language :: Python :: Implementation :: PyPy
    Programming Language :: Python :: Implementation :: CPython
    Programming Language :: C++
    Topic :: Software Development :: Libraries :: Python Modules

keywords =
    C++11
    Python bindings

[options]
python_requires = >=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4
zip_safe = False

[bdist_wheel]
universal=1

[check-manifest]
ignore =
    tests/**
    docs/**
    tools/**
    include/**
    .appveyor.yml
    .cmake-format.yaml
    .gitmodules
    .pre-commit-config.yaml
    .readthedocs.yml
    .clang-tidy
    pybind11/include/**
    pybind11/share/**
    CMakeLists.txt


[flake8]
max-line-length = 99
show_source = True
exclude = .git, __pycache__, build, dist, docs, tools, venv
ignore =
    # required for pretty matrix formatting: multiple spaces after `,` and `[`
    E201, E241, W504,
    # camelcase 'cPickle' imported as lowercase 'pickle'
    N813
    # Black conflict
    W503, E203

[mypy]
files = pybind11
strict = True
href='#n366'>366 367
/* -*- 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_ENUM,
		AST_ENUM_ITEM,

		AST_FCALL,
		AST_TO_BITS,
		AST_TO_SIGNED,
		AST_TO_UNSIGNED,
		AST_SELFSZ,
		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_SHIFTX,
		AST_SHIFT,
		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
	};

	struct AstSrcLocType {
		unsigned int first_line, last_line;
		unsigned int first_column, last_column;
		AstSrcLocType() : first_line(0), last_line(0), first_column(0), last_column(0) {}
		AstSrcLocType(int _first_line, int _first_column, int _last_line, int _last_column) : first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {}
	};

	// 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;
		// set for IDs typed to an enumeration, not used
		bool is_enum;

		// 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 used for ID references in RHS expressions that should use the "new" value for non-blocking assignments
		bool lookahead;

		// 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;
		AstSrcLocType location;

		// 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();
		std::string process_format_str(const std::string &sformat, int next_arg, int stage, int width_hint, bool sign_hint);

		// 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);

		// helpers for enum
		void allocateDefaultEnumValues();
	};

	// 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, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) YS_OVERRIDE;
		RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) YS_OVERRIDE;
		std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false);
		void reprocess_module(RTLIL::Design *design, const 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 LookaheadRewriter;
	struct ProcessGenerator;
}

YOSYS_NAMESPACE_END

#endif