core: add json serialize (#39)

This commit is contained in:
Gaufoo 2020-01-02 16:42:19 +08:00 committed by GitHub
parent a05ab12ea5
commit 62b09da428
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 263 additions and 186 deletions

View File

@ -3,14 +3,43 @@ from multipledispatch.dispatcher import MethodDispatcher
from py_hcl.core.hcl_ops import op_apply
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import UnknownType, HclType
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
class ExprIdGen:
id = -1
@classmethod
def next_id(cls):
cls.id += 1
return cls.id
class ExprPool:
pool = {}
@classmethod
def add(cls, i, obj):
cls.pool[i] = obj
@classmethod
def fetch_all(cls):
p = cls.pool
cls.pool = {}
return p
@json_serialize
class HclExpr(object):
hcl_type = UnknownType()
conn_side = ConnSide.UNKNOWN
def __new__(cls, *args):
obj = super().__new__(cls)
obj.id = ExprIdGen.next_id()
ExprPool.add(obj.id, obj)
return obj
def __ilshift__(self, other):
return op_apply('<<=')(self, other)
@ -58,9 +87,10 @@ class HclExpr(object):
return op_apply('to_bool')(self)
@auto_repr(repr_fields=['hcl_type', 'conn_side', 'assoc_value'])
@json_serialize(json_fields=['id', 'type', 'hcl_type', 'conn_side', 'op_node'])
class ExprHolder(HclExpr):
def __init__(self, hcl_type: HclType, conn_side: ConnSide, assoc_value):
def __init__(self, hcl_type: HclType, conn_side: ConnSide, op_node):
self.type = 'expr_holder'
self.hcl_type = hcl_type
self.conn_side = conn_side
self.assoc_value = assoc_value
self.op_node = op_node

View File

@ -1,21 +1,22 @@
from py_hcl.core.expr.error import ExprError
from py_hcl.core.expr import ExprHolder
from py_hcl.core.expr.error import ExprError
from py_hcl.core.expr.utils import assert_right_side
from py_hcl.core.expr.vec_holder import VecHolder
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.hcl_ops import op_register
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import HclType
from py_hcl.core.type.sint import SIntT
from py_hcl.core.type.uint import UIntT
from py_hcl.core.type.vector import VectorT
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class Add(object):
def __init__(self, left, right):
self.left = left
self.right = right
self.operation = 'add'
self.left_expr_id = left.id
self.right_expr_id = right.id
adder = op_register('+')

View File

@ -1,28 +1,30 @@
from py_hcl.core.expr import ExprHolder
from py_hcl.core.expr.error import ExprError
from py_hcl.core.expr.utils import assert_right_side
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.hcl_ops import op_register
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import HclType
from py_hcl.core.type.sint import SIntT
from py_hcl.core.type.uint import UIntT
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
to_bool = op_register('to_bool')
to_uint = op_register('to_uint')
to_sint = op_register('to_sint')
@auto_repr
@json_serialize
class ToSInt(object):
def __init__(self, expr):
self.expr = expr
self.operation = "to_sint"
self.ref_expr_id = expr.id
@auto_repr
@json_serialize
class ToUInt(object):
def __init__(self, expr):
self.expr = expr
self.operation = "to_uint"
self.ref_expr_id = expr.id
@to_bool(UIntT)

View File

@ -1,35 +1,36 @@
from py_hcl.core.expr import ExprHolder
from py_hcl.core.expr.error import ExprError
from py_hcl.core.expr.io import IO, IOHolder
from py_hcl.core.hcl_ops import op_register
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import HclType
from py_hcl.core.type.bundle import BundleT, Dir
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
field_accessor = op_register('.')
@auto_repr
@json_serialize
class FieldAccess(object):
def __init__(self, expr, item):
self.operation = "field_access"
self.item = item
self.expr = expr
self.ref_expr_id = expr.id
@field_accessor(BundleT)
def _(bd, item):
# TODO: Accurate Error Message
assert item in bd.hcl_type.types
assert item in bd.hcl_type.fields
# build connect side
sd = bd.conn_side
dr, tpe = bd.hcl_type.types[item]
f = bd.hcl_type.fields[item]
dr, tpe = f["dir"], f["hcl_type"]
new_sd = build_new_sd(sd, dr)
# for io
if isinstance(bd, IO):
bd = fetch_inner_io_holder(bd, item)
# # for io
# if isinstance(bd, IO):
# bd = fetch_inner_io_holder(bd, item)
return ExprHolder(tpe, new_sd, FieldAccess(bd, item))
@ -49,9 +50,9 @@ def build_new_sd(sd: ConnSide, dr: Dir) -> ConnSide:
return ConnSide.RT
def fetch_inner_io_holder(io, name) -> IOHolder:
current_node = io.io_chain_head
while True:
if name in current_node.io_holder.named_ports:
return current_node.io_holder
current_node = current_node.next_node
# def fetch_inner_io_holder(io, name) -> IOHolder:
# current_node = io.io_chain_head
# while True:
# if name in current_node.io_holder.named_ports:
# return current_node.io_holder
# current_node = current_node.next_node

View File

@ -7,16 +7,17 @@ from py_hcl.core.type import HclType
from py_hcl.core.type.sint import SIntT
from py_hcl.core.type.uint import UIntT
from py_hcl.core.type.vector import VectorT
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
index = op_register('[i]')
@auto_repr
@json_serialize
class VecIndex(object):
def __init__(self, expr, idx: int):
self.operation = "vec_index"
self.index = idx
self.expr = expr
self.ref_expr_id = expr.id
@index(UIntT)

View File

@ -6,22 +6,24 @@ from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import HclType
from py_hcl.core.type.bundle import Dir, BundleT
from py_hcl.core.utils import module_inherit_mro
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class Input(object):
def __init__(self, hcl_type: HclType):
self.port_dir = 'input'
self.hcl_type = hcl_type
@auto_repr
@json_serialize
class Output(object):
def __init__(self, hcl_type: HclType):
self.port_dir = 'output'
self.hcl_type = hcl_type
@auto_repr
@json_serialize
class IOHolder(object):
def __init__(self, named_ports: Dict[str, Union[Input, Output]],
module_name: Optional[str] = None):
@ -29,7 +31,7 @@ class IOHolder(object):
self.module_name = module_name
@auto_repr
@json_serialize
class IONode(object):
def __init__(self, io_holder: IOHolder,
next_node: Optional["IOHolder"]):
@ -37,9 +39,11 @@ class IONode(object):
self.next_node = next_node
@auto_repr(repr_fields=["hcl_type", "conn_side", "io_chain_head"])
@json_serialize(json_fields=["id", "type", "hcl_type",
"conn_side", "io_chain_head"])
class IO(HclExpr):
def __init__(self, hcl_type: HclType, io_chain_head: IONode):
self.type = 'io'
self.hcl_type = hcl_type
self.conn_side = ConnSide.RT
self.io_chain_head = io_chain_head
@ -67,11 +71,11 @@ def calc_type_from_ports(named_ports: Dict[str, Union[Input, Output]]):
types = {}
for k, v in named_ports.items():
if isinstance(v, Input):
types[k] = (Dir.SRC, v.hcl_type)
types[k] = {"dir": Dir.SRC, "hcl_type": v.hcl_type}
continue
if isinstance(v, Output):
types[k] = (Dir.SINK, v.hcl_type)
types[k] = {"dir": Dir.SINK, "hcl_type": v.hcl_type}
continue
raise ExprError.io_value(

View File

@ -1,11 +1,12 @@
from py_hcl.core.expr import ExprHolder
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr(repr_fields=['module_name'])
@json_serialize(json_fields=['operation', 'module_name'])
class ModuleInst(object):
def __init__(self, module_cls):
self.operation = 'module_inst'
self.packed_module = module_cls.packed_module
self.module_name = module_cls.packed_module.name

View File

@ -1,32 +1,34 @@
from py_hcl.core.expr import ExprHolder
from py_hcl.core.expr.error import ExprError
from py_hcl.core.expr.utils import assert_right_side
from py_hcl.core.expr.vec_holder import VecHolder
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.expr.error import ExprError
from py_hcl.core.hcl_ops import op_register
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import HclType
from py_hcl.core.type.sint import SIntT
from py_hcl.core.type.uint import UIntT
from py_hcl.core.type.vector import VectorT
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
slice_ = op_register('[i:j]')
@auto_repr
@json_serialize
class Bits(object):
def __init__(self, expr, high, low):
self.operation = 'bits'
self.high = high
self.low = low
self.expr = expr
self.ref_expr_id = expr.id
@auto_repr
@json_serialize
class VecSlice(object):
def __init__(self, expr, low, high):
self.operation = 'vec_slice'
self.low = low
self.high = high
self.expr = expr
self.ref_expr_id = expr.id
@slice_(UIntT)

View File

@ -1,10 +1,10 @@
from py_hcl.core.expr import HclExpr
from py_hcl.core.stmt.connect import ConnSide
from py_hcl.core.type import HclType
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr(repr_fields=['hcl_type', 'conn_side'])
@json_serialize(json_fields=['hcl_type', 'conn_side'])
class Wire(HclExpr):
def __init__(self, hcl_type: HclType):
self.hcl_type = hcl_type

View File

@ -1,9 +1,9 @@
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class PackedModule(object):
def __init__(self, name, named_expr_list, statement_list):
def __init__(self, name, named_expr_chain, statement_chain):
self.name = name
self.named_expr_list = named_expr_list
self.statement_list = statement_list
self.named_expr_chain = named_expr_chain
self.statement_chain = statement_chain

View File

@ -7,6 +7,6 @@ def extract(dct):
for k, v in dct.items():
# TODO: check if is source not composed expression
if isinstance(v, HclExpr):
res[k] = v
res[k] = {"expr_id": v.id}
return res

View File

@ -1,10 +1,10 @@
from typing import Optional, Dict
from py_hcl.core.expr import HclExpr
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class NamedExprHolder(object):
def __init__(self, module_name: str,
named_expressions: Dict[str, HclExpr]):
@ -12,16 +12,17 @@ class NamedExprHolder(object):
self.named_expressions = named_expressions
@auto_repr
@json_serialize
class NamedExprNode(object):
def __init__(self,
named_expr_holder: NamedExprHolder,
next_node: Optional["NamedExprNode"]):
self.named_expr_holder = named_expr_holder
self.next_node = next_node
if next_node:
self.next_node = next_node
@auto_repr
class NamedExprList(object):
def __init__(self, named_expr_list_head: NamedExprNode):
self.named_expr_list_head = named_expr_list_head
@json_serialize
class NamedExprChain(object):
def __init__(self, named_expr_chain_head: NamedExprNode):
self.named_expr_chain_head = named_expr_chain_head

View File

@ -1,25 +1,26 @@
from typing import Optional
from py_hcl.core.stmt import BlockStatement
from py_hcl.utils import auto_repr
from py_hcl.core.stmt import ClusterStatement
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class StmtHolder(object):
def __init__(self, module_name: str, top_statement: BlockStatement):
def __init__(self, module_name: str, top_statement: ClusterStatement):
self.module_name = module_name
self.top_statement = top_statement
@auto_repr
@json_serialize
class StmtNode(object):
def __init__(self, stmt_holder: StmtHolder,
next_node: Optional["StmtNode"]):
self.stmt_holder = stmt_holder
self.next_node = next_node
if next_node:
self.next_node = next_node
@auto_repr
class StmtList(object):
def __init__(self, stmt_list_head: StmtNode):
self.stmt_list_head = stmt_list_head
@json_serialize
class StmtChain(object):
def __init__(self, stmt_chain_head: StmtNode):
self.stmt_chain_head = stmt_chain_head

View File

@ -1,30 +1,30 @@
from typing import List
from py_hcl.core.module_factory.inherit_list.named_expr import NamedExprList, \
from .inherit_list.named_expr import NamedExprChain, \
NamedExprNode, NamedExprHolder
from py_hcl.core.module_factory.inherit_list.stmt_holder import StmtList, \
from .inherit_list.stmt_holder import StmtChain, \
StmtHolder, StmtNode
def merge_expr(modules: List[type],
expr_holder: NamedExprHolder) -> NamedExprList:
expr_holder: NamedExprHolder) -> NamedExprChain:
expr_list = None
for m in modules[::-1]:
h = m.packed_module.named_expr_list \
.named_expr_list_head.named_expr_holder
h = m.packed_module.named_expr_chain \
.named_expr_chain_head.named_expr_holder
expr_list = NamedExprNode(h, expr_list)
expr_list = NamedExprNode(expr_holder, expr_list)
return NamedExprList(expr_list)
return NamedExprChain(expr_list)
def merge_statement(modules: List[type],
stmt_holder: StmtHolder) -> StmtList:
stmt_holder: StmtHolder) -> StmtChain:
stmt_list = None
for m in modules[::-1]:
h = m.packed_module.statement_list \
.stmt_list_head.stmt_holder
h = m.packed_module.statement_chain \
.stmt_chain_head.stmt_holder
stmt_list = StmtNode(h, stmt_list)
stmt_list = StmtNode(stmt_holder, stmt_list)
return StmtList(stmt_list)
return StmtChain(stmt_list)

