GithubHelp home page GithubHelp logo

veryl-lang / veryl Goto Github PK

View Code? Open in Web Editor NEW
408.0 9.0 19.0 69.74 MB

Veryl: A Modern Hardware Description Language

License: Other

Rust 98.65% Makefile 0.12% SystemVerilog 1.00% TypeScript 0.19% JavaScript 0.05%
rtl rust systemverilog verilog

veryl's People

Contributors

dalance avatar dependabot[bot] avatar github-actions[bot] avatar jsinger67 avatar nblei avatar rahulk4102 avatar ysawc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

veryl's Issues

variable declaration / assign declaration reconsideration

variable declaration and assign declaration seems to be similar. It may be confusable.
Additionally, visilibity of variable declaration may be less than other declarations because it doesn't have any keyword.

// variable declaration
a: logic [10];

// assign declaration
assign a = 1;

// assign declaration with type
assign a: logic [10] = 1;

Alternative idea.

// variable declaration
let a: logic [10];

// variable declaration with binding
let a: logic [10] = 1;

import/export declaration

import PackageA::Item;
import PackageB::*;

module's import like below causes parsing and formatting complexity.

module ModuleA import PackageA::* (
) {
}

Instead of supporting module's import, is it sufficient like below?

import PackageA::*;

module ModuleA (
) {
}

instantiation notation

The current syntax is below:

b ::: ModuleB #(
    // parameter override
} {
    // port connection
}

The reason of ::: is

  • : is the same as variable declaration
  • :: is the same as name space path separator

If let like #7 is introduced, : can be used.

Or keyword is good?

inst b : ModuleB #(
) {
}

case statement

always_ff (clk) {
    case x {
        0: a = 1;
        1: a = 2;
        2: {
            a = 3;
            b = 4;
        }
        default: a = 4;
    }
}

enum value range check

The veryl build command generates SV code even if an enum value is outrange.

orignal VL code:

module test {
  enum e_foo_bar: logic [1] {
    foo = 0,
    bar = 2
  }
}

generated SV code:

module test ;
    typedef enum logic [1-1:0] {
        foo = 0,
        bar = 2
    } e_foo_bar;
endmodule

The verly command needs to check range of enum values because this causes a compile error.

Error-[ENUMRANGE] Enum label outside value range
testbench.sv, 7
  The enum label 'BAR' has the value 2 which is outside the range of the base 
  type of the enum 'e_foo_bar', which is 1 bit unsigned.
  If this is indeed the intended value, consider expressing it as as sized 
  literal of the same width and signedness as the enum base type.

Generated SV code with comments is illegal

The build commmand genertes illegal SV code from VL code with comments.
These comments are put:

  • between else and if of else-if statement
  • before condition of if statement

These are an exaple code and generated SV code:

module test_module (
 i_clk: 	input logic,
 i_rst_n:	input logic,
 i_up:	input logic,
 i_down:    input logic,
 o_count:	output logic[8]
) {
  count: 	logic[8];
  up_down: 	logic[2];

  always_comb {
    up_down = (i_up << 1) | i_down;
  }

  always_ff (i_clk, i_rst_n) {
    if_reset {
      count = 0;
    }
    else // count up
    if up_down == 2'b10 {
      count = count + 1;
    }
    else if // count down
    up_down == 2'b01 {
      count = count - 1;
    }
  }
}
module test_module (
    input  logic         i_clk  ,
    input  logic         i_rst_n,
    input  logic         i_up   ,
    input  logic         i_down ,
    output logic [8-1:0] o_count
) ;
    logic [8-1:0] count  ;
    logic [2-1:0] up_down;
    always_comb begin
        up_down = (i_up << 1) | i_down;
    end
    always_ff @ (posedge i_clk, negedge i_rst_n) begin
        if (!i_rst_n) begin
            count <= 0;
        end else // count up if (up_down == 2'b10) begin
            count <= count + 1;
        end else if // count down (up_down == 2'b01) begin
            count <= count - 1;
        end
    end
