Skip to content

Commit

Permalink
feat(gen_bd): control_s_axi over NoC
Browse files Browse the repository at this point in the history
  • Loading branch information
jake-ke committed Jun 19, 2024
1 parent 98ffa56 commit 9e5ce69
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 432 deletions.
52 changes: 13 additions & 39 deletions gen_vivado_bd.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
arm_hbm_tcl,
arm_tcl,
assign_arm_bd_address,
assign_mb_bd_address,
mb_tcl,
proc_tcl,
)

Expand Down Expand Up @@ -373,44 +371,11 @@ def connect_dut_arm_hbm_tcl(stream_attr: dict[str, dict[str, str]]) -> list[str]
return tcl


def gen_mb_bd(
bd_name: str,
top_mod: str,
mmap_ports: dict[str, dict[str, int]],
stream_attr: dict[str, dict[str, str]],
) -> list[str]:
"""Generates Vivado block design with Microblaze.
Merges the tcl commands from the helper functions and dumps to a file.
Args:
bd_name: name of the block design.
top_mod: name of the top-level module.
mmap_ports: list of top-level mmap ports connected to the memory.
stream_attr: dictionary of top-level stream ports. Keys are "src" name.
Values are "dest" name, "bandwidth", and "width".
Returns a list of tcl commands.
"""
tcl = []
tcl += proc_tcl()
tcl += mb_tcl(bd_name)
tcl += dut_tcl(
top_mod,
mmap_ports,
stream_attr,
False,
"",
)
tcl += connect_dut_mb_tcl(stream_attr)
tcl += assign_mb_bd_address()
return tcl


