yosys/frontends/ast/ast.h

426 lines
15 KiB
C
Raw Normal View History

/* -*- c++ -*-
2013-01-05 04:13:26 -06:00
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
2015-07-02 04:14:30 -05:00
*
2013-01-05 04:13:26 -06:00
* 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.
2015-07-02 04:14:30 -05:00
*
2013-01-05 04:13:26 -06:00
* 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
2013-01-05 04:13:26 -06:00
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,
2013-01-05 04:13:26 -06:00
AST_WIRE,
AST_MEMORY,
AST_AUTOWIRE,
AST_PARAMETER,
AST_LOCALPARAM,
AST_DEFPARAM,
2013-01-05 04:13:26 -06:00
AST_PARASET,
AST_ARGUMENT,
AST_RANGE,
AST_MULTIRANGE,
2013-01-05 04:13:26 -06:00
AST_CONSTANT,
AST_REALVALUE,
2013-01-05 04:13:26 -06:00
AST_CELLTYPE,
AST_IDENTIFIER,
AST_PREFIX,
AST_ASSERT,
AST_ASSUME,
AST_LIVE,
AST_FAIR,
AST_COVER,
AST_ENUM,
AST_ENUM_ITEM,
2013-01-05 04:13:26 -06:00
AST_FCALL,
AST_TO_BITS,
2013-01-05 04:13:26 -06:00
AST_TO_SIGNED,
AST_TO_UNSIGNED,
AST_SELFSZ,
AST_CAST_SIZE,
2013-01-05 04:13:26 -06:00
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,
2013-01-05 04:13:26 -06:00
AST_LT,
AST_LE,
AST_EQ,
AST_NE,
AST_EQX,
AST_NEX,
2013-01-05 04:13:26 -06:00
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,
2013-01-05 04:13:26 -06:00
AST_TCALL,
AST_ASSIGN,
AST_CELL,
AST_PRIMITIVE,
2014-06-07 04:48:50 -05:00
AST_CELLARRAY,
2013-01-05 04:13:26 -06:00
AST_ALWAYS,
AST_INITIAL,
2013-01-05 04:13:26 -06:00
AST_BLOCK,
AST_ASSIGN_EQ,
AST_ASSIGN_LE,
AST_CASE,
AST_COND,
AST_CONDX,
AST_CONDZ,
2013-01-05 04:13:26 -06:00
AST_DEFAULT,
AST_FOR,
AST_WHILE,
AST_REPEAT,
2013-01-05 04:13:26 -06:00
AST_GENVAR,
AST_GENFOR,
AST_GENIF,
AST_GENCASE,
2013-01-05 04:13:26 -06:00
AST_GENBLOCK,
AST_TECALL,
2020-05-08 08:40:49 -05:00
2013-01-05 04:13:26 -06:00
AST_POSEDGE,
AST_NEGEDGE,
AST_EDGE,
AST_INTERFACE,
AST_INTERFACEPORT,
AST_INTERFACEPORTTYPE,
AST_MODPORT,
AST_MODPORTMEMBER,
AST_PACKAGE,
AST_WIRETYPE,
2020-05-08 08:40:49 -05:00
AST_TYPEDEF,
AST_STRUCT,
AST_UNION,
Add support for parsing the SystemVerilog 'bind' construct This doesn't do anything useful yet: the patch just adds support for the syntax to the lexer and parser and adds some tests to check the syntax parses properly. This generates AST nodes, but doesn't yet generate RTLIL. Since our existing hierarchical_identifier parser doesn't allow bit selects (so you can't do something like foo[1].bar[2].baz), I've also not added support for a trailing bit select (the "constant_bit_select" non-terminal in "bind_target_instance" in the spec). If we turn out to need this in future, we'll want to augment hierarchical_identifier and its other users too. Note that you can't easily use the BNF from the spec: bind_directive ::= "bind" bind_target_scope [ : bind_target_instance_list] bind_instantiation ; | "bind" bind_target_instance bind_instantiation ; even if you fix the lookahead problem, because code like this matches both branches in the BNF: bind a b b_i (.*); The problem is that 'a' could either be a module name or a degenerate hierarchical reference. This seems to be a genuine syntactic ambiguity, which the spec resolves (p739) by saying that we have to wait until resolution time (the hierarchy pass) and take whatever is defined, treating 'a' as an instance name if it names both an instance and a module. To keep the parser simple, it currently accepts this invalid syntax: bind a.b : c d e (.*); This is invalid because we're in the first branch of the BNF above, so the "a.b" term should match bind_target_scope: a module or interface identifier, not an arbitrary hierarchical identifier. This will fail in the hierarchy pass (when it's implemented in a future patch).
2020-05-21 11:36:29 -05:00
AST_STRUCT_ITEM,
AST_BIND
2013-01-05 04:13:26 -06:00
};
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) {}
};
2013-01-05 04:13:26 -06:00
// 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
{
2014-12-28 20:11:50 -06:00
// for dict<> and pool<>
unsigned int hashidx_;
unsigned int hash() const { return hashidx_; }
2013-01-05 04:13:26 -06:00
// 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);
2013-01-05 04:13:26 -06:00
// 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;
2013-01-05 04:13:26 -06:00
int port_id, range_left, range_right;
uint32_t integer;
double realvalue;
// set for IDs typed to an enumeration, not used
bool is_enum;
2013-01-05 04:13:26 -06:00
// if this is a multirange memory then this vector contains offset and length of each dimension
std::vector<int> multirange_dimensions;
std::vector<bool> multirange_swapped; // true if range is swapped
2013-01-05 04:13:26 -06:00
// 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;
2013-01-05 04:13:26 -06:00
// 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;
2013-01-05 04:13:26 -06:00
// creating and deleting nodes
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr);
AstNode *clone() const;
void cloneInto(AstNode *other) const;
2013-01-05 04:13:26 -06:00
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,
2014-06-17 14:39:25 -05:00
MEM2REG_FL_CMPLX_LHS = 0x00002000,
MEM2REG_FL_CONST_LHS = 0x00004000,
MEM2REG_FL_VAR_LHS = 0x00008000,
/* proc flags */
MEM2REG_FL_EQ1 = 0x01000000,
};
2013-01-05 04:13:26 -06:00
// 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);
void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
2015-07-31 03:40:09 -05:00
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
verilog: significant block scoping improvements This change set contains a number of bug fixes and improvements related to scoping and resolution in generate and procedural blocks. While many of the frontend changes are interdependent, it may be possible bring the techmap changes in under a separate PR. Declarations within unnamed generate blocks previously encountered issues because the data declarations were left un-prefixed, breaking proper scoping. The LRM outlines behavior for generating names for unnamed generate blocks. The original goal was to add this implicit labelling, but doing so exposed a number of issues downstream. Additional testing highlighted other closely related scope resolution issues, which have been fixed. This change also adds support for block item declarations within unnamed blocks in SystemVerilog mode. 1. Unlabled generate blocks are now implicitly named according to the LRM in `label_genblks`, which is invoked at the beginning of module elaboration 2. The Verilog parser no longer wraps explicitly named generate blocks in a synthetic unnamed generate block to avoid creating extra hierarchy levels where they should not exist 3. The techmap phase now allows special control identifiers to be used outside of the topmost scope, which is necessary because such wires and cells often appear in unlabeled generate blocks, which now prefix the declarations within 4. Some techlibs required modifications because they relied on the previous invalid scope resolution behavior 5. `expand_genblock` has been simplified, now only expanding the outermost scope, completely deferring the inspection and elaboration of nested scopes; names are now resolved by looking in the innermost scope and stepping outward 6. Loop variables now always become localparams during unrolling, allowing them to be resolved and shadowed like any other identifier 7. Identifiers in synthetic function call scopes are now prefixed and resolved in largely the same manner as other blocks before: `$func$\func_01$tests/simple/scopes.blk.v:60$5$\blk\x` after: `\func_01$func$tests/simple/scopes.v:60$5.blk.x` 8. Support identifiers referencing a local generate scope nested more than 1 level deep, i.e. `B.C.x` while within generate scope `A`, or using a prefix of a current or parent scope, i.e. `B.C.D.x` while in `A.B`, `A.B.C`, or `A.B.C.D` 9. Variables can now be declared within unnamed blocks in SystemVerilog mode Addresses the following issues: 656, 2423, 2493
2021-01-27 12:30:22 -06:00
void expand_genblock(const std::string &prefix);
void label_genblks(std::set<std::string>& existing, int &counter);
2014-12-28 20:11:50 -06:00
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);
2016-08-21 06:23:58 -05:00
bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block);
2014-12-28 20:11:50 -06:00
bool mem2reg_check(pool<AstNode*> &mem2reg_set);
void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
2013-01-05 04:13:26 -06:00
void meminfo(int &mem_width, int &mem_size, int &addr_bits);
bool detect_latch(const std::string &var);
const RTLIL::Module* lookup_cell_module();
2013-01-05 04:13:26 -06:00
// additional functionality for evaluating constant functions
struct varinfo_t {
RTLIL::Const val;
int offset;
bool range_swapped;
bool is_signed;
AstNode *arg = nullptr;
bool explicitly_sized;
};
bool has_const_only_constructs();
bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed);
AstNode *eval_const_function(AstNode *fcall, bool must_succeed);
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);
bool is_recursive_function() const;
std::pair<AstNode*, AstNode*> get_tern_choice();
2013-01-05 04:13:26 -06:00
// 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;
2013-01-05 04:13:26 -06:00
// Generate RTLIL for a bind construct
std::vector<RTLIL::Binding *> genBindings() 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);
2013-01-05 04:13:26 -06:00
// 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, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = NULL);
2013-01-05 04:13:26 -06:00
// 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);
2013-01-05 04:13:26 -06:00
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
2013-12-05 05:53:49 -06:00
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() const;
RTLIL::Const asParaConst() const;
2014-08-21 10:11:51 -05:00
uint64_t asInt(bool is_signed);
bool bits_only_01() const;
bool asBool() const;
2014-06-14 01:51:22 -05:00
// helper functions for real valued const eval
int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
2014-06-14 01:51:22 -05:00
double asReal(bool is_signed);
RTLIL::Const realAsConst(int width);
// helpers for enum
void allocateDefaultEnumValues();
2020-05-08 08:40:49 -05:00
void annotateTypedEnums(AstNode *template_node);
// helpers for locations
std::string loc_string() const;
// Helper for looking up identifiers which are prefixed with the current module name
std::string try_pop_module_prefix() const;
2013-01-05 04:13:26 -06:00
};
// 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);
2013-01-05 04:13:26 -06:00
// parametric modules are supported directly by the AST library
2015-08-14 03:56:05 -05:00
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
2013-01-05 04:13:26 -06:00
struct AstModule : RTLIL::Module {
AstNode *ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire;
2020-06-18 18:34:52 -05:00
~AstModule() override;
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) 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) override;
std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false);
void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
bool reprocess_if_necessary(RTLIL::Design *design) override;
2020-06-18 18:34:52 -05:00
RTLIL::Module *clone() const override;
void loadconfig() const;
2013-01-05 04:13:26 -06:00
};
// 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)
2013-01-05 04:13:26 -06:00
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);
// Helper for setting the src attribute.
void set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast);
// struct helper exposed from simplify for genrtlil
AstNode *make_struct_member_range(AstNode *node, AstNode *member_node);
// generate standard $paramod... derived module name; parameters should be
// in the order they are declared in the instantiated module
std::string derived_module_name(std::string stripped_name, const std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> &parameters);
// used to provide simplify() access to the current design for looking up
// modules, ports, wires, etc.
void set_simplify_design_context(const RTLIL::Design *design);
2013-01-05 04:13:26 -06:00
}
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;
2013-01-05 04:13:26 -06:00
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
2014-12-28 12:24:24 -06:00
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 RTLIL::Module *current_module;
extern bool current_always_clocked;
extern dict<std::string, int> current_memwr_count;
extern dict<std::string, pool<int>> current_memwr_visible;
struct LookaheadRewriter;
2013-01-05 04:13:26 -06:00
struct ProcessGenerator;
// Create and add a new AstModule from new_ast, then use it to replace
// old_module in design, renaming old_module to move it out of the way.
// Return the new module.
//
// If original_ast is not null, it will be used as the AST node for the
// new module. Otherwise, new_ast will be used.
RTLIL::Module *
process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module,
AST::AstNode *new_ast,
AST::AstNode *original_ast = nullptr);
2013-01-05 04:13:26 -06:00
}
YOSYS_NAMESPACE_END
2013-01-05 04:13:26 -06:00
#endif