View File

@ -1,30 +1,30 @@
from py_hcl.core.module.packed_module import PackedModule
from py_hcl.core.module_factory.inherit_list.named_expr import NamedExprHolder
from py_hcl.core.module_factory.inherit_list.stmt_holder import StmtHolder
from py_hcl.core.stmt_factory.trapper import StatementTrapper
from py_hcl.core.utils import module_inherit_mro
from . import merger
from . import extractor
from py_hcl.core.module.packed_module import PackedModule
from . import merger
def pack(bases, dct, name) -> PackedModule:
raw_expr = extractor.extract(dct)
raw_scope = StatementTrapper.trap()
named_expr_list, statement_list = \
named_expr_chain, statement_chain = \
handle_inherit(bases, raw_expr, raw_scope, name)
res = PackedModule(name, named_expr_list, statement_list)
res = PackedModule(name, named_expr_chain, statement_chain)
return res
def handle_inherit(bases, named_expression, top_statement, name):
modules = module_inherit_mro(bases)
named_expr_list = \
named_expr_chain = \
merger.merge_expr(modules, NamedExprHolder(name, named_expression))
statement_list = \
statement_chain = \
merger.merge_statement(modules, StmtHolder(name, top_statement))
return named_expr_list, statement_list
return named_expr_chain, statement_chain