def gen_arm_bd_ddr(
bd_attr: dict[str, str],
mmap_ports: dict[str, dict[str, int]],
stream_attr: dict[str, dict[str, str]],
fpd: bool,
) -> list[str]:
"""Generates Vivado block design with ARM and LPDDR.
Expand All @@ -423,12 +388,15 @@ def gen_arm_bd_ddr(
mmap_ports: list of top-level mmap ports connected to the memory.
stream_attr: dictionary of top-level stream ports. Keys are "src" name.
Values are "dest" name, "bandwidth", and "width".
fpd: True if using CIPS M_AXI_FPD for kernel's control_s_axi,
else uses CIPS LPD_AXI_NOC_0 with NoC.
Returns a list of tcl commands.
"""
tcl = []
tcl += proc_tcl()
tcl += arm_tcl(bd_attr["bd_name"], bd_attr["frequency"], False)
tcl += arm_tcl(bd_attr["bd_name"], bd_attr["frequency"], False, fpd)
tcl += arm_ddr_tcl()
tcl += dut_tcl(
bd_attr["top_mod"],
Expand All @@ -446,6 +414,7 @@ def gen_arm_bd_hbm(
bd_attr: dict[str, str],
mmap_ports: dict[str, dict[str, int]],
stream_attr: dict[str, dict[str, str]],
fpd: bool,
) -> list[str]:
"""Generates Vivado block design with ARM and HBM.
Expand All @@ -459,13 +428,16 @@ def gen_arm_bd_hbm(
mmap_ports: list of top-level mmap ports connected to the memory.
stream_attr: dictionary of top-level stream ports. Keys are "src" name.
Values are "dest" name, "bandwidth", and "width".
fpd: True if using CIPS M_AXI_FPD for kernel's control_s_axi,
else uses CIPS LPD_AXI_NOC_0 with NoC.
Returns a list of tcl commands.
"""
tcl = []
tcl += proc_tcl()
tcl += arm_tcl(bd_attr["bd_name"], bd_attr["frequency"], True)
tcl += arm_hbm_tcl(mmap_ports)
tcl += arm_tcl(bd_attr["bd_name"], bd_attr["frequency"], True, fpd)
tcl += arm_hbm_tcl(mmap_ports, fpd)
tcl += dut_tcl(
bd_attr["top_mod"],
mmap_ports,
Expand All @@ -487,6 +459,7 @@ def gen_arm_bd_hbm(
NOC_STREAM_ATTR_JSON = "noc_streams_attr.json"
VIVADO_BD_TCL = "arm_bd.tcl"
BD_NAME = "top_arm"
USE_M_AXI_FPD = False
IMPL_FREQUENCY = "300.0"
HBM_INIT_FILE = "/home/jakeke/rapidstream-noc/test/serpens_hbm48_nasa4704.mem"
with open(f"{TEST_DIR}/{I_ADD_PIPELINE_JSON}", "r", encoding="utf-8") as file:
Expand All @@ -506,6 +479,7 @@ def gen_arm_bd_hbm(
},
test_mmap,
test_stream_attr,
USE_M_AXI_FPD,
)

with open(f"{TEST_DIR}/{VIVADO_BD_TCL}", "w", encoding="utf-8") as file:
Expand Down
1 change: 0 additions & 1 deletion ir_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ def parse_floorplan(ir: dict[str, Any], grouped_mod_name: str) -> dict[str, list
"inst/": parse_top_mod(ir)["submodules"],
}
if grouped_mod_ir := parse_mod(ir, grouped_mod_name):
print("No constraints from the grouped module.")
# grouped module
combined_mods[f"inst/{grouped_mod_name}_0/"] = grouped_mod_ir["submodules"]

Expand Down
6 changes: 4 additions & 2 deletions run_noc_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ class SelectorEnum(Enum):
FREQUENCY = 250.0
IMPL_FREQUENCY = "300.0"
HBM_INIT_FILE = "/home/jakeke/rapidstream-noc/test/serpens_hbm48_nasa4704.mem"
TB_FILE = "/home/jakeke/rapidstream-noc/test/serpens_tb_a48.sv"
TB_FILE = "/home/jakeke/rapidstream-noc/test/serpens_tb_a48_new.sv"
USE_M_AXI_FPD = False

# intermediate dumps
BD_NAME = "top_arm"
Expand Down Expand Up @@ -264,6 +265,7 @@ class SelectorEnum(Enum):
bd_attr=bd_attr,
mmap_ports=mmap_port_ir,
stream_attr=noc_stream_attr,
fpd=USE_M_AXI_FPD,
)
with open(f"{build_dir}/{VIVADO_BD_TCL}", "w", encoding="utf-8") as file:
file.write("\n".join(tcl))
Expand All @@ -290,7 +292,7 @@ class SelectorEnum(Enum):
print("Number of modules:", sum(len(v) for v in floorplan.values()))
print("Used slots: ", floorplan.keys())

tcl += export_constraint(floorplan, D)
tcl += export_constraint(floorplan, USE_M_AXI_FPD, D)

with open(f"{build_dir}/{CONSTRAINT_TCL}", "w", encoding="utf-8") as file:
file.write("\n".join(tcl))
Expand Down
166 changes: 77 additions & 89 deletions tcl_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,9 @@ def gen_vivado_prj_tcl(vivado_prj_params: dict[str, str]) -> list[str]:
return tcl


def export_constraint(floorplan: dict[str, list[str]], device: Device) -> list[str]:
def export_constraint(
floorplan: dict[str, list[str]], fpd: bool, device: Device
) -> list[str]:
"""Generates tcl constraints given the floorplan dictionary.
Returns a list of tcl commands.
Expand All @@ -207,6 +209,30 @@ def export_constraint(floorplan: dict[str, list[str]], device: Device) -> list[s
set_property IOSTANDARD LVDCI_15 [get_ports pl0_resetn_0]
"""
]

# constraint for control_s_axi's NSU
# find the control_s_axi slot region
def find_key_with_substring(floorplan: dict[str, list[str]], substring: str) -> str:
for slot, mods in floorplan.items():
if any(substring in e for e in mods):
return slot
raise NotImplementedError

if not fpd:
control_slot = find_key_with_substring(floorplan, "control_s_axi")
slot_nsu_nodes = concat_slot_nodes(control_slot, "nsu", " ", device)
tcl += [
f"""
set control_nsu_pblock [get_pblocks {control_slot}_nsu]
if {{[llength $control_nsu_pblock] == 0}} {{
create_pblock {control_slot}_nsu
resize_pblock {control_slot}_nsu -add {{{slot_nsu_nodes}}}
}}
add_cells_to_pblock {control_slot}_nsu \
[get_cells */noc_hbm_0/inst/M00_AXI_nsu/*top_INST/NOC_NSU512_INST]
"""
]

