diff --git a/parse.y b/parse.y index cc1e8118d..298e824b6 100644 --- a/parse.y +++ b/parse.y @@ -171,6 +171,21 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) return tmp; } +static named_number_t* make_named_number(perm_string name) +{ + named_number_t*res = new named_number_t; + res->name = name; + return res; +} + +static named_number_t* make_named_number(perm_string name, const verinum&val) +{ + named_number_t*res = new named_number_t; + res->name = name; + res->parm = val; + return res; +} + %} %union { @@ -206,6 +221,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) LexicalScope::range_t* value_range; vector*mports; + named_number_t* named_number; + list* named_numbers; + named_pexpr_t*named_pexpr; svector*named_pexprs; struct parmvalue_t*parmvalue; @@ -230,6 +248,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) PTaskFuncArg function_type; net_decl_assign_t*net_decl_assign; + enum_type_t*enum_type; verinum* number; @@ -357,6 +376,10 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %type parameter_value_ranges_opt %type value_range_expression +%type enum_name +%type enum_name_list +%type enum_data_type + %type task_item task_item_list task_item_list_opt %type task_port_item task_port_decl task_port_decl_list %type function_item function_item_list @@ -549,6 +572,13 @@ block_item_decl if ($1) delete $1; } + /* Enum data types are possible here. */ + + | attribute_list_opt enum_data_type register_variable_list ';' + { pform_set_enum(@2, $2, $3); + if ($1) delete $1; + } + /* real declarations are fairly simple as there is no range of signed flag in the declaration. Create the real as a NetNet::REG with real value. Note that real and realtime are interchangeable @@ -611,6 +641,67 @@ block_item_decls_opt | ; + /* The structure for an enumeration data type is the keyword "enum", + followed by the enumeration values in curly braces. Also allow + for an optional base type. The default base type is "int", but it + can be any of the integral or vector types. */ + +enum_data_type + : K_enum '{' enum_name_list '}' + { enum_type_t*enum_type = new enum_type_t; + enum_type->names .reset($3); + enum_type->base_type = IVL_VT_BOOL; + enum_type->signed_flag = true; + enum_type->range.reset( make_range_from_width(32) ); + $$ = enum_type; + } + | K_enum atom2_type signed_unsigned_opt '{' enum_name_list '}' + { enum_type_t*enum_type = new enum_type_t; + enum_type->names .reset($5); + enum_type->base_type = IVL_VT_BOOL; + enum_type->signed_flag = $3; + enum_type->range.reset( make_range_from_width($2) ); + $$ = enum_type; + } + | K_enum K_integer signed_unsigned_opt '{' enum_name_list '}' + { enum_type_t*enum_type = new enum_type_t; + enum_type->names .reset($5); + enum_type->base_type = IVL_VT_LOGIC; + enum_type->signed_flag = $3; + enum_type->range.reset( make_range_from_width(integer_width) ); + $$ = enum_type; + } + ; + +enum_name_list + : enum_name + { list*lst = new list; + lst->push_back(*$1); + delete $1; + $$ = lst; + } + | enum_name_list ',' enum_name + { list*lst = $1; + lst->push_back(*$3); + delete $3; + $$ = lst; + } + ; + +enum_name + : IDENTIFIER + { perm_string name = lex_strings.make($1); + delete[]$1; + $$ = make_named_number(name); + } + | IDENTIFIER '=' number + { perm_string name = lex_strings.make($1); + delete[]$1; + $$ = make_named_number(name, *$3); + delete $3; + } + ; + case_item : expression_list_proper ':' statement_or_null { PCase::Item*tmp = new PCase::Item; diff --git a/pform.cc b/pform.cc index 6591622e6..010e8d260 100644 --- a/pform.cc +++ b/pform.cc @@ -2463,6 +2463,15 @@ void pform_set_integer_2atom(uint64_t width, bool signed_flag, list delete names; } +void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list*names) +{ + cerr << li.text << ":" << li.first_line << ": " + << "sorry: enum types not supported yet." << endl; + error_count += 1; + delete enum_type; + delete names; +} + svector* pform_make_udp_input_ports(list*names) { svector*out = new svector(names->size()); diff --git a/pform.h b/pform.h index fa5debc72..9cce000a5 100644 --- a/pform.h +++ b/pform.h @@ -35,6 +35,7 @@ # include # include # include +# include # include /* @@ -83,9 +84,10 @@ extern bool pform_library_flag; /* This is information about port name information for named port connections. */ -//typedef struct named named_pexpr_t; typedef named named_pexpr_t; +typedef named named_number_t; + struct parmvalue_t { svector*by_order; svector*by_name; @@ -93,12 +95,20 @@ struct parmvalue_t { struct str_pair_t { ivl_drive_t str0, str1; }; + struct net_decl_assign_t { perm_string name; PExpr*expr; struct net_decl_assign_t*next; }; +struct enum_type_t { + ivl_variable_type_t base_type; + bool signed_flag; + auto_ptr< svector > range; + auto_ptr< list > names; +}; + /* The lgate is gate instantiation information. */ struct lgate { lgate(int =0) @@ -277,6 +287,8 @@ extern void pform_set_reg_time(list*names); extern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list*names); +extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list*names); + /* pform_set_attrib and pform_set_type_attrib exist to support the $attribute syntax, which can only set string values to attributes. The functions keep the value strings that are