def __init__(self, out_stream): self.out = AutoIndentingStream(out_stream, self.INDENT_STEP)
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
def __init__(self, out_stream): self.out = AutoIndentingStream(out_stream, self.INDENT_STEP) self.used_libraries = set()
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)
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)
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
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