Example #1
0
class ToVerilog():
    """
    Convert hdlObject AST back to Verilog 2002
    """
    INDENT_STEP = "    "
    DIR2V = {
        HdlDirection.IN: "input",
        HdlDirection.OUT: "output",
        HdlDirection.INOUT: "inout",
    }

    GENERIC_BIN_OPS = {
        HdlBuildinFn.AND: "&",
        HdlBuildinFn.LOG_AND: "&&",
        HdlBuildinFn.OR: "|",
        HdlBuildinFn.LOG_OR: "||",
        HdlBuildinFn.SUB: "-",
        HdlBuildinFn.ADD: "+",
        HdlBuildinFn.MUL: "*",
        HdlBuildinFn.DIV: "/",
        HdlBuildinFn.MOD: "%",
        HdlBuildinFn.NAND: "~&",
        HdlBuildinFn.NOR: "~|",
        HdlBuildinFn.XOR: "^",
        HdlBuildinFn.XNOR: "~^",
        HdlBuildinFn.EQ: '==',
        HdlBuildinFn.NEQ: "!=",
        HdlBuildinFn.LT: "<",
        HdlBuildinFn.LE: "<=",
        HdlBuildinFn.GT: ">",
        HdlBuildinFn.GE: ">=",
        HdlBuildinFn.SLL: "<<",
        HdlBuildinFn.SRL: ">>",
    }

    def __init__(self, out_stream):
        self.out = AutoIndentingStream(out_stream, self.INDENT_STEP)

    def print_doc(self, obj):
        doc = obj.doc
        if doc is not None:
            doc = doc.split("\n")
            w = self.out.write
            for last, d in iter_with_last_flag(doc):
                if last and d == "":
                    break
                w("//")
                w(d)
                w("\n")

    def print_direction(self, d):
        vd = self.DIR2V[d]
        self.out.write(vd)

    def print_generic_declr(self, g):
        self.print_doc(g)
        w = self.out.write
        w("parameter ")
        is_array = self.print_type_first_part(g.type)
        w(" ")
        w(g.name)
        v = g.value
        if v:
            w(" = ")
            self.print_expr(v)

    def print_port_declr(self, p):
        """
        :type p: HdlVariableDef
        """
        w = self.out.write
        self.print_doc(p)
        self.print_direction(p.direction)
        w(" ")
        l = p.is_latched
        if l:
            w("reg ")

        t = p.type
        is_array = self.print_type_first_part(t)
        if is_array:
            raise NotImplementedError(t)

        w(p.name)

    def print_module_header(self, e):
        """
        :type e: HdlModuleDef
        """
        self.print_doc(e)
        w = self.out.write
        w("module ")
        w(e.name)
        gs = e.params
        if gs:
            w(" #(\n")
            with Indent(self.out):
                for last, g in iter_with_last_flag(gs):
                    self.print_generic_declr(g)
                    if last:
                        w("\n")
                    else:
                        w(",\n")

            w(")")
        ps = e.ports
        if ps:
            w(" (\n")
            with Indent(self.out):
                for last, p in iter_with_last_flag(ps):
                    self.print_port_declr(p)
                    if last:
                        w("\n")
                    else:
                        w(",\n")
            w(")")
        w(";\n")

    def print_expr(self, expr):
        """
        :type expr: iHdlExpr
        """
        w = self.out.write
        if isinstance(expr, HdlName):
            w(expr)
            return
        elif is_str(expr):
            w('"%s"' % expr)
            return
        elif isinstance(expr, HdlIntValue):
            if expr.bits is None:
                w(str(expr.val))
            else:
                if expr.base is None:
                    f = "{0}'h{1:x}"
                else:
                    b = expr.base
                    if b == 2:
                        base_char = 'b'
                    elif b == 8:
                        base_char = 'O'
                    elif b == 10:
                        base_char = 'd'
                    elif b == 16:
                        base_char = 'h'
                    else:
                        raise NotImplementedError(b)
                    f = "{0}'" + base_char + "{1}"
                w(f.format(expr.bits, expr.val))
            return
        elif isinstance(expr, HdlName):
            w(expr.val)
            return
        elif isinstance(expr, HdlAll):
            w("*")
            return
        elif isinstance(expr, HdlCall):
            pe = self.print_expr

            o = expr
            op = expr.fn
            symbol = self.GENERIC_BIN_OPS.get(op, None)
            if symbol is not None:
                op_cnt = len(o.ops)
                if op_cnt == 1:
                    w("(")
                    w(symbol)
                    pe(o.ops[0])
                    w(")")
                elif op_cnt == 2:
                    w("(")
                    pe(o.ops[0])
                    w(" ")
                    w(symbol)
                    w(" ")
                    pe(o.ops[1])
                    w(")")
                return
            if op == HdlBuildinFn.DOWNTO:
                pe(o.ops[0])
                w(":")
                pe(o.ops[1])
                return
            elif op == HdlBuildinFn.TO:
                pe(o.ops[1])
                w(":")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NOT:
                w("!")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.RISING:
                w("posedge ")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.FALLING:
                w("negedge ")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.CONCAT:
                w("{")
                pe(o.ops[0])
                w(", ")
                pe(o.ops[1])
                w("}")
                return
            elif op == HdlBuildinFn.INDEX:
                pe(o.ops[0])
                w("[")
                pe(o.ops[1])
                w("]")
                return
            elif op == HdlBuildinFn.REPL_CONCAT:
                w("{(")
                pe(o.ops[0])
                w("){")
                pe(o.ops[1])
                w("}}")
                return
            elif op == HdlBuildinFn.TERNARY:
                w("(")
                pe(o.ops[0])
                w(") ? (")
                o0, o1 = o.ops[1:]
                pe(o0)
                w(") : (")
                pe(o1)
                w(")")
                return
            elif op == HdlBuildinFn.CALL:
                pe(o.ops[0])
                w("(")
                for is_last, o_n in iter_with_last_flag(o.ops[1:]):
                    pe(o_n)
                    if not is_last:
                        w(", ")
                w(")")
                return
            else:
                raise NotImplementedError(op)
        elif expr is HdlAll:
            w("*")
            return
        elif expr is HdlTypeAuto:
            return

        raise NotImplementedError(expr)

    def print_type_first_part(self, t):
        """
        :type t: iHdlExpr
        :return: True if the type has also the array dimension part
        """
        w = self.out.write
        if t != WIRE:
            op = t if isinstance(t, HdlCall) else None
            if op is None:
                self.print_expr(t)
                return False

            if op and op.fn == HdlBuildinFn.CALL and op.ops[0] == WIRE:
                # 1D vector
                w("[")
                ops = op.ops[1:]
                size_expr = ops[0]
                is_signed = bool(ops[1])
                if is_signed:
                    raise NotImplementedError(op)
                self.print_expr(size_expr)
                w("] ")
            else:
                o = op.fn
                if o == HdlBuildinFn.INDEX:
                    self.print_type_first_part(op.ops[0])
                    return True
                raise NotImplementedError(op)

        return False

    def print_type_array_part(self, t):
        """
        :type t: iHdlExpr
        """
        w = self.out.write
        if isinstance(t, HdlCall) and t.fn == HdlBuildinFn.INDEX:
            self.print_type_array_part(t.ops[0])
            w("[")
            self.print_expr(t.ops[1])
            w("]")

    def print_variable(self, var):
        """
        :type var: HdlVariableDef
        """
        self.print_doc(var)
        name = var.name
        t = var.type
        l = var.is_latched
        w = self.out.write
        if l:
            w("reg ")
        else:
            w("wire ")
        is_array = self.print_type_first_part(t)
        if t != WIRE:
            w(" ")
        w(name)
        if is_array:
            w(" ")
            self.print_type_array_part(t)

    def print_process(self, proc, is_top=False):
        """
        :type proc: HdlStmProcess
        """
        sens = proc.sensitivity
        body = proc.body
        w = self.out.write
        skip_first = False
        if sens is None:
            if len(body) and isinstance(body[0], HdlStmWait):
                skip_first = True
                wait = body[0]
                if is_top:
                    w("always ")
                w("#")
                assert len(wait.val) == 1
                self.print_expr(wait.val[0])
            else:
                assert is_top
                w("initial")
        else:
            if is_top:
                w("always ")
            w("@(")
            for last, item in iter_with_last_flag(sens):
                self.print_expr(item)
                if not last:
                    w(", ")
            w(")")

        if skip_first:
            _body = body[1:]
        else:
            _body = body

        # to prevent useless newline for empty always/time waits
        if _body:
            return self.print_block(_body, True)
        else:
            return True

    def print_block(self, stms, space_before):
        """
        :type stms: List[iHdlStatement]
        :type space_before: bool
        :return: True if requires ;\n after end
        """
        w = self.out.write
        stm_cnt = len(stms)
        if stm_cnt == 0:
            w("\n")
            return True
        elif stm_cnt == 1:
            w("\n")
            with Indent(self.out):
                return self.print_statement(stms[0])

        if space_before:
            w(" ")
        w("begin\n")
        with Indent(self.out):
            for s in stms:
                need_semi = self.print_statement(s)
                if need_semi:
                    w(";\n")
                else:
                    w("\n")
        w("end")
        return False

    def print_if(self, stm):
        """
        :type stm: HdlStmIf
        """
        w = self.out.write
        c = stm.cond
        ifTrue = stm.if_true
        ifFalse = stm.if_false

        w("if (")
        self.print_expr(c)
        w(")")
        need_semi = self.print_block(ifTrue, True)

        for cond, stms in stm.elifs:
            if need_semi:
                w(";\n")
            else:
                w(" ")
            w("else if (")
            self.print_expr(cond)
            w(")")
            need_semi = self.print_block(stms, True)

        if ifFalse is not None:
            if need_semi:
                w(";\n")
            else:
                w(" ")
            w("else")
            need_semi = self.print_block(ifFalse, True)
        if need_semi:
            w(";")

    def print_assignment(self, a, is_top=False):
        """
        :type a: HdlStmAssign
        :return: True if requires ;\n after end
        """
        s = a.src
        d = a.dst
        w = self.out.write
        if is_top:
            w("assign ")
            self.print_expr(d)
            w(" = ")
        else:
            self.print_expr(d)
            if a.is_blocking:
                w(" = ")
            else:
                w(" <= ")

        if a.time_delay is not None:
            w("#")
            self.print_expr(a.time_delay)
            w(" ")
        if a.event_delay is not None:
            w("@")
            if len(a.event_delay) > 1:
                w("(")
            for is_last, e in iter_with_last_flag(a.event_delay):
                self.print_expr(e)
                if not is_last:
                    w(", ")
            if len(a.event_delay) > 1:
                w(")")
            w(" ")

        self.print_expr(s)
        return True

    def print_case(self, cstm):
        """
        :type cstm: HdlStmCase

        :return: True if requires ;\n after end
        """
        w = self.out.write
        w("case(")
        self.print_expr(cstm.switch_on)
        w(")\n")
        with Indent(self.out):
            cases = cstm.cases
            for k, stms in cases:
                self.print_expr(k)
                w(":")
                need_semi = self.print_block(stms, True)
                if need_semi:
                    w(";\n")
                else:
                    w("\n")
            defal = cstm.default
            if defal is not None:
                w("default:")
                need_semi = self.print_block(defal, True)
                if need_semi:
                    w(";\n")
                else:
                    w("\n")
        w("endcase")
        return False

    def print_wait(self, o):
        """
        :type o: HdlStmWait

        :return: True if requires ;\n after end
        """
        self.print_doc(o)
        w = self.out.write
        w("#")
        assert len(o.val) == 1
        self.print_expr(o.val[0])
        return True

    def print_for(self, o):
        """
        :type o: HdlStmFor

        :return: True if requires ;\n after end
        """
        w = self.out.write
        w("for (")
        for is_last, stm in iter_with_last_flag(o.init):
            self.print_statement(stm)
            if not is_last:
                w(", ")
        w("; ")
        self.print_expr(o.cond)
        w("; ")
        for is_last, stm in iter_with_last_flag(o.step):
            self.print_statement(stm)
            if not is_last:
                w(", ")
        w(")")
        return self.print_block(o.body, True)

    def print_for_in(self, o):
        """
        :type o: HdlStmForIn
        :return: True if requires ;\n after end
        """
        raise NotImplementedError()

    def print_while(self, o):
        """
        :type o: HdlStmWhile
        :return: True if requires ;\n after end
        """
        w = self.out.write
        w("while (")
        self.print_expr(o.cond)
        w(") ")
        return self.print_block(o.body, True)

    def print_statement(self, stm, is_top=False):
        """
        :type o: iHdlStatement
        :return: True if requires ;\n after end
        """
        # statement can be also expressin
        if isinstance(stm, iHdlStatement):
            self.print_doc(stm)

        if isinstance(stm, HdlStmProcess):
            return self.print_process(stm, is_top=is_top)
        elif isinstance(stm, HdlStmIf):
            return self.print_if(stm)
        elif isinstance(stm, HdlStmAssign):
            return self.print_assignment(stm, is_top=is_top)
        elif isinstance(stm, HdlStmCase):
            return self.print_case(stm)
        elif isinstance(stm, HdlStmWait):
            return self.print_wait(stm)
        elif isinstance(stm, HdlStmFor):
            return self.print_for(stm)
        elif isinstance(stm, HdlStmForIn):
            return self.print_for_int(stm)
        elif isinstance(stm, HdlStmWhile):
            return self.print_while(stm)
        else:
            self.print_expr(stm)
            return True

    def print_map_item(self, item):
        if isinstance(item,
                      HdlCall) and item.fn == HdlBuildinFn.MAP_ASSOCIATION:
            w = self.out.write
            # k, v pair
            k, v = item.ops
            w(".")
            self.print_expr(k)
            w("(")
            self.print_expr(v)
            w(")")
        else:
            self.print_expr(item)

    def print_map(self, map_):
        w = self.out.write
        with Indent(self.out):
            for last, m in iter_with_last_flag(map_):
                self.print_map_item(m)
                if last:
                    w("\n")
                else:
                    w(",\n")

    def print_component_instance(self, c):
        """
        :type c: HdlComponentInst
        """
        self.print_doc(c)
        w = self.out.write
        assert c.module_name
        self.print_expr(c.module_name)
        w(" ")
        self.print_expr(c.name)
        gms = c.param_map
        if gms:
            w(" #(\n")
            self.print_map(gms)
            w(")")

        pms = c.port_map
        if pms:
            w(" (\n")
            self.print_map(pms)
            w(")")

    def print_module_body(self, a):
        """
        :type a: HdlModuleDef
        """
        w = self.out.write
        with Indent(self.out):
            for o in a.objs:
                if isinstance(o, HdlVariableDef):
                    self.print_variable(o)
                    w(";\n")
                elif isinstance(o, HdlComponentInst):
                    self.print_component_instance(o)
                    w(";\n\n")
                elif isinstance(o, iHdlStatement):
                    need_semi = self.print_statement(o, is_top=True)
                    if need_semi:
                        w(";\n")
                    else:
                        w("\n\n")
                else:
                    raise NotImplementedError(o)

        self.out.write("endmodule\n")

    def print_context(self, context):
        """
        :type context: HdlContext
        """
        last = None
        for o in context.objs:
            if isinstance(o, HdlModuleDec):
                self.print_module_header(o)
            elif isinstance(o, HdlModuleDef):
                assert isinstance(last, HdlModuleDec) \
                        and o.module_name == last.name, (last, o)
                self.print_module_body(o)
            else:
                raise NotImplementedError(o)

            last = o
