3
votes

This is a slightly modified version of the HelloWorld.scala example from https://github.com/freechipsproject/chisel3/wiki/Frequently-Asked-Questions

// say hello                                                                     
package HelloWorld

import chisel3._

class HelloWorld extends Module {
  val io = IO(new Bundle{
    val halt = Output(Bool())
    val may_halt = Input(Bool())
  })
  printf("hello, world!\n");
  when (io.may_halt) {
    io.halt := true.B
  } .otherwise {
    io.halt := false.B
  }
}


// code for building HelloWorld                                                  
object HelloWorld extends App {
  chisel3.Driver.execute(args, () => new HelloWorld)
}

I build it using chisel3 then verilator to generate C++. Here is the interesting part of the C++ harness:

VHelloWorld *top;               // Instantiation of module                       

int main(int argc, char** argv) {
  Verilated::commandArgs(argc, argv); // Remember args                           

  top = new VHelloWorld;              // Create instance                         

  printf("eval loop start\n");
  long long cycle = 0;
  for (; !Verilated::gotFinish(); ++cycle) {
    printf("\tcycle: %lld\n", cycle);
    if (2 <= cycle) {
      printf("\t\tput io_may_halt = 1\n");
      top->io_may_halt = 1;
    }
    top->eval();                      // Evaluate model                          
    if (top->io_halt) {
      printf("\t\tgot an io_halt, so halting\n");
      break;                   // halt when we get the signal to do so           
    }
  }

  printf("eval loop stop\n");
  top->final();                       // Done simulating                         

  delete top;                         // (Though this example doesn't get here)  
  return 0;
}

I run it for a few cycles before signaling it to halt. Yet the "hello, world!" message never comes out.

HelloWorld.cppdir/HelloWorld.exe
eval loop start
    cycle: 0
    cycle: 1
    cycle: 2
        put io_may_halt = 1
        got an io_halt, so halting
eval loop stop
1
I tryied to emit verilog source. And has I can see you have to define macro `PRINTF_COND. You can define it in your verilator compile command line I think. - FabienM
But I have a strange file name in printf verilog command: $fwrite(32'h80000002,"hello, world!\n"); - FabienM
I figured it out: the printf() only happens on a rising clock, so the C++ harness wrapped around the verilator code must explicitly (1) drive the clock low, (2) eval(), (2) drive the clock high, (3) eval(), and then the printf() will print. (Actually I am not sure (2) is required, but it would be weird to not do it.). Note that the verilator examples do not show the C++ harness doing this. - Daniel
You can post an answer to your own question. I suggest doing so to make it clear that the question has in fact been answered. - Scott McPeak

1 Answers

3
votes

I figured it out: the printf() only happens on a rising clock, so the C++ harness wrapped around the verilator code must explicitly (1) drive the clock low, (2) eval(), (2) drive the clock high, (3) eval(), and then the printf() will print. (Actually I am not sure (2) is required, but it would be weird to not do it.).

I had said in my comment above that the verilator examples do not show the C++ harness doing this, however in a more complex example and in a more complex way, they do.