Skip to content

Commit 5fe9a2e

Browse files
authored
Merge 1257a98 into ee933b1
2 parents ee933b1 + 1257a98 commit 5fe9a2e

16 files changed

Lines changed: 152 additions & 305 deletions

File tree

‎iron/applications/llama_3.2_1b/llama_npu.py‎

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
sys.path.insert(0, str(repo_root))
2525

2626
from iron.common.context import AIEContext
27-
from iron.common.utils import XRTSubBuffer
2827
from iron.common.sequence import OperatorSequence
2928
from iron.operators import (
3029
RMSNorm,
@@ -672,12 +671,10 @@ def __init__(self, prompt_len, emb_dim, hidden_dim, n_heads, n_kv_groups, head_d
672671
(n_heads * prompt_len, head_dim), dtype=ml_dtypes.bfloat16
673672
)
674673
self.attn_scores_queries_per_head = [
675-
XRTSubBuffer.from_parent(
676-
self.attn_scores_queries_all,
674+
self.attn_scores_queries_all.subview(
675+
h * prompt_len * head_dim * np.dtype(ml_dtypes.bfloat16).itemsize,
677676
(prompt_len, head_dim),
678-
offset_elements=h * prompt_len * head_dim,
679-
length_elements=prompt_len * head_dim,
680-
dtype=ml_dtypes.bfloat16,
677+
ml_dtypes.bfloat16,
681678
)
682679
for h in range(n_heads)
683680
]
@@ -686,12 +683,10 @@ def __init__(self, prompt_len, emb_dim, hidden_dim, n_heads, n_kv_groups, head_d
686683
(n_kv_groups * head_dim, prompt_len), dtype=ml_dtypes.bfloat16
687684
)
688685
self.attn_scores_keys_per_kv_group = [
689-
XRTSubBuffer.from_parent(
690-
self.attn_scores_keys_all,
686+
self.attn_scores_keys_all.subview(
687+
g * head_dim * prompt_len * np.dtype(ml_dtypes.bfloat16).itemsize,
691688
(head_dim, prompt_len),
692-
offset_elements=g * head_dim * prompt_len,
693-
length_elements=head_dim * prompt_len,
694-
dtype=ml_dtypes.bfloat16,
689+
ml_dtypes.bfloat16,
695690
)
696691
for g in range(n_kv_groups)
697692
]
@@ -700,12 +695,10 @@ def __init__(self, prompt_len, emb_dim, hidden_dim, n_heads, n_kv_groups, head_d
700695
(n_heads * prompt_len, prompt_len), dtype=ml_dtypes.bfloat16
701696
)
702697
self.attn_scores_per_head = [
703-
XRTSubBuffer.from_parent(
704-
self.attn_scores,
698+
self.attn_scores.subview(
699+
h * prompt_len * prompt_len * np.dtype(ml_dtypes.bfloat16).itemsize,
705700
(prompt_len, prompt_len),
706-
offset_elements=h * prompt_len * prompt_len,
707-
length_elements=prompt_len * prompt_len,
708-
dtype=ml_dtypes.bfloat16,
701+
ml_dtypes.bfloat16,
709702
)
710703
for h in range(n_heads)
711704
]
@@ -840,15 +833,13 @@ def __init__(self, config, prompt_len, aie_ops):
840833
config.padded_vocab_size // config.vocab_partitions
841834
)
842835
self.prefill.logits_parts = [
843-
XRTSubBuffer.from_parent(
844-
self.prefill.logits,
836+
self.prefill.logits.subview(
837+
i * logits_part_len * np.dtype(ml_dtypes.bfloat16).itemsize,
845838
(
846839
prompt_len,
847840
config.padded_vocab_size // config.vocab_partitions,
848841
),
849-
offset_elements=i * logits_part_len,
850-
length_elements=logits_part_len,
851-
dtype=ml_dtypes.bfloat16,
842+
ml_dtypes.bfloat16,
852843
)
853844
for i in range(config.vocab_partitions)
854845
]

‎iron/common/base.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,23 +156,20 @@ def get_kernel_artifacts(self) -> list[CompilationArtifact]:
156156
pass
157157

158158
def get_artifacts(
159-
self, prefix: str = "", dynamic_obj_fifos: bool = False
159+
self, prefix: str = ""
160160
) -> tuple[XclbinArtifact, InstsBinArtifact]:
161161
operator_name = prefix + self.name
162162
mlir_artifact = self.get_mlir_artifact()
163163
kernel_deps = self.get_kernel_artifacts()
164-
extra_flags = ["--dynamic-objFifos"] if dynamic_obj_fifos else []
165164
xclbin_artifact = XclbinArtifact(
166165
f"{operator_name}.xclbin",
167166
mlir_input=mlir_artifact,
168167
dependencies=[mlir_artifact] + kernel_deps,
169-
extra_flags=extra_flags,
170168
)
171169
insts_artifact = InstsBinArtifact(
172170
f"{operator_name}.bin",
173171
mlir_input=mlir_artifact,
174172
dependencies=[mlir_artifact],
175-
extra_flags=extra_flags,
176173
)
177174
return xclbin_artifact, insts_artifact
178175

‎iron/common/compilation/__init__.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from .base import (
55
DesignGenerator,
6+
_aiecc_work_dir,
67
plan,
78
execute,
89
compile,

‎iron/common/compilation/base.py‎

Lines changed: 112 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import sys
5050

5151
from iron.common.device_utils import get_kernel_dir
52+
from aie.utils.compile.utils import compile_cxx_core_function, compile_mlir_module
5253

5354
# Global Functions
5455
# ##########################################################################
@@ -487,20 +488,42 @@ def generate_mlir(output_artifact, generator):
487488
f.write(mlir_code)
488489

489490

491+
def _aiecc_work_dir(mlir_filename: str) -> Path:
492+
"""Directory aiecc writes its own 'aie.mlir' copy and '.prj' project directory
493+
into for the given MLIR source artifact's filename.
494+
495+
compile_mlir_module() always names its copy of the source "aie.mlir" inside
496+
the work_dir it's given, rather than reusing the artifact's own filename, so
497+
each MLIR source needs its own work_dir to avoid colliding with every other
498+
artifact's aiecc output in the flat build directory. Callers that need to
499+
find aiecc's project directory afterward (e.g. for a runtime-parameters
500+
scratchpad) should derive it from this same function rather than
501+
re-deriving the convention.
502+
"""
503+
p = Path(mlir_filename)
504+
return p.parent / (p.name + ".d")
505+
506+
507+
def _link_build_outputs_into(work_dir: Path, build_dir: Path) -> None:
508+
"""Symlink every file already built in build_dir into work_dir.
509+
510+
aiecc resolves an MLIR module's relative kernel-object references (e.g.
511+
``link_with = "axpy.o"``, produced by KernelCompilationRule /
512+
ArchiveCompilationRule into the flat build_dir) against work_dir, since
513+
that's where compile_mlir_module() writes its own copy of the MLIR
514+
source. Symlinking makes those lookups succeed without copying kernel
515+
objects into every artifact's own work_dir.
516+
"""
517+
for entry in build_dir.iterdir():
518+
if entry.is_dir():
519+
continue
520+
link = work_dir / entry.name
521+
if not link.exists():
522+
link.symlink_to(entry.resolve())
523+
524+
490525
class AieccCompilationRule(CompilationRule):
491-
def __init__(
492-
self, build_dir, peano_dir, mlir_aie_dir, use_chess=False, *args, **kwargs
493-
):
494-
self.build_dir = build_dir
495-
# AIECC_PATH lets a build point at a locally-built aiecc (e.g. a compiler under
496-
# development) without replacing the installed one. Default = the installed aiecc.
497-
_aiecc_override = os.environ.get("AIECC_PATH")
498-
self.aiecc_path = (
499-
Path(_aiecc_override)
500-
if _aiecc_override
501-
else Path(mlir_aie_dir) / "bin" / "aiecc"
502-
)
503-
self.peano_dir = peano_dir
526+
def __init__(self, use_chess=False, *args, **kwargs):
504527
self.use_chess = use_chess
505528
super().__init__(*args, **kwargs)
506529

@@ -514,41 +537,32 @@ def compile(self, graph):
514537
commands = []
515538

516539
for artifact in worklist:
517-
compile_cmd = [
518-
str(self.aiecc_path),
519-
"-v",
540+
mlir_source = artifact.mlir_input
541+
work_dir = _aiecc_work_dir(mlir_source.filename)
542+
options = [
520543
f"-j{os.environ.get('AIECC_JOBS', '1')}",
521-
]
522-
if self.use_chess:
523-
compile_cmd += [
524-
"--xchesscc",
525-
"--xbridge",
526-
]
527-
else:
528-
compile_cmd += [
529-
"--no-xchesscc",
530-
"--no-xbridge",
531-
"--peano",
532-
str(self.peano_dir),
533-
]
534-
compile_cmd += [
535544
"--expand-load-pdis",
536-
"--get-full-elf",
537-
"--full-elf-name",
538-
os.path.abspath(artifact.filename),
539-
# Unrequested, params.txt is never written and
540-
# SequenceFullELFCallable.params silently returns None. It has
541-
# no name flag of its own, so --output-dir is what puts it in
542-
# the project directory that property reads.
543545
"--get-scratchpad-parameters",
544-
"--output-dir",
545-
os.path.abspath(artifact.mlir_input.filename) + ".prj",
546-
*artifact.extra_flags,
547-
os.path.abspath(artifact.mlir_input.filename),
548-
]
549-
commands.append(
550-
ShellCompilationCommand(compile_cmd, cwd=str(self.build_dir))
551-
)
546+
] + artifact.extra_flags
547+
548+
def _compile(
549+
artifact=artifact,
550+
mlir_source=mlir_source,
551+
work_dir=work_dir,
552+
options=options,
553+
):
554+
work_dir.mkdir(parents=True, exist_ok=True)
555+
_link_build_outputs_into(work_dir, Path(mlir_source.filename).parent)
556+
compile_mlir_module(
557+
Path(mlir_source.filename).read_text(),
558+
full_elf_path=os.path.abspath(artifact.filename),
559+
work_dir=str(work_dir),
560+
options=options,
561+
use_chess=self.use_chess,
562+
verbose=True,
563+
)
564+
565+
commands.append(PythonCallbackCompilationCommand(_compile))
552566
artifact.available = True
553567

554568
return commands
@@ -575,57 +589,53 @@ def compile(self, graph):
575589
commands = []
576590
# Now we know for each mlir source if we need to generate an xclbin, an insts.bin or both for it
577591
for mlir_source in mlir_sources:
578-
compile_cmd = [
579-
str(self.aiecc_path),
580-
"-v",
581-
f"-j{os.environ.get('AIECC_JOBS', '1')}",
582-
]
583-
if self.use_chess:
584-
compile_cmd += [
585-
"--xchesscc",
586-
"--xbridge",
587-
]
588-
else:
589-
compile_cmd += [
590-
"--no-xchesscc",
591-
"--no-xbridge",
592-
"--peano",
593-
str(self.peano_dir),
594-
]
595-
compile_cmd += [
596-
"--dynamic-objFifos",
597-
]
592+
options = [f"-j{os.environ.get('AIECC_JOBS', '1')}"]
593+
xclbin_path = None
594+
insts_path = None
598595
do_compile_xclbin = mlir_source in mlir_sources_to_xclbins
599596
do_compile_insts_bin = mlir_source in mlir_sources_to_insts
600597
if do_compile_xclbin:
601598
first_xclbin = mlir_sources_to_xclbins[mlir_source][
602599
0
603600
] # TODO: this does not handle the case of multiple xclbins with different kernel names or flags from the same MLIR
604-
compile_cmd += first_xclbin.extra_flags + [
605-
"--get-xclbin",
606-
"--xclbin-name=" + os.path.abspath(first_xclbin.filename),
607-
"--xclbin-kernel-name=" + first_xclbin.kernel_name,
601+
xclbin_path = os.path.abspath(first_xclbin.filename)
602+
options += first_xclbin.extra_flags + [
603+
f"--xclbin-kernel-name={first_xclbin.kernel_name}",
608604
]
609605
if first_xclbin.xclbin_input is not None:
610-
compile_cmd += [
606+
options.append(
611607
"--xclbin-input="
612608
+ os.path.abspath(first_xclbin.xclbin_input.filename)
613-
]
609+
)
614610
if do_compile_insts_bin:
615611
first_insts_bin = mlir_sources_to_insts[mlir_source][
616612
0
617613
] # TODO: this does not handle the case of multiple insts.bins with different flags from the same MLIR
618-
# Outputs are selected by --get-<name>; asking only for the insts is what
619-
# "--no-compile" used to mean, so there is nothing to opt out of here.
620-
compile_cmd += first_insts_bin.extra_flags + [
621-
"--get-npu-insts",
622-
"--npu-insts-name=" + os.path.abspath(first_insts_bin.filename),
623-
]
624-
compile_cmd += [os.path.abspath(mlir_source.filename)]
614+
insts_path = os.path.abspath(first_insts_bin.filename)
615+
options += first_insts_bin.extra_flags
625616

626-
commands.append(
627-
ShellCompilationCommand(compile_cmd, cwd=str(self.build_dir))
628-
)
617+
work_dir = _aiecc_work_dir(mlir_source.filename)
618+
619+
def _compile(
620+
mlir_source=mlir_source,
621+
xclbin_path=xclbin_path,
622+
insts_path=insts_path,
623+
options=options,
624+
work_dir=work_dir,
625+
):
626+
work_dir.mkdir(parents=True, exist_ok=True)
627+
_link_build_outputs_into(work_dir, Path(mlir_source.filename).parent)
628+
compile_mlir_module(
629+
Path(mlir_source.filename).read_text(),
630+
insts_path=insts_path,
631+
xclbin_path=xclbin_path,
632+
work_dir=str(work_dir),
633+
options=options,
634+
use_chess=self.use_chess,
635+
verbose=True,
636+
)
637+
638+
commands.append(PythonCallbackCompilationCommand(_compile))
629639

630640
# There may be multiple targets that require an xclbin/insts.bin from the same MLIR with different names; copy them
631641
for sources_to in [mlir_sources_to_xclbins, mlir_sources_to_insts]:
@@ -718,7 +728,6 @@ def matches(self, artifacts):
718728
return any(artifacts.get_worklist(KernelObjectArtifact))
719729

720730
def compile(self, artifacts):
721-
include_path = Path(self.mlir_aie_dir) / "include"
722731
worklist = artifacts.get_worklist(KernelObjectArtifact)
723732
commands = []
724733

@@ -738,41 +747,28 @@ def compile(self, artifacts):
738747
"Expected KernelObject dependency to be a C source file"
739748
)
740749

741-
if self.use_chess:
742-
wrapper_path = Path(self.mlir_aie_dir) / "bin" / "xchesscc_wrapper"
743-
cmd = (
744-
[
745-
str(wrapper_path),
746-
kernel_dir, # e.g. "aie2" or "aie2p"
747-
f"-I{str(include_path)}",
748-
f"-I{str(runtime_lib_include_path)}",
749-
]
750-
+ artifact.extra_flags
751-
+ ["-c", source_file.filename, "-o", artifact.filename]
752-
)
753-
else:
754-
clang_path = Path(self.peano_dir) / "bin" / "clang++"
755-
target = f"{kernel_dir}-none-unknown-elf"
756-
cmd = (
757-
[
758-
str(clang_path),
759-
"-O2",
760-
"-std=c++20",
761-
f"--target={target}",
762-
"-D__AIE_API_AIE_ADF_HPP__",
763-
"-Wno-parentheses",
764-
"-Wno-attributes",
765-
"-Wno-macro-redefined",
766-
"-Wno-empty-body",
767-
"-Wno-missing-template-arg-list-after-template-kw",
768-
f"-I{str(include_path)}",
769-
f"-I{str(runtime_lib_include_path)}",
770-
]
771-
+ artifact.extra_flags
772-
+ ["-c", source_file.filename, "-o", artifact.filename]
773-
)
750+
# -Wno-missing-template-arg-list-after-template-kw only applies to
751+
# the Peano (clang) path: xchesscc's own front end doesn't
752+
# recognize it.
753+
compile_args = list(artifact.extra_flags)
754+
if not self.use_chess:
755+
compile_args = [
756+
"-Wno-missing-template-arg-list-after-template-kw"
757+
] + compile_args
774758

775-
commands.append(ShellCompilationCommand(cmd))
759+
commands.append(
760+
PythonCallbackCompilationCommand(
761+
partial(
762+
compile_cxx_core_function,
763+
source_path=source_file.filename,
764+
target_arch=kernel_dir,
765+
output_path=artifact.filename,
766+
include_dirs=[str(runtime_lib_include_path)],
767+
compile_args=compile_args,
768+
use_chess=self.use_chess,
769+
)
770+
)
771+
)
776772
if artifact.rename_symbols:
777773
commands.extend(self._rename_symbols(artifact))
778774
if artifact.prefix_symbols:

0 commit comments

Comments
 (0)