View File

@ -1,15 +1,17 @@
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class LineStatement(object):
def __init__(self, scope_id, statement):
self.stmt_class = 'line'
self.scope_id = scope_id
self.statement = statement
@auto_repr
class BlockStatement(object):
@json_serialize
class ClusterStatement(object):
def __init__(self, scope_info, stmts):
self.stmt_class = 'cluster'
self.scope_info = scope_info
self.statements = stmts

View File

@ -1,27 +1,22 @@
from py_hcl.core.expr import HclExpr
from py_hcl.core.stmt import ClusterStatement
from py_hcl.core.stmt.error import StatementError
from py_hcl.core.stmt_factory.scope import ScopeManager, ScopeType
from py_hcl.core.stmt import BlockStatement
from py_hcl.core.stmt_factory.trapper import StatementTrapper
from py_hcl.core.type.uint import UIntT
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class When(object):
def __init__(self, cond: HclExpr):
self.cond = cond
self.cond_expr_id = cond.id
@auto_repr
@json_serialize
class ElseWhen(object):
def __init__(self, cond: HclExpr):
self.cond = cond
@auto_repr
class Otherwise(object):
pass
self.cond_expr_id = cond.id
def do_when_enter(cond_expr: HclExpr):
@ -50,8 +45,7 @@ def do_else_when_exit():
def do_otherwise_enter():
check_branch_syntax()
o = Otherwise()
ScopeManager.expand_scope(ScopeType.OTHERWISE, o)
ScopeManager.expand_scope(ScopeType.OTHERWISE)
def do_otherwise_exit():
@ -82,9 +76,9 @@ def check_exists_pre_stmts():
def check_exists_pre_when_block():
last_stmt = StatementTrapper.trapped_stmts[-1][-1]
if isinstance(last_stmt, BlockStatement):
if isinstance(last_stmt, ClusterStatement):
last_scope = last_stmt.scope_info
last_scope_type = last_scope['scope_type']
last_scope_type = last_scope.scope_type
when = last_scope_type == ScopeType.WHEN
else_when = last_scope_type == ScopeType.ELSE_WHEN
@ -100,11 +94,11 @@ def check_exists_pre_when_block():
def check_correct_block_level():
last_stmt = StatementTrapper.trapped_stmts[-1][-1]
if isinstance(last_stmt, BlockStatement):
if isinstance(last_stmt, ClusterStatement):
last_scope = last_stmt.scope_info
current_scope = ScopeManager.current_scope()
last_scope_level = last_scope['scope_level']
current_scope_level = current_scope['scope_level']
last_scope_level = last_scope.scope_level
current_scope_level = current_scope.scope_level
if last_scope_level == current_scope_level + 1:
return