Example #2
0
class ToVhdl():
    """
    Convert hdlObject AST back to VHDL-1993
    """
    INDENT_STEP = "    "
    DIR2V = {
        HdlDirection.IN: "IN",
        HdlDirection.OUT: "OUT",
        HdlDirection.INOUT: "INOUT",
    }

    GENERIC_BIN_OPS = {
        HdlBuildinFn.AND: "AND",
        HdlBuildinFn.LOG_AND: "AND",
        HdlBuildinFn.OR: "OR",
        HdlBuildinFn.LOG_OR: "OR",
        HdlBuildinFn.SUB: "-",
        HdlBuildinFn.ADD: "+",
        HdlBuildinFn.MUL: "*",
        HdlBuildinFn.DIV: "/",
        HdlBuildinFn.MOD: "MOD",
        HdlBuildinFn.NAND: "NAND",
        HdlBuildinFn.NOR: "NOR",
        HdlBuildinFn.XOR: "XOR",
        HdlBuildinFn.XNOR: "XNOR",
        HdlBuildinFn.EQ: '=',
        HdlBuildinFn.NEQ: "/=",
        HdlBuildinFn.LT: "<",
        HdlBuildinFn.LE: "<=",
        HdlBuildinFn.GT: ">",
        HdlBuildinFn.GE: ">=",
        HdlBuildinFn.SLL: "SLL",
        HdlBuildinFn.SRL: "SRL",
        HdlBuildinFn.TO: "TO",
        HdlBuildinFn.DOWNTO: "DOWNTO",
    }

    def __init__(self, out_stream):
        self.out = AutoIndentingStream(out_stream, self.INDENT_STEP)
        self.used_libraries = set()

    def print_doc(self, obj):
        doc = obj.doc
        if doc is not None:
            doc = doc.split("\n")
            w = self.out.write
            for last, d in iter_with_last_flag(doc):
                if last and d == "":
                    break
                w("--")
                w(d)
                w("\n")

    def print_direction(self, d):
        vd = self.DIR2V[d]
        self.out.write(vd)

    def print_generic_or_port_declr(self, o):
        """
        :type p: HdlVariableDef
        """
        self.print_doc(o)
        w = self.out.write
        w(o.name)
        w(" : ")
        d = o.direction
        if d != HdlDirection.INTERNAL:
            self.print_direction(d)
            w(" ")
        self.print_type(o.type)
        v = o.value
        if v:
            w(" := ")
            self.print_expr(v)

    def print_module_header(self, e):
        self.print_doc(e)
        w = self.out.write
        w("ENTITY ")
        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_flag(gs):
                        self.print_generic_or_port_declr(g)
                        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_flag(ps):
                        self.print_generic_or_port_declr(p)
                        if last:
                            w("\n")
                        else:
                            w(",\n")
                w(");\n")
        w("END ENTITY;\n")

    def print_expr(self, expr):
        w = self.out.write
        if isinstance(expr, HdlName):
            w(expr)
            return
        elif isinstance(expr, str):
            w('"%s"' % expr)
            return
        elif isinstance(expr, HdlIntValue):
            v = expr.val
            bits = expr.bits
            if bits is None:
                w(str(v))
            elif bits % 8 == 0:
                f = '"{0:0%dX}"' % (bits % 8)
                w(f % v)
            else:
                f = '"{0:0%db}"' % (bits)
                w(f % v)

            return
        elif isinstance(expr, HdlName):
            w(v)
            return
        elif isinstance(expr, HdlAll):
            w("*")
            return
        elif isinstance(expr, HdlCall):
            pe = self.print_expr

            o = expr
            op = expr.fn
            symbol = self.GENERIC_BIN_OPS.get(op, None)
            if symbol is not None:
                w("(")
                pe(o.ops[0])
                w(" ")
                w(symbol)
                w(" ")
                pe(o.ops[1])
                w(")")
                return
            elif op == HdlBuildinFn.NOT:
                w("!")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.RISING:
                w("RISIG_EDGE(")
                pe(o.ops[0])
                w(")")
                return
            elif op == HdlBuildinFn.FALLING:
                w("FALLING_EDGE(")
                pe(o.ops[0])
                w(")")
                return
            elif op == HdlBuildinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.CONCAT:
                w("{")
                pe(o.ops[0])
                w(", ")
                pe(o.ops[1])
                w("}")
                return
            elif op == HdlBuildinFn.INDEX:
                pe(o.ops[0])
                w("(")
                pe(o.ops[1])
                w(")")
                return
            elif op == HdlBuildinFn.DOT:
                pe(o.ops[0])
                w(".")
                pe(o.ops[1])
                return
            elif op == HdlBuildinFn.TERNARY:
                pe(o.ops[0])
                w(" ? ")
                o0, o1 = o.ops[1:]
                pe(o0)
                w(" : ")
                pe(o1)
                return
            else:
                raise NotImplementedError(op)
        elif expr is HdlAll:
            w("ALL")
            return

        raise NotImplementedError(expr)

    def print_type(self, t):
        """
        """
        self.print_expr(t)

    def print_variable(self, var):
        self.print_doc(var)
        name = var.name
        t = var.type
        l = var.latched
        w = self.out.write
        if l:
            w("reg ")
        else:
            w("wire ")
        is_array = self.print_type_first_part(t)
        w(name)
        if is_array:
            w(" ")
            self.print_type_array_part(t)

    def print_process(self, proc):
        sens = proc.sensitivity
        body = proc.body
        w = self.out.write

        w("PROCESS(")
        for last, item in iter_with_last_flag(sens):
            self.print_expr(item)
            if not last:
                w(", ")
        w(")\n")
        w("BEGIN\n")
        with Indent(self.out):
            for stm in body:
                self.print_statement(stm)

        w("END PROCESS;\n")

    def print_block(self, stms):
        """
        :return: True if statements are wrapped in begin-end block
        """
        w = self.out.write
        if len(stms) != 1:
            w(" BEGIN\n")
        else:
            w("\n")

        with Indent(self.out):
            for s in stms:
                self.print_statement(s)

        if len(stms) != 1:
            w("END")
            return True
        return False

    def print_if(self, stm):
        w = self.out.write
        c = stm.cond
        ifTrue = stm.if_true
        ifFalse = stm.if_false

        w("IF ")
        self.print_expr(c)
        w(" ")
        need_space = self.print_block(ifTrue)

        for cond, stms in stm.elifs:
            if need_space:
                w(" ")
            w("ELSE IF ")
            self.print_expr(cond)
            w(" ")
            need_space = self.print_block(stms)

        if ifFalse is not None:
            if need_space:
                w(" ")
            w("ELSE")
            self.print_block(ifFalse)
        if need_space:
            w("\n")

    def print_assignment(self, a):
        s = a.src
        d = a.dst
        w = self.out.write
        self.print_expr(d)
        w(" <= ")
        self.print_expr(s)
        w(";\n")

    def print_case(self, cstm):
        w = self.out.write
        w("CASE ")
        self.print_expr(cstm.switch_on)
        w(" IS\n")
        with Indent(self.out):
            cases = cstm.cases
            for k, stms in cases:
                w("WHEN ")
                self.print_expr(k)
                w(" => ")
                is_block = self.print_block(stms)
                if is_block:
                    w("\n")
            defal = cstm.default
            if defal is not None:
                is_block = w("WHEN OTHERS => ")
                self.print_block(defal)
                if is_block:
                    w("\n")
        w("END CASE;\n")

    def print_statement(self, stm):
        self.print_doc(stm)
        if isinstance(stm, HdlProcessStm):
            self.print_process(stm)
        elif isinstance(stm, HdlIfStm):
            self.print_if(stm)
        elif isinstance(stm, HdlAssignStm):
            self.print_assignment(stm)
        elif isinstance(stm, HdlCaseStm):
            self.print_case(stm)
        else:
            raise NotImplementedError(stm)

    def print_map_item(self, item):
        if isinstance(item,
                      HdlCall) and item.fn == HdlBuildinFn.MAP_ASSOCIATION:
            w = self.out.write
            # k, v pair
            k, v = item.ops
            w(".")
            self.print_expr(k)
            w("(")
            self.print_expr(v)
            w(")")
        else:
            self.print_expr(item)

    def print_map(self, map_):
        w = self.out.write
        with Indent(self.out):
            for last, m in iter_with_last_flag(map_):
                self.print_map_item(m)
                if last:
                    w("\n")
                else:
                    w(",\n")

    def print_component_instance(self, c):
        """
        :type c: HdlComponentInst
        """
        self.print_doc(c)
        w = self.out.write
        self.print_expr(c.module_name)
        w(" ")
        self.print_expr(c.name)
        gms = c.param_map
        if gms:
            w(" #(\n")
            self.print_map(gms)
            w(")")

        pms = c.port_map
        if pms:
            w(" (\n")
            self.print_map(pms)
            w(")")
        w(";")

    def print_module_body(self, a):
        """
        :type a: HdlModuleDef
        """
        w = self.out.write
        w("ARCHITECTURE ")
        w(a.name)
        w(" OF ")
        w(a.module_name)
        w(" IS\n")
        w("BEGIN\n")
        with Indent(self.out):
            for o in a.objs:
                if isinstance(o, HdlVariableDef):
                    self.print_variable(o)
                    w(";\n")
                elif isinstance(o, HdlComponentInst):
                    self.print_component_instance(o)
                    w("\n")
                elif isinstance(o, iHdlStatement):
                    self.print_statement(o)
                else:
                    raise NotImplementedError()

        self.out.write("END ARCHITECTURE\n")

    def print_library(self, o):
        w = self.out.write
        w("LIBRARY ")
        self.print_expr(o)
        w(";\n")

    def print_hdl_import(self, o):
        """
        :type o: HdlImport
        """
        self.print_doc(o)
        w = self.out.write
        lib_name = o.path[0]
        if lib_name not in self.used_libraries:
            self.print_library(lib_name)

        w("USE ")
        for last, p in iter_with_last_flag(o.path):
            self.print_expr(p)
            if not last:
                w(".")
        w(";\n")

    def print_context(self, context):
        """
        :type context: HdlContext
        """

        w = self.out.write
        for o in context.objs:
            if isinstance(o, HdlModuleDec):
                w("\n")
                self.print_module_header(o)
                w("\n")
            elif isinstance(o, HdlModuleDef):
                self.print_module_body(o)
            elif isinstance(o, HdlImport):
                self.print_hdl_import(o)
            else:
                raise NotImplementedError(o)
