diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index 3dbdc9f638..87e34b63a6 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -12,12 +12,56 @@ def format_gen(width: int) -> FormatType: return {"is_signed": False, "numeric_type": "bitnum", "width": width} -def dump_json(no_peeks: bool): +def piezo_special(): + """A special data-gen helper that creates a commands list while + ensuring that there are: + - No overflows. + - No underflows. + - (queue_util.MAX_CMDS/2) pushes. + - As many pops as there are pushes. + A combination of the above means that no packet is left unpopped. + """ + running_count = 0 # The current size of the queue. + push_goal = int(queue_util.MAX_CMDS / 2) # How many pushes we want overall. + total_push_count = 0 + total_pop_count = 0 + commands = [] + while True: + command = random.choice(["push", "pop"]) + if command == "pop" and running_count == 0: + # This would make us underflow, + # so we'll change the command to `push` instead + command = "push" + if command == "push" and running_count == queue_util.QUEUE_SIZE: + # This would make us overflow, + # so we'll change the command to `pop` instead + command = "pop" + if command == "push": + running_count += 1 + total_push_count += 1 + if command == "pop": + running_count -= 1 + total_pop_count += 1 + # Put the command into `commands`. + commands.append(0 if command == "pop" else 2) + + if total_push_count == push_goal: + # Pad the `commands` list with (push_goal - total_pop_count) `pop`s, + # and then break. + commands += (push_goal - total_pop_count) * [0] + break + + assert len(commands) == queue_util.MAX_CMDS + return commands + + +def dump_json(piezo: bool): """Prints a JSON representation of the data to stdout. The data itself is populated randomly, following certain rules: - It has three "memories": `commands`, `values`, and `ans_mem`. - The `commands` memory has queue_util.MAX_CMDS items, which are 0, 1, or 2. - If the `no_peeks` flag is set, then items are chosen randomly from 0 and 2. + 0: pop, 1: peek, 2: push + If the `piezo` flag is set, then items are chosen from 0 and 2 using a helper. - The `values` memory has queue_util.MAX_CMDS items: random values between 0 and 400. - The `ans_mem` memory has queue_util.MAX_CMDS items, all zeroes. @@ -25,10 +69,11 @@ def dump_json(no_peeks: bool): """ commands = { "commands": { - "data": [ - random.choice([0, 2]) if no_peeks else random.randint(0, 2) - for _ in range(queue_util.MAX_CMDS) - ], + "data": ( + piezo_special() + if piezo + else [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS)] + ), "format": format_gen(2), } } @@ -55,6 +100,6 @@ def dump_json(no_peeks: bool): # Accept a flag that we pass to dump_json. # This says whether we should have any 1s in the `commands` memory. - no_peeks = len(sys.argv) > 1 and sys.argv[1] == "--no-peeks" + piezo = len(sys.argv) > 1 and sys.argv[1] == "--piezo" random.seed(5) - dump_json(no_peeks) + dump_json(piezo)