diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index 303b30a41c..954df2114b 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -9,12 +9,12 @@ 104, 201, 202, + 1, 0, 0, 0, 0, 105, - 106, 0 ], "format": { diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 307166fe21..3e76673b64 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -3,12 +3,12 @@ 101, 102, 201, + 201, 103, 202, 104, 105, 0, - 0, 0 ], "commands": [ @@ -20,12 +20,12 @@ 104, 201, 202, + 1, 0, 0, 0, 0, 105, - 106, 0 ] } diff --git a/calyx-py/test/correctness/pifo.py b/calyx-py/test/correctness/pifo.py index 18e754b6fa..8b1cd02fc6 100644 --- a/calyx-py/test/correctness/pifo.py +++ b/calyx-py/test/correctness/pifo.py @@ -64,7 +64,7 @@ def insert_pifo(prog, name): pifo: cb.ComponentBuilder = prog.component(name) cmd = pifo.input("cmd", 32) - # If this is 0, we pop. Otherwise, we push the value. + # If this is 0, we pop. If it is 1, we peek. Otherwise, we push the value. # Create the two FIFOs and ready them for invocation. fifo_0 = pifo.cell("myfifo_0", fifo.insert_fifo(prog, "fifo_0")) @@ -92,14 +92,17 @@ def insert_pifo(prog, name): flow_eq_1 = util.insert_eq(pifo, flow.out, 1, "flow_eq_1", 1) # flow == 1 len_eq_0 = util.insert_eq(pifo, len.out, 0, "len_eq_0", 32) # `len` == 0 len_eq_10 = util.insert_eq(pifo, len.out, 10, "len_eq_10", 32) # `len` == 10 - cmd_eq_0 = util.insert_eq(pifo, cmd, cb.const(32, 0), "cmd_eq_0", 32) # cmd == 0 - cmd_neq_0 = util.insert_neq(pifo, cmd, cb.const(32, 0), "cmd_neq_0", 32) # cmd != 0 + + cmd_eq_0 = util.insert_eq(pifo, cmd, 0, "cmd_eq_0", 32) # `cmd` == 0 + cmd_eq_1 = util.insert_eq(pifo, cmd, 1, "cmd_eq_1", 32) # `cmd` == 1 + cmd_gt_1 = util.insert_gt(pifo, cmd, 1, "cmd_gt_1", 32) # `cmd` > 1 + err_eq_0 = util.insert_eq(pifo, err.out, 0, "err_eq_0", 1) # err == 0 err_neq_0 = util.insert_neq( pifo, err.out, cb.const(1, 0), "err_neq_0", 1 ) # err != 0 - flip_hot = util.insert_bitwise_flip_reg(pifo, hot, "flip_hot", 1) # Flip `hot`. + flip_hot = util.insert_bitwise_flip_reg(pifo, hot, "flip_hot", 1) # flip `hot`. raise_err = util.insert_reg_store(pifo, err, 1, "raise_err") # set `err` to 1 lower_err = util.insert_reg_store(pifo, err, 0, "lower_err") # set `err` to 0 zero_out_ans = util.insert_reg_store(pifo, ans, 0, "zero_out_ans") # zero out `ans` @@ -110,7 +113,7 @@ def insert_pifo(prog, name): # The main logic. pifo.control += [ cb.par( - # Was it a pop or a push? We can do both cases in parallel. + # Was it a pop, peek, or a push? We can do all cases in parallel. cb.if_( # Did the user call pop? cmd_eq_0[0].out, @@ -212,10 +215,88 @@ def insert_pifo(prog, name): ], ), ), + cb.if_( + # Did the user call peek? + cmd_eq_1[0].out, + cmd_eq_1[1], + cb.if_( + # Yes, the user called peek. But is the queue empty? + len_eq_0[0].out, + len_eq_0[1], + [raise_err, zero_out_ans], # The queue is empty: underflow. + [ # The queue is not empty. Proceed. + # We must check if `hot` is 0 or 1. + lower_err, + cb.par( # We'll check both cases in parallel. + cb.if_( + # Check if `hot` is 0. + hot_eq_0[0].out, + hot_eq_0[1], + [ # `hot` is 0. We'll invoke `peek` on `fifo_0`. + cb.invoke( # First we call peek + fifo_0, + in_cmd=cb.const(32, 1), + ref_ans=ans, # Its answer is our answer. + ref_err=err, + ), + # Our next step depends on whether `fifo_0` + # raised the error flag. + cb.if_( + err_neq_0[0].out, + err_neq_0[1], + [ # `fifo_0` raised an error. + # We'll try to peek from `fifo_1`. + # We'll pass it a lowered `err`. + lower_err, + cb.invoke( + fifo_1, + in_cmd=cb.const(32, 1), + ref_ans=ans, + # Its answer is our answer. + ref_err=err, + # Its error is our error, + # whether it raised one or not. + ), + ], + ), + # Peeking does not affect `hot`. + # Peeking does not affect the length. + ], + ), + # If `hot` is 1, we proceed symmetrically. + cb.if_( + hot_eq_1[0].out, + hot_eq_1[1], + [ + cb.invoke( + fifo_1, + in_cmd=cb.const(32, 1), + ref_ans=ans, + ref_err=err, + ), + cb.if_( + err_neq_0[0].out, + err_neq_0[1], + [ + lower_err, + cb.invoke( + fifo_0, + in_cmd=cb.const(32, 1), + ref_ans=ans, + ref_err=err, + ), + ], + ), + ], + ), + ), + ], + ), + ), cb.if_( # Did the user call push? - cmd_neq_0[0].out, - cmd_neq_0[1], + cmd_gt_1[0].out, + cmd_gt_1[1], cb.if_( # Yes, the user called push. But is the queue full? len_eq_10[0].out,