View File

@ -9,7 +9,7 @@ from py_hcl.core.type.bundle import BundleT, Dir
from py_hcl.core.type.sint import SIntT
from py_hcl.core.type.uint import UIntT
from py_hcl.core.type.vector import VectorT
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
class ConnSide(Enum):
@ -19,11 +19,12 @@ class ConnSide(Enum):
BOTH = 3
@auto_repr
@json_serialize
class Connect(object):
def __init__(self, left, right):
self.left = left
self.right = right
self.stmt_type = 'connect'
self.left_expr_id = left.id
self.right_expr_id = right.id
connector = op_register('<<=')
@ -78,14 +79,14 @@ def _(left, right):
check_connect_dir(left, right)
# TODO: Accurate Error Message
dir_and_types = right.hcl_type.types
dir_and_types = right.hcl_type.fields
keys = dir_and_types.keys()
assert keys == left.hcl_type.types.keys()
assert keys == left.hcl_type.fields.keys()
for k in keys:
lf = op_apply('.')(left, k)
rt = op_apply('.')(right, k)
if dir_and_types[k][0] == Dir.SRC:
if dir_and_types[k]['dir'] == Dir.SRC:
op_apply('<<=')(lf, rt)
else:
op_apply('<<=')(rt, lf)

View File

@ -1,5 +1,7 @@
from enum import Enum
from py_hcl.utils import json_serialize
class ScopeType(Enum):
TOP = 0
@ -9,6 +11,16 @@ class ScopeType(Enum):
OTHERWISE = 4
@json_serialize
class ScopeInfo(object):
def __init__(self, scope_id, scope_level, scope_type, tag_object=None):
self.scope_id = scope_id
self.scope_level = scope_level
self.scope_type = scope_type
if tag_object:
self.tag_object = tag_object
class ScopeLevelManager(object):
_next_scope_level = 0
@ -36,15 +48,16 @@ class ScopeIdManager(object):
class ScopeManager(object):
scope_list = [{
# TOP SCOPE which contains all modules
'scope_id': ScopeIdManager.next_id(),
'scope_level': ScopeLevelManager.current_level(),
'scope_type': ScopeType.TOP,
'tag_object': None
}]
scope_list = [
ScopeInfo(
# TOP SCOPE which contains all modules
scope_id=ScopeIdManager.next_id(),
scope_level=ScopeLevelManager.current_level(),
scope_type=ScopeType.TOP,
)
]
scope_id_map = {
scope_list[0]['scope_id']: scope_list[0]
scope_list[0].scope_id: scope_list[0]
}
scope_expanding_hooks = []
scope_shrinking_hooks = []
@ -55,12 +68,12 @@ class ScopeManager(object):
current_scope = cls.current_scope()
next_id = ScopeIdManager.next_id()
next_scope = {
'scope_id': next_id,
'scope_level': ScopeLevelManager.current_level(),
'scope_type': scope_type,
'tag_object': tag_object
}
next_scope = ScopeInfo(
scope_id=next_id,
scope_level=ScopeLevelManager.current_level(),
scope_type=scope_type,
tag_object=tag_object,
)
cls.scope_id_map[next_id] = next_scope
cls.scope_list.append(next_scope)

