Skip to content

Commit 12fa544

Browse files
committed
add doc for module_inherit_mro
Signed-off-by: zhongzc <zhongzc_arch@outlook.com>
1 parent 72f6456 commit 12fa544

File tree

16 files changed

+137
-66
lines changed

16 files changed

+137
-66
lines changed

py_hcl/core/expr/add.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
from py_hcl.core.hcl_ops import op_register
4545
from py_hcl.core.stmt.connect import VariableType
4646
from py_hcl.core.type import HclType
47-
from py_hcl.core.type.bundle import BundleT, Dir
47+
from py_hcl.core.type.bundle import BundleT, BundleDirection
4848
from py_hcl.core.type.sint import SIntT
4949
from py_hcl.core.type.uint import UIntT
5050
from py_hcl.core.type.vector import VectorT
@@ -99,7 +99,10 @@ def _(lf, rt):
9999
bd_values = {}
100100
for k in lf.hcl_type.fields.keys():
101101
res = getattr(lf, k) + getattr(rt, k)
102-
bd_type_fields[k] = {"dir": Dir.SRC, "hcl_type": res.hcl_type}
102+
bd_type_fields[k] = {
103+
"dir": BundleDirection.SOURCE,
104+
"hcl_type": res.hcl_type
105+
}
103106
bd_values[k] = res
104107

105108
return BundleHolder(BundleT(bd_type_fields), VariableType.VALUE, bd_values)

py_hcl/core/expr/ands.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from py_hcl.core.hcl_ops import op_register
4848
from py_hcl.core.stmt.connect import VariableType
4949
from py_hcl.core.type import HclType
50-
from py_hcl.core.type.bundle import BundleT, Dir
50+
from py_hcl.core.type.bundle import BundleT, BundleDirection
5151
from py_hcl.core.type.sint import SIntT
5252
from py_hcl.core.type.uint import UIntT
5353
from py_hcl.core.type.vector import VectorT
@@ -102,7 +102,10 @@ def _(lf, rt):
102102
bd_values = {}
103103
for k in lf.hcl_type.fields.keys():
104104
res = getattr(lf, k) & getattr(rt, k)
105-
bd_type_fields[k] = {"dir": Dir.SRC, "hcl_type": res.hcl_type}
105+
bd_type_fields[k] = {
106+
"dir": BundleDirection.SOURCE,
107+
"hcl_type": res.hcl_type
108+
}
106109
bd_values[k] = res
107110

108111
return BundleHolder(BundleT(bd_type_fields), VariableType.VALUE, bd_values)

py_hcl/core/expr/field.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from py_hcl.core.hcl_ops import op_register
55
from py_hcl.core.stmt.connect import VariableType
66
from py_hcl.core.type import HclType
7-
from py_hcl.core.type.bundle import BundleT, Dir
7+
from py_hcl.core.type.bundle import BundleT, BundleDirection
88
from py_hcl.utils.serialization import json_serialize
99

1010
field_accessor = op_register('.')
@@ -39,11 +39,12 @@ def _(o, *_):
3939
raise ExprError.op_type_err('field_accessor', o)
4040

4141

42-
def build_new_var_type(var_type: VariableType, dr: Dir) -> VariableType:
42+
def build_new_var_type(var_type: VariableType,
43+
dr: BundleDirection) -> VariableType:
4344
if var_type == VariableType.ASSIGNABLE_VALUE:
4445
return VariableType.ASSIGNABLE_VALUE
4546
if var_type == VariableType.VALUE and dr == dr.SINK:
4647
return VariableType.LOCATION
47-
if var_type == VariableType.LOCATION and dr == dr.SRC:
48+
if var_type == VariableType.LOCATION and dr == dr.SOURCE:
4849
return VariableType.LOCATION
4950
return VariableType.VALUE

py_hcl/core/expr/io.py

+21-23
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from typing import Dict, Union, Optional, Tuple
1+
from typing import Dict, Union, Optional, Tuple, List
22

33
from py_hcl.core.expr import HclExpr
44
from py_hcl.core.expr.error import ExprError
55
from py_hcl.core.stmt.connect import VariableType
66
from py_hcl.core.type import HclType
7-
from py_hcl.core.type.bundle import Dir, BundleT
7+
from py_hcl.core.type.bundle import BundleDirection, BundleT
88
from py_hcl.core.utils import module_inherit_mro
99
from py_hcl.utils.serialization import json_serialize
1010

