Skip to content

Commit 4a21275

Browse files
committed
merge of axi generator renaming
1 parent 0a02e0b commit 4a21275

File tree

5 files changed

+67
-49
lines changed

5 files changed

+67
-49
lines changed

fud2/scripts/axi.rhai

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn wrapper_setup(e) {
2727
let generator_path = if dynamic == "true" {
2828
"$calyx-base/yxi/axi-calyx/dynamic_axi_generator.py"
2929
} else {
30-
"$calyx-base/yxi/axi-calyx/axi-generator.py"
30+
"$calyx-base/yxi/axi-calyx/axi_generator.py"
3131
};
3232
e.config_var_or("axi-generator", "axi.generator", generator_path);
3333
e.config_var_or("python", "python", "python3");
@@ -37,6 +37,8 @@ fn wrapper_setup(e) {
3737
// Define a simple `combine` rule that just concatenates any numer of files.
3838
e.rule("combine", "cat $in > $out");
3939

40+
// Removes imports and `external` primitive blocks added by passes by removing
41+
// everything up until the first line containing `component main`
4042
e.rule(
4143
"remove-imports",
4244
"sed '/^import/d' $in > $out",

fud2/tests/snapshots/tests__test@plan_axi-wrapped.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ yxi = $calyx-base/target/debug/yxi
2222
rule yxi
2323
command = $yxi -l $calyx-base $in > $out
2424

25-
axi-generator = $calyx-base/yxi/axi-calyx/axi-generator.py
25+
axi-generator = $calyx-base/yxi/axi-calyx/axi_generator.py
2626
python = python3
2727
rule gen-axi
2828
command = $python $axi-generator $in > $out

runt.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ cmd = """
6868

6969
[[tests]]
7070
name = "fud2 yxi invocation"
71-
paths = ["yxi/tests/ref-mems-vec-add.futil"]
71+
paths = ["yxi/tests/yxi-tool/ref-mems-vec-add.futil"]
7272
cmd = """
7373
fud2 {} --from calyx --to yxi
7474
"""
@@ -604,14 +604,14 @@ fud e {} -s verilog.cycle_limit 500 \
604604
name = "calyx-py read-write-compute AXI wrapper generation"
605605
paths = ["yxi/tests/axi/read-compute-write/*.yxi"]
606606
cmd = """
607-
python3 yxi/axi-calyx/axi-generator.py {}
607+
python3 yxi/axi-calyx/axi_generator.py {}
608608
"""
609609

610610
[[tests]]
611611
name = "calyx-py dynamic AXI wrapper generation"
612612
paths = ["yxi/tests/axi/dynamic/*.yxi"]
613613
cmd = """
614-
python3 yxi/axi-calyx/dynamic-axi-generator.py {}
614+
python3 yxi/axi-calyx/dynamic_axi_generator.py {}
615615
"""
616616

617617
#Ignore fud2 stderr for now due to ninja nondeterminism
@@ -681,4 +681,4 @@ make --silent -B TEST_PATH={} COCOTB_LOG_LEVEL=CRITICAL |\
681681
make clean && \
682682
rm -f results.xml
683683
684-
"""
684+
"""

yxi/axi-calyx/axi-generator.py renamed to yxi/axi-calyx/axi_generator.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# The *original* axi generator which implement a read-compute-write sequence
2+
# to get data in and out of the computational kernel.
3+
# A `dynamic_axi_generator` also exists
4+
15
from calyx.builder import (
26
Builder,
37
add_comp_ports,

yxi/axi-calyx/dynamic_axi_generator.py

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
from calyx.builder import (
2-
Builder,
3-
add_comp_ports,
4-
invoke,
5-
par,
6-
while_,
7-
if_
8-
)
1+
# Implements an AXI controller which dynamically reads and writes data
2+
# in and out of the computational kernel as needed. Compare with the
3+
# read-compute-write implementation in the original `axi_generator`.
4+
5+
from calyx.builder import Builder, add_comp_ports, invoke, par, while_, if_
96
from axi_controller_generator import add_control_subordinate
107
from typing import Literal
118
from math import log2, ceil
@@ -21,11 +18,12 @@
2118
width_key = "data_width"
2219
size_key = "total_size"
2320
name_key = "name"
24-
#This returns an array based on dimensions of memory
21+
# This returns an array based on dimensions of memory
2522
address_width_key = "idx_sizes"
2623
type_key = "memory_type"
2724

28-
#TODO (nathanielnrn): Should we make these comb groups?
25+
26+
# TODO (nathanielnrn): Should we make these comb groups?
2927
def add_address_translator(prog, mem):
3028
address_width = mem[address_width_key][0]
3129
data_width = mem[width_key]
@@ -36,13 +34,14 @@ def add_address_translator(prog, mem):
3634
translator_output = [("axi_address", 64)]
3735
add_comp_ports(address_translator, translator_inputs, translator_output)
3836

39-
#Cells
40-
#XRT expects 64 bit address.
41-
address_mult = address_translator.const_mult(64, width_in_bytes(data_width), f"mul_{name}")
37+
# Cells
38+
# XRT expects 64 bit address.
39+
address_mult = address_translator.const_mult(
40+
64, width_in_bytes(data_width), f"mul_{name}"
41+
)
4242
pad_input_addr = address_translator.pad(address_width, 64, f"pad_input_addr")
4343

44-
45-
#Assignment
44+
# Assignment
4645
with address_translator.continuous:
4746
pad_input_addr.in_ = address_translator.this()["calyx_mem_addr"]
4847
address_mult.in_ = pad_input_addr.out
@@ -113,12 +112,14 @@ def _add_m_to_s_address_channel(prog, mem, prefix: Literal["AW", "AR"]):
113112
xhandshake_occurred.write_en = (~xhandshake_occurred.out) @ 1
114113

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

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

138-
139138
m_to_s_address_channel.control += [
140139
par(
141140
invoke(bt_reg, in_in=0),
@@ -227,7 +226,7 @@ def add_read_channel(prog, mem):
227226
# Control
228227
invoke_n_RLAST = invoke(n_RLAST, in_in=1)
229228
# invoke_bt_reg = invoke(bt_reg, in_in=0)
230-
229+
231230
# Could arguably get rid of this while loop for the dynamic verison, but this
232231
# matches nicely with non dynamic version and conforms to spec,
233232
# and will be easier to extend to variable length dynamic transfers in the future
@@ -245,11 +244,7 @@ def add_write_channel(prog, mem):
245244
name = mem[name_key]
246245
# Inputs/Outputs
247246
write_channel = prog.component(f"m_write_channel_{name}")
248-
channel_inputs = [
249-
("ARESETn", 1),
250-
("WREADY", 1),
251-
("write_data", data_width)
252-
]
247+
channel_inputs = [("ARESETn", 1), ("WREADY", 1), ("write_data", data_width)]
253248
# TODO(nathanielnrn): We currently assume WDATA is the same width as the
254249
# memory. This limits throughput many AXI data busses are much wider
255250
# i.e., 512 bits.
@@ -294,7 +289,7 @@ def add_write_channel(prog, mem):
294289
write_channel.this()["WLAST"] = 1
295290

296291
# done after handshake
297-
#TODO(nathanielnrn): Perhaps we can combine between handshake_occurred and bt_reg
292+
# TODO(nathanielnrn): Perhaps we can combine between handshake_occurred and bt_reg
298293
bt_reg.in_ = (wvalid.out & WREADY) @ 1
299294
bt_reg.in_ = ~(wvalid.out & WREADY) @ 0
300295
bt_reg.write_en = 1
@@ -350,6 +345,7 @@ def add_bresp_channel(prog, mem):
350345
# Control
351346
bresp_channel.control += [invoke(bt_reg, in_in=0), block_transfer]
352347

348+
353349
def add_read_controller(prog, mem):
354350
add_arread_channel(prog, mem)
355351
add_read_channel(prog, mem)
@@ -377,18 +373,21 @@ def add_read_controller(prog, mem):
377373
(f"ARBURST", 2),
378374
(f"ARPROT", 3),
379375
(f"RREADY", 1),
380-
#sent out to axi_dyn_mem
376+
# sent out to axi_dyn_mem
381377
(f"read_data", data_width),
382378
]
383379

384380
add_comp_ports(read_controller, read_controller_inputs, read_controller_outputs)
385381

386-
#Cells
387-
simple_ar_channel = read_controller.cell(f"ar_channel_{name}", prog.get_component(f"m_ar_channel_{name}"))
388-
simple_read_channel = read_controller.cell(f"read_channel_{name}", prog.get_component(f"m_read_channel_{name}"))
382+
# Cells
383+
simple_ar_channel = read_controller.cell(
384+
f"ar_channel_{name}", prog.get_component(f"m_ar_channel_{name}")
385+
)
386+
simple_read_channel = read_controller.cell(
387+
f"read_channel_{name}", prog.get_component(f"m_read_channel_{name}")
388+
)
389389
# No groups necesarry
390390

391-
392391
# Control
393392
# Invokes
394393

@@ -422,6 +421,7 @@ def add_read_controller(prog, mem):
422421
simple_read_invoke,
423422
]
424423

424+
425425
def add_write_controller(prog, mem):
426426
add_awwrite_channel(prog, mem)
427427
add_write_channel(prog, mem)
@@ -455,13 +455,18 @@ def add_write_controller(prog, mem):
455455

456456
add_comp_ports(write_controller, write_controller_inputs, write_controller_outputs)
457457

458-
#Cells
459-
simple_aw_channel = write_controller.cell(f"aw_channel_{name}", prog.get_component(f"m_aw_channel_{name}"))
460-
simple_write_channel = write_controller.cell(f"write_channel_{name}", prog.get_component(f"m_write_channel_{name}"))
461-
simple_bresp_channel = write_controller.cell(f"bresp_channel_{name}", prog.get_component(f"m_bresp_channel_{name}"))
458+
# Cells
459+
simple_aw_channel = write_controller.cell(
460+
f"aw_channel_{name}", prog.get_component(f"m_aw_channel_{name}")
461+
)
462+
simple_write_channel = write_controller.cell(
463+
f"write_channel_{name}", prog.get_component(f"m_write_channel_{name}")
464+
)
465+
simple_bresp_channel = write_controller.cell(
466+
f"bresp_channel_{name}", prog.get_component(f"m_bresp_channel_{name}")
467+
)
462468
# No groups necesarry
463469

464-
465470
# Control
466471
# Invokes
467472
simple_aw_invoke = invoke(
@@ -498,6 +503,7 @@ def add_write_controller(prog, mem):
498503
simple_bresp_invoke,
499504
]
500505

506+
501507
def add_axi_dyn_mem(prog, mem):
502508
address_width = mem[address_width_key][0]
503509
data_width = mem[width_key]
@@ -506,7 +512,7 @@ def add_axi_dyn_mem(prog, mem):
506512
prog.import_("primitives/memories/dyn.futil")
507513
axi_dyn_mem = prog.component(f"axi_dyn_mem_{name}")
508514
# Inputs/Outputs
509-
dyn_mem_inputs =[
515+
dyn_mem_inputs = [
510516
("addr0", address_width, [("write_together", 1), "data"]),
511517
("content_en", 1, [("write_together", 1), ("go", 1)]),
512518
("write_en", 1, [("write_together", 2)]),
@@ -606,13 +612,12 @@ def add_axi_dyn_mem(prog, mem):
606612
out_WDATA=this_component["WDATA"],
607613
out_BREADY=this_component["BREADY"],
608614
)
609-
615+
610616
axi_dyn_mem.control += [
611617
latch_write_en,
612618
if_(write_en_reg.out, write_controller_invoke, read_controller_invoke)
613619
]
614620

615-
616621

617622
# NOTE: Unlike the channel functions, this can expect multiple mems
618623
def add_wrapper_comp(prog, mems):
@@ -746,7 +751,10 @@ def add_wrapper_comp(prog, mems):
746751

747752
# TODO: Don't think these need to be marked external, but we
748753
# we need to raise them at some point form original calyx program
749-
axi_mem = wrapper_comp.cell(f"axi_dyn_mem_{mem_name}", prog.get_component(f"axi_dyn_mem_{mem_name}"))
754+
axi_mem = wrapper_comp.cell(
755+
f"axi_dyn_mem_{mem_name}", prog.get_component(f"axi_dyn_mem_{mem_name}")
756+
)
757+
750758
# Wires
751759

752760
with wrapper_comp.continuous:
@@ -759,7 +767,9 @@ def add_wrapper_comp(prog, mems):
759767
# Connect wrapper ports with axi_dyn_mem ports
760768

761769
# Read controller portion inputs
762-
axi_mem["ARESETn"] = wrapper_comp.this()[f"{mem_name}_ARESETn"] #note that both styles work
770+
axi_mem["ARESETn"] = wrapper_comp.this()[
771+
f"{mem_name}_ARESETn"
772+
] # note that both styles work
763773
# wrapper_comp.this()[f"{mem_name}_ARESETn"] = axi_mem["ARESETn"] #note that both styles work
764774
axi_mem.ARREADY = wrapper_comp.this()[f"{mem_name}_ARREADY"]
765775
axi_mem.RVALID = wrapper_comp.this()[f"{mem_name}_RVALID"]
@@ -876,7 +886,9 @@ def check_mems_wellformed(mems):
876886
mem[width_key]
877887
).is_integer(), "Width must be a power of 2 to be correctly described by xSIZE"
878888
assert mem[size_key] > 0, "Memory size must be greater than 0"
879-
assert mem[type_key] == "Dynamic", "Only dynamic memories are currently supported for dynamic axi"
889+
assert (
890+
mem[type_key] == "Dynamic"
891+
), "Only dynamic memories are currently supported for dynamic axi"
880892

881893

882894
if __name__ == "__main__":
@@ -894,4 +906,4 @@ def check_mems_wellformed(mems):
894906
yxifile = open(yxi_filename)
895907
yxi = json.load(yxifile)
896908
mems = yxi["memories"]
897-
build().emit()
909+
build().emit()

0 commit comments

Comments
 (0)