fabianschuiki/llhd-sim

Drive events get reordered

Closed this issue · 2 comments

It seems that drive events are being reordered in an arbitrary fashion at times. Seen this in a larger code example, but for example not in the following code (which works fine):

proc @foo () (i32$ %out) {
%entry:
    drv %out 0
    drv %out 1
    drv %out 2
    drv %out 3
    wait %end for 1ns
%end:
    halt
}

Output in the VCD file is 3 for %out.

The following example does not work however:

proc @n274 (i32$ %0, i32$ %1, i32$ %2, i32$ %3, i32$ %4, i32$ %5) (i1$ %6, i1$ %7, i1$ %8) {
%9:
    br label %body
%body:
    %11 = prb %3
    %12 = prb %0
    %13 = cmp eq i32 %11 %12
    drv %6 %13
    %15 = prb %4
    %16 = prb %1
    %17 = cmp eq i32 %15 %16
    drv %7 %17
    %19 = prb %5
    %20 = prb %2
    %21 = cmp eq i32 %19 %20
    drv %8 %21
    br label %check
%check:
    wait %body, %0, %1, %2, %3, %4, %5
}

proc @n275 (i1$ %0, i1$ %1, i1$ %2, i1$ %3, i1$ %4, i1$ %5) (i1$ %6, i1$ %7, i1$ %8, i1$ %9) {
%10:
    br label %body
%body:
    drv %6 1
    %13 = prb %6
    %14 = prb %0
    %15 = and i1 %13 %14
    drv %7 %15
    %17 = prb %7
    %18 = prb %1
    %19 = and i1 %17 %18
    drv %8 %19
    %21 = prb %8
    %22 = prb %2
    %23 = and i1 %21 %22
    drv %9 %23
    br label %check
%check:
    wait %body, %0, %1, %2, %6, %7, %8
}

proc @n276 (i32$ %0, i32$ %1, i32$ %2, i1$ %3, i1$ %4, i1$ %5) (i32$ %6) {
%7:
    br label %body
%body:
    drv %6 0
    %10 = prb %3
    br %10 label %if_true %if_false
%check:
    wait %body, %0, %1, %2, %3, %4, %5
%if_true:
    %13 = prb %0
    drv %6 %13
    br label %if_exit
%if_false:
    br label %if_exit
%if_exit:
    %17 = prb %4
    br %17 label %if_true0 %if_false0
%if_true0:
    %19 = prb %1
    drv %6 %19
    br label %if_exit0
%if_false0:
    br label %if_exit0
%if_exit0:
    %23 = prb %5
    br %23 label %if_true1 %if_false1
%if_true1:
    %25 = prb %2
    drv %6 %25
    br label %if_exit1
%if_false1:
    br label %if_exit1
%if_exit1:
    br label %check
}

proc @n277 (i1$ %0, i1$ %1, i1$ %2, i32$ %3, i32$ %4, i32$ %5, i32$ %6, i1$ %7, i1$ %8, i1$ %9, i1$ %10, i1$ %11, i1$ %12, i32$ %13, i1$ %14) (i32$ %15, i32$ %16, i32$ %17, i32$ %18, i1$ %19) {
%20:
    br label %init
%init:
    %22 = prb %0
    %23 = prb %1
    wait %check, %0, %1
%check:
    %25 = prb %0
    %26 = cmp eq i1 %22 0
    %27 = cmp neq i1 %25 0
    %posedge = and i1 %26 %27
    %28 = prb %1
    %29 = cmp eq i1 %28 0
    %30 = cmp neq i1 %23 0
    %negedge = and i1 %29 %30
    %event_or = or i1 %posedge %negedge
    br %event_or label %event %init
%event:
    %32 = prb %1
    %33 = not i1 %32
    br %33 label %if_true %if_false
%if_true:
    drv %16 0
    drv %17 0
    drv %18 0
    drv %19 0
    br label %if_exit
%if_false:
    %40 = prb %2
    br %40 label %if_true0 %if_false0
%if_exit:
    br label %20
%if_true0:
    %43 = prb %10
    br %43 label %if_true1 %if_false1
%if_false0:
    br label %if_exit0
%if_exit0:
    br label %if_exit
%if_true1:
    %47 = prb %7
    br %47 label %if_true2 %if_false2
%if_false1:
    br label %if_exit1
%if_exit1:
    %50 = prb %11
    br %50 label %if_true3 %if_false3
%if_true2:
    drv %16 0
    br label %if_exit2
%if_false2:
    %54 = prb %16
    %55 = add i32 %54 1
    drv %16 %55
    br label %if_exit2
%if_exit2:
    br label %if_exit1
%if_true3:
    %59 = prb %8
    br %59 label %if_true4 %if_false4
%if_false3:
    br label %if_exit3
%if_exit3:
    %62 = prb %12
    br %62 label %if_true5 %if_false5
%if_true4:
    drv %17 0
    br label %if_exit4
%if_false4:
    %66 = prb %17
    %67 = add i32 %66 1
    drv %17 %67
    br label %if_exit4
%if_exit4:
    br label %if_exit3
%if_true5:
    %71 = prb %9
    br %71 label %if_true6 %if_false6
%if_false5:
    br label %if_exit5
%if_exit5:
    %74 = prb %15
    %75 = prb %13
    %76 = add i32 %74 %75
    drv %15 %76
    %78 = prb %14
    drv %19 %78
    br label %if_exit0
%if_true6:
    drv %18 0
    br label %if_exit6
%if_false6:
    %83 = prb %18
    %84 = add i32 %83 1
    drv %18 %84
    br label %if_exit6
%if_exit6:
    br label %if_exit5
}