Example #3
0
class ToVerilog():
    """
    Convert hdlObject AST back to Verilog 2002
    """
    INDENT_STEP = "    "
    DIR2V = {
        HdlDirection.IN: "input",
        HdlDirection.OUT: "output",
        HdlDirection.INOUT: "inout",
    }

    GENERIC_BIN_OPS = {
        HdlBuiltinFn.AND: "&",
        HdlBuiltinFn.LOG_AND: "&&",
        HdlBuiltinFn.OR: "|",
        HdlBuiltinFn.LOG_OR: "||",
        HdlBuiltinFn.SUB: "-",
        HdlBuiltinFn.ADD: "+",
        HdlBuiltinFn.MUL: "*",
        HdlBuiltinFn.DIV: "/",
        HdlBuiltinFn.MOD: "%",
        HdlBuiltinFn.NAND: "~&",
        HdlBuiltinFn.NOR: "~|",
        HdlBuiltinFn.XOR: "^",
        HdlBuiltinFn.XNOR: "~^",
        HdlBuiltinFn.EQ: '==',
        HdlBuiltinFn.NEQ: "!=",
        HdlBuiltinFn.LT: "<",
        HdlBuiltinFn.LE: "<=",
        HdlBuiltinFn.GT: ">",
        HdlBuiltinFn.GE: ">=",
        HdlBuiltinFn.SLL: "<<",
        HdlBuiltinFn.SRL: ">>",
    }
    ASSIGN_OPS = {
        HdlBuiltinFn.ASSIGN: '=',
        HdlBuiltinFn.PLUS_ASSIGN: '+=',
        HdlBuiltinFn.MINUS_ASSIGN: '-=',
        HdlBuiltinFn.MUL_ASSIGN: '*=',
        HdlBuiltinFn.DIV_ASSIGN: '/=',
        HdlBuiltinFn.MOD_ASSIGN: '%=',
        HdlBuiltinFn.AND_ASSIGN: '&=',
        HdlBuiltinFn.OR_ASSIGN: '|=',
        HdlBuiltinFn.XOR_ASSIGN: '^=',
        HdlBuiltinFn.SHIFT_LEFT_ASSIGN: '<<=',
        HdlBuiltinFn.SHIFT_RIGHT_ASSIGN: '>>=',
        HdlBuiltinFn.ARITH_SHIFT_LEFT_ASSIGN: '<<<=',
        HdlBuiltinFn.ARITH_SHIFT_RIGHT_ASSIGN: '>>>=',
    }

    def __init__(self, out_stream):
        self.out = AutoIndentingStream(out_stream, self.INDENT_STEP)

    def print_doc(self, obj):
        doc = obj.doc
        if doc is not None:
            doc = doc.split("\n")
            w = self.out.write
            for last, d in iter_with_last_flag(doc):
                if last and d == "":
                    break
                w("//")
                w(d)
                w("\n")

    def print_direction(self, d):
        vd = self.DIR2V[d]
        self.out.write(vd)

    def print_generic_declr(self, g):
        self.print_doc(g)
        w = self.out.write
        w("parameter ")
        is_array = self.print_type_first_part(g.type)
        if g.type is not HdlTypeAuto:
            w(" ")
        w(g.name)
        v = g.value
        if is_array:
            self.print_type_array_part(g.type)
        if v:
            w(" = ")
            self.print_expr(v)

    def print_port_declr(self, p):
        """
        :type p: HdlVariableDef
        """
        w = self.out.write
        self.print_doc(p)
        self.print_direction(p.direction)
        w(" ")

        t = p.type
        is_array = self.print_type_first_part(t)
        w(" ")

        w(p.name)
        if is_array:
            self.print_type_array_part(t)

    def print_module_header(self, e):
        """
        :type e: HdlModuleDef
        """
        self.print_doc(e)
        w = self.out.write
        w("module ")
        w(e.name)
        gs = e.params
        if gs:
            w(" #(\n")
            with Indent(self.out):
                for last, g in iter_with_last_flag(gs):
                    self.print_generic_declr(g)
                    if last:
                        w("\n")
                    else:
                        w(",\n")

            w(")")
        ps = e.ports
        if ps:
            w(" (\n")
            with Indent(self.out):
                for last, p in iter_with_last_flag(ps):
                    self.print_port_declr(p)
                    if last:
                        w("\n")
                    else:
                        w(",\n")
            w(")")
        w(";\n")

    def print_expr(self, expr):
        """
        :type expr: iHdlExpr
        """
        w = self.out.write
        if isinstance(expr, HdlName):
            w(expr)
            return
        elif is_str(expr):
            w('"%s"' % expr)
            return
        elif isinstance(expr, HdlIntValue):
            if expr.bits is None:
                w(str(expr.val))
            else:
                if expr.base is None:
                    f = "{0}'h{1:x}"
                else:
                    b = expr.base
                    if b == 2:
                        base_char = 'b'
                    elif b == 8:
                        base_char = 'O'
                    elif b == 10:
                        base_char = 'd'
                    elif b == 16:
                        base_char = 'h'
                    else:
                        raise NotImplementedError(b)
                    f = "{0}'" + base_char + "{1}"
                w(f.format(expr.bits, expr.val))
            return
        elif isinstance(expr, HdlName):
            w(expr.val)
            return
        elif isinstance(expr, HdlAll):
            w("*")
            return
        elif isinstance(expr, HdlCall):
            pe = self.print_expr

            o = expr
            op = expr.fn
            symbol = self.GENERIC_BIN_OPS.get(op, None)
            if symbol is not None:
                op_cnt = len(o.ops)
                if op_cnt == 1:
                    w("(")
                    w(symbol)
                    pe(o.ops[0])
                    w(")")
                elif op_cnt == 2:
                    w("(")
                    pe(o.ops[0])
                    w(" ")
                    w(symbol)
                    w(" ")
                    pe(o.ops[1])
                    w(")")
                return
            symbol = self.ASSIGN_OPS.get(op, None)
            if symbol is not None:
                pe(o.ops[0])
                w(" ")
                w(symbol)
                w(" ")
                pe(o.ops[1])
                return
            if op == HdlBuiltinFn.DOWNTO:
                pe(o.ops[0])
                w(":")
                pe(o.ops[1])
                return
            elif op == HdlBuiltinFn.TO:
                pe(o.ops[1])
                w(":")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.NOT:
                w("!")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.RISING:
                w("posedge ")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.FALLING:
                w("negedge ")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.CONCAT:
                w("{")
                pe(o.ops[0])
                w(", ")
                pe(o.ops[1])
                w("}")
                return
            elif op == HdlBuiltinFn.INDEX:
                pe(o.ops[0])
                w("[")
                pe(o.ops[1])
                w("]")
                return
            elif op == HdlBuiltinFn.REPL_CONCAT:
                w("{(")
                pe(o.ops[0])
                w("){")
                pe(o.ops[1])
                w("}}")
                return
            elif op == HdlBuiltinFn.TERNARY:
                w("(")
                pe(o.ops[0])
                w(") ? (")
                o0, o1 = o.ops[1:]
                pe(o0)
                w(") : (")
                pe(o1)
                w(")")
                return
            elif op == HdlBuiltinFn.CALL:
                pe(o.ops[0])
                w("(")
                for is_last, o_n in iter_with_last_flag(o.ops[1:]):
                    pe(o_n)
                    if not is_last:
                        w(", ")
                w(")")
                return
            elif op == HdlBuiltinFn.TYPE_OF:
                w("type(")
                pe(o.ops[0])
                w(")")
                return
            else:
                raise NotImplementedError(op)
        elif expr is HdlAll:
            w("*")
            return
        elif expr is HdlTypeAuto:
            return
        elif expr is None:
            w("null")
            return

        raise NotImplementedError(expr)

    def print_type_first_part(self, t):
        """
        :type t: iHdlExpr
        :return: True if the type has also the array dimension part
        """
        w = self.out.write
        t, array_dims = collect_array_dims(t)
        wire_params = get_wire_t_params(t)
        if wire_params is None:
            if t != HdlTypeAuto:
                if isinstance(t, HdlCall) and t.fn == HdlBuiltinFn.TYPE_OF:
                    w("var ")
                self.print_expr(t)
        else:
            base_t, width, is_signed, _ = wire_params
            w(base_t)
            if width is not None:
                # 1D vector
                w("[")
                if is_signed:
                    raise NotImplementedError(t)
                self.print_expr(width)
                w("]")
        return len(array_dims) > 0

    def print_type_array_part(self, t):
        """
        :type t: iHdlExpr
        """
        w = self.out.write
        _, array_dim = collect_array_dims(t)
        for ad in array_dim:
            w("[")
            self.print_expr(ad)
            w("]")

    def print_variable(self, var):
        """
        :type var: HdlVariableDef
        """
        self.print_doc(var)
        name = var.name
        t = var.type
        w = self.out.write
        if var.is_const:
            w("localparam ")
        is_array = self.print_type_first_part(t)
        w(" ")
        w(name)
        if is_array:
            self.print_type_array_part(t)

    def print_process(self, proc, is_top=False):
        """
        :type proc: HdlStmProcess
        """
        sens = proc.sensitivity
        body = proc.body
        w = self.out.write
        skip_body = False
        if sens is None:
            if isinstance(body, HdlStmWait):
                skip_body = True
                wait = body
            elif (isinstance(body, HdlStmBlock) and body.body
                  and isinstance(body.body[0], HdlStmWait)):
                wait = body.body[0]
                body = copy(body)
                body.body = body.body[1:]
            else:
                wait = None

            if wait is not None:
                if is_top:
                    w("always ")
                w("#")
                assert len(wait.val) == 1
                self.print_expr(wait.val[0])
            else:
                assert is_top
                w("initial")
        else:
            if is_top:
                w("always ")
            w("@(")
            for last, item in iter_with_last_flag(sens):
                self.print_expr(item)
                if not last:
                    w(", ")
            w(")")

        # to prevent useless newline for empty always/time waits
        if skip_body:
            return True
        else:
            return self.print_statement_in_statement(body)

    def print_statement_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:
                stm = stm.body[0]
            else:
                w(" ")
                return self.print_block(stm)

        w("\n")
        with Indent(self.out):
            return self.print_statement(stm)

    def print_block(self, stm):
        """
        :type stm: HdlStmBlock
        """
        w = self.out.write

        w("begin\n")
        with Indent(self.out):
            for s in stm.body:
                need_semi = self.print_statement(s)
                if need_semi:
                    w(";\n")
                else:
                    w("\n")
        w("end")
        return False

    def print_if(self, stm):
        """
        :type stm: HdlStmIf
        """
        w = self.out.write
        c = stm.cond
        ifTrue = stm.if_true
        ifFalse = stm.if_false

        w("if (")
        self.print_expr(c)
        w(")")
        need_semi = self.print_statement_in_statement(ifTrue)

        for cond, stms in stm.elifs:
            if need_semi:
                w(";\n")
            else:
                w(" ")
            w("else if (")
            self.print_expr(cond)
            w(")")
            need_semi = self.print_statement_in_statement(stms)

        if ifFalse is not None:
            if need_semi:
                w(";\n")
            else:
                w(" ")
            w("else")
            need_semi = self.print_statement_in_statement(ifFalse)
        if need_semi:
            w(";")

    def print_assignment(self, a, is_top=False):
        """
        :type a: HdlStmAssign
        :return: True if requires ;\n after end
        """
        s = a.src
        d = a.dst
        w = self.out.write
        if is_top:
            w("assign ")
            self.print_expr(d)
            w(" = ")
        else:
            self.print_expr(d)
            if a.is_blocking:
                w(" = ")
            else:
                w(" <= ")

        if a.time_delay is not None:
            w("#")
            self.print_expr(a.time_delay)
            w(" ")
        if a.event_delay is not None:
            w("@")
            if len(a.event_delay) > 1:
                w("(")
            for is_last, e in iter_with_last_flag(a.event_delay):
                self.print_expr(e)
                if not is_last:
                    w(", ")
            if len(a.event_delay) > 1:
                w(")")
            w(" ")

        self.print_expr(s)
        return True

    def print_case(self, cstm):
        """
        :type cstm: HdlStmCase

        :return: True if requires ;\n after end
        """
        w = self.out.write
        w("case(")
        self.print_expr(cstm.switch_on)
        w(")\n")
        with Indent(self.out):
            cases = cstm.cases
            for k, stms in cases:
                self.print_expr(k)
                w(":")
                need_semi = self.print_statement_in_statement(stms)
                if need_semi:
                    w(";\n")
                else:
                    w("\n")
            defal = cstm.default
            if defal is not None:
                w("default:")
                need_semi = self.print_statement_in_statement(defal)
                if need_semi:
                    w(";\n")
                else:
                    w("\n")
        w("endcase")
        return False

    def print_wait(self, o):
        """
        :type o: HdlStmWait

        :return: True if requires ;\n after end
        """
        self.print_doc(o)
        w = self.out.write
        w("#")
        assert len(o.val) == 1
        self.print_expr(o.val[0])
        return True

    def print_for(self, o):
        """
        :type o: HdlStmFor

        :return: True if requires ;\n after end
        """
        w = self.out.write
        w("for (")
        if isinstance(o.init, HdlStmBlock):
            init_stms = o.init.body
        else:
            init_stms = [
                o.init,
            ]

        for is_last, stm in iter_with_last_flag(init_stms):
            self.print_statement(stm)
            if not is_last:
                w(", ")
        w("; ")
        self.print_expr(o.cond)
        w("; ")
        if isinstance(o.init, HdlStmBlock):
            step_stms = o.step.body
        else:
            step_stms = [
                o.step,
            ]

        for is_last, stm in iter_with_last_flag(step_stms):
            self.print_statement(stm)
            if not is_last:
                w(", ")
        w(")")
        return self.print_statement_in_statement(o.body)

    def print_for_in(self, o):
        """
        :type o: HdlStmForIn
        :return: True if requires ;\n after end
        """
        raise NotImplementedError()

    def print_while(self, o):
        """
        :type o: HdlStmWhile
        :return: True if requires ;\n after end
        """
        w = self.out.write
        w("while (")
        self.print_expr(o.cond)
        w(") ")
        return self.print_block(o.body, True)

    def print_statement(self, stm, is_top=False):
        """
        :type o: iHdlStatement
        :return: True if requires ;\n after end
        """
        # statement can be also expressin
        if isinstance(stm, iHdlStatement):
            self.print_doc(stm)

        if isinstance(stm, HdlStmProcess):
            return self.print_process(stm, is_top=is_top)
        elif isinstance(stm, HdlStmIf):
            return self.print_if(stm)
        elif isinstance(stm, HdlStmAssign):
            return self.print_assignment(stm, is_top=is_top)
        elif isinstance(stm, HdlStmCase):
            return self.print_case(stm)
        elif isinstance(stm, HdlStmWait):
            return self.print_wait(stm)
        elif isinstance(stm, HdlStmFor):
            return self.print_for(stm)
        elif isinstance(stm, HdlStmForIn):
            return self.print_for_int(stm)
        elif isinstance(stm, HdlStmWhile):
            return self.print_while(stm)
        elif isinstance(stm, HdlStmBlock):
            return self.print_block(stm)
        else:
            self.print_expr(stm)
            return True

    def print_map_item(self, item):
        if isinstance(item, HdlCall)\
                and item.fn == HdlBuiltinFn.MAP_ASSOCIATION:
            w = self.out.write
            # k, v pair
            k, v = item.ops
            w(".")
            self.print_expr(k)
            w("(")
            self.print_expr(v)
            w(")")
        else:
            self.print_expr(item)

    def print_map(self, map_):
        w = self.out.write
        with Indent(self.out):
            for last, m in iter_with_last_flag(map_):
                self.print_map_item(m)
                if last:
                    w("\n")
                else:
                    w(",\n")

    def print_component_instance(self, c):
        """
        :type c: HdlComponentInst
        """
        self.print_doc(c)
        w = self.out.write
        assert c.module_name
        self.print_expr(c.module_name)
        w(" ")
        self.print_expr(c.name)
        gms = c.param_map
        if gms:
            w(" #(\n")
            self.print_map(gms)
            w(")")

        pms = c.port_map
        if pms:
            w(" (\n")
            self.print_map(pms)
            w(")")

    def print_function_def(self, o):
        """
        :type o: HdlFunctionDef
        """
        self.print_doc(o)
        w = self.out.write
        if o.is_task:
            w("task ")
        else:
            w("function ")
        if not o.is_static:
            w("automatic ")

        if not o.is_task:
            self.print_type_first_part(o.return_t)
            self.print_type_array_part(o.return_t)

        if o.is_virtual or o.is_operator:
            raise NotImplementedError(o)
        w(" ")
        w(o.name)
        ps = o.params
        if ps:
            w(" (\n")
            with Indent(self.out):
                for last, p in iter_with_last_flag(ps):
                    self.print_port_declr(p)
                    if last:
                        w("\n")
                    else:
                        w(",\n")
            w(")")
        w(";\n")
        with Indent(self.out):
            for s in o.body:
                if isinstance(s, HdlVariableDef):
                    self.print_variable(s)
                    w(";\n")
                elif isinstance(s, iHdlStatement):
                    need_semi = self.print_statement(s)
                    if need_semi:
                        w(";\n")
                    else:
                        w("\n")
                else:
                    self.print_expr(s)
                    w(";\n")

        if o.is_task:
            w("endtask")
        else:
            w("endfunction")

    def print_module_body(self, a):
        """
        :type a: HdlModuleDef
        """
        w = self.out.write
        with Indent(self.out):
            for o in a.objs:
                if isinstance(o, HdlVariableDef):
                    self.print_variable(o)
                    w(";\n")
                elif isinstance(o, HdlComponentInst):
                    self.print_component_instance(o)
                    w(";\n\n")
                elif isinstance(o, iHdlStatement):
                    need_semi = self.print_statement(o, is_top=True)
                    if need_semi:
                        w(";\n")
                    else:
                        w("\n\n")
                elif isinstance(o, HdlFunctionDef):
                    self.print_function_def(o)
                    w("\n")
                else:
                    raise NotImplementedError(o)

        self.out.write("endmodule\n")

    def print_context(self, context):
        """
        :type context: HdlContext
        """
        last = None
        for o in context.objs:
            if isinstance(o, HdlModuleDec):
                self.print_module_header(o)
            elif isinstance(o, HdlModuleDef):
                assert isinstance(last, HdlModuleDec) \
                        and o.module_name == last.name, (last, o)
                self.print_module_body(o)
            else:
                raise NotImplementedError(o)

            last = o
