OpenXiangShan / difftest

Modern co-simulation framework for RISC-V CPUs
Mulan Permissive Software License, Version 2
118 stars 67 forks source link

[BUG] The emu compilation time never changed after first build #509

Open cebarobot opened 5 days ago

cebarobot commented 5 days ago

Related component: build

Describe the bug

When running emu, it would print the emu compilation time at first. But if I modify any RTL code or c/c++ code and rebuild the emu, the compilation time which emu prints never changed. It is always the time when the project was built for the first time.

To Reproduce Steps to reproduce the behavior:

  1. Clone the XiangShan repository and initialize it.
    $ git clone https://github.com/OpenXiangShan/XiangShan.git
    $ cd XiangShan
    $ export NOOP_HOME=$(pwd)
    $ make init
  2. Build
    $ make emu CONFIG=MinimalConfig -j64
  3. Run emu and get an compilation time. Also check the build/emu file timestamp.
    $ ./build/emu
    emu compiled at Nov 17 2024, 19:59:39
    $ ls -l ./build/emu
    -rwxr-xr-x 1 ceba ceba 89827624 Nov 17 20:01 ./build/emu
  4. Modify any source code files, for example, src/main/scala/xiangshan/backend/fu/Alu.scala
    $ git diff src/main/scala/xiangshan/backend/fu/Alu.scala
    diff --git a/src/main/scala/xiangshan/backend/fu/Alu.scala b/src/main/scala/xiangshan/backend/fu/Alu.scala
    index b5ac11039..99a8e6376 100644
    --- a/src/main/scala/xiangshan/backend/fu/Alu.scala
    +++ b/src/main/scala/xiangshan/backend/fu/Alu.scala
    @@ -62,7 +62,7 @@ class LeftShiftWordModule(implicit p: Parameters) extends XSModule {
     val sllw = Output(UInt((XLEN/2).W))
     val revSllw = Output(UInt((XLEN/2).W))
    })
    -  io.sllw := io.sllSrc << io.shamt
    +  io.sllw := io.sllSrc >> io.shamt
    io.revSllw := io.sllSrc << io.revShamt
    }
  5. Build again
    $ make emu CONFIG=MinimalConfig -j64
  6. Run emu again and get the same compilation time. Also check the build/emu file timestamp.
    $ ./build/emu
    emu compiled at Nov 17 2024, 19:59:39
    $ ls -l ./build/emu
    -rwxr-xr-x 1 ceba ceba 89811240 Nov 17 20:36 ./build/emu

Expected behavior The emu compiled at timestamp should reflect the most recent compilation time. Or at least update whenever the source code (Verilog) changes.

Screenshots After fisrt build: image

After a modification of source code and second build: image

What you expect us (DiffTest developers) to do for you

The emu compiled at timestamp is printed in function common_init_without_assertion in C++ file common.cpp:

  Info("%s compiled at %s, %s\n", elf_name, __DATE__, __TIME__);

It use two marco: __DATE__ and __TIME__. These two macros will be replaced with their actual values during the preprocessing step of compiling common.cpp. After preprocessing, such line code may change to: (Actually, Info should also be replaced, but it does not matter here).

  Info("%s compiled at %s, %s\n", elf_name, "Nov 17 2024", "19:59:39");

Therefore, after compilation, "Nov 17 2024", "19:59:39" was hardcoded into common.o. Unless recompile the common.cpp, function common_init_without_assertion would always print out emu compiled at Nov 17 2024, 19:59:39.

Now let see whether common.cpp will be recompiled.

The compilation of common.cpp is controled by VSimTop.mk, the makefile generate by verilator. The result common.o has these dependency:

# From VSimTop.mk
common.o: /abs-path-to/difftest/src/test/csrc/common/common.cpp
# From common.d, including all header files included by common.cpp
common.o: \
  /abs-path-to/difftest/src/test/csrc/common/common.cpp \
  /abs-path-to/difftest/src/test/csrc/common/common.h \
  /abs-path-to/difftest/config/config.h \
  /abs-path-to/build/generated-src/diffstate.h

It's obviously that, there is no verilog files and c++ files generated from verilog files in denpency.

Additional context

Also see #508.

poemonsense commented 5 days ago

How about cleaning the build directory before running verilator? We can run clean_obj when building $(EMU_MK)

Then the common.cpp will always be re-compiled once the DUT changes.

cebarobot commented 5 days ago

How about cleaning the build directory before running verilator? We can run clean_obj when building $(EMU_MK)

Then the common.cpp will always be re-compiled once the DUT changes.

I think the overhead is huge. In that way, more than 25 cpp files need to be recompiled...

poemonsense commented 5 days ago

How about cleaning the build directory before running verilator? We can run clean_obj when building $(EMU_MK) Then the common.cpp will always be re-compiled once the DUT changes.

I think the overhead is huge. In that way, more than 25 cpp files need to be recompiled...

Compared to recompiling the DUTs, compiling only 25 C++ files is minor. I believe the current bottleneck is at compiling Verilater-generated C++ files?

Or, how about cleaning only common.o, if you don't want recompiling 25 files?