• Y
    ram: use asynchronous ram and change dpi-c function prototype · b3c864bd
    Yinan Xu 提交于
    Previously, the RAM is synchronous.
    However, due to verilator issues, the bug is hidden by Buffer that includes FFs.
    
    The buffer works as follows (simplified):
    always @(posedge clk)
      data_out <= data_form_ram_helper;
    
    data_from_ram_helper is given by (synchronous read):
    always @(posedge clk)
      ram_helper(raddr, data_from_ram_helper);
    
    At every positive edge, data_out should be assigned with data_from_ram_helper_old,
    and data_from_ram_helper should then be evaluated to the new value during the next clock cycle.
    However, verilator evaluates data_from_ram_helper first and then assigns it to data_out,
    that is, data_out is incorrectly assigned by data_from_ram_helper.
    
    For example, verilator gives the following sequence:
     raddr    data_from_ram_helper     data_out
      0               X                    X
      1             data[0]             data[0]
      2             data[1]             data[1]
    
    However, the correct values should be:
     raddr    data_from_ram_helper     data_out
      0               X                    X
      1             data[0]                X
      2             data[1]             data[0]
    
    Previously, due to the two bugs, ram works well.
    However, when it comes to multi-threading, they are put to two threads
    and since verilator does not find the relationship between raddr and data_from_ram_helper, data_out,
    they don't follow any specific evaluation order.
    Thus, multi-threaded emu randomly produces difftest error.
    
    To prove that verilator incorrectly evaluates DPI-C functions and related signals
    (however, it's also possible that we were using DPI-C functions incorrectly),
    one can change ram.v to
      always @(posedge clk) begin
        rdata <= ram_read_helper(raddr);
        ram_write_helper(waddr, wdata);
      end
    This should be the same with previous version of ram.v but it will give errors on difftest.
    
    To solve the issue, this commit makes two modifications:
    (1) make the ram asynchronous
    AXIWrapper requests the RAM to be asynchronous such that after ar.fire() we have eight cycles of rdata[0-7].
    (2) changes DPI-C function prototype to uint64_t ram_read_helper(uint64_t raddr)
    In this form, verilator detects the correct order between data_from_ram_helper and data_out evaluation.
    b3c864bd
ram.cpp 4.6 KB