Skip to content

Commit

Permalink
Queues: collect magic numbers, pass 100 commands (#1771)
Browse files Browse the repository at this point in the history
  • Loading branch information
anshumanmohan committed Nov 16, 2023
1 parent 5160e84 commit 879d13c
Show file tree
Hide file tree
Showing 14 changed files with 2,966 additions and 183 deletions.
12 changes: 6 additions & 6 deletions calyx-py/calyx/fifo_oracle.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import queues

import calyx.queues as queues
import calyx.queue_util as queue_util

if __name__ == "__main__":
commands, values = queues.parse_json()
pifo = queues.Fifo([])
ans = queues.operate_queue(commands, values, pifo)
queues.dump_json(commands, values, ans)
commands, values = queue_util.parse_json()
fifo = queues.Fifo([])
ans = queues.operate_queue(commands, values, fifo)
queue_util.dump_json(commands, values, ans)
8 changes: 4 additions & 4 deletions calyx-py/calyx/pifo_oracle.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import queues

import calyx.queues as queues
import calyx.queue_util as 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)
8 changes: 5 additions & 3 deletions calyx-py/calyx/pifotree_oracle.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import queues
import calyx.queues as queues
import calyx.queue_util as queue_util


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.
Expand All @@ -19,4 +20,5 @@
)

ans = queues.operate_queue(commands, values, pifo)
queues.dump_json(commands, values, ans)
queue_util.dump_json(commands, values, ans)

19 changes: 9 additions & 10 deletions calyx-py/calyx/queue_call.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# pylint: disable=import-error
import calyx.queue_util as queue_util
import calyx.builder as cb

MAX_CMDS = 15
ANS_MEM_LEN = 10


def insert_main(prog, queue):
"""Inserts the component `main` into the program.
Expand Down Expand Up @@ -33,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, 10, 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)
Expand Down Expand Up @@ -79,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?
Expand Down Expand Up @@ -116,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?
],
),
],
Expand Down
27 changes: 15 additions & 12 deletions calyx-py/calyx/queue_data_gen.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import random
import json
from typing import Dict, Union

MAX_CMDS = 15
ANS_MEM_LEN = 10
import calyx.queue_util as queue_util

FormatType = Dict[str, Union[bool, str, int]]

Expand All @@ -17,29 +15,34 @@ 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 ANS_MEM_LEN 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.
# We'll "rig" these random values a little.
# 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 // 20)
+ [random.randint(0, 2) for _ in range(queue_util.MAX_CMDS * 19 // 20)],
"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(ANS_MEM_LEN)],
# The `ans_mem` memory has ANS_MEM_LEN 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),
}
}
Expand Down
29 changes: 29 additions & 0 deletions calyx-py/calyx/queue_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import json
import sys

MAX_CMDS = 100
QUEUE_SIZE = 10


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))
61 changes: 27 additions & 34 deletions calyx-py/calyx/queues.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import sys
import json
from dataclasses import dataclass
from typing import List

ANS_MEM_LEN = 10
import calyx.queue_util as queue_util


@dataclass
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 = None):
self.data = data
self.max_len = max_len or queue_util.QUEUE_SIZE

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."""
Expand Down Expand Up @@ -49,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.
Expand All @@ -64,19 +71,26 @@ 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.
"""

def __init__(self, queue_1, queue_2, boundary):
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 or queue_util.QUEUE_SIZE
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."""
if self.pifo_len == self.max_len:
raise IndexError("Cannot push to full PIFO.")
if val < self.boundary:
self.data[0].push(val)
else:
Expand Down Expand Up @@ -120,30 +134,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.
Expand All @@ -164,8 +154,11 @@ 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 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] * (queue_util.MAX_CMDS - len(ans))
return ans
Loading

0 comments on commit 879d13c

Please sign in to comment.