Skip to content

[PyRTG] Refactor targets/configs #8399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 47 additions & 22 deletions frontends/PyRTG/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,41 @@ include(AddMLIRPython)
add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=pyrtg.circt.")

declare_mlir_python_sources(PyRTGSources
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pyrtg"
SOURCES
pyrtg/__init__.py
pyrtg/arrays.py
pyrtg/bags.py
pyrtg/control_flow.py
pyrtg/core.py
pyrtg/index.py
pyrtg/integers.py
pyrtg/labels.py
pyrtg/rtg.py
pyrtg/sequences.py
pyrtg/sets.py
pyrtg/support.py
pyrtg/target.py
pyrtg/tests.py
pyrtg/resources.py
pyrtg/rtgtest.py
pyrtg/scf.py
pyrtg/tuples.py
rtgtool/rtgtool.py
__init__.py
base.py
contexts.py
resources.py
rtgtest.py
support.py
)

declare_mlir_python_sources(PyRTGSources.Core
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pyrtg"
ADD_TO_PARENT PyRTGSources
SOURCES
arrays.py
bags.py
configs.py
control_flow.py
core.py
index.py
integers.py
labels.py
memories.py
rtg.py
scf.py
sequences.py
sets.py
tests.py
tuples.py
)

declare_mlir_python_sources(PyRTGToolSources
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/rtgtool"
SOURCES
rtgtool.py
)

################################################################################
Expand Down Expand Up @@ -63,20 +77,31 @@ add_mlir_python_modules(PyRTG_CIRCTPythonModules
)

add_mlir_python_modules(PyRTG
ROOT_PREFIX "${PYRTG_PYTHON_PACKAGE_DIR}/"
INSTALL_PREFIX "python_packages/"
ROOT_PREFIX "${PYRTG_PYTHON_PACKAGE_DIR}/pyrtg"
INSTALL_PREFIX "python_packages/pyrtg"
DECLARED_SOURCES
PyRTGSources
COMMON_CAPI_LINK_LIBS
PyRTG_CIRCTPythonCAPI
)

add_mlir_python_modules(PyRTGTool
ROOT_PREFIX "${PYRTG_PYTHON_PACKAGE_DIR}/rtgtool"
INSTALL_PREFIX "python_packages/pyrtg/rtgtool"
DECLARED_SOURCES
PyRTGToolSources
)

install(TARGETS PyRTG_CIRCTPythonCAPI
DESTINATION python_packages/pyrtg/circt/_mlir_libs
RUNTIME_DEPENDENCIES
PRE_EXCLUDE_REGEXES ".*"
PRE_INCLUDE_REGEXES ".*zlib.*"
COMPONENT PyRTG
)

add_dependencies(PyRTGTool PyRTG)
add_dependencies(install-PyRTGTool install-PyRTG)

add_dependencies(PyRTG PyRTG_CIRCTPythonModules)
add_dependencies(install-PyRTG install-PyRTG_CIRCTPythonModules)
4 changes: 3 additions & 1 deletion frontends/PyRTG/src/pyrtg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
from .integers import Integer, Bool
from .bags import Bag
from .sequences import sequence, Sequence, RandomizedSequence
from .target import target, entry
from .configs import config, Param, Config
from .resources import IntegerRegister, Immediate
from .arrays import Array
from .contexts import CPUCore
from .control_flow import If, Else, EndIf, For, Foreach
from .tuples import Tuple
from .memories import Memory, MemoryBlock
5 changes: 3 additions & 2 deletions frontends/PyRTG/src/pyrtg/arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from __future__ import annotations

from .circt import ir
from .base import ir
from .rtg import rtg
from .index import index
from .core import Value
Expand Down Expand Up @@ -71,7 +71,8 @@ def _get_ssa_value(self) -> ir.Value:
def get_type(self) -> ir.Type:
return self._value.type

def type(element_type: ir.Type) -> ir.Type:
@staticmethod
def ty(element_type: ir.Type) -> ir.Type:
"""
Returns the array type for the given element type.
"""
Expand Down
5 changes: 3 additions & 2 deletions frontends/PyRTG/src/pyrtg/bags.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from __future__ import annotations

