nlsynth / karuta

Karuta HLS Compiler: High level synthesis from prototype based object oriented script language to RTL (Verilog) aiming to be useful for FPGA development.
Other
99 stars 4 forks source link

How to write an infinite loop ? #2

Closed ikwzm closed 8 years ago

ikwzm commented 8 years ago

I wrote fib.n

object Fib = Kernel.clone();
object Global.Fib = Fib;

int Fib.param  = 0;
int Fib.result = 0;

def Fib.fib(){
  int curr;
  int next;
  int prev;
  int i;
  curr = 0;
  next = 1;
  for (i = 0; i < param; ++i) {
    prev = curr;
    curr = next;
    next = next + prev;
  }
  result = curr;
}

def Fib.main() {
  int *req = 0;
  int *in  = 1;
  int *out = 2;
  while(1) {
    if (*req != 0) {
      param = *in;
      fib();
      *out = result;
    }
  }
}
if (Env.isMain()) {
  Fib.setDump("./tmp/fib");
  Fib.compile();
  Fib.writeHdl("fib.v");
  Fib.writeHdl("fib.cpp");
}

generated fib.v

// 0.1.9

module mod_main(clk, rst, addr_o, write_en_o, data_o, data_i);
  input clk;
  input rst;
  // EXTERNAL_RAM
  output [31:0] addr_o;
  output write_en_o;
  output [31:0] data_o;
  input [31:0] data_i;

  reg [31:0] addr_o;
  reg write_en_o;
  reg [31:0] data_o;

  reg [31:0]  r1_main;
  reg [31:0]  r3_main;
  reg [-1:0]  r7_main;
  reg  r6_main;
  reg [31:0]  r14_main;
  reg [31:0]  reg_t3_v1;
  reg [31:0]  reg_t2_v3;
  reg [31:0]  reg_t4_v4;
  reg [31:0]  reg_t4_v5;
  reg [31:0]  reg_t3_v6;
  reg [31:0]  reg_t2_v9;
  reg  r6_main_v17;
  reg [31:0]  r9_main_v18;
  reg  reg_t9;
  reg  reg_t10;
  wire  wire_t12;
  wire  wire_t13;
  wire [31:0]  wire_t14;
  wire [31:0]  wire_t15;
  wire [31:0]  wire_t16;
  wire  wire_t17;
  wire [31:0]  wire_t18;
  wire [31:0]  wire_t19;

  // declare state begin
 `define S_0 0
 `define S_65 65
 `define S_3 3
 `define S_13 13
 `define S_66 66
 `define S_20 20
 `define S_63 63
 `define S_50 50
 `define S_54 54

  reg [7:0] cur_st;
  // declare state end

  // resources begin
  // branch_1

  // eq_5

  // inv_6

  // gt_8
  wire gt_8_d0;
  wire [31:0] gt_8_s0;
  wire [31:0] gt_8_s1;
  assign gt_8_s0 = (cur_st == `S_50) ? r9_main_v18 : (0);
  assign gt_8_s1 = (cur_st == `S_50) ? wire_t16 : (0);
  assign gt_8_d0 = (gt_8_s0 > gt_8_s1);

  // add_9
  wire [31:0] add_9_d0;
  wire [31:0] add_9_s0;
  wire [31:0] add_9_s1;
  assign add_9_s0 = (cur_st == `S_54) ? reg_t3_v1 : (0);
  assign add_9_s1 = (cur_st == `S_54) ? reg_t2_v3 : (0);
  assign add_9_d0 = (add_9_s0 + add_9_s1);

  // selector_12

  // sram_if_13

  // add_15
  wire [31:0] add_15_d0;
  wire [31:0] add_15_s0;
  wire [31:0] add_15_s1;
  assign add_15_s0 = (cur_st == `S_54) ? r1_main : (0);
  assign add_15_s1 = (cur_st == `S_54) ? 32'd1 : (0);
  assign add_15_d0 = (add_15_s0 + add_15_s1);

  // resources end

  // insn wires begin
  assign o_insn_117_0 = data_i;
  wire [-1:0] o_insn_118_0; // id:118
  assign o_insn_118_0 = data_i;
  wire o_insn_5_0; // id:5
  assign o_insn_5_0 = r7_main==32'd0;
  wire o_insn_6_0; // id:6
  assign o_insn_6_0 = !wire_t12;
  assign o_insn_120_0 = data_i;
  wire [31:0] o_insn_121_0; // id:121
  assign o_insn_121_0 = data_i;
  assign o_insn_123_0 = data_i;
  wire [31:0] o_insn_110_0; // id:110
  assign o_insn_110_0 = reg_t9 ? r14_main : reg_t3_v6;
  wire [31:0] o_insn_113_0; // id:113
  assign o_insn_113_0 = reg_t10 ? reg_t2_v9 : r3_main;
  wire [31:0] o_insn_116_0; // id:116
  assign o_insn_116_0 = r6_main ? reg_t4_v5 : reg_t4_v4;
  wire o_insn_78_0; // id:78
  assign o_insn_78_0 = gt_8_d0;
  wire [31:0] o_insn_85_0; // id:85
  assign o_insn_85_0 = add_9_d0;
  wire [31:0] o_insn_89_0; // id:89
  assign o_insn_89_0 = add_15_d0;
  // insn wires end

  // insn result wires begin
   assign wire_t12 = o_insn_5_0;
   assign wire_t13 = o_insn_6_0;
   assign wire_t14 = o_insn_110_0;
   assign wire_t15 = o_insn_113_0;
   assign wire_t16 = o_insn_116_0;
   assign wire_t17 = o_insn_78_0;
   assign wire_t18 = o_insn_85_0;
   assign wire_t19 = o_insn_89_0;
  // insn result wires end

  // sub state regs begin
  // sub state regs end
  always @(posedge clk) begin
    if (rst) begin
      cur_st <= `S_0;
    end else begin
`ifdef NLI_DEBUG
      $display("NLI:st mod_main_main=%d", cur_st);
      $display("NLI: r1_main =%d r3_main =%d r7_main =%d r6_main =%d r14_main =%d reg_t3_v1 =%d reg_t2_v3 =%d reg_t4_v4 =%d reg_t4_v5 =%d reg_t3_v6 =%d reg_t2_v9 =%d r6_main_v17 =%d r9_main_v18 =%d reg_t9 =%d reg_t10 =%d" ,r1_main ,r3_main ,r7_main ,r6_main ,r14_main ,reg_t3_v1 ,reg_t2_v3 ,reg_t4_v4 ,reg_t4_v5 ,reg_t3_v6 ,reg_t2_v9 ,r6_main_v17 ,r9_main_v18 ,reg_t9 ,reg_t10);
`endif
      // state output
      write_en_o <= (cur_st == `S_20);
      // FSM.
      case (cur_st)
        `S_0: begin
          addr_o <= 0;
          cur_st <= `S_65;
        end
        `S_65: begin
          r7_main <= o_insn_118_0;
          cur_st <= `S_3;
        end
        `S_3: begin
          r6_main_v17 <= wire_t13;
          if (wire_t13) begin
            cur_st <= `S_13;
          end else
          cur_st <= `S_63;
        end
        `S_13: begin
          reg_t2_v9 <= 32'd0;
          reg_t3_v6 <= 32'd1;
          reg_t4_v4 <= 32'd0;
          reg_t9 <= 2'd0;
          reg_t10 <= 2'd1;
          r6_main <= 2'd0;
          addr_o <= 1;
          cur_st <= `S_66;
        end
        `S_66: begin
          r9_main_v18 <= o_insn_121_0;
          cur_st <= `S_50;
        end
        `S_20: begin
          addr_o <= 2;
          data_o <= reg_t2_v3;
          cur_st <= `S_63;
        end
        `S_63: begin
          cur_st <= `S_63;
        end
        `S_50: begin
          reg_t3_v1 <= wire_t14;
          reg_t2_v3 <= wire_t15;
          r1_main <= wire_t16;
          r6_main <= wire_t17;
          if (wire_t17) begin
            cur_st <= `S_54;
          end else
          cur_st <= `S_20;
        end
        `S_54: begin
          r3_main <= reg_t3_v1;
          reg_t10 <= 2'd0;
          r6_main <= 2'd1;
          reg_t9 <= 2'd1;
          r14_main <= wire_t18;
          reg_t2_v9 <= wire_t18;
          reg_t4_v5 <= wire_t19;
          cur_st <= `S_50;
        end
      endcase
    end
  end

  // imported modules begin
  // imported modules end

  // sub modules begin
  // sub modules end

endmodule

module fib(clk, rst, addr_o, write_en_o, data_o, data_i);
  input clk;
  input rst;
  // EXTERNAL_RAM
  output [31:0] addr_o;
  output write_en_o;
  output [31:0] data_o;
  input [31:0] data_i;
  mod_main mod_main_inst(.clk(clk), .rst(rst), .addr_o(addr_o), .write_en_o(write_en_o), .data_o(data_o), .data_i(data_i));
endmodule

I wrote fib_test.v(test_bench for fib.v)

module fib_test;
   reg         clk = 0;
   reg         fib_rst;
   reg  [31:0] fib_mem[1:0];
   wire [31:0] fib_data_i;
   wire [31:0] fib_addr;
   wire        fib_wen;
   wire [31:0] fib_data_o;

   always #10
      clk <= !clk;

   task test;
      input [31:0] n;
      input [31:0] expected_result;
      integer      timeout;
      begin
         @(posedge clk);
         fib_mem[0] <= #1 1;
         fib_mem[1] <= #1 n;
         timeout    = 1000;
         begin: loop
            forever begin
               @(posedge clk);
               fib_mem[0] <= #1 0;
               if (fib_wen) begin
                  if (fib_data_o !== expected_result)
                      $display("fib_return = %d expected but %d found.", expected_result, fib_data_o);
          else
                      $display("fib_return = %d ok", fib_data_o);
                  disable loop;
               end
               if (timeout == 0) begin
                  $display("fib_wen is timeout.");
                  disable loop;
               end
               timeout = timeout - 1;
            end
         end
      end
   endtask

   initial begin
      fib_rst    <= 1;
      fib_mem[0] <= 0;
      fib_mem[1] <= 0;
      repeat(10) @(posedge clk);
      fib_rst    <= 0;
      repeat(10) @(posedge clk);
      test(0, 0);
      test(1, 1);
      test(2, 1);
      test(3, 2);
      test(4, 3);
      test(5, 5);
      test(6, 8);
      $stop;
   end

   assign fib_data_i = (fib_addr == 1) ? fib_mem[1] : fib_mem[0];

   fib dut(
       .clk       (clk       ),
       .rst       (fib_rst   ),
       .addr_o    (fib_addr  ),
       .write_en_o(fib_wen   ),
       .data_o    (fib_data_o),
       .data_i    (fib_data_i)
    );
endmodule // fib_test

simulation on Xilinx Vivado 2015.3

Vivado Simulator 2015.3
Copyright 1986-1999, 2001-2015 Xilinx, Inc. All Rights Reserved.
Running: E:/Xilinx/Vivado/2015.3/bin/unwrapped/win64.o/xelab.exe -wto ca0f9a24fe224f95b56a3f9bec2c8575 --debug typical --relax --mt 2 -L xil_defaultlib -L unisims_ver -L unimacro_ver -L secureip --snapshot fib_test_behav xil_defaultlib.fib_test xil_defaultlib.glbl -log elaborate.log 
Using 2 slave threads.
Starting static elaboration
Completed static elaboration
Starting simulation data flow analysis
WARNING: [XSIM 43-4100] "H:/gist/msgpack-vhdl-examples/examples/fibonacci/sim/vivado/neonlight/fib_test/fib_test.sim/sim_1/behav/glbl.v" Line 6. Module glbl has a timescale but at least one module in design doesn't have timescale.
WARNING: [XSIM 43-4100] "H:/gist/msgpack-vhdl-examples/examples/fibonacci/sim/vivado/neonlight/fib_test/fib_test.sim/sim_1/behav/glbl.v" Line 6. Module glbl has a timescale but at least one module in design doesn't have timescale.
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
Compiling module xil_defaultlib.mod_main
Compiling module xil_defaultlib.fib
Compiling module xil_defaultlib.fib_test
Compiling module xil_defaultlib.glbl
Built simulation snapshot fib_test_behav
Vivado Simulator 2015.3
Time resolution is 1 ps
run all
fib_wen is timeout.
fib_wen is timeout.
fib_wen is timeout.
fib_wen is timeout.
fib_wen is timeout.
fib_wen is timeout.
fib_wen is timeout.

Without becoming infinite loop , it seems they've been out of the loop at one time . Do I make a mistake in anything?

yt76 commented 8 years ago

Something like following should work, but I guess I have to fix the initializations on reset issue here too. // BEGIN object Fib = Kernel.clone();

channel Fib.in = int; channel Fib.out = int;

def Fib.main() { while (true) { int param = in; int curr; int next; int prev; int i; curr = 0; next = 1; for (i = 0; i < param; ++i) { prev = curr; curr = next; next = next + prev; } out = curr; } }

Fib.compile(); Fib.writeHdl("fib.v"); // END

yt76 commented 8 years ago

oops. wrong indent. I'll let you know when confirmation is done.

yt76 commented 8 years ago

I fixed uninitialized output registers on reset, but I found while(true) loop is not working :cry:

Looking into it...

btw. the above code will output verilog input/output like

module fib(clk, rst, channel_out_data, channel_out_en, channel_out_rdy, channel_in_data, channel_in_en, channel_in_rdy);

Both channel_out and channel_in have _data, _rdy and _en to handshake the timing.

yt76 commented 8 years ago

It seems almost working, but there are some remaining issues around optimizers.. still investigating.