Skip to content

Commit

Permalink
Parsing for Verilog task and function declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Dec 9, 2024
1 parent f3992e8 commit 4062b25
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,10 @@ BEFORE ?i:before
<VLOG>"while" { return tWHILE; }
<VLOG>"repeat" { return tREPEAT; }
<VLOG>"do" { return tDO; }
<VLOG>"task" { return tTASK; }
<VLOG>"endtask" { return tENDTASK; }
<VLOG>"function" { return tFUNCTION; }
<VLOG>"endfunction" { return tENDFUNCTION; }

<VLOG>{SYSTASK} { yylval.str = xstrdup(yytext); return tSYSTASK; }
<VLOG>{VLOG_ID} { yylval.str = xstrdup(yytext); return tID; }
Expand Down
3 changes: 2 additions & 1 deletion src/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ const char *token_str(token_t tok)
"shortint", "longint", "int", "integer", "time", "typedef", "logic",
"enum", "tagged", "abort", "sync_abort", "async_abort", "before",
"before!", "before_", "before!_", "|->", "|=>", "next", "inf",
"repeat", "do", "endpoint", "<<", ">>", "<<<", ">>>",
"repeat", "do", "endpoint", "<<", ">>", "<<<", ">>>", "task",
"endtask", "endfunction",
};

if (tok >= 200 && tok - 200 < ARRAY_LEN(token_strs))
Expand Down
3 changes: 3 additions & 0 deletions src/scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,5 +411,8 @@ bool is_scanned_as_psl(void);
#define tSHIFTRL 511
#define tSHIFTLA 512
#define tSHIFTRA 513
#define tTASK 514
#define tENDTASK 515
#define tENDFUNCTION 516

#endif // _SCAN_H
9 changes: 8 additions & 1 deletion src/vlog/vlog-node.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ static const imask_t has_map[V_LAST_NODE_KIND] = {

// V_DO_WHILE
(I_VALUE | I_STMTS),

// V_TASK_DECL
(I_IDENT | I_STMTS | I_DECLS),

// V_FUNC_DECL
(I_IDENT | I_STMTS | I_DECLS | I_TYPE),
};

static const char *kind_text_map[V_LAST_NODE_KIND] = {
Expand All @@ -166,7 +172,8 @@ static const char *kind_text_map[V_LAST_NODE_KIND] = {
"V_SPECIFY", "V_PRIMITIVE", "V_UDP_TABLE", "V_UDP_ENTRY",
"V_DATA_TYPE", "V_TYPE_DECL", "V_ENUM_DECL", "V_ENUM_NAME",
"V_UNION_DECL", "V_STRUCT_DECL", "V_EVENT_CONTROL", "V_EMPTY",
"V_REPEAT", "V_WHILE", "V_DO_WHILE",
"V_REPEAT", "V_WHILE", "V_DO_WHILE", "V_TASK_DECL",
"V_FUNC_DECL",
};

static const change_allowed_t change_allowed[] = {
Expand Down
2 changes: 2 additions & 0 deletions src/vlog/vlog-node.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ typedef enum {
V_REPEAT,
V_WHILE,
V_DO_WHILE,
V_TASK_DECL,
V_FUNC_DECL,

V_LAST_NODE_KIND
} vlog_kind_t;
Expand Down
189 changes: 183 additions & 6 deletions src/vlog/vlog-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ static vlog_node_t p_data_type_or_implicit(void)

BEGIN("data type or implicit");

if (scan(tREG, tSTRUCT, tUNION, tENUM, tSVINT))
if (scan(tREG, tSTRUCT, tUNION, tENUM, tSVINT, tLOGIC))
return p_data_type();
else
return p_implicit_data_type();
Expand Down Expand Up @@ -2002,6 +2002,171 @@ static void p_data_declaration(vlog_node_t mod)
}
}

