Skip to content

Commit

Permalink
Parsing for VHDL-2019 improved type generics
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jul 6, 2023
1 parent 9d039a1 commit 60836fc
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 23 deletions.
64 changes: 46 additions & 18 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,14 @@ static void dump_generics(tree_t t, int indent, const char *trailer)
if (ngenerics > 1) {
print_syntax("\n");
for (int i = 0; i < ngenerics; i++) {
if (i > 0) print_syntax(";\n");
dump_port(tree_generic(t, i), indent + 2);
tree_t g = tree_generic(t, i);
dump_port(g, indent + 2);
if (i + 1 == ngenerics && (tree_flags(g) & TREE_F_PREDEFINED)) {
print_syntax(";\n");
tab(indent - 1);
}
else if (i + 1 < ngenerics)
print_syntax(";\n");
}
}
else
Expand Down Expand Up @@ -1360,27 +1366,49 @@ static void dump_port(tree_t t, int indent)
if (tree_flags(t) & TREE_F_PREDEFINED)
print_syntax("-- predefined ");

const char *class = NULL, *dir = NULL;
switch (tree_class(t)) {
case C_SIGNAL: class = "signal"; break;
case C_VARIABLE: class = "variable"; break;
case C_DEFAULT: class = ""; break;
case C_CONSTANT: class = "constant"; break;
case C_FILE: class = "file"; break;
case C_TYPE: class = "type"; break;
case C_FUNCTION: class = "function"; break;
case C_PROCEDURE: class = "procedure"; break;
case C_PACKAGE: class = "package"; break;
default:
assert(false);
}
print_syntax("#%s %s", class, istr(tree_ident(t)));
const class_t class = tree_class(t);
print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));

