Source code for hdlConvertorAst.to.verilog.stm

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