entity @addr_gen (i1$ %clk_i, i1$ %rst_ni, i1$ %enable_i) (i32$ %addr_o, i1$ %done_o) {
    %pointer = sig i32 1024
    %bound_0 = sig i32 3
    %bound_1 = sig i32 3
    %bound_2 = sig i32 1
    %index_0 = sig i32
    %index_1 = sig i32
    %index_2 = sig i32
    %stride_0 = sig i32 4
    %stride_1 = sig i32 16
    %stride_2 = sig i32 256
    %max_0 = sig i1
    %max_1 = sig i1
    %max_2 = sig i1
    %enable_0 = sig i1
    %enable_1 = sig i1
    %enable_2 = sig i1
    %active_stride = sig i32
    %done_d = sig i1
    %done_q = sig i1
    %0 = prb %pointer
    drv %addr_o %0
    %2 = prb %done_d
    drv %done_o %2
    inst @n274 (%bound_0, %bound_1, %bound_2, %index_0, %index_1, %index_2) (%max_0, %max_1, %max_2)
    inst @n275 (%max_0, %max_1, %max_2, %enable_0, %enable_1, %enable_2) (%enable_0, %enable_1, %enable_2, %done_d)
    inst @n276 (%stride_0, %stride_1, %stride_2, %enable_0, %enable_1, %enable_2) (%active_stride)
    inst @n277 (%clk_i, %rst_ni, %enable_i, %pointer, %index_0, %index_1, %index_2, %max_0, %max_1, %max_2, %enable_0, %enable_1, %enable_2, %active_stride, %done_d) (%pointer, %index_0, %index_1, %index_2, %done_q)
}

proc @n234 () (i1$ %0, i1$ %1) {
%2:
    wait %4 for 1ns
%4:
    drv %1 0
    wait %7 for 1ns
%7:
    drv %1 1
    wait %10 for 1ns
%10:
    %loop_count = var i32
    store i32 100 %loop_count
    br label %loop_body
%loop_body:
    %13 = load i32 %loop_count
    %14 = cmp neq i32 %13 0
    br %14 label %loop_continue %loop_exit
%loop_exit:
    wait %17 for 1ns
%loop_continue:
    drv %0 1
    wait %20 for 500ps
%20:
    drv %0 0
    wait %23 for 500ps
%23:
    %24 = load i32 %loop_count
    %25 = sub i32 %24 1
    store i32 %25 %loop_count
    br label %loop_body
%17:
    halt
}

entity @testbench () () {
    %clk_i = sig i1
    %rst_ni = sig i1 1
    %enable_i = sig i1 1
    %addr_o = sig i32
    %done_o = sig i1
    %dut = inst @addr_gen (%clk_i, %rst_ni, %enable_i) (%addr_o, %done_o)
    inst @n234 () (%clk_i, %rst_ni)
}

Output in the VCD file is always 0 for active_stride, except when enable_2 = 1, then it is 0x100 as expected. It seems that the events issue during @n276 get reordered such that the initial drive to 0 may overtake the other events.

This repository is now deprecated in favor of the implementation within LLHD. Tracking continues there.