Skip to content

Commit

Permalink
12 najaverilogverilogexception parser error syntax error unexpected e…
Browse files Browse the repository at this point in the history
…xpecting (#13)

* Adding failing associated test

* Adding support for defparam, working on tests

* More testing

* Exclude coverage from non constant number

* remove throw from coverage
  • Loading branch information
xtofalex authored Sep 17, 2024
1 parent d5f980f commit d10d53e
Show file tree
Hide file tree
Showing 11 changed files with 1,029 additions and 21 deletions.
15 changes: 15 additions & 0 deletions src/NajaVerilogSnippet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "VerilogConstructor.h"

#include <iostream>
#include <sstream>

namespace {

Expand Down Expand Up @@ -44,6 +45,20 @@ class VerilogConstructorExample: public naja::verilog::VerilogConstructor {
void addParameterAssignment(const naja::verilog::Identifier& parameter, const naja::verilog::Expression& expression) override {
std::cout << "addParameterAssignment: " << parameter.getString() << ": " << expression.getString() << std::endl;
}
virtual void addDefParameterAssignment(
const naja::verilog::Identifiers& hierarchicalParameter,
const naja::verilog::Expression& expression) override {
std::ostringstream oss;
for (size_t i = 0; i < hierarchicalParameter.size(); i++) {
oss << hierarchicalParameter[i].getString();
if (i < hierarchicalParameter.size() - 1) {
oss << ".";
}
}
std::cout << "addDefParameterAssignment: "
<< oss.str()
<< ": " << expression.getString() << std::endl;
}
void endModule() override {
std::cout << "endModule" << std::endl;
}
Expand Down
3 changes: 3 additions & 0 deletions src/VerilogConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class VerilogConstructor {
virtual void addOrderedInstanceConnection(size_t portIndex, const Expression& expression) {}
virtual void endInstantiation() {}
virtual void addParameterAssignment(const naja::verilog::Identifier& parameter, const Expression& expression) {}
virtual void addDefParameterAssignment(
const naja::verilog::Identifiers& hierarchicalParameter,
const naja::verilog::Expression& expression) {}
virtual void endModule() {}
//LCOV_EXCL_STOP
private:
Expand Down
89 changes: 69 additions & 20 deletions src/VerilogParser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ static naja::verilog::Number generateNumber(
%token SUPPLY1_KW
%token WIRE_KW
%token ASSIGN_KW
%token DEFPARAM_KW
%token END 0 "end of file"

%token<std::string> IDENTIFIER_TK
Expand All @@ -136,7 +137,6 @@ static naja::verilog::Number generateNumber(

%type<naja::verilog::Identifier> identifier;
//no support for XMRs for the moment
%type<naja::verilog::Identifier> hierarchical_identifier;
%type<naja::verilog::Identifier> hierarchical_net_identifier;
%type<naja::verilog::Identifier> module_identifier;
%type<naja::verilog::Identifier> name_of_module_instance;
Expand All @@ -151,16 +151,19 @@ static naja::verilog::Number generateNumber(
%type<naja::verilog::Range> constant_range_expression.opt;
%type<naja::verilog::Identifier> net_identifier;
%type<naja::verilog::Identifiers> list_of_identifiers;
%type<naja::verilog::Identifiers> hierarchical_identifier;
%type<naja::verilog::Identifiers> hierarchical_parameter_identifier;
%type<naja::verilog::RangeIdentifiers> net_lvalue;
%type<naja::verilog::RangeIdentifiers> list_of_net_lvalues;
%type<naja::verilog::Identifier> module_instance;
%type<naja::verilog::Identifier> port_identifier;

%type<naja::verilog::Number> number;
%type<naja::verilog::Number> constant_primary;
%type<naja::verilog::Number> constant_expression;
%type<naja::verilog::Expression> constant_mintypmax_expression;
%type<std::string> unary_operator;
%type<naja::verilog::Expression> primary;
%type<naja::verilog::Expression> constant_primary;
%type<naja::verilog::Expression> constant_expression;
%type<naja::verilog::Expression> expression;
%type<naja::verilog::Expression> expression.opt;
%type<naja::verilog::Expression> mintypmax_expression;
Expand All @@ -186,20 +189,48 @@ identifier
$$ = naja::verilog::Identifier(escaped, true);
}

constant_primary: number
primary
: number {
$$.valid_ = true; $$.value_ = $1; }
//no support for XMRs for the moment: should be hierarchical_identifier below
| identifier constant_range_expression.opt {
$$.valid_ = true; $$.value_ = naja::verilog::RangeIdentifier($1, $2); }
| STRING_TK { $$.valid_ = true; $$.value_ = $1.substr(1, $1.size()-2); }
| concatenation { $$.valid_ = true; $$.value_ = naja::verilog::Concatenation($1); }
;

constant_primary
: number {
$$.valid_ = true; $$.value_ = $1; }
| STRING_TK { $$.valid_ = true; $$.value_ = $1.substr(1, $1.size()-2); }
;

unary_operator: SIGN_TK;

constant_expression: constant_primary {
$$ = $1;
}
| unary_operator constant_primary {
$$ = $2;
if ($1 == "-") { $$.sign_ = false; }
auto expression = $2;
if (expression.value_.index() == naja::verilog::Expression::NUMBER) {
auto number = std::get<naja::verilog::Number>(expression.value_);
if ($1 == "-") { number.sign_ = false; }
$$.valid_ = true;
$$.value_ = number;
} else {
throw VerilogException("Only constant number expression are supported"); //LCOV_EXCL_LINE
}
}

range: '[' constant_expression ':' constant_expression ']' {
$$ = Range($2.getInt(), $4.getInt());
if ($2.value_.index() == naja::verilog::Expression::NUMBER and
$4.value_.index() == naja::verilog::Expression::NUMBER) {
auto number1 = std::get<naja::verilog::Number>($2.value_);
auto number2 = std::get<naja::verilog::Number>($4.value_);
$$ = Range(number1.getInt(), number2.getInt());
} else {
throw VerilogException("Only constant number expression are supported"); //LCOV_EXCL_LINE
}
}

range.opt: %empty { $$.valid_ = false; } | range { $$ = $1; }
Expand All @@ -221,7 +252,20 @@ port_type_io
| OUTPUT_KW { $$ = naja::verilog::Port::Direction::Output; }
;

non_port_module_item : module_or_generate_item;
non_port_module_item: module_or_generate_item;

hierarchical_parameter_identifier: hierarchical_identifier;

constant_mintypmax_expression: constant_expression;

defparam_assignment: hierarchical_parameter_identifier '=' constant_mintypmax_expression {
constructor->setCurrentLocation(@$.begin.line, @$.begin.column);
constructor->addDefParameterAssignment($1, $3);
}

list_of_defparam_assignments: defparam_assignment| list_of_defparam_assignments defparam_assignment;

parameter_override: DEFPARAM_KW list_of_defparam_assignments ';'

hierarchical_net_identifier: identifier;

Expand Down Expand Up @@ -253,6 +297,7 @@ continuous_assign: ASSIGN_KW list_of_net_assignments ';'
module_or_generate_item:
module_or_generate_item_declaration
| module_instantiation
| parameter_override
| continuous_assign
;

Expand Down Expand Up @@ -298,13 +343,26 @@ number
$$ = Number($1);
}

//no support for XMRs for the moment
hierarchical_identifier: identifier;
//hierarchical_identifier ::=
//{ identifier [ [ constant_expression ] ] . } identifier
hierarchical_identifier
: identifier {
$$ = { $1 };
}
| hierarchical_identifier '.' identifier {
$1.push_back($3);
$$ = $1;
}

//only numeric values (one bit) [4] or [4:5] are supported
constant_range_expression.opt: %empty { $$.valid_ = false; }
| '[' constant_expression ']' {
$$ = Range($2.getInt());
if ($2.value_.index() == naja::verilog::Expression::NUMBER) {
auto number = std::get<naja::verilog::Number>($2.value_);
$$ = Range(number.getInt());
} else {
throw VerilogException("Only constant number expression are supported"); //LCOV_EXCL_LINE
}
}
| range {
$$ = $1;
Expand All @@ -321,15 +379,6 @@ expression {

concatenation: '{' list_of_expressions '}' { $$ = $2; }

primary
: number {
$$.valid_ = true; $$.value_ = $1; }
| hierarchical_identifier constant_range_expression.opt {
$$.valid_ = true; $$.value_ = naja::verilog::RangeIdentifier($1, $2); }
| STRING_TK { $$.valid_ = true; $$.value_ = $1.substr(1, $1.size()-2); }
| concatenation { $$.valid_ = true; $$.value_ = naja::verilog::Concatenation($1); }
;

expression: primary { $$ = $1; }

expression.opt: %empty { $$.valid_ = false; } | expression { $$ = $1; }
Expand Down
1 change: 1 addition & 0 deletions src/VerilogScanner.ll
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ wire { return token::WIRE_KW; }
supply0 { return token::SUPPLY0_KW; }
supply1 { return token::SUPPLY1_KW; }
assign { return token::ASSIGN_KW; }
defparam { return token::DEFPARAM_KW; }

{IDENTIFIER} { yylval->build<std::string>( yytext ); return token::IDENTIFIER_TK; }
{ESCAPED_IDENTIFIER} {
Expand Down
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ set(tests
NajaVerilogTest9.cpp
NajaVerilogTest10.cpp
NajaVerilogTest11.cpp
NajaVerilogTest12.cpp
NajaVerilogTest13.cpp
NajaVerilogTestMultipleFiles.cpp
NajaVerilogTestErrors.cpp
)
Expand Down
92 changes: 92 additions & 0 deletions test/NajaVerilogTest12.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-FileCopyrightText: 2024 The Naja verilog authors <https://github.com/najaeda/naja-verilog/blob/main/AUTHORS>
//
// SPDX-License-Identifier: Apache-2.0

#include "gtest/gtest.h"

#include <filesystem>
#include <fstream>

#include "VerilogConstructor.h"

using namespace naja::verilog;

#include "VerilogConstructorTest.h"

#ifndef NAJA_VERILOG_BENCHMARKS
#define NAJA_VERILOG_BENCHMARKS "Undefined"
#endif

TEST(NajaVerilogTest12, test) {
VerilogConstructorTest constructor;
std::filesystem::path test12Path(
std::filesystem::path(NAJA_VERILOG_BENCHMARKS)
/ std::filesystem::path("benchmarks")
/ std::filesystem::path("test12.v"));

constructor.setFirstPass(true);
constructor.parse(test12Path);
ASSERT_EQ(1, constructor.modules_.size());
auto test = constructor.modules_[0];
EXPECT_TRUE(test->ports_.empty());
EXPECT_TRUE(test->nets_.empty());
EXPECT_TRUE(test->assigns_.empty());
EXPECT_TRUE(test->instances_.empty());

constructor.setFirstPass(false);
constructor.parse(test12Path);
ASSERT_EQ(1, constructor.modules_.size());
EXPECT_TRUE(test->ports_.empty());
EXPECT_TRUE(test->assigns_.empty());
ASSERT_EQ(2, test->nets_.size());
ASSERT_EQ(3, test->instances_.size());

auto ins1 = test->instances_[0];
EXPECT_EQ("ins1", ins1.identifier_.name_);
EXPECT_FALSE(ins1.identifier_.escaped_);
EXPECT_EQ("CFG1", ins1.model_.name_);
EXPECT_TRUE(ins1.parameterAssignments_.empty());

auto mem = test->instances_[1];
EXPECT_EQ("mem_regfile_mem_regfile_0_0", mem.identifier_.name_);
EXPECT_FALSE(mem.identifier_.escaped_);
EXPECT_EQ("RAM64x18", mem.model_.name_);
EXPECT_TRUE(mem.parameterAssignments_.empty());

auto ins2 = test->instances_[2];
EXPECT_EQ("$$ins2@@", ins2.identifier_.name_);
EXPECT_FALSE(ins2.identifier_.escaped_);
EXPECT_EQ("CFG1", ins2.model_.name_);
EXPECT_TRUE(ins2.parameterAssignments_.empty());

EXPECT_EQ(3, test->defParameterAssignments_.size());
auto def0Path = test->defParameterAssignments_[0].first;
auto def0Value = test->defParameterAssignments_[0].second;
EXPECT_EQ(2, def0Path.size());
EXPECT_EQ("ins1", def0Path[0].name_);
EXPECT_FALSE(def0Path[0].escaped_);
EXPECT_EQ("INIT", def0Path[1].name_);
EXPECT_FALSE(def0Path[1].escaped_);
EXPECT_EQ("2'h1", def0Value.getString());
EXPECT_EQ(Expression::Type::NUMBER ,def0Value.value_.index());

auto def1Path = test->defParameterAssignments_[1].first;
auto def1Value = test->defParameterAssignments_[1].second;
EXPECT_EQ(2, def1Path.size());
EXPECT_EQ("mem_regfile_mem_regfile_0_0", def1Path[0].name_);
EXPECT_FALSE(def1Path[0].escaped_);
EXPECT_EQ("RAMINDEX", def1Path[1].name_);
EXPECT_FALSE(def1Path[1].escaped_);
EXPECT_EQ(Expression::Type::STRING ,def1Value.value_.index());
EXPECT_EQ("mem_regfile[7:0]%32%8%SPEED%0%0%MICRO_RAM", def1Value.getString());

auto def2Path = test->defParameterAssignments_[2].first;
auto def2Value = test->defParameterAssignments_[2].second;
EXPECT_EQ(2, def2Path.size());
EXPECT_EQ("$$ins2@@", def2Path[0].name_);
EXPECT_TRUE(def2Path[0].escaped_);
EXPECT_EQ("INIT", def2Path[1].name_);
EXPECT_FALSE(def2Path[1].escaped_);
EXPECT_EQ(Expression::Type::NUMBER ,def2Value.value_.index());
EXPECT_EQ("2'h2", def2Value.getString());
}
57 changes: 57 additions & 0 deletions test/NajaVerilogTest13.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2024 The Naja verilog authors <https://github.com/najaeda/naja-verilog/blob/main/AUTHORS>
//
// SPDX-License-Identifier: Apache-2.0

#include "gtest/gtest.h"

#include <filesystem>
#include <fstream>

#include "VerilogConstructor.h"

using namespace naja::verilog;

#include "VerilogConstructorTest.h"

#ifndef NAJA_VERILOG_BENCHMARKS
#define NAJA_VERILOG_BENCHMARKS "Undefined"
#endif

TEST(NajaVerilogTest13, test) {
VerilogConstructorTest constructor;
std::filesystem::path test13Path(
std::filesystem::path(NAJA_VERILOG_BENCHMARKS)
/ std::filesystem::path("benchmarks")
/ std::filesystem::path("test13.v"));

constructor.setFirstPass(true);
constructor.parse(test13Path);
ASSERT_EQ(1, constructor.modules_.size());
auto test = constructor.modules_[0];
ASSERT_EQ(27, test->ports_.size());
EXPECT_TRUE(test->nets_.empty());
EXPECT_TRUE(test->assigns_.empty());
EXPECT_TRUE(test->instances_.empty());

constructor.setFirstPass(false);
constructor.parse(test13Path);
ASSERT_EQ(1, constructor.modules_.size());
ASSERT_EQ(27, test->ports_.size());
ASSERT_EQ(67, test->nets_.size());
EXPECT_TRUE(test->assigns_.empty());
EXPECT_EQ(69, test->instances_.size());
#if 0
EXPECT_EQ("ins", instance.identifier_.name_);
EXPECT_EQ("MOD", instance.model_.name_);
EXPECT_EQ(2, instance.parameterAssignments_.size());
using Parameters = std::vector<std::pair<std::string, std::string>>;
Parameters parameters;
for (const auto& [parameter, value]: instance.parameterAssignments_) {
parameters.push_back({parameter, value});
}
EXPECT_EQ("elem10", parameters[0].first);
EXPECT_EQ("'o0", parameters[0].second);
EXPECT_EQ("elem11", parameters[1].first);
EXPECT_EQ("8'o84", parameters[1].second);
#endif
}
9 changes: 9 additions & 0 deletions test/VerilogConstructorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,13 @@ void VerilogConstructorTest::addAssign(
if (not inFirstPass()) {
currentModule_->assigns_.push_back(Assign(identifiers, expression));
}
}

void VerilogConstructorTest::addDefParameterAssignment(
const naja::verilog::Identifiers& hierarchicalParameter,
const naja::verilog::Expression& expression) {
if (not inFirstPass()) {
currentModule_->defParameterAssignments_.push_back(
VerilogConstructorTest::Module::DefParameterAssignment(hierarchicalParameter, expression));
}
}
Loading

0 comments on commit d10d53e

Please sign in to comment.