if (tree_class(t) == C_PACKAGE) {
if (class == C_PACKAGE) {
print_syntax(" #is #new ");
dump_expr(tree_value(t));
}
else if (class == C_TYPE) {
print_syntax(" #is ");

type_t type = tree_type(t);
switch (type_subkind(type)) {
case GTYPE_PRIVATE:
print_syntax("#private");
break;
case GTYPE_SCALAR:
print_syntax("<>");
break;
case GTYPE_DISCRETE:
print_syntax("(<>)");
break;
case GTYPE_INTEGER:
print_syntax("#range <>");
break;
case GTYPE_PHYSICAL:
print_syntax("#units <>");
break;
case GTYPE_FLOATING:
print_syntax("#range <> . <>");
break;
case GTYPE_ARRAY:
print_syntax("#array (..) #of ..");
break;
case GTYPE_ACCESS:
print_syntax("#access ..");
break;
case GTYPE_FILE:
print_syntax("#file #of ..");
break;
}
}
else {
const char *dir = NULL;
switch (tree_subkind(t)) {
case PORT_IN: dir = "in"; break;
case PORT_OUT: dir = "out"; break;
Expand Down
2 changes: 2 additions & 0 deletions src/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ NUMERIC ?i:numeric
STRING_K ?i:string
WITHIN ?i:within
VIEW ?i:view
PRIVATE ?i:private

%%

Expand Down Expand Up @@ -372,6 +373,7 @@ VIEW ?i:view
{PARAMETER} { TOKEN_08(tPARAMETER); }
{DEFAULT} { TOKEN_08(tDEFAULT); }
{VIEW} { TOKEN_19(tVIEW); }
{PRIVATE} { TOKEN_19(tPRIVATE); }

`{IF} { TOKEN(tCONDIF); }
`{ELSE} { TOKEN(tCONDELSE); }
Expand Down
218 changes: 218 additions & 0 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ static tree_t p_concurrent_procedure_call_statement(ident_t label, tree_t name);
static tree_t p_subprogram_instantiation_declaration(void);
static tree_t p_record_element_constraint(type_t base);
static void p_selected_waveforms(tree_t stmt, tree_t target, tree_t reject);
static type_t p_index_subtype_definition(void);
static type_t p_anonymous_type_indication(void);
static tree_t p_psl_declaration(void);
static psl_node_t p_psl_sequence(void);
static psl_node_t p_psl_property(void);
Expand Down Expand Up @@ -4808,9 +4810,220 @@ static void p_interface_file_declaration(tree_t parent, tree_kind_t kind)
}
}

static void p_private_incomplete_type_definition(type_t type)
{
// 2019: private

BEGIN("private incomplete type definition");

consume(tPRIVATE);

type_set_subkind(type, GTYPE_PRIVATE);
}

static void p_scalar_incomplete_type_definition(type_t type)
{
// 2019: <>

BEGIN("scalar incomplete type definition");

consume(tBOX);

type_set_subkind(type, GTYPE_SCALAR);
}

static void p_discrete_incomplete_type_definition(type_t type)
{
// 2019: ( <> )

BEGIN("discrete incomplete type definition");

consume(tLPAREN);
consume(tBOX);
consume(tRPAREN);

type_set_subkind(type, GTYPE_DISCRETE);
}

static void p_integer_incomplete_type_definition(type_t type)
{
// 2019: range <>

BEGIN("integer incomplete type definition");

consume(tRANGE);
consume(tBOX);

type_set_subkind(type, GTYPE_INTEGER);
}

static void p_physical_incomplete_type_definition(type_t type)
{
// 2019: units <>

BEGIN("physical incomplete type definition");

consume(tUNITS);
consume(tBOX);

type_set_subkind(type, GTYPE_PHYSICAL);
}

static void p_floating_incomplete_type_definition(type_t type)
{
// 2019: range <> . <>

BEGIN("floating incomplete type definition");

consume(tRANGE);
consume(tBOX);
consume(tDOT);
consume(tBOX);

type_set_subkind(type, GTYPE_FLOATING);
}

static type_t p_array_index_incomplete_type(void)
{
// index_subtype_definition | index_constraint | anonymous_type_indication

return p_index_subtype_definition();
}

static void p_array_index_incomplete_type_list(type_t type)
{
// array_index_incomplete_type { , array_index_incomplete_type }

do {
(void)p_array_index_incomplete_type();
} while (optional(tCOMMA));
}

static type_t p_incomplete_subtype_indication(void)
{
// subtype_indication | anonymous_type_indication

if (peek() == tTYPE)
return p_anonymous_type_indication();
else
return p_subtype_indication();
}

static void p_array_incomplete_type_definition(type_t type)
{
// 2019: array ( array_index_incomplete_type_list )
// of element_incomplete_subtype_indication

BEGIN("array incomplete type definition");

consume(tARRAY);
consume(tLPAREN);

p_array_index_incomplete_type_list(type);

consume(tRPAREN);
consume(tOF);

(void)p_incomplete_subtype_indication();

type_set_subkind(type, GTYPE_ARRAY);
}

static void p_access_incomplete_type_definition(type_t type)
{
// 2019: access incomplete_subtype_indication

BEGIN("access incomplete type definition");

consume(tACCESS);

(void)p_incomplete_subtype_indication();

type_set_subkind(type, GTYPE_ACCESS);
}

static void p_file_incomplete_type_definition(type_t type)
{
// 2019: file of incomplete_subtype_indication

BEGIN("file incomplete type definition");

consume(tFILE);
consume(tOF);

(void)p_incomplete_subtype_indication();

type_set_subkind(type, GTYPE_FILE);
}

static void p_incomplete_type_definition(type_t type)
{
// private_incomplete_type_definition
// | scalar_incomplete_type_definition
// | discrete_incomplete_type_definition
// | integer_incomplete_type_definition
// | physical_incomplete_type_definition
// | floating_incomplete_type_definition
// | array_incomplete_type_definition
// | access_incomplete_type_definition
// | file_incomplete_type_definition

BEGIN("incomplete type definition");

require_std(STD_19, "incomplete type definition");

switch (peek()) {
case tPRIVATE:
p_private_incomplete_type_definition(type);
break;
case tBOX:
p_scalar_incomplete_type_definition(type);
break;
case tLPAREN:
p_discrete_incomplete_type_definition(type);
break;
case tRANGE:
if (peek_nth(3) == tDOT)
p_floating_incomplete_type_definition(type);
else
p_integer_incomplete_type_definition(type);
break;
case tUNITS:
p_physical_incomplete_type_definition(type);
break;
case tARRAY:
p_array_incomplete_type_definition(type);
break;
case tACCESS:
p_access_incomplete_type_definition(type);
break;
case tFILE:
p_file_incomplete_type_definition(type);
break;
default:
one_of(tPRIVATE, tBOX, tLPAREN, tRANGE, tUNITS, tARRAY, tACCESS, tFILE);
}
}

static type_t p_anonymous_type_indication(void)
{
// type is incomplete_type_definition

BEGIN("anonymous type indication");

consume(tTYPE);
consume(tIS);

type_t type = type_new(T_GENERIC);
p_incomplete_type_definition(type);

return type;
}

static void p_interface_type_declaration(tree_t parent, tree_kind_t kind)
{
// 2008: type identifier
// 2019: type identifier [ is incomplete_type_definition ]

BEGIN("interface type declaration");

Expand All @@ -4823,6 +5036,11 @@ static void p_interface_type_declaration(tree_t parent, tree_kind_t kind)
type_t type = type_new(T_GENERIC);
type_set_ident(type, id);

if (optional(tIS))
p_incomplete_type_definition(type);
else
type_set_subkind(type, GTYPE_PRIVATE);

tree_t d = tree_new(kind);
tree_set_ident(d, id);
tree_set_loc(d, CURRENT_LOC);
Expand Down
2 changes: 1 addition & 1 deletion src/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ const char *token_str(token_t tok)
"restrict", "restrict_guarantee", "strong", "fairness", "cover",
"property", "sequence", "const", "mutable", "hdltype", "boolean",
"bit", "bitvector", "numeric", "string", "[*", "[+]", "[=", "[->",
"&&", "within", "system task", "view"
"&&", "within", "system task", "view", "private"
};

if (tok > 0 && tok - 200 < ARRAY_LEN(token_strs))
Expand Down
1 change: 1 addition & 0 deletions src/scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,5 +271,6 @@ void reset_verilog_parser(void);
#define tWITHIN 382
#define tSYSTASK 383
#define tVIEW 384
#define tPRIVATE 385

#endif // _SCAN_H
13 changes: 12 additions & 1 deletion src/type.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static const imask_t has_map[T_LAST_TYPE_KIND] = {
(I_IDENT | I_DECLS),

// T_GENERIC
(I_IDENT),
(I_IDENT | I_SUBKIND),

// T_VIEW
(I_IDENT | I_DESIGNATED | I_FIELDS),
Expand Down Expand Up @@ -349,6 +349,17 @@ bool type_has_elem(type_t t)
return lookup_item(&type_object, t, I_ELEM)->object != NULL;
}

unsigned type_subkind(type_t t)
{
item_t *item = lookup_item(&type_object, t, I_SUBKIND);
return item->ival;
}

void type_set_subkind(type_t t, unsigned sub)
{
lookup_item(&type_object, t, I_SUBKIND)->ival = sub;
}

bool type_is_universal(type_t t)
{
assert(t != NULL);
Expand Down
Loading

0 comments on commit 60836fc

Please sign in to comment.