for slot in floorplan.keys():
slot1, slot2 = slot.split("_TO_")
assert slot1 == slot2
Expand Down Expand Up @@ -312,97 +338,59 @@ def get_count_and_slack(


if __name__ == "__main__":
import subprocess
import json

from ir_helper import parse_floorplan, parse_inter_slot, parse_top_mod
from vh1582_nocgraph import vh1582_nocgraph

TEST_DIR = "/home/jakeke/rapidstream-noc/test/tmp"
USE_M_AXI_FPD = False
I_ADD_PIPELINE_JSON = "add_pipeline.json"
SELECTED_STREAMS_JSON = "noc_streams.json"
NOC_PASS_WRAPPER_JSON = "noc_pass_wrapper.json"
CONSTRAINT_TCL = "constraint.tcl"
DUMP_NEG_PATHS_TCL = "dump_neg_paths.tcl"
TEST_DIR = "/home/jakeke/rapidstream-noc/test/build_a48_empty"
test_tcl = dump_neg_paths_summary(TEST_DIR)
with open(f"{TEST_DIR}/{DUMP_NEG_PATHS_TCL}", "w", encoding="utf-8") as file:
GROUPED_MOD_NAME = "axis_noc_if"

G = vh1582_nocgraph()
D = Device(
part_num="PART_NUM",
board_part="BOARD_PART",
slot_width=2,
slot_height=2,
noc_graph=G,
nmu_per_slot=[], # generated
nsu_per_slot=[], # generated
cr_mapping=[
["CLOCKREGION_X0Y1:CLOCKREGION_X4Y4", "CLOCKREGION_X0Y5:CLOCKREGION_X4Y7"],
["CLOCKREGION_X5Y1:CLOCKREGION_X9Y4", "CLOCKREGION_X5Y5:CLOCKREGION_X9Y7"],
],
)

with open(f"{TEST_DIR}/{I_ADD_PIPELINE_JSON}", "r", encoding="utf-8") as file:
test_design = json.load(file)
with open(f"{TEST_DIR}/{NOC_PASS_WRAPPER_JSON}", "r", encoding="utf-8") as file:
noc_pass_wrapper_ir = json.load(file)
with open(f"{TEST_DIR}/{SELECTED_STREAMS_JSON}", "r", encoding="utf-8") as file:
test_noc_streams = json.load(file)[GROUPED_MOD_NAME]

test_streams_slots, _ = parse_inter_slot(parse_top_mod(test_design))
test_floorplan = parse_floorplan(noc_pass_wrapper_ir, GROUPED_MOD_NAME)

test_tcl = export_noc_constraint(test_streams_slots, test_noc_streams, D)
test_tcl += export_constraint(test_floorplan, USE_M_AXI_FPD, D)
with open(f"{TEST_DIR}/{CONSTRAINT_TCL}", "w", encoding="utf-8") as file:
file.write("\n".join(test_tcl))

zsh_cmds = f"""
source ~/.zshrc && amd
vivado -mode batch -source {TEST_DIR}/{DUMP_NEG_PATHS_TCL}
"""
print(zsh_cmds)
subprocess.run(["zsh", "-c", zsh_cmds], check=True)

inter_slot_fifos = [
"PE_inst_Serpens_11_hs_if_din",
"PE_inst_Serpens_26_hs_if_din",
"PE_inst_Serpens_33_hs_if_din",
"Yvec_inst_Serpens_2_hs_if_din",
"Yvec_inst_Serpens_8_hs_if_din",
"fifo_A_Serpens_0_hs_if_din",
"fifo_A_Serpens_10_hs_if_din",
"fifo_A_Serpens_1_hs_if_din",
"fifo_A_Serpens_2_hs_if_din",
"fifo_A_Serpens_33_hs_if_din",
"fifo_A_Serpens_34_hs_if_din",
"fifo_A_Serpens_35_hs_if_din",
"fifo_A_Serpens_36_hs_if_din",
"fifo_A_Serpens_37_hs_if_din",
"fifo_A_Serpens_38_hs_if_din",
"fifo_A_Serpens_39_hs_if_din",
"fifo_A_Serpens_3_hs_if_din",
"fifo_A_Serpens_40_hs_if_din",
"fifo_A_Serpens_41_hs_if_din",
"fifo_A_Serpens_42_hs_if_din",
"fifo_A_Serpens_43_hs_if_din",
"fifo_A_Serpens_44_hs_if_din",
"fifo_A_Serpens_45_hs_if_din",
"fifo_A_Serpens_46_hs_if_din",
"fifo_A_Serpens_47_hs_if_din",
"fifo_A_Serpens_4_hs_if_din",
"fifo_A_Serpens_5_hs_if_din",
"fifo_A_Serpens_6_hs_if_din",
"fifo_A_Serpens_7_hs_if_din",
"fifo_A_Serpens_8_hs_if_din",
"fifo_A_Serpens_9_hs_if_din",
"fifo_X_pe_Serpens_11_hs_if_din",
"fifo_X_pe_Serpens_26_hs_if_din",
"fifo_X_pe_Serpens_33_hs_if_din",
"fifo_Y_pe_Serpens_11_hs_if_din",
"fifo_Y_pe_Serpens_12_hs_if_din",
"fifo_Y_pe_Serpens_13_hs_if_din",
"fifo_Y_pe_Serpens_14_hs_if_din",
"fifo_Y_pe_Serpens_15_hs_if_din",
"fifo_Y_pe_Serpens_16_hs_if_din",
"fifo_Y_pe_Serpens_17_hs_if_din",
"fifo_Y_pe_Serpens_24_hs_if_din",
"fifo_Y_pe_Serpens_25_hs_if_din",
"fifo_Y_pe_Serpens_2_hs_if_din",
"fifo_Y_pe_Serpens_33_hs_if_din",
"fifo_Y_pe_Serpens_34_hs_if_din",
"fifo_Y_pe_Serpens_35_hs_if_din",
"fifo_Y_pe_Serpens_8_hs_if_din",
"fifo_Y_pe_abd_Serpens_3_hs_if_din",
"fifo_Y_pe_abd_Serpens_6_hs_if_din",
"fifo_Y_pe_abd_Serpens_7_hs_if_din",
"fifo_aXvec_Serpens_2_hs_if_din",
"fifo_aXvec_Serpens_8_hs_if_din",
]
# test_tcl = dump_neg_paths_summary(TEST_DIR)
# with open(f"{TEST_DIR}/{DUMP_NEG_PATHS_TCL}", "w", encoding="utf-8") as file:
# file.write("\n".join(test_tcl))

selected = [
"PE_inst_Serpens_11_hs_if_din",
"Yvec_inst_Serpens_8_hs_if_din",
"fifo_A_Serpens_0_hs_if_din",
"fifo_A_Serpens_2_hs_if_din",
"fifo_A_Serpens_39_hs_if_din",
"fifo_A_Serpens_3_hs_if_din",
"fifo_A_Serpens_43_hs_if_din",
"fifo_A_Serpens_47_hs_if_din",
"fifo_A_Serpens_7_hs_if_din",
"fifo_X_pe_Serpens_11_hs_if_din",
"fifo_X_pe_Serpens_26_hs_if_din",
"fifo_X_pe_Serpens_33_hs_if_din",
"fifo_Y_pe_Serpens_2_hs_if_din",
"fifo_Y_pe_Serpens_33_hs_if_din",
"fifo_Y_pe_Serpens_34_hs_if_din",
"fifo_Y_pe_Serpens_35_hs_if_din",
"fifo_Y_pe_abd_Serpens_6_hs_if_din",
"fifo_Y_pe_abd_Serpens_7_hs_if_din",
"fifo_aXvec_Serpens_8_hs_if_din",
]
# zsh_cmds = f"""
# source ~/.zshrc && amd
# vivado -mode batch -source {TEST_DIR}/{DUMP_NEG_PATHS_TCL}
# """
# print(zsh_cmds)
# subprocess.run(["zsh", "-c", zsh_cmds], check=True)

parse_neg_paths(TEST_DIR, inter_slot_fifos, selected)
# parse_neg_paths(TEST_DIR, inter_slot_fifos, selected)
Loading

0 comments on commit 9e5ce69

Please sign in to comment.