Skip to content

Commit

Permalink
eDSL: Tidy memories (#2052)
Browse files Browse the repository at this point in the history
* Require group names for comb_mem loads and stores

* Require group names for seq mem loads and stores

* Rename for consistency

* Unify two helpers

* Unify two helpers for seq mem reads

* Unify two more helpers

* Use the argument label more often

* Some backticks
  • Loading branch information
anshumanmohan authored May 27, 2024
1 parent b260b37 commit db79307
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 70 deletions.
66 changes: 16 additions & 50 deletions calyx-py/calyx/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,76 +704,42 @@ def reg_store(self, reg, val, groupname=None):
reg_grp.done = reg.done
return reg_grp

def mem_load_comb_mem_d1(self, mem, i, reg, groupname=None):
def mem_load_d1(self, mem, i, reg, groupname, is_comb=False):
"""Inserts wiring into `self` to perform `reg := mem[i]`,
where `mem` is a comb_mem_d1 memory.
where `mem` is a seq_d1 memory or a comb_mem_d1 memory (if `is_comb` is True)
"""
assert mem.is_comb_mem_d1()
groupname = groupname or f"{mem.name()}_load_to_reg"
assert mem.is_seq_mem_d1() if not is_comb else mem.is_comb_mem_d1()
with self.group(groupname) as load_grp:
mem.addr0 = i
reg.write_en = 1
reg.in_ = mem.read_data
if is_comb:
reg.write_en = 1
reg.in_ = mem.read_data
else:
mem.content_en = 1
reg.write_en = mem.done @ 1
reg.in_ = mem.done @ mem.read_data
load_grp.done = reg.done
return load_grp

def mem_store_comb_mem_d1(self, mem, i, val, groupname=None):
"""Inserts wiring into `self` to perform `mem[i] := val`,
where `mem` is a comb_mem_d1 memory."""
assert mem.is_comb_mem_d1()
groupname = groupname or f"store_into_{mem.name()}"
with self.group(groupname) as store_grp:
mem.addr0 = i
mem.write_en = 1
mem.write_data = val
store_grp.done = mem.done
return store_grp

def mem_read_seq_d1(self, mem, i, groupname=None):
"""Inserts wiring into `self` to latch `mem[i]` as the output of `mem`,
where `mem` is a seq_d1 memory.
Note that this does not write the value anywhere.
"""
assert mem.is_seq_mem_d1()
groupname = groupname or f"read_from_{mem.name()}"
with self.group(groupname) as read_grp:
mem.addr0 = i
mem.content_en = 1
read_grp.done = mem.done
return read_grp

def mem_write_seq_d1_to_reg(self, mem, reg, groupname=None):
"""Inserts wiring into `self` to perform reg := <mem_latched_value>,
where `mem` is a seq_d1 memory that already has some latched value.
"""
assert mem.is_seq_mem_d1()
groupname = groupname or f"{mem.name()}_write_to_reg"
with self.group(groupname) as write_grp:
reg.write_en = 1
reg.in_ = mem.read_data
write_grp.done = reg.done
return write_grp

def mem_store_seq_d1(self, mem, i, val, groupname=None):
def mem_store_d1(self, mem, i, val, groupname, is_comb=False):
"""Inserts wiring into `self` to perform `mem[i] := val`,
where `mem` is a seq_d1 memory.
where `mem` is a seq_d1 memory or a comb_mem_d1 memory (if `is_comb` is True)
"""
assert mem.is_seq_mem_d1()
groupname = groupname or f"{mem.name()}_store"
assert mem.is_seq_mem_d1() if not is_comb else mem.is_comb_mem_d1()
with self.group(groupname) as store_grp:
mem.addr0 = i
mem.write_en = 1
mem.write_data = val
mem.content_en = 1
store_grp.done = mem.done
if not is_comb:
mem.content_en = 1
return store_grp

def mem_load_to_mem(self, mem, i, ans, j, groupname=None):
def mem_load_to_mem(self, mem, i, ans, j, groupname):
"""Inserts wiring into `self` to perform `ans[j] := mem[i]`,
where `mem` and `ans` are both comb_mem_d1 memories.
"""
assert mem.is_comb_mem_d1() and ans.is_comb_mem_d1()
groupname = groupname or f"{mem.name()}_load_to_mem"
with self.group(groupname) as load_grp:
mem.addr0 = i
ans.write_en = 1
Expand Down
8 changes: 4 additions & 4 deletions calyx-py/calyx/gen_exp.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,9 +700,9 @@ def build_base_not_e(degree, width, int_width, is_signed) -> Program:
ret = main.comb_mem_d1("ret", width, 1, 1, is_external=True)
f = main.comp_instance("f", "fp_pow_full")

read_base = main.mem_load_comb_mem_d1(b, 0, base_reg, "read_base")
read_exp = main.mem_load_comb_mem_d1(x, 0, exp_reg, "read_exp")
write_to_memory = main.mem_store_comb_mem_d1(ret, 0, f.out, "write_to_memory")
read_base = main.mem_load_d1(b, 0, base_reg, "read_base", is_comb=True)
read_exp = main.mem_load_d1(x, 0, exp_reg, "read_exp", is_comb=True)
write_to_memory = main.mem_store_d1(ret, 0, f.out, "write_to_memory", is_comb=True)

main.control += [
read_base,
Expand Down Expand Up @@ -741,7 +741,7 @@ def build_base_is_e(degree, width, int_width, is_signed) -> Program:
t.write_en = 1
init.done = t.done

write_to_memory = main.mem_store_comb_mem_d1(ret, 0, e.out, "write_to_memory")
write_to_memory = main.mem_store_d1(ret, 0, e.out, "write_to_memory", is_comb=True)

main.control += [
init,
Expand Down
12 changes: 3 additions & 9 deletions calyx-py/calyx/queue_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,8 @@ def insert_runner(prog, queue, name, stats_component=None):
cmd_le_1 = runner.le_use(cmd.out, 1) # cmd <= 1, meaning cmd is pop or peek

# Wiring to perform `cmd := commands[i]` and `value := values[i]`.
read_cmd = runner.mem_read_seq_d1(commands, i.out, "read_cmd_phase1")
write_cmd_to_reg = runner.mem_write_seq_d1_to_reg(commands, cmd, "write_cmd_phase2")
read_value = runner.mem_read_seq_d1(values, i.out, "read_value")
write_value_to_reg = runner.mem_write_seq_d1_to_reg(
values, value, "write_value_to_reg"
)
write_cmd_to_reg = runner.mem_load_d1(commands, i.out, cmd, "write_cmd")
write_value_to_reg = runner.mem_load_d1(values, i.out, value, "write_value")

# Wiring to raise/lower flags and compute a negation.
raise_has_ans = runner.reg_store(has_ans, 1, "raise_has_ans")
Expand All @@ -85,9 +81,7 @@ def insert_runner(prog, queue, name, stats_component=None):
check_if_out_of_cmds, _ = runner.eq_store_in_reg(i.out, queue_util.MAX_CMDS, err)

runner.control += [
read_cmd,
write_cmd_to_reg, # `cmd := commands[i]`
read_value,
write_value_to_reg, # `value := values[i]`
(
cb.invoke( # Invoke the queue.
Expand Down Expand Up @@ -149,7 +143,7 @@ def insert_main(prog, queue, controller=None, stats_component=None):

j = main.reg(32) # The index on the answer-list we'll write to
incr_j = main.incr(j) # j++
write_ans = main.mem_store_seq_d1(ans_mem, j.out, dataplane_ans.out, "write_ans")
write_ans = main.mem_store_d1(ans_mem, j.out, dataplane_ans.out, "write_ans")
# ans_mem[j] = dataplane_ans
lower_has_ans = main.reg_store(has_ans, 0, "lower_has_ans") # has_ans := 0

Expand Down
8 changes: 2 additions & 6 deletions calyx-py/test/correctness/queues/fifo.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,8 @@ def insert_fifo(prog, name, queue_len_factor=QUEUE_LEN_FACTOR):
raise_err = fifo.reg_store(err, 1, "raise_err") # err := 1

# Load and store into an arbitary slot in memory
write_to_mem = fifo.mem_store_seq_d1(mem, write.out, value, "write_payload_to_mem")
read_from_mem = fifo.mem_read_seq_d1(mem, read.out, "read_payload_from_mem_phase1")
write_to_ans = fifo.mem_write_seq_d1_to_reg(
mem, ans, "read_payload_from_mem_phase2"
)
write_to_mem = fifo.mem_store_d1(mem, write.out, value, "write_payload_to_mem")
write_to_ans = fifo.mem_load_d1(mem, read.out, ans, "read_payload_from_mem")

fifo.control += cb.par(
# Was it a (pop/peek), or a push? We can do those two cases in parallel.
Expand All @@ -73,7 +70,6 @@ def insert_fifo(prog, name, queue_len_factor=QUEUE_LEN_FACTOR):
len_eq_0,
raise_err, # The queue is empty: underflow.
[ # The queue is not empty. Proceed.
read_from_mem, # Read from the queue.
write_to_ans, # Write the answer to the answer register.
cb.if_with(
cmd_eq_0, # Did the user call pop?
Expand Down
2 changes: 1 addition & 1 deletion frontends/ntt-pipeline/gen-ntt-pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def preamble_group(comp: cb.ComponentBuilder, row):
def epilogue_group(comp: cb.ComponentBuilder, row):
input = comp.get_cell("a")
A = comp.get_cell(f"A{row}")
comp.mem_store_comb_mem_d1(input, row, A.out, f"epilogue_{row}")
comp.mem_store_d1(input, row, A.out, f"epilogue_{row}", is_comb=True)

def insert_cells(comp: cb.ComponentBuilder):
# memories
Expand Down

0 comments on commit db79307

Please sign in to comment.