From 2f18cb04592e1dbf2f8eebb06a97afbadd17bff5 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan <10830208+anshumanmohan@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:56:41 -0500 Subject: [PATCH] `fifo`: better testing (#1762) --- calyx-py/calyx/fifo_data_gen.py | 53 +++++++++++++++++++++++ calyx-py/calyx/fifo_oracle.py | 60 +++++++++++++++++++++++++++ calyx-py/test/correctness/fifo.data | 40 +++++++++--------- calyx-py/test/correctness/fifo.expect | 54 ++++++++++++------------ 4 files changed, 160 insertions(+), 47 deletions(-) create mode 100644 calyx-py/calyx/fifo_data_gen.py create mode 100644 calyx-py/calyx/fifo_oracle.py diff --git a/calyx-py/calyx/fifo_data_gen.py b/calyx-py/calyx/fifo_data_gen.py new file mode 100644 index 0000000000..da07f57f49 --- /dev/null +++ b/calyx-py/calyx/fifo_data_gen.py @@ -0,0 +1,53 @@ +import random +import time +import json +from typing import Dict, Union + +MAX_CMDS = 15 +ANS_MEM_LEN = 10 + +FormatType = Dict[str, Union[bool, str, int]] + + +def format_gen(width: int) -> FormatType: + """Generates a format object for a bitvector of length `width`.""" + return {"is_signed": False, "numeric_type": "bitnum", "width": width} + + +def dump_json(): + """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 MAX_CMDS items, which are 0, 1, or 2. + - The `values` memory has MAX_CMDS items: random values between 0 and 100. + - The `ans_mem` memory has ANS_MEM_LEN items, all zeroes. + - Each memory has a `format` field, which is a format object for a bitvector. + """ + commands = { + "commands": { + "data": [random.randint(0, 2) for _ in range(MAX_CMDS)], + # The `commands` memory has MAX_CMDS items, which are 0, 1, or 2. + "format": format_gen(2), + } + } + values = { + "values": { + "data": [random.randint(0, 100) for _ in range(MAX_CMDS)], + # The `values` memory has MAX_CMDS items: random values between 0 and 100. + "format": format_gen(32), + } + } + ans_mem = { + "ans_mem": { + "data": [0 for _ in range(ANS_MEM_LEN)], + # The `ans_mem` memory has ANS_MEM_LEN items, all zeroes. + "format": format_gen(32), + } + } + + print(json.dumps(commands | values | ans_mem, indent=2)) + + +if __name__ == "__main__": + random.seed(5) + dump_json() diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py new file mode 100644 index 0000000000..6ca4fbd542 --- /dev/null +++ b/calyx-py/calyx/fifo_oracle.py @@ -0,0 +1,60 @@ +import sys +import json + + +def parse_json(): + """Effectively the opposite of `data_gen`: + Given a JSON file formatted for Calyx purposes, parse it into its two lists: + - The `commands` memory, which has MAX_CMDS items. + - The `values` memory, which has MAX_CMDS items. + Returns the two lists. + """ + + # The JSON file is piped to us in stdin. + data = json.load(sys.stdin) + commands = data["commands"]["data"] + values = data["values"]["data"] + return commands, values + + +def operate_fifo(commands, values): + """Given the three lists, operate a FIFO routine. + - Read the comammands list in order. + - When the value is 0, we "pop" the FIFO and write the value to the answer memory. + - When it is 1, we "peek" into the FIFO and write the value to the answer memory. + - When it is 2, we push the coressponding item in the `values` list to the FIFO. + + In the end, we return the answer memory. + """ + fifo = [] + ans = [] + for cmd, val in zip(commands, values): + if cmd == 0: + if len(fifo) == 0: + break + ans.append(fifo.pop(0)) + elif cmd == 1: + if len(fifo) == 0: + break + ans.append(fifo[0]) + elif cmd == 2: + fifo.append(val) + # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. + ans += [0] * (10 - len(ans)) + return ans + + +def dump_json(commands, values, ans_mem): + """Prints a JSON representation of the data to stdout.""" + payload = { + "ans_mem": ans_mem, + "commands": commands, + "values": values, + } + print(json.dumps(payload, indent=2)) + + +if __name__ == "__main__": + commands, values = parse_json() + ans = operate_fifo(commands, values) + dump_json(commands, values, ans) diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index f0c8359a9b..65ab3d659a 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -4,15 +4,15 @@ 2, 1, 2, - 2, - 0, - 2, - 2, + 1, 2, 2, 2, 2, 0, + 1, + 0, + 2, 0, 0, 0 @@ -25,21 +25,21 @@ }, "values": { "data": [ - 100, - 0, - 101, - 102, - 0, - 103, - 104, - 105, - 106, - 107, - 108, - 0, - 0, - 0, - 0 + 47, + 60, + 31, + 48, + 69, + 13, + 73, + 31, + 1, + 93, + 27, + 52, + 35, + 23, + 98 ], "format": { "is_signed": false, @@ -66,4 +66,4 @@ "width": 32 } } -} \ No newline at end of file +} diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index 72d5cf8bd2..20595ecca5 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -1,13 +1,13 @@ { "ans_mem": [ - 100, - 100, - 101, - 102, - 103, - 104, - 0, - 0, + 47, + 47, + 47, + 31, + 31, + 69, + 13, + 73, 0, 0 ], @@ -15,34 +15,34 @@ 2, 1, 2, - 2, - 0, - 2, - 2, + 1, 2, 2, 2, 2, 0, + 1, + 0, + 2, 0, 0, 0 ], "values": [ - 100, - 0, - 101, - 102, - 0, - 103, - 104, - 105, - 106, - 107, - 108, - 0, - 0, - 0, - 0 + 47, + 60, + 31, + 48, + 69, + 13, + 73, + 31, + 1, + 93, + 27, + 52, + 35, + 23, + 98 ] }