endmodule

if (up_down == 2'b10) begin and (up_down == 2'b01) begin are hidden because they are comments.
I think /* */ comment format should be used for inserted comments.

Using SV sytem functions

SystemVerilog has useful sytem functions, such as $clog2.
I'd like to use SV system functions within VL code but I got a syntax error.

Error: parol_runtime::unexpected_token

  × Unexpected token: LA(1) (Error)
   ╭─[test.vl:3:1]
 3 │   parameter MAX_COUNT:   u32 = 8,
 4 │   parameter COUNT_WIDTH: u32 = $clog2(MAX_COUNT + 1)
   ·                                ┬
   ·                                ╰── Unexpected token
 5 │ )(
   ╰────
  help: Unexpected token

Does not support such feature?

improve syntax error

The current syntax error is from parol's error.
It may not be suitable with language server.

Not report a syntax error when parsing VL code including syntax error

I got a problem that veryl build command does not report a error when parsing VL code including a syntax error.

How to reproduce:

Run veryl build command with following VL code.

module test_module (
 i_clk: input logic,
 i_rst_n: input logic,
 i_d: input logic,
 o_d: output logic
) {
  d: logic;

  always_comb {
    o_d = d;
  }

  always_ff (i_clk, i_rst_n) {
    if_rest {
      d = 0;
    }
    else {
      d = i_d;
    }
  }
}

I expect the command reports a syntax error because there is a typo (if_reset -> if_rest).
But the command completes SV code generation.

var / inst statement

let statement for variable declaration and module/interface instantiation.

// variable declaration
let value_a: logic [10];

// assignment after declaration
assgin value_a = 1;

// variable declaration with assignment
let value_b: logic [10] = 1;

// module instantiation
let module_a: inst moduleA;

// interface instantiation
let if_a: inst interfaceA;

// interface array
let if_b: inst interfaceB [10];

// module with parameter and port connection
let module_b: inst moduleB #(
    a,
    b: 10,
) {
    a,
    b: 10,
};


project definition like Cargo.toml

The definition will contain..

  • project name
  • version ( semver? )
  • license
  • configuration
    • default clk/rst porality
    • format configuration
    • output location
  • dependencies

Loop statement support

My existing SV code includes loop statements such as for loop and while loop so I'd like Veryl to support these statements.

I think SV (C lang) style for loop statement is very bother notation because there are many similar code for example int i = 0; and ++i;. So I'd like you to introduce simple notation.

refactoring identifier separator

Now :: and . are used as identifier separator.

import PackageA::A;

module ModuleA (
    a: input PackageA::struct_t,
    b: modport InterfaceA.master,
) {
    assign a.memberA = b.funcA(1);
    assign b.portA = PackageA::parameterA;
}

Almost . is used for [instance/variable identifier].[member identifier] and :: is used for [type/definition identifier]::[member identifier].
But InterfaceA.master seems to be inconsistent.

How about InterfaceA::master? and is there another case?

import PackageA::A;

module ModuleA (
    a: input PackageA::struct_t,
    b: modport InterfaceA::master,
) {
    assign a.memberA = b.funcA(1);
    assign b.portA = PackageA::parameterA;
}

modport/interface at port declaration

Is adding modport in port declaration of module declaration more explicit?

module ModuleA (
    a: input   logic,
    b: output  logic,
    c: modport InterfaceA.master,
) {
}

Part select using position and width

Part select using position and width (a[pos+:WIDTH]/a[pos-:WIDTH]) is useful feature.
So I'd like you to import this feature to veryl.

In addition, I think part select using index and width like below is a code showing often.

b = a[2*i+:2];

Therefore, I'd like you to introduce a syntax sugger for this code like below.

b = a[2, i]; // a[2*i+:2]

allow variable forward reference

SystemVerilog don't allow variable forward reference.
It causes distributed variable declarations which are included in the same group.

// Move the declaration to the top of code to avoid forward reference
let b2: logic;

