Skip to content

Commit

Permalink
formating
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanielnrn committed Dec 30, 2024
1 parent 108fdf4 commit 51d948a
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 85 deletions.
5 changes: 4 additions & 1 deletion yxi/axi-calyx/axi_generator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# The *original* axi generator which implement a read-compute-write sequence
# to get data in and out of the computational kernel.
# A `dynamic_axi_generator` also exists

from calyx.builder import (
Builder,
add_comp_ports,
invoke,
while_with,
par,
while_,
)
Expand Down
184 changes: 100 additions & 84 deletions yxi/axi-calyx/dynamic_axi_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@
# in and out of the computational kernel as needed. Compare with the
# read-compute-write implementation in the original `axi_generator`.

from calyx.builder import (
Builder,
add_comp_ports,
invoke,
par,
while_,
if_
)
from calyx.builder import Builder, add_comp_ports, invoke, par, while_, if_
from typing import Literal
from math import log2, ceil
import json
Expand All @@ -21,11 +14,12 @@
width_key = "data_width"
size_key = "total_size"
name_key = "name"
#This returns an array based on dimensions of memory
# This returns an array based on dimensions of memory
address_width_key = "idx_sizes"
type_key = "memory_type"

#TODO (nathanielnrn): Should we make these comb groups?

# TODO (nathanielnrn): Should we make these comb groups?
def add_address_translator(prog, mem):
address_width = mem[address_width_key][0]
data_width = mem[width_key]
Expand All @@ -36,13 +30,14 @@ def add_address_translator(prog, mem):
translator_output = [("axi_address", 64)]
add_comp_ports(address_translator, translator_inputs, translator_output)

#Cells
#XRT expects 64 bit address.
address_mult = address_translator.const_mult(64, width_in_bytes(data_width), f"mul_{name}")
# Cells
# XRT expects 64 bit address.
address_mult = address_translator.const_mult(
64, width_in_bytes(data_width), f"mul_{name}"
)
pad_input_addr = address_translator.pad(address_width, 64, f"pad_input_addr")


#Assignment
# Assignment
with address_translator.continuous:
pad_input_addr.in_ = address_translator.this()["calyx_mem_addr"]
address_mult.in_ = pad_input_addr.out
Expand Down Expand Up @@ -113,12 +108,14 @@ def _add_m_to_s_address_channel(prog, mem, prefix: Literal["AW", "AR"]):
xhandshake_occurred.write_en = (~xhandshake_occurred.out) @ 1

# Drive output signals for transfer
m_to_s_address_channel.this()[f"{x}ADDR"] = m_to_s_address_channel.this()["axi_address"]
m_to_s_address_channel.this()[f"{x}ADDR"] = m_to_s_address_channel.this()[
"axi_address"
]
# This is taken from mem size, we assume the databus width is the size
# of our memory cell and that width is a power of 2
# TODO(nathanielnrn): convert to binary instead of decimal
m_to_s_address_channel.this()[f"{x}SIZE"] = width_xsize(mem[width_key])
#Dynamic accesses only need asingle transfer per transcation
# Dynamic accesses only need asingle transfer per transcation
m_to_s_address_channel.this()[f"{x}LEN"] = 0
m_to_s_address_channel.this()[f"{x}BURST"] = 1 # Must be INCR for XRT
# Required by spec, we hardcode to privileged, non-secure, data access
Expand All @@ -130,12 +127,10 @@ def _add_m_to_s_address_channel(prog, mem, prefix: Literal["AW", "AR"]):
bt_reg.write_en = 1
do_x_transfer.done = bt_reg.out


# ARLEN must be between 0-255, make sure to subtract 1 from yxi
# size when assigning to ARLEN
# assert mem[size_key] < 256, "Memory size must be less than 256"


