From 3c3079e6acf7d96b67de7e1635e26d9c1ae477ff Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 13:31:19 -0500 Subject: [PATCH 01/29] Oracle for FIFOs --- calyx-py/test/correctness/fifo_data_gen.py | 52 +++++++++++++++++++++ calyx-py/test/correctness/fifo_oracle.py | 54 ++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 calyx-py/test/correctness/fifo_data_gen.py create mode 100644 calyx-py/test/correctness/fifo_oracle.py diff --git a/calyx-py/test/correctness/fifo_data_gen.py b/calyx-py/test/correctness/fifo_data_gen.py new file mode 100644 index 0000000000..636b95a3c4 --- /dev/null +++ b/calyx-py/test/correctness/fifo_data_gen.py @@ -0,0 +1,52 @@ +import random +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` array has MAX_CMDS items, which are 0, 1, or 2. + - The `values` array has MAX_CMDS items: random values between 0 and 100. + - The `ans_mem` array 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` array 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` array 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` array 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(4) + dump_json() diff --git a/calyx-py/test/correctness/fifo_oracle.py b/calyx-py/test/correctness/fifo_oracle.py new file mode 100644 index 0000000000..dee3d80765 --- /dev/null +++ b/calyx-py/test/correctness/fifo_oracle.py @@ -0,0 +1,54 @@ +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` array, which has MAX_CMDS items. + - The `values` array, which has MAX_CMDS items. + + Returns the three lists. + """ + with open("fifo.data", "r") as f: + data = json.load(f) + 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: + ans.append(fifo.pop(0)) + elif cmd == 1: + 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): + 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) From ab0408d3600d6039c06fd8e81b02909449f48d69 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 13:43:03 -0500 Subject: [PATCH 02/29] Good pseudorandom seed --- calyx-py/test/correctness/fifo_data_gen.py | 3 ++- calyx-py/test/correctness/fifo_oracle.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/calyx-py/test/correctness/fifo_data_gen.py b/calyx-py/test/correctness/fifo_data_gen.py index 636b95a3c4..d35de6086c 100644 --- a/calyx-py/test/correctness/fifo_data_gen.py +++ b/calyx-py/test/correctness/fifo_data_gen.py @@ -1,4 +1,5 @@ import random +import time import json from typing import Dict, Union @@ -48,5 +49,5 @@ def dump_json(): if __name__ == "__main__": - random.seed(4) + random.seed(5) dump_json() diff --git a/calyx-py/test/correctness/fifo_oracle.py b/calyx-py/test/correctness/fifo_oracle.py index dee3d80765..aecda22a0b 100644 --- a/calyx-py/test/correctness/fifo_oracle.py +++ b/calyx-py/test/correctness/fifo_oracle.py @@ -1,3 +1,4 @@ +import sys import json @@ -9,8 +10,9 @@ def parse_json(): Returns the three lists. """ - with open("fifo.data", "r") as f: - data = json.load(f) + + # 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 @@ -29,8 +31,12 @@ def operate_fifo(commands, values): 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) From 0b1e60317bf73e1b4744871ecd386aec469ffddb Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 13:46:17 -0500 Subject: [PATCH 03/29] Move two files out of runt's way --- calyx-py/{test/correctness => calyx}/fifo_data_gen.py | 0 calyx-py/{test/correctness => calyx}/fifo_oracle.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename calyx-py/{test/correctness => calyx}/fifo_data_gen.py (100%) rename calyx-py/{test/correctness => calyx}/fifo_oracle.py (100%) diff --git a/calyx-py/test/correctness/fifo_data_gen.py b/calyx-py/calyx/fifo_data_gen.py similarity index 100% rename from calyx-py/test/correctness/fifo_data_gen.py rename to calyx-py/calyx/fifo_data_gen.py diff --git a/calyx-py/test/correctness/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py similarity index 100% rename from calyx-py/test/correctness/fifo_oracle.py rename to calyx-py/calyx/fifo_oracle.py From 7a8bbb928c2daa48623c33582e134683a0c90948 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 13:46:47 -0500 Subject: [PATCH 04/29] Use new, randomly generated data and expect files for actual testing --- calyx-py/test/correctness/fifo.data | 40 ++++++++++---------- calyx-py/test/correctness/fifo.expect | 54 +++++++++++++-------------- 2 files changed, 47 insertions(+), 47 deletions(-) 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 ] } From d7eca6eb36805e501b53f63c8a7a6595d267b69b Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 14:20:10 -0500 Subject: [PATCH 05/29] Nits --- calyx-py/calyx/fifo_data_gen.py | 12 ++++++------ calyx-py/calyx/fifo_oracle.py | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/calyx-py/calyx/fifo_data_gen.py b/calyx-py/calyx/fifo_data_gen.py index d35de6086c..da07f57f49 100644 --- a/calyx-py/calyx/fifo_data_gen.py +++ b/calyx-py/calyx/fifo_data_gen.py @@ -18,29 +18,29 @@ 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` array has MAX_CMDS items, which are 0, 1, or 2. - - The `values` array has MAX_CMDS items: random values between 0 and 100. - - The `ans_mem` array has ANS_MEM_LEN items, all zeroes. + - 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` array has MAX_CMDS items, which are 0, 1, or 2. + # 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` array has MAX_CMDS items: random values between 0 and 100. + # 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` array has ANS_MEM_LEN items, all zeroes. + # The `ans_mem` memory has ANS_MEM_LEN items, all zeroes. "format": format_gen(32), } } diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index aecda22a0b..6ca4fbd542 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -5,10 +5,9 @@ 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` array, which has MAX_CMDS items. - - The `values` array, which has MAX_CMDS items. - - Returns the three 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. @@ -46,6 +45,7 @@ def operate_fifo(commands, values): def dump_json(commands, values, ans_mem): + """Prints a JSON representation of the data to stdout.""" payload = { "ans_mem": ans_mem, "commands": commands, From 70a69ee83d89fcee1bae46d6a1c9ac74b58de308 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 18:40:01 -0500 Subject: [PATCH 06/29] Generalize fifo_data_gen to all kinds of queues --- calyx-py/calyx/{fifo_data_gen.py => queue_data_gen.py} | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) rename calyx-py/calyx/{fifo_data_gen.py => queue_data_gen.py} (93%) diff --git a/calyx-py/calyx/fifo_data_gen.py b/calyx-py/calyx/queue_data_gen.py similarity index 93% rename from calyx-py/calyx/fifo_data_gen.py rename to calyx-py/calyx/queue_data_gen.py index da07f57f49..13f5cf211b 100644 --- a/calyx-py/calyx/fifo_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -1,5 +1,4 @@ import random -import time import json from typing import Dict, Union @@ -19,7 +18,7 @@ def dump_json(): 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 `values` memory has MAX_CMDS items: random values between 0 and 400. - 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. """ @@ -32,8 +31,8 @@ def dump_json(): } 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. + "data": [random.randint(0, 400) for _ in range(MAX_CMDS)], + # The `values` memory has MAX_CMDS items: random values between 0 and 00. "format": format_gen(32), } } From 61b43e5a91bcd3c48923cdb3c573503b4d090ec3 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Tue, 7 Nov 2023 19:03:29 -0500 Subject: [PATCH 07/29] Automatic generation of PIFO data and expect --- calyx-py/calyx/fifo_oracle.py | 4 +- calyx-py/calyx/pifo_oracle.py | 79 +++++++++++++++++++++++++++ calyx-py/test/correctness/pifo.data | 38 ++++++------- calyx-py/test/correctness/pifo.expect | 54 +++++++++--------- 4 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 calyx-py/calyx/pifo_oracle.py diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index 6ca4fbd542..66cfdebdbc 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -18,8 +18,8 @@ def parse_json(): def operate_fifo(commands, values): - """Given the three lists, operate a FIFO routine. - - Read the comammands list in order. + """Given the two lists, operate a FIFO routine. + - Read the commands 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. diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py new file mode 100644 index 0000000000..282ccd0798 --- /dev/null +++ b/calyx-py/calyx/pifo_oracle.py @@ -0,0 +1,79 @@ +import fifo_oracle + + +def operate_pifo(commands, values): + """Given the three lists, operate a PIFO routine. + We do this by maintaining two FIFOs and toggling between them when popping. + We have a variable called `hot` that indicates which FIFO is to be popped next. + `hot` starts at 1. + + - Read the commands list in order. + - When the value is 0, we "pop" the PIFO and write the value to the answer memory. + + This is a little complicated since we are actually popping from two FIFOs. + + If `len(FIFO_1) + len(FIFO_2)` = 0, break. + + Try `pop(FIFO_{hot})`. + * If it succeeds it will return a value `v`; just put `v` in + the answer memory. + Also flip `hot` so it points to the other sub-queue. + * If it fails because of underflow, return `pop(queue_{not-hot})`. + Leave `hot` as it was. + - When it is 1, we "peek" into the PIFO and write the value to the answer memory. + - When it is 2, we push the coressponding item in the `values` list into + one of our two FIFOs. + + In particular, if the value is less than 200, it goes into the first FIFO. + + If it is greater than 200, it goes into the second FIFO. + + In the end, we return the answer memory. + """ + fifo_1 = [] + fifo_2 = [] + ans = [] + hot = 1 + for cmd, val in zip(commands, values): + pifo_len = len(fifo_1) + len(fifo_2) + if cmd == 0: + if pifo_len == 0: + break + # We have to pop from the PIFO. + if hot == 1: + try: + ans.append(fifo_1.pop(0)) # Suceess. + hot = 2 # Flip hot. + except IndexError: + ans.append(fifo_2.pop(0)) # Recovery. Leave hot as it was. + else: + try: + ans.append(fifo_2.pop(0)) # Suceess. + hot = 1 # Flip hot. + except IndexError: + ans.append(fifo_1.pop(0)) # Recovery. Leave hot as it was. + elif cmd == 1: + if pifo_len == 0: + break + # We have to peek into the PIFO. + if hot == 1: + try: + ans.append(fifo_1[0]) # Suceess. + except IndexError: + ans.append(fifo_2[0]) # Recovery. + else: + try: + ans.append(fifo_2[0]) # Suceess. + except IndexError: + ans.append(fifo_1[0]) # Recovery. + elif cmd == 2: + # We have to push into the PIFO. + if val < 200: + fifo_1.append(val) + else: + fifo_2.append(val) + + # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. + ans += [0] * (10 - len(ans)) + return ans + + +if __name__ == "__main__": + commands, values = fifo_oracle.parse_json() + ans = operate_pifo(commands, values) + fifo_oracle.dump_json(commands, values, ans) diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index fc06886e71..5f72a3db88 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -2,19 +2,19 @@ "commands": { "data": [ 2, + 1, 2, - 0, - 0, + 1, 2, 2, 2, 2, - 1, 0, + 1, 0, + 2, 0, 0, - 2, 0 ], "format": { @@ -25,21 +25,21 @@ }, "values": { "data": [ - 101, - 102, - 0, - 0, - 103, - 104, - 201, - 202, - 0, - 0, - 0, - 0, - 0, - 105, - 0 + 190, + 240, + 126, + 194, + 278, + 52, + 293, + 127, + 6, + 374, + 110, + 208, + 143, + 93, + 392 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 0631155c8d..e29484e3fe 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -1,48 +1,48 @@ { "ans_mem": [ - 101, - 102, - 201, - 201, - 103, - 202, - 104, - 105, + 190, + 190, + 190, + 278, + 278, + 126, + 293, + 52, 0, 0 ], "commands": [ 2, + 1, 2, - 0, - 0, + 1, 2, 2, 2, 2, - 1, 0, + 1, 0, + 2, 0, 0, - 2, 0 ], "values": [ - 101, - 102, - 0, - 0, - 103, - 104, - 201, - 202, - 0, - 0, - 0, - 0, - 0, - 105, - 0 + 190, + 240, + 126, + 194, + 278, + 52, + 293, + 127, + 6, + 374, + 110, + 208, + 143, + 93, + 392 ] } From 481f8189aa480a0e01258a7775a9a1cc0ebb3ede Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 11:17:14 -0500 Subject: [PATCH 08/29] OO style for FIFO --- calyx-py/calyx/fifo_oracle.py | 59 ++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index 66cfdebdbc..8c106f93ac 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -1,6 +1,11 @@ import sys import json +from dataclasses import dataclass +from typing import List + +ANS_MEM_LEN = 10 + def parse_json(): """Effectively the opposite of `data_gen`: @@ -17,6 +22,37 @@ def parse_json(): return commands, values +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)) + + +@dataclass +class Fifo: + """A FIFO data structure. + Supports the operations `push`, `pop`, and `peek`. + """ + + data: List[int] + + def push(self, val: int): + """Pushes `val` to the FIFO.""" + self.data.append(val) + + def pop(self) -> int: + """Pops the FIFO.""" + return self.data.pop(0) + + def peek(self) -> int: + """Peeks into the FIFO.""" + return self.data[0] + + def operate_fifo(commands, values): """Given the two lists, operate a FIFO routine. - Read the commands list in order. @@ -26,34 +62,27 @@ def operate_fifo(commands, values): In the end, we return the answer memory. """ - fifo = [] + fifo = Fifo([]) ans = [] for cmd, val in zip(commands, values): if cmd == 0: if len(fifo) == 0: break - ans.append(fifo.pop(0)) + ans.append(fifo.pop()) + elif cmd == 1: if len(fifo) == 0: break - ans.append(fifo[0]) + ans.append(fifo.peek()) + elif cmd == 2: - fifo.append(val) + fifo.push(val) + # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. - ans += [0] * (10 - len(ans)) + ans += [0] * (ANS_MEM_LEN - 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) From ca732ec1317bf57ac732c3cf4506e8a8aa928e30 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 11:28:26 -0500 Subject: [PATCH 09/29] PIFOs in OO style --- calyx-py/calyx/pifo_oracle.py | 150 ++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 53 deletions(-) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index 282ccd0798..eec86a4e62 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -1,75 +1,119 @@ import fifo_oracle +from dataclasses import dataclass +from typing import List, Tuple + +ANS_MEM_LEN = 10 + + +@dataclass +class Pifo: + """A PIFO data structure. + Supports the operations `push`, `pop`, and `peek`. -def operate_pifo(commands, values): - """Given the three lists, operate a PIFO routine. We do this by maintaining two FIFOs and toggling between them when popping. We have a variable called `hot` that indicates which FIFO is to be popped next. `hot` starts at 1. - - Read the commands list in order. - - When the value is 0, we "pop" the PIFO and write the value to the answer memory. - + This is a little complicated since we are actually popping from two FIFOs. - + If `len(FIFO_1) + len(FIFO_2)` = 0, break. - + Try `pop(FIFO_{hot})`. - * If it succeeds it will return a value `v`; just put `v` in - the answer memory. - Also flip `hot` so it points to the other sub-queue. - * If it fails because of underflow, return `pop(queue_{not-hot})`. - Leave `hot` as it was. - - When it is 1, we "peek" into the PIFO and write the value to the answer memory. - - When it is 2, we push the coressponding item in the `values` list into - one of our two FIFOs. - + In particular, if the value is less than 200, it goes into the first FIFO. - + If it is greater than 200, it goes into the second FIFO. + We maintain a variable called `pifo_len`: the sum of the lengths of the two FIFOs. + + When asked to pop: + - If `pifo_len` is 0, we raise an error. + - Else, if `hot` is 1, we try to pop from FIFO_1. + + If it succeeds, we flip `hot` to 2 and return the value we got. + + If it fails, we pop from FIFO_2 and return the value we got. + We leave `hot` as it was. + - If `hot` is 2, we proceed symmetrically. + - We decrement `pifo_len` by 1. + + When asked to peek: + We do the same thing as above, except: + - We peek instead of popping. + - We don't flip `hot`. + + When asked to push: + - If the value to be pushed is less than 200, we push it into FIFO_1. + - Else, we push it into FIFO_2. + - We increment `pifo_len` by 1. + """ + + data = Tuple[fifo_oracle.Fifo, fifo_oracle.Fifo] + def __init__(self): + self.data = (fifo_oracle.Fifo([]), fifo_oracle.Fifo([])) + self.hot = 1 + self.pifo_len = 0 + + def push(self, val: int): + """Pushes `val` to the PIFO.""" + if val < 200: + self.data[0].push(val) + else: + self.data[1].push(val) + self.pifo_len += 1 + + def pop(self) -> int: + """Pops the PIFO.""" + if self.pifo_len == 0: + raise IndexError("Cannot pop from empty PIFO.") + if self.hot == 1: + try: + self.pifo_len -= 1 + self.hot = 2 + return self.data[0].pop() + except IndexError: + self.pifo_len -= 1 + return self.data[1].pop() + else: + try: + self.pifo_len -= 1 + self.hot = 1 + return self.data[1].pop() + except IndexError: + self.pifo_len -= 1 + return self.data[0].pop() + + def peek(self) -> int: + """Peeks into the PIFO.""" + if self.pifo_len == 0: + raise IndexError("Cannot peek into empty PIFO.") + if self.hot == 1: + try: + return self.data[0].peek() + except IndexError: + return self.data[1].peek() + else: + try: + return self.data[1].peek() + except IndexError: + return self.data[0].peek() + + +def operate_pifo(commands, values): + """Given the three lists, operate a PIFO routine. In the end, we return the answer memory. """ - fifo_1 = [] - fifo_2 = [] + + pifo = Pifo() ans = [] - hot = 1 for cmd, val in zip(commands, values): - pifo_len = len(fifo_1) + len(fifo_2) if cmd == 0: - if pifo_len == 0: + try: + ans.append(pifo.pop()) + except IndexError: break - # We have to pop from the PIFO. - if hot == 1: - try: - ans.append(fifo_1.pop(0)) # Suceess. - hot = 2 # Flip hot. - except IndexError: - ans.append(fifo_2.pop(0)) # Recovery. Leave hot as it was. - else: - try: - ans.append(fifo_2.pop(0)) # Suceess. - hot = 1 # Flip hot. - except IndexError: - ans.append(fifo_1.pop(0)) # Recovery. Leave hot as it was. + elif cmd == 1: - if pifo_len == 0: + try: + ans.append(pifo.peek()) + except IndexError: break - # We have to peek into the PIFO. - if hot == 1: - try: - ans.append(fifo_1[0]) # Suceess. - except IndexError: - ans.append(fifo_2[0]) # Recovery. - else: - try: - ans.append(fifo_2[0]) # Suceess. - except IndexError: - ans.append(fifo_1[0]) # Recovery. + elif cmd == 2: - # We have to push into the PIFO. - if val < 200: - fifo_1.append(val) - else: - fifo_2.append(val) + pifo.push(val) # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. - ans += [0] * (10 - len(ans)) + ans += [0] * (ANS_MEM_LEN - len(ans)) return ans From 1a03b1ec129429e1c31898969bcf7362728ad17f Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:03:13 -0500 Subject: [PATCH 10/29] Generalize PIFO to take any two queues --- calyx-py/calyx/pifo_oracle.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index eec86a4e62..16d214d617 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -11,17 +11,18 @@ class Pifo: """A PIFO data structure. Supports the operations `push`, `pop`, and `peek`. - We do this by maintaining two FIFOs and toggling between them when popping. - We have a variable called `hot` that indicates which FIFO is to be popped next. + We do this by maintaining two queues that are given to us at initialization. + We toggle between these queues when popping/peeking. + We have a variable called `hot` that says which queue is to be popped/peeked next. `hot` starts at 1. - We maintain a variable called `pifo_len`: the sum of the lengths of the two FIFOs. + We maintain a variable called `pifo_len`: the sum of the lengths of the two queues. When asked to pop: - If `pifo_len` is 0, we raise an error. - - Else, if `hot` is 1, we try to pop from FIFO_1. + - Else, if `hot` is 1, we try to pop from queue_1. + If it succeeds, we flip `hot` to 2 and return the value we got. - + If it fails, we pop from FIFO_2 and return the value we got. + + If it fails, we pop from queue_2 and return the value we got. We leave `hot` as it was. - If `hot` is 2, we proceed symmetrically. - We decrement `pifo_len` by 1. @@ -32,15 +33,13 @@ class Pifo: - We don't flip `hot`. When asked to push: - - If the value to be pushed is less than 200, we push it into FIFO_1. - - Else, we push it into FIFO_2. + - If the value to be pushed is less than 200, we push it into queue_1. + - Else, we push it into queue_2. - We increment `pifo_len` by 1. """ - data = Tuple[fifo_oracle.Fifo, fifo_oracle.Fifo] - - def __init__(self): - self.data = (fifo_oracle.Fifo([]), fifo_oracle.Fifo([])) + def __init__(self, queue_1, queue_2): + self.data = (queue_1, queue_2) self.hot = 1 self.pifo_len = 0 @@ -91,10 +90,13 @@ def peek(self) -> int: def operate_pifo(commands, values): """Given the three lists, operate a PIFO routine. + In this case, we have our PIFO just orchestrate two FIFOs. In the end, we return the answer memory. """ - pifo = Pifo() + pifo = Pifo(fifo_oracle.Fifo([]), fifo_oracle.Fifo([])) + # Our PIFO is simple: it just orchestrates two FIFOs. + ans = [] for cmd, val in zip(commands, values): if cmd == 0: From 5f9ca75f6e340562e4b48fc397277f34135ff5ec Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:19:06 -0500 Subject: [PATCH 11/29] Lift the different queues into their own file --- calyx-py/calyx/fifo_oracle.py | 37 ++------- calyx-py/calyx/pifo_oracle.py | 88 +------------------- calyx-py/calyx/queues.py | 114 ++++++++++++++++++++++++++ calyx-py/test/correctness/fifo.data | 28 +++---- calyx-py/test/correctness/fifo.expect | 44 +++++----- 5 files changed, 160 insertions(+), 151 deletions(-) create mode 100644 calyx-py/calyx/queues.py diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index 8749e247e6..da21a12d41 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -1,8 +1,6 @@ import sys import json - -from dataclasses import dataclass -from typing import List +import queues ANS_MEM_LEN = 10 @@ -32,27 +30,6 @@ def dump_json(commands, values, ans_mem): print(json.dumps(payload, indent=2)) -@dataclass -class Fifo: - """A FIFO data structure. - Supports the operations `push`, `pop`, and `peek`. - """ - - data: List[int] - - def push(self, val: int): - """Pushes `val` to the FIFO.""" - self.data.append(val) - - def pop(self) -> int: - """Pops the FIFO.""" - return self.data.pop(0) - - def peek(self) -> int: - """Peeks into the FIFO.""" - return self.data[0] - - def operate_fifo(commands, values): """Given the two lists, operate a FIFO routine. - Read the commands list in order. @@ -62,18 +39,20 @@ def operate_fifo(commands, values): In the end, we return the answer memory. """ - fifo = Fifo([]) + fifo = queues.Fifo([]) ans = [] for cmd, val in zip(commands, values): if cmd == 0: - if len(fifo) == 0: + try: + ans.append(fifo.pop()) + except IndexError: break - ans.append(fifo.pop()) elif cmd == 1: - if len(fifo) == 0: + try: + ans.append(fifo.peek()) + except IndexError: break - ans.append(fifo.peek()) elif cmd == 2: fifo.push(val) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index 16d214d617..12edb3d98b 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -1,100 +1,16 @@ +import queues import fifo_oracle -from dataclasses import dataclass -from typing import List, Tuple - ANS_MEM_LEN = 10 -@dataclass -class Pifo: - """A PIFO data structure. - Supports the operations `push`, `pop`, and `peek`. - - We do this by maintaining two queues that are given to us at initialization. - We toggle between these queues when popping/peeking. - We have a variable called `hot` that says which queue is to be popped/peeked next. - `hot` starts at 1. - - We maintain a variable called `pifo_len`: the sum of the lengths of the two queues. - - When asked to pop: - - If `pifo_len` is 0, we raise an error. - - Else, if `hot` is 1, we try to pop from queue_1. - + If it succeeds, we flip `hot` to 2 and return the value we got. - + If it fails, we pop from queue_2 and return the value we got. - We leave `hot` as it was. - - If `hot` is 2, we proceed symmetrically. - - We decrement `pifo_len` by 1. - - When asked to peek: - We do the same thing as above, except: - - We peek instead of popping. - - We don't flip `hot`. - - When asked to push: - - If the value to be pushed is less than 200, we push it into queue_1. - - Else, we push it into queue_2. - - We increment `pifo_len` by 1. - """ - - def __init__(self, queue_1, queue_2): - self.data = (queue_1, queue_2) - self.hot = 1 - self.pifo_len = 0 - - def push(self, val: int): - """Pushes `val` to the PIFO.""" - if val < 200: - self.data[0].push(val) - else: - self.data[1].push(val) - self.pifo_len += 1 - - def pop(self) -> int: - """Pops the PIFO.""" - if self.pifo_len == 0: - raise IndexError("Cannot pop from empty PIFO.") - if self.hot == 1: - try: - self.pifo_len -= 1 - self.hot = 2 - return self.data[0].pop() - except IndexError: - self.pifo_len -= 1 - return self.data[1].pop() - else: - try: - self.pifo_len -= 1 - self.hot = 1 - return self.data[1].pop() - except IndexError: - self.pifo_len -= 1 - return self.data[0].pop() - - def peek(self) -> int: - """Peeks into the PIFO.""" - if self.pifo_len == 0: - raise IndexError("Cannot peek into empty PIFO.") - if self.hot == 1: - try: - return self.data[0].peek() - except IndexError: - return self.data[1].peek() - else: - try: - return self.data[1].peek() - except IndexError: - return self.data[0].peek() - - def operate_pifo(commands, values): """Given the three lists, operate a PIFO routine. In this case, we have our PIFO just orchestrate two FIFOs. In the end, we return the answer memory. """ - pifo = Pifo(fifo_oracle.Fifo([]), fifo_oracle.Fifo([])) + pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([])) # Our PIFO is simple: it just orchestrates two FIFOs. ans = [] diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py new file mode 100644 index 0000000000..ae5b00f13a --- /dev/null +++ b/calyx-py/calyx/queues.py @@ -0,0 +1,114 @@ +from dataclasses import dataclass +from typing import List, Tuple + + +@dataclass +class Fifo: + """A FIFO data structure. + Supports the operations `push`, `pop`, and `peek`. + """ + + def __init__(self, data: List[int]): + self.data = data + + def push(self, val: int): + """Pushes `val` to the FIFO.""" + self.data.append(val) + + def pop(self) -> int: + """Pops the FIFO.""" + if len(self.data) == 0: + raise IndexError("Cannot pop from empty FIFO.") + return self.data.pop(0) + + def peek(self) -> int: + """Peeks into the FIFO.""" + if len(self.data) == 0: + raise IndexError("Cannot peek into empty FIFO.") + return self.data[0] + + def __len__(self) -> int: + return len(self.data) + + +@dataclass +class Pifo: + """A PIFO data structure. + Supports the operations `push`, `pop`, and `peek`. + + We do this by maintaining two queues that are given to us at initialization. + We toggle between these queues when popping/peeking. + We have a variable called `hot` that says which queue is to be popped/peeked next. + `hot` starts at 1. + + We maintain internally a variable called `pifo_len`: + the sum of the lengths of the two queues. + + When asked to pop: + - If `pifo_len` is 0, we raise an error. + - Else, if `hot` is 1, we try to pop from queue_1. + + If it succeeds, we flip `hot` to 2 and return the value we got. + + If it fails, we pop from queue_2 and return the value we got. + We leave `hot` as it was. + - If `hot` is 2, we proceed symmetrically. + - We decrement `pifo_len` by 1. + + When asked to peek: + We do the same thing as above, except: + - We peek instead of popping. + - We don't flip `hot`. + + When asked to push: + - If the value to be pushed is less than 200, we push it into queue_1. + - Else, we push it into queue_2. + - We increment `pifo_len` by 1. + """ + + def __init__(self, queue_1, queue_2): + self.data = (queue_1, queue_2) + self.hot = 1 + self.pifo_len = len(queue_1) + len(queue_2) + + def push(self, val: int): + """Pushes `val` to the PIFO.""" + if val < 200: + self.data[0].push(val) + else: + self.data[1].push(val) + self.pifo_len += 1 + + def pop(self) -> int: + """Pops the PIFO.""" + if self.pifo_len == 0: + raise IndexError("Cannot pop from empty PIFO.") + self.pifo_len -= 1 + if self.hot == 1: + try: + self.hot = 2 + return self.data[0].pop() + except IndexError: + return self.data[1].pop() + else: + try: + self.hot = 1 + return self.data[1].pop() + except IndexError: + return self.data[0].pop() + + def peek(self) -> int: + """Peeks into the PIFO.""" + if self.pifo_len == 0: + raise IndexError("Cannot peek into empty PIFO.") + if self.hot == 1: + try: + return self.data[0].peek() + except IndexError: + return self.data[1].peek() + else: + try: + return self.data[1].peek() + except IndexError: + return self.data[0].peek() + + def __len__(self) -> int: + return self.pifo_len diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index 65ab3d659a..5f72a3db88 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -25,21 +25,21 @@ }, "values": { "data": [ - 47, - 60, - 31, - 48, - 69, - 13, - 73, - 31, - 1, - 93, - 27, + 190, + 240, + 126, + 194, + 278, 52, - 35, - 23, - 98 + 293, + 127, + 6, + 374, + 110, + 208, + 143, + 93, + 392 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index 20595ecca5..d55133390a 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -1,13 +1,13 @@ { "ans_mem": [ - 47, - 47, - 47, - 31, - 31, - 69, - 13, - 73, + 190, + 190, + 190, + 126, + 126, + 278, + 52, + 293, 0, 0 ], @@ -29,20 +29,20 @@ 0 ], "values": [ - 47, - 60, - 31, - 48, - 69, - 13, - 73, - 31, - 1, - 93, - 27, + 190, + 240, + 126, + 194, + 278, 52, - 35, - 23, - 98 + 293, + 127, + 6, + 374, + 110, + 208, + 143, + 93, + 392 ] } From d02103ccd9a8825749534974c3b50b1702e185b6 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:31:10 -0500 Subject: [PATCH 12/29] Lift the runner logic too --- calyx-py/calyx/fifo_oracle.py | 79 +++-------------------------------- calyx-py/calyx/pifo_oracle.py | 40 +++--------------- calyx-py/calyx/queues.py | 64 ++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 111 deletions(-) diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index da21a12d41..c862694e75 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -1,78 +1,11 @@ -import sys -import json import queues -ANS_MEM_LEN = 10 +if __name__ == "__main__": + commands, values = queues.parse_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 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)) - - -def operate_fifo(commands, values): - """Given the two lists, operate a FIFO routine. - - Read the commands 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 = queues.Fifo([]) - ans = [] - for cmd, val in zip(commands, values): - if cmd == 0: - try: - ans.append(fifo.pop()) - except IndexError: - break - - elif cmd == 1: - try: - ans.append(fifo.peek()) - except IndexError: - break - - elif cmd == 2: - fifo.push(val) - - # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. - ans += [0] * (ANS_MEM_LEN - 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)) - + pifo = queues.Fifo([]) + # Our PIFO is simple: it just orchestrates two FIFOs. -if __name__ == "__main__": - commands, values = parse_json() - ans = operate_fifo(commands, values) - dump_json(commands, values, ans) + ans = queues.operate_queue(commands, values, pifo) + queues.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index 12edb3d98b..aef0fd4709 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -1,41 +1,11 @@ import queues -import fifo_oracle -ANS_MEM_LEN = 10 +if __name__ == "__main__": + commands, values = queues.parse_json() -def operate_pifo(commands, values): - """Given the three lists, operate a PIFO routine. - In this case, we have our PIFO just orchestrate two FIFOs. - In the end, we return the answer memory. - """ - - pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([])) + pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([]), 200) # Our PIFO is simple: it just orchestrates two FIFOs. - ans = [] - for cmd, val in zip(commands, values): - if cmd == 0: - try: - ans.append(pifo.pop()) - except IndexError: - break - - elif cmd == 1: - try: - ans.append(pifo.peek()) - except IndexError: - break - - elif cmd == 2: - pifo.push(val) - - # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. - ans += [0] * (ANS_MEM_LEN - len(ans)) - return ans - - -if __name__ == "__main__": - commands, values = fifo_oracle.parse_json() - ans = operate_pifo(commands, values) - fifo_oracle.dump_json(commands, values, ans) + ans = queues.operate_queue(commands, values, pifo) + queues.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index ae5b00f13a..836da890d2 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -1,6 +1,10 @@ +import sys +import json from dataclasses import dataclass from typing import List, Tuple +ANS_MEM_LEN = 10 + @dataclass class Fifo: @@ -40,6 +44,7 @@ class Pifo: We toggle between these queues when popping/peeking. We have a variable called `hot` that says which queue is to be popped/peeked next. `hot` starts at 1. + We also take at initialization a `boundary` value. We maintain internally a variable called `pifo_len`: the sum of the lengths of the two queues. @@ -59,19 +64,20 @@ class Pifo: - We don't flip `hot`. When asked to push: - - If the value to be pushed is less than 200, we push it into queue_1. + - If the value to be pushed is less than `boundary`, we push it into queue_1. - Else, we push it into queue_2. - We increment `pifo_len` by 1. """ - def __init__(self, queue_1, queue_2): + def __init__(self, queue_1, queue_2, boundary): self.data = (queue_1, queue_2) self.hot = 1 self.pifo_len = len(queue_1) + len(queue_2) + self.boundary = boundary def push(self, val: int): """Pushes `val` to the PIFO.""" - if val < 200: + if val < self.boundary: self.data[0].push(val) else: self.data[1].push(val) @@ -112,3 +118,55 @@ def peek(self) -> int: def __len__(self) -> int: return self.pifo_len + + +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 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)) + + +def operate_queue(commands, values, queue): + """Given the two lists, one of commands and one of values. + Feed these into our queue, and return the answer memory. + """ + + ans = [] + for cmd, val in zip(commands, values): + if cmd == 0: + try: + ans.append(queue.pop()) + except IndexError: + break + + elif cmd == 1: + try: + ans.append(queue.peek()) + except IndexError: + break + + elif cmd == 2: + queue.push(val) + + # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. + ans += [0] * (ANS_MEM_LEN - len(ans)) + return ans From 0b9c6004cc942d35fb7e61752b8cd2a7c91d4911 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:32:49 -0500 Subject: [PATCH 13/29] Tidying --- calyx-py/calyx/queues.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index 836da890d2..da1948feac 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -1,7 +1,7 @@ import sys import json from dataclasses import dataclass -from typing import List, Tuple +from typing import List ANS_MEM_LEN = 10 @@ -128,7 +128,6 @@ def parse_json(): 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"] From 8c32e723efd974d906541edcab69e02d7f10c3e4 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:33:15 -0500 Subject: [PATCH 14/29] Remove stray file --- calyx-py/calyx/fifo_data_gen.py | 53 --------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 calyx-py/calyx/fifo_data_gen.py diff --git a/calyx-py/calyx/fifo_data_gen.py b/calyx-py/calyx/fifo_data_gen.py deleted file mode 100644 index da07f57f49..0000000000 --- a/calyx-py/calyx/fifo_data_gen.py +++ /dev/null @@ -1,53 +0,0 @@ -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() From 84cf9c5f83d61782530d2a18f7ba812e696f7a89 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:42:06 -0500 Subject: [PATCH 15/29] Tidying --- calyx-py/calyx/fifo_oracle.py | 3 --- calyx-py/calyx/pifo_oracle.py | 2 +- calyx-py/calyx/queues.py | 22 +++++++++++----------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index c862694e75..8cc4104f58 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -3,9 +3,6 @@ if __name__ == "__main__": commands, values = queues.parse_json() - pifo = queues.Fifo([]) - # Our PIFO is simple: it just orchestrates two FIFOs. - ans = queues.operate_queue(commands, values, pifo) queues.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index aef0fd4709..55d7a81bc6 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -4,8 +4,8 @@ if __name__ == "__main__": commands, values = queues.parse_json() + # Our PIFO is simple: it just orchestrates two FIFOs. The boundary is 200. pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([]), 200) - # Our PIFO is simple: it just orchestrates two FIFOs. ans = queues.operate_queue(commands, values, pifo) queues.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index da1948feac..c9c493b9e6 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -43,7 +43,7 @@ class Pifo: We do this by maintaining two queues that are given to us at initialization. We toggle between these queues when popping/peeking. We have a variable called `hot` that says which queue is to be popped/peeked next. - `hot` starts at 1. + `hot` starts at 0. We also take at initialization a `boundary` value. We maintain internally a variable called `pifo_len`: @@ -51,11 +51,11 @@ class Pifo: When asked to pop: - If `pifo_len` is 0, we raise an error. - - Else, if `hot` is 1, we try to pop from queue_1. - + If it succeeds, we flip `hot` to 2 and return the value we got. - + If it fails, we pop from queue_2 and return the value we got. + - Else, if `hot` is 0, we try to pop from queue_0. + + If it succeeds, we flip `hot` to 1 and return the value we got. + + If it fails, we pop from queue_1 and return the value we got. We leave `hot` as it was. - - If `hot` is 2, we proceed symmetrically. + - If `hot` is 1, we proceed symmetrically. - We decrement `pifo_len` by 1. When asked to peek: @@ -71,7 +71,7 @@ class Pifo: def __init__(self, queue_1, queue_2, boundary): self.data = (queue_1, queue_2) - self.hot = 1 + self.hot = 0 self.pifo_len = len(queue_1) + len(queue_2) self.boundary = boundary @@ -87,16 +87,16 @@ def pop(self) -> int: """Pops the PIFO.""" if self.pifo_len == 0: raise IndexError("Cannot pop from empty PIFO.") - self.pifo_len -= 1 - if self.hot == 1: + self.pifo_len -= 1 # We decrement `pifo_len` by 1. + if self.hot == 0: try: - self.hot = 2 + self.hot = 1 return self.data[0].pop() except IndexError: return self.data[1].pop() else: try: - self.hot = 1 + self.hot = 0 return self.data[1].pop() except IndexError: return self.data[0].pop() @@ -105,7 +105,7 @@ def peek(self) -> int: """Peeks into the PIFO.""" if self.pifo_len == 0: raise IndexError("Cannot peek into empty PIFO.") - if self.hot == 1: + if self.hot == 0: try: return self.data[0].peek() except IndexError: From e388fdb9bcc65bb00261d79d0cf056f5e3ff8ff7 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 12:53:48 -0500 Subject: [PATCH 16/29] New data for PIFO tree --- calyx-py/test/correctness/pifo_tree.data | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 254f74da65..5f72a3db88 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -2,17 +2,17 @@ "commands": { "data": [ 2, + 1, 2, + 1, 2, 2, 2, 2, 0, + 1, 0, - 0, - 0, - 0, - 0, + 2, 0, 0, 0 @@ -25,21 +25,21 @@ }, "values": { "data": [ - 11, - 12, - 201, - 202, - 203, - 101, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 190, + 240, + 126, + 194, + 278, + 52, + 293, + 127, + 6, + 374, + 110, + 208, + 143, + 93, + 392 ], "format": { "is_signed": false, @@ -66,4 +66,4 @@ "width": 32 } } -} \ No newline at end of file +} From d29de942a457c3c995abdabb47b1ee806ff2d41f Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 8 Nov 2023 13:00:33 -0500 Subject: [PATCH 17/29] PIFO tree oracle! --- calyx-py/calyx/pifotree_oracle.py | 22 +++++++++ calyx-py/test/correctness/pifo_tree.expect | 54 +++++++++++----------- 2 files changed, 49 insertions(+), 27 deletions(-) create mode 100644 calyx-py/calyx/pifotree_oracle.py diff --git a/calyx-py/calyx/pifotree_oracle.py b/calyx-py/calyx/pifotree_oracle.py new file mode 100644 index 0000000000..9f83b83fca --- /dev/null +++ b/calyx-py/calyx/pifotree_oracle.py @@ -0,0 +1,22 @@ +import queues + + +if __name__ == "__main__": + commands, values = queues.parse_json() + + # Our PIFO is a little complicated: it is a tree of queues. + # The root has two children, which are PIFOs. + # - PIFO_red is the left child. + # + PIFO_red itself has two children, which are FIFOs. + # * FIFO_purple is the left child. + # * FIFO_tangerine is the right child. + # * The boundary for this is 100. + # - FIFO_blue is the right child. + # - The boundary for this is 200. + + pifo = queues.Pifo( + queues.Pifo(queues.Fifo([]), queues.Fifo([]), 100), queues.Fifo([]), 200 + ) + + ans = queues.operate_queue(commands, values, pifo) + queues.dump_json(commands, values, ans) diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index e72076fcf7..c0040e323f 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -1,48 +1,48 @@ { "ans_mem": [ - 11, - 201, - 101, - 202, - 12, - 203, - 0, - 0, + 190, + 190, + 52, + 278, + 278, + 190, + 293, + 126, 0, 0 ], "commands": [ 2, + 1, 2, + 1, 2, 2, 2, 2, 0, + 1, 0, - 0, - 0, - 0, - 0, + 2, 0, 0, 0 ], "values": [ - 11, - 12, - 201, - 202, - 203, - 101, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 190, + 240, + 126, + 194, + 278, + 52, + 293, + 127, + 6, + 374, + 110, + 208, + 143, + 93, + 392 ] } From cf3a9bfe0ed5cd1ee3b32c19900aa0722bfab679 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Fri, 10 Nov 2023 14:22:55 -0500 Subject: [PATCH 18/29] No more ans_mem_len --- calyx-py/calyx/queue_call.py | 3 +-- calyx-py/calyx/queue_data_gen.py | 7 +++---- calyx-py/calyx/queues.py | 6 +++--- calyx-py/test/correctness/fifo.data | 5 +++++ calyx-py/test/correctness/fifo.expect | 5 +++++ calyx-py/test/correctness/pifo.data | 5 +++++ calyx-py/test/correctness/pifo.expect | 5 +++++ calyx-py/test/correctness/pifo_tree.data | 5 +++++ calyx-py/test/correctness/pifo_tree.expect | 5 +++++ 9 files changed, 37 insertions(+), 9 deletions(-) diff --git a/calyx-py/calyx/queue_call.py b/calyx-py/calyx/queue_call.py index e8e0ad1cc9..0f1b3a3e6c 100644 --- a/calyx-py/calyx/queue_call.py +++ b/calyx-py/calyx/queue_call.py @@ -2,7 +2,6 @@ import calyx.builder as cb MAX_CMDS = 15 -ANS_MEM_LEN = 10 def insert_main(prog, queue): @@ -35,7 +34,7 @@ def insert_main(prog, queue): commands = main.seq_mem_d1("commands", 2, MAX_CMDS, 32, is_external=True) values = main.seq_mem_d1("values", 32, MAX_CMDS, 32, is_external=True) - ans_mem = main.seq_mem_d1("ans_mem", 32, 10, 32, is_external=True) + ans_mem = main.seq_mem_d1("ans_mem", 32, MAX_CMDS, 32, is_external=True) # The two components we'll use: queue = main.cell("myqueue", queue) diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index 13f5cf211b..0f9c98d7c8 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -3,7 +3,6 @@ from typing import Dict, Union MAX_CMDS = 15 -ANS_MEM_LEN = 10 FormatType = Dict[str, Union[bool, str, int]] @@ -19,7 +18,7 @@ def dump_json(): - 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 400. - - The `ans_mem` memory has ANS_MEM_LEN items, all zeroes. + - The `ans_mem` memory has MAX_CMDS items, all zeroes. - Each memory has a `format` field, which is a format object for a bitvector. """ commands = { @@ -38,8 +37,8 @@ def dump_json(): } ans_mem = { "ans_mem": { - "data": [0 for _ in range(ANS_MEM_LEN)], - # The `ans_mem` memory has ANS_MEM_LEN items, all zeroes. + "data": [0 for _ in range(MAX_CMDS)], + # The `ans_mem` memory has MAX_CMDS items, all zeroes. "format": format_gen(32), } } diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index c9c493b9e6..2e1754c84e 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from typing import List -ANS_MEM_LEN = 10 +MAX_CMDS = 15 @dataclass @@ -166,6 +166,6 @@ def operate_queue(commands, values, queue): elif cmd == 2: queue.push(val) - # Pad the answer memory with zeroes until it is of length ANS_MEM_LEN. - ans += [0] * (ANS_MEM_LEN - len(ans)) + # Pad the answer memory with zeroes until it is of length MAX_CMDS. + ans += [0] * (MAX_CMDS - len(ans)) return ans diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index 5f72a3db88..2439a4ae13 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -58,6 +58,11 @@ 0, 0, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "format": { diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index d55133390a..29ea3e5e39 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -9,6 +9,11 @@ 52, 293, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "commands": [ diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index 5f72a3db88..2439a4ae13 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -58,6 +58,11 @@ 0, 0, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "format": { diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index e29484e3fe..1aea21b691 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -9,6 +9,11 @@ 293, 52, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "commands": [ diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 5f72a3db88..2439a4ae13 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -58,6 +58,11 @@ 0, 0, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "format": { diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index c0040e323f..c15c273d50 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -9,6 +9,11 @@ 293, 126, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "commands": [ From 302ee0b160fa69d20f2f08372424c9e15e8281e6 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Fri, 10 Nov 2023 15:10:48 -0500 Subject: [PATCH 19/29] const in one place --- calyx-py/calyx/fifo_oracle.py | 6 +++--- calyx-py/calyx/pifo_oracle.py | 6 +++--- calyx-py/calyx/pifotree_oracle.py | 5 +++-- calyx-py/calyx/queue_call.py | 9 ++++----- calyx-py/calyx/queue_data_gen.py | 23 ++++++++++++----------- calyx-py/calyx/queue_util.py | 28 ++++++++++++++++++++++++++++ calyx-py/calyx/queues.py | 31 ++----------------------------- 7 files changed, 55 insertions(+), 53 deletions(-) create mode 100644 calyx-py/calyx/queue_util.py diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index 8cc4104f58..76a4d0919e 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -1,8 +1,8 @@ import queues - +import queue_util if __name__ == "__main__": - commands, values = queues.parse_json() + commands, values = queue_util.parse_json() pifo = queues.Fifo([]) ans = queues.operate_queue(commands, values, pifo) - queues.dump_json(commands, values, ans) + queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index 55d7a81bc6..d60f3349b5 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -1,11 +1,11 @@ import queues - +import queue_util if __name__ == "__main__": - commands, values = queues.parse_json() + commands, values = queue_util.parse_json() # Our PIFO is simple: it just orchestrates two FIFOs. The boundary is 200. pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([]), 200) ans = queues.operate_queue(commands, values, pifo) - queues.dump_json(commands, values, ans) + queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifotree_oracle.py b/calyx-py/calyx/pifotree_oracle.py index 9f83b83fca..0979b3eafa 100644 --- a/calyx-py/calyx/pifotree_oracle.py +++ b/calyx-py/calyx/pifotree_oracle.py @@ -1,8 +1,9 @@ +import queue_util import queues if __name__ == "__main__": - commands, values = queues.parse_json() + commands, values = queue_util.parse_json() # Our PIFO is a little complicated: it is a tree of queues. # The root has two children, which are PIFOs. @@ -19,4 +20,4 @@ ) ans = queues.operate_queue(commands, values, pifo) - queues.dump_json(commands, values, ans) + queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/queue_call.py b/calyx-py/calyx/queue_call.py index 0f1b3a3e6c..cc2437cbd6 100644 --- a/calyx-py/calyx/queue_call.py +++ b/calyx-py/calyx/queue_call.py @@ -1,8 +1,7 @@ # pylint: disable=import-error +import calyx.queue_util as queue_util import calyx.builder as cb -MAX_CMDS = 15 - def insert_main(prog, queue): """Inserts the component `main` into the program. @@ -32,9 +31,9 @@ def insert_main(prog, queue): # - one ref register, `ans`, into which the result of a pop or peek is written. # - one ref register, `err`, which is raised if an error occurs. - commands = main.seq_mem_d1("commands", 2, MAX_CMDS, 32, is_external=True) - values = main.seq_mem_d1("values", 32, MAX_CMDS, 32, is_external=True) - ans_mem = main.seq_mem_d1("ans_mem", 32, MAX_CMDS, 32, is_external=True) + commands = main.seq_mem_d1("commands", 2, queue_util.MAX_CMDS, 32, is_external=True) + values = main.seq_mem_d1("values", 32, queue_util.MAX_CMDS, 32, is_external=True) + ans_mem = main.seq_mem_d1("ans_mem", 32, queue_util.MAX_CMDS, 32, is_external=True) # The two components we'll use: queue = main.cell("myqueue", queue) diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index 0f9c98d7c8..1e1f6a39b8 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -1,8 +1,7 @@ import random import json from typing import Dict, Union - -MAX_CMDS = 15 +import queue_util FormatType = Dict[str, Union[bool, str, int]] @@ -16,29 +15,31 @@ 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 400. - - The `ans_mem` memory has MAX_CMDS items, all zeroes. + - The `commands` memory has queue_util.MAX_CMDS items, which are 0, 1, or 2. + - 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. - 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. + "data": [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS)], + # The `commands` memory has queue_util.MAX_CMDS items, which are 0, 1, or 2. "format": format_gen(2), } } values = { "values": { - "data": [random.randint(0, 400) for _ in range(MAX_CMDS)], - # The `values` memory has MAX_CMDS items: random values between 0 and 00. + "data": [random.randint(0, 400) for _ in range(queue_util.MAX_CMDS)], + # The `values` memory has queue_util.MAX_CMDS items: random values + # between 0 and 400. "format": format_gen(32), } } ans_mem = { "ans_mem": { - "data": [0 for _ in range(MAX_CMDS)], - # The `ans_mem` memory has MAX_CMDS items, all zeroes. + "data": [0 for _ in range(queue_util.MAX_CMDS)], + # The `ans_mem` memory has queue_util.MAX_CMDS items, all zeroes. "format": format_gen(32), } } diff --git a/calyx-py/calyx/queue_util.py b/calyx-py/calyx/queue_util.py new file mode 100644 index 0000000000..f1b52a6bf3 --- /dev/null +++ b/calyx-py/calyx/queue_util.py @@ -0,0 +1,28 @@ +import json +import sys + +MAX_CMDS = 15 + + +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. + """ + + data = json.load(sys.stdin) + commands = data["commands"]["data"] + values = data["values"]["data"] + return commands, values + + +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)) diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index 2e1754c84e..3a7e2092b3 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -1,9 +1,6 @@ -import sys -import json from dataclasses import dataclass from typing import List - -MAX_CMDS = 15 +import queue_util @dataclass @@ -120,30 +117,6 @@ def __len__(self) -> int: return self.pifo_len -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. - """ - - data = json.load(sys.stdin) - commands = data["commands"]["data"] - values = data["values"]["data"] - return commands, values - - -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)) - - def operate_queue(commands, values, queue): """Given the two lists, one of commands and one of values. Feed these into our queue, and return the answer memory. @@ -167,5 +140,5 @@ def operate_queue(commands, values, queue): queue.push(val) # Pad the answer memory with zeroes until it is of length MAX_CMDS. - ans += [0] * (MAX_CMDS - len(ans)) + ans += [0] * (queue_util.MAX_CMDS - len(ans)) return ans From d0b4db6f21cf1c8f788725c85416b19460327339 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Fri, 10 Nov 2023 15:14:32 -0500 Subject: [PATCH 20/29] Better imports --- calyx-py/calyx/fifo_oracle.py | 4 ++-- calyx-py/calyx/pifo_oracle.py | 4 ++-- calyx-py/calyx/pifotree_oracle.py | 4 ++-- calyx-py/calyx/queue_data_gen.py | 2 +- calyx-py/calyx/queues.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index 76a4d0919e..a84442e232 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -1,5 +1,5 @@ -import queues -import queue_util +import calyx.queues as queues +import calyx.queue_util as queue_util if __name__ == "__main__": commands, values = queue_util.parse_json() diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index d60f3349b5..f454a75407 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -1,5 +1,5 @@ -import queues -import queue_util +import calyx.queues as queues +import calyx.queue_util as queue_util if __name__ == "__main__": commands, values = queue_util.parse_json() diff --git a/calyx-py/calyx/pifotree_oracle.py b/calyx-py/calyx/pifotree_oracle.py index 0979b3eafa..e36c901b97 100644 --- a/calyx-py/calyx/pifotree_oracle.py +++ b/calyx-py/calyx/pifotree_oracle.py @@ -1,5 +1,5 @@ -import queue_util -import queues +import calyx.queues as queues +import calyx.queue_util as queue_util if __name__ == "__main__": diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index 1e1f6a39b8..9132aa2c3b 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -1,7 +1,7 @@ import random import json from typing import Dict, Union -import queue_util +import calyx.queue_util as queue_util FormatType = Dict[str, Union[bool, str, int]] diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index 3a7e2092b3..e8426ccbef 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from typing import List -import queue_util +import calyx.queue_util as queue_util @dataclass From cbe2abbff2d5f79cec5fba68a9cb9b383e78a0cf Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Fri, 10 Nov 2023 15:18:19 -0500 Subject: [PATCH 21/29] Rigged random values --- calyx-py/calyx/queue_data_gen.py | 7 +++-- calyx-py/test/correctness/fifo.data | 16 +++++------ calyx-py/test/correctness/fifo.expect | 32 +++++++++++----------- calyx-py/test/correctness/pifo.data | 16 +++++------ calyx-py/test/correctness/pifo.expect | 28 +++++++++---------- calyx-py/test/correctness/pifo_tree.data | 16 +++++------ calyx-py/test/correctness/pifo_tree.expect | 28 +++++++++---------- 7 files changed, 73 insertions(+), 70 deletions(-) diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index 9132aa2c3b..bfcb425ef4 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -23,8 +23,11 @@ def dump_json(): """ commands = { "commands": { - "data": [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS)], - # The `commands` memory has queue_util.MAX_CMDS items, which are 0, 1, or 2. + # We'll "rig" these random values a little. + # The first 20% of the commands will be 2 (push). + # The rest will be generated randomly from among 0, 1, and 2. + "data": [2] * (queue_util.MAX_CMDS // 5) + + [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS * 4 // 5)], "format": format_gen(2), } } diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index 2439a4ae13..50e17cc317 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -1,6 +1,9 @@ { "commands": { "data": [ + 2, + 2, + 2, 2, 1, 2, @@ -12,10 +15,7 @@ 0, 1, 0, - 2, - 0, - 0, - 0 + 2 ], "format": { "is_signed": false, @@ -25,6 +25,9 @@ }, "values": { "data": [ + 26, + 80, + 57, 190, 240, 126, @@ -36,10 +39,7 @@ 6, 374, 110, - 208, - 143, - 93, - 392 + 208 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index 29ea3e5e39..ba91de2750 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -1,13 +1,13 @@ { "ans_mem": [ - 190, - 190, - 190, - 126, - 126, - 278, - 52, - 293, + 26, + 26, + 26, + 80, + 80, + 0, + 0, + 0, 0, 0, 0, @@ -17,6 +17,9 @@ 0 ], "commands": [ + 2, + 2, + 2, 2, 1, 2, @@ -28,12 +31,12 @@ 0, 1, 0, - 2, - 0, - 0, - 0 + 2 ], "values": [ + 26, + 80, + 57, 190, 240, 126, @@ -45,9 +48,6 @@ 6, 374, 110, - 208, - 143, - 93, - 392 + 208 ] } diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index 2439a4ae13..50e17cc317 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -1,6 +1,9 @@ { "commands": { "data": [ + 2, + 2, + 2, 2, 1, 2, @@ -12,10 +15,7 @@ 0, 1, 0, - 2, - 0, - 0, - 0 + 2 ], "format": { "is_signed": false, @@ -25,6 +25,9 @@ }, "values": { "data": [ + 26, + 80, + 57, 190, 240, 126, @@ -36,10 +39,7 @@ 6, 374, 110, - 208, - 143, - 93, - 392 + 208 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 1aea21b691..1236d67098 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -1,13 +1,13 @@ { "ans_mem": [ - 190, - 190, - 190, + 26, + 26, + 26, 278, 278, - 126, - 293, - 52, + 0, + 0, + 0, 0, 0, 0, @@ -17,6 +17,9 @@ 0 ], "commands": [ + 2, + 2, + 2, 2, 1, 2, @@ -28,12 +31,12 @@ 0, 1, 0, - 2, - 0, - 0, - 0 + 2 ], "values": [ + 26, + 80, + 57, 190, 240, 126, @@ -45,9 +48,6 @@ 6, 374, 110, - 208, - 143, - 93, - 392 + 208 ] } diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 2439a4ae13..50e17cc317 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -1,6 +1,9 @@ { "commands": { "data": [ + 2, + 2, + 2, 2, 1, 2, @@ -12,10 +15,7 @@ 0, 1, 0, - 2, - 0, - 0, - 0 + 2 ], "format": { "is_signed": false, @@ -25,6 +25,9 @@ }, "values": { "data": [ + 26, + 80, + 57, 190, 240, 126, @@ -36,10 +39,7 @@ 6, 374, 110, - 208, - 143, - 93, - 392 + 208 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index c15c273d50..1236d67098 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -1,13 +1,13 @@ { "ans_mem": [ - 190, - 190, - 52, + 26, + 26, + 26, 278, 278, - 190, - 293, - 126, + 0, + 0, + 0, 0, 0, 0, @@ -17,6 +17,9 @@ 0 ], "commands": [ + 2, + 2, + 2, 2, 1, 2, @@ -28,12 +31,12 @@ 0, 1, 0, - 2, - 0, - 0, - 0 + 2 ], "values": [ + 26, + 80, + 57, 190, 240, 126, @@ -45,9 +48,6 @@ 6, 374, 110, - 208, - 143, - 93, - 392 + 208 ] } From a0bef3d5335e94aa6184d687be45a507cb2c9978 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Fri, 10 Nov 2023 15:42:55 -0500 Subject: [PATCH 22/29] Playing with const soem --- calyx-py/calyx/queue_call.py | 9 +++--- calyx-py/calyx/queue_util.py | 2 +- calyx-py/test/correctness/fifo.data | 27 ++++++++++++---- calyx-py/test/correctness/fifo.expect | 37 +++++++++++++++------- calyx-py/test/correctness/pifo.data | 27 ++++++++++++---- calyx-py/test/correctness/pifo.expect | 35 ++++++++++++++------ calyx-py/test/correctness/pifo_tree.data | 27 ++++++++++++---- calyx-py/test/correctness/pifo_tree.expect | 35 ++++++++++++++------ 8 files changed, 145 insertions(+), 54 deletions(-) diff --git a/calyx-py/calyx/queue_call.py b/calyx-py/calyx/queue_call.py index cc2437cbd6..e66b50fc73 100644 --- a/calyx-py/calyx/queue_call.py +++ b/calyx-py/calyx/queue_call.py @@ -77,10 +77,10 @@ def insert_main(prog, queue): loop_goes_on # Does the `err` flag say that the loop should continue? ) - update_i_neq_15, _ = main.neq_store_in_reg( + update_i_neq_max_cmds, _ = main.neq_store_in_reg( i.out, - cb.const(32, 15), - "i_neq_15", + cb.const(32, queue_util.MAX_CMDS), + "i_neq_max_cmds", 32, loop_goes_on # Does the `i` index say that the loop should continue? @@ -114,7 +114,8 @@ def insert_main(prog, queue): ], ), incr_i, # Increment the command index - update_i_neq_15, # Did this increment make us need to break? + update_i_neq_max_cmds, + # Did this increment make us need to break? ], ), ], diff --git a/calyx-py/calyx/queue_util.py b/calyx-py/calyx/queue_util.py index f1b52a6bf3..2ab93ab5d4 100644 --- a/calyx-py/calyx/queue_util.py +++ b/calyx-py/calyx/queue_util.py @@ -1,7 +1,7 @@ import json import sys -MAX_CMDS = 15 +MAX_CMDS = 20 def parse_json(): diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index 50e17cc317..2a188684ac 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -5,6 +5,7 @@ 2, 2, 2, + 2, 1, 2, 1, @@ -15,7 +16,11 @@ 0, 1, 0, - 2 + 2, + 0, + 0, + 0, + 1 ], "format": { "is_signed": false, @@ -25,10 +30,6 @@ }, "values": { "data": [ - 26, - 80, - 57, - 190, 240, 126, 194, @@ -39,7 +40,16 @@ 6, 374, 110, - 208 + 208, + 143, + 93, + 392, + 199, + 81, + 390, + 36, + 71, + 316 ], "format": { "is_signed": false, @@ -63,6 +73,11 @@ 0, 0, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "format": { diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index ba91de2750..8d98e13c42 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -1,10 +1,15 @@ { "ans_mem": [ - 26, - 26, - 26, - 80, - 80, + 240, + 240, + 240, + 126, + 126, + 194, + 278, + 52, + 127, + 0, 0, 0, 0, @@ -21,6 +26,7 @@ 2, 2, 2, + 2, 1, 2, 1, @@ -31,13 +37,13 @@ 0, 1, 0, - 2 + 2, + 0, + 0, + 0, + 1 ], "values": [ - 26, - 80, - 57, - 190, 240, 126, 194, @@ -48,6 +54,15 @@ 6, 374, 110, - 208 + 208, + 143, + 93, + 392, + 199, + 81, + 390, + 36, + 71, + 316 ] } diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index 50e17cc317..2a188684ac 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -5,6 +5,7 @@ 2, 2, 2, + 2, 1, 2, 1, @@ -15,7 +16,11 @@ 0, 1, 0, - 2 + 2, + 0, + 0, + 0, + 1 ], "format": { "is_signed": false, @@ -25,10 +30,6 @@ }, "values": { "data": [ - 26, - 80, - 57, - 190, 240, 126, 194, @@ -39,7 +40,16 @@ 6, 374, 110, - 208 + 208, + 143, + 93, + 392, + 199, + 81, + 390, + 36, + 71, + 316 ], "format": { "is_signed": false, @@ -63,6 +73,11 @@ 0, 0, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "format": { diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 1236d67098..25bea2e915 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -1,10 +1,15 @@ { "ans_mem": [ - 26, - 26, - 26, - 278, + 126, + 126, + 126, + 240, + 240, + 194, 278, + 52, + 374, + 0, 0, 0, 0, @@ -21,6 +26,7 @@ 2, 2, 2, + 2, 1, 2, 1, @@ -31,13 +37,13 @@ 0, 1, 0, - 2 + 2, + 0, + 0, + 0, + 1 ], "values": [ - 26, - 80, - 57, - 190, 240, 126, 194, @@ -48,6 +54,15 @@ 6, 374, 110, - 208 + 208, + 143, + 93, + 392, + 199, + 81, + 390, + 36, + 71, + 316 ] } diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 50e17cc317..2a188684ac 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -5,6 +5,7 @@ 2, 2, 2, + 2, 1, 2, 1, @@ -15,7 +16,11 @@ 0, 1, 0, - 2 + 2, + 0, + 0, + 0, + 1 ], "format": { "is_signed": false, @@ -25,10 +30,6 @@ }, "values": { "data": [ - 26, - 80, - 57, - 190, 240, 126, 194, @@ -39,7 +40,16 @@ 6, 374, 110, - 208 + 208, + 143, + 93, + 392, + 199, + 81, + 390, + 36, + 71, + 316 ], "format": { "is_signed": false, @@ -63,6 +73,11 @@ 0, 0, 0, + 0, + 0, + 0, + 0, + 0, 0 ], "format": { diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index 1236d67098..b6689609d2 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -1,10 +1,15 @@ { "ans_mem": [ - 26, - 26, - 26, - 278, + 52, + 52, + 52, + 240, + 240, + 126, 278, + 81, + 374, + 0, 0, 0, 0, @@ -21,6 +26,7 @@ 2, 2, 2, + 2, 1, 2, 1, @@ -31,13 +37,13 @@ 0, 1, 0, - 2 + 2, + 0, + 0, + 0, + 1 ], "values": [ - 26, - 80, - 57, - 190, 240, 126, 194, @@ -48,6 +54,15 @@ 6, 374, 110, - 208 + 208, + 143, + 93, + 392, + 199, + 81, + 390, + 36, + 71, + 316 ] } From 01ad8ae01ce46773e0b0feefb77368cf6e9d9de4 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 15 Nov 2023 12:54:23 -0500 Subject: [PATCH 23/29] FIFO works with 100 commands and queue of length 10 --- calyx-py/calyx/fifo_oracle.py | 4 +- calyx-py/calyx/pifo_oracle.py | 7 +- calyx-py/calyx/pifotree_oracle.py | 10 +- calyx-py/calyx/queue_util.py | 3 +- calyx-py/calyx/queues.py | 25 +- calyx-py/test/correctness/fifo.data | 280 ++++- calyx-py/test/correctness/fifo.expect | 298 ++++- calyx-py/test/correctness/piezo_pifotree.yx | 1197 +++++++++++++++++++ calyx-py/test/correctness/pifo.data | 280 ++++- calyx-py/test/correctness/pifo.expect | 298 ++++- calyx-py/test/correctness/pifo_tree.data | 280 ++++- calyx-py/test/correctness/pifo_tree.expect | 298 ++++- 12 files changed, 2824 insertions(+), 156 deletions(-) create mode 100644 calyx-py/test/correctness/piezo_pifotree.yx diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index a84442e232..790189305d 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -3,6 +3,6 @@ if __name__ == "__main__": commands, values = queue_util.parse_json() - pifo = queues.Fifo([]) - ans = queues.operate_queue(commands, values, pifo) + fifo = queues.Fifo([], queue_util.QUEUE_SIZE) + ans = queues.operate_queue(commands, values, fifo) queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index f454a75407..4e13bd64ff 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -5,7 +5,12 @@ commands, values = queue_util.parse_json() # Our PIFO is simple: it just orchestrates two FIFOs. The boundary is 200. - pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([]), 200) + pifo = queues.Pifo( + queues.Fifo([], queue_util.QUEUE_SIZE), + queues.Fifo([], queue_util.QUEUE_SIZE), + 200, + queue_util.QUEUE_SIZE, + ) ans = queues.operate_queue(commands, values, pifo) queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifotree_oracle.py b/calyx-py/calyx/pifotree_oracle.py index e36c901b97..a6d077ad8c 100644 --- a/calyx-py/calyx/pifotree_oracle.py +++ b/calyx-py/calyx/pifotree_oracle.py @@ -16,7 +16,15 @@ # - The boundary for this is 200. pifo = queues.Pifo( - queues.Pifo(queues.Fifo([]), queues.Fifo([]), 100), queues.Fifo([]), 200 + queues.Pifo( + queues.Fifo([], queue_util.QUEUE_SIZE), + queues.Fifo([], queue_util.QUEUE_SIZE), + 100, + queue_util.QUEUE_SIZE, + ), + queues.Fifo([], queue_util.QUEUE_SIZE), + 200, + queue_util.QUEUE_SIZE, ) ans = queues.operate_queue(commands, values, pifo) diff --git a/calyx-py/calyx/queue_util.py b/calyx-py/calyx/queue_util.py index 2ab93ab5d4..e04380a0b0 100644 --- a/calyx-py/calyx/queue_util.py +++ b/calyx-py/calyx/queue_util.py @@ -1,7 +1,8 @@ import json import sys -MAX_CMDS = 20 +MAX_CMDS = 100 +QUEUE_SIZE = 10 def parse_json(): diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index e8426ccbef..2e43d4f315 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -7,14 +7,20 @@ class Fifo: """A FIFO data structure. Supports the operations `push`, `pop`, and `peek`. + Inherent to the queue is its `max_len`, which is given to us at initialization + and we cannot exceed. """ - def __init__(self, data: List[int]): + def __init__(self, data: List[int], max_len: int): self.data = data + self.max_len = max_len def push(self, val: int): """Pushes `val` to the FIFO.""" - self.data.append(val) + if len(self.data) < self.max_len: + self.data.append(val) + else: + raise IndexError("Cannot push to full FIFO.") def pop(self) -> int: """Pops the FIFO.""" @@ -46,6 +52,10 @@ class Pifo: We maintain internally a variable called `pifo_len`: the sum of the lengths of the two queues. + Inherent to the queue is its `max_len`, which is given to us at initialization + and we cannot exceed. + + When asked to pop: - If `pifo_len` is 0, we raise an error. - Else, if `hot` is 0, we try to pop from queue_0. @@ -66,11 +76,15 @@ class Pifo: - We increment `pifo_len` by 1. """ - def __init__(self, queue_1, queue_2, boundary): + def __init__(self, queue_1, queue_2, boundary, max_len): self.data = (queue_1, queue_2) self.hot = 0 self.pifo_len = len(queue_1) + len(queue_2) self.boundary = boundary + self.max_len = max_len + assert ( + self.pifo_len <= self.max_len + ) # We can't be initialized with a PIFO that is too long. def push(self, val: int): """Pushes `val` to the PIFO.""" @@ -137,7 +151,10 @@ def operate_queue(commands, values, queue): break elif cmd == 2: - queue.push(val) + try: + queue.push(val) + except IndexError: + break # Pad the answer memory with zeroes until it is of length MAX_CMDS. ans += [0] * (queue_util.MAX_CMDS - len(ans)) diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index 2a188684ac..be6996d271 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -1,6 +1,22 @@ { "commands": { "data": [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, 2, 2, 2, @@ -20,7 +36,71 @@ 0, 0, 0, - 1 + 1, + 1, + 0, + 1, + 2, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 2, + 2, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 1, + 0, + 1, + 1, + 1, + 1, + 2, + 1, + 0 ], "format": { "is_signed": false, @@ -30,26 +110,106 @@ }, "values": { "data": [ - 240, - 126, - 194, - 278, - 52, - 293, - 127, - 6, + 246, + 241, + 360, + 90, + 29, + 131, + 11, + 383, + 183, + 206, + 9, + 281, + 214, + 187, + 192, + 296, + 4, + 231, + 23, + 362, + 92, + 319, + 100, + 60, + 386, + 125, + 236, + 176, + 262, + 181, + 268, + 128, + 397, + 236, + 55, + 301, + 383, + 399, + 188, + 151, + 18, + 221, + 46, + 106, + 174, + 262, + 312, + 185, + 75, + 174, + 141, + 359, + 279, + 47, + 159, + 351, + 162, + 156, + 90, + 40, + 320, + 76, + 369, + 352, + 158, + 247, + 82, + 368, + 24, + 41, + 307, + 273, + 207, + 16, + 121, + 379, + 304, + 176, + 128, + 233, + 333, + 215, + 74, + 28, + 326, + 16, + 252, + 171, + 106, + 66, 374, - 110, - 208, - 143, - 93, - 392, - 199, - 81, - 390, - 36, - 71, - 316 + 288, + 67, + 322, + 211, + 54, + 86, + 222, + 190, + 76 ], "format": { "is_signed": false, @@ -59,6 +219,86 @@ }, "ans_mem": { "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index 8d98e13c42..3133867b03 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -1,14 +1,94 @@ { "ans_mem": [ - 240, - 240, - 240, - 126, - 126, - 194, - 278, - 52, - 127, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, @@ -22,6 +102,22 @@ 0 ], "commands": [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, 2, 2, 2, @@ -41,28 +137,172 @@ 0, 0, 0, - 1 + 1, + 1, + 0, + 1, + 2, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 2, + 2, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 1, + 0, + 1, + 1, + 1, + 1, + 2, + 1, + 0 ], "values": [ - 240, - 126, - 194, - 278, - 52, - 293, - 127, - 6, + 246, + 241, + 360, + 90, + 29, + 131, + 11, + 383, + 183, + 206, + 9, + 281, + 214, + 187, + 192, + 296, + 4, + 231, + 23, + 362, + 92, + 319, + 100, + 60, + 386, + 125, + 236, + 176, + 262, + 181, + 268, + 128, + 397, + 236, + 55, + 301, + 383, + 399, + 188, + 151, + 18, + 221, + 46, + 106, + 174, + 262, + 312, + 185, + 75, + 174, + 141, + 359, + 279, + 47, + 159, + 351, + 162, + 156, + 90, + 40, + 320, + 76, + 369, + 352, + 158, + 247, + 82, + 368, + 24, + 41, + 307, + 273, + 207, + 16, + 121, + 379, + 304, + 176, + 128, + 233, + 333, + 215, + 74, + 28, + 326, + 16, + 252, + 171, + 106, + 66, 374, - 110, - 208, - 143, - 93, - 392, - 199, - 81, - 390, - 36, - 71, - 316 + 288, + 67, + 322, + 211, + 54, + 86, + 222, + 190, + 76 ] } diff --git a/calyx-py/test/correctness/piezo_pifotree.yx b/calyx-py/test/correctness/piezo_pifotree.yx new file mode 100644 index 0000000000..c0357fc521 --- /dev/null +++ b/calyx-py/test/correctness/piezo_pifotree.yx @@ -0,0 +1,1197 @@ +import "primitives/core.futil"; +import "primitives/binary_operators.futil"; +import "primitives/memories.futil"; +component stats(flow: 1) -> (count_0: 32, count_1: 32) { + cells { + count_0_sto = std_reg(32); + count_1_sto = std_reg(32); + count_0_sto_incr = std_add(32); + count_1_sto_incr = std_add(32); + eq_1 = std_eq(1); + eq_2 = std_eq(1); + } + wires { + group count_0_sto_incr_group { + count_0_sto_incr.left = count_0_sto.out; + count_0_sto_incr.right = 32'd1; + count_0_sto.write_en = 1'd1; + count_0_sto.in = count_0_sto_incr.out; + count_0_sto_incr_group[done] = count_0_sto.done; + } + group count_1_sto_incr_group { + count_1_sto_incr.left = count_1_sto.out; + count_1_sto_incr.right = 32'd1; + count_1_sto.write_en = 1'd1; + count_1_sto.in = count_1_sto_incr.out; + count_1_sto_incr_group[done] = count_1_sto.done; + } + comb group eq_1_group { + eq_1.left = flow; + eq_1.right = 1'd0; + } + comb group eq_2_group { + eq_2.left = flow; + eq_2.right = 1'd1; + } + count_0 = count_0_sto.out; + count_1 = count_1_sto.out; + } + control { + seq { + par { + if eq_1.out with eq_1_group { + seq { + count_0_sto_incr_group; + } + } + if eq_2.out with eq_2_group { + seq { + count_1_sto_incr_group; + } + } + } + } + } +} +component fifo_purple(cmd: 2, value: 32) -> () { + cells { + mem = seq_mem_d1(32, 10, 32); + next_write = std_reg(32); + next_read = std_reg(32); + ref ans = std_reg(32); + ref err = std_reg(1); + len = std_reg(32); + eq_1 = std_eq(2); + eq_2 = std_eq(2); + eq_3 = std_eq(2); + eq_4 = std_eq(32); + eq_5 = std_eq(32); + eq_6 = std_eq(32); + eq_7 = std_eq(32); + next_write_incr = std_add(32); + next_read_incr = std_add(32); + len_incr = std_add(32); + len_decr = std_sub(32); + } + wires { + comb group eq_1_group { + eq_1.left = cmd; + eq_1.right = 2'd0; + } + comb group eq_2_group { + eq_2.left = cmd; + eq_2.right = 2'd1; + } + comb group eq_3_group { + eq_3.left = cmd; + eq_3.right = 2'd2; + } + comb group eq_4_group { + eq_4.left = next_write.out; + eq_4.right = 32'd10; + } + comb group eq_5_group { + eq_5.left = next_read.out; + eq_5.right = 32'd10; + } + comb group eq_6_group { + eq_6.left = len.out; + eq_6.right = 32'd0; + } + comb group eq_7_group { + eq_7.left = len.out; + eq_7.right = 32'd10; + } + group next_write_incr_group { + next_write_incr.left = next_write.out; + next_write_incr.right = 32'd1; + next_write.write_en = 1'd1; + next_write.in = next_write_incr.out; + next_write_incr_group[done] = next_write.done; + } + group next_read_incr_group { + next_read_incr.left = next_read.out; + next_read_incr.right = 32'd1; + next_read.write_en = 1'd1; + next_read.in = next_read_incr.out; + next_read_incr_group[done] = next_read.done; + } + group len_incr_group { + len_incr.left = len.out; + len_incr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_incr.out; + len_incr_group[done] = len.done; + } + group len_decr_group { + len_decr.left = len.out; + len_decr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_decr.out; + len_decr_group[done] = len.done; + } + group flash_write { + next_write.in = 32'd0; + next_write.write_en = 1'd1; + flash_write[done] = next_write.done; + } + group flash_read { + next_read.in = 32'd0; + next_read.write_en = 1'd1; + flash_read[done] = next_read.done; + } + group raise_err { + err.in = 1'd1; + err.write_en = 1'd1; + raise_err[done] = err.done; + } + group flash_ans { + ans.in = 32'd0; + ans.write_en = 1'd1; + flash_ans[done] = ans.done; + } + group write_payload_to_mem { + mem.addr0 = next_write.out; + mem.write_en = 1'd1; + mem.write_data = value; + write_payload_to_mem[done] = mem.write_done; + } + group read_payload_from_mem_phase1 { + mem.addr0 = next_read.out; + mem.read_en = 1'd1; + read_payload_from_mem_phase1[done] = mem.read_done; + } + group read_payload_from_mem_phase2 { + ans.write_en = 1'd1; + ans.in = mem.read_data; + read_payload_from_mem_phase2[done] = ans.done; + } + } + control { + seq { + par { + if eq_1.out with eq_1_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + read_payload_from_mem_phase1; + read_payload_from_mem_phase2; + next_read_incr_group; + if eq_5.out with eq_5_group { + flash_read; + } + len_decr_group; + } + } + } + if eq_2.out with eq_2_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + read_payload_from_mem_phase1; + read_payload_from_mem_phase2; + } + } + } + if eq_3.out with eq_3_group { + if eq_7.out with eq_7_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + write_payload_to_mem; + next_write_incr_group; + if eq_4.out with eq_4_group { + flash_write; + } + len_incr_group; + } + } + } + } + } + } +} +component fifo_tangerine(cmd: 2, value: 32) -> () { + cells { + mem = seq_mem_d1(32, 10, 32); + next_write = std_reg(32); + next_read = std_reg(32); + ref ans = std_reg(32); + ref err = std_reg(1); + len = std_reg(32); + eq_1 = std_eq(2); + eq_2 = std_eq(2); + eq_3 = std_eq(2); + eq_4 = std_eq(32); + eq_5 = std_eq(32); + eq_6 = std_eq(32); + eq_7 = std_eq(32); + next_write_incr = std_add(32); + next_read_incr = std_add(32); + len_incr = std_add(32); + len_decr = std_sub(32); + } + wires { + comb group eq_1_group { + eq_1.left = cmd; + eq_1.right = 2'd0; + } + comb group eq_2_group { + eq_2.left = cmd; + eq_2.right = 2'd1; + } + comb group eq_3_group { + eq_3.left = cmd; + eq_3.right = 2'd2; + } + comb group eq_4_group { + eq_4.left = next_write.out; + eq_4.right = 32'd10; + } + comb group eq_5_group { + eq_5.left = next_read.out; + eq_5.right = 32'd10; + } + comb group eq_6_group { + eq_6.left = len.out; + eq_6.right = 32'd0; + } + comb group eq_7_group { + eq_7.left = len.out; + eq_7.right = 32'd10; + } + group next_write_incr_group { + next_write_incr.left = next_write.out; + next_write_incr.right = 32'd1; + next_write.write_en = 1'd1; + next_write.in = next_write_incr.out; + next_write_incr_group[done] = next_write.done; + } + group next_read_incr_group { + next_read_incr.left = next_read.out; + next_read_incr.right = 32'd1; + next_read.write_en = 1'd1; + next_read.in = next_read_incr.out; + next_read_incr_group[done] = next_read.done; + } + group len_incr_group { + len_incr.left = len.out; + len_incr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_incr.out; + len_incr_group[done] = len.done; + } + group len_decr_group { + len_decr.left = len.out; + len_decr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_decr.out; + len_decr_group[done] = len.done; + } + group flash_write { + next_write.in = 32'd0; + next_write.write_en = 1'd1; + flash_write[done] = next_write.done; + } + group flash_read { + next_read.in = 32'd0; + next_read.write_en = 1'd1; + flash_read[done] = next_read.done; + } + group raise_err { + err.in = 1'd1; + err.write_en = 1'd1; + raise_err[done] = err.done; + } + group flash_ans { + ans.in = 32'd0; + ans.write_en = 1'd1; + flash_ans[done] = ans.done; + } + group write_payload_to_mem { + mem.addr0 = next_write.out; + mem.write_en = 1'd1; + mem.write_data = value; + write_payload_to_mem[done] = mem.write_done; + } + group read_payload_from_mem_phase1 { + mem.addr0 = next_read.out; + mem.read_en = 1'd1; + read_payload_from_mem_phase1[done] = mem.read_done; + } + group read_payload_from_mem_phase2 { + ans.write_en = 1'd1; + ans.in = mem.read_data; + read_payload_from_mem_phase2[done] = ans.done; + } + } + control { + seq { + par { + if eq_1.out with eq_1_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + read_payload_from_mem_phase1; + read_payload_from_mem_phase2; + next_read_incr_group; + if eq_5.out with eq_5_group { + flash_read; + } + len_decr_group; + } + } + } + if eq_2.out with eq_2_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + read_payload_from_mem_phase1; + read_payload_from_mem_phase2; + } + } + } + if eq_3.out with eq_3_group { + if eq_7.out with eq_7_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + write_payload_to_mem; + next_write_incr_group; + if eq_4.out with eq_4_group { + flash_write; + } + len_incr_group; + } + } + } + } + } + } +} +component pifo_red(cmd: 2, value: 32) -> () { + cells { + queue_l = fifo_purple(); + queue_r = fifo_tangerine(); + flow = std_reg(1); + lt_1 = std_lt(32); + ref ans = std_reg(32); + ref err = std_reg(1); + len = std_reg(32); + hot = std_reg(1); + eq_2 = std_eq(1); + eq_3 = std_eq(1); + eq_4 = std_eq(1); + eq_5 = std_eq(1); + eq_6 = std_eq(32); + eq_7 = std_eq(32); + eq_8 = std_eq(2); + eq_9 = std_eq(2); + eq_10 = std_eq(2); + eq_11 = std_eq(1); + neq_12 = std_neq(1); + hot_not = std_not(1); + len_incr = std_add(32); + len_decr = std_sub(32); + } + wires { + group infer_flow { + lt_1.left = 32'd100; + lt_1.right = value; + flow.write_en = 1'd1; + flow.in = lt_1.out; + infer_flow[done] = flow.done; + } + comb group eq_2_group { + eq_2.left = hot.out; + eq_2.right = 1'd0; + } + comb group eq_3_group { + eq_3.left = hot.out; + eq_3.right = 1'd1; + } + comb group eq_4_group { + eq_4.left = flow.out; + eq_4.right = 1'd0; + } + comb group eq_5_group { + eq_5.left = flow.out; + eq_5.right = 1'd1; + } + comb group eq_6_group { + eq_6.left = len.out; + eq_6.right = 32'd0; + } + comb group eq_7_group { + eq_7.left = len.out; + eq_7.right = 32'd10; + } + comb group eq_8_group { + eq_8.left = cmd; + eq_8.right = 2'd0; + } + comb group eq_9_group { + eq_9.left = cmd; + eq_9.right = 2'd1; + } + comb group eq_10_group { + eq_10.left = cmd; + eq_10.right = 2'd2; + } + comb group eq_11_group { + eq_11.left = err.out; + eq_11.right = 1'd0; + } + comb group neq_12_group { + neq_12.left = err.out; + neq_12.right = 1'd0; + } + group hot_not_group { + hot_not.in = hot.out; + hot.write_en = 1'd1; + hot.in = hot_not.out; + hot_not_group[done] = hot.done; + } + group raise_err { + err.in = 1'd1; + err.write_en = 1'd1; + raise_err[done] = err.done; + } + group lower_err { + err.in = 1'd0; + err.write_en = 1'd1; + lower_err[done] = err.done; + } + group flash_ans { + ans.in = 32'd0; + ans.write_en = 1'd1; + flash_ans[done] = ans.done; + } + group len_incr_group { + len_incr.left = len.out; + len_incr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_incr.out; + len_incr_group[done] = len.done; + } + group len_decr_group { + len_decr.left = len.out; + len_decr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_decr.out; + len_decr_group[done] = len.done; + } + } + control { + seq { + par { + if eq_8.out with eq_8_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + lower_err; + par { + if eq_2.out with eq_2_group { + seq { + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + par { + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + if eq_11.out with eq_11_group { + seq { + hot_not_group; + } + } + } + } + } + if eq_3.out with eq_3_group { + seq { + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + par { + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + if eq_11.out with eq_11_group { + seq { + hot_not_group; + } + } + } + } + } + } + len_decr_group; + } + } + } + if eq_9.out with eq_9_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + lower_err; + par { + if eq_2.out with eq_2_group { + seq { + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + } + } + if eq_3.out with eq_3_group { + seq { + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + } + } + } + } + } + } + if eq_10.out with eq_10_group { + if eq_7.out with eq_7_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + lower_err; + infer_flow; + par { + if eq_4.out with eq_4_group { + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + } + if eq_5.out with eq_5_group { + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + if eq_11.out with eq_11_group { + seq { + len_incr_group; + } + } + } + } + } + } + } + } +} +component fifo_blue(cmd: 2, value: 32) -> () { + cells { + mem = seq_mem_d1(32, 10, 32); + next_write = std_reg(32); + next_read = std_reg(32); + ref ans = std_reg(32); + ref err = std_reg(1); + len = std_reg(32); + eq_1 = std_eq(2); + eq_2 = std_eq(2); + eq_3 = std_eq(2); + eq_4 = std_eq(32); + eq_5 = std_eq(32); + eq_6 = std_eq(32); + eq_7 = std_eq(32); + next_write_incr = std_add(32); + next_read_incr = std_add(32); + len_incr = std_add(32); + len_decr = std_sub(32); + } + wires { + comb group eq_1_group { + eq_1.left = cmd; + eq_1.right = 2'd0; + } + comb group eq_2_group { + eq_2.left = cmd; + eq_2.right = 2'd1; + } + comb group eq_3_group { + eq_3.left = cmd; + eq_3.right = 2'd2; + } + comb group eq_4_group { + eq_4.left = next_write.out; + eq_4.right = 32'd10; + } + comb group eq_5_group { + eq_5.left = next_read.out; + eq_5.right = 32'd10; + } + comb group eq_6_group { + eq_6.left = len.out; + eq_6.right = 32'd0; + } + comb group eq_7_group { + eq_7.left = len.out; + eq_7.right = 32'd10; + } + group next_write_incr_group { + next_write_incr.left = next_write.out; + next_write_incr.right = 32'd1; + next_write.write_en = 1'd1; + next_write.in = next_write_incr.out; + next_write_incr_group[done] = next_write.done; + } + group next_read_incr_group { + next_read_incr.left = next_read.out; + next_read_incr.right = 32'd1; + next_read.write_en = 1'd1; + next_read.in = next_read_incr.out; + next_read_incr_group[done] = next_read.done; + } + group len_incr_group { + len_incr.left = len.out; + len_incr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_incr.out; + len_incr_group[done] = len.done; + } + group len_decr_group { + len_decr.left = len.out; + len_decr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_decr.out; + len_decr_group[done] = len.done; + } + group flash_write { + next_write.in = 32'd0; + next_write.write_en = 1'd1; + flash_write[done] = next_write.done; + } + group flash_read { + next_read.in = 32'd0; + next_read.write_en = 1'd1; + flash_read[done] = next_read.done; + } + group raise_err { + err.in = 1'd1; + err.write_en = 1'd1; + raise_err[done] = err.done; + } + group flash_ans { + ans.in = 32'd0; + ans.write_en = 1'd1; + flash_ans[done] = ans.done; + } + group write_payload_to_mem { + mem.addr0 = next_write.out; + mem.write_en = 1'd1; + mem.write_data = value; + write_payload_to_mem[done] = mem.write_done; + } + group read_payload_from_mem_phase1 { + mem.addr0 = next_read.out; + mem.read_en = 1'd1; + read_payload_from_mem_phase1[done] = mem.read_done; + } + group read_payload_from_mem_phase2 { + ans.write_en = 1'd1; + ans.in = mem.read_data; + read_payload_from_mem_phase2[done] = ans.done; + } + } + control { + seq { + par { + if eq_1.out with eq_1_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + read_payload_from_mem_phase1; + read_payload_from_mem_phase2; + next_read_incr_group; + if eq_5.out with eq_5_group { + flash_read; + } + len_decr_group; + } + } + } + if eq_2.out with eq_2_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + read_payload_from_mem_phase1; + read_payload_from_mem_phase2; + } + } + } + if eq_3.out with eq_3_group { + if eq_7.out with eq_7_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + write_payload_to_mem; + next_write_incr_group; + if eq_4.out with eq_4_group { + flash_write; + } + len_incr_group; + } + } + } + } + } + } +} +component pifo_root(cmd: 2, value: 32) -> () { + cells { + queue_l = pifo_red(); + queue_r = fifo_blue(); + ref stats = stats(); + flow = std_reg(1); + lt_1 = std_lt(32); + ref ans = std_reg(32); + ref err = std_reg(1); + len = std_reg(32); + hot = std_reg(1); + eq_2 = std_eq(1); + eq_3 = std_eq(1); + eq_4 = std_eq(1); + eq_5 = std_eq(1); + eq_6 = std_eq(32); + eq_7 = std_eq(32); + eq_8 = std_eq(2); + eq_9 = std_eq(2); + eq_10 = std_eq(2); + eq_11 = std_eq(1); + neq_12 = std_neq(1); + hot_not = std_not(1); + len_incr = std_add(32); + len_decr = std_sub(32); + } + wires { + group infer_flow { + lt_1.left = 32'd200; + lt_1.right = value; + flow.write_en = 1'd1; + flow.in = lt_1.out; + infer_flow[done] = flow.done; + } + comb group eq_2_group { + eq_2.left = hot.out; + eq_2.right = 1'd0; + } + comb group eq_3_group { + eq_3.left = hot.out; + eq_3.right = 1'd1; + } + comb group eq_4_group { + eq_4.left = flow.out; + eq_4.right = 1'd0; + } + comb group eq_5_group { + eq_5.left = flow.out; + eq_5.right = 1'd1; + } + comb group eq_6_group { + eq_6.left = len.out; + eq_6.right = 32'd0; + } + comb group eq_7_group { + eq_7.left = len.out; + eq_7.right = 32'd10; + } + comb group eq_8_group { + eq_8.left = cmd; + eq_8.right = 2'd0; + } + comb group eq_9_group { + eq_9.left = cmd; + eq_9.right = 2'd1; + } + comb group eq_10_group { + eq_10.left = cmd; + eq_10.right = 2'd2; + } + comb group eq_11_group { + eq_11.left = err.out; + eq_11.right = 1'd0; + } + comb group neq_12_group { + neq_12.left = err.out; + neq_12.right = 1'd0; + } + group hot_not_group { + hot_not.in = hot.out; + hot.write_en = 1'd1; + hot.in = hot_not.out; + hot_not_group[done] = hot.done; + } + group raise_err { + err.in = 1'd1; + err.write_en = 1'd1; + raise_err[done] = err.done; + } + group lower_err { + err.in = 1'd0; + err.write_en = 1'd1; + lower_err[done] = err.done; + } + group flash_ans { + ans.in = 32'd0; + ans.write_en = 1'd1; + flash_ans[done] = ans.done; + } + group len_incr_group { + len_incr.left = len.out; + len_incr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_incr.out; + len_incr_group[done] = len.done; + } + group len_decr_group { + len_decr.left = len.out; + len_decr.right = 32'd1; + len.write_en = 1'd1; + len.in = len_decr.out; + len_decr_group[done] = len.done; + } + } + control { + seq { + par { + if eq_8.out with eq_8_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + lower_err; + par { + if eq_2.out with eq_2_group { + seq { + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + par { + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + if eq_11.out with eq_11_group { + seq { + hot_not_group; + } + } + } + } + } + if eq_3.out with eq_3_group { + seq { + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + par { + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + if eq_11.out with eq_11_group { + seq { + hot_not_group; + } + } + } + } + } + } + len_decr_group; + } + } + } + if eq_9.out with eq_9_group { + if eq_6.out with eq_6_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + lower_err; + par { + if eq_2.out with eq_2_group { + seq { + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + } + } + if eq_3.out with eq_3_group { + seq { + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + if neq_12.out with neq_12_group { + seq { + lower_err; + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + } + } + } + } + } + } + if eq_10.out with eq_10_group { + if eq_7.out with eq_7_group { + seq { + raise_err; + flash_ans; + } + } else { + seq { + lower_err; + infer_flow; + par { + if eq_4.out with eq_4_group { + invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)(); + } + if eq_5.out with eq_5_group { + invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)(); + } + } + if eq_11.out with eq_11_group { + seq { + len_incr_group; + invoke stats(flow=flow.out)(); + } + } + } + } + } + } + } + } +} +component dataplane() -> () { + cells { + ref stats_runner = stats(); + myqueue = pifo_root(); + ref commands = seq_mem_d1(2, 15, 32); + ref values = seq_mem_d1(32, 15, 32); + ref has_ans = std_reg(1); + ref component_ans = std_reg(32); + ref component_err = std_reg(1); + i = std_reg(32); + command = std_reg(2); + value = std_reg(32); + i_incr = std_add(32); + le_1 = std_le(2); + not_2 = std_not(1); + i_eq_MAX_CMDS = std_eq(32); + } + wires { + group i_incr_group { + i_incr.left = i.out; + i_incr.right = 32'd1; + i.write_en = 1'd1; + i.in = i_incr.out; + i_incr_group[done] = i.done; + } + comb group le_1_group { + le_1.left = command.out; + le_1.right = 2'd1; + } + group read_cmd_phase1 { + commands.addr0 = i.out; + commands.read_en = 1'd1; + read_cmd_phase1[done] = commands.read_done; + } + group write_cmd_phase2 { + command.write_en = 1'd1; + command.in = commands.read_data; + write_cmd_phase2[done] = command.done; + } + group read_value { + values.addr0 = i.out; + values.read_en = 1'd1; + read_value[done] = values.read_done; + } + group write_value_to_reg { + value.write_en = 1'd1; + value.in = values.read_data; + write_value_to_reg[done] = value.done; + } + group raise_has_ans { + has_ans.in = 1'd1; + has_ans.write_en = 1'd1; + raise_has_ans[done] = has_ans.done; + } + group lower_has_ans { + has_ans.in = 1'd0; + has_ans.write_en = 1'd1; + lower_has_ans[done] = has_ans.done; + } + comb group not_2_group { + not_2.in = component_err.out; + } + group i_eq_MAX_CMDS_group { + i_eq_MAX_CMDS.left = i.out; + i_eq_MAX_CMDS.right = 32'd15; + component_err.write_en = 1'd1; + component_err.in = i_eq_MAX_CMDS.out; + i_eq_MAX_CMDS_group[done] = component_err.done; + } + } + control { + seq { + read_cmd_phase1; + write_cmd_phase2; + read_value; + write_value_to_reg; + invoke myqueue[ans=component_ans, err=component_err, stats=stats_runner](cmd=command.out, value=value.out)(); + if not_2.out with not_2_group { + seq { + if le_1.out with le_1_group { + seq { + raise_has_ans; + } + } else { + seq { + lower_has_ans; + } + } + i_incr_group; + i_eq_MAX_CMDS_group; + } + } + } + } +} +component controller() -> () { + cells { + ref stats_controller = stats(); + count_0 = std_reg(32); + count_1 = std_reg(32); + } + wires { + group get_data_locally { + count_0.in = stats_controller.count_0; + count_0.write_en = 1'd1; + count_1.in = stats_controller.count_1; + count_1.write_en = 1'd1; + get_data_locally[done] = count_0.done & count_1.done ? 1'd1; + } + } + control { + seq { + get_data_locally; + } + } +} +component main() -> () { + cells { + stats_main = stats(); + dataplane = dataplane(); + controller = controller(); + has_ans = std_reg(1); + dataplane_ans = std_reg(32); + dataplane_err = std_reg(1); + @external commands = seq_mem_d1(2, 15, 32); + @external values = seq_mem_d1(32, 15, 32); + @external ans_mem = seq_mem_d1(32, 10, 32); + j = std_reg(32); + j_incr = std_add(32); + eq_1 = std_eq(1); + } + wires { + group j_incr_group { + j_incr.left = j.out; + j_incr.right = 32'd1; + j.write_en = 1'd1; + j.in = j_incr.out; + j_incr_group[done] = j.done; + } + group write_ans { + ans_mem.addr0 = j.out; + ans_mem.write_en = 1'd1; + ans_mem.write_data = dataplane_ans.out; + write_ans[done] = ans_mem.write_done; + } + comb group eq_1_group { + eq_1.left = dataplane_err.out; + eq_1.right = 1'd0; + } + } + control { + seq { + while eq_1.out with eq_1_group { + seq { + invoke dataplane[commands=commands, values=values, has_ans=has_ans, component_ans=dataplane_ans, component_err=dataplane_err, stats_runner=stats_main]()(); + if has_ans.out { + seq { + write_ans; + j_incr_group; + } + } + invoke controller[stats_controller=stats_main]()(); + } + } + } + } +} diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index 2a188684ac..be6996d271 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -1,6 +1,22 @@ { "commands": { "data": [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, 2, 2, 2, @@ -20,7 +36,71 @@ 0, 0, 0, - 1 + 1, + 1, + 0, + 1, + 2, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 2, + 2, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 1, + 0, + 1, + 1, + 1, + 1, + 2, + 1, + 0 ], "format": { "is_signed": false, @@ -30,26 +110,106 @@ }, "values": { "data": [ - 240, - 126, - 194, - 278, - 52, - 293, - 127, - 6, + 246, + 241, + 360, + 90, + 29, + 131, + 11, + 383, + 183, + 206, + 9, + 281, + 214, + 187, + 192, + 296, + 4, + 231, + 23, + 362, + 92, + 319, + 100, + 60, + 386, + 125, + 236, + 176, + 262, + 181, + 268, + 128, + 397, + 236, + 55, + 301, + 383, + 399, + 188, + 151, + 18, + 221, + 46, + 106, + 174, + 262, + 312, + 185, + 75, + 174, + 141, + 359, + 279, + 47, + 159, + 351, + 162, + 156, + 90, + 40, + 320, + 76, + 369, + 352, + 158, + 247, + 82, + 368, + 24, + 41, + 307, + 273, + 207, + 16, + 121, + 379, + 304, + 176, + 128, + 233, + 333, + 215, + 74, + 28, + 326, + 16, + 252, + 171, + 106, + 66, 374, - 110, - 208, - 143, - 93, - 392, - 199, - 81, - 390, - 36, - 71, - 316 + 288, + 67, + 322, + 211, + 54, + 86, + 222, + 190, + 76 ], "format": { "is_signed": false, @@ -59,6 +219,86 @@ }, "ans_mem": { "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 25bea2e915..3133867b03 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -1,14 +1,94 @@ { "ans_mem": [ - 126, - 126, - 126, - 240, - 240, - 194, - 278, - 52, - 374, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, @@ -22,6 +102,22 @@ 0 ], "commands": [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, 2, 2, 2, @@ -41,28 +137,172 @@ 0, 0, 0, - 1 + 1, + 1, + 0, + 1, + 2, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 2, + 2, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 1, + 0, + 1, + 1, + 1, + 1, + 2, + 1, + 0 ], "values": [ - 240, - 126, - 194, - 278, - 52, - 293, - 127, - 6, + 246, + 241, + 360, + 90, + 29, + 131, + 11, + 383, + 183, + 206, + 9, + 281, + 214, + 187, + 192, + 296, + 4, + 231, + 23, + 362, + 92, + 319, + 100, + 60, + 386, + 125, + 236, + 176, + 262, + 181, + 268, + 128, + 397, + 236, + 55, + 301, + 383, + 399, + 188, + 151, + 18, + 221, + 46, + 106, + 174, + 262, + 312, + 185, + 75, + 174, + 141, + 359, + 279, + 47, + 159, + 351, + 162, + 156, + 90, + 40, + 320, + 76, + 369, + 352, + 158, + 247, + 82, + 368, + 24, + 41, + 307, + 273, + 207, + 16, + 121, + 379, + 304, + 176, + 128, + 233, + 333, + 215, + 74, + 28, + 326, + 16, + 252, + 171, + 106, + 66, 374, - 110, - 208, - 143, - 93, - 392, - 199, - 81, - 390, - 36, - 71, - 316 + 288, + 67, + 322, + 211, + 54, + 86, + 222, + 190, + 76 ] } diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 2a188684ac..be6996d271 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -1,6 +1,22 @@ { "commands": { "data": [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, 2, 2, 2, @@ -20,7 +36,71 @@ 0, 0, 0, - 1 + 1, + 1, + 0, + 1, + 2, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 2, + 2, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 1, + 0, + 1, + 1, + 1, + 1, + 2, + 1, + 0 ], "format": { "is_signed": false, @@ -30,26 +110,106 @@ }, "values": { "data": [ - 240, - 126, - 194, - 278, - 52, - 293, - 127, - 6, + 246, + 241, + 360, + 90, + 29, + 131, + 11, + 383, + 183, + 206, + 9, + 281, + 214, + 187, + 192, + 296, + 4, + 231, + 23, + 362, + 92, + 319, + 100, + 60, + 386, + 125, + 236, + 176, + 262, + 181, + 268, + 128, + 397, + 236, + 55, + 301, + 383, + 399, + 188, + 151, + 18, + 221, + 46, + 106, + 174, + 262, + 312, + 185, + 75, + 174, + 141, + 359, + 279, + 47, + 159, + 351, + 162, + 156, + 90, + 40, + 320, + 76, + 369, + 352, + 158, + 247, + 82, + 368, + 24, + 41, + 307, + 273, + 207, + 16, + 121, + 379, + 304, + 176, + 128, + 233, + 333, + 215, + 74, + 28, + 326, + 16, + 252, + 171, + 106, + 66, 374, - 110, - 208, - 143, - 93, - 392, - 199, - 81, - 390, - 36, - 71, - 316 + 288, + 67, + 322, + 211, + 54, + 86, + 222, + 190, + 76 ], "format": { "is_signed": false, @@ -59,6 +219,86 @@ }, "ans_mem": { "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index b6689609d2..14d81cd825 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -1,14 +1,94 @@ { "ans_mem": [ - 52, - 52, - 52, - 240, - 240, - 126, - 278, - 81, - 374, + 90, + 90, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, @@ -27,42 +107,202 @@ 2, 2, 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 1, + 2, + 1, + 2, + 2, + 2, + 2, + 0, 1, + 0, 2, + 0, + 0, + 0, + 1, + 1, + 0, 1, 2, + 0, + 2, + 0, + 0, 2, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, 2, 2, + 1, + 0, + 0, + 0, + 0, + 0, + 0, 0, + 0, + 1, 1, 0, 2, + 2, + 2, + 0, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 1, 0, 0, + 1, 0, - 1 + 1, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 1, + 0, + 1, + 1, + 1, + 1, + 2, + 1, + 0 ], "values": [ - 240, - 126, - 194, - 278, - 52, - 293, - 127, - 6, + 246, + 241, + 360, + 90, + 29, + 131, + 11, + 383, + 183, + 206, + 9, + 281, + 214, + 187, + 192, + 296, + 4, + 231, + 23, + 362, + 92, + 319, + 100, + 60, + 386, + 125, + 236, + 176, + 262, + 181, + 268, + 128, + 397, + 236, + 55, + 301, + 383, + 399, + 188, + 151, + 18, + 221, + 46, + 106, + 174, + 262, + 312, + 185, + 75, + 174, + 141, + 359, + 279, + 47, + 159, + 351, + 162, + 156, + 90, + 40, + 320, + 76, + 369, + 352, + 158, + 247, + 82, + 368, + 24, + 41, + 307, + 273, + 207, + 16, + 121, + 379, + 304, + 176, + 128, + 233, + 333, + 215, + 74, + 28, + 326, + 16, + 252, + 171, + 106, + 66, 374, - 110, - 208, - 143, - 93, - 392, - 199, - 81, - 390, - 36, - 71, - 316 + 288, + 67, + 322, + 211, + 54, + 86, + 222, + 190, + 76 ] } From 61eaf496657a7c3e4457964a196da0b4ca3ac342 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 15 Nov 2023 12:56:49 -0500 Subject: [PATCH 24/29] PIFO and PIFOtree can also handle long lists of commands --- calyx-py/calyx/queues.py | 3 +++ calyx-py/test/correctness/pifo_tree.expect | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index 2e43d4f315..826392dcef 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -71,6 +71,7 @@ class Pifo: - We don't flip `hot`. When asked to push: + - If the PIFO is at length `max_len`, we raise an error. - If the value to be pushed is less than `boundary`, we push it into queue_1. - Else, we push it into queue_2. - We increment `pifo_len` by 1. @@ -88,6 +89,8 @@ def __init__(self, queue_1, queue_2, boundary, max_len): def push(self, val: int): """Pushes `val` to the PIFO.""" + if self.pifo_len == self.max_len: + raise IndexError("Cannot push to full PIFO.") if val < self.boundary: self.data[0].push(val) else: diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index 14d81cd825..3133867b03 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -1,7 +1,7 @@ { "ans_mem": [ - 90, - 90, + 0, + 0, 0, 0, 0, From 456ca022000f7d1232f09f3efecfef0cfa3bb183 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 15 Nov 2023 13:13:23 -0500 Subject: [PATCH 25/29] Optional max length of queue --- calyx-py/calyx/fifo_oracle.py | 2 +- calyx-py/calyx/pifo_oracle.py | 7 +------ calyx-py/calyx/pifotree_oracle.py | 10 +--------- calyx-py/calyx/queues.py | 8 ++++---- 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/calyx-py/calyx/fifo_oracle.py b/calyx-py/calyx/fifo_oracle.py index 790189305d..68f9905807 100644 --- a/calyx-py/calyx/fifo_oracle.py +++ b/calyx-py/calyx/fifo_oracle.py @@ -3,6 +3,6 @@ if __name__ == "__main__": commands, values = queue_util.parse_json() - fifo = queues.Fifo([], queue_util.QUEUE_SIZE) + fifo = queues.Fifo([]) ans = queues.operate_queue(commands, values, fifo) queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifo_oracle.py b/calyx-py/calyx/pifo_oracle.py index 4e13bd64ff..f454a75407 100644 --- a/calyx-py/calyx/pifo_oracle.py +++ b/calyx-py/calyx/pifo_oracle.py @@ -5,12 +5,7 @@ commands, values = queue_util.parse_json() # Our PIFO is simple: it just orchestrates two FIFOs. The boundary is 200. - pifo = queues.Pifo( - queues.Fifo([], queue_util.QUEUE_SIZE), - queues.Fifo([], queue_util.QUEUE_SIZE), - 200, - queue_util.QUEUE_SIZE, - ) + pifo = queues.Pifo(queues.Fifo([]), queues.Fifo([]), 200) ans = queues.operate_queue(commands, values, pifo) queue_util.dump_json(commands, values, ans) diff --git a/calyx-py/calyx/pifotree_oracle.py b/calyx-py/calyx/pifotree_oracle.py index a6d077ad8c..e36c901b97 100644 --- a/calyx-py/calyx/pifotree_oracle.py +++ b/calyx-py/calyx/pifotree_oracle.py @@ -16,15 +16,7 @@ # - The boundary for this is 200. pifo = queues.Pifo( - queues.Pifo( - queues.Fifo([], queue_util.QUEUE_SIZE), - queues.Fifo([], queue_util.QUEUE_SIZE), - 100, - queue_util.QUEUE_SIZE, - ), - queues.Fifo([], queue_util.QUEUE_SIZE), - 200, - queue_util.QUEUE_SIZE, + queues.Pifo(queues.Fifo([]), queues.Fifo([]), 100), queues.Fifo([]), 200 ) ans = queues.operate_queue(commands, values, pifo) diff --git a/calyx-py/calyx/queues.py b/calyx-py/calyx/queues.py index 826392dcef..77f2982efc 100644 --- a/calyx-py/calyx/queues.py +++ b/calyx-py/calyx/queues.py @@ -11,9 +11,9 @@ class Fifo: and we cannot exceed. """ - def __init__(self, data: List[int], max_len: int): + def __init__(self, data: List[int], max_len: int = None): self.data = data - self.max_len = max_len + self.max_len = max_len or queue_util.QUEUE_SIZE def push(self, val: int): """Pushes `val` to the FIFO.""" @@ -77,12 +77,12 @@ class Pifo: - We increment `pifo_len` by 1. """ - def __init__(self, queue_1, queue_2, boundary, max_len): + def __init__(self, queue_1, queue_2, boundary, max_len=None): self.data = (queue_1, queue_2) self.hot = 0 self.pifo_len = len(queue_1) + len(queue_2) self.boundary = boundary - self.max_len = max_len + self.max_len = max_len or queue_util.QUEUE_SIZE assert ( self.pifo_len <= self.max_len ) # We can't be initialized with a PIFO that is too long. From 359e8abc039b1e29245cdcc368c8f01204a6db8c Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 15 Nov 2023 13:25:08 -0500 Subject: [PATCH 26/29] Less rigging --- calyx-py/calyx/queue_data_gen.py | 6 +-- calyx-py/test/correctness/fifo.data | 44 +++++++++++----------- calyx-py/test/correctness/fifo.expect | 44 +++++++++++----------- calyx-py/test/correctness/pifo.data | 44 +++++++++++----------- calyx-py/test/correctness/pifo.expect | 44 +++++++++++----------- calyx-py/test/correctness/pifo_tree.data | 44 +++++++++++----------- calyx-py/test/correctness/pifo_tree.expect | 44 +++++++++++----------- 7 files changed, 135 insertions(+), 135 deletions(-) diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index bfcb425ef4..256dffaabb 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -24,10 +24,10 @@ def dump_json(): commands = { "commands": { # We'll "rig" these random values a little. - # The first 20% of the commands will be 2 (push). + # The first 10% of the commands will be 2 (push). # The rest will be generated randomly from among 0, 1, and 2. - "data": [2] * (queue_util.MAX_CMDS // 5) - + [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS * 4 // 5)], + "data": [2] * (queue_util.MAX_CMDS // 10) + + [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS * 9 // 10)], "format": format_gen(2), } } diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index be6996d271..3babc996ab 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -1,16 +1,6 @@ { "commands": { "data": [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -100,7 +90,17 @@ 1, 2, 1, - 0 + 0, + 1, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 1, + 1 ], "format": { "is_signed": false, @@ -110,16 +110,6 @@ }, "values": { "data": [ - 246, - 241, - 360, - 90, - 29, - 131, - 11, - 383, - 183, - 206, 9, 281, 214, @@ -209,7 +199,17 @@ 86, 222, 190, - 76 + 76, + 30, + 215, + 150, + 72, + 232, + 317, + 86, + 267, + 232, + 249 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index 3133867b03..715fdd20eb 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -102,16 +102,6 @@ 0 ], "commands": [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -201,19 +191,19 @@ 1, 2, 1, - 0 + 0, + 1, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 1, + 1 ], "values": [ - 246, - 241, - 360, - 90, - 29, - 131, - 11, - 383, - 183, - 206, 9, 281, 214, @@ -303,6 +293,16 @@ 86, 222, 190, - 76 + 76, + 30, + 215, + 150, + 72, + 232, + 317, + 86, + 267, + 232, + 249 ] } diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index be6996d271..3babc996ab 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -1,16 +1,6 @@ { "commands": { "data": [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -100,7 +90,17 @@ 1, 2, 1, - 0 + 0, + 1, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 1, + 1 ], "format": { "is_signed": false, @@ -110,16 +110,6 @@ }, "values": { "data": [ - 246, - 241, - 360, - 90, - 29, - 131, - 11, - 383, - 183, - 206, 9, 281, 214, @@ -209,7 +199,17 @@ 86, 222, 190, - 76 + 76, + 30, + 215, + 150, + 72, + 232, + 317, + 86, + 267, + 232, + 249 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 3133867b03..715fdd20eb 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -102,16 +102,6 @@ 0 ], "commands": [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -201,19 +191,19 @@ 1, 2, 1, - 0 + 0, + 1, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 1, + 1 ], "values": [ - 246, - 241, - 360, - 90, - 29, - 131, - 11, - 383, - 183, - 206, 9, 281, 214, @@ -303,6 +293,16 @@ 86, 222, 190, - 76 + 76, + 30, + 215, + 150, + 72, + 232, + 317, + 86, + 267, + 232, + 249 ] } diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index be6996d271..3babc996ab 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -1,16 +1,6 @@ { "commands": { "data": [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -100,7 +90,17 @@ 1, 2, 1, - 0 + 0, + 1, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 1, + 1 ], "format": { "is_signed": false, @@ -110,16 +110,6 @@ }, "values": { "data": [ - 246, - 241, - 360, - 90, - 29, - 131, - 11, - 383, - 183, - 206, 9, 281, 214, @@ -209,7 +199,17 @@ 86, 222, 190, - 76 + 76, + 30, + 215, + 150, + 72, + 232, + 317, + 86, + 267, + 232, + 249 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index 3133867b03..715fdd20eb 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -102,16 +102,6 @@ 0 ], "commands": [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -201,19 +191,19 @@ 1, 2, 1, - 0 + 0, + 1, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 1, + 1 ], "values": [ - 246, - 241, - 360, - 90, - 29, - 131, - 11, - 383, - 183, - 206, 9, 281, 214, @@ -303,6 +293,16 @@ 86, 222, 190, - 76 + 76, + 30, + 215, + 150, + 72, + 232, + 317, + 86, + 267, + 232, + 249 ] } From a85da3bba30c2e692883c0fbd3612c2839487143 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Wed, 15 Nov 2023 13:26:10 -0500 Subject: [PATCH 27/29] Less rigging --- calyx-py/calyx/queue_data_gen.py | 6 ++--- calyx-py/test/correctness/fifo.data | 22 +++++++++--------- calyx-py/test/correctness/fifo.expect | 26 +++++++++++----------- calyx-py/test/correctness/pifo.data | 22 +++++++++--------- calyx-py/test/correctness/pifo.expect | 26 +++++++++++----------- calyx-py/test/correctness/pifo_tree.data | 22 +++++++++--------- calyx-py/test/correctness/pifo_tree.expect | 26 +++++++++++----------- 7 files changed, 75 insertions(+), 75 deletions(-) diff --git a/calyx-py/calyx/queue_data_gen.py b/calyx-py/calyx/queue_data_gen.py index 256dffaabb..327f2d86db 100644 --- a/calyx-py/calyx/queue_data_gen.py +++ b/calyx-py/calyx/queue_data_gen.py @@ -24,10 +24,10 @@ def dump_json(): commands = { "commands": { # We'll "rig" these random values a little. - # The first 10% of the commands will be 2 (push). + # The first 5% of the commands will be 2 (push). # The rest will be generated randomly from among 0, 1, and 2. - "data": [2] * (queue_util.MAX_CMDS // 10) - + [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS * 9 // 10)], + "data": [2] * (queue_util.MAX_CMDS // 20) + + [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS * 19 // 20)], "format": format_gen(2), } } diff --git a/calyx-py/test/correctness/fifo.data b/calyx-py/test/correctness/fifo.data index 3babc996ab..7d0d68fb24 100644 --- a/calyx-py/test/correctness/fifo.data +++ b/calyx-py/test/correctness/fifo.data @@ -1,11 +1,6 @@ { "commands": { "data": [ - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -100,6 +95,11 @@ 0, 2, 1, + 1, + 0, + 2, + 1, + 1, 1 ], "format": { @@ -110,11 +110,6 @@ }, "values": { "data": [ - 9, - 281, - 214, - 187, - 192, 296, 4, 231, @@ -209,7 +204,12 @@ 86, 267, 232, - 249 + 249, + 352, + 373, + 162, + 245, + 140 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/fifo.expect b/calyx-py/test/correctness/fifo.expect index 715fdd20eb..63c85e68a1 100644 --- a/calyx-py/test/correctness/fifo.expect +++ b/calyx-py/test/correctness/fifo.expect @@ -1,7 +1,7 @@ { "ans_mem": [ - 0, - 0, + 296, + 296, 0, 0, 0, @@ -102,11 +102,6 @@ 0 ], "commands": [ - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -201,14 +196,14 @@ 0, 2, 1, + 1, + 0, + 2, + 1, + 1, 1 ], "values": [ - 9, - 281, - 214, - 187, - 192, 296, 4, 231, @@ -303,6 +298,11 @@ 86, 267, 232, - 249 + 249, + 352, + 373, + 162, + 245, + 140 ] } diff --git a/calyx-py/test/correctness/pifo.data b/calyx-py/test/correctness/pifo.data index 3babc996ab..7d0d68fb24 100644 --- a/calyx-py/test/correctness/pifo.data +++ b/calyx-py/test/correctness/pifo.data @@ -1,11 +1,6 @@ { "commands": { "data": [ - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -100,6 +95,11 @@ 0, 2, 1, + 1, + 0, + 2, + 1, + 1, 1 ], "format": { @@ -110,11 +110,6 @@ }, "values": { "data": [ - 9, - 281, - 214, - 187, - 192, 296, 4, 231, @@ -209,7 +204,12 @@ 86, 267, 232, - 249 + 249, + 352, + 373, + 162, + 245, + 140 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo.expect b/calyx-py/test/correctness/pifo.expect index 715fdd20eb..342f598736 100644 --- a/calyx-py/test/correctness/pifo.expect +++ b/calyx-py/test/correctness/pifo.expect @@ -1,7 +1,7 @@ { "ans_mem": [ - 0, - 0, + 4, + 4, 0, 0, 0, @@ -102,11 +102,6 @@ 0 ], "commands": [ - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -201,14 +196,14 @@ 0, 2, 1, + 1, + 0, + 2, + 1, + 1, 1 ], "values": [ - 9, - 281, - 214, - 187, - 192, 296, 4, 231, @@ -303,6 +298,11 @@ 86, 267, 232, - 249 + 249, + 352, + 373, + 162, + 245, + 140 ] } diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 3babc996ab..7d0d68fb24 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -1,11 +1,6 @@ { "commands": { "data": [ - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -100,6 +95,11 @@ 0, 2, 1, + 1, + 0, + 2, + 1, + 1, 1 ], "format": { @@ -110,11 +110,6 @@ }, "values": { "data": [ - 9, - 281, - 214, - 187, - 192, 296, 4, 231, @@ -209,7 +204,12 @@ 86, 267, 232, - 249 + 249, + 352, + 373, + 162, + 245, + 140 ], "format": { "is_signed": false, diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index 715fdd20eb..342f598736 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -1,7 +1,7 @@ { "ans_mem": [ - 0, - 0, + 4, + 4, 0, 0, 0, @@ -102,11 +102,6 @@ 0 ], "commands": [ - 2, - 2, - 2, - 2, - 2, 2, 2, 2, @@ -201,14 +196,14 @@ 0, 2, 1, + 1, + 0, + 2, + 1, + 1, 1 ], "values": [ - 9, - 281, - 214, - 187, - 192, 296, 4, 231, @@ -303,6 +298,11 @@ 86, 267, 232, - 249 + 249, + 352, + 373, + 162, + 245, + 140 ] } From e7f6717f6fd7e82c27a161725060d420b586dd0a Mon Sep 17 00:00:00 2001 From: Anshuman Mohan <10830208+anshumanmohan@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:33:51 -0500 Subject: [PATCH 28/29] Update pifotree_oracle.py --- calyx-py/calyx/pifotree_oracle.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calyx-py/calyx/pifotree_oracle.py b/calyx-py/calyx/pifotree_oracle.py index 7340ac234a..9ca1f2c350 100644 --- a/calyx-py/calyx/pifotree_oracle.py +++ b/calyx-py/calyx/pifotree_oracle.py @@ -20,4 +20,5 @@ ) ans = queues.operate_queue(commands, values, pifo) - queue_util.dump_json(commands, values, ans) \ No newline at end of file + queue_util.dump_json(commands, values, ans) + From 7c157f28b4c58ceb692b2e6c4643275b568bf5e5 Mon Sep 17 00:00:00 2001 From: Anshuman Mohan Date: Thu, 16 Nov 2023 16:44:46 -0500 Subject: [PATCH 29/29] Newly generated .data and .expect to reverse bad merge --- calyx-py/test/correctness/pifo_tree.data | 10 ++++++++-- calyx-py/test/correctness/pifo_tree.expect | 2 -- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/calyx-py/test/correctness/pifo_tree.data b/calyx-py/test/correctness/pifo_tree.data index 3fa1c191c9..7d0d68fb24 100644 --- a/calyx-py/test/correctness/pifo_tree.data +++ b/calyx-py/test/correctness/pifo_tree.data @@ -2,9 +2,7 @@ "commands": { "data": [ 2, - 1, 2, - 1, 2, 2, 2, @@ -21,6 +19,14 @@ 0, 2, 0, + 0, + 0, + 1, + 1, + 0, + 1, + 2, + 0, 2, 0, 0, diff --git a/calyx-py/test/correctness/pifo_tree.expect b/calyx-py/test/correctness/pifo_tree.expect index 7902d5bfb7..342f598736 100644 --- a/calyx-py/test/correctness/pifo_tree.expect +++ b/calyx-py/test/correctness/pifo_tree.expect @@ -103,9 +103,7 @@ ], "commands": [ 2, - 1, 2, - 1, 2, 2, 2,