Example #4
0
class ToVhdl():
    """
    Convert hdlObject AST back to VHDL-1993
    """
    INDENT_STEP = "    "
    DIR2V = {
        HdlDirection.IN: "IN",
        HdlDirection.OUT: "OUT",
        HdlDirection.INOUT: "INOUT",
    }

    GENERIC_BIN_OPS = {
        HdlBuiltinFn.AND: "AND",
        HdlBuiltinFn.LOG_AND: "AND",
        HdlBuiltinFn.OR: "OR",
        HdlBuiltinFn.LOG_OR: "OR",
        HdlBuiltinFn.SUB: "-",
        HdlBuiltinFn.ADD: "+",
        HdlBuiltinFn.MUL: "*",
        HdlBuiltinFn.DIV: "/",
        HdlBuiltinFn.MOD: "MOD",
        HdlBuiltinFn.NAND: "NAND",
        HdlBuiltinFn.NOR: "NOR",
        HdlBuiltinFn.XOR: "XOR",
        HdlBuiltinFn.XNOR: "XNOR",
        HdlBuiltinFn.EQ: '=',
        HdlBuiltinFn.NEQ: "/=",
        HdlBuiltinFn.LT: "<",
        HdlBuiltinFn.LE: "<=",
        HdlBuiltinFn.GT: ">",
        HdlBuiltinFn.GE: ">=",
        HdlBuiltinFn.SLL: "SLL",
        HdlBuiltinFn.SRL: "SRL",
        HdlBuiltinFn.TO: "TO",
        HdlBuiltinFn.DOWNTO: "DOWNTO",
        HdlBuiltinFn.ARROW: "=>",
        HdlBuiltinFn.MAP_ASSOCIATION: "=>",
    }

    def __init__(self, out_stream):
        self.out = AutoIndentingStream(out_stream, self.INDENT_STEP)
        self.used_libraries = set()

    def print_doc(self, obj):
        doc = obj.doc
        if doc is not None:
            doc = doc.split("\n")
            w = self.out.write
            for last, d in iter_with_last_flag(doc):
                if last and d == "":
                    break
                w("--")
                w(d)
                w("\n")

    def print_direction(self, d):
        vd = self.DIR2V[d]
        self.out.write(vd)

    def print_generic_or_port_declr(self, o):
        """
        :type p: HdlVariableDef
        """
        self.print_doc(o)
        w = self.out.write
        w(o.name)
        w(" : ")
        d = o.direction
        if d != HdlDirection.INTERNAL:
            self.print_direction(d)
            w(" ")
        self.print_type(o.type)
        v = o.value
        if v:
            w(" := ")
            self.print_expr(v)

    def print_module_header(self, e, vhdl_obj_name="ENTITY"):
        """
        :param e: Entity
        :type e: HdlModuleDec
        """
        self.print_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_flag(gs):
                        self.print_generic_or_port_declr(g)
                        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_flag(ps):
                        self.print_generic_or_port_declr(p)
                        if last:
                            w("\n")
                        else:
                            w(",\n")
                w(");\n")
        w("END ")
        w(vhdl_obj_name)
        w(";\n")

    def print_component(self, o):
        """
        :type o: HdlModuleDec
        """
        self.print_module_header(o, vhdl_obj_name="COMPONENT")

    def print_assert(self, args):
        """
        :type args: List[iHdlExpr]
        """
        w = self.out.write
        w("ASSERT ")
        for is_last, (prefix, a) in iter_with_last_flag(
                zip(("", "REPORT ", "SEVERITY "), args)):
            w(prefix)
            self.print_expr(a)
            if not is_last:
                w(" ")

    def print_report(self, args):
        """
        :type args: List[iHdlExpr]
        """
        w = self.out.write
        w("REPORT ")
        for is_last, (prefix, a) in iter_with_last_flag(
                zip(("", "SEVERITY "), args)):
            w(prefix)
            self.print_expr(a)
            if not is_last:
                w(" ")

    def print_expr(self, expr):
        w = self.out.write
        if isinstance(expr, HdlName):
            w(expr)
            return
        elif is_str(expr):
            w('"%s"' % expr)
            return
        elif isinstance(expr, HdlIntValue):
            v = expr.val
            bits = expr.bits
            if bits is None:
                if expr.base is not None:
                    if expr.base == 256:
                        w("'%s'" % str(v))
                        return
                    bases = {
                        2: "B",
                        8: "O",
                        16: "X",
                    }
                    b = bases[expr.base]
                    w('%s"%"' % (b, v))
                w(str(v))
                return

            elif bits % 8 == 0:
                f = 'X"{0:0%dX}"' % (bits / 8)
            else:
                f = '"{0:0%db}"' % (bits)
            w(f.format(v))

            return
        elif expr is HdlAll:  # one previous line had 'elif isinstance(expr, HdlAll)'
            w("ALL")
            return
        elif expr is HdlOthers:
            w("OTHERS")
            return
        elif isinstance(expr, HdlCall):
            pe = self.print_expr
            fn = expr.ops[0]
            if fn == HdlName("assert"):
                self.print_assert(expr.ops[1:])
                return
            elif fn == HdlName("report"):
                self.print_report(expr.ops[1:])
                return

            o = expr
            op = expr.fn
            symbol = self.GENERIC_BIN_OPS.get(op, None)
            if symbol is not None:
                w("(")
                pe(o.ops[0])
                w(" ")
                w(symbol)
                w(" ")
                pe(o.ops[1])
                w(")")
                return
            elif op == HdlBuiltinFn.NOT:
                w("!")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.RISING:
                w("RISIG_EDGE(")
                pe(o.ops[0])
                w(")")
                return
            elif op == HdlBuiltinFn.FALLING:
                w("FALLING_EDGE(")
                pe(o.ops[0])
                w(")")
                return
            elif op == HdlBuiltinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuiltinFn.CONCAT:
                w("{")
                pe(o.ops[0])
                w(", ")
                pe(o.ops[1])
                w("}")
                return
            elif op == HdlBuiltinFn.INDEX or op == HdlBuiltinFn.CALL:
                pe(o.ops[0])
                w("(")
                for isLast, a in iter_with_last_flag(o.ops[1:]):
                    pe(a)
                    if not isLast:
                        w(", ")
                w(")")
                return
            elif op == HdlBuiltinFn.DOT:
                pe(o.ops[0])
                w(".")
                pe(o.ops[1])
                return
            elif op == HdlBuiltinFn.TERNARY:
                pe(o.ops[0])
                w(" ? ")
                o0, o1 = o.ops[1:]
                pe(o0)
                w(" : ")
                pe(o1)
                return
            elif op == HdlBuiltinFn.APOSTROPHE:
                pe(o.ops[0])
                w("'")
                args = o.ops[1]
                if isinstance(args, list):
                    # aggregate
                    w("(")
                    for isLast, a in iter_with_last_flag(args):
                        pe(a)
                        if not isLast:
                            w(", ")
                    w(")")
                else:
                    # normal attribute
                    pe(args)
                return
            else:
                raise NotImplementedError(op)
        elif isinstance(expr, list):
            w("(\n")
            with Indent(self.out):
                for is_last, elem in iter_with_last_flag(expr):
                    self.print_expr(elem)
                    if not is_last:
                        w(",\n")
            w(")")
            return
        raise NotImplementedError(expr)

    def print_type(self, t):
        """
        :type t: iHdlExpr
        """
        self.print_expr(t)

    def print_variable(self, var, end=";\n"):
        """
        :type var: HdlVariableDef
        """
        self.print_doc(var)
        name = var.name
        t = var.type
        latch = var.is_latched
        c = var.is_const
        w = self.out.write
        if c:
            w("CONSTANT ")
        elif latch:
            w("VARIABLE ")
        else:
            w("SIGNAL ")
        w(name)
        w(" : ")
        self.print_type(t)
        v = var.value
        if v is not None:
            w(" := ")
            self.print_expr(v)
        w(end)

    def print_process(self, proc):
        """
        :type proc: HdlStmProcess
        """
        sens = proc.sensitivity
        body = proc.body
        w = self.out.write

        w("PROCESS")
        if sens:
            w("(")
            for last, item in iter_with_last_flag(sens):
                self.print_expr(item)
                if not last:
                    w(", ")
            w(")")
        w("\n")
        self.print_block(body, force_space_before=False)
        w(" PROCESS;\n")

    def print_block(self, stms, force_space_before=True):
        """
        :type stms: Union[List[iHdlStatement], iHdlStatement, iHdlExpr]
        :return: True if statements are wrapped in begin-end block
        """
        w = self.out.write
        if isinstance(stms, HdlStmBlock):
            must_have_begin_end = True
            stms = stms.body
        elif isinstance(stms, list):
            must_have_begin_end = len(stms) != 1
        else:
            must_have_begin_end = False
            stms = [stms, ]

        if must_have_begin_end:
            if force_space_before:
                w(" BEGIN\n")
            else:
                w("BEGIN\n")
        else:
            w("\n")

        with Indent(self.out):
            for s in stms:
                if isinstance(s, iHdlStatement):
                    self.print_statement(s)
                else:
                    self.print_expr(s)
                    w(";\n")

        if must_have_begin_end:
            w("END")
            return True

        return False

    def print_if(self, stm):
        """
        :type stm: HdlStmIf
        """
        w = self.out.write
        c = stm.cond
        ifTrue = stm.if_true
        ifFalse = stm.if_false

        w("IF ")
        self.print_expr(c)
        w(" THEN ")
        need_space = self.print_block(ifTrue)

        for cond, stms in stm.elifs:
            if need_space:
                w(" ")
            w("ELSIF ")
            self.print_expr(cond)
            w(" THEN ")
            need_space = self.print_block(stms)

        if ifFalse is not None:
            if need_space:
                w(" ")
            w("ELSE")
            self.print_block(ifFalse)
        if need_space:
            w("\n")
        w("END IF;\n")

    def print_assignment(self, a):
        """
        :type a: HdlStmAssign
        """
        s = a.src
        d = a.dst
        w = self.out.write
        if a.time_delay is not None:
            raise NotImplementedError()
        if a.event_delay is not None:
            raise NotImplementedError()

        self.print_expr(d)
        w(" <= ")
        self.print_expr(s)
        w(";\n")

    def print_case(self, cstm):
        """
        :type cstm: HdlStmCase
        """
        w = self.out.write
        w("CASE ")
        self.print_expr(cstm.switch_on)
        w(" IS\n")
        with Indent(self.out):
            cases = cstm.cases
            for k, stms in cases:
                w("WHEN ")
                self.print_expr(k)
                w(" => ")
                is_block = self.print_block(stms)
                if is_block:
                    w("\n")
            defal = cstm.default
            if defal is not None:
                is_block = w("WHEN OTHERS => ")
                self.print_block(defal)
                if is_block:
                    w("\n")
        w("END CASE;\n")

    def print_statement(self, o):
        """
        :type o: iHdlStatement
        """
        self.print_doc(o)
        if isinstance(o, HdlStmProcess):
            self.print_process(o)
        elif isinstance(o, HdlStmIf):
            self.print_if(o)
        elif isinstance(o, HdlStmAssign):
            self.print_assignment(o)
        elif isinstance(o, HdlStmCase):
            self.print_case(o)
        elif isinstance(o, HdlStmWait):
            self.print_wait(o)
        elif isinstance(o, HdlStmReturn):
            self.print_return(o)
        elif isinstance(o, HdlStmFor):
            self.print_for(o)
        else:
            raise NotImplementedError(o)

    def print_return(self, o):
        """
        :type o: HdlStmReturn
        """
        w = self.out.write
        w("RETURN")
        if o.val is not None:
            w(" ")
            self.print_expr(o.val)
        w(";\n")

    def print_for(self, o):
        """
        :type o: HdlStmFor
        """
        w = self.out.write
        w("FOR ")
        self.print_expr(o.params[0])
        w(" IN ")
        self.print_expr(o.params[1])
        w(" LOOP\n")
        with Indent(self.out):
            for b in o.body:
                self.print_statement(b)
        w("END FOR;\n")

    def print_wait(self, o):
        """
        :type o: HdlStmWait
        """
        w = self.out.write
        w("WAIT")
        for e in o.val:
            if isinstance(e, HdlCall) and e.fn == HdlBuiltinFn.MUL:
                w(" FOR ")
                self.print_expr(e.ops[0])
                w(" ")
                self.print_expr(e.ops[1])
            else:
                w(" ON ")
                self.print_expr(e)
        w(";\n")

    def print_map_item(self, item):
        self.print_expr(item)

    def print_map(self, map_):
        w = self.out.write
        with Indent(self.out):
            for last, m in iter_with_last_flag(map_):
                self.print_map_item(m)
                if last:
                    w("\n")
                else:
                    w(",\n")

    def print_component_instance(self, c):
        """
        :type c: HdlComponentInst
        """
        self.print_doc(c)
        w = self.out.write
        self.print_expr(c.name)
        w(": ")
        self.print_expr(c.module_name)
        gms = c.param_map
        if gms:
            w(" GENERIC MAP(\n")
            self.print_map(gms)
            w(")")

        pms = c.port_map
        if pms:
            w(" PORT MAP(\n")
            self.print_map(pms)
            w(")")
        w(";")

    def print_body_items(self, objs):
        w = self.out.write
        in_def_section = True
        with Indent(self.out):
            for o in objs:
                if isinstance(o, HdlVariableDef):
                    assert in_def_section, o
                    self.print_variable(o)
                    continue
                elif isinstance(o, HdlModuleDec):
                    assert in_def_section, o
                    self.print_component(o)
                    continue
                elif isinstance(o, HdlFunctionDef):
                    assert in_def_section, o
                    self.print_function(o)
                    continue

                if in_def_section:
                    with UnIndent(self.out):
                        w("BEGIN\n")
                    in_def_section = False

                if isinstance(o, HdlComponentInst):
                    self.print_component_instance(o)
                    w("\n")
                elif isinstance(o, iHdlStatement):
                    self.print_statement(o)
                else:
                    raise NotImplementedError(o)
        if in_def_section:
            w("BEGIN\n")

    def print_module_body(self, a):
        """
        :type a: HdlModuleDef
        """
        w = self.out.write
        w("ARCHITECTURE ")
        w(a.name)
        w(" OF ")
        w(a.module_name)
        w(" IS\n")
        self.print_body_items(a.objs)
        self.out.write("END ARCHITECTURE;\n")

    def print_function(self, o):
        """
        :type o: HdlFunctionDef
        """
        w = self.out.write
        self.print_doc(o)
        is_procedure = o.return_t is None
        if is_procedure:
            w("PROCEDURE ")
        else:
            w("FUNCTION ")

        w(o.name)

        w(" (")
        with Indent(self.out):
            for is_last, par in iter_with_last_flag(o.params):
                self.print_variable(par, end="")
                if not is_last:
                    w(",\n")
        w(")")
        if not is_procedure:
            w(" RETURN ")
            self.print_type(o.return_t)
        w("\n")
        w("IS\n")
        self.print_body_items(o.body)
        w("END FUNCTION;\n")

    def print_library(self, o):
        lib_name = o.name
        self.used_libraries.add(lib_name)
        w = self.out.write
        w("LIBRARY ")
        w(lib_name)
        w(";\n")

    def print_hdl_import(self, o):
        """
        :type o: HdlImport
        """
        self.print_doc(o)
        w = self.out.write
        w("USE ")
        for last, p in iter_with_last_flag(o.path):
            self.print_expr(p)
            if not last:
                w(".")
        w(";\n")

    def print_namespace(self, o):
        """
        :type o: HdlNamespace
        """
        self.print_doc(o)
        w = self.out.write
        # if o.declaration_only:
        w("PACKAGE ")
        w(o.name)
        w(" IS\n")
        with Indent(self.out):
            for _o in o.objs:
                self.print_main_obj(_o)

        w("END PACKAGE;\n")

    def print_main_obj(self, o):
        w = self.out.write
        if isinstance(o, HdlModuleDec):
            w("\n")
            self.print_module_header(o)
            w("\n")
        elif isinstance(o, HdlModuleDef):
            self.print_module_body(o)
        elif isinstance(o, HdlNamespace):
            self.print_namespace(o)
        elif isinstance(o, HdlVariableDef):
            self.print_variable(o)
        elif isinstance(o, HdlFunctionDef):
            self.print_function(o)
        else:
            raise NotImplementedError(o)

    def print_context(self, context):
        """
        :type context: HdlContext
        """
        for o in context.objs:
            if isinstance(o, HdlImport):
                self.print_hdl_import(o)
            elif isinstance(o, HdlLibrary):
                self.print_library(o)
            else:
                self.print_main_obj(o)
