diff --git a/calyx-py/calyx/builder.py b/calyx-py/calyx/builder.py index bbfea8ac7a..159e3ce686 100644 --- a/calyx-py/calyx/builder.py +++ b/calyx-py/calyx/builder.py @@ -76,6 +76,7 @@ def __init__( self.prog = prog self.component: ast.Component = ast.Component( name, + attributes = [], inputs=[], outputs=[], structs=cells, @@ -112,6 +113,11 @@ def output(self, name: str, size: int) -> ExprBuilder: self.component.outputs.append(ast.PortDef(ast.CompVar(name), size)) return self.this()[name] + def attribute(self, name: str, value: int) -> None: + """Declare an attribute on the component. + """ + self.component.attributes.append(ast.CompAttribute(name, value)) + def this(self) -> ThisBuilder: """Get a handle to the component's `this` cell. diff --git a/calyx-py/calyx/py_ast.py b/calyx-py/calyx/py_ast.py index 4b0269840a..5456f26737 100644 --- a/calyx-py/calyx/py_ast.py +++ b/calyx-py/calyx/py_ast.py @@ -45,6 +45,7 @@ def doc(self) -> str: @dataclass class Component: name: str + attributes : list[Attribute] inputs: list[PortDef] outputs: list[PortDef] wires: list[Structure] @@ -59,11 +60,13 @@ def __init__( outputs: list[PortDef], structs: list[Structure], controls: Control, + attributes: Optional[list[CompAttribute]] = None, latency: Optional[int] = None, ): + self.name = name + self.attributes = attributes self.inputs = inputs self.outputs = outputs - self.name = name self.controls = controls self.latency = latency @@ -86,15 +89,30 @@ def doc(self) -> str: ins = ", ".join([s.doc() for s in self.inputs]) outs = ", ".join([s.doc() for s in self.outputs]) latency_annotation = ( - f"static<{self.latency}> " if self.latency is not None else "" + f"static<{self.latency}> " if self.latency is not None else "" ) - signature = f"{latency_annotation}component {self.name}({ins}) -> ({outs})" + attribute_annotation = f"<{', '.join([f'{a.doc()}' for a in self.attributes])}>" if self.attributes else "" + signature = f"{latency_annotation}component {self.name}{attribute_annotation}({ins}) -> ({outs})" cells = block("cells", [c.doc() for c in self.cells]) wires = block("wires", [w.doc() for w in self.wires]) controls = block("control", [self.controls.doc()]) return block(signature, [cells, wires, controls]) +#Attribute +@dataclass +class Attribute(Emittable): + pass + +@dataclass +class CompAttribute(Attribute): + name: str + value: int + + def doc(self) -> str: + return f"\"{self.name}\"={self.value}" + + # Ports @dataclass class Port(Emittable): diff --git a/calyx-py/test/example.py b/calyx-py/test/example.py index 83ad49ac19..f3986a0b98 100644 --- a/calyx-py/test/example.py +++ b/calyx-py/test/example.py @@ -63,7 +63,12 @@ # Create the component. main_component = Component( - name="main", inputs=[], outputs=[], structs=cells + wires, controls=controls + name="main", + attributes=[], + inputs=[], + outputs=[], + structs=cells + wires, + controls=controls, ) # Create the Calyx program. diff --git a/calyx-py/test/if.py b/calyx-py/test/if.py index d7f60600b6..6acf102cc6 100644 --- a/calyx-py/test/if.py +++ b/calyx-py/test/if.py @@ -42,7 +42,12 @@ controls = If(CompPort(lt, "out"), cond, Enable(true), Enable(false)) main_component = Component( - name="main", inputs=[], outputs=[], structs=cells + wires, controls=controls + name="main", + attributes=[], + inputs=[], + outputs=[], + structs=cells + wires, + controls=controls, ) # Create the Calyx program. diff --git a/calyx-py/test/invoke.py b/calyx-py/test/invoke.py index fb46c34aba..a941abf735 100644 --- a/calyx-py/test/invoke.py +++ b/calyx-py/test/invoke.py @@ -37,6 +37,7 @@ foo_component = Component( name="foo", + attributes=[], inputs=[PortDef(CompVar("a"), 32)], outputs=[PortDef(CompVar("out"), 32)], structs=foo_cells + foo_wires, @@ -83,6 +84,7 @@ main_component = Component( name="main", + attributes=[], inputs=[], outputs=[], structs=cells + wires, diff --git a/docs/builder/ref.md b/docs/builder/ref.md index 423da6db87..b60c0c813a 100644 --- a/docs/builder/ref.md +++ b/docs/builder/ref.md @@ -93,6 +93,21 @@ def add_my_component(prog): Note that it's possible to [create a handle][hndl] to input and output ports. +### Defining Component Attributes + +Components can be given attributes. Similar to ports, just specify the name of the attribute and its value. +Note that `attribute(name, value)` does not return a handle to the attribute. + +```python +my_component.attribute("my_attribute", 1) +``` + +Will create a component that looks like: + +``` +component my_component<"my_attribute"=1>(...) -> (...) { +``` + ### Multi-Component Designs Calyx supports [multi-component designs][multi]. The [top-level example][top] demonstrates how to construct multi-component designs using the library.