static v_port_kind_t p_port_direction(void)
{
// input | output | inout | ref

BEGIN("port direction");

switch (one_of(tINPUT, tOUTPUT, tINOUT)) {
case tINPUT: return V_PORT_INPUT;
case tOUTPUT: return V_PORT_OUTPUT;
case tINOUT: return V_PORT_INOUT;
default: return V_PORT_INPUT;
}
}

static v_port_kind_t p_tf_port_direction(void)
{
// port_direction | const ref

BEGIN("task or function port direction");

return p_port_direction();
}

static vlog_node_t p_tf_port_item(void)
{
// { attribute_instance } [ tf_port_direction ] [ var ]
// data_type_or_implicit [ port_identifier { variable_dimension }
// [ = expression ] ]

BEGIN("task or function port item");

vlog_node_t v = vlog_new(V_PORT_DECL);

if (scan(tINPUT, tOUTPUT))
vlog_set_subkind(v, p_tf_port_direction());
else
vlog_set_subkind(v, V_PORT_INPUT);

vlog_set_type(v, p_data_type_or_implicit());

if (peek() == tID) {
vlog_set_ident(v, p_identifier());

if (optional(tEQ))
vlog_set_value(v, p_expression());
}

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static void p_tf_port_list(vlog_node_t tf)
{
// tf_port_item { , tf_port_item }

BEGIN("task or function port list");

do {
p_tf_port_item();
} while (optional(tCOMMA));
}

static void p_task_body_declaration(vlog_node_t task)
{
// [ interface_identifier . | class_scope ] task_identifier ;
// { tf_item_declaration } { statement_or_null }
// endtask [ : task_identifier ]
// | [ interface_identifier . | class_scope ] task_identifier
// ( [ tf_port_list ] ) ; { block_item_declaration }
// { statement_or_null } endtask [ : task_identifier ]

BEGIN("task body declaration");

ident_t id = p_identifier();
vlog_set_ident(task, id);

if (optional(tLPAREN)) {
p_tf_port_list(task);
consume(tRPAREN);
}

consume(tSEMI);

while (not_at_token(tENDTASK)) {
vlog_node_t s = p_statement_or_null();
if (s != NULL)
vlog_add_stmt(task, s);
}

consume(tENDTASK);
}

static vlog_node_t p_task_declaration(void)
{
// task [ dynamic_override_specifiers ] [ lifetime ] task_body_declaration

BEGIN("task declaration");

vlog_node_t v = vlog_new(V_TASK_DECL);

consume(tTASK);

p_task_body_declaration(v);

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static vlog_node_t p_function_data_type_or_implicit(void)
{
// data_type_or_void | implicit_data_type

BEGIN("function data type or implicit");

return p_implicit_data_type();
}

static void p_function_body_declaration(vlog_node_t func)
{
// function_data_type_or_implicit [ interface_identifier . | class_scope ]
// function_identifier ; { tf_item_declaration }
// { function_statement_or_null } endfunction [ : function_identifier ]
// | function_data_type_or_implicit [ interface_identifier . | class_scope ]
// function_identifier ( [ tf_port_list ] ) ; { block_item_declaration }
// { function_statement_or_null } endfunction [ : function_identifier ]

BEGIN("function body declaration");

vlog_set_type(func, p_function_data_type_or_implicit());

ident_t id = p_identifier();
vlog_set_ident(func, id);

if (optional(tLPAREN)) {
p_tf_port_list(func);
consume(tRPAREN);
}

consume(tSEMI);

while (not_at_token(tENDFUNCTION)) {
vlog_node_t s = p_statement_or_null();
if (s != NULL)
vlog_add_stmt(func, s);
}

consume(tENDFUNCTION);
}

static vlog_node_t p_function_declaration(void)
{
// function [ lifetime ] function_body_declaration

BEGIN("function declaration");

vlog_node_t v = vlog_new(V_FUNC_DECL);

consume(tFUNCTION);

p_function_body_declaration(v);

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static void p_package_or_generate_item_declaration(vlog_node_t mod)
{
// net_declaration | data_declaration | task_declaration
Expand All @@ -2027,9 +2192,15 @@ static void p_package_or_generate_item_declaration(vlog_node_t mod)
case tSVINT:
p_data_declaration(mod);
break;
case tTASK:
vlog_add_decl(mod, p_task_declaration());
break;
case tFUNCTION:
vlog_add_decl(mod, p_function_declaration());
break;
default:
one_of(tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT, tUNION, tTYPEDEF,
tENUM, tSVINT);
tENUM, tSVINT, tTASK, tFUNCTION);
drop_tokens_until(tSEMI);
break;
}
Expand Down Expand Up @@ -2073,14 +2244,16 @@ static void p_module_common_item(vlog_node_t mod)
case tTYPEDEF:
case tENUM:
case tSVINT:
case tTASK:
case tFUNCTION:
p_module_or_generate_item_declaration(mod);
break;
case tASSIGN:
p_continuous_assign(mod);
break;
default:
one_of(tALWAYS, tINITIAL, tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT,
tUNION, tTYPEDEF, tENUM, tSVINT, tASSIGN);
tUNION, tTYPEDEF, tENUM, tSVINT, tTASK, tFUNCTION, tASSIGN);
drop_tokens_until(tSEMI);
}
}
Expand Down Expand Up @@ -2541,6 +2714,8 @@ static void p_module_or_generate_item(vlog_node_t mod)
case tTYPEDEF:
case tENUM:
case tSVINT:
case tTASK:
case tFUNCTION:
p_module_common_item(mod);
break;
case tPULLDOWN:
Expand All @@ -2560,8 +2735,8 @@ static void p_module_or_generate_item(vlog_node_t mod)
break;
default:
one_of(tALWAYS, tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT, tUNION, tASSIGN,
tINITIAL, tTYPEDEF, tENUM, tSVINT, tPULLDOWN, tPULLUP, tID, tAND,
tNAND, tOR, tNOR, tXOR, tXNOR, tNOT, tBUF);
tINITIAL, tTYPEDEF, tENUM, tSVINT, tTASK, tFUNCTION, tPULLDOWN,
tPULLUP, tID, tAND, tNAND, tOR, tNOR, tXOR, tXNOR, tNOT, tBUF);
drop_tokens_until(tSEMI);
}
}
Expand Down Expand Up @@ -2599,6 +2774,8 @@ static void p_non_port_module_item(vlog_node_t mod)
case tTYPEDEF:
case tENUM:
case tSVINT:
case tTASK:
case tFUNCTION:
p_module_or_generate_item(mod);
break;
case tSPECIFY:
Expand All @@ -2608,7 +2785,7 @@ static void p_non_port_module_item(vlog_node_t mod)
one_of(tALWAYS, tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT, tUNION,
tASSIGN, tPULLDOWN, tPULLUP, tID, tATTRBEGIN, tAND, tNAND,
tOR, tNOR, tXOR, tXNOR, tNOT, tBUF, tTYPEDEF, tENUM, tSVINT,
tSPECIFY);
tTASK, tFUNCTION, tSPECIFY);
drop_tokens_until(tSEMI);
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/test_vlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ START_TEST(test_parse1)
fail_unless(vlog_kind(m) == V_MODULE);
fail_unless(vlog_stmts(m) == 11);
fail_unless(vlog_ports(m) == 0);
fail_unless(vlog_decls(m) == 6);
fail_unless(vlog_decls(m) == 9);

vlog_node_t x = vlog_decl(m, 0);
fail_unless(vlog_kind(x) == V_NET_DECL);
Expand Down
9 changes: 9 additions & 0 deletions test/vlog/parse1.v
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@ module parse1;
end
int r1 = 5;
wire w1 = 0;
task task1;
@(x) y = 2;
endtask // task1
task task2(input int x, output logic y);
y = !x;
endtask // task2
function sum(input int a, b);
sum = a + b;
endfunction // sum
endmodule // parse1

0 comments on commit 4062b25

Please sign in to comment.