Example #5
0
class ToVerilog():
    """
    Convert hdlObject AST back to Verilog 2002
    """
    INDENT_STEP = "    "
    DIR2V = {
        HdlDirection.IN: "input",
        HdlDirection.OUT: "output",
        HdlDirection.INOUT: "inout",
    }

    GENERIC_BIN_OPS = {
        HdlBuildinFn.AND: "&",
        HdlBuildinFn.LOG_AND: "&&",
        HdlBuildinFn.OR: "|",
        HdlBuildinFn.LOG_OR: "||",
        HdlBuildinFn.SUB: "-",
        HdlBuildinFn.ADD: "+",
        HdlBuildinFn.MUL: "*",
        HdlBuildinFn.DIV: "/",
        HdlBuildinFn.MOD: "%",
        HdlBuildinFn.NAND: "~&",
        HdlBuildinFn.NOR: "~|",
        HdlBuildinFn.XOR: "^",
        HdlBuildinFn.XNOR: "~^",
        HdlBuildinFn.EQ: '==',
        HdlBuildinFn.NEQ: "!=",
        HdlBuildinFn.LT: "<",
        HdlBuildinFn.LE: "<=",
        HdlBuildinFn.GT: ">",
        HdlBuildinFn.GE: ">=",
        HdlBuildinFn.SLL: "<<",
        HdlBuildinFn.SRL: ">>",
    }

    def __init__(self, out_stream):
        self.out = AutoIndentingStream(out_stream, self.INDENT_STEP)

    def print_doc(self, obj):
        doc = obj.doc
        if doc is not None:
            doc = doc.split("\n")
            w = self.out.write
            for last, d in iter_with_last_flag(doc):
                if last and d == "":
                    break
                w("//")
                w(d)
                w("\n")

    def print_direction(self, d):
        vd = self.DIR2V[d]
        self.out.write(vd)

    def print_generic_declr(self, g):
        self.print_doc(g)
        w = self.out.write
        w("parameter ")
        is_array = self.print_type_first_part(g.type)
        w(" ")
        w(g.name)
        v = g.value
        if v:
            w(" = ")
            self.print_expr(v)

    def print_port_declr(self, p):
        """
        :type p: HdlVariableDef
        """
        w = self.out.write
        self.print_doc(p)
        self.print_direction(p.direction)
        w(" ")
        l = p.latched
        if l:
            w("reg ")

        t = p.type
        is_array = self.print_type_first_part(t)
        if is_array:
            raise NotImplementedError(t)

        w(p.name)

    def print_module_header(self, e):
        self.print_doc(e)
        w = self.out.write
        w("module ")
        w(e.name)
        gs = e.params
        if gs:
            w(" #(\n")
            with Indent(self.out):
                for last, g in iter_with_last_flag(gs):
                    self.print_generic_declr(g)
                    if last:
                        w("\n")
                    else:
                        w(",\n")

            w(")")
        ps = e.ports
        if ps:
            w(" (\n")
            with Indent(self.out):
                for last, p in iter_with_last_flag(ps):
                    self.print_port_declr(p)
                    if last:
                        w("\n")
                    else:
                        w(",\n")
            w(")")
        w(";\n")

    def print_expr(self, expr, sensitivity=False):
        w = self.out.write
        if isinstance(expr, HdlName):
            w(expr)
            return
        elif isinstance(expr, str):
            w('"%s"' % expr)
            return
        elif isinstance(expr, HdlIntValue):
            if expr.bits is None:
                w(str(expr.val))
            else:
                if expr.base is None:
                    f = "{0}'h{1:x}"
                else:
                    b = expr.base
                    if b == 2:
                        f = "{0}b'{1}"
                    elif b == 8:
                        f = "{0}O'{1}"
                    elif b == 10:
                        f = "{0}d'{1}"
                    elif b == 16:
                        f = "{0}h'{1}"
                    else:
                        raise NotImplementedError(b)
                w(f.format(expr.bits, expr.val))
            return
        elif isinstance(expr, HdlName):
            w(expr.val)
            return
        elif isinstance(expr, HdlAll):
            w("*")
            return
        elif isinstance(expr, HdlCall):

            def pe(e):
                return self.print_expr(e, sensitivity=sensitivity)

            o = expr
            op = expr.fn
            symbol = self.GENERIC_BIN_OPS.get(op, None)
            if symbol is not None:
                if sensitivity and op == HdlBuildinFn.OR:
                    symbol = "or"
                op_cnt = len(o.ops)
                if op_cnt == 1:
                    w("(")
                    w(symbol)
                    pe(o.ops[0])
                    w(")")
                elif op_cnt == 2:
                    w("(")
                    pe(o.ops[0])
                    w(" ")
                    w(symbol)
                    w(" ")
                    pe(o.ops[1])
                    w(")")
                return
            if op == HdlBuildinFn.DOWNTO:
                pe(o.ops[0])
                w(":")
                pe(o.ops[1])
                return
            elif op == HdlBuildinFn.TO:
                pe(o.ops[1])
                w(":")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NOT:
                w("!")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.RISING:
                assert sensitivity
                w("posedge ")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.FALLING:
                assert sensitivity
                w("negedge ")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.NEG:
                w("~")
                pe(o.ops[0])
                return
            elif op == HdlBuildinFn.CONCAT:
                w("{")
                pe(o.ops[0])
                w(", ")
                pe(o.ops[1])
                w("}")
                return
            elif op == HdlBuildinFn.INDEX:
                pe(o.ops[0])
                w("[")
                pe(o.ops[1])
                w("]")
                return
            elif op == HdlBuildinFn.REPL_CONCAT:
                w("{(")
                pe(o.ops[0])
                w("){")
                pe(o.ops[1])
                w("}}")
                return
            elif op == HdlBuildinFn.TERNARY:
                pe(o.ops[0])
                w(" ? ")
                o0, o1 = o.ops[1:]
                pe(o0)
                w(" : ")
                pe(o1)
                return
            elif op == HdlBuildinFn.CALL:
                pe(o.ops[0])
                w("(")
                for is_last, o_n in iter_with_last_flag(o.ops[1:]):
                    pe(o_n)
                    if not is_last:
                        w(", ")
                w(")")
                return
            else:
                raise NotImplementedError(op)
        elif expr is HdlAll:
            w("*")
            return

        raise NotImplementedError(expr)

    def print_type_first_part(self, t):
        """
        :return: True if the type has also the array dimmension part
        """
        w = self.out.write
        if t != WIRE:
            op = t if isinstance(t, HdlCall) else None
            if op is None:
                self.print_expr(t)
                return False

            if op and op.fn == HdlBuildinFn.CALL and op.ops[0] == WIRE:
                # 1D vector
                w("[")
                ops = op.ops[1:]
                size_expr = ops[0]
                is_signed = bool(ops[1])
                if is_signed:
                    raise NotImplementedError(op)
                self.print_expr(size_expr)
                w("] ")
            else:
                o = op.fn
                if o == HdlBuildinFn.INDEX:
                    self.print_type_first_part(op.ops[0])
                    return True
                raise NotImplementedError(op)

        return False

    def print_type_array_part(self, t):
        w = self.out.write
        if isinstance(t, HdlCall) and t.fn == HdlBuildinFn.INDEX:
            self.print_type_array_part(t.ops[0])
            w("[")
            self.print_expr(t.ops[1])
            w("]")

    def print_variable(self, var):
        self.print_doc(var)
        name = var.name
        t = var.type
        l = var.latched
        w = self.out.write
        if l:
            w("reg ")
        else:
            w("wire ")
        is_array = self.print_type_first_part(t)
        w(name)
        if is_array:
            w(" ")
            self.print_type_array_part(t)

    def print_process(self, proc):
        sens = proc.sensitivity
        body = proc.body
        w = self.out.write

        w("always @ (")
        for last, item in iter_with_last_flag(sens):
            self.print_expr(item, sensitivity=True)
            if not last:
                w(", ")
        w(") begin\n")
        with Indent(self.out):
            for stm in body:
                self.print_statement(stm)

        w("end\n")

    def print_block(self, stms):
        """
        :return: True if statements are wrapped in begin-end block
        """
        w = self.out.write
        if len(stms) != 1:
            w(" begin\n")
        else:
            w("\n")

        with Indent(self.out):
            for s in stms:
                self.print_statement(s)

        if len(stms) != 1:
            w("end")
            return True
        return False

    def print_if(self, stm):
        w = self.out.write
        c = stm.cond
        ifTrue = stm.if_true
        ifFalse = stm.if_false

        w("if (")
        self.print_expr(c)
        w(")")
        need_space = self.print_block(ifTrue)

        for cond, stms in stm.elifs:
            if need_space:
                w(" ")
            w("else if (")
            self.print_expr(cond)
            w(")")
            need_space = self.print_block(stms)

        if ifFalse is not None:
            if need_space:
                w(" ")
            w("else")
            self.print_block(ifFalse)
        if need_space:
            w("\n")

    def print_assignment(self, a, is_top=False):
        s = a.src
        d = a.dst
        w = self.out.write
        if is_top:
            w("assign ")
            self.print_expr(d)
            w(" = ")
            self.print_expr(s)
        else:
            self.print_expr(d)
            w(" <= ")
            self.print_expr(s)
        w(";\n")

    def print_case(self, cstm):
        w = self.out.write
        w("case(")
        self.print_expr(cstm.switch_on)
        w(")\n")
        with Indent(self.out):
            cases = cstm.cases
            for k, stms in cases:
                self.print_expr(k)
                w(":")
                is_block = self.print_block(stms)
                if is_block:
                    w("\n")
            defal = cstm.default
            if defal is not None:
                is_block = w("default:")
                self.print_block(defal)
                if is_block:
                    w("\n")
        w("endcase\n")

    def print_statement(self, stm, is_top=False):
        self.print_doc(stm)
        if isinstance(stm, HdlProcessStm):
            self.print_process(stm)
        elif isinstance(stm, HdlIfStm):
            self.print_if(stm)
        elif isinstance(stm, HdlAssignStm):
            self.print_assignment(stm, is_top=is_top)
        elif isinstance(stm, HdlCaseStm):
            self.print_case(stm)
        else:
            raise NotImplementedError(stm)

    def print_map_item(self, item):
        if isinstance(item,
                      HdlCall) and item.fn == HdlBuildinFn.MAP_ASSOCIATION:
            w = self.out.write
            # k, v pair
            k, v = item.ops
            w(".")
            self.print_expr(k)
            w("(")
            self.print_expr(v)
            w(")")
        else:
            self.print_expr(item)

    def print_map(self, map_):
        w = self.out.write
        with Indent(self.out):
            for last, m in iter_with_last_flag(map_):
                self.print_map_item(m)
                if last:
                    w("\n")
                else:
                    w(",\n")

    def print_component_instance(self, c):
        """
        :type c: HdlComponentInst
        """
        self.print_doc(c)
        w = self.out.write
        assert c.module_name
        self.print_expr(c.module_name)
        w(" ")
        self.print_expr(c.name)
        gms = c.param_map
        if gms:
            w(" #(\n")
            self.print_map(gms)
            w(")")

        pms = c.port_map
        if pms:
            w(" (\n")
            self.print_map(pms)
            w(")")
        w(";")

    def print_module_body(self, a):
        """
        :type a: HdlModuleDef
        """
        w = self.out.write
        with Indent(self.out):
            for o in a.objs:
                if isinstance(o, HdlVariableDef):
                    self.print_variable(o)
                    w(";\n")
                elif isinstance(o, HdlComponentInst):
                    self.print_component_instance(o)
                    w("\n")
                elif isinstance(o, iHdlStatement):
                    self.print_statement(o, is_top=True)
                else:
                    raise NotImplementedError(o)

        self.out.write("endmodule\n")

    def print_context(self, context):
        """
        :type context: HdlContext
        """
        last = None
        for o in context.objs:
            if isinstance(o, HdlModuleDec):
                self.print_module_header(o)
            elif isinstance(o, HdlModuleDef):
                assert isinstance(last, HdlModuleDec) \
                        and o.module_name == last.name, (last, o)
                self.print_module_body(o)
            else:
                raise NotImplementedError(o)

            last = o