veryl-lang / veryl

Veryl: A Modern Hardware Description Language
Other
505 stars 24 forks source link

Minimal support of unit test #550

Closed dalance closed 6 months ago

dalance commented 8 months ago

Unit test feature has many consideration points from simulation only description like delay and clocking to testing framework like UVM. I'll add minimal support of unit test because these consideration takes many time.

This proposal is syntax to include tests which are written by other languages. I think SystemVerilog and cocotb are appropriate candidates. Especially cocotb may be suitable with unit test because it doesn't required testbench module.

module ModuleA {
}

// Use SystemVerilog Test
#[testbench]
include_sv!("tb.sv");

#[test]
include_sv!("test1.sv");
#[test]
include_sv!("test2.sv");

// Use cocotb Test
//   cocotb doesn't require testbench module normally
#[test]
include_cocotb!("test1.py", ModuleA);
#[test]
include_cocotb!("test2.py", ModuleA);

veryl test command like below can be implemented if these syntax is added.

$ veryl test --sim verilator
$ veryl test --sim vcs

In the future, Veryl native test will be written like below:

#[testbench]
module tb {
}

#[test]
module test1 {
}

Related: #209 #164

saturn77 commented 7 months ago

I would also like to add the possible concept of a native Rust component as a DPI function to be called into the testbench.

Veryl compiler would process the .veryl file as normal, but also separate out any #Pragma__Rust DPI component into a compiled .so library so it could be linked with a verilator simulation.

An example testbench is shown below.

