from hdlConvertorAst.hdlAst import HdlOpType, HdlStmWait, HdlStmBlock,\
HdlStmProcessTriggerConstrain
from hdlConvertorAst.to.hdlUtils import Indent, iter_with_last
from hdlConvertorAst.to.verilog.expr import ToVerilog2005Expr
[docs]class ToVerilog2005Stm(ToVerilog2005Expr):
ASSIGN_OPS = {
HdlOpType.ASSIGN: '=',
HdlOpType.PLUS_ASSIGN: '+=',
HdlOpType.MINUS_ASSIGN: '-=',
HdlOpType.MUL_ASSIGN: '*=',
HdlOpType.DIV_ASSIGN: '/=',
HdlOpType.MOD_ASSIGN: '%=',
HdlOpType.AND_ASSIGN: '&=',
HdlOpType.OR_ASSIGN: '|=',
HdlOpType.XOR_ASSIGN: '^=',
HdlOpType.SHIFT_LEFT_ASSIGN: '<<=',
HdlOpType.SHIFT_RIGHT_ASSIGN: '>>=',
HdlOpType.ARITH_SHIFT_LEFT_ASSIGN: '<<<=',
HdlOpType.ARITH_SHIFT_RIGHT_ASSIGN: '>>>=',
}
[docs] def __init__(self, out_stream):
super(ToVerilog2005Stm, self).__init__(out_stream)
self.top_stm = None
self.is_in_loop_spec = False
[docs] def visit_iHdlStatement(self, stm):
"""
:type stm: iHdlStatement
"""
if self.top_stm is None:
self.top_stm = stm
try:
return ToVerilog2005Expr.visit_iHdlStatement(self, stm)
finally:
self.top_stm = None
else:
return ToVerilog2005Expr.visit_iHdlStatement(self, stm)
[docs] def visit_HdlStmProcess(self, proc):
"""
:type proc: HdlStmProcess
"""
self.visit_doc(proc)
sens = proc.sensitivity
body = proc.body
w = self.out.write
skip_body = False
if sens is None and proc.trigger_constrain is None:
if isinstance(body, HdlStmWait):
skip_body = True
wait = body
body = []
elif (isinstance(body, HdlStmBlock)
and body.body
and isinstance(body.body[0], HdlStmWait)):
wait = body.body[0]
body = body.body[1:]
else:
wait = None
if wait is None:
assert self.top_stm is proc
assert isinstance(body, HdlStmBlock), body
body = body.body
wait = body[-1]
assert isinstance(wait, HdlStmWait), wait
assert len(wait.val) == 0
body = body[:-1]
w("initial")
else:
if self.top_stm is proc:
w("always ")
w("#")
assert len(wait.val) == 1
self.visit_iHdlExpr(wait.val[0])
_body = HdlStmBlock()
_body.body = body
body = _body
else:
tr = proc.trigger_constrain
if self.top_stm is proc:
if tr is None:
w("always ")
elif tr is HdlStmProcessTriggerConstrain.FF:
w("always_ff ")
elif tr is HdlStmProcessTriggerConstrain.COMB:
w("always_comb ")
elif tr is HdlStmProcessTriggerConstrain.LATCH:
w("always_latch ")
else:
raise ValueError(proc.trigger_constrain)
if tr is None:
w("@(")
for last, item in iter_with_last(sens):
self.visit_iHdlExpr(item)
if not last:
w(", ")
w(")")
else:
assert not sens
# to prevent useless newline for empty always/time waits
if skip_body:
return True
else:
return self.visit_iHdlStatement_in_statement(body)
[docs] def visit_iHdlStatement_in_statement(self, stm):
"""
Print statement which is body of other statement
e.g. body of process, branch of if-then-else or case of case stememnt
"""
w = self.out.write
if isinstance(stm, HdlStmBlock):
if len(stm.body) == 1 and not stm.labels:
stm = stm.body[0]
else:
w(" ")
return self.visit_HdlStmBlock(stm)
w("\n")
with Indent(self.out):
return self.visit_iHdlStatement(stm)
[docs] def visit_HdlStmBlock(self, o):
"""
:type o: HdlStmBlock
"""
self.visit_doc(o)
w = self.out.write
if o.in_preproc:
w("generate ")
w("begin")
if o.labels:
w(": ")
w(o.labels[0])
w("\n")
with Indent(self.out):
for s in o.body:
need_semi = self.visit_iHdlStatement(s)
if need_semi:
w(";\n")
else:
w("\n")
w("end")
if o.in_preproc:
w(" endgenerate")
return False
[docs] def visit_HdlStmIf(self, o):
"""
:type o: HdlStmIf
"""
self.visit_doc(o)
w = self.out.write
if o.in_preproc:
w("generate ")
w("if (")
self.visit_iHdlExpr(o.cond)
w(")")
need_semi = self.visit_iHdlStatement_in_statement(o.if_true)
for cond, stms in o.elifs:
if need_semi:
w(";\n")
else:
w(" ")
w("else if (")
self.visit_iHdlExpr(cond)
w(")")
need_semi = self.visit_iHdlStatement_in_statement(stms)
ifFalse = o.if_false
if ifFalse is not None:
if need_semi:
w(";\n")
else:
w(" ")
w("else")
need_semi = self.visit_iHdlStatement_in_statement(ifFalse)
if o.in_preproc:
if need_semi:
w(";\n")
else:
w("\n")
w("endgenerate")
return False
else:
return need_semi
[docs] def visit_HdlStmAssign(self, o):
"""
:type o: HdlStmAssign
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
w = self.out.write
ts = self.top_stm
if not self.is_in_loop_spec and (ts is o or (ts is not None and ts.in_preproc)):
w("assign ")
self.visit_iHdlExpr(o.dst)
w(" = ")
else:
self.visit_iHdlExpr(o.dst)
if o.is_blocking:
w(" = ")
else:
w(" <= ")
if o.time_delay is not None:
w("#")
self.visit_iHdlExpr(o.time_delay)
w(" ")
if o.event_delay is not None:
w("@")
if len(o.event_delay) > 1:
w("(")
for is_last, e in iter_with_last(o.event_delay):
self.visit_iHdlExpr(e)
if not is_last:
w(", ")
if len(o.event_delay) > 1:
w(")")
w(" ")
self.visit_iHdlExpr(o.src)
return True
[docs] def visit_HdlStmCase(self, o):
"""
:type o: HdlStmCase
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
w = self.out.write
if o.uniq_constrain is not None:
w(o.uniq_constrain.name.lower())
w(" ")
w(o.type.name.lower())
w("(")
self.visit_iHdlExpr(o.switch_on)
w(")\n")
with Indent(self.out):
cases = o.cases
for k, stms in cases:
self.visit_iHdlExpr(k)
w(":")
need_semi = self.visit_iHdlStatement_in_statement(stms)
if need_semi:
w(";\n")
else:
w("\n")
defal = o.default
if defal is not None:
w("default:")
need_semi = self.visit_iHdlStatement_in_statement(defal)
if need_semi:
w(";\n")
else:
w("\n")
w("endcase")
return False
[docs] def visit_HdlStmWait(self, o):
"""
:type o: HdlStmWait
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
w = self.out.write
w("#")
assert len(o.val) == 1, o.val
self.visit_iHdlExpr(o.val[0])
return True
[docs] def visit_HdlStmFor(self, o):
"""
:type o: HdlStmFor
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
w = self.out.write
if o.in_preproc:
w("generate ")
w("for (")
if isinstance(o.init, HdlStmBlock):
init_stms = o.init.body
else:
init_stms = [o.init, ]
trnt = self._type_requires_nettype
in_in_loop_spec = self.is_in_loop_spec
try:
self._type_requires_nettype = False
self.is_in_loop_spec = True
for is_last, stm in iter_with_last(init_stms):
self.visit_iHdlStatement(stm)
if not is_last:
w(", ")
finally:
self.is_in_loop_spec = in_in_loop_spec
self._type_requires_nettype = trnt
w("; ")
self.visit_iHdlExpr(o.cond)
w("; ")
if isinstance(o.step, HdlStmBlock):
step_stms = o.step.body
else:
step_stms = [o.step, ]
for is_last, stm in iter_with_last(step_stms):
self.visit_iHdlStatement(stm)
if not is_last:
w(", ")
w(")")
need_semi = self.visit_iHdlStatement_in_statement(o.body)
if o.in_preproc:
if need_semi:
w(";\n")
else:
w("\n")
w("endgenerate")
return False
else:
return need_semi
[docs] def visit_HdlStmForIn(self, o):
"""
:type o: HdlStmForIn
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
raise NotImplementedError()
[docs] def visit_HdlStmWhile(self, o):
"""
:type o: HdlStmWhile
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
w = self.out.write
w("while (")
self.visit_iHdlExpr(o.cond)
w(") ")
return self.visit_iHdlStatement(o.body)
[docs] def visit_HdlStmRepeat(self, o):
"""
:type o: HdlStmRepeat
:return: True if requires ;\\n after end
"""
self.visit_doc(o)
w = self.out.write
w("repeat (")
self.visit_iHdlExpr(o.n)
w(") ")
return self.visit_iHdlStatement(o.body)
[docs] def visit_HdlStmReturn(self, o):
"""
:type o: HdlStmReturn
"""
self.visit_doc(o)
w = self.out.write
w("return")
if o.val is not None:
w(" ")
self.visit_iHdlExpr(o.val)
return True
[docs] def visit_HdlStmContinue(self, o):
"""
:type o: HdlStmContinue
"""
self.visit_doc(o)
self.out.write("continue")
return True
[docs] def visit_HdlStmBreak(self, o):
"""
:type o: HdlStmBreak
"""
self.visit_doc(o)
self.out.write("break")
return True
[docs] def visit_HdlStmThrow(self, o):
"""
:type o: HdlStmThrow
"""
raise ValueError("SystemVerilog does not have exceptions")
# [TODO] SV only
[docs] def visit_HdlImport(self, o):
"""
:type o: HdlImport
"""
self.visit_doc(o)
w = self.out.write
w("import ")
package, name = o.path
self.visit_iHdlExpr(package)
w("::")
self.visit_iHdlExpr(name)
return True