/*! @file verilog_ast.h @brief Contains Declarations of datastructures and functions which represent and operate on the Verilog Abstract Syntax Tree (AST) */ #include #include #include #include "verilog_ast_common.h" #ifndef VERILOG_AST_H #define VERILOG_AST_H extern int yylineno; //! Forward declare. Defines the core node type for the AST. typedef struct ast_node_t ast_node; /*! @brief Typedef to make it easier to change into a proper structure later. @note The pointer is already included in the type. */ typedef struct ast_identifier_t * ast_identifier; //! Placeholder until this is implemented properly. typedef struct ast_concatenation_t ast_concatenation; //! Expression type over a struct typedef struct ast_expression_t ast_expression; //! Expression type over a struct typedef struct ast_function_call_t ast_function_call; //! An item within a module. Duh. typedef struct ast_module_item_t ast_module_item; //! Stores different Operators. typedef enum ast_operator_e{ OPERATOR_STAR , //!< OPERATOR_PLUS , //!< OPERATOR_MINUS , //!< OPERATOR_ASL , //!< Arithmetic shift left OPERATOR_ASR , //!< Arithmetic shift right OPERATOR_LSL , //!< logical shift left OPERATOR_LSR , //!< logical shift right OPERATOR_DIV , //!< divide OPERATOR_POW , //!< pow OPERATOR_MOD , //!< mod OPERATOR_GTE , //!< greater than or equal to OPERATOR_LTE , //!< OPERATOR_GT , //!< OPERATOR_LT , //!< OPERATOR_L_NEG , //!< OPERATOR_L_AND , //!< OPERATOR_L_OR , //!< OPERATOR_C_EQ , //!< OPERATOR_L_EQ , //!< OPERATOR_C_NEQ , //!< OPERATOR_L_NEQ , //!< OPERATOR_B_NEG , //!< OPERATOR_B_AND , //!< OPERATOR_B_OR , //!< OPERATOR_B_XOR , //!< OPERATOR_B_EQU , //!< OPERATOR_B_NAND , //!< OPERATOR_B_NOR , //!< OPERATOR_TERNARY , //!< OPERATOR_NONE = 0 } ast_operator; typedef char * ast_string ; //! A set of lvalue and corresponding assigned expressions typedef struct ast_assignment_t ast_assignment; //! A single lvalue=expression assignment. typedef struct ast_single_assignment_t ast_single_assignment; //! Generate block (of statements) type. typedef struct ast_generate_block_t ast_generate_block; typedef struct ast_delay3_t ast_delay3; typedef struct ast_delay2_t ast_delay2; typedef struct ast_delay_value_t ast_delay_value ; typedef struct ast_pull_strength_t ast_drive_strength; typedef void * ast_macro_use ; typedef void * ast_minmax_exp ; //! Number data structure. typedef struct ast_number_t ast_number ; typedef struct ast_range_t ast_range ; typedef struct ast_block_item_declaration_t ast_block_item_declaration; typedef void * ast_tf_input_declaration; typedef struct ast_statement_t ast_statement; typedef struct ast_module_declaration_t ast_module_declaration; //! Stores the values of booleans. typedef enum ast_boolean_e { AST_TRUE=1, AST_FALSE=0 } ast_boolean; //! Describes a rising or falling edge, or where none is specified. typedef enum ast_edge_e{ EDGE_POS, //! Positive edge EDGE_NEG, //! Negative edge EDGE_NONE, //! Not edge triggered EDGE_ANY //! Positive or negative edge. } ast_edge; //! Describes the direction of a port typedef enum ast_port_direction_e{ PORT_INPUT, //!< Input port. PORT_OUTPUT, //!< Output port. PORT_INOUT, //!< Bi-directional port. PORT_NONE, //!< Used for when we don't know at declaration time. } ast_port_direction; /*! @defgroup ast-node-meta Meta Data @{ @ingroup ast-construction @brief Objects used to represent meta data about a particular construct. */ //! Refers to a source code file line number. typedef int ast_line; //! Refers to a source code file name. typedef char * ast_file; /*! @brief Stores "meta" information and other tagging stuff about nodes. */ typedef struct ast_metadata_t{ ast_line line; //!< The line number the construct came from. ast_file file; //!< The file the construct came from. } ast_metadata; /*! @} */ //-------------- Numbers --------------------------------------- /*! @defgroup ast-node-numbers Numbers @{ @ingroup ast-construction @brief Objects used to represent individual numbers. */ //! Base value of a number representation. typedef enum ast_number_base_e{ BASE_BINARY, BASE_OCTAL, BASE_DECIMAL, BASE_HEX } ast_number_base; //! How is the number represented? typedef enum ast_number_representation_e{ REP_BITS, //!< For numbers specified per digit. REP_INTEGER, //!< For "Integer" typed numbers" REP_FLOAT //!< For "real" typed numbers. } ast_number_representation; /*! @brief Stores the base, value and width (in bits) of a number. */ struct ast_number_t{ ast_metadata meta; //!< Node metadata. unsigned int width; //!< Width of the number in bits. ast_number_base base; //!< Hex, octal, binary, decimal. ast_number_representation representation; //!< How is it expressed? union{ char * as_bits; float as_float; int as_int; }; }; /*! @brief Creates a new number representation object. */ ast_number * ast_new_number( ast_number_base base, //!< What is the base of the number. ast_number_representation representation, //!< How to interepret digits. char * digits //!< The string token representing the number. ); /*! @brief A utility function for converting an ast number into a string. @param [in] n - The number to turn into a string. */ char * ast_number_tostring( ast_number * n ); /*! @} */ //-------------- attributes ------------------------------------ /*! @defgroup ast-node-attributes Attributes @{ @ingroup ast-construction @brief Describes attributes passed to modules, functions and expression assignments. */ /*! @brief Node data describing an attribute. */ typedef struct ast_node_attributes_t ast_node_attributes; struct ast_node_attributes_t { ast_metadata meta; //!< Node metadata. ast_identifier attr_name; //!< Name of the attribute ast_expression * attr_value; //!< Value of the attribute. ast_node_attributes * next; //!< Next one in a linked list. }; /*! @brief Creates and returns as a pointer a new attribute descriptor. @param [in] name - The name of the parameter/attribute. @param [in] value - The value the attribute should take. */ ast_node_attributes * ast_new_attributes( ast_identifier name, ast_expression * value ); /*! @brief Creates and returns a new attribute node with the specified value and name. @param [inout] parent - Pointer to the node which represents the list of attribute name,value pairs. @param [in] toadd - The new attribute to add. */ void ast_append_attribute(ast_node_attributes * parent, ast_node_attributes * toadd); /*! @} */ // -------------------------------- Concatenations --------------------------- /*! @defgroup ast-node-concatenations Concatenations @{ @ingroup ast-construction @brief Concatenations of expressions, l-values, variables, nets and module paths. */ //! Describes the type of concatenation being dealt with. typedef enum ast_concatenation_type_e { CONCATENATION_EXPRESSION, //!< A set of expressions concatenated CONCATENATION_CONSTANT_EXPRESSION, //!< Constant expressions CONCATENATION_NET, //!< Net name concatenation (lvalue) CONCATENATION_VARIABLE, //!< Variable name concatenation (lvalue) CONCATENATION_MODULE_PATH //!< Module path concatenation. } ast_concatenation_type; //! Fully describes a concatenation in terms of type and data. struct ast_concatenation_t{ ast_metadata meta; //!< Node metadata. ast_concatenation_type type; //!< The type of concatenation ast_expression * repeat;//!< The number of repetitions. Normally 1. ast_list * items; //!< sequence of items. }; /*! @brief Creates a new AST concatenation element with the supplied type and initial starting value. @param [in] repeat - Used for replications or multiple_concatenation @param [in] type - What sort of values are being concatenated? @param [in] first_value - The first element of the concatentation. @details Depending on the type supplied, the type of first_value should be: - CONCATENATION_EXPRESSION : ast_expression - CONCATENATION_CONSTANT_EXPRESSION : ast_expression - CONCATENATION_NET : ast_identifier - CONCATENATION_VARIABLE : ast_identifer - CONCATENATION_MODULE_PATH : ast_identifier */ ast_concatenation * ast_new_concatenation(ast_concatenation_type type, ast_expression * repeat, void * first_value); /*! @brief Creates and returns a new empty concatenation of the specified type. @param [in] type - What sort of values are being concatenated? */ ast_concatenation * ast_new_empty_concatenation(ast_concatenation_type type); /*! @brief Adds a new data element on to the *front* of a concatenation. @param [inout] element - THe concantenation being extended, @param [in] repeat - Is the concatenation repeated? @param [in] data - The item to add to the concatenation sequence. */ void ast_extend_concatenation(ast_concatenation * element, ast_expression * repeat, void * data); /*! @} */ // -------------------------------- L Value ------------------------ /*! @defgroup ast-node-lvalues L-Values @{ @ingroup ast-construction @brief Represents the class of values which represent the left hand term of an assignment. */ /*! @brief Identifies the kind of LValue the @ref ast_lvalue structure holds. */ typedef enum ast_lvalue_type_e { SPECPARAM_ID, PARAM_ID, NET_IDENTIFIER, //!< Identifies a wire/reg VAR_IDENTIFIER, //!< Identifies a variable GENVAR_IDENTIFIER, //!< Generateor variable. NET_CONCATENATION, //!< Concatenation of net identifiers VAR_CONCATENATION //!< Concatenation of variable identifiers. } ast_lvalue_type; /*! @brief Storage for the data describing an assignment L Value. */ typedef union ast_lvalue_data_u { ast_identifier identifier; //!< Identifier value. ast_concatenation * concatenation; //!< Concatenation list. } ast_lvalue_data ; /*! @brief Stores and describes an expression l value. */ typedef struct ast_lvalue_t { ast_metadata meta; //!< Node metadata. ast_lvalue_data data; //!< The identifier or concattenation being assigned. ast_lvalue_type type; //!< The type of the L Value assignment. } ast_lvalue; /*! @brief Creates and returns a new @ref ast_lvalue pointer, with the data type being a single identifier of either @ref NET_IDENTIFIER or @ref VAR_IDENTIFIER. */ ast_lvalue * ast_new_lvalue_id(ast_lvalue_type type, ast_identifier id); /*! @brief Creates and returns a new @ref ast_lvalue pointer, with the data type being a concatenation holder of either @ref NET_CONCATENATION or @ref VAR_CONCATENATION. */ ast_lvalue * ast_new_lvalue_concat(ast_lvalue_type type, ast_concatenation*id); /*! @} */ // -------------------------------- Function Calls --------------------------- /*! @defgroup ast-node-function-calls Function Calls @{ @ingroup ast-construction @brief Represents a call to a system or user function. Note this is destinct from a function declaration. */ /*! @brief describes a single call to a function, constant function, or system fucntion. */ struct ast_function_call_t { ast_metadata meta; //!< Node metadata. ast_boolean constant; //!< Constant function call? ast_boolean system; //!< System function call? ast_identifier function; //!< Function identifier ast_list * arguments; //!< Linked list of arguments. ast_node_attributes * attributes; }; /*! @brief Creates and returns a new node representing a function call. @param [in] arguments - list of elements of type ast_expression representing the various parameters to the function. If the function has no arguments, then it is an empty list, not NULL. @param [in] id - Function identifier / name @param [in] constant - Does this function return a constant value? @param [in] system - Is this a system function? @param [in] attr - Attributes for vendor specific tool features. */ ast_function_call * ast_new_function_call(ast_identifier id, ast_boolean constant, ast_boolean system, ast_node_attributes * attr, ast_list * arguments); /*! @} */ // -------------------------------- Primaries ---------------------- /*! @defgroup ast-node-expression-primaries Expression Primaries @{ @ingroup ast-node-expressions @brief Expresses primary terms of expressions. These can be sub-expressions, numbers, identifiers etc. */ /*! @brief Describes the kind of expression primary being represented, and hence the sort of expression we are dealing with. */ typedef enum ast_primary_type_e { CONSTANT_PRIMARY, PRIMARY, MODULE_PATH_PRIMARY } ast_primary_type; //! The kind of production the expression primary holds. typedef enum ast_primary_value_type_e { PRIMARY_NUMBER, PRIMARY_IDENTIFIER, PRIMARY_CONCATENATION, PRIMARY_FUNCTION_CALL, PRIMARY_MINMAX_EXP, PRIMARY_MACRO_USAGE } ast_primary_value_type; //! The expression primary can produce several different sub-expressions: typedef union ast_primary_value_e { ast_number * number; //!< A single constant number ast_identifier identifier; //!< Net or variable identifier. ast_concatenation * concatenation; //!< Concatenation of expressions. ast_function_call * function_call; //!< Call to a function. ast_expression * minmax; ast_macro_use macro; //!< A MACRO expansion. char * string; } ast_primary_value; /*! @brief Stores the type and value of an AST primary expression. @details The following AST_PRIMARY_VALUE_TYPE values map to the following ast_primary_value_members: - PRIMARY_NUMBER : use value.number - PRIMARY_IDENTIFIER : use value.identifier - PRIMARY_CONCATENATION : use value.concatenation - PRIMARY_FUNCTION_CALL : use value.function_call - PRIMARY_MINMAX_EXP : use value.minmax - PRIMARY_MACRO_USAGE : use value.macro */ typedef struct ast_primary_t { ast_metadata meta; //!< Node metadata. ast_primary_type primary_type; //!< @see ast_primary_type ast_primary_value_type value_type; //!< @see ast_primary_value_type ast_primary_value value; //!< @see ast_primary_value } ast_primary; /*! @brief A utility function for converting an ast expression primaries back into a string representation. @param [in] p - The expression primary to turn into a string. */ char * ast_primary_tostring( ast_primary * p ); /*! @brief Creates a new ast primary which is part of a constant expression tree with the supplied type and value. @param [in] type - Self explanatory */ ast_primary * ast_new_constant_primary(ast_primary_value_type type); /*! @brief Creates a new AST primary wrapper around a function call. @param [in] call - The AST node representing a function call. */ ast_primary * ast_new_primary_function_call(ast_function_call * call); /*! @brief Creates a new ast primary which is part of an expression tree with the supplied type and value. @param [in] type - Self explanatory */ ast_primary * ast_new_primary(ast_primary_value_type type); /*! @brief Creates a new ast primary which is part of a constant expression tree with the supplied type and value. @param [in] type - Self explanatory */ ast_primary * ast_new_module_path_primary(ast_primary_value_type type); /*! @} */ // -------------------------------- Expressions -------------------- /*! @defgroup ast-node-expressions Expressions @{ @ingroup ast-construction @brief Super-group for data-structures representing the kinds of expressions that Verilog has. */ //! Describes the kind of expression a node contains. typedef enum ast_expression_type_e { PRIMARY_EXPRESSION, //!< A straight value UNARY_EXPRESSION, //!< A unary op: "~bits" for example. BINARY_EXPRESSION, //!< The "normal" expression RANGE_EXPRESSION_UP_DOWN, //!< Bit range expression RANGE_EXPRESSION_INDEX, //!< Bit index expression MINTYPMAX_EXPRESSION, //!< Minimum typical maximum CONDITIONAL_EXPRESSION, //!< Conditional expression MODULE_PATH_PRIMARY_EXPRESSION, MODULE_PATH_BINARY_EXPRESSION, MODULE_PATH_UNARY_EXPRESSION, MODULE_PATH_CONDITIONAL_EXPRESSION, MODULE_PATH_MINTYPMAX_EXPRESSION, STRING_EXPRESSION //!< Just a normal string. No operations. } ast_expression_type; //! Returns the string representation of an operator; char * ast_operator_tostring(ast_operator op); /*! @brief Storage type for an entire expression / subexpression tree. @details Each expression node has left and right children (unless it is a leaf) and an operation. The idea being that if the children are primaries, then we extract their value, perform the operation described in this node, and return up the expression tree, or recurse into a child expression as appropriate. @todo This part of the tree (and sub parts) is currently quite messy. When I come to actually using this for something practicle, I may end up re-writing it. That will be post the first "release" though. */ struct ast_expression_t { ast_metadata meta; //!< Node metadata. ast_expression_type type; //!< What sort of expression is this? ast_node_attributes * attributes; //!< Additional expression attributes. ast_expression * left; //!< LHS of operation ast_expression * right; //!< RHS of operation ast_expression * aux; //!< Optional auxiliary/predicate. ast_primary * primary; //!< Valid IFF type == PRIMARY_EXPRESSION. ast_operator operation; //!< What are we doing? ast_boolean constant; //!< True iff constant_expression. ast_string string; //!< The string constant. Valid IFF type == STRING_EXPRESSION. }; /*! @brief A utility function for converting an ast expression tree back into a string representation. @param [in] exp - The expression to turn into a string. */ char * ast_expression_tostring( ast_expression * exp ); /*! @brief Creates and returns a new expression primary. @details This is simply an expression instance wrapped around a primary instance for the purposes of mirroring the expression tree gramamr. Whether or not the expression is constant is denoted by the type member of the passed primary. @param [in] p - The primary to insert into the expression. */ ast_expression * ast_new_expression_primary(ast_primary * p); /*! @brief Creates a new binary infix expression with the supplied operands. @param [in] left - LHS of the infix operation. @param [in] right - RHS of the infix operation. @param [in] operation - What do we do?! @param [in] attr - Attributes applied to the expression. @param [in] constant - Is this a constant expression we can simplify? */ ast_expression * ast_new_binary_expression(ast_expression * left, ast_expression * right, ast_operator operation, ast_node_attributes * attr, ast_boolean constant); /*! @brief Creates a new unary expression with the supplied operation. @param [in] operand - The thing to operate on. @param [in] operation - What do we do?! @param [in] attr - Expression attributes. @param [in] constant - Is this a constant expression we can simplify? */ ast_expression * ast_new_unary_expression(ast_primary * operand, ast_operator operation, ast_node_attributes * attr, ast_boolean constant); /*! @brief Creates a new range expression with the supplied operands. @param [in] left - The Upper range of the expression @param [in] right - The lower range of the expression. @details For example, when specifying a simple bus in verilog: @code wire [31:0] bus_data; @endcode Then the `31` would go into left, and the `0` into the right. */ ast_expression * ast_new_range_expression(ast_expression * left, ast_expression * right); /*! @brief Creates a new range index expression with the supplied operands. @param [in] left - The single expression index into an array. @details Used to represent code like... @code wire [32:0] adder_result; assign overflow = adder_result[32]; @endcode Here, accessing the 32nd bit of `adder_result` is an index expression. */ ast_expression * ast_new_index_expression(ast_expression * left); /*! @brief Creates a new string expression. @param [in] string - The string. Duh. */ ast_expression * ast_new_string_expression(ast_string string); /*! @brief Creates a new conditional expression node. @param [in] condition - Decides which result expression is presented. @param [in] if_true - executed if condition == true (!0) @param [in] if_false - executed if condition == false (0). @param [in] attr - Attributes @note The condition is stored in the aux member, if_true in left, and if_false on the right. @details Can be used to represent ternary operations: @code assign stall = mem_error || mem_stall ? 1'b0 : global_stall; @endcode */ ast_expression * ast_new_conditional_expression(ast_expression * condition, ast_expression * if_true, ast_expression * if_false, ast_node_attributes * attr); /*! @brief Creates a new (min,typical,maximum) expression. @details If the mintypmax expression only specifies a typical value, then the min and max arguments should be NULL, and only typ set. @param [in] min - Minimum value in the distribution. @param [in] typ - Typical / average. @param [in] max - Maximum value in the distribution. */ ast_expression * ast_new_mintypmax_expression(ast_expression * min, ast_expression * typ, ast_expression * max); /*! @} */ // -------------------------------- Specify Blocks --------------------------- /*! @defgroup ast-node-path-declaration Path Declarations @{ @ingroup ast-construction @brief Describes construction of path declarations and delay specifiers. */ //! Describes the type of path being declared. typedef enum ast_path_declaration_type_e{ SIMPLE_PARALLEL_PATH, SIMPLE_FULL_PATH, EDGE_SENSITIVE_PARALLEL_PATH, EDGE_SENSITIVE_FULL_PATH, STATE_DEPENDENT_PARALLEL_PATH, STATE_DEPENDENT_FULL_PATH, STATE_DEPENDENT_EDGE_PARALLEL_PATH, STATE_DEPENDENT_EDGE_FULL_PATH, } ast_path_declaration_type; //! Describes the declaration of a path. typedef struct ast_simple_parallel_path_declaration_t{ ast_metadata meta; //!< Node metadata. ast_identifier input_terminal; ast_operator polarity; ast_identifier output_terminal; ast_list * delay_value; } ast_simple_parallel_path_declaration; //! Describes the declaration of a path. typedef struct ast_simple_full_path_declaration_t{ ast_metadata meta; //!< Node metadata. ast_list * input_terminals; ast_operator polarity; ast_list * output_terminals; ast_list * delay_value; } ast_simple_full_path_declaration; //! Describes a single edge sensitive path declaration typedef struct ast_edge_sensitive_parallel_path_declaration_t { ast_metadata meta; //!< Node metadata. ast_edge edge; //!< edge_identifier ast_identifier input_terminal; //!< specify_input_terminal_descriptor ast_operator polarity; //!< polarity_operator ast_identifier output_terminal; //!< specify_output_terminal_descriptor ast_expression * data_source; //!< data_source_expression ast_list * delay_value; //!< path_delay_value } ast_edge_sensitive_parallel_path_declaration; //! Describes a parallel edge sensitive path declaration typedef struct ast_edge_sensitive_full_path_declaration_t { ast_metadata meta; //!< Node metadata. ast_edge edge; //!< edge_identifier ast_list * input_terminal; //!< list_of_path_inputs ast_operator polarity; //!< polarity_operator ast_list * output_terminal; //!< list_of_path_outputs ast_expression * data_source; //!< data_source_expression ast_list * delay_value; //!< path_delay_value } ast_edge_sensitive_full_path_declaration; //! Struct which holds the type and data of a path declaration. typedef struct ast_path_declaration_t{ ast_metadata meta; //!< Node metadata. ast_path_declaration_type type; ast_expression * state_expression; //!< Used iff type == state_dependent_* union { ast_simple_parallel_path_declaration * parallel; ast_simple_full_path_declaration * full; ast_edge_sensitive_parallel_path_declaration * es_parallel; ast_edge_sensitive_full_path_declaration * es_full; }; } ast_path_declaration; /*! @brief Creates and returns a new path declaration type. Expects that the data be filled in manually; */ ast_path_declaration * ast_new_path_declaration(ast_path_declaration_type type); /*! @brief Creates and returns a pointer to a new simple parallel path declaration. */ ast_simple_parallel_path_declaration * ast_new_simple_parallel_path_declaration ( ast_identifier input_terminal, ast_operator polarity, ast_identifier output_terminal, ast_list * delay_value ); /*! @brief Creates and returns a pointer to a new simple full path declaration. */ ast_simple_full_path_declaration * ast_new_simple_full_path_declaration ( ast_list * input_terminals, ast_operator polarity, ast_list * output_terminals, ast_list * delay_value ); /*! @brief Describes a single edge sensitive path declaration */ ast_edge_sensitive_parallel_path_declaration * ast_new_edge_sensitive_parallel_path_declaration( ast_edge edge, //!< edge_identifier ast_identifier input_terminal, //!< specify_input_terminal_descriptor ast_operator polarity, //!< polarity_operator ast_identifier output_terminal, //!< specify_output_terminal_descriptor ast_expression * data_source, //!< data_source_expression ast_list * delay_value //!< path_delay_value ); /*! @brief Describes a parallel edge sensitive path declaration */ ast_edge_sensitive_full_path_declaration * ast_new_edge_sensitive_full_path_declaration( ast_edge edge, //!< edge_identifier ast_list * input_terminal, //!< list_of_path_inputs ast_operator polarity, //!< polarity_operator ast_list * output_terminal, //!< list_of_path_outputs ast_expression * data_source, //!< data_source_expression ast_list * delay_value //!< path_delay_value ); /*! @} */ // -------------------------------- Task Enable Statements ------------------- /*! @defgroup ast-node-task-enable-statements Task Enable Statements @{ @ingroup ast-node-procedural @brief Describes task enable statements. */ //! Fully describes a task enable statement. typedef struct ast_task_enable_statement_t{ ast_metadata meta; //!< Node metadata. ast_list * expressions; //!< Arguments to the task ast_identifier identifier; //!< Task identifier. ast_boolean is_system; //!< Is this a system task? } ast_task_enable_statement; /*! @brief creates and returns a pointer to a new task-enable statement. */ ast_task_enable_statement * ast_new_task_enable_statement( ast_list * expressions, ast_identifier identifier, ast_boolean is_system ); /*! @} */ // -------------------------------- Loop Statements -------------------------- /*! @defgroup ast-node-loop-statements Loop Statements @{ @ingroup ast-node-procedural @brief Describes for and while loop representation. */ //! Describes the different syntactic methods of looping. typedef enum ast_loop_type_e{ LOOP_FOREVER, LOOP_REPEAT, LOOP_WHILE, LOOP_FOR, LOOP_GENERATE } ast_loop_type; //! Fully describes a single loop statement. typedef struct ast_loop_statement_t{ ast_metadata meta; //!< Node metadata. ast_loop_type type; //!< The type of loop union{ ast_statement * inner_statement; //!< Loop body. ast_list * generate_items; //!< IFF type == LOOP_GENERATE; }; ast_expression * condition; //!< Condition on which the loop runs. ast_single_assignment * initial; //!< Initial condition for for loops. ast_single_assignment * modify; //!< Modification assignment for for loop. } ast_loop_statement; /*! @brief Creates and returns a new forever loop statement. @param inner_statement - Pointer to the inner body of statements which make upt the loop body. */ ast_loop_statement * ast_new_forever_loop_statement( ast_statement * inner_statement ); /*! @brief Creates and returns a new for loop statement. @param inner_statements - Pointer to the inner body of statements which make up the loop body. @param initial_condition - Assignement which sets up the initial condition of the iterator. @param modify_assignment - How the iterator variable changes with each loop iteration. @param continue_condition - Expression which governs whether the loop should continue or break. */ ast_loop_statement * ast_new_for_loop_statement( ast_statement * inner_statements, ast_single_assignment * initial_condition, ast_single_assignment * modify_assignment, ast_expression * continue_condition ); /*! @brief Creates and returns a new generate loop statement. @param inner_statements - Pointer to the inner body of statements which make up the loop body. @param initial_condition - Assignement which sets up the initial condition of the iterator. @param modify_assignment - How the iterator variable changes with each loop iteration. @param continue_condition - Expression which governs whether the loop should continue or break. */ ast_loop_statement * ast_new_generate_loop_statement( ast_list * inner_statements, ast_single_assignment * initial_condition, ast_single_assignment * modify_assignment, ast_expression * continue_condition ); /*! @brief Creates and returns a while loop statement. @param inner_statement - Pointer to the inner body of statements which make upt the loop body. @param continue_condition - Expression which governs whether the loop should continue or break. */ ast_loop_statement * ast_new_while_loop_statement( ast_statement * inner_statement, ast_expression * continue_condition ); /*! @brief Creates and returns a repeat loop statement. @param inner_statement - Pointer to the inner body of statements which make upt the loop body. @param continue_condition - Expression which governs whether the loop should continue or break. */ ast_loop_statement * ast_new_repeat_loop_statement( ast_statement * inner_statement, ast_expression * continue_condition ); /*! @} */ // -------------------------------- Case Statements -------------------------- /*! @defgroup ast-node-case-statements Case Statements @{ @ingroup ast-node-procedural @brief */ //! Records the three different types of case statement Verilog has. typedef enum ast_case_statement_type_e{ CASE, CASEX, CASEZ } ast_case_statement_type; //! Describes a single exeuctable item in a case statement. typedef struct ast_case_item_t{ ast_metadata meta; //!< Node metadata. ast_list * conditions; //!< A list of condtions, one must be met. ast_statement * body; //!< What to execute if the condition is met. ast_boolean is_default; //!< This is the default item. } ast_case_item; //! Describes the top level of a case statement in terms of its items. typedef struct ast_case_statement_t{ ast_metadata meta; //!< Node metadata. ast_expression * expression; //!< The thing to be evaluated. ast_list * cases; //!< Statements, conditionally run. ast_statement * default_item; //!< Default IFF no item matches. ast_case_statement_type type; //!< CASE, CASEX or CASEZ. ast_boolean is_function; //!< Is this a function_case_statement? } ast_case_statement; /*! @brief Create and return a new item in a cast statement. @param conditions - The conditions on which the item is executed. @param body - Executes when any of the conditions are met. */ ast_case_item * ast_new_case_item(ast_list * conditions, ast_statement * body); /*! @brief Creates and returns a new case statement. @param expression - The expression evaluated to select a case. @param cases - list of possible cases. */ ast_case_statement * ast_new_case_statement(ast_expression * expression, ast_list * cases, ast_case_statement_type type); /*! @} */ // -------------------------------- IF Else Statements ----------------------- /*! @defgroup ast-node-if-else If Else Statements @{ @ingroup ast-node-procedural @brief */ //! Describes a single if-then-do statement. typedef struct ast_conditional_statement_t { ast_metadata meta; //!< Node metadata. ast_statement * statement; //!< What should be executed. ast_expression * condition; //!< Execute iff true. } ast_conditional_statement; //! Describes a complete set of if-elseif-else statements typedef struct ast_if_else_t{ ast_metadata meta; //!< Node metadata. ast_list * conditional_statements; //!< Ordered list of if-elseifs ast_statement * else_condition; //!< Execute iff no conditonals are met. } ast_if_else; /*! @brief Creates and returns a new conditional statement. @param statement - what to run if the condition holds true. @param condtion - the condition on which statement is run. */ ast_conditional_statement * ast_new_conditional_statement( ast_statement * statement, ast_expression * condition ); /*! @brief Creates a new if-then-else-then statement. @param if_condition - the conditional statement. @param else_condition - What to do if no conditional statements are executed. This can be NULL. @details This node also supports "if then elseif then else then" statements, and uses the ast_extend_if_else function to append a new ast_conditional_statement to the end of a list of if-else conditions. Priority of exectuion is given to items added first. */ ast_if_else * ast_new_if_else( ast_conditional_statement * if_condition, ast_statement * else_condition ); /*! @brief Adds an additional conditional (ha..) to an existing if-else statement. @param conditional_statements - the existing if-else tree. @param new_statement - The new statement to add at the end of the existing if-then conditions, but before any else_condtion. */ void ast_extend_if_else( ast_if_else * conditional_statements, ast_list * new_statement ); /*! @} */ // -------------------------------- Timing Control Statements ---------------- /*! @defgroup ast-node-timing-control Timing Control Statements @{ @ingroup ast-construction @brief */ //! Describes a single wait statement. typedef struct ast_wait_statement_t{ ast_metadata meta; //!< Node metadata. ast_expression * expression; //!< How long to wait for. ast_statement * statement; //!< What to execute after waiting. } ast_wait_statement; typedef enum ast_event_expression_type_e{ EVENT_EXPRESSION, //!< Goes to a single expression EVENT_POSEDGE, //!< on posedge EVENT_NEGEDGE, //!< on negedge EVENT_SEQUENCE //!< Covers event_expression COMMA event_expression } ast_event_expression_type; //! Describes a single event expression typedef struct ast_event_expression_t ast_event_expression; struct ast_event_expression_t { ast_event_expression_type type; union{ ast_expression * expression; //!< Single event expressions. ast_list * sequence; //!< Used for CSV lists of events }; }; //! Whether an event control struct contains a list of triggers, no triggers // or triggers on anything. typedef enum ast_event_control_type_e{ EVENT_CTRL_NONE, EVENT_CTRL_ANY, EVENT_CTRL_TRIGGERS } ast_event_control_type; //! Describes the type of event triggers. typedef struct ast_event_control_t{ ast_metadata meta; //!< Node metadata. ast_event_control_type type; ast_event_expression * expression; } ast_event_control; //! What sort of procedural timing control statement is this? typedef enum ast_timing_control_statement_type_e{ TIMING_CTRL_DELAY_CONTROL, TIMING_CTRL_EVENT_CONTROL, TIMING_CTRL_EVENT_CONTROL_REPEAT } ast_timing_control_statement_type; //! Denotes whether a delay control expression is a single value or a range typedef enum ast_delay_ctrl_type_e{ DELAY_CTRL_VALUE, DELAY_CTRL_MINTYPMAX } ast_delay_ctrl_type; //! Describes a single delay control statement typedef struct ast_delay_ctrl_t{ ast_metadata meta; //!< Node metadata. ast_delay_ctrl_type type; union{ ast_delay_value * value; ast_expression * mintypmax; }; } ast_delay_ctrl; //! Describes a single procedural timing control statement. typedef struct ast_timing_control_statement_t{ ast_metadata meta; //!< Node metadata. ast_timing_control_statement_type type; union{ ast_delay_ctrl * delay; ast_event_control * event_ctrl; }; ast_expression * repeat; //!< NULL unless part of repeat statement. ast_statement * statement; //!< What to execute after the control. } ast_timing_control_statement; /*! @brief Creates and returns a new wait statement. */ ast_wait_statement * ast_new_wait_statement( ast_expression * wait_for, ast_statement * statement ); /*! @brief Creates a new event expression node @param trigger_edge - the edge on which the trigger is activated. @param expression - the expression to monitor the waveforms of. */ ast_event_expression * ast_new_event_expression( ast_edge trigger_edge, ast_expression * expression ); /*! @brief Creates a new event expression node, which is itself a sequence of sub-expressions. */ ast_event_expression * ast_new_event_expression_sequence( ast_event_expression * left, ast_event_expression * right ); /*! @brief Creates and returns a new event control specifier. */ ast_event_control * ast_new_event_control( ast_event_control_type type, ast_event_expression * expression ); /*! @brief creates and returns a new delay control statement. */ ast_delay_ctrl * ast_new_delay_ctrl_value(ast_delay_value * value); /*! @brief creates and returns a new delay control statement. */ ast_delay_ctrl * ast_new_delay_ctrl_mintypmax( ast_expression * mintypmax ); /*! @brief Creates and returns a new timing control statement node. */ ast_timing_control_statement * ast_new_timing_control_statement_delay( ast_timing_control_statement_type type, ast_statement * statement, ast_delay_ctrl * delay_ctrl ); /*! @brief Creates and returns a new timing control statement node. */ ast_timing_control_statement * ast_new_timing_control_statement_event( ast_timing_control_statement_type type, ast_expression * repeat, ast_statement * statement, ast_event_control * event_ctrl ); /*! @} */ // -------------------------------- Fork Join Sequential --------------------- /*! @defgroup ast-node-fork-join Fork Join and Sequential Blocks @{ @ingroup ast-node-module-items @brief Fork join and sequential stamement blocks. */ //! Contains the identifier from a disable statement. typedef struct ast_disable_statement_t{ ast_metadata meta; //!< Node metadata. ast_identifier id; } ast_disable_statement; //! Creates and returns a pointer to a new disable statement. ast_disable_statement * ast_new_disable_statement(ast_identifier id); //! Describes the type of a block of statements. typedef enum ast_block_type_e{ BLOCK_SEQUENTIAL, BLOCK_SEQUENTIAL_INITIAL, BLOCK_SEQUENTIAL_ALWAYS, BLOCK_FUNCTION_SEQUENTIAL, BLOCK_PARALLEL, } ast_block_type; /*! @brief Fully describes a single block of statements. @details this is used to represent begin...end constructs, always, initial blocks, and collections of statements in the body of a function or task. */ typedef struct ast_statement_block_t{ ast_metadata meta; //!< Node metadata. ast_block_type type; ast_identifier block_identifier; ast_list * declarations; ast_list * statements; ast_timing_control_statement * trigger; //1 range selector ID_HAS_INDEX, //!< Has an index selector ID_HAS_NONE //!< Has neither a range or index selector. } ast_id_range_or_index; /*! @brief Structure containing all information on an identifier. */ struct ast_identifier_t{ ast_metadata meta; //!< Node metadata. ast_identifier_type type; //!< What construct does it identify? char * identifier; //!< The identifier value. unsigned int from_line; //!< The line number of the file. ast_boolean is_system; //!< Is this a system identifier? ast_identifier next; //!< Represents a hierarchical id. ast_id_range_or_index range_or_idx; //!< Is it indexed or ranged? union{ ast_list * ranges; //!< For multi-dimensional arrays. ast_range * range; //!< Iff range_or_idx == ID_HAS_RANGE ast_expression * index; //!< Iff range_or_idx == ID_HAS_INDEX }; }; /*! @brief Simply returns the fully qualified representation of an identifier as a string. @details Where the identifier is "simple" or a system id, then the identifier will just be returned as a character array. Where it is a hierarchical idenifier, then a dot separated string of all identifiers in the hierarchy will be returned. @param [in] id - The identifier object to return a string representation of. @returns A copy of the identifiers full name, as a null terminated character array. */ char * ast_identifier_tostring(ast_identifier id); /*! @brief Acts like strcmp but works on ast identifiers. */ int ast_identifier_cmp( ast_identifier a, ast_identifier b ); /*! @brief Creates and returns a new node representing an identifier. @details By default, the returned identifier has the ID_UNKNOWN type, and this is set later when the parser winds back up and knows which rules to follow. Also, the is_system member is set to false. If you want a new system idenifier instance, use the @ref ast_new_system_identifier function. */ ast_identifier ast_new_identifier( char * identifier, //!< String text of the identifier. unsigned int from_line //!< THe line the idenifier came from. ); /*! @brief Creates and returns a new node representing an identifier. @details By default, the returned identifier has the ID_SYSTEM_* type, */ ast_identifier ast_new_system_identifier( char * identifier, //!< String text of the identifier. unsigned int from_line //!< THe line the idenifier came from. ); /*! @brief Used to construct linked lists of hierarchical identifiers. @details The child node is linked to the next field of the parent, and the parent field returned. @param [in] child - The child to add to the hierarchy. @param [inout] parent - The parent identifier. */ ast_identifier ast_append_identifier( ast_identifier parent, ast_identifier child ); /*! @brief Used to set the range field of an identifier. @param [inout] id - The identifier to set the range for. @param [in] range - The range the identifier refers to. @post Also sets the range_or_idx member to ID_HAS_RANGE */ void ast_identifier_set_range( ast_identifier id, ast_range * range ); /*! @brief Used to set the index field of an identifier. @param [inout] id - The identifier to set the index for. @param [in] index - The index the identifier refers to. @post Also sets the range_or_idx member to ID_HAS_INDEX */ void ast_identifier_set_index( ast_identifier id, ast_expression * index ); /*! @} */ // -------------------------------- Configuration Source --------------------- /*! @defgroup ast-node-configuration-source Configuration Source @{ @ingroup ast-construction @brief Describes configuration constructs. */ //! Fully describes a config rule statemnet. See Annex 1.2 typedef struct ast_config_rule_statement_t{ ast_metadata meta; //!< Node metadata. ast_boolean is_default; ast_boolean multiple_clauses; //