from .circt import ir, support
from .base import ir, support
from .rtg import rtg
from .core import Value
from .index import index
Expand Down Expand Up @@ -143,7 +143,8 @@ def _get_ssa_value(self) -> ir.Value:
def get_type(self) -> ir.Type:
return self._value.type

def type(*args: ir.Type) -> ir.Type:
@staticmethod
def ty(*args: ir.Type) -> ir.Type:
"""
Returns the bag type for the given element type.
"""
Expand Down
9 changes: 9 additions & 0 deletions frontends/PyRTG/src/pyrtg/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

from .circt import ir, support, dialects

import sys

sys.modules[__name__ + '.dialects'] = dialects
119 changes: 119 additions & 0 deletions frontends/PyRTG/src/pyrtg/configs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

from __future__ import annotations

from .core import CodeGenRoot
from .base import ir
from .rtg import rtg


class Param:
"""
This class represents a configuration parameter. An instance of this class
should be added as an attribute to a config class (i.e., a class that
inherits from 'Config' and has a '@config' decorator).

There are two ways to do this:
* Declare the attribute in the class directly or in the constructor. In this
case, the 'loader' keyword argument has to be used to pass a callable
(e.g., a lambda) which will construct the value to be assigned to this
parameter.
* Declare the attribute in the 'load' method. Here either the 'loader'
callback can be used or the 'value' keyword argument can be used to assign
the value directly.

Note that any parameter assignments/declarations in the 'load' method take
precedence.

In both cases, the 'name' keyword argument can be used to assign a name to
this parameter. You have to make sure that no two parameters in a config have
the same name. By default, the name of the attribute within the config class
will be used as the name.
"""

def __init__(self, **kwargs) -> Param:
if "value" in kwargs:
self._value = kwargs["value"]

if "loader" in kwargs:
self._loader = kwargs["loader"]

if "name" in kwargs:
self._name = kwargs["name"]

if hasattr(self, "_value") == hasattr(self, "_loader"):
raise AttributeError(
"either the 'value' or 'loader' argument must be used but not both")

def get_type(self) -> ir.Type:
if not hasattr(self, "_value"):
raise AttributeError(
"type can only be accesses after the config has been loaded")

return self._value.get_type()

def get_name(self) -> str:
if not hasattr(self, "_name"):
raise AttributeError(
"name can only be accesses after the config has been loaded")

return self._name


def config(cls):
"""
Represents an RTG Configuration. Constructs an instance of the decorated
class which registers it as an RTG config.
"""

inst = cls()
for attr_name, attr in cls.__dict__.items():
if isinstance(attr, Param):
setattr(inst, attr_name, attr)
inst._name = cls.__name__
return inst


class Config(CodeGenRoot):
"""
An RTG Config is a collection of parameters that define the capabilities and
characteristics of a specific test target.
"""

def get_params(self) -> list[Param]:
if not self._already_generated:
raise RuntimeError(
"can only get params once the config has been generated")

params = []
for attr_name, attr in self.__dict__.items():
if isinstance(attr, Param):
if not hasattr(attr, "_name"):
attr._name = attr_name
params.append(attr)

return params

def _codegen(self) -> None:
self._already_generated = True

# Construct the target operation.
target_op = rtg.TargetOp(self._name, ir.TypeAttr.get(rtg.DictType.get()))
entry_block = ir.Block.create_at_start(target_op.bodyRegion, [])
with ir.InsertionPoint(entry_block):
if hasattr(self, "load"):
self.load()

params = self.get_params()
for param in params:
if not hasattr(param, "_value"):
param._value = param._loader()

params.sort(key=lambda param: param.get_name())
rtg.YieldOp([param._value for param in params])

dict_entries = [(ir.StringAttr.get(param.get_name()), param.get_type())
for param in params]
target_op.target = ir.TypeAttr.get(rtg.DictType.get(dict_entries))
Loading