コード例 #1
0
def test_clock_interaction():
    mods = []
    num_child = 4
    for i in range(num_child):
        mod = Generator("mod", True)
        in_ = mod.input("in", 4)
        out_ = mod.output("out", 4)
        clk = mod.clock("clk")
        seq = mod.sequential((posedge, clk))
        seq.add_stmt(out_.assign(in_))
        mods.append(mod)
    parent = Generator("parent", True)
    clk = parent.clock("clk")
    in_ = parent.input("in", 4)
    out = parent.output("out", 4)
    for i, mod in enumerate(mods):
        parent.add_child("mod{0}".format(i), mod)
        parent.wire(mod.ports.clk, clk)
        if i == 0:
            continue
        parent.wire(mod.ports["in"], mods[i - 1].ports.out)
    parent.wire(mods[0].ports["in"], in_)
    parent.wire(out, mods[-1].ports.out)
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(parent,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
コード例 #2
0
ファイル: test_debug.py プロジェクト: mfkiwl/kratos
def test_inst_id():
    def create_mod():
        m = Generator("mod", True)
        in_ = m.input("in", 1)
        out = m.output("out", 1)
        comb = m.combinational()
        comb.add_stmt(out.assign(in_))
        return m

    mod = Generator("parent", True)
    input_ = mod.input("in", 1)
    output = mod.output("out", 1)
    mods = [create_mod() for _ in range(2)]
    expr = None
    for i, m_ in enumerate(mods):
        mod.add_child("mod{0}".format(i), m_)
        mod.wire(input_, m_.ports["in"])
        if expr is None:
            expr = m_.ports["out"]
        else:
            expr = expr & m_.ports["out"]
    mod.wire(output, expr)

    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        verilog(mod,
                insert_debug_info=True,
                debug_db_filename=debug_db,
                optimize_passthrough=False)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * FROM instance")
        res = c.fetchall()
        assert len(res) == 3
        conn.close()
コード例 #3
0
def test_assert():
    from kratos import assert_
    mod = Generator("mod", True)
    in_ = mod.input("in", 1)
    out_ = mod.output("out", 1)

    @always_comb
    def code():
        # we introduce this bug on purpose
        out_ = in_ - 1
        assert_(out_ == in_)

    mod.add_always(code)
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(mod,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
        with open(filename) as f:
            content = f.read()
            assert "assert (out == in) else" in content
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * FROM breakpoint")
        lines = c.fetchall()
        assert len(lines) == 2
        # they are only one line apart
        assert abs(lines[0][2] - lines[1][2]) == 1
        conn.close()
    # once we remove the assertion, it should not be there
    _kratos.passes.remove_assertion(mod.internal_generator)
    src = verilog(mod)[0]["mod"]
    assert "assert" not in src
コード例 #4
0
def test_nested_scope():
    from kratos import clog2
    mod = Generator("FindHighestBit", True)
    width = 4
    data = mod.input("data", width)
    h_bit = mod.output("h_bit", clog2(width))
    done = mod.var("done", 1)

    @always_comb
    def find_bit():
        done = 0
        h_bit = 0
        for i in range(width):
            if ~done:
                if data[i]:
                    done = 1
                    h_bit = i

    mod.add_always(find_bit, label="block")
    verilog(mod, insert_debug_info=True)
    block = mod.get_marked_stmt("block")
    last_if = block[-1]
    for i in range(len(last_if.then_[-1].then_)):
        stmt = last_if.then_[-1].then_[i]
        context = stmt.scope_context
        if len(context) > 0:
            assert "i" in context
            is_var, var = context["i"]
            assert not is_var
            assert var == "3"
コード例 #5
0
def test_wire():
    mod = Generator("mod", True)
    in_ = mod.input("in", 1)
    out_ = mod.output("out", 1)
    # context
    a = 1
    mod.wire(out_, in_)
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(mod,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * FROM breakpoint")
        assert len(c.fetchall()) == 1
        c.execute(
            """SELECT variable.value FROM variable, context
                     WHERE context.name = ? AND context.variable_id = variable.id""",
            "a")
        v = int(c.fetchone()[0])
        assert v == a
        conn.close()
コード例 #6
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_data_if():
    class Mod(Generator):
        def __init__(self, bool_flag):
            super().__init__("mod1")
            self.in_ = self.port("in", 1, PortDirection.In)
            self.out_ = self.port("out", 1, PortDirection.Out)
            self.bool_flag = bool_flag

            self.add_code(self.code)

        def code(self):
            if self.bool_flag:
                if self.in_ == self.const(1, 1):
                    self.out_ = 1
                else:
                    self.out_ = 0
            else:
                if self.in_ == self.const(0, 1):
                    self.out_ = 0
                else:
                    self.out_ = 1

    mod = Mod(True)
    mod_src = verilog(mod)
    src = mod_src["mod1"]
    assert is_valid_verilog(src)
    assert "in == 1'h1" in src
    # need to clear the context, otherwise it will be a different module name
    Generator.clear_context()
    mod = Mod(False)
    mod_src = verilog(mod)
    src = mod_src["mod1"]
    assert is_valid_verilog(src)
    assert "in == 1'h0" in src
コード例 #7
0
def test_array_packed():
    from kratos import PackedStruct
    mod = Generator("mod", True)
    aa = mod.var("a", 2, size=(2, 4), packed=True)
    struct = PackedStruct("s", [("read", 16, False), ("data", 16, False)])
    ss = mod.var_packed("s", struct)
    mod.add_stmt(aa.assign(4))
    setattr(mod, "sss", ss)
    mod.add_stmt(ss["read"].assign(0))
    mod.add_stmt(ss["data"].assign(1))

    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        verilog(mod, debug_db_filename=debug_db, insert_debug_info=True)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute(
            "SELECT variable.value, generator_variable.name FROM variable, generator_variable WHERE variable.id = generator_variable.variable_id"
        )
        vars_ = c.fetchall()
        c.execute(
            "SELECT variable.value, context.name FROM variable, context WHERE variable.id = context.variable_id"
        )
        vars_ += c.fetchall()
        correct_struct, correct_array, correct_self = False, False, False
        for value, name in vars_:
            if value == "a[1][3]" and name == "aa.1.3":
                correct_array = True
            if value == "s.read" and name == "ss.read":
                correct_struct = True
            if "self.sss" in name:
                correct_self = True
        assert correct_array and correct_struct, correct_self
        conn.close()
コード例 #8
0
def test_design_hierarchy():
    from functools import reduce
    mods = []
    num_child = 4
    num_child_child = 3

    def add_child(m):
        output = None
        outputs_ = []
        for c in range(num_child_child):
            child = Generator("child", True)
            m.add_child("child{0}".format(c), child)
            in__ = child.input("in", 4)
            out__ = child.output("out", 4)
            clk__ = child.clock("clk")
            m.wire(m.ports.clk, clk__)
            if output is None:
                m.wire(m.ports["in"], in__)
            else:
                m.wire(output, in__)
            output = out__
            seq_ = child.sequential((posedge, clk__))
            seq_.add_stmt(out__.assign(in__))
            outputs_.append(out__)
        return outputs_

    for i in range(num_child):
        mod = Generator("mod", True)
        mod.input("in", 4)
        out_ = mod.output("out", 4)
        clk = mod.clock("clk")
        seq = mod.sequential((posedge, clk))
        outputs = add_child(mod)
        seq.add_stmt(out_.assign(reduce(lambda x, y: x + y, outputs)))
        mods.append(mod)
    parent = Generator("parent")
    clk = parent.clock("clk")
    in_ = parent.input("in", 4)
    out = parent.output("out", 4)
    for i, mod in enumerate(mods):
        parent.add_child("mod{0}".format(i), mod)
        parent.wire(mod.ports.clk, clk)
        if i == 0:
            continue
        parent.wire(mod.ports["in"], mods[i - 1].ports.out)
    parent.wire(mods[0].ports["in"], in_)
    parent.wire(out, mods[-1].ports.out)
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(parent,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * FROM hierarchy")
        mods = c.fetchall()
        assert len(mods) == num_child_child * num_child + num_child
        conn.close()
コード例 #9
0
def test_context():
    class Mod(Generator):
        def __init__(self, width):
            super().__init__("mod", True)
            in_ = self.input("in", width)
            out = self.output("out", width)
            sel = self.input("sel", width)
            # test self variables
            self.out = out
            self.width = width

            @always_comb
            def code():
                if sel:
                    out = 0
                else:
                    for i in range(width):
                        out[i] = 1

            self.add_always(code)

    mod = Mod(4)
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(mod,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * FROM context")
        variables = c.fetchall()
        assert len(variables) > 20
        conn.close()
コード例 #10
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_verilog_file():
    mod = PassThroughTop()
    with tempfile.TemporaryDirectory() as tempdir:
        filename = os.path.join(tempdir, "mod.sv")
        verilog(mod, filename=filename, debug=True, optimize_passthrough=False)
        with open(filename) as f:
            src = f.read()
            assert is_valid_verilog(src)
コード例 #11
0
def test_port_interface():
    mod = Generator("mod")
    mod.interface(ConfigInterface(), "port_interface", is_port=True)

    with tempfile.TemporaryDirectory() as temp:
        filename = os.path.join(temp, "mod.sv")
        verilog(mod, filename=filename)
        with open(filename) as f:
            content = f.read()
            assert "endinterface" in content
コード例 #12
0
def test_db_dump():
    mod = Generator("mod", True)
    comb = mod.combinational()
    comb.add_stmt(mod.var("a", 1).assign(mod.var("b", 1)))

    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        # hashing and generate verilog
        verilog(mod, insert_debug_info=True, debug_db_filename=debug_db)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * from breakpoint")
        result = c.fetchall()
        assert len(result) == 1
        conn.close()
コード例 #13
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_more_debug2():
    class Top(Generator):
        def __init__(self):
            super().__init__("top", True)

            self.port("in", 1, PortDirection.In)
            self.port("out", 1, PortDirection.Out)

            pass_through = PassThroughMod()
            self.add_child_generator("pass", pass_through)
            self.wire(
                self["pass"].ports["in"],
                self.ports["in"],
            )

            self.add_code(self.code_block)

        def code_block(self):
            self.ports.out = self["pass"].ports.out

    mod = Top()
    mod_src, debug_info = verilog(mod, debug=True)
    src = mod_src["top"]
    debug = debug_info["top"]
    assert is_valid_verilog(src)
    assert len(debug) > 3
コード例 #14
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_create():
    class Mod(Generator):
        def __init__(self, width, is_clone=False):
            super().__init__(f"mod_{width}", is_clone=is_clone)

            self.in_ = self.port("in", width, PortDirection.In)
            self.out_ = self.port("out", width, PortDirection.Out)
            self.wire(self.out_, self.in_)

    mod1 = Mod.create(width=1)
    mod2 = Mod.create(width=2)
    mod3 = Mod.create(width=1)

    assert not mod1.is_cloned
    assert not mod2.is_cloned
    assert mod3.is_cloned
    assert mod3.def_instance == mod1

    # modify mod 3
    mod3.initialize_clone()
    mod3.in_.width = 3
    mod3.out_.width = 3
    assert not mod3.is_cloned
    mod_src = verilog(mod3)

    # we didn't change the name
    assert "mod_1" in mod_src
    assert "2:0" in mod_src["mod_1"]
    assert is_valid_verilog(mod_src["mod_1"])
コード例 #15
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_pass():
    def change_name(generator):
        class Visitor(ASTVisitor):
            def __init__(self):
                ASTVisitor.__init__(self)

            def visit(self, node):
                if isinstance(node, Port):
                    # rename the output port
                    if node.name == "out":
                        node.name = "test"

        visitor = Visitor()
        visitor.visit_root(generator)

    class Mod1(Generator):
        def __init__(self):
            super().__init__("mod1", True)
            self.in_ = self.port("in", 1, PortDirection.In)
            self.out_ = self.port("out", 1, PortDirection.Out)
            self.wire(self.out_, self.in_)

    mod = Mod1()
    mod_src = verilog(mod, additional_passes={"name_change": change_name})
    src = mod_src["mod1"]
    assert is_valid_verilog(src)
    assert "logic  test" in src
コード例 #16
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_static_eval_for_loop():
    class Mod(Generator):
        def __init__(self, num_loop):
            super().__init__("mod1", True)
            self.in_ = self.port("in", 1, PortDirection.In)
            self.out_ = self.port("out", num_loop, PortDirection.Out)
            self.num_loop = num_loop

            self.add_code(self.code)

        def code(self):
            if self.in_ == self.const(1, 1):
                for i in range(self.num_loop):
                    self.out_[i] = 1
            else:
                for i in range(self.num_loop):
                    self.out_[i] = 0

    loop = 4
    mod = Mod(loop)
    mod_src, mod_debug = verilog(mod, debug=True)
    src = mod_src["mod1"]
    mod_mapping = mod_debug["mod1"]
    lines = list(mod_mapping.keys())
    lines.sort()
    for ii in range(len(mod_mapping) - loop, len(mod_mapping) - 1):
        assert mod_mapping[lines[-1]][-1] == mod_mapping[lines[ii]][-1]
    assert is_valid_verilog(src)
コード例 #17
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_debug():
    class Mod(Generator):
        def __init__(self):
            super().__init__("mod1", True)
            self.in_ = self.port("in", 1, PortDirection.In)
            self.out_1 = self.port("out1", 1, PortDirection.Out)
            self.out_2 = self.port("out2", 1, PortDirection.Out)

            self.wire(self.out_1, self.in_)

            self.add_code(self.code)

        def code(self):
            self.out_2 = self.in_

    mod = Mod()
    mod_src, mod_debug = verilog(mod, debug=True)
    src_mapping = mod_debug["mod1"]
    assert len(src_mapping) == 7
    verilog_lines = mod_src["mod1"].split("\n")
    verilog_ln = 0
    for ln, line in enumerate(verilog_lines):
        if "assign out1 = in;" in line:
            verilog_ln = ln + 1
            break
    fn, ln = src_mapping[verilog_ln][0]
    with open(fn) as f:
        python_lns = f.readlines()
    assert "self.wire(self.out_1, self.in_)" in python_lns[ln - 1]
コード例 #18
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_fanout_mod_inst():
    class Mod2(Generator):
        def __init__(self):
            super().__init__("mod2")
            self.in_ = self.port("in", 1, PortDirection.In)
            self.out_ = self.port("out", 1, PortDirection.Out)

            self.mod_1 = PassThroughMod()
            self.mod_2 = PassThroughMod()

            self.add_child_generator("mod1", self.mod_1)
            self.add_child_generator("mod2", self.mod_2)

            self.wire(self.in_, self.mod_1.in_)
            self.wire(self.in_, self.mod_2.in_)

            self.add_code(self.code)

        def code(self):
            self.out_ = self.mod_1.out_ + self.mod_2.out_

    mod = Mod2()
    mod_src = verilog(mod, optimize_passthrough=False)
    assert "mod2" in mod_src
    src = mod_src["mod2"]
    assert is_valid_verilog(src)
コード例 #19
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_clone():
    class Mod2(Generator):
        def __init__(self):
            super().__init__("mod2")
            self.in_ = self.port("in", 2, PortDirection.In)
            self.out_ = self.port("out", 2, PortDirection.Out)

            self.child1 = PassThroughMod.clone()
            self.child2 = PassThroughMod.clone()
            self.add_child_generator("child1", self.child1)
            self.add_child_generator("child2", self.child2)

            self.add_code(self.code)

        def code(self):
            self.child1.ports["in"] = self.in_[0]
            self.child2.ports["in"] = self.in_[1]

            self.out_[0] = self.child1.ports.out
            self.out_[1] = self.child2.ports.out

    mod = Mod2()
    assert not mod.child1.is_cloned
    assert mod.child2.is_cloned
    mod_src = verilog(mod, False, False, False)
    src = mod_src["mod2"]
    assert is_valid_verilog(src)
コード例 #20
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_more_debug1():
    mod = PassThroughTop()
    mod_src, debug_info = verilog(mod, debug=True)
    src = mod_src["top"]
    debug = debug_info["top"]
    assert is_valid_verilog(src)
    assert len(debug) > 3
コード例 #21
0
def test_one_hot_decoder():
    cases = 16
    num_tests = 10
    output_size = 20

    decoder = OneHotDecoder(cases, output_size)
    mod_src = verilog(decoder)

    with tempfile.TemporaryDirectory() as tempdir:
        filename = os.path.join(tempdir, decoder.name + ".sv")
        with open(filename, "w+") as f:
            for value in mod_src.values():
                f.write(value)
                f.write("\n")

        # import it as magma circuit
        circuit = magma.DefineFromVerilogFile(filename,
                                              target_modules=[decoder.name],
                                              shallow=True)[0]

        tester = fault.Tester(circuit)

        tester.zero_inputs()

        for i in range(num_tests):
            value = random.randrange(cases)
            tester.poke(circuit.S, value)
            tester.eval()
            tester.expect(circuit.O, 1 << value)

        tester.compile_and_run(target="verilator",
                               skip_compile=True,
                               directory=tempdir,
                               flags=["-Wno-fatal"])
コード例 #22
0
def test_regression_2():
    from kratos.func import dpi_function

    @dpi_function(8)
    def func(arg0):
        pass

    class Mod(Generator):
        def __init__(self):
            super().__init__("mod", debug=True)
            self._in = self.input("in", 2)
            self._out = self.output("out", 8)
            self._reg = self.var("val", 8)

            self.add_always(self.code)

        @always_comb
        def code(self):
            # because the types are inferred
            # implicit const conversion doesn't work here
            self._reg = func(const(1, 2))
            self._out = func(const(1, 2))

    mod = Mod()
    mod_src = verilog(mod)
    assert "func" in mod_src[1]
コード例 #23
0
    def build(self, src_nodes, view):

        gen_spec = importlib.util.spec_from_file_location(
            self.gen_name, self.src_path)
        gen_mod = importlib.util.module_from_spec(gen_spec)
        gen_spec.loader.exec_module(gen_mod)
        vlog_gen = getattr(gen_mod, self.gen_name)

        if len(src_nodes) > 1:
            config = {}
            for src_node in src_nodes:
                config[src_node.name] = src_node.config_dict
        else:
            config = src_nodes[0].config_dict

        kratos.verilog(vlog_gen(**config), filename=self.snk_path)
        return self.snk_path
コード例 #24
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_async_reg():
    reg_width = 16
    reg = AsyncReg(reg_width)
    # produce verilog
    verilog_src = verilog(reg)
    assert "register" in verilog_src
    reg_src = verilog_src["register"]
    assert is_valid_verilog(reg_src)
コード例 #25
0
def test_seq_debug():
    class Mod(Generator):
        def __init__(self):
            super().__init__("mod", True)
            # ports
            self.in_ = self.input("in1", 1)
            self.clock("clk")
            for i in range(4):
                self.output("out{0}".format(i), 1)

            self.add_always(self.code1)
            self.add_always(self.code2)

        @always_comb
        def code1(self):
            if self.in_ == 0:
                self.ports.out0 = 0
                self.ports.out1 = 0
            else:
                self.ports.out0 = 1
                self.ports.out1 = 1

        @always_ff((posedge, "clk"))
        def code2(self):
            if self.in_ == 0:
                self.ports.out2 = 0
                self.ports.out3 = 0
            else:
                self.ports.out2 = 1
                self.ports.out3 = 1

    mod = Mod()
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(mod,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT * FROM breakpoint WHERE id=7")
        result = c.fetchall()
        assert len(result) == 1
        conn.close()
コード例 #26
0
ファイル: test_expr.py プロジェクト: mfkiwl/kratos
def test_md_array():
    mod = Generator("mod")
    a = mod.var("a", 16, size=(4, 2), packed=True)
    b = mod.var("b", 16, size=(4, 2), packed=True)
    c = mod.var("c", 16, size=(2,), packed=True)
    mod.wire(b, a)
    mod.wire(c, a[1])
    src = verilog(mod)["mod"]
    assert "logic [3:0][1:0][15:0] a;" in src
コード例 #27
0
ファイル: test_generator.py プロジェクト: leonardt/kratos
def test_pass_through():
    mod = PassThroughTop()
    # turn off pass through module optimization since it will remove
    # mod2 completely
    mod_src = verilog(mod, optimize_passthrough=True)
    assert "top" in mod_src
    assert "mod1" not in mod_src
    assert is_valid_verilog(mod_src["top"])
    assert "mod1" not in mod_src["top"]
コード例 #28
0
def test_regression_flatten_array_param():
    from _kratos import create_wrapper_flatten
    mod = Generator("mod")
    p = mod.parameter("param", value=16)
    mod.input("in", width=p)
    inst = create_wrapper_flatten(mod.internal_generator, "wrapper")
    gen = Generator("", internal_generator=inst)
    src = verilog(gen)["wrapper"]
    assert "parameter param = 32'h10" in src
コード例 #29
0
def test_metadata():
    mod = Generator("mod", True)
    mod.input("in", 1)
    mod.output("out", 1)
    mod.wire(mod.ports.out, mod.ports["in"])
    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        filename = os.path.join(temp, "test.sv")
        verilog(mod,
                filename=filename,
                insert_debug_info=True,
                debug_db_filename=debug_db)
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        c.execute("SELECT value FROM metadata WHERE name = ?", ["top_name"])
        value = c.fetchone()[0]
        assert value == "mod"
        conn.close()
コード例 #30
0
ファイル: test_debug.py プロジェクト: mfkiwl/kratos
def test_ssa_debug():
    mod = Generator("mod", debug=True)
    a = mod.var("a", 4)
    clk = mod.clock("clk")
    b = mod.var("b", 1)
    loop_size = 4

    @always_comb
    def logic1():
        a = 0
        if b:
            for i in range(loop_size):
                a = a + i

    @always_ff((posedge, clk))
    def logic2():
        if a == 1:
            b = 1
        else:
            b = 0

    mod.add_always(logic1, ssa_transform=True)
    mod.add_always(logic2)

    with tempfile.TemporaryDirectory() as temp:
        debug_db = os.path.join(temp, "debug.db")
        verilog(mod,
                insert_debug_info=True,
                debug_db_filename=debug_db,
                ssa_transform=True)
        # assert the line number tracking
        conn = sqlite3.connect(debug_db)
        c = conn.cursor()
        idx = get_line("                a = a + i")
        c.execute("SELECT * FROM breakpoint WHERE line_num=?", (idx, ))
        result = c.fetchall()
        assert len(result) == loop_size
        assert "a_4" in result[0][-1]
        # check the context variable
        c.execute(
            "SELECT * FROM context_variable WHERE context_variable.name = 'i'")
        result = c.fetchall()
        assert len(result) == loop_size
        conn.close()