Skip to content

Commit

Permalink
Parse Verilog for loops
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jan 15, 2025
1 parent 230dffd commit 231ae7a
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 14 deletions.
6 changes: 5 additions & 1 deletion src/lexer.l
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* -*- mode: c; c-basic-offset: 3 -*- */

/*
* Copyright (C) 2011-2024 Nick Gasson
* Copyright (C) 2011-2025 Nick Gasson
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -662,6 +662,9 @@ BEFORE ?i:before
<VLOG>"(*" { return tATTRBEGIN; }
<VLOG>"*)" { return tATTREND; }
<VLOG>"%" { return tPERCENT; }
<VLOG>"++" { return tPLUSPLUS; }
<VLOG>"--" { return tMINUSMINUS; }
<VLOG>"var" { return tVAR; }
<VLOG>"specify" { return tSPECIFY; }
<VLOG>"endspecify" { return tENDSPECIFY; }
<VLOG>"primitive" { return tPRIMITIVE; }
Expand Down Expand Up @@ -703,6 +706,7 @@ BEFORE ?i:before
<VLOG>"endfunction" { return tENDFUNCTION; }
<VLOG>"wait" { return tWAIT; }
<VLOG>"parameter" { return tPARAMETER; }
<VLOG>"for" { return tFOR; }

<VLOG>{SYSTASK} { yylval.str = xstrdup(yytext); return tSYSTASK; }
<VLOG>{VLOG_ID} { yylval.str = xstrdup(yytext); return tID; }
Expand Down
4 changes: 2 additions & 2 deletions src/nvc.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2011-2024 Nick Gasson
// Copyright (C) 2011-2025 Nick Gasson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -73,7 +73,7 @@ typedef struct {
} cmd_state_t;

const char copy_string[] =
"Copyright (C) 2011-2024 Nick Gasson\n"
"Copyright (C) 2011-2025 Nick Gasson\n"
"This program comes with ABSOLUTELY NO WARRANTY. This is free software, "
"and\nyou are welcome to redistribute it under certain conditions. See "
"the GNU\nGeneral Public Licence for details.";
Expand Down
5 changes: 3 additions & 2 deletions src/scan.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2014-2024 Nick Gasson
// Copyright (C) 2014-2025 Nick Gasson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -262,7 +262,8 @@ const char *token_str(token_t tok)
"before!", "before_", "before!_", "|->", "|=>", "next", "inf",
"repeat", "do", "endpoint", "<<", ">>", "<<<", ">>>", "task",
"endtask", "endfunction", "`begin_keywords", "`end_keywords", "real",
"shortreal", "realtime", "`__nvc_push", "`__nvc_pop",
"shortreal", "realtime", "`__nvc_push", "`__nvc_pop", "++", "--",
"var",
};

if (tok >= 200 && tok - 200 < ARRAY_LEN(token_strs))
Expand Down
5 changes: 4 additions & 1 deletion src/scan.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2022-2024 Nick Gasson
// Copyright (C) 2022-2025 Nick Gasson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -424,5 +424,8 @@ bool is_scanned_as_psl(void);
#define tREALTIME 521
#define tNVCPUSH 522
#define tNVCPOP 523
#define tPLUSPLUS 524
#define tMINUSMINUS 525
#define tVAR 526

#endif // _SCAN_H
20 changes: 18 additions & 2 deletions src/vlog/vlog-node.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2022-2024 Nick Gasson
// Copyright (C) 2022-2025 Nick Gasson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -174,6 +174,21 @@ static const imask_t has_map[V_LAST_NODE_KIND] = {

// V_CONCAT
(I_PARAMS),

// V_FOR_LOOP
(I_LEFT | I_VALUE | I_RIGHT | I_STMTS),

// V_FOR_INIT
(I_DECLS | I_STMTS),

// V_FOR_STEP
(I_STMTS),

// V_PREFIX
(I_TARGET | I_SUBKIND),

// V_POSTFIX
(I_TARGET | I_SUBKIND),
};

static const char *kind_text_map[V_LAST_NODE_KIND] = {
Expand All @@ -189,7 +204,8 @@ static const char *kind_text_map[V_LAST_NODE_KIND] = {
"V_UNION_DECL", "V_STRUCT_DECL", "V_EVENT_CONTROL", "V_EMPTY",
"V_REPEAT", "V_WHILE", "V_DO_WHILE", "V_TASK_DECL",
"V_FUNC_DECL", "V_WAIT", "V_PARAM_DECL", "V_COND_EXPR",
"V_REAL", "V_CONCAT",
"V_REAL", "V_CONCAT", "V_FOR_LOOP", "V_FOR_INIT",
"V_FOR_STEP", "V_PREFIX", "V_POSTFIX",
};

static const change_allowed_t change_allowed[] = {
Expand Down
12 changes: 11 additions & 1 deletion src/vlog/vlog-node.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2022-2024 Nick Gasson
// Copyright (C) 2022-2025 Nick Gasson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -94,6 +94,11 @@ typedef enum {
V_COND_EXPR,
V_REAL,
V_CONCAT,
V_FOR_LOOP,
V_FOR_INIT,
V_FOR_STEP,
V_PREFIX,
V_POSTFIX,

V_LAST_NODE_KIND
} vlog_kind_t;
Expand Down Expand Up @@ -149,6 +154,11 @@ typedef enum {
V_UNARY_IDENTITY,
} vlog_unary_t;

typedef enum {
V_INCDEC_PLUS,
V_INCDEC_MINUS,
} vlog_incdec_t;

typedef enum {
V_ASSIGN_EQUALS,
} vlog_assign_t;
Expand Down
182 changes: 179 additions & 3 deletions src/vlog/vlog-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static vlog_node_t p_constant_expression(void);
static vlog_node_t p_data_type(void);
static void p_list_of_variable_decl_assignments(vlog_node_t parent,
vlog_node_t datatype);
static vlog_node_t p_variable_lvalue(void);

static inline void _pop_state(const rule_state_t *r)
{
Expand Down Expand Up @@ -1267,6 +1268,34 @@ static vlog_unary_t p_unary_operator(void)
}
}

static vlog_incdec_t p_inc_or_dec_operator(void)
{
// ++ | --

BEGIN("inc or dec operator");

switch (one_of(tPLUSPLUS, tMINUSMINUS)) {
case tMINUSMINUS: return V_INCDEC_MINUS;
case tPLUSPLUS:
default: return V_INCDEC_PLUS;
}
}

static vlog_node_t p_inc_or_dec_expression(vlog_node_t head)
{
// inc_or_dec_operator { attribute_instance } variable_lvalue
// | variable_lvalue { attribute_instance } inc_or_dec_operator

BEGIN_WITH_HEAD("inc or dec expression", head);

vlog_node_t v = vlog_new(head ? V_POSTFIX : V_PREFIX);
vlog_set_subkind(v, p_inc_or_dec_operator());
vlog_set_target(v, head ?: p_variable_lvalue());

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static vlog_node_t p_nonbinary_expression(void)
{
// primary | unary_operator { attribute_instance } primary
Expand All @@ -1293,9 +1322,12 @@ static vlog_node_t p_nonbinary_expression(void)
vlog_set_loc(v, CURRENT_LOC);
return v;
}
case tPLUSPLUS:
case tMINUSMINUS:
return p_inc_or_dec_expression(NULL);
default:
one_of(tID, tSTRING, tNUMBER, tUNSIGNED, tREAL, tSYSTASK, tLPAREN,
tLBRACE, tMINUS, tTILDE, tBANG);
tLBRACE, tMINUS, tTILDE, tBANG, tPLUSPLUS, tMINUSMINUS);
return p_select(error_marker());
}
}
Expand Down Expand Up @@ -1723,6 +1755,116 @@ static vlog_node_t p_conditional_statement(void)
return v;
}

static vlog_node_t p_variable_assignment(vlog_kind_t kind)
{
// variable_lvalue = expression

BEGIN("variable assignment");

vlog_node_t v = vlog_new(kind);
vlog_set_target(v, p_variable_lvalue());

consume(tEQ);

vlog_set_value(v, p_expression());

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static void p_list_of_variable_assignments(vlog_node_t parent)
{
// variable_assignment { , variable_assignment }

BEGIN("list of variable assignments");

do {
vlog_node_t v = p_variable_assignment(V_BASSIGN);
vlog_add_stmt(parent, v);
} while (optional(tCOMMA));
}

static void p_for_variable_declaration(vlog_node_t parent)
{
// [ var ] data_type variable_identifier = expression
// { , variable_identifier = expression }

BEGIN("for variable declaration");

optional(tVAR);

vlog_node_t dt = p_data_type();

do {
vlog_node_t v = vlog_new(V_VAR_DECL);
vlog_set_ident(v, p_identifier());
vlog_set_type(v, dt);

consume(tEQ);

vlog_set_value(v, p_expression());

vlog_set_loc(v, CURRENT_LOC);
vlog_add_decl(parent, v);
} while (optional(tCOMMA));
}

static vlog_node_t p_for_initialization(void)
{
// list_of_variable_assignments
// | for_variable_declaration { , for_variable_declaration }

BEGIN("for initialization");

vlog_node_t v = vlog_new(V_FOR_INIT);

if (scan(tREG, tSTRUCT, tUNION, tENUM, tSVINT, tINTEGER, tSVREAL,
tSHORTREAL, tREALTIME, tLOGIC, tVAR)) {
do {
p_for_variable_declaration(v);
} while (optional(tCOMMA));
}
else
p_list_of_variable_assignments(v);

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static vlog_node_t p_for_step(void)
{
// operator_assignment | inc_or_dec_expression | function_subroutine_call

BEGIN("for step");

vlog_node_t v = vlog_new(V_FOR_STEP);

switch (peek()) {
case tPLUSPLUS:
case tMINUSMINUS:
vlog_add_stmt(v, p_inc_or_dec_expression(NULL));
break;
default:
{
vlog_node_t head = p_variable_lvalue();

switch (peek()) {
case tPLUSPLUS:
case tMINUSMINUS:
vlog_add_stmt(v, p_inc_or_dec_expression(head));
break;
default:
vlog_add_stmt(v, p_operator_assignment(head));
break;
}
}
break;
}

vlog_set_loc(v, CURRENT_LOC);
return v;
}

static vlog_node_t p_loop_statement(void)
{
// forever statement_or_null
Expand All @@ -1736,7 +1878,7 @@ static vlog_node_t p_loop_statement(void)

BEGIN("loop statement");

switch (one_of(tFOREVER, tWHILE, tREPEAT, tDO)) {
switch (one_of(tFOREVER, tWHILE, tREPEAT, tDO, tFOR)) {
case tFOREVER:
{
vlog_node_t v = vlog_new(V_FOREVER);
Expand Down Expand Up @@ -1800,6 +1942,39 @@ static vlog_node_t p_loop_statement(void)
return v;
}

case tFOR:
{
vlog_node_t v = vlog_new(V_FOR_LOOP);

consume(tLPAREN);

if (not_at_token(tSEMI))
vlog_set_left(v, p_for_initialization());
else
vlog_set_left(v, vlog_new(V_FOR_INIT));

consume(tSEMI);

if (not_at_token(tSEMI))
vlog_set_value(v, p_expression());

consume(tSEMI);

if (not_at_token(tRPAREN))
vlog_set_right(v, p_for_step());
else
vlog_set_right(v, vlog_new(V_FOR_STEP));

consume(tRPAREN);

vlog_node_t s = p_statement_or_null();
if (s != NULL)
vlog_add_stmt(v, s);

vlog_set_loc(v, CURRENT_LOC);
return v;
}

default:
should_not_reach_here();
}
Expand Down Expand Up @@ -1872,12 +2047,13 @@ static vlog_node_t p_statement_item(void)
case tWHILE:
case tREPEAT:
case tDO:
case tFOR:
return p_loop_statement();
case tWAIT:
return p_wait_statement();
default:
one_of(tID, tAT, tHASH, tBEGIN, tSYSTASK, tIF, tFOREVER, tWHILE, tREPEAT,
tDO, tWAIT);
tDO, tFOR, tWAIT);
drop_tokens_until(tSEMI);
return NULL;
}
Expand Down
Loading

0 comments on commit 231ae7a

Please sign in to comment.