m_to_s_address_channel.control += [
par(
invoke(bt_reg, in_in=0),
Expand Down Expand Up @@ -227,7 +222,7 @@ def add_read_channel(prog, mem):
# Control
invoke_n_RLAST = invoke(n_RLAST, in_in=1)
# invoke_bt_reg = invoke(bt_reg, in_in=0)

# Could arguably get rid of this while loop for the dynamic verison, but this
# matches nicely with non dynamic version and conforms to spec,
# and will be easier to exten to variable length dynamic transfers in the future
Expand All @@ -245,11 +240,7 @@ def add_write_channel(prog, mem):
name = mem[name_key]
# Inputs/Outputs
write_channel = prog.component(f"m_write_channel_{name}")
channel_inputs = [
("ARESETn", 1),
("WREADY", 1),
("write_data", data_width)
]
channel_inputs = [("ARESETn", 1), ("WREADY", 1), ("write_data", data_width)]
# TODO(nathanielnrn): We currently assume WDATA is the same width as the
# memory. This limits throughput many AXI data busses are much wider
# i.e., 512 bits.
Expand Down Expand Up @@ -295,7 +286,7 @@ def add_write_channel(prog, mem):
write_channel.this()["WLAST"] = 1

# done after handshake
#TODO(nathanielnrn): Perhaps we can combine between handshake_occurred and bt_reg
# TODO(nathanielnrn): Perhaps we can combine between handshake_occurred and bt_reg
bt_reg.in_ = (wvalid.out & WREADY) @ 1
bt_reg.in_ = ~(wvalid.out & WREADY) @ 0
bt_reg.write_en = 1
Expand Down Expand Up @@ -351,6 +342,7 @@ def add_bresp_channel(prog, mem):
# Control
bresp_channel.control += [invoke(bt_reg, in_in=0), block_transfer]


def add_read_controller(prog, mem):
data_width = mem[width_key]
name = mem[name_key]
Expand All @@ -375,18 +367,21 @@ def add_read_controller(prog, mem):
(f"ARBURST", 2),
(f"ARPROT", 3),
(f"RREADY", 1),
#sent out to axi_dyn_mem
# sent out to axi_dyn_mem
(f"read_data", data_width),
]

add_comp_ports(read_controller, read_controller_inputs, read_controller_outputs)

#Cells
simple_ar_channel = read_controller.cell(f"ar_channel_{name}", prog.get_component(f"m_ar_channel_{name}"))
simple_read_channel = read_controller.cell(f"read_channel_{name}", prog.get_component(f"m_read_channel_{name}"))
# Cells
simple_ar_channel = read_controller.cell(
f"ar_channel_{name}", prog.get_component(f"m_ar_channel_{name}")
)
simple_read_channel = read_controller.cell(
f"read_channel_{name}", prog.get_component(f"m_read_channel_{name}")
)
# No groups necesarry


# Control
# Invokes

Expand Down Expand Up @@ -420,6 +415,7 @@ def add_read_controller(prog, mem):
simple_read_invoke,
]


def add_write_controller(prog, mem):
data_width = mem[width_key]
name = mem[name_key]
Expand Down Expand Up @@ -450,13 +446,18 @@ def add_write_controller(prog, mem):

add_comp_ports(write_controller, write_controller_inputs, write_controller_outputs)

#Cells
simple_aw_channel = write_controller.cell(f"aw_channel_{name}", prog.get_component(f"m_aw_channel_{name}"))
simple_write_channel = write_controller.cell(f"write_channel_{name}", prog.get_component(f"m_write_channel_{name}"))
simple_bresp_channel = write_controller.cell(f"bresp_channel_{name}", prog.get_component(f"m_bresp_channel_{name}"))
# Cells
simple_aw_channel = write_controller.cell(
f"aw_channel_{name}", prog.get_component(f"m_aw_channel_{name}")
)
simple_write_channel = write_controller.cell(
f"write_channel_{name}", prog.get_component(f"m_write_channel_{name}")
)
simple_bresp_channel = write_controller.cell(
f"bresp_channel_{name}", prog.get_component(f"m_bresp_channel_{name}")
)
# No groups necesarry


# Control
# Invokes
simple_aw_invoke = invoke(
Expand Down Expand Up @@ -493,6 +494,7 @@ def add_write_controller(prog, mem):
simple_bresp_invoke,
]