Note that this testbench is in the same Veryl module as the design. Also note the example uses psuedo-code for brevity. Finally the [#derive(dual_use)] macro would allow the struct to be translated to SystemVerilog but also used for Rust .so compile.

#[testbench]
// A standard type way 
import "DPI-C" function u32 triple_add (input u32 a, input u32 b, input u32 c);
// OR another way
import "DPI-Functions" // since the DPI function is attached to this module; Veryl would know to include it.

module tb {
// instantiate DUT as dut 
// clock generator code ...
// reset generator code ...
#[derive(dual_use, rust_component)]
struct Dut {
a : u32, 
b : u32, 
c : u32, 
result : u32, 
}

#Pragma__Rust
impl Dut { 
  pub fn triple_add (&mut self)  {
      self.result = (self.a + self.b + self.c) >> 5
  }
}
#Pragma_End

var dut : Dut;

// main loop 
while index < NUM {
    dut.a = some_value;
    dut.b = some_value_b;
    dut.c = some_value_c; 

    delay_some_clock_cycles;

    assert(dut.result == triple_add(some_value, some_value_b, some_value_c, "adder failure!");    

}
dalance commented 7 months ago

Looks good! If not only generating expected value but also whole testbench can be written by Rust, it seems to be better. Then verification framework like UVM can be constructed by Rust.

Syntax to embed other languages seems to be required too. Rust macro style will be like below?

inline!("rust") {
    // Rust code
}

inline!("sv") {
    // SystemVerilog code
}

inline!("cocotb") {
    // Python code
}

include!("rust", "test.rs");
include!("sv", "test.sv");
include!("cocotb", "test.py");

Additionally the inline!("sv") can be used in the design for rare case description which can't be represented by Veryl like inline assembly.

saturn77 commented 7 months ago

The inline! macro does look like a very good approach, and is also flexible with placing code within the original source file and also in external files. Very effective feature to handle multiple languages in one file.

The only issue that I would see is that if you inline python, the target output should be a separate file (versus the SystemVerilog that is transpiled from the Veryl code)

Perhaps some code syntax needs to be incorporated that tells Veryl where to place the output of inline! macro - and how to import it into the final SystemVerilog output. An idea is shown below.

inline!("rust") {
   #[derive(dpi_import)]  /// generate a .so shared object, but also import into final SystemVerilog target
   /// some function here 
}

However, if one wanted to manually create a large amount of DPI Rust functions in a separate file, this would not be necessary if the user wanted to manually import into a SystemVerilog file.

dalance commented 7 months ago

Sure. The inline keyword may not be suitable because it means a way for integration. Is it better that both language and integration way are specified like below?

embed!("sv", "inline") {
}

embed!("python", "cocotb") {
}

embed!("rust", "dpi_import") {
}
saturn77 commented 7 months ago

The embed! macro seems like a very good approach.

The syntax appears to be of the form "embed! (arg1=lang, arg2=file_target)"

This approach would allow for future expansion if needed, like for example

"embed! (arg1=lang, arg2=file_target, arg3=sim_target)"

So extending this to assertions:

embed!("sv", "inline", "assert") {
property req_gnt;
    @(posedge clk) req |=> gnt;
endproperty

assert_req_gnt: assert property (req_gnt) else $error("req not followed by gnt.");
}

The assert argument would be used if simulating with verilator, but something like arg3 could default to "none".

dalance commented 7 months ago

First of all, I'll try to implement the following two SystemVerilog tests. The second is cocotb integration.

// external SystemVerilog test
#[testbench]
include!("tb.sv", "inline");

#[test]
include!("test1.sv", "inline");

// embedded SystemVerilog test
#[testbench]
embed!("sv", "inline") {
    // SystemVerilog code
}

#[test]
embed!("sv", "inline") {
    // SystemVerilog code
}

// external cocotb test
#[test]
include!("test1.py", "cocotb");

// embedded cocotb test
#[test]
embed!("python", "cocotb") {
    // Python code
}
dalance commented 7 months ago

I explored the syntax implementation of embed. So I found the code blocks of foreign language should be marked more clearly. This is because editors supporting embedded language search the embedded code block by a simple regex.

For example, the following code block can be identified by {sv{ and }sv}, and these pattern probably don't appear in SystemVerilog code.

embed("inline") {sv{
    // SystemVerilog code
}sv}
saturn77 commented 7 months ago

That marking of the code blocks as you posted above appears very reasonable; such that someone adding this code in the main veryl file has a short and efficient syntax to mark code as sv.

Another idea is to use double under syntax as shown below. Perhaps the end sv symbol could be removed (as shown), and the double under syntax could be made as as "private attribute" in Veryl similar to Python.

embed("inline") { __sv__ {
    // SystemVerilog code
}}
dalance commented 7 months ago

A simple end pattern causes mistake of syntax highlighting engine because the engine usually uses simple regex pattern matching.

embed("inline") { __sv__ {
    assign a = {1{1'b1}};  // This `}}` will be identified as the end of code block
}}

So there is trade-off like "}sv} is ugly, but difficult to make mistake" and "}} is clean, but easy to make mistake". We need to explore an appropriate compromise.

// Markdown code block style
embed("inline") ```sv
    // SystemVerilog code

// C# Raw string literal style embed("inline") sv""" // SystemVerilog code """

saturn77 commented 7 months ago

The markdown style syntax seems a little more clear.

But I wanted to see what this would look like, and generated a quick example below where is an embedded rust snippet, that is called as DPI function in the embedded SV snippet.

The flow that I use most often is SystemVerilog --> Cocotb --> Verilator; however, after using this flow many times, I still prefer to have a "basic" testbench module that is pure SV. The example below takes a look at how this would work, where all of this would be in the #[test] portion of the Veryl main module.

#[test] 
//----------------------------
// Embed SV test case
//----------------------------
embed("inline") rust"""
// This is a DPI function, meant to be called
// by systemverilog testbench for immediate 
// verification of the adder result. The 
// no_mangle is used for C abi. 

#[no_mangle]
pub fn adder_check(arg_a : i32, arg_b : i32) -> i32 {
    arg_a + arg_b 
}
/// Note that the above function could be much more 
/// complicated; this is where the value of a DPI 
/// function comes in, e.g. something like a Taylor
/// series expansion or matrix multiplier i.e. 
#[no_mangle]
pub fn taylor_cosine_check (x : i32) -> i32 {
1 - 0.5*(x**2) + (1/24)*(x**4) + . . . . 
}
"""
embed("inline") sv"""

module adder_tb; 
/// Basic testbench for the adder in the alu 

// import the C-ABI Rust DPI function declared earlier 
import "DPI" function int adder_check(input int i_adder_arg_a, input int i_adder_arg_b);

logic i_clock, i_reset
int i_adder_arg_a, i_adder_arg_b; 
int o_adder_result; 
veryl_adder uAdd (.*);   // instantiate the DUT, transpiled from Veryl

initial begin
    i_clock <= 0;  
end

always begin 
    #10 i_clock <= !i_clock;
end

initial begin 
i_reset <= 0; 
#10 i_reset <= 1'b0; 
#40 i_reset <= 1'b1; 
#100 i_reset <= 1'b0; 
#100;
i_adder_arg_a = 10;
i_adder_arg_b = 35;
#2;
$assert (dut.o_adder_result == adder_check(adder_arg_a, adder_arg_b));  

$finish(2);
end
endmodule
"""
dalance commented 7 months ago

The current idea is like below:


// "dpi_rust" means that the code block will be compiled as Rust to a shared object,
// and the object will be loaded as a DPI module on RTL simulator.
embed("dpi_rust") rust"""
#[no_mangle]
pub fn adder_check(arg_a : i32, arg_b : i32) -> i32 {
    arg_a + arg_b 
}
"""

// `#[test]` means that the annotated block will be enabled at test only.
// If there are some annotated blocks, they are executed as individual tests.
// "inline" means that the code block will be expanded to the transpiled code as is.
#[test(test_name)]
embed("inline") sv"""
module test;
    import "DPI" function int adder_check(input int i_adder_arg_a, input int i_adder_arg_b);

    logic i_clock, i_reset
    int i_adder_arg_a, i_adder_arg_b; 
    int o_adder_result; 
    veryl_adder uAdd (.*);

    initial begin
        i_clock <= 0;  
    end

    always begin 
        #10 i_clock <= !i_clock;
    end

    initial begin 
        i_reset <= 0; 
        #10 i_reset <= 1'b0; 
        #40 i_reset <= 1'b1; 
        #100 i_reset <= 1'b0; 
        #100;
        i_adder_arg_a = 10;
        i_adder_arg_b = 35;
        #2;
        $assert (dut.o_adder_result == adder_check(adder_arg_a, adder_arg_b));  
        $finish(2);
    end
endmodule
"""
saturn77 commented 7 months ago

The combined #[test] and embed("inline") markers definitely convey the functionality and the overall syntax is clear, looks good.

dalance commented 7 months ago

I've rethought about code block syntax. """ or ``` can't check match of open and close, it causes syntax ambiguous. So {{{ and }}} seems to be better. If there is }}} in code block, } } } can be used instead of it to avoid syntax highlight error.