// Module A
let a0: logic = b2 + 1;

// Module B
let b0: logic;
let b1: logic;
// let b2: logic <- This position is suitable

Unlike general programming language, RTL don't have code order.
So variable forward reference is natural in RTL.

Need to insert type cast

Inserting type cast is needed when LHS of assignment is enum variable and RHS of assignment is non-enum value.
If no type cast is inserted then EDA tool may report a warning like below.

Warning-[ENUMASSIGN] Illegal assignment to enum variable
testbench.sv, 13
test, "foo_bar = 0;"
  Only expressions of the enum type can be assigned to an enum variable. 
  The type int is incompatible with the enum 'e_foo_bar'
  Expression: 0
  Use the static cast operator to convert the expression to enum type.

However generated SV code does not include type cast.

orignal VL code:

module test {
  enum e_foo_bar: logic [1] {
    foo = 0,
    bar = 1
  }

  let foo_bar: e_foo_bar;
  always_comb {
    foo_bar = foo;
    foo_bar = bar;
    foo_bar = 0;
    foo_bar = 1;
  }
}

generated SV code:

module test ;
    typedef enum logic [1-1:0] {
        foo = 0,
        bar = 1
    } e_foo_bar;
    e_foo_bar foo_bar ;
    always_comb begin
        foo_bar = foo;
        foo_bar = bar;
        foo_bar = 0;
        foo_bar = 1;
    end
endmodule

Useage of tri keyword

I think in Varyl tri keyword is used as a data type.
On the other hand, in SystemVerilog the tri keyword is used to show that a declared element is a wire and to allow the element to have multiple drivers. Therefore, its usage is similar to the usage of the var keyword.

package foo_pkg;
  typedef enum logic {
    FOO_0,
    FOO_1
  } e_foo;
endpackage

module foo_sub
  import foo_pkg::*;
(
  inout tri e_foo io_foo
);
  assign io_foo = FOO_0;
endmodule

module foo_top;
  import foo_pkg::*;

  tri e_foo foo;
  assign foo = FOO_1;
  foo_sub u_sub (foo);
endmodule

I think Veryl should also use the tri like the var keyword.

concatenation

Verilog style

assign a = {x, 1'b1, y[10:0]};
assign a = {{10{x}}, {10{y}}}; 

Repeat style has some problems.

  • too many {}
  • parsing difficulty (concatenation can't detect until consuming expression of repeating number)

To resolve the second, repeating number should be after repeating operator.
Repeating operator should be keyword or symbol?

assign = a { x repeat 10, y repeat 10};
assign = a { x @ 10, y @ 10};

forbid parameter declaration in module

If there are parameter declarations in module dispersedly, user of module can't find overridable paramaters easily.

module #(
    parameter A: u32 = 1,
) {
    localparam C: u32 = 1;

    // some descriptions...

    parameter B: u32 = 1;  // <- forbid This

}

Incorrect if block scope

Currently, the following code causes duplicated identifier error.
Each claure of if declaration should have independent scope.

if a ==1 :label {
    let a: logic;
} else {
    let a: logic;
}

remove () in always_ff

Removing () in always_ff is uniform as if statement.

always_ff (clk) {
}
always_ff (clk, rst) {
}
always_ff (posedge clk, async_low rst) {
}

to

always_ff clk {
}
always_ff clk, rst {
}
always_ff posedge clk, async_low rst {
}

enum member scope

enum member of SystemVerilog has the same scope of the enum.

enum EnumA {
    memberA,
    memberB,
}

var a: EnumA = memberA;

This causes name conflict easily.
How about EnumA::memberA.

enum EnumA: logic {
    memberA,
    memberB,
}

var a: EnumA = EnumA::memberA;

In translated SystemVerilog, prefix is added to avoid conflict.

typedef enum  logic {
    EnumA_memberA,
    EnumA_memberB,
} EnumA;

EnumA a;
assign a = EnumA_memberA;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.