View File

@ -1,4 +1,4 @@
from py_hcl.core.stmt import LineStatement, BlockStatement
from py_hcl.core.stmt import LineStatement, ClusterStatement
from .scope import ScopeManager, ScopeType
@ -29,7 +29,7 @@ class StatementTrapper(object):
@classmethod
def track(cls, statement):
statement = LineStatement(
ScopeManager.current_scope()['scope_id'],
ScopeManager.current_scope().scope_id,
statement
)
cls.trapped_stmts[-1].append(statement)
@ -41,7 +41,7 @@ class StatementTrapper(object):
@classmethod
def on_scope_shrinking(cls, current_scope, next_scope):
stmts = cls.trapped_stmts.pop()
cls.trapped_stmts[-1].append(BlockStatement(current_scope, stmts))
cls.trapped_stmts[-1].append(ClusterStatement(current_scope, stmts))
set_up()

View File

@ -1,7 +1,7 @@
from py_hcl.utils import auto_repr
from py_hcl.utils import json_serialize
@auto_repr
@json_serialize
class HclType(object):
pass

View File

@ -1,5 +1,5 @@
from enum import Enum
from typing import Dict, Tuple
from typing import Dict
from py_hcl.core.type import HclType
from py_hcl.core.type.wrapper import vec_wrap, bd_fld_wrap
@ -13,12 +13,13 @@ class Dir(Enum):
@bd_fld_wrap
@vec_wrap
class BundleT(HclType):
def __init__(self, types: Dict[str, Tuple[Dir, HclType]]):
self.types = types
def __init__(self, fields: Dict[str, dict]):
self.type = "bundle"
self.fields = fields
def rev(self):
types = {}
for k, v in self.types.items():
d = Dir.SINK if v[0] == Dir.SRC else Dir.SRC
types[k] = (d, v[1])
return BundleT(types)
# def rev(self):
# types = {}
# for k, v in self.fields.items():
# d = Dir.SINK if v[0] == Dir.SRC else Dir.SRC
# types[k] = {dir: d, type: v[1]}
# return BundleT(types)