#[test(test_name)]
embed ("inline") sv{{{
// SystemVerilog code
assign a = {1{1{1'b1}}}; // highlight error, but not syntax error
assign a = {1{1{1'b1} } }; // no error on both highlight and syntax
}}}
dalance commented 7 months ago

One more minor update. The way of embedding is not an arbitrary string, but one of the pre-defined candidates. So embed(inline) may be better than embed("inline").

#[test(test_name)]
embed (inline) sv{{{
// SystemVerilog code
}}}
dalance commented 7 months ago

I've added veryl test command at #648. Currently Verilator and Synopsys VCS are supported.

$ veryl test testcases/veryl/48_test.veryl
[INFO ]   Processing file (testcases/veryl/48_test.veryl)
[INFO ]   Processing file (/home/hatta/.cache/veryl/dependencies/f2cfd55b8b535b4497ddd9984ae36e1d/src/delay.veryl)
[INFO ]   Processing file (/home/hatta/.cache/veryl/dependencies/535a83e749a9560ea19660a7a19f8eed/src/delay.veryl)
[INFO ]       Output filelist (/home/hatta/work/repos/veryl/veryl_testcase.f)
[INFO ]    Compiling test (test1)
[INFO ]    Executing test (test1)
[INFO ]    Succeeded test (test1)
$ veryl test --verbose testcases/veryl/48_test.veryl
[DEBUG]       Loaded metadata (/home/hatta/work/repos/veryl/Veryl.toml)
[DEBUG]       Loaded metadata (/home/hatta/.cache/veryl/dependencies/535a83e749a9560ea19660a7a19f8eed/Veryl.toml)
[DEBUG]       Loaded metadata (/home/hatta/.cache/veryl/dependencies/f2cfd55b8b535b4497ddd9984ae36e1d/Veryl.toml)
[DEBUG]       Loaded metadata (/home/hatta/.cache/veryl/dependencies/f2cfd55b8b535b4497ddd9984ae36e1d/Veryl.toml)
[DEBUG]        Found file (/home/hatta/.cache/veryl/dependencies/f2cfd55b8b535b4497ddd9984ae36e1d/src/delay.veryl)
[DEBUG]       Loaded metadata (/home/hatta/.cache/veryl/dependencies/535a83e749a9560ea19660a7a19f8eed/Veryl.toml)
[DEBUG]        Found file (/home/hatta/.cache/veryl/dependencies/535a83e749a9560ea19660a7a19f8eed/src/delay.veryl)
[INFO ]   Processing file (testcases/veryl/48_test.veryl)
[INFO ]   Processing file (/home/hatta/.cache/veryl/dependencies/f2cfd55b8b535b4497ddd9984ae36e1d/src/delay.veryl)
[INFO ]   Processing file (/home/hatta/.cache/veryl/dependencies/535a83e749a9560ea19660a7a19f8eed/src/delay.veryl)
[DEBUG]       Output file (/home/hatta/work/repos/veryl/testcases/sv/48_test.sv)
[DEBUG]       Output file (/home/hatta/work/repos/veryl/dependencies/veryl_sample2/src/delay.sv)
[DEBUG]       Output file (/home/hatta/work/repos/veryl/dependencies/veryl_sample1/src/delay.sv)
[INFO ]       Output filelist (/home/hatta/work/repos/veryl/veryl_testcase.f)
[INFO ]    Compiling test (test1)
[DEBUG]    Verilator log: make: Entering directory '/tmp/.tmp4aQPTZ/obj_dir'
[DEBUG]    Verilator log: g++ -Os  -I.  -MMD -I/home/hatta/local/share/verilator/include -I/home/hatta/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable    -DVL_TIME_CONTEXT   -c -o verilated.o /home/hatta/local/share/verilator/include/verilated.cpp
[DEBUG]    Verilator log: g++ -Os  -I.  -MMD -I/home/hatta/local/share/verilator/include -I/home/hatta/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable    -DVL_TIME_CONTEXT   -c -o verilated_threads.o /home/hatta/local/share/verilator/include/verilated_threads.cpp
[DEBUG]    Verilator log: /usr/bin/python3 /home/hatta/local/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include Vtest1.cpp Vtest1___024root__DepSet_h92c8f392__0.cpp Vtest1___024root__DepSet_h5799c38b__0.cpp Vtest1__main.cpp Vtest1___024root__Slow.cpp Vtest1___024root__DepSet_h5799c38b__0__Slow.cpp Vtest1__Syms.cpp > Vtest1__ALL.cpp
[DEBUG]    Verilator log: g++ -Os  -I.  -MMD -I/home/hatta/local/share/verilator/include -I/home/hatta/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable    -DVL_TIME_CONTEXT   -c -o Vtest1__ALL.o Vtest1__ALL.cpp
[DEBUG]    Verilator log: echo "" > Vtest1__ALL.verilator_deplist.tmp
[DEBUG]    Verilator log: Archive ar -rcs Vtest1__ALL.a Vtest1__ALL.o
[DEBUG]    Verilator log: g++    verilated.o verilated_threads.o Vtest1__ALL.a    -pthread -lpthread   -o Vtest1
[DEBUG]    Verilator log: rm Vtest1__ALL.verilator_deplist.tmp
[DEBUG]    Verilator log: make: Leaving directory '/tmp/.tmp4aQPTZ/obj_dir'
[DEBUG]    Verilator log: - V e r i l a t i o n   R e p o r t: Verilator 5.024 2024-04-05 rev v5.024-42-gc561fe8ba
[DEBUG]    Verilator log: - Verilator: Built from 0.030 MB sources in 5 modules, into 0.018 MB in 7 C++ files needing 0.000 MB
[DEBUG]    Verilator log: - Verilator: Walltime 4.630 s (elab=0.000, cvt=0.003, bld=4.622); cpu 0.000 s on 1 threads; alloced 8.254 MB
[INFO ]    Executing test (test1)
[DEBUG]    Verilator log: hello
[DEBUG]    Verilator log: - /home/hatta/work/repos/veryl/testcases/sv/48_test.sv:9: Verilog $finish
[DEBUG]    Verilator log: - S i m u l a t i o n   R e p o r t: Verilator 5.024 2024-04-05
[DEBUG]    Verilator log: - Verilator: $finish at 1ps; walltime 0.001 s; speed 0.000 s/s
[DEBUG]    Verilator log: - Verilator: cpu 0.000 s on 1 threads; alloced 249 MB
[INFO ]    Succeeded test (test1)
[DEBUG]      Elapsed time (4759 milliseconds)
$ veryl test --sim vcs testcases/veryl/48_test.veryl
[INFO ]     Removing dependency (https://github.com/veryl-lang/sample @ 0.10.0)
[INFO ]     Removing dependency (https://github.com/veryl-lang/sample @ 0.9.0)
[INFO ]   Processing file (testcases/veryl/48_test.veryl)
[INFO ]       Output filelist (/home/hatta/work/repos/veryl/veryl_testcase.f)
[INFO ]    Compiling test (test1)
[INFO ]    Executing test (test1)
Error: "/home/hatta/work/repos/veryl/testcases/sv/48_test.sv", 8: test1.unnamed$$_0: at time 0
aaa

[WARN ]       Failed test (test1)
$ veryl test --sim vcs --verbose testcases/veryl/48_test.veryl
[DEBUG]       Loaded metadata (/home/hatta/work/repos/veryl/Veryl.toml)
[INFO ]   Processing file (testcases/veryl/48_test.veryl)
[DEBUG]       Output file (/home/hatta/work/repos/veryl/testcases/sv/48_test.sv)
[INFO ]       Output filelist (/home/hatta/work/repos/veryl/veryl_testcase.f)
[INFO ]    Compiling test (test1)
[DEBUG]          VCS log: Info: [VCS_SAVE_RESTORE_INFO] ASLR (Address Space Layout Randomization) is detected on the machine. To enable $save functionality, ASLR will be switched off and simv re-executed.
[DEBUG]          VCS log: Please use '-no_save' simv switch to avoid this.
[DEBUG]          VCS log:                          Chronologic VCS (TM)
[DEBUG]          VCS log:          Version U-2023.03_Full64 -- Thu Apr 11 17:02:38 2024
[DEBUG]          VCS log:
[DEBUG]          VCS log:                     Copyright (c) 1991 - 2023 Synopsys, Inc.
[DEBUG]          VCS log:    This software and the associated documentation are proprietary to Synopsys,
[DEBUG]          VCS log:  Inc. This software may only be used in accordance with the terms and conditions
[DEBUG]          VCS log:  of a written license agreement with Synopsys, Inc. All other use, reproduction,
[DEBUG]          VCS log:    or distribution of this software is strictly prohibited.  Licensed Products
[DEBUG]          VCS log:      communicate with Synopsys servers for the purpose of providing software
[DEBUG]          VCS log:     updates, detecting software piracy and verifying that customers are using
[DEBUG]          VCS log:     Licensed Products in conformity with the applicable License Key for such
[DEBUG]          VCS log:   Licensed Products. Synopsys will use information gathered in connection with
[DEBUG]          VCS log:     this process to deliver software updates and pursue software pirates and
[DEBUG]          VCS log:                                    infringers.
[DEBUG]          VCS log:
[DEBUG]          VCS log:  Inclusivity & Diversity - Visit SolvNetPlus to read the "Synopsys Statement on
[DEBUG]          VCS log:             Inclusivity and Diversity" (Refer to article 000036315 at
[DEBUG]          VCS log:                         https://solvnetplus.synopsys.com)
[DEBUG]          VCS log:
[DEBUG]          VCS log: Parsing design file '/home/hatta/work/repos/veryl/testcases/sv/48_test.sv'
[DEBUG]          VCS log: Top Level Modules:
[DEBUG]          VCS log:        veryl_testcase_Module48
[DEBUG]          VCS log:        test1
[DEBUG]          VCS log: No TimeScale specified
[DEBUG]          VCS log: Starting vcs inline pass...
[DEBUG]          VCS log:
[DEBUG]          VCS log: 2 modules and 0 UDP read.
[DEBUG]          VCS log: recompiling module veryl_testcase_Module48
[DEBUG]          VCS log: recompiling module test1
[DEBUG]          VCS log: Both modules done.
[DEBUG]          VCS log: rm -f _cuarc*.so _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so
[DEBUG]          VCS log: if [ -x ../simv ]; then chmod a-x ../simv; fi
[DEBUG]          VCS log: g++  -o ../simv      -rdynamic  -Wl,-rpath='$ORIGIN'/simv.daidir -Wl,-rpath=./simv.daidir -Wl,-rpath=/storage/eda/tools/synopsys/VCS/U-2023.03/linux64/lib -L/storage/eda/tools/synopsys/VCS/U-2023.03/linux64/lib  -Wl,-rpath-link=./  /usr/lib64/libnuma.so.1   objs/amcQw_d.o   _319973_archive_1.so  SIM_l.o      rmapats_mop.o rmapats.o rmar.o rmar_nd.o  rmar_llvm_0_1.o rmar_llvm_0_0.o            -lvirsim -lerrorinf -lsnpsmalloc -lvfs    -lvcsnew -lsimprofile -luclinative /storage/eda/tools/synopsys/VCS/U-2023.03/linux64/lib/vcs_tls.o   -Wl,-whole-archive  -lvcsucli    -Wl,-no-whole-archive          /storage/eda/tools/synopsys/VCS/U-2023.03/linux64/lib/vcs_save_restore_new.o -ldl  -lc -lm -lpthread -ldl
[DEBUG]          VCS log: ../simv up to date
[DEBUG]          VCS log: CPU time: .252 seconds to compile + .193 seconds to elab + .223 seconds to link
[INFO ]    Executing test (test1)
[DEBUG]          VCS log: Info: [VCS_SAVE_RESTORE_INFO] ASLR (Address Space Layout Randomization) is detected on the machine. To enable $save functionality, ASLR will be switched off and simv re-executed.
[DEBUG]          VCS log: Please use '-no_save' simv switch to avoid this.
[DEBUG]          VCS log: Chronologic VCS simulator copyright 1991-2023
[DEBUG]          VCS log: Contains Synopsys proprietary information.
[DEBUG]          VCS log: Compiler version U-2023.03_Full64; Runtime version U-2023.03_Full64;  Apr 11 17:02 2024
[DEBUG]          VCS log: hello
[DEBUG]          VCS log: "/home/hatta/work/repos/veryl/testcases/sv/48_test.sv", 8: test1.unnamed$$_0: started at 0s failed at 0s
[DEBUG]          VCS log:       Offending '0'
[DEBUG]          VCS log: Error: "/home/hatta/work/repos/veryl/testcases/sv/48_test.sv", 8: test1.unnamed$$_0: at time 0
[DEBUG]          VCS log: aaa
[DEBUG]          VCS log: $finish called from file "/home/hatta/work/repos/veryl/testcases/sv/48_test.sv", line 9.
[DEBUG]          VCS log: $finish at simulation time                    0
[DEBUG]          VCS log:            V C S   S i m u l a t i o n   R e p o r t
[DEBUG]          VCS log: Time: 0
[DEBUG]          VCS log: CPU Time:      0.220 seconds;       Data structure size:   0.0Mb
[DEBUG]          VCS log: Thu Apr 11 17:02:39 2024
[WARN ]       Failed test (test1)
[DEBUG]      Elapsed time (1353 milliseconds)
dalance commented 7 months ago

I'll close this issue after merging #648, and the remaining issues are moved to #658 and #659.

saturn77 commented 7 months ago

That is excellent work, look forward to testing this feature with verilator.

dalance commented 6 months ago

I've merged #648. Now Verilator, VCS and Vivado Simulator are supported. I'll release v0.9.0 after document update.