from hdlConvertorAst.hdlAst import HdlDirection, iHdlStatement, \
HdlIdDef, HdlModuleDec, HdlFunctionDef, HdlCompInst, \
HdlTypeType, HdlOp, HdlOpType, HdlValueIdspace, HdlPhysicalDef, \
HdlEnumDef, HdlTypeSubtype, HdlValueInt, HdlClassDef, HdlClassType, \
HdlValueId
from hdlConvertorAst.to.hdlUtils import Indent, iter_with_last, UnIndent
from hdlConvertorAst.to.vhdl.stm import ToVhdl2008Stm
[docs]class ToVhdl2008(ToVhdl2008Stm):
"""
Convert hdlObject AST back to VHDL
"""
DIR2V = {
HdlDirection.IN: "IN",
HdlDirection.OUT: "OUT",
HdlDirection.INOUT: "INOUT",
}
[docs] def __init__(self, out_stream):
ToVhdl2008Stm.__init__(self, out_stream)
self.in_typedef = False
[docs] def visit_doc(self, obj):
return super(ToVhdl2008, self).visit_doc(obj, "--")
[docs] def visit_direction(self, d):
vd = self.DIR2V[d]
self.out.write(vd)
[docs] def visit_main_obj(self, o):
ToVhdl2008Stm.visit_main_obj(self, o)
add_nl = isinstance(o, (HdlModuleDec, HdlModuleDec, HdlValueIdspace))
if add_nl:
self.out.write("\n")
[docs] def visit_param_or_port_declr(self, o, is_param):
"""
:type p: HdlIdDef
"""
self.visit_doc(o)
w = self.out.write
w(o.name)
w(" : ")
if not is_param:
d = o.direction
if d != HdlDirection.INTERNAL:
self.visit_direction(d)
w(" ")
self.visit_type(o.type)
v = o.value
if v is not None:
w(" := ")
self.visit_iHdlExpr(v)
[docs] def visit_HdlModuleDec(self, e, vhdl_obj_name="ENTITY"):
"""
:param e: Entity
:type e: HdlModuleDec
"""
self.visit_doc(e)
w = self.out.write
w(vhdl_obj_name)
w(" ")
w(e.name)
w(" IS\n")
gs = e.params
if gs:
with Indent(self.out):
w("GENERIC(\n")
with Indent(self.out):
for last, g in iter_with_last(gs):
self.visit_param_or_port_declr(g, True)
if last:
w("\n")
else:
w(";\n")
w(");\n")
ps = e.ports
if ps:
with Indent(self.out):
w("PORT(\n")
with Indent(self.out):
for last, p in iter_with_last(ps):
self.visit_param_or_port_declr(p, False)
if last:
w("\n")
else:
w(";\n")
w(");\n")
di = e.objs
if di:
with Indent(self.out):
for o in di:
self.visit_iHdlObj(o)
w("END ")
w(vhdl_obj_name)
w(";\n")
[docs] def visit_component(self, o):
"""
:type o: HdlModuleDec
"""
self.visit_HdlModuleDec(o, vhdl_obj_name="COMPONENT")
[docs] def visit_type(self, t):
"""
:type t: iHdlExpr
"""
self.visit_iHdlExpr(t)
[docs] def visit_map_item(self, item):
self.visit_iHdlExpr(item)
[docs] def visit_map(self, map_):
w = self.out.write
with Indent(self.out):
for last, m in iter_with_last(map_):
self.visit_map_item(m)
if last:
w("\n")
else:
w(",\n")
[docs] def visit_HdlCompInst(self, c):
"""
:type c: HdlCompInst
"""
self.visit_doc(c)
w = self.out.write
w(c.name.val)
w(": ")
if not isinstance(c.module_name, HdlValueId):
w("ENTITY ")
self.visit_iHdlExpr(c.module_name)
gms = c.param_map
if gms:
w(" GENERIC MAP(\n")
self.visit_map(gms)
w(")")
pms = c.port_map
if pms:
w(" PORT MAP(\n")
self.visit_map(pms)
w(")")
w(";")
[docs] def visit_body_items(self, objs):
w = self.out.write
in_def_section = True
with Indent(self.out):
for o in objs:
if isinstance(o, HdlIdDef):
assert in_def_section, o
self.visit_HdlIdDef(o)
continue
elif isinstance(o, HdlModuleDec):
assert in_def_section, o
self.visit_component(o)
continue
elif isinstance(o, HdlFunctionDef):
assert in_def_section, o
self.visit_HdlFunctionDef(o)
continue
if in_def_section:
with UnIndent(self.out):
w("BEGIN\n")
in_def_section = False
if isinstance(o, HdlCompInst):
self.visit_HdlCompInst(o)
w("\n")
elif isinstance(o, iHdlStatement):
self.visit_iHdlStatement(o)
elif isinstance(o, HdlOp) and o.fn == HdlOpType.CALL:
self.visit_HdlOp(o)
w(";\n")
else:
raise NotImplementedError(o)
if in_def_section:
w("BEGIN\n")
[docs] def visit_HdlModuleDef(self, o):
"""
:type o: HdlModuleDef
"""
w = self.out.write
if o.dec is not None:
self.visit_HdlModuleDec(o.dec)
w("\n")
self.visit_doc(o)
w("ARCHITECTURE ")
w(o.name)
w(" OF ")
w(o.module_name.val)
w(" IS\n")
self.visit_body_items(o.objs)
self.out.write("END ARCHITECTURE;\n")
[docs] def visit_HdlIdDef(self, var, end=";\n"):
"""
:type var: HdlIdDef
"""
self.visit_doc(var)
w = self.out.write
name = var.name
t = var.type
if t == HdlTypeType:
assert not var.is_shared
orig_in_typedef = self.in_typedef
try:
self.in_typedef = True
# typedef
w("TYPE ")
w(name)
w(" IS ")
_t = var.value
if isinstance(_t, HdlEnumDef):
self.visit_HdlEnumDef(_t)
elif isinstance(_t, HdlOp):
if _t.fn == HdlOpType.INDEX:
w("ARRAY (")
for last, i in iter_with_last(_t.ops[1:]):
self.visit_iHdlExpr(i)
if not last:
w(", ")
w(") OF ")
self.visit_iHdlExpr(_t.ops[0])
elif _t.fn == HdlOpType.RANGE:
w("RANGE ")
assert len(_t.ops) == 1, _t.ops
self.visit_iHdlExpr(_t.ops[0])
else:
raise NotImplementedError(_t.fn)
elif isinstance(_t, HdlClassDef):
self.visit_HdlClassDef(_t)
elif isinstance(_t, HdlPhysicalDef):
self.visit_HdlPhysicalDef(_t)
else:
raise NotImplementedError(type(_t))
finally:
self.in_typedef = orig_in_typedef
elif t == HdlTypeSubtype:
assert not var.is_shared
orig_in_typedef = self.in_typedef
try:
self.in_typedef = True
w("SUBTYPE ")
w(name)
w(" IS ")
self.visit_iHdlExpr(var.value)
finally:
self.in_typedef = orig_in_typedef
else:
# signal/variable/port/generic
if not self.in_typedef:
latch = var.is_latched
c = var.is_const
if c:
assert not var.is_shared
w("CONSTANT ")
elif latch:
if var.is_shared:
w("SHARED ")
w("VARIABLE ")
else:
assert not var.is_shared
w("SIGNAL ")
w(name)
w(" : ")
self.visit_type(t)
v = var.value
if v is not None:
w(" := ")
self.visit_iHdlExpr(v)
w(end)
[docs] def visit_HdlClassDef(self, o):
"""
:type o: HdlClassDef
"""
w = self.out.write
assert o.type == HdlClassType.STRUCT, o.type
w("RECORD\n")
with Indent(self.out):
for m in o.members:
self.visit_HdlIdDef(m)
w("END RECORD")
[docs] def visit_HdlPhysicalDef(self, o):
"""
:type o: HdlPhysicalDef
"""
w = self.out.write
self.visit_HdlOp(o.range)
w("\n")
with Indent(self.out):
w("UNITS\n")
with Indent(self.out):
for k, v in o.members:
w(k)
if v is not None:
w(" = ")
self.visit_HdlOp(v)
w(";\n")
w("END UNITS")
[docs] def visit_HdlEnumDef(self, o):
"""
:type o: HdlEnumDef
"""
w = self.out.write
w('(')
for last, ev in iter_with_last(o.values):
k, v = ev
if k is not None:
w(k)
else:
assert isinstance(v, HdlValueInt) and v.base == 256, v
self.visit_HdlValueInt(v)
if not last:
w(", ")
w(")")
[docs] def visit_HdlFunctionDef(self, o):
"""
:type o: HdlFunctionDef
"""
self.visit_doc(o)
w = self.out.write
is_procedure = o.return_t is None
if is_procedure:
w("PROCEDURE ")
else:
w("FUNCTION ")
w(o.name)
if o.params:
w(" (")
with Indent(self.out):
for is_last, par in iter_with_last(o.params):
self.visit_HdlIdDef(par, end="")
if not is_last:
w(";\n")
w(")")
if not is_procedure:
w(" RETURN ")
self.visit_type(o.return_t)
if o.is_declaration_only:
w(";\n")
else:
w("\n")
w("IS\n")
self.visit_body_items(o.body)
if is_procedure:
w("END PROCEDURE;\n")
else:
w("END FUNCTION;\n")
[docs] def visit_HdlLibrary(self, o):
"""
:type o: HdlLibrary
"""
self.visit_doc(o)
w = self.out.write
w("LIBRARY ")
w(o.name)
w(";\n")
[docs] def visit_HdlImport(self, o):
"""
:type o: HdlImport
"""
self.visit_doc(o)
w = self.out.write
w("USE ")
for last, p in iter_with_last(o.path):
self.visit_iHdlExpr(p)
if not last:
w(".")
w(";\n")
[docs] def visit_HdlValueIdspace(self, o):
"""
:type o: HdlValueIdspace
"""
self.visit_doc(o)
w = self.out.write
# TODO:: if o.declaration_only:
w("PACKAGE ")
w(o.name)
w(" IS\n")
with Indent(self.out):
for _o in o.objs:
self.visit_main_obj(_o)
w("END PACKAGE;\n")
[docs] def _visit_HdlStmExitOrNext(self, o, stm_name):
"""
:type o: HdlOp
:type stm_name: str
:attention: next/exit statement is represented as a call of next/exit function
and does not have a specific object, as it is expression it does not render
the ending ;
"""
assert o.fn == HdlOpType.CALL and o.ops[0] == HdlValueId(stm_name), o
w = self.out.write
w(stm_name)
if len(o.ops) == 1:
pass
elif len(o.ops) == 2:
# label
w(" ")
self.visit_iHdlExpr(o.ops[1])
elif len(o.ops) == 3:
# label, condition
w(" ")
_, label, cond = o.ops
self.visit_iHdlExpr(label)
w(" WHEN (")
self.visit_iHdlExpr(cond)
w(")")
else:
raise ValueError(o)
[docs] def visit_HdlOp(self, o):
arg0 = o.ops[0]
if o.fn == HdlOpType.CALL and isinstance(arg0, HdlValueId):
if arg0.val == "EXIT":
return self.visit_HdlStmExit(o)
elif arg0.val == "NEXT":
return self.visit_HdlStmNext(o)
return ToVhdl2008Stm.visit_HdlOp(self, o)
[docs] def visit_HdlStmExit(self, o):
"""
:type o: HdlOp
"""
return self._visit_HdlStmExitOrNext(o, "EXIT")
[docs] def visit_HdlStmNext(self, o):
"""
:type o: HdlOp
"""
return self._visit_HdlStmExitOrNext(o, "NEXT")