@@ -32,54 +32,52 @@ def __init__(self,
3232
self.module_name = module_name
3333

3434

35-
@json_serialize
36-
class IONode(object):
37-
def __init__(self, io_holder: IOHolder, next_node: Optional["IOHolder"]):
38-
self.io_holder = io_holder
39-
if next_node is not None:
40-
self.next_node = next_node
41-
42-
4335
@json_serialize(
44-
json_fields=["id", "type", "hcl_type", "variable_type", "io_chain_head"])
36+
json_fields=["id", "type", "hcl_type", "variable_type", "io_chain"])
4537
class IO(HclExpr):
46-
def __init__(self, hcl_type: HclType, io_chain_head: IONode):
38+
def __init__(self, hcl_type: HclType, io_chain: List[IOHolder]):
4739
self.type = 'io'
4840
self.hcl_type = hcl_type
4941
self.variable_type = VariableType.VALUE
50-
self.io_chain_head = io_chain_head
42+
self.io_chain = io_chain
5143

5244

5345
def io_extend(modules: Tuple[type]):
46+
"""
47+
48+
49+
"""
50+
5451
modules = module_inherit_mro(modules)
5552

5653
current_ports = {}
57-
io_chain = None
54+
io_chain = []
5855
for m in modules[::-1]:
59-
h = m.io.io_chain_head.io_holder
56+
h = m.io.io_chain[0]
6057
current_ports.update(h.named_ports)
61-
io_chain = IONode(h, io_chain)
58+
io_chain.insert(0, h)
6259

6360
def _(named_ports: Dict[str, Union[Input, Output]]):
6461
current_ports.update(named_ports)
65-
io_chain_head = IONode(IOHolder(named_ports), io_chain)
66-
return IO(calc_type_from_ports(current_ports), io_chain_head)
62+
io_chain.insert(0, IOHolder(named_ports))
63+
return IO(__build_bundle_type_from_ports(current_ports), io_chain)
6764

6865
return _
6966

7067

71-
def calc_type_from_ports(named_ports: Dict[str, Union[Input, Output]]):
72-
types = {}
68+
def __build_bundle_type_from_ports(
69+
named_ports: Dict[str, Union[Input, Output]]) -> BundleT:
70+
fields = {}
7371
for k, v in named_ports.items():
7472
if isinstance(v, Input):
75-
types[k] = {"dir": Dir.SRC, "hcl_type": v.hcl_type}
73+
fields[k] = {"dir": BundleDirection.SOURCE, "hcl_type": v.hcl_type}
7674
continue
7775

7876
if isinstance(v, Output):
79-
types[k] = {"dir": Dir.SINK, "hcl_type": v.hcl_type}
77+
fields[k] = {"dir": BundleDirection.SINK, "hcl_type": v.hcl_type}
8078
continue
8179

8280
raise ExprError.io_value_err(
8381
"type of '{}' is {}, not Input or Output".format(k, type(v)))
8482

85-
return BundleT(types)
83+
return BundleT(fields)

py_hcl/core/expr/ors.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from py_hcl.core.hcl_ops import op_register
4848
from py_hcl.core.stmt.connect import VariableType
4949
from py_hcl.core.type import HclType
50-
from py_hcl.core.type.bundle import BundleT, Dir
50+
from py_hcl.core.type.bundle import BundleT, BundleDirection
5151
from py_hcl.core.type.sint import SIntT
5252
from py_hcl.core.type.uint import UIntT
5353
from py_hcl.core.type.vector import VectorT
@@ -102,7 +102,10 @@ def _(lf, rt):
102102
bd_values = {}
103103
for k in lf.hcl_type.fields.keys():
104104
res = getattr(lf, k) | getattr(rt, k)
105-
bd_type_fields[k] = {"dir": Dir.SRC, "hcl_type": res.hcl_type}
105+
bd_type_fields[k] = {
106+
"dir": BundleDirection.SOURCE,
107+
"hcl_type": res.hcl_type
108+
}
106109
bd_values[k] = res
107110

108111
return BundleHolder(BundleT(bd_type_fields), VariableType.VALUE, bd_values)

