CIRCT 20.0.0git
Loading...
Searching...
No Matches
fsm.py
Go to the documentation of this file.
1# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2# See https://llvm.org/LICENSE.txt for license information.
3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5from . import fsm as fsm
6from .. import support
7from ..dialects._ods_common import _cext as _ods_cext
8from ..ir import *
9from ._fsm_ops_gen import *
10from ._fsm_ops_gen import _Dialect
11
12
13def _get_or_add_single_block(region, args=[]):
14 if len(region.blocks) == 0:
15 region.blocks.append(*args)
16 return region.blocks[0]
17
18
19@_ods_cext.register_operation(_Dialect, replace=True)
21
22 def __init__(self,
23 name,
24 initial_state,
25 input_ports,
26 output_ports,
27 *,
28 attributes={},
29 loc=None,
30 ip=None):
31 attributes["sym_name"] = StringAttr.get(name)
32 attributes["initialState"] = StringAttr.get(initial_state)
33
34 input_types = []
35 output_types = []
36 for (i, (_, port_type)) in enumerate(input_ports):
37 input_types.append(port_type)
38
39 for (i, (_, port_type)) in enumerate(output_ports):
40 output_types.append(port_type)
41
42 attributes["function_type"] = TypeAttr.get(
43 FunctionType.get(inputs=input_types, results=output_types))
44
45 OpView.__init__(
46 self,
47 self.build_generic(attributes=attributes,
48 results=[],
49 operands=[],
50 successors=None,
51 regions=1,
52 loc=loc,
53 ip=ip))
54
56
57 @property
58 def type(self):
59 return FunctionType(TypeAttr(self.attributes["function_type"]).value)
60
61 def instantiate(self, name: str, loc=None, ip=None, **kwargs):
62 """ FSM Instantiation function"""
63 in_names = support.attribute_to_var(self.attributes['in_names'])
64 inputs = [kwargs[port].value for port in in_names]
65
66 # Clock and resets are not part of the input ports of the FSM, but
67 # it is at the point of `fsm.hw_instance` instantiation that they
68 # must be connected.
69 # Attach backedges to these, and associate these backedges to the operation.
70 # They can then be accessed at the point of instantiation and assigned.
71 clock = support.BackedgeBuilder().create(
72 IntegerType.get_signed(1),
73 StringAttr(self.attributes['clock_name']).value, self)
74 reset = support.BackedgeBuilder().create(
75 IntegerType.get_signed(1),
76 StringAttr(self.attributes['reset_name']).value, self)
77
78 op = fsm.HWInstanceOp(outputs=self.type.results,
79 inputs=inputs,
80 sym_name=StringAttr.get(name),
81 machine=FlatSymbolRefAttr.get(self.sym_name.value),
82 clock=clock.result,
83 reset=reset.result if reset else None,
84 loc=loc,
85 ip=ip)
86 op.backedges = {}
87
88 def set_OpOperand(name, backedge):
89 index = None
90 for i, operand in enumerate(op.operands):
91 if operand == backedge.result:
92 index = i
93 break
94 assert index is not None
95 op_operand = support.OpOperand(op, index, op.operands[index], op)
96 setattr(op, f'_{name}_backedge', op_operand)
97 op.backedges[i] = backedge
98
99 set_OpOperand('clock', clock)
100 if reset:
101 set_OpOperand('reset', reset)
102
103 return op
104
105
106@_ods_cext.register_operation(_Dialect, replace=True)
108
109 @staticmethod
110 def create(to_state):
111 op = fsm.TransitionOp(to_state)
112 return op
113
114 def set_guard(self, guard_fn):
115 """Executes a function to generate a guard for the transition.
116 The function is executed within the guard region of this operation."""
117 guard_block = _get_or_add_single_block(self.guard)
118 with InsertionPoint(guard_block):
119 guard = guard_fn()
120 guard_type = support.type_to_pytype(guard.type)
121 if guard_type.width != 1:
122 raise ValueError('The guard must be a single bit')
123 fsm.ReturnOp(operand=guard)
124
125
126@_ods_cext.register_operation(_Dialect, replace=True)
128
129 def __init__(self, name, *, loc=None, ip=None):
130 attributes = {}
131 attributes["sym_name"] = StringAttr.get(name)
132
133 OpView.__init__(
134 self,
135 self.build_generic(attributes=attributes,
136 results=[],
137 operands=[],
138 successors=None,
139 regions=2,
140 loc=loc,
141 ip=ip))
142
143 @staticmethod
144 def create(name):
145 return fsm.StateOp(name)
146
147 @property
148 def output(self):
149 return _get_or_add_single_block(super().output)
150
151 @property
152 def transitions(self):
153 return _get_or_add_single_block(super().transitions)
154
155
156@_ods_cext.register_operation(_Dialect, replace=True)
158
159 @staticmethod
160 def create(*operands):
161 return fsm.OutputOp(operands)
__init__(self, name, initial_state, input_ports, output_ports, *attributes={}, loc=None, ip=None)
Definition fsm.py:30
type(self)
Definition fsm.py:58
instantiate(self, str name, loc=None, ip=None, **kwargs)
Definition fsm.py:61
create(*operands)
Definition fsm.py:160
output(self)
Definition fsm.py:148
__init__(self, name, *loc=None, ip=None)
Definition fsm.py:129
transitions(self)
Definition fsm.py:152
create(name)
Definition fsm.py:144
create(to_state)
Definition fsm.py:110
set_guard(self, guard_fn)
Definition fsm.py:114
_get_or_add_single_block(region, args=[])
Definition fsm.py:13