From 8782c74a4604392cc968d10c183b787fe2464a40 Mon Sep 17 00:00:00 2001 From: Kabir Samsi Date: Mon, 15 Jul 2024 15:12:41 -0400 Subject: [PATCH] Began binary-heap based PIEO implementation --- .../queues/binheap/binheap_pieo.py | 162 ++++++++++++++++++ calyx-py/test/correctness/queues/pieo.py | 32 ++-- 2 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 calyx-py/test/correctness/queues/binheap/binheap_pieo.py diff --git a/calyx-py/test/correctness/queues/binheap/binheap_pieo.py b/calyx-py/test/correctness/queues/binheap/binheap_pieo.py new file mode 100644 index 0000000000..b6aa2d0643 --- /dev/null +++ b/calyx-py/test/correctness/queues/binheap/binheap_pieo.py @@ -0,0 +1,162 @@ +# pylint: disable=import-error +import sys +import binheap +import calyx.builder as cb +import calyx.queue_call as qc + +def insert_pieo(prog, name, val_queue, time_queue, rank_queue, queue_len, stats=None, static=False): + pieo = prog.component(name) + + queue_size_factor = 4 + + # Declare the two sub-queues as cells of this component. + val_queue = pieo.cell("val_queue", val_queue) + time_queue = pieo.cell("time_queue", time_queue) + rank_queue = pieo.cell("rank_queue", rank_queue) + + ans_mem = pieo.seq_mem_d1("out", 32, queue_len, queue_size_factor, is_external=True) + + ans = pieo.reg(32) + err = pieo.reg(1) + + ans_index = pieo.reg(32) + + def push(value, rank, time=0): + """Push an element into the heap (timewise) """ + #Parallelly push value, time and rank into their respective heaps + return cb.par( + cb.invoke( + val_queue, + in_value=cb.const(32, value), + in_rank=cb.const(64, rank), + in_cmd=cb.const(2, 2), + ref_ans=ans, + ref_err=err, + ), + cb.invoke( + time_queue, + in_value=cb.const(32, time), + in_rank=cb.const(64, rank), + in_cmd=cb.const(2, 2), + ref_ans=ans, + ref_err=err, + ), + cb.invoke( + rank_queue, + in_value=cb.const(32, time), + in_rank=cb.const(64, rank), + in_cmd=cb.const(2, 2), + ref_ans=ans, + ref_err=err, + ) + ) + + def peek_by_value(value, time): + #Scan every element of the heap until the correct one is found + queue_index = pieo.reg(32) + + #Stores accessed times from popping queue + time_ans = pieo.reg(32) + val_ans = pieo.reg(32) + rank_ans = pieo.reg(32) + + + cached_vals = pieo.seq_mem_d1("cached_vals", 32, queue_len, 32) + cached_times = pieo.seq_mem_d1("cached_times", 32, queue_len, 32) + cached_ranks = pieo.seq_mem_d1("cached_ranks", 32, queue_len, 32) + + #Equality checkers + value_eq = pieo.eq_use(value, time_ans) + time_leq = pieo.le_use(val_ans, time) + overflow_check = pieo.lt_use(queue_index, queue_len) + + return [ + cb.seq( + cb.while_with ((value_eq & time_leq & overflow_check), + cb.seq([ + cb.par( + [cb.invoke( + q, + in_value=0, + in_rank=0, + in_cmd=0, #Pop from queue + ref_ans=ans, + ref_err=err, + )] + for (q, ans) in ((val_queue, val_ans), (time_queue, time_ans), (rank_queue, rank_ans)) + ), + pieo.mem_store_d1(cached_vals, queue_index, val_ans, "cache_vals"), + pieo.mem_store_d1(cached_times, queue_index, time_ans, "cache_times"), + pieo.mem_store_d1(cached_ranks, queue_index, rank_ans, "cache_ranks"), + pieo.incr(queue_index) + ]) + ), + cb.if_with((value_eq & time_leq), + cb.seq([ + pieo.mem_store_d1(ans_mem, ans_index, val_ans, ""), + cb.incr(ans_index), + + cb. + cb.par( + cb.invoke( + val_queue, + in_value=cb.const(32, v), + in_rank=cb.const(64, r), + in_cmd=cb.const(2, 2), + ref_ans=ans, + ref_err=err, + ), + cb.invoke( + time_queue, + in_value=cb.const(32, v), + in_rank=cb.const(64, r), + in_cmd=cb.const(2, 2), + ref_ans=ans, + ref_err=err, + ), + cb.invoke( + rank_queue, + in_value=cb.const(32, r), + in_rank=cb.const(64, r), + in_cmd=cb.const(2, 2), + ref_ans=ans, + ref_err=err, + ) + ) + for (v, t, r) in + ) + ) + ) + # comp.mem_store_d1(out, index - 1, ans.out, f"store_ans_{index}"), + ] + + def pop_and_store(): + queue_index = pieo.reg(32) + + return [ + cb.invoke( + val_queue, + in_value=cb.const(32, 50), + in_rank=cb.const(64, 50), + in_cmd=cb.const(2, 0), + ref_ans=ans, + ref_err=err, + ), + pieo.mem_store_d1(ans_mem, index - 1, ans.out, f"store_ans_{index}"), + ] + +def build(): + """Top-level function to build the program.""" + num_cmds = int(sys.argv[1]) + keepgoing = "--keepgoing" in sys.argv + prog = cb.Builder() + val_queue = binheap.insert_binheap(prog, "val_queue", 4, 32, 32) + time_queue = binheap.insert_binheap(prog, "time_queue", 4, 32, 32) + rank_queue = binheap.insert_binheap(prog, "rank_queue", 4, 32, 32) + pieo = insert_pieo(prog, "pieo", val_queue, time_queue, rank_queue, 16) + qc.insert_main(prog, pieo, num_cmds, keepgoing=keepgoing) + return prog.program + + +if __name__ == "__main__": + build().emit() \ No newline at end of file diff --git a/calyx-py/test/correctness/queues/pieo.py b/calyx-py/test/correctness/queues/pieo.py index b43bd09d94..e4e83d1445 100644 --- a/calyx-py/test/correctness/queues/pieo.py +++ b/calyx-py/test/correctness/queues/pieo.py @@ -170,15 +170,18 @@ def insert_shift_backward(prog, name, length, idx): def query_time(prog, name, length, current_time): """Component for finding the lowest-rank element matching a time predicate""" comp = prog.component(name) - idx = comp.reg(32) - inc = comp.incr(idx) - ready_time = comp.reg(32) mem = comp.seq_mem_d2("queue", *length, 3, is_ref=True) idx = comp.reg(32, is_ref=True) + + #Register loads in the readiness time at each level + ready_time = comp.reg(32) + inc = comp.incr(idx) + found = comp.reg(1, is_ref=True) load_time = comp.mem_load_d2(mem, idx, 1, ready_time, "load_time") + time_leq = comp.le_use(ready_time.out, current_time.out) idx_leq = comp.lt_use(idx.out, length) @@ -246,10 +249,6 @@ def insert_pieo(prog, max_cmds, queue_size): incr_cmd_idx = pieo.add_store_in_reg(cmd_idx.out, 1, cmd_idx, "incr_cmd_idx") cmd_in_range = pieo.lt_use(cmd_idx.out, max_cmds) - ans_index = pieo.reg(32, "ans_index") - insert_pos = pieo.reg(32) - result = pieo.reg(32) - #Data trackers (reading from external memory) cmd, value, time, rank = ( pieo.reg(3, "cmd"), @@ -272,11 +271,18 @@ def insert_pieo(prog, max_cmds, queue_size): for i in range(3) ] - #Write memory - write = pieo.mem_store_d1(ans_mem, ans_index.out, result, "store_result") + #Reference registers + ans_index = pieo.reg(32, "ans_index") + insert_pos = pieo.reg(32) + remove_pos = pieo.reg(32) + result = pieo.reg(32) + #Invoke cells find_push_loc = insert_find_push_loc(prog, "find_push_loc", queue_dim, rank) - push_loc = insert_push_loc(prog, "insert_push_loc", queue_dim, (value, time, rank), insert_pos) + push_loc = insert_push_loc(prog, "push_loc", queue_dim, (value, time, rank), insert_pos) + shift_backward = insert_shift_backward(prog, "shift_backward", ) + + write = pieo.mem_store_d1(ans_mem, ans_index.out, result, "store_result") #Check the type of command cmd_eqs = [pieo.eq_use(cmd.out, i) for i in range(5)] @@ -286,7 +292,9 @@ def insert_pieo(prog, max_cmds, queue_size): load_cmd, cb.par ( cb.if_with(cmd_eqs[0] & not_minned, - print("Peek by time") + cb.seq( + + ) ), cb.if_with(cmd_eqs[1] & not_minned, @@ -319,7 +327,7 @@ def build(): num_cmds = 20000 keepgoing = "--keepgoing" in sys.argv prog = cb.Builder() - pieo = insert_pieo(prog, "pieo", 16) + pieo = insert_pieo(prog, 20000, 16) qc.insert_main(prog, pieo, num_cmds, keepgoing=keepgoing) return prog.program