py_hcl/core/expr/utils/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def ensure_all_args_are_values(f):
4040
py_hcl.core.expr.error.ExprError: Specified expresion has an invalid
4141
variable type
4242
"""
43-
4443
def _(*args):
4544
check_lists = [a for a in args if hasattr(a, 'variable_type')]
4645
sides = [VariableType.VALUE, VariableType.ASSIGNABLE_VALUE]

py_hcl/core/expr/xor.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
from py_hcl.core.hcl_ops import op_register
4545
from py_hcl.core.stmt.connect import VariableType
4646
from py_hcl.core.type import HclType
47-
from py_hcl.core.type.bundle import BundleT, Dir
47+
from py_hcl.core.type.bundle import BundleT, BundleDirection
4848
from py_hcl.core.type.sint import SIntT
4949
from py_hcl.core.type.uint import UIntT
5050
from py_hcl.core.type.vector import VectorT
@@ -99,7 +99,10 @@ def _(lf, rt):
9999
bd_values = {}
100100
for k in lf.hcl_type.fields.keys():
101101
res = getattr(lf, k) ^ getattr(rt, k)
102-
bd_type_fields[k] = {"dir": Dir.SRC, "hcl_type": res.hcl_type}
102+
bd_type_fields[k] = {
103+
"dir": BundleDirection.SOURCE,
104+
"hcl_type": res.hcl_type
105+
}
103106
bd_values[k] = res
104107

105108
return BundleHolder(BundleT(bd_type_fields), VariableType.VALUE, bd_values)

py_hcl/core/module/meta_module.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def __init__(cls, name, bases, dct):
1414
name = fetch_module_name(name)
1515

1616
check_io_exist(dct, name)
17-
dct["io"].io_chain_head.io_holder.module_name = name
17+
dct["io"].io_chain[0].module_name = name
1818

1919
packed = packer.pack(bases, dct, name)
2020
cls.packed_module = packed

py_hcl/core/stmt/connect.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
from py_hcl.core.stmt.error import StatementError
4949
from py_hcl.core.stmt_factory.trapper import StatementTrapper
5050
from py_hcl.core.type import HclType
51-
from py_hcl.core.type.bundle import BundleT, Dir
51+
from py_hcl.core.type.bundle import BundleT, BundleDirection
5252
from py_hcl.core.type.sint import SIntT
5353
from py_hcl.core.type.uint import UIntT
5454
from py_hcl.core.type.vector import VectorT
@@ -166,7 +166,7 @@ def _(left, right):
166166
for k in keys:
167167
lf = op_apply('.')(left, k)
168168
rt = op_apply('.')(right, k)
169-
if dir_and_types[k]['dir'] == Dir.SRC:
169+
if dir_and_types[k]['dir'] == BundleDirection.SOURCE:
170170
op_apply('<<=')(lf, rt)
171171
else:
172172
op_apply('<<=')(rt, lf)

py_hcl/core/type/bundle.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from py_hcl.core.type.wrapper import vec_wrap, bd_fld_wrap
66

77

8-
class Dir(Enum):
9-
SRC = 1
8+
class BundleDirection(Enum):
9+
SOURCE = 1
1010
SINK = 2
1111

1212

py_hcl/core/type/wrapper.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
@dispatch()
77
def invert_exp(self: HclType):
8-
from py_hcl.core.type.bundle import Dir
9-
return {'dir': Dir.SINK, 'hcl_type': self}
8+
from py_hcl.core.type.bundle import BundleDirection
9+
return {'dir': BundleDirection.SINK, 'hcl_type': self}
1010

1111

1212
def bd_fld_wrap(cls):

py_hcl/core/utils/__init__.py

+73-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,79 @@
11
from typing import Tuple, List
22

33

4-
def module_inherit_mro(modules: Tuple[type]) -> List[type]:
4+
def module_inherit_mro(bases: Tuple[type]) -> List[type]:
5+
"""
6+
Returns modules in method resolution order.
7+
8+
As we want to handle inherit stuff, the mro is a very basic entry to travel
9+
the inherit graph.
10+
11+
12+
Examples
13+
--------
14+
15+
>>> from py_hcl import *
16+
17+
A normal PyHCL module `V`:
18+
19+
>>> class V(Module):
20+
... io = IO()
21+
22+
23+
A PyHCL module `W` inheriting `V`:
24+
25+
>>> class W(V):
26+
... io = io_extend(V)()
27+
28+
29+
Let's see the bases of `W`:
30+
31+
>>> W.__bases__
32+
(<class 'py_hcl.core.utils.V'>,)
33+
34+
35+
So we can get the mro of its bases via `module_inherit_mro`:
36+
37+
>>> module_inherit_mro(W.__bases__)
38+
[<class 'py_hcl.core.utils.V'>,
39+
<class 'py_hcl.core.module.base_module.BaseModule'>]
40+
41+
42+
A more complicated case:
43+
44+
>>> class X(W):
45+
... io = io_extend(W)()
46+
47+
>>> class Y(V):
48+
... io = io_extend(V)()
49+
50+
>>> class Z(X, Y):
51+
... io = io_extend(X, Y)()
52+
53+
54+
To handle expression inheritance or statement inheritance of the module
55+
`Z`, we can first get the mro of `Z`'s bases:
56+
57+
>>> module_inherit_mro(Z.__bases__)
58+
[<class 'py_hcl.core.utils.X'>,
59+
<class 'py_hcl.core.utils.W'>,
60+
<class 'py_hcl.core.utils.Y'>,
61+
<class 'py_hcl.core.utils.V'>,
62+
<class 'py_hcl.core.module.base_module.BaseModule'>]
63+
64+
"""
65+
566
from py_hcl.core.module.meta_module import MetaModule
667

7-
modules = type("_hcl_fake_module", modules, {}).mro()
8-
modules = [m for m in modules[1:] if isinstance(m, MetaModule)]
68+
# Step 1: Build a fake Python class extending bases.
69+
#
70+
# Since `Module`s inherit from `MetaModule`, class construction here will
71+
# trigger `MetaModule.__init__`. We get around the side effect by adding a
72+
# conditional early return at the beginning of `MetaModule.__init__`.
73+
fake_type = type("_hcl_fake_module", bases, {})
74+
75+
# Step 2: Get the method resolution order of the fake class.
76+
# Step 3: Filter useless types in the mro.
77+
modules = [m for m in fake_type.mro()[1:] if isinstance(m, MetaModule)]
78+
979
return modules

py_hcl/dsl/type/bundle.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from typing import Union
22

33
from py_hcl.core.type import HclType
4-
from py_hcl.core.type.bundle import BundleT, Dir
4+
from py_hcl.core.type.bundle import BundleT, BundleDirection
55

66

77
def Bundle(**named_ports: Union[HclType, dict]) -> BundleT:
88
t = {
99
k: ({
10-
'dir': Dir.SRC,
10+
'dir': BundleDirection.SOURCE,
1111
'hcl_type': v
1212
} if isinstance(v, HclType) else v)
1313
for k, v in named_ports.items()

py_hcl/transformer/pyhcl_to_firrtl/conv_expr.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,9 @@ def convert_expr_op(expr_holder: ExprHolder, fa: FieldAccess):
138138
obj = GlobalContext.expr_table[fa.ref_expr_id]
139139

140140
def fetch_current_io_holder(obj):
141-
current_node = obj.io_chain_head
142-
while True:
143-
if fa.item in current_node.io_holder.named_ports:
144-
return current_node.io_holder
145-
current_node = current_node.next_node
141+
for io_holder in obj.io_chain:
142+
if fa.item in io_holder.named_ports:
143+
return io_holder
146144

147145
if isinstance(obj, IO):
148146
io_holder = fetch_current_io_holder(obj)

py_hcl/transformer/pyhcl_to_firrtl/conv_module.py

+4-12
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,9 @@ def flatten_statement_chain(statement_chain: StmtChain):
6161

6262
def flatten_io_chain(io: IO):
6363
ports = {}
64-
node = io.io_chain_head
6564

66-
while True:
67-
holder = node.io_holder
68-
# reverse the dict order
69-
for k in list(holder.named_ports.keys())[::-1]:
70-
v = holder.named_ports[k]
71-
ports[build_io_name(holder.module_name, k)] = v
72-
73-
if not hasattr(node, "next_node"):
74-
break
75-
node = node.next_node
65+
for io_holder in io.io_chain:
66+
for k, v in io_holder.named_ports.items():
67+
ports[build_io_name(io_holder.module_name, k)] = v
7668

77-
return {k: ports[k] for k in list(ports.keys())[::-1]}
69+
return ports

0 commit comments

Comments
 (0)