def add_axi_dyn_mem(prog, mem):
address_width = mem[address_width_key][0]
data_width = mem[width_key]
Expand All @@ -501,7 +503,7 @@ def add_axi_dyn_mem(prog, mem):
prog.import_("primitives/memories/dyn.futil")
axi_dyn_mem = prog.component(f"axi_dyn_mem_{name}")
# Inputs/Outputs
dyn_mem_inputs =[
dyn_mem_inputs = [
("addr0", address_width, [("write_together", 1), "data"]),
("content_en", 1, [("write_together", 1), ("go", 1)]),
("write_en", 1, [("write_together", 2)]),
Expand Down Expand Up @@ -541,9 +543,15 @@ def add_axi_dyn_mem(prog, mem):
add_comp_ports(axi_dyn_mem, dyn_mem_inputs, dyn_mem_outputs)

# Cells
address_translator = axi_dyn_mem.cell(f"address_translator_{name}", prog.get_component(f"address_translator_{name}"))
read_controller = axi_dyn_mem.cell(f"read_controller_{name}", prog.get_component(f"read_controller_{name}"))
write_controller = axi_dyn_mem.cell(f"write_controller_{name}", prog.get_component(f"write_controller_{name}"))
address_translator = axi_dyn_mem.cell(
f"address_translator_{name}", prog.get_component(f"address_translator_{name}")
)
read_controller = axi_dyn_mem.cell(
f"read_controller_{name}", prog.get_component(f"read_controller_{name}")
)
write_controller = axi_dyn_mem.cell(
f"write_controller_{name}", prog.get_component(f"write_controller_{name}")
)

# Wires
this_component = axi_dyn_mem.this()
Expand All @@ -552,51 +560,54 @@ def add_axi_dyn_mem(prog, mem):
address_translator.calyx_mem_addr = this_component["addr0"]
axi_dyn_mem.this()["read_data"] = read_controller.read_data

#Control
# Control
read_controller_invoke = invoke(
axi_dyn_mem.get_cell(f"read_controller_{name}"),
in_axi_address=address_translator.axi_address,
in_ARESETn=this_component[f"ARESETn"],
in_ARREADY=this_component[f"ARREADY"],
in_RVALID=this_component[f"RVALID"],
in_RLAST=this_component[f"RLAST"],
in_RDATA=this_component[f"RDATA"],
in_RRESP=this_component[f"RRESP"],
out_ARVALID=this_component[f"ARVALID"],
out_ARADDR=this_component[f"ARADDR"],
out_ARSIZE=this_component[f"ARSIZE"],
out_ARLEN=this_component[f"ARLEN"],
out_ARBURST=this_component[f"ARBURST"],
out_ARPROT=this_component[f"ARPROT"],
out_RREADY=this_component[f"RREADY"],
out_read_data=this_component[f"read_data"],
)
axi_dyn_mem.get_cell(f"read_controller_{name}"),
in_axi_address=address_translator.axi_address,
in_ARESETn=this_component[f"ARESETn"],
in_ARREADY=this_component[f"ARREADY"],
in_RVALID=this_component[f"RVALID"],
in_RLAST=this_component[f"RLAST"],
in_RDATA=this_component[f"RDATA"],
in_RRESP=this_component[f"RRESP"],
out_ARVALID=this_component[f"ARVALID"],
out_ARADDR=this_component[f"ARADDR"],
out_ARSIZE=this_component[f"ARSIZE"],
out_ARLEN=this_component[f"ARLEN"],
out_ARBURST=this_component[f"ARBURST"],
out_ARPROT=this_component[f"ARPROT"],
out_RREADY=this_component[f"RREADY"],
out_read_data=this_component[f"read_data"],
)

write_controller_invoke = invoke(
axi_dyn_mem.get_cell(f"write_controller_{name}"),
in_axi_address=address_translator.axi_address,
in_write_data=this_component["write_data"],
in_ARESETn=this_component["ARESETn"],
in_AWREADY=this_component["AWREADY"],
in_WREADY=this_component["WREADY"],
in_BVALID=this_component["BVALID"],
out_AWVALID=this_component["AWVALID"],
out_AWADDR=this_component["AWADDR"],
out_AWSIZE=this_component["AWSIZE"],
out_AWLEN=this_component["AWLEN"],
out_AWBURST=this_component["AWBURST"],
out_AWPROT=this_component[f"AWPROT"],
out_WVALID=this_component["WVALID"],
out_WLAST=this_component["WLAST"],
out_WDATA=this_component["WDATA"],
out_BREADY=this_component["BREADY"],
axi_dyn_mem.get_cell(f"write_controller_{name}"),
in_axi_address=address_translator.axi_address,
in_write_data=this_component["write_data"],
in_ARESETn=this_component["ARESETn"],
in_AWREADY=this_component["AWREADY"],
in_WREADY=this_component["WREADY"],
in_BVALID=this_component["BVALID"],
out_AWVALID=this_component["AWVALID"],
out_AWADDR=this_component["AWADDR"],
out_AWSIZE=this_component["AWSIZE"],
out_AWLEN=this_component["AWLEN"],
out_AWBURST=this_component["AWBURST"],
out_AWPROT=this_component[f"AWPROT"],
out_WVALID=this_component["WVALID"],
out_WLAST=this_component["WLAST"],
out_WDATA=this_component["WDATA"],
out_BREADY=this_component["BREADY"],
)

axi_dyn_mem.control += [
if_(axi_dyn_mem.this()["write_en"], write_controller_invoke, read_controller_invoke)
if_(
axi_dyn_mem.this()["write_en"],
write_controller_invoke,
read_controller_invoke,
)
]



# NOTE: Unlike the channel functions, this can expect multiple mems
def add_main_comp(prog, mems):
Expand Down Expand Up @@ -665,7 +676,9 @@ def add_main_comp(prog, mems):

# TODO: Don't think these need to be marked external, but we
# we need to raise them at some point form original calyx program
axi_mem = wrapper_comp.cell(f"axi_dyn_mem_{mem_name}", prog.get_component(f"axi_dyn_mem_{mem_name}"))
axi_mem = wrapper_comp.cell(
f"axi_dyn_mem_{mem_name}", prog.get_component(f"axi_dyn_mem_{mem_name}")
)

# Wires

Expand All @@ -679,7 +692,9 @@ def add_main_comp(prog, mems):
# Connect wrapper ports with axi_dyn_mem ports

# Read controller portion inputs
axi_mem["ARESETn"] = wrapper_comp.this()[f"{mem_name}_ARESETn"] #note that both styles work
axi_mem["ARESETn"] = wrapper_comp.this()[
f"{mem_name}_ARESETn"
] # note that both styles work
# wrapper_comp.this()[f"{mem_name}_ARESETn"] = axi_mem["ARESETn"] #note that both styles work
axi_mem.ARREADY = wrapper_comp.this()[f"{mem_name}_ARREADY"]
axi_mem.RVALID = wrapper_comp.this()[f"{mem_name}_RVALID"]
Expand Down Expand Up @@ -709,7 +724,6 @@ def add_main_comp(prog, mems):
wrapper_comp.this()[f"{mem_name}_WDATA"] = axi_mem.WDATA
wrapper_comp.this()[f"{mem_name}_BREADY"] = axi_mem.BREADY


# Creates `<mem_name> = internal_mem_<mem_name>` as refs in invocation of `main_compute`
ref_mem_kwargs[f"ref_{mem_name}"] = axi_mem

Expand Down Expand Up @@ -760,7 +774,7 @@ def build():
add_address_translator(prog, mem)
add_read_controller(prog, mem)
add_write_controller(prog, mem)
add_axi_dyn_mem(prog, mem) #TODO: need one for each mem
add_axi_dyn_mem(prog, mem) # TODO: need one for each mem
add_main_comp(prog, mems)
return prog.program

Expand All @@ -775,7 +789,9 @@ def check_mems_wellformed(mems):
mem[width_key]
).is_integer(), "Width must be a power of 2 to be correctly described by xSIZE"
assert mem[size_key] > 0, "Memory size must be greater than 0"
assert mem[type_key] == "Dynamic", "Only dynamic memories are currently supported for dynamic axi"
assert (
mem[type_key] == "Dynamic"
), "Only dynamic memories are currently supported for dynamic axi"


if __name__ == "__main__":
Expand All @@ -793,4 +809,4 @@ def check_mems_wellformed(mems):
yxifile = open(yxi_filename)
yxi = json.load(yxifile)
mems = yxi["memories"]
build().emit()
build().emit()

0 comments on commit 51d948a

Please sign in to comment.