View File

@ -2,4 +2,5 @@ from py_hcl.core.type import HclType
class ClockT(HclType):
pass
def __init__(self):
self.type = "clock"

View File

@ -7,6 +7,7 @@ from py_hcl.utils import signed_num_bin_len
@vec_wrap
class SIntT(HclType):
def __init__(self, width):
self.type = "sint"
self.width = width
def __call__(self, value: int):

View File

@ -7,6 +7,7 @@ from py_hcl.utils import unsigned_num_bin_len
@vec_wrap
class UIntT(HclType):
def __init__(self, width):
self.type = "uint"
self.width = width
def __call__(self, value: int):

View File

@ -7,5 +7,6 @@ class VectorT(HclType):
def __init__(self, inner_type: HclType, size: int):
# TODO: Accurate Error Message
assert size > 0
self.type = "vector"
self.size = size
self.inner_type = inner_type

View File

@ -1,11 +1,11 @@
from typing import Tuple, Union
from typing import Union
from py_hcl.core.type import HclType
from py_hcl.core.type.bundle import BundleT, Dir
def Bundle(**named_ports: Union[HclType, Tuple[Dir, HclType]]) -> BundleT:
t = {k: ((Dir.SRC, v) if isinstance(v, HclType) else v)
def Bundle(**named_ports: Union[HclType, dict]) -> BundleT:
t = {k: ({dir: Dir.SRC, type: v} if isinstance(v, HclType) else v)
for k, v in named_ports.items()}
return BundleT(t)

View File

@ -1,3 +1,5 @@
import json
from enum import Enum
from functools import partial
from multipledispatch import dispatch
@ -11,24 +13,38 @@ def unsigned_num_bin_len(num):
return len("{:b}".format(num))
def auto_repr(cls=None, repr_fields=()):
def _(_cls, _repr_fields):
def __repr__(self):
if len(_repr_fields) == 0:
def json_serialize(cls=None, json_fields=()):
def rec(v):
if hasattr(v, "json_obj"):
return v.json_obj()
elif isinstance(v, dict):
return {k: rec(v) for k, v in v.items()}
elif isinstance(v, (list, tuple)):
return [rec(v) for v in v]
elif isinstance(v, Enum):
return v.name
return v
def serialize(self):
return json.dumps(self.json_obj(), indent=2)
def _(_cls, _json_fields):
def js(self):
if len(_json_fields) == 0:
kv = vars(self)
else:
kv = {f: vars(self)[f] for f in _repr_fields}
ls = ['{}={}'.format(k, _fm(v)) for k, v in kv.items()]
fs = _iter_repr(ls)
return '%s {%s}' % (type(self).__name__, ''.join(fs))
kv = {f: vars(self)[f] for f in _json_fields}
_cls.__repr__ = __repr__
return {k: rec(v) for k, v in kv.items()}
_cls.json_obj = js
_cls.__str__ = serialize
return _cls
if cls:
return _(cls, repr_fields)
return _(cls, json_fields)
return partial(_, _repr_fields=repr_fields)
return partial(_, _json_fields=json_fields)
@dispatch()

View File

@ -30,35 +30,35 @@ def test_branch():
with otherwise():
c <<= a + b
s = A.packed_module.statement_list \
.stmt_list_head.stmt_holder.top_statement.statements
s = A.packed_module.statement_chain \
.stmt_chain_head.stmt_holder.top_statement.statements
assert len(s) == 4
si = ScopeManager.get_scope_info(s[0].scope_id)
assert si['scope_type'] == ScopeType.GROUND
assert si.scope_type == ScopeType.GROUND
assert isinstance(s[0].statement, Connect)
si = s[1].scope_info
assert si['scope_type'] == ScopeType.WHEN
assert si['scope_level'] == 2
assert si.scope_type == ScopeType.WHEN
assert si.scope_level == 2
assert len(s[1].statements) == 2
si = s[2].scope_info
assert si['scope_type'] == ScopeType.ELSE_WHEN
assert si['scope_level'] == 2
assert si.scope_type == ScopeType.ELSE_WHEN
assert si.scope_level == 2
assert len(s[2].statements) == 3
si = s[2].statements[1].scope_info
assert si['scope_type'] == ScopeType.WHEN
assert si['scope_level'] == 3
assert si.scope_type == ScopeType.WHEN
assert si.scope_level == 3
si = s[2].statements[2].scope_info
assert si['scope_type'] == ScopeType.OTHERWISE
assert si['scope_level'] == 3
assert si.scope_type == ScopeType.OTHERWISE
assert si.scope_level == 3
si = s[3].scope_info
assert si['scope_type'] == ScopeType.OTHERWISE
assert si['scope_level'] == 2
assert si.scope_type == ScopeType.OTHERWISE
assert si.scope_level == 2
assert len(s[3].statements) == 1

View File

@ -1,5 +1,6 @@
import pytest
from py_hcl.core.expr import ExprPool
from py_hcl.core.expr.error import ExprError
from py_hcl.core.type.bundle import BundleT
from py_hcl.dsl.expr.io import IO, Input, Output
@ -16,10 +17,11 @@ def test_io():
io.o <<= io.i
t = A.packed_module.named_expr_list.named_expr_list_head \
.named_expr_holder.named_expressions['io'].hcl_type
t = A.packed_module.named_expr_chain.named_expr_chain_head \
.named_expr_holder.named_expressions['io']
t = ExprPool.pool[t['expr_id']].hcl_type
assert isinstance(t, BundleT)
assert len(t.types) == 2
assert len(t.fields) == 2
def test_io_no_wrap_io():

View File

@ -12,7 +12,7 @@ def test_module():
a = HclExpr()
assert hasattr(A, "packed_module")
assert len(A.packed_module.named_expr_list.named_expr_list_head
assert len(A.packed_module.named_expr_chain.named_expr_chain_head
.named_expr_holder.named_expressions) == 2

View File

@ -15,7 +15,7 @@ def test_statement():
c <<= a + b
s = A.packed_module.statement_list \
.stmt_list_head.stmt_holder.top_statement.statements
s = A.packed_module.statement_chain \
.stmt_chain_head.stmt_holder.top_statement.statements
assert len(s) == 1
assert isinstance(s[0].statement, Connect)