forked from opendacs/PyHCL
core: add json serialize (#39)
This commit is contained in:
parent
a05ab12ea5
commit
62b09da428
|
@ -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
|
||||
|
|
|
@ -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('+')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -2,4 +2,5 @@ from py_hcl.core.type import HclType
|
|||
|
||||
|
||||
class ClockT(HclType):
|
||||
pass
|
||||
def __init__(self):
|
||||
self.type = "clock"
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue